This commit is contained in:
1 parent
0b05152bcf
commit
d87c100398
9 files changed
+265
-65
No files matched your search
@@ -21,6 +21,15 @@ namespace {
|
||||
return value;
|
||||
}
|
||||
|
||||
std::uint32_t ParseCanId(const std::string &text) {
|
||||
const std::uint32_t rawId = ParseDecimal(
|
||||
text, std::numeric_limits<std::uint32_t>::max(), "CAN ID");
|
||||
// Only bit 31 may accompany the actual 29-bit identifier.
|
||||
if ((rawId & 0x60000000U) != 0U)
|
||||
throw std::runtime_error("CAN ID exceeds the 29-bit identifier range.");
|
||||
return rawId;
|
||||
}
|
||||
|
||||
double ParsePhysicalValue(const std::string &text, const char *field) {
|
||||
static const std::regex number(
|
||||
R"(^[+-]?(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)(?:[eE][+-]?[0-9]+)?$)");
|
||||
@@ -193,11 +202,7 @@ FrameInfo DbcFrameHandler::ParseFrameLine(const std::string &line) {
|
||||
if (!(stream >> keyword >> idText) || keyword != "BO_")
|
||||
throw std::runtime_error("Missing CAN ID in frame definition.");
|
||||
|
||||
const std::uint32_t rawCanId = ParseDecimal(
|
||||
idText, std::numeric_limits<std::uint32_t>::max(), "CAN ID");
|
||||
// Only bit 31 may accompany the actual 29-bit identifier.
|
||||
if ((rawCanId & 0x60000000U) != 0U)
|
||||
throw std::runtime_error("CAN ID exceeds the 29-bit identifier range.");
|
||||
const std::uint32_t rawCanId = ParseCanId(idText);
|
||||
|
||||
std::string nameText;
|
||||
if (!std::getline(stream, nameText, ':') || stream.eof())
|
||||
@@ -273,50 +278,6 @@ SignalInfo DbcSignalHandler::ParseSignalLine(const std::string &line) {
|
||||
return signal;
|
||||
}
|
||||
|
||||
void DbcCommentHandler::ParseCommentLine(const std::string &line, DbcDatabase &database) {
|
||||
/*
|
||||
* Examples:
|
||||
* CM_ BO_ 256 "Frame comment";
|
||||
* CM_ SG_ 256 EngineSpeed "Signal comment";
|
||||
*/
|
||||
|
||||
std::istringstream stream(line);
|
||||
std::string token;
|
||||
stream >> token;
|
||||
|
||||
if (token != "CM_")
|
||||
return;
|
||||
|
||||
stream >> token;
|
||||
if (token != "BO_" && token != "SG_")
|
||||
return;
|
||||
|
||||
std::uint32_t rawCanId = 0U;
|
||||
std::uint32_t canId = 0U;
|
||||
bool isExtended = false;
|
||||
std::string signalName;
|
||||
stream >> rawCanId;
|
||||
if (token == "SG_")
|
||||
stream >> signalName;
|
||||
NormalizeCanId(rawCanId, canId, isExtended);
|
||||
|
||||
const std::string::size_type quoteBegin = line.find('"');
|
||||
const std::string::size_type quoteEnd = line.rfind('"');
|
||||
if (quoteBegin == std::string::npos || quoteEnd == std::string::npos || quoteEnd <= quoteBegin)
|
||||
return;
|
||||
|
||||
FrameInfo *frame = FindFrameById(database, canId, isExtended);
|
||||
if (frame == nullptr)
|
||||
return;
|
||||
const std::string comment = line.substr(quoteBegin + 1U, quoteEnd - quoteBegin - 1U);
|
||||
if (token == "BO_") {
|
||||
frame->comment = comment;
|
||||
return;
|
||||
}
|
||||
SignalInfo *signal = FindSignalByName(*frame, signalName);
|
||||
if (signal != nullptr)
|
||||
signal->comment = comment;
|
||||
}
|
||||
|
||||
namespace {
|
||||
FrameInfo *FindFrameById(DbcDatabase &database,
|
||||
@@ -365,7 +326,67 @@ void DbcSignalHandler::Handle(const std::string &line, DbcParseContext &context)
|
||||
}
|
||||
|
||||
void DbcCommentHandler::Handle(const std::string &line, DbcParseContext &context) const {
|
||||
ParseCommentLine(line, context.database);
|
||||
std::istringstream stream(line);
|
||||
std::string keyword;
|
||||
std::string target;
|
||||
stream >> keyword >> target;
|
||||
if (keyword != "CM_" || (target != "BO_" && target != "SG_"))
|
||||
return;
|
||||
|
||||
PendingComment pending;
|
||||
pending.isSignal = target == "SG_";
|
||||
pending.lineNumber = context.lineNumber;
|
||||
std::string idText;
|
||||
if (!(stream >> idText))
|
||||
throw std::runtime_error("Missing CAN ID in CM_ statement.");
|
||||
NormalizeCanId(ParseCanId(idText), pending.canId, pending.isExtended);
|
||||
if (pending.isSignal && (!(stream >> pending.signalName) ||
|
||||
pending.signalName.find_first_of("\";") != std::string::npos))
|
||||
throw std::runtime_error("Missing or invalid signal name in CM_ statement.");
|
||||
|
||||
stream >> std::ws;
|
||||
if (stream.get() != '"')
|
||||
throw std::runtime_error("Missing opening quote in CM_ statement.");
|
||||
bool closed = false;
|
||||
char character;
|
||||
while (stream.get(character)) {
|
||||
if (character == '"') {
|
||||
closed = true;
|
||||
break;
|
||||
}
|
||||
if (character == '\\') {
|
||||
if (!stream.get(character) || (character != '"' && character != '\\'))
|
||||
throw std::runtime_error("Invalid escape in CM_ statement.");
|
||||
}
|
||||
pending.comment += character;
|
||||
}
|
||||
if (!closed)
|
||||
throw std::runtime_error("Unterminated CM_ comment.");
|
||||
stream >> std::ws;
|
||||
if (stream.get() != ';')
|
||||
throw std::runtime_error("Missing semicolon in CM_ statement.");
|
||||
stream >> std::ws;
|
||||
if (!stream.eof())
|
||||
throw std::runtime_error("Unexpected trailing text in CM_ statement.");
|
||||
context.pendingComments.push_back(std::move(pending));
|
||||
}
|
||||
|
||||
void DbcParseContext::ResolveComments(const std::string &filePath) {
|
||||
for (const PendingComment &pending: pendingComments) {
|
||||
FrameInfo *frame = FindFrameById(database, pending.canId, pending.isExtended);
|
||||
if (!frame)
|
||||
throw DbcDiagnosticError(DbcDiagnosticCode::InvalidStatement, filePath,
|
||||
pending.lineNumber, "Unresolved CM_ frame reference.");
|
||||
if (pending.isSignal) {
|
||||
SignalInfo *signal = FindSignalByName(*frame, pending.signalName);
|
||||
if (!signal)
|
||||
throw DbcDiagnosticError(DbcDiagnosticCode::InvalidStatement, filePath,
|
||||
pending.lineNumber, "Unresolved CM_ signal reference: " + pending.signalName);
|
||||
signal->comment = pending.comment;
|
||||
} else {
|
||||
frame->comment = pending.comment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DbcStatementDispatcher::DbcStatementDispatcher() {
|
||||
|
||||
Reference in new issue
Block a user