trick/include/trick/var_binary_parser.hh

142 lines
5.0 KiB
C++

#include <unistd.h>
#include <vector>
#include <string>
#include <map>
#include <exception>
#include "trick/parameter_types.h"
class IncorrectUsageException : public std::exception
{
private:
std::string _message;
public:
IncorrectUsageException(std::string msg) : _message(msg) {}
const char * what() const noexcept override { return _message.c_str(); }
};
class ParseTypeException : public IncorrectUsageException
{
public:
ParseTypeException() : IncorrectUsageException("Mismatched trick type and template call") {}
};
class MalformedMessageException : public std::exception
{
private:
std::string _message;
public:
MalformedMessageException() : _message("Attempted to parse an incorrectly formed message") {}
MalformedMessageException(std::string msg) : _message(msg) {}
const char * what() const noexcept override { return _message.c_str(); }
};
typedef union Number {
unsigned char raw_bytes[sizeof(long long)]; // Raw bytes
uint8_t unsigned_char_val;
int8_t char_val;
bool bool_val;
wchar_t wchar_val;
uint16_t unsigned_short_val;
int16_t short_val;
uint32_t unsigned_int_val;
int32_t int_val;
uint64_t unsigned_long_val;
int64_t long_val;
unsigned long long unsigned_long_long_val;
long long long_long_val;
float float_val;
double double_val;
} Number;
const static std::map<TRICK_TYPE, unsigned int> type_size_map = {{TRICK_CHARACTER, sizeof(char)},
{TRICK_UNSIGNED_CHARACTER, sizeof(unsigned char)},
{TRICK_SHORT, sizeof(short)},
{TRICK_UNSIGNED_SHORT, sizeof(unsigned short)},
{TRICK_INTEGER, sizeof(int)},
{TRICK_UNSIGNED_INTEGER, sizeof(unsigned int)},
{TRICK_LONG, sizeof(long)},
{TRICK_UNSIGNED_LONG, sizeof(unsigned long)},
{TRICK_LONG_LONG, sizeof(long long)},
{TRICK_UNSIGNED_LONG_LONG, sizeof(unsigned long)},
{TRICK_FLOAT, sizeof (float)},
{TRICK_DOUBLE, sizeof (double)},
{TRICK_BOOLEAN, sizeof (bool)},
{TRICK_WCHAR, sizeof (wchar_t)}
};
class Var {
public:
Var () : _has_name(false) {};
void setValue(const std::vector<unsigned char>& bytes, size_t size, TRICK_TYPE type, bool byteswap = false);
void setName(size_t name_size, const std::vector<unsigned char>& name_data);
// The closest to runtime return type polymorphism that I can think of
// There won't be a general case
template <typename T>
T getValue() const;
std::vector<unsigned char> getRawBytes() const;
int getArraySize() const;
std::string getName() const;
TRICK_TYPE getType() const;
private:
std::vector<unsigned char> value_bytes;
Number getInterpreter () const;
bool _has_name;
unsigned int _name_length;
std::string _name;
bool _byteswap;
TRICK_TYPE _trick_type;
unsigned int _var_size;
unsigned int _arr_length;
};
class ParsedBinaryMessage {
public:
ParsedBinaryMessage() : ParsedBinaryMessage(false, false) {}
ParsedBinaryMessage (bool byteswap, bool nonames) : _message_type(0), _message_size(0), _num_vars(0), _byteswap(byteswap), _nonames(nonames) {}
void combine (const ParsedBinaryMessage& message);
int parse (const std::vector<unsigned char>& bytes);
int getMessageType() const;
unsigned int getMessageSize() const;
unsigned int getNumVars() const;
Var getVariable(const std::string& name);
Var getVariable(unsigned int index);
std::vector<Var> variables;
private:
static bool validateMessageType(int message_type);
int _message_type;
unsigned int _message_size;
unsigned int _num_vars;
bool _byteswap;
bool _nonames;
const static size_t header_size;
const static size_t message_indicator_size;
const static size_t variable_num_size;
const static size_t message_size_size;
const static size_t variable_name_length_size;
const static size_t variable_type_size;
const static size_t variable_size_size;
};