/* * PacketLib.h * * Created on: Nov 24, 2022 * Author: valerio */ #ifndef INCLUDE_BASEPACKET_H_ #define INCLUDE_BASEPACKET_H_ #include #include #include #include #include #include #include namespace inaf::oasbo::PacketLib { class BasePacketStructure { public: virtual ~BasePacketStructure() = default; virtual std::vector> getPacketStructure() = 0; }; template class T, typename V> class BasePacket { protected: std::vector fieldSizes; T structure; std::map fieldNameToIndexMap; std::map indexToFieldNameMap; uint8_t *binaryPointer; void updateFieldSizes( const std::vector> ¶msTuple) { std::for_each(paramsTuple.begin(), paramsTuple.end(), [&](const std::tuple &tup) { this->fieldSizes.push_back(std::get<2>(tup)); }); } void updateFieldNameAndIndexMap( const std::vector> ¶msTuple) { std::for_each(paramsTuple.begin(), paramsTuple.end(), [&](const std::tuple &tup) { this->fieldNameToIndexMap[std::get<1>(tup)] = std::get<0>( tup); this->indexToFieldNameMap[std::get<0>(tup)] = std::get<1>( tup); }); } void initMemoryStructure(int numberOfField) { this->structure.resize(numberOfField); std::fill(this->structure.begin(), this->structure.end(), 0); } void updateStructureFromBinary() { size_t num_bit_read = 0; // offset from the beginning of the byte for (long unsigned int i = 0; i < this->fieldSizes.size(); i++) { int bit_rem = this->fieldSizes[i]; //remaining bits to read V val = 0; //final value of the field while (bit_rem > 0) { size_t read = this->binaryPointer[num_bit_read / 8]; size_t mask = std::pow(2, 8 - num_bit_read % 8) - 1; read = read & mask; bit_rem = bit_rem - 8 + num_bit_read % 8; read = (bit_rem >= 0) * (read << bit_rem) + (bit_rem < 0) * (read >> -bit_rem); val += read; num_bit_read = (bit_rem > 0) * (num_bit_read + 8 - num_bit_read % 8) + (bit_rem <= 0) * (num_bit_read + 8 - num_bit_read % 8 + bit_rem); } this->structure[i] = val; } } public: BasePacket(std::vector> paramsTuple) { this->updateFieldSizes(paramsTuple); this->updateFieldNameAndIndexMap(paramsTuple); this->initMemoryStructure(paramsTuple.size()); this->binaryPointer = new uint8_t[paramsTuple.size() * sizeof(size_t)]; //tot number of field times the maximum bytesize of the value; } virtual ~BasePacket() = default; std::vector const* getFieldSizes() const { return &fieldSizes; } uint8_t const* getBinaryPointer() const { return binaryPointer; } T const* getStructure() const { return &structure; } void copyToBinaryPointer(const uint8_t *from, uint size) { std::memcpy(binaryPointer, from, size); updateStructureFromBinary(); } void copyToBinaryPointer(const uint8_t *from, uint size, uint offset) { std::memcpy(&binaryPointer[offset], from, size); updateStructureFromBinary(); } size_t indexOfField(std::string fieldName) { return this->fieldNameToIndexMap.at(fieldName); } std::string fieldNameOfIndex(size_t index) { return this->indexToFieldNameMap.at(index); } V getNumberOfFields() { return this->structure.size(); } V operator[](int index) const { return this->structure[index]; } V operator[](std::string fieldName) const { int index = this->fieldNameToIndexMap.at(fieldName); return this->structure[index]; } typename T::iterator begin() const { return this->getStructure()->begin(); } typename T::iterator end() const { return this->getStructure()->end(); } typename T::const_iterator cbegin() const { return this->getStructure()->cbegin(); } typename T::const_iterator cend() const { return this->getStructure()->cend(); } void setValueAt(int index, V val) const { structure.at(index) = val; } V at(int index) const { return this->structure.at(index); } virtual size_t getHeaderSize()=0; virtual size_t getPayloadSize()=0; virtual size_t getTailSize()=0; virtual size_t getMaxPacketSize()=0; }; } #endif