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