forked from LinuxDevon/dbc_parser_cpp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdbc.cpp
More file actions
165 lines (128 loc) · 5.12 KB
/
Copy pathdbc.cpp
File metadata and controls
165 lines (128 loc) · 5.12 KB
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include <fast_float/fast_float.h>
#include <libdbc/dbc.hpp>
#include <libdbc/exceptions/error.hpp>
#include <libdbc/utils/utils.hpp>
#include <regex>
namespace {
const auto floatPattern = "(-?\\d+\\.?(\\d+)?)"; // Can be negative
const auto signalIdentifierPattern = "(SG_)";
const auto namePattern = "(\\w+)";
const auto bitStartPattern = "(\\d+)"; // Cannot be negative
const auto lengthPattern = "(\\d+)"; // Cannot be negative
const auto byteOrderPattern = "([0-1])";
const auto signPattern = "(\\+|\\-)";
const auto scalePattern = "(\\d+\\.?(\\d+)?)"; // Non negative float
const auto offsetPattern = floatPattern;
const auto offsetScalePattern = std::string("\\(") + scalePattern + "\\," + offsetPattern + "\\)";
const auto minPattern = floatPattern;
const auto maxPattern = floatPattern;
const auto minMaxPattern = std::string("\\[") + minPattern + "\\|" + maxPattern + "\\]";
const auto unitPattern = "\"(.*)\""; // Random string
const auto receiverPattern = "([\\w\\,]+|Vector__XXX)*";
const auto whiteSpace = "\\s";
} // anonymous namespace
namespace libdbc {
DbcParser::DbcParser()
: version("")
, nodes()
, version_re("^(VERSION)\\s\"(.*)\"")
, bit_timing_re("^(BS_:)")
, name_space_re("^(NS_)\\s\\:")
, node_re("^(BU_:)\\s((?:[\\w]+?\\s?)*)")
, message_re("^(BO_)\\s(\\d+)\\s(\\w+)\\:\\s(\\d+)\\s(\\w+|Vector__XXX)")
,
// NOTE: No multiplex support yet
signal_re(std::string("^") + whiteSpace + signalIdentifierPattern + whiteSpace + namePattern + whiteSpace + "\\:" + whiteSpace + bitStartPattern + "\\|"
+ lengthPattern + "\\@" + byteOrderPattern + signPattern + whiteSpace + offsetScalePattern + whiteSpace + minMaxPattern + whiteSpace + unitPattern
+ whiteSpace + receiverPattern) {
}
void DbcParser::parse_file(const std::string& file) {
std::ifstream s(file.c_str());
std::string line;
std::vector<std::string> lines;
messages.clear();
parse_dbc_header(s);
parse_dbc_nodes(s);
while (!s.eof()) {
utils::StreamHandler::get_next_non_blank_line(s, line);
lines.push_back(line);
}
parse_dbc_messages(lines);
}
std::string DbcParser::get_version() const {
return version;
}
std::vector<std::string> DbcParser::get_nodes() const {
return nodes;
}
std::vector<libdbc::Message> DbcParser::get_messages() const {
return messages;
}
Message::ParseSignalsStatus DbcParser::parseMessage(const uint32_t id, const std::vector<uint8_t>& data, std::vector<double>& out_values) {
for (const auto& message : messages) {
if (message.id() == id)
return message.parseSignals(data, out_values);
}
return Message::ParseSignalsStatus::ErrorUnknownID;
}
void DbcParser::parse_dbc_header(std::istream& file_stream) {
std::string line;
std::smatch match;
utils::StreamHandler::get_line(file_stream, line);
if (!std::regex_search(line, match, version_re)) {
throw validity_error();
}
version = match.str(2);
utils::StreamHandler::get_next_non_blank_line(file_stream, line);
utils::StreamHandler::skip_to_next_blank_line(file_stream, line);
utils::StreamHandler::get_next_non_blank_line(file_stream, line);
if (!std::regex_search(line, match, bit_timing_re))
throw validity_error();
}
void DbcParser::parse_dbc_nodes(std::istream& file_stream) {
std::string line;
std::smatch match;
utils::StreamHandler::get_next_non_blank_line(file_stream, line);
if (!std::regex_search(line, match, node_re))
throw validity_error();
if (match.length() > 2) {
std::string n = match.str(2);
utils::String::split(n, nodes);
}
}
void DbcParser::parse_dbc_messages(const std::vector<std::string>& lines) {
std::smatch match;
for (const auto& line : lines) {
if (std::regex_search(line, match, message_re)) {
uint32_t id = std::stoul(match.str(2));
std::string name = match.str(3);
uint8_t size = std::stoul(match.str(4));
std::string node = match.str(5);
Message msg(id, name, size, node);
messages.push_back(msg);
}
if (std::regex_search(line, match, signal_re)) {
std::string name = match.str(2);
bool is_multiplexed = false; // No support yet
uint32_t start_bit = std::stoul(match.str(3));
uint32_t size = std::stoul(match.str(4));
bool is_bigendian = (std::stoul(match.str(5)) == 0);
bool is_signed = (match.str(6) == "-");
// Alternate groups because a group is for the decimal portion
double factor;
fast_float::from_chars(match.str(7).data(), match.str(7).data() + match.str(7).size(), factor);
double offset;
fast_float::from_chars(match.str(9).data(), match.str(9).data() + match.str(9).size(), offset);
double min;
fast_float::from_chars(match.str(11).data(), match.str(11).data() + match.str(11).size(), min);
double max;
fast_float::from_chars(match.str(13).data(), match.str(13).data() + match.str(13).size(), max);
std::string unit = match.str(15);
std::vector<std::string> receivers;
utils::String::split(match.str(16), receivers, ',');
Signal sig(name, is_multiplexed, start_bit, size, is_bigendian, is_signed, factor, offset, min, max, unit, receivers);
messages.back().appendSignal(sig);
}
}
}
}