blob: fe96308dc966315c2b2170cc88ca2363b48760d4 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
#include <cstring>
#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;
}
|