Thu, 11 Dec 2014 05:58:55 +0200
- code cleanup
- added network-related classes (bytestream, ipaddress, udp socket)
5 | 1 | #include "bytestream.h" |
2 | #include <string.h> | |
3 | ||
4 | bool Bytestream::sink; | |
5 | ||
6 | // ------------------------------------------------------------------------------------------------- | |
7 | // | |
8 | Bytestream::Bytestream (unsigned long length) : | |
9 | m_data (nullptr) | |
10 | { | |
11 | resize (length); | |
12 | clear(); | |
13 | } | |
14 | ||
15 | // ------------------------------------------------------------------------------------------------- | |
16 | // | |
17 | Bytestream::Bytestream (const unsigned char* data, unsigned long length) : | |
18 | m_data (nullptr) | |
19 | { | |
20 | m_data = nullptr; | |
21 | init (data, length); | |
22 | } | |
23 | ||
24 | // ------------------------------------------------------------------------------------------------- | |
25 | // | |
26 | Bytestream::Bytestream (const Vector<unsigned char>& bytes) : | |
27 | m_data (nullptr) | |
28 | { | |
29 | init (bytes.data(), bytes.size()); | |
30 | } | |
31 | ||
32 | // ------------------------------------------------------------------------------------------------- | |
33 | // | |
34 | Bytestream::~Bytestream() | |
35 | { | |
36 | delete m_data; | |
37 | } | |
38 | ||
39 | // ------------------------------------------------------------------------------------------------- | |
40 | // | |
41 | void Bytestream::resize (unsigned long newsize) | |
42 | { | |
43 | Vector<unsigned char> olddata; | |
44 | unsigned long oldsize = 0L; | |
45 | ||
46 | if (m_data != nullptr) | |
47 | { | |
48 | oldsize = allocated_size(); | |
49 | olddata.resize (oldsize); | |
50 | memcpy (olddata.data(), m_data, oldsize); | |
51 | } | |
52 | ||
53 | delete[] m_data; | |
54 | m_allocatedSize = newsize; | |
55 | m_data = new unsigned char[newsize]; | |
56 | ||
57 | if (olddata > 0L) | |
58 | memcpy (m_data, olddata, min (oldsize, newsize)); | |
59 | } | |
60 | ||
61 | // ------------------------------------------------------------------------------------------------- | |
62 | // | |
63 | void Bytestream::init (const unsigned char* data, unsigned long length) | |
64 | { | |
65 | resize (length); | |
66 | memcpy (m_data, data, length); | |
67 | m_cursor = &m_data[0]; | |
68 | m_writtenLength = length; | |
69 | } | |
70 | ||
71 | // ------------------------------------------------------------------------------------------------- | |
72 | // | |
73 | void Bytestream::clear() | |
74 | { | |
75 | m_cursor = &m_data[0]; | |
76 | m_writtenLength = 0; | |
77 | } | |
78 | ||
79 | // ------------------------------------------------------------------------------------------------- | |
80 | // | |
81 | char Bytestream::read_byte (bool* ok) | |
82 | { | |
83 | *ok = bytes_left() > 0; | |
84 | return *ok ? *m_cursor++ : -1; | |
85 | } | |
86 | ||
87 | // ------------------------------------------------------------------------------------------------- | |
88 | // | |
89 | short int Bytestream::read_short (bool* ok) | |
90 | { | |
91 | if (bytes_left() < 2) | |
92 | { | |
93 | *ok = false; | |
94 | return false; | |
95 | } | |
96 | ||
97 | short int val = 0; | |
98 | ||
99 | for (int i = 0; i < 2; ++i) | |
100 | val |= *m_cursor++ << (i * 8); | |
101 | ||
102 | *ok = true; | |
103 | return true; | |
104 | } | |
105 | ||
106 | // ------------------------------------------------------------------------------------------------- | |
107 | // | |
108 | long int Bytestream::read_long (bool* ok) | |
109 | { | |
110 | if (bytes_left() < 4) | |
111 | { | |
112 | *ok = false; | |
113 | return -1; | |
114 | } | |
115 | ||
116 | long int val = 0; | |
117 | ||
118 | for (int i = 0; i < 4; ++i) | |
119 | val |= *m_cursor++ << (i * 8); | |
120 | ||
121 | *ok = true; | |
122 | return val; | |
123 | } | |
124 | ||
125 | // ------------------------------------------------------------------------------------------------- | |
126 | // | |
127 | float Bytestream::read_float (bool* ok) | |
128 | { | |
129 | int value = read_long (ok); | |
130 | ||
131 | if (*ok == false) | |
132 | return -1.0f; | |
133 | ||
134 | return reinterpret_cast<float&> (value); | |
135 | } | |
136 | ||
137 | // ------------------------------------------------------------------------------------------------- | |
138 | // | |
139 | String Bytestream::read_string (bool* ok) | |
140 | { | |
141 | // Zandronum sends strings of maximum 2048 characters, though it only | |
142 | // reads 2047-character long ones so I guess we can follow up and do | |
143 | // the same :-) | |
144 | static char buffer[MAX_NETWORK_STRING]; | |
145 | unsigned char* stringEnd; | |
146 | unsigned char* stringBegin = m_cursor; | |
147 | unsigned char* end = m_data + allocated_size(); | |
148 | ||
149 | // where's the end of the string? | |
150 | for (stringEnd = m_cursor; *stringEnd != '\0'; ++stringEnd) | |
151 | { | |
152 | if (stringEnd == end) | |
153 | { | |
154 | // past the end of the buffer! Argh! | |
155 | *ok = false; | |
156 | return ""; | |
157 | } | |
158 | } | |
159 | ||
160 | m_cursor = stringEnd + 1; | |
161 | *ok = true; | |
162 | unsigned int length = stringEnd - m_cursor; | |
163 | ||
164 | // ensure we won't write past the buffer (note: we still moved | |
165 | // past the excess bytes in the above statement, those are ignored) | |
166 | if (length >= MAX_NETWORK_STRING) | |
167 | length = MAX_NETWORK_STRING - 1; | |
168 | ||
169 | memcpy (buffer, stringBegin, length); | |
170 | buffer[length] = '\0'; | |
171 | return String (buffer); | |
172 | } | |
173 | ||
174 | // ------------------------------------------------------------------------------------------------- | |
175 | // | |
176 | METHOD | |
177 | Bytestream::read (unsigned char* buffer, unsigned long length, bool* ok) -> void | |
178 | { | |
179 | if (bytes_left() < length) | |
180 | { | |
181 | *ok = false; | |
182 | return; | |
183 | } | |
184 | ||
185 | memcpy (buffer, m_cursor, length); | |
186 | m_cursor += length; | |
187 | *ok = true; | |
188 | } | |
189 | ||
190 | // ------------------------------------------------------------------------------------------------- | |
191 | // | |
192 | void Bytestream::write (unsigned char val) | |
193 | { | |
194 | *m_cursor++ = val; | |
195 | m_writtenLength++; | |
196 | } | |
197 | ||
198 | // ------------------------------------------------------------------------------------------------- | |
199 | // | |
200 | void Bytestream::write (const unsigned char* val, unsigned int length) | |
201 | { | |
202 | grow_to_fit (length); | |
203 | memcpy (m_cursor, val, length); | |
204 | m_cursor += length; | |
205 | m_writtenLength += length; | |
206 | } | |
207 | ||
208 | // ------------------------------------------------------------------------------------------------- | |
209 | // | |
210 | void Bytestream::grow_to_fit (unsigned long bytes) | |
211 | { | |
212 | if (space_left() < bytes) | |
213 | resize (allocated_size() + bytes + 128); | |
214 | } | |
215 | ||
216 | // ------------------------------------------------------------------------------------------------- | |
217 | // | |
218 | void Bytestream::write_byte (char val) | |
219 | { | |
220 | grow_to_fit (1); | |
221 | write (val); | |
222 | } | |
223 | ||
224 | // ------------------------------------------------------------------------------------------------- | |
225 | // | |
226 | void Bytestream::write_short (short int val) | |
227 | { | |
228 | grow_to_fit (2); | |
229 | ||
230 | for (int i = 0; i < 2; ++i) | |
231 | write ((val >> (i * 8)) & 0xFF); | |
232 | } | |
233 | ||
234 | // ------------------------------------------------------------------------------------------------- | |
235 | // | |
236 | void Bytestream::write_long (long int val) | |
237 | { | |
238 | grow_to_fit (4); | |
239 | ||
240 | for (int i = 0; i < 4; ++i) | |
241 | write ((val >> (i * 8)) & 0xFF); | |
242 | } | |
243 | ||
244 | // ------------------------------------------------------------------------------------------------- | |
245 | // | |
246 | void Bytestream::write_float (float val) | |
247 | { | |
248 | // I know this is probably dangerous but this is what Zandronum does so yeah | |
249 | write_long (reinterpret_cast<int&> (val)); | |
250 | } | |
251 | ||
252 | // ------------------------------------------------------------------------------------------------- | |
253 | // | |
254 | void Bytestream::write_string (const String& val) | |
255 | { | |
256 | grow_to_fit (val.length() + 1); | |
257 | write (reinterpret_cast<const unsigned char*> (val.chars()), val.length()); | |
258 | write (0); | |
259 | } | |
260 | ||
261 | // ------------------------------------------------------------------------------------------------- | |
262 | // | |
263 | void Bytestream::write_buffer (const Bytestream& other) | |
264 | { | |
265 | write (other.data(), other.written_length()); | |
266 | } |