Overte C++ Documentation
SerDes.h
1 //
2 // SerDes.h
3 //
4 //
5 // Created by Dale Glass on 5/6/2022
6 // Copyright 2024 Overte e.V.
7 //
8 // Distributed under the Apache License, Version 2.0.
9 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10 //
11 
12 #pragma once
13 #include <string>
14 #include <cstring>
15 #include <QtCore/QByteArray>
16 #include <QDebug>
17 #include <glm/glm.hpp>
18 
62  public:
63 
82  class SizeTracker {
83  public:
84  SizeTracker(DataSerializer &parent) : _parent(parent) {
85  _start_pos = _parent.pos();
86  }
87 
88  ~SizeTracker() {
89  size_t cur_pos = _parent.pos();
90 
91  if ( cur_pos >= _start_pos ) {
92  _parent._lastAdvance = cur_pos - _start_pos;
93  } else {
94  _parent._lastAdvance = 0;
95  }
96  }
97 
98  private:
99  DataSerializer &_parent;
100  size_t _start_pos = 0;
101  };
102 
108  static const int DEFAULT_SIZE = 1500;
109 
116  static const char PADDING_CHAR = (char)0xAA;
117 
126  _capacity = DEFAULT_SIZE;
127  _pos = 0;
128  _length = 0;
129  _store = new char[_capacity];
130  }
131 
144  DataSerializer(char *externalStore, size_t storeLength) {
145  _capacity = storeLength;
146  _length = 0;
147  _pos = 0;
148  _storeIsExternal = true;
149  _store = externalStore;
150  }
151 
163  DataSerializer(uint8_t *externalStore, size_t storeLength) : DataSerializer((char*)externalStore, storeLength) {
164 
165  }
166 
167  DataSerializer(const DataSerializer &) = delete;
168  DataSerializer &operator=(const DataSerializer &) = delete;
169 
170 
171 
172  ~DataSerializer() {
173  if (!_storeIsExternal) {
174  delete[] _store;
175  }
176  }
177 
187  void addPadding(size_t bytes) {
188  if (!extendBy(bytes, "padding")) {
189  return;
190  }
191 
192  // Fill padding with something recognizable. Will keep valgrind happier.
193  memset(&_store[_pos], PADDING_CHAR, bytes);
194  _pos += bytes;
195  }
196 
204  return *this << int8_t(c);
205  }
206 
214  if (!extendBy(1, "int8_t")) {
215  return *this;
216  }
217 
218  _store[_pos++] = c;
219  return *this;
220  }
221 
222 
224 
231  DataSerializer &operator<<(uint16_t val) {
232  return *this << int16_t(val);
233  }
234 
241  DataSerializer &operator<<(int16_t val) {
242  if (!extendBy(sizeof(val), "int16_t")) {
243  return *this;
244  }
245 
246  memcpy(&_store[_pos], (char*)&val, sizeof(val));
247  _pos += sizeof(val);
248  return *this;
249  }
250 
251 
252 
254 
261  DataSerializer &operator<<(uint32_t val) {
262  return *this << int32_t(val);
263  }
264 
271  DataSerializer &operator<<(int32_t val) {
272  if (!extendBy(sizeof(val), "int32_t")) {
273  return *this;
274  }
275 
276  memcpy(&_store[_pos], (char*)&val, sizeof(val));
277  _pos += sizeof(val);
278  return *this;
279  }
280 
282 
289  DataSerializer &operator<<(uint64_t val) {
290  return *this << int64_t(val);
291  }
292 
299  DataSerializer &operator<<(int64_t val) {
300  if (!extendBy(sizeof(val), "int64_t")) {
301  return *this;
302  }
303 
304  memcpy(&_store[_pos], (char*)&val, sizeof(val));
305  _pos += sizeof(val);
306  return *this;
307  }
308 
310 
318  if (extendBy(sizeof(val), "float")) {
319  memcpy(&_store[_pos], (char*)&val, sizeof(val));
320  _pos += sizeof(val);
321  }
322  return *this;
323  }
324 
325 
327 
328 
335  DataSerializer &operator<<(glm::vec3 val) {
336  size_t sz = sizeof(val.x);
337  if (extendBy(sz*3, "glm::vec3")) {
338  memcpy(&_store[_pos ], (char*)&val.x, sz);
339  memcpy(&_store[_pos + sz ], (char*)&val.y, sz);
340  memcpy(&_store[_pos + sz*2], (char*)&val.z, sz);
341 
342  _pos += sz*3;
343  }
344  return *this;
345  }
346 
348 
355  DataSerializer &operator<<(glm::vec4 val) {
356  size_t sz = sizeof(val.x);
357  if (extendBy(sz*4, "glm::vec4")) {
358  memcpy(&_store[_pos ], (char*)&val.x, sz);
359  memcpy(&_store[_pos + sz ], (char*)&val.y, sz);
360  memcpy(&_store[_pos + sz*2], (char*)&val.z, sz);
361  memcpy(&_store[_pos + sz*3], (char*)&val.w, sz);
362 
363  _pos += sz*4;
364  }
365  return *this;
366  }
367 
369 
376  DataSerializer &operator<<(glm::ivec2 val) {
377  size_t sz = sizeof(val.x);
378  if (extendBy(sz*2, "glm::ivec2")) {
379  memcpy(&_store[_pos ], (char*)&val.x, sz);
380  memcpy(&_store[_pos + sz ], (char*)&val.y, sz);
381 
382  _pos += sz*2;
383  }
384  return *this;
385  }
386 
387 
389 
398  DataSerializer &operator<<(const char *val) {
399  size_t len = strlen(val)+1;
400  if (extendBy(len, "string")) {
401  memcpy(&_store[_pos], val, len);
402  _pos += len;
403  }
404  return *this;
405  }
406 
415  DataSerializer &operator<<(const QString &val) {
416  return *this << val.toUtf8().constData();
417  }
418 
419 
421 
431  char *buffer() const { return _store; }
432 
438  size_t pos() const { return _pos; }
439 
445  size_t length() const { return _length; }
446 
456  size_t capacity() const { return _capacity; }
457 
464  bool isEmpty() const { return _length == 0; }
465 
474  bool isOverflow() const { return _overflow; }
475 
480  void rewind() { _pos = 0; _overflow = false; _lastAdvance = 0; }
481 
482 
491  size_t lastAdvance() const { return _lastAdvance; }
492 
503  friend QDebug operator<<(QDebug debug, const DataSerializer &ds);
504 
505  private:
506  bool extendBy(size_t bytes, const QString &type_name) {
507  //qDebug() << "Extend by" << bytes;
508 
509  if ( _capacity < _length + bytes) {
510  if ( _storeIsExternal ) {
511  qCritical() << "Serializer trying to write past end of output buffer of" << _capacity << "bytes. Error writing" << bytes << "bytes for" << type_name << " from position " << _pos << ", length " << _length;
512  _overflow = true;
513  return false;
514  }
515 
516  changeAllocation(_length + bytes);
517  }
518 
519  _length += bytes;
520  _lastAdvance = bytes;
521  return true;
522  }
523 
524  // This is split up here to try to make the class as inline-friendly as possible.
525  void changeAllocation(size_t new_size);
526 
527  char *_store;
528  bool _storeIsExternal = false;
529  bool _overflow = false;
530  size_t _capacity = 0;
531  size_t _length = 0;
532  size_t _pos = 0;
533  size_t _lastAdvance = 0;
534 };
535 
574  public:
575 
594  class SizeTracker {
595  public:
596  SizeTracker(DataDeserializer &parent) : _parent(parent) {
597  _start_pos = _parent.pos();
598  }
599 
600  ~SizeTracker() {
601  size_t cur_pos = _parent.pos();
602 
603  if ( cur_pos >= _start_pos ) {
604  _parent._lastAdvance = cur_pos - _start_pos;
605  } else {
606  _parent._lastAdvance = 0;
607  }
608  }
609 
610  private:
611  DataDeserializer &_parent;
612  size_t _start_pos = 0;
613  };
614 
621  DataDeserializer(const char *externalStore, size_t storeLength) {
622  _length = storeLength;
623  _pos = 0;
624  _store = externalStore;
625  _lastAdvance = 0;
626  }
627 
634  DataDeserializer(const uint8_t *externalStore, size_t storeLength) : DataDeserializer((const char*)externalStore, storeLength) {
635 
636  }
637 
645  DataDeserializer(const DataSerializer &serializer) : DataDeserializer(serializer.buffer(), serializer.length()) {
646 
647  }
648 
654  void skipPadding(size_t bytes) {
655  if (!canAdvanceBy(bytes, "padding")) {
656  return;
657  }
658 
659  _pos += bytes;
660  _lastAdvance = bytes;
661  }
662 
663 
671  return *this >> reinterpret_cast<int8_t&>(c);
672  }
673 
681  if ( canAdvanceBy(1, "int8_t") ) {
682  c = _store[_pos++];
683  _lastAdvance = sizeof(c);
684  }
685 
686  return *this;
687  }
688 
690 
697  DataDeserializer &operator>>(uint16_t &val) {
698  return *this >> reinterpret_cast<int16_t&>(val);
699  }
700 
707  DataDeserializer &operator>>(int16_t &val) {
708  if ( canAdvanceBy(sizeof(val), "int16_t") ) {
709  memcpy((char*)&val, &_store[_pos], sizeof(val));
710  _pos += sizeof(val);
711  _lastAdvance = sizeof(val);
712  }
713 
714  return *this;
715  }
716 
718 
725  DataDeserializer &operator>>(uint32_t &val) {
726  return *this >> reinterpret_cast<int32_t&>(val);
727  }
728 
735  DataDeserializer &operator>>(int32_t &val) {
736  if ( canAdvanceBy(sizeof(val), "int32_t") ) {
737  memcpy((char*)&val, &_store[_pos], sizeof(val));
738  _pos += sizeof(val);
739  _lastAdvance = sizeof(val);
740  }
741  return *this;
742  }
743 
745 
752  DataDeserializer &operator>>(uint64_t &val) {
753  return *this >> reinterpret_cast<int64_t&>(val);
754  }
755 
762  DataDeserializer &operator>>(int64_t &val) {
763  if ( canAdvanceBy(sizeof(val), "int64_t") ) {
764  memcpy((char*)&val, &_store[_pos], sizeof(val));
765  _pos += sizeof(val);
766  _lastAdvance = sizeof(val);
767  }
768  return *this;
769  }
770 
772 
773 
781  if ( canAdvanceBy(sizeof(val), "float") ) {
782  memcpy((char*)&val, &_store[_pos], sizeof(val));
783  _pos += sizeof(val);
784  _lastAdvance = sizeof(val);
785  }
786  return *this;
787  }
788 
790 
791 
792 
793 
800  DataDeserializer &operator>>(glm::vec3 &val) {
801  size_t sz = sizeof(val.x);
802 
803  if ( canAdvanceBy(sz*3, "glm::vec3") ) {
804  memcpy((char*)&val.x, &_store[_pos ], sz);
805  memcpy((char*)&val.y, &_store[_pos + sz ], sz);
806  memcpy((char*)&val.z, &_store[_pos + sz*2], sz);
807 
808  _pos += sz*3;
809  _lastAdvance = sz * 3;
810  }
811 
812  return *this;
813  }
814 
816 
817 
824  DataDeserializer &operator>>(glm::vec4 &val) {
825  size_t sz = sizeof(val.x);
826 
827  if ( canAdvanceBy(sz*4, "glm::vec4")) {
828  memcpy((char*)&val.x, &_store[_pos ], sz);
829  memcpy((char*)&val.y, &_store[_pos + sz ], sz);
830  memcpy((char*)&val.z, &_store[_pos + sz*2], sz);
831  memcpy((char*)&val.w, &_store[_pos + sz*3], sz);
832 
833  _pos += sz*4;
834  _lastAdvance = sz*4;
835  }
836  return *this;
837  }
838 
840 
841 
848  DataDeserializer &operator>>(glm::ivec2 &val) {
849  size_t sz = sizeof(val.x);
850 
851  if ( canAdvanceBy(sz*2, "glm::ivec2") ) {
852  memcpy((char*)&val.x, &_store[_pos ], sz);
853  memcpy((char*)&val.y, &_store[_pos + sz ], sz);
854 
855  _pos += sz*2;
856  _lastAdvance = sz * 2;
857  }
858 
859  return *this;
860  }
861 
863 
873  const char *buffer() const { return _store; }
874 
880  size_t pos() const { return _pos; }
881 
887  size_t length() const { return _length; }
888 
895  bool isEmpty() const { return _length == 0; }
896 
905  bool isOverflow() const { return _overflow; }
906 
911  void rewind() { _pos = 0; _overflow = false; _lastAdvance = 0; }
912 
921  size_t lastAdvance() const { return _lastAdvance; }
922 
933  friend QDebug operator<<(QDebug debug, const DataDeserializer &ds);
934 
935  private:
936  bool canAdvanceBy(size_t bytes, const QString &type_name) {
937  //qDebug() << "Checking advance by" << bytes;
938 
939  if ( _length < _pos + bytes) {
940  qCritical() << "Deserializer trying to read past end of input buffer of" << _length << "bytes, reading" << bytes << "bytes for" << type_name << "from position " << _pos;
941  _overflow = true;
942  return false;
943  }
944 
945  return true;
946  }
947 
948  const char *_store;
949  bool _overflow = false;
950  size_t _length = 0;
951  size_t _pos = 0;
952  size_t _lastAdvance = 0;
953 };
RAII tracker of advance position.
Definition: SerDes.h:594
Data deserializer.
Definition: SerDes.h:573
DataDeserializer & operator>>(int64_t &val)
Read an int64_t from the buffer.
Definition: SerDes.h:762
void rewind()
Reset the serializer to the start, clear overflow bit.
Definition: SerDes.h:911
DataDeserializer & operator>>(uint32_t &val)
Read an uint32_t from the buffer.
Definition: SerDes.h:725
DataDeserializer(const char *externalStore, size_t storeLength)
Construct a Deserializer *.
Definition: SerDes.h:621
DataDeserializer & operator>>(int16_t &val)
Read an int16_t from the buffer.
Definition: SerDes.h:707
DataDeserializer & operator>>(glm::vec3 &val)
Read a glm::vec3 from the buffer.
Definition: SerDes.h:800
friend QDebug operator<<(QDebug debug, const DataDeserializer &ds)
Dump the contents of this object into QDebug.
Definition: SerDes.cpp:62
DataDeserializer & operator>>(int32_t &val)
Read an int32_t from the buffer.
Definition: SerDes.h:735
size_t lastAdvance() const
Size of the last advance.
Definition: SerDes.h:921
void skipPadding(size_t bytes)
Skips padding in the input.
Definition: SerDes.h:654
bool isEmpty() const
Whether there's any data in the buffer.
Definition: SerDes.h:895
DataDeserializer & operator>>(float &val)
Read an float from the buffer.
Definition: SerDes.h:780
DataDeserializer(const DataSerializer &serializer)
Construct a new Deserializer reading data from a Serializer.
Definition: SerDes.h:645
DataDeserializer & operator>>(glm::ivec2 &val)
Read a glm::ivec2 from the buffer.
Definition: SerDes.h:848
DataDeserializer & operator>>(uint16_t &val)
Read an uint16_t from the buffer.
Definition: SerDes.h:697
DataDeserializer & operator>>(int8_t &c)
Read an int8_t from the buffer.
Definition: SerDes.h:680
bool isOverflow() const
The buffer size limit has been reached.
Definition: SerDes.h:905
DataDeserializer(const uint8_t *externalStore, size_t storeLength)
Construct a Deserializer.
Definition: SerDes.h:634
DataDeserializer & operator>>(uint64_t &val)
Read an uint64_t from the buffer.
Definition: SerDes.h:752
const char * buffer() const
Pointer to the start of the internal buffer.
Definition: SerDes.h:873
size_t length() const
Last position that was written to in the buffer. Starts at 0.
Definition: SerDes.h:887
DataDeserializer & operator>>(uint8_t &c)
Read an uint8_t from the buffer.
Definition: SerDes.h:670
DataDeserializer & operator>>(glm::vec4 &val)
Read a glm::vec4 from the buffer.
Definition: SerDes.h:824
size_t pos() const
Current position in the buffer. Starts at 0.
Definition: SerDes.h:880
RAII tracker of advance position.
Definition: SerDes.h:82
Data serializer.
Definition: SerDes.h:61
size_t lastAdvance() const
Size of the last advance.
Definition: SerDes.h:491
DataSerializer & operator<<(int16_t val)
Add an int16_t to the output.
Definition: SerDes.h:241
DataSerializer & operator<<(const char *val)
Write a null-terminated string into the buffer.
Definition: SerDes.h:398
DataSerializer & operator<<(uint16_t val)
Add an uint16_t to the output.
Definition: SerDes.h:231
DataSerializer & operator<<(glm::ivec2 val)
Add a glm::ivec2 to the output.
Definition: SerDes.h:376
DataSerializer & operator<<(glm::vec3 val)
Add an glm::vec3 to the output.
Definition: SerDes.h:335
void addPadding(size_t bytes)
Adds padding to the output.
Definition: SerDes.h:187
DataSerializer & operator<<(float val)
Add an float to the output.
Definition: SerDes.h:317
DataSerializer & operator<<(uint8_t c)
Add an uint8_t to the output.
Definition: SerDes.h:203
size_t pos() const
Current position in the buffer. Starts at 0.
Definition: SerDes.h:438
DataSerializer()
Construct a dynamically allocated serializer.
Definition: SerDes.h:125
DataSerializer & operator<<(uint64_t val)
Add an uint64_t to the output.
Definition: SerDes.h:289
bool isOverflow() const
The buffer size limit has been reached.
Definition: SerDes.h:474
static const int DEFAULT_SIZE
Default size for a dynamically allocated buffer.
Definition: SerDes.h:108
DataSerializer & operator<<(uint32_t val)
Add an uint32_t to the output.
Definition: SerDes.h:261
size_t length() const
Last position that was written to in the buffer. Starts at 0.
Definition: SerDes.h:445
size_t capacity() const
Current capacity of the buffer.
Definition: SerDes.h:456
DataSerializer & operator<<(int64_t val)
Add an int64_t to the output.
Definition: SerDes.h:299
static const char PADDING_CHAR
Character to use for padding.
Definition: SerDes.h:116
void rewind()
Reset the serializer to the start, clear overflow bit.
Definition: SerDes.h:480
DataSerializer & operator<<(int8_t c)
Add an int8_t to the output.
Definition: SerDes.h:213
DataSerializer & operator<<(const QString &val)
Write a QString into the buffer.
Definition: SerDes.h:415
bool isEmpty() const
Whether there's any data in the buffer.
Definition: SerDes.h:464
DataSerializer & operator<<(int32_t val)
Add an int32_t to the output.
Definition: SerDes.h:271
char * buffer() const
Pointer to the start of the internal buffer.
Definition: SerDes.h:431
DataSerializer(char *externalStore, size_t storeLength)
Construct a statically allocated serializer.
Definition: SerDes.h:144
DataSerializer & operator<<(glm::vec4 val)
Add a glm::vec4 to the output.
Definition: SerDes.h:355
DataSerializer(uint8_t *externalStore, size_t storeLength)
Construct a statically allocated serializer.
Definition: SerDes.h:163