This commit is contained in:
deeaitch committed 2026-10-20 13:38:21 -04:00
1 parent 849ce31e2f
commit a55d1c58ed
272 files changed
+41866 -261

No files matched your search

+20 -29
View File
@@ -104,7 +104,8 @@ namespace {
throw std::runtime_error("Unsupported attribute scope: " + text);
}
std::int64_t Integer(const std::string &text) {
template<class Numeric>
Numeric ParseNumber(const std::string &text) {
const char *begin = text.data();
const char *end = begin + text.size();
if (begin != end && *begin == '+') {
@@ -112,22 +113,7 @@ namespace {
if (begin != end && (*begin == '-' || *begin == '+'))
throw std::runtime_error("Invalid attribute number: " + text);
}
std::int64_t value = 0;
const std::from_chars_result parsed = std::from_chars(begin, end, value);
if (begin == end || parsed.ec != std::errc() || parsed.ptr != end)
throw std::runtime_error("Invalid attribute integer: " + text);
return value;
}
double Number(const std::string &text) {
const char *begin = text.data();
const char *end = begin + text.size();
if (begin != end && *begin == '+') {
++begin;
if (begin != end && (*begin == '-' || *begin == '+'))
throw std::runtime_error("Invalid attribute number: " + text);
}
double value = 0.0;
Numeric value = 0;
const std::from_chars_result parsed = std::from_chars(begin, end, value);
if (begin == end || parsed.ec != std::errc() || parsed.ptr != end || !std::isfinite(value))
throw std::runtime_error("Invalid attribute number: " + text);
@@ -148,12 +134,12 @@ namespace {
}
if (token.quoted) throw std::runtime_error("Numeric attribute requires an unquoted number.");
if (definition.type == AttributeType::Float) {
const double value = Number(token.text);
const double value = ParseNumber<double>(token.text);
if (value < definition.minimum || value > definition.maximum)
throw std::runtime_error("Attribute FLOAT value outside definition range.");
return value;
}
const std::int64_t value = Integer(token.text);
const std::int64_t value = ParseNumber<std::int64_t>(token.text);
if (value < definition.integerMinimum || value > definition.integerMaximum)
throw std::runtime_error("Attribute integer/ENUM value outside definition range.");
return value;
@@ -171,14 +157,14 @@ namespace {
const std::string type = tokens.Word();
if (type == "INT" || type == "HEX") {
definition.type = type == "INT" ? AttributeType::Integer : AttributeType::Hex;
definition.integerMinimum = Integer(tokens.Word());
definition.integerMaximum = Integer(tokens.Word());
definition.integerMinimum = ParseNumber<std::int64_t>(tokens.Word());
definition.integerMaximum = ParseNumber<std::int64_t>(tokens.Word());
if (definition.integerMinimum > definition.integerMaximum)
throw std::runtime_error("Reversed attribute integer range.");
} else if (type == "FLOAT") {
definition.type = AttributeType::Float;
definition.minimum = Number(tokens.Word());
definition.maximum = Number(tokens.Word());
definition.minimum = ParseNumber<double>(tokens.Word());
definition.maximum = ParseNumber<double>(tokens.Word());
if (definition.minimum > definition.maximum)
throw std::runtime_error("Reversed attribute FLOAT range.");
} else if (type == "STRING") {
@@ -217,7 +203,7 @@ namespace {
}
void ParseId(const std::string &text, AttributeAssignment &assignment) {
const std::int64_t raw = Integer(text);
const std::int64_t raw = ParseNumber<std::int64_t>(text);
if (raw < 0 || raw > std::numeric_limits<std::uint32_t>::max() || (raw & 0x60000000U) != 0)
throw std::runtime_error("Invalid attribute CAN ID.");
const std::uint32_t id = static_cast<std::uint32_t>(raw);
@@ -247,7 +233,12 @@ namespace {
void ApplyDefault(DbcDatabase &database, const std::string &name, const AttributeDefinition &definition) {
if (!definition.defaultValue) return;
if (definition.scope == AttributeScope::Database) database.attributes[name] = *definition.defaultValue;
if (definition.scope == AttributeScope::Database) {
database.attributes[name] = *definition.defaultValue;
return;
}
if (definition.scope != AttributeScope::Frame && definition.scope != AttributeScope::Signal)
return;
for (FrameInfo &frame: database.frames) {
if (definition.scope == AttributeScope::Frame) frame.attributes[name] = *definition.defaultValue;
if (definition.scope == AttributeScope::Signal) {
@@ -266,20 +257,20 @@ void DbcParseContext::ResolveAttributes(const std::string &filePath, std::vector
std::vector<std::size_t> assignmentLines;
// Resolve each phase independently of source ordering.
const char *keywords[] = {"BA_DEF_", "BA_DEF_DEF_", "BA_"};
for (int phase = 0; phase < 3; ++phase) {
for (const char *phase: keywords) {
for (const PendingAttribute &pending: pendingAttributes) {
const std::string keyword = pending.statement.substr(0U, pending.statement.find_first_of(" \t"));
if (keyword != keywords[phase]) continue;
if (keyword != phase) continue;
try {
AttributeTokens tokens(pending.statement);
tokens.Word();
if (phase == 0) {
if (keyword == "BA_DEF_") {
Define(tokens, database);
continue;
}
const std::string name = tokens.Quoted();
AttributeDefinition &definition = FindDefinition(database, name);
if (phase == 1) {
if (keyword == "BA_DEF_DEF_") {
if (definition.defaultValue) throw std::runtime_error("Duplicate attribute default: " + name);
definition.defaultValue = Value(tokens.Take(), definition, true);
ValidateCycleTime(name, *definition.defaultValue);