|
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 } |