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

#ifndef INCLUDE_BASEPACKET_H_
#define INCLUDE_BASEPACKET_H_

#include <vector>
#include <map>
#include <string>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>

namespace inaf::oasbo::PacketLib {

class BasePacketStructure {

public:
	virtual ~BasePacketStructure() = default;
	virtual std::vector<std::tuple<int, std::string, int>> getPacketStructure() = 0;
};

Valerio Pastore's avatar
Valerio Pastore committed
class _iterator;
Valerio Pastore's avatar
Valerio Pastore committed
class BasePacket {
Valerio Pastore's avatar
Valerio Pastore committed
protected:
Valerio Pastore's avatar
Valerio Pastore committed
	std::vector<int> fieldSizes;
Valerio Pastore's avatar
Valerio Pastore committed
	std::map<size_t, size_t> fieldNameToOffsetsMap;
Valerio Pastore's avatar
Valerio Pastore committed
	std::map<std::string, int> fieldNameToIndexMap;
	std::map<int, std::string> indexToFieldNameMap;
	uint8_t *binaryPointer;

Valerio Pastore's avatar
Valerio Pastore committed

Valerio Pastore's avatar
Valerio Pastore committed
	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) {
Valerio Pastore's avatar
Valerio Pastore committed
					this->fieldSizes.push_back(std::get < 2 > (tup));
Valerio Pastore's avatar
Valerio Pastore committed

	void updateFieldOffsets(
			const std::vector<std::tuple<int, std::string, int>> &paramsTuple) {
		size_t offset = 0;
		for (size_t i = 0; i < paramsTuple.size(); i++) {
			fieldNameToOffsetsMap[i] = offset;
			offset += std::get < 2 > (paramsTuple[i]);
		}
	}
Valerio Pastore's avatar
Valerio Pastore committed
	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) {
Valerio Pastore's avatar
Valerio Pastore committed
					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
				});
	}

public:

	BasePacket(std::vector<std::tuple<int, std::string, int>> paramsTuple) {
		this->updateFieldSizes(paramsTuple);
		this->updateFieldNameAndIndexMap(paramsTuple);
Valerio Pastore's avatar
Valerio Pastore committed
		this->updateFieldOffsets(paramsTuple);
Valerio Pastore's avatar
Valerio Pastore committed
		this->binaryPointer = new uint8_t[paramsTuple.size() * sizeof(size_t)]; //tot number of field times the maximum bytesize of the value;
	}
	virtual ~BasePacket() = default;

Valerio Pastore's avatar
Valerio Pastore committed
	size_t readValueFromBinaryAt(int index) {
		size_t num_bit_read = fieldNameToOffsetsMap[index]; // offset from the beginning of the byte
		int bit_rem = this->fieldSizes[index]; //remaining bits to read
		size_t value = 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);
			value += 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);
		}
		return value;
	}

Valerio Pastore's avatar
Valerio Pastore committed
	std::vector<int> const* getFieldSizes() const {
		return &fieldSizes;
	}
	uint8_t const* getBinaryPointer() const {
		return binaryPointer;
	}
Valerio Pastore's avatar
Valerio Pastore committed

Valerio Pastore's avatar
Valerio Pastore committed
	void copyToBinaryPointer(const uint8_t *from, uint size) {
		std::memcpy(binaryPointer, from, size);
	}
	void copyToBinaryPointer(const uint8_t *from, uint size, uint offset) {
		std::memcpy(&binaryPointer[offset], from, size);
	}

	size_t indexOfField(std::string fieldName) {
		return this->fieldNameToIndexMap.at(fieldName);
	}
	std::string fieldNameOfIndex(size_t index) {
		return this->indexToFieldNameMap.at(index);
	}

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

	virtual size_t getHeaderSize()=0;
	virtual size_t getPayloadSize()=0;
	virtual size_t getTailSize()=0;
	virtual size_t getMaxPacketSize()=0;
};
}
#endif