Merge branch 'master' of git://github.com/thepowersgang/acess2
[tpg/acess2.git] / Usermode / Applications / axwin4_src / Common / serialisation.cpp
1 /*
2  * Acess2 GUI v4
3  * - By John Hodge (thePowersGang) 
4  *
5  * serialisation.cpp
6  * - IPC Serialisation
7  */
8 #include <serialisation.hpp>
9 #include <cstddef>
10 #include <stdexcept>
11 #include <acess/sys.h>  // SysDebug
12
13 namespace AxWin {
14
15 CDeserialiser::CDeserialiser(const ::std::vector<uint8_t>& vector):
16         m_vect(vector),
17         m_offset(0)
18 {
19 }
20 CDeserialiser::CDeserialiser(::std::vector<uint8_t>&& vector):
21         m_vect(vector),
22         m_offset(0)
23 {
24 }
25 CDeserialiser& CDeserialiser::operator=(const CDeserialiser& x)
26 {
27         m_vect = x.m_vect;
28         m_offset = x.m_offset;
29 }
30
31 bool CDeserialiser::IsConsumed() const
32 {
33         return m_offset == m_vect.size();
34 }
35
36 ::uint8_t CDeserialiser::ReadU8()
37 {
38         RangeCheck("CDeserialiser::ReadU8", 1);
39         uint8_t rv = m_vect[m_offset];
40         m_offset ++;
41         return rv;
42 }
43
44 ::uint16_t CDeserialiser::ReadU16()
45 {
46         RangeCheck("CDeserialiser::ReadU16", 2);
47         uint16_t rv = m_vect[m_offset] | ((uint16_t)m_vect[m_offset+1] << 8);
48         m_offset += 2;
49         return rv;
50 }
51
52 ::int16_t CDeserialiser::ReadS16()
53 {
54         uint16_t rv_u = ReadU16();
55         if( rv_u < 0x8000 )
56                 return rv_u;
57         else
58                 return ~rv_u + 1;
59 }
60
61 ::uint32_t CDeserialiser::ReadU32()
62 {
63         uint32_t rv = ReadU16();
64         rv |= (uint32_t)ReadU16() << 16;
65         return rv;
66 }
67
68 ::uint64_t CDeserialiser::ReadU64()
69 {
70         uint64_t rv = ReadU32();
71         rv |= (uint64_t)ReadU32() << 32;
72         return rv;
73 }
74
75 const ::std::vector<uint8_t> CDeserialiser::ReadBuffer()
76 {
77         RangeCheck("CDeserialiser::ReadBuffer(len)", 2);
78         size_t  size = ReadU16();
79         
80         auto range_start = m_vect.begin() + int(m_offset);
81         ::std::vector<uint8_t> ret( range_start, range_start + int(size) );
82         m_offset += size;
83         return ret;
84 }
85
86 const ::std::string CDeserialiser::ReadString()
87 {
88         RangeCheck("CDeserialiser::ReadString(len)", 1);
89         uint8_t len = ReadU8();
90         
91         RangeCheck("CDeserialiser::ReadString(data)", len);
92         ::std::string ret( reinterpret_cast<const char*>(m_vect.data()+m_offset), len );
93         m_offset += len;
94         return ret;
95 }
96
97 void CDeserialiser::RangeCheck(const char *Method, size_t bytes) throw(::std::out_of_range)
98 {
99         if( m_offset + bytes > m_vect.size() ) {
100                 ::_SysDebug("%s - out of range %i+%i >= %i", Method, m_offset, bytes, m_vect.size());
101                 throw ::std::out_of_range(Method);
102         }
103 }
104
105 CSerialiser::CSerialiser()
106 {
107 }
108
109 void CSerialiser::WriteU8(::uint8_t Value)
110 {
111         m_data.push_back(Value);
112 }
113
114 void CSerialiser::WriteU16(::uint16_t Value)
115 {
116         m_data.push_back(Value & 0xFF);
117         m_data.push_back(Value >> 8);
118 }
119
120 void CSerialiser::WriteS16(::int16_t Value)
121 {
122         if( Value < 0 )
123         {
124                 ::uint16_t rawval = 0x10000 - (::int32_t)Value;
125                 WriteU16(rawval);
126         }
127         else
128         {
129                 WriteU16(Value);
130         }
131 }
132
133 void CSerialiser::WriteU32(::uint32_t Value)
134 {
135         m_data.push_back(Value & 0xFF);
136         m_data.push_back(Value >>  8);
137         m_data.push_back(Value >> 16);
138         m_data.push_back(Value >> 24);
139 }
140
141 void CSerialiser::WriteU64(::uint64_t Value)
142 {
143         WriteU32(Value);
144         WriteU32(Value>>32);
145 }
146
147 void CSerialiser::WriteBuffer(size_t n, const void* val)
148 {
149         const uint8_t*  val8 = static_cast<const uint8_t*>(val);
150         if( n > 0xFFFF )
151                 throw ::std::length_error("CSerialiser::WriteBuffer");
152         m_data.reserve( m_data.size() + 2 + n );
153         WriteU16(n);
154         for( size_t i = 0; i < n; i ++ )
155                 m_data.push_back(val8[i]);
156 }
157
158 void CSerialiser::WriteString(const char* val, size_t n)
159 {
160         if( n > 0xFF )
161                 throw ::std::length_error("CSerialiser::WriteString");
162         m_data.reserve( m_data.size() + 1 + n );
163         WriteU8(n);
164         for( size_t i = 0; i < n; i ++ )
165                 m_data.push_back(val[i]);
166 }
167
168 void CSerialiser::WriteSub(const CSerialiser& val)
169 {
170         // TODO: Append reference to sub-buffer contents
171         m_data.reserve( m_data.size() + val.m_data.size() );
172         for( auto byte : val.m_data )
173                 m_data.push_back( byte );
174 }
175
176 const ::std::vector<uint8_t>& CSerialiser::Compact()
177 {
178         return m_data;
179 }
180
181 };      // namespace AxWin
182

UCC git Repository :: git.ucc.asn.au