#include #include "frame.h" unsigned char hex_byte_to_byte(unsigned char byte) { if (byte >= 'a' && byte <= 'f') return byte - 'a' + 10; if (byte >= 'A' && byte <= 'F') return byte - 'A' + 10; if (byte >= '0' && byte <= '9') return byte - '0'; throw std::invalid_argument("Character isn't a hex value!"); } unsigned char hex_value_to_byte(const unsigned char* hex) { // Could've been done with sprintf, however this is faster return (hex_byte_to_byte(hex[0]) << 4) | hex_byte_to_byte(hex[1]); } unsigned char next_hex_byte(const unsigned char*& iso_tp_frame) { if (*iso_tp_frame == '\0') throw "Bad"; char byte = hex_value_to_byte(iso_tp_frame); iso_tp_frame += 2; return byte; } /* Private */ void Frame::parse_frame_str(const unsigned char* iso_tp_frame) { // Every two characters in a frame represent the hex value of a single byte // Example (spaces added for visual clarity): // b0 b1 b2 b3 b4 b5 b6 b7 // 02 10 C0 00 00 00 00 00 unsigned char byte0 = next_hex_byte(iso_tp_frame); this->type =(FrameType)((byte0 & 0b11110000) >> 4); this->size = byte0 & 0b00001111; switch (this->type) { // Single frame case SF: this->data_size = size; break; // First frame case FF: { unsigned char byte1 = next_hex_byte(iso_tp_frame); this->size = (this->size << 8) | byte1; this->data_size = 6; } break; // Consecutive frame case CF: this->index = this->size; this->data_size = 7; // Message objects track total amount of data // from multipart messages this->size = data_size; break; // Flow control frame case FC: this->data_size = 2; // The FC flag takes less than a byte, so I'm // not considering it data. Maybe I should? this->size = 2; break; } this->data = new unsigned char[this->data_size]; for (int i = 0; i < this->data_size; ++i) { this->data[i] = next_hex_byte(iso_tp_frame); } } void Frame::free() { delete[] this->data; } void Frame::copyFrom(const Frame& other) { this->type = other.type; this->index = other.index; this->size = other.size; this->data_size = other.data_size; this->data = new unsigned char[this->data_size]; std::memcpy(this->data, other.data, this->data_size); } /* Public */ Frame::Frame(const char* iso_tp_frame) : index(0) { this->parse_frame_str((const unsigned char*)iso_tp_frame); } Frame::~Frame() { free(); } Frame::Frame(const Frame& other) { copyFrom(other); } Frame& Frame::operator=(const Frame& other) { if (this != &other) { free(); copyFrom(other); } return *this; } FrameType Frame::get_type() const { return this->type; } unsigned char Frame::get_index() const { return this->index; } unsigned int Frame::get_size() const { return this->size; } unsigned int Frame::get_data_size() const { return this->data_size; } const unsigned char* Frame::get_data() const { return this->data; } std::ostream& operator<<(std::ostream& os, const Frame& f) { for (int i = 0; i < f.data_size; ++i) { os << (unsigned)f.data[i]; } return os; }