sources/network/bytestream.cpp

branch
protocol5
changeset 159
970d58a01e8b
parent 158
de7574d292ad
child 167
0150f86e68f0
equal deleted inserted replaced
155:9f71f854474a 159:970d58a01e8b
30 30
31 #include "bytestream.h" 31 #include "bytestream.h"
32 #include <string.h> 32 #include <string.h>
33 BEGIN_ZFC_NAMESPACE 33 BEGIN_ZFC_NAMESPACE
34 34
35 // ------------------------------------------------------------------------------------------------- 35 /*!
36 // 36 * \brief Constructs a byte cursor. The cursor is placed to the beginning of the stream.
37 Bytestream::Bytestream (unsigned long length) : 37 * \param data
38 m_data (nullptr) 38 */
39 { 39 Bytestream::Bytestream(ByteArray& data) :
40 resize (length); 40 m_data(data),
41 clear(); 41 m_position(0) {}
42 } 42
43 43 /*!
44 // ------------------------------------------------------------------------------------------------- 44 * \brief Ensures that the specified amount of bytes can be read. Raises IOError if this is not the case.
45 // 45 * \param bytes Amount of bytes to check.
46 Bytestream::Bytestream (const unsigned char* data, unsigned long length) : 46 */
47 m_data (nullptr) 47 void Bytestream::ensureReadSpace(int bytes)
48 { 48 {
49 init (data, length); 49 if (bytesLeft() < bytes)
50 }
51
52 // -------------------------------------------------------------------------------------------------
53 //
54 Bytestream::Bytestream (const Vector<unsigned char>& bytes) :
55 m_data (nullptr)
56 {
57 init (bytes.data(), bytes.size());
58 }
59
60 // -------------------------------------------------------------------------------------------------
61 //
62 Bytestream::Bytestream (const Bytestream& other) :
63 m_data (nullptr)
64 {
65 init (other.data(), other.written_length());
66 }
67
68 // -------------------------------------------------------------------------------------------------
69 //
70 Bytestream::~Bytestream()
71 {
72 delete[] m_data;
73 }
74
75 // -------------------------------------------------------------------------------------------------
76 Bytestream& Bytestream::operator= (const Bytestream& other)
77 {
78 init (other.data(), other.written_length());
79 return *this;
80 }
81
82 // -------------------------------------------------------------------------------------------------
83 //
84 void Bytestream::resize (unsigned long newsize)
85 {
86 Vector<unsigned char> olddata;
87 unsigned long oldsize = 0L;
88
89 if (m_data != nullptr)
90 { 50 {
91 oldsize = allocated_size(); 51 int bytesPast = bytes - bytesLeft();
92 olddata.resize (oldsize);
93 memcpy (olddata.data(), m_data, oldsize);
94 }
95
96 delete[] m_data;
97 m_allocatedSize = newsize;
98 m_data = new unsigned char[newsize];
99
100 if (oldsize > 0L)
101 memcpy (m_data, olddata, min (oldsize, newsize));
102 }
103
104 // -------------------------------------------------------------------------------------------------
105 //
106 void Bytestream::init (const unsigned char* data, unsigned long length)
107 {
108 resize (length);
109 memcpy (m_data, data, length);
110 m_cursor = &m_data[0];
111 m_writtenLength = length;
112 }
113
114 // -------------------------------------------------------------------------------------------------
115 //
116 void Bytestream::clear()
117 {
118 m_cursor = &m_data[0];
119 m_writtenLength = 0;
120 }
121
122 // -------------------------------------------------------------------------------------------------
123 //
124 void Bytestream::ensure_read_space (unsigned int bytes)
125 {
126 if (bytes_left() < bytes)
127 {
128 int bytesPast = bytes - bytes_left();
129
130 String message; 52 String message;
131 message.sprintf ("attempted to read %d byte%s past the end of bytestream", 53 message.sprintf("attempted to read %d byte%s past the end of bytestream", bytesPast, plural(bytesPast));
132 bytesPast, bytesPast != -1 ? "s" : "");
133 throw IOError (message); 54 throw IOError (message);
134 } 55 }
135 } 56 }
136 57
137 // ------------------------------------------------------------------------------------------------- 58 /*!
138 // 59 * \returns the amount of bytes remaining for reading.
139 int8_t Bytestream::read_byte() 60 */
140 { 61 int Bytestream::bytesLeft() const
141 ensure_read_space (1); 62 {
142 return *m_cursor++; 63 return m_data.size() - m_position;
143 } 64 }
144 65
145 // ------------------------------------------------------------------------------------------------- 66 /*!
146 // 67 * \returns an iterator to the current data position.
147 int16_t Bytestream::read_short() 68 */
148 { 69 ByteArray::Iterator Bytestream::getCurrentIterator()
149 ensure_read_space (2); 70 {
150 short int result = 0; 71 return m_data.begin() + m_position;
72 }
73
74 /*!
75 * \brief Reads in a byte.
76 * \returns the read byte.
77 */
78 int8_t Bytestream::readByte()
79 {
80 ensureReadSpace(1);
81 return read();
82 }
83
84 /*!
85 * \brief Reads in two bytes to form an integer value.
86 * \returns the read value.
87 */
88 int16_t Bytestream::readShort()
89 {
90 ensureReadSpace (2);
91 int16_t result = 0;
151 92
152 for (int i : range(2)) 93 for (int i : range(2))
153 result |= m_cursor[i] << (i * 8); 94 result |= read() << (i * 8);
154 95
155 m_cursor += 2;
156 return result; 96 return result;
157 } 97 }
158 98
159 // ------------------------------------------------------------------------------------------------- 99 /*!
160 // 100 * \brief Reads in four bytes to form an integer value.
161 int32_t Bytestream::read_long() 101 * \returns the read value.
162 { 102 */
163 ensure_read_space (4); 103 int32_t Bytestream::readLong()
164 long int result = 0; 104 {
105 ensureReadSpace (4);
106 int32_t result = 0;
165 107
166 for (int i : range(4)) 108 for (int i : range(4))
167 result |= m_cursor[i] << (i * 8); 109 result |= read() << (i * 8);
168 110
169 m_cursor += 4;
170 return result; 111 return result;
171 } 112 }
172 113
173 // ------------------------------------------------------------------------------------------------- 114 /*!
174 // 115 * \brief Reads in four bytes to form a floating point number.
175 float Bytestream::read_float() 116 * \returns the read value.
117 */
118 float Bytestream::readFloat()
176 { 119 {
177 float value; 120 float value;
178 int intvalue = read_long(); 121 int intvalue = readLong();
179 memcpy (&value, &intvalue, sizeof intvalue); 122 memcpy(&value, &intvalue, sizeof intvalue);
180 return value; 123 return value;
181 } 124 }
182 125
183 // ------------------------------------------------------------------------------------------------- 126 /*!
184 // 127 * \brief Reads in characters until a null terminator is encountered.
185 String Bytestream::read_string() 128 * \returns the read string.
186 { 129 */
187 // Zandronum sends strings of maximum 2048 characters, though it only 130 String Bytestream::readString()
188 // reads 2047-character long ones so I guess we can follow up and do 131 {
189 // the same :-) 132 ByteArray::Iterator stringEndIterator;
190 static char buffer[MAX_NETWORK_STRING];
191 unsigned char* stringEnd;
192 unsigned char* stringBegin = m_cursor;
193 unsigned char* end = m_data + allocated_size();
194 133
195 // Where's the end of the string? 134 // Where's the end of the string?
196 for (stringEnd = m_cursor; *stringEnd != '\0'; ++stringEnd) 135 for (stringEndIterator = getCurrentIterator(); *stringEndIterator != '\0'; ++stringEndIterator)
197 { 136 {
198 if (stringEnd == end) 137 if (stringEndIterator == m_data.end())
199 { 138 {
200 // Past the end of the buffer 139 // Past the end of the buffer
201 throw IOError ("unterminated or too long string in packet"); 140 throw IOError("unterminated or too long string in packet");
202 } 141 }
203 } 142 }
204 143
205 unsigned int length = stringEnd - m_cursor; 144 // Skip past the null terminator.
206 m_cursor = stringEnd + 1; 145 if (*stringEndIterator == '\0')
207 memcpy (buffer, stringBegin, length); 146 stringEndIterator += 1;
208 buffer[length] = '\0'; 147
209 return String (buffer); 148 // Build and return the string, and advance the position.
210 } 149 int stringStart = m_position;
211 150 unsigned int length = stringEndIterator - getCurrentIterator();
212 // ------------------------------------------------------------------------------------------------- 151 length = min<int>(length, MAX_NETWORK_STRING);
213 // 152 m_position += length;
214 void Bytestream::read (unsigned char* buffer, unsigned long length) 153 return String::fromBytes(m_data.splice(stringStart, stringStart + length));
215 { 154 }
216 ensure_read_space (length); 155
217 memcpy (buffer, m_cursor, length); 156 /*!
218 m_cursor += length; 157 * \brief Reads in a buffer of the specified length.
219 } 158 * \param length Amount of bytes to read.
220 159 * \returns the read buffer.
221 // ------------------------------------------------------------------------------------------------- 160 */
222 // 161 ByteArray Bytestream::readBuffer(int length)
223 void Bytestream::write (unsigned char val) 162 {
224 { 163 ensureReadSpace(length);
225 *m_cursor++ = val; 164 ByteArray result(length);
226 m_writtenLength++; 165 memcpy(result.data(), m_data.data() + m_position, length);
227 } 166 m_position += length;
228 167 return result;
229 // ------------------------------------------------------------------------------------------------- 168 }
230 // 169
231 void Bytestream::write (const unsigned char* val, unsigned int length) 170 /*!
232 { 171 * \brief Writes an integer to the end of the data as one byte.
233 grow_to_fit (length); 172 * \param value Value to write
234 memcpy (m_cursor, val, length); 173 */
235 m_cursor += length; 174 void Bytestream::writeByte(int8_t value)
236 m_writtenLength += length; 175 {
237 } 176 m_data.append(value);
238 177 }
239 // ------------------------------------------------------------------------------------------------- 178
240 // 179 /*!
241 void Bytestream::grow_to_fit (unsigned long bytes) 180 * \brief Writes an integer to the end of the data as 2 bytes.
242 { 181 * \param value Value to write
243 if (space_left() < bytes) 182 */
244 resize (allocated_size() + bytes + 128); 183 void Bytestream::writeShort(int16_t value)
245 } 184 {
246
247 // -------------------------------------------------------------------------------------------------
248 //
249 void Bytestream::write_byte (int8_t val)
250 {
251 grow_to_fit (1);
252 write (val);
253 }
254
255 // -------------------------------------------------------------------------------------------------
256 //
257 void Bytestream::write_short (int16_t val)
258 {
259 grow_to_fit (2);
260
261 for (int i : range(2)) 185 for (int i : range(2))
262 write ((val >> (i * 8)) & 0xFF); 186 m_data.append((value >> (i * 8)) & 0xFF);
263 } 187 }
264 188
265 // ------------------------------------------------------------------------------------------------- 189 /*!
266 // 190 * \brief Writes an integer to the end of the data as 4 bytes.
267 void Bytestream::write_long (int32_t val) 191 * \param value Value to write
268 { 192 */
269 grow_to_fit (4); 193 void Bytestream::writeLong(int32_t value)
270 194 {
271 for (int i : range(4)) 195 for (int i : range(4))
272 write ((val >> (i * 8)) & 0xFF); 196 m_data.append((value >> (i * 8)) & 0xFF);
273 } 197 }
274 198
275 // ------------------------------------------------------------------------------------------------- 199 /*!
276 // 200 * \brief Writes a floating-point number to the end of the data.
277 void Bytestream::write_float (float val) 201 * \param value Value to write.
202 */
203 void Bytestream::writeFloat(float value)
278 { 204 {
279 // I know this is probably dangerous but this is what Zandronum does so yeah 205 // I know this is probably dangerous but this is what Zandronum does so yeah
280 int intvalue; 206 int intvalue;
281 memcpy (&intvalue, &val, sizeof val); 207 memcpy (&intvalue, &value, sizeof value);
282 write_long (intvalue); 208 writeLong (intvalue);
283 } 209 }
284 210
285 // ------------------------------------------------------------------------------------------------- 211 /*!
286 // 212 * \brief Writes the given string to the end of the data.
287 void Bytestream::write_string (const String& val) 213 * \param text String to write.
288 { 214 */
289 grow_to_fit (val.length() + 1); 215 void Bytestream::writeString(const String& string)
290 write (reinterpret_cast<const unsigned char*> (val.chars()), val.length()); 216 {
291 write (0); 217 m_data.append(string.toBytes(), string.length());
292 } 218 m_data.append(0);
293 219 }
294 // ------------------------------------------------------------------------------------------------- 220
295 // 221 /*!
296 void Bytestream::write_buffer (const Bytestream& other) 222 * \returns the current position the stream cursor in the data.
297 { 223 */
298 write (other.data(), other.written_length()); 224 int Bytestream::position() const
225 {
226 return m_position;
227 }
228
229 /*!
230 * \brief Seeks the stream cursor to the beginning of the data.
231 */
232 void Bytestream::rewind()
233 {
234 m_position = 0;
235 }
236
237 /*!
238 * \brief Seeks the stream cursor to a custom location.
239 * \param position Position to seek too.
240 */
241 void Bytestream::seek(int position)
242 {
243 m_position = position;
244 }
245
246 /*!
247 * \brief Reads a byte and advances the cursor. No safety checks are done.
248 * \returns the read byte.
249 */
250 int8_t Bytestream::read()
251 {
252 return m_data[m_position++];
299 } 253 }
300 254
301 END_ZFC_NAMESPACE 255 END_ZFC_NAMESPACE

mercurial