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 /// Gets an own header at some time
436 class RTIBasicDataStream {
438 RTIBasicDataStream() : _offset(0) {}
440 /// Get aligned offset that aligns to a multiple of size
441 static inline unsigned getAlignedOffset(unsigned offset, unsigned size)
443 return ((offset + size - 1)/size) * size;
450 class HLADecodeStream : public RTIBasicDataStream {
452 HLADecodeStream(const RTIData& value) :
456 bool alignOffsetForSize(unsigned size)
458 _offset = getAlignedOffset(_offset, size);
459 return _offset <= _value.size();
462 bool skip(unsigned size)
465 return _offset <= _value.size();
469 { return _value.size() <= _offset; }
471 const RTIData& getData() const
474 #define TYPED_READ_IMPLEMENTATION(type, base, suffix) \
475 bool decode##base##suffix(type& value) \
477 if (_value.size() < _offset + sizeof(type)) \
479 value = _value.get##base##suffix(_offset); \
480 _offset += sizeof(type); \
484 TYPED_READ_IMPLEMENTATION(uint8_t, UInt, 8)
485 TYPED_READ_IMPLEMENTATION(int8_t, Int, 8)
486 TYPED_READ_IMPLEMENTATION(uint16_t, UInt, 16LE)
487 TYPED_READ_IMPLEMENTATION(uint16_t, UInt, 16BE)
488 TYPED_READ_IMPLEMENTATION(int16_t, Int, 16LE)
489 TYPED_READ_IMPLEMENTATION(int16_t, Int, 16BE)
490 TYPED_READ_IMPLEMENTATION(uint32_t, UInt, 32LE)
491 TYPED_READ_IMPLEMENTATION(uint32_t, UInt, 32BE)
492 TYPED_READ_IMPLEMENTATION(int32_t, Int, 32LE)
493 TYPED_READ_IMPLEMENTATION(int32_t, Int, 32BE)
494 TYPED_READ_IMPLEMENTATION(uint64_t, UInt, 64LE)
495 TYPED_READ_IMPLEMENTATION(uint64_t, UInt, 64BE)
496 TYPED_READ_IMPLEMENTATION(int64_t, Int, 64LE)
497 TYPED_READ_IMPLEMENTATION(int64_t, Int, 64BE)
499 TYPED_READ_IMPLEMENTATION(float, Float, 32LE)
500 TYPED_READ_IMPLEMENTATION(float, Float, 32BE)
501 TYPED_READ_IMPLEMENTATION(double, Float, 64LE)
502 TYPED_READ_IMPLEMENTATION(double, Float, 64BE)
504 #undef TYPED_READ_IMPLEMENTATION
507 const RTIData& _value;
510 class HLAEncodeStream : public RTIBasicDataStream {
512 HLAEncodeStream(RTIData& value) :
516 bool alignOffsetForSize(unsigned size)
518 _offset = getAlignedOffset(_offset, size);
519 _value.resize(_offset);
523 bool skip(unsigned size)
526 _value.resize(_offset);
531 { return _value.size() <= _offset; }
533 void setData(const RTIData& data)
536 #define TYPED_WRITE_IMPLEMENTATION(type, base, suffix) \
537 bool encode##base##suffix(type value) \
539 unsigned nextOffset = _offset + sizeof(type); \
540 _value.resize(nextOffset); \
541 _value.set##base##suffix(value, _offset); \
542 _offset = nextOffset; \
546 TYPED_WRITE_IMPLEMENTATION(uint8_t, UInt, 8)
547 TYPED_WRITE_IMPLEMENTATION(int8_t, Int, 8)
548 TYPED_WRITE_IMPLEMENTATION(uint16_t, UInt, 16LE)
549 TYPED_WRITE_IMPLEMENTATION(uint16_t, UInt, 16BE)
550 TYPED_WRITE_IMPLEMENTATION(int16_t, Int, 16LE)
551 TYPED_WRITE_IMPLEMENTATION(int16_t, Int, 16BE)
552 TYPED_WRITE_IMPLEMENTATION(uint32_t, UInt, 32LE)
553 TYPED_WRITE_IMPLEMENTATION(uint32_t, UInt, 32BE)
554 TYPED_WRITE_IMPLEMENTATION(int32_t, Int, 32LE)
555 TYPED_WRITE_IMPLEMENTATION(int32_t, Int, 32BE)
556 TYPED_WRITE_IMPLEMENTATION(uint64_t, UInt, 64LE)
557 TYPED_WRITE_IMPLEMENTATION(uint64_t, UInt, 64BE)
558 TYPED_WRITE_IMPLEMENTATION(int64_t, Int, 64LE)
559 TYPED_WRITE_IMPLEMENTATION(int64_t, Int, 64BE)
561 TYPED_WRITE_IMPLEMENTATION(float, Float, 32LE)
562 TYPED_WRITE_IMPLEMENTATION(float, Float, 32BE)
563 TYPED_WRITE_IMPLEMENTATION(double, Float, 64LE)
564 TYPED_WRITE_IMPLEMENTATION(double, Float, 64BE)
566 #undef TYPED_WRITE_IMPLEMENTATION
572 } // namespace simgear