This commit is contained in:
deeaitch committed 2026-10-23 20:28:55 -04:00
1 parent a702cffd93
commit 8d06165979
18 files changed
+611 -215

No files matched your search

+16 -20
View File
@@ -3,6 +3,7 @@
#include "decode_database.h"
#include "j1939.h"
#include "multiplex_graph.h"
#include "signal_layout.h"
#include <bitset>
#include <cmath>
@@ -21,7 +22,8 @@ namespace {
throw std::invalid_argument("Invalid signal value type: " + signal.name);
if (signal.multiplexing.role != MultiplexRole::Unconditional &&
signal.multiplexing.role != MultiplexRole::Selector &&
signal.multiplexing.role != MultiplexRole::Branch)
signal.multiplexing.role != MultiplexRole::Branch &&
signal.multiplexing.role != MultiplexRole::BranchSelector)
throw std::invalid_argument("Invalid multiplexing role: " + signal.name);
if (!IsValidSignalLayout(signal.startBit, signal.length,
signal.byteOrder == ByteOrder::Intel, dlc))
@@ -45,13 +47,7 @@ namespace {
return bits;
}
bool AreMutuallyExclusive(const DecodeSignal &first, const DecodeSignal &second) {
return first.multiplexing.role == MultiplexRole::Branch &&
second.multiplexing.role == MultiplexRole::Branch &&
first.multiplexing.value != second.multiplexing.value;
}
void ValidateFrame(const DecodeFrame &frame) {
dbc_detail::MultiplexGraph ValidateFrame(const DecodeFrame &frame) {
const std::uint32_t maximumId = frame.isExtended ? 0x1FFFFFFFU : 0x7FFU;
if (frame.canId > maximumId)
throw std::invalid_argument("Invalid normalized CAN ID: " + std::to_string(frame.canId));
@@ -60,33 +56,28 @@ namespace {
throw std::invalid_argument("Invalid J1939 PGN metadata: " + frame.name);
std::unordered_set<std::string> names;
const DecodeSignal *selector = nullptr;
for (const DecodeSignal &signal: frame.signals) {
if (!names.insert(signal.name).second)
throw std::invalid_argument("Duplicate runtime signal key: " + signal.name);
ValidateSignal(signal, frame.dlc);
if (signal.multiplexing.role == MultiplexRole::Selector) {
if (selector != nullptr || signal.valueType != ValueType::Unsigned)
throw std::invalid_argument("Multiplexing requires one unsigned selector per frame");
selector = &signal;
}
if (IsMultiplexSelector(signal.multiplexing.role) && signal.valueType != ValueType::Unsigned)
throw std::invalid_argument("Multiplex selectors must be unsigned.");
}
const dbc_detail::MultiplexGraph graph(frame.signals);
std::vector<SignalBits> layouts;
layouts.reserve(frame.signals.size());
for (std::size_t index = 0U; index < frame.signals.size(); ++index) {
const DecodeSignal &signal = frame.signals[index];
if (signal.multiplexing.role == MultiplexRole::Branch &&
(selector == nullptr ||
(selector->length < 64U && signal.multiplexing.value >= (std::uint64_t(1U) << selector->length))))
throw std::invalid_argument("Missing selector or branch value outside selector range: " + signal.name);
const SignalBits bits = GetSignalBits(signal);
for (std::size_t previous = 0U; previous < index; ++previous) {
if (!AreMutuallyExclusive(signal, frame.signals[previous]) && (bits & layouts[previous]).any())
if (!graph.AreMutuallyExclusive(index, previous) && (bits & layouts[previous]).any())
throw std::invalid_argument("Overlapping signals: " + signal.name);
}
layouts.push_back(bits);
}
return graph;
}
}// namespace
@@ -95,8 +86,9 @@ DecodeDatabase::Storage::Storage(const std::vector<DecodeFrame> &definitions)
// Validate the complete snapshot before creating its lookup index.
std::unordered_set<FrameKey, FrameKeyHasher> keys;
keys.reserve(frames.size());
multiplexGraphs.reserve(frames.size());
for (const DecodeFrame &frame: frames) {
ValidateFrame(frame);
multiplexGraphs.push_back(ValidateFrame(frame));
if (!keys.insert(frame.GetKey()).second)
throw std::invalid_argument("Duplicate runtime frame key");
}
@@ -153,3 +145,7 @@ std::shared_ptr<const DecodeSignal> DecodeDatabase::FindSignal(const SignalKey &
}
return nullptr;
}
const dbc_detail::MultiplexGraph &DecodeDatabase::GetMultiplexGraph(const FrameKey &key) const {
return storage->multiplexGraphs[storage->frameIndexByKey.at(key)];
}