Newer
Older
#include <string>
#include <cstring>
#include <algorithm>
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
namespace inaf::oasbo::Packets
{
/**
* @class BasePacketStructure
* @brief Represents the structure of a base packet.
*
* The BasePacketStructure class provides functionality to define and manipulate the structure of a base packet.
* It stores information about the fields, their sizes, offsets, and mappings between field names and indices.
* The class also provides methods to retrieve information about the structure, such as the byte size, field offsets, and field names.
*
* @note This is an abstract base class and should be derived to define specific packet structures. In particular, you should define
* the sourceReadingFunc function.
*/
class BasePacketStructure
{
protected:
/**
* @brief Type alias for the packet structure.
*
* This alias represents the structure of a packet. It is defined as a vector of tuples, where each tuple contains three elements:
* - The first element is of type uint and represents the field index.
* - The second element is of type std::string and represents the field name.
* - The third element is of type uint and represents the field bit size.
*/
using Structure = std::vector<std::tuple<uint, std::string, uint>>; /**< Type alias for the packet structure. */
std::string source; /**< The source of the packet. */
Structure structure; /**< The structure of the packet. */
uint byteSize; /**< The size of the packet in bytes. */
std::vector<uint> fieldSizes; /**< vector of the sizes of the fields in the packet. */
std::unordered_map<uint, uint> indexToOffsetsMap; /**< Mapping of field index to field offset. */
std::unordered_map<std::string, uint> fieldNameToIndexMap; /**< Mapping of field name to field index. */
std::unordered_map<uint, std::string> indexToFieldNameMap; /**< Mapping of field index to field name. */
std::function<Structure(std::string)> sourceReadingFunc; /**< Function to read the packet source and return the structure. */
/**
* @brief Updates the field sizes based on the structure.
* @param structure The structure of the packet.
*/
void updateFieldSizes(const Structure &structure)
{
std::for_each(structure.begin(), structure.end(),
[&](const std::tuple<uint, std::string, uint> &tup)
{
this->fieldSizes.push_back(std::get<2>(tup));
});
}
/**
* @brief Updates the field offsets based on the structure.
* @param structure The structure of the packet.
*/
void updateFieldOffsets(const Structure &structure)
{
uint offset = 0;
for (size_t i = 0; i < structure.size(); i++)
{
indexToOffsetsMap[i] = offset;
offset += std::get<2>(structure[i]);
/**
* @brief Updates the field name and index maps based on the structure.
* @param structure The structure of the packet.
*/
void updateFieldNameAndIndexMap(const Structure &structure)
{
std::for_each(structure.begin(), structure.end(),
[&](const std::tuple<uint, std::string, uint> &tup)
{
this->fieldNameToIndexMap[std::get<1>(tup)] = std::get<0>(tup);
this->indexToFieldNameMap[std::get<0>(tup)] = std::get<1>(tup);
});
}
/**
* @brief Updates the packet structure based on the source.
* @param source The source of the packet structure.
*/
void updateStructure(std::string source)
{
this->source = source;
this->structure = sourceReadingFunc(source);
updateFieldSizes(structure);
updateFieldOffsets(structure);
updateFieldNameAndIndexMap(structure);
uint bitSize = std::accumulate(fieldSizes.begin(), fieldSizes.end(), 0);
this->byteSize = bitSize % 8 == 0 ? bitSize / 8 : bitSize / 8 + 1;
}
public:
/**
* @brief Destructor.
*/
virtual ~BasePacketStructure() = default;
/**
* @brief Constructor.
* @param source The source of the packet structure.
* @param sourceReadingFunc The function to read the packet source and return the structure.
*/
BasePacketStructure(std::string source, std::function<Structure(std::string)> sourceReadingFunc) : source(source), sourceReadingFunc(sourceReadingFunc)
{
this->updateStructure(source);
}
/**
* @brief Copy constructor.
* @param other The other BasePacketStructure object to copy from.
*/
BasePacketStructure(const BasePacketStructure &other)
{
this->source = other.source;
this->byteSize = other.byteSize;
this->fieldSizes = other.fieldSizes;
this->indexToOffsetsMap = other.indexToOffsetsMap;
this->fieldNameToIndexMap = other.fieldNameToIndexMap;
this->indexToFieldNameMap = other.indexToFieldNameMap;
this->sourceReadingFunc = other.sourceReadingFunc;
}
/**
* @brief Changes the source of the packet and updates the structure.
* @param source The new source of the packet structure.
*/
void changeSource(std::string source)
{
updateStructure(source);
}
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
/**
* @brief Gets the size of the packet in bytes.
* @return The size of the packet in bytes.
*/
uint getByteSize()
{
return this->byteSize;
}
/**
* @brief Gets the source of the packet structure.
* @return The source of the packet structure.
*/
std::string getSource()
{
return this->source;
}
/**
* @brief Gets the bit offset of a field in the packet structure.
* @param index The index of the field.
* @return The bit offset of the field, or std::nullopt if the field does not exist.
*/
std::optional<uint> bitOffsetOf(uint index)
{
if (index <= this->numberOfFields())
{
return indexToOffsetsMap.at(index);
}
else
{
time_t now = time(nullptr);
std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
<< "]\t[Base Packet]\t"
<< "No field at " << index
<< ", max is " << numberOfFields() << ", returning nullopt."
<< std::endl;
return std::nullopt;
}
}
/**
* @brief Gets the bit size of a field in the packet structure.
* @param index The index of the field.
* @return The bit size of the field, or std::nullopt if the field does not exist.
*/
std::optional<uint> bitSizeOf(uint index)
{
if (index <= this->numberOfFields())
{
return this->fieldSizes[index];
}
else
{
time_t now = time(nullptr);
std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
<< "]\t[Base Packet]\t"
<< "No field at " << index
<< ", max is " << numberOfFields() << ", returning nullopt."
<< std::endl;
return std::nullopt;
}
}
/**
* @brief Gets the index of a field in the packet structure based on its name.
* @param fieldName The name of the field.
* @return The index of the field, or std::nullopt if the field does not exist.
*/
std::optional<uint> indexOfField(std::string fieldName)
{
std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(),
[](unsigned char c)
{
return std::tolower(c);
});
try
{
return this->fieldNameToIndexMap.at(fieldName);
}
catch (const std::out_of_range &oor)
{
time_t now = time(nullptr);
std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
<< "]\t[Base Packet]\t"
<< "No field of name " << fieldName
<< ", returning nullopt." << std::endl;
return std::nullopt;
}
}
/**
* @brief Gets the name of a field in the packet based on its index.
* @param index The index of the field.
* @return The name of the field, or std::nullopt if the field does not exist.
*/
std::optional<std::string> fieldNameOfIndex(uint index)
{
try
{
return this->indexToFieldNameMap.at(index);
}
catch (const std::out_of_range &oor)
{
time_t now = time(nullptr);
std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
<< "]\t[Base Packet]\t"
<< "No field at " << index
<< ", max is " << numberOfFields() << ", returning nullopt."
<< std::endl;
return std::nullopt;
}
}
/**
* @brief Gets the number of fields in the packet.
* @return The number of fields in the packet.
*/
uint numberOfFields()
{
return this->fieldSizes.size();
}
/**
* @brief Gets the field name to index map.
* @return The field name to index map.
*/
std::unordered_map<std::string, uint> getFieldNameToIndexMap() const
{
return this->fieldNameToIndexMap;
}
/**
* @brief Gets the index to offset map.
* @return The index to offset map.
*/
std::unordered_map<uint, uint> getIndexToOffsetsMap() const
{
return this->indexToOffsetsMap;
}
/**
* @brief Gets the index to field name map.
* @return The index to field name map.
*/
std::unordered_map<uint, std::string> getIndexToFieldNameMap() const
{
return this->indexToFieldNameMap;
}
};
/**
* @brief Represents an iterator that iterates over individual fields in the packet.
*
* The `bit_iterator` class provides a random access iterator interface for iterating over individual fields in the packet.
* It is templated on the value type of the packet fields. I.e. if the largest packet fields is 32-bit, then the value type should be at least uint32_t.
*
* @tparam ValueType The value type of the values returned by the iterator. The value
*/
template <typename ValueType>
class bit_iterator
{
using iterator_category = std::random_access_iterator_tag;
using value_type = ValueType;
using difference_type = std::ptrdiff_t;
using pointer = ValueType *;
using reference = ValueType &;
/**
* @brief Pointer to the packet data.
*/
const uint8_t *m_data;
/**
* @brief Current offset within the packet.
*/
int m_offset;
/**
* @brief Pointer to the BasePacketStructure.
*/
BasePacketStructure *m_structure;
/**
* @brief Function to retrieve the value from data based on offset and size.
*/
std::function<ValueType(const uint8_t *, uint, uint)> m_func;
private:
const uint8_t *m_data;
int m_offset;
BasePacketStructure *m_structure;
std::function<ValueType(const uint8_t *, uint, uint)> m_func;
public:
bit_iterator(const uint8_t *data, int offset,
BasePacketStructure *structure,
std::function<ValueType(const uint8_t *, uint, uint)> func) : m_data(data), m_offset(offset), m_structure(structure), m_func(func)
{
}
bit_iterator(const bit_iterator &other) : m_data(other.m_data), m_offset(other.m_offset), m_structure(
other.m_structure),
m_func(other.m_func)
{
}
bit_iterator &operator++()
{
++m_offset;
return *this;
}
bit_iterator operator++(int)
{
bit_iterator temp(*this);
++m_offset;
return temp;
}
bit_iterator &operator--()
{
--m_offset;
return *this;
}
bit_iterator operator--(int)
{
bit_iterator temp(*this);
--m_offset;
return temp;
}
bit_iterator operator+(int n) const
{
return bit_iterator(m_data, m_offset + n, m_structure, m_func);
}
bit_iterator operator-(int n) const
{
return bit_iterator(m_data, m_offset - n, m_structure, m_func);
}
int operator-(const bit_iterator &other) const
{
return m_offset - other.m_offset;
}
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
bool operator==(const bit_iterator &other) const
{
return m_data == other.m_data && m_offset == other.m_offset;
}
bool operator!=(const bit_iterator &other) const
{
return !(*this == other);
}
ValueType operator*() const
{
auto offset = m_structure->bitOffsetOf(m_offset); // offset from the beginning of the byte
auto num_bits = m_structure->bitSizeOf(m_offset);
return m_func(m_data, offset.value(), num_bits.value());
}
};
/**
* @brief Represents a template class for handling packets with a specific structure.
*
* The `BasePacketTempl` class provides a generic template for handling packets with a specified structure.
* It includes methods for reading and writing values from/to memory, as well as other utility functions.
*
* @tparam ValueType The value type of the largest packet fields. i.e The value type should be at least uint32_t if the largest packet field is 32-bit.
*/
template <typename ValueType>
class BasePacketTempl
{
protected:
BasePacketStructure *packetStructure; /**< Pointer to the structure defining the packet. */
uint8_t *memoryPointer; /**< Pointer to the memory containing packet data. */
/**
* @brief reads a binary value from a memory location pointed to by binaryPointer.
* The binary value is represented by num_bits bits starting from the offset-th bit in the memory.
*
* @param binaryPointer Pointer to the memory containing the binary value.
* @param offset The offset of the first bit of the binary value.
* @param num_bits The number of bits to read.
* @return ValueType The value read from memory.
*/
static ValueType _readValueFromMemoryAt_(const uint8_t *binaryPointer,
uint offset, uint num_bits)
{
// Calculate the bit offset from the byte offset:
uint bit_offset = offset % 8;
// Calculate the byte offset from the bit offset:
uint byte_offset = offset / 8;
ValueType value = 0;
ValueType bit = 1;
for (uint i = 0; i < num_bits; i++)
{
// Calculate the byte and bit index of the current bit:
uint byte_index = byte_offset + (bit_offset + i) / 8;
uint bit_index = (bit_offset + i) % 8;
uint8_t byte = binaryPointer[byte_index];
// Create a bit mask to isolate the desired bit:
uint8_t bit_mask = 1 << (7 - bit_index);
// Set the corresponding bit in the return value if the retrieved bit is 1:
value |= (byte & bit_mask) ? (bit << (num_bits - i - 1)) : 0;
}
return value;
}
/**
* @brief Calculates the minimum number of bits required to represent a given value.
*
* @param value The value to calculate the minimum bits for.
* @return size_t The minimum number of bits required.
*/
size_t minBitsRequired(size_t value) const
{
// Handle special cases
size_t bitsNeeded = 1;
while (value != 0)
{
bitsNeeded++;
value >>= 1;
}
return bitsNeeded;
}
public:
/**
* @brief Constructor for the BasePacketTempl class.
*
* @param structure The structure defining the packet.
*/
BasePacketTempl(BasePacketStructure &structure)
{
this->packetStructure = new BasePacketStructure(structure);
this->memoryPointer = new uint8_t[structure.getByteSize()];
}
/**
* @brief Copy constructor for the BasePacketTempl class.
*
* @param other The other BasePacketTempl object to copy.
*/
BasePacketTempl(const BasePacketTempl &other)
{
this->packetStructure = new BasePacketStructure(other.getPacketStructure());
this->memoryPointer = new uint8_t[other.packetStructure->getByteSize()];
std::memcpy(this->memoryPointer, other.memoryPointer,
other.packetStructure->getByteSize());
}
/**
* @brief Destructor for the BasePacketTempl class.
*/
virtual ~BasePacketTempl() = default;
/**
* @brief Updates the packet structure.
* @param structure The new packet structure.
*/
void updatePacketStructure(BasePacketStructure &structure)
{
size_t newSize = structure.getByteSize();
size_t oldSize = this->packetStructure->getByteSize();
uint8_t *buff = new uint8_t[newSize];
std::memset(buff, 0, newSize);
std::memcpy(buff, memoryPointer, std::min(newSize, oldSize));
delete this->memoryPointer;
this->memoryPointer = new uint8_t[newSize];
std::memcpy(memoryPointer, buff, newSize);
delete[] buff;
this->packetStructure = &structure;
}
/**
* @brief Reads a value from the memory at a given index.
* @param index The index of the field to read.
* @return std::optional<ValueType> The value read from memory, or std::nullopt if the field does not exist.
*/
std::optional<ValueType> readValueFromMemoryAt(uint index) const
{
auto offset = packetStructure->bitOffsetOf(index); // offset from the beginning of the byte
auto num_bits = packetStructure->bitSizeOf(index); // remaining bits to read
if (offset.has_value() && num_bits.has_value())
return _readValueFromMemoryAt_(memoryPointer, offset.value(),
num_bits.value());
else
{
time_t now = time(nullptr);
std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
<< "]\t[Base Packet]\t"
<< "Error: No field at " << index
<< ", max is " << packetStructure->numberOfFields()
<< ", returning nullopt" << std::endl;
return std::nullopt;
}
}
/**
* @brief Returns a pointer to the memory in which stores the packet.
*
* This function returns a constant pointer to the memory.
*
* @return A constant pointer to the memory.
*/
uint8_t const *getPointerToMemory() const
{
return memoryPointer;
}
/**
* @brief Copies data from a source memory location to the packet's memory.
*
* @param from Pointer to the source memory location.
* @param size Number of bytes to copy.
* @return int The number of bytes copied.
*/
int copyToMemory(const uint8_t *from, uint size)
{
uint max_writable = this->packetStructure->getByteSize();
if (size > max_writable)
{
time_t now = time(nullptr);
std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
<< "]\t[Base Packet]\t"
<< "Error: you are trying to copy "
<< size << " byte where the max size is: " << max_writable
<< std::endl;
std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
<< "]\t[Base Packet]\t"
<< "\tI copy only until "
<< max_writable << " byte" << std::endl;
std::memcpy(memoryPointer, from, max_writable);
return max_writable;
}
else
{
std::memcpy(memoryPointer, from, size);
return size;
}
}
/**
* Copies data from the given memory location to the packet's memory buffer.
*
* @param from Pointer to the source memory location.
* @param size Number of bytes to copy.
* @param offset Offset in the packet's memory buffer to start copying to.
* @return The number of bytes copied.
*/
int copyToMemory(const uint8_t *from, uint size, uint offset)
{
uint max_writable = this->packetStructure->getByteSize();
if (offset > max_writable)
{
time_t now = time(nullptr);
std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
<< "]\t[Base Packet]\t"
<< "Error: you are trying to copy starting from " << offset
<< " byte where the max size is: " << max_writable
<< std::endl;
return -1;
}
if (size + offset > max_writable)
{
time_t now = time(nullptr);
std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
<< "]\t[Base Packet]\t"
<< "Error: you are trying to copy "
<< size + offset << " byte where the max size is: "
<< max_writable << std::endl;
std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
<< "]\t[Base Packet]\t"
<< "\tI copy only until "
<< max_writable << " byte" << std::endl;
int to_write = max_writable - offset;
std::memcpy(&memoryPointer[offset], from, to_write);
return to_write;
}
else
{
std::memcpy(&memoryPointer[offset], from, size);
return size;
}
}
/**
* @brief Accesses the value at the specified index in the packet.
*
* @param index The index of the value to access.
* @return An optional containing the value at the specified index, if it exists.
*/
std::optional<ValueType> operator[](uint index) const
{
return readValueFromMemoryAt(index);
}
/**
* @brief Accesses the value of a field in the packet by its field name.
*
* @param fieldName The name of the field to access.
* @return An optional value of the specified field type. If the field does not exist, the optional will be empty.
*/
std::optional<ValueType> operator[](std::string fieldName) const
{
std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(),
[](unsigned char c)
{
return std::tolower(c);
});
auto index = packetStructure->indexOfField(fieldName);
if (index.has_value())
return readValueFromMemoryAt(index.value());
else
return std::nullopt;
}
/**
* @brief Returns a constant bit iterator pointing to the beginning of the packet data.
*
* @return A constant bit iterator pointing to the beginning of the packet data.
*/
bit_iterator<ValueType> begin() const
{
return bit_iterator<ValueType>(memoryPointer, 0, packetStructure,
&_readValueFromMemoryAt_);
}
/**
* @brief Returns a bit_iterator pointing to the end of the container.
*
* @return A bit_iterator pointing to the end of the container.
*/
bit_iterator<ValueType> end() const
{
return bit_iterator<ValueType>(memoryPointer,
packetStructure->numberOfFields(), packetStructure,
&_readValueFromMemoryAt_);
}
/**
* Writes a value into memory at the specified index.
*
* @param index The index at which to write the value.
* @param value The value to be written.
* @return An optional containing number of fits written, if any.
*/
std::optional<uint> writeValueIntoMemoryAtIndex(uint index, ValueType value)
{
auto offset = this->packetStructure->bitOffsetOf(index);
auto numbits = this->packetStructure->bitSizeOf(index);
size_t min_req = minBitsRequired(value);
if (!offset.has_value() || !numbits.has_value())
return std::nullopt;
if (numbits < min_req)
{
time_t now = time(nullptr);
std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
<< "]\t[Base Packet]\t"
<< "Error: you are trying to write "
<< value << " which requires at least " << min_req
<< " bits in a field of size " << numbits << std::endl;
return std::nullopt;
}
// Calculate the bit offset from the byte offset:
uint bitoffset = offset.value() % 8;
// Calculate the byte offset from the bit offset:
uint byteoffset = offset.value() / 8;
uint numbits_written = 0;
for (size_t i = 0; i < numbits; i++)
{
// Calculate the byte and bit index of the current bit:
uint byte_index = byteoffset + (bitoffset + i) / 8;
uint bit_index = (bitoffset + i) % 8;
// Create a bit mask to isolate the desired bit:
uint8_t bit_mask = 1 << (7 - bit_index);
// Set the corresponding bit in the binary array if the value is 1:
if ((value >> (numbits.value() - i - 1)) & 1)
{
memoryPointer[byte_index] |= bit_mask;
numbits_written++;
}
else
{
memoryPointer[byte_index] &= ~bit_mask;
}
}
return numbits_written;
}
/**
* @brief Get the byte size of the packet structure.
*
* @return The byte size of the packet structure.
*/
uint getPacketStructureByteSize() const
{
return packetStructure->getByteSize();
}
/**
* @brief Returns the packet structure of the BasePacket.
*
* @return A reference to the packet structure.
*/
BasePacketStructure &getPacketStructure() const
{
return *(this->packetStructure);
}
/**
* @brief Checks if the packet has a recognized header.
* @note This is a pure virtual function and must be implemented by derived classes.
* @return true if the packet has a recognized header, false otherwise.
*/
virtual bool hasRecognizedHeader() const = 0;
/**
* @brief Checks if the passed data has a recognized header.
* @param buff The data to check.
* @note This is a pure virtual function and must be implemented by derived classes.
* @return true if buff has a recognized header, false otherwise.
*/
virtual bool isRecognizedHeader(std::vector<uint8_t> buff) const = 0;
/**
* @brief Get the size of the header of the packet.
* @note This is a pure virtual function and must be implemented by derived classes.
* @return The size of the header as an unsigned integer.
*/
virtual uint getHeaderSize() const = 0;
/**
* @brief Get the size of the payload of the packet.
* @note This is a pure virtual function and must be implemented by derived classes.
* @return The size of the payload as an unsigned integer.
*/
virtual uint getPayloadSize() const = 0;
/**
* @brief Get the size of the tail of the packet.
* @note This is a pure virtual function and must be implemented by derived classes.
* @return The size of the tail as an unsigned integer.
*/
virtual uint getTailSize() const = 0;
};
using valueType = size_t;
/**
* @brief Represents a concrete class derived from BasePacketTempl with a specified value type.
*
* The `BasePacket` class is a concrete class derived from `BasePacketTempl` with a value type of `size_t`.
*/
class BasePacket : public BasePacketTempl<valueType>
{
protected:
public:
BasePacket(BasePacketStructure &structure) : BasePacketTempl<valueType>(structure)
{
}
virtual ~BasePacket() = default;
};
}