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