Skip to content
Base_Packet.h 3.9 KiB
Newer Older
Valerio Pastore's avatar
Valerio Pastore committed
/*
Valerio Pastore's avatar
Valerio Pastore committed
 * PacketLib.h
Valerio Pastore's avatar
Valerio Pastore committed
 *
Valerio Pastore's avatar
Valerio Pastore committed
 *  Created on: Nov 24, 2022
 *      Author: valerio
Valerio Pastore's avatar
Valerio Pastore committed
 */

Valerio Pastore's avatar
Valerio Pastore committed
#ifndef INCLUDE_BASEPACKET_H_
#define INCLUDE_BASEPACKET_H_
Valerio Pastore's avatar
Valerio Pastore committed

Valerio Pastore's avatar
Valerio Pastore committed
#include <vector>
#include <map>
#include <string>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
Valerio Pastore's avatar
Valerio Pastore committed


Valerio Pastore's avatar
Valerio Pastore committed
namespace PacketLib {
Valerio Pastore's avatar
Valerio Pastore committed

Valerio Pastore's avatar
Valerio Pastore committed
template<template<typename > class T>
class BasePacket {
Valerio Pastore's avatar
Valerio Pastore committed

Valerio Pastore's avatar
Valerio Pastore committed
private:
	std::vector<int> fieldSizes;
	T<size_t> structure;
	std::map<std::string, int> fieldNameToIndexMap;
	std::map<int, std::string> indexToFieldNameMap;
	uint8_t *binaryPointer;

	void updateFieldSizes(
			const std::vector<std::tuple<int, std::string, int>> &paramsTuple) {
		std::for_each(paramsTuple.begin(), paramsTuple.end(),
				[&](const std::tuple<int, std::string, int> &tup) {
					this->fieldSizes.push_back(std::get<2>(tup));
				});
	}
	void updateFieldNameAndIndexMap(
			const std::vector<std::tuple<int, std::string, int>> &paramsTuple) {
		std::for_each(paramsTuple.begin(), paramsTuple.end(),
				[&](const std::tuple<int, std::string, int> &tup) {
					this->fieldNameToIndexMap[std::get<1>(tup)] = std::get<0>(tup);
					this->indexToFieldNameMap[std::get<0>(tup)] = std::get<1>(tup);
				});
	}
Valerio Pastore's avatar
Valerio Pastore committed

Valerio Pastore's avatar
Valerio Pastore committed
	void initMemoryStructure(int numberOfField) {
		this->structure.resize(numberOfField);
	    std::fill(this->structure.begin(), this->structure.end(), 0);
	}
Valerio Pastore's avatar
Valerio Pastore committed

Valerio Pastore's avatar
Valerio Pastore committed
	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
			size_t val = 0; //final value of the field
Valerio Pastore's avatar
Valerio Pastore committed
			while(bit_rem > 0){
Valerio Pastore's avatar
Valerio Pastore committed
				size_t read = this->binaryPointer[num_bit_read/8];
				size_t mask = std::pow(2,8-num_bit_read%8)-1;
Valerio Pastore's avatar
Valerio Pastore committed
				read = read & mask;

				bit_rem = bit_rem - 8 + num_bit_read%8;
Valerio Pastore's avatar
Valerio Pastore committed
				read = (bit_rem >= 0)*
						(read << bit_rem) +
Valerio Pastore's avatar
Valerio Pastore committed
						(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);
			}
Valerio Pastore's avatar
Valerio Pastore committed
			this->structure[i] = val;
Valerio Pastore's avatar
Valerio Pastore committed
		}
	}

Valerio Pastore's avatar
Valerio Pastore committed
public:
	BasePacket(std::vector<std::tuple<int, std::string, int>> 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;
	}
Valerio Pastore's avatar
Valerio Pastore committed

Valerio Pastore's avatar
Valerio Pastore committed
	std::vector<int> const* getFieldSizes() const {
		return &fieldSizes;
Valerio Pastore's avatar
Valerio Pastore committed
	}
Valerio Pastore's avatar
Valerio Pastore committed
	uint8_t const* getBinaryPointer() const {
		return binaryPointer;
	}
	T<size_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);
	}
	size_t getNumberOfFields(){
		return this->structure.size();
	}
	size_t operator[](int index) const {
		return this->structure[index];
	}

	size_t operator[](std::string fieldName) const {
		int index = this->fieldNameToIndexMap.at(fieldName);
		return this->structure[index];
Valerio Pastore's avatar
Valerio Pastore committed
	}

Valerio Pastore's avatar
Valerio Pastore committed
	typename T<size_t>::iterator begin() const {
		return this->getStructure()->begin();
	}
	typename T<size_t>::iterator end() const {
		return this->getStructure()->end();
	}
	typename T<size_t>::const_iterator cbegin() const {
		return this->getStructure()->cbegin();
	}
	typename T<size_t>::const_iterator cend() const {
		return this->getStructure()->cend();
	}
	void setValueAt(int index, size_t val) const {
		structure.at(index) = val;
	}
	size_t at(int index) const {
		return this->structure.at(index);
	}
};
}
#endif /* INCLUDE_BASEPACKET_H_ */