SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
simpleserializer.cpp
Go to the documentation of this file.
1 #include <stdint.h>
3 
4 #if __WORDSIZE == 64
5 #define PRINTF_FORMAT_S32 "%d"
6 #define PRINTF_FORMAT_U32 "%u"
7 #define PRINTF_FORMAT_S64 "%d"
8 #define PRINTF_FORMAT_U64 "%u"
9 #else
10 #define PRINTF_FORMAT_S32 "%d"
11 #define PRINTF_FORMAT_U32 "%u"
12 #define PRINTF_FORMAT_S64 "%lld"
13 #define PRINTF_FORMAT_U64 "%llu"
14 #endif
15 
16 template <bool> struct Assert { };
17 typedef Assert<(bool(sizeof(float) == 4))> float_must_be_32_bits[bool(sizeof(float) == 4) ? 1 : -1];
18 typedef Assert<(bool(sizeof(double) == 8))> double_must_be_64_bits[bool(sizeof(double) == 8) ? 1 : -1];
19 
21  m_data(),
22  m_finalized(false)
23 {
24  m_data.reserve(100);
25 
26  // write version information
27  int length;
28  if(version >= (1 << 24))
29  length = 4;
30  else if(version >= (1 << 16))
31  length = 3;
32  else if(version >= (1 << 8))
33  length = 2;
34  else if(version > 0)
35  length = 1;
36  else length = 0;
37  if(!writeTag(TVersion, 0, length))
38  return;
39  length--;
40  for(int i = length; i >= 0; i--)
41  m_data.push_back((char)((version >> (i * 8)) & 0xff));
42 }
43 
44 void SimpleSerializer::writeS32(quint32 id, qint32 value)
45 {
46  int length;
47 
48  if(id == 0) {
49  qCritical("SimpleSerializer: ID 0 is not allowed");
50  return;
51  }
52 
53  if((value < -(1 << 23)) || (value >= (1 << 23)))
54  length = 4;
55  else if((value < -(1 << 15)) || (value >= (1 << 15)))
56  length = 3;
57  else if((value < -(1 << 7)) || (value >= (1 << 7)))
58  length = 2;
59  else if(value != 0)
60  length = 1;
61  else length = 0;
62 
63  if(!writeTag(TSigned32, id, length))
64  return;
65 
66  length--;
67  for(int i = length; i >= 0; i--)
68  m_data.push_back((char)((value >> (i * 8)) & 0xff));
69 }
70 
71 void SimpleSerializer::writeU32(quint32 id, quint32 value)
72 {
73  int length;
74 
75  if(id == 0) {
76  qCritical("SimpleSerializer: ID 0 is not allowed");
77  return;
78  }
79 
80  if(value >= (1 << 24))
81  length = 4;
82  else if(value >= (1 << 16))
83  length = 3;
84  else if(value >= (1 << 8))
85  length = 2;
86  else if(value > 0)
87  length = 1;
88  else length = 0;
89 
90  if(!writeTag(TUnsigned32, id, length))
91  return;
92 
93  length--;
94  for(int i = length; i >= 0; i--)
95  m_data.push_back((char)((value >> (i * 8)) & 0xff));
96 }
97 
98 void SimpleSerializer::writeS64(quint32 id, qint64 value)
99 {
100  int length;
101 
102  if(id == 0) {
103  qCritical("SimpleSerializer: ID 0 is not allowed");
104  return;
105  }
106 
107  if((value < -(1ll << 55)) || (value >= (1ll << 55)))
108  length = 8;
109  else if((value < -(1ll << 47)) || (value >= (1ll << 47)))
110  length = 7;
111  else if((value < -(1ll << 39)) || (value >= (1ll << 39)))
112  length = 6;
113  else if((value < -(1ll << 31)) || (value >= (1ll << 31)))
114  length = 5;
115  else if((value < -(1ll << 23)) || (value >= (1ll << 23)))
116  length = 4;
117  else if((value < -(1ll << 15)) || (value >= (1ll << 15)))
118  length = 3;
119  else if((value < -(1ll << 7)) || (value >= (1ll << 7)))
120  length = 2;
121  else if(value != 0)
122  length = 1;
123  else length = 0;
124 
125  if(!writeTag(TSigned64, id, length))
126  return;
127 
128  length--;
129  for(int i = length; i >= 0; i--)
130  m_data.push_back((char)((value >> (i * 8)) & 0xff));
131 }
132 
133 void SimpleSerializer::writeU64(quint32 id, quint64 value)
134 {
135  int length;
136 
137  if(id == 0) {
138  qCritical("SimpleSerializer: ID 0 is not allowed");
139  return;
140  }
141 
142  if(value >= (1ll << 56))
143  length = 8;
144  else if(value >= (1ll << 48))
145  length = 7;
146  else if(value >= (1ll << 40))
147  length = 6;
148  else if(value >= (1ll << 32))
149  length = 5;
150  else if(value >= (1ll << 24))
151  length = 4;
152  else if(value >= (1ll << 16))
153  length = 3;
154  else if(value >= (1ll << 8))
155  length = 2;
156  else if(value > 0)
157  length = 1;
158  else length = 0;
159 
160  if(!writeTag(TUnsigned64, id, length))
161  return;
162 
163  length--;
164  for(int i = length; i >= 0; i--)
165  m_data.push_back((char)((value >> (i * 8)) & 0xff));
166 }
167 
168 union floatasint {
169  quint32 u;
170  float f;
171 };
172 
173 void SimpleSerializer::writeFloat(quint32 id, float value)
174 {
175  union floatasint tmp;
176  if(id == 0) {
177  qCritical("SimpleSerializer: ID 0 is not allowed");
178  return;
179  }
180 
181  if(!writeTag(TFloat, id, 4))
182  return;
183 
184  tmp.f = value;
185  m_data.push_back((char)((tmp.u >> 24) & 0xff));
186  m_data.push_back((char)((tmp.u >> 16) & 0xff));
187  m_data.push_back((char)((tmp.u >> 8) & 0xff));
188  m_data.push_back((char)(tmp.u & 0xff));
189 }
190 
191 union doubleasint {
192  quint64 u;
193  double d;
194 };
195 
196 void SimpleSerializer::writeDouble(quint32 id, double value)
197 {
198  union doubleasint tmp;
199  if(id == 0) {
200  qCritical("SimpleSerializer: ID 0 is not allowed");
201  return;
202  }
203 
204  if(!writeTag(TDouble, id, 8))
205  return;
206 
207  tmp.d = value;
208  m_data.push_back((char)((tmp.u >> 56) & 0xff));
209  m_data.push_back((char)((tmp.u >> 48) & 0xff));
210  m_data.push_back((char)((tmp.u >> 40) & 0xff));
211  m_data.push_back((char)((tmp.u >> 32) & 0xff));
212  m_data.push_back((char)((tmp.u >> 24) & 0xff));
213  m_data.push_back((char)((tmp.u >> 16) & 0xff));
214  m_data.push_back((char)((tmp.u >> 8) & 0xff));
215  m_data.push_back((char)(tmp.u & 0xff));
216 }
217 
218 void SimpleSerializer::writeBool(quint32 id, bool value)
219 {
220  if(id == 0) {
221  qCritical("SimpleSerializer: ID 0 is not allowed");
222  return;
223  }
224 
225  if(!writeTag(TBool, id, 1))
226  return;
227  if(value)
228  m_data.push_back((char)0x01);
229  else m_data.push_back((char)0x00);
230 }
231 
232 void SimpleSerializer::writeString(quint32 id, const QString& value)
233 {
234  if(id == 0) {
235  qCritical("SimpleSerializer: ID 0 is not allowed");
236  return;
237  }
238 
239  QByteArray utf8 = value.toUtf8();
240  if(!writeTag(TString, id, utf8.size()))
241  return;
242  m_data.append(utf8);
243 }
244 
245 void SimpleSerializer::writeBlob(quint32 id, const QByteArray& value)
246 {
247  if(id == 0) {
248  qCritical("SimpleSerializer: ID 0 is not allowed");
249  return;
250  }
251 
252  if(!writeTag(TBlob, id, value.size()))
253  return;
254  m_data.append(value);
255 }
256 
257 const QByteArray& SimpleSerializer::final()
258 {
259  m_finalized = true;
260  return m_data;
261 }
262 
263 bool SimpleSerializer::writeTag(Type type, quint32 id, quint32 length)
264 {
265  if(m_finalized) {
266  qCritical("SimpleSerializer: config has already been finalized (id %u)", id);
267  return false;
268  }
269 
270  int idLen;
271  int lengthLen;
272 
273  if(id < (1 << 8))
274  idLen = 0;
275  else if(id < (1 << 16))
276  idLen = 1;
277  else if(id < (1 << 24))
278  idLen = 2;
279  else idLen = 3;
280 
281  if(length < (1 << 8))
282  lengthLen = 0;
283  else if(length < (1 << 16))
284  lengthLen = 1;
285  else if(length < (1 << 24))
286  lengthLen = 2;
287  else lengthLen = 3;
288 
289  m_data.push_back((char)((type << 4) | (idLen << 2) | lengthLen));
290  for(int i = idLen; i >= 0; i--)
291  m_data.push_back((char)((id >> (i * 8)) & 0xff));
292  for(int i = lengthLen; i >= 0; i--)
293  m_data.push_back((char)((length >> (i * 8)) & 0xff));
294  return true;
295 }
296 
297 SimpleDeserializer::SimpleDeserializer(const QByteArray& data) :
298  m_data(data)
299 {
300  m_valid = parseAll();
301 
302  // read version information
303  uint readOfs;
304  Elements::const_iterator it = m_elements.constFind(0);
305  if(it == m_elements.constEnd())
306  goto setInvalid;
307  if(it->type != TVersion)
308  goto setInvalid;
309  if(it->length > 4)
310  goto setInvalid;
311 
312  readOfs = it->ofs;
313  m_version = 0;
314  for(uint i = 0; i < it->length; i++)
315  m_version = (m_version << 8) | readByte(&readOfs);
316  return;
317 
318 setInvalid:
319  m_valid = false;
320 }
321 
322 bool SimpleDeserializer::readS32(quint32 id, qint32* result, qint32 def) const
323 {
324  uint readOfs;
325  qint32 tmp;
326  Elements::const_iterator it = m_elements.constFind(id);
327  if(it == m_elements.constEnd())
328  goto returnDefault;
329  if(it->type != TSigned32)
330  goto returnDefault;
331  if(it->length > 4)
332  goto returnDefault;
333 
334  readOfs = it->ofs;
335  tmp = 0;
336  for(uint i = 0; i < it->length; i++) {
337  quint8 byte = readByte(&readOfs);
338  if((i == 0) && (byte & 0x80))
339  tmp = -1;
340  tmp = (tmp << 8) | byte;
341  }
342  *result = tmp;
343  return true;
344 
345 returnDefault:
346  *result = def;
347  return false;
348 }
349 
350 bool SimpleDeserializer::readU32(quint32 id, quint32* result, quint32 def) const
351 {
352  uint readOfs;
353  quint32 tmp;
354  Elements::const_iterator it = m_elements.constFind(id);
355  if(it == m_elements.constEnd())
356  goto returnDefault;
357  if(it->type != TUnsigned32)
358  goto returnDefault;
359  if(it->length > 4)
360  goto returnDefault;
361 
362  readOfs = it->ofs;
363  tmp = 0;
364  for(uint i = 0; i < it->length; i++)
365  tmp = (tmp << 8) | readByte(&readOfs);
366  *result = tmp;
367  return true;
368 
369 returnDefault:
370  *result = def;
371  return false;
372 }
373 
374 bool SimpleDeserializer::readS64(quint32 id, qint64* result, qint64 def) const
375 {
376  uint readOfs;
377  qint64 tmp;
378  Elements::const_iterator it = m_elements.constFind(id);
379  if(it == m_elements.constEnd())
380  goto returnDefault;
381  if(it->type != TSigned64)
382  goto returnDefault;
383  if(it->length > 8)
384  goto returnDefault;
385 
386  readOfs = it->ofs;
387  tmp = 0;
388  for(uint i = 0; i < it->length; i++) {
389  quint8 byte = readByte(&readOfs);
390  if((i == 0) && (byte & 0x80))
391  tmp = -1;
392  tmp = (tmp << 8) | byte;
393  }
394  *result = tmp;
395  return true;
396 
397 returnDefault:
398  *result = def;
399  return false;
400 }
401 
402 bool SimpleDeserializer::readU64(quint32 id, quint64* result, quint64 def) const
403 {
404  uint readOfs;
405  quint64 tmp;
406  Elements::const_iterator it = m_elements.constFind(id);
407  if(it == m_elements.constEnd())
408  goto returnDefault;
409  if(it->type != TUnsigned64)
410  goto returnDefault;
411  if(it->length > 8)
412  goto returnDefault;
413 
414  readOfs = it->ofs;
415  tmp = 0;
416  for(uint i = 0; i < it->length; i++)
417  tmp = (tmp << 8) | readByte(&readOfs);
418  *result = tmp;
419  return true;
420 
421 returnDefault:
422  *result = def;
423  return false;
424 }
425 
426 bool SimpleDeserializer::readFloat(quint32 id, float* result, float def) const
427 {
428  uint readOfs;
429  union floatasint tmp;
430  Elements::const_iterator it = m_elements.constFind(id);
431  if(it == m_elements.constEnd())
432  goto returnDefault;
433  if(it->type != TFloat)
434  goto returnDefault;
435  if(it->length != 4)
436  goto returnDefault;
437 
438  readOfs = it->ofs;
439  tmp.u = 0;
440  for(int i = 0; i < 4; i++)
441  tmp.u = (tmp.u << 8) | readByte(&readOfs);
442  *result = tmp.f;
443  return true;
444 
445 returnDefault:
446  *result = def;
447  return false;
448 }
449 
450 bool SimpleDeserializer::readDouble(quint32 id, double* result, double def) const
451 {
452  uint readOfs;
453  union doubleasint tmp;
454  Elements::const_iterator it = m_elements.constFind(id);
455  if(it == m_elements.constEnd())
456  goto returnDefault;
457  if(it->type != TDouble)
458  goto returnDefault;
459  if(it->length != 8)
460  goto returnDefault;
461 
462  readOfs = it->ofs;
463  tmp.u = 0;
464  for(int i = 0; i < 8; i++)
465  tmp.u = (tmp.u << 8) | readByte(&readOfs);
466  *result = tmp.d;
467  return true;
468 
469 returnDefault:
470  *result = def;
471  return false;
472 }
473 
474 union real4asint {
475  quint32 u;
477 };
478 
479 union real8asint {
480  quint64 u;
482 };
483 
484 bool SimpleDeserializer::readReal(quint32 id, Real* result, Real def) const
485 {
486  if(sizeof(Real) == 4) {
487  uint readOfs;
488  union real4asint tmp;
489  Elements::const_iterator it = m_elements.constFind(id);
490  if(it == m_elements.constEnd())
491  goto returnDefault32;
492  if(it->type != TFloat)
493  goto returnDefault32;
494  if(it->length != 4)
495  goto returnDefault32;
496 
497  readOfs = it->ofs;
498  tmp.u = 0;
499  for(int i = 0; i < 4; i++)
500  tmp.u = (tmp.u << 8) | readByte(&readOfs);
501  *result = tmp.r;
502  return true;
503 
504  returnDefault32:
505  *result = def;
506  return false;
507  } else {
508  uint readOfs;
509  union real8asint tmp;
510  Elements::const_iterator it = m_elements.constFind(id);
511  if(it == m_elements.constEnd())
512  goto returnDefault64;
513  if(it->type != TDouble)
514  goto returnDefault64;
515  if(it->length != 8)
516  goto returnDefault64;
517 
518  readOfs = it->ofs;
519  tmp.u = 0;
520  for(int i = 0; i < 8; i++)
521  tmp.u = (tmp.u << 8) | readByte(&readOfs);
522  *result = tmp.r;
523  return true;
524 
525  returnDefault64:
526  *result = def;
527  return false;
528  }
529 }
530 
531 bool SimpleDeserializer::readBool(quint32 id, bool* result, bool def) const
532 {
533  uint readOfs;
534  quint8 tmp;
535  Elements::const_iterator it = m_elements.constFind(id);
536  if(it == m_elements.constEnd())
537  goto returnDefault;
538  if(it->type != TBool)
539  goto returnDefault;
540  if(it->length != 1)
541  goto returnDefault;
542 
543  readOfs = it->ofs;
544  tmp = readByte(&readOfs);
545  if(tmp == 0x00)
546  *result = false;
547  else *result = true;
548  return true;
549 
550 returnDefault:
551  *result = def;
552  return false;
553 }
554 
555 bool SimpleDeserializer::readString(quint32 id, QString* result, const QString& def) const
556 {
557  Elements::const_iterator it = m_elements.constFind(id);
558  if(it == m_elements.constEnd())
559  goto returnDefault;
560  if(it->type != TString)
561  goto returnDefault;
562 
563  *result = QString::fromUtf8(m_data.data() + it->ofs, it->length);
564  return true;
565 
566 returnDefault:
567  *result = def;
568  return false;
569 }
570 
571 bool SimpleDeserializer::readBlob(quint32 id, QByteArray* result, const QByteArray& def) const
572 {
573  Elements::const_iterator it = m_elements.constFind(id);
574  if(it == m_elements.constEnd())
575  goto returnDefault;
576  if(it->type != TBlob)
577  goto returnDefault;
578 
579  *result = QByteArray(m_data.data() + it->ofs, it->length);
580  return true;
581 
582 returnDefault:
583  *result = def;
584  return false;
585 }
586 
588 {
589  if(!m_valid) {
590  qDebug("SimpleDeserializer dump: data invalid");
591  return;
592  } else {
593  qDebug("SimpleDeserializer dump: version %u", m_version);
594  }
595 
596  for(Elements::const_iterator it = m_elements.constBegin(); it != m_elements.constEnd(); ++it) {
597  switch(it->type) {
598  case TSigned32: {
599  qint32 tmp;
600  readS32(it.key(), &tmp);
601  qDebug("id %d, S32, len %d: " PRINTF_FORMAT_S32, it.key(), it->length, tmp);
602  break;
603  }
604  case TUnsigned32: {
605  quint32 tmp;
606  readU32(it.key(), &tmp);
607  qDebug("id %d, U32, len %d: " PRINTF_FORMAT_U32, it.key(), it->length, tmp);
608  break;
609  }
610  case TSigned64: {
611  qint64 tmp;
612  readS64(it.key(), &tmp);
613 // qDebug("id %d, S64, len %d: " PRINTF_FORMAT_S64, it.key(), it->length, (int)tmp);
614  break;
615  }
616  case TUnsigned64: {
617  quint64 tmp;
618  readU64(it.key(), &tmp);
619 // qDebug("id %d, U64, len %d: " PRINTF_FORMAT_U64, it.key(), it->length, (uint)tmp);
620  break;
621  }
622  case TFloat: {
623  float tmp;
624  readFloat(it.key(), &tmp);
625  qDebug("id %d, FLOAT, len %d: %f", it.key(), it->length, tmp);
626  break;
627  }
628  case TDouble: {
629  double tmp;
630  readDouble(it.key(), &tmp);
631  qDebug("id %d, DOUBLE, len %d: %f", it.key(), it->length, tmp);
632  break;
633  }
634  case TBool: {
635  bool tmp;
636  readBool(it.key(), &tmp);
637  qDebug("id %d, BOOL, len %d: %s", it.key(), it->length, tmp ? "true" : "false");
638  break;
639  }
640  case TString: {
641  QString tmp;
642  readString(it.key(), &tmp);
643  qDebug("id %d, STRING, len %d: \"%s\"", it.key(), it->length, qPrintable(tmp));
644  break;
645  }
646  case TBlob: {
647  QByteArray tmp;
648  readBlob(it.key(), &tmp);
649  qDebug("id %d, BLOB, len %d", it.key(), it->length);
650  break;
651  }
652  case TVersion: {
653  qDebug("id %d, VERSION, len %d", it.key(), it->length);
654  break;
655  }
656  default: {
657  qDebug("id %d, UNKNOWN TYPE 0x%02x, len %d", it.key(), it->type, it->length);
658  break;
659  }
660  }
661  }
662 }
663 
665 {
666  uint readOfs = 0;
667  Type type;
668  quint32 id;
669  quint32 length;
670 
671  /*
672  QString hex;
673  for(int i = 0; i < m_data.size(); i++)
674  hex.append(QString("%1 ").arg((quint8)m_data[i], 2, 16, QChar('0')));
675  qDebug("%s", qPrintable(hex));
676  qDebug("==");
677  */
678 
679  while(readOfs < (uint)m_data.size()) {
680  if(!readTag(&readOfs, m_data.size(), &type, &id, &length))
681  return false;
682 
683  //qDebug("-- id %d, TYPE 0x%02x, len %d", id, type, length);
684 
685  if(m_elements.contains(id)) {
686  qDebug("SimpleDeserializer: same ID found twice (id %u)", id);
687  return false;
688  }
689 
690  m_elements.insert(id, Element(type, readOfs, length));
691 
692  readOfs += length;
693 
694  if(readOfs == (uint)m_data.size())
695  return true;
696  }
697  return false;
698 }
699 
700 bool SimpleDeserializer::readTag(uint* readOfs, uint readEnd, Type* type, quint32* id, quint32* length) const
701 {
702  quint8 tag = readByte(readOfs);
703 
704  *type = (Type)(tag >> 4);
705  int idLen = ((tag >> 2) & 0x03) + 1;
706  int lengthLen = (tag & 0x03) + 1;
707 
708  // make sure we have enough header bytes left
709  if(((*readOfs) + idLen + lengthLen) > readEnd)
710  return false;
711 
712  quint32 tmp = 0;
713  for(int i = 0; i < idLen; i++)
714  tmp = (tmp << 8) | readByte(readOfs);
715  *id = tmp;
716  tmp = 0;
717  for(int i = 0; i < lengthLen; i++)
718  tmp = (tmp << 8) | readByte(readOfs);
719  *length = tmp;
720 
721  // check if payload fits the buffer
722  if(((*readOfs) + (*length)) > readEnd)
723  return false;
724  else return true;
725 }
726 
Assert<(bool(sizeof(double)==8))> double_must_be_64_bits[bool(sizeof(double)==8) ? 1 :-1]
quint8 readByte(uint *readOfs) const
void writeDouble(quint32 id, double value)
bool readFloat(quint32 id, float *result, float def=0) const
bool readS64(quint32 id, qint64 *result, qint64 def=0) const
void writeFloat(quint32 id, float value)
#define PRINTF_FORMAT_U32
void writeBlob(quint32 id, const QByteArray &value)
Assert<(bool(sizeof(float)==4))> float_must_be_32_bits[bool(sizeof(float)==4) ? 1 :-1]
bool readU32(quint32 id, quint32 *result, quint32 def=0) const
bool readDouble(quint32 id, double *result, double def=0) const
bool readString(quint32 id, QString *result, const QString &def=QString::null) const
bool readBool(quint32 id, bool *result, bool def=false) const
SimpleSerializer(quint32 version)
bool writeTag(Type type, quint32 id, quint32 length)
bool readS32(quint32 id, qint32 *result, qint32 def=0) const
bool readBlob(quint32 id, QByteArray *result, const QByteArray &def=QByteArray()) const
int32_t i
Definition: decimators.h:244
void writeS32(quint32 id, qint32 value)
bool readU64(quint32 id, quint64 *result, quint64 def=0) const
void writeU32(quint32 id, quint32 value)
bool readTag(uint *readOfs, uint readEnd, Type *type, quint32 *id, quint32 *length) const
#define PRINTF_FORMAT_S32
bool readReal(quint32 id, Real *result, Real def=0) const
SimpleDeserializer(const QByteArray &data)
void writeBool(quint32 id, bool value)
void writeS64(quint32 id, qint64 value)
void writeString(quint32 id, const QString &value)
float Real
Definition: dsptypes.h:42
const QByteArray & final()
void writeU64(quint32 id, quint64 value)