This commit is contained in:
deeaitch committed 2026-10-07 18:32:51 -04:00
1 parent a533d9aa00
commit a0938cb29c
14 files changed
+375 -13

No files matched your search

+88 -3
View File
@@ -169,9 +169,24 @@ SignalInfo DbcSignalHandler::ParseSignalLine(const std::string &line) {
throw std::runtime_error("Malformed or unsupported SG_ signal definition.");
SignalInfo signal;
signal.name = TrimText(fields[1].str());
if (signal.name.empty() || signal.name.find_first_of(" \t\r\n") != std::string::npos)
throw std::runtime_error("Invalid signal name or unsupported multiplexing syntax.");
std::istringstream nameFields(fields[1].str());
std::string marker;
std::string extra;
nameFields >> signal.name >> marker;
if (signal.name.empty() || (nameFields >> extra))
throw std::runtime_error("Invalid signal name or multiplexing marker.");
if (marker == "M")
signal.multiplexing.role = MultiplexRole::Selector;
else if (!marker.empty()) {
if (marker[0] != 'm')
throw std::runtime_error("Unsupported multiplexing marker.");
const std::string value = marker.substr(1U);
const std::from_chars_result parsed = std::from_chars(
value.data(), value.data() + value.size(), signal.multiplexing.value);
if (value.empty() || parsed.ec != std::errc() || parsed.ptr != value.data() + value.size())
throw std::runtime_error("Invalid or unsupported multiplexing marker.");
signal.multiplexing.role = MultiplexRole::Branch;
}
signal.startBit = ParseDecimal(fields[2].str(),
std::numeric_limits<std::uint32_t>::max(), "signal start bit");
@@ -281,6 +296,7 @@ namespace {
void DbcFrameHandler::Handle(const std::string &line, DbcParseContext &context) const {
context.database.frames.push_back(ParseFrameLine(line));
context.currentFrame = &context.database.frames.back();
context.signalLines.emplace_back();
}
void DbcSignalHandler::Handle(const std::string &line, DbcParseContext &context) const {
@@ -298,6 +314,7 @@ void DbcSignalHandler::Handle(const std::string &line, DbcParseContext &context)
bit = (bit % 8U == 0U) ? bit + 15U : bit - 1U;
}
context.currentFrame->signals.push_back(std::move(signal));
context.signalLines.back().push_back(context.lineNumber);
}
void DbcCommentHandler::Handle(const std::string &line, DbcParseContext &context) const {
@@ -306,6 +323,7 @@ void DbcCommentHandler::Handle(const std::string &line, DbcParseContext &context
}
DbcStatementDispatcher::DbcStatementDispatcher() {
RegisterType<DbcUnsupportedMultiplexingHandler>("SG_MUL_VAL_");
RegisterType<DbcFrameHandler>("BO_");
RegisterType<DbcSignalHandler>("SG_");
RegisterType<DbcCommentHandler>("CM_");
@@ -408,3 +426,70 @@ void DbcParseContext::ResolveValueDescriptions(const std::string &filePath) {
}
}
}
void DbcUnsupportedMultiplexingHandler::Handle(const std::string &, DbcParseContext &) const {
throw std::runtime_error("Extended and nested multiplexing are unsupported.");
}
namespace {
std::vector<std::uint64_t> SignalBits(const SignalInfo &signal) {
std::vector<std::uint64_t> bits;
std::uint64_t bit = signal.startBit;
for (std::uint32_t index = 0U; index < signal.length; ++index) {
bits.push_back(bit);
if (signal.isLittleEndian)
++bit;
else
bit = bit % 8U == 0U ? bit + 15U : bit - 1U;
}
return bits;
}
bool SignalsOverlap(const SignalInfo &first, const SignalInfo &second) {
const std::vector<std::uint64_t> firstBits = SignalBits(first);
const std::vector<std::uint64_t> secondBits = SignalBits(second);
for (const std::uint64_t firstBit : firstBits) {
for (const std::uint64_t secondBit : secondBits) {
if (firstBit == secondBit)
return true;
}
}
return false;
}
}
void DbcParseContext::ValidateMultiplexing(const std::string &filePath) const {
for (std::size_t frameIndex = 0U; frameIndex < database.frames.size(); ++frameIndex) {
const FrameInfo &frame = database.frames[frameIndex];
const SignalInfo *selector = nullptr;
for (std::size_t index = 0U; index < frame.signals.size(); ++index) {
const SignalInfo &signal = frame.signals[index];
if (signal.multiplexing.role != MultiplexRole::Selector)
continue;
if (selector != nullptr || signal.isSigned)
throw std::runtime_error(filePath + ":" + std::to_string(signalLines[frameIndex][index]) +
": Multiplexing requires one unsigned selector per frame.");
selector = &signal;
}
for (std::size_t index = 0U; index < frame.signals.size(); ++index) {
const SignalInfo &signal = frame.signals[index];
std::string error;
if (signal.multiplexing.role == MultiplexRole::Branch) {
if (selector == nullptr)
error = "Multiplexed branch has no selector.";
else if (selector->length < 64U && signal.multiplexing.value >= (std::uint64_t(1U) << selector->length))
error = "Branch value exceeds selector raw range.";
}
for (std::size_t previous = 0U; previous < index && error.empty(); ++previous) {
const SignalInfo &other = frame.signals[previous];
const bool exclusive = signal.multiplexing.role == MultiplexRole::Branch &&
other.multiplexing.role == MultiplexRole::Branch &&
signal.multiplexing.value != other.multiplexing.value;
if (!exclusive && SignalsOverlap(signal, other))
error = "Signals overlap without mutually exclusive multiplexing conditions.";
}
if (!error.empty())
throw std::runtime_error(filePath + ":" + std::to_string(signalLines[frameIndex][index]) + ": " + error);
}
}
}