1 // Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Library General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 #include <simgear/misc/stdint.hxx>
27 /// Sigh, this is std::vector<char>, except that
28 /// you could feed that with external pointers without copying ...
29 /// Note on alignment: the c++ standard garantees (5.3.4.10) that
30 /// new (unsigned) char returns sufficiently aligned memory
31 /// for all relevant cases
39 RTIData(unsigned size) :
44 RTIData(char* data, unsigned size) :
49 RTIData(const char* data, unsigned size) :
53 { setData(data, size); }
54 RTIData(const char* data) :
59 RTIData(const RTIData& data) :
64 unsigned size = data.size();
67 memcpy(_data, data.data(), size);
77 const char* data() const
86 { return _size == 0; }
97 void resize(unsigned size)
101 if (_capacity < size) {
102 unsigned capacity = 2*_capacity;
104 ensureCapacity(capacity);
106 ensureCapacity(size);
111 void reserve(unsigned capacity)
113 if (capacity <= _capacity)
115 ensureCapacity(capacity);
118 void setData(char* data, unsigned size)
126 void setData(const char* data, unsigned size)
131 memcpy(_data, data, size);
133 void setData(const char* data)
138 size_t size = strlen(data) + 1;
143 RTIData& operator=(const RTIData& data)
145 unsigned size = data.size();
148 memcpy(_data, data.data(), size);
153 void getData8(char data[1], unsigned offset = 0) const
155 data[0] = _data[offset];
158 void setData8(const char data[1], unsigned offset = 0)
160 _data[offset] = data[0];
163 void getData16LE(char data[2], unsigned offset = 0) const
165 if (hostIsLittleEndian()) {
166 data[0] = _data[offset];
167 data[1] = _data[offset+1];
169 data[1] = _data[offset];
170 data[0] = _data[offset+1];
173 void setData16LE(const char data[2], unsigned offset = 0)
175 if (hostIsLittleEndian()) {
176 _data[offset] = data[0];
177 _data[offset+1] = data[1];
179 _data[offset] = data[1];
180 _data[offset+1] = data[0];
184 void getData16BE(char data[2], unsigned offset = 0) const
186 if (hostIsLittleEndian()) {
187 data[1] = _data[offset];
188 data[0] = _data[offset+1];
190 data[0] = _data[offset];
191 data[1] = _data[offset+1];
194 void setData16BE(const char data[2], unsigned offset = 0)
196 if (hostIsLittleEndian()) {
197 _data[offset] = data[1];
198 _data[offset+1] = data[0];
200 _data[offset] = data[0];
201 _data[offset+1] = data[1];
206 void getData32LE(char data[4], unsigned offset = 0) const
208 if (hostIsLittleEndian()) {
209 data[0] = _data[offset];
210 data[1] = _data[offset+1];
211 data[2] = _data[offset+2];
212 data[3] = _data[offset+3];
214 data[3] = _data[offset];
215 data[2] = _data[offset+1];
216 data[1] = _data[offset+2];
217 data[0] = _data[offset+3];
220 void setData32LE(const char data[4], unsigned offset = 0)
222 if (hostIsLittleEndian()) {
223 _data[offset] = data[0];
224 _data[offset+1] = data[1];
225 _data[offset+2] = data[2];
226 _data[offset+3] = data[3];
228 _data[offset] = data[3];
229 _data[offset+1] = data[2];
230 _data[offset+2] = data[1];
231 _data[offset+3] = data[0];
235 void getData32BE(char data[4], unsigned offset = 0) const
237 if (hostIsLittleEndian()) {
238 data[3] = _data[offset];
239 data[2] = _data[offset+1];
240 data[1] = _data[offset+2];
241 data[0] = _data[offset+3];
243 data[0] = _data[offset];
244 data[1] = _data[offset+1];
245 data[2] = _data[offset+2];
246 data[3] = _data[offset+3];
249 void setData32BE(const char data[4], unsigned offset = 0)
251 if (hostIsLittleEndian()) {
252 _data[offset] = data[3];
253 _data[offset+1] = data[2];
254 _data[offset+2] = data[1];
255 _data[offset+3] = data[0];
257 _data[offset] = data[0];
258 _data[offset+1] = data[1];
259 _data[offset+2] = data[2];
260 _data[offset+3] = data[3];
265 void getData64LE(char data[8], unsigned offset = 0) const
267 if (hostIsLittleEndian()) {
268 data[0] = _data[offset];
269 data[1] = _data[offset+1];
270 data[2] = _data[offset+2];
271 data[3] = _data[offset+3];
272 data[4] = _data[offset+4];
273 data[5] = _data[offset+5];
274 data[6] = _data[offset+6];
275 data[7] = _data[offset+7];
277 data[7] = _data[offset];
278 data[6] = _data[offset+1];
279 data[5] = _data[offset+2];
280 data[4] = _data[offset+3];
281 data[3] = _data[offset+4];
282 data[2] = _data[offset+5];
283 data[1] = _data[offset+6];
284 data[0] = _data[offset+7];
287 void setData64LE(const char data[8], unsigned offset = 0)
289 if (hostIsLittleEndian()) {
290 _data[offset] = data[0];
291 _data[offset+1] = data[1];
292 _data[offset+2] = data[2];
293 _data[offset+3] = data[3];
294 _data[offset+4] = data[4];
295 _data[offset+5] = data[5];
296 _data[offset+6] = data[6];
297 _data[offset+7] = data[7];
299 _data[offset] = data[7];
300 _data[offset+1] = data[6];
301 _data[offset+2] = data[5];
302 _data[offset+3] = data[4];
303 _data[offset+4] = data[3];
304 _data[offset+5] = data[2];
305 _data[offset+6] = data[1];
306 _data[offset+7] = data[0];
310 void getData64BE(char data[8], unsigned offset = 0) const
312 if (hostIsLittleEndian()) {
313 data[7] = _data[offset];
314 data[6] = _data[offset+1];
315 data[5] = _data[offset+2];
316 data[4] = _data[offset+3];
317 data[3] = _data[offset+4];
318 data[2] = _data[offset+5];
319 data[1] = _data[offset+6];
320 data[0] = _data[offset+7];
322 data[0] = _data[offset];
323 data[1] = _data[offset+1];
324 data[2] = _data[offset+2];
325 data[3] = _data[offset+3];
326 data[4] = _data[offset+4];
327 data[5] = _data[offset+5];
328 data[6] = _data[offset+6];
329 data[7] = _data[offset+7];
332 void setData64BE(const char data[8], unsigned offset = 0)
334 if (hostIsLittleEndian()) {
335 _data[offset] = data[7];
336 _data[offset+1] = data[6];
337 _data[offset+2] = data[5];
338 _data[offset+3] = data[4];
339 _data[offset+4] = data[3];
340 _data[offset+5] = data[2];
341 _data[offset+6] = data[1];
342 _data[offset+7] = data[0];
344 _data[offset] = data[0];
345 _data[offset+1] = data[1];
346 _data[offset+2] = data[2];
347 _data[offset+3] = data[3];
348 _data[offset+4] = data[4];
349 _data[offset+5] = data[5];
350 _data[offset+6] = data[6];
351 _data[offset+7] = data[7];
356 #define TYPED_GETSET_IMPLEMENTATION(type, base, suffix) \
357 type get##base##suffix(unsigned offset = 0) const \
361 char u8[sizeof(type)]; \
363 getData##suffix(u.u8, offset); \
366 void set##base##suffix(type value, unsigned offset = 0) \
370 char u8[sizeof(type)]; \
373 setData##suffix(u.u8, offset); \
376 TYPED_GETSET_IMPLEMENTATION(uint8_t, UInt, 8)
377 TYPED_GETSET_IMPLEMENTATION(int8_t, Int, 8)
378 TYPED_GETSET_IMPLEMENTATION(uint16_t, UInt, 16LE)
379 TYPED_GETSET_IMPLEMENTATION(uint16_t, UInt, 16BE)
380 TYPED_GETSET_IMPLEMENTATION(int16_t, Int, 16LE)
381 TYPED_GETSET_IMPLEMENTATION(int16_t, Int, 16BE)
382 TYPED_GETSET_IMPLEMENTATION(uint32_t, UInt, 32LE)
383 TYPED_GETSET_IMPLEMENTATION(uint32_t, UInt, 32BE)
384 TYPED_GETSET_IMPLEMENTATION(int32_t, Int, 32LE)
385 TYPED_GETSET_IMPLEMENTATION(int32_t, Int, 32BE)
386 TYPED_GETSET_IMPLEMENTATION(uint64_t, UInt, 64LE)
387 TYPED_GETSET_IMPLEMENTATION(uint64_t, UInt, 64BE)
388 TYPED_GETSET_IMPLEMENTATION(int64_t, Int, 64LE)
389 TYPED_GETSET_IMPLEMENTATION(int64_t, Int, 64BE)
391 TYPED_GETSET_IMPLEMENTATION(float, Float, 32LE)
392 TYPED_GETSET_IMPLEMENTATION(float, Float, 32BE)
393 TYPED_GETSET_IMPLEMENTATION(double, Float, 64LE)
394 TYPED_GETSET_IMPLEMENTATION(double, Float, 64BE)
396 #undef TYPED_GETSET_IMPLEMENTATION
399 static inline bool hostIsLittleEndian()
409 void ensureCapacity(unsigned capacity)
413 char* data = new char[capacity];
415 memcpy(data, _data, _size);
419 _capacity = capacity;
427 // A single attribute/parameter update blob
428 typedef std::pair<unsigned, RTIData> RTIIndexDataPair;
430 // A complete set of updates we received in one reflect/receive call
431 typedef std::list<RTIIndexDataPair> RTIIndexDataPairList;
433 /// Gets an own header at some time
435 class RTIBasicDataStream {
437 RTIBasicDataStream() : _offset(0) {}
439 /// Get aligned offset that aligns to a multiple of size
440 static inline unsigned getAlignedOffset(unsigned offset, unsigned size)
442 return ((offset + size - 1)/size) * size;
449 class HLADecodeStream : public RTIBasicDataStream {
451 HLADecodeStream(const RTIData& value) :
455 bool alignOffsetForSize(unsigned size)
457 _offset = getAlignedOffset(_offset, size);
458 return _offset <= _value.size();
461 bool skip(unsigned size)
464 return _offset <= _value.size();
468 { return _value.size() <= _offset; }
470 const RTIData& getData() const
473 #define TYPED_READ_IMPLEMENTATION(type, base, suffix) \
474 bool decode##base##suffix(type& value) \
476 if (_value.size() < _offset + sizeof(type)) \
478 value = _value.get##base##suffix(_offset); \
479 _offset += sizeof(type); \
483 TYPED_READ_IMPLEMENTATION(uint8_t, UInt, 8)
484 TYPED_READ_IMPLEMENTATION(int8_t, Int, 8)
485 TYPED_READ_IMPLEMENTATION(uint16_t, UInt, 16LE)
486 TYPED_READ_IMPLEMENTATION(uint16_t, UInt, 16BE)
487 TYPED_READ_IMPLEMENTATION(int16_t, Int, 16LE)
488 TYPED_READ_IMPLEMENTATION(int16_t, Int, 16BE)
489 TYPED_READ_IMPLEMENTATION(uint32_t, UInt, 32LE)
490 TYPED_READ_IMPLEMENTATION(uint32_t, UInt, 32BE)
491 TYPED_READ_IMPLEMENTATION(int32_t, Int, 32LE)
492 TYPED_READ_IMPLEMENTATION(int32_t, Int, 32BE)
493 TYPED_READ_IMPLEMENTATION(uint64_t, UInt, 64LE)
494 TYPED_READ_IMPLEMENTATION(uint64_t, UInt, 64BE)
495 TYPED_READ_IMPLEMENTATION(int64_t, Int, 64LE)
496 TYPED_READ_IMPLEMENTATION(int64_t, Int, 64BE)
498 TYPED_READ_IMPLEMENTATION(float, Float, 32LE)
499 TYPED_READ_IMPLEMENTATION(float, Float, 32BE)
500 TYPED_READ_IMPLEMENTATION(double, Float, 64LE)
501 TYPED_READ_IMPLEMENTATION(double, Float, 64BE)
503 #undef TYPED_READ_IMPLEMENTATION
506 const RTIData& _value;
509 class HLAEncodeStream : public RTIBasicDataStream {
511 HLAEncodeStream(RTIData& value) :
515 bool alignOffsetForSize(unsigned size)
517 _offset = getAlignedOffset(_offset, size);
518 _value.resize(_offset);
522 bool skip(unsigned size)
525 _value.resize(_offset);
530 { return _value.size() <= _offset; }
532 void setData(const RTIData& data)
535 #define TYPED_WRITE_IMPLEMENTATION(type, base, suffix) \
536 bool encode##base##suffix(type value) \
538 unsigned nextOffset = _offset + sizeof(type); \
539 _value.resize(nextOffset); \
540 _value.set##base##suffix(value, _offset); \
541 _offset = nextOffset; \
545 TYPED_WRITE_IMPLEMENTATION(uint8_t, UInt, 8)
546 TYPED_WRITE_IMPLEMENTATION(int8_t, Int, 8)
547 TYPED_WRITE_IMPLEMENTATION(uint16_t, UInt, 16LE)
548 TYPED_WRITE_IMPLEMENTATION(uint16_t, UInt, 16BE)
549 TYPED_WRITE_IMPLEMENTATION(int16_t, Int, 16LE)
550 TYPED_WRITE_IMPLEMENTATION(int16_t, Int, 16BE)
551 TYPED_WRITE_IMPLEMENTATION(uint32_t, UInt, 32LE)
552 TYPED_WRITE_IMPLEMENTATION(uint32_t, UInt, 32BE)
553 TYPED_WRITE_IMPLEMENTATION(int32_t, Int, 32LE)
554 TYPED_WRITE_IMPLEMENTATION(int32_t, Int, 32BE)
555 TYPED_WRITE_IMPLEMENTATION(uint64_t, UInt, 64LE)
556 TYPED_WRITE_IMPLEMENTATION(uint64_t, UInt, 64BE)
557 TYPED_WRITE_IMPLEMENTATION(int64_t, Int, 64LE)
558 TYPED_WRITE_IMPLEMENTATION(int64_t, Int, 64BE)
560 TYPED_WRITE_IMPLEMENTATION(float, Float, 32LE)
561 TYPED_WRITE_IMPLEMENTATION(float, Float, 32BE)
562 TYPED_WRITE_IMPLEMENTATION(double, Float, 64LE)
563 TYPED_WRITE_IMPLEMENTATION(double, Float, 64BE)
565 #undef TYPED_WRITE_IMPLEMENTATION
571 } // namespace simgear