Parser and test for var_binary (#1425)

This commit is contained in:
Jacqueline Deans 2023-01-11 09:27:30 -06:00 committed by GitHub
parent a8daf4514c
commit 97cf685b6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 1812 additions and 16 deletions

5
.gitignore vendored
View File

@ -37,4 +37,7 @@ civet_server_error.log
server.pem
archive/
.venv
trickops_logs/
trickops_logs/
*.gcda
*.gcno
coverage.info

View File

@ -96,13 +96,16 @@ UTILS_DIRS := \
${TRICK_HOME}/trick_source/trick_utils/shm \
${TRICK_HOME}/trick_source/trick_utils/math \
${TRICK_HOME}/trick_source/trick_utils/units \
${TRICK_HOME}/trick_source/trick_utils/unicode
${TRICK_HOME}/trick_source/trick_utils/unicode \
${TRICK_HOME}/trick_source/trick_utils/var_binary_parser
UTILS_OBJS := $(addsuffix /object_$(TRICK_HOST_CPU)/*.o ,$(UTILS_DIRS))
# filter out the directories that make their own libraries
UTILS_OBJS := $(filter-out ${TRICK_HOME}/trick_source/trick_utils/comm/%, $(UTILS_OBJS))
UTILS_OBJS := $(filter-out ${TRICK_HOME}/trick_source/trick_utils/math/%, $(UTILS_OBJS))
UTILS_OBJS := $(filter-out ${TRICK_HOME}/trick_source/trick_utils/units/%, $(UTILS_OBJS))
UTILS_OBJS := $(filter-out ${TRICK_HOME}/trick_source/trick_utils/var_binary_parser/%, $(UTILS_OBJS))
#-------------------------------------------------------------------------------
# Specify the contents of: libtrick_pyip.a
@ -306,9 +309,20 @@ sim_test:
pytest:
make -C share/trick/pymods/trick
code-coverage: test
lcov --capture --directory trick_source/sim_services --output-file coverage_large.info
lcov --remove coverage_large.info '/Library/*' '/usr/*' '*/io_src/*' '*/test/*' -o coverage.info
COVERAGE_DIRS = trick_source/sim_services \
trick_source/trick_utils/var_binary_parser \
trick_source/trick_utils/unicode \
trick_source/trick_utils/units \
trick_source/trick_utils/interpolator \
trick_source/trick_utils/comm \
trick_source/trick_utils/SAIntegrator
extra-coverage-builds:
@ $(MAKE) test -C trick_source/trick_utils/SAIntegrator
code-coverage: test extra-coverage-builds
lcov --capture $(addprefix --directory , $(COVERAGE_DIRS)) --output-file coverage_large.info
lcov --remove coverage_large.info '/Library/*' '/usr/*' '*/io_src/*' '*/test/*' '*/unittest/*' -o coverage.info
rm coverage_large.info
lcov --list coverage.info

View File

@ -0,0 +1,120 @@
#include <unistd.h>
#include <vector>
#include <string>
#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;
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::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;
};
class ParsedBinaryMessage {
public:
ParsedBinaryMessage() : _byteswap(false), _nonames(false) {}
ParsedBinaryMessage (bool byteswap, bool nonames) : _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;
};

View File

@ -13,7 +13,9 @@ typedef enum {
VS_SIE_RESOURCE = 2,
VS_LIST_SIZE = 3 ,
VS_STDIO = 4,
VS_SEND_ONCE = 5
VS_SEND_ONCE = 5,
VS_MIN_CODE = VS_IP_ERROR,
VS_MAX_CODE = VS_SEND_ONCE
} VS_MESSAGE_TYPE ;
#endif

View File

@ -1,13 +1,14 @@
TRICK_CFLAGS += -I./models
TRICK_CXXFLAGS += -I./models -I$(GTEST_HOME)/include -std=c++11
TRICK_CXXFLAGS += -I./models
all: test_client
clean: clean_test_client
TEST_CLIENT_LIBS += -L${GTEST_HOME}lib64 -L${GTEST_HOME}lib -lgtest -lgtest_main -lpthread
TEST_CLIENT_LIBS += -L${GTEST_HOME}/lib64 -L${GTEST_HOME}/lib -lgtest -lgtest_main -lpthread -L${TRICK_LIB_DIR} -ltrick_var_binary_parser
test_client: models/test_client/test_client.cpp
cd models/test_client; $(TRICK_CXX) test_client.cpp $(TRICK_SYSTEM_LDFLAGS) $(TRICK_CXXFLAGS) -o test_client $(TEST_CLIENT_LIBS) -std=c++11
test_client: models/test_client/test_client.cpp
cd models/test_client; $(TRICK_CXX) test_client.cpp -o test_client $(TRICK_CXXFLAGS) -I$(TRICK_HOME)/include $(TEST_CLIENT_LIBS) -std=c++11
clean_test_client:
rm -f models/test_client/test_client
rm -f models/test_client/test_client

View File

@ -13,6 +13,8 @@
#include <gtest/gtest.h>
#include "trick/var_binary_parser.hh"
#define SOCKET_BUF_SIZE 20480
#define DOUBLE_TOL 1e-5
@ -92,6 +94,21 @@ class Socket {
ret = receive();
}
std::vector<unsigned char> receive_bytes() {
unsigned char buffer[SOCKET_BUF_SIZE];
int numBytes = recv(_socket_fd, buffer, SOCKET_BUF_SIZE, 0);
if (numBytes < 0) {
std::cout << "Failed to read from socket" << std::endl;
}
std::vector<unsigned char> bytes;
for (int i = 0; i < numBytes; i++) {
bytes.push_back(buffer[i]);
}
return bytes;
}
bool check_for_message_availible(long timeout_sec = 2) {
fd_set read_fd_set;
struct timeval timeout = { .tv_sec = timeout_sec, .tv_usec = 0 };
@ -581,9 +598,6 @@ TEST_F (VariableServerTest, CopyAndWriteModes) {
// Is this what we want? Maybe we should have more strict communication on whether the data has been staged so the first message isn't incorrect
spin();
// expected = "0 -1234 1234";
// EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0);
// std::cout << "\tExpected: " << expected << "\n\tActual: " << reply << std::endl;
expected = "-1234 1234";
parse_message(socket.receive());
EXPECT_EQ(strcmp_IgnoringWhiteSpace(vars, expected), 0) << "Received: " << vars << " Expected: " << expected;
@ -683,6 +697,163 @@ TEST_F (VariableServerTest, CopyAndWriteModes) {
socket.clear_buffered_data();
}
bool getCompleteBinaryMessage(ParsedBinaryMessage& message, Socket& socket) {
static const int max_retries = 5;
int tries = 0;
bool parse_success = false;
std::vector<unsigned char> reply;
// Try parsing until message received is correct
// May take a cycle or 2 to update properly
while (!parse_success && tries++ < max_retries) {
try {
reply = socket.receive_bytes();
message.parse(reply);
parse_success = true;
} catch (const MalformedMessageException& ex) {
std::cout << "Attempt " << tries << " failed with exception " << ex.what() << std::endl;;
}
}
return parse_success;
}
TEST_F (VariableServerTest, Binary) {
if (socket_status != 0) {
FAIL();
}
std::vector<unsigned char> reply;
socket << "trick.var_binary()\ntrick.var_add(\"vsx.vst.c\")\ntrick.var_add(\"vsx.vst.k\")\ntrick.var_add(\"vsx.vst.o\")\ntrick.var_add(\"vsx.vst.m\")\n";
ParsedBinaryMessage message;
if (!getCompleteBinaryMessage(message, socket)) {
FAIL() << "Parser was not able to interpret the message.";
}
EXPECT_EQ(message.getMessageType(), 0);
ASSERT_EQ(message.getNumVars(), 4);
EXPECT_EQ(strcmp(message.variables[0].getName().c_str(), "vsx.vst.c"), 0);
EXPECT_EQ(message.variables[0].getType(), TRICK_SHORT);
EXPECT_EQ(message.variables[0].getValue<short>(), -1234);
EXPECT_EQ(strcmp(message.variables[1].getName().c_str(), "vsx.vst.k"), 0);
EXPECT_EQ(message.variables[1].getType(), TRICK_LONG_LONG);
EXPECT_EQ(message.variables[1].getValue<long long>(), -12345678912345);
EXPECT_EQ(strcmp(message.variables[2].getName().c_str(), "vsx.vst.o"), 0);
EXPECT_EQ(message.variables[2].getType(), TRICK_STRING);
std::string actual = message.variables[2].getValue<std::string>();
std::string expected = "You will rejoice to hear that no disaster has accompanied the commencement of an enterprise which you have regarded with such evil forebodings. I arrived here yesterday, and my first task is to assure my dear sister of my welfare and increasing confidence in the success of my undertaking.\0";
EXPECT_EQ(actual.substr(0, actual.size()-1), expected);
Var variable = message.getVariable("vsx.vst.m");
EXPECT_EQ(strcmp(variable.getName().c_str(), "vsx.vst.m"), 0);
EXPECT_EQ(variable.getType(), TRICK_BOOLEAN);
EXPECT_EQ(variable.getValue<bool>(), true);
// Switch to nonames
socket << "trick.var_binary_nonames()\n";
ParsedBinaryMessage noname_message(false, true);
if (!getCompleteBinaryMessage(noname_message, socket)) {
FAIL() << "Parser was not able to interpret the message.";
}
EXPECT_EQ(noname_message.getMessageType(), 0);
ASSERT_EQ(noname_message.getNumVars(), 4);
EXPECT_EQ(strcmp(noname_message.variables[0].getName().c_str(), "<no name>"), 0);
EXPECT_EQ(noname_message.variables[0].getType(), TRICK_SHORT);
EXPECT_EQ(noname_message.variables[0].getValue<short>(), -1234);
EXPECT_EQ(strcmp(noname_message.variables[1].getName().c_str(), "<no name>"), 0);
EXPECT_EQ(noname_message.variables[1].getType(), TRICK_LONG_LONG);
EXPECT_EQ(noname_message.variables[1].getValue<long long>(), -12345678912345);
EXPECT_EQ(strcmp(noname_message.variables[2].getName().c_str(), "<no name>"), 0);
EXPECT_EQ(noname_message.variables[2].getType(), TRICK_STRING);
actual = noname_message.variables[2].getValue<std::string>();
EXPECT_EQ(actual.substr(0, actual.size()-1), expected);
Var variable_noname = noname_message.getVariable(3);
EXPECT_EQ(strcmp(variable_noname.getName().c_str(), "<no name>"), 0);
EXPECT_EQ(variable_noname.getType(), TRICK_BOOLEAN);
EXPECT_EQ(variable_noname.getValue<bool>(), true);
}
TEST_F (VariableServerTest, DISABLED_BinaryByteswap) {
// TODO: VAR_BYTESWAP DOES NOT APPEAR TO WORK CORRECTLY
std::vector<unsigned char> reply;
socket << "trick.var_binary()\ntrick.var_byteswap(False)\ntrick.var_add(\"vsx.vst.f\")\ntrick.var_add(\"vsx.vst.j\")\n";
socket.receive_bytes();
reply = socket.receive_bytes();
// Test byteswap
std::cout << "Message: ";
for (unsigned char byte : reply) {
std::cout << "0x" << std::setw(2) << std::setfill('0') << std::hex << (int)byte << " ";
}
std::cout << std::endl;
ParsedBinaryMessage message;
try {
message.parse(reply);
} catch (const MalformedMessageException& ex) {
FAIL() << "Parser threw an exception: " << ex.what();
}
EXPECT_EQ(message.getMessageType(), 0);
ASSERT_EQ(message.getNumVars(), 2);
EXPECT_EQ(strcmp(message.variables[0].getName().c_str(), "vsx.vst.f"), 0);
EXPECT_EQ(message.variables[0].getType(), TRICK_UNSIGNED_INTEGER);
EXPECT_EQ(message.variables[0].getValue<unsigned int>(), 123456);
EXPECT_EQ(strcmp(message.variables[1].getName().c_str(), "vsx.vst.j"), 0);
EXPECT_EQ(message.variables[1].getType(), TRICK_DOUBLE);
EXPECT_EQ(message.variables[1].getValue<double>(), -1234.567890);
socket << "trick.var_byteswap(True)\n";
socket.receive_bytes();
reply = socket.receive_bytes();
std::cout << "Message: ";
for (unsigned char byte : reply) {
std::cout << "0x" << std::setw(2) << std::setfill('0') << std::hex << (int)byte << " ";
}
std::cout << std::endl;
ParsedBinaryMessage byteswap_message(true, false);
try {
byteswap_message.parse(reply);
} catch (const MalformedMessageException& ex) {
FAIL() << "Parser threw an exception: " << ex.what();
}
EXPECT_EQ(byteswap_message.getMessageType(), 0);
ASSERT_EQ(byteswap_message.getNumVars(), 2);
EXPECT_EQ(strcmp(byteswap_message.variables[0].getName().c_str(), "vsx.vst.f"), 0);
EXPECT_EQ(byteswap_message.variables[0].getType(), TRICK_UNSIGNED_INTEGER);
EXPECT_EQ(byteswap_message.variables[0].getValue<unsigned int>(), 123456);
std::cout << "Byteswap value: " << byteswap_message.variables[0].getValue<unsigned int>() << std::endl;
EXPECT_EQ(strcmp(byteswap_message.variables[1].getName().c_str(), "vsx.vst.j"), 0);
EXPECT_EQ(byteswap_message.variables[1].getType(), TRICK_DOUBLE);
EXPECT_EQ(byteswap_message.variables[1].getValue<double>(), -1234.567890);
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
int result = RUN_ALL_TESTS();

View File

@ -3,7 +3,7 @@ RM = rm -rf
CC = cc
CPP = c++
CFLAGS = -g -Wall -std=c++11
CFLAGS = -g -Wall -std=c++11 ${TRICK_CXXFLAGS}
INCLUDE_DIRS = -Iinclude
OBJDIR = obj
LIBDIR = lib

View File

@ -3,7 +3,7 @@ include ${TRICK_HOME}/share/trick/makefiles/Makefile.common
RM = rm -rf
TRICK_CPPFLAGS += -I$(GTEST_HOME)/include -I$(TRICK_HOME)/include -g -Wall -Wextra -std=c++11 ${TRICK_SYSTEM_CXXFLAGS}
TRICK_CPPFLAGS += -I$(GTEST_HOME)/include -I$(TRICK_HOME)/include -g -Wall -Wextra -std=c++11 ${TRICK_CXXFLAGS}
INCLUDE_DIRS = -I../include -I$(GTEST_HOME)/include
SAI_OBJDIR = obj

View File

@ -0,0 +1,2 @@
*.o
TEST_var_binary_parser

View File

@ -0,0 +1,52 @@
RM = rm -rf
CC = cc
CPP = c++
include ${TRICK_HOME}/share/trick/makefiles/Makefile.common
#include ${TRICK_HOME}/share/trick/makefiles/Makefile.tricklib
CFLAGS = -g -Wall -Wextra -std=c++11 $(TRICK_CXXFLAGS)
INCLUDE_DIRS = -I${TRICK_HOME}/include
OBJDIR = obj
LIBDIR = lib
LIBNAME = libtrick_var_binary_parser.a
LIBOBJS = ${OBJDIR}/var_binary_parser.o
TRICK_LIB := $(TRICK_LIB_DIR)/$(LIBNAME)
# TRICK_LIB := $(TRICK_HOME)/lib/$(LIBNAME)
trick: ${TRICK_LIB}
install: ${TRICK_LIB}
all: test
test: ${LIBDIR}/${LIBNAME}
${MAKE} -C test
$(LIBOBJS): $(OBJDIR)/%.o : src/%.cc | $(OBJDIR)
$(CPP) $(CFLAGS) ${INCLUDE_DIRS} -c $< -o $@
${LIBDIR}/${LIBNAME}: ${LIBOBJS} | ${LIBDIR}
ar crs $@ ${LIBOBJS}
${OBJDIR}:
mkdir -p ${OBJDIR}
${LIBDIR}:
mkdir -p ${LIBDIR}
${TRICK_LIB}: ${LIBDIR}/${LIBNAME}
cp ${LIBDIR}/${LIBNAME} $(TRICK_LIB)
clean:
${RM} -r ${OBJDIR}
${MAKE} -C test clean
spotless:
${RM} ${OBJDIR}
${RM} ${LIBDIR}
${MAKE} -C unittest spotless
${MAKE} -C examples spotless

View File

@ -0,0 +1,364 @@
#include "trick/var_binary_parser.hh"
#include "trick/variable_server_message_types.h"
#include <climits>
#include <iostream>
#include <sstream>
// Utility method
uint64_t bytesToInt(const std::vector<unsigned char>& bytes, bool byteswap) {
uint64_t result = 0;
if (byteswap) {
for (unsigned int i = 0; i < bytes.size(); i++) {
result |= bytes[bytes.size() - 1 - i] << i*8;
}
} else {
for (unsigned int i = 0; i < bytes.size(); i++) {
result |= bytes[i] << i*8;
}
}
return result;
}
class MessageIterator {
public:
MessageIterator(const std::vector<unsigned char>& container) : _container(container), _index(0) {}
std::vector<unsigned char> slice(unsigned int length) {
unsigned int slice_end = _index + length;
if (_index > _container.size() || slice_end > _container.size()) {
throw MalformedMessageException("Message ends unexpectedly");
}
return std::vector<unsigned char>(_container.begin() + _index, _container.begin() + slice_end);
}
void operator+= (int n) {
_index += n;
}
private:
std::vector<unsigned char> _container;
unsigned int _index;
};
/**************************************************************************
* Var implementation
**************************************************************************/
const size_t ParsedBinaryMessage::header_size = 12;
const size_t ParsedBinaryMessage::message_indicator_size = 4;
const size_t ParsedBinaryMessage::variable_num_size = 4;
const size_t ParsedBinaryMessage::message_size_size = 4;
const size_t ParsedBinaryMessage::variable_name_length_size = 4;
const size_t ParsedBinaryMessage::variable_type_size = 4;
const size_t ParsedBinaryMessage::variable_size_size = 4;
int ParsedBinaryMessage::parse (const std::vector<unsigned char>& bytes){
if (bytes.size() < header_size) {
throw MalformedMessageException(std::string("Not enough bytes in message to contain header: expected at least 12, got " + std::to_string(bytes.size())));
}
MessageIterator messageIterator (bytes);
// First 4 bytes is message type
_message_type = bytesToInt(messageIterator.slice(message_indicator_size), _byteswap);
if (!validateMessageType(_message_type)) {
throw MalformedMessageException(std::string("Received unknown message type: " + std::to_string(_message_type)));
}
messageIterator += message_indicator_size;
// Next 4 bytes is message size
_message_size = bytesToInt(messageIterator.slice(message_size_size), _byteswap);
if (bytes.size() - message_indicator_size != _message_size) {
std::string error_message = "Message size in header (" + std::to_string(_message_size) + ") does not match size of message received (" + std::to_string(bytes.size() - message_indicator_size) + ")";
throw MalformedMessageException(error_message);
}
messageIterator += message_size_size;
// Next 4 bytes is number of variables
_num_vars = bytesToInt(messageIterator.slice(variable_num_size), _byteswap);
messageIterator += variable_num_size;
// Pull out all of the variables
for (unsigned int i = 0; i < _num_vars; i++) {
Var variable;
if (!_nonames) {
// Get the name
size_t name_length = bytesToInt(messageIterator.slice(variable_name_length_size), _byteswap);
messageIterator += variable_name_length_size;
variable.setName(name_length, messageIterator.slice(name_length));
messageIterator += name_length;
}
// Parse the type first
int var_type = bytesToInt(messageIterator.slice(variable_type_size), _byteswap);
messageIterator += variable_type_size;
size_t var_size = bytesToInt(messageIterator.slice(variable_size_size), _byteswap);
messageIterator += variable_size_size;
variable.setValue(messageIterator.slice(var_size), var_size, static_cast<TRICK_TYPE>(var_type), _byteswap);
messageIterator += var_size;
variables.emplace_back(variable);
}
return 0;
}
void ParsedBinaryMessage::combine (const ParsedBinaryMessage& other) {
if (_message_type != other._message_type) {
std::string error_message = "Trying to combine two messages with different message indicators (" + std::to_string(_message_type) + " and " + std::to_string(other._message_type) + ")";
throw MalformedMessageException(error_message);
}
// Combined size - subtract the header size from other message size
_message_size += other._message_size - message_size_size - variable_num_size;
// Combine variables
_num_vars += other._num_vars;
variables.insert(variables.end(), other.variables.begin(), other.variables.end());
// Other error checking - duplicate variables?
}
Var ParsedBinaryMessage::getVariable(const std::string& name) {
if (_nonames)
throw IncorrectUsageException("Cannot fetch variables by name in noname message");
for (auto variable : variables) {
if (variable.getName() == name)
return variable;
}
throw IncorrectUsageException("Variable " + name + " does not exist in this message.");
}
Var ParsedBinaryMessage::getVariable(unsigned int index) {
if (index >= variables.size()) {
throw IncorrectUsageException("Variable index " + std::to_string(index) + " does not exist in this message.");
}
return variables[index];
}
int ParsedBinaryMessage::getMessageType() const {
return _message_type;
}
unsigned int ParsedBinaryMessage::getMessageSize() const {
return _message_size;
}
unsigned int ParsedBinaryMessage::getNumVars() const {
return _num_vars;
}
// Static methods
bool ParsedBinaryMessage::validateMessageType(int message_type) {
return message_type >= VS_MIN_CODE && message_type <= VS_MAX_CODE;
}
/**************************************************************************
* Var implementation
**************************************************************************/
void Var::setName(size_t name_size, const std::vector<unsigned char>& name_data) {
_has_name = true;
_name_length = name_size;
std::stringstream ss;
for (unsigned char character : name_data) {
ss << static_cast<char>(character);
}
_name = ss.str();
}
void Var::setValue(const std::vector<unsigned char>& bytes, size_t size, TRICK_TYPE type, bool byteswap) {
_trick_type = type;
_var_size = size;
_byteswap = byteswap;
value_bytes = std::vector<unsigned char> (bytes);
}
Number Var::getInterpreter() const {
Number interpreted_val;
if (_byteswap) {
for (unsigned int i = 0; i < _var_size; i++) {
interpreted_val.raw_bytes[i] = value_bytes[_var_size - 1 - i];
}
} else {
for (unsigned int i = 0; i < _var_size; i++) {
interpreted_val.raw_bytes[i] = value_bytes[i];
}
}
return interpreted_val;
}
std::string Var::getName() const {
if (_has_name) {
return _name;
} else {
return std::string ("<no name>");
}
}
TRICK_TYPE Var::getType() const {
return _trick_type;
}
// Template specialization for each supported type
template<>
char Var::getValue<char> () const {
if (_trick_type != TRICK_CHARACTER) {
throw ParseTypeException();
}
return getInterpreter().char_val;
}
template<>
unsigned char Var::getValue<unsigned char> () const {
if (_trick_type != TRICK_UNSIGNED_CHARACTER) {
throw ParseTypeException();
}
return getInterpreter().unsigned_char_val;
}
template<>
bool Var::getValue<bool> () const {
if (_trick_type != TRICK_BOOLEAN) {
throw ParseTypeException();
}
return getInterpreter().bool_val;
}
template<>
short Var::getValue<short> () const {
if (_trick_type != TRICK_SHORT) {
throw ParseTypeException();
}
return getInterpreter().short_val;
}
template<>
unsigned short Var::getValue<unsigned short> () const {
if (_trick_type != TRICK_UNSIGNED_SHORT) {
throw ParseTypeException();
}
return getInterpreter().unsigned_short_val;
}
template<>
unsigned int Var::getValue<unsigned int> () const {
if (_trick_type != TRICK_UNSIGNED_INTEGER) {
throw ParseTypeException();
}
return getInterpreter().unsigned_int_val;
}
template<>
int Var::getValue<int> () const {
if (_trick_type != TRICK_INTEGER) {
throw ParseTypeException();
}
return getInterpreter().int_val;
}
template<>
long Var::getValue<long> () const {
if (_trick_type != TRICK_LONG) {
throw ParseTypeException();
}
return getInterpreter().long_val;
}
template<>
unsigned long Var::getValue<unsigned long> () const {
if (_trick_type != TRICK_UNSIGNED_LONG) {
throw ParseTypeException();
}
return getInterpreter().unsigned_long_val;
}
template<>
long long Var::getValue<long long> () const {
if (_trick_type != TRICK_LONG_LONG) {
throw ParseTypeException();
}
return getInterpreter().long_long_val;
}
template<>
unsigned long long Var::getValue<unsigned long long> () const {
if (_trick_type != TRICK_UNSIGNED_LONG_LONG) {
throw ParseTypeException();
}
return getInterpreter().unsigned_long_long_val;
}
template<>
float Var::getValue<float> () const {
if (_trick_type != TRICK_FLOAT) {
throw ParseTypeException();
}
return getInterpreter().float_val;
}
template<>
double Var::getValue<double> () const {
if (_trick_type != TRICK_DOUBLE) {
throw ParseTypeException();
}
return getInterpreter().double_val;
}
template <>
std::string Var::getValue<std::string> () const {
if (_trick_type != TRICK_STRING) {
throw ParseTypeException();
}
std::stringstream stream;
for (unsigned char character : value_bytes) {
stream << static_cast<char>(character);
}
return stream.str();
}
template <>
wchar_t Var::getValue<wchar_t> () const {
if (_trick_type != TRICK_WCHAR) {
throw ParseTypeException();
}
return getInterpreter().wchar_val;
}

View File

@ -0,0 +1,37 @@
#SYNOPSIS:
#
## make [all] - makes everything.
# make TARGET - makes the given target.
# # make clean - removes all files generated by make.
# Flags passed to the preprocessor.
CPPFLAGS += -g -Wall -Wextra -std=c++11 ${TRICK_SYSTEM_CXXFLAGS} -I../include -I${TRICK_HOME}/include
# TRICK_LIBS = ${TRICK_LIB_DIR}/libtrick_units.a
EXEC_LINK_LIBS += -L${GTEST_HOME}/lib64 -L${GTEST_HOME}/lib -lgtest -lgtest_main
#Added pthreads for Ubuntu
EXEC_LINK_LIBS += -lpthread
OTHER_OBJECTS = ../obj/*.o
TESTS = TEST_var_binary_parser
GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \
$(GTEST_DIR)/include/gtest/internal/*.h
all : $(TESTS) test
test: $(TESTS)
./TEST_var_binary_parser --gtest_output=xml:${TRICK_HOME}/trick_test/TEST_var_binary_parser.xml
clean :
rm -f $(TESTS)
rm -f *.o
TEST_var_binary_parser.o : TEST_var_binary_parser.cc $(OTHER_OBJECTS)
$(CXX) $(CPPFLAGS) -c $<
TEST_var_binary_parser : TEST_var_binary_parser.o $(OTHER_OBJECTS)
@echo 'Building TEST_var_binary_parser'
$(CXX) $(TRICK_SYSTEM_LDFLAGS) -o $@ $^ -L${TRICK_HOME}/lib_${TRICK_HOST_CPU} $(LIBS) $(EXEC_LINK_LIBS)

File diff suppressed because it is too large Load Diff