F´ Flight Software - C/C++ Documentation
A framework for building embedded system applications to NASA flight quality standards.
Serializable.cpp
Go to the documentation of this file.
2 #include <Fw/Types/Assert.hpp>
5 #include <cstdio>
6 #include <cstring> // memcpy
7 #ifdef BUILD_UT
8 #include <Fw/Types/String.hpp>
9 #include <iomanip>
10 #endif
11 
12 namespace Fw {
13 
15 
17 
18 // ----------------------------------------------------------------------
19 #if FW_SERIALIZABLE_TO_STRING || FW_ENABLE_TEXT_LOGGING || BUILD_UT
20 
21 void Serializable::toString(StringBase& text) const {
22  text = "NOSPEC"; // set to not specified.
23 }
24 
25 #endif
26 
27 #ifdef BUILD_UT
28 std::ostream& operator<<(std::ostream& os, const Serializable& val) {
29  Fw::String out;
30  val.toString(out);
31 
32  os << out;
33 
34  return os;
35 }
36 #endif
37 
39 
41  : m_buffAddr(buffAddr), m_capacity(capacity), m_serLoc(0), m_deserLoc(0) {
42  // Ensure buffAddr & capacity are consistent
43  FW_ASSERT((buffAddr == nullptr) == (capacity == 0), static_cast<FwAssertArgType>(capacity));
44 }
45 
47 
49  this->m_serLoc = src.m_serLoc;
50  this->m_deserLoc = src.m_deserLoc;
51  const U8* srcBuffAddr = src.m_buffAddr;
52  U8* thisBuffAddr = this->m_buffAddr;
53  FW_ASSERT(srcBuffAddr != nullptr);
54  FW_ASSERT(thisBuffAddr != nullptr);
55  // destination has to be same or bigger
56  FW_ASSERT(src.m_serLoc <= this->m_capacity, static_cast<FwAssertArgType>(src.m_serLoc),
57  static_cast<FwAssertArgType>(this->m_capacity));
58  (void)memcpy(thisBuffAddr, srcBuffAddr, static_cast<size_t>(this->m_serLoc));
59 }
60 
61 // Copy constructor doesn't make sense in this virtual class as there is nothing to copy. Derived classes should
62 // call the empty constructor and then call their own copy function
63 LinearBufferBase& LinearBufferBase::operator=(const LinearBufferBase& src) { // lgtm[cpp/rule-of-two]
64  this->copyFrom(src);
65  return *this;
66 }
67 
68 // serialization routines
69 
71  if (this->m_serLoc + static_cast<Serializable::SizeType>(sizeof(val)) - 1 >= this->m_capacity) {
73  }
74  U8* buffAddr = this->m_buffAddr;
75  FW_ASSERT(buffAddr != nullptr);
76  buffAddr[this->m_serLoc] = val;
77  this->m_serLoc += static_cast<Serializable::SizeType>(sizeof(val));
78  this->m_deserLoc = 0;
79 
80  return FW_SERIALIZE_OK;
81 }
82 
84  return serializeFrom(static_cast<U8>(val), mode);
85 }
86 
87 #if FW_HAS_16_BIT == 1
89  if (this->m_serLoc + static_cast<Serializable::SizeType>(sizeof(val)) - 1 >= this->m_capacity) {
91  }
92  U8* buffAddr = this->m_buffAddr;
93  FW_ASSERT(buffAddr != nullptr);
94  switch (mode) {
95  case Endianness::BIG:
96  // MSB first
97  buffAddr[this->m_serLoc + 0] = static_cast<U8>(val >> 8);
98  buffAddr[this->m_serLoc + 1] = static_cast<U8>(val);
99  break;
100  case Endianness::LITTLE:
101  // LSB first
102  buffAddr[this->m_serLoc + 0] = static_cast<U8>(val);
103  buffAddr[this->m_serLoc + 1] = static_cast<U8>(val >> 8);
104  break;
105  default:
106  FW_ASSERT(false);
107  break;
108  }
109  this->m_serLoc += static_cast<Serializable::SizeType>(sizeof(val));
110  this->m_deserLoc = 0;
111  return FW_SERIALIZE_OK;
112 }
113 
115  return serializeFrom(static_cast<U16>(val), mode);
116 }
117 #endif
118 #if FW_HAS_32_BIT == 1
120  if (this->m_serLoc + static_cast<Serializable::SizeType>(sizeof(val)) - 1 >= this->m_capacity) {
122  }
123  U8* buffAddr = this->m_buffAddr;
124  FW_ASSERT(buffAddr != nullptr);
125  switch (mode) {
126  case Endianness::BIG:
127  // MSB first
128  buffAddr[this->m_serLoc + 0] = static_cast<U8>(val >> 24);
129  buffAddr[this->m_serLoc + 1] = static_cast<U8>(val >> 16);
130  buffAddr[this->m_serLoc + 2] = static_cast<U8>(val >> 8);
131  buffAddr[this->m_serLoc + 3] = static_cast<U8>(val);
132  break;
133  case Endianness::LITTLE:
134  // LSB first
135  buffAddr[this->m_serLoc + 0] = static_cast<U8>(val);
136  buffAddr[this->m_serLoc + 1] = static_cast<U8>(val >> 8);
137  buffAddr[this->m_serLoc + 2] = static_cast<U8>(val >> 16);
138  buffAddr[this->m_serLoc + 3] = static_cast<U8>(val >> 24);
139  break;
140  default:
141  FW_ASSERT(false);
142  break;
143  }
144  this->m_serLoc += static_cast<Serializable::SizeType>(sizeof(val));
145  this->m_deserLoc = 0;
146  return FW_SERIALIZE_OK;
147 }
148 
150  return serializeFrom(static_cast<U32>(val), mode);
151 }
152 #endif
153 
154 #if FW_HAS_64_BIT == 1
156  if (this->m_serLoc + static_cast<Serializable::SizeType>(sizeof(val)) - 1 >= this->m_capacity) {
158  }
159  U8* buffAddr = this->m_buffAddr;
160  FW_ASSERT(buffAddr != nullptr);
161  switch (mode) {
162  case Endianness::BIG:
163  // MSB first
164  buffAddr[this->m_serLoc + 0] = static_cast<U8>(val >> 56);
165  buffAddr[this->m_serLoc + 1] = static_cast<U8>(val >> 48);
166  buffAddr[this->m_serLoc + 2] = static_cast<U8>(val >> 40);
167  buffAddr[this->m_serLoc + 3] = static_cast<U8>(val >> 32);
168  buffAddr[this->m_serLoc + 4] = static_cast<U8>(val >> 24);
169  buffAddr[this->m_serLoc + 5] = static_cast<U8>(val >> 16);
170  buffAddr[this->m_serLoc + 6] = static_cast<U8>(val >> 8);
171  buffAddr[this->m_serLoc + 7] = static_cast<U8>(val);
172  break;
173  case Endianness::LITTLE:
174  // LSB first
175  buffAddr[this->m_serLoc + 0] = static_cast<U8>(val);
176  buffAddr[this->m_serLoc + 1] = static_cast<U8>(val >> 8);
177  buffAddr[this->m_serLoc + 2] = static_cast<U8>(val >> 16);
178  buffAddr[this->m_serLoc + 3] = static_cast<U8>(val >> 24);
179  buffAddr[this->m_serLoc + 4] = static_cast<U8>(val >> 32);
180  buffAddr[this->m_serLoc + 5] = static_cast<U8>(val >> 40);
181  buffAddr[this->m_serLoc + 6] = static_cast<U8>(val >> 48);
182  buffAddr[this->m_serLoc + 7] = static_cast<U8>(val >> 56);
183  break;
184  default:
185  FW_ASSERT(false);
186  break;
187  }
188  this->m_serLoc += static_cast<Serializable::SizeType>(sizeof(val));
189  this->m_deserLoc = 0;
190  return FW_SERIALIZE_OK;
191 }
192 
194  return serializeFrom(static_cast<U64>(val), mode);
195 }
196 #endif
197 
199  // floating point values need to be byte-swapped as well, so copy to U64 and use that routine
200  U64 u64Val;
201  (void)memcpy(&u64Val, &val, sizeof(val));
202  return this->serializeFrom(u64Val, mode);
203 }
204 
206  // floating point values need to be byte-swapped as well, so copy to U32 and use that routine
207  U32 u32Val;
208  (void)memcpy(&u32Val, &val, sizeof(val));
209  return this->serializeFrom(u32Val, mode);
210 }
211 
213  // booleans are encoded as a single byte
214  static_assert(FW_SERIALIZE_TRUE_VALUE <= 0xFF && FW_SERIALIZE_FALSE_VALUE <= 0xFF,
215  "boolean wire values must fit in one byte");
216  static_assert(static_cast<int>(FW_SERIALIZE_TRUE_VALUE) != static_cast<int>(FW_SERIALIZE_FALSE_VALUE),
217  "boolean wire values must be distinct");
218  const U8 byteVal = val ? static_cast<U8>(FW_SERIALIZE_TRUE_VALUE) : static_cast<U8>(FW_SERIALIZE_FALSE_VALUE);
219  return this->serializeFrom(byteVal, mode);
220 }
221 
223  // pointers are serialized as their integer representation
224  return this->serializeFrom(reinterpret_cast<PlatformPointerCastType>(val), mode);
225 }
226 
228  Serializable::SizeType length,
229  Endianness endianMode) {
230  return this->serializeFrom(buff, static_cast<FwSizeType>(length), Serialization::INCLUDE_LENGTH, endianMode);
231 }
232 
235  FwSizeType length,
236  Serialization::t lengthMode,
237  Endianness endianMode) { // First serialize length
238  SerializeStatus stat;
239  if (lengthMode == Serialization::INCLUDE_LENGTH) {
240  stat = this->serializeFrom(static_cast<FwSizeStoreType>(length), endianMode);
241  if (stat != FW_SERIALIZE_OK) {
242  return stat;
243  }
244  }
245 
246  // make sure we have enough space
247  // Note: m_serLoc <= m_capacity is a class invariant, so this subtraction cannot underflow.
248  if (length > this->m_capacity - this->m_serLoc) {
250  }
251 
252  if (length > 0) {
253  FW_ASSERT(buff != nullptr);
254  }
255  U8* buffAddr = this->m_buffAddr;
256  FW_ASSERT(buffAddr != nullptr);
257  // copy buffer to our buffer; memmove is used because the source may overlap this buffer
258  (void)memmove(&buffAddr[this->m_serLoc], buff, static_cast<size_t>(length));
259  this->m_serLoc += static_cast<Serializable::SizeType>(length);
260  this->m_deserLoc = 0;
261 
262  return FW_SERIALIZE_OK;
263 }
264 
266  Endianness mode) {
267  return val.serializeTo(*this, mode);
268 }
269 
271  Endianness mode) {
272  Serializable::SizeType size = val.getSize();
273  // Note: m_serLoc <= m_capacity is a class invariant, so this subtraction cannot underflow.
274  Serializable::SizeType available = this->m_capacity - this->m_serLoc;
275  if (size > available || static_cast<Serializable::SizeType>(sizeof(FwSizeStoreType)) > available - size) {
277  }
278 
279  // First, serialize size
280  SerializeStatus stat = this->serializeFrom(static_cast<FwSizeStoreType>(size), mode);
281  if (stat != FW_SERIALIZE_OK) {
282  return stat;
283  }
284 
285  U8* thisBuffAddr = this->m_buffAddr;
286  const U8* valBuffAddr = val.getBuffAddr();
287  FW_ASSERT(thisBuffAddr != nullptr);
288  FW_ASSERT(valBuffAddr != nullptr);
289  // serialize buffer
290  (void)memcpy(&thisBuffAddr[this->m_serLoc], valBuffAddr, static_cast<size_t>(size));
291  this->m_serLoc += size;
292  this->m_deserLoc = 0;
293 
294  return FW_SERIALIZE_OK;
295 }
296 
299  if ((size < std::numeric_limits<FwSizeStoreType>::min()) || (size > std::numeric_limits<FwSizeStoreType>::max())) {
300  status = FW_SERIALIZE_FORMAT_ERROR;
301  }
302  if (status == FW_SERIALIZE_OK) {
303  status = this->serializeFrom(static_cast<FwSizeStoreType>(size), mode);
304  }
305  return status;
306 }
307 
308 // deserialization routines
309 
311  // check for room
312  const Serializable::SizeType size = this->m_serLoc;
313  if (size == this->m_deserLoc) {
315  } else if (size - this->m_deserLoc < static_cast<Serializable::SizeType>(sizeof(val))) {
317  }
318  // read from current location
319  U8* buffAddr = this->m_buffAddr;
320  FW_ASSERT(buffAddr != nullptr);
321  val = buffAddr[this->m_deserLoc + 0];
322  this->m_deserLoc += static_cast<Serializable::SizeType>(sizeof(val));
323  return FW_SERIALIZE_OK;
324 }
325 
327  // check for room
328  const Serializable::SizeType size = this->m_serLoc;
329  if (size == this->m_deserLoc) {
331  } else if (size - this->m_deserLoc < static_cast<Serializable::SizeType>(sizeof(val))) {
333  }
334  // read from current location
335  U8* buffAddr = this->m_buffAddr;
336  FW_ASSERT(buffAddr != nullptr);
337  val = static_cast<I8>(buffAddr[this->m_deserLoc + 0]);
338  this->m_deserLoc += static_cast<Serializable::SizeType>(sizeof(val));
339  return FW_SERIALIZE_OK;
340 }
341 
342 #if FW_HAS_16_BIT == 1
344  // check for room
345  const Serializable::SizeType size = this->m_serLoc;
346  if (size == this->m_deserLoc) {
348  } else if (size - this->m_deserLoc < static_cast<Serializable::SizeType>(sizeof(val))) {
350  }
351  // read from current location
352  U8* buffAddr = this->m_buffAddr;
353  FW_ASSERT(buffAddr != nullptr);
354  switch (mode) {
355  case Endianness::BIG:
356  // MSB first
357  val = static_cast<U16>(((buffAddr[this->m_deserLoc + 1]) << 0) | ((buffAddr[this->m_deserLoc + 0]) << 8));
358  break;
359  case Endianness::LITTLE:
360  // LSB first
361  val = static_cast<U16>(((buffAddr[this->m_deserLoc + 0]) << 0) | ((buffAddr[this->m_deserLoc + 1]) << 8));
362  break;
363  default:
364  FW_ASSERT(false);
365  break;
366  }
367  this->m_deserLoc += static_cast<Serializable::SizeType>(sizeof(val));
368  return FW_SERIALIZE_OK;
369 }
370 
372  U16 unsignVal = 0;
373  SerializeStatus res = deserializeTo(unsignVal, mode);
375  val = static_cast<I16>(unsignVal);
376  }
377  return res;
378 }
379 #endif
380 #if FW_HAS_32_BIT == 1
382  // check for room
383  const Serializable::SizeType size = this->m_serLoc;
384  if (size == this->m_deserLoc) {
386  } else if (size - this->m_deserLoc < static_cast<Serializable::SizeType>(sizeof(val))) {
388  }
389  // read from current location
390  U8* buffAddr = this->m_buffAddr;
391  FW_ASSERT(buffAddr != nullptr);
392  switch (mode) {
393  case Endianness::BIG:
394  // MSB first
395  val = (static_cast<U32>(buffAddr[this->m_deserLoc + 3]) << 0) |
396  (static_cast<U32>(buffAddr[this->m_deserLoc + 2]) << 8) |
397  (static_cast<U32>(buffAddr[this->m_deserLoc + 1]) << 16) |
398  (static_cast<U32>(buffAddr[this->m_deserLoc + 0]) << 24);
399  break;
400  case Endianness::LITTLE:
401  // LSB first
402  val = (static_cast<U32>(buffAddr[this->m_deserLoc + 0]) << 0) |
403  (static_cast<U32>(buffAddr[this->m_deserLoc + 1]) << 8) |
404  (static_cast<U32>(buffAddr[this->m_deserLoc + 2]) << 16) |
405  (static_cast<U32>(buffAddr[this->m_deserLoc + 3]) << 24);
406  break;
407  default:
408  FW_ASSERT(false);
409  break;
410  }
411  this->m_deserLoc += static_cast<Serializable::SizeType>(sizeof(val));
412  return FW_SERIALIZE_OK;
413 }
414 
416  U32 unsignVal = 0;
417  SerializeStatus res = deserializeTo(unsignVal, mode);
419  val = static_cast<I32>(unsignVal);
420  }
421  return res;
422 }
423 #endif
424 
425 #if FW_HAS_64_BIT == 1
426 
428  // check for room
429  if (this->m_serLoc == this->m_deserLoc) {
431  } else if (this->m_serLoc - this->m_deserLoc < static_cast<Serializable::SizeType>(sizeof(val))) {
433  }
434  // read from current location
435  U8* buffAddr = this->m_buffAddr;
436  FW_ASSERT(buffAddr != nullptr);
437  switch (mode) {
438  case Endianness::BIG:
439  // MSB first
440  val = (static_cast<U64>(buffAddr[this->m_deserLoc + 7]) << 0) |
441  (static_cast<U64>(buffAddr[this->m_deserLoc + 6]) << 8) |
442  (static_cast<U64>(buffAddr[this->m_deserLoc + 5]) << 16) |
443  (static_cast<U64>(buffAddr[this->m_deserLoc + 4]) << 24) |
444  (static_cast<U64>(buffAddr[this->m_deserLoc + 3]) << 32) |
445  (static_cast<U64>(buffAddr[this->m_deserLoc + 2]) << 40) |
446  (static_cast<U64>(buffAddr[this->m_deserLoc + 1]) << 48) |
447  (static_cast<U64>(buffAddr[this->m_deserLoc + 0]) << 56);
448  break;
449  case Endianness::LITTLE:
450  // LSB first
451  val = (static_cast<U64>(buffAddr[this->m_deserLoc + 0]) << 0) |
452  (static_cast<U64>(buffAddr[this->m_deserLoc + 1]) << 8) |
453  (static_cast<U64>(buffAddr[this->m_deserLoc + 2]) << 16) |
454  (static_cast<U64>(buffAddr[this->m_deserLoc + 3]) << 24) |
455  (static_cast<U64>(buffAddr[this->m_deserLoc + 4]) << 32) |
456  (static_cast<U64>(buffAddr[this->m_deserLoc + 5]) << 40) |
457  (static_cast<U64>(buffAddr[this->m_deserLoc + 6]) << 48) |
458  (static_cast<U64>(buffAddr[this->m_deserLoc + 7]) << 56);
459  break;
460  default:
461  FW_ASSERT(false);
462  break;
463  }
464  this->m_deserLoc += static_cast<Serializable::SizeType>(sizeof(val));
465  return FW_SERIALIZE_OK;
466 }
467 
469  U64 unsignVal;
470  SerializeStatus res = deserializeTo(unsignVal, mode);
472  val = static_cast<I64>(unsignVal);
473  }
474  return res;
475 }
476 #endif
477 
479  // deserialize as 64-bit int to handle endianness
480  U64 tempVal;
481  SerializeStatus stat = this->deserializeTo(tempVal, mode);
482  if (stat != FW_SERIALIZE_OK) {
483  return stat;
484  }
485  // copy to argument
486  (void)memcpy(&val, &tempVal, sizeof(val));
487 
488  return FW_SERIALIZE_OK;
489 }
490 
492  U8 byteVal = 0;
493  const SerializeStatus stat = this->deserializeTo(byteVal, mode);
494  if (stat != FW_SERIALIZE_OK) {
495  return stat;
496  }
497  if (FW_SERIALIZE_TRUE_VALUE == byteVal) {
498  val = true;
499  } else if (FW_SERIALIZE_FALSE_VALUE == byteVal) {
500  val = false;
501  } else {
502  // leave the malformed byte unconsumed
503  this->m_deserLoc -= static_cast<Serializable::SizeType>(sizeof(byteVal));
505  }
506  return FW_SERIALIZE_OK;
507 }
508 
510  // Deserialize as pointer cast, then convert to void*
511  PlatformPointerCastType pointerCastVal = 0;
512  const SerializeStatus stat = this->deserializeTo(pointerCastVal, mode);
513  if (stat == FW_SERIALIZE_OK) {
514  val = reinterpret_cast<void*>(pointerCastVal);
515  }
516  return stat;
517 }
518 
520  // deserialize as 32-bit int to handle endianness
521  U32 tempVal = 0;
522  SerializeStatus stat = this->deserializeTo(tempVal, mode);
523  if (stat != FW_SERIALIZE_OK) {
524  return stat;
525  }
526  (void)memcpy(&val, &tempVal, sizeof(val));
527 
528  return FW_SERIALIZE_OK;
529 }
530 
532  Serializable::SizeType& length,
533  Endianness endianMode) {
534  FwSizeType length_in_out = static_cast<FwSizeType>(length);
535  SerializeStatus status = this->deserializeTo(buff, length_in_out, Serialization::INCLUDE_LENGTH, endianMode);
536  length = static_cast<Serializable::SizeType>(length_in_out);
537  return status;
538 }
539 
541  Serializable::SizeType& length,
542  Serialization::t lengthMode,
543  Endianness endianMode) {
544  U8* buffAddr = this->m_buffAddr;
545  FW_ASSERT(buffAddr != nullptr);
546 
547  if (lengthMode == Serialization::INCLUDE_LENGTH) {
548  FwSizeStoreType storedLength = 0;
549 
550  SerializeStatus stat = this->deserializeTo(storedLength, endianMode);
551 
552  if (stat != FW_SERIALIZE_OK) {
553  return stat;
554  }
555 
556  // make sure it fits
557  if ((storedLength > this->getDeserializeSizeLeft()) || (storedLength > length)) {
559  }
560 
561  if (storedLength > 0) {
562  FW_ASSERT(buff != nullptr);
563  }
564  (void)memcpy(buff, &buffAddr[this->m_deserLoc], static_cast<size_t>(storedLength));
565 
566  length = static_cast<FwSizeType>(storedLength);
567 
568  } else {
569  // make sure enough is left
570  if (length > this->getDeserializeSizeLeft()) {
572  }
573 
574  if (length > 0) {
575  FW_ASSERT(buff != nullptr);
576  }
577  (void)memcpy(buff, &buffAddr[this->m_deserLoc], static_cast<size_t>(length));
578  }
579 
580  this->m_deserLoc += static_cast<Serializable::SizeType>(length);
581  return FW_SERIALIZE_OK;
582 }
583 
585  return val.deserializeFrom(*this, mode);
586 }
587 
589  U8* valBuffAddr = val.getBuffAddr();
590  FW_ASSERT(valBuffAddr != nullptr);
592 
593  FwSizeStoreType storedLength = 0;
594 
595  stat = this->deserializeTo(storedLength, mode);
596 
597  if (stat != FW_SERIALIZE_OK) {
598  return stat;
599  }
600 
601  // make sure destination has enough room
602 
603  if ((storedLength > val.getCapacity()) || (storedLength > this->getDeserializeSizeLeft())) {
605  }
606 
607  U8* thisBuffAddr = this->m_buffAddr;
608  FW_ASSERT(thisBuffAddr != nullptr);
609  (void)memcpy(valBuffAddr, &thisBuffAddr[this->m_deserLoc], static_cast<size_t>(storedLength));
610 
611  stat = val.setBuffLen(storedLength);
612 
613  if (stat != FW_SERIALIZE_OK) {
614  return stat;
615  }
616 
617  this->m_deserLoc += storedLength;
618 
619  return FW_SERIALIZE_OK;
620 }
621 
623  FwSizeStoreType storedSize = 0;
624  Fw::SerializeStatus status = this->deserializeTo(storedSize, mode);
625  if (status == FW_SERIALIZE_OK) {
626  size = static_cast<FwSizeType>(storedSize);
627  }
628  return status;
629 }
630 
632  this->m_deserLoc = 0;
633  this->m_serLoc = 0;
634 }
635 
637  this->m_deserLoc = 0;
638 }
639 
642  // compute new ser loc
643  const FwSizeType newSerLoc = this->m_serLoc + numBytesToSkip;
644  // check for room
645  if (newSerLoc <= this->m_capacity) {
646  // update ser loc
647  this->m_serLoc = static_cast<Serializable::SizeType>(newSerLoc);
648  } else {
649  status = FW_SERIALIZE_NO_ROOM_LEFT;
650  }
651  return status;
652 }
653 
655  // check for room
656  const Serializable::SizeType size = this->m_serLoc;
657  if (size == this->m_deserLoc) {
659  } else if (size - this->m_deserLoc < numBytesToSkip) {
661  }
662  // update location in buffer to skip the value
663  this->m_deserLoc += static_cast<Serializable::SizeType>(numBytesToSkip);
664  return FW_SERIALIZE_OK;
665 }
666 
668  // Reset serialization
669  this->resetSer();
670  // Advance to offset
671  return this->serializeSkip(offset);
672 }
674  // Reset deserialization
675  this->resetDeser();
676  // Advance to offset
677  return this->deserializeSkip(offset);
678 }
679 
681  return this->m_serLoc;
682 }
683 
685  if (this->m_capacity < length) {
687  } else {
688  FW_ASSERT(src);
689  U8* buffAddr = this->m_buffAddr;
690  FW_ASSERT(buffAddr != nullptr);
691  (void)memcpy(buffAddr, src, static_cast<size_t>(length));
692  this->m_serLoc = length;
693  this->m_deserLoc = 0;
694  return FW_SERIALIZE_OK;
695  }
696 }
697 
699  if (this->m_capacity < length) {
701  } else {
702  this->m_serLoc = length;
703  this->m_deserLoc = 0;
704  return FW_SERIALIZE_OK;
705  }
706 }
707 
709  FW_ASSERT(this->m_serLoc >= this->m_deserLoc, static_cast<FwAssertArgType>(this->m_serLoc),
710  static_cast<FwAssertArgType>(this->m_deserLoc));
711  return this->m_serLoc - this->m_deserLoc;
712 }
713 
715  FW_ASSERT(this->m_capacity >= this->m_serLoc, static_cast<FwAssertArgType>(this->m_capacity),
716  static_cast<FwAssertArgType>(this->m_serLoc));
717  return this->m_capacity - this->m_serLoc;
718 }
719 
721  Serializable::SizeType size) {
722  // make sure there is sufficient size in destination
723  if (dest.getCapacity() < size) {
725  }
726  // make sure there is sufficient buffer in source
727  if (this->getDeserializeSizeLeft() < size) {
729  }
730 
731  // otherwise, set destination buffer to data from deserialization pointer plus size
732  U8* buffAddr = this->m_buffAddr;
733 
734  FW_ASSERT(buffAddr);
735  SerializeStatus stat = dest.setBuff(&buffAddr[this->m_deserLoc], size);
736  if (stat == FW_SERIALIZE_OK) {
737  this->m_deserLoc += size;
738  }
739  return stat;
740 }
741 
743  Serializable::SizeType size) {
744  // make sure there is sufficient size in destination
745  const Serializable::SizeType destCapacity = dest.getCapacity();
746  const Serializable::SizeType destSize = dest.getSize();
747  if (destCapacity < size + destSize) {
749  }
750  // make sure there is sufficient buffer in source
751  if (this->getDeserializeSizeLeft() < size) {
753  }
754 
755  // otherwise, serialize bytes to destination without writing length
756  U8* buffAddr = this->m_buffAddr;
757  SerializeStatus stat = dest.serializeFrom(&buffAddr[this->m_deserLoc], size, Serialization::OMIT_LENGTH);
758  if (stat == FW_SERIALIZE_OK) {
759  this->m_deserLoc += size;
760  }
761  return stat;
762 }
763 
764 // return address of buffer not yet deserialized. This is used
765 // to copy the remainder of a buffer.
767  const U8* buffAddr = this->m_buffAddr;
768  FW_ASSERT(buffAddr != nullptr);
769  return &buffAddr[this->m_deserLoc];
770 }
771 
774  U8* buffAddr = this->m_buffAddr;
775  FW_ASSERT(buffAddr != nullptr);
776  return &buffAddr[this->m_serLoc];
777 }
778 
779 #ifdef BUILD_UT
780 bool LinearBufferBase::operator==(const LinearBufferBase& other) const {
781  if (this->m_serLoc != other.getSize()) {
782  return false;
783  }
784 
785  const U8* us = this->m_buffAddr;
786  const U8* them = other.getBuffAddr();
787 
788  FW_ASSERT(us);
789  FW_ASSERT(them);
790 
791  for (Serializable::SizeType byte = 0; byte < this->m_serLoc; byte++) {
792  if (us[byte] != them[byte]) {
793  return false;
794  }
795  }
796 
797  return true;
798 }
799 
800 std::ostream& operator<<(std::ostream& os, const LinearBufferBase& buff) {
801  const U8* us = buff.getBuffAddr();
802 
803  FW_ASSERT(us);
804 
805  for (Serializable::SizeType byte = 0; byte < buff.getSize(); byte++) {
806  os << "[" << std::setw(2) << std::hex << std::setfill('0') << us[byte] << "]" << std::dec;
807  }
808 
809  return os;
810 }
811 #endif
812 
814  : LinearBufferBase(nullptr, 0) {
815  this->setExtBuffer(buffPtr, size);
816 }
817 
819  this->clear();
820 }
821 
823  // Allow setting buffer with null pointer and zero size (for initialization/reset)
824  // but reject null pointer with non-zero size
825  FW_ASSERT((buffPtr != nullptr) || (size == 0), static_cast<FwAssertArgType>(size));
826  this->clear();
827  this->setBuffAddrInternal(buffPtr);
828  this->setCapacityInternal(size);
829 }
830 
832  this->resetSer();
833  this->resetDeser();
834  this->setBuffAddrInternal(nullptr);
835  this->setCapacityInternal(0);
836 }
837 
838 // ----------------------------------------------------------------------
839 // Deprecated method implementations for backward compatibility
840 // ----------------------------------------------------------------------
841 
842 Serializable::SizeType LinearBufferBase::getBuffLength() const {
843  return this->m_serLoc;
844 }
845 
846 Serializable::SizeType LinearBufferBase::getBuffLeft() {
847  return this->getDeserializeSizeLeft();
848 }
849 
851  return this->serializeFrom(val);
852 }
854  return this->serializeFrom(val);
855 }
856 #if FW_HAS_16_BIT == 1
858  return this->serializeFrom(val);
859 }
861  return this->serializeFrom(val);
862 }
863 #endif
864 #if FW_HAS_32_BIT == 1
866  return this->serializeFrom(val);
867 }
869  return this->serializeFrom(val);
870 }
871 #endif
872 #if FW_HAS_64_BIT == 1
874  return this->serializeFrom(val);
875 }
877  return this->serializeFrom(val);
878 }
879 #endif
881  return this->serializeFrom(val);
882 }
884  return this->serializeFrom(val);
885 }
887  return this->serializeFrom(val);
888 }
890  return this->serializeFrom(val);
891 }
892 
893 // Deprecated method for backward compatibility
895  FwSizeType length,
896  bool noLength) {
898  return this->serializeFrom(buff, length, mode);
899 }
900 
902  return this->serializeFrom(buff, length);
903 }
905  FwSizeType length,
906  Serialization::t mode) {
907  return this->serializeFrom(buff, length, mode);
908 }
910  return this->serializeFrom(val);
911 }
913  return this->serializeFrom(val);
914 }
915 
916 FW_SERIALIZE_FORCE_INLINE_LBB SerializeStatus LinearBufferBase::deserialize(U8& val) {
917  return this->deserializeTo(val);
918 }
919 FW_SERIALIZE_FORCE_INLINE_LBB SerializeStatus LinearBufferBase::deserialize(I8& val) {
920  return this->deserializeTo(val);
921 }
922 #if FW_HAS_16_BIT == 1
923 FW_SERIALIZE_FORCE_INLINE_LBB SerializeStatus LinearBufferBase::deserialize(U16& val) {
924  return this->deserializeTo(val);
925 }
926 FW_SERIALIZE_FORCE_INLINE_LBB SerializeStatus LinearBufferBase::deserialize(I16& val) {
927  return this->deserializeTo(val);
928 }
929 #endif
930 #if FW_HAS_32_BIT == 1
931 FW_SERIALIZE_FORCE_INLINE_LBB SerializeStatus LinearBufferBase::deserialize(U32& val) {
932  return this->deserializeTo(val);
933 }
934 FW_SERIALIZE_FORCE_INLINE_LBB SerializeStatus LinearBufferBase::deserialize(I32& val) {
935  return this->deserializeTo(val);
936 }
937 #endif
938 #if FW_HAS_64_BIT == 1
939 FW_SERIALIZE_FORCE_INLINE_LBB SerializeStatus LinearBufferBase::deserialize(U64& val) {
940  return this->deserializeTo(val);
941 }
942 FW_SERIALIZE_FORCE_INLINE_LBB SerializeStatus LinearBufferBase::deserialize(I64& val) {
943  return this->deserializeTo(val);
944 }
945 #endif
946 FW_SERIALIZE_FORCE_INLINE_LBB SerializeStatus LinearBufferBase::deserialize(F32& val) {
947  return this->deserializeTo(val);
948 }
949 FW_SERIALIZE_FORCE_INLINE_LBB SerializeStatus LinearBufferBase::deserialize(F64& val) {
950  return this->deserializeTo(val);
951 }
952 FW_SERIALIZE_FORCE_INLINE_LBB SerializeStatus LinearBufferBase::deserialize(bool& val) {
953  return this->deserializeTo(val);
954 }
955 FW_SERIALIZE_FORCE_INLINE_LBB SerializeStatus LinearBufferBase::deserialize(void*& val) {
956  return this->deserializeTo(val);
957 }
958 
959 // Deprecated method for backward compatibility
960 FW_SERIALIZE_FORCE_INLINE_LBB SerializeStatus LinearBufferBase::deserialize(U8* buff,
961  FwSizeType& length,
962  bool noLength) {
964  return this->deserializeTo(buff, length, mode);
965 }
966 
967 FW_SERIALIZE_FORCE_INLINE_LBB SerializeStatus LinearBufferBase::deserialize(U8* buff, FwSizeType& length) {
968  return this->deserializeTo(buff, length, Serialization::INCLUDE_LENGTH);
969 }
970 
971 FW_SERIALIZE_FORCE_INLINE_LBB SerializeStatus LinearBufferBase::deserialize(U8* buff,
972  FwSizeType& length,
973  Serialization::t mode) {
974  return this->deserializeTo(buff, length, mode);
975 }
976 
977 FW_SERIALIZE_FORCE_INLINE_LBB SerializeStatus LinearBufferBase::deserialize(Serializable& val) {
978  return this->deserializeTo(val);
979 }
980 FW_SERIALIZE_FORCE_INLINE_LBB SerializeStatus LinearBufferBase::deserialize(LinearBufferBase& val) {
981  return this->deserializeTo(val);
982 }
983 
984 Serializable::SizeType ExternalSerializeBuffer::getBuffCapacity() const {
985  return this->getCapacity();
986 }
987 
988 } // namespace Fw
Serialization/Deserialization operation was successful.
void clear()
Clear external buffer.
void copyFrom(const LinearBufferBase &src)
Copy data from source buffer.
virtual Serializable::SizeType getCapacity() const =0
Get buffer capacity.
Deserialization buffer was empty when trying to read more data.
SerializeStatus setBuff(const U8 *src, Serializable::SizeType length) override
Set buffer contents from external source.
PlatformSizeType FwSizeType
SerializeStatus moveSerToOffset(FwSizeType offset) override
Move serialization pointer to specified offset.
virtual SerializeStatus serializeTo(SerialBufferBase &buffer, Endianness mode=Endianness::BIG) const =0
Serialize the contents of this object to a buffer.
const U8 * getBuffAddrLeft() const
Get address of remaining non-deserialized data.
Serializable::SizeType getSize() const override
Get current buffer size.
SerializeStatus deserializeTo(U8 &val, Endianness mode=Endianness::BIG) override
Deserialize an 8-bit unsigned integer value.
Fw::SerializeStatus serialize(Fw::SerialBufferBase &serializer, FwSizeType size)
Serialize an idle packet of exactly size bytes (header and idle data) into serializer ...
Definition: IdlePacket.cpp:16
int8_t I8
8-bit signed integer
Definition: BasicTypes.h:51
No room left in the buffer to serialize data.
void setBuffAddrInternal(U8 *addr)
virtual SerializeStatus deserializeFrom(SerialBufferBase &buffer, Endianness mode=Endianness::BIG)=0
Deserialize the contents of this object from a buffer.
LinearBufferBase & operator=(const LinearBufferBase &src)
Copy assignment operator.
Deserialization data had incorrect values (unexpected data types)
SerializeStatus serializeFrom(U8 val, Endianness mode=Endianness::BIG) override
Serialize an 8-bit unsigned integer value.
virtual SerializeStatus serializeFrom(U8 val, Endianness mode=Endianness::BIG)=0
Serialize an 8-bit unsigned integer value.
Serializable::SizeType getCapacity() const override
Get buffer capacity.
SerializeStatus deserializeSkip(FwSizeType numBytesToSkip) override
Skip specified number of bytes during deserialization.
ExternalSerializeBuffer()
Default constructor.
SerializeStatus
forward declaration for string
float F32
32-bit floating point
Definition: BasicTypes.h:84
virtual ~SerialBufferBase()
Virtual destructor.
Data was the wrong format (e.g. wrong packet type)
U8 * getBuffAddr()
Get buffer address for data filling (non-const version)
SerializeStatus moveDeserToOffset(FwSizeType offset) override
Move deserialization pointer to specified offset.
Omit length from serialization.
Data was left in the buffer, but not enough to deserialize.
Serializable::SizeType getDeserializeSizeLeft() const override
Get remaining deserialization buffer size.
FwSizeType SizeType
Serializable()
Default constructor.
void resetDeser() override
Reset deserialization pointer to beginning of buffer.
void resetSer() override
Reset serialization pointer to beginning of buffer.
FwSizeType FwSizeStoreType
void setCapacityInternal(Serializable::SizeType capacity)
#define FW_SERIALIZE_FORCE_INLINE_LBB
Definition: FpConfig.h:154
SerializeStatus copyRawOffset(SerialBufferBase &dest, Serializable::SizeType size) override
Append raw bytes to destination from this buffer and advance source offset.
virtual SerializeStatus setBuff(const U8 *src, Serializable::SizeType length)=0
Set buffer contents from external source.
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:54
SerializeStatus setBuffLen(Serializable::SizeType length) override
Set buffer length manually.
static U32 min(const U32 a, const U32 b)
Definition: Checksum.cpp:16
void setExtBuffer(U8 *buffPtr, Serializable::SizeType size)
Set the external buffer.
virtual ~Serializable()
Virtual destructor.
double F64
64-bit floating point (double). Required for compiler-supplied double promotion.
Definition: BasicTypes.h:86
SerializeStatus deserializeSize(FwSizeType &size, Endianness mode=Endianness::BIG) override
Deserialize a size value.
SerializeStatus copyRaw(SerialBufferBase &dest, Serializable::SizeType size) override
Copy raw bytes from this buffer to destination and advance source offset.
Include length as first token in serialization.
Little endian serialization.
SerializeStatus serializeSize(const FwSizeType size, Endianness mode=Endianness::BIG) override
Serialize a size value.
Implementation of malloc based allocator.
Endianness
virtual Serializable::SizeType getSize() const =0
Get current buffer size.
#define FW_ASSERT(...)
Definition: Assert.hpp:14
Serializable::SizeType getSerializeSizeLeft() const override
Get remaining serialization buffer size.
SerializeStatus serializeSkip(FwSizeType numBytesToSkip) override
Skip specified number of bytes during serialization.
U8 * getBuffAddrSer()
Get address of end of serialization (DANGEROUS!)
virtual ~LinearBufferBase()
Destructor.
Big endian serialization.