]> Dogcows Code - chaz/yoink/blob - src/moof/packet.cc
the massive refactoring effort
[chaz/yoink] / src / moof / packet.cc
1
2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
3 **] All rights reserved.
4 *
5 * vi:ts=4 sw=4 tw=75
6 *
7 * Distributable under the terms and conditions of the 2-clause BSD license;
8 * see the file COPYING for a complete text of the license.
9 *
10 **************************************************************************/
11
12 #include "../config.h"
13
14 #include <algorithm>
15 #if HAVE_BYTESWAP_H
16 #include <byteswap.h>
17 #endif
18 #include <cstdlib>
19
20 #if HAVE_ARPA_INET_H
21 #include <arpa/inet.h>
22 #endif
23
24 #include <SDL/SDL.h>
25
26 #include "packet.hh"
27
28
29 #ifndef bswap_16
30 #define bswap_16(x) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
31 #endif
32
33 #ifndef bswap_32
34 #define bswap_32(x) ((((x) & 0xff000000) >> 24) | \
35 (((x) & 0x00ff0000) >> 8) | \
36 (((x) & 0x0000ff00) << 8) | \
37 (((x) & 0x000000ff) << 24))
38 #endif
39
40 #ifndef bswap_64
41 #define bswap_64(x) (((x) << 56) | \
42 (((x) << 40) & 0xff000000000000ULL) | \
43 (((x) << 24) & 0xff0000000000ULL) | \
44 (((x) << 8) & 0xff00000000ULL) | \
45 (((x) >> 8) & 0xff000000ULL) | \
46 (((x) >> 24) & 0xff0000ULL) | \
47 (((x) >> 40) & 0xff00ULL) | \
48 ((x) >> 56))
49 #endif
50
51
52 #if !HAVE_ARPA_INET_H
53 static uint16_t htons(uint16_t x)
54 {
55 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
56 return bswap_16(x);
57 #else
58 return x;
59 #endif
60 }
61 static uint16_t ntohs(uint16_t x)
62 {
63 return htons(x);
64 }
65
66 static uint32_t htonl(uint32_t x)
67 {
68 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
69 return bswap_32(x);
70 #else
71 return x;
72 #endif
73 }
74 static uint32_t ntohl(uint32_t x)
75 {
76 return htonl(x);
77 }
78 #endif
79
80
81 static uint64_t htonll(uint64_t x)
82 {
83 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
84 return bswap_64(x);
85 #else
86 return x;
87 #endif
88 }
89 static uint64_t ntohll(uint64_t x)
90 {
91 return htonll(x);
92 }
93
94
95 namespace moof {
96
97
98 packet::packet(size_t size) :
99 buffer_((char*)malloc(size)),
100 size_(size) {}
101
102 packet::packet(const char* data, size_t size) :
103 buffer_((char*)malloc(size)),
104 size_(size),
105 state_(size),
106 saved_(size)
107 {
108 if (buffer_) memcpy(buffer_, data, size);
109 else throw std::length_error("out of memory");
110 }
111
112
113 packet::packet(const packet& copy) :
114 buffer_((char*)malloc(copy.size_)),
115 size_(copy.size_),
116 state_(copy.state_),
117 saved_(copy.saved_)
118 {
119 if (buffer_) memcpy(buffer_, copy.buffer_, size_);
120 else throw std::length_error("out of memory");
121 }
122
123 packet& packet::operator = (const packet& copy)
124 {
125 free(buffer_);
126 buffer_ = (char*)malloc(copy.size_);
127 size_ = copy.size_;
128 if (buffer_) memcpy(buffer_, copy.buffer_, size_);
129 else throw std::length_error("out of memory");
130
131 state_ = copy.state_;
132 saved_ = copy.saved_;
133 return *this;
134 }
135
136
137 packet::~packet()
138 {
139 free(buffer_);
140 }
141
142
143 packet& packet::operator << (bool value)
144 {
145 int bit = state_.write_bool_num % 8;
146 if (bit == 0)
147 {
148 state_.write_bool_mark = state_.write_mark;
149
150 unsigned char byte = 0;
151 if (write(&byte, 1) == 0) throw std::length_error("out of memory");
152 }
153
154 if (value) buffer_[state_.write_bool_mark] |= (1 << bit);
155 ++state_.write_bool_num;
156
157 return *this;
158 }
159
160
161 packet& packet::operator << (int8_t value)
162 {
163 return *this << reinterpret_cast<uint8_t&>(value);
164 }
165
166 packet& packet::operator << (int16_t value)
167 {
168 return *this << reinterpret_cast<uint16_t&>(value);
169 }
170
171 packet& packet::operator << (int32_t value)
172 {
173 return *this << reinterpret_cast<uint32_t&>(value);
174 }
175
176 packet& packet::operator << (int64_t value)
177 {
178 return *this << reinterpret_cast<uint64_t&>(value);
179 }
180
181
182 packet& packet::operator << (uint8_t value)
183 {
184 if (write(&value, sizeof(value)) != sizeof(value))
185 {
186 throw std::length_error("out of memory");
187 }
188 return *this;
189 }
190
191 packet& packet::operator << (uint16_t value)
192 {
193 value = htons(value);
194 if (write(&value, sizeof(value)) != sizeof(value))
195 {
196 throw std::length_error("out of memory");
197 }
198 return *this;
199 }
200
201 packet& packet::operator << (uint32_t value)
202 {
203 value = htonl(value);
204 if (write(&value, sizeof(value)) != sizeof(value))
205 {
206 throw std::length_error("out of memory");
207 }
208 return *this;
209 }
210
211 packet& packet::operator << (uint64_t value)
212 {
213 value = htonll(value);
214 if (write(&value, sizeof(value)) != sizeof(value))
215 {
216 throw std::length_error("out of memory");
217 }
218 return *this;
219 }
220
221 packet& packet::operator << (float value)
222 {
223 // XXX: assumes the ieee-754
224 uint32_t* integer = reinterpret_cast<uint32_t*>(&value);
225 *integer = htonl(*integer);
226 if (write(integer, sizeof(value)) != sizeof(value))
227 {
228 throw std::length_error("out of memory");
229 }
230 return *this;
231 }
232
233 packet& packet::operator << (double value)
234 {
235 // XXX: assumes the ieee-754
236 uint64_t* integer = reinterpret_cast<uint64_t*>(&value);
237 *integer = htonll(*integer);
238 if (write(integer, sizeof(value)) != sizeof(value))
239 {
240 throw std::length_error("out of memory");
241 }
242 return *this;
243 }
244
245 size_t packet::write(const void* bytes, size_t size)
246 {
247 size_t num_bytes = std::min(size, size_ - state_.write_mark);
248 if (!buffer_ || num_bytes < size)
249 {
250 int num_pages = 1 + size / PAGE_SIZE;
251 int new_size = size_ + num_pages * PAGE_SIZE;
252 char* new_buffer = (char*)realloc(buffer_, new_size);
253 if (new_buffer)
254 {
255 buffer_ = new_buffer;
256 size_ = new_size;
257 num_bytes = size;
258 }
259 if (!buffer_) return 0;
260 }
261 memcpy(buffer_ + state_.write_mark, bytes, num_bytes);
262 state_.write_mark += num_bytes;
263 return num_bytes;
264 }
265
266
267 packet& packet::operator >> (bool& value)
268 {
269 int bit = state_.read_bool_num % 8;
270 if (bit == 0)
271 {
272 state_.read_bool_mark = state_.read_mark;
273
274 unsigned char byte = 0;
275 if (read(&byte, 1) == 0) throw std::out_of_range("end of packet");
276 }
277
278 value = 1 & (buffer_[state_.read_bool_mark] >> bit);
279 ++state_.read_bool_num;
280
281 return *this;
282 }
283
284 packet& packet::operator >> (int8_t& value)
285 {
286 return *this >> reinterpret_cast<uint8_t&>(value);
287 }
288
289 packet& packet::operator >> (int16_t& value)
290 {
291 return *this >> reinterpret_cast<uint16_t&>(value);
292 }
293
294 packet& packet::operator >> (int32_t& value)
295 {
296 return *this >> reinterpret_cast<uint32_t&>(value);
297 }
298
299 packet& packet::operator >> (int64_t& value)
300 {
301 return *this >> reinterpret_cast<uint64_t&>(value);
302 }
303
304 packet& packet::operator >> (uint8_t& value)
305 {
306 if (read(&value, sizeof(value)) != sizeof(value))
307 {
308 throw std::out_of_range("end of packet");
309 }
310 return *this;
311 }
312
313 packet& packet::operator >> (uint16_t& value)
314 {
315 if (read(&value, sizeof(value)) != sizeof(value))
316 {
317 throw std::out_of_range("end of packet");
318 }
319 value = ntohs(value);
320 return *this;
321 }
322
323 packet& packet::operator >> (uint32_t& value)
324 {
325 if (read(&value, sizeof(value)) != sizeof(value))
326 {
327 throw std::out_of_range("end of packet");
328 }
329 value = ntohl(value);
330 return *this;
331 }
332
333 packet& packet::operator >> (uint64_t& value)
334 {
335 if (read(&value, sizeof(value)) != sizeof(value))
336 {
337 throw std::out_of_range("end of packet");
338 }
339 value = ntohll(value);
340 return *this;
341 }
342
343 packet& packet::operator >> (float& value)
344 {
345 // XXX: assumes the ieee-754
346 uint32_t* integer = reinterpret_cast<uint32_t*>(&value);
347 if (read(integer, sizeof(value)) != sizeof(value))
348 {
349 throw std::out_of_range("end of packet");
350 }
351 *integer = htonl(*integer);
352 return *this;
353 }
354
355 packet& packet::operator >> (double& value)
356 {
357 // XXX: assumes the ieee-754
358 uint64_t* integer = reinterpret_cast<uint64_t*>(&value);
359 if (read(integer, sizeof(value)) != sizeof(value))
360 {
361 throw std::out_of_range("end of packet");
362 }
363 *integer = htonll(*integer);
364 return *this;
365 }
366
367 size_t packet::read(void* bytes, size_t size)
368 {
369 size_t num_bytes = std::min(size, state_.write_mark - state_.read_mark);
370 memcpy(bytes, buffer_ + state_.read_mark, num_bytes);
371 state_.read_mark += num_bytes;
372 return num_bytes;
373 }
374
375
376 void packet::clear()
377 {
378 state_.read_mark = state_.write_mark;
379 state_.read_bool_mark = 0;
380 state_.read_bool_num = 0;
381 state_.write_bool_mark = 0;
382 state_.write_bool_num = 0;
383 }
384
385
386 void packet::save()
387 {
388 saved_ = state_;
389 }
390
391 void packet::revert()
392 {
393 state_ = saved_;
394 }
395
396
397 } // namespace moof
398
This page took 0.050816 seconds and 5 git commands to generate.