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 swap(RTIData& data)
120 std::swap(_data, data._data);
121 std::swap(_size, data._size);
122 std::swap(_capacity, data._capacity);
125 void setData(char* data, unsigned size)
133 void setData(const char* data, unsigned size)
138 memcpy(_data, data, size);
140 void setData(const char* data)
145 size_t size = strlen(data) + 1;
150 RTIData& operator=(const RTIData& data)
152 unsigned size = data.size();
155 memcpy(_data, data.data(), size);
160 void getData8(char data[1], unsigned offset = 0) const
162 data[0] = _data[offset];
165 void setData8(const char data[1], unsigned offset = 0)
167 _data[offset] = data[0];
170 void getData16LE(char data[2], unsigned offset = 0) const
172 if (hostIsLittleEndian()) {
173 data[0] = _data[offset];
174 data[1] = _data[offset+1];
176 data[1] = _data[offset];
177 data[0] = _data[offset+1];
180 void setData16LE(const char data[2], unsigned offset = 0)
182 if (hostIsLittleEndian()) {
183 _data[offset] = data[0];
184 _data[offset+1] = data[1];
186 _data[offset] = data[1];
187 _data[offset+1] = data[0];
191 void getData16BE(char data[2], unsigned offset = 0) const
193 if (hostIsLittleEndian()) {
194 data[1] = _data[offset];
195 data[0] = _data[offset+1];
197 data[0] = _data[offset];
198 data[1] = _data[offset+1];
201 void setData16BE(const char data[2], unsigned offset = 0)
203 if (hostIsLittleEndian()) {
204 _data[offset] = data[1];
205 _data[offset+1] = data[0];
207 _data[offset] = data[0];
208 _data[offset+1] = data[1];
213 void getData32LE(char data[4], unsigned offset = 0) const
215 if (hostIsLittleEndian()) {
216 data[0] = _data[offset];
217 data[1] = _data[offset+1];
218 data[2] = _data[offset+2];
219 data[3] = _data[offset+3];
221 data[3] = _data[offset];
222 data[2] = _data[offset+1];
223 data[1] = _data[offset+2];
224 data[0] = _data[offset+3];
227 void setData32LE(const char data[4], unsigned offset = 0)
229 if (hostIsLittleEndian()) {
230 _data[offset] = data[0];
231 _data[offset+1] = data[1];
232 _data[offset+2] = data[2];
233 _data[offset+3] = data[3];
235 _data[offset] = data[3];
236 _data[offset+1] = data[2];
237 _data[offset+2] = data[1];
238 _data[offset+3] = data[0];
242 void getData32BE(char data[4], unsigned offset = 0) const
244 if (hostIsLittleEndian()) {
245 data[3] = _data[offset];
246 data[2] = _data[offset+1];
247 data[1] = _data[offset+2];
248 data[0] = _data[offset+3];
250 data[0] = _data[offset];
251 data[1] = _data[offset+1];
252 data[2] = _data[offset+2];
253 data[3] = _data[offset+3];
256 void setData32BE(const char data[4], unsigned offset = 0)
258 if (hostIsLittleEndian()) {
259 _data[offset] = data[3];
260 _data[offset+1] = data[2];
261 _data[offset+2] = data[1];
262 _data[offset+3] = data[0];
264 _data[offset] = data[0];
265 _data[offset+1] = data[1];
266 _data[offset+2] = data[2];
267 _data[offset+3] = data[3];
272 void getData64LE(char data[8], unsigned offset = 0) const
274 if (hostIsLittleEndian()) {
275 data[0] = _data[offset];
276 data[1] = _data[offset+1];
277 data[2] = _data[offset+2];
278 data[3] = _data[offset+3];
279 data[4] = _data[offset+4];
280 data[5] = _data[offset+5];
281 data[6] = _data[offset+6];
282 data[7] = _data[offset+7];
284 data[7] = _data[offset];
285 data[6] = _data[offset+1];
286 data[5] = _data[offset+2];
287 data[4] = _data[offset+3];
288 data[3] = _data[offset+4];
289 data[2] = _data[offset+5];
290 data[1] = _data[offset+6];
291 data[0] = _data[offset+7];
294 void setData64LE(const char data[8], unsigned offset = 0)
296 if (hostIsLittleEndian()) {
297 _data[offset] = data[0];
298 _data[offset+1] = data[1];
299 _data[offset+2] = data[2];
300 _data[offset+3] = data[3];
301 _data[offset+4] = data[4];
302 _data[offset+5] = data[5];
303 _data[offset+6] = data[6];
304 _data[offset+7] = data[7];
306 _data[offset] = data[7];
307 _data[offset+1] = data[6];
308 _data[offset+2] = data[5];
309 _data[offset+3] = data[4];
310 _data[offset+4] = data[3];
311 _data[offset+5] = data[2];
312 _data[offset+6] = data[1];
313 _data[offset+7] = data[0];
317 void getData64BE(char data[8], unsigned offset = 0) const
319 if (hostIsLittleEndian()) {
320 data[7] = _data[offset];
321 data[6] = _data[offset+1];
322 data[5] = _data[offset+2];
323 data[4] = _data[offset+3];
324 data[3] = _data[offset+4];
325 data[2] = _data[offset+5];
326 data[1] = _data[offset+6];
327 data[0] = _data[offset+7];
329 data[0] = _data[offset];
330 data[1] = _data[offset+1];
331 data[2] = _data[offset+2];
332 data[3] = _data[offset+3];
333 data[4] = _data[offset+4];
334 data[5] = _data[offset+5];
335 data[6] = _data[offset+6];
336 data[7] = _data[offset+7];
339 void setData64BE(const char data[8], unsigned offset = 0)
341 if (hostIsLittleEndian()) {
342 _data[offset] = data[7];
343 _data[offset+1] = data[6];
344 _data[offset+2] = data[5];
345 _data[offset+3] = data[4];
346 _data[offset+4] = data[3];
347 _data[offset+5] = data[2];
348 _data[offset+6] = data[1];
349 _data[offset+7] = data[0];
351 _data[offset] = data[0];
352 _data[offset+1] = data[1];
353 _data[offset+2] = data[2];
354 _data[offset+3] = data[3];
355 _data[offset+4] = data[4];
356 _data[offset+5] = data[5];
357 _data[offset+6] = data[6];
358 _data[offset+7] = data[7];
363 #define TYPED_GETSET_IMPLEMENTATION(type, base, suffix) \
364 type get##base##suffix(unsigned offset = 0) const \
368 char u8[sizeof(type)]; \
370 getData##suffix(u.u8, offset); \
373 void set##base##suffix(type value, unsigned offset = 0) \
377 char u8[sizeof(type)]; \
380 setData##suffix(u.u8, offset); \
383 TYPED_GETSET_IMPLEMENTATION(uint8_t, UInt, 8)
384 TYPED_GETSET_IMPLEMENTATION(int8_t, Int, 8)
385 TYPED_GETSET_IMPLEMENTATION(uint16_t, UInt, 16LE)
386 TYPED_GETSET_IMPLEMENTATION(uint16_t, UInt, 16BE)
387 TYPED_GETSET_IMPLEMENTATION(int16_t, Int, 16LE)
388 TYPED_GETSET_IMPLEMENTATION(int16_t, Int, 16BE)
389 TYPED_GETSET_IMPLEMENTATION(uint32_t, UInt, 32LE)
390 TYPED_GETSET_IMPLEMENTATION(uint32_t, UInt, 32BE)
391 TYPED_GETSET_IMPLEMENTATION(int32_t, Int, 32LE)
392 TYPED_GETSET_IMPLEMENTATION(int32_t, Int, 32BE)
393 TYPED_GETSET_IMPLEMENTATION(uint64_t, UInt, 64LE)
394 TYPED_GETSET_IMPLEMENTATION(uint64_t, UInt, 64BE)
395 TYPED_GETSET_IMPLEMENTATION(int64_t, Int, 64LE)
396 TYPED_GETSET_IMPLEMENTATION(int64_t, Int, 64BE)
398 TYPED_GETSET_IMPLEMENTATION(float, Float, 32LE)
399 TYPED_GETSET_IMPLEMENTATION(float, Float, 32BE)
400 TYPED_GETSET_IMPLEMENTATION(double, Float, 64LE)
401 TYPED_GETSET_IMPLEMENTATION(double, Float, 64BE)
403 #undef TYPED_GETSET_IMPLEMENTATION
406 static inline bool hostIsLittleEndian()
416 void ensureCapacity(unsigned capacity)
420 char* data = new char[capacity];
422 memcpy(data, _data, _size);
426 _capacity = capacity;
434 // A single attribute/parameter update blob
435 typedef std::pair<unsigned, RTIData> RTIIndexDataPair;
437 // A complete set of updates we received in one reflect/receive call
438 typedef std::list<RTIIndexDataPair> RTIIndexDataPairList;
440 /// Gets an own header at some time
442 class RTIBasicDataStream {
444 RTIBasicDataStream() : _offset(0) {}
446 /// Get aligned offset that aligns to a multiple of size
447 static inline unsigned getAlignedOffset(unsigned offset, unsigned size)
449 return ((offset + size - 1)/size) * size;
456 class HLADecodeStream : public RTIBasicDataStream {
458 HLADecodeStream(const RTIData& value) :
462 bool alignOffsetForSize(unsigned size)
464 _offset = getAlignedOffset(_offset, size);
465 return _offset <= _value.size();
468 bool skip(unsigned size)
471 return _offset <= _value.size();
475 { return _value.size() <= _offset; }
477 const RTIData& getData() const
480 #define TYPED_READ_IMPLEMENTATION(type, base, suffix) \
481 bool decode##base##suffix(type& value) \
483 if (_value.size() < _offset + sizeof(type)) \
485 value = _value.get##base##suffix(_offset); \
486 _offset += sizeof(type); \
490 TYPED_READ_IMPLEMENTATION(uint8_t, UInt, 8)
491 TYPED_READ_IMPLEMENTATION(int8_t, Int, 8)
492 TYPED_READ_IMPLEMENTATION(uint16_t, UInt, 16LE)
493 TYPED_READ_IMPLEMENTATION(uint16_t, UInt, 16BE)
494 TYPED_READ_IMPLEMENTATION(int16_t, Int, 16LE)
495 TYPED_READ_IMPLEMENTATION(int16_t, Int, 16BE)
496 TYPED_READ_IMPLEMENTATION(uint32_t, UInt, 32LE)
497 TYPED_READ_IMPLEMENTATION(uint32_t, UInt, 32BE)
498 TYPED_READ_IMPLEMENTATION(int32_t, Int, 32LE)
499 TYPED_READ_IMPLEMENTATION(int32_t, Int, 32BE)
500 TYPED_READ_IMPLEMENTATION(uint64_t, UInt, 64LE)
501 TYPED_READ_IMPLEMENTATION(uint64_t, UInt, 64BE)
502 TYPED_READ_IMPLEMENTATION(int64_t, Int, 64LE)
503 TYPED_READ_IMPLEMENTATION(int64_t, Int, 64BE)
505 TYPED_READ_IMPLEMENTATION(float, Float, 32LE)
506 TYPED_READ_IMPLEMENTATION(float, Float, 32BE)
507 TYPED_READ_IMPLEMENTATION(double, Float, 64LE)
508 TYPED_READ_IMPLEMENTATION(double, Float, 64BE)
510 #undef TYPED_READ_IMPLEMENTATION
513 const RTIData& _value;
516 class HLAEncodeStream : public RTIBasicDataStream {
518 HLAEncodeStream(RTIData& value) :
522 bool alignOffsetForSize(unsigned size)
524 _offset = getAlignedOffset(_offset, size);
525 _value.resize(_offset);
529 bool skip(unsigned size)
532 _value.resize(_offset);
537 { return _value.size() <= _offset; }
539 void setData(const RTIData& data)
542 #define TYPED_WRITE_IMPLEMENTATION(type, base, suffix) \
543 bool encode##base##suffix(type value) \
545 unsigned nextOffset = _offset + sizeof(type); \
546 _value.resize(nextOffset); \
547 _value.set##base##suffix(value, _offset); \
548 _offset = nextOffset; \
552 TYPED_WRITE_IMPLEMENTATION(uint8_t, UInt, 8)
553 TYPED_WRITE_IMPLEMENTATION(int8_t, Int, 8)
554 TYPED_WRITE_IMPLEMENTATION(uint16_t, UInt, 16LE)
555 TYPED_WRITE_IMPLEMENTATION(uint16_t, UInt, 16BE)
556 TYPED_WRITE_IMPLEMENTATION(int16_t, Int, 16LE)
557 TYPED_WRITE_IMPLEMENTATION(int16_t, Int, 16BE)
558 TYPED_WRITE_IMPLEMENTATION(uint32_t, UInt, 32LE)
559 TYPED_WRITE_IMPLEMENTATION(uint32_t, UInt, 32BE)
560 TYPED_WRITE_IMPLEMENTATION(int32_t, Int, 32LE)
561 TYPED_WRITE_IMPLEMENTATION(int32_t, Int, 32BE)
562 TYPED_WRITE_IMPLEMENTATION(uint64_t, UInt, 64LE)
563 TYPED_WRITE_IMPLEMENTATION(uint64_t, UInt, 64BE)
564 TYPED_WRITE_IMPLEMENTATION(int64_t, Int, 64LE)
565 TYPED_WRITE_IMPLEMENTATION(int64_t, Int, 64BE)
567 TYPED_WRITE_IMPLEMENTATION(float, Float, 32LE)
568 TYPED_WRITE_IMPLEMENTATION(float, Float, 32BE)
569 TYPED_WRITE_IMPLEMENTATION(double, Float, 64LE)
570 TYPED_WRITE_IMPLEMENTATION(double, Float, 64BE)
572 #undef TYPED_WRITE_IMPLEMENTATION
578 } // namespace simgear