From 0708316a3772411fc54d58bb38d3fe7a036ce0c1 Mon Sep 17 00:00:00 2001 From: deeaitch Date: Sun, 11 Oct 2026 06:30:18 -0400 Subject: [PATCH] Closes #14 --- README.md | 107 +- changelog.md | 17 + core/core_files.pri | 2 + core/dbc_decode_builder.cpp | 17 +- core/dbc_decode_builder.h | 3 +- core/dbc_decoder.cpp | 42 +- core/dbc_decoder.h | 30 +- core/decode_database.cpp | 52 + core/decode_database.h | 106 +- core/definition_key.h | 62 + docs/dbcframework.tag | 63 +- docs/doxygen_warnings.log | 26 +- docs/html/annotated.html | 10 +- docs/html/annotated_dup.js | 4 +- docs/html/classDbcDecodeBuilder.html | 16 +- docs/html/classDbcDecoder-members.html | 2 +- docs/html/classDbcDecoder.html | 32 +- docs/html/classDbcDecoder.js | 2 +- docs/html/classDecodeDatabase-members.html | 113 ++ docs/html/classDecodeDatabase.html | 234 +++ docs/html/classDecodeDatabase.js | 6 + docs/html/classes.html | 4 +- .../html/dbc__coverage__test_8cpp_source.html | 1513 +++++++++-------- docs/html/dbc__decode__builder_8cpp.html | 1 + .../dbc__decode__builder_8cpp_source.html | 140 +- docs/html/dbc__decode__builder_8h_source.html | 12 +- docs/html/dbc__decoder_8cpp.html | 1 + docs/html/dbc__decoder_8cpp_source.html | 398 +++-- docs/html/dbc__decoder_8h_source.html | 167 +- docs/html/dbc__decoder__test_8cpp_source.html | 225 ++- .../html/dbc__lifetime__test_8cpp_source.html | 387 +++++ docs/html/dbc__parser__test_8cpp_source.html | 625 +++---- .../dbc__statement__handler_8cpp_source.html | 2 +- docs/html/dbc__tree__model_8cpp_source.html | 2 +- docs/html/dbc__tree__model_8h_source.html | 2 +- docs/html/decode__database_8cpp_source.html | 176 ++ docs/html/decode__database_8h.html | 18 +- docs/html/decode__database_8h.js | 4 +- docs/html/decode__database_8h_source.html | 216 ++- docs/html/definition__key_8h_source.html | 178 ++ .../dir_4270bfced15e0e73154b13468c7c9ad9.html | 4 + .../dir_4270bfced15e0e73154b13468c7c9ad9.js | 2 + .../dir_59425e443f801f1f2fd8bbe4959a3ccf.html | 2 + .../dir_59425e443f801f1f2fd8bbe4959a3ccf.js | 1 + docs/html/examples_2main_8cpp_source.html | 26 +- docs/html/files.html | 29 +- docs/html/functions.html | 11 +- docs/html/functions_func.html | 4 +- docs/html/functions_vars.html | 7 +- docs/html/hierarchy.html | 12 +- docs/html/hierarchy.js | 4 +- docs/html/index.qhp | 171 +- docs/html/inherit_graph_10.map | 2 +- docs/html/inherit_graph_10.md5 | 2 +- docs/html/inherit_graph_10.svg | 2 +- docs/html/inherit_graph_16.map | 2 +- docs/html/inherit_graph_16.md5 | 2 +- docs/html/inherit_graph_16.svg | 2 +- docs/html/inherit_graph_23.map | 6 +- docs/html/inherit_graph_23.md5 | 2 +- docs/html/inherit_graph_23.svg | 46 +- docs/html/inherit_graph_24.map | 2 +- docs/html/inherit_graph_24.md5 | 2 +- docs/html/inherit_graph_24.svg | 10 +- docs/html/inherit_graph_25.map | 6 +- docs/html/inherit_graph_25.md5 | 2 +- docs/html/inherit_graph_25.svg | 49 +- docs/html/inherit_graph_26.map | 2 +- docs/html/inherit_graph_26.md5 | 2 +- docs/html/inherit_graph_26.svg | 13 +- docs/html/inherit_graph_27.map | 3 + docs/html/inherit_graph_27.md5 | 1 + docs/html/inherit_graph_27.svg | 22 + docs/html/inherit_graph_28.map | 3 + docs/html/inherit_graph_28.md5 | 1 + docs/html/inherit_graph_28.svg | 22 + docs/html/inherits.html | 10 +- docs/html/md_README.html | 154 +- docs/html/md_changelog.html | 8 +- docs/html/md_tests_2README.html | 20 +- docs/html/menudata.js | 2 + docs/html/navtreedata.js | 102 +- docs/html/navtreeindex0.js | 204 +-- docs/html/navtreeindex1.js | 39 +- docs/html/search/all_1.js | 2 +- docs/html/search/all_10.js | 15 +- docs/html/search/all_11.js | 10 +- docs/html/search/all_12.js | 23 +- docs/html/search/all_13.js | 22 +- docs/html/search/all_14.js | 22 +- docs/html/search/all_15.js | 39 +- docs/html/search/all_16.js | 58 +- docs/html/search/all_17.js | 43 +- docs/html/search/all_18.js | 19 +- docs/html/search/all_19.js | 14 +- docs/html/search/all_1a.js | 6 +- docs/html/search/all_1b.js | 5 + docs/html/search/all_2.js | 2 +- docs/html/search/all_3.js | 2 +- docs/html/search/all_4.js | 2 +- docs/html/search/all_5.js | 33 +- docs/html/search/all_6.js | 16 +- docs/html/search/all_7.js | 24 +- docs/html/search/all_8.js | 40 +- docs/html/search/all_9.js | 8 +- docs/html/search/all_a.js | 29 +- docs/html/search/all_b.js | 21 +- docs/html/search/all_c.js | 2 +- docs/html/search/all_d.js | 27 +- docs/html/search/all_e.js | 10 +- docs/html/search/all_f.js | 20 +- docs/html/search/classes_0.js | 2 +- docs/html/search/classes_5.js | 4 +- docs/html/search/functions_3.js | 3 +- docs/html/search/functions_4.js | 2 +- docs/html/search/functions_5.js | 13 +- docs/html/search/searchdata.js | 4 +- docs/html/search/variables_10.js | 6 + docs/html/search/variables_2.js | 2 +- docs/html/search/variables_6.js | 2 +- docs/html/search/variables_7.js | 3 +- docs/html/search/variables_8.js | 3 +- docs/html/search/variables_9.js | 2 +- docs/html/search/variables_a.js | 4 +- docs/html/search/variables_b.js | 5 +- docs/html/search/variables_c.js | 3 +- docs/html/search/variables_d.js | 2 +- docs/html/search/variables_e.js | 2 +- docs/html/search/variables_f.js | 4 +- docs/html/structDbcDatabase.html | 2 +- docs/html/structDecodeFrame-members.html | 13 +- docs/html/structDecodeFrame.html | 72 +- docs/html/structDecodeSignal.html | 56 +- .../html/structDecodedFrameValue-members.html | 7 +- docs/html/structDecodedFrameValue.html | 45 +- docs/html/structDecodedFrameValue.js | 3 +- .../structDecodedSignalValue-members.html | 11 +- docs/html/structDecodedSignalValue.html | 51 +- docs/html/structDecodedSignalValue.js | 3 +- docs/html/structFrameKey.html | 18 +- docs/html/structFrameKeyHasher.html | 8 +- docs/html/structRawCanFrame.html | 4 +- docs/html/structSignalKey-members.html | 113 ++ docs/html/structSignalKey.html | 235 +++ docs/html/structSignalKeyHasher-members.html | 109 ++ docs/html/structSignalKeyHasher.html | 150 ++ docs/html/tests_2main_8cpp_source.html | 17 +- examples/main.cpp | 4 +- tests/README.md | 20 +- tests/dbc_coverage_test.cpp | 47 +- tests/dbc_decoder_test.cpp | 12 +- tests/dbc_lifetime_test.cpp | 242 +++ tests/dbc_parser_test.cpp | 17 +- tests/main.cpp | 5 +- tests/tests.pro | 2 +- 155 files changed, 5190 insertions(+), 2691 deletions(-) create mode 100644 core/decode_database.cpp create mode 100644 core/definition_key.h create mode 100644 docs/html/classDecodeDatabase-members.html create mode 100644 docs/html/classDecodeDatabase.html create mode 100644 docs/html/classDecodeDatabase.js create mode 100644 docs/html/dbc__lifetime__test_8cpp_source.html create mode 100644 docs/html/decode__database_8cpp_source.html create mode 100644 docs/html/definition__key_8h_source.html create mode 100644 docs/html/inherit_graph_27.map create mode 100644 docs/html/inherit_graph_27.md5 create mode 100644 docs/html/inherit_graph_27.svg create mode 100644 docs/html/inherit_graph_28.map create mode 100644 docs/html/inherit_graph_28.md5 create mode 100644 docs/html/inherit_graph_28.svg create mode 100644 docs/html/search/all_1b.js create mode 100644 docs/html/search/variables_10.js create mode 100644 docs/html/structSignalKey-members.html create mode 100644 docs/html/structSignalKey.html create mode 100644 docs/html/structSignalKeyHasher-members.html create mode 100644 docs/html/structSignalKeyHasher.html create mode 100644 tests/dbc_lifetime_test.cpp diff --git a/README.md b/README.md index 99aef63..dfb1868 100644 --- a/README.md +++ b/README.md @@ -321,7 +321,7 @@ This structure is used directly by the decoder. ## `FrameKey` -Fast lookup key for runtime frame matching. +Stable identifier for runtime frame matching and application state. Fields: @@ -334,22 +334,20 @@ This matters because the same numeric identifier must not be confused between st ## `DecodeDatabase` -Top-level runtime decode container. +Immutable runtime snapshot with a private frame index. Build it with +`DbcDecodeBuilder::Build(parsed)` or construct it from `std::vector`. +Construction rejects duplicate frame keys and duplicate signal names within a +frame with `std::invalid_argument`, including manually supplied metadata. -Fields: +- `GetFrames()` returns a borrowed `const std::vector&`. +- `FindFrame(FrameKey)` returns `std::shared_ptr`. +- `FindSignal(SignalKey)` returns `std::shared_ptr`. +- Missing definitions return an empty handle. +- Copying a database shares its snapshot; replacing it installs another snapshot. -- `frames` -- `frameIndexByKey` - -Conceptually: - -```text -DecodeDatabase - ├── vector - └── unordered_map -``` - -This gives the decoder fast access to a frame definition using CAN ID and frame type. +Frame lookup uses a hash index; signal lookup scans the matched frame's signals. +Decoding shares the snapshot without copying definitions or allocating ownership +objects per signal. --- @@ -380,6 +378,7 @@ Represents one decoded signal result. Fields: - `definition` +- `key` - `rawValue` - `physicalValue` - `valid` @@ -426,6 +425,7 @@ Represents one decoded frame result. Fields: - `definition` +- `key` - `signals` - `valid` @@ -433,10 +433,77 @@ Fields: `valid` separately: insufficient payload data can leave individual signals invalid even when the frame is valid. An unknown frame returns `valid == false`. -The frame and signal `definition` pointers refer into `DecodeDatabase`. Keep -that database alive and avoid changes that invalidate its frame or signal -storage while using decoded results. The decoder applies factor and offset; -it does not clamp physical values to the declared minimum and maximum. +The decoder applies factor and offset; it does not clamp physical values to the +declared minimum and maximum. + +### Definition ownership and reload + +`DecodedFrameValue::definition` and `DecodedSignalValue::definition` are owning +`std::shared_ptr` handles. Each handle retains the immutable runtime +snapshot. Definitions remain valid until the last database copy, lookup handle, +or decoded result owning that snapshot is released. An independently copied +signal result retains its definition even after the parent frame result is +removed. Copying or moving results preserves ownership. + +Reload by assigning a newly built database. Stored results continue to describe +the old DBC, including its units, scaling, comments, and `VAL_` descriptions; +subsequent decoding uses the new DBC. Removed definitions cannot be found in the +new database, but old results safely retain their old definitions. Keeping even +one signal handle retains the whole old snapshot; release stored results when +that metadata is no longer needed. + +`GetFrames()` is a borrowed view. References, iterators, and raw pointers obtained +from it or from a handle's `.get()` do not retain ownership. Keep an owning handle +or an unchanged database copy while using them. Do not retain mutable aliases +into a vector moved into the database constructor. The raw string pointer from +`GetValueDescription()` follows the same rule: keep the signal definition handle +alive while using the string. + +Parsed `DbcDatabase`/`FrameInfo`/`SignalInfo` remain ordinary mutable value +containers: borrowed pointers follow standard vector invalidation rules. Builders +copy their metadata, so parsed input may be changed or destroyed after building. +Tree nodes own metadata copies; the Qt model owns its tree and invalidates model +indexes on reset. Runtime handles do not depend on the parsed database or tree. +Synchronize replacement of a shared database variable with decoding; immutable +snapshots do not make concurrent assignment to the same object safe. + +### Stable frame and signal identifiers + +`DecodedFrameValue::key` is a `FrameKey` (normalized `canId`, `isExtended`), also +available through `DecodeFrame::GetKey()`. `DecodedSignalValue::key` is a +`SignalKey` (frame key, exact case-sensitive signal name). Both are value types +with equality and hashers (`FrameKeyHasher`, `SignalKeyHasher`) for application +maps and saved selections. Construct the same keys from parsed metadata when +needed; do not use addresses or vector positions as identifiers. + +Keys stay equal across reloads and reordering when their components stay equal. +Frame renaming and changes to units, bit layout, scaling, or descriptions do not +change a key. Changing a CAN ID/frame type or renaming a signal produces a new +key. The same name in different frames and standard/extended frames with the +same numeric CAN ID remain distinct. Keys identify definitions within one logical +DBC database; applications combining databases must add their own database ID. +A key is not a version identifier: matching keys in different snapshots may have +different metadata. Use `valid`/the definition handle to distinguish a matched +result; default keys alone do not indicate successful decoding. + +```cpp +DecodeDatabase runtime = DbcDecodeBuilder().Build(parsed); +DecodedFrameValue stored = DbcDecoder().Decode(runtime, rawFrame); +if (stored.valid && !stored.signals.empty()) { + DecodedSignalValue saved = stored.signals.front(); + SignalKey selection = saved.key; + runtime = DbcDecodeBuilder().Build(parser.ParseFile("updated.dbc")); + std::shared_ptr current = runtime.FindSignal(selection); + // saved.definition retains old metadata; current holds new metadata or is empty. +} +``` + +**API migration:** replace reads of `runtime.frames` with `runtime.GetFrames()`. +To edit runtime definitions, prepare a vector and construct a new database; +`frameIndexByKey` is now private and built automatically. `DbcDecoder::FindFrame` +and result `definition` fields now use owning handles instead of raw pointers; +`definition->name`, boolean/null checks, and existing decode calls remain usable. +Use `.get()` only for temporary raw-pointer interoperation with an owner alive. --- @@ -986,7 +1053,7 @@ if (const std::string *description = value.GetValueDescription()) { It returns `nullptr` for an invalid decode or an unknown value; numeric decoding and `physicalValue` are unchanged. A mapped empty string returns a non-null pointer. The pointer belongs to the signal definition and stays valid while that -definition and mapping remain alive and unchanged. +definition remains alive. A decoded signal owns its immutable definition across reload. For metadata or standalone raw values, use `FindValueDescription(signal.valueDescriptions, rawValue)`, where `rawValue` is diff --git a/changelog.md b/changelog.md index 309c2d3..8ae623b 100644 --- a/changelog.md +++ b/changelog.md @@ -10,6 +10,13 @@ existing Git tag; subsequent changes are listed as unreleased. #### Added +- Stable application identifiers: `FrameKey` (normalized CAN ID and frame type) + and `SignalKey` (frame key and signal name), with equality and hashers. +- Runtime `FindSignal`, frame `GetKey`, and keys on decoded frame/signal results. +- Reload/lifetime tests for retained frames and independent signals, lookup + handles, copies/moves, snapshot release, stable keys, removed/renamed definitions, + failed/empty reloads, duplicate keys, and insufficient payloads. + - `ParseFileWithDiagnostics` and `DbcParseResult` with severity, stable error code, supplied file path, physical line number, and message for each diagnostic. - Warnings for unregistered statements, including floating-point signal types, @@ -21,6 +28,16 @@ existing Git tag; subsequent changes are listed as unreleased. #### Changed +- **API change:** `DecodeDatabase` is an immutable shared snapshot. Use + `GetFrames()` for reads or construct a new snapshot from a vector; its frame + index is private and built automatically, with duplicate-key validation. +- **API change:** decoded `definition` fields and `DbcDecoder::FindFrame` return + `shared_ptr` ownership. Stored results retain old definitions across + reload/clear/destruction, including separately copied signals and `VAL_` strings. + Decoding shares metadata without per-result definition copies. +- Documented borrowed views, owning handles, snapshot retention, identifier scope, + reload behavior, application migration, and synchronization requirements. + - Kept `ParseFile` compatible while sharing parsing with the diagnostic API. Parsing stops at the first error and never returns a partial database. - Deferred value-description and multiplexing errors carry structured source diff --git a/core/core_files.pri b/core/core_files.pri index da5a3df..7a41c26 100644 --- a/core/core_files.pri +++ b/core/core_files.pri @@ -1,4 +1,5 @@ SOURCES += \ + $$PWD/decode_database.cpp \ $$PWD/dbc_decode_builder.cpp \ $$PWD/dbc_decoder.cpp \ $$PWD/dbc_parser.cpp \ @@ -7,6 +8,7 @@ SOURCES += \ $$PWD/tree_node.cpp HEADERS += \ + $$PWD/definition_key.h \ $$PWD/dbc_diagnostic.h \ $$PWD/multiplexing.h \ $$PWD/dbc_database.h \ diff --git a/core/dbc_decode_builder.cpp b/core/dbc_decode_builder.cpp index 7504af5..b1c0171 100644 --- a/core/dbc_decode_builder.cpp +++ b/core/dbc_decode_builder.cpp @@ -10,11 +10,13 @@ */ #include "dbc_decode_builder.h" +#include DecodeDatabase DbcDecodeBuilder::Build(const DbcDatabase &source) const { - DecodeDatabase result; + std::vector frames; + frames.reserve(source.frames.size()); - for (const FrameInfo &sourceFrame : source.frames) { + for (const FrameInfo &sourceFrame: source.frames) { DecodeFrame targetFrame; targetFrame.name = sourceFrame.name; @@ -26,7 +28,8 @@ DecodeDatabase DbcDecodeBuilder::Build(const DbcDatabase &source) const { targetFrame.transmitter = sourceFrame.transmitter; targetFrame.comment = sourceFrame.comment; - for (const SignalInfo &sourceSignal : sourceFrame.signals) { + targetFrame.signals.reserve(sourceFrame.signals.size()); + for (const SignalInfo &sourceSignal: sourceFrame.signals) { DecodeSignal targetSignal; targetSignal.multiplexing = sourceSignal.multiplexing; @@ -44,13 +47,11 @@ DecodeDatabase DbcDecodeBuilder::Build(const DbcDatabase &source) const { targetSignal.comment = sourceSignal.comment; targetSignal.valueDescriptions = sourceSignal.valueDescriptions; - targetFrame.signals.push_back(targetSignal); + targetFrame.signals.push_back(std::move(targetSignal)); } - result.frames.push_back(targetFrame); - result.frameIndexByKey[FrameKey(targetFrame.canId, targetFrame.isExtended)] = - result.frames.size() - 1U; + frames.push_back(std::move(targetFrame)); } - return result; + return DecodeDatabase(std::move(frames)); } diff --git a/core/dbc_decode_builder.h b/core/dbc_decode_builder.h index 737b192..530cb94 100644 --- a/core/dbc_decode_builder.h +++ b/core/dbc_decode_builder.h @@ -23,7 +23,8 @@ public: /** * @brief Build runtime decode database. * @param source Parsed DBC database. - * @return Runtime-ready decode database. + * @return Immutable runtime snapshot independent of source lifetime. + * @throws std::invalid_argument for duplicate frame keys or signal names. */ DecodeDatabase Build(const DbcDatabase &source) const; }; diff --git a/core/dbc_decoder.cpp b/core/dbc_decoder.cpp index 4301764..ef8da84 100644 --- a/core/dbc_decoder.cpp +++ b/core/dbc_decoder.cpp @@ -10,28 +10,19 @@ */ #include "dbc_decoder.h" +#include -const DecodeFrame *DbcDecoder::FindFrame(const DecodeDatabase &database, - std::uint32_t canId, - bool isExtended) const { - const FrameKey key(canId, isExtended); - const std::unordered_map::const_iterator it = - database.frameIndexByKey.find(key); - - if (it == database.frameIndexByKey.end()) - return nullptr; - - const std::size_t index = it->second; - if (index >= database.frames.size()) - return nullptr; - - return &database.frames[index]; +std::shared_ptr DbcDecoder::FindFrame(const DecodeDatabase &database, + std::uint32_t canId, + bool isExtended) const { + return database.FindFrame(FrameKey(canId, isExtended)); } DecodedFrameValue DbcDecoder::Decode(const DecodeDatabase &database, const RawCanFrame &frame) const { DecodedFrameValue result; - const DecodeFrame *definition = FindFrame(database, frame.canId, frame.isExtended); + result.key = FrameKey(frame.canId, frame.isExtended); + const std::shared_ptr definition = FindFrame(database, frame.canId, frame.isExtended); if (definition == nullptr) return result; @@ -40,17 +31,22 @@ DecodedFrameValue DbcDecoder::Decode(const DecodeDatabase &database, result.valid = true; const SelectorState selector = ReadSelector(*definition, frame); - for (const DecodeSignal &signal : definition->signals) - result.signals.push_back(DecodeOneSignal(signal, frame, selector)); + result.signals.reserve(definition->signals.size()); + for (const DecodeSignal &signal: definition->signals) { + DecodedSignalValue decoded = DecodeOneSignal(signal, frame, selector); + decoded.definition = std::shared_ptr(definition, &signal); + decoded.key = SignalKey(result.key, signal.name); + result.signals.push_back(std::move(decoded)); + } return result; } DbcDecoder::SelectorState DbcDecoder::ReadSelector(const DecodeFrame &definition, - const RawCanFrame &frame) { + const RawCanFrame &frame) { SelectorState selector; std::size_t count = 0U; - for (const DecodeSignal &signal : definition.signals) { + for (const DecodeSignal &signal: definition.signals) { if (signal.multiplexing.role == MultiplexRole::Selector) { selector.definition = &signal; ++count; @@ -67,13 +63,11 @@ DbcDecoder::SelectorState DbcDecoder::ReadSelector(const DecodeFrame &definition } DecodedSignalValue DbcDecoder::DecodeOneSignal(const DecodeSignal &signal, - const RawCanFrame &frame, - const SelectorState &selector) { + const RawCanFrame &frame, + const SelectorState &selector) { DecodedSignalValue decoded; std::uint64_t unsignedValue = 0U; - decoded.definition = &signal; - if (signal.length == 0U || signal.length > 64U || (signal.multiplexing.role != MultiplexRole::Unconditional && !selector.valid)) { return decoded; diff --git a/core/dbc_decoder.h b/core/dbc_decoder.h index 4ab5f56..3908871 100644 --- a/core/dbc_decoder.h +++ b/core/dbc_decoder.h @@ -22,9 +22,9 @@ * @brief Raw CAN frame used for runtime or trace decoding. */ struct RawCanFrame { - std::uint32_t canId = 0U; /**< Normalized CAN ID. */ - bool isExtended = false; /**< true for extended frame. */ - std::vector data; /**< Payload bytes. */ + std::uint32_t canId = 0U; /**< Normalized CAN ID. */ + bool isExtended = false; /**< true for extended frame. */ + std::vector data; /**< Payload bytes. */ RawCanFrame() = default; }; @@ -41,10 +41,11 @@ enum class SignalDecodeStatus { * @brief One decoded signal value. */ struct DecodedSignalValue { - const DecodeSignal *definition = nullptr; /**< Signal definition. */ - RawSignalValue rawValue = std::uint64_t(0U); /**< Exact signed or unsigned raw value. */ - double physicalValue = 0.0; /**< Converted physical value. */ - bool valid = false; /**< true if decoding succeeded. */ + std::shared_ptr definition; /**< Owning immutable definition. */ + SignalKey key; /**< Stable application identifier. */ + RawSignalValue rawValue = std::uint64_t(0U); /**< Exact signed or unsigned raw value. */ + double physicalValue = 0.0; /**< Converted physical value. */ + bool valid = false; /**< true if decoding succeeded. */ SignalDecodeStatus status = SignalDecodeStatus::InvalidDefinition; /** Lookup using the raw integer; nullptr for invalid or unmapped values. */ @@ -59,9 +60,10 @@ struct DecodedSignalValue { * @brief Fully decoded frame. */ struct DecodedFrameValue { - const DecodeFrame *definition = nullptr; /**< Frame definition. */ - std::vector signals; /**< Decoded signal values. */ - bool valid = false; /**< true if frame was matched. */ + std::shared_ptr definition; /**< Owning immutable definition. */ + FrameKey key; /**< Stable application identifier. */ + std::vector signals; /**< Decoded signal values. */ + bool valid = false; /**< true if frame was matched. */ DecodedFrameValue() = default; }; @@ -76,11 +78,11 @@ public: * @param database Runtime decode database. * @param canId Normalized CAN ID. * @param isExtended true for extended frame. - * @return Pointer to frame definition or nullptr. + * @return Owning immutable frame handle or nullptr. Safe across reload. */ - const DecodeFrame *FindFrame(const DecodeDatabase &database, - std::uint32_t canId, - bool isExtended) const; + std::shared_ptr FindFrame(const DecodeDatabase &database, + std::uint32_t canId, + bool isExtended) const; /** * @brief Decode one raw CAN frame. diff --git a/core/decode_database.cpp b/core/decode_database.cpp new file mode 100644 index 0000000..693d229 --- /dev/null +++ b/core/decode_database.cpp @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: MIT +// Copyright (c) 2026 Dim Himro + +#include "decode_database.h" +#include +#include +#include + +DecodeDatabase::Storage::Storage(std::vector definitions) + : frames(std::move(definitions)) { + frameIndexByKey.reserve(frames.size()); + for (std::size_t index = 0U; index < frames.size(); ++index) { + const DecodeFrame &frame = frames[index]; + if (!frameIndexByKey.emplace(frame.GetKey(), index).second) + throw std::invalid_argument("Duplicate runtime frame key"); + std::unordered_set names; + for (const DecodeSignal &signal: frame.signals) { + if (!names.insert(signal.name).second) + throw std::invalid_argument("Duplicate runtime signal key"); + } + } +} + +DecodeDatabase::DecodeDatabase(std::vector frames) + : storage(std::make_shared(std::move(frames))) { +} + +const std::vector &DecodeDatabase::GetFrames() const { + static const std::vector empty; + return storage ? storage->frames : empty; +} + +std::shared_ptr DecodeDatabase::FindFrame(const FrameKey &key) const { + if (!storage) + return nullptr; + const std::unordered_map::const_iterator it = + storage->frameIndexByKey.find(key); + if (it == storage->frameIndexByKey.end()) + return nullptr; + return std::shared_ptr(storage, &storage->frames[it->second]); +} + +std::shared_ptr DecodeDatabase::FindSignal(const SignalKey &key) const { + const std::shared_ptr frame = FindFrame(key.frame); + if (!frame) + return nullptr; + for (const DecodeSignal &signal: frame->signals) { + if (signal.name == key.name) + return std::shared_ptr(frame, &signal); + } + return nullptr; +} diff --git a/core/decode_database.h b/core/decode_database.h index 671947f..4461829 100644 --- a/core/decode_database.h +++ b/core/decode_database.h @@ -12,9 +12,11 @@ #ifndef DECODE_DATABASE_H #define DECODE_DATABASE_H -#include "value_descriptions.h" +#include "definition_key.h" #include "multiplexing.h" +#include "value_descriptions.h" #include +#include #include #include #include @@ -40,19 +42,19 @@ enum class ValueType { */ struct DecodeSignal { Multiplexing multiplexing; - std::string name; /**< Signal name. */ - std::uint32_t startBit = 0U; /**< DBC start bit. */ - std::uint32_t length = 0U; /**< Signal length in bits. */ - ByteOrder byteOrder = ByteOrder::Intel; /**< Intel or Motorola. */ - ValueType valueType = ValueType::Unsigned; /**< Signed or unsigned. */ - double factor = 1.0; /**< Scaling factor. */ - double offset = 0.0; /**< Physical offset. */ - double minimum = 0.0; /**< Minimum physical value. */ - double maximum = 0.0; /**< Maximum physical value. */ - std::string unit; /**< Physical unit. */ - std::vector receivers; /**< Receivers. */ - ValueDescriptions valueDescriptions; /**< Raw integer state descriptions. */ - std::string comment; /**< Comment. */ + std::string name; /**< Signal name. */ + std::uint32_t startBit = 0U; /**< DBC start bit. */ + std::uint32_t length = 0U; /**< Signal length in bits. */ + ByteOrder byteOrder = ByteOrder::Intel; /**< Intel or Motorola. */ + ValueType valueType = ValueType::Unsigned; /**< Signed or unsigned. */ + double factor = 1.0; /**< Scaling factor. */ + double offset = 0.0; /**< Physical offset. */ + double minimum = 0.0; /**< Minimum physical value. */ + double maximum = 0.0; /**< Maximum physical value. */ + std::string unit; /**< Physical unit. */ + std::vector receivers; /**< Receivers. */ + ValueDescriptions valueDescriptions; /**< Raw integer state descriptions. */ + std::string comment; /**< Comment. */ DecodeSignal() = default; }; @@ -61,54 +63,52 @@ struct DecodeSignal { * @brief Runtime-ready frame definition. */ struct DecodeFrame { - std::string name; /**< Frame name. */ - std::uint32_t canId = 0U; /**< Normalized CAN ID. */ - bool isExtended = false; /**< true for extended frame. */ - std::uint8_t dlc = 0U; /**< Payload length. */ - std::uint32_t pgn = 0U; /**< PGN if available. */ - bool hasPgn = false; /**< true if PGN is valid. */ - std::string transmitter; /**< Transmitter ECU. */ - std::string comment; /**< Frame comment. */ - std::vector signals; /**< Signal definitions. */ + std::string name; /**< Frame name. */ + std::uint32_t canId = 0U; /**< Normalized CAN ID. */ + bool isExtended = false; /**< true for extended frame. */ + std::uint8_t dlc = 0U; /**< Payload length. */ + std::uint32_t pgn = 0U; /**< PGN if available. */ + bool hasPgn = false; /**< true if PGN is valid. */ + std::string transmitter; /**< Transmitter ECU. */ + std::string comment; /**< Frame comment. */ + std::vector signals; /**< Signal definitions. */ DecodeFrame() = default; -}; -/** - * @brief Key for fast frame lookup. - */ -struct FrameKey { - std::uint32_t canId = 0U; - bool isExtended = false; - - FrameKey() = default; - - FrameKey(std::uint32_t id, bool extended) - : canId(id), isExtended(extended) { - } - - bool operator==(const FrameKey &other) const { - return (canId == other.canId) && (isExtended == other.isExtended); + FrameKey GetKey() const { + return FrameKey(canId, isExtended); } }; /** - * @brief Hasher for frame key. + * @brief Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. + * Owning lookup handles and decoded results keep old definitions alive. */ -struct FrameKeyHasher { - std::size_t operator()(const FrameKey &key) const { - const std::size_t a = static_cast(key.canId); - const std::size_t b = key.isExtended ? 1U : 0U; - return (a * 1315423911U) ^ b; - } -}; +class DecodeDatabase { +public: + DecodeDatabase() = default; + /** + * Freeze definitions and build the frame index. + * Do not retain mutable aliases into moved input vectors. + * @throws std::invalid_argument for duplicate frame keys or signal names. + */ + explicit DecodeDatabase(std::vector frames); -/** - * @brief Runtime decode database with fast lookup by CAN ID. - */ -struct DecodeDatabase { - std::vector frames; - std::unordered_map frameIndexByKey; + /** Borrowed view, valid while this snapshot remains alive and unchanged. */ + const std::vector &GetFrames() const; + /** Owning handles retain the entire snapshot across reload or destruction. */ + std::shared_ptr FindFrame(const FrameKey &key) const; + std::shared_ptr FindSignal(const SignalKey &key) const; + +private: + struct Storage { + std::vector frames; + std::unordered_map frameIndexByKey; + + explicit Storage(std::vector definitions); + }; + + std::shared_ptr storage; }; #endif /* DECODE_DATABASE_H */ diff --git a/core/definition_key.h b/core/definition_key.h new file mode 100644 index 0000000..44d2efc --- /dev/null +++ b/core/definition_key.h @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT +// Copyright (c) 2026 Dim Himro + +#ifndef DEFINITION_KEY_H +#define DEFINITION_KEY_H + +#include +#include +#include +#include + +/** + * @brief Stable frame identifier: normalized CAN ID and frame type. + */ +struct FrameKey { + std::uint32_t canId = 0U; + bool isExtended = false; + + FrameKey() = default; + + FrameKey(std::uint32_t id, bool extended) + : canId(id), isExtended(extended) { + } + + bool operator==(const FrameKey &other) const { + return (canId == other.canId) && (isExtended == other.isExtended); + } +}; + +/** + * @brief Hasher for frame key. + */ +struct FrameKeyHasher { + std::size_t operator()(const FrameKey &key) const { + const std::size_t a = static_cast(key.canId); + const std::size_t b = key.isExtended ? 1U : 0U; + return (a * 1315423911U) ^ b; + } +}; + +/** Stable signal identifier within one logical DBC database. */ +struct SignalKey { + FrameKey frame; + std::string name; + + SignalKey() = default; + SignalKey(FrameKey frameKey, std::string signalName) + : frame(frameKey), name(std::move(signalName)) { + } + + bool operator==(const SignalKey &other) const { + return frame == other.frame && name == other.name; + } +}; + +struct SignalKeyHasher { + std::size_t operator()(const SignalKey &key) const { + return FrameKeyHasher()(key.frame) ^ (std::hash()(key.name) << 1U); + } +}; + +#endif /* DEFINITION_KEY_H */ diff --git a/docs/dbcframework.tag b/docs/dbcframework.tag index ac810c0..84239b9 100644 --- a/docs/dbcframework.tag +++ b/docs/dbcframework.tag @@ -69,9 +69,7 @@ decode__database_8h.html DecodeSignal DecodeFrame - FrameKey - FrameKeyHasher - DecodeDatabase + DecodeDatabase ByteOrder @@ -168,10 +166,10 @@ DbcDecoder classDbcDecoder.html - const DecodeFrame * + std::shared_ptr< const DecodeFrame > FindFrame classDbcDecoder.html - ab2cfb2fb711c95d3a29365546b89f3da + a4005c4311f57b7faf21c0cb31463039c (const DecodeDatabase &database, std::uint32_t canId, bool isExtended) const @@ -271,18 +269,46 @@ classDbcValueDescriptionHandler.html DbcStatementHandler - + DecodeDatabase - structDecodeDatabase.html + classDecodeDatabase.html + + + DecodeDatabase + classDecodeDatabase.html + aa935a3a0d334f932d6a8c89a3818286a + (std::vector< DecodeFrame > frames) + + + const std::vector< DecodeFrame > & + GetFrames + classDecodeDatabase.html + aa034c1510984a85f60ad6c0bd744d6e8 + () const + + + std::shared_ptr< const DecodeFrame > + FindFrame + classDecodeDatabase.html + a780d6e747a48b10a5eb0ab85448d2970 + (const FrameKey &key) const + DecodedFrameValue structDecodedFrameValue.html - const DecodeFrame * + std::shared_ptr< const DecodeFrame > definition structDecodedFrameValue.html - a60dda1cc352d2c8087f0bdbc81dd266c + a33e971ba10030506007aa201c89f351d + + + + FrameKey + key + structDecodedFrameValue.html + a32143efe2023a1ecd977a9ae93e50b73 @@ -311,10 +337,17 @@ () const - const DecodeSignal * + std::shared_ptr< const DecodeSignal > definition structDecodedSignalValue.html - acadc3b3bb21dd6b0412d342c7e6b20d7 + a828b5ef7faefc14fbf5dbd46249bcad2 + + + + SignalKey + key + structDecodedSignalValue.html + a33df0fcd92b23b3e08539906fc6b4c4a @@ -704,6 +737,14 @@ + + SignalKey + structSignalKey.html + + + SignalKeyHasher + structSignalKeyHasher.html + TreeNode classTreeNode.html diff --git a/docs/doxygen_warnings.log b/docs/doxygen_warnings.log index e271c1f..36166ce 100644 --- a/docs/doxygen_warnings.log +++ b/docs/doxygen_warnings.log @@ -7,9 +7,10 @@ /home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:79: warning: Compound DbcUnsupportedMultiplexingHandler is not documented. /home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:74: warning: Compound DbcValueDescriptionHandler is not documented. /home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:12: warning: Compound PendingValueDescriptions is not documented. +/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/definition_key.h:56: warning: Compound SignalKeyHasher is not documented. /home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_decoder.h:32: warning: Member SignalDecodeStatus (enumeration) of file dbc_decoder.h is not documented. /home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/examples/main.cpp:100: warning: Member main(int argc, char *argv[]) (function) of file examples/main.cpp is not documented. -/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/README.md:1509: warning: end of comment block while expecting command +/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/README.md:1576: warning: end of comment block while expecting command /home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:68: warning: Member Handle(const std::string &line, DbcParseContext &context) const override (function) of class DbcCommentHandler is not documented. /home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_diagnostic.h:26: warning: Member severity (variable) of struct DbcDiagnostic is not documented. /home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_diagnostic.h:27: warning: Member code (variable) of struct DbcDiagnostic is not documented. @@ -46,15 +47,15 @@ /home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/qt/dbc_tree_model.h:44: warning: Member flags(const QModelIndex &index) const override (function) of class DbcTreeModel is not documented. /home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:81: warning: Member Handle(const std::string &line, DbcParseContext &context) const override (function) of class DbcUnsupportedMultiplexingHandler is not documented. /home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:76: warning: Member Handle(const std::string &line, DbcParseContext &context) const override (function) of class DbcValueDescriptionHandler is not documented. -/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:110: warning: Member frames (variable) of struct DecodeDatabase is not documented. -/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:111: warning: Member frameIndexByKey (variable) of struct DecodeDatabase is not documented. -/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_decoder.h:48: warning: Member status (variable) of struct DecodedSignalValue is not documented. -/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:42: warning: Member multiplexing (variable) of struct DecodeSignal is not documented. -/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:86: warning: Member FrameKey(std::uint32_t id, bool extended) (function) of struct FrameKey is not documented. -/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:90: warning: Member operator==(const FrameKey &other) const (function) of struct FrameKey is not documented. -/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:81: warning: Member canId (variable) of struct FrameKey is not documented. -/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:82: warning: Member isExtended (variable) of struct FrameKey is not documented. -/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:99: warning: Member operator()(const FrameKey &key) const (function) of struct FrameKeyHasher is not documented. +/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:101: warning: Member FindSignal(const SignalKey &key) const (function) of class DecodeDatabase is not documented. +/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_decoder.h:49: warning: Member status (variable) of struct DecodedSignalValue is not documented. +/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:78: warning: Member GetKey() const (function) of struct DecodeFrame is not documented. +/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:44: warning: Member multiplexing (variable) of struct DecodeSignal is not documented. +/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/definition_key.h:21: warning: Member FrameKey(std::uint32_t id, bool extended) (function) of struct FrameKey is not documented. +/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/definition_key.h:25: warning: Member operator==(const FrameKey &other) const (function) of struct FrameKey is not documented. +/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/definition_key.h:16: warning: Member canId (variable) of struct FrameKey is not documented. +/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/definition_key.h:17: warning: Member isExtended (variable) of struct FrameKey is not documented. +/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/definition_key.h:34: warning: Member operator()(const FrameKey &key) const (function) of struct FrameKeyHasher is not documented. /home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/multiplexing.h:15: warning: Member role (variable) of struct Multiplexing is not documented. /home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/multiplexing.h:16: warning: Member value (variable) of struct Multiplexing is not documented. /home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:13: warning: Member canId (variable) of struct PendingValueDescriptions is not documented. @@ -63,6 +64,11 @@ /home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:16: warning: Member descriptions (variable) of struct PendingValueDescriptions is not documented. /home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:17: warning: Member lineNumber (variable) of struct PendingValueDescriptions is not documented. /home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/signal_info.h:25: warning: Member multiplexing (variable) of struct SignalInfo is not documented. +/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/definition_key.h:47: warning: Member SignalKey(FrameKey frameKey, std::string signalName) (function) of struct SignalKey is not documented. +/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/definition_key.h:51: warning: Member operator==(const SignalKey &other) const (function) of struct SignalKey is not documented. +/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/definition_key.h:43: warning: Member frame (variable) of struct SignalKey is not documented. +/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/definition_key.h:44: warning: Member name (variable) of struct SignalKey is not documented. +/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/definition_key.h:57: warning: Member operator()(const SignalKey &key) const (function) of struct SignalKeyHasher is not documented. /home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/typefactory.h:61: warning: Member BasePtr (typedef) of class TypeFactory is not documented. /home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/typefactory.h:62: warning: Member CreatorFn (typedef) of class TypeFactory is not documented. /home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/typefactory.h:110: warning: Member classes (variable) of class TypeFactory is not documented. diff --git a/docs/html/annotated.html b/docs/html/annotated.html index b4d65fe..9df1d9b 100644 --- a/docs/html/annotated.html +++ b/docs/html/annotated.html @@ -113,20 +113,22 @@ $(document).ready(function(){initNavTree('annotated.html',''); initResizable();  CDbcTreeModel  CDbcUnsupportedMultiplexingHandler  CDbcValueDescriptionHandler - CDecodeDatabaseRuntime decode database with fast lookup by CAN ID + CDecodeDatabaseImmutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles and decoded results keep old definitions alive  CDecodedFrameValueFully decoded frame  CDecodedSignalValueOne decoded signal value  CDecodeFrameRuntime-ready frame definition  CDecodeSignalRuntime-ready signal definition  CFrameInfoDescribes one CAN frame from a DBC file - CFrameKeyKey for fast frame lookup + CFrameKeyStable frame identifier: normalized CAN ID and frame type  CFrameKeyHasherHasher for frame key  CMultiplexing  CPendingValueDescriptions  CRawCanFrameRaw CAN frame used for runtime or trace decoding  CSignalInfoDescribes one signal inside a DBC frame - CTreeNodeTree node for later use in model/view or other hierarchy consumers - CTypeFactoryRegistry-based factory for creating objects by runtime identifier + CSignalKey + CSignalKeyHasher + CTreeNodeTree node for later use in model/view or other hierarchy consumers + CTypeFactoryRegistry-based factory for creating objects by runtime identifier diff --git a/docs/html/annotated_dup.js b/docs/html/annotated_dup.js index a227194..775a659 100644 --- a/docs/html/annotated_dup.js +++ b/docs/html/annotated_dup.js @@ -18,7 +18,7 @@ var annotated_dup = [ "DbcTreeModel", "classDbcTreeModel.html", null ], [ "DbcUnsupportedMultiplexingHandler", "classDbcUnsupportedMultiplexingHandler.html", null ], [ "DbcValueDescriptionHandler", "classDbcValueDescriptionHandler.html", null ], - [ "DecodeDatabase", "structDecodeDatabase.html", null ], + [ "DecodeDatabase", "classDecodeDatabase.html", "classDecodeDatabase" ], [ "DecodedFrameValue", "structDecodedFrameValue.html", "structDecodedFrameValue" ], [ "DecodedSignalValue", "structDecodedSignalValue.html", "structDecodedSignalValue" ], [ "DecodeFrame", "structDecodeFrame.html", "structDecodeFrame" ], @@ -30,6 +30,8 @@ var annotated_dup = [ "PendingValueDescriptions", "structPendingValueDescriptions.html", null ], [ "RawCanFrame", "structRawCanFrame.html", "structRawCanFrame" ], [ "SignalInfo", "structSignalInfo.html", "structSignalInfo" ], + [ "SignalKey", "structSignalKey.html", null ], + [ "SignalKeyHasher", "structSignalKeyHasher.html", null ], [ "TreeNode", "classTreeNode.html", "classTreeNode" ], [ "TypeFactory", "classTypeFactory.html", "classTypeFactory" ] ]; \ No newline at end of file diff --git a/docs/html/classDbcDecodeBuilder.html b/docs/html/classDbcDecodeBuilder.html index 450021b..fa29228 100644 --- a/docs/html/classDbcDecodeBuilder.html +++ b/docs/html/classDbcDecodeBuilder.html @@ -104,7 +104,7 @@ $(document).ready(function(){initNavTree('classDbcDecodeBuilder.html',''); initR - +

Public Member Functions

DecodeDatabase Build (const DbcDatabase &source) const
DecodeDatabase Build (const DbcDatabase &source) const
 Build runtime decode database.
 
@@ -120,7 +120,7 @@ Public Member Functions diff --git a/docs/html/classDbcDecoder-members.html b/docs/html/classDbcDecoder-members.html index 5d18037..ebe7e4e 100644 --- a/docs/html/classDbcDecoder-members.html +++ b/docs/html/classDbcDecoder-members.html @@ -97,7 +97,7 @@ $(document).ready(function(){initNavTree('classDbcDecoder.html',''); initResizab

This is the complete list of members for DbcDecoder, including all inherited members.

- +
Decode(const DecodeDatabase &database, const RawCanFrame &frame) constDbcDecoder
FindFrame(const DecodeDatabase &database, std::uint32_t canId, bool isExtended) constDbcDecoder
FindFrame(const DecodeDatabase &database, std::uint32_t canId, bool isExtended) constDbcDecoder
diff --git a/docs/html/classDbcDecoder.html b/docs/html/classDbcDecoder.html index 77ddeee..4f0483e 100644 --- a/docs/html/classDbcDecoder.html +++ b/docs/html/classDbcDecoder.html @@ -105,28 +105,28 @@ $(document).ready(function(){initNavTree('classDbcDecoder.html',''); initResizab - - - - + + + +

Public Member Functions

const DecodeFrame * FindFrame (const DecodeDatabase &database, std::uint32_t canId, bool isExtended) const
 Find frame definition by CAN ID.
 
DecodedFrameValue Decode (const DecodeDatabase &database, const RawCanFrame &frame) const
std::shared_ptr< const DecodeFrame > FindFrame (const DecodeDatabase &database, std::uint32_t canId, bool isExtended) const
 Find frame definition by CAN ID.
 
DecodedFrameValue Decode (const DecodeDatabase &database, const RawCanFrame &frame) const
 Decode one raw CAN frame.
 

Detailed Description

Runtime CAN decoder using prebuilt decode database.

-

Definition at line 72 of file dbc_decoder.h.

+

Definition at line 74 of file dbc_decoder.h.

Member Function Documentation

- -

◆ FindFrame()

+ +

◆ FindFrame()

- + - + @@ -158,11 +158,13 @@ Public Member Functions
const DecodeFrame * DbcDecoder::FindFrame std::shared_ptr< const DecodeFrame > DbcDecoder::FindFrame (const DecodeDatabase & const DecodeDatabase &  database,
-
Returns
Pointer to frame definition or nullptr.
+
Returns
Owning immutable frame handle or nullptr. Safe across reload.
-

Definition at line 14 of file dbc_decoder.cpp.

+

Definition at line 15 of file dbc_decoder.cpp.

-

Referenced by Decode().

+

References DecodeDatabase::FindFrame().

+ +

Referenced by Decode().

@@ -175,7 +177,7 @@ Public Member Functions DecodedFrameValue DbcDecoder::Decode ( - const DecodeDatabase &  + const DecodeDatabase &  database, @@ -202,9 +204,9 @@ Public Member Functions
Returns
Decoded frame value.
-

Definition at line 31 of file dbc_decoder.cpp.

+

Definition at line 21 of file dbc_decoder.cpp.

-

References RawCanFrame::canId, DecodedFrameValue::definition, FindFrame(), RawCanFrame::isExtended, and DecodedFrameValue::valid.

+

References RawCanFrame::canId, DecodedSignalValue::definition, DecodedFrameValue::definition, FindFrame(), RawCanFrame::isExtended, DecodedSignalValue::key, DecodedFrameValue::key, and DecodedFrameValue::valid.

diff --git a/docs/html/classDbcDecoder.js b/docs/html/classDbcDecoder.js index e36dac7..71df33f 100644 --- a/docs/html/classDbcDecoder.js +++ b/docs/html/classDbcDecoder.js @@ -1,5 +1,5 @@ var classDbcDecoder = [ - [ "FindFrame", "classDbcDecoder.html#ab2cfb2fb711c95d3a29365546b89f3da", null ], + [ "FindFrame", "classDbcDecoder.html#a4005c4311f57b7faf21c0cb31463039c", null ], [ "Decode", "classDbcDecoder.html#a345951ffe5d943a70d3a1ea1f39e74f7", null ] ]; \ No newline at end of file diff --git a/docs/html/classDecodeDatabase-members.html b/docs/html/classDecodeDatabase-members.html new file mode 100644 index 0000000..9e7dc4f --- /dev/null +++ b/docs/html/classDecodeDatabase-members.html @@ -0,0 +1,113 @@ + + + + + + + +DBC Framework: Member List + + + + + + + + + + + + + +
+
+ + + + + + +
+
DBC Framework +
+
DBC parsing and CAN signal decoding framework
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
DecodeDatabase Member List
+
+
+ +

This is the complete list of members for DecodeDatabase, including all inherited members.

+ + + + + + +
DecodeDatabase()=default (defined in DecodeDatabase)DecodeDatabase
DecodeDatabase(std::vector< DecodeFrame > frames)DecodeDatabaseexplicit
FindFrame(const FrameKey &key) constDecodeDatabase
FindSignal(const SignalKey &key) const (defined in DecodeDatabase)DecodeDatabase
GetFrames() constDecodeDatabase
+
+ + + + diff --git a/docs/html/classDecodeDatabase.html b/docs/html/classDecodeDatabase.html new file mode 100644 index 0000000..fd1a9f2 --- /dev/null +++ b/docs/html/classDecodeDatabase.html @@ -0,0 +1,234 @@ + + + + + + + +DBC Framework: DecodeDatabase Class Reference + + + + + + + + + + + + + +
+
+ + + + + + +
+
DBC Framework +
+
DBC parsing and CAN signal decoding framework
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+ +
DecodeDatabase Class Reference
+
+
+ +

Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles and decoded results keep old definitions alive. + More...

+ +

#include <decode_database.h>

+ + + + + + + + + + +

+Public Member Functions

 DecodeDatabase (std::vector< DecodeFrame > frames)
 
const std::vector< DecodeFrame > & GetFrames () const
 
std::shared_ptr< const DecodeFrame > FindFrame (const FrameKey &key) const
 
std::shared_ptr< const DecodeSignal > FindSignal (const SignalKey &key) const
 
+

Detailed Description

+

Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles and decoded results keep old definitions alive.

+ +

Definition at line 87 of file decode_database.h.

+

Constructor & Destructor Documentation

+ +

◆ DecodeDatabase()

+ +
+
+ + + + + +
+ + + + + + + + +
DecodeDatabase::DecodeDatabase (std::vector< DecodeFrame > frames)
+
+explicit
+
+

Freeze definitions and build the frame index. Do not retain mutable aliases into moved input vectors.

Exceptions
+ + +
std::invalid_argumentfor duplicate frame keys or signal names.
+
+
+ +

Definition at line 24 of file decode_database.cpp.

+ +
+
+

Member Function Documentation

+ +

◆ GetFrames()

+ +
+
+ + + + + + + +
const std::vector< DecodeFrame > & DecodeDatabase::GetFrames () const
+
+

Borrowed view, valid while this snapshot remains alive and unchanged.

+ +

Definition at line 28 of file decode_database.cpp.

+ +
+
+ +

◆ FindFrame()

+ +
+
+ + + + + + + + +
std::shared_ptr< const DecodeFrame > DecodeDatabase::FindFrame (const FrameKey & key) const
+
+

Owning handles retain the entire snapshot across reload or destruction.

+ +

Definition at line 33 of file decode_database.cpp.

+ +

Referenced by DbcDecoder::FindFrame().

+ +
+
+ +

◆ FindSignal()

+ +
+
+ + + + + + + + +
std::shared_ptr< const DecodeSignal > DecodeDatabase::FindSignal (const SignalKey & key) const
+
+ +

Definition at line 43 of file decode_database.cpp.

+ +
+
+
The documentation for this class was generated from the following files: +
+
+ + + + diff --git a/docs/html/classDecodeDatabase.js b/docs/html/classDecodeDatabase.js new file mode 100644 index 0000000..33aac06 --- /dev/null +++ b/docs/html/classDecodeDatabase.js @@ -0,0 +1,6 @@ +var classDecodeDatabase = +[ + [ "DecodeDatabase", "classDecodeDatabase.html#aa935a3a0d334f932d6a8c89a3818286a", null ], + [ "GetFrames", "classDecodeDatabase.html#aa034c1510984a85f60ad6c0bd744d6e8", null ], + [ "FindFrame", "classDecodeDatabase.html#a780d6e747a48b10a5eb0ab85448d2970", null ] +]; \ No newline at end of file diff --git a/docs/html/classes.html b/docs/html/classes.html index bdf0080..a397671 100644 --- a/docs/html/classes.html +++ b/docs/html/classes.html @@ -97,7 +97,7 @@ $(document).ready(function(){initNavTree('classes.html',''); initResizable(); })
D
-
DbcCommentHandler
DbcDatabase
DbcDecodeBuilder
DbcDecoder
DbcDiagnostic
DbcDiagnosticError
DbcFrameHandler
DbcHeaderHandler
DbcParseContext
DbcParser
DbcParseResult
DbcSignalHandler
DbcStatementDispatcher
DbcStatementHandler
DbcTreeBuilder
DbcTreeModel
DbcUnsupportedMultiplexingHandler
DbcValueDescriptionHandler
DecodeDatabase
DecodedFrameValue
DecodedSignalValue
DecodeFrame
DecodeSignal
+
DbcCommentHandler
DbcDatabase
DbcDecodeBuilder
DbcDecoder
DbcDiagnostic
DbcDiagnosticError
DbcFrameHandler
DbcHeaderHandler
DbcParseContext
DbcParser
DbcParseResult
DbcSignalHandler
DbcStatementDispatcher
DbcStatementHandler
DbcTreeBuilder
DbcTreeModel
DbcUnsupportedMultiplexingHandler
DbcValueDescriptionHandler
DecodeDatabase
DecodedFrameValue
DecodedSignalValue
DecodeFrame
DecodeSignal
F
FrameInfo
FrameKey
FrameKeyHasher
@@ -112,7 +112,7 @@ $(document).ready(function(){initNavTree('classes.html',''); initResizable(); })
RawCanFrame
S
-
SignalInfo
+
SignalInfo
SignalKey
SignalKeyHasher
T
TreeNode
TypeFactory
diff --git a/docs/html/dbc__coverage__test_8cpp_source.html b/docs/html/dbc__coverage__test_8cpp_source.html index 636d6de..aca7cd9 100644 --- a/docs/html/dbc__coverage__test_8cpp_source.html +++ b/docs/html/dbc__coverage__test_8cpp_source.html @@ -120,740 +120,744 @@ $(document).ready(function(){initNavTree('dbc__coverage__test_8cpp_source.html',
20 return DbcParser().ParseFile(file.fileName().toStdString());
21 }
22
-
23 DecodeDatabase SingleSignal(const DecodeSignal &signal) {
-
24 DecodeDatabase database;
-
25 DecodeFrame frame;
-
26 frame.canId = 17U;
-
27 frame.signals.push_back(signal);
-
28 database.frames.push_back(frame);
-
29 database.frameIndexByKey.emplace(FrameKey(17U, false), 0U);
-
30 return database;
-
31 }
-
32
-
33 // Independent reference: collect the visited bits first, then weight them.
-
34 // Motorola uses a linear MSB-first coordinate instead of sawtooth traversal.
-
35 std::uint64_t ReferenceExtract(const std::vector<std::uint8_t> &data,
-
36 ByteOrder order, unsigned start, unsigned length) {
-
37 std::uint64_t expected = 0;
-
38 for (unsigned i = 0; i < length; ++i) {
-
39 const unsigned coordinate = order == ByteOrder::Intel
-
40 ? start + i
-
41 : (start / 8U) * 8U + (7U - start % 8U) + i;
-
42 const unsigned bit = order == ByteOrder::Intel ? coordinate % 8U : 7U - coordinate % 8U;
-
43 const unsigned weight = order == ByteOrder::Intel ? i : length - 1U - i;
-
44 expected |= std::uint64_t((data.at(coordinate / 8U) >> bit) & 1U) << weight;
-
45 }
-
46 return expected;
-
47 }
-
48
-
49 struct FactoryBase {
-
50 virtual ~FactoryBase() = default;
-
51 virtual int Value() const = 0;
-
52 };
-
53 struct FactoryFirst : FactoryBase {
-
54 explicit FactoryFirst(std::unique_ptr<int> value) : value(std::move(value)) {}
-
55 int Value() const override { return *value; }
-
56 std::unique_ptr<int> value;
-
57 };
-
58 struct FactorySecond : FactoryFirst {
-
59 using FactoryFirst::FactoryFirst;
-
60 int Value() const override { return *value + 1; }
-
61 };
-
62}// namespace
-
63
-
64class CoverageTest : public QObject {
-
65 Q_OBJECT
-
66private Q_SLOTS:
-
67 void frameLookup();
-
68 void signedBoundaries_data();
-
69 void signedBoundaries();
-
70 void extraction_data();
-
71 void extraction();
-
72 void invalidSignalStatus_data();
-
73 void invalidSignalStatus();
-
74 void malformedRuntimeMultiplexing_data();
-
75 void malformedRuntimeMultiplexing();
-
76 void pgn_data();
-
77 void pgn();
-
78 void comments_data();
-
79 void comments();
-
80 void ignoredCommentStatements_data();
-
81 void ignoredCommentStatements();
-
82 void ambiguousValueReferences_data();
-
83 void ambiguousValueReferences();
-
84 void valueReferenceScope();
-
85 void fileFormatting_data();
-
86 void fileFormatting();
-
87 void missingFile();
-
88 void builders();
-
89 void physicalConversion_data();
-
90 void physicalConversion();
-
91 void multiplexingScenarios();
-
92 void multiplexingErrorLocations_data();
-
93 void multiplexingErrorLocations();
-
94 void escapedValueDescriptions();
-
95 void factory();
-
96};
-
97
-
98void CoverageTest::frameLookup() {
-
99 DbcDecoder decoder;
-
100 RawCanFrame raw;
-
101 raw.canId = 17U;
-
102 DecodeDatabase empty;
-
103 QVERIFY(decoder.FindFrame(empty, 17U, false) == nullptr);
-
104 const DecodedFrameValue absent = decoder.Decode(empty, raw);
-
105 QVERIFY(!absent.valid);
-
106 QVERIFY(absent.definition == nullptr);
-
107 QVERIFY(absent.signals.empty());
-
108 DecodeSignal signal;
-
109 DecodeDatabase database = SingleSignal(signal);
-
110 QVERIFY(decoder.FindFrame(database, 18U, false) == nullptr);
-
111 QVERIFY(decoder.FindFrame(database, 17U, true) == nullptr);
-
112 raw.isExtended = true;
+
23 DecodeDatabase SingleSignal(const DecodeSignal &signal) {
+
24 DecodeFrame frame;
+
25 frame.canId = 17U;
+
26 frame.signals.push_back(signal);
+
27 return DecodeDatabase({frame});
+
28 }
+
29
+
30 // Independent reference: collect the visited bits first, then weight them.
+
31 // Motorola uses a linear MSB-first coordinate instead of sawtooth traversal.
+
32 std::uint64_t ReferenceExtract(const std::vector<std::uint8_t> &data,
+
33 ByteOrder order, unsigned start, unsigned length) {
+
34 std::uint64_t expected = 0;
+
35 for (unsigned i = 0; i < length; ++i) {
+
36 const unsigned coordinate = order == ByteOrder::Intel
+
37 ? start + i
+
38 : (start / 8U) * 8U + (7U - start % 8U) + i;
+
39 const unsigned bit = order == ByteOrder::Intel ? coordinate % 8U : 7U - coordinate % 8U;
+
40 const unsigned weight = order == ByteOrder::Intel ? i : length - 1U - i;
+
41 expected |= std::uint64_t((data.at(coordinate / 8U) >> bit) & 1U) << weight;
+
42 }
+
43 return expected;
+
44 }
+
45
+
46 struct FactoryBase {
+
47 virtual ~FactoryBase() = default;
+
48 virtual int Value() const = 0;
+
49 };
+
50 struct FactoryFirst : FactoryBase {
+
51 explicit FactoryFirst(std::unique_ptr<int> value) : value(std::move(value)) {}
+
52 int Value() const override { return *value; }
+
53 std::unique_ptr<int> value;
+
54 };
+
55 struct FactorySecond : FactoryFirst {
+
56 using FactoryFirst::FactoryFirst;
+
57 int Value() const override { return *value + 1; }
+
58 };
+
59}// namespace
+
60
+
61class CoverageTest : public QObject {
+
62 Q_OBJECT
+
63private Q_SLOTS:
+
64 void frameLookup();
+
65 void signedBoundaries_data();
+
66 void signedBoundaries();
+
67 void extraction_data();
+
68 void extraction();
+
69 void invalidSignalStatus_data();
+
70 void invalidSignalStatus();
+
71 void malformedRuntimeMultiplexing_data();
+
72 void malformedRuntimeMultiplexing();
+
73 void pgn_data();
+
74 void pgn();
+
75 void comments_data();
+
76 void comments();
+
77 void ignoredCommentStatements_data();
+
78 void ignoredCommentStatements();
+
79 void ambiguousValueReferences_data();
+
80 void ambiguousValueReferences();
+
81 void valueReferenceScope();
+
82 void fileFormatting_data();
+
83 void fileFormatting();
+
84 void missingFile();
+
85 void builders();
+
86 void physicalConversion_data();
+
87 void physicalConversion();
+
88 void multiplexingScenarios();
+
89 void multiplexingErrorLocations_data();
+
90 void multiplexingErrorLocations();
+
91 void escapedValueDescriptions();
+
92 void factory();
+
93};
+
94
+
95void CoverageTest::frameLookup() {
+
96 DbcDecoder decoder;
+
97 RawCanFrame raw;
+
98 raw.canId = 17U;
+
99 DecodeDatabase empty;
+
100 QVERIFY(decoder.FindFrame(empty, 17U, false) == nullptr);
+
101 const DecodedFrameValue absent = decoder.Decode(empty, raw);
+
102 QVERIFY(!absent.valid);
+
103 QVERIFY(absent.definition == nullptr);
+
104 QVERIFY(absent.signals.empty());
+
105 DecodeSignal signal;
+
106 DecodeDatabase database = SingleSignal(signal);
+
107 QVERIFY(decoder.FindFrame(database, 18U, false) == nullptr);
+
108 QVERIFY(decoder.FindFrame(database, 17U, true) == nullptr);
+
109 raw.isExtended = true;
+
110 QVERIFY(!decoder.Decode(database, raw).valid);
+
111 raw.isExtended = false;
+
112 raw.canId = 18U;
113 QVERIFY(!decoder.Decode(database, raw).valid);
-
114 raw.isExtended = false;
-
115 raw.canId = 18U;
-
116 QVERIFY(!decoder.Decode(database, raw).valid);
-
117 raw.canId = 17U;
-
118 database.frameIndexByKey.at(FrameKey(17U, false)) = database.frames.size();
-
119 QVERIFY(decoder.FindFrame(database, 17U, false) == nullptr);
-
120 QVERIFY(!decoder.Decode(database, raw).valid);
-
121 database.frameIndexByKey.at(FrameKey(17U, false)) = 0U;
-
122 database.frames[0].signals.clear();
-
123 const DecodedFrameValue matched = decoder.Decode(database, raw);
-
124 QVERIFY(matched.valid);
-
125 QCOMPARE(matched.definition, &database.frames[0]);
-
126 QVERIFY(matched.signals.empty());
-
127}
-
128
-
129void CoverageTest::signedBoundaries_data() {
-
130 QTest::addColumn<int>("order");
-
131 QTest::addColumn<unsigned>("length");
-
132 QTest::addColumn<qlonglong>("expected");
-
133 for (int order = 0; order < 2; ++order) {
-
134 for (unsigned length: {1U, 2U, 7U, 8U, 31U, 32U, 63U}) {
-
135 const std::int64_t half = std::int64_t(1) << (length - 1U);
-
136 const std::array<std::int64_t, 4> values{{0, -1, -half, half - 1}};
-
137 for (unsigned index = 0; index < values.size(); ++index) {
-
138 const QByteArray name = QByteArray::number(order) + "-" + QByteArray::number(length) + "-" + QByteArray::number(index);
-
139 QTest::newRow(name.constData()) << order << length << qlonglong(values[index]);
-
140 }
-
141 }
-
142 }
-
143}
-
144
-
145void CoverageTest::signedBoundaries() {
-
146 QFETCH(int, order);
-
147 QFETCH(unsigned, length);
-
148 QFETCH(qlonglong, expected);
-
149 DecodeSignal signal;
-
150 signal.byteOrder = order == 0 ? ByteOrder::Intel : ByteOrder::Motorola;
-
151 signal.startBit = order == 0 ? 0U : 7U;
-
152 signal.length = length;
-
153 signal.valueType = ValueType::Signed;
-
154 RawCanFrame raw;
-
155 raw.canId = 17U;
-
156 raw.data.assign(8U, 0U);
-
157 const std::uint64_t bits = static_cast<std::uint64_t>(expected);
-
158 for (unsigned i = 0; i < length; ++i) {
-
159 const unsigned weight = order == 0 ? i : length - 1U - i;
-
160 const unsigned position = order == 0 ? i % 8U : 7U - i % 8U;
-
161 raw.data[i / 8U] |= static_cast<std::uint8_t>(((bits >> weight) & 1U) << position);
-
162 }
-
163 const DecodeDatabase database = SingleSignal(signal);
-
164 const DecodedFrameValue result = DbcDecoder().Decode(database, raw);
-
165 QVERIFY(result.signals[0].valid);
-
166 QVERIFY(std::holds_alternative<std::int64_t>(result.signals[0].rawValue));
-
167 QCOMPARE(std::get<std::int64_t>(result.signals[0].rawValue), static_cast<std::int64_t>(expected));
-
168}
-
169
-
170void CoverageTest::extraction_data() {
-
171 QTest::addColumn<int>("order");
-
172 QTest::addColumn<unsigned>("start");
-
173 QTest::addColumn<unsigned>("length");
-
174 for (int order = 0; order < 2; ++order)
-
175 for (unsigned start = 0; start < 16U; ++start)
-
176 for (unsigned length = 1; length <= 64U; ++length) {
-
177 const QByteArray name = QByteArray::number(order) + "-" + QByteArray::number(start) + "-" + QByteArray::number(length);
-
178 QTest::newRow(name.constData()) << order << start << length;
-
179 }
-
180}
-
181
-
182void CoverageTest::extraction() {
-
183 QFETCH(int, order);
-
184 QFETCH(unsigned, start);
-
185 QFETCH(unsigned, length);
-
186 DecodeSignal signal;
-
187 signal.byteOrder = order == 0 ? ByteOrder::Intel : ByteOrder::Motorola;
-
188 signal.startBit = start;
-
189 signal.length = length;
-
190 const DecodeDatabase database = SingleSignal(signal);
-
191 RawCanFrame raw;
-
192 raw.canId = 17U;
-
193 const std::vector<std::vector<std::uint8_t>> patterns = {
-
194 std::vector<std::uint8_t>(10U, 0U),
-
195 std::vector<std::uint8_t>(10U, 255U),
-
196 {0xA5, 0x3C, 0x81, 0x7E, 0x12, 0xD4, 0x69, 0xB0, 0x5A, 0xC3}};
-
197 for (const std::vector<std::uint8_t> &data: patterns) {
-
198 raw.data = data;
-
199 const unsigned firstCoordinate = order == 0 ? start : (start / 8U) * 8U + 7U - start % 8U;
-
200 raw.data.resize((firstCoordinate + length + 7U) / 8U);
-
201 const DecodedFrameValue decoded = DbcDecoder().Decode(database, raw);
-
202 QVERIFY(decoded.signals[0].valid);
-
203 QCOMPARE(std::get<std::uint64_t>(decoded.signals[0].rawValue), ReferenceExtract(data, signal.byteOrder, start, length));
-
204 }
-
205}
-
206
-
207void CoverageTest::invalidSignalStatus_data() {
-
208 QTest::addColumn<int>("order");
-
209 QTest::addColumn<unsigned>("start");
-
210 QTest::addColumn<unsigned>("length");
-
211 QTest::addColumn<unsigned>("bytes");
-
212 QTest::addColumn<int>("status");
-
213 for (int order = 0; order < 2; ++order) {
-
214 const unsigned start = order == 0 ? 0U : 7U;
-
215 const QByteArray prefix = QByteArray::number(order);
-
216 QTest::newRow((prefix + "-zero").constData()) << order << start << 0U << 1U << int(SignalDecodeStatus::InvalidDefinition);
-
217 QTest::newRow((prefix + "-65").constData()) << order << start << 65U << 9U << int(SignalDecodeStatus::InvalidDefinition);
-
218 QTest::newRow((prefix + "-empty").constData()) << order << start << 8U << 0U << int(SignalDecodeStatus::InsufficientPayload);
-
219 QTest::newRow((prefix + "-short").constData()) << order << start << 16U << 1U << int(SignalDecodeStatus::InsufficientPayload);
-
220 QTest::newRow((prefix + "-large-start").constData()) << order << std::numeric_limits<unsigned>::max() << 8U << 1U << int(SignalDecodeStatus::InsufficientPayload);
-
221 }
-
222}
-
223
-
224void CoverageTest::invalidSignalStatus() {
-
225 QFETCH(int, order);
-
226 QFETCH(unsigned, start);
-
227 QFETCH(unsigned, length);
-
228 QFETCH(unsigned, bytes);
-
229 QFETCH(int, status);
-
230 DecodeSignal signal;
-
231 signal.startBit = start;
-
232 signal.length = length;
-
233 signal.byteOrder = order == 0 ? ByteOrder::Intel : ByteOrder::Motorola;
-
234 const DecodeDatabase database = SingleSignal(signal);
-
235 RawCanFrame raw;
-
236 raw.canId = 17U;
-
237 raw.data.assign(bytes, 255U);
-
238 const DecodedFrameValue decoded = DbcDecoder().Decode(database, raw);
-
239 QVERIFY(decoded.valid);
-
240 QVERIFY(!decoded.signals[0].valid);
-
241 QCOMPARE(int(decoded.signals[0].status), status);
-
242 QVERIFY(decoded.signals[0].GetValueDescription() == nullptr);
-
243}
-
244
-
245void CoverageTest::malformedRuntimeMultiplexing_data() {
-
246 QTest::addColumn<int>("kind");
-
247 QTest::newRow("two-selectors") << 0;
-
248 QTest::newRow("signed-selector") << 1;
-
249 QTest::newRow("65-bit-selector") << 2;
-
250 QTest::newRow("branch-out-of-range") << 3;
-
251}
-
252
-
253void CoverageTest::malformedRuntimeMultiplexing() {
-
254 QFETCH(int, kind);
-
255 DecodeSignal selector;
-
256 selector.length = 1U;
-
257 selector.multiplexing.role = MultiplexRole::Selector;
-
258 DecodeDatabase database = SingleSignal(selector);
-
259 DecodeSignal branch;
-
260 branch.startBit = 8U;
-
261 branch.length = 8U;
-
262 branch.multiplexing.role = MultiplexRole::Branch;
-
263 branch.multiplexing.value = 1U;
-
264 database.frames[0].signals.push_back(branch);
-
265 DecodeSignal ordinary;
-
266 ordinary.startBit = 16U;
-
267 ordinary.length = 8U;
-
268 database.frames[0].signals.push_back(ordinary);
-
269 if (kind == 0) database.frames[0].signals.push_back(selector);
-
270 if (kind == 1) database.frames[0].signals[0].valueType = ValueType::Signed;
-
271 if (kind == 2) database.frames[0].signals[0].length = 65U;
-
272 if (kind == 3) database.frames[0].signals[1].multiplexing.value = 2U;
-
273 RawCanFrame raw;
-
274 raw.canId = 17U;
-
275 raw.data = {1U, 42U, 99U};
-
276 const DecodedFrameValue result = DbcDecoder().Decode(database, raw);
-
277 QCOMPARE(int(result.signals[1].status), int(SignalDecodeStatus::InvalidDefinition));
-
278 QVERIFY(!result.signals[1].valid);
-
279 QVERIFY(result.signals[2].valid);
-
280 QCOMPARE(std::get<std::uint64_t>(result.signals[2].rawValue), std::uint64_t(99));
-
281 if (kind != 3) {
-
282 QCOMPARE(int(result.signals[0].status), int(SignalDecodeStatus::InvalidDefinition));
-
283 if (kind == 0) QCOMPARE(int(result.signals[3].status), int(SignalDecodeStatus::InvalidDefinition));
-
284 }
-
285}
-
286
-
287void CoverageTest::pgn_data() {
-
288 QTest::addColumn<unsigned>("id");
-
289 QTest::addColumn<unsigned>("expected");
-
290 QTest::addColumn<bool>("hasPgn");
-
291 QTest::newRow("standard") << 0x7FFU << 0U << false;
-
292 for (unsigned dp: {0U, 1U})
-
293 for (unsigned pf: {239U, 240U})
-
294 for (unsigned ps: {0U, 0xABU}) {
-
295 const unsigned id = 0x80000000U | (dp << 24U) | (pf << 16U) | (ps << 8U) | 0x42U;
-
296 const unsigned expected = (dp << 16U) | (pf == 239U ? 0xEF00U : 0xF000U | ps);
-
297 const QByteArray name = QByteArray::number(dp) + "-" + QByteArray::number(pf) + "-" + QByteArray::number(ps);
-
298 QTest::newRow(name.constData()) << id << expected << true;
-
299 }
-
300}
-
301
-
302void CoverageTest::pgn() {
-
303 QFETCH(unsigned, id);
-
304 QFETCH(unsigned, expected);
-
305 QFETCH(bool, hasPgn);
-
306 const DbcDatabase parsed = ParseText("BO_ " + std::to_string(id) + " Frame: 8 ECU\n");
-
307 QCOMPARE(parsed.frames[0].hasPgn, hasPgn);
-
308 QCOMPARE(parsed.frames[0].pgn, expected);
-
309}
-
310
-
311void CoverageTest::comments_data() {
-
312 QTest::addColumn<QString>("before");
-
313 QTest::addColumn<QString>("after");
-
314 QTest::addColumn<QString>("frameComment");
-
315 QTest::addColumn<QString>("signalComment");
-
316 QTest::newRow("tabs") << QString::fromUtf8("") << QString::fromUtf8("CM_\tBO_ 1 \"Frame\";\nCM_\tSG_ 1 State \"Signal\";\n") << QString::fromUtf8("Frame") << QString::fromUtf8("Signal");
-
317 QTest::newRow("empty-overwrite") << QString::fromUtf8("") << QString::fromUtf8("CM_ BO_ 1 \"Old\";\nCM_ BO_ 1 \"\";\nCM_ SG_ 1 State \"Old\";\nCM_ SG_ 1 State \"\";\n") << QString::fromUtf8("") << QString::fromUtf8("");
-
318 QTest::newRow("last-wins") << QString::fromUtf8("") << QString::fromUtf8("CM_ BO_ 1 \"First\";\nCM_ BO_ 1 \"Last\";\nCM_ SG_ 1 State \"First\";\nCM_ SG_ 1 State \"Last\";\n") << QString::fromUtf8("Last") << QString::fromUtf8("Last");
-
319 QTest::newRow("missing-targets") << QString::fromUtf8("") << QString::fromUtf8("CM_ BO_ 2 \"Unknown\";\nCM_ SG_ 2 State \"Unknown\";\nCM_ SG_ 1 Missing \"Unknown\";\n") << QString::fromUtf8("") << QString::fromUtf8("");
-
320 // Current documented limitation: comments resolve only already parsed targets.
-
321 QTest::newRow("before-definitions") << QString::fromUtf8("CM_ BO_ 1 \"Early\";\nCM_ SG_ 1 State \"Early\";\n") << QString::fromUtf8("") << QString::fromUtf8("") << QString::fromUtf8("");
-
322 QTest::newRow("missing-quotes") << QString::fromUtf8("") << QString::fromUtf8("CM_ BO_ 1 Missing;\nCM_ SG_ 1 State \"Unclosed;\n") << QString::fromUtf8("") << QString::fromUtf8("");
-
323}
-
324
-
325void CoverageTest::comments() {
-
326 QFETCH(QString, before);
-
327 QFETCH(QString, after);
-
328 QFETCH(QString, frameComment);
-
329 QFETCH(QString, signalComment);
-
330 const DbcDatabase parsed = ParseText(before.toStdString() + "BO_ 1 Frame: 1 ECU\nSG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n" + after.toStdString());
-
331 QCOMPARE(parsed.frames[0].comment, frameComment.toStdString());
-
332 QCOMPARE(parsed.frames[0].signals[0].comment, signalComment.toStdString());
-
333}
-
334
-
335void CoverageTest::ignoredCommentStatements_data() {
-
336 QTest::addColumn<QString>("statement");
-
337 QTest::newRow("empty") << QString();
-
338 QTest::newRow("wrong-keyword") << QStringLiteral("OTHER_ BO_ 1 \"Ignored\";");
-
339 QTest::newRow("keyword-prefix") << QStringLiteral("CM_OTHER BO_ 1 \"Ignored\";");
-
340 QTest::newRow("frame-without-cm") << QStringLiteral("BO_ 1 \"Ignored\";");
-
341 QTest::newRow("missing-subtype") << QStringLiteral("CM_");
-
342 QTest::newRow("global-comment") << QStringLiteral("CM_ \"Ignored\";");
-
343 QTest::newRow("node-comment") << QStringLiteral("CM_ BU_ ECU \"Ignored\";");
-
344 QTest::newRow("environment-comment") << QStringLiteral("CM_ EV_ State \"Ignored\";");
-
345 QTest::newRow("unknown-subtype") << QStringLiteral("CM_ OTHER_ 1 \"Ignored\";");
-
346}
-
347
-
348void CoverageTest::ignoredCommentStatements() {
-
349 QFETCH(QString, statement);
-
350 DbcDatabase database;
-
351 FrameInfo frame;
-
352 frame.canId = 1U;
-
353 frame.name = "Frame";
-
354 frame.comment = "Existing frame comment";
-
355 SignalInfo signal;
-
356 signal.name = "State";
-
357 signal.comment = "Existing signal comment";
-
358 frame.signals.push_back(signal);
-
359 database.frames.push_back(frame);
-
360 DbcParseContext context{database, &database.frames[0]};
-
361
-
362 // The handler is public: callers may bypass keyword dispatch. Ignored input
-
363 // must preserve existing metadata, including comments already assigned.
-
364 DbcCommentHandler().Handle(statement.toStdString(), context);
-
365 QCOMPARE(database.frames.size(), std::size_t(1));
-
366 QCOMPARE(database.frames[0].canId, 1U);
-
367 QCOMPARE(database.frames[0].name, frame.name);
-
368 QCOMPARE(database.frames[0].comment, frame.comment);
-
369 QCOMPARE(database.frames[0].signals.size(), std::size_t(1));
-
370 QCOMPARE(database.frames[0].signals[0].name, signal.name);
-
371 QCOMPARE(database.frames[0].signals[0].comment, signal.comment);
-
372 QCOMPARE(context.currentFrame, &database.frames[0]);
-
373}
-
374
-
375void CoverageTest::ambiguousValueReferences_data() {
-
376 QTest::addColumn<bool>("duplicateFrames");
-
377 QTest::addColumn<bool>("extended");
-
378 QTest::newRow("duplicate-standard-frames") << true << false;
-
379 QTest::newRow("duplicate-extended-frames") << true << true;
-
380 QTest::newRow("duplicate-signals-in-standard-frame") << false << false;
-
381 QTest::newRow("duplicate-signals-in-extended-frame") << false << true;
-
382}
-
383
-
384void CoverageTest::ambiguousValueReferences() {
-
385 QFETCH(bool, duplicateFrames);
-
386 QFETCH(bool, extended);
-
387 DbcDatabase database;
-
388 FrameInfo frame;
-
389 frame.canId = 1U;
-
390 frame.name = "Frame";
-
391 frame.isExtended = extended;
-
392 SignalInfo signal;
-
393 signal.name = "State";
-
394 frame.signals.push_back(signal);
-
395 if (!duplicateFrames) frame.signals.push_back(signal);
-
396 database.frames.push_back(frame);
-
397 if (duplicateFrames) database.frames.push_back(frame);
-
398
-
399 // ParseFile rejects duplicate definitions earlier. Construct the database
-
400 // through the public metadata API to exercise the resolver's own checks.
-
401 DbcParseContext context{database, nullptr};
-
402 context.lineNumber = 37U;
-
403 const std::string rawId = extended ? "2147483649" : "1";
-
404 DbcValueDescriptionHandler().Handle("VAL_ " + rawId + " State 0 \"Off\";", context);
-
405 QCOMPARE(context.pendingValues.size(), std::size_t(1));
-
406 QCOMPARE(context.pendingValues[0].lineNumber, std::size_t(37));
-
407 const std::string path = "manual database.dbc";
-
408 try {
-
409 context.ResolveValueDescriptions(path);
-
410 QFAIL("The resolver must reject an ambiguous target");
-
411 } catch (const std::runtime_error &error) {
-
412 const std::string message = duplicateFrames ? "Ambiguous VAL_ frame reference."
-
413 : "Ambiguous VAL_ signal reference: State";
-
414 QCOMPARE(std::string(error.what()), path + ":37: " + message);
-
415 }
-
416 // Ambiguity must be detected before applying any descriptions.
-
417 for (const FrameInfo &candidate: database.frames)
-
418 for (const SignalInfo &candidateSignal: candidate.signals)
-
419 QVERIFY(candidateSignal.valueDescriptions.empty());
-
420}
-
421
-
422void CoverageTest::valueReferenceScope() {
-
423 DbcDatabase database;
-
424 FrameInfo frame;
-
425 frame.canId = 1U;
-
426 SignalInfo signal;
-
427 signal.name = "State";
-
428 frame.signals.push_back(signal);
-
429 database.frames.push_back(frame);
-
430 frame.isExtended = true;
+
114 raw.canId = 17U;
+
115 DecodeFrame noSignals;
+
116 noSignals.canId = 17U;
+
117 database = DecodeDatabase({noSignals});
+
118 const DecodedFrameValue matched = decoder.Decode(database, raw);
+
119 QVERIFY(matched.valid);
+
120 QCOMPARE(matched.definition.get(), &database.GetFrames()[0]);
+
121 QVERIFY(matched.signals.empty());
+
122}
+
123
+
124void CoverageTest::signedBoundaries_data() {
+
125 QTest::addColumn<int>("order");
+
126 QTest::addColumn<unsigned>("length");
+
127 QTest::addColumn<qlonglong>("expected");
+
128 for (int order = 0; order < 2; ++order) {
+
129 for (unsigned length: {1U, 2U, 7U, 8U, 31U, 32U, 63U}) {
+
130 const std::int64_t half = std::int64_t(1) << (length - 1U);
+
131 const std::array<std::int64_t, 4> values{{0, -1, -half, half - 1}};
+
132 for (unsigned index = 0; index < values.size(); ++index) {
+
133 const QByteArray name = QByteArray::number(order) + "-" + QByteArray::number(length) + "-" + QByteArray::number(index);
+
134 QTest::newRow(name.constData()) << order << length << qlonglong(values[index]);
+
135 }
+
136 }
+
137 }
+
138}
+
139
+
140void CoverageTest::signedBoundaries() {
+
141 QFETCH(int, order);
+
142 QFETCH(unsigned, length);
+
143 QFETCH(qlonglong, expected);
+
144 DecodeSignal signal;
+
145 signal.byteOrder = order == 0 ? ByteOrder::Intel : ByteOrder::Motorola;
+
146 signal.startBit = order == 0 ? 0U : 7U;
+
147 signal.length = length;
+
148 signal.valueType = ValueType::Signed;
+
149 RawCanFrame raw;
+
150 raw.canId = 17U;
+
151 raw.data.assign(8U, 0U);
+
152 const std::uint64_t bits = static_cast<std::uint64_t>(expected);
+
153 for (unsigned i = 0; i < length; ++i) {
+
154 const unsigned weight = order == 0 ? i : length - 1U - i;
+
155 const unsigned position = order == 0 ? i % 8U : 7U - i % 8U;
+
156 raw.data[i / 8U] |= static_cast<std::uint8_t>(((bits >> weight) & 1U) << position);
+
157 }
+
158 const DecodeDatabase database = SingleSignal(signal);
+
159 const DecodedFrameValue result = DbcDecoder().Decode(database, raw);
+
160 QVERIFY(result.signals[0].valid);
+
161 QVERIFY(std::holds_alternative<std::int64_t>(result.signals[0].rawValue));
+
162 QCOMPARE(std::get<std::int64_t>(result.signals[0].rawValue), static_cast<std::int64_t>(expected));
+
163}
+
164
+
165void CoverageTest::extraction_data() {
+
166 QTest::addColumn<int>("order");
+
167 QTest::addColumn<unsigned>("start");
+
168 QTest::addColumn<unsigned>("length");
+
169 for (int order = 0; order < 2; ++order)
+
170 for (unsigned start = 0; start < 16U; ++start)
+
171 for (unsigned length = 1; length <= 64U; ++length) {
+
172 const QByteArray name = QByteArray::number(order) + "-" + QByteArray::number(start) + "-" + QByteArray::number(length);
+
173 QTest::newRow(name.constData()) << order << start << length;
+
174 }
+
175}
+
176
+
177void CoverageTest::extraction() {
+
178 QFETCH(int, order);
+
179 QFETCH(unsigned, start);
+
180 QFETCH(unsigned, length);
+
181 DecodeSignal signal;
+
182 signal.byteOrder = order == 0 ? ByteOrder::Intel : ByteOrder::Motorola;
+
183 signal.startBit = start;
+
184 signal.length = length;
+
185 const DecodeDatabase database = SingleSignal(signal);
+
186 RawCanFrame raw;
+
187 raw.canId = 17U;
+
188 const std::vector<std::vector<std::uint8_t>> patterns = {
+
189 std::vector<std::uint8_t>(10U, 0U),
+
190 std::vector<std::uint8_t>(10U, 255U),
+
191 {0xA5, 0x3C, 0x81, 0x7E, 0x12, 0xD4, 0x69, 0xB0, 0x5A, 0xC3}};
+
192 for (const std::vector<std::uint8_t> &data: patterns) {
+
193 raw.data = data;
+
194 const unsigned firstCoordinate = order == 0 ? start : (start / 8U) * 8U + 7U - start % 8U;
+
195 raw.data.resize((firstCoordinate + length + 7U) / 8U);
+
196 const DecodedFrameValue decoded = DbcDecoder().Decode(database, raw);
+
197 QVERIFY(decoded.signals[0].valid);
+
198 QCOMPARE(std::get<std::uint64_t>(decoded.signals[0].rawValue), ReferenceExtract(data, signal.byteOrder, start, length));
+
199 }
+
200}
+
201
+
202void CoverageTest::invalidSignalStatus_data() {
+
203 QTest::addColumn<int>("order");
+
204 QTest::addColumn<unsigned>("start");
+
205 QTest::addColumn<unsigned>("length");
+
206 QTest::addColumn<unsigned>("bytes");
+
207 QTest::addColumn<int>("status");
+
208 for (int order = 0; order < 2; ++order) {
+
209 const unsigned start = order == 0 ? 0U : 7U;
+
210 const QByteArray prefix = QByteArray::number(order);
+
211 QTest::newRow((prefix + "-zero").constData()) << order << start << 0U << 1U << int(SignalDecodeStatus::InvalidDefinition);
+
212 QTest::newRow((prefix + "-65").constData()) << order << start << 65U << 9U << int(SignalDecodeStatus::InvalidDefinition);
+
213 QTest::newRow((prefix + "-empty").constData()) << order << start << 8U << 0U << int(SignalDecodeStatus::InsufficientPayload);
+
214 QTest::newRow((prefix + "-short").constData()) << order << start << 16U << 1U << int(SignalDecodeStatus::InsufficientPayload);
+
215 QTest::newRow((prefix + "-large-start").constData()) << order << std::numeric_limits<unsigned>::max() << 8U << 1U << int(SignalDecodeStatus::InsufficientPayload);
+
216 }
+
217}
+
218
+
219void CoverageTest::invalidSignalStatus() {
+
220 QFETCH(int, order);
+
221 QFETCH(unsigned, start);
+
222 QFETCH(unsigned, length);
+
223 QFETCH(unsigned, bytes);
+
224 QFETCH(int, status);
+
225 DecodeSignal signal;
+
226 signal.startBit = start;
+
227 signal.length = length;
+
228 signal.byteOrder = order == 0 ? ByteOrder::Intel : ByteOrder::Motorola;
+
229 const DecodeDatabase database = SingleSignal(signal);
+
230 RawCanFrame raw;
+
231 raw.canId = 17U;
+
232 raw.data.assign(bytes, 255U);
+
233 const DecodedFrameValue decoded = DbcDecoder().Decode(database, raw);
+
234 QVERIFY(decoded.valid);
+
235 QVERIFY(!decoded.signals[0].valid);
+
236 QCOMPARE(int(decoded.signals[0].status), status);
+
237 QVERIFY(decoded.signals[0].GetValueDescription() == nullptr);
+
238}
+
239
+
240void CoverageTest::malformedRuntimeMultiplexing_data() {
+
241 QTest::addColumn<int>("kind");
+
242 QTest::newRow("two-selectors") << 0;
+
243 QTest::newRow("signed-selector") << 1;
+
244 QTest::newRow("65-bit-selector") << 2;
+
245 QTest::newRow("branch-out-of-range") << 3;
+
246}
+
247
+
248void CoverageTest::malformedRuntimeMultiplexing() {
+
249 QFETCH(int, kind);
+
250 DecodeSignal selector;
+
251 selector.length = 1U;
+
252 selector.multiplexing.role = MultiplexRole::Selector;
+
253 selector.name = "Selector";
+
254 std::vector<DecodeFrame> definitions = SingleSignal(selector).GetFrames();
+
255 DecodeSignal branch;
+
256 branch.name = "Branch";
+
257 branch.startBit = 8U;
+
258 branch.length = 8U;
+
259 branch.multiplexing.role = MultiplexRole::Branch;
+
260 branch.multiplexing.value = 1U;
+
261 definitions[0].signals.push_back(branch);
+
262 DecodeSignal ordinary;
+
263 ordinary.name = "Ordinary";
+
264 ordinary.startBit = 16U;
+
265 ordinary.length = 8U;
+
266 definitions[0].signals.push_back(ordinary);
+
267 if (kind == 0) {
+
268 selector.name = "SecondSelector";
+
269 definitions[0].signals.push_back(selector);
+
270 }
+
271 if (kind == 1) definitions[0].signals[0].valueType = ValueType::Signed;
+
272 if (kind == 2) definitions[0].signals[0].length = 65U;
+
273 if (kind == 3) definitions[0].signals[1].multiplexing.value = 2U;
+
274 const DecodeDatabase database(std::move(definitions));
+
275 RawCanFrame raw;
+
276 raw.canId = 17U;
+
277 raw.data = {1U, 42U, 99U};
+
278 const DecodedFrameValue result = DbcDecoder().Decode(database, raw);
+
279 QCOMPARE(int(result.signals[1].status), int(SignalDecodeStatus::InvalidDefinition));
+
280 QVERIFY(!result.signals[1].valid);
+
281 QVERIFY(result.signals[2].valid);
+
282 QCOMPARE(std::get<std::uint64_t>(result.signals[2].rawValue), std::uint64_t(99));
+
283 if (kind != 3) {
+
284 QCOMPARE(int(result.signals[0].status), int(SignalDecodeStatus::InvalidDefinition));
+
285 if (kind == 0) QCOMPARE(int(result.signals[3].status), int(SignalDecodeStatus::InvalidDefinition));
+
286 }
+
287}
+
288
+
289void CoverageTest::pgn_data() {
+
290 QTest::addColumn<unsigned>("id");
+
291 QTest::addColumn<unsigned>("expected");
+
292 QTest::addColumn<bool>("hasPgn");
+
293 QTest::newRow("standard") << 0x7FFU << 0U << false;
+
294 for (unsigned dp: {0U, 1U})
+
295 for (unsigned pf: {239U, 240U})
+
296 for (unsigned ps: {0U, 0xABU}) {
+
297 const unsigned id = 0x80000000U | (dp << 24U) | (pf << 16U) | (ps << 8U) | 0x42U;
+
298 const unsigned expected = (dp << 16U) | (pf == 239U ? 0xEF00U : 0xF000U | ps);
+
299 const QByteArray name = QByteArray::number(dp) + "-" + QByteArray::number(pf) + "-" + QByteArray::number(ps);
+
300 QTest::newRow(name.constData()) << id << expected << true;
+
301 }
+
302}
+
303
+
304void CoverageTest::pgn() {
+
305 QFETCH(unsigned, id);
+
306 QFETCH(unsigned, expected);
+
307 QFETCH(bool, hasPgn);
+
308 const DbcDatabase parsed = ParseText("BO_ " + std::to_string(id) + " Frame: 8 ECU\n");
+
309 QCOMPARE(parsed.frames[0].hasPgn, hasPgn);
+
310 QCOMPARE(parsed.frames[0].pgn, expected);
+
311}
+
312
+
313void CoverageTest::comments_data() {
+
314 QTest::addColumn<QString>("before");
+
315 QTest::addColumn<QString>("after");
+
316 QTest::addColumn<QString>("frameComment");
+
317 QTest::addColumn<QString>("signalComment");
+
318 QTest::newRow("tabs") << QString::fromUtf8("") << QString::fromUtf8("CM_\tBO_ 1 \"Frame\";\nCM_\tSG_ 1 State \"Signal\";\n") << QString::fromUtf8("Frame") << QString::fromUtf8("Signal");
+
319 QTest::newRow("empty-overwrite") << QString::fromUtf8("") << QString::fromUtf8("CM_ BO_ 1 \"Old\";\nCM_ BO_ 1 \"\";\nCM_ SG_ 1 State \"Old\";\nCM_ SG_ 1 State \"\";\n") << QString::fromUtf8("") << QString::fromUtf8("");
+
320 QTest::newRow("last-wins") << QString::fromUtf8("") << QString::fromUtf8("CM_ BO_ 1 \"First\";\nCM_ BO_ 1 \"Last\";\nCM_ SG_ 1 State \"First\";\nCM_ SG_ 1 State \"Last\";\n") << QString::fromUtf8("Last") << QString::fromUtf8("Last");
+
321 QTest::newRow("missing-targets") << QString::fromUtf8("") << QString::fromUtf8("CM_ BO_ 2 \"Unknown\";\nCM_ SG_ 2 State \"Unknown\";\nCM_ SG_ 1 Missing \"Unknown\";\n") << QString::fromUtf8("") << QString::fromUtf8("");
+
322 // Current documented limitation: comments resolve only already parsed targets.
+
323 QTest::newRow("before-definitions") << QString::fromUtf8("CM_ BO_ 1 \"Early\";\nCM_ SG_ 1 State \"Early\";\n") << QString::fromUtf8("") << QString::fromUtf8("") << QString::fromUtf8("");
+
324 QTest::newRow("missing-quotes") << QString::fromUtf8("") << QString::fromUtf8("CM_ BO_ 1 Missing;\nCM_ SG_ 1 State \"Unclosed;\n") << QString::fromUtf8("") << QString::fromUtf8("");
+
325}
+
326
+
327void CoverageTest::comments() {
+
328 QFETCH(QString, before);
+
329 QFETCH(QString, after);
+
330 QFETCH(QString, frameComment);
+
331 QFETCH(QString, signalComment);
+
332 const DbcDatabase parsed = ParseText(before.toStdString() + "BO_ 1 Frame: 1 ECU\nSG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n" + after.toStdString());
+
333 QCOMPARE(parsed.frames[0].comment, frameComment.toStdString());
+
334 QCOMPARE(parsed.frames[0].signals[0].comment, signalComment.toStdString());
+
335}
+
336
+
337void CoverageTest::ignoredCommentStatements_data() {
+
338 QTest::addColumn<QString>("statement");
+
339 QTest::newRow("empty") << QString();
+
340 QTest::newRow("wrong-keyword") << QStringLiteral("OTHER_ BO_ 1 \"Ignored\";");
+
341 QTest::newRow("keyword-prefix") << QStringLiteral("CM_OTHER BO_ 1 \"Ignored\";");
+
342 QTest::newRow("frame-without-cm") << QStringLiteral("BO_ 1 \"Ignored\";");
+
343 QTest::newRow("missing-subtype") << QStringLiteral("CM_");
+
344 QTest::newRow("global-comment") << QStringLiteral("CM_ \"Ignored\";");
+
345 QTest::newRow("node-comment") << QStringLiteral("CM_ BU_ ECU \"Ignored\";");
+
346 QTest::newRow("environment-comment") << QStringLiteral("CM_ EV_ State \"Ignored\";");
+
347 QTest::newRow("unknown-subtype") << QStringLiteral("CM_ OTHER_ 1 \"Ignored\";");
+
348}
+
349
+
350void CoverageTest::ignoredCommentStatements() {
+
351 QFETCH(QString, statement);
+
352 DbcDatabase database;
+
353 FrameInfo frame;
+
354 frame.canId = 1U;
+
355 frame.name = "Frame";
+
356 frame.comment = "Existing frame comment";
+
357 SignalInfo signal;
+
358 signal.name = "State";
+
359 signal.comment = "Existing signal comment";
+
360 frame.signals.push_back(signal);
+
361 database.frames.push_back(frame);
+
362 DbcParseContext context{database, &database.frames[0]};
+
363
+
364 // The handler is public: callers may bypass keyword dispatch. Ignored input
+
365 // must preserve existing metadata, including comments already assigned.
+
366 DbcCommentHandler().Handle(statement.toStdString(), context);
+
367 QCOMPARE(database.frames.size(), std::size_t(1));
+
368 QCOMPARE(database.frames[0].canId, 1U);
+
369 QCOMPARE(database.frames[0].name, frame.name);
+
370 QCOMPARE(database.frames[0].comment, frame.comment);
+
371 QCOMPARE(database.frames[0].signals.size(), std::size_t(1));
+
372 QCOMPARE(database.frames[0].signals[0].name, signal.name);
+
373 QCOMPARE(database.frames[0].signals[0].comment, signal.comment);
+
374 QCOMPARE(context.currentFrame, &database.frames[0]);
+
375}
+
376
+
377void CoverageTest::ambiguousValueReferences_data() {
+
378 QTest::addColumn<bool>("duplicateFrames");
+
379 QTest::addColumn<bool>("extended");
+
380 QTest::newRow("duplicate-standard-frames") << true << false;
+
381 QTest::newRow("duplicate-extended-frames") << true << true;
+
382 QTest::newRow("duplicate-signals-in-standard-frame") << false << false;
+
383 QTest::newRow("duplicate-signals-in-extended-frame") << false << true;
+
384}
+
385
+
386void CoverageTest::ambiguousValueReferences() {
+
387 QFETCH(bool, duplicateFrames);
+
388 QFETCH(bool, extended);
+
389 DbcDatabase database;
+
390 FrameInfo frame;
+
391 frame.canId = 1U;
+
392 frame.name = "Frame";
+
393 frame.isExtended = extended;
+
394 SignalInfo signal;
+
395 signal.name = "State";
+
396 frame.signals.push_back(signal);
+
397 if (!duplicateFrames) frame.signals.push_back(signal);
+
398 database.frames.push_back(frame);
+
399 if (duplicateFrames) database.frames.push_back(frame);
+
400
+
401 // ParseFile rejects duplicate definitions earlier. Construct the database
+
402 // through the public metadata API to exercise the resolver's own checks.
+
403 DbcParseContext context{database, nullptr};
+
404 context.lineNumber = 37U;
+
405 const std::string rawId = extended ? "2147483649" : "1";
+
406 DbcValueDescriptionHandler().Handle("VAL_ " + rawId + " State 0 \"Off\";", context);
+
407 QCOMPARE(context.pendingValues.size(), std::size_t(1));
+
408 QCOMPARE(context.pendingValues[0].lineNumber, std::size_t(37));
+
409 const std::string path = "manual database.dbc";
+
410 try {
+
411 context.ResolveValueDescriptions(path);
+
412 QFAIL("The resolver must reject an ambiguous target");
+
413 } catch (const std::runtime_error &error) {
+
414 const std::string message = duplicateFrames ? "Ambiguous VAL_ frame reference."
+
415 : "Ambiguous VAL_ signal reference: State";
+
416 QCOMPARE(std::string(error.what()), path + ":37: " + message);
+
417 }
+
418 // Ambiguity must be detected before applying any descriptions.
+
419 for (const FrameInfo &candidate: database.frames)
+
420 for (const SignalInfo &candidateSignal: candidate.signals)
+
421 QVERIFY(candidateSignal.valueDescriptions.empty());
+
422}
+
423
+
424void CoverageTest::valueReferenceScope() {
+
425 DbcDatabase database;
+
426 FrameInfo frame;
+
427 frame.canId = 1U;
+
428 SignalInfo signal;
+
429 signal.name = "State";
+
430 frame.signals.push_back(signal);
431 database.frames.push_back(frame);
-
432 frame.canId = 2U;
-
433 frame.isExtended = false;
-
434 database.frames.push_back(frame);
-
435
-
436 DbcParseContext context{database, nullptr};
-
437 const DbcValueDescriptionHandler handler;
-
438 context.lineNumber = 3U;
-
439 handler.Handle("VAL_ 1 State 0 \"Standard\";", context);
-
440 context.lineNumber = 7U;
-
441 handler.Handle("VAL_ 2147483649 State 0 \"Extended\";", context);
-
442 context.ResolveValueDescriptions("manual database.dbc");
-
443
-
444 const std::string *standard = FindValueDescription(database.frames[0].signals[0].valueDescriptions, std::uint64_t(0));
-
445 const std::string *extended = FindValueDescription(database.frames[1].signals[0].valueDescriptions, std::uint64_t(0));
-
446 QVERIFY(standard != nullptr);
-
447 QVERIFY(extended != nullptr);
-
448 QCOMPARE(*standard, std::string("Standard"));
-
449 QCOMPARE(*extended, std::string("Extended"));
-
450 QVERIFY(database.frames[2].signals[0].valueDescriptions.empty());
-
451}
-
452
-
453void CoverageTest::fileFormatting_data() {
-
454 QTest::addColumn<QString>("text");
-
455 QTest::addColumn<unsigned>("frames");
-
456 QTest::newRow("empty") << QString::fromUtf8("") << 0U;
-
457 QTest::newRow("whitespace") << QString::fromUtf8(" \t\r\n\n\t") << 0U;
-
458 QTest::newRow("unknown-only") << QString::fromUtf8("VERSION \"test\"\nBU_: ECU\nUNKNOWN_ data\n") << 0U;
-
459 QTest::newRow("no-final-newline") << QString::fromUtf8("BO_ 1 Frame: 1 ECU\nSG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU") << 1U;
-
460 QTest::newRow("crlf") << QString::fromUtf8("\r\nBO_ 1 Frame: 1 ECU\r\nSG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\r\nCM_ BO_ 1 \"Comment\";\r\nVAL_ 1 State 0 \"Off\";\r\n") << 1U;
-
461}
-
462
-
463void CoverageTest::fileFormatting() {
-
464 QFETCH(QString, text);
-
465 QFETCH(unsigned, frames);
-
466 const DbcDatabase parsed = ParseText(text.toStdString());
-
467 QCOMPARE(parsed.frames.size(), std::size_t(frames));
-
468 if (frames) {
-
469 QCOMPARE(parsed.frames[0].signals.size(), std::size_t(1));
-
470 if (text.contains("\r\nBO_")) {
-
471 QCOMPARE(parsed.frames[0].comment, std::string("Comment"));
-
472 const std::string *description = FindValueDescription(parsed.frames[0].signals[0].valueDescriptions, std::uint64_t(0));
-
473 QVERIFY(description != nullptr);
-
474 QCOMPARE(*description, std::string("Off"));
-
475 }
-
476 }
-
477}
-
478
-
479void CoverageTest::missingFile() {
-
480 QTemporaryFile file;
-
481 QVERIFY(file.open());
-
482 const QString path = file.fileName();
-
483 QVERIFY(file.remove());
-
484 try {
-
485 DbcParser().ParseFile(path.toStdString());
-
486 QFAIL("Missing file must throw");
-
487 } catch (const std::runtime_error &error) {
-
488 QCOMPARE(std::string(error.what()), "Failed to open DBC file: " + path.toStdString());
-
489 }
-
490}
-
491
-
492void CoverageTest::builders() {
-
493 const DecodeDatabase emptyRuntime = DbcDecodeBuilder().Build(DbcDatabase());
-
494 QVERIFY(emptyRuntime.frames.empty());
-
495 QVERIFY(emptyRuntime.frameIndexByKey.empty());
-
496 const std::unique_ptr<TreeNode> emptyTree = DbcTreeBuilder().Build(DbcDatabase());
-
497 QCOMPARE(emptyTree->GetType(), NodeType::Root);
-
498 QCOMPARE(emptyTree->GetName(), std::string("dbc"));
-
499 QCOMPARE(emptyTree->GetChildCount(), std::size_t(0));
-
500 QVERIFY(emptyTree->GetFrame() == nullptr && emptyTree->GetSignal() == nullptr);
-
501 const DbcDatabase expected = ParseText(
-
502 "BO_ 256 Standard: 3 ECU1\n"
-
503 "SG_ Mode M : 0|8@1+ (2,3) [0|513] \"mode\" ECU1,ECU2\n"
-
504 "SG_ Branch m1 : 15|8@0- (-2,5) [-249|261] \"rpm\" ECU2,ECU3\n"
-
505 "SG_ Always : 16|8@1+ (0.25,-1) [-1|62.75] \"V\" ECU3\n"
-
506 "CM_ BO_ 256 \"Frame comment\";\nCM_ SG_ 256 Branch \"Branch comment\";\n"
-
507 "VAL_ 256 Branch -1 \"Negative\" 1 \"Positive\";\n"
-
508 "BO_ 2163212866 Extended: 8 ECU4\n");
-
509 DecodeDatabase runtime;
-
510 std::unique_ptr<TreeNode> tree;
-
511 {
-
512 DbcDatabase source = expected;
-
513 runtime = DbcDecodeBuilder().Build(source);
-
514 tree = DbcTreeBuilder().Build(source);
-
515 source.frames[0].name = "Changed";
-
516 source.frames[0].signals[1].receivers.clear();
-
517 source.frames[0].signals[1].valueDescriptions.clear();
-
518 source.frames.clear();
-
519 }
-
520 QCOMPARE(runtime.frames.size(), expected.frames.size());
-
521 QCOMPARE(tree->GetChildCount(), expected.frames.size());
-
522 QCOMPARE(runtime.frameIndexByKey.size(), expected.frames.size());
-
523 for (std::size_t i = 0; i < expected.frames.size(); ++i) {
-
524 const FrameInfo &frame = expected.frames[i];
-
525 const DecodeFrame &decodedFrame = runtime.frames[i];
-
526 const TreeNode *node = tree->GetChild(i);
-
527 QVERIFY(node && node->GetFrame());
-
528 QCOMPARE(node->GetType(), NodeType::Frame);
-
529 QCOMPARE(node->GetName(), frame.name);
-
530 QVERIFY(node->GetSignal() == nullptr);
-
531 QCOMPARE(runtime.frameIndexByKey.at(FrameKey(frame.canId, frame.isExtended)), i);
-
532 const FrameInfo &copied = *node->GetFrame();
-
533 QCOMPARE(copied.name, frame.name);
-
534 QCOMPARE(decodedFrame.name, frame.name);
-
535 QCOMPARE(copied.canId, frame.canId);
-
536 QCOMPARE(decodedFrame.canId, frame.canId);
-
537 QCOMPARE(copied.isExtended, frame.isExtended);
-
538 QCOMPARE(decodedFrame.isExtended, frame.isExtended);
-
539 QCOMPARE(copied.dlc, frame.dlc);
-
540 QCOMPARE(decodedFrame.dlc, frame.dlc);
-
541 QCOMPARE(copied.pgn, frame.pgn);
-
542 QCOMPARE(decodedFrame.pgn, frame.pgn);
-
543 QCOMPARE(copied.hasPgn, frame.hasPgn);
-
544 QCOMPARE(decodedFrame.hasPgn, frame.hasPgn);
-
545 QCOMPARE(copied.transmitter, frame.transmitter);
-
546 QCOMPARE(decodedFrame.transmitter, frame.transmitter);
-
547 QCOMPARE(copied.comment, frame.comment);
-
548 QCOMPARE(decodedFrame.comment, frame.comment);
-
549 QCOMPARE(node->GetChildCount(), frame.signals.size());
-
550 QCOMPARE(copied.signals.size(), frame.signals.size());
-
551 QCOMPARE(decodedFrame.signals.size(), frame.signals.size());
-
552 for (std::size_t j = 0; j < frame.signals.size(); ++j) {
-
553 const SignalInfo &original = frame.signals[j];
-
554 const DecodeSignal &target = decodedFrame.signals[j];
-
555 const TreeNode *leaf = node->GetChild(j);
-
556 QVERIFY(leaf && leaf->GetSignal());
-
557 QCOMPARE(leaf->GetType(), NodeType::Signal);
-
558 QCOMPARE(leaf->GetName(), original.name);
-
559 QVERIFY(leaf->GetFrame() == nullptr);
-
560 // Check both the frame payload copy and each child payload copy.
-
561 for (const SignalInfo *copy: {&copied.signals[j], leaf->GetSignal()}) {
-
562 QCOMPARE(copy->name, original.name);
-
563 QCOMPARE(copy->startBit, original.startBit);
-
564 QCOMPARE(copy->length, original.length);
-
565 QCOMPARE(copy->isLittleEndian, original.isLittleEndian);
-
566 QCOMPARE(copy->isSigned, original.isSigned);
-
567 QCOMPARE(copy->factor, original.factor);
-
568 QCOMPARE(copy->offset, original.offset);
-
569 QCOMPARE(copy->minimum, original.minimum);
-
570 QCOMPARE(copy->maximum, original.maximum);
-
571 QCOMPARE(copy->unit, original.unit);
-
572 QCOMPARE(copy->comment, original.comment);
-
573 QVERIFY(copy->receivers == original.receivers);
-
574 QVERIFY(copy->valueDescriptions == original.valueDescriptions);
-
575 QCOMPARE(copy->multiplexing.role, original.multiplexing.role);
-
576 QCOMPARE(copy->multiplexing.value, original.multiplexing.value);
-
577 }
-
578 QCOMPARE(target.name, original.name);
-
579 QCOMPARE(target.startBit, original.startBit);
-
580 QCOMPARE(target.length, original.length);
-
581 QCOMPARE(target.byteOrder, original.isLittleEndian ? ByteOrder::Intel : ByteOrder::Motorola);
-
582 QCOMPARE(target.valueType, original.isSigned ? ValueType::Signed : ValueType::Unsigned);
-
583 QCOMPARE(target.factor, original.factor);
-
584 QCOMPARE(target.offset, original.offset);
-
585 QCOMPARE(target.minimum, original.minimum);
-
586 QCOMPARE(target.maximum, original.maximum);
-
587 QCOMPARE(target.unit, original.unit);
-
588 QCOMPARE(target.comment, original.comment);
-
589 QVERIFY(target.receivers == original.receivers);
-
590 QVERIFY(target.valueDescriptions == original.valueDescriptions);
-
591 QCOMPARE(target.multiplexing.role, original.multiplexing.role);
-
592 QCOMPARE(target.multiplexing.value, original.multiplexing.value);
-
593 }
-
594 }
-
595}
-
596
-
597void CoverageTest::physicalConversion_data() {
-
598 QTest::addColumn<double>("factor");
-
599 QTest::addColumn<double>("offset");
-
600 QTest::addColumn<double>("expected");
-
601 QTest::newRow("zero-factor") << 0.0 << 7.0 << 7.0;
-
602 QTest::newRow("negative-factor") << -2.0 << 5.0 << -15.0;
-
603 QTest::newRow("above-declared-range") << 2.0 << 3.0 << 23.0;
-
604}
-
605
-
606void CoverageTest::physicalConversion() {
-
607 QFETCH(double, factor);
-
608 QFETCH(double, offset);
-
609 QFETCH(double, expected);
-
610 DecodeSignal signal;
-
611 signal.length = 8U;
-
612 signal.factor = factor;
-
613 signal.offset = offset;
-
614 signal.minimum = 0.0;
-
615 signal.maximum = 1.0;
-
616 const DecodeDatabase database = SingleSignal(signal);
-
617 RawCanFrame raw;
-
618 raw.canId = 17U;
-
619 raw.data = {10U};
-
620 const DecodedFrameValue decoded = DbcDecoder().Decode(database, raw);
-
621 QVERIFY(decoded.signals[0].valid);
-
622 QCOMPARE(std::get<std::uint64_t>(decoded.signals[0].rawValue), std::uint64_t(10));
-
623 QCOMPARE(decoded.signals[0].physicalValue, expected);
-
624}
-
625
-
626void CoverageTest::multiplexingScenarios() {
-
627 const DecodeDatabase selectorOnly = DbcDecodeBuilder().Build(ParseText(
-
628 "BO_ 1 Frame: 1 ECU\nSG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n"));
-
629 RawCanFrame raw;
-
630 raw.canId = 1U;
-
631 raw.data = {1U};
-
632 const DecodedFrameValue only = DbcDecoder().Decode(selectorOnly, raw);
-
633 QCOMPARE(only.signals.size(), std::size_t(1));
-
634 QVERIFY(only.signals[0].valid);
-
635 const DecodeDatabase database = DbcDecodeBuilder().Build(ParseText(
-
636 "BO_ 1 First: 3 ECU\n"
-
637 "SG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n"
-
638 "SG_ A m0 : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
-
639 "SG_ B m0 : 16|8@1+ (1,0) [0|255] \"\" ECU\n"
-
640 "BO_ 2 Second: 2 ECU\n"
-
641 "SG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n"
-
642 "SG_ A m1 : 8|8@1+ (1,0) [0|255] \"\" ECU\n"));
-
643 raw.data = {0U, 42U, 99U};
-
644 const DecodedFrameValue first = DbcDecoder().Decode(database, raw);
-
645 QVERIFY(first.signals[1].valid && first.signals[2].valid);
-
646 QCOMPARE(std::get<std::uint64_t>(first.signals[1].rawValue), std::uint64_t(42));
-
647 QCOMPARE(std::get<std::uint64_t>(first.signals[2].rawValue), std::uint64_t(99));
-
648 raw.canId = 2U;
-
649 const DecodedFrameValue secondInactive = DbcDecoder().Decode(database, raw);
-
650 QCOMPARE(secondInactive.signals[1].status, SignalDecodeStatus::Inactive);
-
651 raw.data[0] = 1U;
-
652 QVERIFY(DbcDecoder().Decode(database, raw).signals[1].valid);
-
653 raw.canId = 1U;
-
654 const DecodedFrameValue firstInactive = DbcDecoder().Decode(database, raw);
-
655 QCOMPARE(firstInactive.signals[1].status, SignalDecodeStatus::Inactive);
-
656 QCOMPARE(firstInactive.signals[2].status, SignalDecodeStatus::Inactive);
-
657}
-
658
-
659void CoverageTest::multiplexingErrorLocations_data() {
-
660 QTest::addColumn<QString>("text");
-
661 QTest::addColumn<unsigned>("line");
-
662 QTest::addColumn<QString>("message");
-
663 const QString header = "BO_ 1 Frame: 3 ECU\n\n";
-
664 const QString selector = "SG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n";
-
665 const QString branch = "SG_ A m1 : 8|8@1+ (1,0) [0|255] \"\" ECU\n";
-
666 QTest::newRow("missing-selector") << header + branch << 3U << QString::fromUtf8("Multiplexed branch has no selector.");
-
667 QTest::newRow("second-selector") << header + selector + "\nSG_ Other M : 16|1@1+ (1,0) [0|1] \"\" ECU\n"
-
668 << 5U << QString::fromUtf8("Multiplexing requires one unsigned selector per frame.");
-
669 QTest::newRow("signed-selector") << header + "SG_ Mode M : 0|1@1- (1,0) [-1|0] \"\" ECU\n"
-
670 << 3U << QString::fromUtf8("Multiplexing requires one unsigned selector per frame.");
-
671 QTest::newRow("branch-range") << header + "SG_ A m2 : 8|8@1+ (1,0) [0|255] \"\" ECU\n" + selector << 3U << QString::fromUtf8("Branch value exceeds selector raw range.");
-
672 QTest::newRow("same-branch-overlap") << header + selector + branch + "SG_ B m1 : 15|8@0+ (1,0) [0|255] \"\" ECU\n"
-
673 << 5U << QString::fromUtf8("Signals overlap without mutually exclusive multiplexing conditions.");
-
674 QTest::newRow("selector-overlap") << header + selector + "SG_ A m1 : 0|1@1+ (1,0) [0|1] \"\" ECU\n"
-
675 << 4U << QString::fromUtf8("Signals overlap without mutually exclusive multiplexing conditions.");
-
676 QTest::newRow("unconditional-overlap") << header + selector + branch + "SG_ Always : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
-
677 << 5U << QString::fromUtf8("Signals overlap without mutually exclusive multiplexing conditions.");
-
678 QTest::newRow("ordinary-overlap") << header + "SG_ A : 8|8@1+ (1,0) [0|255] \"\" ECU\nSG_ B : 15|8@0+ (1,0) [0|255] \"\" ECU\n"
-
679 << 4U << QString::fromUtf8("Signals overlap without mutually exclusive multiplexing conditions.");
-
680 QTest::newRow("extended-multiplexing") << header + "SG_MUL_VAL_ 1 A Mode 1-2;\n"
-
681 << 3U << QString::fromUtf8("Extended and nested multiplexing are unsupported.");
-
682 QTest::newRow("nested-marker") << header + "SG_ A m1M : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
-
683 << 3U << QString::fromUtf8("Invalid or unsupported multiplexing marker.");
-
684}
-
685
-
686void CoverageTest::multiplexingErrorLocations() {
-
687 QFETCH(QString, text);
-
688 QFETCH(unsigned, line);
-
689 QFETCH(QString, message);
-
690 QTemporaryFile file;
-
691 QVERIFY(file.open());
-
692 const QByteArray content = text.toUtf8();
-
693 QCOMPARE(file.write(content), qint64(content.size()));
-
694 QVERIFY(file.flush());
-
695 try {
-
696 DbcParser().ParseFile(file.fileName().toStdString());
-
697 QFAIL("Expected multiplexing rejection");
-
698 } catch (const std::runtime_error &error) {
-
699 QCOMPARE(QString::fromStdString(error.what()), file.fileName() + ":" + QString::number(line) + ": " + message);
-
700 }
-
701}
-
702
-
703void CoverageTest::escapedValueDescriptions() {
-
704 const DbcDatabase parsed = ParseText(
-
705 "BO_ 1 Frame: 1 ECU\nSG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
-
706 R"dbc(VAL_ 1 State -0 "Ноль" 1 "C:\\trace" 2 "\\\"quoted\"\\";)dbc"
-
707 "\n");
-
708 const ValueDescriptions &values = parsed.frames[0].signals[0].valueDescriptions;
-
709 QCOMPARE(values.size(), std::size_t(3));
-
710 QVERIFY(values.find(RawSignalValue(std::int64_t(0))) == values.end());
-
711 const std::string *zero = FindValueDescription(values, std::int64_t(0));
-
712 const std::string *path = FindValueDescription(values, std::uint64_t(1));
-
713 const std::string *quoted = FindValueDescription(values, std::uint64_t(2));
-
714 QVERIFY(zero && path && quoted);
-
715 QCOMPARE(*zero, std::string("Ноль"));
-
716 QCOMPARE(*path, std::string("C:\\trace"));
-
717 QCOMPARE(*quoted, std::string("\\\"quoted\"\\"));
-
718 QVERIFY(NormalizeValueKey(RawSignalValue(std::int64_t(0))) == RawSignalValue(std::uint64_t(0)));
-
719 QVERIFY(NormalizeValueKey(RawSignalValue(std::int64_t(-1))) == RawSignalValue(std::int64_t(-1)));
-
720}
-
721
-
722void CoverageTest::factory() {
- -
724 QVERIFY(!factory.contains("value"));
-
725 QVERIFY_THROWS_EXCEPTION(std::out_of_range, static_cast<void>(factory.creator("missing")));
-
726 QVERIFY_THROWS_EXCEPTION(std::out_of_range, static_cast<void>(factory.create("missing", std::make_unique<int>(1))));
-
727 factory.registerType<FactoryFirst>("value");
-
728 QVERIFY(factory.contains("value"));
-
729 std::unique_ptr<int> argument = std::make_unique<int>(42);
-
730 const std::shared_ptr<FactoryBase> first = factory.create("value", std::move(argument));
-
731 QVERIFY(argument == nullptr);
-
732 QCOMPARE(first->Value(), 42);
-
733 const TypeFactory<std::string, FactoryBase, std::unique_ptr<int>>::CreatorFn creator = factory.creator("value");
-
734 QCOMPARE(creator(std::make_unique<int>(7))->Value(), 7);
-
735 factory.registerType<FactorySecond>("value");
-
736 QCOMPARE(factory.create("value", std::make_unique<int>(42))->Value(), 43);
-
737 QCOMPARE(first->Value(), 42);
-
738 QCOMPARE(creator(std::make_unique<int>(7))->Value(), 7);
-
739}
-
740
-
741int RunCoverageTests(int argc, char **argv) {
-
742 CoverageTest tests;
-
743 return QTest::qExec(&tests, argc, argv);
-
744}
-
745#include "dbc_coverage_test.moc"
+
432 frame.isExtended = true;
+
433 database.frames.push_back(frame);
+
434 frame.canId = 2U;
+
435 frame.isExtended = false;
+
436 database.frames.push_back(frame);
+
437
+
438 DbcParseContext context{database, nullptr};
+
439 const DbcValueDescriptionHandler handler;
+
440 context.lineNumber = 3U;
+
441 handler.Handle("VAL_ 1 State 0 \"Standard\";", context);
+
442 context.lineNumber = 7U;
+
443 handler.Handle("VAL_ 2147483649 State 0 \"Extended\";", context);
+
444 context.ResolveValueDescriptions("manual database.dbc");
+
445
+
446 const std::string *standard = FindValueDescription(database.frames[0].signals[0].valueDescriptions, std::uint64_t(0));
+
447 const std::string *extended = FindValueDescription(database.frames[1].signals[0].valueDescriptions, std::uint64_t(0));
+
448 QVERIFY(standard != nullptr);
+
449 QVERIFY(extended != nullptr);
+
450 QCOMPARE(*standard, std::string("Standard"));
+
451 QCOMPARE(*extended, std::string("Extended"));
+
452 QVERIFY(database.frames[2].signals[0].valueDescriptions.empty());
+
453}
+
454
+
455void CoverageTest::fileFormatting_data() {
+
456 QTest::addColumn<QString>("text");
+
457 QTest::addColumn<unsigned>("frames");
+
458 QTest::newRow("empty") << QString::fromUtf8("") << 0U;
+
459 QTest::newRow("whitespace") << QString::fromUtf8(" \t\r\n\n\t") << 0U;
+
460 QTest::newRow("unknown-only") << QString::fromUtf8("VERSION \"test\"\nBU_: ECU\nUNKNOWN_ data\n") << 0U;
+
461 QTest::newRow("no-final-newline") << QString::fromUtf8("BO_ 1 Frame: 1 ECU\nSG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU") << 1U;
+
462 QTest::newRow("crlf") << QString::fromUtf8("\r\nBO_ 1 Frame: 1 ECU\r\nSG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\r\nCM_ BO_ 1 \"Comment\";\r\nVAL_ 1 State 0 \"Off\";\r\n") << 1U;
+
463}
+
464
+
465void CoverageTest::fileFormatting() {
+
466 QFETCH(QString, text);
+
467 QFETCH(unsigned, frames);
+
468 const DbcDatabase parsed = ParseText(text.toStdString());
+
469 QCOMPARE(parsed.frames.size(), std::size_t(frames));
+
470 if (frames) {
+
471 QCOMPARE(parsed.frames[0].signals.size(), std::size_t(1));
+
472 if (text.contains("\r\nBO_")) {
+
473 QCOMPARE(parsed.frames[0].comment, std::string("Comment"));
+
474 const std::string *description = FindValueDescription(parsed.frames[0].signals[0].valueDescriptions, std::uint64_t(0));
+
475 QVERIFY(description != nullptr);
+
476 QCOMPARE(*description, std::string("Off"));
+
477 }
+
478 }
+
479}
+
480
+
481void CoverageTest::missingFile() {
+
482 QTemporaryFile file;
+
483 QVERIFY(file.open());
+
484 const QString path = file.fileName();
+
485 QVERIFY(file.remove());
+
486 try {
+
487 DbcParser().ParseFile(path.toStdString());
+
488 QFAIL("Missing file must throw");
+
489 } catch (const std::runtime_error &error) {
+
490 QCOMPARE(std::string(error.what()), "Failed to open DBC file: " + path.toStdString());
+
491 }
+
492}
+
493
+
494void CoverageTest::builders() {
+
495 const DecodeDatabase emptyRuntime = DbcDecodeBuilder().Build(DbcDatabase());
+
496 QVERIFY(emptyRuntime.GetFrames().empty());
+
497 QVERIFY(!emptyRuntime.FindFrame(FrameKey(0U, false)));
+
498 const std::unique_ptr<TreeNode> emptyTree = DbcTreeBuilder().Build(DbcDatabase());
+
499 QCOMPARE(emptyTree->GetType(), NodeType::Root);
+
500 QCOMPARE(emptyTree->GetName(), std::string("dbc"));
+
501 QCOMPARE(emptyTree->GetChildCount(), std::size_t(0));
+
502 QVERIFY(emptyTree->GetFrame() == nullptr && emptyTree->GetSignal() == nullptr);
+
503 const DbcDatabase expected = ParseText(
+
504 "BO_ 256 Standard: 3 ECU1\n"
+
505 "SG_ Mode M : 0|8@1+ (2,3) [0|513] \"mode\" ECU1,ECU2\n"
+
506 "SG_ Branch m1 : 15|8@0- (-2,5) [-249|261] \"rpm\" ECU2,ECU3\n"
+
507 "SG_ Always : 16|8@1+ (0.25,-1) [-1|62.75] \"V\" ECU3\n"
+
508 "CM_ BO_ 256 \"Frame comment\";\nCM_ SG_ 256 Branch \"Branch comment\";\n"
+
509 "VAL_ 256 Branch -1 \"Negative\" 1 \"Positive\";\n"
+
510 "BO_ 2163212866 Extended: 8 ECU4\n");
+
511 DecodeDatabase runtime;
+
512 std::unique_ptr<TreeNode> tree;
+
513 {
+
514 DbcDatabase source = expected;
+
515 runtime = DbcDecodeBuilder().Build(source);
+
516 tree = DbcTreeBuilder().Build(source);
+
517 source.frames[0].name = "Changed";
+
518 source.frames[0].signals[1].receivers.clear();
+
519 source.frames[0].signals[1].valueDescriptions.clear();
+
520 source.frames.clear();
+
521 }
+
522 QCOMPARE(runtime.GetFrames().size(), expected.frames.size());
+
523 QCOMPARE(tree->GetChildCount(), expected.frames.size());
+
524 for (std::size_t i = 0; i < expected.frames.size(); ++i) {
+
525 const FrameInfo &frame = expected.frames[i];
+
526 const DecodeFrame &decodedFrame = runtime.GetFrames()[i];
+
527 const TreeNode *node = tree->GetChild(i);
+
528 QVERIFY(node && node->GetFrame());
+
529 QCOMPARE(node->GetType(), NodeType::Frame);
+
530 QCOMPARE(node->GetName(), frame.name);
+
531 QVERIFY(node->GetSignal() == nullptr);
+
532 QCOMPARE(runtime.FindFrame(FrameKey(frame.canId, frame.isExtended)).get(), &decodedFrame);
+
533 const FrameInfo &copied = *node->GetFrame();
+
534 QCOMPARE(copied.name, frame.name);
+
535 QCOMPARE(decodedFrame.name, frame.name);
+
536 QCOMPARE(copied.canId, frame.canId);
+
537 QCOMPARE(decodedFrame.canId, frame.canId);
+
538 QCOMPARE(copied.isExtended, frame.isExtended);
+
539 QCOMPARE(decodedFrame.isExtended, frame.isExtended);
+
540 QCOMPARE(copied.dlc, frame.dlc);
+
541 QCOMPARE(decodedFrame.dlc, frame.dlc);
+
542 QCOMPARE(copied.pgn, frame.pgn);
+
543 QCOMPARE(decodedFrame.pgn, frame.pgn);
+
544 QCOMPARE(copied.hasPgn, frame.hasPgn);
+
545 QCOMPARE(decodedFrame.hasPgn, frame.hasPgn);
+
546 QCOMPARE(copied.transmitter, frame.transmitter);
+
547 QCOMPARE(decodedFrame.transmitter, frame.transmitter);
+
548 QCOMPARE(copied.comment, frame.comment);
+
549 QCOMPARE(decodedFrame.comment, frame.comment);
+
550 QCOMPARE(node->GetChildCount(), frame.signals.size());
+
551 QCOMPARE(copied.signals.size(), frame.signals.size());
+
552 QCOMPARE(decodedFrame.signals.size(), frame.signals.size());
+
553 for (std::size_t j = 0; j < frame.signals.size(); ++j) {
+
554 const SignalInfo &original = frame.signals[j];
+
555 const DecodeSignal &target = decodedFrame.signals[j];
+
556 const TreeNode *leaf = node->GetChild(j);
+
557 QVERIFY(leaf && leaf->GetSignal());
+
558 QCOMPARE(leaf->GetType(), NodeType::Signal);
+
559 QCOMPARE(leaf->GetName(), original.name);
+
560 QVERIFY(leaf->GetFrame() == nullptr);
+
561 // Check both the frame payload copy and each child payload copy.
+
562 for (const SignalInfo *copy: {&copied.signals[j], leaf->GetSignal()}) {
+
563 QCOMPARE(copy->name, original.name);
+
564 QCOMPARE(copy->startBit, original.startBit);
+
565 QCOMPARE(copy->length, original.length);
+
566 QCOMPARE(copy->isLittleEndian, original.isLittleEndian);
+
567 QCOMPARE(copy->isSigned, original.isSigned);
+
568 QCOMPARE(copy->factor, original.factor);
+
569 QCOMPARE(copy->offset, original.offset);
+
570 QCOMPARE(copy->minimum, original.minimum);
+
571 QCOMPARE(copy->maximum, original.maximum);
+
572 QCOMPARE(copy->unit, original.unit);
+
573 QCOMPARE(copy->comment, original.comment);
+
574 QVERIFY(copy->receivers == original.receivers);
+
575 QVERIFY(copy->valueDescriptions == original.valueDescriptions);
+
576 QCOMPARE(copy->multiplexing.role, original.multiplexing.role);
+
577 QCOMPARE(copy->multiplexing.value, original.multiplexing.value);
+
578 }
+
579 QCOMPARE(target.name, original.name);
+
580 QCOMPARE(target.startBit, original.startBit);
+
581 QCOMPARE(target.length, original.length);
+
582 QCOMPARE(target.byteOrder, original.isLittleEndian ? ByteOrder::Intel : ByteOrder::Motorola);
+
583 QCOMPARE(target.valueType, original.isSigned ? ValueType::Signed : ValueType::Unsigned);
+
584 QCOMPARE(target.factor, original.factor);
+
585 QCOMPARE(target.offset, original.offset);
+
586 QCOMPARE(target.minimum, original.minimum);
+
587 QCOMPARE(target.maximum, original.maximum);
+
588 QCOMPARE(target.unit, original.unit);
+
589 QCOMPARE(target.comment, original.comment);
+
590 QVERIFY(target.receivers == original.receivers);
+
591 QVERIFY(target.valueDescriptions == original.valueDescriptions);
+
592 QCOMPARE(target.multiplexing.role, original.multiplexing.role);
+
593 QCOMPARE(target.multiplexing.value, original.multiplexing.value);
+
594 }
+
595 }
+
596}
+
597
+
598void CoverageTest::physicalConversion_data() {
+
599 QTest::addColumn<double>("factor");
+
600 QTest::addColumn<double>("offset");
+
601 QTest::addColumn<double>("expected");
+
602 QTest::newRow("zero-factor") << 0.0 << 7.0 << 7.0;
+
603 QTest::newRow("negative-factor") << -2.0 << 5.0 << -15.0;
+
604 QTest::newRow("above-declared-range") << 2.0 << 3.0 << 23.0;
+
605}
+
606
+
607void CoverageTest::physicalConversion() {
+
608 QFETCH(double, factor);
+
609 QFETCH(double, offset);
+
610 QFETCH(double, expected);
+
611 DecodeSignal signal;
+
612 signal.length = 8U;
+
613 signal.factor = factor;
+
614 signal.offset = offset;
+
615 signal.minimum = 0.0;
+
616 signal.maximum = 1.0;
+
617 const DecodeDatabase database = SingleSignal(signal);
+
618 RawCanFrame raw;
+
619 raw.canId = 17U;
+
620 raw.data = {10U};
+
621 const DecodedFrameValue decoded = DbcDecoder().Decode(database, raw);
+
622 QVERIFY(decoded.signals[0].valid);
+
623 QCOMPARE(std::get<std::uint64_t>(decoded.signals[0].rawValue), std::uint64_t(10));
+
624 QCOMPARE(decoded.signals[0].physicalValue, expected);
+
625}
+
626
+
627void CoverageTest::multiplexingScenarios() {
+
628 const DecodeDatabase selectorOnly = DbcDecodeBuilder().Build(ParseText(
+
629 "BO_ 1 Frame: 1 ECU\nSG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n"));
+
630 RawCanFrame raw;
+
631 raw.canId = 1U;
+
632 raw.data = {1U};
+
633 const DecodedFrameValue only = DbcDecoder().Decode(selectorOnly, raw);
+
634 QCOMPARE(only.signals.size(), std::size_t(1));
+
635 QVERIFY(only.signals[0].valid);
+
636 const DecodeDatabase database = DbcDecodeBuilder().Build(ParseText(
+
637 "BO_ 1 First: 3 ECU\n"
+
638 "SG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n"
+
639 "SG_ A m0 : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
+
640 "SG_ B m0 : 16|8@1+ (1,0) [0|255] \"\" ECU\n"
+
641 "BO_ 2 Second: 2 ECU\n"
+
642 "SG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n"
+
643 "SG_ A m1 : 8|8@1+ (1,0) [0|255] \"\" ECU\n"));
+
644 raw.data = {0U, 42U, 99U};
+
645 const DecodedFrameValue first = DbcDecoder().Decode(database, raw);
+
646 QVERIFY(first.signals[1].valid && first.signals[2].valid);
+
647 QCOMPARE(std::get<std::uint64_t>(first.signals[1].rawValue), std::uint64_t(42));
+
648 QCOMPARE(std::get<std::uint64_t>(first.signals[2].rawValue), std::uint64_t(99));
+
649 raw.canId = 2U;
+
650 const DecodedFrameValue secondInactive = DbcDecoder().Decode(database, raw);
+
651 QCOMPARE(secondInactive.signals[1].status, SignalDecodeStatus::Inactive);
+
652 raw.data[0] = 1U;
+
653 QVERIFY(DbcDecoder().Decode(database, raw).signals[1].valid);
+
654 raw.canId = 1U;
+
655 const DecodedFrameValue firstInactive = DbcDecoder().Decode(database, raw);
+
656 QCOMPARE(firstInactive.signals[1].status, SignalDecodeStatus::Inactive);
+
657 QCOMPARE(firstInactive.signals[2].status, SignalDecodeStatus::Inactive);
+
658}
+
659
+
660void CoverageTest::multiplexingErrorLocations_data() {
+
661 QTest::addColumn<QString>("text");
+
662 QTest::addColumn<unsigned>("line");
+
663 QTest::addColumn<QString>("message");
+
664 const QString header = "BO_ 1 Frame: 3 ECU\n\n";
+
665 const QString selector = "SG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n";
+
666 const QString branch = "SG_ A m1 : 8|8@1+ (1,0) [0|255] \"\" ECU\n";
+
667 QTest::newRow("missing-selector") << header + branch << 3U << QString::fromUtf8("Multiplexed branch has no selector.");
+
668 QTest::newRow("second-selector") << header + selector + "\nSG_ Other M : 16|1@1+ (1,0) [0|1] \"\" ECU\n"
+
669 << 5U << QString::fromUtf8("Multiplexing requires one unsigned selector per frame.");
+
670 QTest::newRow("signed-selector") << header + "SG_ Mode M : 0|1@1- (1,0) [-1|0] \"\" ECU\n"
+
671 << 3U << QString::fromUtf8("Multiplexing requires one unsigned selector per frame.");
+
672 QTest::newRow("branch-range") << header + "SG_ A m2 : 8|8@1+ (1,0) [0|255] \"\" ECU\n" + selector << 3U << QString::fromUtf8("Branch value exceeds selector raw range.");
+
673 QTest::newRow("same-branch-overlap") << header + selector + branch + "SG_ B m1 : 15|8@0+ (1,0) [0|255] \"\" ECU\n"
+
674 << 5U << QString::fromUtf8("Signals overlap without mutually exclusive multiplexing conditions.");
+
675 QTest::newRow("selector-overlap") << header + selector + "SG_ A m1 : 0|1@1+ (1,0) [0|1] \"\" ECU\n"
+
676 << 4U << QString::fromUtf8("Signals overlap without mutually exclusive multiplexing conditions.");
+
677 QTest::newRow("unconditional-overlap") << header + selector + branch + "SG_ Always : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
+
678 << 5U << QString::fromUtf8("Signals overlap without mutually exclusive multiplexing conditions.");
+
679 QTest::newRow("ordinary-overlap") << header + "SG_ A : 8|8@1+ (1,0) [0|255] \"\" ECU\nSG_ B : 15|8@0+ (1,0) [0|255] \"\" ECU\n"
+
680 << 4U << QString::fromUtf8("Signals overlap without mutually exclusive multiplexing conditions.");
+
681 QTest::newRow("extended-multiplexing") << header + "SG_MUL_VAL_ 1 A Mode 1-2;\n"
+
682 << 3U << QString::fromUtf8("Extended and nested multiplexing are unsupported.");
+
683 QTest::newRow("nested-marker") << header + "SG_ A m1M : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
+
684 << 3U << QString::fromUtf8("Invalid or unsupported multiplexing marker.");
+
685}
+
686
+
687void CoverageTest::multiplexingErrorLocations() {
+
688 QFETCH(QString, text);
+
689 QFETCH(unsigned, line);
+
690 QFETCH(QString, message);
+
691 QTemporaryFile file;
+
692 QVERIFY(file.open());
+
693 const QByteArray content = text.toUtf8();
+
694 QCOMPARE(file.write(content), qint64(content.size()));
+
695 QVERIFY(file.flush());
+
696 try {
+
697 DbcParser().ParseFile(file.fileName().toStdString());
+
698 QFAIL("Expected multiplexing rejection");
+
699 } catch (const std::runtime_error &error) {
+
700 QCOMPARE(QString::fromStdString(error.what()), file.fileName() + ":" + QString::number(line) + ": " + message);
+
701 }
+
702}
+
703
+
704void CoverageTest::escapedValueDescriptions() {
+
705 const DbcDatabase parsed = ParseText(
+
706 "BO_ 1 Frame: 1 ECU\nSG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
+
707 R"dbc(VAL_ 1 State -0 "Ноль" 1 "C:\\trace" 2 "\\\"quoted\"\\";)dbc"
+
708 "\n");
+
709 const ValueDescriptions &values = parsed.frames[0].signals[0].valueDescriptions;
+
710 QCOMPARE(values.size(), std::size_t(3));
+
711 QVERIFY(values.find(RawSignalValue(std::int64_t(0))) == values.end());
+
712 const std::string *zero = FindValueDescription(values, std::int64_t(0));
+
713 const std::string *path = FindValueDescription(values, std::uint64_t(1));
+
714 const std::string *quoted = FindValueDescription(values, std::uint64_t(2));
+
715 QVERIFY(zero && path && quoted);
+
716 QCOMPARE(*zero, std::string("Ноль"));
+
717 QCOMPARE(*path, std::string("C:\\trace"));
+
718 QCOMPARE(*quoted, std::string("\\\"quoted\"\\"));
+
719 QVERIFY(NormalizeValueKey(RawSignalValue(std::int64_t(0))) == RawSignalValue(std::uint64_t(0)));
+
720 QVERIFY(NormalizeValueKey(RawSignalValue(std::int64_t(-1))) == RawSignalValue(std::int64_t(-1)));
+
721}
+
722
+
723void CoverageTest::factory() {
+ +
725 QVERIFY(!factory.contains("value"));
+
726 QVERIFY_THROWS_EXCEPTION(std::out_of_range, static_cast<void>(factory.creator("missing")));
+
727 QVERIFY_THROWS_EXCEPTION(std::out_of_range, static_cast<void>(factory.create("missing", std::make_unique<int>(1))));
+
728 factory.registerType<FactoryFirst>("value");
+
729 QVERIFY(factory.contains("value"));
+
730 std::unique_ptr<int> argument = std::make_unique<int>(42);
+
731 const std::shared_ptr<FactoryBase> first = factory.create("value", std::move(argument));
+
732 QVERIFY(argument == nullptr);
+
733 QCOMPARE(first->Value(), 42);
+
734 const TypeFactory<std::string, FactoryBase, std::unique_ptr<int>>::CreatorFn creator = factory.creator("value");
+
735 QCOMPARE(creator(std::make_unique<int>(7))->Value(), 7);
+
736 factory.registerType<FactorySecond>("value");
+
737 QCOMPARE(factory.create("value", std::make_unique<int>(42))->Value(), 43);
+
738 QCOMPARE(first->Value(), 42);
+
739 QCOMPARE(creator(std::make_unique<int>(7))->Value(), 7);
+
740}
+
741
+
742int RunCoverageTests(int argc, char **argv) {
+
743 CoverageTest tests;
+
744 return QTest::qExec(&tests, argc, argv);
+
745}
+
746#include "dbc_coverage_test.moc"
Converts parsed DBC data into runtime decode database.
-
DecodeDatabase Build(const DbcDatabase &source) const
Build runtime decode database.
-
Runtime CAN decoder using prebuilt decode database.
Definition dbc_decoder.h:72
-
DecodedFrameValue Decode(const DecodeDatabase &database, const RawCanFrame &frame) const
Decode one raw CAN frame.
-
const DecodeFrame * FindFrame(const DecodeDatabase &database, std::uint32_t canId, bool isExtended) const
Find frame definition by CAN ID.
+
DecodeDatabase Build(const DbcDatabase &source) const
Build runtime decode database.
+
Runtime CAN decoder using prebuilt decode database.
Definition dbc_decoder.h:74
+
DecodedFrameValue Decode(const DecodeDatabase &database, const RawCanFrame &frame) const
Decode one raw CAN frame.
+
std::shared_ptr< const DecodeFrame > FindFrame(const DecodeDatabase &database, std::uint32_t canId, bool isExtended) const
Find frame definition by CAN ID.
Minimal DBC parser.
Definition dbc_parser.h:33
DbcDatabase ParseFile(const std::string &filePath) const
Parse DBC file.
Builds a simple tree from parsed DBC database.
std::unique_ptr< TreeNode > Build(const DbcDatabase &database) const
Build tree representation of parsed DBC data.
+
Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles a...
+
std::shared_ptr< const DecodeFrame > FindFrame(const FrameKey &key) const
+
const std::vector< DecodeFrame > & GetFrames() const
Tree node for later use in model/view or other hierarchy consumers.
Definition tree_node.h:35
const SignalInfo * GetSignal() const
Get signal payload if node is signal.
Definition tree_node.cpp:64
const TreeNode * GetChild(std::size_t index) const
Get child by index.
Definition tree_node.cpp:38
@@ -870,38 +874,37 @@ $(document).ready(function(){initNavTree('dbc__coverage__test_8cpp_source.html',
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
-
ByteOrder
Signal byte order used for runtime decoding.
-
ValueType
Signal numeric type.
+
ByteOrder
Signal byte order used for runtime decoding.
+
ValueType
Signal numeric type.
Parsed DBC content stored in a simple internal form.
std::vector< FrameInfo > frames
-
Runtime decode database with fast lookup by CAN ID.
-
Runtime-ready frame definition.
-
std::uint32_t pgn
- -
std::string comment
- -
std::uint8_t dlc
-
std::uint32_t canId
-
std::string name
-
std::string transmitter
-
Runtime-ready signal definition.
- -
std::string unit
- - -
std::string name
-
ValueDescriptions valueDescriptions
- -
ValueType valueType
-
std::uint32_t startBit
-
std::vector< std::string > receivers
-
ByteOrder byteOrder
-
std::uint32_t length
-
std::string comment
-
Fully decoded frame.
Definition dbc_decoder.h:61
- -
const DecodeFrame * definition
Definition dbc_decoder.h:62
+
Runtime-ready frame definition.
+
std::uint32_t pgn
+ +
std::string comment
+ +
std::uint8_t dlc
+
std::uint32_t canId
+
std::string name
+
std::string transmitter
+
Runtime-ready signal definition.
+ +
std::string unit
+ + +
std::string name
+
ValueDescriptions valueDescriptions
+ +
ValueType valueType
+
std::uint32_t startBit
+
std::vector< std::string > receivers
+
ByteOrder byteOrder
+
std::uint32_t length
+
std::string comment
+
Fully decoded frame.
Definition dbc_decoder.h:62
+
std::shared_ptr< const DecodeFrame > definition
Definition dbc_decoder.h:63
+
Describes one CAN frame from a DBC file.
Definition frame_info.h:24
bool isExtended
Definition frame_info.h:27
bool hasPgn
Definition frame_info.h:29
@@ -911,7 +914,7 @@ $(document).ready(function(){initNavTree('dbc__coverage__test_8cpp_source.html',
std::string comment
Definition frame_info.h:32
std::uint32_t pgn
Definition frame_info.h:28
std::uint32_t canId
Definition frame_info.h:26
-
Key for fast frame lookup.
+
Stable frame identifier: normalized CAN ID and frame type.
Raw CAN frame used for runtime or trace decoding.
Definition dbc_decoder.h:24
std::vector< std::uint8_t > data
Definition dbc_decoder.h:27
std::uint32_t canId
Definition dbc_decoder.h:25
diff --git a/docs/html/dbc__decode__builder_8cpp.html b/docs/html/dbc__decode__builder_8cpp.html index 6750082..7e51f3b 100644 --- a/docs/html/dbc__decode__builder_8cpp.html +++ b/docs/html/dbc__decode__builder_8cpp.html @@ -97,6 +97,7 @@ $(document).ready(function(){initNavTree('dbc__decode__builder_8cpp.html',''); i

Created: 2026-03-13 Author: Deeaitch (Dim. Himro) More...

#include "dbc_decode_builder.h"
+#include <utility>

Go to the source code of this file.

Detailed Description

diff --git a/docs/html/dbc__decode__builder_8cpp_source.html b/docs/html/dbc__decode__builder_8cpp_source.html index 1b62c42..9392261 100644 --- a/docs/html/dbc__decode__builder_8cpp_source.html +++ b/docs/html/dbc__decode__builder_8cpp_source.html @@ -100,82 +100,82 @@ $(document).ready(function(){initNavTree('dbc__decode__builder_8cpp_source.html'
Go to the documentation of this file.
1
12#include "dbc_decode_builder.h"
-
13
-
- -
15 DecodeDatabase result;
-
16
-
17 for (const FrameInfo &sourceFrame : source.frames) {
-
18 DecodeFrame targetFrame;
-
19
-
20 targetFrame.name = sourceFrame.name;
-
21 targetFrame.canId = sourceFrame.canId;
-
22 targetFrame.isExtended = sourceFrame.isExtended;
-
23 targetFrame.dlc = sourceFrame.dlc;
-
24 targetFrame.pgn = sourceFrame.pgn;
-
25 targetFrame.hasPgn = sourceFrame.hasPgn;
-
26 targetFrame.transmitter = sourceFrame.transmitter;
-
27 targetFrame.comment = sourceFrame.comment;
-
28
-
29 for (const SignalInfo &sourceSignal : sourceFrame.signals) {
-
30 DecodeSignal targetSignal;
-
31
-
32 targetSignal.multiplexing = sourceSignal.multiplexing;
-
33 targetSignal.name = sourceSignal.name;
-
34 targetSignal.startBit = sourceSignal.startBit;
-
35 targetSignal.length = sourceSignal.length;
-
36 targetSignal.byteOrder = sourceSignal.isLittleEndian ? ByteOrder::Intel : ByteOrder::Motorola;
-
37 targetSignal.valueType = sourceSignal.isSigned ? ValueType::Signed : ValueType::Unsigned;
-
38 targetSignal.factor = sourceSignal.factor;
-
39 targetSignal.offset = sourceSignal.offset;
-
40 targetSignal.minimum = sourceSignal.minimum;
-
41 targetSignal.maximum = sourceSignal.maximum;
-
42 targetSignal.unit = sourceSignal.unit;
-
43 targetSignal.receivers = sourceSignal.receivers;
-
44 targetSignal.comment = sourceSignal.comment;
-
45 targetSignal.valueDescriptions = sourceSignal.valueDescriptions;
-
46
-
47 targetFrame.signals.push_back(targetSignal);
-
48 }
+
13#include <utility>
+
14
+
+ +
16 std::vector<DecodeFrame> frames;
+
17 frames.reserve(source.frames.size());
+
18
+
19 for (const FrameInfo &sourceFrame: source.frames) {
+
20 DecodeFrame targetFrame;
+
21
+
22 targetFrame.name = sourceFrame.name;
+
23 targetFrame.canId = sourceFrame.canId;
+
24 targetFrame.isExtended = sourceFrame.isExtended;
+
25 targetFrame.dlc = sourceFrame.dlc;
+
26 targetFrame.pgn = sourceFrame.pgn;
+
27 targetFrame.hasPgn = sourceFrame.hasPgn;
+
28 targetFrame.transmitter = sourceFrame.transmitter;
+
29 targetFrame.comment = sourceFrame.comment;
+
30
+
31 targetFrame.signals.reserve(sourceFrame.signals.size());
+
32 for (const SignalInfo &sourceSignal: sourceFrame.signals) {
+
33 DecodeSignal targetSignal;
+
34
+
35 targetSignal.multiplexing = sourceSignal.multiplexing;
+
36 targetSignal.name = sourceSignal.name;
+
37 targetSignal.startBit = sourceSignal.startBit;
+
38 targetSignal.length = sourceSignal.length;
+
39 targetSignal.byteOrder = sourceSignal.isLittleEndian ? ByteOrder::Intel : ByteOrder::Motorola;
+
40 targetSignal.valueType = sourceSignal.isSigned ? ValueType::Signed : ValueType::Unsigned;
+
41 targetSignal.factor = sourceSignal.factor;
+
42 targetSignal.offset = sourceSignal.offset;
+
43 targetSignal.minimum = sourceSignal.minimum;
+
44 targetSignal.maximum = sourceSignal.maximum;
+
45 targetSignal.unit = sourceSignal.unit;
+
46 targetSignal.receivers = sourceSignal.receivers;
+
47 targetSignal.comment = sourceSignal.comment;
+
48 targetSignal.valueDescriptions = sourceSignal.valueDescriptions;
49
-
50 result.frames.push_back(targetFrame);
-
51 result.frameIndexByKey[FrameKey(targetFrame.canId, targetFrame.isExtended)] =
-
52 result.frames.size() - 1U;
-
53 }
-
54
-
55 return result;
-
56}
+
50 targetFrame.signals.push_back(std::move(targetSignal));
+
51 }
+
52
+
53 frames.push_back(std::move(targetFrame));
+
54 }
+
55
+
56 return DecodeDatabase(std::move(frames));
+
57}
-
DecodeDatabase Build(const DbcDatabase &source) const
Build runtime decode database.
+
DecodeDatabase Build(const DbcDatabase &source) const
Build runtime decode database.
+
Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles a...
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Parsed DBC content stored in a simple internal form.
std::vector< FrameInfo > frames
-
Runtime decode database with fast lookup by CAN ID.
-
Runtime-ready frame definition.
-
std::uint32_t pgn
- -
std::string comment
- -
std::uint8_t dlc
-
std::uint32_t canId
-
std::string name
-
std::string transmitter
-
Runtime-ready signal definition.
- -
std::string unit
- - -
std::string name
-
ValueDescriptions valueDescriptions
- -
ValueType valueType
-
std::uint32_t startBit
-
std::vector< std::string > receivers
-
ByteOrder byteOrder
-
std::uint32_t length
-
std::string comment
+
Runtime-ready frame definition.
+
std::uint32_t pgn
+ +
std::string comment
+ +
std::uint8_t dlc
+
std::uint32_t canId
+
std::string name
+
std::string transmitter
+
Runtime-ready signal definition.
+ +
std::string unit
+ + +
std::string name
+
ValueDescriptions valueDescriptions
+ +
ValueType valueType
+
std::uint32_t startBit
+
std::vector< std::string > receivers
+
ByteOrder byteOrder
+
std::uint32_t length
+
std::string comment
Describes one CAN frame from a DBC file.
Definition frame_info.h:24
-
Key for fast frame lookup.
Describes one signal inside a DBC frame.
Definition signal_info.h:24
diff --git a/docs/html/dbc__decode__builder_8h_source.html b/docs/html/dbc__decode__builder_8h_source.html index d3cd986..d2858de 100644 --- a/docs/html/dbc__decode__builder_8h_source.html +++ b/docs/html/dbc__decode__builder_8h_source.html @@ -108,17 +108,17 @@ $(document).ready(function(){initNavTree('dbc__decode__builder_8h_source.html','
22public:
-
28 DecodeDatabase Build(const DbcDatabase &source) const;
-
29};
+
29 DecodeDatabase Build(const DbcDatabase &source) const;
+
30};
-
30
-
31#endif /* DBC_DECODE_BUILDER_H */
+
31
+
32#endif /* DBC_DECODE_BUILDER_H */
Converts parsed DBC data into runtime decode database.
-
DecodeDatabase Build(const DbcDatabase &source) const
Build runtime decode database.
+
DecodeDatabase Build(const DbcDatabase &source) const
Build runtime decode database.
+
Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles a...
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Parsed DBC content stored in a simple internal form.
-
Runtime decode database with fast lookup by CAN ID.
diff --git a/docs/html/dbc__decoder_8cpp.html b/docs/html/dbc__decoder_8cpp.html index d121dcf..17fbfd5 100644 --- a/docs/html/dbc__decoder_8cpp.html +++ b/docs/html/dbc__decoder_8cpp.html @@ -97,6 +97,7 @@ $(document).ready(function(){initNavTree('dbc__decoder_8cpp.html',''); initResiz

Created: 2026-03-13 Author: Deeaitch (Dim. Himro) More...

#include "dbc_decoder.h"
+#include <utility>

Go to the source code of this file.

Detailed Description

diff --git a/docs/html/dbc__decoder_8cpp_source.html b/docs/html/dbc__decoder_8cpp_source.html index 832e3ca..06a125b 100644 --- a/docs/html/dbc__decoder_8cpp_source.html +++ b/docs/html/dbc__decoder_8cpp_source.html @@ -100,223 +100,221 @@ $(document).ready(function(){initNavTree('dbc__decoder_8cpp_source.html',''); in
Go to the documentation of this file.
1
12#include "dbc_decoder.h"
-
13
-
- -
15 std::uint32_t canId,
-
16 bool isExtended) const {
-
17 const FrameKey key(canId, isExtended);
-
18 const std::unordered_map<FrameKey, std::size_t, FrameKeyHasher>::const_iterator it =
-
19 database.frameIndexByKey.find(key);
+
13#include <utility>
+
14
+
+
15std::shared_ptr<const DecodeFrame> DbcDecoder::FindFrame(const DecodeDatabase &database,
+
16 std::uint32_t canId,
+
17 bool isExtended) const {
+
18 return database.FindFrame(FrameKey(canId, isExtended));
+
19}
+
20
-
21 if (it == database.frameIndexByKey.end())
-
22 return nullptr;
-
23
-
24 const std::size_t index = it->second;
-
25 if (index >= database.frames.size())
-
26 return nullptr;
-
27
-
28 return &database.frames[index];
-
29}
-
-
30
-
- -
32 const RawCanFrame &frame) const {
-
33 DecodedFrameValue result;
-
34 const DecodeFrame *definition = FindFrame(database, frame.canId, frame.isExtended);
-
35
-
36 if (definition == nullptr)
-
37 return result;
-
38
-
39 result.definition = definition;
-
40 result.valid = true;
+
+ +
22 const RawCanFrame &frame) const {
+
23 DecodedFrameValue result;
+
24 result.key = FrameKey(frame.canId, frame.isExtended);
+
25 const std::shared_ptr<const DecodeFrame> definition = FindFrame(database, frame.canId, frame.isExtended);
+
26
+
27 if (definition == nullptr)
+
28 return result;
+
29
+
30 result.definition = definition;
+
31 result.valid = true;
+
32
+
33 const SelectorState selector = ReadSelector(*definition, frame);
+
34 result.signals.reserve(definition->signals.size());
+
35 for (const DecodeSignal &signal: definition->signals) {
+
36 DecodedSignalValue decoded = DecodeOneSignal(signal, frame, selector);
+
37 decoded.definition = std::shared_ptr<const DecodeSignal>(definition, &signal);
+
38 decoded.key = SignalKey(result.key, signal.name);
+
39 result.signals.push_back(std::move(decoded));
+
40 }
41
-
42 const SelectorState selector = ReadSelector(*definition, frame);
-
43 for (const DecodeSignal &signal : definition->signals)
-
44 result.signals.push_back(DecodeOneSignal(signal, frame, selector));
-
45
-
46 return result;
-
47}
+
42 return result;
+
43}
-
48
-
49DbcDecoder::SelectorState DbcDecoder::ReadSelector(const DecodeFrame &definition,
-
50 const RawCanFrame &frame) {
-
51 SelectorState selector;
-
52 std::size_t count = 0U;
-
53 for (const DecodeSignal &signal : definition.signals) {
-
54 if (signal.multiplexing.role == MultiplexRole::Selector) {
-
55 selector.definition = &signal;
-
56 ++count;
-
57 }
-
58 }
-
59 if (count != 1U)
-
60 return selector;
-
61
-
62 const DecodeSignal &signal = *selector.definition;
-
63 selector.valid = signal.valueType == ValueType::Unsigned &&
-
64 signal.length > 0U && signal.length <= 64U;
-
65 selector.available = selector.valid && ExtractUnsigned(frame.data, signal, selector.value);
-
66 return selector;
-
67}
-
68
-
69DecodedSignalValue DbcDecoder::DecodeOneSignal(const DecodeSignal &signal,
-
70 const RawCanFrame &frame,
-
71 const SelectorState &selector) {
-
72 DecodedSignalValue decoded;
-
73 std::uint64_t unsignedValue = 0U;
-
74
-
75 decoded.definition = &signal;
-
76
-
77 if (signal.length == 0U || signal.length > 64U ||
-
78 (signal.multiplexing.role != MultiplexRole::Unconditional && !selector.valid)) {
-
79 return decoded;
-
80 }
-
81 if (signal.multiplexing.role == MultiplexRole::Branch) {
-
82 if (selector.definition->length < 64U && signal.multiplexing.value >= (std::uint64_t(1U) << selector.definition->length)) {
-
83 return decoded;
-
84 }
-
85 if (!selector.available) {
-
86 decoded.status = SignalDecodeStatus::SelectorUnavailable;
-
87 return decoded;
-
88 }
-
89 if (signal.multiplexing.value != selector.value) {
-
90 decoded.status = SignalDecodeStatus::Inactive;
-
91 return decoded;
-
92 }
-
93 }
-
94 if (!ExtractUnsigned(frame.data, signal, unsignedValue)) {
-
95 decoded.status = SignalDecodeStatus::InsufficientPayload;
-
96 return decoded;
-
97 }
-
98
-
99 if (signal.valueType == ValueType::Signed)
-
100 decoded.rawValue = SignExtend(unsignedValue, signal.length);
+
44
+
45DbcDecoder::SelectorState DbcDecoder::ReadSelector(const DecodeFrame &definition,
+
46 const RawCanFrame &frame) {
+
47 SelectorState selector;
+
48 std::size_t count = 0U;
+
49 for (const DecodeSignal &signal: definition.signals) {
+
50 if (signal.multiplexing.role == MultiplexRole::Selector) {
+
51 selector.definition = &signal;
+
52 ++count;
+
53 }
+
54 }
+
55 if (count != 1U)
+
56 return selector;
+
57
+
58 const DecodeSignal &signal = *selector.definition;
+
59 selector.valid = signal.valueType == ValueType::Unsigned &&
+
60 signal.length > 0U && signal.length <= 64U;
+
61 selector.available = selector.valid && ExtractUnsigned(frame.data, signal, selector.value);
+
62 return selector;
+
63}
+
64
+
65DecodedSignalValue DbcDecoder::DecodeOneSignal(const DecodeSignal &signal,
+
66 const RawCanFrame &frame,
+
67 const SelectorState &selector) {
+
68 DecodedSignalValue decoded;
+
69 std::uint64_t unsignedValue = 0U;
+
70
+
71 if (signal.length == 0U || signal.length > 64U ||
+
72 (signal.multiplexing.role != MultiplexRole::Unconditional && !selector.valid)) {
+
73 return decoded;
+
74 }
+
75 if (signal.multiplexing.role == MultiplexRole::Branch) {
+
76 if (selector.definition->length < 64U && signal.multiplexing.value >= (std::uint64_t(1U) << selector.definition->length)) {
+
77 return decoded;
+
78 }
+
79 if (!selector.available) {
+
80 decoded.status = SignalDecodeStatus::SelectorUnavailable;
+
81 return decoded;
+
82 }
+
83 if (signal.multiplexing.value != selector.value) {
+
84 decoded.status = SignalDecodeStatus::Inactive;
+
85 return decoded;
+
86 }
+
87 }
+
88 if (!ExtractUnsigned(frame.data, signal, unsignedValue)) {
+
89 decoded.status = SignalDecodeStatus::InsufficientPayload;
+
90 return decoded;
+
91 }
+
92
+
93 if (signal.valueType == ValueType::Signed)
+
94 decoded.rawValue = SignExtend(unsignedValue, signal.length);
+
95 else
+
96 decoded.rawValue = unsignedValue;
+
97
+
98 double numericValue;
+
99 if (const std::int64_t *signedValue = std::get_if<std::int64_t>(&decoded.rawValue))
+
100 numericValue = static_cast<double>(*signedValue);
101 else
-
102 decoded.rawValue = unsignedValue;
-
103
-
104 double numericValue;
-
105 if (const std::int64_t *signedValue = std::get_if<std::int64_t>(&decoded.rawValue))
-
106 numericValue = static_cast<double>(*signedValue);
-
107 else
-
108 numericValue = static_cast<double>(std::get<std::uint64_t>(decoded.rawValue));
-
109 decoded.physicalValue = numericValue * signal.factor + signal.offset;
-
110 decoded.valid = true;
-
111 decoded.status = SignalDecodeStatus::Valid;
-
112
-
113 return decoded;
-
114}
+
102 numericValue = static_cast<double>(std::get<std::uint64_t>(decoded.rawValue));
+
103 decoded.physicalValue = numericValue * signal.factor + signal.offset;
+
104 decoded.valid = true;
+
105 decoded.status = SignalDecodeStatus::Valid;
+
106
+
107 return decoded;
+
108}
+
109
+
110bool DbcDecoder::ExtractUnsigned(const std::vector<std::uint8_t> &data,
+
111 const DecodeSignal &signal,
+
112 std::uint64_t &value) {
+
113 if ((signal.length == 0U) || (signal.length > 64U))
+
114 return false;
115
-
116bool DbcDecoder::ExtractUnsigned(const std::vector<std::uint8_t> &data,
-
117 const DecodeSignal &signal,
-
118 std::uint64_t &value) {
-
119 if ((signal.length == 0U) || (signal.length > 64U))
-
120 return false;
+
116 if (signal.byteOrder == ByteOrder::Intel)
+
117 return ExtractIntel(data, signal.startBit, signal.length, value);
+
118
+
119 return ExtractMotorola(data, signal.startBit, signal.length, value);
+
120}
121
-
122 if (signal.byteOrder == ByteOrder::Intel)
-
123 return ExtractIntel(data, signal.startBit, signal.length, value);
-
124
-
125 return ExtractMotorola(data, signal.startBit, signal.length, value);
-
126}
+
122bool DbcDecoder::ExtractIntel(const std::vector<std::uint8_t> &data,
+
123 std::uint32_t startBit,
+
124 std::uint32_t length,
+
125 std::uint64_t &value) {
+
126 value = 0U;
127
-
128bool DbcDecoder::ExtractIntel(const std::vector<std::uint8_t> &data,
-
129 std::uint32_t startBit,
-
130 std::uint32_t length,
-
131 std::uint64_t &value) {
-
132 value = 0U;
-
133
-
134 for (std::uint32_t bitIndex = 0U; bitIndex < length; ++bitIndex) {
-
135 const std::uint32_t absoluteBit = startBit + bitIndex;
-
136 const std::uint32_t byteIndex = absoluteBit / 8U;
-
137 const std::uint32_t bitInByte = absoluteBit % 8U;
+
128 for (std::uint32_t bitIndex = 0U; bitIndex < length; ++bitIndex) {
+
129 const std::uint32_t absoluteBit = startBit + bitIndex;
+
130 const std::uint32_t byteIndex = absoluteBit / 8U;
+
131 const std::uint32_t bitInByte = absoluteBit % 8U;
+
132
+
133 if (byteIndex >= data.size())
+
134 return false;
+
135
+
136 const std::uint64_t bitValue =
+
137 (static_cast<std::uint64_t>((data[byteIndex] >> bitInByte) & 0x01U) << bitIndex);
138
-
139 if (byteIndex >= data.size())
-
140 return false;
+
139 value |= bitValue;
+
140 }
141
-
142 const std::uint64_t bitValue =
-
143 (static_cast<std::uint64_t>((data[byteIndex] >> bitInByte) & 0x01U) << bitIndex);
+
142 return true;
+
143}
144
-
145 value |= bitValue;
-
146 }
-
147
-
148 return true;
-
149}
-
150
-
151bool DbcDecoder::ExtractMotorola(const std::vector<std::uint8_t> &data,
-
152 std::uint32_t startBit,
-
153 std::uint32_t length,
-
154 std::uint64_t &value) {
-
155 /*
-
156 * DBC Motorola bit numbering:
-
157 * - startBit points to the most significant bit of the signal
-
158 * - inside a byte, bit numbering goes 7..0
-
159 * - crossing byte boundary moves to the next byte, bit 7
-
160 * Example: a signal starting at 7 follows 7..0, 15..8, 23..16.
-
161 */
-
162
-
163 value = 0U;
-
164
-
165 std::size_t byteIndex = startBit / 8U;
-
166 std::uint32_t bitInByte = startBit % 8U;
-
167
-
168 for (std::uint32_t bitIndex = 0U; bitIndex < length; ++bitIndex) {
-
169 if (byteIndex >= data.size())
-
170 return false;
-
171
-
172 value <<= 1U;
-
173 value |= static_cast<std::uint64_t>((data[byteIndex] >> bitInByte) & 0x01U);
-
174
-
175 if (bitInByte == 0U) {
-
176 ++byteIndex;
-
177 bitInByte = 7U;
-
178 } else
-
179 --bitInByte;
-
180 }
-
181
-
182 return true;
-
183}
-
184
-
185std::int64_t DbcDecoder::SignExtend(std::uint64_t value, std::uint32_t bitLength) {
-
186 if ((bitLength == 0U) || (bitLength > 64U))
-
187 return 0;
+
145bool DbcDecoder::ExtractMotorola(const std::vector<std::uint8_t> &data,
+
146 std::uint32_t startBit,
+
147 std::uint32_t length,
+
148 std::uint64_t &value) {
+
149 /*
+
150 * DBC Motorola bit numbering:
+
151 * - startBit points to the most significant bit of the signal
+
152 * - inside a byte, bit numbering goes 7..0
+
153 * - crossing byte boundary moves to the next byte, bit 7
+
154 * Example: a signal starting at 7 follows 7..0, 15..8, 23..16.
+
155 */
+
156
+
157 value = 0U;
+
158
+
159 std::size_t byteIndex = startBit / 8U;
+
160 std::uint32_t bitInByte = startBit % 8U;
+
161
+
162 for (std::uint32_t bitIndex = 0U; bitIndex < length; ++bitIndex) {
+
163 if (byteIndex >= data.size())
+
164 return false;
+
165
+
166 value <<= 1U;
+
167 value |= static_cast<std::uint64_t>((data[byteIndex] >> bitInByte) & 0x01U);
+
168
+
169 if (bitInByte == 0U) {
+
170 ++byteIndex;
+
171 bitInByte = 7U;
+
172 } else
+
173 --bitInByte;
+
174 }
+
175
+
176 return true;
+
177}
+
178
+
179std::int64_t DbcDecoder::SignExtend(std::uint64_t value, std::uint32_t bitLength) {
+
180 if ((bitLength == 0U) || (bitLength > 64U))
+
181 return 0;
+
182
+
183 const std::uint64_t signMask = std::uint64_t(1U) << (bitLength - 1U);
+
184 const std::uint64_t valueMask = (bitLength == 64U)
+
185 ? ~std::uint64_t(0U)
+
186 : (std::uint64_t(1U) << bitLength) - 1U;
+
187 value &= valueMask;
188
-
189 const std::uint64_t signMask = std::uint64_t(1U) << (bitLength - 1U);
-
190 const std::uint64_t valueMask = (bitLength == 64U)
-
191 ? ~std::uint64_t(0U)
-
192 : (std::uint64_t(1U) << bitLength) - 1U;
-
193 value &= valueMask;
-
194
-
195 if ((value & signMask) == 0U)
-
196 return static_cast<std::int64_t>(value);
-
197
-
198 // The complemented magnitude fits int64_t, including for INT64_MIN.
-
199 return -1 - static_cast<std::int64_t>((~value) & valueMask);
-
200}
-
DecodedFrameValue Decode(const DecodeDatabase &database, const RawCanFrame &frame) const
Decode one raw CAN frame.
-
const DecodeFrame * FindFrame(const DecodeDatabase &database, std::uint32_t canId, bool isExtended) const
Find frame definition by CAN ID.
+
189 if ((value & signMask) == 0U)
+
190 return static_cast<std::int64_t>(value);
+
191
+
192 // The complemented magnitude fits int64_t, including for INT64_MIN.
+
193 return -1 - static_cast<std::int64_t>((~value) & valueMask);
+
194}
+
DecodedFrameValue Decode(const DecodeDatabase &database, const RawCanFrame &frame) const
Decode one raw CAN frame.
+
std::shared_ptr< const DecodeFrame > FindFrame(const DecodeDatabase &database, std::uint32_t canId, bool isExtended) const
Find frame definition by CAN ID.
+
Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles a...
+
std::shared_ptr< const DecodeFrame > FindFrame(const FrameKey &key) const
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
-
Runtime decode database with fast lookup by CAN ID.
-
Runtime-ready frame definition.
-
Runtime-ready signal definition.
- - -
ValueType valueType
-
std::uint32_t startBit
-
ByteOrder byteOrder
-
std::uint32_t length
-
Fully decoded frame.
Definition dbc_decoder.h:61
- -
const DecodeFrame * definition
Definition dbc_decoder.h:62
+
Runtime-ready frame definition.
+
Runtime-ready signal definition.
+ + +
ValueType valueType
+
std::uint32_t startBit
+
ByteOrder byteOrder
+
std::uint32_t length
+
Fully decoded frame.
Definition dbc_decoder.h:62
+ +
std::shared_ptr< const DecodeFrame > definition
Definition dbc_decoder.h:63
+
One decoded signal value.
Definition dbc_decoder.h:43
-
RawSignalValue rawValue
Definition dbc_decoder.h:45
- - -
const DecodeSignal * definition
Definition dbc_decoder.h:44
-
Key for fast frame lookup.
+ +
RawSignalValue rawValue
Definition dbc_decoder.h:46
+ +
std::shared_ptr< const DecodeSignal > definition
Definition dbc_decoder.h:44
+ +
Stable frame identifier: normalized CAN ID and frame type.
Raw CAN frame used for runtime or trace decoding.
Definition dbc_decoder.h:24
std::vector< std::uint8_t > data
Definition dbc_decoder.h:27
std::uint32_t canId
Definition dbc_decoder.h:25
bool isExtended
Definition dbc_decoder.h:26
+
diff --git a/docs/html/dbc__decoder_8h_source.html b/docs/html/dbc__decoder_8h_source.html index de6b2ec..ab35196 100644 --- a/docs/html/dbc__decoder_8h_source.html +++ b/docs/html/dbc__decoder_8h_source.html @@ -110,9 +110,9 @@ $(document).ready(function(){initNavTree('dbc__decoder_8h_source.html',''); init
20
-
25 std::uint32_t canId = 0U;
-
26 bool isExtended = false;
-
27 std::vector<std::uint8_t> data;
+
25 std::uint32_t canId = 0U;
+
26 bool isExtended = false;
+
27 std::vector<std::uint8_t> data;
29 RawCanFrame() = default;
30};
@@ -127,94 +127,99 @@ $(document).ready(function(){initNavTree('dbc__decoder_8h_source.html',''); init
39
-
44 const DecodeSignal *definition = nullptr;
-
45 RawSignalValue rawValue = std::uint64_t(0U);
-
46 double physicalValue = 0.0;
-
47 bool valid = false;
-
48 SignalDecodeStatus status = SignalDecodeStatus::InvalidDefinition;
-
49
-
-
51 const std::string *GetValueDescription() const {
-
52 return valid && definition ? FindValueDescription(definition->valueDescriptions, rawValue) : nullptr;
-
53 }
+
44 std::shared_ptr<const DecodeSignal> definition;
+ +
46 RawSignalValue rawValue = std::uint64_t(0U);
+
47 double physicalValue = 0.0;
+
48 bool valid = false;
+
49 SignalDecodeStatus status = SignalDecodeStatus::InvalidDefinition;
+
50
+
+
52 const std::string *GetValueDescription() const {
+
53 return valid && definition ? FindValueDescription(definition->valueDescriptions, rawValue) : nullptr;
+
54 }
-
54
-
55 DecodedSignalValue() = default;
-
56};
+
55
+
56 DecodedSignalValue() = default;
+
57};
-
57
-
- -
62 const DecodeFrame *definition = nullptr;
-
63 std::vector<DecodedSignalValue> signals;
-
64 bool valid = false;
-
66 DecodedFrameValue() = default;
-
67};
+
58
+
+ +
63 std::shared_ptr<const DecodeFrame> definition;
+ +
65 std::vector<DecodedSignalValue> signals;
+
66 bool valid = false;
+
68 DecodedFrameValue() = default;
+
69};
-
68
-
- -
73public:
-
81 const DecodeFrame *FindFrame(const DecodeDatabase &database,
-
82 std::uint32_t canId,
-
83 bool isExtended) const;
-
84
- -
92 const RawCanFrame &frame) const;
-
93
-
94private:
-
95 struct SelectorState {
-
96 const DecodeSignal *definition = nullptr;
-
97 bool valid = false;
-
98 bool available = false;
-
99 std::uint64_t value = 0U;
-
100 };
-
101
-
102 static SelectorState ReadSelector(const DecodeFrame &definition, const RawCanFrame &frame);
-
103 static DecodedSignalValue DecodeOneSignal(const DecodeSignal &signal,
-
104 const RawCanFrame &frame,
-
105 const SelectorState &selector);
-
106
-
107 static bool ExtractUnsigned(const std::vector<std::uint8_t> &data,
-
108 const DecodeSignal &signal,
-
109 std::uint64_t &value);
-
110
-
111 static bool ExtractIntel(const std::vector<std::uint8_t> &data,
-
112 std::uint32_t startBit,
-
113 std::uint32_t length,
-
114 std::uint64_t &value);
-
115
-
116 static bool ExtractMotorola(const std::vector<std::uint8_t> &data,
-
117 std::uint32_t startBit,
-
118 std::uint32_t length,
-
119 std::uint64_t &value);
-
120
-
121 static std::int64_t SignExtend(std::uint64_t value, std::uint32_t bitLength);
-
122};
+
70
+
+ +
75public:
+
83 std::shared_ptr<const DecodeFrame> FindFrame(const DecodeDatabase &database,
+
84 std::uint32_t canId,
+
85 bool isExtended) const;
+
86
+ +
94 const RawCanFrame &frame) const;
+
95
+
96private:
+
97 struct SelectorState {
+
98 const DecodeSignal *definition = nullptr;
+
99 bool valid = false;
+
100 bool available = false;
+
101 std::uint64_t value = 0U;
+
102 };
+
103
+
104 static SelectorState ReadSelector(const DecodeFrame &definition, const RawCanFrame &frame);
+
105 static DecodedSignalValue DecodeOneSignal(const DecodeSignal &signal,
+
106 const RawCanFrame &frame,
+
107 const SelectorState &selector);
+
108
+
109 static bool ExtractUnsigned(const std::vector<std::uint8_t> &data,
+
110 const DecodeSignal &signal,
+
111 std::uint64_t &value);
+
112
+
113 static bool ExtractIntel(const std::vector<std::uint8_t> &data,
+
114 std::uint32_t startBit,
+
115 std::uint32_t length,
+
116 std::uint64_t &value);
+
117
+
118 static bool ExtractMotorola(const std::vector<std::uint8_t> &data,
+
119 std::uint32_t startBit,
+
120 std::uint32_t length,
+
121 std::uint64_t &value);
+
122
+
123 static std::int64_t SignExtend(std::uint64_t value, std::uint32_t bitLength);
+
124};
-
123
-
124#endif /* DBC_DECODER_H */
-
Runtime CAN decoder using prebuilt decode database.
Definition dbc_decoder.h:72
-
DecodedFrameValue Decode(const DecodeDatabase &database, const RawCanFrame &frame) const
Decode one raw CAN frame.
-
const DecodeFrame * FindFrame(const DecodeDatabase &database, std::uint32_t canId, bool isExtended) const
Find frame definition by CAN ID.
+
125
+
126#endif /* DBC_DECODER_H */
+
Runtime CAN decoder using prebuilt decode database.
Definition dbc_decoder.h:74
+
DecodedFrameValue Decode(const DecodeDatabase &database, const RawCanFrame &frame) const
Decode one raw CAN frame.
+
std::shared_ptr< const DecodeFrame > FindFrame(const DecodeDatabase &database, std::uint32_t canId, bool isExtended) const
Find frame definition by CAN ID.
+
Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles a...
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
-
Runtime decode database with fast lookup by CAN ID.
-
Runtime-ready frame definition.
-
Runtime-ready signal definition.
-
ValueDescriptions valueDescriptions
-
Fully decoded frame.
Definition dbc_decoder.h:61
- -
const DecodeFrame * definition
Definition dbc_decoder.h:62
+
Runtime-ready frame definition.
+
Runtime-ready signal definition.
+
Fully decoded frame.
Definition dbc_decoder.h:62
+ +
std::shared_ptr< const DecodeFrame > definition
Definition dbc_decoder.h:63
+
One decoded signal value.
Definition dbc_decoder.h:43
-
RawSignalValue rawValue
Definition dbc_decoder.h:45
- - -
const DecodeSignal * definition
Definition dbc_decoder.h:44
-
const std::string * GetValueDescription() const
Definition dbc_decoder.h:51
+ +
RawSignalValue rawValue
Definition dbc_decoder.h:46
+ +
std::shared_ptr< const DecodeSignal > definition
Definition dbc_decoder.h:44
+ +
const std::string * GetValueDescription() const
Definition dbc_decoder.h:52
+
Stable frame identifier: normalized CAN ID and frame type.
Raw CAN frame used for runtime or trace decoding.
Definition dbc_decoder.h:24
std::vector< std::uint8_t > data
Definition dbc_decoder.h:27
std::uint32_t canId
Definition dbc_decoder.h:25
bool isExtended
Definition dbc_decoder.h:26
+
diff --git a/docs/html/dbc__decoder__test_8cpp_source.html b/docs/html/dbc__decoder__test_8cpp_source.html index f0c12a0..8162103 100644 --- a/docs/html/dbc__decoder__test_8cpp_source.html +++ b/docs/html/dbc__decoder__test_8cpp_source.html @@ -168,124 +168,119 @@ $(document).ready(function(){initNavTree('dbc__decoder__test_8cpp_source.html','
68 definition.canId = 0x123U;
69 definition.dlc = static_cast<std::uint8_t>(test.data.size());
70 definition.signals.push_back(signal);
-
71 DecodeDatabase database;
-
72 database.frames.push_back(definition);
-
73 database.frameIndexByKey.emplace(FrameKey(definition.canId, false), 0U);
-
74
-
75 RawCanFrame frame;
-
76 frame.canId = definition.canId;
-
77 frame.data = test.data;
-
78 const DecodedFrameValue result = DbcDecoder().Decode(database, frame);
-
79 QVERIFY2(result.valid, test.name);
-
80 QCOMPARE(result.definition, &database.frames[0]);
-
81 QCOMPARE(result.signals.size(), std::size_t(1U));
-
82 const DecodedSignalValue &decoded = result.signals[0];
-
83 QCOMPARE(decoded.definition, &database.frames[0].signals[0]);
-
84 QCOMPARE(decoded.valid, test.valid);
-
85 if (!test.valid)
-
86 return;
-
87
-
88 if (test.valueType == ValueType::Signed) {
-
89 const std::int64_t *raw = std::get_if<std::int64_t>(&decoded.rawValue);
-
90 QVERIFY(raw != nullptr);
-
91 QCOMPARE(*raw, test.rawValue);
-
92 } else {
-
93 const std::uint64_t *raw = std::get_if<std::uint64_t>(&decoded.rawValue);
-
94 QVERIFY(raw != nullptr);
-
95 QCOMPARE(*raw, static_cast<std::uint64_t>(test.rawValue));
-
96 }
-
97 QCOMPARE(decoded.physicalValue, test.physicalValue);
-
98}
-
99
-
100void DbcDecoderTest::boundaries() {
-
101 for (ByteOrder order: {ByteOrder::Intel, ByteOrder::Motorola}) {
-
102 for (ValueType type: {ValueType::Unsigned, ValueType::Signed}) {
-
103 for (std::uint64_t bits: {std::uint64_t(0U), std::uint64_t(0x7FFFFFFFFFFFFFFFULL),
-
104 std::uint64_t(0x8000000000000000ULL),
-
105 std::uint64_t(0x8000000000000001ULL),
-
106 std::uint64_t(0xFFFFFFFFFFFFFFFFULL)}) {
-
107 DecodeDatabase database;
-
108 DecodeFrame definition;
-
109 DecodeSignal signal;
-
110 signal.startBit = order == ByteOrder::Intel ? 0U : 7U;
-
111 signal.length = 64U;
-
112 signal.byteOrder = order;
-
113 signal.valueType = type;
-
114 signal.factor = 0.5;
-
115 signal.offset = 10.0;
-
116 definition.signals.push_back(signal);
-
117 database.frames.push_back(definition);
-
118 database.frameIndexByKey.emplace(FrameKey(0U, false), 0U);
-
119 RawCanFrame frame;
-
120 for (unsigned byte = 0U; byte < 8U; ++byte) {
-
121 const unsigned shift = (order == ByteOrder::Intel ? byte : 7U - byte) * 8U;
-
122 frame.data.push_back(static_cast<std::uint8_t>(bits >> shift));
-
123 }
-
124 const DecodedFrameValue result = DbcDecoder().Decode(database, frame);
-
125 const std::int64_t signedExpected = bits <= 0x7FFFFFFFFFFFFFFFULL
-
126 ? static_cast<std::int64_t>(bits)
-
127 : std::numeric_limits<std::int64_t>::min() +
-
128 static_cast<std::int64_t>(bits - 0x8000000000000000ULL);
-
129 const DecodedSignalValue &decoded = result.signals.at(0U);
-
130 const RawSignalValue expected = type == ValueType::Unsigned
-
131 ? std::variant<std::int64_t, std::uint64_t>(bits)
-
132 : std::variant<std::int64_t, std::uint64_t>(signedExpected);
-
133 const double physical = (type == ValueType::Unsigned
-
134 ? static_cast<double>(bits)
-
135 : static_cast<double>(signedExpected)) *
-
136 0.5 +
-
137 10.0;
-
138 std::ostringstream actualText;
-
139 std::ostringstream expectedText;
-
140 if (const std::int64_t *signedValue = std::get_if<std::int64_t>(&decoded.rawValue))
-
141 actualText << *signedValue;
+
71 const DecodeDatabase database({definition});
+
72
+
73 RawCanFrame frame;
+
74 frame.canId = definition.canId;
+
75 frame.data = test.data;
+
76 const DecodedFrameValue result = DbcDecoder().Decode(database, frame);
+
77 QVERIFY2(result.valid, test.name);
+
78 QCOMPARE(result.definition.get(), &database.GetFrames()[0]);
+
79 QCOMPARE(result.signals.size(), std::size_t(1U));
+
80 const DecodedSignalValue &decoded = result.signals[0];
+
81 QCOMPARE(decoded.definition.get(), &database.GetFrames()[0].signals[0]);
+
82 QCOMPARE(decoded.valid, test.valid);
+
83 if (!test.valid)
+
84 return;
+
85
+
86 if (test.valueType == ValueType::Signed) {
+
87 const std::int64_t *raw = std::get_if<std::int64_t>(&decoded.rawValue);
+
88 QVERIFY(raw != nullptr);
+
89 QCOMPARE(*raw, test.rawValue);
+
90 } else {
+
91 const std::uint64_t *raw = std::get_if<std::uint64_t>(&decoded.rawValue);
+
92 QVERIFY(raw != nullptr);
+
93 QCOMPARE(*raw, static_cast<std::uint64_t>(test.rawValue));
+
94 }
+
95 QCOMPARE(decoded.physicalValue, test.physicalValue);
+
96}
+
97
+
98void DbcDecoderTest::boundaries() {
+
99 for (ByteOrder order: {ByteOrder::Intel, ByteOrder::Motorola}) {
+
100 for (ValueType type: {ValueType::Unsigned, ValueType::Signed}) {
+
101 for (std::uint64_t bits: {std::uint64_t(0U), std::uint64_t(0x7FFFFFFFFFFFFFFFULL),
+
102 std::uint64_t(0x8000000000000000ULL),
+
103 std::uint64_t(0x8000000000000001ULL),
+
104 std::uint64_t(0xFFFFFFFFFFFFFFFFULL)}) {
+
105 DecodeFrame definition;
+
106 DecodeSignal signal;
+
107 signal.startBit = order == ByteOrder::Intel ? 0U : 7U;
+
108 signal.length = 64U;
+
109 signal.byteOrder = order;
+
110 signal.valueType = type;
+
111 signal.factor = 0.5;
+
112 signal.offset = 10.0;
+
113 definition.signals.push_back(signal);
+
114 const DecodeDatabase database({definition});
+
115 RawCanFrame frame;
+
116 for (unsigned byte = 0U; byte < 8U; ++byte) {
+
117 const unsigned shift = (order == ByteOrder::Intel ? byte : 7U - byte) * 8U;
+
118 frame.data.push_back(static_cast<std::uint8_t>(bits >> shift));
+
119 }
+
120 const DecodedFrameValue result = DbcDecoder().Decode(database, frame);
+
121 const std::int64_t signedExpected = bits <= 0x7FFFFFFFFFFFFFFFULL
+
122 ? static_cast<std::int64_t>(bits)
+
123 : std::numeric_limits<std::int64_t>::min() +
+
124 static_cast<std::int64_t>(bits - 0x8000000000000000ULL);
+
125 const DecodedSignalValue &decoded = result.signals.at(0U);
+
126 const RawSignalValue expected = type == ValueType::Unsigned
+
127 ? std::variant<std::int64_t, std::uint64_t>(bits)
+
128 : std::variant<std::int64_t, std::uint64_t>(signedExpected);
+
129 const double physical = (type == ValueType::Unsigned
+
130 ? static_cast<double>(bits)
+
131 : static_cast<double>(signedExpected)) *
+
132 0.5 +
+
133 10.0;
+
134 std::ostringstream actualText;
+
135 std::ostringstream expectedText;
+
136 if (const std::int64_t *signedValue = std::get_if<std::int64_t>(&decoded.rawValue))
+
137 actualText << *signedValue;
+
138 else
+
139 actualText << std::get<std::uint64_t>(decoded.rawValue);
+
140 if (type == ValueType::Unsigned)
+
141 expectedText << bits;
142 else
-
143 actualText << std::get<std::uint64_t>(decoded.rawValue);
-
144 if (type == ValueType::Unsigned)
-
145 expectedText << bits;
-
146 else
-
147 expectedText << signedExpected;
-
148 QVERIFY(decoded.valid);
-
149 QVERIFY(decoded.rawValue == expected);
-
150 QCOMPARE(decoded.physicalValue, physical);
-
151 QCOMPARE(actualText.str(), expectedText.str());
-
152 }
-
153 }
-
154 }
-
155}
-
156
-
157int RunDecoderTests(int argc, char **argv) {
-
158 DbcDecoderTest tests;
-
159 return QTest::qExec(&tests, argc, argv);
-
160}
-
161
-
162#include "dbc_decoder_test.moc"
-
Runtime CAN decoder using prebuilt decode database.
Definition dbc_decoder.h:72
-
DecodedFrameValue Decode(const DecodeDatabase &database, const RawCanFrame &frame) const
Decode one raw CAN frame.
+
143 expectedText << signedExpected;
+
144 QVERIFY(decoded.valid);
+
145 QVERIFY(decoded.rawValue == expected);
+
146 QCOMPARE(decoded.physicalValue, physical);
+
147 QCOMPARE(actualText.str(), expectedText.str());
+
148 }
+
149 }
+
150 }
+
151}
+
152
+
153int RunDecoderTests(int argc, char **argv) {
+
154 DbcDecoderTest tests;
+
155 return QTest::qExec(&tests, argc, argv);
+
156}
+
157
+
158#include "dbc_decoder_test.moc"
+
Runtime CAN decoder using prebuilt decode database.
Definition dbc_decoder.h:74
+
DecodedFrameValue Decode(const DecodeDatabase &database, const RawCanFrame &frame) const
Decode one raw CAN frame.
+
Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles a...
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
-
ByteOrder
Signal byte order used for runtime decoding.
-
ValueType
Signal numeric type.
-
Runtime decode database with fast lookup by CAN ID.
-
Runtime-ready frame definition.
-
std::uint8_t dlc
-
std::uint32_t canId
-
Runtime-ready signal definition.
- -
std::string name
- -
ValueType valueType
-
std::uint32_t startBit
-
ByteOrder byteOrder
-
std::uint32_t length
-
Fully decoded frame.
Definition dbc_decoder.h:61
- -
const DecodeFrame * definition
Definition dbc_decoder.h:62
+
ByteOrder
Signal byte order used for runtime decoding.
+
ValueType
Signal numeric type.
+
Runtime-ready frame definition.
+
std::uint8_t dlc
+
std::uint32_t canId
+
Runtime-ready signal definition.
+ +
std::string name
+ +
ValueType valueType
+
std::uint32_t startBit
+
ByteOrder byteOrder
+
std::uint32_t length
+
Fully decoded frame.
Definition dbc_decoder.h:62
+
std::shared_ptr< const DecodeFrame > definition
Definition dbc_decoder.h:63
+
One decoded signal value.
Definition dbc_decoder.h:43
-
RawSignalValue rawValue
Definition dbc_decoder.h:45
- - -
const DecodeSignal * definition
Definition dbc_decoder.h:44
-
Key for fast frame lookup.
+
RawSignalValue rawValue
Definition dbc_decoder.h:46
+ +
std::shared_ptr< const DecodeSignal > definition
Definition dbc_decoder.h:44
+
Raw CAN frame used for runtime or trace decoding.
Definition dbc_decoder.h:24
std::vector< std::uint8_t > data
Definition dbc_decoder.h:27
std::uint32_t canId
Definition dbc_decoder.h:25
diff --git a/docs/html/dbc__lifetime__test_8cpp_source.html b/docs/html/dbc__lifetime__test_8cpp_source.html new file mode 100644 index 0000000..7a96641 --- /dev/null +++ b/docs/html/dbc__lifetime__test_8cpp_source.html @@ -0,0 +1,387 @@ + + + + + + + +DBC Framework: dbc_lifetime_test.cpp Source File + + + + + + + + + + + + + +
+
+ + + + + + +
+
DBC Framework +
+
DBC parsing and CAN signal decoding framework
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
dbc_lifetime_test.cpp
+
+
+
1// SPDX-License-Identifier: MIT
+
2// Copyright (c) 2026 Dim Himro
+
3
+ +
5#include "dbc_decoder.h"
+
6#include "dbc_parser.h"
+
7#include <QTemporaryFile>
+
8#include <QtTest>
+
9#include <stdexcept>
+
10#include <type_traits>
+
11#include <unordered_map>
+
12#include <utility>
+
13
+
14static_assert(std::is_same_v<decltype(std::declval<const DecodeDatabase &>().GetFrames()),
+
15 const std::vector<DecodeFrame> &>);
+
16static_assert(std::is_same_v<decltype(DecodedFrameValue::definition), std::shared_ptr<const DecodeFrame>>);
+
17static_assert(std::is_same_v<decltype(DecodedSignalValue::definition), std::shared_ptr<const DecodeSignal>>);
+
18
+
19namespace {
+
20 DecodeDatabase BuildText(const std::string &text) {
+
21 QTemporaryFile file;
+
22 if (!file.open() ||
+
23 file.write(text.data(), static_cast<qint64>(text.size())) != static_cast<qint64>(text.size()) ||
+
24 !file.flush())
+
25 throw std::runtime_error("Cannot write reload fixture");
+
26 return DbcDecodeBuilder().Build(DbcParser().ParseFile(file.fileName().toStdString()));
+
27 }
+
28
+
29 const std::string firstDbc =
+
30 "BO_ 17 OldFrame: 2 ECU\n"
+
31 "SG_ State : 0|8@1+ (2,1) [1|511] \"old\" ECU\n"
+
32 "SG_ Removed : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
+
33 "VAL_ 17 State 1 \"Old label\";\n"
+
34 "BO_ 18 Deleted: 1 ECU\n"
+
35 "SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n";
+
36 const std::string secondDbc =
+
37 "BO_ 2147483665 Extended: 1 ECU\n"
+
38 "SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
+
39 "BO_ 17 NewFrame: 2 ECU\n"
+
40 "SG_ Renamed : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
+
41 "SG_ State : 0|8@1+ (4,0) [0|1020] \"new\" ECU\n"
+
42 "VAL_ 17 State 1 \"New label\";\n";
+
43}// namespace
+
44
+
45class DbcLifetimeTest : public QObject {
+
46 Q_OBJECT
+
47private Q_SLOTS:
+
48 void reload();
+
49 void independentSignalLifetime();
+
50 void lookupLifetime();
+
51 void keys();
+
52 void duplicateKeys();
+
53 void failedReload();
+
54 void invalidResults();
+
55 void retainedMultiplexStatuses();
+
56};
+
57
+
58void DbcLifetimeTest::reload() {
+
59 DecodeDatabase database = BuildText(firstDbc);
+
60 RawCanFrame raw;
+
61 raw.canId = 17U;
+
62 raw.data = {1U, 42U};
+
63 DecodedFrameValue oldResult = DbcDecoder().Decode(database, raw);
+
64 const DecodedFrameValue copied = oldResult;
+
65 DecodedFrameValue moved = std::move(oldResult);
+
66 std::weak_ptr<const DecodeFrame> oldDefinition = moved.definition;
+
67 database = BuildText(secondDbc);
+
68 const DecodedFrameValue current = DbcDecoder().Decode(database, raw);
+
69 QVERIFY(current.valid && moved.valid && copied.valid);
+
70 QVERIFY(current.definition != moved.definition);
+
71 QVERIFY(current.key == moved.key);
+
72 QVERIFY(current.signals[1].key == moved.signals[0].key);
+
73 QCOMPARE(moved.definition->name, std::string("OldFrame"));
+
74 QCOMPARE(copied.definition, moved.definition);
+
75 QCOMPARE(moved.signals[0].physicalValue, 3.0);
+
76 QCOMPARE(current.signals[1].physicalValue, 4.0);
+
77 QCOMPARE(moved.signals[0].definition->unit, std::string("old"));
+
78 QCOMPARE(current.signals[1].definition->unit, std::string("new"));
+
79 QCOMPARE(*moved.signals[0].GetValueDescription(), std::string("Old label"));
+
80 QCOMPARE(*current.signals[1].GetValueDescription(), std::string("New label"));
+
81 QCOMPARE(moved.signals[1].definition->name, std::string("Removed"));
+
82 QVERIFY(!database.FindSignal(moved.signals[1].key));
+
83 database = DecodeDatabase();
+
84 QVERIFY(!oldDefinition.expired());
+
85 QCOMPARE(current.definition->name, std::string("NewFrame"));
+
86 QCOMPARE(*current.signals[1].GetValueDescription(), std::string("New label"));
+
87}
+
88
+
89void DbcLifetimeTest::independentSignalLifetime() {
+ +
91 std::weak_ptr<const DecodeSignal> definition;
+
92 const std::string *label = nullptr;
+
93 {
+
94 DecodeDatabase database = BuildText(firstDbc);
+
95 RawCanFrame raw;
+
96 raw.canId = 17U;
+
97 raw.data = {1U, 0U};
+
98 DecodedFrameValue result = DbcDecoder().Decode(database, raw);
+
99 saved = result.signals[0];
+
100 definition = saved.definition;
+
101 label = saved.GetValueDescription();
+
102 result = DecodedFrameValue();
+
103 database = BuildText(secondDbc);
+
104 }
+
105 QVERIFY(!definition.expired());
+
106 QVERIFY(label != nullptr);
+
107 QCOMPARE(*label, std::string("Old label"));
+
108 QCOMPARE(saved.definition->factor, 2.0);
+
109 DecodedSignalValue copied = saved;
+
110 DecodedSignalValue moved = std::move(saved);
+
111 QCOMPARE(moved.definition, copied.definition);
+
112 saved = DecodedSignalValue();
+
113 moved = DecodedSignalValue();
+
114 QVERIFY(!definition.expired());
+
115 copied = DecodedSignalValue();
+
116 QVERIFY(definition.expired());
+
117}
+
118
+
119void DbcLifetimeTest::lookupLifetime() {
+
120 std::shared_ptr<const DecodeFrame> frame;
+
121 std::shared_ptr<const DecodeSignal> signal;
+
122 std::weak_ptr<const DecodeFrame> released;
+
123 {
+
124 DecodeDatabase database = BuildText(firstDbc);
+
125 DecodeDatabase copy = database;
+
126 frame = DbcDecoder().FindFrame(database, 17U, false);
+
127 signal = copy.FindSignal(SignalKey(FrameKey(17U, false), "State"));
+
128 QVERIFY(frame && signal);
+
129 QCOMPARE(frame.get(), &copy.GetFrames()[0]);
+
130 QCOMPARE(signal.get(), &frame->signals[0]);
+
131 released = frame;
+
132 database = BuildText(secondDbc);
+
133 DecodeDatabase moved = std::move(copy);
+
134 QVERIFY(copy.GetFrames().empty());
+
135 QVERIFY(!copy.FindFrame(FrameKey(17U, false)));
+
136 QCOMPARE(moved.FindFrame(FrameKey(17U, false)), frame);
+
137 }
+
138 QCOMPARE(frame->name, std::string("OldFrame"));
+
139 frame.reset();
+
140 QVERIFY(!released.expired());
+
141 QCOMPARE(signal->name, std::string("State"));
+
142 signal.reset();
+
143 QVERIFY(released.expired());
+
144}
+
145
+
146void DbcLifetimeTest::keys() {
+
147 const FrameKey frame(17U, false);
+
148 const SignalKey state(frame, "State");
+
149 const DecodeDatabase first = BuildText(firstDbc);
+
150 const DecodeDatabase second = BuildText(secondDbc);
+
151 QVERIFY(first.FindFrame(frame)->GetKey() == second.FindFrame(frame)->GetKey());
+
152 QVERIFY(first.FindSignal(state) && second.FindSignal(state));
+
153 QVERIFY(!second.FindFrame(FrameKey(18U, false)));
+
154 QVERIFY(!second.FindSignal(SignalKey(frame, "Removed")));
+
155 QVERIFY(second.FindSignal(SignalKey(frame, "Renamed")));
+
156 QVERIFY(second.FindSignal(SignalKey(FrameKey(17U, true), "State")));
+
157 QVERIFY(!second.FindSignal(SignalKey(FrameKey(999U, false), "State")));
+
158 QVERIFY(first.FindSignal(SignalKey(FrameKey(18U, false), "State")));
+
159 std::unordered_map<FrameKey, int, FrameKeyHasher> frames;
+
160 frames.emplace(frame, 1);
+
161 frames.emplace(FrameKey(17U, true), 2);
+
162 QCOMPARE(frames.size(), std::size_t(2U));
+
163 std::unordered_map<SignalKey, int, SignalKeyHasher> signals;
+
164 signals.emplace(state, 1);
+
165 signals.emplace(SignalKey(FrameKey(17U, true), "State"), 2);
+
166 signals.emplace(SignalKey(frame, "Renamed"), 3);
+
167 signals.emplace(SignalKey(FrameKey(18U, false), "State"), 4);
+
168 QCOMPARE(signals.at(SignalKey(FrameKey(17U, false), "State")), 1);
+
169 QCOMPARE(signals.size(), std::size_t(4U));
+
170}
+
171
+
172void DbcLifetimeTest::duplicateKeys() {
+
173 DecodeFrame frame;
+
174 frame.canId = 17U;
+
175 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (void) DecodeDatabase({frame, frame}));
+
176 DecodeSignal signal;
+
177 signal.name = "State";
+
178 frame.signals = {signal, signal};
+
179 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (void) DecodeDatabase({frame}));
+
180 DbcDatabase parsed;
+
181 FrameInfo source;
+
182 source.canId = 17U;
+
183 parsed.frames = {source, source};
+
184 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (void) DbcDecodeBuilder().Build(parsed));
+
185}
+
186
+
187void DbcLifetimeTest::failedReload() {
+
188 DecodeDatabase database = BuildText(firstDbc);
+
189 const std::shared_ptr<const DecodeFrame> original = database.FindFrame(FrameKey(17U, false));
+
190 QVERIFY_THROWS_EXCEPTION(std::runtime_error, database = BuildText("BO_ invalid\n"));
+
191 QCOMPARE(database.FindFrame(FrameKey(17U, false)), original);
+
192 database = BuildText("");
+
193 QVERIFY(database.GetFrames().empty());
+
194 QVERIFY(!database.FindFrame(FrameKey(17U, false)));
+
195 QCOMPARE(original->name, std::string("OldFrame"));
+
196}
+
197
+
198void DbcLifetimeTest::invalidResults() {
+
199 RawCanFrame raw;
+
200 raw.canId = 17U;
+
201 DecodedFrameValue result = DbcDecoder().Decode(BuildText(firstDbc), raw);
+
202 QVERIFY(result.valid);
+
203 QVERIFY(!result.signals[0].valid);
+
204 QCOMPARE(result.signals[0].status, SignalDecodeStatus::InsufficientPayload);
+
205 QVERIFY(!result.signals[0].GetValueDescription());
+
206 QCOMPARE(result.signals[0].definition->name, std::string("State"));
+
207 result = DbcDecoder().Decode(DecodeDatabase(), raw);
+
208 QVERIFY(!result.valid && !result.definition && result.signals.empty());
+
209 QVERIFY(result.key == FrameKey(17U, false));
+
210 QVERIFY(!DecodedSignalValue().GetValueDescription());
+
211 QVERIFY(!DecodeDatabase().FindSignal(SignalKey(FrameKey(17U, false), "State")));
+
212}
+
213
+
214void DbcLifetimeTest::retainedMultiplexStatuses() {
+
215 const std::string text =
+
216 "BO_ 17 Frame: 2 ECU\n"
+
217 "SG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n"
+
218 "SG_ State m1 : 8|8@1+ (1,0) [0|255] \"\" ECU\n";
+
219 const std::vector<std::vector<std::uint8_t>> payloads = {{0U}, {}, {1U}};
+
220 const SignalDecodeStatus statuses[] = {SignalDecodeStatus::Inactive,
+
221 SignalDecodeStatus::SelectorUnavailable,
+
222 SignalDecodeStatus::InsufficientPayload};
+
223 for (std::size_t index = 0U; index < payloads.size(); ++index) {
+
224 DecodeDatabase database = BuildText(text);
+
225 RawCanFrame raw;
+
226 raw.canId = 17U;
+
227 raw.data = payloads[index];
+
228 const DecodedSignalValue saved = DbcDecoder().Decode(database, raw).signals[1];
+
229 database = BuildText(secondDbc);
+
230 QCOMPARE(saved.status, statuses[index]);
+
231 QVERIFY(!saved.valid && !saved.GetValueDescription());
+
232 QCOMPARE(saved.definition->multiplexing.role, MultiplexRole::Branch);
+
233 QVERIFY(saved.key == SignalKey(FrameKey(17U, false), "State"));
+
234 }
+
235}
+
236
+
237int RunLifetimeTests(int argc, char **argv) {
+
238 DbcLifetimeTest test;
+
239 return QTest::qExec(&test, argc, argv);
+
240}
+
241
+
242#include "dbc_lifetime_test.moc"
+
Converts parsed DBC data into runtime decode database.
+
DecodeDatabase Build(const DbcDatabase &source) const
Build runtime decode database.
+
Runtime CAN decoder using prebuilt decode database.
Definition dbc_decoder.h:74
+
DecodedFrameValue Decode(const DecodeDatabase &database, const RawCanFrame &frame) const
Decode one raw CAN frame.
+
std::shared_ptr< const DecodeFrame > FindFrame(const DecodeDatabase &database, std::uint32_t canId, bool isExtended) const
Find frame definition by CAN ID.
+
Minimal DBC parser.
Definition dbc_parser.h:33
+
Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles a...
+
std::shared_ptr< const DecodeFrame > FindFrame(const FrameKey &key) const
+
const std::vector< DecodeFrame > & GetFrames() const
+
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Parsed DBC content stored in a simple internal form.
+
std::vector< FrameInfo > frames
+
Runtime-ready frame definition.
+
std::uint32_t canId
+
Runtime-ready signal definition.
+
std::string name
+
Fully decoded frame.
Definition dbc_decoder.h:62
+ +
std::shared_ptr< const DecodeFrame > definition
Definition dbc_decoder.h:63
+ +
One decoded signal value.
Definition dbc_decoder.h:43
+ +
std::shared_ptr< const DecodeSignal > definition
Definition dbc_decoder.h:44
+ +
const std::string * GetValueDescription() const
Definition dbc_decoder.h:52
+
Describes one CAN frame from a DBC file.
Definition frame_info.h:24
+
std::uint32_t canId
Definition frame_info.h:26
+
Stable frame identifier: normalized CAN ID and frame type.
+
Raw CAN frame used for runtime or trace decoding.
Definition dbc_decoder.h:24
+
std::vector< std::uint8_t > data
Definition dbc_decoder.h:27
+
std::uint32_t canId
Definition dbc_decoder.h:25
+ +
+
+ + + + diff --git a/docs/html/dbc__parser__test_8cpp_source.html b/docs/html/dbc__parser__test_8cpp_source.html index 4c2e305..d139fd5 100644 --- a/docs/html/dbc__parser__test_8cpp_source.html +++ b/docs/html/dbc__parser__test_8cpp_source.html @@ -359,7 +359,7 @@ $(document).ready(function(){initNavTree('dbc__parser__test_8cpp_source.html',''
259 QCOMPARE(warning.lineNumber, std::size_t(5U));
260 const std::string keyword = statement.substr(0U, statement.find(' '));
261 CHECK(warning.message.find("'" + keyword + "'") != std::string::npos, statement);
-
262 const DecodeDatabase runtime = DbcDecodeBuilder().Build(result.database);
+
262 const DecodeDatabase runtime = DbcDecodeBuilder().Build(result.database);
263 RawCanFrame raw;
264 raw.canId = 1U;
265 raw.data = {1U};
@@ -370,7 +370,7 @@ $(document).ready(function(){initNavTree('dbc__parser__test_8cpp_source.html',''
270 CHECK(decoded.signals[0].GetValueDescription() &&
271 *decoded.signals[0].GetValueDescription() == "On",
272 "Warnings preserve VAL_ descriptions");
-
273 QCOMPARE(runtime.frames[0].signals[0].comment, std::string("Signal comment"));
+
273 QCOMPARE(runtime.GetFrames()[0].signals[0].comment, std::string("Signal comment"));
274 }
275}
276
@@ -576,17 +576,17 @@ $(document).ready(function(){initNavTree('dbc__parser__test_8cpp_source.html',''
476 QCOMPARE(parsed.frames[0].signals[0].comment, std::string("Standard state"));
477 QCOMPARE(parsed.frames[1].signals[0].comment, std::string("Extended state"));
478 QCOMPARE(parsed.frames[2].signals.size(), std::size_t(2U));
-
479 const DecodeDatabase runtime = DbcDecodeBuilder().Build(parsed);
+
479 const DecodeDatabase runtime = DbcDecodeBuilder().Build(parsed);
480 RawCanFrame raw;
481 raw.canId = 1U;
482 raw.data = {7U};
483 const DecodedFrameValue standard = DbcDecoder().Decode(runtime, raw);
484 QVERIFY(standard.valid);
-
485 QCOMPARE(standard.definition->comment, std::string("Standard"));
+
485 QCOMPARE(standard.definition->comment, std::string("Standard"));
486 raw.isExtended = true;
487 const DecodedFrameValue extended = DbcDecoder().Decode(runtime, raw);
488 QVERIFY(extended.valid);
-
489 QCOMPARE(extended.definition->comment, std::string("Extended"));
+
489 QCOMPARE(extended.definition->comment, std::string("Extended"));
490}
491
492void DbcParserTest::integration() {
@@ -620,7 +620,7 @@ $(document).ready(function(){initNavTree('dbc__parser__test_8cpp_source.html',''
520 fixture.Write("BO_ 1 Frame: 3 ECU\n" + first + second + common + selector +
521 "VAL_ 1 First -1 \"Negative\";\n");
522 const DbcDatabase parsed = DbcParser().ParseFile(fixture.path.string());
-
523 const DecodeDatabase runtime = DbcDecodeBuilder().Build(parsed);
+
523 const DecodeDatabase runtime = DbcDecodeBuilder().Build(parsed);
524 CHECK(parsed.frames[0].signals[3].multiplexing.role == MultiplexRole::Selector,
525 "Selector declared after branches");
526 const std::unique_ptr<TreeNode> tree = DbcTreeBuilder().Build(parsed);
@@ -687,8 +687,8 @@ $(document).ready(function(){initNavTree('dbc__parser__test_8cpp_source.html',''
587 "SG_ Branch m18446744073709551615 : 64|8@1+ (1,0) [0|255] \"\" ECU\n"
588 "SG_ Mode M : 7|64@0+ (0,5) [0|1] \"\" ECU\n");
589 const DbcDatabase parsed = DbcParser().ParseFile(fixture.path.string());
-
590 DecodeDatabase runtime = DbcDecodeBuilder().Build(parsed);
-
591 CHECK(runtime.frames[0].signals[0].multiplexing.value == std::numeric_limits<std::uint64_t>::max(),
+
590 DecodeDatabase runtime = DbcDecodeBuilder().Build(parsed);
+
591 CHECK(runtime.GetFrames()[0].signals[0].multiplexing.value == std::numeric_limits<std::uint64_t>::max(),
592 "Exact uint64 branch metadata");
593 RawCanFrame raw;
594 raw.canId = 1U;
@@ -701,302 +701,305 @@ $(document).ready(function(){initNavTree('dbc__parser__test_8cpp_source.html',''
601 result = DbcDecoder().Decode(runtime, raw);
602 CHECK(result.signals[0].status == SignalDecodeStatus::Inactive,
603 "Adjacent large integers remain distinct");
-
604 runtime.frames[0].signals[1].length = 0U;
-
605 result = DbcDecoder().Decode(runtime, raw);
-
606 CHECK(result.signals[0].status == SignalDecodeStatus::InvalidDefinition &&
-
607 result.signals[1].status == SignalDecodeStatus::InvalidDefinition,
-
608 "Malformed runtime selector distinguished from payload errors");
-
609 runtime.frames[0].signals.pop_back();
-
610 result = DbcDecoder().Decode(runtime, raw);
-
611 CHECK(result.signals[0].status == SignalDecodeStatus::InvalidDefinition,
-
612 "Missing runtime selector");
-
613 fixture.Write("BO_ 1 Frame: 2 ECU\n\n"
-
614 "SG_ Branch m2 : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
-
615 "SG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n");
-
616 bool rejected = false;
-
617 try {
-
618 DbcParser().ParseFile(fixture.path.string());
-
619 } catch (const std::runtime_error &error) {
-
620 rejected = std::string(error.what()).find(fixture.path.string() + ":3: ") == 0U;
-
621 }
-
622 CHECK(rejected, "Deferred validation reports branch source line");
-
623 fixture.Write("BO_ 1 Frame: 2 ECU\n"
-
624 "SG_ A : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
-
625 "SG_ B : 15|8@0+ (1,0) [0|255] \"\" ECU\n");
-
626 rejected = false;
-
627 try {
-
628 DbcParser().ParseFile(fixture.path.string());
-
629 } catch (const std::runtime_error &) {
-
630 rejected = true;
-
631 }
-
632 CHECK(rejected, "Ordinary overlapping signals rejected");
-
633}
-
634
-
635void DbcParserTest::invalidSignals() {
-
636 Fixture fixture;
-
637 const std::string ordinary = SignalLine("0", "8", "1+", "1", "0", "0", "255");
-
638 for (const std::string value: {"-1", "+1", "0junk", "0x10", "1.5",
-
639 "4294967296", "999999999999999999999"}) {
-
640 RejectSignal(fixture, SignalLine(value, "8", "1+", "1", "0", "0", "255"));
-
641 RejectSignal(fixture, SignalLine("0", value, "1+", "1", "0", "0", "255"));
-
642 }
-
643 for (const std::string length: {"0", "65"})
-
644 RejectSignal(fixture, SignalLine("0", length, "1+", "1", "0", "0", "255"));
-
645 for (const std::string order: {"2+", "9-", "1", "1x", "1++", "01+"})
-
646 RejectSignal(fixture, SignalLine("0", "8", order, "1", "0", "0", "255"));
-
647 for (const std::string value: {"1junk", "nan", "NaN", "inf", "-inf", "1e999", "1e-999", "0x1p2", "", "1e", "1.2.3"}) {
-
648 RejectSignal(fixture, SignalLine("0", "8", "1+", value, "0", "0", "255"));
-
649 RejectSignal(fixture, SignalLine("0", "8", "1+", "1", value, "0", "255"));
-
650 RejectSignal(fixture, SignalLine("0", "8", "1+", "1", "0", value, "255"));
-
651 RejectSignal(fixture, SignalLine("0", "8", "1+", "1", "0", "0", value));
-
652 }
-
653 RejectSignal(fixture, SignalLine("0", "8", "1+", "1", "0", "2", "1"));
-
654 for (const std::string name: {"", "Two Names", "Value m1M"}) {
-
655 std::string line = ordinary;
-
656 line.replace(4U, 5U, name);
-
657 RejectSignal(fixture, line);
-
658 }
-
659 for (const std::string broken: {
-
660 "SG_", "SG_ Value", "SG_ Value : 0|8@1+ (1,0) [0|255] ECU",
-
661 "SG_ Value : 0|8@1+ (1,0) [0|255] \"\"",
-
662 "SG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU,",
-
663 "SG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU extra"})
-
664 RejectSignal(fixture, broken);
-
665 RejectSignal(fixture, SignalLine("64", "1", "1+", "1", "0", "0", "1"));
-
666 RejectSignal(fixture, SignalLine("63", "2", "1+", "1", "0", "0", "3"));
-
667 RejectSignal(fixture, SignalLine("56", "2", "0+", "1", "0", "0", "3"));
-
668 RejectSignal(fixture, SignalLine("4294967295", "64", "1+", "1", "0", "0", "1"));
-
669 RejectSignal(fixture, ordinary, 0U);
-
670 for (const char delimiter: {'|', '@', '(', ')', '[', ']', '"'}) {
-
671 std::string line = ordinary;
-
672 line.erase(line.find(delimiter), 1U);
-
673 RejectSignal(fixture, line);
-
674 }
-
675}
-
676
-
677void DbcParserTest::validSignals() {
-
678 Fixture fixture;
-
679 const DbcParser signalParser;
-
680 fixture.Write("BO_ 1 Frame: 8 ECU\n" +
-
681 SignalLine("0", "8", "1+", "0", "0", "0", "0") + "\n" +
-
682 SignalLine("8", "8", "1-", "-1", "0", "-255", "0", "Negative") + "\n");
-
683 const DbcDatabase factors = signalParser.ParseFile(fixture.path.string());
-
684 CHECK(factors.frames[0].signals.size() == 2U &&
-
685 factors.frames[0].signals[0].factor == 0.0 &&
-
686 factors.frames[0].signals[1].factor == -1.0,
-
687 "Zero and negative factors and equal range boundaries");
-
688
-
689 struct SignalCase {
-
690 const char *start;
-
691 const char *length;
-
692 const char *order;
-
693 unsigned payload;
-
694 };
-
695 const SignalCase validSignals[] = {
-
696 {"0", "1", "1+", 1U},
-
697 {"7", "1", "0-", 1U},
-
698 {"0", "64", "1+", 8U},
-
699 {"7", "64", "0-", 8U},
-
700 {"63", "1", "1+", 8U},
-
701 {"56", "1", "0+", 8U},
-
702 {"3", "12", "0+", 2U},
-
703 {"2039", "1", "1+", 255U}};
-
704 for (const SignalCase &test: validSignals) {
-
705 fixture.Write("BO_ 1 Frame: " + std::to_string(test.payload) + " ECU\n" +
-
706 SignalLine(test.start, test.length, test.order, ".5e+1", "-2.5E-1", "-1.", "+2e2") + "\n");
-
707 try {
-
708 const DbcDatabase parsed = signalParser.ParseFile(fixture.path.string());
-
709 const SignalInfo &signal = parsed.frames.at(0).signals.at(0);
-
710 QCOMPARE(signal.startBit, static_cast<std::uint32_t>(std::stoul(test.start)));
-
711 QCOMPARE(signal.length, static_cast<std::uint32_t>(std::stoul(test.length)));
-
712 QCOMPARE(signal.isLittleEndian, test.order[0] == '1');
-
713 QCOMPARE(signal.isSigned, test.order[1] == '-');
-
714 QCOMPARE(signal.factor, 5.0);
-
715 QCOMPARE(signal.offset, -0.25);
-
716 QCOMPARE(signal.minimum, -1.0);
-
717 QCOMPARE(signal.maximum, 200.0);
-
718 } catch (const std::exception &error) { CHECK(false, error.what()); }
-
719 }
-
720 fixture.Write("BO_ 1 Frame: 8 ECU\n"
-
721 "SG_\tValue\t:\t0 | 8 @1+ ( 1 , 0 ) [ 0 | 255 ] \"rpm\" ECU1,\tECU2\n");
-
722 try {
-
723 const DbcDatabase parsed = signalParser.ParseFile(fixture.path.string());
-
724 const SignalInfo &signal = parsed.frames.at(0).signals.at(0);
-
725 CHECK(signal.name == "Value" && signal.unit == "rpm" &&
-
726 signal.receivers == std::vector<std::string>({"ECU1", "ECU2"}),
-
727 "Signal tabs, spaces, and receiver list");
-
728 } catch (const std::exception &error) { CHECK(false, error.what()); }
-
729}
-
730
-
731void DbcParserTest::dispatch() {
-
732 CountingHandler::instances = 0;
-
733 CountingHandler::calls = 0;
-
734 DbcDatabase dispatchDatabase;
-
735 DbcParseContext context{dispatchDatabase, nullptr};
-
736 DbcStatementDispatcher dispatcher;
-
737 dispatcher.RegisterType<CountingHandler>("TEST_");
-
738 CHECK(dispatcher.Dispatch("TEST_ first", context) &&
-
739 dispatcher.Dispatch("TEST_ second", context) &&
-
740 CountingHandler::instances == 1 && CountingHandler::calls == 2 &&
-
741 dispatchDatabase.frames.size() == 2U,
-
742 "Factory dispatch and handler reuse");
-
743 CHECK(!dispatcher.Dispatch("TEST_OTHER data", context) &&
-
744 !dispatcher.Dispatch("BO_TX_BU_ 1 : ECU;", context) &&
-
745 !dispatcher.Dispatch("VAL_TABLE_ States 0 \"Stopped\";", context) &&
-
746 CountingHandler::calls == 2,
-
747 "Exact and unknown keyword dispatch");
-
748}
-
749
-
750void DbcParserTest::independentSessions() {
-
751 Fixture fixture;
-
752 const DbcParser parser;
-
753 fixture.Write("BO_ 1 First: 8 ECU\n");
-
754 CHECK(parser.ParseFile(fixture.path.string()).frames.size() == 1U, "First parse");
-
755 fixture.Write("SG_ Speed : invalid\n");
-
756 try {
-
757 parser.ParseFile(fixture.path.string());
-
758 CHECK(false, "Independent parse context");
-
759 } catch (const std::runtime_error &error) {
-
760 CHECK(std::string(error.what()).find("Signal found before any frame") !=
-
761 std::string::npos,
-
762 "Independent parse context");
-
763 }
-
764 fixture.Write("BO_ 2 Second: 8 ECU\n");
-
765 const DbcDatabase recovered = parser.ParseFile(fixture.path.string());
-
766 CHECK(recovered.frames.size() == 1U && recovered.frames[0].canId == 2U,
-
767 "Fresh parse after error");
-
768}
-
769
-
770
-
771void DbcParserTest::valueDescriptions() {
-
772 Fixture fixture;
-
773 fixture.Write(
-
774 "VAL_\t256\tState\t0\t\"Off\"\t1 \"On\" 2 \"Error with spaces; and \\\"quotes\\\"\";\n"
-
775 "BO_ 256 Status: 8 ECU\n"
-
776 "SG_ State : 0|8@1+ (2,10) [0|520] \"\" ECU\n"
-
777 "VAL_ 256 State 3 \"\";\n"
-
778 "VAL_ 2147483904 State -9223372036854775808 \"Minimum\" -1 \"Negative\" 9223372036854775807 \"Maximum\";\n"
-
779 "BO_ 2147483904 Extended: 8 ECU\n"
-
780 "SG_ State : 0|64@1- (1,0) [-1e20|1e20] \"\" ECU\n"
-
781 "BO_ 2048 Unsigned: 8 ECU\n"
-
782 "SG_ State : 0|64@1+ (1,0) [0|2e20] \"\" ECU\n"
-
783 "VAL_ 2147485696 State 9223372036854775808 \"High\" 18446744073709551615 \"Full\";\n");
-
784 const DbcDatabase parsed = DbcParser().ParseFile(fixture.path.string());
-
785 const DecodeDatabase runtime = DbcDecodeBuilder().Build(parsed);
-
786 const std::unique_ptr<TreeNode> tree = DbcTreeBuilder().Build(parsed);
-
787 CHECK(tree->GetChild(0)->GetSignal() == nullptr, "Frame node");
-
788 for (std::size_t index = 0; index < parsed.frames.size(); ++index) {
-
789 CHECK(tree->GetChild(index)->GetChild(0)->GetSignal()->valueDescriptions ==
-
790 parsed.frames[index].signals[0].valueDescriptions &&
-
791 runtime.frames[index].signals[0].valueDescriptions ==
-
792 parsed.frames[index].signals[0].valueDescriptions,
-
793 "All mappings survive both builders");
-
794 }
-
795 CHECK(tree->GetChild(0)->GetChild(0)->GetSignal()->valueDescriptions ==
-
796 runtime.frames[0].signals[0].valueDescriptions,
-
797 "Both builders preserve descriptions");
-
798 RawCanFrame frame;
-
799 frame.canId = 256;
-
800 frame.data.resize(8);
-
801 const std::string expected[] = {"Off", "On", "Error with spaces; and \"quotes\"", ""};
-
802 for (unsigned value = 0; value < 5; ++value) {
-
803 frame.data[0] = value;
-
804 const DecodedSignalValue decoded = DbcDecoder().Decode(runtime, frame).signals[0];
-
805 CHECK(decoded.valid && decoded.physicalValue == value * 2 + 10, "Numeric scaling unchanged");
-
806 const std::string *description = decoded.GetValueDescription();
-
807 CHECK(value < 4 ? description && *description == expected[value] : !description,
-
808 "Raw lookup and unknown value");
-
809 }
-
810 frame.isExtended = true;
-
811 struct Boundary {
-
812 std::uint64_t bits;
-
813 const char *description;
-
814 };
-
815 for (const Boundary &test: {Boundary{0x8000000000000000ULL, "Minimum"},
-
816 Boundary{0xFFFFFFFFFFFFFFFFULL, "Negative"},
-
817 Boundary{0x7FFFFFFFFFFFFFFFULL, "Maximum"}}) {
-
818 for (unsigned byte = 0; byte < 8; ++byte)
-
819 frame.data[byte] = static_cast<std::uint8_t>(test.bits >> (byte * 8));
-
820 const DecodedSignalValue decoded = DbcDecoder().Decode(runtime, frame).signals[0];
-
821 CHECK(decoded.GetValueDescription() && *decoded.GetValueDescription() == test.description,
-
822 "Signed boundaries and distinct extended frame");
-
823 }
-
824 frame.canId = 2048;
-
825 for (const Boundary &test: {Boundary{0x8000000000000000ULL, "High"},
-
826 Boundary{0xFFFFFFFFFFFFFFFFULL, "Full"}}) {
-
827 for (unsigned byte = 0; byte < 8; ++byte)
-
828 frame.data[byte] = static_cast<std::uint8_t>(test.bits >> (byte * 8));
-
829 const DecodedSignalValue decoded = DbcDecoder().Decode(runtime, frame).signals[0];
-
830 CHECK(decoded.GetValueDescription() && *decoded.GetValueDescription() == test.description,
-
831 "Unsigned boundaries");
-
832 }
-
833 CHECK(FindValueDescription(runtime.frames[0].signals[0].valueDescriptions, std::int64_t(1)) != nullptr,
-
834 "Nonnegative signed lookup matches unsigned key");
-
835 frame.data.clear();
-
836 CHECK(!DbcDecoder().Decode(runtime, frame).signals[0].GetValueDescription(), "Invalid decode has no description");
-
837}
-
838
-
839void DbcParserTest::invalidValueDescriptions() {
-
840 Fixture fixture;
-
841 const std::string definitions = "BO_ 1 Frame: 8 ECU\nSG_ State : 0|64@1+ (1,0) [0|2e20] \"\" ECU\n";
-
842 for (const std::string statement: {
-
843 "VAL_", "VAL_ 1 State;", "VAL_ 1 State ;", "VAL_ 1 State 0 \"Off\"",
-
844 "VAL_ 1 State 0 \"Off\"; junk", "VAL_ 1 State 0 Off;",
-
845 "VAL_ 1 State 0 \"Unclosed;", "VAL_ 1 State 0 \"Off\"1 \"On\";",
-
846 "VAL_ 1 State 0 \"Off\" 00 \"Duplicate\";",
-
847 "VAL_ 1 State 0 \"Off\" -0 \"Duplicate\";",
-
848 "VAL_ 1 State 0 \"Off\";\nVAL_ 1 State 0 \"Duplicate\";",
-
849 "VAL_ 2 State 0 \"Missing frame\";", "VAL_ 1 Missing 0 \"Missing signal\";",
-
850 "VAL_ -1 State 0 \"Bad ID\";", "VAL_ 536870912 State 0 \"Bad ID\";",
-
851 "VAL_ 4294967296 State 0 \"Bad ID\";", "VAL_ Environment 0 \"Unsupported\";",
-
852 "VAL_ 1 State 0 \"Bad\\q escape\";"}) {
-
853 fixture.Write(definitions + statement + '\n');
-
854 const int line = statement.find('\n') == std::string::npos ? 3 : 4;
-
855 try {
-
856 DbcParser().ParseFile(fixture.path.string());
-
857 CHECK(false, statement);
-
858 } catch (const std::runtime_error &error) {
-
859 CHECK(std::string(error.what()).find(fixture.path.string() + ":" + std::to_string(line) + ": ") == 0,
-
860 statement + " " + error.what());
-
861 }
-
862 }
-
863 for (const std::string suffix: {
-
864 "BO_ 1 Other: 8 ECU\n", // Duplicate frame definition.
-
865 "SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n",// Duplicate signal definition.
-
866 ""}) {
-
867 fixture.Write("VAL_ 1 " + std::string(suffix.empty() ? "Missing" : "State") +
-
868 " 0 \"Description\";\n" + definitions + suffix);
-
869 try {
-
870 DbcParser().ParseFile(fixture.path.string());
-
871 CHECK(false, "Missing reference or duplicate definition");
-
872 } catch (const std::runtime_error &error) {
-
873 const std::string line = suffix.empty() ? "1" : "4";
-
874 CHECK(std::string(error.what()).find(fixture.path.string() + ":" + line + ": ") == 0,
-
875 "Error retains the reference or duplicate definition source location");
-
876 }
-
877 }
-
878 for (const std::string number: {"+1", "1x", "0x10", "1.5", "1e2", "--1",
-
879 "-9223372036854775809", "18446744073709551616"}) {
-
880 fixture.Write("VAL_ 1 State " + number + " \"Bad\";\n" + definitions);
-
881 try {
-
882 DbcParser().ParseFile(fixture.path.string());
-
883 CHECK(false, number);
-
884 } catch (const std::runtime_error &error) {
-
885 CHECK(std::string(error.what()).find(fixture.path.string() + ":1: ") == 0, number);
-
886 }
-
887 }
-
888}
-
889
-
890int RunParserTests(int argc, char **argv) {
-
891 DbcParserTest tests;
-
892 return QTest::qExec(&tests, argc, argv);
-
893}
-
894
-
895#include "dbc_parser_test.moc"
+
604 std::vector<DecodeFrame> definitions = runtime.GetFrames();
+
605 definitions[0].signals[1].length = 0U;
+
606 runtime = DecodeDatabase(definitions);
+
607 result = DbcDecoder().Decode(runtime, raw);
+
608 CHECK(result.signals[0].status == SignalDecodeStatus::InvalidDefinition &&
+
609 result.signals[1].status == SignalDecodeStatus::InvalidDefinition,
+
610 "Malformed runtime selector distinguished from payload errors");
+
611 definitions[0].signals.pop_back();
+
612 runtime = DecodeDatabase(definitions);
+
613 result = DbcDecoder().Decode(runtime, raw);
+
614 CHECK(result.signals[0].status == SignalDecodeStatus::InvalidDefinition,
+
615 "Missing runtime selector");
+
616 fixture.Write("BO_ 1 Frame: 2 ECU\n\n"
+
617 "SG_ Branch m2 : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
+
618 "SG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n");
+
619 bool rejected = false;
+
620 try {
+
621 DbcParser().ParseFile(fixture.path.string());
+
622 } catch (const std::runtime_error &error) {
+
623 rejected = std::string(error.what()).find(fixture.path.string() + ":3: ") == 0U;
+
624 }
+
625 CHECK(rejected, "Deferred validation reports branch source line");
+
626 fixture.Write("BO_ 1 Frame: 2 ECU\n"
+
627 "SG_ A : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
+
628 "SG_ B : 15|8@0+ (1,0) [0|255] \"\" ECU\n");
+
629 rejected = false;
+
630 try {
+
631 DbcParser().ParseFile(fixture.path.string());
+
632 } catch (const std::runtime_error &) {
+
633 rejected = true;
+
634 }
+
635 CHECK(rejected, "Ordinary overlapping signals rejected");
+
636}
+
637
+
638void DbcParserTest::invalidSignals() {
+
639 Fixture fixture;
+
640 const std::string ordinary = SignalLine("0", "8", "1+", "1", "0", "0", "255");
+
641 for (const std::string value: {"-1", "+1", "0junk", "0x10", "1.5",
+
642 "4294967296", "999999999999999999999"}) {
+
643 RejectSignal(fixture, SignalLine(value, "8", "1+", "1", "0", "0", "255"));
+
644 RejectSignal(fixture, SignalLine("0", value, "1+", "1", "0", "0", "255"));
+
645 }
+
646 for (const std::string length: {"0", "65"})
+
647 RejectSignal(fixture, SignalLine("0", length, "1+", "1", "0", "0", "255"));
+
648 for (const std::string order: {"2+", "9-", "1", "1x", "1++", "01+"})
+
649 RejectSignal(fixture, SignalLine("0", "8", order, "1", "0", "0", "255"));
+
650 for (const std::string value: {"1junk", "nan", "NaN", "inf", "-inf", "1e999", "1e-999", "0x1p2", "", "1e", "1.2.3"}) {
+
651 RejectSignal(fixture, SignalLine("0", "8", "1+", value, "0", "0", "255"));
+
652 RejectSignal(fixture, SignalLine("0", "8", "1+", "1", value, "0", "255"));
+
653 RejectSignal(fixture, SignalLine("0", "8", "1+", "1", "0", value, "255"));
+
654 RejectSignal(fixture, SignalLine("0", "8", "1+", "1", "0", "0", value));
+
655 }
+
656 RejectSignal(fixture, SignalLine("0", "8", "1+", "1", "0", "2", "1"));
+
657 for (const std::string name: {"", "Two Names", "Value m1M"}) {
+
658 std::string line = ordinary;
+
659 line.replace(4U, 5U, name);
+
660 RejectSignal(fixture, line);
+
661 }
+
662 for (const std::string broken: {
+
663 "SG_", "SG_ Value", "SG_ Value : 0|8@1+ (1,0) [0|255] ECU",
+
664 "SG_ Value : 0|8@1+ (1,0) [0|255] \"\"",
+
665 "SG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU,",
+
666 "SG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU extra"})
+
667 RejectSignal(fixture, broken);
+
668 RejectSignal(fixture, SignalLine("64", "1", "1+", "1", "0", "0", "1"));
+
669 RejectSignal(fixture, SignalLine("63", "2", "1+", "1", "0", "0", "3"));
+
670 RejectSignal(fixture, SignalLine("56", "2", "0+", "1", "0", "0", "3"));
+
671 RejectSignal(fixture, SignalLine("4294967295", "64", "1+", "1", "0", "0", "1"));
+
672 RejectSignal(fixture, ordinary, 0U);
+
673 for (const char delimiter: {'|', '@', '(', ')', '[', ']', '"'}) {
+
674 std::string line = ordinary;
+
675 line.erase(line.find(delimiter), 1U);
+
676 RejectSignal(fixture, line);
+
677 }
+
678}
+
679
+
680void DbcParserTest::validSignals() {
+
681 Fixture fixture;
+
682 const DbcParser signalParser;
+
683 fixture.Write("BO_ 1 Frame: 8 ECU\n" +
+
684 SignalLine("0", "8", "1+", "0", "0", "0", "0") + "\n" +
+
685 SignalLine("8", "8", "1-", "-1", "0", "-255", "0", "Negative") + "\n");
+
686 const DbcDatabase factors = signalParser.ParseFile(fixture.path.string());
+
687 CHECK(factors.frames[0].signals.size() == 2U &&
+
688 factors.frames[0].signals[0].factor == 0.0 &&
+
689 factors.frames[0].signals[1].factor == -1.0,
+
690 "Zero and negative factors and equal range boundaries");
+
691
+
692 struct SignalCase {
+
693 const char *start;
+
694 const char *length;
+
695 const char *order;
+
696 unsigned payload;
+
697 };
+
698 const SignalCase validSignals[] = {
+
699 {"0", "1", "1+", 1U},
+
700 {"7", "1", "0-", 1U},
+
701 {"0", "64", "1+", 8U},
+
702 {"7", "64", "0-", 8U},
+
703 {"63", "1", "1+", 8U},
+
704 {"56", "1", "0+", 8U},
+
705 {"3", "12", "0+", 2U},
+
706 {"2039", "1", "1+", 255U}};
+
707 for (const SignalCase &test: validSignals) {
+
708 fixture.Write("BO_ 1 Frame: " + std::to_string(test.payload) + " ECU\n" +
+
709 SignalLine(test.start, test.length, test.order, ".5e+1", "-2.5E-1", "-1.", "+2e2") + "\n");
+
710 try {
+
711 const DbcDatabase parsed = signalParser.ParseFile(fixture.path.string());
+
712 const SignalInfo &signal = parsed.frames.at(0).signals.at(0);
+
713 QCOMPARE(signal.startBit, static_cast<std::uint32_t>(std::stoul(test.start)));
+
714 QCOMPARE(signal.length, static_cast<std::uint32_t>(std::stoul(test.length)));
+
715 QCOMPARE(signal.isLittleEndian, test.order[0] == '1');
+
716 QCOMPARE(signal.isSigned, test.order[1] == '-');
+
717 QCOMPARE(signal.factor, 5.0);
+
718 QCOMPARE(signal.offset, -0.25);
+
719 QCOMPARE(signal.minimum, -1.0);
+
720 QCOMPARE(signal.maximum, 200.0);
+
721 } catch (const std::exception &error) { CHECK(false, error.what()); }
+
722 }
+
723 fixture.Write("BO_ 1 Frame: 8 ECU\n"
+
724 "SG_\tValue\t:\t0 | 8 @1+ ( 1 , 0 ) [ 0 | 255 ] \"rpm\" ECU1,\tECU2\n");
+
725 try {
+
726 const DbcDatabase parsed = signalParser.ParseFile(fixture.path.string());
+
727 const SignalInfo &signal = parsed.frames.at(0).signals.at(0);
+
728 CHECK(signal.name == "Value" && signal.unit == "rpm" &&
+
729 signal.receivers == std::vector<std::string>({"ECU1", "ECU2"}),
+
730 "Signal tabs, spaces, and receiver list");
+
731 } catch (const std::exception &error) { CHECK(false, error.what()); }
+
732}
+
733
+
734void DbcParserTest::dispatch() {
+
735 CountingHandler::instances = 0;
+
736 CountingHandler::calls = 0;
+
737 DbcDatabase dispatchDatabase;
+
738 DbcParseContext context{dispatchDatabase, nullptr};
+
739 DbcStatementDispatcher dispatcher;
+
740 dispatcher.RegisterType<CountingHandler>("TEST_");
+
741 CHECK(dispatcher.Dispatch("TEST_ first", context) &&
+
742 dispatcher.Dispatch("TEST_ second", context) &&
+
743 CountingHandler::instances == 1 && CountingHandler::calls == 2 &&
+
744 dispatchDatabase.frames.size() == 2U,
+
745 "Factory dispatch and handler reuse");
+
746 CHECK(!dispatcher.Dispatch("TEST_OTHER data", context) &&
+
747 !dispatcher.Dispatch("BO_TX_BU_ 1 : ECU;", context) &&
+
748 !dispatcher.Dispatch("VAL_TABLE_ States 0 \"Stopped\";", context) &&
+
749 CountingHandler::calls == 2,
+
750 "Exact and unknown keyword dispatch");
+
751}
+
752
+
753void DbcParserTest::independentSessions() {
+
754 Fixture fixture;
+
755 const DbcParser parser;
+
756 fixture.Write("BO_ 1 First: 8 ECU\n");
+
757 CHECK(parser.ParseFile(fixture.path.string()).frames.size() == 1U, "First parse");
+
758 fixture.Write("SG_ Speed : invalid\n");
+
759 try {
+
760 parser.ParseFile(fixture.path.string());
+
761 CHECK(false, "Independent parse context");
+
762 } catch (const std::runtime_error &error) {
+
763 CHECK(std::string(error.what()).find("Signal found before any frame") !=
+
764 std::string::npos,
+
765 "Independent parse context");
+
766 }
+
767 fixture.Write("BO_ 2 Second: 8 ECU\n");
+
768 const DbcDatabase recovered = parser.ParseFile(fixture.path.string());
+
769 CHECK(recovered.frames.size() == 1U && recovered.frames[0].canId == 2U,
+
770 "Fresh parse after error");
+
771}
+
772
+
773
+
774void DbcParserTest::valueDescriptions() {
+
775 Fixture fixture;
+
776 fixture.Write(
+
777 "VAL_\t256\tState\t0\t\"Off\"\t1 \"On\" 2 \"Error with spaces; and \\\"quotes\\\"\";\n"
+
778 "BO_ 256 Status: 8 ECU\n"
+
779 "SG_ State : 0|8@1+ (2,10) [0|520] \"\" ECU\n"
+
780 "VAL_ 256 State 3 \"\";\n"
+
781 "VAL_ 2147483904 State -9223372036854775808 \"Minimum\" -1 \"Negative\" 9223372036854775807 \"Maximum\";\n"
+
782 "BO_ 2147483904 Extended: 8 ECU\n"
+
783 "SG_ State : 0|64@1- (1,0) [-1e20|1e20] \"\" ECU\n"
+
784 "BO_ 2048 Unsigned: 8 ECU\n"
+
785 "SG_ State : 0|64@1+ (1,0) [0|2e20] \"\" ECU\n"
+
786 "VAL_ 2147485696 State 9223372036854775808 \"High\" 18446744073709551615 \"Full\";\n");
+
787 const DbcDatabase parsed = DbcParser().ParseFile(fixture.path.string());
+
788 const DecodeDatabase runtime = DbcDecodeBuilder().Build(parsed);
+
789 const std::unique_ptr<TreeNode> tree = DbcTreeBuilder().Build(parsed);
+
790 CHECK(tree->GetChild(0)->GetSignal() == nullptr, "Frame node");
+
791 for (std::size_t index = 0; index < parsed.frames.size(); ++index) {
+
792 CHECK(tree->GetChild(index)->GetChild(0)->GetSignal()->valueDescriptions ==
+
793 parsed.frames[index].signals[0].valueDescriptions &&
+
794 runtime.GetFrames()[index].signals[0].valueDescriptions ==
+
795 parsed.frames[index].signals[0].valueDescriptions,
+
796 "All mappings survive both builders");
+
797 }
+
798 CHECK(tree->GetChild(0)->GetChild(0)->GetSignal()->valueDescriptions ==
+
799 runtime.GetFrames()[0].signals[0].valueDescriptions,
+
800 "Both builders preserve descriptions");
+
801 RawCanFrame frame;
+
802 frame.canId = 256;
+
803 frame.data.resize(8);
+
804 const std::string expected[] = {"Off", "On", "Error with spaces; and \"quotes\"", ""};
+
805 for (unsigned value = 0; value < 5; ++value) {
+
806 frame.data[0] = value;
+
807 const DecodedSignalValue decoded = DbcDecoder().Decode(runtime, frame).signals[0];
+
808 CHECK(decoded.valid && decoded.physicalValue == value * 2 + 10, "Numeric scaling unchanged");
+
809 const std::string *description = decoded.GetValueDescription();
+
810 CHECK(value < 4 ? description && *description == expected[value] : !description,
+
811 "Raw lookup and unknown value");
+
812 }
+
813 frame.isExtended = true;
+
814 struct Boundary {
+
815 std::uint64_t bits;
+
816 const char *description;
+
817 };
+
818 for (const Boundary &test: {Boundary{0x8000000000000000ULL, "Minimum"},
+
819 Boundary{0xFFFFFFFFFFFFFFFFULL, "Negative"},
+
820 Boundary{0x7FFFFFFFFFFFFFFFULL, "Maximum"}}) {
+
821 for (unsigned byte = 0; byte < 8; ++byte)
+
822 frame.data[byte] = static_cast<std::uint8_t>(test.bits >> (byte * 8));
+
823 const DecodedSignalValue decoded = DbcDecoder().Decode(runtime, frame).signals[0];
+
824 CHECK(decoded.GetValueDescription() && *decoded.GetValueDescription() == test.description,
+
825 "Signed boundaries and distinct extended frame");
+
826 }
+
827 frame.canId = 2048;
+
828 for (const Boundary &test: {Boundary{0x8000000000000000ULL, "High"},
+
829 Boundary{0xFFFFFFFFFFFFFFFFULL, "Full"}}) {
+
830 for (unsigned byte = 0; byte < 8; ++byte)
+
831 frame.data[byte] = static_cast<std::uint8_t>(test.bits >> (byte * 8));
+
832 const DecodedSignalValue decoded = DbcDecoder().Decode(runtime, frame).signals[0];
+
833 CHECK(decoded.GetValueDescription() && *decoded.GetValueDescription() == test.description,
+
834 "Unsigned boundaries");
+
835 }
+
836 CHECK(FindValueDescription(runtime.GetFrames()[0].signals[0].valueDescriptions, std::int64_t(1)) != nullptr,
+
837 "Nonnegative signed lookup matches unsigned key");
+
838 frame.data.clear();
+
839 CHECK(!DbcDecoder().Decode(runtime, frame).signals[0].GetValueDescription(), "Invalid decode has no description");
+
840}
+
841
+
842void DbcParserTest::invalidValueDescriptions() {
+
843 Fixture fixture;
+
844 const std::string definitions = "BO_ 1 Frame: 8 ECU\nSG_ State : 0|64@1+ (1,0) [0|2e20] \"\" ECU\n";
+
845 for (const std::string statement: {
+
846 "VAL_", "VAL_ 1 State;", "VAL_ 1 State ;", "VAL_ 1 State 0 \"Off\"",
+
847 "VAL_ 1 State 0 \"Off\"; junk", "VAL_ 1 State 0 Off;",
+
848 "VAL_ 1 State 0 \"Unclosed;", "VAL_ 1 State 0 \"Off\"1 \"On\";",
+
849 "VAL_ 1 State 0 \"Off\" 00 \"Duplicate\";",
+
850 "VAL_ 1 State 0 \"Off\" -0 \"Duplicate\";",
+
851 "VAL_ 1 State 0 \"Off\";\nVAL_ 1 State 0 \"Duplicate\";",
+
852 "VAL_ 2 State 0 \"Missing frame\";", "VAL_ 1 Missing 0 \"Missing signal\";",
+
853 "VAL_ -1 State 0 \"Bad ID\";", "VAL_ 536870912 State 0 \"Bad ID\";",
+
854 "VAL_ 4294967296 State 0 \"Bad ID\";", "VAL_ Environment 0 \"Unsupported\";",
+
855 "VAL_ 1 State 0 \"Bad\\q escape\";"}) {
+
856 fixture.Write(definitions + statement + '\n');
+
857 const int line = statement.find('\n') == std::string::npos ? 3 : 4;
+
858 try {
+
859 DbcParser().ParseFile(fixture.path.string());
+
860 CHECK(false, statement);
+
861 } catch (const std::runtime_error &error) {
+
862 CHECK(std::string(error.what()).find(fixture.path.string() + ":" + std::to_string(line) + ": ") == 0,
+
863 statement + " " + error.what());
+
864 }
+
865 }
+
866 for (const std::string suffix: {
+
867 "BO_ 1 Other: 8 ECU\n", // Duplicate frame definition.
+
868 "SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n",// Duplicate signal definition.
+
869 ""}) {
+
870 fixture.Write("VAL_ 1 " + std::string(suffix.empty() ? "Missing" : "State") +
+
871 " 0 \"Description\";\n" + definitions + suffix);
+
872 try {
+
873 DbcParser().ParseFile(fixture.path.string());
+
874 CHECK(false, "Missing reference or duplicate definition");
+
875 } catch (const std::runtime_error &error) {
+
876 const std::string line = suffix.empty() ? "1" : "4";
+
877 CHECK(std::string(error.what()).find(fixture.path.string() + ":" + line + ": ") == 0,
+
878 "Error retains the reference or duplicate definition source location");
+
879 }
+
880 }
+
881 for (const std::string number: {"+1", "1x", "0x10", "1.5", "1e2", "--1",
+
882 "-9223372036854775809", "18446744073709551616"}) {
+
883 fixture.Write("VAL_ 1 State " + number + " \"Bad\";\n" + definitions);
+
884 try {
+
885 DbcParser().ParseFile(fixture.path.string());
+
886 CHECK(false, number);
+
887 } catch (const std::runtime_error &error) {
+
888 CHECK(std::string(error.what()).find(fixture.path.string() + ":1: ") == 0, number);
+
889 }
+
890 }
+
891}
+
892
+
893int RunParserTests(int argc, char **argv) {
+
894 DbcParserTest tests;
+
895 return QTest::qExec(&tests, argc, argv);
+
896}
+
897
+
898#include "dbc_parser_test.moc"
Converts parsed DBC data into runtime decode database.
-
DecodeDatabase Build(const DbcDatabase &source) const
Build runtime decode database.
-
Runtime CAN decoder using prebuilt decode database.
Definition dbc_decoder.h:72
-
DecodedFrameValue Decode(const DecodeDatabase &database, const RawCanFrame &frame) const
Decode one raw CAN frame.
+
DecodeDatabase Build(const DbcDatabase &source) const
Build runtime decode database.
+
Runtime CAN decoder using prebuilt decode database.
Definition dbc_decoder.h:74
+
DecodedFrameValue Decode(const DecodeDatabase &database, const RawCanFrame &frame) const
Decode one raw CAN frame.
Minimal DBC parser.
Definition dbc_parser.h:33
DbcParseResult ParseFileWithDiagnostics(const std::string &filePath) const
Parse with warnings and a structured first error instead of throwing.
DbcDatabase ParseFile(const std::string &filePath) const
Parse DBC file.
@@ -1005,6 +1008,8 @@ $(document).ready(function(){initNavTree('dbc__parser__test_8cpp_source.html',''
Builds a simple tree from parsed DBC database.
std::unique_ptr< TreeNode > Build(const DbcDatabase &database) const
Build tree representation of parsed DBC data.
+
Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles a...
+
const std::vector< DecodeFrame > & GetFrames() const
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
@@ -1014,15 +1019,13 @@ $(document).ready(function(){initNavTree('dbc__parser__test_8cpp_source.html','' -
Runtime decode database with fast lookup by CAN ID.
-
std::string comment
-
Fully decoded frame.
Definition dbc_decoder.h:61
- -
const DecodeFrame * definition
Definition dbc_decoder.h:62
+
Fully decoded frame.
Definition dbc_decoder.h:62
+
std::shared_ptr< const DecodeFrame > definition
Definition dbc_decoder.h:63
+
One decoded signal value.
Definition dbc_decoder.h:43
- - -
const std::string * GetValueDescription() const
Definition dbc_decoder.h:51
+ + +
const std::string * GetValueDescription() const
Definition dbc_decoder.h:52
Describes one CAN frame from a DBC file.
Definition frame_info.h:24
bool isExtended
Definition frame_info.h:27
std::string transmitter
Definition frame_info.h:31
diff --git a/docs/html/dbc__statement__handler_8cpp_source.html b/docs/html/dbc__statement__handler_8cpp_source.html index b515b56..d3c1516 100644 --- a/docs/html/dbc__statement__handler_8cpp_source.html +++ b/docs/html/dbc__statement__handler_8cpp_source.html @@ -632,7 +632,7 @@ $(document).ready(function(){initNavTree('dbc__statement__handler_8cpp_source.ht
530}
bool Dispatch(const std::string &line, DbcParseContext &context) const
-
ByteOrder
Signal byte order used for runtime decoding.
+
ByteOrder
Signal byte order used for runtime decoding.
Parsed DBC content stored in a simple internal form.
std::vector< FrameInfo > frames
diff --git a/docs/html/dbc__tree__model_8cpp_source.html b/docs/html/dbc__tree__model_8cpp_source.html index 2827a63..86d598a 100644 --- a/docs/html/dbc__tree__model_8cpp_source.html +++ b/docs/html/dbc__tree__model_8cpp_source.html @@ -254,7 +254,7 @@ $(document).ready(function(){initNavTree('dbc__tree__model_8cpp_source.html','')
std::size_t GetRow() const
Definition tree_node.cpp:72
NodeType GetType() const
Get node type.
Definition tree_node.cpp:52
const FrameInfo * GetFrame() const
Get frame payload if node is frame.
Definition tree_node.cpp:60
-
ByteOrder
Signal byte order used for runtime decoding.
+
ByteOrder
Signal byte order used for runtime decoding.
Describes one CAN frame from a DBC file.
Definition frame_info.h:24
bool isExtended
Definition frame_info.h:27
std::uint8_t dlc
Definition frame_info.h:30
diff --git a/docs/html/dbc__tree__model_8h_source.html b/docs/html/dbc__tree__model_8h_source.html index c485175..a3390c4 100644 --- a/docs/html/dbc__tree__model_8h_source.html +++ b/docs/html/dbc__tree__model_8h_source.html @@ -149,7 +149,7 @@ $(document).ready(function(){initNavTree('dbc__tree__model_8h_source.html','');
50#endif
Tree node for later use in model/view or other hierarchy consumers.
Definition tree_node.h:35
-
ByteOrder
Signal byte order used for runtime decoding.
+
ByteOrder
Signal byte order used for runtime decoding.
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
diff --git a/docs/html/decode__database_8cpp_source.html b/docs/html/decode__database_8cpp_source.html new file mode 100644 index 0000000..b145df5 --- /dev/null +++ b/docs/html/decode__database_8cpp_source.html @@ -0,0 +1,176 @@ + + + + + + + +DBC Framework: decode_database.cpp Source File + + + + + + + + + + + + + +
+
+ + + + + + +
+
DBC Framework +
+
DBC parsing and CAN signal decoding framework
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
decode_database.cpp
+
+
+
1// SPDX-License-Identifier: MIT
+
2// Copyright (c) 2026 Dim Himro
+
3
+
4#include "decode_database.h"
+
5#include <stdexcept>
+
6#include <unordered_set>
+
7#include <utility>
+
8
+
9DecodeDatabase::Storage::Storage(std::vector<DecodeFrame> definitions)
+
10 : frames(std::move(definitions)) {
+
11 frameIndexByKey.reserve(frames.size());
+
12 for (std::size_t index = 0U; index < frames.size(); ++index) {
+
13 const DecodeFrame &frame = frames[index];
+
14 if (!frameIndexByKey.emplace(frame.GetKey(), index).second)
+
15 throw std::invalid_argument("Duplicate runtime frame key");
+
16 std::unordered_set<std::string> names;
+
17 for (const DecodeSignal &signal: frame.signals) {
+
18 if (!names.insert(signal.name).second)
+
19 throw std::invalid_argument("Duplicate runtime signal key");
+
20 }
+
21 }
+
22}
+
23
+
+
24DecodeDatabase::DecodeDatabase(std::vector<DecodeFrame> frames)
+
25 : storage(std::make_shared<const Storage>(std::move(frames))) {
+
26}
+
+
27
+
+
28const std::vector<DecodeFrame> &DecodeDatabase::GetFrames() const {
+
29 static const std::vector<DecodeFrame> empty;
+
30 return storage ? storage->frames : empty;
+
31}
+
+
32
+
+
33std::shared_ptr<const DecodeFrame> DecodeDatabase::FindFrame(const FrameKey &key) const {
+
34 if (!storage)
+
35 return nullptr;
+
36 const std::unordered_map<FrameKey, std::size_t, FrameKeyHasher>::const_iterator it =
+
37 storage->frameIndexByKey.find(key);
+
38 if (it == storage->frameIndexByKey.end())
+
39 return nullptr;
+
40 return std::shared_ptr<const DecodeFrame>(storage, &storage->frames[it->second]);
+
41}
+
+
42
+
43std::shared_ptr<const DecodeSignal> DecodeDatabase::FindSignal(const SignalKey &key) const {
+
44 const std::shared_ptr<const DecodeFrame> frame = FindFrame(key.frame);
+
45 if (!frame)
+
46 return nullptr;
+
47 for (const DecodeSignal &signal: frame->signals) {
+
48 if (signal.name == key.name)
+
49 return std::shared_ptr<const DecodeSignal>(frame, &signal);
+
50 }
+
51 return nullptr;
+
52}
+
std::shared_ptr< const DecodeFrame > FindFrame(const FrameKey &key) const
+
const std::vector< DecodeFrame > & GetFrames() const
+
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Runtime-ready frame definition.
+
Runtime-ready signal definition.
+
Stable frame identifier: normalized CAN ID and frame type.
+ +
+
+ + + + diff --git a/docs/html/decode__database_8h.html b/docs/html/decode__database_8h.html index f002d94..7a90096 100644 --- a/docs/html/decode__database_8h.html +++ b/docs/html/decode__database_8h.html @@ -99,9 +99,11 @@ $(document).ready(function(){initNavTree('decode__database_8h.html',''); initRes

Created: 2026-03-13 Author: Deeaitch (Dim. Himro) More...

-
#include "value_descriptions.h"
+
#include "definition_key.h"
#include "multiplexing.h"
+#include "value_descriptions.h"
#include <cstdint>
+#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
@@ -116,14 +118,8 @@ Classes struct  DecodeFrame  Runtime-ready frame definition. More...
  -struct  FrameKey - Key for fast frame lookup. More...
-  -struct  FrameKeyHasher - Hasher for frame key. More...
-  -struct  DecodeDatabase - Runtime decode database with fast lookup by CAN ID. More...
+class  DecodeDatabase + Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles and decoded results keep old definitions alive. More...
 

Signal byte order used for runtime decoding.

-

Definition at line 25 of file decode_database.h.

+

Definition at line 27 of file decode_database.h.

@@ -193,7 +189,7 @@ Enumerations

Signal numeric type.

-

Definition at line 33 of file decode_database.h.

+

Definition at line 35 of file decode_database.h.

diff --git a/docs/html/decode__database_8h.js b/docs/html/decode__database_8h.js index 5fce961..fad6f3e 100644 --- a/docs/html/decode__database_8h.js +++ b/docs/html/decode__database_8h.js @@ -2,9 +2,7 @@ var decode__database_8h = [ [ "DecodeSignal", "structDecodeSignal.html", "structDecodeSignal" ], [ "DecodeFrame", "structDecodeFrame.html", "structDecodeFrame" ], - [ "FrameKey", "structFrameKey.html", null ], - [ "FrameKeyHasher", "structFrameKeyHasher.html", null ], - [ "DecodeDatabase", "structDecodeDatabase.html", null ], + [ "DecodeDatabase", "classDecodeDatabase.html", "classDecodeDatabase" ], [ "ByteOrder", "decode__database_8h.html#aaeb92d42f5a6e27b8ba19f18d69d142b", [ [ "Intel", "decode__database_8h.html#aaeb92d42f5a6e27b8ba19f18d69d142baff97a9fdede09eaf6e1c8ec9f6a61dd5", null ], [ "Motorola", "decode__database_8h.html#aaeb92d42f5a6e27b8ba19f18d69d142ba2ed1afe3c9215523e4272f46e6186b31", null ] diff --git a/docs/html/decode__database_8h_source.html b/docs/html/decode__database_8h_source.html index e241bc0..15f26f9 100644 --- a/docs/html/decode__database_8h_source.html +++ b/docs/html/decode__database_8h_source.html @@ -102,126 +102,122 @@ $(document).ready(function(){initNavTree('decode__database_8h_source.html','');
12#ifndef DECODE_DATABASE_H
13#define DECODE_DATABASE_H
14
-
15#include "value_descriptions.h"
+
15#include "definition_key.h"
16#include "multiplexing.h"
-
17#include <cstdint>
-
18#include <string>
-
19#include <unordered_map>
-
20#include <vector>
-
21
-
-
25enum class ByteOrder {
-
26 Intel,
-
27 Motorola
-
28};
+
17#include "value_descriptions.h"
+
18#include <cstdint>
+
19#include <memory>
+
20#include <string>
+
21#include <unordered_map>
+
22#include <vector>
+
23
+
+
27enum class ByteOrder {
+
28 Intel,
+
29 Motorola
+
30};
-
29
-
-
33enum class ValueType {
-
34 Unsigned,
-
35 Signed
-
36};
+
31
+
+
35enum class ValueType {
+
36 Unsigned,
+
37 Signed
+
38};
-
37
-
- -
42 Multiplexing multiplexing;
-
43 std::string name;
-
44 std::uint32_t startBit = 0U;
-
45 std::uint32_t length = 0U;
-
46 ByteOrder byteOrder = ByteOrder::Intel;
-
47 ValueType valueType = ValueType::Unsigned;
-
48 double factor = 1.0;
-
49 double offset = 0.0;
-
50 double minimum = 0.0;
-
51 double maximum = 0.0;
-
52 std::string unit;
-
53 std::vector<std::string> receivers;
-
54 ValueDescriptions valueDescriptions;
-
55 std::string comment;
-
57 DecodeSignal() = default;
-
58};
+
39
+
+ +
44 Multiplexing multiplexing;
+
45 std::string name;
+
46 std::uint32_t startBit = 0U;
+
47 std::uint32_t length = 0U;
+
48 ByteOrder byteOrder = ByteOrder::Intel;
+
49 ValueType valueType = ValueType::Unsigned;
+
50 double factor = 1.0;
+
51 double offset = 0.0;
+
52 double minimum = 0.0;
+
53 double maximum = 0.0;
+
54 std::string unit;
+
55 std::vector<std::string> receivers;
+
56 ValueDescriptions valueDescriptions;
+
57 std::string comment;
+
59 DecodeSignal() = default;
+
60};
-
59
-
- -
64 std::string name;
-
65 std::uint32_t canId = 0U;
-
66 bool isExtended = false;
-
67 std::uint8_t dlc = 0U;
-
68 std::uint32_t pgn = 0U;
-
69 bool hasPgn = false;
-
70 std::string transmitter;
-
71 std::string comment;
-
72 std::vector<DecodeSignal> signals;
-
74 DecodeFrame() = default;
-
75};
+
61
+
+ +
66 std::string name;
+
67 std::uint32_t canId = 0U;
+
68 bool isExtended = false;
+
69 std::uint8_t dlc = 0U;
+
70 std::uint32_t pgn = 0U;
+
71 bool hasPgn = false;
+
72 std::string transmitter;
+
73 std::string comment;
+
74 std::vector<DecodeSignal> signals;
+
76 DecodeFrame() = default;
+
77
+
78 FrameKey GetKey() const {
+
79 return FrameKey(canId, isExtended);
+
80 }
+
81};
-
76
-
-
80struct FrameKey {
-
81 std::uint32_t canId = 0U;
-
82 bool isExtended = false;
-
83
-
84 FrameKey() = default;
-
85
-
86 FrameKey(std::uint32_t id, bool extended)
-
87 : canId(id), isExtended(extended) {
-
88 }
-
89
-
90 bool operator==(const FrameKey &other) const {
-
91 return (canId == other.canId) && (isExtended == other.isExtended);
-
92 }
-
93};
-
-
94
-
- -
99 std::size_t operator()(const FrameKey &key) const {
-
100 const std::size_t a = static_cast<std::size_t>(key.canId);
-
101 const std::size_t b = key.isExtended ? 1U : 0U;
-
102 return (a * 1315423911U) ^ b;
-
103 }
-
104};
-
-
105
-
- -
110 std::vector<DecodeFrame> frames;
-
111 std::unordered_map<FrameKey, std::size_t, FrameKeyHasher> frameIndexByKey;
+
82
+
+ +
88public:
+
89 DecodeDatabase() = default;
+
95 explicit DecodeDatabase(std::vector<DecodeFrame> frames);
+
96
+
98 const std::vector<DecodeFrame> &GetFrames() const;
+
100 std::shared_ptr<const DecodeFrame> FindFrame(const FrameKey &key) const;
+
101 std::shared_ptr<const DecodeSignal> FindSignal(const SignalKey &key) const;
+
102
+
103private:
+
104 struct Storage {
+
105 std::vector<DecodeFrame> frames;
+
106 std::unordered_map<FrameKey, std::size_t, FrameKeyHasher> frameIndexByKey;
+
107
+
108 explicit Storage(std::vector<DecodeFrame> definitions);
+
109 };
+
110
+
111 std::shared_ptr<const Storage> storage;
112};
113
114#endif /* DECODE_DATABASE_H */
-
ByteOrder
Signal byte order used for runtime decoding.
-
ValueType
Signal numeric type.
-
Runtime decode database with fast lookup by CAN ID.
-
Runtime-ready frame definition.
-
std::uint32_t pgn
- -
std::string comment
- -
std::uint8_t dlc
-
std::uint32_t canId
-
std::string name
-
std::string transmitter
-
Runtime-ready signal definition.
- -
std::string unit
- - -
std::string name
-
ValueDescriptions valueDescriptions
- -
ValueType valueType
-
std::uint32_t startBit
-
std::vector< std::string > receivers
-
ByteOrder byteOrder
-
std::uint32_t length
-
std::string comment
-
Hasher for frame key.
-
Key for fast frame lookup.
+
Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles a...
+
std::shared_ptr< const DecodeFrame > FindFrame(const FrameKey &key) const
+
const std::vector< DecodeFrame > & GetFrames() const
+
ByteOrder
Signal byte order used for runtime decoding.
+
ValueType
Signal numeric type.
+
Runtime-ready frame definition.
+
std::uint32_t pgn
+ +
std::string comment
+ +
std::uint8_t dlc
+
std::uint32_t canId
+
std::string name
+
std::string transmitter
+
Runtime-ready signal definition.
+ +
std::string unit
+ + +
std::string name
+
ValueDescriptions valueDescriptions
+ +
ValueType valueType
+
std::uint32_t startBit
+
std::vector< std::string > receivers
+
ByteOrder byteOrder
+
std::uint32_t length
+
std::string comment
+
Stable frame identifier: normalized CAN ID and frame type.
+
diff --git a/docs/html/definition__key_8h_source.html b/docs/html/definition__key_8h_source.html new file mode 100644 index 0000000..a9d0490 --- /dev/null +++ b/docs/html/definition__key_8h_source.html @@ -0,0 +1,178 @@ + + + + + + + +DBC Framework: definition_key.h Source File + + + + + + + + + + + + + +
+
+

@@ -167,7 +163,7 @@ Enumerations

+ + + + + +
+
DBC Framework +
+
DBC parsing and CAN signal decoding framework
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
definition_key.h
+
+
+
1// SPDX-License-Identifier: MIT
+
2// Copyright (c) 2026 Dim Himro
+
3
+
4#ifndef DEFINITION_KEY_H
+
5#define DEFINITION_KEY_H
+
6
+
7#include <cstdint>
+
8#include <functional>
+
9#include <string>
+
10#include <utility>
+
11
+
+
15struct FrameKey {
+
16 std::uint32_t canId = 0U;
+
17 bool isExtended = false;
+
18
+
19 FrameKey() = default;
+
20
+
21 FrameKey(std::uint32_t id, bool extended)
+
22 : canId(id), isExtended(extended) {
+
23 }
+
24
+
25 bool operator==(const FrameKey &other) const {
+
26 return (canId == other.canId) && (isExtended == other.isExtended);
+
27 }
+
28};
+
+
29
+
+ +
34 std::size_t operator()(const FrameKey &key) const {
+
35 const std::size_t a = static_cast<std::size_t>(key.canId);
+
36 const std::size_t b = key.isExtended ? 1U : 0U;
+
37 return (a * 1315423911U) ^ b;
+
38 }
+
39};
+
+
40
+
+
42struct SignalKey {
+
43 FrameKey frame;
+
44 std::string name;
+
45
+
46 SignalKey() = default;
+
47 SignalKey(FrameKey frameKey, std::string signalName)
+
48 : frame(frameKey), name(std::move(signalName)) {
+
49 }
+
50
+
51 bool operator==(const SignalKey &other) const {
+
52 return frame == other.frame && name == other.name;
+
53 }
+
54};
+
+
55
+
+ +
57 std::size_t operator()(const SignalKey &key) const {
+
58 return FrameKeyHasher()(key.frame) ^ (std::hash<std::string>()(key.name) << 1U);
+
59 }
+
60};
+
+
61
+
62#endif /* DEFINITION_KEY_H */
+
Hasher for frame key.
+
Stable frame identifier: normalized CAN ID and frame type.
+ + +
+
+ + + + diff --git a/docs/html/dir_4270bfced15e0e73154b13468c7c9ad9.html b/docs/html/dir_4270bfced15e0e73154b13468c7c9ad9.html index f56e574..17724eb 100644 --- a/docs/html/dir_4270bfced15e0e73154b13468c7c9ad9.html +++ b/docs/html/dir_4270bfced15e0e73154b13468c7c9ad9.html @@ -129,9 +129,13 @@ Files  dbc_tree_builder.h  Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
  + decode_database.cpp +   decode_database.h  Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
  + definition_key.h +   frame_info.h  Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
  diff --git a/docs/html/dir_4270bfced15e0e73154b13468c7c9ad9.js b/docs/html/dir_4270bfced15e0e73154b13468c7c9ad9.js index 33f3e57..3a2182e 100644 --- a/docs/html/dir_4270bfced15e0e73154b13468c7c9ad9.js +++ b/docs/html/dir_4270bfced15e0e73154b13468c7c9ad9.js @@ -12,7 +12,9 @@ var dir_4270bfced15e0e73154b13468c7c9ad9 = [ "dbc_statement_handler.h", "dbc__statement__handler_8h_source.html", null ], [ "dbc_tree_builder.cpp", "dbc__tree__builder_8cpp.html", null ], [ "dbc_tree_builder.h", "dbc__tree__builder_8h.html", "dbc__tree__builder_8h" ], + [ "decode_database.cpp", "decode__database_8cpp_source.html", null ], [ "decode_database.h", "decode__database_8h.html", "decode__database_8h" ], + [ "definition_key.h", "definition__key_8h_source.html", null ], [ "frame_info.h", "frame__info_8h.html", "frame__info_8h" ], [ "multiplexing.h", "multiplexing_8h_source.html", null ], [ "signal_info.h", "signal__info_8h.html", "signal__info_8h" ], diff --git a/docs/html/dir_59425e443f801f1f2fd8bbe4959a3ccf.html b/docs/html/dir_59425e443f801f1f2fd8bbe4959a3ccf.html index 3601aa5..060b2ea 100644 --- a/docs/html/dir_59425e443f801f1f2fd8bbe4959a3ccf.html +++ b/docs/html/dir_59425e443f801f1f2fd8bbe4959a3ccf.html @@ -100,6 +100,8 @@ Files    dbc_decoder_test.cpp   + dbc_lifetime_test.cpp +   dbc_parser_test.cpp    dbc_tree_model_test.cpp diff --git a/docs/html/dir_59425e443f801f1f2fd8bbe4959a3ccf.js b/docs/html/dir_59425e443f801f1f2fd8bbe4959a3ccf.js index 8743b94..74e6d20 100644 --- a/docs/html/dir_59425e443f801f1f2fd8bbe4959a3ccf.js +++ b/docs/html/dir_59425e443f801f1f2fd8bbe4959a3ccf.js @@ -2,6 +2,7 @@ var dir_59425e443f801f1f2fd8bbe4959a3ccf = [ [ "dbc_coverage_test.cpp", "dbc__coverage__test_8cpp_source.html", null ], [ "dbc_decoder_test.cpp", "dbc__decoder__test_8cpp_source.html", null ], + [ "dbc_lifetime_test.cpp", "dbc__lifetime__test_8cpp_source.html", null ], [ "dbc_parser_test.cpp", "dbc__parser__test_8cpp_source.html", null ], [ "dbc_tree_model_test.cpp", "dbc__tree__model__test_8cpp_source.html", null ], [ "tests/main.cpp", "tests_2main_8cpp_source.html", null ], diff --git a/docs/html/examples_2main_8cpp_source.html b/docs/html/examples_2main_8cpp_source.html index 9f0ec34..fbc9d49 100644 --- a/docs/html/examples_2main_8cpp_source.html +++ b/docs/html/examples_2main_8cpp_source.html @@ -163,12 +163,12 @@ $(document).ready(function(){initNavTree('examples_2main_8cpp_source.html','');
73}
74
75static void PrintDecodedFrame(const DecodedFrameValue &decoded) {
-
76 if (!decoded.valid || (decoded.definition == nullptr)) {
+
76 if (!decoded.valid || (decoded.definition == nullptr)) {
77 std::cout << "No frame definition found.\n";
78 return;
79 }
80
-
81 std::cout << "Decoded frame: " << decoded.definition->name << "\n";
+
81 std::cout << "Decoded frame: " << decoded.definition->name << "\n";
82
83 for (const DecodedSignalValue &signal : decoded.signals) {
84
@@ -204,15 +204,15 @@ $(document).ready(function(){initNavTree('examples_2main_8cpp_source.html','');
114 PrintTree(root.get(), 0);
115
116 DbcDecodeBuilder decodeBuilder;
-
117 DecodeDatabase decodeDatabase = decodeBuilder.Build(database);
+
117 DecodeDatabase decodeDatabase = decodeBuilder.Build(database);
118
119 /*
120 * Example raw frame.
121 * Replace with live CAN frame or trace record later.
122 */
123 RawCanFrame rawFrame;
-
124 rawFrame.canId = decodeDatabase.frames.empty() ? 0U : decodeDatabase.frames[0].canId;
-
125 rawFrame.isExtended = decodeDatabase.frames.empty() ? false : decodeDatabase.frames[0].isExtended;
+
124 rawFrame.canId = decodeDatabase.GetFrames().empty() ? 0U : decodeDatabase.GetFrames()[0].canId;
+
125 rawFrame.isExtended = decodeDatabase.GetFrames().empty() ? false : decodeDatabase.GetFrames()[0].isExtended;
126 rawFrame.data.resize(8U, 0U);
127
128 DbcDecoder decoder;
@@ -228,13 +228,15 @@ $(document).ready(function(){initNavTree('examples_2main_8cpp_source.html','');
138 return 0;
139}
Converts parsed DBC data into runtime decode database.
-
DecodeDatabase Build(const DbcDatabase &source) const
Build runtime decode database.
-
Runtime CAN decoder using prebuilt decode database.
Definition dbc_decoder.h:72
-
DecodedFrameValue Decode(const DecodeDatabase &database, const RawCanFrame &frame) const
Decode one raw CAN frame.
+
DecodeDatabase Build(const DbcDatabase &source) const
Build runtime decode database.
+
Runtime CAN decoder using prebuilt decode database.
Definition dbc_decoder.h:74
+
DecodedFrameValue Decode(const DecodeDatabase &database, const RawCanFrame &frame) const
Decode one raw CAN frame.
Minimal DBC parser.
Definition dbc_parser.h:33
DbcDatabase ParseFile(const std::string &filePath) const
Parse DBC file.
Builds a simple tree from parsed DBC database.
std::unique_ptr< TreeNode > Build(const DbcDatabase &database) const
Build tree representation of parsed DBC data.
+
Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles a...
+
const std::vector< DecodeFrame > & GetFrames() const
Tree node for later use in model/view or other hierarchy consumers.
Definition tree_node.h:35
const SignalInfo * GetSignal() const
Get signal payload if node is signal.
Definition tree_node.cpp:64
const TreeNode * GetChild(std::size_t index) const
Get child by index.
Definition tree_node.cpp:38
@@ -247,11 +249,9 @@ $(document).ready(function(){initNavTree('examples_2main_8cpp_source.html','');
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Parsed DBC content stored in a simple internal form.
-
Runtime decode database with fast lookup by CAN ID.
-
std::string name
-
Fully decoded frame.
Definition dbc_decoder.h:61
- -
const DecodeFrame * definition
Definition dbc_decoder.h:62
+
Fully decoded frame.
Definition dbc_decoder.h:62
+
std::shared_ptr< const DecodeFrame > definition
Definition dbc_decoder.h:63
+
One decoded signal value.
Definition dbc_decoder.h:43
Describes one CAN frame from a DBC file.
Definition frame_info.h:24
bool isExtended
Definition frame_info.h:27
diff --git a/docs/html/files.html b/docs/html/files.html index 10f4bd5..85ba198 100644 --- a/docs/html/files.html +++ b/docs/html/files.html @@ -108,15 +108,17 @@ $(document).ready(function(){initNavTree('files.html',''); initResizable(); });  dbc_statement_handler.h  dbc_tree_builder.cppCreated: 2026-03-13 Author: Deeaitch (Dim. Himro)  dbc_tree_builder.hCreated: 2026-03-13 Author: Deeaitch (Dim. Himro) - decode_database.hCreated: 2026-03-13 Author: Deeaitch (Dim. Himro) - frame_info.hCreated: 2026-03-13 Author: Deeaitch (Dim. Himro) - multiplexing.h - signal_info.hCreated: 2026-03-13 Author: Deeaitch (Dim. Himro) - text_utils.h - tree_node.cppCreated: 2026-03-13 Author: Deeaitch (Dim. Himro) - tree_node.hCreated: 2026-03-13 Author: Deeaitch (Dim. Himro) - typefactory.h - value_descriptions.h + decode_database.cpp + decode_database.hCreated: 2026-03-13 Author: Deeaitch (Dim. Himro) + definition_key.h + frame_info.hCreated: 2026-03-13 Author: Deeaitch (Dim. Himro) + multiplexing.h + signal_info.hCreated: 2026-03-13 Author: Deeaitch (Dim. Himro) + text_utils.h + tree_node.cppCreated: 2026-03-13 Author: Deeaitch (Dim. Himro) + tree_node.hCreated: 2026-03-13 Author: Deeaitch (Dim. Himro) + typefactory.h + value_descriptions.h  ▼ examples  main.cppCreated: 2026-03-13 Author: Deeaitch (Dim. Himro)  ▼ qt @@ -125,10 +127,11 @@ $(document).ready(function(){initNavTree('files.html',''); initResizable(); });  ▼ tests  dbc_coverage_test.cpp  dbc_decoder_test.cpp - dbc_parser_test.cpp - dbc_tree_model_test.cpp - main.cpp - tree_node_test.cpp + dbc_lifetime_test.cpp + dbc_parser_test.cpp + dbc_tree_model_test.cpp + main.cpp + tree_node_test.cpp diff --git a/docs/html/functions.html b/docs/html/functions.html index 2ddb63d..c891107 100644 --- a/docs/html/functions.html +++ b/docs/html/functions.html @@ -115,7 +115,8 @@ $(document).ready(function(){initNavTree('functions.html',''); initResizable();

- d -

@@ -123,7 +124,7 @@ $(document).ready(function(){initNavTree('functions.html',''); initResizable();

- f -

@@ -132,6 +133,7 @@ $(document).ready(function(){initNavTree('functions.html',''); initResizable();
  • GetChild() : TreeNode
  • GetChildCount() : TreeNode
  • GetFrame() : TreeNode
  • +
  • GetFrames() : DecodeDatabase
  • GetName() : TreeNode
  • GetParent() : TreeNode
  • GetRow() : TreeNode
  • @@ -153,6 +155,11 @@ $(document).ready(function(){initNavTree('functions.html',''); initResizable(); +

    - k -

    + +

    - l -

    diff --git a/docs/html/functions_func.html b/docs/html/functions_func.html index 69aa63a..579da61 100644 --- a/docs/html/functions_func.html +++ b/docs/html/functions_func.html @@ -97,11 +97,13 @@ $(document).ready(function(){initNavTree('functions_func.html',''); initResizabl
  • create() : TypeFactory< ClassId, BaseClass, Args >
  • creator() : TypeFactory< ClassId, BaseClass, Args >
  • Decode() : DbcDecoder
  • +
  • DecodeDatabase() : DecodeDatabase
  • Dispatch() : DbcStatementDispatcher
  • -
  • FindFrame() : DbcDecoder
  • +
  • FindFrame() : DbcDecoder, DecodeDatabase
  • GetChild() : TreeNode
  • GetChildCount() : TreeNode
  • GetFrame() : TreeNode
  • +
  • GetFrames() : DecodeDatabase
  • GetName() : TreeNode
  • GetParent() : TreeNode
  • GetRow() : TreeNode
  • diff --git a/docs/html/functions_vars.html b/docs/html/functions_vars.html index 36265bb..1c8e905 100644 --- a/docs/html/functions_vars.html +++ b/docs/html/functions_vars.html @@ -105,7 +105,7 @@ $(document).ready(function(){initNavTree('functions_vars.html',''); initResizabl

    - d -

    @@ -128,6 +128,11 @@ $(document).ready(function(){initNavTree('functions_vars.html',''); initResizabl +

    - k -

    + +

    - l -

    diff --git a/docs/html/hierarchy.html b/docs/html/hierarchy.html index fee79e2..8c64f68 100644 --- a/docs/html/hierarchy.html +++ b/docs/html/hierarchy.html @@ -113,7 +113,7 @@ This inheritance list is sorted roughly, but not completely, alphabetically: CDbcUnsupportedMultiplexingHandler  CDbcValueDescriptionHandler  CDbcTreeBuilderBuilds a simple tree from parsed DBC database - CDecodeDatabaseRuntime decode database with fast lookup by CAN ID + CDecodeDatabaseImmutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles and decoded results keep old definitions alive  CDecodedFrameValueFully decoded frame  CDecodedSignalValueOne decoded signal value  CDecodeFrameRuntime-ready frame definition @@ -122,7 +122,7 @@ This inheritance list is sorted roughly, but not completely, alphabetically: ▼Cstd::runtime_errorSTL class  CDbcDiagnosticError  CFrameInfoDescribes one CAN frame from a DBC file - CFrameKeyKey for fast frame lookup + CFrameKeyStable frame identifier: normalized CAN ID and frame type  CFrameKeyHasherHasher for frame key  CMultiplexing  CPendingValueDescriptions @@ -130,9 +130,11 @@ This inheritance list is sorted roughly, but not completely, alphabetically: CDbcTreeModel  CRawCanFrameRaw CAN frame used for runtime or trace decoding  CSignalInfoDescribes one signal inside a DBC frame - CTreeNodeTree node for later use in model/view or other hierarchy consumers - CTypeFactory< ClassId, BaseClass, Args >Registry-based factory for creating objects by runtime identifier - CTypeFactory< std::string, DbcStatementHandler > + CSignalKey + CSignalKeyHasher + CTreeNodeTree node for later use in model/view or other hierarchy consumers + CTypeFactory< ClassId, BaseClass, Args >Registry-based factory for creating objects by runtime identifier + CTypeFactory< std::string, DbcStatementHandler > diff --git a/docs/html/hierarchy.js b/docs/html/hierarchy.js index e2a8401..9a2cd08 100644 --- a/docs/html/hierarchy.js +++ b/docs/html/hierarchy.js @@ -17,7 +17,7 @@ var hierarchy = [ "DbcValueDescriptionHandler", "classDbcValueDescriptionHandler.html", null ] ] ], [ "DbcTreeBuilder", "classDbcTreeBuilder.html", null ], - [ "DecodeDatabase", "structDecodeDatabase.html", null ], + [ "DecodeDatabase", "classDecodeDatabase.html", null ], [ "DecodedFrameValue", "structDecodedFrameValue.html", null ], [ "DecodedSignalValue", "structDecodedSignalValue.html", null ], [ "DecodeFrame", "structDecodeFrame.html", null ], @@ -37,6 +37,8 @@ var hierarchy = ] ], [ "RawCanFrame", "structRawCanFrame.html", null ], [ "SignalInfo", "structSignalInfo.html", null ], + [ "SignalKey", "structSignalKey.html", null ], + [ "SignalKeyHasher", "structSignalKeyHasher.html", null ], [ "TreeNode", "classTreeNode.html", null ], [ "TypeFactory< ClassId, BaseClass, Args >", "classTypeFactory.html", null ], [ "TypeFactory< std::string, DbcStatementHandler >", "classTypeFactory.html", null ] diff --git a/docs/html/index.qhp b/docs/html/index.qhp index b1fbab3..470f7b3 100644 --- a/docs/html/index.qhp +++ b/docs/html/index.qhp @@ -71,64 +71,68 @@
    -
    -
    -
    -
    +
    +
    +
    -
    -
    -
    +
    +
    +
    -
    -
    +
    +
    +
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    +
    +
    -
    -
    -
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    +
    +
    +
    -
    -
    -
    -
    -
    -
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    -
    -
    -
    -
    -
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    -
    -
    -
    -
    +
    +
    +
    +
    +
    @@ -141,7 +145,7 @@
    -
    +
    @@ -176,16 +180,21 @@
    -
    +
    +
    +
    +
    -
    +
    +
    -
    +
    +
    @@ -255,6 +264,10 @@
    +
    +
    +
    +
    @@ -296,7 +309,7 @@
    -
    +
    @@ -316,6 +329,8 @@
    +
    +
    @@ -349,18 +364,20 @@
    -
    +
    +
    -
    +
    +
    -
    +
    @@ -380,6 +397,7 @@
    +
    @@ -407,11 +425,10 @@
    -
    -
    -
    -
    -
    +
    +
    +
    +
    @@ -422,6 +439,7 @@
    +
    @@ -491,6 +509,7 @@
    +
    @@ -523,7 +542,7 @@ - + @@ -535,6 +554,8 @@ + + @@ -560,19 +581,22 @@ - - + + + - + + + @@ -586,6 +610,8 @@ + + @@ -677,6 +703,8 @@ classDbcValueDescriptionHandler-members.html classDbcValueDescriptionHandler.html classDbcValueDescriptionHandler__inherit__graph.svg +classDecodeDatabase-members.html +classDecodeDatabase.html classTreeNode-members.html classTreeNode.html classTypeFactory-members.html @@ -697,6 +725,7 @@ dbc__decoder_8h_source.html dbc__decoder__test_8cpp_source.html dbc__diagnostic_8h_source.html +dbc__lifetime__test_8cpp_source.html dbc__parser_8cpp.html dbc__parser_8cpp_source.html dbc__parser_8h.html @@ -711,8 +740,10 @@ dbc__tree__model_8cpp_source.html dbc__tree__model_8h_source.html dbc__tree__model__test_8cpp_source.html +decode__database_8cpp_source.html decode__database_8h.html decode__database_8h_source.html +definition__key_8h_source.html dir_0f63d6441a2c250919e1e8723011eb2f.html dir_4270bfced15e0e73154b13468c7c9ad9.html dir_59425e443f801f1f2fd8bbe4959a3ccf.html @@ -754,6 +785,8 @@ inherit_graph_24.svg inherit_graph_25.svg inherit_graph_26.svg +inherit_graph_27.svg +inherit_graph_28.svg inherit_graph_3.svg inherit_graph_4.svg inherit_graph_5.svg @@ -789,6 +822,7 @@ search/all_18.js search/all_19.js search/all_1a.js +search/all_1b.js search/all_2.js search/all_3.js search/all_4.js @@ -845,6 +879,7 @@ search/searchdata.js search/variables_0.js search/variables_1.js +search/variables_10.js search/variables_2.js search/variables_3.js search/variables_4.js @@ -871,8 +906,6 @@ structDbcParseContext.html structDbcParseResult-members.html structDbcParseResult.html -structDecodeDatabase-members.html -structDecodeDatabase.html structDecodeFrame-members.html structDecodeFrame.html structDecodeSignal-members.html @@ -895,6 +928,10 @@ structRawCanFrame.html structSignalInfo-members.html structSignalInfo.html +structSignalKey-members.html +structSignalKey.html +structSignalKeyHasher-members.html +structSignalKeyHasher.html svg.min.js sync_off.png sync_on.png diff --git a/docs/html/inherit_graph_10.map b/docs/html/inherit_graph_10.map index 849ced6..42b5434 100644 --- a/docs/html/inherit_graph_10.map +++ b/docs/html/inherit_graph_10.map @@ -1,3 +1,3 @@ - + diff --git a/docs/html/inherit_graph_10.md5 b/docs/html/inherit_graph_10.md5 index 92a0f01..3eb9292 100644 --- a/docs/html/inherit_graph_10.md5 +++ b/docs/html/inherit_graph_10.md5 @@ -1 +1 @@ -7b890cf55980a81b2aa2570b6e5b0f21 \ No newline at end of file +69d61ee297cd29b98a4f18e2423d5426 \ No newline at end of file diff --git a/docs/html/inherit_graph_10.svg b/docs/html/inherit_graph_10.svg index 2907443..d024b33 100644 --- a/docs/html/inherit_graph_10.svg +++ b/docs/html/inherit_graph_10.svg @@ -11,7 +11,7 @@ Node0 - + DecodeDatabase diff --git a/docs/html/inherit_graph_16.map b/docs/html/inherit_graph_16.map index 51fec7c..f4a18a3 100644 --- a/docs/html/inherit_graph_16.map +++ b/docs/html/inherit_graph_16.map @@ -1,3 +1,3 @@ - + diff --git a/docs/html/inherit_graph_16.md5 b/docs/html/inherit_graph_16.md5 index 26c0d3e..e33d4ca 100644 --- a/docs/html/inherit_graph_16.md5 +++ b/docs/html/inherit_graph_16.md5 @@ -1 +1 @@ -ab35c84b554d480a0ee1155c1179d2db \ No newline at end of file +d9608cce91db8bae16d0a4008a468656 \ No newline at end of file diff --git a/docs/html/inherit_graph_16.svg b/docs/html/inherit_graph_16.svg index 23a807a..5c70634 100644 --- a/docs/html/inherit_graph_16.svg +++ b/docs/html/inherit_graph_16.svg @@ -11,7 +11,7 @@ Node0 - + FrameKey diff --git a/docs/html/inherit_graph_23.map b/docs/html/inherit_graph_23.map index f17e7e3..1e0f215 100644 --- a/docs/html/inherit_graph_23.map +++ b/docs/html/inherit_graph_23.map @@ -1,7 +1,3 @@ - - - - - + diff --git a/docs/html/inherit_graph_23.md5 b/docs/html/inherit_graph_23.md5 index 9cbfdde..a182027 100644 --- a/docs/html/inherit_graph_23.md5 +++ b/docs/html/inherit_graph_23.md5 @@ -1 +1 @@ -fcc3a46e0f291589c12d6b87f268a06f \ No newline at end of file +7431f1cf350c15283d4994c7ea7fd895 \ No newline at end of file diff --git a/docs/html/inherit_graph_23.svg b/docs/html/inherit_graph_23.svg index f99f5c0..39da555 100644 --- a/docs/html/inherit_graph_23.svg +++ b/docs/html/inherit_graph_23.svg @@ -4,52 +4,16 @@ - + Graphical Class Hierarchy Node0 - - -std::exception - - - - - -Node1 - - -std::runtime_error - - - - - -Node0->Node1 - - - - - - - - -Node2 - - -DbcDiagnosticError - - - - - -Node1->Node2 - - - + + +SignalKey diff --git a/docs/html/inherit_graph_24.map b/docs/html/inherit_graph_24.map index d2067d8..f5ce2c8 100644 --- a/docs/html/inherit_graph_24.map +++ b/docs/html/inherit_graph_24.map @@ -1,3 +1,3 @@ - + diff --git a/docs/html/inherit_graph_24.md5 b/docs/html/inherit_graph_24.md5 index 53a15e0..1631bc5 100644 --- a/docs/html/inherit_graph_24.md5 +++ b/docs/html/inherit_graph_24.md5 @@ -1 +1 @@ -0e692ac66fcc5782f37efa2f3d64c466 \ No newline at end of file +9cbeda36cad4be0f515a467c983bc7c5 \ No newline at end of file diff --git a/docs/html/inherit_graph_24.svg b/docs/html/inherit_graph_24.svg index a741e27..ac54809 100644 --- a/docs/html/inherit_graph_24.svg +++ b/docs/html/inherit_graph_24.svg @@ -4,16 +4,16 @@ - + Graphical Class Hierarchy Node0 - - -TreeNode + + +SignalKeyHasher diff --git a/docs/html/inherit_graph_25.map b/docs/html/inherit_graph_25.map index cc8fd2d..f17e7e3 100644 --- a/docs/html/inherit_graph_25.map +++ b/docs/html/inherit_graph_25.map @@ -1,3 +1,7 @@ - + + + + + diff --git a/docs/html/inherit_graph_25.md5 b/docs/html/inherit_graph_25.md5 index feef5c8..9cbfdde 100644 --- a/docs/html/inherit_graph_25.md5 +++ b/docs/html/inherit_graph_25.md5 @@ -1 +1 @@ -fd991ac56e8b35f6def7a3942058b044 \ No newline at end of file +fcc3a46e0f291589c12d6b87f268a06f \ No newline at end of file diff --git a/docs/html/inherit_graph_25.svg b/docs/html/inherit_graph_25.svg index 1e19eb8..f99f5c0 100644 --- a/docs/html/inherit_graph_25.svg +++ b/docs/html/inherit_graph_25.svg @@ -4,17 +4,52 @@ - - + + Graphical Class Hierarchy Node0 - - -TypeFactory< ClassId, - BaseClass, Args > + + +std::exception + + + + + +Node1 + + +std::runtime_error + + + + + +Node0->Node1 + + + + + + + + +Node2 + + +DbcDiagnosticError + + + + + +Node1->Node2 + + + diff --git a/docs/html/inherit_graph_26.map b/docs/html/inherit_graph_26.map index f89295a..d2067d8 100644 --- a/docs/html/inherit_graph_26.map +++ b/docs/html/inherit_graph_26.map @@ -1,3 +1,3 @@ - + diff --git a/docs/html/inherit_graph_26.md5 b/docs/html/inherit_graph_26.md5 index 0956862..53a15e0 100644 --- a/docs/html/inherit_graph_26.md5 +++ b/docs/html/inherit_graph_26.md5 @@ -1 +1 @@ -2e92ed9cb6b5a27ab688cfd97eafecca \ No newline at end of file +0e692ac66fcc5782f37efa2f3d64c466 \ No newline at end of file diff --git a/docs/html/inherit_graph_26.svg b/docs/html/inherit_graph_26.svg index cb57a17..a741e27 100644 --- a/docs/html/inherit_graph_26.svg +++ b/docs/html/inherit_graph_26.svg @@ -4,17 +4,16 @@ - - + + Graphical Class Hierarchy Node0 - - -TypeFactory< std::string, - DbcStatementHandler > + + +TreeNode diff --git a/docs/html/inherit_graph_27.map b/docs/html/inherit_graph_27.map new file mode 100644 index 0000000..cc8fd2d --- /dev/null +++ b/docs/html/inherit_graph_27.map @@ -0,0 +1,3 @@ + + + diff --git a/docs/html/inherit_graph_27.md5 b/docs/html/inherit_graph_27.md5 new file mode 100644 index 0000000..feef5c8 --- /dev/null +++ b/docs/html/inherit_graph_27.md5 @@ -0,0 +1 @@ +fd991ac56e8b35f6def7a3942058b044 \ No newline at end of file diff --git a/docs/html/inherit_graph_27.svg b/docs/html/inherit_graph_27.svg new file mode 100644 index 0000000..1e19eb8 --- /dev/null +++ b/docs/html/inherit_graph_27.svg @@ -0,0 +1,22 @@ + + + + + + +Graphical Class Hierarchy + + +Node0 + + +TypeFactory< ClassId, + BaseClass, Args > + + + + + diff --git a/docs/html/inherit_graph_28.map b/docs/html/inherit_graph_28.map new file mode 100644 index 0000000..f89295a --- /dev/null +++ b/docs/html/inherit_graph_28.map @@ -0,0 +1,3 @@ + + + diff --git a/docs/html/inherit_graph_28.md5 b/docs/html/inherit_graph_28.md5 new file mode 100644 index 0000000..0956862 --- /dev/null +++ b/docs/html/inherit_graph_28.md5 @@ -0,0 +1 @@ +2e92ed9cb6b5a27ab688cfd97eafecca \ No newline at end of file diff --git a/docs/html/inherit_graph_28.svg b/docs/html/inherit_graph_28.svg new file mode 100644 index 0000000..cb57a17 --- /dev/null +++ b/docs/html/inherit_graph_28.svg @@ -0,0 +1,22 @@ + + + + + + +Graphical Class Hierarchy + + +Node0 + + +TypeFactory< std::string, + DbcStatementHandler > + + + + + diff --git a/docs/html/inherits.html b/docs/html/inherits.html index 26e32f1..4ea50dc 100644 --- a/docs/html/inherits.html +++ b/docs/html/inherits.html @@ -119,10 +119,12 @@ $(document).ready(function(){initNavTree('hierarchy.html',''); initResizable();

    This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.

    - - - - + + + + + + diff --git a/docs/html/md_README.html b/docs/html/md_README.html index fd5b40c..9337e05 100644 --- a/docs/html/md_README.html +++ b/docs/html/md_README.html @@ -175,7 +175,7 @@ Why the Runtime Decode Layer Exists

    Because of that, the design uses a dedicated runtime-ready structure:

    @@ -359,7 +359,7 @@ Purpose

    <tt>FrameKey</tt>

    -

    Fast lookup key for runtime frame matching.

    +

    Stable identifier for runtime frame matching and application state.

    Fields:

    • canId
    • @@ -369,17 +369,15 @@ Purpose

      <tt>DecodeDatabase</tt>

      -

      Top-level runtime decode container.

      -

      Fields:

      +

      Immutable runtime snapshot with a private frame index. Build it with DbcDecodeBuilder::Build(parsed) or construct it from std::vector<DecodeFrame>. Construction rejects duplicate frame keys and duplicate signal names within a frame with std::invalid_argument, including manually supplied metadata.

        -
      • frames
      • -
      • frameIndexByKey
      • +
      • GetFrames() returns a borrowed const std::vector<DecodeFrame>&.
      • +
      • FindFrame(FrameKey) returns std::shared_ptr<const DecodeFrame>.
      • +
      • FindSignal(SignalKey) returns std::shared_ptr<const DecodeSignal>.
      • +
      • Missing definitions return an empty handle.
      • +
      • Copying a database shares its snapshot; replacing it installs another snapshot.
      -

      Conceptually:

      -
      DecodeDatabase
      -
      ├── vector<DecodeFrame>
      -
      └── unordered_map<FrameKey, index>
      -

      This gives the decoder fast access to a frame definition using CAN ID and frame type.

      +

      Frame lookup uses a hash index; signal lookup scans the matched frame's signals. Decoding shares the snapshot without copying definitions or allocating ownership objects per signal.


      Decoder Layer

      @@ -405,6 +403,7 @@ Decoder Layer

      Fields:

      • definition
      • +
      • key
      • rawValue
      • physicalValue
      • valid
      • @@ -429,13 +428,44 @@ Raw value representation and precision

        Fields:

        • definition
        • +
        • key
        • signals
        • valid

        valid means a matching frame definition was found. Check each signal's valid separately: insufficient payload data can leave individual signals invalid even when the frame is valid. An unknown frame returns valid == false.

        -

        The frame and signal definition pointers refer into DecodeDatabase. Keep that database alive and avoid changes that invalidate its frame or signal storage while using decoded results. The decoder applies factor and offset; it does not clamp physical values to the declared minimum and maximum.

        +

        The decoder applies factor and offset; it does not clamp physical values to the declared minimum and maximum.

        +

        +Definition ownership and reload

        +

        DecodedFrameValue::definition and DecodedSignalValue::definition are owning std::shared_ptr<const ...> handles. Each handle retains the immutable runtime snapshot. Definitions remain valid until the last database copy, lookup handle, or decoded result owning that snapshot is released. An independently copied signal result retains its definition even after the parent frame result is removed. Copying or moving results preserves ownership.

        +

        Reload by assigning a newly built database. Stored results continue to describe the old DBC, including its units, scaling, comments, and VAL_ descriptions; subsequent decoding uses the new DBC. Removed definitions cannot be found in the new database, but old results safely retain their old definitions. Keeping even one signal handle retains the whole old snapshot; release stored results when that metadata is no longer needed.

        +

        GetFrames() is a borrowed view. References, iterators, and raw pointers obtained from it or from a handle's .get() do not retain ownership. Keep an owning handle or an unchanged database copy while using them. Do not retain mutable aliases into a vector moved into the database constructor. The raw string pointer from GetValueDescription() follows the same rule: keep the signal definition handle alive while using the string.

        +

        Parsed DbcDatabase/FrameInfo/SignalInfo remain ordinary mutable value containers: borrowed pointers follow standard vector invalidation rules. Builders copy their metadata, so parsed input may be changed or destroyed after building. Tree nodes own metadata copies; the Qt model owns its tree and invalidates model indexes on reset. Runtime handles do not depend on the parsed database or tree. Synchronize replacement of a shared database variable with decoding; immutable snapshots do not make concurrent assignment to the same object safe.

        +

        +Stable frame and signal identifiers

        +

        DecodedFrameValue::key is a FrameKey (normalized canId, isExtended), also available through DecodeFrame::GetKey(). DecodedSignalValue::key is a SignalKey (frame key, exact case-sensitive signal name). Both are value types with equality and hashers (FrameKeyHasher, SignalKeyHasher) for application maps and saved selections. Construct the same keys from parsed metadata when needed; do not use addresses or vector positions as identifiers.

        +

        Keys stay equal across reloads and reordering when their components stay equal. Frame renaming and changes to units, bit layout, scaling, or descriptions do not change a key. Changing a CAN ID/frame type or renaming a signal produces a new key. The same name in different frames and standard/extended frames with the same numeric CAN ID remain distinct. Keys identify definitions within one logical DBC database; applications combining databases must add their own database ID. A key is not a version identifier: matching keys in different snapshots may have different metadata. Use valid/the definition handle to distinguish a matched result; default keys alone do not indicate successful decoding.

        +
        +
        DecodedFrameValue stored = DbcDecoder().Decode(runtime, rawFrame);
        +
        if (stored.valid && !stored.signals.empty()) {
        +
        DecodedSignalValue saved = stored.signals.front();
        +
        SignalKey selection = saved.key;
        +
        runtime = DbcDecodeBuilder().Build(parser.ParseFile("updated.dbc"));
        +
        std::shared_ptr<const DecodeSignal> current = runtime.FindSignal(selection);
        +
        // saved.definition retains old metadata; current holds new metadata or is empty.
        +
        }
        +
        Converts parsed DBC data into runtime decode database.
        +
        DecodeDatabase Build(const DbcDatabase &source) const
        Build runtime decode database.
        +
        Runtime CAN decoder using prebuilt decode database.
        Definition dbc_decoder.h:74
        +
        DecodedFrameValue Decode(const DecodeDatabase &database, const RawCanFrame &frame) const
        Decode one raw CAN frame.
        +
        Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles a...
        +
        Fully decoded frame.
        Definition dbc_decoder.h:62
        + +
        One decoded signal value.
        Definition dbc_decoder.h:43
        + + +

        API migration: replace reads of runtime.frames with runtime.GetFrames(). To edit runtime definitions, prepare a vector and construct a new database; frameIndexByKey is now private and built automatically. DbcDecoder::FindFrame and result definition fields now use owning handles instead of raw pointers; definition->name, boolean/null checks, and existing decode calls remain usable. Use .get() only for temporary raw-pointer interoperation with an owner alive.


        -

        +

        <tt>DbcDecoder</tt>

        Main runtime decoder class.

        Responsibilities:

        @@ -452,7 +482,7 @@ Raw value representation and precision
      • Decode(...)

      -

      +

      Parser Support

      The current parser supports the following DBC elements:

        @@ -463,7 +493,7 @@ Parser Support
      • VAL_ signal value descriptions
      • basic M / mN multiplexing
      -

      +

      Structured diagnostics

      ParseFileWithDiagnostics(path) returns DbcParseResult containing database and diagnostics. Each DbcDiagnostic has severity, code, filePath, lineNumber, and message. Paths preserve the caller's supplied spelling. Lines are one-based physical lines, including blank lines; file-level errors use zero.

      const DbcParser parser;
      @@ -473,16 +503,13 @@ Structured diagnostics
      << ": " << diagnostic.message << '\n';
      }
      if (!result.HasErrors()) {
      -
      const DecodeDatabase runtime = DbcDecodeBuilder().Build(result.database);
      +
      const DecodeDatabase runtime = DbcDecodeBuilder().Build(result.database);
      // Inspect warnings before relying on decoding results.
      }
      -
      Converts parsed DBC data into runtime decode database.
      -
      DecodeDatabase Build(const DbcDatabase &source) const
      Build runtime decode database.
      Minimal DBC parser.
      Definition dbc_parser.h:33
      DbcParseResult ParseFileWithDiagnostics(const std::string &filePath) const
      Parse with warnings and a structured first error instead of throwing.
      -
      Runtime decode database with fast lookup by CAN ID.
      @@ -506,9 +533,9 @@ Structured diagnostics

      Common VERSION, NS_, BS_, and BU_ headers produce no diagnostics. Single-token symbols inside the NS_ declaration list are quiet regardless of indentation, even when they name unsupported syntax. Frame, signal, bus, and node definitions or a line with arguments end the list. Actual unsupported statements outside that list are reported. Node and bus metadata are not stored. Other comment forms (CM_, CM_ BU_, CM_ EV_) are ignored by the comment handler; comments only attach to already parsed frames/signals. Supported statements currently require one physical line.

      ParseFile(path) remains compatible: it returns the database, discards warnings, and throws std::runtime_error on the first error with the existing path:line: format. Use ParseFileWithDiagnostics to see skipped syntax. Resource failures such as allocation errors may still throw.


      -

      +

      Supported DBC Syntax

      -

      +

      Frame definition

      Example:

      BO_ 256 EngineData: 8 EEC1
      @@ -520,7 +547,7 @@ Frame definition
    • transmitter ECU

    • -

      +

      Frame validation and parse errors

      BO_ definitions require a decimal CAN ID, a nonempty single-token frame name, a colon, a decimal payload length, and a transmitter token. Spaces or tabs may separate fields, and whitespace before the colon is accepted. Additional trailing fields are rejected.

      Numeric fields must contain decimal digits only; signs, hexadecimal notation, fractional values, suffixes, and overflow are rejected. CAN IDs may contain the 29-bit identifier plus the optional DBC extended flag (bit 31). Bits 29 and 30 are rejected rather than silently discarded. For compatibility, unflagged IDs above 0x7FF are still treated as extended.

      @@ -529,7 +556,7 @@ Frame validation and parse errors
      example.dbc:3: Invalid CAN ID: invalid

      Frame and signal definitions are validated as described here; comprehensive DBC grammar coverage is still planned. File-open exceptions contain the path but no line number. The structured diagnostic API uses line zero for file-level errors.


      -

      +

      Signal definition

      Example:

      SG_ EngineSpeed : 0|16@1+ (0.125,0) [0|8000] "rpm" ECU1,ECU2
      @@ -548,7 +575,7 @@ Signal definition
    • receivers

    • -

      +

      Signal validation and parse errors

      SG_ statements are matched completely. Signal names must be nonempty and contain no whitespace. Spaces and tabs are accepted between syntax elements; byte order and signedness remain adjacent (@0+, @0-, @1+, or @1-). A quoted unit (which may be empty) and a nonempty comma-separated receiver list are required. Unexpected trailing fields are rejected.

      Start bits must be unsigned decimal integers fitting uint32_t; lengths must be within 1..64 bits. Signs, fractional values, numeric suffixes, and overflow are rejected for these fields. Every signal bit must fit within the frame's declared payload length, using Intel increasing bit positions or Motorola sawtooth traversal. This uses the stored payload length without introducing an additional CAN or CAN FD payload limit.

      @@ -556,7 +583,7 @@ Signal validation and parse errors

      Basic multiplexing markers M and mN are supported as described below. Overlapping signals are rejected unless their branch values differ. Duplicate frame keys and signal names within a frame are rejected.

      Invalid signal definitions stop parsing with path:line: description, including when the signal exceeds the declared payload length.


      -

      +

      Basic multiplexing

      BO_ 256 Status: 3 ECU
      SG_ Mode M : 0|8@1+ (1,0) [0|255] "" ECU
      @@ -583,7 +610,7 @@ Basic multiplexing
      Severity / code Meaning

      All statuses except Valid have valid == false; their numeric fields contain no decoded data and GetValueDescription() returns nullptr. Check status to distinguish inactive branches from errors. Consumers constructing runtime metadata manually must obey the same non-overlap rules as the parser. Extended and nested multiplexing are outside this stage and are explicitly rejected, rather than silently decoded as unconditional signals.


      -

      +

      Comments

      Frame comment example:

      CM_ BO_ 256 "Engine data frame";
      @@ -595,7 +622,7 @@ Comments
    • SignalInfo::comment

    -

    +

    CAN ID Normalization

    The parser normalizes frame identifiers.

    Common DBC behavior:

    @@ -610,7 +637,7 @@ CAN ID Normalization

    This is important both for correct lookup and for future interoperability with live CAN APIs.


    -

    +

    PGN Extraction

    PGN is derived only when the frame is treated as extended.

    The current logic is simplified J1939 extraction:

    @@ -621,7 +648,7 @@ PGN Extraction

    This is enough for a practical start but should not be treated as full J1939 validation.


    -

    +

    Decode Flow

    Typical runtime decode flow:

    RawCanFrame
    @@ -636,7 +663,7 @@ Decode Flow
    ↓
    DecodedFrameValue

    -

    +

    Intel and Motorola Extraction

    The decoder currently has separate extraction paths:

      @@ -647,7 +674,7 @@ Intel and Motorola Extraction

      Intel and Motorola require different bit extraction logic.

      This is one of the main reasons why the runtime decode layer should be explicit and prepared in advance.


      -

      +

      Example Usage

      Include the public headers from the core/ include directory supplied by core/core.pri:

      #include "dbc_parser.h"
      @@ -658,23 +685,23 @@ Example Usage
      Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
      Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
      Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
      -

      +

      Parse DBC

      DbcParser parser;
      DbcDatabase database = parser.ParseFile("example.dbc");
      DbcDatabase ParseFile(const std::string &filePath) const
      Parse DBC file.
      Parsed DBC content stored in a simple internal form.
      -

      +

      Build UI tree

      DbcTreeBuilder treeBuilder;
      std::unique_ptr<TreeNode> root = treeBuilder.Build(database);
      Builds a simple tree from parsed DBC database.
      std::unique_ptr< TreeNode > Build(const DbcDatabase &database) const
      Build tree representation of parsed DBC data.
      -

      +

      Build runtime decode database

      DbcDecodeBuilder decodeBuilder;
      -
      DecodeDatabase decodeDatabase = decodeBuilder.Build(database);
      -

      +
      DecodeDatabase decodeDatabase = decodeBuilder.Build(database);
      +

      Decode a raw frame

      RawCanFrame rawFrame;
      rawFrame.canId = 256; // EngineData from the DBC example above
      @@ -683,15 +710,12 @@ Decode a raw frame
      DbcDecoder decoder;
      DecodedFrameValue decoded = decoder.Decode(decodeDatabase, rawFrame);
      -
      Runtime CAN decoder using prebuilt decode database.
      Definition dbc_decoder.h:72
      -
      DecodedFrameValue Decode(const DecodeDatabase &database, const RawCanFrame &frame) const
      Decode one raw CAN frame.
      -
      Fully decoded frame.
      Definition dbc_decoder.h:61
      Raw CAN frame used for runtime or trace decoding.
      Definition dbc_decoder.h:24
      std::vector< std::uint8_t > data
      Definition dbc_decoder.h:27
      std::uint32_t canId
      Definition dbc_decoder.h:25
      bool isExtended
      Definition dbc_decoder.h:26

      -

      +

      Unified Decode Strategy

      A key design goal is that the same decoder should work for both:

        @@ -699,7 +723,7 @@ Unified Decode Strategy
      • trace replay frames

      That means this architecture supports:

      -

      +

      live path

      live CAN input
      ↓
      @@ -708,7 +732,7 @@ live path
      DbcDecoder
      ↓
      decoded signal values
      -

      +

      trace path

      trace reader
      ↓
      @@ -719,7 +743,7 @@ trace path
      decoded signal values

      This avoids duplicating decode logic in two separate parts of the application.


      -

      +

      Intended Use in FrameTap

      This module is meant to support at least the following FrameTap workflows:

        @@ -745,7 +769,7 @@ Intended Use in FrameTap
        - live frames
        - trace replay

        -

        +

        Why the Tree Is Not Enough

        The tree exists for browsing.

        However, runtime decode should not rely on tree traversal because that would introduce unnecessary coupling and inefficiency.

        @@ -755,9 +779,9 @@ Why the Tree Is Not Enough
      • minimal interpretation at decode time
      • direct signal definitions already prepared
      -

      That is why DecodeDatabase is a separate layer.

      +

      That is why DecodeDatabase is a separate layer.


      -

      +

      Statement Handler Factory

      DbcParser owns file reading, trimming, line numbers, and error reporting. Each ParseFile() call creates a fresh DbcParseContext and a DbcStatementDispatcher. The context contains the parsed database and current frame; handlers receive it by reference and retain no parsing state.

      The dispatcher uses TypeFactory<std::string, DbcStatementHandler> to create registered handlers once per parsing session, then reuses them for all matching lines:

      @@ -778,7 +802,7 @@ Statement Handler Factory

      Registration creates one handler; replacing a registration replaces that instance. Register during initialization before dispatching. A line is routed using its full first whitespace-delimited keyword, so BO_TX_BU_ cannot match BO_. Unregistered keywords produce UnsupportedStatement warnings through ParseFileWithDiagnostics. SG_ and CM_ accept spaces and tabs after their keywords.

      This factory handles statements inside DBC files. A separate format-level factory can be introduced when another file format is implemented. The decoder and database builders remain independent of statement dispatch.


      -

      +

      Signal value descriptions (<tt>VAL_</tt>)

      Signal descriptions attach text to exact raw integer values:

      BO_ 256 Status: 8 ECU
      @@ -813,7 +837,7 @@ if (const std::string *description = value.GetValueDescription()) { It returns <tt>nullptr</tt> for an invalid decode or an unknown value; numeric decoding and <tt>physicalValue</tt> are unchanged. A mapped empty string returns a non-null pointer. The pointer belongs to the signal definition and stays valid while that -definition and mapping remain alive and unchanged. +definition remains alive. A decoded signal owns its immutable definition across reload. For metadata or standalone raw values, use <tt>FindValueDescription(signal.valueDescriptions, rawValue)</tt>, where <tt>rawValue</tt> is @@ -828,7 +852,7 @@ are outside this implementation; the optional Qt adapter exposes signal mappings <hr> -@section autotoc_md112 Current Limitations +@section autotoc_md114 Current Limitations This is still a minimal implementation. @@ -862,11 +886,11 @@ byte boundaries, and 64-bit values. <hr> -@section autotoc_md114 Recommended Next Steps +@section autotoc_md116 Recommended Next Steps A practical development order would be: -@subsection autotoc_md115 Stage 1 - already implemented +@subsection autotoc_md117 Stage 1 - already implemented - <tt>BO_</tt> - <tt>SG_</tt> @@ -881,13 +905,13 @@ A practical development order would be: - runtime decode database - runtime decoder -@subsection autotoc_md116 Stage 2 +@subsection autotoc_md118 Stage 2 Recommended additions: - selective decoding of only chosen signals -@subsection autotoc_md117 Stage 3 +@subsection autotoc_md119 Stage 3 Recommended additions: @@ -897,7 +921,7 @@ Recommended additions: - CSV export of decoded traces - optimized filtering and signal selection -@subsection autotoc_md118 Stage 4 +@subsection autotoc_md120 Stage 4 Advanced functionality: @@ -908,7 +932,7 @@ Advanced functionality: <hr> -@section autotoc_md120 Build Integration +@section autotoc_md122 Build Integration The repository supplies qmake projects. A C++17 compiler is required; the root build also requires Qt Core and Qt Test development packages. Other build @@ -939,7 +963,7 @@ source lists live in <tt>tests/parser_tests.pri</tt> and <tt>t When building a consumer separately, pass <tt>DBC_CORE_BUILD_DIR=/absolute/path/to/build/core</tt> to qmake. -@subsection autotoc_md121 Build core without Qt libraries +@subsection autotoc_md123 Build core without Qt libraries From the repository root: @@ -952,7 +976,7 @@ make -j qmake is still the build tool; this target does not link Qt libraries. -@subsection autotoc_md122 Optional Qt model adapter +@subsection autotoc_md124 Optional Qt model adapter The adapter and its <tt>QAbstractItemModelTester</tt> suite use Qt 6.8.2. The adapter itself links only Qt Core. @@ -1073,7 +1097,7 @@ Valid items are enabled and selectable, with no editing support.

      Each value-description entry contains value (qlonglong for negative keys, qulonglong for nonnegative keys) and description (QString). This preserves the full signed/unsigned 64-bit range without converting through double. An unmapped signal returns an empty list. Data comes from SignalInfo::valueDescriptions. Unsupported roles return invalid QVariant.

      -

      +

      Standalone tree tests without Qt

      From the repository root, use only a C++17 compiler:

      @@ -1082,7 +1106,7 @@ Standalone tree tests without Qt
      /tmp/dbc_tree_node_test

      -

      +

      Build and run the demo

      After building core, run these commands from the repository root:

      @@ -1094,7 +1118,7 @@ Build and run the demo

      The demo prints the parsed tree and decodes eight zero bytes using the first frame definition. Replace that sample payload in examples/main.cpp to feed live CAN data or trace records.

      -

      +

      Generate API documentation

      With Doxygen installed, run from the repository root:

      @@ -1104,17 +1128,17 @@ Generate API documentation


      -

      +

      Regression tests

      See tests/README.md for QtTest build and execution commands. Tests cover frame validation and error locations, Intel and Motorola extraction, signal syntax and payload bounds, VAL_ syntax and reference validation, raw description lookup and preservation through both builders, statement dispatch, signed and unsigned 64-bit boundaries, physical conversion, numeric output, and invalid signal payloads.

      -

      +

      Measuring code coverage

      Coverage instrumentation is separate from the QtTest suite named CoverageTest: that suite runs extra regression checks, but coverage counters require a specially instrumented build. Use a separate build directory for each coverage tool.

      -

      +

      GCC, gcov, and LCOV on Debian/Ubuntu

      Install the build and report tools:

      @@ -1168,7 +1192,7 @@ GCC, gcov, and LCOV on Debian/Ubuntu

      After adding direct comment-handler and ambiguous VAL_ reference tests, the same configuration measured 98.4% line coverage (728/740) and 71.4% branch coverage (841/1178).

      See GCC instrumentation options and the LCOV project documentation.

      -

      +

      Configure the GCC coverage build in Qt Creator

        @@ -1184,7 +1208,7 @@ Configure the GCC coverage build in Qt Creator

      -

      +

      Configure all build variants in Qt Creator

      The local dbc.pro.user stores machine-specific kit IDs and build/run settings. It is ignored by Git (*.user) and should not be committed or copied between machines. Recreate the configurations below through the UI when setting up a new checkout. The Qt4ProjectManager identifiers inside .user are historical Qt Creator setting names; the project still requires Qt 6.8.2.

      diff --git a/docs/html/md_changelog.html b/docs/html/md_changelog.html index d740b6b..2dabd74 100644 --- a/docs/html/md_changelog.html +++ b/docs/html/md_changelog.html @@ -101,6 +101,9 @@ Unreleased

      Added

        +
      • Stable application identifiers: FrameKey (normalized CAN ID and frame type) and SignalKey (frame key and signal name), with equality and hashers.
      • +
      • Runtime FindSignal, frame GetKey, and keys on decoded frame/signal results.
      • +
      • Reload/lifetime tests for retained frames and independent signals, lookup handles, copies/moves, snapshot release, stable keys, removed/renamed definitions, failed/empty reloads, duplicate keys, and insufficient payloads.
      • ParseFileWithDiagnostics and DbcParseResult with severity, stable error code, supplied file path, physical line number, and message for each diagnostic.
      • Warnings for unregistered statements, including floating-point signal types, attributes, signal type references, environment variables, and vendor extensions.
      • Quiet common DBC header handlers registered through TypeFactory; NS_ symbol declarations do not produce unsupported-statement warnings.
      • @@ -109,6 +112,9 @@ Added

        Changed

          +
        • API change: DecodeDatabase is an immutable shared snapshot. Use GetFrames() for reads or construct a new snapshot from a vector; its frame index is private and built automatically, with duplicate-key validation.
        • +
        • API change: decoded definition fields and DbcDecoder::FindFrame return shared_ptr<const ...> ownership. Stored results retain old definitions across reload/clear/destruction, including separately copied signals and VAL_ strings. Decoding shares metadata without per-result definition copies.
        • +
        • Documented borrowed views, owning handles, snapshot retention, identifier scope, reload behavior, application migration, and synchronization requirements.
        • Kept ParseFile compatible while sharing parsing with the diagnostic API. Parsing stops at the first error and never returns a partial database.
        • Deferred value-description and multiplexing errors carry structured source locations without extracting them from exception messages.
        • Documented supported syntax, warning behavior, diagnostic codes, and limitations.
        • @@ -208,7 +214,7 @@ Added
          • Initialized the repository with a README and MIT license. (4270459)
          • Added the DBC parser, frame and signal metadata, a tree representation and builder, a demonstration program, and a qmake project. (2a90b2d)
          • -
          • Added runtime decoding through DbcDecodeBuilder, DecodeDatabase, and DbcDecoder, including CAN-frame lookup, Intel and Motorola extraction, signed and unsigned signals, and factor/offset conversion. Updated parser metadata and the demo to support decoding. (a53a5df)
          • +
          • Added runtime decoding through DbcDecodeBuilder, DecodeDatabase, and DbcDecoder, including CAN-frame lookup, Intel and Motorola extraction, signed and unsigned signals, and factor/offset conversion. Updated parser metadata and the demo to support decoding. (a53a5df)

          Documentation and maintenance

          diff --git a/docs/html/md_tests_2README.html b/docs/html/md_tests_2README.html index 7f9937b..f09c1a0 100644 --- a/docs/html/md_tests_2README.html +++ b/docs/html/md_tests_2README.html @@ -93,7 +93,7 @@ $(document).ready(function(){initNavTree('md_tests_2README.html',''); initResiza
          QtTest regression tests
          -

          For instrumented builds, LCOV HTML reports, and Qt Creator coverage configuration, see Measuring code coverage. For the complete IDE build/run configuration set, see Configure all build variants in Qt Creator. The Coverage configuration uses coverage_report.sh after its instrumented build; the script takes the source and build directories as its two arguments.

          +

          For instrumented builds, LCOV HTML reports, and Qt Creator coverage configuration, see Measuring code coverage. For the complete IDE build/run configuration set, see Configure all build variants in Qt Creator. The Coverage configuration uses coverage_report.sh after its instrumented build; the script takes the source and build directories as its two arguments.

          Open the repository's root dbc.pro in Qt Creator. It contains core (a static C++17 library) and tests (the dbc_tests QtTest executable). Core is built first; tests link its archive rather than compiling its implementation again. Qt Core and Qt Test development packages are required for tests only. The optional model tests also link QtGui, which is provided by Qt base development packages. The adapter library itself still links only QtCore.

          Build from the repository root with the installed Qt 6.8.2:

          mkdir build
          @@ -101,7 +101,7 @@ $(document).ready(function(){initNavTree('md_tests_2README.html',''); initResiza
          qmake6 ../dbc.pro
          make -j
          make check
          -

          Or run ./tests/dbc_tests directly. Parser, decoder, and additional coverage suites run, and the executable returns nonzero when any suite fails. Decoder cases appear as individual QtTest data rows; parser checks are grouped into named test slots. Checks also run in release builds.

          +

          Or run ./tests/dbc_tests directly. Parser, decoder, lifetime, and additional coverage suites run, and the executable returns nonzero when any suite fails. Decoder cases appear as individual QtTest data rows; parser checks are grouped into named test slots. Checks also run in release builds.

          To build tests separately against an existing core build:

          mkdir /tmp/dbc-tests-build
          cd /tmp/dbc-tests-build
          @@ -109,24 +109,28 @@ $(document).ready(function(){initNavTree('md_tests_2README.html',''); initResiza
          DBC_CORE_BUILD_DIR=/absolute/path/to/build/core
          make
          make check
          -

          parser_tests.pri and decoder_tests.pri include the original test sources; tests.pro also includes dbc_coverage_test.cpp. ../core/core.pri supplies the library include path and linkage.

          -

          +

          parser_tests.pri and decoder_tests.pri include the original test sources; tests.pro also includes dbc_coverage_test.cpp and dbc_lifetime_test.cpp. ../core/core.pri supplies the library include path and linkage.

          +

          Decoder coverage

          Coverage includes Motorola bit numbering within and across bytes, unaligned signals, signed values, scaling, 64-bit extraction, signed/unsigned boundary values (including INT64_MIN, INT64_MAX, and UINT64_MAX), numeric output, invalid lengths, insufficient payloads, and Intel regression cases. Frame validity means the definition was found; insufficient payloads are checked through signal validity.

          -

          +

          Parser coverage

          Structured diagnostic tests cover severity, code, supplied path, and physical line numbers for skipped syntax and immediate/deferred errors; warnings preceding an error are retained, and failed parses return an empty database. Common headers and namespace symbol lists stay quiet. Tests also check file-open errors, fresh parse sessions, and compatibility with the legacy throwing API. The diagnostic audit also covers 15 unsupported-statement variants, all namespace termination forms, CRLF and missing final newlines, relative paths with spaces, first-error stopping, deferred diagnostic ordering, duplicate definitions/values, selector ranges, overlaps, and preservation of supported decoding and metadata. On Linux, reading a directory exercises the distinct FileReadError path.

          Parser tests cover standard and extended CAN IDs, whitespace, payload storage boundaries, missing fields, malformed and overflowing numbers, reserved ID bits, error paths and line numbers, and integration with signals and comments. Duplicate definitions are rejected at their source lines, including equivalent extended ID encodings and repeated signal names within a frame. Standard and extended frames may share a numeric ID, and separate frames may reuse signal names. Signal tests cover complete syntax and numeric validation, scientific notation, finite physical parameters and ordered ranges, spaces and tabs, receiver lists, unsupported multiplexing, and Intel/Motorola declared-payload boundaries. Value-description tests cover full VAL_ syntax, whitespace, escaped quotes, empty text, exact integer boundaries, duplicate keys within and across statements, deferred and normalized frame references, missing targets, error locations, raw lookup with scaling, unknown/invalid values, and both database builders. Temporary DBC fixtures are created in the system temporary directory and removed automatically.

          Dispatch tests also verify exact keyword matching, handler construction and reuse, unknown statements, and independent parsing sessions, including recovery after errors.

          -

          +

          Tree and optional model tests

          tree_node_test.cpp is a standalone C++17 executable without Qt; see the root README for its compiler command. It checks parents, sibling positions, null children, bounds, and unique_ptr transfer.

          Enable CONFIG+=dbc_qt in the root qmake invocation to build dbc_qt and dbc_model_tests alongside existing tests. Qt 6.8.2 is required. make check runs all suites. Model tests parse a temporary DBC fixture and use QAbstractItemModelTester, verify navigation across columns, invalid/foreign indexes, metadata and exact VAL_ integers, and persistent-index invalidation when reloading or clearing the tree. Their QGuiApplication registers graphical metatypes used by QAbstractItemModelTester, avoiding the invalid QPixmap type warning in Qt 6.8.2. The test executable defaults to QT_QPA_PLATFORM=offscreen when the variable is unset or empty, so no display server is needed. An explicit platform setting is preserved.

          Basic multiplexing coverage includes selector declarations after branches, Intel/Motorola branch overlap, signed active values and VAL_ lookup, unconditional signals, inactive branches, missing selector/branch payloads, exact UINT64_MAX selector matching, malformed runtime selectors, source locations, and rejection of invalid markers, selector references/ranges, overlaps, and SG_MUL_VAL_.

          -

          +

          Additional regression coverage

          dbc_coverage_test.cpp runs as part of dbc_tests. It covers signed boundaries below 64 bits, deterministic extraction comparisons for both byte orders across lengths 1–64, frame lookup failures, exact decode statuses, malformed runtime multiplexing, PGN boundaries, comment handling, file formatting, metadata copying and source lifetime, physical conversion, and TypeFactory registration/creation. Direct resolver tests construct ambiguous databases through the public metadata API, verify source locations, and check that ambiguous targets receive no values.

          -

          All QtTest targets use Qt 6.8.2 and QVERIFY_THROWS_EXCEPTION. Exception tests explicitly discard nodiscard results when only the exception is being checked. The standalone tree test requires only a C++17 compiler.

          +

          All QtTest targets use Qt 6.8.2 and QVERIFY_THROWS_EXCEPTION. Exception tests explicitly discard nodiscard results when only the exception is being checked. The standalone tree test requires only a C++17 compiler.

          +

          +Definition lifetime and reload coverage

          +

          dbc_lifetime_test.cpp checks retained definitions and value-description strings across reload, clear, and destruction; independently saved signal results; copied/moved results and database copies; owning lookup handles; and release of the old snapshot after its final owner is removed. Compile-time checks enforce const access to runtime metadata. Reload fixtures change ordering, frame names, scaling, units, and descriptions, remove definitions, and rename signals.

          +

          Key tests check equality and hashing, standard/extended separation, the same signal name in different frames, and missing lookups. Constructor tests reject duplicate runtime keys, including manually supplied parsed metadata. Failed reload leaves the active database intact; empty reload clears it. Invalid/unknown results and insufficient payloads retain their documented ownership and status behavior. Inactive branches and unavailable selectors also retain definitions across reload.

          diff --git a/docs/html/menudata.js b/docs/html/menudata.js index 33978e4..df4e015 100644 --- a/docs/html/menudata.js +++ b/docs/html/menudata.js @@ -39,6 +39,7 @@ var menudata={children:[ {text:"g",url:"functions.html#index_g"}, {text:"h",url:"functions.html#index_h"}, {text:"i",url:"functions.html#index_i"}, +{text:"k",url:"functions.html#index_k"}, {text:"l",url:"functions.html#index_l"}, {text:"m",url:"functions.html#index_m"}, {text:"n",url:"functions.html#index_n"}, @@ -57,6 +58,7 @@ var menudata={children:[ {text:"f",url:"functions_vars.html#index_f"}, {text:"h",url:"functions_vars.html#index_h"}, {text:"i",url:"functions_vars.html#index_i"}, +{text:"k",url:"functions_vars.html#index_k"}, {text:"l",url:"functions_vars.html#index_l"}, {text:"m",url:"functions_vars.html#index_m"}, {text:"n",url:"functions_vars.html#index_n"}, diff --git a/docs/html/navtreedata.js b/docs/html/navtreedata.js index 654e3ad..ff8c69b 100644 --- a/docs/html/navtreedata.js +++ b/docs/html/navtreedata.js @@ -84,64 +84,68 @@ var NAVTREE = [ "DecodedSignalValue", "md_README.html#autotoc_md62", [ [ "Raw value representation and precision", "md_README.html#autotoc_md64", null ] ] ], - [ "DecodedFrameValue", "md_README.html#autotoc_md66", null ], - [ "DbcDecoder", "md_README.html#autotoc_md68", null ], - [ "Parser Support", "md_README.html#autotoc_md70", [ - [ "Structured diagnostics", "md_README.html#autotoc_md71", null ] + [ "DecodedFrameValue", "md_README.html#autotoc_md66", [ + [ "Definition ownership and reload", "md_README.html#autotoc_md67", null ], + [ "Stable frame and signal identifiers", "md_README.html#autotoc_md68", null ] ] ], - [ "Supported DBC Syntax", "md_README.html#autotoc_md73", null ], - [ "Frame definition", "md_README.html#autotoc_md74", [ - [ "Frame validation and parse errors", "md_README.html#autotoc_md76", null ] + [ "DbcDecoder", "md_README.html#autotoc_md70", null ], + [ "Parser Support", "md_README.html#autotoc_md72", [ + [ "Structured diagnostics", "md_README.html#autotoc_md73", null ] ] ], - [ "Signal definition", "md_README.html#autotoc_md78", [ - [ "Signal validation and parse errors", "md_README.html#autotoc_md80", null ] + [ "Supported DBC Syntax", "md_README.html#autotoc_md75", null ], + [ "Frame definition", "md_README.html#autotoc_md76", [ + [ "Frame validation and parse errors", "md_README.html#autotoc_md78", null ] ] ], - [ "Basic multiplexing", "md_README.html#autotoc_md82", null ], - [ "Comments", "md_README.html#autotoc_md84", null ], - [ "CAN ID Normalization", "md_README.html#autotoc_md86", null ], - [ "PGN Extraction", "md_README.html#autotoc_md88", null ], - [ "Decode Flow", "md_README.html#autotoc_md90", null ], - [ "Intel and Motorola Extraction", "md_README.html#autotoc_md92", null ], - [ "Example Usage", "md_README.html#autotoc_md94", [ - [ "Parse DBC", "md_README.html#autotoc_md95", null ], - [ "Build UI tree", "md_README.html#autotoc_md96", null ], - [ "Build runtime decode database", "md_README.html#autotoc_md97", null ], - [ "Decode a raw frame", "md_README.html#autotoc_md98", null ] + [ "Signal definition", "md_README.html#autotoc_md80", [ + [ "Signal validation and parse errors", "md_README.html#autotoc_md82", null ] ] ], - [ "Unified Decode Strategy", "md_README.html#autotoc_md100", [ - [ "live path", "md_README.html#autotoc_md101", null ], - [ "trace path", "md_README.html#autotoc_md102", null ] + [ "Basic multiplexing", "md_README.html#autotoc_md84", null ], + [ "Comments", "md_README.html#autotoc_md86", null ], + [ "CAN ID Normalization", "md_README.html#autotoc_md88", null ], + [ "PGN Extraction", "md_README.html#autotoc_md90", null ], + [ "Decode Flow", "md_README.html#autotoc_md92", null ], + [ "Intel and Motorola Extraction", "md_README.html#autotoc_md94", null ], + [ "Example Usage", "md_README.html#autotoc_md96", [ + [ "Parse DBC", "md_README.html#autotoc_md97", null ], + [ "Build UI tree", "md_README.html#autotoc_md98", null ], + [ "Build runtime decode database", "md_README.html#autotoc_md99", null ], + [ "Decode a raw frame", "md_README.html#autotoc_md100", null ] ] ], - [ "Intended Use in FrameTap", "md_README.html#autotoc_md104", null ], - [ "Why the Tree Is Not Enough", "md_README.html#autotoc_md106", null ], - [ "Statement Handler Factory", "md_README.html#autotoc_md108", null ], - [ "Signal value descriptions (VAL_)", "md_README.html#autotoc_md110", null ], - [ "Current Limitations", "md_README.html#autotoc_md112", null ], - [ "Recommended Next Steps", "md_README.html#autotoc_md114", [ - [ "Stage 1 - already implemented", "md_README.html#autotoc_md115", null ], - [ "Stage 2", "md_README.html#autotoc_md116", null ], - [ "Stage 3", "md_README.html#autotoc_md117", null ], - [ "Stage 4", "md_README.html#autotoc_md118", null ] + [ "Unified Decode Strategy", "md_README.html#autotoc_md102", [ + [ "live path", "md_README.html#autotoc_md103", null ], + [ "trace path", "md_README.html#autotoc_md104", null ] ] ], - [ "Build Integration", "md_README.html#autotoc_md120", [ - [ "Build core without Qt libraries", "md_README.html#autotoc_md121", null ], - [ "Optional Qt model adapter", "md_README.html#autotoc_md122", null ], - [ "Standalone tree tests without Qt", "md_README.html#autotoc_md123", null ], - [ "Build and run the demo", "md_README.html#autotoc_md124", null ], - [ "Generate API documentation", "md_README.html#autotoc_md125", null ] + [ "Intended Use in FrameTap", "md_README.html#autotoc_md106", null ], + [ "Why the Tree Is Not Enough", "md_README.html#autotoc_md108", null ], + [ "Statement Handler Factory", "md_README.html#autotoc_md110", null ], + [ "Signal value descriptions (VAL_)", "md_README.html#autotoc_md112", null ], + [ "Current Limitations", "md_README.html#autotoc_md114", null ], + [ "Recommended Next Steps", "md_README.html#autotoc_md116", [ + [ "Stage 1 - already implemented", "md_README.html#autotoc_md117", null ], + [ "Stage 2", "md_README.html#autotoc_md118", null ], + [ "Stage 3", "md_README.html#autotoc_md119", null ], + [ "Stage 4", "md_README.html#autotoc_md120", null ] ] ], - [ "Regression tests", "md_README.html#autotoc_md127", null ], - [ "Measuring code coverage", "md_README.html#autotoc_md128", [ - [ "GCC, gcov, and LCOV on Debian/Ubuntu", "md_README.html#autotoc_md129", null ], - [ "Configure the GCC coverage build in Qt Creator", "md_README.html#autotoc_md130", null ], - [ "Configure all build variants in Qt Creator", "md_README.html#autotoc_md131", null ] + [ "Build Integration", "md_README.html#autotoc_md122", [ + [ "Build core without Qt libraries", "md_README.html#autotoc_md123", null ], + [ "Optional Qt model adapter", "md_README.html#autotoc_md124", null ], + [ "Standalone tree tests without Qt", "md_README.html#autotoc_md125", null ], + [ "Build and run the demo", "md_README.html#autotoc_md126", null ], + [ "Generate API documentation", "md_README.html#autotoc_md127", null ] + ] ], + [ "Regression tests", "md_README.html#autotoc_md129", null ], + [ "Measuring code coverage", "md_README.html#autotoc_md130", [ + [ "GCC, gcov, and LCOV on Debian/Ubuntu", "md_README.html#autotoc_md131", null ], + [ "Configure the GCC coverage build in Qt Creator", "md_README.html#autotoc_md132", null ], + [ "Configure all build variants in Qt Creator", "md_README.html#autotoc_md133", null ] ] ] ] ], [ "QtTest regression tests", "md_tests_2README.html", [ - [ "Decoder coverage", "md_tests_2README.html#autotoc_md133", null ], - [ "Parser coverage", "md_tests_2README.html#autotoc_md134", null ], - [ "Tree and optional model tests", "md_tests_2README.html#autotoc_md135", null ], - [ "Additional regression coverage", "md_tests_2README.html#autotoc_md136", null ] + [ "Decoder coverage", "md_tests_2README.html#autotoc_md135", null ], + [ "Parser coverage", "md_tests_2README.html#autotoc_md136", null ], + [ "Tree and optional model tests", "md_tests_2README.html#autotoc_md137", null ], + [ "Additional regression coverage", "md_tests_2README.html#autotoc_md138", null ], + [ "Definition lifetime and reload coverage", "md_tests_2README.html#autotoc_md139", null ] ] ], [ "Classes", "annotated.html", [ [ "Class List", "annotated.html", "annotated_dup" ], @@ -166,7 +170,7 @@ var NAVTREE = var NAVTREEINDEX = [ "annotated.html", -"structRawCanFrame.html#a2d0e7fa0e3d5c20bbed55ed8f7888ff4" +"structFrameInfo.html#aa2b198ea0f55e560c123d35e7b3ecab9" ]; var SYNCONMSG = 'click to disable panel synchronisation'; diff --git a/docs/html/navtreeindex0.js b/docs/html/navtreeindex0.js index 5a99e1b..8b18d8a 100644 --- a/docs/html/navtreeindex0.js +++ b/docs/html/navtreeindex0.js @@ -6,7 +6,7 @@ var NAVTREEINDEX0 = "classDbcDecodeBuilder.html#a2bc6386dfb5e58976c42e22c19ec471b":[3,0,2,0], "classDbcDecoder.html":[3,0,3], "classDbcDecoder.html#a345951ffe5d943a70d3a1ea1f39e74f7":[3,0,3,1], -"classDbcDecoder.html#ab2cfb2fb711c95d3a29365546b89f3da":[3,0,3,0], +"classDbcDecoder.html#a4005c4311f57b7faf21c0cb31463039c":[3,0,3,0], "classDbcDiagnosticError.html":[3,0,5], "classDbcFrameHandler.html":[3,0,6], "classDbcHeaderHandler.html":[3,0,7], @@ -22,25 +22,29 @@ var NAVTREEINDEX0 = "classDbcTreeModel.html":[3,0,15], "classDbcUnsupportedMultiplexingHandler.html":[3,0,16], "classDbcValueDescriptionHandler.html":[3,0,17], -"classTreeNode.html":[3,0,30], -"classTreeNode.html#a226518612d0d00b5988a2c44fc21d3f1":[3,0,30,12], -"classTreeNode.html#a4727ff801a2d1b9323c5ae50a35457a6":[3,0,30,7], -"classTreeNode.html#a6161f2ebb92184eab4215d121870e788":[3,0,30,3], -"classTreeNode.html#a81047bd7d2a4cc96b9ef5e20d0d63b5f":[3,0,30,8], -"classTreeNode.html#a8e38dd591d8801d7ee3a7dbad90c67fc":[3,0,30,1], -"classTreeNode.html#a984a98d5ccf7ef1f5a18094c6821f35d":[3,0,30,0], -"classTreeNode.html#aa48fbc17903eb8cfa40353e29f853c6f":[3,0,30,4], -"classTreeNode.html#aaac5b8d9dc9e5ae1f367d1adbcf20e18":[3,0,30,10], -"classTreeNode.html#ab9f00f5253d56461bb2d420fd639c5ae":[3,0,30,2], -"classTreeNode.html#abdd82460187dca8d3e5d66f5d5c529ea":[3,0,30,6], -"classTreeNode.html#ad501f97eeec7f7d3353bfae838fbb6a8":[3,0,30,5], -"classTreeNode.html#afa2f4b0aafa12d3d41ed00df8e0250c9":[3,0,30,9], -"classTreeNode.html#afc503b40004764163605d6dbdb4ef811":[3,0,30,11], -"classTypeFactory.html":[3,0,31], -"classTypeFactory.html#a1a119ad2956abe146213c6ca124d8dd4":[3,0,31,3], -"classTypeFactory.html#a3f43b03d6e3a0fd503fdec01ecf62e9f":[3,0,31,2], -"classTypeFactory.html#ad6d85795285ee21193ac03e1b24762d3":[3,0,31,0], -"classTypeFactory.html#ad82f537569ece3d3a4a376523fa94473":[3,0,31,1], +"classDecodeDatabase.html":[3,0,18], +"classDecodeDatabase.html#a780d6e747a48b10a5eb0ab85448d2970":[3,0,18,2], +"classDecodeDatabase.html#aa034c1510984a85f60ad6c0bd744d6e8":[3,0,18,1], +"classDecodeDatabase.html#aa935a3a0d334f932d6a8c89a3818286a":[3,0,18,0], +"classTreeNode.html":[3,0,32], +"classTreeNode.html#a226518612d0d00b5988a2c44fc21d3f1":[3,0,32,12], +"classTreeNode.html#a4727ff801a2d1b9323c5ae50a35457a6":[3,0,32,7], +"classTreeNode.html#a6161f2ebb92184eab4215d121870e788":[3,0,32,3], +"classTreeNode.html#a81047bd7d2a4cc96b9ef5e20d0d63b5f":[3,0,32,8], +"classTreeNode.html#a8e38dd591d8801d7ee3a7dbad90c67fc":[3,0,32,1], +"classTreeNode.html#a984a98d5ccf7ef1f5a18094c6821f35d":[3,0,32,0], +"classTreeNode.html#aa48fbc17903eb8cfa40353e29f853c6f":[3,0,32,4], +"classTreeNode.html#aaac5b8d9dc9e5ae1f367d1adbcf20e18":[3,0,32,10], +"classTreeNode.html#ab9f00f5253d56461bb2d420fd639c5ae":[3,0,32,2], +"classTreeNode.html#abdd82460187dca8d3e5d66f5d5c529ea":[3,0,32,6], +"classTreeNode.html#ad501f97eeec7f7d3353bfae838fbb6a8":[3,0,32,5], +"classTreeNode.html#afa2f4b0aafa12d3d41ed00df8e0250c9":[3,0,32,9], +"classTreeNode.html#afc503b40004764163605d6dbdb4ef811":[3,0,32,11], +"classTypeFactory.html":[3,0,33], +"classTypeFactory.html#a1a119ad2956abe146213c6ca124d8dd4":[3,0,33,3], +"classTypeFactory.html#a3f43b03d6e3a0fd503fdec01ecf62e9f":[3,0,33,2], +"classTypeFactory.html#ad6d85795285ee21193ac03e1b24762d3":[3,0,33,0], +"classTypeFactory.html#ad82f537569ece3d3a4a376523fa94473":[3,0,33,1], "classes.html":[3,1], "dbc__coverage__test_8cpp_source.html":[4,0,3,0], "dbc__database_8h.html":[4,0,0,0], @@ -55,11 +59,12 @@ var NAVTREEINDEX0 = "dbc__decoder_8h_source.html":[4,0,0,4], "dbc__decoder__test_8cpp_source.html":[4,0,3,1], "dbc__diagnostic_8h_source.html":[4,0,0,5], +"dbc__lifetime__test_8cpp_source.html":[4,0,3,2], "dbc__parser_8cpp.html":[4,0,0,6], "dbc__parser_8cpp_source.html":[4,0,0,6], "dbc__parser_8h.html":[4,0,0,7], "dbc__parser_8h_source.html":[4,0,0,7], -"dbc__parser__test_8cpp_source.html":[4,0,3,2], +"dbc__parser__test_8cpp_source.html":[4,0,3,3], "dbc__statement__handler_8cpp_source.html":[4,0,0,8], "dbc__statement__handler_8h_source.html":[4,0,0,9], "dbc__tree__builder_8cpp.html":[4,0,0,10], @@ -68,15 +73,17 @@ var NAVTREEINDEX0 = "dbc__tree__builder_8h_source.html":[4,0,0,11], "dbc__tree__model_8cpp_source.html":[4,0,2,0], "dbc__tree__model_8h_source.html":[4,0,2,1], -"dbc__tree__model__test_8cpp_source.html":[4,0,3,3], -"decode__database_8h.html":[4,0,0,12], -"decode__database_8h.html#aaeb92d42f5a6e27b8ba19f18d69d142b":[4,0,0,12,5], -"decode__database_8h.html#aaeb92d42f5a6e27b8ba19f18d69d142ba2ed1afe3c9215523e4272f46e6186b31":[4,0,0,12,5,1], -"decode__database_8h.html#aaeb92d42f5a6e27b8ba19f18d69d142baff97a9fdede09eaf6e1c8ec9f6a61dd5":[4,0,0,12,5,0], -"decode__database_8h.html#ad9971b6ef33e02ba2c75d19c1d2518a1":[4,0,0,12,6], -"decode__database_8h.html#ad9971b6ef33e02ba2c75d19c1d2518a1a71fed0c3428bf1a2e19af257c4bac379":[4,0,0,12,6,1], -"decode__database_8h.html#ad9971b6ef33e02ba2c75d19c1d2518a1aa1a914735b205424ba6c40b85528d78a":[4,0,0,12,6,0], -"decode__database_8h_source.html":[4,0,0,12], +"dbc__tree__model__test_8cpp_source.html":[4,0,3,4], +"decode__database_8cpp_source.html":[4,0,0,12], +"decode__database_8h.html":[4,0,0,13], +"decode__database_8h.html#aaeb92d42f5a6e27b8ba19f18d69d142b":[4,0,0,13,3], +"decode__database_8h.html#aaeb92d42f5a6e27b8ba19f18d69d142ba2ed1afe3c9215523e4272f46e6186b31":[4,0,0,13,3,1], +"decode__database_8h.html#aaeb92d42f5a6e27b8ba19f18d69d142baff97a9fdede09eaf6e1c8ec9f6a61dd5":[4,0,0,13,3,0], +"decode__database_8h.html#ad9971b6ef33e02ba2c75d19c1d2518a1":[4,0,0,13,4], +"decode__database_8h.html#ad9971b6ef33e02ba2c75d19c1d2518a1a71fed0c3428bf1a2e19af257c4bac379":[4,0,0,13,4,1], +"decode__database_8h.html#ad9971b6ef33e02ba2c75d19c1d2518a1aa1a914735b205424ba6c40b85528d78a":[4,0,0,13,4,0], +"decode__database_8h_source.html":[4,0,0,13], +"definition__key_8h_source.html":[4,0,0,14], "dir_0f63d6441a2c250919e1e8723011eb2f.html":[4,0,2], "dir_4270bfced15e0e73154b13468c7c9ad9.html":[4,0,0], "dir_59425e443f801f1f2fd8bbe4959a3ccf.html":[4,0,3], @@ -84,8 +91,8 @@ var NAVTREEINDEX0 = "examples_2main_8cpp.html":[4,0,1,0], "examples_2main_8cpp_source.html":[4,0,1,0], "files.html":[4,0], -"frame__info_8h.html":[4,0,0,13], -"frame__info_8h_source.html":[4,0,0,13], +"frame__info_8h.html":[4,0,0,15], +"frame__info_8h_source.html":[4,0,0,15], "functions.html":[3,3,0], "functions_func.html":[3,3,1], "functions_vars.html":[3,3,2], @@ -94,30 +101,31 @@ var NAVTREEINDEX0 = "hierarchy.html":[3,2], "index.html":[], "md_README.html":[1], -"md_README.html#autotoc_md100":[1,34], -"md_README.html#autotoc_md101":[1,34,0], -"md_README.html#autotoc_md102":[1,34,1], -"md_README.html#autotoc_md104":[1,35], -"md_README.html#autotoc_md106":[1,36], -"md_README.html#autotoc_md108":[1,37], -"md_README.html#autotoc_md110":[1,38], -"md_README.html#autotoc_md112":[1,39], -"md_README.html#autotoc_md114":[1,40], -"md_README.html#autotoc_md115":[1,40,0], -"md_README.html#autotoc_md116":[1,40,1], -"md_README.html#autotoc_md117":[1,40,2], -"md_README.html#autotoc_md118":[1,40,3], -"md_README.html#autotoc_md120":[1,41], -"md_README.html#autotoc_md121":[1,41,0], -"md_README.html#autotoc_md122":[1,41,1], -"md_README.html#autotoc_md123":[1,41,2], -"md_README.html#autotoc_md124":[1,41,3], -"md_README.html#autotoc_md125":[1,41,4], -"md_README.html#autotoc_md127":[1,42], -"md_README.html#autotoc_md128":[1,43], -"md_README.html#autotoc_md129":[1,43,0], -"md_README.html#autotoc_md130":[1,43,1], -"md_README.html#autotoc_md131":[1,43,2], +"md_README.html#autotoc_md100":[1,33,3], +"md_README.html#autotoc_md102":[1,34], +"md_README.html#autotoc_md103":[1,34,0], +"md_README.html#autotoc_md104":[1,34,1], +"md_README.html#autotoc_md106":[1,35], +"md_README.html#autotoc_md108":[1,36], +"md_README.html#autotoc_md110":[1,37], +"md_README.html#autotoc_md112":[1,38], +"md_README.html#autotoc_md114":[1,39], +"md_README.html#autotoc_md116":[1,40], +"md_README.html#autotoc_md117":[1,40,0], +"md_README.html#autotoc_md118":[1,40,1], +"md_README.html#autotoc_md119":[1,40,2], +"md_README.html#autotoc_md120":[1,40,3], +"md_README.html#autotoc_md122":[1,41], +"md_README.html#autotoc_md123":[1,41,0], +"md_README.html#autotoc_md124":[1,41,1], +"md_README.html#autotoc_md125":[1,41,2], +"md_README.html#autotoc_md126":[1,41,3], +"md_README.html#autotoc_md127":[1,41,4], +"md_README.html#autotoc_md129":[1,42], +"md_README.html#autotoc_md130":[1,43], +"md_README.html#autotoc_md131":[1,43,0], +"md_README.html#autotoc_md132":[1,43,1], +"md_README.html#autotoc_md133":[1,43,2], "md_README.html#autotoc_md24":[1,0], "md_README.html#autotoc_md26":[1,1], "md_README.html#autotoc_md27":[1,1,0], @@ -143,25 +151,26 @@ var NAVTREEINDEX0 = "md_README.html#autotoc_md62":[1,20], "md_README.html#autotoc_md64":[1,20,0], "md_README.html#autotoc_md66":[1,21], -"md_README.html#autotoc_md68":[1,22], -"md_README.html#autotoc_md70":[1,23], -"md_README.html#autotoc_md71":[1,23,0], -"md_README.html#autotoc_md73":[1,24], -"md_README.html#autotoc_md74":[1,25], -"md_README.html#autotoc_md76":[1,25,0], -"md_README.html#autotoc_md78":[1,26], -"md_README.html#autotoc_md80":[1,26,0], -"md_README.html#autotoc_md82":[1,27], -"md_README.html#autotoc_md84":[1,28], -"md_README.html#autotoc_md86":[1,29], -"md_README.html#autotoc_md88":[1,30], -"md_README.html#autotoc_md90":[1,31], -"md_README.html#autotoc_md92":[1,32], -"md_README.html#autotoc_md94":[1,33], -"md_README.html#autotoc_md95":[1,33,0], -"md_README.html#autotoc_md96":[1,33,1], -"md_README.html#autotoc_md97":[1,33,2], -"md_README.html#autotoc_md98":[1,33,3], +"md_README.html#autotoc_md67":[1,21,0], +"md_README.html#autotoc_md68":[1,21,1], +"md_README.html#autotoc_md70":[1,22], +"md_README.html#autotoc_md72":[1,23], +"md_README.html#autotoc_md73":[1,23,0], +"md_README.html#autotoc_md75":[1,24], +"md_README.html#autotoc_md76":[1,25], +"md_README.html#autotoc_md78":[1,25,0], +"md_README.html#autotoc_md80":[1,26], +"md_README.html#autotoc_md82":[1,26,0], +"md_README.html#autotoc_md84":[1,27], +"md_README.html#autotoc_md86":[1,28], +"md_README.html#autotoc_md88":[1,29], +"md_README.html#autotoc_md90":[1,30], +"md_README.html#autotoc_md92":[1,31], +"md_README.html#autotoc_md94":[1,32], +"md_README.html#autotoc_md96":[1,33], +"md_README.html#autotoc_md97":[1,33,0], +"md_README.html#autotoc_md98":[1,33,1], +"md_README.html#autotoc_md99":[1,33,2], "md_changelog.html":[0], "md_changelog.html#autotoc_md1":[0,0], "md_changelog.html#autotoc_md10":[0,0,2,0], @@ -186,20 +195,20 @@ var NAVTREEINDEX0 = "md_changelog.html#autotoc_md8":[0,0,1,2], "md_changelog.html#autotoc_md9":[0,0,2], "md_tests_2README.html":[2], -"md_tests_2README.html#autotoc_md133":[2,0], -"md_tests_2README.html#autotoc_md134":[2,1], -"md_tests_2README.html#autotoc_md135":[2,2], -"md_tests_2README.html#autotoc_md136":[2,3], -"multiplexing_8h_source.html":[4,0,0,14], +"md_tests_2README.html#autotoc_md135":[2,0], +"md_tests_2README.html#autotoc_md136":[2,1], +"md_tests_2README.html#autotoc_md137":[2,2], +"md_tests_2README.html#autotoc_md138":[2,3], +"md_tests_2README.html#autotoc_md139":[2,4], +"multiplexing_8h_source.html":[4,0,0,16], "pages.html":[], -"signal__info_8h.html":[4,0,0,15], -"signal__info_8h_source.html":[4,0,0,15], +"signal__info_8h.html":[4,0,0,17], +"signal__info_8h_source.html":[4,0,0,17], "structDbcDatabase.html":[3,0,1], "structDbcDatabase.html#a2cade5d0234ee816132127542f8c612b":[3,0,1,0], "structDbcDiagnostic.html":[3,0,4], "structDbcParseContext.html":[3,0,8], "structDbcParseResult.html":[3,0,10], -"structDecodeDatabase.html":[3,0,18], "structDecodeFrame.html":[3,0,21], "structDecodeFrame.html#a1d3c54055c0cbceb73adf551f7067f23":[3,0,21,4], "structDecodeFrame.html#a2551102670c4a540fced4c71da0b369d":[3,0,21,5], @@ -225,29 +234,20 @@ var NAVTREEINDEX0 = "structDecodeSignal.html#acd4ef5ee30421d117b5756854302debb":[3,0,22,2], "structDecodeSignal.html#ae28c905d4a2bc86419c2a8361bfea473":[3,0,22,12], "structDecodedFrameValue.html":[3,0,19], -"structDecodedFrameValue.html#a4f51c31110dba1f73a763c596372beb0":[3,0,19,2], -"structDecodedFrameValue.html#a60dda1cc352d2c8087f0bdbc81dd266c":[3,0,19,0], -"structDecodedFrameValue.html#adae123ac7fbb4a5c314b64b01109f4a8":[3,0,19,1], +"structDecodedFrameValue.html#a32143efe2023a1ecd977a9ae93e50b73":[3,0,19,1], +"structDecodedFrameValue.html#a33e971ba10030506007aa201c89f351d":[3,0,19,0], +"structDecodedFrameValue.html#a4f51c31110dba1f73a763c596372beb0":[3,0,19,3], +"structDecodedFrameValue.html#adae123ac7fbb4a5c314b64b01109f4a8":[3,0,19,2], "structDecodedSignalValue.html":[3,0,20], -"structDecodedSignalValue.html#a503c90b4b1a610b8252c45e466367c28":[3,0,20,2], -"structDecodedSignalValue.html#a6847d05b3cb00d5e0f6c611968f57978":[3,0,20,3], -"structDecodedSignalValue.html#aac0ed361af545cde48d0e6f41a859686":[3,0,20,4], -"structDecodedSignalValue.html#acadc3b3bb21dd6b0412d342c7e6b20d7":[3,0,20,1], +"structDecodedSignalValue.html#a33df0fcd92b23b3e08539906fc6b4c4a":[3,0,20,2], +"structDecodedSignalValue.html#a503c90b4b1a610b8252c45e466367c28":[3,0,20,3], +"structDecodedSignalValue.html#a6847d05b3cb00d5e0f6c611968f57978":[3,0,20,4], +"structDecodedSignalValue.html#a828b5ef7faefc14fbf5dbd46249bcad2":[3,0,20,1], +"structDecodedSignalValue.html#aac0ed361af545cde48d0e6f41a859686":[3,0,20,5], "structDecodedSignalValue.html#affc38af1bf31bcb6f2c33044bce92bd2":[3,0,20,0], "structFrameInfo.html":[3,0,23], "structFrameInfo.html#a34b726afaad2ac5c697fdb2ac070cdaf":[3,0,23,2], "structFrameInfo.html#a3f7e25d67ddae22f2ed50823a5a26084":[3,0,23,8], "structFrameInfo.html#a4737a5420213ad4304724e39f3a4e55d":[3,0,23,4], -"structFrameInfo.html#a92749ec3798d4211a505860fb389a9e8":[3,0,23,6], -"structFrameInfo.html#aa2b198ea0f55e560c123d35e7b3ecab9":[3,0,23,5], -"structFrameInfo.html#abb53a7f93ed7abc0ea1ae4a8ccafcdcb":[3,0,23,0], -"structFrameInfo.html#ace75121294f9d89b762080ab5643293c":[3,0,23,7], -"structFrameInfo.html#aee518b33f1000bf0b7f6e4a87474c943":[3,0,23,3], -"structFrameInfo.html#af470b0742c05bfbffc31c51a68f5c05e":[3,0,23,1], -"structFrameKey.html":[3,0,24], -"structFrameKeyHasher.html":[3,0,25], -"structMultiplexing.html":[3,0,26], -"structPendingValueDescriptions.html":[3,0,27], -"structRawCanFrame.html":[3,0,28], -"structRawCanFrame.html#a0acb487612104c99c9907344c035df83":[3,0,28,2] +"structFrameInfo.html#a92749ec3798d4211a505860fb389a9e8":[3,0,23,6] }; diff --git a/docs/html/navtreeindex1.js b/docs/html/navtreeindex1.js index 2a072e1..3a8ac1e 100644 --- a/docs/html/navtreeindex1.js +++ b/docs/html/navtreeindex1.js @@ -1,5 +1,16 @@ var NAVTREEINDEX1 = { +"structFrameInfo.html#aa2b198ea0f55e560c123d35e7b3ecab9":[3,0,23,5], +"structFrameInfo.html#abb53a7f93ed7abc0ea1ae4a8ccafcdcb":[3,0,23,0], +"structFrameInfo.html#ace75121294f9d89b762080ab5643293c":[3,0,23,7], +"structFrameInfo.html#aee518b33f1000bf0b7f6e4a87474c943":[3,0,23,3], +"structFrameInfo.html#af470b0742c05bfbffc31c51a68f5c05e":[3,0,23,1], +"structFrameKey.html":[3,0,24], +"structFrameKeyHasher.html":[3,0,25], +"structMultiplexing.html":[3,0,26], +"structPendingValueDescriptions.html":[3,0,27], +"structRawCanFrame.html":[3,0,28], +"structRawCanFrame.html#a0acb487612104c99c9907344c035df83":[3,0,28,2], "structRawCanFrame.html#a2d0e7fa0e3d5c20bbed55ed8f7888ff4":[3,0,28,0], "structRawCanFrame.html#a462193d275adc1dba8bd18ffa0e36bb7":[3,0,28,1], "structSignalInfo.html":[3,0,29], @@ -16,17 +27,19 @@ var NAVTREEINDEX1 = "structSignalInfo.html#adf1c4331b9eabced0d7fdda40ff0eb52":[3,0,29,8], "structSignalInfo.html#ae4f78d99a2750aa564d7eba860171499":[3,0,29,5], "structSignalInfo.html#af363b1563fb4c7cc8973f9a80c06846c":[3,0,29,3], -"tests_2main_8cpp_source.html":[4,0,3,4], -"text__utils_8h_source.html":[4,0,0,16], -"tree__node_8cpp.html":[4,0,0,17], -"tree__node_8cpp_source.html":[4,0,0,17], -"tree__node_8h.html":[4,0,0,18], -"tree__node_8h.html#acac9cbaeea226ed297804c012dc12b16":[4,0,0,18,1], -"tree__node_8h.html#acac9cbaeea226ed297804c012dc12b16a085fea7abdc5d904fe69a3081efd7398":[4,0,0,18,1,2], -"tree__node_8h.html#acac9cbaeea226ed297804c012dc12b16a3bb3e8c8a24891ba0f7608bcc96f8b0a":[4,0,0,18,1,1], -"tree__node_8h.html#acac9cbaeea226ed297804c012dc12b16afa03eb688ad8aa1db593d33dabd89bad":[4,0,0,18,1,0], -"tree__node_8h_source.html":[4,0,0,18], -"tree__node__test_8cpp_source.html":[4,0,3,5], -"typefactory_8h_source.html":[4,0,0,19], -"value__descriptions_8h_source.html":[4,0,0,20] +"structSignalKey.html":[3,0,30], +"structSignalKeyHasher.html":[3,0,31], +"tests_2main_8cpp_source.html":[4,0,3,5], +"text__utils_8h_source.html":[4,0,0,18], +"tree__node_8cpp.html":[4,0,0,19], +"tree__node_8cpp_source.html":[4,0,0,19], +"tree__node_8h.html":[4,0,0,20], +"tree__node_8h.html#acac9cbaeea226ed297804c012dc12b16":[4,0,0,20,1], +"tree__node_8h.html#acac9cbaeea226ed297804c012dc12b16a085fea7abdc5d904fe69a3081efd7398":[4,0,0,20,1,2], +"tree__node_8h.html#acac9cbaeea226ed297804c012dc12b16a3bb3e8c8a24891ba0f7608bcc96f8b0a":[4,0,0,20,1,1], +"tree__node_8h.html#acac9cbaeea226ed297804c012dc12b16afa03eb688ad8aa1db593d33dabd89bad":[4,0,0,20,1,0], +"tree__node_8h_source.html":[4,0,0,20], +"tree__node__test_8cpp_source.html":[4,0,3,6], +"typefactory_8h_source.html":[4,0,0,21], +"value__descriptions_8h_source.html":[4,0,0,22] }; diff --git a/docs/html/search/all_1.js b/docs/html/search/all_1.js index 5fe8838..4a5c663 100644 --- a/docs/html/search/all_1.js +++ b/docs/html/search/all_1.js @@ -1,6 +1,6 @@ var searchData= [ - ['1_20already_20implemented_0',['Stage 1 - already implemented',['../md_README.html#autotoc_md115',1,'']]], + ['1_20already_20implemented_0',['Stage 1 - already implemented',['../md_README.html#autotoc_md117',1,'']]], ['1_20parse_20and_20ui_20path_1',['1. Parse and UI path',['../md_README.html#autotoc_md27',1,'']]], ['10_2001_2',['2026-10-01',['../md_changelog.html#autotoc_md15',1,'']]], ['10_2005_3',['2026-10-05',['../md_changelog.html#autotoc_md11',1,'']]], diff --git a/docs/html/search/all_10.js b/docs/html/search/all_10.js index a9d8425..9b467b5 100644 --- a/docs/html/search/all_10.js +++ b/docs/html/search/all_10.js @@ -1,8 +1,13 @@ var searchData= [ - ['name_0',['name',['../structDecodeSignal.html#a58cf5844f2272a23dcb9687d912e4780',1,'DecodeSignal::name'],['../structDecodeFrame.html#aa0a7f8fd5bfde2148dfd0d838328f579',1,'DecodeFrame::name'],['../structFrameInfo.html#abb53a7f93ed7abc0ea1ae4a8ccafcdcb',1,'FrameInfo::name'],['../structSignalInfo.html#a379e422a00cad56f896cacf60455b088',1,'SignalInfo::name']]], - ['next_20steps_1',['Recommended Next Steps',['../md_README.html#autotoc_md114',1,'']]], - ['nodetype_2',['NodeType',['../tree__node_8h.html#acac9cbaeea226ed297804c012dc12b16',1,'tree_node.h']]], - ['normalization_3',['CAN ID Normalization',['../md_README.html#autotoc_md86',1,'']]], - ['not_20enough_4',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md106',1,'']]] + ['maintenance_0',['maintenance',['../md_changelog.html#autotoc_md14',1,'Documentation and maintenance'],['../md_changelog.html#autotoc_md22',1,'Documentation and maintenance']]], + ['maximum_1',['maximum',['../structDecodeSignal.html#a4a6ba87142a9badbf0ca830e9e709cb7',1,'DecodeSignal::maximum'],['../structSignalInfo.html#adf1c4331b9eabced0d7fdda40ff0eb52',1,'SignalInfo::maximum']]], + ['measuring_20code_20coverage_2',['Measuring code coverage',['../md_README.html#autotoc_md130',1,'']]], + ['minimum_3',['minimum',['../structDecodeSignal.html#a0fb84e19a0ab3bd50b6f65c1075ebc25',1,'DecodeSignal::minimum'],['../structSignalInfo.html#ada7bf94fbeaa26bd08c73982b5af255b',1,'SignalInfo::minimum']]], + ['model_20adapter_4',['Optional Qt model adapter',['../md_README.html#autotoc_md124',1,'']]], + ['model_20tests_5',['Tree and optional model tests',['../md_tests_2README.html#autotoc_md137',1,'']]], + ['module_20documentation_6',['DBC Parser and Runtime Decode Module Documentation',['../md_README.html',1,'']]], + ['module_20layout_7',['Module Layout',['../md_README.html#autotoc_md32',1,'']]], + ['motorola_20extraction_8',['Intel and Motorola Extraction',['../md_README.html#autotoc_md94',1,'']]], + ['multiplexing_9',['multiplexing',['../md_README.html#autotoc_md84',1,'Basic multiplexing'],['../structMultiplexing.html',1,'Multiplexing']]] ]; diff --git a/docs/html/search/all_11.js b/docs/html/search/all_11.js index 2f4e13f..ac067a1 100644 --- a/docs/html/search/all_11.js +++ b/docs/html/search/all_11.js @@ -1,8 +1,8 @@ var searchData= [ - ['offset_0',['offset',['../structDecodeSignal.html#a92db637af4e224a0ae70173050dc3f74',1,'DecodeSignal::offset'],['../structSignalInfo.html#ab7d0769f47aa540656b22e4e49db517e',1,'SignalInfo::offset']]], - ['on_20debian_20ubuntu_1',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md129',1,'']]], - ['optional_20model_20tests_2',['Tree and optional model tests',['../md_tests_2README.html#autotoc_md135',1,'']]], - ['optional_20qt_20model_20adapter_3',['Optional Qt model adapter',['../md_README.html#autotoc_md122',1,'']]], - ['overview_4',['Overview',['../md_README.html#autotoc_md24',1,'']]] + ['name_0',['name',['../structDecodeSignal.html#a58cf5844f2272a23dcb9687d912e4780',1,'DecodeSignal::name'],['../structDecodeFrame.html#aa0a7f8fd5bfde2148dfd0d838328f579',1,'DecodeFrame::name'],['../structFrameInfo.html#abb53a7f93ed7abc0ea1ae4a8ccafcdcb',1,'FrameInfo::name'],['../structSignalInfo.html#a379e422a00cad56f896cacf60455b088',1,'SignalInfo::name']]], + ['next_20steps_1',['Recommended Next Steps',['../md_README.html#autotoc_md116',1,'']]], + ['nodetype_2',['NodeType',['../tree__node_8h.html#acac9cbaeea226ed297804c012dc12b16',1,'tree_node.h']]], + ['normalization_3',['CAN ID Normalization',['../md_README.html#autotoc_md88',1,'']]], + ['not_20enough_4',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md108',1,'']]] ]; diff --git a/docs/html/search/all_12.js b/docs/html/search/all_12.js index aa6131a..164a502 100644 --- a/docs/html/search/all_12.js +++ b/docs/html/search/all_12.js @@ -1,20 +1,9 @@ var searchData= [ - ['parse_20and_20ui_20path_0',['1. Parse and UI path',['../md_README.html#autotoc_md27',1,'']]], - ['parse_20dbc_1',['Parse DBC',['../md_README.html#autotoc_md95',1,'']]], - ['parse_20errors_2',['parse errors',['../md_README.html#autotoc_md76',1,'Frame validation and parse errors'],['../md_README.html#autotoc_md80',1,'Signal validation and parse errors']]], - ['parsed_20data_20structures_3',['Parsed Data Structures',['../md_README.html#autotoc_md34',1,'']]], - ['parsefile_4',['ParseFile',['../classDbcParser.html#aef72826942c9095d653fafa435855e56',1,'DbcParser']]], - ['parsefilewithdiagnostics_5',['ParseFileWithDiagnostics',['../classDbcParser.html#a0e915ce79c2e3d4c95a5aaf2bf0409bc',1,'DbcParser']]], - ['parser_20and_20runtime_20decode_20module_20documentation_6',['DBC Parser and Runtime Decode Module Documentation',['../md_README.html',1,'']]], - ['parser_20coverage_7',['Parser coverage',['../md_tests_2README.html#autotoc_md134',1,'']]], - ['parser_20support_8',['Parser Support',['../md_README.html#autotoc_md70',1,'']]], - ['path_9',['path',['../md_README.html#autotoc_md27',1,'1. Parse and UI path'],['../md_README.html#autotoc_md28',1,'2. Runtime decode path'],['../md_README.html#autotoc_md101',1,'live path'],['../md_README.html#autotoc_md102',1,'trace path']]], - ['pendingvaluedescriptions_10',['PendingValueDescriptions',['../structPendingValueDescriptions.html',1,'']]], - ['pgn_11',['pgn',['../structFrameInfo.html#aee518b33f1000bf0b7f6e4a87474c943',1,'FrameInfo::pgn'],['../structDecodeFrame.html#a1d3c54055c0cbceb73adf551f7067f23',1,'DecodeFrame::pgn']]], - ['pgn_20extraction_12',['PGN Extraction',['../md_README.html#autotoc_md88',1,'']]], - ['physicalvalue_13',['physicalValue',['../structDecodedSignalValue.html#a6847d05b3cb00d5e0f6c611968f57978',1,'DecodedSignalValue']]], - ['precision_14',['Raw value representation and precision',['../md_README.html#autotoc_md64',1,'']]], - ['public_15',['public',['../structFrameInfo.html#a3f7e25d67ddae22f2ed50823a5a26084',1,'FrameInfo::public'],['../structDecodeFrame.html#a7f4e71bbdec3f424b625e724e3dfbf14',1,'DecodeFrame::public'],['../structDecodedFrameValue.html#adae123ac7fbb4a5c314b64b01109f4a8',1,'DecodedFrameValue::public']]], - ['purpose_16',['Purpose',['../md_README.html#autotoc_md45',1,'']]] + ['offset_0',['offset',['../structDecodeSignal.html#a92db637af4e224a0ae70173050dc3f74',1,'DecodeSignal::offset'],['../structSignalInfo.html#ab7d0769f47aa540656b22e4e49db517e',1,'SignalInfo::offset']]], + ['on_20debian_20ubuntu_1',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md131',1,'']]], + ['optional_20model_20tests_2',['Tree and optional model tests',['../md_tests_2README.html#autotoc_md137',1,'']]], + ['optional_20qt_20model_20adapter_3',['Optional Qt model adapter',['../md_README.html#autotoc_md124',1,'']]], + ['overview_4',['Overview',['../md_README.html#autotoc_md24',1,'']]], + ['ownership_20and_20reload_5',['Definition ownership and reload',['../md_README.html#autotoc_md67',1,'']]] ]; diff --git a/docs/html/search/all_13.js b/docs/html/search/all_13.js index 4c40f73..191bae6 100644 --- a/docs/html/search/all_13.js +++ b/docs/html/search/all_13.js @@ -1,8 +1,20 @@ var searchData= [ - ['qt_0',['Standalone tree tests without Qt',['../md_README.html#autotoc_md123',1,'']]], - ['qt_20creator_1',['qt creator',['../md_README.html#autotoc_md131',1,'Configure all build variants in Qt Creator'],['../md_README.html#autotoc_md130',1,'Configure the GCC coverage build in Qt Creator']]], - ['qt_20libraries_2',['Build core without Qt libraries',['../md_README.html#autotoc_md121',1,'']]], - ['qt_20model_20adapter_3',['Optional Qt model adapter',['../md_README.html#autotoc_md122',1,'']]], - ['qttest_20regression_20tests_4',['QtTest regression tests',['../md_tests_2README.html',1,'']]] + ['parse_20and_20ui_20path_0',['1. Parse and UI path',['../md_README.html#autotoc_md27',1,'']]], + ['parse_20dbc_1',['Parse DBC',['../md_README.html#autotoc_md97',1,'']]], + ['parse_20errors_2',['parse errors',['../md_README.html#autotoc_md78',1,'Frame validation and parse errors'],['../md_README.html#autotoc_md82',1,'Signal validation and parse errors']]], + ['parsed_20data_20structures_3',['Parsed Data Structures',['../md_README.html#autotoc_md34',1,'']]], + ['parsefile_4',['ParseFile',['../classDbcParser.html#aef72826942c9095d653fafa435855e56',1,'DbcParser']]], + ['parsefilewithdiagnostics_5',['ParseFileWithDiagnostics',['../classDbcParser.html#a0e915ce79c2e3d4c95a5aaf2bf0409bc',1,'DbcParser']]], + ['parser_20and_20runtime_20decode_20module_20documentation_6',['DBC Parser and Runtime Decode Module Documentation',['../md_README.html',1,'']]], + ['parser_20coverage_7',['Parser coverage',['../md_tests_2README.html#autotoc_md136',1,'']]], + ['parser_20support_8',['Parser Support',['../md_README.html#autotoc_md72',1,'']]], + ['path_9',['path',['../md_README.html#autotoc_md27',1,'1. Parse and UI path'],['../md_README.html#autotoc_md28',1,'2. Runtime decode path'],['../md_README.html#autotoc_md103',1,'live path'],['../md_README.html#autotoc_md104',1,'trace path']]], + ['pendingvaluedescriptions_10',['PendingValueDescriptions',['../structPendingValueDescriptions.html',1,'']]], + ['pgn_11',['pgn',['../structFrameInfo.html#aee518b33f1000bf0b7f6e4a87474c943',1,'FrameInfo::pgn'],['../structDecodeFrame.html#a1d3c54055c0cbceb73adf551f7067f23',1,'DecodeFrame::pgn']]], + ['pgn_20extraction_12',['PGN Extraction',['../md_README.html#autotoc_md90',1,'']]], + ['physicalvalue_13',['physicalValue',['../structDecodedSignalValue.html#a6847d05b3cb00d5e0f6c611968f57978',1,'DecodedSignalValue']]], + ['precision_14',['Raw value representation and precision',['../md_README.html#autotoc_md64',1,'']]], + ['public_15',['public',['../structFrameInfo.html#a3f7e25d67ddae22f2ed50823a5a26084',1,'FrameInfo::public'],['../structDecodeFrame.html#a7f4e71bbdec3f424b625e724e3dfbf14',1,'DecodeFrame::public'],['../structDecodedFrameValue.html#adae123ac7fbb4a5c314b64b01109f4a8',1,'DecodedFrameValue::public']]], + ['purpose_16',['Purpose',['../md_README.html#autotoc_md45',1,'']]] ]; diff --git a/docs/html/search/all_14.js b/docs/html/search/all_14.js index 4a1f61e..6c9ae5c 100644 --- a/docs/html/search/all_14.js +++ b/docs/html/search/all_14.js @@ -1,20 +1,8 @@ var searchData= [ - ['raw_20frame_0',['Decode a raw frame',['../md_README.html#autotoc_md98',1,'']]], - ['raw_20value_20representation_20and_20precision_1',['Raw value representation and precision',['../md_README.html#autotoc_md64',1,'']]], - ['rawcanframe_2',['RawCanFrame',['../structRawCanFrame.html',1,'']]], - ['rawcanframe_20tt_3',['<tt>RawCanFrame</tt>',['../md_README.html#autotoc_md60',1,'']]], - ['rawvalue_4',['rawValue',['../structDecodedSignalValue.html#a503c90b4b1a610b8252c45e466367c28',1,'DecodedSignalValue']]], - ['receivers_5',['receivers',['../structDecodeSignal.html#abdbae62a64d2df716bf60c6b67b30eaa',1,'DecodeSignal::receivers'],['../structSignalInfo.html#a2c95562fd0b29327a7fd7b1e6feee7f3',1,'SignalInfo::receivers']]], - ['recommended_20next_20steps_6',['Recommended Next Steps',['../md_README.html#autotoc_md114',1,'']]], - ['registertype_7',['registerType',['../classTypeFactory.html#ad6d85795285ee21193ac03e1b24762d3',1,'TypeFactory']]], - ['regression_20coverage_8',['Additional regression coverage',['../md_tests_2README.html#autotoc_md136',1,'']]], - ['regression_20tests_9',['regression tests',['../md_tests_2README.html',1,'QtTest regression tests'],['../md_README.html#autotoc_md127',1,'Regression tests']]], - ['representation_20and_20precision_10',['Raw value representation and precision',['../md_README.html#autotoc_md64',1,'']]], - ['run_20the_20demo_11',['Build and run the demo',['../md_README.html#autotoc_md124',1,'']]], - ['runtime_20decode_20database_12',['Build runtime decode database',['../md_README.html#autotoc_md97',1,'']]], - ['runtime_20decode_20layer_13',['Runtime Decode Layer',['../md_README.html#autotoc_md44',1,'']]], - ['runtime_20decode_20layer_20exists_14',['Why the Runtime Decode Layer Exists',['../md_README.html#autotoc_md30',1,'']]], - ['runtime_20decode_20module_20documentation_15',['DBC Parser and Runtime Decode Module Documentation',['../md_README.html',1,'']]], - ['runtime_20decode_20path_16',['2. Runtime decode path',['../md_README.html#autotoc_md28',1,'']]] + ['qt_0',['Standalone tree tests without Qt',['../md_README.html#autotoc_md125',1,'']]], + ['qt_20creator_1',['qt creator',['../md_README.html#autotoc_md133',1,'Configure all build variants in Qt Creator'],['../md_README.html#autotoc_md132',1,'Configure the GCC coverage build in Qt Creator']]], + ['qt_20libraries_2',['Build core without Qt libraries',['../md_README.html#autotoc_md123',1,'']]], + ['qt_20model_20adapter_3',['Optional Qt model adapter',['../md_README.html#autotoc_md124',1,'']]], + ['qttest_20regression_20tests_4',['QtTest regression tests',['../md_tests_2README.html',1,'']]] ]; diff --git a/docs/html/search/all_15.js b/docs/html/search/all_15.js index ee54676..f411f4c 100644 --- a/docs/html/search/all_15.js +++ b/docs/html/search/all_15.js @@ -1,23 +1,22 @@ var searchData= [ - ['signal_20definition_0',['Signal definition',['../md_README.html#autotoc_md78',1,'']]], - ['signal_20validation_20and_20parse_20errors_1',['Signal validation and parse errors',['../md_README.html#autotoc_md80',1,'']]], - ['signal_20value_20descriptions_20tt_20val_5f_20tt_2',['Signal value descriptions (<tt>VAL_</tt>)',['../md_README.html#autotoc_md110',1,'']]], - ['signal_5finfo_2eh_3',['signal_info.h',['../signal__info_8h.html',1,'']]], - ['signalinfo_4',['SignalInfo',['../structSignalInfo.html',1,'']]], - ['signalinfo_20tt_5',['<tt>SignalInfo</tt>',['../md_README.html#autotoc_md35',1,'']]], - ['stage_201_20already_20implemented_6',['Stage 1 - already implemented',['../md_README.html#autotoc_md115',1,'']]], - ['stage_202_7',['Stage 2',['../md_README.html#autotoc_md116',1,'']]], - ['stage_203_8',['Stage 3',['../md_README.html#autotoc_md117',1,'']]], - ['stage_204_9',['Stage 4',['../md_README.html#autotoc_md118',1,'']]], - ['standalone_20tree_20tests_20without_20qt_10',['Standalone tree tests without Qt',['../md_README.html#autotoc_md123',1,'']]], - ['startbit_11',['startbit',['../structDecodeSignal.html#aaf5d7527ddf65b6355c2b4f3626df22d',1,'DecodeSignal::startBit'],['../structSignalInfo.html#ace290724f9801521609aedaa946d61f1',1,'SignalInfo::startBit']]], - ['statement_20handler_20factory_12',['Statement Handler Factory',['../md_README.html#autotoc_md108',1,'']]], - ['steps_13',['Recommended Next Steps',['../md_README.html#autotoc_md114',1,'']]], - ['strategy_14',['Unified Decode Strategy',['../md_README.html#autotoc_md100',1,'']]], - ['structured_20diagnostics_15',['Structured diagnostics',['../md_README.html#autotoc_md71',1,'']]], - ['structures_16',['Parsed Data Structures',['../md_README.html#autotoc_md34',1,'']]], - ['support_17',['Parser Support',['../md_README.html#autotoc_md70',1,'']]], - ['supported_20dbc_20syntax_18',['Supported DBC Syntax',['../md_README.html#autotoc_md73',1,'']]], - ['syntax_19',['Supported DBC Syntax',['../md_README.html#autotoc_md73',1,'']]] + ['raw_20frame_0',['Decode a raw frame',['../md_README.html#autotoc_md100',1,'']]], + ['raw_20value_20representation_20and_20precision_1',['Raw value representation and precision',['../md_README.html#autotoc_md64',1,'']]], + ['rawcanframe_2',['RawCanFrame',['../structRawCanFrame.html',1,'']]], + ['rawcanframe_20tt_3',['<tt>RawCanFrame</tt>',['../md_README.html#autotoc_md60',1,'']]], + ['rawvalue_4',['rawValue',['../structDecodedSignalValue.html#a503c90b4b1a610b8252c45e466367c28',1,'DecodedSignalValue']]], + ['receivers_5',['receivers',['../structSignalInfo.html#a2c95562fd0b29327a7fd7b1e6feee7f3',1,'SignalInfo::receivers'],['../structDecodeSignal.html#abdbae62a64d2df716bf60c6b67b30eaa',1,'DecodeSignal::receivers']]], + ['recommended_20next_20steps_6',['Recommended Next Steps',['../md_README.html#autotoc_md116',1,'']]], + ['registertype_7',['registerType',['../classTypeFactory.html#ad6d85795285ee21193ac03e1b24762d3',1,'TypeFactory']]], + ['regression_20coverage_8',['Additional regression coverage',['../md_tests_2README.html#autotoc_md138',1,'']]], + ['regression_20tests_9',['regression tests',['../md_tests_2README.html',1,'QtTest regression tests'],['../md_README.html#autotoc_md129',1,'Regression tests']]], + ['reload_10',['Definition ownership and reload',['../md_README.html#autotoc_md67',1,'']]], + ['reload_20coverage_11',['Definition lifetime and reload coverage',['../md_tests_2README.html#autotoc_md139',1,'']]], + ['representation_20and_20precision_12',['Raw value representation and precision',['../md_README.html#autotoc_md64',1,'']]], + ['run_20the_20demo_13',['Build and run the demo',['../md_README.html#autotoc_md126',1,'']]], + ['runtime_20decode_20database_14',['Build runtime decode database',['../md_README.html#autotoc_md99',1,'']]], + ['runtime_20decode_20layer_15',['Runtime Decode Layer',['../md_README.html#autotoc_md44',1,'']]], + ['runtime_20decode_20layer_20exists_16',['Why the Runtime Decode Layer Exists',['../md_README.html#autotoc_md30',1,'']]], + ['runtime_20decode_20module_20documentation_17',['DBC Parser and Runtime Decode Module Documentation',['../md_README.html',1,'']]], + ['runtime_20decode_20path_18',['2. Runtime decode path',['../md_README.html#autotoc_md28',1,'']]] ]; diff --git a/docs/html/search/all_16.js b/docs/html/search/all_16.js index 3bfccda..4618291 100644 --- a/docs/html/search/all_16.js +++ b/docs/html/search/all_16.js @@ -1,37 +1,27 @@ var searchData= [ - ['tests_0',['tests',['../md_tests_2README.html',1,'QtTest regression tests'],['../md_README.html#autotoc_md127',1,'Regression tests'],['../md_tests_2README.html#autotoc_md135',1,'Tree and optional model tests']]], - ['tests_20without_20qt_1',['Standalone tree tests without Qt',['../md_README.html#autotoc_md123',1,'']]], - ['the_20demo_2',['Build and run the demo',['../md_README.html#autotoc_md124',1,'']]], - ['the_20gcc_20coverage_20build_20in_20qt_20creator_3',['Configure the GCC coverage build in Qt Creator',['../md_README.html#autotoc_md130',1,'']]], - ['the_20runtime_20decode_20layer_20exists_4',['Why the Runtime Decode Layer Exists',['../md_README.html#autotoc_md30',1,'']]], - ['the_20tree_20is_20not_20enough_5',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md106',1,'']]], - ['trace_20path_6',['trace path',['../md_README.html#autotoc_md102',1,'']]], - ['transmitter_7',['transmitter',['../structFrameInfo.html#a92749ec3798d4211a505860fb389a9e8',1,'FrameInfo::transmitter'],['../structDecodeFrame.html#ad78241dc40c793aabb8495b6989b81a9',1,'DecodeFrame::transmitter']]], - ['tree_8',['Build UI tree',['../md_README.html#autotoc_md96',1,'']]], - ['tree_20and_20optional_20model_20tests_9',['Tree and optional model tests',['../md_tests_2README.html#autotoc_md135',1,'']]], - ['tree_20is_20not_20enough_10',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md106',1,'']]], - ['tree_20layer_11',['UI Tree Layer',['../md_README.html#autotoc_md41',1,'']]], - ['tree_20tests_20without_20qt_12',['Standalone tree tests without Qt',['../md_README.html#autotoc_md123',1,'']]], - ['tree_5fnode_2ecpp_13',['tree_node.cpp',['../tree__node_8cpp.html',1,'']]], - ['tree_5fnode_2eh_14',['tree_node.h',['../tree__node_8h.html',1,'']]], - ['treenode_15',['treenode',['../classTreeNode.html#ab9f00f5253d56461bb2d420fd639c5ae',1,'TreeNode::TreeNode()'],['../classTreeNode.html',1,'TreeNode'],['../classTreeNode.html#a984a98d5ccf7ef1f5a18094c6821f35d',1,'TreeNode::TreeNode()'],['../classTreeNode.html#a8e38dd591d8801d7ee3a7dbad90c67fc',1,'TreeNode::TreeNode(const FrameInfo &frame)']]], - ['treenode_20tt_16',['<tt>TreeNode</tt>',['../md_README.html#autotoc_md42',1,'']]], - ['tt_20byteorder_20tt_17',['<tt>ByteOrder</tt>',['../md_README.html#autotoc_md47',1,'']]], - ['tt_20dbcdatabase_20tt_18',['<tt>DbcDatabase</tt>',['../md_README.html#autotoc_md39',1,'']]], - ['tt_20dbcdecoder_20tt_19',['<tt>DbcDecoder</tt>',['../md_README.html#autotoc_md68',1,'']]], - ['tt_20decodedatabase_20tt_20',['<tt>DecodeDatabase</tt>',['../md_README.html#autotoc_md57',1,'']]], - ['tt_20decodedframevalue_20tt_21',['<tt>DecodedFrameValue</tt>',['../md_README.html#autotoc_md66',1,'']]], - ['tt_20decodedsignalvalue_20tt_22',['<tt>DecodedSignalValue</tt>',['../md_README.html#autotoc_md62',1,'']]], - ['tt_20decodeframe_20tt_23',['<tt>DecodeFrame</tt>',['../md_README.html#autotoc_md53',1,'']]], - ['tt_20decodesignal_20tt_24',['<tt>DecodeSignal</tt>',['../md_README.html#autotoc_md51',1,'']]], - ['tt_20frameinfo_20tt_25',['<tt>FrameInfo</tt>',['../md_README.html#autotoc_md37',1,'']]], - ['tt_20framekey_20tt_26',['<tt>FrameKey</tt>',['../md_README.html#autotoc_md55',1,'']]], - ['tt_20rawcanframe_20tt_27',['<tt>RawCanFrame</tt>',['../md_README.html#autotoc_md60',1,'']]], - ['tt_20signalinfo_20tt_28',['<tt>SignalInfo</tt>',['../md_README.html#autotoc_md35',1,'']]], - ['tt_20treenode_20tt_29',['<tt>TreeNode</tt>',['../md_README.html#autotoc_md42',1,'']]], - ['tt_20val_5f_20tt_30',['Signal value descriptions (<tt>VAL_</tt>)',['../md_README.html#autotoc_md110',1,'']]], - ['tt_20valuetype_20tt_31',['<tt>ValueType</tt>',['../md_README.html#autotoc_md49',1,'']]], - ['typefactory_32',['TypeFactory',['../classTypeFactory.html',1,'']]], - ['typefactory_3c_20std_3a_3astring_2c_20dbcstatementhandler_20_3e_33',['TypeFactory< std::string, DbcStatementHandler >',['../classTypeFactory.html',1,'']]] + ['signal_20definition_0',['Signal definition',['../md_README.html#autotoc_md80',1,'']]], + ['signal_20identifiers_1',['Stable frame and signal identifiers',['../md_README.html#autotoc_md68',1,'']]], + ['signal_20validation_20and_20parse_20errors_2',['Signal validation and parse errors',['../md_README.html#autotoc_md82',1,'']]], + ['signal_20value_20descriptions_20tt_20val_5f_20tt_3',['Signal value descriptions (<tt>VAL_</tt>)',['../md_README.html#autotoc_md112',1,'']]], + ['signal_5finfo_2eh_4',['signal_info.h',['../signal__info_8h.html',1,'']]], + ['signalinfo_5',['SignalInfo',['../structSignalInfo.html',1,'']]], + ['signalinfo_20tt_6',['<tt>SignalInfo</tt>',['../md_README.html#autotoc_md35',1,'']]], + ['signalkey_7',['SignalKey',['../structSignalKey.html',1,'']]], + ['signalkeyhasher_8',['SignalKeyHasher',['../structSignalKeyHasher.html',1,'']]], + ['stable_20frame_20and_20signal_20identifiers_9',['Stable frame and signal identifiers',['../md_README.html#autotoc_md68',1,'']]], + ['stage_201_20already_20implemented_10',['Stage 1 - already implemented',['../md_README.html#autotoc_md117',1,'']]], + ['stage_202_11',['Stage 2',['../md_README.html#autotoc_md118',1,'']]], + ['stage_203_12',['Stage 3',['../md_README.html#autotoc_md119',1,'']]], + ['stage_204_13',['Stage 4',['../md_README.html#autotoc_md120',1,'']]], + ['standalone_20tree_20tests_20without_20qt_14',['Standalone tree tests without Qt',['../md_README.html#autotoc_md125',1,'']]], + ['startbit_15',['startbit',['../structSignalInfo.html#ace290724f9801521609aedaa946d61f1',1,'SignalInfo::startBit'],['../structDecodeSignal.html#aaf5d7527ddf65b6355c2b4f3626df22d',1,'DecodeSignal::startBit']]], + ['statement_20handler_20factory_16',['Statement Handler Factory',['../md_README.html#autotoc_md110',1,'']]], + ['steps_17',['Recommended Next Steps',['../md_README.html#autotoc_md116',1,'']]], + ['strategy_18',['Unified Decode Strategy',['../md_README.html#autotoc_md102',1,'']]], + ['structured_20diagnostics_19',['Structured diagnostics',['../md_README.html#autotoc_md73',1,'']]], + ['structures_20',['Parsed Data Structures',['../md_README.html#autotoc_md34',1,'']]], + ['support_21',['Parser Support',['../md_README.html#autotoc_md72',1,'']]], + ['supported_20dbc_20syntax_22',['Supported DBC Syntax',['../md_README.html#autotoc_md75',1,'']]], + ['syntax_23',['Supported DBC Syntax',['../md_README.html#autotoc_md75',1,'']]] ]; diff --git a/docs/html/search/all_17.js b/docs/html/search/all_17.js index 2581eed..ec968d2 100644 --- a/docs/html/search/all_17.js +++ b/docs/html/search/all_17.js @@ -1,12 +1,37 @@ var searchData= [ - ['ubuntu_0',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md129',1,'']]], - ['ui_20path_1',['1. Parse and UI path',['../md_README.html#autotoc_md27',1,'']]], - ['ui_20tree_2',['Build UI tree',['../md_README.html#autotoc_md96',1,'']]], - ['ui_20tree_20layer_3',['UI Tree Layer',['../md_README.html#autotoc_md41',1,'']]], - ['unified_20decode_20strategy_4',['Unified Decode Strategy',['../md_README.html#autotoc_md100',1,'']]], - ['unit_5',['unit',['../structDecodeSignal.html#a38eed9ca7581423fd8bfbedcffc12092',1,'DecodeSignal::unit'],['../structSignalInfo.html#a1f214f03e94ef5794de2d3367bfcbd01',1,'SignalInfo::unit']]], - ['unreleased_6',['Unreleased',['../md_changelog.html#autotoc_md1',1,'']]], - ['usage_7',['Example Usage',['../md_README.html#autotoc_md94',1,'']]], - ['use_20in_20frametap_8',['Intended Use in FrameTap',['../md_README.html#autotoc_md104',1,'']]] + ['tests_0',['tests',['../md_tests_2README.html',1,'QtTest regression tests'],['../md_README.html#autotoc_md129',1,'Regression tests'],['../md_tests_2README.html#autotoc_md137',1,'Tree and optional model tests']]], + ['tests_20without_20qt_1',['Standalone tree tests without Qt',['../md_README.html#autotoc_md125',1,'']]], + ['the_20demo_2',['Build and run the demo',['../md_README.html#autotoc_md126',1,'']]], + ['the_20gcc_20coverage_20build_20in_20qt_20creator_3',['Configure the GCC coverage build in Qt Creator',['../md_README.html#autotoc_md132',1,'']]], + ['the_20runtime_20decode_20layer_20exists_4',['Why the Runtime Decode Layer Exists',['../md_README.html#autotoc_md30',1,'']]], + ['the_20tree_20is_20not_20enough_5',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md108',1,'']]], + ['trace_20path_6',['trace path',['../md_README.html#autotoc_md104',1,'']]], + ['transmitter_7',['transmitter',['../structFrameInfo.html#a92749ec3798d4211a505860fb389a9e8',1,'FrameInfo::transmitter'],['../structDecodeFrame.html#ad78241dc40c793aabb8495b6989b81a9',1,'DecodeFrame::transmitter']]], + ['tree_8',['Build UI tree',['../md_README.html#autotoc_md98',1,'']]], + ['tree_20and_20optional_20model_20tests_9',['Tree and optional model tests',['../md_tests_2README.html#autotoc_md137',1,'']]], + ['tree_20is_20not_20enough_10',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md108',1,'']]], + ['tree_20layer_11',['UI Tree Layer',['../md_README.html#autotoc_md41',1,'']]], + ['tree_20tests_20without_20qt_12',['Standalone tree tests without Qt',['../md_README.html#autotoc_md125',1,'']]], + ['tree_5fnode_2ecpp_13',['tree_node.cpp',['../tree__node_8cpp.html',1,'']]], + ['tree_5fnode_2eh_14',['tree_node.h',['../tree__node_8h.html',1,'']]], + ['treenode_15',['treenode',['../classTreeNode.html#ab9f00f5253d56461bb2d420fd639c5ae',1,'TreeNode::TreeNode()'],['../classTreeNode.html',1,'TreeNode'],['../classTreeNode.html#a984a98d5ccf7ef1f5a18094c6821f35d',1,'TreeNode::TreeNode()'],['../classTreeNode.html#a8e38dd591d8801d7ee3a7dbad90c67fc',1,'TreeNode::TreeNode(const FrameInfo &frame)']]], + ['treenode_20tt_16',['<tt>TreeNode</tt>',['../md_README.html#autotoc_md42',1,'']]], + ['tt_20byteorder_20tt_17',['<tt>ByteOrder</tt>',['../md_README.html#autotoc_md47',1,'']]], + ['tt_20dbcdatabase_20tt_18',['<tt>DbcDatabase</tt>',['../md_README.html#autotoc_md39',1,'']]], + ['tt_20dbcdecoder_20tt_19',['<tt>DbcDecoder</tt>',['../md_README.html#autotoc_md70',1,'']]], + ['tt_20decodedatabase_20tt_20',['<tt>DecodeDatabase</tt>',['../md_README.html#autotoc_md57',1,'']]], + ['tt_20decodedframevalue_20tt_21',['<tt>DecodedFrameValue</tt>',['../md_README.html#autotoc_md66',1,'']]], + ['tt_20decodedsignalvalue_20tt_22',['<tt>DecodedSignalValue</tt>',['../md_README.html#autotoc_md62',1,'']]], + ['tt_20decodeframe_20tt_23',['<tt>DecodeFrame</tt>',['../md_README.html#autotoc_md53',1,'']]], + ['tt_20decodesignal_20tt_24',['<tt>DecodeSignal</tt>',['../md_README.html#autotoc_md51',1,'']]], + ['tt_20frameinfo_20tt_25',['<tt>FrameInfo</tt>',['../md_README.html#autotoc_md37',1,'']]], + ['tt_20framekey_20tt_26',['<tt>FrameKey</tt>',['../md_README.html#autotoc_md55',1,'']]], + ['tt_20rawcanframe_20tt_27',['<tt>RawCanFrame</tt>',['../md_README.html#autotoc_md60',1,'']]], + ['tt_20signalinfo_20tt_28',['<tt>SignalInfo</tt>',['../md_README.html#autotoc_md35',1,'']]], + ['tt_20treenode_20tt_29',['<tt>TreeNode</tt>',['../md_README.html#autotoc_md42',1,'']]], + ['tt_20val_5f_20tt_30',['Signal value descriptions (<tt>VAL_</tt>)',['../md_README.html#autotoc_md112',1,'']]], + ['tt_20valuetype_20tt_31',['<tt>ValueType</tt>',['../md_README.html#autotoc_md49',1,'']]], + ['typefactory_32',['TypeFactory',['../classTypeFactory.html',1,'']]], + ['typefactory_3c_20std_3a_3astring_2c_20dbcstatementhandler_20_3e_33',['TypeFactory< std::string, DbcStatementHandler >',['../classTypeFactory.html',1,'']]] ]; diff --git a/docs/html/search/all_18.js b/docs/html/search/all_18.js index 7f92ea5..b909aa5 100644 --- a/docs/html/search/all_18.js +++ b/docs/html/search/all_18.js @@ -1,13 +1,12 @@ var searchData= [ - ['v1_200_20—_202026_2006_2014_0',['v1.0 — 2026-06-14',['../md_changelog.html#autotoc_md18',1,'']]], - ['val_5f_20tt_1',['Signal value descriptions (<tt>VAL_</tt>)',['../md_README.html#autotoc_md110',1,'']]], - ['valid_2',['valid',['../structDecodedSignalValue.html#aac0ed361af545cde48d0e6f41a859686',1,'DecodedSignalValue::valid'],['../structDecodedFrameValue.html#a4f51c31110dba1f73a763c596372beb0',1,'DecodedFrameValue::valid']]], - ['validation_20and_20parse_20errors_3',['validation and parse errors',['../md_README.html#autotoc_md76',1,'Frame validation and parse errors'],['../md_README.html#autotoc_md80',1,'Signal validation and parse errors']]], - ['value_20descriptions_20tt_20val_5f_20tt_4',['Signal value descriptions (<tt>VAL_</tt>)',['../md_README.html#autotoc_md110',1,'']]], - ['value_20representation_20and_20precision_5',['Raw value representation and precision',['../md_README.html#autotoc_md64',1,'']]], - ['valuedescriptions_6',['valuedescriptions',['../structDecodeSignal.html#a822155d9bf4ed5f3300c9e9befe606ff',1,'DecodeSignal::valueDescriptions'],['../structSignalInfo.html#a43f47d0433d0cc39076bd7278b46af9c',1,'SignalInfo::valueDescriptions']]], - ['valuetype_7',['valuetype',['../structDecodeSignal.html#a9d37638129263b8902ba5be59baf39a8',1,'DecodeSignal::valueType'],['../decode__database_8h.html#ad9971b6ef33e02ba2c75d19c1d2518a1',1,'ValueType: decode_database.h']]], - ['valuetype_20tt_8',['<tt>ValueType</tt>',['../md_README.html#autotoc_md49',1,'']]], - ['variants_20in_20qt_20creator_9',['Configure all build variants in Qt Creator',['../md_README.html#autotoc_md131',1,'']]] + ['ubuntu_0',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md131',1,'']]], + ['ui_20path_1',['1. Parse and UI path',['../md_README.html#autotoc_md27',1,'']]], + ['ui_20tree_2',['Build UI tree',['../md_README.html#autotoc_md98',1,'']]], + ['ui_20tree_20layer_3',['UI Tree Layer',['../md_README.html#autotoc_md41',1,'']]], + ['unified_20decode_20strategy_4',['Unified Decode Strategy',['../md_README.html#autotoc_md102',1,'']]], + ['unit_5',['unit',['../structDecodeSignal.html#a38eed9ca7581423fd8bfbedcffc12092',1,'DecodeSignal::unit'],['../structSignalInfo.html#a1f214f03e94ef5794de2d3367bfcbd01',1,'SignalInfo::unit']]], + ['unreleased_6',['Unreleased',['../md_changelog.html#autotoc_md1',1,'']]], + ['usage_7',['Example Usage',['../md_README.html#autotoc_md96',1,'']]], + ['use_20in_20frametap_8',['Intended Use in FrameTap',['../md_README.html#autotoc_md106',1,'']]] ]; diff --git a/docs/html/search/all_19.js b/docs/html/search/all_19.js index 2c45351..91bc6da 100644 --- a/docs/html/search/all_19.js +++ b/docs/html/search/all_19.js @@ -1,7 +1,13 @@ var searchData= [ - ['why_20the_20runtime_20decode_20layer_20exists_0',['Why the Runtime Decode Layer Exists',['../md_README.html#autotoc_md30',1,'']]], - ['why_20the_20tree_20is_20not_20enough_1',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md106',1,'']]], - ['without_20qt_2',['Standalone tree tests without Qt',['../md_README.html#autotoc_md123',1,'']]], - ['without_20qt_20libraries_3',['Build core without Qt libraries',['../md_README.html#autotoc_md121',1,'']]] + ['v1_200_20—_202026_2006_2014_0',['v1.0 — 2026-06-14',['../md_changelog.html#autotoc_md18',1,'']]], + ['val_5f_20tt_1',['Signal value descriptions (<tt>VAL_</tt>)',['../md_README.html#autotoc_md112',1,'']]], + ['valid_2',['valid',['../structDecodedSignalValue.html#aac0ed361af545cde48d0e6f41a859686',1,'DecodedSignalValue::valid'],['../structDecodedFrameValue.html#a4f51c31110dba1f73a763c596372beb0',1,'DecodedFrameValue::valid']]], + ['validation_20and_20parse_20errors_3',['validation and parse errors',['../md_README.html#autotoc_md78',1,'Frame validation and parse errors'],['../md_README.html#autotoc_md82',1,'Signal validation and parse errors']]], + ['value_20descriptions_20tt_20val_5f_20tt_4',['Signal value descriptions (<tt>VAL_</tt>)',['../md_README.html#autotoc_md112',1,'']]], + ['value_20representation_20and_20precision_5',['Raw value representation and precision',['../md_README.html#autotoc_md64',1,'']]], + ['valuedescriptions_6',['valuedescriptions',['../structDecodeSignal.html#a822155d9bf4ed5f3300c9e9befe606ff',1,'DecodeSignal::valueDescriptions'],['../structSignalInfo.html#a43f47d0433d0cc39076bd7278b46af9c',1,'SignalInfo::valueDescriptions']]], + ['valuetype_7',['valuetype',['../structDecodeSignal.html#a9d37638129263b8902ba5be59baf39a8',1,'DecodeSignal::valueType'],['../decode__database_8h.html#ad9971b6ef33e02ba2c75d19c1d2518a1',1,'ValueType: decode_database.h']]], + ['valuetype_20tt_8',['<tt>ValueType</tt>',['../md_README.html#autotoc_md49',1,'']]], + ['variants_20in_20qt_20creator_9',['Configure all build variants in Qt Creator',['../md_README.html#autotoc_md133',1,'']]] ]; diff --git a/docs/html/search/all_1a.js b/docs/html/search/all_1a.js index f1c1625..d902d6a 100644 --- a/docs/html/search/all_1a.js +++ b/docs/html/search/all_1a.js @@ -1,5 +1,7 @@ var searchData= [ - ['—_202026_2003_2013_0',['Initial implementation — 2026-03-13',['../md_changelog.html#autotoc_md20',1,'']]], - ['—_202026_2006_2014_1',['v1.0 — 2026-06-14',['../md_changelog.html#autotoc_md18',1,'']]] + ['why_20the_20runtime_20decode_20layer_20exists_0',['Why the Runtime Decode Layer Exists',['../md_README.html#autotoc_md30',1,'']]], + ['why_20the_20tree_20is_20not_20enough_1',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md108',1,'']]], + ['without_20qt_2',['Standalone tree tests without Qt',['../md_README.html#autotoc_md125',1,'']]], + ['without_20qt_20libraries_3',['Build core without Qt libraries',['../md_README.html#autotoc_md123',1,'']]] ]; diff --git a/docs/html/search/all_1b.js b/docs/html/search/all_1b.js new file mode 100644 index 0000000..f1c1625 --- /dev/null +++ b/docs/html/search/all_1b.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['—_202026_2003_2013_0',['Initial implementation — 2026-03-13',['../md_changelog.html#autotoc_md20',1,'']]], + ['—_202026_2006_2014_1',['v1.0 — 2026-06-14',['../md_changelog.html#autotoc_md18',1,'']]] +]; diff --git a/docs/html/search/all_2.js b/docs/html/search/all_2.js index 63282d0..43efda9 100644 --- a/docs/html/search/all_2.js +++ b/docs/html/search/all_2.js @@ -1,6 +1,6 @@ var searchData= [ - ['2_0',['Stage 2',['../md_README.html#autotoc_md116',1,'']]], + ['2_0',['Stage 2',['../md_README.html#autotoc_md118',1,'']]], ['2_20runtime_20decode_20path_1',['2. Runtime decode path',['../md_README.html#autotoc_md28',1,'']]], ['2026_2003_2013_2',['Initial implementation — 2026-03-13',['../md_changelog.html#autotoc_md20',1,'']]], ['2026_2006_2014_3',['v1.0 — 2026-06-14',['../md_changelog.html#autotoc_md18',1,'']]], diff --git a/docs/html/search/all_3.js b/docs/html/search/all_3.js index f80e8ca..84f0fd4 100644 --- a/docs/html/search/all_3.js +++ b/docs/html/search/all_3.js @@ -1,4 +1,4 @@ var searchData= [ - ['3_0',['Stage 3',['../md_README.html#autotoc_md117',1,'']]] + ['3_0',['Stage 3',['../md_README.html#autotoc_md119',1,'']]] ]; diff --git a/docs/html/search/all_4.js b/docs/html/search/all_4.js index 20df124..4e80a63 100644 --- a/docs/html/search/all_4.js +++ b/docs/html/search/all_4.js @@ -1,4 +1,4 @@ var searchData= [ - ['4_0',['Stage 4',['../md_README.html#autotoc_md118',1,'']]] + ['4_0',['Stage 4',['../md_README.html#autotoc_md120',1,'']]] ]; diff --git a/docs/html/search/all_5.js b/docs/html/search/all_5.js index 816a080..ec57e00 100644 --- a/docs/html/search/all_5.js +++ b/docs/html/search/all_5.js @@ -1,21 +1,24 @@ var searchData= [ - ['a_20raw_20frame_0',['Decode a raw frame',['../md_README.html#autotoc_md98',1,'']]], - ['adapter_1',['Optional Qt model adapter',['../md_README.html#autotoc_md122',1,'']]], + ['a_20raw_20frame_0',['Decode a raw frame',['../md_README.html#autotoc_md100',1,'']]], + ['adapter_1',['Optional Qt model adapter',['../md_README.html#autotoc_md124',1,'']]], ['addchild_2',['AddChild',['../classTreeNode.html#a6161f2ebb92184eab4215d121870e788',1,'TreeNode']]], ['added_3',['added',['../md_changelog.html#autotoc_md3',1,'Added'],['../md_changelog.html#autotoc_md6',1,'Added'],['../md_changelog.html#autotoc_md10',1,'Added'],['../md_changelog.html#autotoc_md21',1,'Added']]], - ['additional_20regression_20coverage_4',['Additional regression coverage',['../md_tests_2README.html#autotoc_md136',1,'']]], - ['all_20build_20variants_20in_20qt_20creator_5',['Configure all build variants in Qt Creator',['../md_README.html#autotoc_md131',1,'']]], - ['already_20implemented_6',['Stage 1 - already implemented',['../md_README.html#autotoc_md115',1,'']]], - ['and_20lcov_20on_20debian_20ubuntu_7',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md129',1,'']]], - ['and_20maintenance_8',['and maintenance',['../md_changelog.html#autotoc_md14',1,'Documentation and maintenance'],['../md_changelog.html#autotoc_md22',1,'Documentation and maintenance']]], - ['and_20motorola_20extraction_9',['Intel and Motorola Extraction',['../md_README.html#autotoc_md92',1,'']]], - ['and_20optional_20model_20tests_10',['Tree and optional model tests',['../md_tests_2README.html#autotoc_md135',1,'']]], - ['and_20parse_20errors_11',['and parse errors',['../md_README.html#autotoc_md76',1,'Frame validation and parse errors'],['../md_README.html#autotoc_md80',1,'Signal validation and parse errors']]], + ['additional_20regression_20coverage_4',['Additional regression coverage',['../md_tests_2README.html#autotoc_md138',1,'']]], + ['all_20build_20variants_20in_20qt_20creator_5',['Configure all build variants in Qt Creator',['../md_README.html#autotoc_md133',1,'']]], + ['already_20implemented_6',['Stage 1 - already implemented',['../md_README.html#autotoc_md117',1,'']]], + ['and_20lcov_20on_20debian_20ubuntu_7',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md131',1,'']]], + ['and_20maintenance_8',['and maintenance',['../md_changelog.html#autotoc_md22',1,'Documentation and maintenance'],['../md_changelog.html#autotoc_md14',1,'Documentation and maintenance']]], + ['and_20motorola_20extraction_9',['Intel and Motorola Extraction',['../md_README.html#autotoc_md94',1,'']]], + ['and_20optional_20model_20tests_10',['Tree and optional model tests',['../md_tests_2README.html#autotoc_md137',1,'']]], + ['and_20parse_20errors_11',['and parse errors',['../md_README.html#autotoc_md78',1,'Frame validation and parse errors'],['../md_README.html#autotoc_md82',1,'Signal validation and parse errors']]], ['and_20precision_12',['Raw value representation and precision',['../md_README.html#autotoc_md64',1,'']]], - ['and_20run_20the_20demo_13',['Build and run the demo',['../md_README.html#autotoc_md124',1,'']]], - ['and_20runtime_20decode_20module_20documentation_14',['DBC Parser and Runtime Decode Module Documentation',['../md_README.html',1,'']]], - ['and_20ui_20path_15',['1. Parse and UI path',['../md_README.html#autotoc_md27',1,'']]], - ['api_20documentation_16',['Generate API documentation',['../md_README.html#autotoc_md125',1,'']]], - ['architecture_17',['High-Level Architecture',['../md_README.html#autotoc_md26',1,'']]] + ['and_20reload_13',['Definition ownership and reload',['../md_README.html#autotoc_md67',1,'']]], + ['and_20reload_20coverage_14',['Definition lifetime and reload coverage',['../md_tests_2README.html#autotoc_md139',1,'']]], + ['and_20run_20the_20demo_15',['Build and run the demo',['../md_README.html#autotoc_md126',1,'']]], + ['and_20runtime_20decode_20module_20documentation_16',['DBC Parser and Runtime Decode Module Documentation',['../md_README.html',1,'']]], + ['and_20signal_20identifiers_17',['Stable frame and signal identifiers',['../md_README.html#autotoc_md68',1,'']]], + ['and_20ui_20path_18',['1. Parse and UI path',['../md_README.html#autotoc_md27',1,'']]], + ['api_20documentation_19',['Generate API documentation',['../md_README.html#autotoc_md127',1,'']]], + ['architecture_20',['High-Level Architecture',['../md_README.html#autotoc_md26',1,'']]] ]; diff --git a/docs/html/search/all_6.js b/docs/html/search/all_6.js index 3319821..994993f 100644 --- a/docs/html/search/all_6.js +++ b/docs/html/search/all_6.js @@ -1,14 +1,14 @@ var searchData= [ - ['basic_20multiplexing_0',['Basic multiplexing',['../md_README.html#autotoc_md82',1,'']]], + ['basic_20multiplexing_0',['Basic multiplexing',['../md_README.html#autotoc_md84',1,'']]], ['build_1',['build',['../classDbcDecodeBuilder.html#a2bc6386dfb5e58976c42e22c19ec471b',1,'DbcDecodeBuilder::Build()'],['../classDbcTreeBuilder.html#a7e57d067d831b14b383947fd125edd4b',1,'DbcTreeBuilder::Build()']]], - ['build_20and_20run_20the_20demo_2',['Build and run the demo',['../md_README.html#autotoc_md124',1,'']]], - ['build_20core_20without_20qt_20libraries_3',['Build core without Qt libraries',['../md_README.html#autotoc_md121',1,'']]], - ['build_20in_20qt_20creator_4',['Configure the GCC coverage build in Qt Creator',['../md_README.html#autotoc_md130',1,'']]], - ['build_20integration_5',['Build Integration',['../md_README.html#autotoc_md120',1,'']]], - ['build_20runtime_20decode_20database_6',['Build runtime decode database',['../md_README.html#autotoc_md97',1,'']]], - ['build_20ui_20tree_7',['Build UI tree',['../md_README.html#autotoc_md96',1,'']]], - ['build_20variants_20in_20qt_20creator_8',['Configure all build variants in Qt Creator',['../md_README.html#autotoc_md131',1,'']]], + ['build_20and_20run_20the_20demo_2',['Build and run the demo',['../md_README.html#autotoc_md126',1,'']]], + ['build_20core_20without_20qt_20libraries_3',['Build core without Qt libraries',['../md_README.html#autotoc_md123',1,'']]], + ['build_20in_20qt_20creator_4',['Configure the GCC coverage build in Qt Creator',['../md_README.html#autotoc_md132',1,'']]], + ['build_20integration_5',['Build Integration',['../md_README.html#autotoc_md122',1,'']]], + ['build_20runtime_20decode_20database_6',['Build runtime decode database',['../md_README.html#autotoc_md99',1,'']]], + ['build_20ui_20tree_7',['Build UI tree',['../md_README.html#autotoc_md98',1,'']]], + ['build_20variants_20in_20qt_20creator_8',['Configure all build variants in Qt Creator',['../md_README.html#autotoc_md133',1,'']]], ['byteorder_9',['byteorder',['../structDecodeSignal.html#abdc4c4bb4a67a6d61d6ca81e8a52833d',1,'DecodeSignal::byteOrder'],['../decode__database_8h.html#aaeb92d42f5a6e27b8ba19f18d69d142b',1,'ByteOrder: decode_database.h']]], ['byteorder_20tt_10',['<tt>ByteOrder</tt>',['../md_README.html#autotoc_md47',1,'']]] ]; diff --git a/docs/html/search/all_7.js b/docs/html/search/all_7.js index 00e4a67..7677122 100644 --- a/docs/html/search/all_7.js +++ b/docs/html/search/all_7.js @@ -1,19 +1,19 @@ var searchData= [ - ['can_20id_20normalization_0',['CAN ID Normalization',['../md_README.html#autotoc_md86',1,'']]], + ['can_20id_20normalization_0',['CAN ID Normalization',['../md_README.html#autotoc_md88',1,'']]], ['canid_1',['canid',['../structDecodeFrame.html#a52e10215388db7df8b541b9d9909edcf',1,'DecodeFrame::canId'],['../structFrameInfo.html#af470b0742c05bfbffc31c51a68f5c05e',1,'FrameInfo::canId'],['../structRawCanFrame.html#a2d0e7fa0e3d5c20bbed55ed8f7888ff4',1,'RawCanFrame::canId']]], - ['changed_2',['changed',['../md_changelog.html#autotoc_md16',1,'Changed'],['../md_changelog.html#autotoc_md12',1,'Changed'],['../md_changelog.html#autotoc_md7',1,'Changed'],['../md_changelog.html#autotoc_md4',1,'Changed']]], + ['changed_2',['changed',['../md_changelog.html#autotoc_md4',1,'Changed'],['../md_changelog.html#autotoc_md7',1,'Changed'],['../md_changelog.html#autotoc_md12',1,'Changed'],['../md_changelog.html#autotoc_md16',1,'Changed']]], ['changelog_3',['Changelog',['../md_changelog.html',1,'']]], - ['code_20coverage_4',['Measuring code coverage',['../md_README.html#autotoc_md128',1,'']]], - ['comment_5',['comment',['../structSignalInfo.html#ac99ba7563a5dad01e39c4257216953f5',1,'SignalInfo::comment'],['../structFrameInfo.html#ace75121294f9d89b762080ab5643293c',1,'FrameInfo::comment'],['../structDecodeFrame.html#a25819ef907a32391af5c9f7cae9cdb22',1,'DecodeFrame::comment'],['../structDecodeSignal.html#ae28c905d4a2bc86419c2a8361bfea473',1,'DecodeSignal::comment']]], - ['comments_6',['Comments',['../md_README.html#autotoc_md84',1,'']]], - ['configure_20all_20build_20variants_20in_20qt_20creator_7',['Configure all build variants in Qt Creator',['../md_README.html#autotoc_md131',1,'']]], - ['configure_20the_20gcc_20coverage_20build_20in_20qt_20creator_8',['Configure the GCC coverage build in Qt Creator',['../md_README.html#autotoc_md130',1,'']]], + ['code_20coverage_4',['Measuring code coverage',['../md_README.html#autotoc_md130',1,'']]], + ['comment_5',['comment',['../structDecodeSignal.html#ae28c905d4a2bc86419c2a8361bfea473',1,'DecodeSignal::comment'],['../structDecodeFrame.html#a25819ef907a32391af5c9f7cae9cdb22',1,'DecodeFrame::comment'],['../structFrameInfo.html#ace75121294f9d89b762080ab5643293c',1,'FrameInfo::comment'],['../structSignalInfo.html#ac99ba7563a5dad01e39c4257216953f5',1,'SignalInfo::comment']]], + ['comments_6',['Comments',['../md_README.html#autotoc_md86',1,'']]], + ['configure_20all_20build_20variants_20in_20qt_20creator_7',['Configure all build variants in Qt Creator',['../md_README.html#autotoc_md133',1,'']]], + ['configure_20the_20gcc_20coverage_20build_20in_20qt_20creator_8',['Configure the GCC coverage build in Qt Creator',['../md_README.html#autotoc_md132',1,'']]], ['contains_9',['contains',['../classTypeFactory.html#a1a119ad2956abe146213c6ca124d8dd4',1,'TypeFactory']]], - ['core_20without_20qt_20libraries_10',['Build core without Qt libraries',['../md_README.html#autotoc_md121',1,'']]], - ['coverage_11',['coverage',['../md_tests_2README.html#autotoc_md136',1,'Additional regression coverage'],['../md_tests_2README.html#autotoc_md133',1,'Decoder coverage'],['../md_README.html#autotoc_md128',1,'Measuring code coverage'],['../md_tests_2README.html#autotoc_md134',1,'Parser coverage']]], - ['coverage_20build_20in_20qt_20creator_12',['Configure the GCC coverage build in Qt Creator',['../md_README.html#autotoc_md130',1,'']]], + ['core_20without_20qt_20libraries_10',['Build core without Qt libraries',['../md_README.html#autotoc_md123',1,'']]], + ['coverage_11',['coverage',['../md_tests_2README.html#autotoc_md138',1,'Additional regression coverage'],['../md_tests_2README.html#autotoc_md135',1,'Decoder coverage'],['../md_tests_2README.html#autotoc_md139',1,'Definition lifetime and reload coverage'],['../md_README.html#autotoc_md130',1,'Measuring code coverage'],['../md_tests_2README.html#autotoc_md136',1,'Parser coverage']]], + ['coverage_20build_20in_20qt_20creator_12',['Configure the GCC coverage build in Qt Creator',['../md_README.html#autotoc_md132',1,'']]], ['create_13',['create',['../classTypeFactory.html#a3f43b03d6e3a0fd503fdec01ecf62e9f',1,'TypeFactory']]], - ['creator_14',['creator',['../md_README.html#autotoc_md131',1,'Configure all build variants in Qt Creator'],['../md_README.html#autotoc_md130',1,'Configure the GCC coverage build in Qt Creator'],['../classTypeFactory.html#ad82f537569ece3d3a4a376523fa94473',1,'TypeFactory::creator()']]], - ['current_20limitations_15',['Current Limitations',['../md_README.html#autotoc_md112',1,'']]] + ['creator_14',['creator',['../md_README.html#autotoc_md133',1,'Configure all build variants in Qt Creator'],['../md_README.html#autotoc_md132',1,'Configure the GCC coverage build in Qt Creator'],['../classTypeFactory.html#ad82f537569ece3d3a4a376523fa94473',1,'TypeFactory::creator()']]], + ['current_20limitations_15',['Current Limitations',['../md_README.html#autotoc_md114',1,'']]] ]; diff --git a/docs/html/search/all_8.js b/docs/html/search/all_8.js index c65644a..9ee8360 100644 --- a/docs/html/search/all_8.js +++ b/docs/html/search/all_8.js @@ -2,10 +2,10 @@ var searchData= [ ['data_0',['data',['../structRawCanFrame.html#a0acb487612104c99c9907344c035df83',1,'RawCanFrame']]], ['data_20structures_1',['Parsed Data Structures',['../md_README.html#autotoc_md34',1,'']]], - ['database_2',['Build runtime decode database',['../md_README.html#autotoc_md97',1,'']]], - ['dbc_3',['Parse DBC',['../md_README.html#autotoc_md95',1,'']]], + ['database_2',['Build runtime decode database',['../md_README.html#autotoc_md99',1,'']]], + ['dbc_3',['Parse DBC',['../md_README.html#autotoc_md97',1,'']]], ['dbc_20parser_20and_20runtime_20decode_20module_20documentation_4',['DBC Parser and Runtime Decode Module Documentation',['../md_README.html',1,'']]], - ['dbc_20syntax_5',['Supported DBC Syntax',['../md_README.html#autotoc_md73',1,'']]], + ['dbc_20syntax_5',['Supported DBC Syntax',['../md_README.html#autotoc_md75',1,'']]], ['dbc_5fdatabase_2eh_6',['dbc_database.h',['../dbc__database_8h.html',1,'']]], ['dbc_5fdecode_5fbuilder_2ecpp_7',['dbc_decode_builder.cpp',['../dbc__decode__builder_8cpp.html',1,'']]], ['dbc_5fdecode_5fbuilder_2eh_8',['dbc_decode_builder.h',['../dbc__decode__builder_8h.html',1,'']]], @@ -20,7 +20,7 @@ var searchData= ['dbcdatabase_20tt_17',['<tt>DbcDatabase</tt>',['../md_README.html#autotoc_md39',1,'']]], ['dbcdecodebuilder_18',['DbcDecodeBuilder',['../classDbcDecodeBuilder.html',1,'']]], ['dbcdecoder_19',['DbcDecoder',['../classDbcDecoder.html',1,'']]], - ['dbcdecoder_20tt_20',['<tt>DbcDecoder</tt>',['../md_README.html#autotoc_md68',1,'']]], + ['dbcdecoder_20tt_20',['<tt>DbcDecoder</tt>',['../md_README.html#autotoc_md70',1,'']]], ['dbcdiagnostic_21',['DbcDiagnostic',['../structDbcDiagnostic.html',1,'']]], ['dbcdiagnosticerror_22',['DbcDiagnosticError',['../classDbcDiagnosticError.html',1,'']]], ['dbcframehandler_23',['DbcFrameHandler',['../classDbcFrameHandler.html',1,'']]], @@ -35,18 +35,18 @@ var searchData= ['dbctreemodel_32',['DbcTreeModel',['../classDbcTreeModel.html',1,'']]], ['dbcunsupportedmultiplexinghandler_33',['DbcUnsupportedMultiplexingHandler',['../classDbcUnsupportedMultiplexingHandler.html',1,'']]], ['dbcvaluedescriptionhandler_34',['DbcValueDescriptionHandler',['../classDbcValueDescriptionHandler.html',1,'']]], - ['debian_20ubuntu_35',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md129',1,'']]], + ['debian_20ubuntu_35',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md131',1,'']]], ['decode_36',['Decode',['../classDbcDecoder.html#a345951ffe5d943a70d3a1ea1f39e74f7',1,'DbcDecoder']]], - ['decode_20a_20raw_20frame_37',['Decode a raw frame',['../md_README.html#autotoc_md98',1,'']]], - ['decode_20database_38',['Build runtime decode database',['../md_README.html#autotoc_md97',1,'']]], - ['decode_20flow_39',['Decode Flow',['../md_README.html#autotoc_md90',1,'']]], + ['decode_20a_20raw_20frame_37',['Decode a raw frame',['../md_README.html#autotoc_md100',1,'']]], + ['decode_20database_38',['Build runtime decode database',['../md_README.html#autotoc_md99',1,'']]], + ['decode_20flow_39',['Decode Flow',['../md_README.html#autotoc_md92',1,'']]], ['decode_20layer_40',['Runtime Decode Layer',['../md_README.html#autotoc_md44',1,'']]], ['decode_20layer_20exists_41',['Why the Runtime Decode Layer Exists',['../md_README.html#autotoc_md30',1,'']]], ['decode_20module_20documentation_42',['DBC Parser and Runtime Decode Module Documentation',['../md_README.html',1,'']]], ['decode_20path_43',['2. Runtime decode path',['../md_README.html#autotoc_md28',1,'']]], - ['decode_20strategy_44',['Unified Decode Strategy',['../md_README.html#autotoc_md100',1,'']]], + ['decode_20strategy_44',['Unified Decode Strategy',['../md_README.html#autotoc_md102',1,'']]], ['decode_5fdatabase_2eh_45',['decode_database.h',['../decode__database_8h.html',1,'']]], - ['decodedatabase_46',['DecodeDatabase',['../structDecodeDatabase.html',1,'']]], + ['decodedatabase_46',['decodedatabase',['../classDecodeDatabase.html',1,'DecodeDatabase'],['../classDecodeDatabase.html#aa935a3a0d334f932d6a8c89a3818286a',1,'DecodeDatabase::DecodeDatabase()']]], ['decodedatabase_20tt_47',['<tt>DecodeDatabase</tt>',['../md_README.html#autotoc_md57',1,'']]], ['decodedframevalue_48',['DecodedFrameValue',['../structDecodedFrameValue.html',1,'']]], ['decodedframevalue_20tt_49',['<tt>DecodedFrameValue</tt>',['../md_README.html#autotoc_md66',1,'']]], @@ -54,16 +54,18 @@ var searchData= ['decodedsignalvalue_20tt_51',['<tt>DecodedSignalValue</tt>',['../md_README.html#autotoc_md62',1,'']]], ['decodeframe_52',['DecodeFrame',['../structDecodeFrame.html',1,'']]], ['decodeframe_20tt_53',['<tt>DecodeFrame</tt>',['../md_README.html#autotoc_md53',1,'']]], - ['decoder_20coverage_54',['Decoder coverage',['../md_tests_2README.html#autotoc_md133',1,'']]], + ['decoder_20coverage_54',['Decoder coverage',['../md_tests_2README.html#autotoc_md135',1,'']]], ['decoder_20layer_55',['Decoder Layer',['../md_README.html#autotoc_md59',1,'']]], ['decodesignal_56',['DecodeSignal',['../structDecodeSignal.html',1,'']]], ['decodesignal_20tt_57',['<tt>DecodeSignal</tt>',['../md_README.html#autotoc_md51',1,'']]], - ['definition_58',['definition',['../structDecodedFrameValue.html#a60dda1cc352d2c8087f0bdbc81dd266c',1,'DecodedFrameValue::definition'],['../structDecodedSignalValue.html#acadc3b3bb21dd6b0412d342c7e6b20d7',1,'DecodedSignalValue::definition'],['../md_README.html#autotoc_md74',1,'Frame definition'],['../md_README.html#autotoc_md78',1,'Signal definition']]], - ['demo_59',['Build and run the demo',['../md_README.html#autotoc_md124',1,'']]], - ['descriptions_20tt_20val_5f_20tt_60',['Signal value descriptions (<tt>VAL_</tt>)',['../md_README.html#autotoc_md110',1,'']]], - ['diagnostics_61',['Structured diagnostics',['../md_README.html#autotoc_md71',1,'']]], - ['dispatch_62',['Dispatch',['../classDbcStatementDispatcher.html#a495c2d5c7ebb8103b1987cdd87c142ed',1,'DbcStatementDispatcher']]], - ['dlc_63',['dlc',['../structFrameInfo.html#aa2b198ea0f55e560c123d35e7b3ecab9',1,'FrameInfo::dlc'],['../structDecodeFrame.html#a51111ac13988be372d5673d12cf3e060',1,'DecodeFrame::dlc']]], - ['documentation_64',['documentation',['../md_README.html',1,'DBC Parser and Runtime Decode Module Documentation'],['../md_changelog.html#autotoc_md19',1,'Documentation'],['../md_README.html#autotoc_md125',1,'Generate API documentation']]], - ['documentation_20and_20maintenance_65',['documentation and maintenance',['../md_changelog.html#autotoc_md14',1,'Documentation and maintenance'],['../md_changelog.html#autotoc_md22',1,'Documentation and maintenance']]] + ['definition_58',['definition',['../structDecodedFrameValue.html#a33e971ba10030506007aa201c89f351d',1,'DecodedFrameValue::definition'],['../structDecodedSignalValue.html#a828b5ef7faefc14fbf5dbd46249bcad2',1,'DecodedSignalValue::definition'],['../md_README.html#autotoc_md76',1,'Frame definition'],['../md_README.html#autotoc_md80',1,'Signal definition']]], + ['definition_20lifetime_20and_20reload_20coverage_59',['Definition lifetime and reload coverage',['../md_tests_2README.html#autotoc_md139',1,'']]], + ['definition_20ownership_20and_20reload_60',['Definition ownership and reload',['../md_README.html#autotoc_md67',1,'']]], + ['demo_61',['Build and run the demo',['../md_README.html#autotoc_md126',1,'']]], + ['descriptions_20tt_20val_5f_20tt_62',['Signal value descriptions (<tt>VAL_</tt>)',['../md_README.html#autotoc_md112',1,'']]], + ['diagnostics_63',['Structured diagnostics',['../md_README.html#autotoc_md73',1,'']]], + ['dispatch_64',['Dispatch',['../classDbcStatementDispatcher.html#a495c2d5c7ebb8103b1987cdd87c142ed',1,'DbcStatementDispatcher']]], + ['dlc_65',['dlc',['../structFrameInfo.html#aa2b198ea0f55e560c123d35e7b3ecab9',1,'FrameInfo::dlc'],['../structDecodeFrame.html#a51111ac13988be372d5673d12cf3e060',1,'DecodeFrame::dlc']]], + ['documentation_66',['documentation',['../md_README.html',1,'DBC Parser and Runtime Decode Module Documentation'],['../md_changelog.html#autotoc_md19',1,'Documentation'],['../md_README.html#autotoc_md127',1,'Generate API documentation']]], + ['documentation_20and_20maintenance_67',['documentation and maintenance',['../md_changelog.html#autotoc_md22',1,'Documentation and maintenance'],['../md_changelog.html#autotoc_md14',1,'Documentation and maintenance']]] ]; diff --git a/docs/html/search/all_9.js b/docs/html/search/all_9.js index ccf20df..3d22a59 100644 --- a/docs/html/search/all_9.js +++ b/docs/html/search/all_9.js @@ -1,9 +1,9 @@ var searchData= [ - ['enough_0',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md106',1,'']]], - ['errors_1',['errors',['../md_README.html#autotoc_md76',1,'Frame validation and parse errors'],['../md_README.html#autotoc_md80',1,'Signal validation and parse errors']]], - ['example_20usage_2',['Example Usage',['../md_README.html#autotoc_md94',1,'']]], + ['enough_0',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md108',1,'']]], + ['errors_1',['errors',['../md_README.html#autotoc_md78',1,'Frame validation and parse errors'],['../md_README.html#autotoc_md82',1,'Signal validation and parse errors']]], + ['example_20usage_2',['Example Usage',['../md_README.html#autotoc_md96',1,'']]], ['examples_2fmain_2ecpp_3',['main.cpp',['../examples_2main_8cpp.html',1,'']]], ['exists_4',['Why the Runtime Decode Layer Exists',['../md_README.html#autotoc_md30',1,'']]], - ['extraction_5',['extraction',['../md_README.html#autotoc_md92',1,'Intel and Motorola Extraction'],['../md_README.html#autotoc_md88',1,'PGN Extraction']]] + ['extraction_5',['extraction',['../md_README.html#autotoc_md94',1,'Intel and Motorola Extraction'],['../md_README.html#autotoc_md90',1,'PGN Extraction']]] ]; diff --git a/docs/html/search/all_a.js b/docs/html/search/all_a.js index 48a09a6..b66e5f7 100644 --- a/docs/html/search/all_a.js +++ b/docs/html/search/all_a.js @@ -1,19 +1,20 @@ var searchData= [ ['factor_0',['factor',['../structDecodeSignal.html#a428c39913a366a8476dd291061354391',1,'DecodeSignal::factor'],['../structSignalInfo.html#ae4f78d99a2750aa564d7eba860171499',1,'SignalInfo::factor']]], - ['factory_1',['Statement Handler Factory',['../md_README.html#autotoc_md108',1,'']]], - ['findframe_2',['FindFrame',['../classDbcDecoder.html#ab2cfb2fb711c95d3a29365546b89f3da',1,'DbcDecoder']]], + ['factory_1',['Statement Handler Factory',['../md_README.html#autotoc_md110',1,'']]], + ['findframe_2',['findframe',['../classDbcDecoder.html#a4005c4311f57b7faf21c0cb31463039c',1,'DbcDecoder::FindFrame()'],['../classDecodeDatabase.html#a780d6e747a48b10a5eb0ab85448d2970',1,'DecodeDatabase::FindFrame()']]], ['fixed_3',['fixed',['../md_changelog.html#autotoc_md13',1,'Fixed'],['../md_changelog.html#autotoc_md17',1,'Fixed'],['../md_changelog.html#autotoc_md8',1,'Fixed']]], - ['flow_4',['Decode Flow',['../md_README.html#autotoc_md90',1,'']]], - ['frame_5',['Decode a raw frame',['../md_README.html#autotoc_md98',1,'']]], - ['frame_20definition_6',['Frame definition',['../md_README.html#autotoc_md74',1,'']]], - ['frame_20validation_20and_20parse_20errors_7',['Frame validation and parse errors',['../md_README.html#autotoc_md76',1,'']]], - ['frame_5finfo_2eh_8',['frame_info.h',['../frame__info_8h.html',1,'']]], - ['frameinfo_9',['FrameInfo',['../structFrameInfo.html',1,'']]], - ['frameinfo_20tt_10',['<tt>FrameInfo</tt>',['../md_README.html#autotoc_md37',1,'']]], - ['framekey_11',['FrameKey',['../structFrameKey.html',1,'']]], - ['framekey_20tt_12',['<tt>FrameKey</tt>',['../md_README.html#autotoc_md55',1,'']]], - ['framekeyhasher_13',['FrameKeyHasher',['../structFrameKeyHasher.html',1,'']]], - ['frames_14',['frames',['../structDbcDatabase.html#a2cade5d0234ee816132127542f8c612b',1,'DbcDatabase']]], - ['frametap_15',['Intended Use in FrameTap',['../md_README.html#autotoc_md104',1,'']]] + ['flow_4',['Decode Flow',['../md_README.html#autotoc_md92',1,'']]], + ['frame_5',['Decode a raw frame',['../md_README.html#autotoc_md100',1,'']]], + ['frame_20and_20signal_20identifiers_6',['Stable frame and signal identifiers',['../md_README.html#autotoc_md68',1,'']]], + ['frame_20definition_7',['Frame definition',['../md_README.html#autotoc_md76',1,'']]], + ['frame_20validation_20and_20parse_20errors_8',['Frame validation and parse errors',['../md_README.html#autotoc_md78',1,'']]], + ['frame_5finfo_2eh_9',['frame_info.h',['../frame__info_8h.html',1,'']]], + ['frameinfo_10',['FrameInfo',['../structFrameInfo.html',1,'']]], + ['frameinfo_20tt_11',['<tt>FrameInfo</tt>',['../md_README.html#autotoc_md37',1,'']]], + ['framekey_12',['FrameKey',['../structFrameKey.html',1,'']]], + ['framekey_20tt_13',['<tt>FrameKey</tt>',['../md_README.html#autotoc_md55',1,'']]], + ['framekeyhasher_14',['FrameKeyHasher',['../structFrameKeyHasher.html',1,'']]], + ['frames_15',['frames',['../structDbcDatabase.html#a2cade5d0234ee816132127542f8c612b',1,'DbcDatabase']]], + ['frametap_16',['Intended Use in FrameTap',['../md_README.html#autotoc_md106',1,'']]] ]; diff --git a/docs/html/search/all_b.js b/docs/html/search/all_b.js index f81d884..6d7364b 100644 --- a/docs/html/search/all_b.js +++ b/docs/html/search/all_b.js @@ -1,16 +1,17 @@ var searchData= [ - ['gcc_20coverage_20build_20in_20qt_20creator_0',['Configure the GCC coverage build in Qt Creator',['../md_README.html#autotoc_md130',1,'']]], - ['gcc_20gcov_20and_20lcov_20on_20debian_20ubuntu_1',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md129',1,'']]], - ['gcov_20and_20lcov_20on_20debian_20ubuntu_2',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md129',1,'']]], - ['generate_20api_20documentation_3',['Generate API documentation',['../md_README.html#autotoc_md125',1,'']]], + ['gcc_20coverage_20build_20in_20qt_20creator_0',['Configure the GCC coverage build in Qt Creator',['../md_README.html#autotoc_md132',1,'']]], + ['gcc_20gcov_20and_20lcov_20on_20debian_20ubuntu_1',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md131',1,'']]], + ['gcov_20and_20lcov_20on_20debian_20ubuntu_2',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md131',1,'']]], + ['generate_20api_20documentation_3',['Generate API documentation',['../md_README.html#autotoc_md127',1,'']]], ['getchild_4',['getchild',['../classTreeNode.html#a4727ff801a2d1b9323c5ae50a35457a6',1,'TreeNode::GetChild(std::size_t index) const'],['../classTreeNode.html#a81047bd7d2a4cc96b9ef5e20d0d63b5f',1,'TreeNode::GetChild(std::size_t index)']]], ['getchildcount_5',['GetChildCount',['../classTreeNode.html#abdd82460187dca8d3e5d66f5d5c529ea',1,'TreeNode']]], ['getframe_6',['GetFrame',['../classTreeNode.html#afc503b40004764163605d6dbdb4ef811',1,'TreeNode']]], - ['getname_7',['GetName',['../classTreeNode.html#aaac5b8d9dc9e5ae1f367d1adbcf20e18',1,'TreeNode']]], - ['getparent_8',['GetParent',['../classTreeNode.html#aa48fbc17903eb8cfa40353e29f853c6f',1,'TreeNode']]], - ['getrow_9',['GetRow',['../classTreeNode.html#ad501f97eeec7f7d3353bfae838fbb6a8',1,'TreeNode']]], - ['getsignal_10',['GetSignal',['../classTreeNode.html#a226518612d0d00b5988a2c44fc21d3f1',1,'TreeNode']]], - ['gettype_11',['GetType',['../classTreeNode.html#afa2f4b0aafa12d3d41ed00df8e0250c9',1,'TreeNode']]], - ['getvaluedescription_12',['GetValueDescription',['../structDecodedSignalValue.html#affc38af1bf31bcb6f2c33044bce92bd2',1,'DecodedSignalValue']]] + ['getframes_7',['GetFrames',['../classDecodeDatabase.html#aa034c1510984a85f60ad6c0bd744d6e8',1,'DecodeDatabase']]], + ['getname_8',['GetName',['../classTreeNode.html#aaac5b8d9dc9e5ae1f367d1adbcf20e18',1,'TreeNode']]], + ['getparent_9',['GetParent',['../classTreeNode.html#aa48fbc17903eb8cfa40353e29f853c6f',1,'TreeNode']]], + ['getrow_10',['GetRow',['../classTreeNode.html#ad501f97eeec7f7d3353bfae838fbb6a8',1,'TreeNode']]], + ['getsignal_11',['GetSignal',['../classTreeNode.html#a226518612d0d00b5988a2c44fc21d3f1',1,'TreeNode']]], + ['gettype_12',['GetType',['../classTreeNode.html#afa2f4b0aafa12d3d41ed00df8e0250c9',1,'TreeNode']]], + ['getvaluedescription_13',['GetValueDescription',['../structDecodedSignalValue.html#affc38af1bf31bcb6f2c33044bce92bd2',1,'DecodedSignalValue']]] ]; diff --git a/docs/html/search/all_c.js b/docs/html/search/all_c.js index fc978ee..b87fdf7 100644 --- a/docs/html/search/all_c.js +++ b/docs/html/search/all_c.js @@ -1,6 +1,6 @@ var searchData= [ - ['handler_20factory_0',['Statement Handler Factory',['../md_README.html#autotoc_md108',1,'']]], + ['handler_20factory_0',['Statement Handler Factory',['../md_README.html#autotoc_md110',1,'']]], ['haspgn_1',['haspgn',['../structDecodeFrame.html#a2551102670c4a540fced4c71da0b369d',1,'DecodeFrame::hasPgn'],['../structFrameInfo.html#a4737a5420213ad4304724e39f3a4e55d',1,'FrameInfo::hasPgn']]], ['high_20level_20architecture_2',['High-Level Architecture',['../md_README.html#autotoc_md26',1,'']]] ]; diff --git a/docs/html/search/all_d.js b/docs/html/search/all_d.js index 0feaf0e..ab6e442 100644 --- a/docs/html/search/all_d.js +++ b/docs/html/search/all_d.js @@ -1,16 +1,17 @@ var searchData= [ - ['id_20normalization_0',['CAN ID Normalization',['../md_README.html#autotoc_md86',1,'']]], - ['implementation_20—_202026_2003_2013_1',['Initial implementation — 2026-03-13',['../md_changelog.html#autotoc_md20',1,'']]], - ['implemented_2',['Stage 1 - already implemented',['../md_README.html#autotoc_md115',1,'']]], - ['in_20frametap_3',['Intended Use in FrameTap',['../md_README.html#autotoc_md104',1,'']]], - ['in_20qt_20creator_4',['in qt creator',['../md_README.html#autotoc_md131',1,'Configure all build variants in Qt Creator'],['../md_README.html#autotoc_md130',1,'Configure the GCC coverage build in Qt Creator']]], - ['initial_20implementation_20—_202026_2003_2013_5',['Initial implementation — 2026-03-13',['../md_changelog.html#autotoc_md20',1,'']]], - ['integration_6',['Build Integration',['../md_README.html#autotoc_md120',1,'']]], - ['intel_20and_20motorola_20extraction_7',['Intel and Motorola Extraction',['../md_README.html#autotoc_md92',1,'']]], - ['intended_20use_20in_20frametap_8',['Intended Use in FrameTap',['../md_README.html#autotoc_md104',1,'']]], - ['is_20not_20enough_9',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md106',1,'']]], - ['isextended_10',['isextended',['../structRawCanFrame.html#a462193d275adc1dba8bd18ffa0e36bb7',1,'RawCanFrame::isExtended'],['../structDecodeFrame.html#a3ee2348d781f8f15aaf87e8dcf57ec41',1,'DecodeFrame::isExtended'],['../structFrameInfo.html#a34b726afaad2ac5c697fdb2ac070cdaf',1,'FrameInfo::isExtended']]], - ['islittleendian_11',['isLittleEndian',['../structSignalInfo.html#af363b1563fb4c7cc8973f9a80c06846c',1,'SignalInfo']]], - ['issigned_12',['isSigned',['../structSignalInfo.html#a52a52b320eef92fbcb4626307f9a498f',1,'SignalInfo']]] + ['id_20normalization_0',['CAN ID Normalization',['../md_README.html#autotoc_md88',1,'']]], + ['identifiers_1',['Stable frame and signal identifiers',['../md_README.html#autotoc_md68',1,'']]], + ['implementation_20—_202026_2003_2013_2',['Initial implementation — 2026-03-13',['../md_changelog.html#autotoc_md20',1,'']]], + ['implemented_3',['Stage 1 - already implemented',['../md_README.html#autotoc_md117',1,'']]], + ['in_20frametap_4',['Intended Use in FrameTap',['../md_README.html#autotoc_md106',1,'']]], + ['in_20qt_20creator_5',['in qt creator',['../md_README.html#autotoc_md133',1,'Configure all build variants in Qt Creator'],['../md_README.html#autotoc_md132',1,'Configure the GCC coverage build in Qt Creator']]], + ['initial_20implementation_20—_202026_2003_2013_6',['Initial implementation — 2026-03-13',['../md_changelog.html#autotoc_md20',1,'']]], + ['integration_7',['Build Integration',['../md_README.html#autotoc_md122',1,'']]], + ['intel_20and_20motorola_20extraction_8',['Intel and Motorola Extraction',['../md_README.html#autotoc_md94',1,'']]], + ['intended_20use_20in_20frametap_9',['Intended Use in FrameTap',['../md_README.html#autotoc_md106',1,'']]], + ['is_20not_20enough_10',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md108',1,'']]], + ['isextended_11',['isextended',['../structFrameInfo.html#a34b726afaad2ac5c697fdb2ac070cdaf',1,'FrameInfo::isExtended'],['../structDecodeFrame.html#a3ee2348d781f8f15aaf87e8dcf57ec41',1,'DecodeFrame::isExtended'],['../structRawCanFrame.html#a462193d275adc1dba8bd18ffa0e36bb7',1,'RawCanFrame::isExtended']]], + ['islittleendian_12',['isLittleEndian',['../structSignalInfo.html#af363b1563fb4c7cc8973f9a80c06846c',1,'SignalInfo']]], + ['issigned_13',['isSigned',['../structSignalInfo.html#a52a52b320eef92fbcb4626307f9a498f',1,'SignalInfo']]] ]; diff --git a/docs/html/search/all_e.js b/docs/html/search/all_e.js index 78ca020..199fcb0 100644 --- a/docs/html/search/all_e.js +++ b/docs/html/search/all_e.js @@ -1,12 +1,4 @@ var searchData= [ - ['layer_0',['layer',['../md_README.html#autotoc_md59',1,'Decoder Layer'],['../md_README.html#autotoc_md44',1,'Runtime Decode Layer'],['../md_README.html#autotoc_md41',1,'UI Tree Layer']]], - ['layer_20exists_1',['Why the Runtime Decode Layer Exists',['../md_README.html#autotoc_md30',1,'']]], - ['layout_2',['Module Layout',['../md_README.html#autotoc_md32',1,'']]], - ['lcov_20on_20debian_20ubuntu_3',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md129',1,'']]], - ['length_4',['length',['../structDecodeSignal.html#acd4ef5ee30421d117b5756854302debb',1,'DecodeSignal::length'],['../structSignalInfo.html#a1008b5201f71848177217bd52fb84baa',1,'SignalInfo::length']]], - ['level_20architecture_5',['High-Level Architecture',['../md_README.html#autotoc_md26',1,'']]], - ['libraries_6',['Build core without Qt libraries',['../md_README.html#autotoc_md121',1,'']]], - ['limitations_7',['Current Limitations',['../md_README.html#autotoc_md112',1,'']]], - ['live_20path_8',['live path',['../md_README.html#autotoc_md101',1,'']]] + ['key_0',['key',['../structDecodedSignalValue.html#a33df0fcd92b23b3e08539906fc6b4c4a',1,'DecodedSignalValue::key'],['../structDecodedFrameValue.html#a32143efe2023a1ecd977a9ae93e50b73',1,'DecodedFrameValue::key']]] ]; diff --git a/docs/html/search/all_f.js b/docs/html/search/all_f.js index 21542a3..4030811 100644 --- a/docs/html/search/all_f.js +++ b/docs/html/search/all_f.js @@ -1,13 +1,13 @@ var searchData= [ - ['maintenance_0',['maintenance',['../md_changelog.html#autotoc_md14',1,'Documentation and maintenance'],['../md_changelog.html#autotoc_md22',1,'Documentation and maintenance']]], - ['maximum_1',['maximum',['../structDecodeSignal.html#a4a6ba87142a9badbf0ca830e9e709cb7',1,'DecodeSignal::maximum'],['../structSignalInfo.html#adf1c4331b9eabced0d7fdda40ff0eb52',1,'SignalInfo::maximum']]], - ['measuring_20code_20coverage_2',['Measuring code coverage',['../md_README.html#autotoc_md128',1,'']]], - ['minimum_3',['minimum',['../structDecodeSignal.html#a0fb84e19a0ab3bd50b6f65c1075ebc25',1,'DecodeSignal::minimum'],['../structSignalInfo.html#ada7bf94fbeaa26bd08c73982b5af255b',1,'SignalInfo::minimum']]], - ['model_20adapter_4',['Optional Qt model adapter',['../md_README.html#autotoc_md122',1,'']]], - ['model_20tests_5',['Tree and optional model tests',['../md_tests_2README.html#autotoc_md135',1,'']]], - ['module_20documentation_6',['DBC Parser and Runtime Decode Module Documentation',['../md_README.html',1,'']]], - ['module_20layout_7',['Module Layout',['../md_README.html#autotoc_md32',1,'']]], - ['motorola_20extraction_8',['Intel and Motorola Extraction',['../md_README.html#autotoc_md92',1,'']]], - ['multiplexing_9',['multiplexing',['../md_README.html#autotoc_md82',1,'Basic multiplexing'],['../structMultiplexing.html',1,'Multiplexing']]] + ['layer_0',['layer',['../md_README.html#autotoc_md59',1,'Decoder Layer'],['../md_README.html#autotoc_md44',1,'Runtime Decode Layer'],['../md_README.html#autotoc_md41',1,'UI Tree Layer']]], + ['layer_20exists_1',['Why the Runtime Decode Layer Exists',['../md_README.html#autotoc_md30',1,'']]], + ['layout_2',['Module Layout',['../md_README.html#autotoc_md32',1,'']]], + ['lcov_20on_20debian_20ubuntu_3',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md131',1,'']]], + ['length_4',['length',['../structDecodeSignal.html#acd4ef5ee30421d117b5756854302debb',1,'DecodeSignal::length'],['../structSignalInfo.html#a1008b5201f71848177217bd52fb84baa',1,'SignalInfo::length']]], + ['level_20architecture_5',['High-Level Architecture',['../md_README.html#autotoc_md26',1,'']]], + ['libraries_6',['Build core without Qt libraries',['../md_README.html#autotoc_md123',1,'']]], + ['lifetime_20and_20reload_20coverage_7',['Definition lifetime and reload coverage',['../md_tests_2README.html#autotoc_md139',1,'']]], + ['limitations_8',['Current Limitations',['../md_README.html#autotoc_md114',1,'']]], + ['live_20path_9',['live path',['../md_README.html#autotoc_md103',1,'']]] ]; diff --git a/docs/html/search/classes_0.js b/docs/html/search/classes_0.js index 751a4fe..3331d21 100644 --- a/docs/html/search/classes_0.js +++ b/docs/html/search/classes_0.js @@ -18,7 +18,7 @@ var searchData= ['dbctreemodel_15',['DbcTreeModel',['../classDbcTreeModel.html',1,'']]], ['dbcunsupportedmultiplexinghandler_16',['DbcUnsupportedMultiplexingHandler',['../classDbcUnsupportedMultiplexingHandler.html',1,'']]], ['dbcvaluedescriptionhandler_17',['DbcValueDescriptionHandler',['../classDbcValueDescriptionHandler.html',1,'']]], - ['decodedatabase_18',['DecodeDatabase',['../structDecodeDatabase.html',1,'']]], + ['decodedatabase_18',['DecodeDatabase',['../classDecodeDatabase.html',1,'']]], ['decodedframevalue_19',['DecodedFrameValue',['../structDecodedFrameValue.html',1,'']]], ['decodedsignalvalue_20',['DecodedSignalValue',['../structDecodedSignalValue.html',1,'']]], ['decodeframe_21',['DecodeFrame',['../structDecodeFrame.html',1,'']]], diff --git a/docs/html/search/classes_5.js b/docs/html/search/classes_5.js index 3cc8467..b92fb16 100644 --- a/docs/html/search/classes_5.js +++ b/docs/html/search/classes_5.js @@ -1,4 +1,6 @@ var searchData= [ - ['signalinfo_0',['SignalInfo',['../structSignalInfo.html',1,'']]] + ['signalinfo_0',['SignalInfo',['../structSignalInfo.html',1,'']]], + ['signalkey_1',['SignalKey',['../structSignalKey.html',1,'']]], + ['signalkeyhasher_2',['SignalKeyHasher',['../structSignalKeyHasher.html',1,'']]] ]; diff --git a/docs/html/search/functions_3.js b/docs/html/search/functions_3.js index 4dcc0f5..1d7cf78 100644 --- a/docs/html/search/functions_3.js +++ b/docs/html/search/functions_3.js @@ -1,5 +1,6 @@ var searchData= [ ['decode_0',['Decode',['../classDbcDecoder.html#a345951ffe5d943a70d3a1ea1f39e74f7',1,'DbcDecoder']]], - ['dispatch_1',['Dispatch',['../classDbcStatementDispatcher.html#a495c2d5c7ebb8103b1987cdd87c142ed',1,'DbcStatementDispatcher']]] + ['decodedatabase_1',['DecodeDatabase',['../classDecodeDatabase.html#aa935a3a0d334f932d6a8c89a3818286a',1,'DecodeDatabase']]], + ['dispatch_2',['Dispatch',['../classDbcStatementDispatcher.html#a495c2d5c7ebb8103b1987cdd87c142ed',1,'DbcStatementDispatcher']]] ]; diff --git a/docs/html/search/functions_4.js b/docs/html/search/functions_4.js index 4087d48..27deb57 100644 --- a/docs/html/search/functions_4.js +++ b/docs/html/search/functions_4.js @@ -1,4 +1,4 @@ var searchData= [ - ['findframe_0',['FindFrame',['../classDbcDecoder.html#ab2cfb2fb711c95d3a29365546b89f3da',1,'DbcDecoder']]] + ['findframe_0',['findframe',['../classDbcDecoder.html#a4005c4311f57b7faf21c0cb31463039c',1,'DbcDecoder::FindFrame()'],['../classDecodeDatabase.html#a780d6e747a48b10a5eb0ab85448d2970',1,'DecodeDatabase::FindFrame()']]] ]; diff --git a/docs/html/search/functions_5.js b/docs/html/search/functions_5.js index ac4a700..09c3f1c 100644 --- a/docs/html/search/functions_5.js +++ b/docs/html/search/functions_5.js @@ -3,10 +3,11 @@ var searchData= ['getchild_0',['getchild',['../classTreeNode.html#a4727ff801a2d1b9323c5ae50a35457a6',1,'TreeNode::GetChild(std::size_t index) const'],['../classTreeNode.html#a81047bd7d2a4cc96b9ef5e20d0d63b5f',1,'TreeNode::GetChild(std::size_t index)']]], ['getchildcount_1',['GetChildCount',['../classTreeNode.html#abdd82460187dca8d3e5d66f5d5c529ea',1,'TreeNode']]], ['getframe_2',['GetFrame',['../classTreeNode.html#afc503b40004764163605d6dbdb4ef811',1,'TreeNode']]], - ['getname_3',['GetName',['../classTreeNode.html#aaac5b8d9dc9e5ae1f367d1adbcf20e18',1,'TreeNode']]], - ['getparent_4',['GetParent',['../classTreeNode.html#aa48fbc17903eb8cfa40353e29f853c6f',1,'TreeNode']]], - ['getrow_5',['GetRow',['../classTreeNode.html#ad501f97eeec7f7d3353bfae838fbb6a8',1,'TreeNode']]], - ['getsignal_6',['GetSignal',['../classTreeNode.html#a226518612d0d00b5988a2c44fc21d3f1',1,'TreeNode']]], - ['gettype_7',['GetType',['../classTreeNode.html#afa2f4b0aafa12d3d41ed00df8e0250c9',1,'TreeNode']]], - ['getvaluedescription_8',['GetValueDescription',['../structDecodedSignalValue.html#affc38af1bf31bcb6f2c33044bce92bd2',1,'DecodedSignalValue']]] + ['getframes_3',['GetFrames',['../classDecodeDatabase.html#aa034c1510984a85f60ad6c0bd744d6e8',1,'DecodeDatabase']]], + ['getname_4',['GetName',['../classTreeNode.html#aaac5b8d9dc9e5ae1f367d1adbcf20e18',1,'TreeNode']]], + ['getparent_5',['GetParent',['../classTreeNode.html#aa48fbc17903eb8cfa40353e29f853c6f',1,'TreeNode']]], + ['getrow_6',['GetRow',['../classTreeNode.html#ad501f97eeec7f7d3353bfae838fbb6a8',1,'TreeNode']]], + ['getsignal_7',['GetSignal',['../classTreeNode.html#a226518612d0d00b5988a2c44fc21d3f1',1,'TreeNode']]], + ['gettype_8',['GetType',['../classTreeNode.html#afa2f4b0aafa12d3d41ed00df8e0250c9',1,'TreeNode']]], + ['getvaluedescription_9',['GetValueDescription',['../structDecodedSignalValue.html#affc38af1bf31bcb6f2c33044bce92bd2',1,'DecodedSignalValue']]] ]; diff --git a/docs/html/search/searchdata.js b/docs/html/search/searchdata.js index 7aa779b..6008f18 100644 --- a/docs/html/search/searchdata.js +++ b/docs/html/search/searchdata.js @@ -1,10 +1,10 @@ var indexSectionsWithContent = { - 0: "01234abcdefghilmnopqrstuvw—", + 0: "01234abcdefghiklmnopqrstuvw—", 1: "dfmprst", 2: "defst", 3: "abcdfgprt", - 4: "bcdfhilmnoprstuv", + 4: "bcdfhiklmnoprstuv", 5: "bnv", 6: "acdmpqrt" }; diff --git a/docs/html/search/variables_10.js b/docs/html/search/variables_10.js new file mode 100644 index 0000000..d699763 --- /dev/null +++ b/docs/html/search/variables_10.js @@ -0,0 +1,6 @@ +var searchData= +[ + ['valid_0',['valid',['../structDecodedSignalValue.html#aac0ed361af545cde48d0e6f41a859686',1,'DecodedSignalValue::valid'],['../structDecodedFrameValue.html#a4f51c31110dba1f73a763c596372beb0',1,'DecodedFrameValue::valid']]], + ['valuedescriptions_1',['valuedescriptions',['../structDecodeSignal.html#a822155d9bf4ed5f3300c9e9befe606ff',1,'DecodeSignal::valueDescriptions'],['../structSignalInfo.html#a43f47d0433d0cc39076bd7278b46af9c',1,'SignalInfo::valueDescriptions']]], + ['valuetype_2',['valueType',['../structDecodeSignal.html#a9d37638129263b8902ba5be59baf39a8',1,'DecodeSignal']]] +]; diff --git a/docs/html/search/variables_2.js b/docs/html/search/variables_2.js index d7b3dad..0c18c8f 100644 --- a/docs/html/search/variables_2.js +++ b/docs/html/search/variables_2.js @@ -1,6 +1,6 @@ var searchData= [ ['data_0',['data',['../structRawCanFrame.html#a0acb487612104c99c9907344c035df83',1,'RawCanFrame']]], - ['definition_1',['definition',['../structDecodedSignalValue.html#acadc3b3bb21dd6b0412d342c7e6b20d7',1,'DecodedSignalValue::definition'],['../structDecodedFrameValue.html#a60dda1cc352d2c8087f0bdbc81dd266c',1,'DecodedFrameValue::definition']]], + ['definition_1',['definition',['../structDecodedSignalValue.html#a828b5ef7faefc14fbf5dbd46249bcad2',1,'DecodedSignalValue::definition'],['../structDecodedFrameValue.html#a33e971ba10030506007aa201c89f351d',1,'DecodedFrameValue::definition']]], ['dlc_2',['dlc',['../structDecodeFrame.html#a51111ac13988be372d5673d12cf3e060',1,'DecodeFrame::dlc'],['../structFrameInfo.html#aa2b198ea0f55e560c123d35e7b3ecab9',1,'FrameInfo::dlc']]] ]; diff --git a/docs/html/search/variables_6.js b/docs/html/search/variables_6.js index 52fc426..199fcb0 100644 --- a/docs/html/search/variables_6.js +++ b/docs/html/search/variables_6.js @@ -1,4 +1,4 @@ var searchData= [ - ['length_0',['length',['../structDecodeSignal.html#acd4ef5ee30421d117b5756854302debb',1,'DecodeSignal::length'],['../structSignalInfo.html#a1008b5201f71848177217bd52fb84baa',1,'SignalInfo::length']]] + ['key_0',['key',['../structDecodedSignalValue.html#a33df0fcd92b23b3e08539906fc6b4c4a',1,'DecodedSignalValue::key'],['../structDecodedFrameValue.html#a32143efe2023a1ecd977a9ae93e50b73',1,'DecodedFrameValue::key']]] ]; diff --git a/docs/html/search/variables_7.js b/docs/html/search/variables_7.js index 8c626f1..52fc426 100644 --- a/docs/html/search/variables_7.js +++ b/docs/html/search/variables_7.js @@ -1,5 +1,4 @@ var searchData= [ - ['maximum_0',['maximum',['../structDecodeSignal.html#a4a6ba87142a9badbf0ca830e9e709cb7',1,'DecodeSignal::maximum'],['../structSignalInfo.html#adf1c4331b9eabced0d7fdda40ff0eb52',1,'SignalInfo::maximum']]], - ['minimum_1',['minimum',['../structDecodeSignal.html#a0fb84e19a0ab3bd50b6f65c1075ebc25',1,'DecodeSignal::minimum'],['../structSignalInfo.html#ada7bf94fbeaa26bd08c73982b5af255b',1,'SignalInfo::minimum']]] + ['length_0',['length',['../structDecodeSignal.html#acd4ef5ee30421d117b5756854302debb',1,'DecodeSignal::length'],['../structSignalInfo.html#a1008b5201f71848177217bd52fb84baa',1,'SignalInfo::length']]] ]; diff --git a/docs/html/search/variables_8.js b/docs/html/search/variables_8.js index 16390c6..8c626f1 100644 --- a/docs/html/search/variables_8.js +++ b/docs/html/search/variables_8.js @@ -1,4 +1,5 @@ var searchData= [ - ['name_0',['name',['../structDecodeSignal.html#a58cf5844f2272a23dcb9687d912e4780',1,'DecodeSignal::name'],['../structDecodeFrame.html#aa0a7f8fd5bfde2148dfd0d838328f579',1,'DecodeFrame::name'],['../structFrameInfo.html#abb53a7f93ed7abc0ea1ae4a8ccafcdcb',1,'FrameInfo::name'],['../structSignalInfo.html#a379e422a00cad56f896cacf60455b088',1,'SignalInfo::name']]] + ['maximum_0',['maximum',['../structDecodeSignal.html#a4a6ba87142a9badbf0ca830e9e709cb7',1,'DecodeSignal::maximum'],['../structSignalInfo.html#adf1c4331b9eabced0d7fdda40ff0eb52',1,'SignalInfo::maximum']]], + ['minimum_1',['minimum',['../structDecodeSignal.html#a0fb84e19a0ab3bd50b6f65c1075ebc25',1,'DecodeSignal::minimum'],['../structSignalInfo.html#ada7bf94fbeaa26bd08c73982b5af255b',1,'SignalInfo::minimum']]] ]; diff --git a/docs/html/search/variables_9.js b/docs/html/search/variables_9.js index ee45616..16390c6 100644 --- a/docs/html/search/variables_9.js +++ b/docs/html/search/variables_9.js @@ -1,4 +1,4 @@ var searchData= [ - ['offset_0',['offset',['../structDecodeSignal.html#a92db637af4e224a0ae70173050dc3f74',1,'DecodeSignal::offset'],['../structSignalInfo.html#ab7d0769f47aa540656b22e4e49db517e',1,'SignalInfo::offset']]] + ['name_0',['name',['../structDecodeSignal.html#a58cf5844f2272a23dcb9687d912e4780',1,'DecodeSignal::name'],['../structDecodeFrame.html#aa0a7f8fd5bfde2148dfd0d838328f579',1,'DecodeFrame::name'],['../structFrameInfo.html#abb53a7f93ed7abc0ea1ae4a8ccafcdcb',1,'FrameInfo::name'],['../structSignalInfo.html#a379e422a00cad56f896cacf60455b088',1,'SignalInfo::name']]] ]; diff --git a/docs/html/search/variables_a.js b/docs/html/search/variables_a.js index bf8a391..ee45616 100644 --- a/docs/html/search/variables_a.js +++ b/docs/html/search/variables_a.js @@ -1,6 +1,4 @@ var searchData= [ - ['pgn_0',['pgn',['../structDecodeFrame.html#a1d3c54055c0cbceb73adf551f7067f23',1,'DecodeFrame::pgn'],['../structFrameInfo.html#aee518b33f1000bf0b7f6e4a87474c943',1,'FrameInfo::pgn']]], - ['physicalvalue_1',['physicalValue',['../structDecodedSignalValue.html#a6847d05b3cb00d5e0f6c611968f57978',1,'DecodedSignalValue']]], - ['public_2',['public',['../structDecodedFrameValue.html#adae123ac7fbb4a5c314b64b01109f4a8',1,'DecodedFrameValue::public'],['../structDecodeFrame.html#a7f4e71bbdec3f424b625e724e3dfbf14',1,'DecodeFrame::public'],['../structFrameInfo.html#a3f7e25d67ddae22f2ed50823a5a26084',1,'FrameInfo::public']]] + ['offset_0',['offset',['../structDecodeSignal.html#a92db637af4e224a0ae70173050dc3f74',1,'DecodeSignal::offset'],['../structSignalInfo.html#ab7d0769f47aa540656b22e4e49db517e',1,'SignalInfo::offset']]] ]; diff --git a/docs/html/search/variables_b.js b/docs/html/search/variables_b.js index 52b5519..bf8a391 100644 --- a/docs/html/search/variables_b.js +++ b/docs/html/search/variables_b.js @@ -1,5 +1,6 @@ var searchData= [ - ['rawvalue_0',['rawValue',['../structDecodedSignalValue.html#a503c90b4b1a610b8252c45e466367c28',1,'DecodedSignalValue']]], - ['receivers_1',['receivers',['../structDecodeSignal.html#abdbae62a64d2df716bf60c6b67b30eaa',1,'DecodeSignal::receivers'],['../structSignalInfo.html#a2c95562fd0b29327a7fd7b1e6feee7f3',1,'SignalInfo::receivers']]] + ['pgn_0',['pgn',['../structDecodeFrame.html#a1d3c54055c0cbceb73adf551f7067f23',1,'DecodeFrame::pgn'],['../structFrameInfo.html#aee518b33f1000bf0b7f6e4a87474c943',1,'FrameInfo::pgn']]], + ['physicalvalue_1',['physicalValue',['../structDecodedSignalValue.html#a6847d05b3cb00d5e0f6c611968f57978',1,'DecodedSignalValue']]], + ['public_2',['public',['../structDecodedFrameValue.html#adae123ac7fbb4a5c314b64b01109f4a8',1,'DecodedFrameValue::public'],['../structDecodeFrame.html#a7f4e71bbdec3f424b625e724e3dfbf14',1,'DecodeFrame::public'],['../structFrameInfo.html#a3f7e25d67ddae22f2ed50823a5a26084',1,'FrameInfo::public']]] ]; diff --git a/docs/html/search/variables_c.js b/docs/html/search/variables_c.js index eb3e73b..52b5519 100644 --- a/docs/html/search/variables_c.js +++ b/docs/html/search/variables_c.js @@ -1,4 +1,5 @@ var searchData= [ - ['startbit_0',['startbit',['../structDecodeSignal.html#aaf5d7527ddf65b6355c2b4f3626df22d',1,'DecodeSignal::startBit'],['../structSignalInfo.html#ace290724f9801521609aedaa946d61f1',1,'SignalInfo::startBit']]] + ['rawvalue_0',['rawValue',['../structDecodedSignalValue.html#a503c90b4b1a610b8252c45e466367c28',1,'DecodedSignalValue']]], + ['receivers_1',['receivers',['../structDecodeSignal.html#abdbae62a64d2df716bf60c6b67b30eaa',1,'DecodeSignal::receivers'],['../structSignalInfo.html#a2c95562fd0b29327a7fd7b1e6feee7f3',1,'SignalInfo::receivers']]] ]; diff --git a/docs/html/search/variables_d.js b/docs/html/search/variables_d.js index 3733358..eb3e73b 100644 --- a/docs/html/search/variables_d.js +++ b/docs/html/search/variables_d.js @@ -1,4 +1,4 @@ var searchData= [ - ['transmitter_0',['transmitter',['../structDecodeFrame.html#ad78241dc40c793aabb8495b6989b81a9',1,'DecodeFrame::transmitter'],['../structFrameInfo.html#a92749ec3798d4211a505860fb389a9e8',1,'FrameInfo::transmitter']]] + ['startbit_0',['startbit',['../structDecodeSignal.html#aaf5d7527ddf65b6355c2b4f3626df22d',1,'DecodeSignal::startBit'],['../structSignalInfo.html#ace290724f9801521609aedaa946d61f1',1,'SignalInfo::startBit']]] ]; diff --git a/docs/html/search/variables_e.js b/docs/html/search/variables_e.js index 7a9aea0..3733358 100644 --- a/docs/html/search/variables_e.js +++ b/docs/html/search/variables_e.js @@ -1,4 +1,4 @@ var searchData= [ - ['unit_0',['unit',['../structDecodeSignal.html#a38eed9ca7581423fd8bfbedcffc12092',1,'DecodeSignal::unit'],['../structSignalInfo.html#a1f214f03e94ef5794de2d3367bfcbd01',1,'SignalInfo::unit']]] + ['transmitter_0',['transmitter',['../structDecodeFrame.html#ad78241dc40c793aabb8495b6989b81a9',1,'DecodeFrame::transmitter'],['../structFrameInfo.html#a92749ec3798d4211a505860fb389a9e8',1,'FrameInfo::transmitter']]] ]; diff --git a/docs/html/search/variables_f.js b/docs/html/search/variables_f.js index d699763..7a9aea0 100644 --- a/docs/html/search/variables_f.js +++ b/docs/html/search/variables_f.js @@ -1,6 +1,4 @@ var searchData= [ - ['valid_0',['valid',['../structDecodedSignalValue.html#aac0ed361af545cde48d0e6f41a859686',1,'DecodedSignalValue::valid'],['../structDecodedFrameValue.html#a4f51c31110dba1f73a763c596372beb0',1,'DecodedFrameValue::valid']]], - ['valuedescriptions_1',['valuedescriptions',['../structDecodeSignal.html#a822155d9bf4ed5f3300c9e9befe606ff',1,'DecodeSignal::valueDescriptions'],['../structSignalInfo.html#a43f47d0433d0cc39076bd7278b46af9c',1,'SignalInfo::valueDescriptions']]], - ['valuetype_2',['valueType',['../structDecodeSignal.html#a9d37638129263b8902ba5be59baf39a8',1,'DecodeSignal']]] + ['unit_0',['unit',['../structDecodeSignal.html#a38eed9ca7581423fd8bfbedcffc12092',1,'DecodeSignal::unit'],['../structSignalInfo.html#a1f214f03e94ef5794de2d3367bfcbd01',1,'SignalInfo::unit']]] ]; diff --git a/docs/html/structDbcDatabase.html b/docs/html/structDbcDatabase.html index d67a43b..fabc5df 100644 --- a/docs/html/structDbcDatabase.html +++ b/docs/html/structDbcDatabase.html @@ -127,7 +127,7 @@ Public Attributes

          Definition at line 23 of file dbc_database.h.

          -

          Referenced by DbcTreeBuilder::Build(), and DbcDecodeBuilder::Build().

          +

          Referenced by DbcTreeBuilder::Build(), and DbcDecodeBuilder::Build().

          diff --git a/docs/html/structDecodeFrame-members.html b/docs/html/structDecodeFrame-members.html index 9e6679b..6d0a9dc 100644 --- a/docs/html/structDecodeFrame-members.html +++ b/docs/html/structDecodeFrame-members.html @@ -100,12 +100,13 @@ $(document).ready(function(){initNavTree('structDecodeFrame.html',''); initResiz commentDecodeFrame DecodeFrame()=default (defined in DecodeFrame)DecodeFrame dlcDecodeFrame - hasPgnDecodeFrame - isExtendedDecodeFrame - nameDecodeFrame - pgnDecodeFrame - publicDecodeFrame - transmitterDecodeFrame + GetKey() const (defined in DecodeFrame)DecodeFrameinline + hasPgnDecodeFrame + isExtendedDecodeFrame + nameDecodeFrame + pgnDecodeFrame + publicDecodeFrame + transmitterDecodeFrame diff --git a/docs/html/structDecodeFrame.html b/docs/html/structDecodeFrame.html index b370909..bb60520 100644 --- a/docs/html/structDecodeFrame.html +++ b/docs/html/structDecodeFrame.html @@ -91,6 +91,7 @@ $(document).ready(function(){initNavTree('structDecodeFrame.html',''); initResiz
          DecodeFrame Struct Reference
          @@ -102,6 +103,11 @@ $(document).ready(function(){initNavTree('structDecodeFrame.html',''); initResiz

          #include <decode_database.h>

          + + + +

          +Public Member Functions

          FrameKey GetKey () const
           
          @@ -126,8 +132,36 @@ Public Attributes

          Detailed Description

          Runtime-ready frame definition.

          -

          Definition at line 63 of file decode_database.h.

          -

          Member Data Documentation

          +

          Definition at line 65 of file decode_database.h.

          +

          Member Function Documentation

          + +

          ◆ GetKey()

          + +
          +
          +

          Public Attributes

          std::string name
          + + + + +
          + + + + + + + +
          FrameKey DecodeFrame::GetKey () const
          +
          +inline
          +
          + +

          Definition at line 78 of file decode_database.h.

          + +
          + +

          Member Data Documentation

          ◆ name

          @@ -141,9 +175,9 @@ Public Attributes

          Frame name.

          -

          Definition at line 64 of file decode_database.h.

          +

          Definition at line 66 of file decode_database.h.

          -

          Referenced by DbcDecodeBuilder::Build().

          +

          Referenced by DbcDecodeBuilder::Build().

          @@ -160,9 +194,9 @@ Public Attributes

          Normalized CAN ID.

          -

          Definition at line 65 of file decode_database.h.

          +

          Definition at line 67 of file decode_database.h.

          -

          Referenced by DbcDecodeBuilder::Build().

          +

          Referenced by DbcDecodeBuilder::Build().

          @@ -179,9 +213,9 @@ Public Attributes

          true for extended frame.

          -

          Definition at line 66 of file decode_database.h.

          +

          Definition at line 68 of file decode_database.h.

          -

          Referenced by DbcDecodeBuilder::Build().

          +

          Referenced by DbcDecodeBuilder::Build().

          @@ -198,9 +232,9 @@ Public Attributes

          Payload length.

          -

          Definition at line 67 of file decode_database.h.

          +

          Definition at line 69 of file decode_database.h.

          -

          Referenced by DbcDecodeBuilder::Build().

          +

          Referenced by DbcDecodeBuilder::Build().

          @@ -217,9 +251,9 @@ Public Attributes

          PGN if available.

          -

          Definition at line 68 of file decode_database.h.

          +

          Definition at line 70 of file decode_database.h.

          -

          Referenced by DbcDecodeBuilder::Build().

          +

          Referenced by DbcDecodeBuilder::Build().

          @@ -236,9 +270,9 @@ Public Attributes

          true if PGN is valid.

          -

          Definition at line 69 of file decode_database.h.

          +

          Definition at line 71 of file decode_database.h.

          -

          Referenced by DbcDecodeBuilder::Build().

          +

          Referenced by DbcDecodeBuilder::Build().

          @@ -255,9 +289,9 @@ Public Attributes

          Transmitter ECU.

          -

          Definition at line 70 of file decode_database.h.

          +

          Definition at line 72 of file decode_database.h.

          -

          Referenced by DbcDecodeBuilder::Build().

          +

          Referenced by DbcDecodeBuilder::Build().

          @@ -274,9 +308,9 @@ Public Attributes

          Frame comment.

          -

          Definition at line 71 of file decode_database.h.

          +

          Definition at line 73 of file decode_database.h.

          -

          Referenced by DbcDecodeBuilder::Build().

          +

          Referenced by DbcDecodeBuilder::Build().

          @@ -293,7 +327,7 @@ Public Attributes

          Signal definitions.

          -

          Definition at line 72 of file decode_database.h.

          +

          Definition at line 74 of file decode_database.h.

          diff --git a/docs/html/structDecodeSignal.html b/docs/html/structDecodeSignal.html index 4fc775c..919b78b 100644 --- a/docs/html/structDecodeSignal.html +++ b/docs/html/structDecodeSignal.html @@ -136,7 +136,7 @@ Public Attributes

          Detailed Description

          Runtime-ready signal definition.

          -

          Definition at line 41 of file decode_database.h.

          +

          Definition at line 43 of file decode_database.h.

          Member Data Documentation

          ◆ multiplexing

          @@ -150,7 +150,7 @@ Public Attributes
          -

          Definition at line 42 of file decode_database.h.

          +

          Definition at line 44 of file decode_database.h.

          @@ -167,9 +167,9 @@ Public Attributes

          Signal name.

          -

          Definition at line 43 of file decode_database.h.

          +

          Definition at line 45 of file decode_database.h.

          -

          Referenced by DbcDecodeBuilder::Build().

          +

          Referenced by DbcDecodeBuilder::Build().

          @@ -186,9 +186,9 @@ Public Attributes

          DBC start bit.

          -

          Definition at line 44 of file decode_database.h.

          +

          Definition at line 46 of file decode_database.h.

          -

          Referenced by DbcDecodeBuilder::Build().

          +

          Referenced by DbcDecodeBuilder::Build().

          @@ -205,9 +205,9 @@ Public Attributes

          Signal length in bits.

          -

          Definition at line 45 of file decode_database.h.

          +

          Definition at line 47 of file decode_database.h.

          -

          Referenced by DbcDecodeBuilder::Build().

          +

          Referenced by DbcDecodeBuilder::Build().

          @@ -224,9 +224,9 @@ Public Attributes

          Intel or Motorola.

          -

          Definition at line 46 of file decode_database.h.

          +

          Definition at line 48 of file decode_database.h.

          -

          Referenced by DbcDecodeBuilder::Build().

          +

          Referenced by DbcDecodeBuilder::Build().

          @@ -243,9 +243,9 @@ Public Attributes

          Signed or unsigned.

          -

          Definition at line 47 of file decode_database.h.

          +

          Definition at line 49 of file decode_database.h.

          -

          Referenced by DbcDecodeBuilder::Build().

          +

          Referenced by DbcDecodeBuilder::Build().

          @@ -262,9 +262,9 @@ Public Attributes

          Scaling factor.

          -

          Definition at line 48 of file decode_database.h.

          +

          Definition at line 50 of file decode_database.h.

          -

          Referenced by DbcDecodeBuilder::Build().

          +

          Referenced by DbcDecodeBuilder::Build().

          @@ -281,9 +281,9 @@ Public Attributes

          Physical offset.

          -

          Definition at line 49 of file decode_database.h.

          +

          Definition at line 51 of file decode_database.h.

          -

          Referenced by DbcDecodeBuilder::Build().

          +

          Referenced by DbcDecodeBuilder::Build().

          @@ -300,9 +300,9 @@ Public Attributes

          Minimum physical value.

          -

          Definition at line 50 of file decode_database.h.

          +

          Definition at line 52 of file decode_database.h.

          -

          Referenced by DbcDecodeBuilder::Build().

          +

          Referenced by DbcDecodeBuilder::Build().

          @@ -319,9 +319,9 @@ Public Attributes

          Maximum physical value.

          -

          Definition at line 51 of file decode_database.h.

          +

          Definition at line 53 of file decode_database.h.

          -

          Referenced by DbcDecodeBuilder::Build().

          +

          Referenced by DbcDecodeBuilder::Build().

          @@ -338,9 +338,9 @@ Public Attributes

          Physical unit.

          -

          Definition at line 52 of file decode_database.h.

          +

          Definition at line 54 of file decode_database.h.

          -

          Referenced by DbcDecodeBuilder::Build().

          +

          Referenced by DbcDecodeBuilder::Build().

          @@ -357,9 +357,9 @@ Public Attributes

          Receivers.

          -

          Definition at line 53 of file decode_database.h.

          +

          Definition at line 55 of file decode_database.h.

          -

          Referenced by DbcDecodeBuilder::Build().

          +

          Referenced by DbcDecodeBuilder::Build().

          @@ -376,9 +376,9 @@ Public Attributes

          Raw integer state descriptions.

          -

          Definition at line 54 of file decode_database.h.

          +

          Definition at line 56 of file decode_database.h.

          -

          Referenced by DbcDecodeBuilder::Build(), and DecodedSignalValue::GetValueDescription().

          +

          Referenced by DbcDecodeBuilder::Build().

          @@ -395,9 +395,9 @@ Public Attributes

          Comment.

          -

          Definition at line 55 of file decode_database.h.

          +

          Definition at line 57 of file decode_database.h.

          -

          Referenced by DbcDecodeBuilder::Build().

          +

          Referenced by DbcDecodeBuilder::Build().

          diff --git a/docs/html/structDecodedFrameValue-members.html b/docs/html/structDecodedFrameValue-members.html index 4d9b779..3d24f0e 100644 --- a/docs/html/structDecodedFrameValue-members.html +++ b/docs/html/structDecodedFrameValue-members.html @@ -97,9 +97,10 @@ $(document).ready(function(){initNavTree('structDecodedFrameValue.html',''); ini

          This is the complete list of members for DecodedFrameValue, including all inherited members.

          - - - + + + +
          DecodedFrameValue()=default (defined in DecodedFrameValue)DecodedFrameValue
          definitionDecodedFrameValue
          publicDecodedFrameValue
          validDecodedFrameValue
          definitionDecodedFrameValue
          keyDecodedFrameValue
          publicDecodedFrameValue
          validDecodedFrameValue
          diff --git a/docs/html/structDecodedFrameValue.html b/docs/html/structDecodedFrameValue.html index 40faccb..f0b9160 100644 --- a/docs/html/structDecodedFrameValue.html +++ b/docs/html/structDecodedFrameValue.html @@ -104,8 +104,10 @@ $(document).ready(function(){initNavTree('structDecodedFrameValue.html',''); ini - - + + + + @@ -114,24 +116,43 @@ Public Attributes

          Detailed Description

          Fully decoded frame.

          -

          Definition at line 61 of file dbc_decoder.h.

          +

          Definition at line 62 of file dbc_decoder.h.

          Member Data Documentation

          - -

          ◆ definition

          + +

          ◆ definition

          Public Attributes

          const DecodeFrame * definition = nullptr
           
          std::shared_ptr< const DecodeFrame > definition
           
          FrameKey key
           
          std::vector< DecodedSignalValue > public
           
          bool valid = false
          - +
          const DecodeFrame* DecodedFrameValue::definition = nullptrstd::shared_ptr<const DecodeFrame> DecodedFrameValue::definition
          -

          Frame definition.

          +

          Owning immutable definition.

          -

          Definition at line 62 of file dbc_decoder.h.

          +

          Definition at line 63 of file dbc_decoder.h.

          -

          Referenced by DbcDecoder::Decode().

          +

          Referenced by DbcDecoder::Decode().

          + +
          + + +

          ◆ key

          + +
          +
          + + + + +
          FrameKey DecodedFrameValue::key
          +
          +

          Stable application identifier.

          + +

          Definition at line 64 of file dbc_decoder.h.

          + +

          Referenced by DbcDecoder::Decode().

          @@ -148,7 +169,7 @@ Public Attributes

          Decoded signal values.

          -

          Definition at line 63 of file dbc_decoder.h.

          +

          Definition at line 65 of file dbc_decoder.h.

          @@ -165,9 +186,9 @@ Public Attributes

          true if frame was matched.

          -

          Definition at line 64 of file dbc_decoder.h.

          +

          Definition at line 66 of file dbc_decoder.h.

          -

          Referenced by DbcDecoder::Decode().

          +

          Referenced by DbcDecoder::Decode().

          diff --git a/docs/html/structDecodedFrameValue.js b/docs/html/structDecodedFrameValue.js index 6e26145..53f4684 100644 --- a/docs/html/structDecodedFrameValue.js +++ b/docs/html/structDecodedFrameValue.js @@ -1,6 +1,7 @@ var structDecodedFrameValue = [ - [ "definition", "structDecodedFrameValue.html#a60dda1cc352d2c8087f0bdbc81dd266c", null ], + [ "definition", "structDecodedFrameValue.html#a33e971ba10030506007aa201c89f351d", null ], + [ "key", "structDecodedFrameValue.html#a32143efe2023a1ecd977a9ae93e50b73", null ], [ "public", "structDecodedFrameValue.html#adae123ac7fbb4a5c314b64b01109f4a8", null ], [ "valid", "structDecodedFrameValue.html#a4f51c31110dba1f73a763c596372beb0", null ] ]; \ No newline at end of file diff --git a/docs/html/structDecodedSignalValue-members.html b/docs/html/structDecodedSignalValue-members.html index c7fea96..4f8c9e7 100644 --- a/docs/html/structDecodedSignalValue-members.html +++ b/docs/html/structDecodedSignalValue-members.html @@ -97,12 +97,13 @@ $(document).ready(function(){initNavTree('structDecodedSignalValue.html',''); in

          This is the complete list of members for DecodedSignalValue, including all inherited members.

          - + - - - - + + + + +
          DecodedSignalValue()=default (defined in DecodedSignalValue)DecodedSignalValue
          definitionDecodedSignalValue
          definitionDecodedSignalValue
          GetValueDescription() constDecodedSignalValueinline
          physicalValueDecodedSignalValue
          rawValueDecodedSignalValue
          status (defined in DecodedSignalValue)DecodedSignalValue
          validDecodedSignalValue
          keyDecodedSignalValue
          physicalValueDecodedSignalValue
          rawValueDecodedSignalValue
          status (defined in DecodedSignalValue)DecodedSignalValue
          validDecodedSignalValue
          diff --git a/docs/html/structDecodedSignalValue.html b/docs/html/structDecodedSignalValue.html index 1b35271..6f58434 100644 --- a/docs/html/structDecodedSignalValue.html +++ b/docs/html/structDecodedSignalValue.html @@ -110,8 +110,10 @@ Public Member Functions - - + + + + @@ -150,29 +152,48 @@ Public Attributes

          Lookup using the raw integer; nullptr for invalid or unmapped values.

          -

          Definition at line 51 of file dbc_decoder.h.

          +

          Definition at line 52 of file dbc_decoder.h.

          -

          References definition, rawValue, valid, and DecodeSignal::valueDescriptions.

          +

          References definition, rawValue, and valid.

          Member Data Documentation

          - -

          ◆ definition

          + +

          ◆ definition

          Public Attributes

          const DecodeSignal * definition = nullptr
           
          std::shared_ptr< const DecodeSignal > definition
           
          SignalKey key
           
          RawSignalValue rawValue = std::uint64_t(0U)
           
          double physicalValue = 0.0
          - +
          const DecodeSignal* DecodedSignalValue::definition = nullptrstd::shared_ptr<const DecodeSignal> DecodedSignalValue::definition
          -

          Signal definition.

          +

          Owning immutable definition.

          Definition at line 44 of file dbc_decoder.h.

          -

          Referenced by GetValueDescription().

          +

          Referenced by DbcDecoder::Decode(), and GetValueDescription().

          + +
          + + +

          ◆ key

          + +
          +
          + + + + +
          SignalKey DecodedSignalValue::key
          +
          +

          Stable application identifier.

          + +

          Definition at line 45 of file dbc_decoder.h.

          + +

          Referenced by DbcDecoder::Decode().

          @@ -189,9 +210,9 @@ Public Attributes

          Exact signed or unsigned raw value.

          -

          Definition at line 45 of file dbc_decoder.h.

          +

          Definition at line 46 of file dbc_decoder.h.

          -

          Referenced by GetValueDescription().

          +

          Referenced by GetValueDescription().

          @@ -208,7 +229,7 @@ Public Attributes

          Converted physical value.

          -

          Definition at line 46 of file dbc_decoder.h.

          +

          Definition at line 47 of file dbc_decoder.h.

          @@ -225,9 +246,9 @@ Public Attributes

          true if decoding succeeded.

          -

          Definition at line 47 of file dbc_decoder.h.

          +

          Definition at line 48 of file dbc_decoder.h.

          -

          Referenced by GetValueDescription().

          +

          Referenced by GetValueDescription().

          @@ -243,7 +264,7 @@ Public Attributes
          -

          Definition at line 48 of file dbc_decoder.h.

          +

          Definition at line 49 of file dbc_decoder.h.

          diff --git a/docs/html/structDecodedSignalValue.js b/docs/html/structDecodedSignalValue.js index d4a015f..cb0464d 100644 --- a/docs/html/structDecodedSignalValue.js +++ b/docs/html/structDecodedSignalValue.js @@ -1,7 +1,8 @@ var structDecodedSignalValue = [ [ "GetValueDescription", "structDecodedSignalValue.html#affc38af1bf31bcb6f2c33044bce92bd2", null ], - [ "definition", "structDecodedSignalValue.html#acadc3b3bb21dd6b0412d342c7e6b20d7", null ], + [ "definition", "structDecodedSignalValue.html#a828b5ef7faefc14fbf5dbd46249bcad2", null ], + [ "key", "structDecodedSignalValue.html#a33df0fcd92b23b3e08539906fc6b4c4a", null ], [ "rawValue", "structDecodedSignalValue.html#a503c90b4b1a610b8252c45e466367c28", null ], [ "physicalValue", "structDecodedSignalValue.html#a6847d05b3cb00d5e0f6c611968f57978", null ], [ "valid", "structDecodedSignalValue.html#aac0ed361af545cde48d0e6f41a859686", null ] diff --git a/docs/html/structFrameKey.html b/docs/html/structFrameKey.html index 40c6dc2..298d52b 100644 --- a/docs/html/structFrameKey.html +++ b/docs/html/structFrameKey.html @@ -98,10 +98,10 @@ $(document).ready(function(){initNavTree('structFrameKey.html',''); initResizabl
          -

          Key for fast frame lookup. +

          Stable frame identifier: normalized CAN ID and frame type. More...

          -

          #include <decode_database.h>

          +

          #include <definition_key.h>

          @@ -118,9 +118,9 @@ Public Attributes

          Public Member Functions

           

          Detailed Description

          -

          Key for fast frame lookup.

          +

          Stable frame identifier: normalized CAN ID and frame type.

          -

          Definition at line 80 of file decode_database.h.

          +

          Definition at line 15 of file definition_key.h.

          Constructor & Destructor Documentation

          ◆ FrameKey()

          @@ -156,7 +156,7 @@ Public Attributes
          -

          Definition at line 86 of file decode_database.h.

          +

          Definition at line 21 of file definition_key.h.

          @@ -185,7 +185,7 @@ Public Attributes
          -

          Definition at line 90 of file decode_database.h.

          +

          Definition at line 25 of file definition_key.h.

          @@ -202,7 +202,7 @@ Public Attributes
          -

          Definition at line 81 of file decode_database.h.

          +

          Definition at line 16 of file definition_key.h.

          @@ -218,12 +218,12 @@ Public Attributes
          -

          Definition at line 82 of file decode_database.h.

          +

          Definition at line 17 of file definition_key.h.


          The documentation for this struct was generated from the following file: diff --git a/docs/html/structFrameKeyHasher.html b/docs/html/structFrameKeyHasher.html index c559633..59772b4 100644 --- a/docs/html/structFrameKeyHasher.html +++ b/docs/html/structFrameKeyHasher.html @@ -100,7 +100,7 @@ $(document).ready(function(){initNavTree('structFrameKeyHasher.html',''); initRe

          Hasher for frame key. More...

          -

          #include <decode_database.h>

          +

          #include <definition_key.h>

          @@ -110,7 +110,7 @@ Public Member Functions

          Detailed Description

          Hasher for frame key.

          -

          Definition at line 98 of file decode_database.h.

          +

          Definition at line 33 of file definition_key.h.

          Member Function Documentation

          ◆ operator()()

          @@ -136,12 +136,12 @@ Public Member Functions

          Public Member Functions

          -

          Definition at line 99 of file decode_database.h.

          +

          Definition at line 34 of file definition_key.h.


          The documentation for this struct was generated from the following file: diff --git a/docs/html/structRawCanFrame.html b/docs/html/structRawCanFrame.html index f5c1288..fe8ced3 100644 --- a/docs/html/structRawCanFrame.html +++ b/docs/html/structRawCanFrame.html @@ -131,7 +131,7 @@ Public Attributes

          Definition at line 25 of file dbc_decoder.h.

          -

          Referenced by DbcDecoder::Decode().

          +

          Referenced by DbcDecoder::Decode().

          @@ -150,7 +150,7 @@ Public Attributes

          Definition at line 26 of file dbc_decoder.h.

          -

          Referenced by DbcDecoder::Decode().

          +

          Referenced by DbcDecoder::Decode().

          diff --git a/docs/html/structSignalKey-members.html b/docs/html/structSignalKey-members.html new file mode 100644 index 0000000..50aa8b0 --- /dev/null +++ b/docs/html/structSignalKey-members.html @@ -0,0 +1,113 @@ + + + + + + + +DBC Framework: Member List + + + + + + + + + + + + + +
          +
          + + + + + + +
          +
          DBC Framework +
          +
          DBC parsing and CAN signal decoding framework
          +
          +
          + + + + + + + +
          +
          + +
          +
          +
          + +
          + +
          +
          + + +
          +
          +
          +
          +
          +
          Loading...
          +
          Searching...
          +
          No Matches
          +
          +
          +
          +
          + +
          +
          SignalKey Member List
          +
          +
          + +

          This is the complete list of members for SignalKey, including all inherited members.

          + + + + + + +
          frame (defined in SignalKey)SignalKey
          name (defined in SignalKey)SignalKey
          operator==(const SignalKey &other) const (defined in SignalKey)SignalKeyinline
          SignalKey()=default (defined in SignalKey)SignalKey
          SignalKey(FrameKey frameKey, std::string signalName) (defined in SignalKey)SignalKeyinline
          +
          + + + + diff --git a/docs/html/structSignalKey.html b/docs/html/structSignalKey.html new file mode 100644 index 0000000..cb917f3 --- /dev/null +++ b/docs/html/structSignalKey.html @@ -0,0 +1,235 @@ + + + + + + + +DBC Framework: SignalKey Struct Reference + + + + + + + + + + + + + +
          +
          + + + + + + +
          +
          DBC Framework +
          +
          DBC parsing and CAN signal decoding framework
          +
          +
          + + + + + + + +
          +
          + +
          +
          +
          + +
          + +
          +
          + + +
          +
          +
          +
          +
          +
          Loading...
          +
          Searching...
          +
          No Matches
          +
          +
          +
          +
          + +
          + +
          SignalKey Struct Reference
          +
          +
          + +

          #include <definition_key.h>

          + + + + + + +

          +Public Member Functions

           SignalKey (FrameKey frameKey, std::string signalName)
           
          bool operator== (const SignalKey &other) const
           
          + + + + + +

          +Public Attributes

          FrameKey frame
           
          std::string name
           
          +

          Detailed Description

          +

          Stable signal identifier within one logical DBC database.

          + +

          Definition at line 42 of file definition_key.h.

          +

          Constructor & Destructor Documentation

          + +

          ◆ SignalKey()

          + +
          +
          + + + + + +
          + + + + + + + + + + + + + + + + + + +
          SignalKey::SignalKey (FrameKey frameKey,
          std::string signalName 
          )
          +
          +inline
          +
          + +

          Definition at line 47 of file definition_key.h.

          + +
          +
          +

          Member Function Documentation

          + +

          ◆ operator==()

          + +
          +
          + + + + + +
          + + + + + + + + +
          bool SignalKey::operator== (const SignalKey & other) const
          +
          +inline
          +
          + +

          Definition at line 51 of file definition_key.h.

          + +
          +
          +

          Member Data Documentation

          + +

          ◆ frame

          + +
          +
          + + + + +
          FrameKey SignalKey::frame
          +
          + +

          Definition at line 43 of file definition_key.h.

          + +
          +
          + +

          ◆ name

          + +
          +
          + + + + +
          std::string SignalKey::name
          +
          + +

          Definition at line 44 of file definition_key.h.

          + +
          +
          +
          The documentation for this struct was generated from the following file: +
          +
          + + + + diff --git a/docs/html/structSignalKeyHasher-members.html b/docs/html/structSignalKeyHasher-members.html new file mode 100644 index 0000000..59ac5f9 --- /dev/null +++ b/docs/html/structSignalKeyHasher-members.html @@ -0,0 +1,109 @@ + + + + + + + +DBC Framework: Member List + + + + + + + + + + + + + +
          +
          + + + + + + +
          +
          DBC Framework +
          +
          DBC parsing and CAN signal decoding framework
          +
          +
          + + + + + + + +
          +
          + +
          +
          +
          + +
          + +
          +
          + + +
          +
          +
          +
          +
          +
          Loading...
          +
          Searching...
          +
          No Matches
          +
          +
          +
          +
          + +
          +
          SignalKeyHasher Member List
          +
          +
          + +

          This is the complete list of members for SignalKeyHasher, including all inherited members.

          + + +
          operator()(const SignalKey &key) const (defined in SignalKeyHasher)SignalKeyHasherinline
          +
          + + + + diff --git a/docs/html/structSignalKeyHasher.html b/docs/html/structSignalKeyHasher.html new file mode 100644 index 0000000..0d7dfe1 --- /dev/null +++ b/docs/html/structSignalKeyHasher.html @@ -0,0 +1,150 @@ + + + + + + + +DBC Framework: SignalKeyHasher Struct Reference + + + + + + + + + + + + + +
          +
          + + + + + + +
          +
          DBC Framework +
          +
          DBC parsing and CAN signal decoding framework
          +
          +
          + + + + + + + +
          +
          + +
          +
          +
          + +
          + +
          +
          + + +
          +
          +
          +
          +
          +
          Loading...
          +
          Searching...
          +
          No Matches
          +
          +
          +
          +
          + +
          + +
          SignalKeyHasher Struct Reference
          +
          +
          + + + + +

          +Public Member Functions

          std::size_t operator() (const SignalKey &key) const
           
          +

          Detailed Description

          +
          +

          Definition at line 56 of file definition_key.h.

          +

          Member Function Documentation

          + +

          ◆ operator()()

          + +
          +
          + + + + + +
          + + + + + + + + +
          std::size_t SignalKeyHasher::operator() (const SignalKey & key) const
          +
          +inline
          +
          + +

          Definition at line 57 of file definition_key.h.

          + +
          +
          +
          The documentation for this struct was generated from the following file: +
          +
          + + + + diff --git a/docs/html/tests_2main_8cpp_source.html b/docs/html/tests_2main_8cpp_source.html index 71efedb..4a4c0a0 100644 --- a/docs/html/tests_2main_8cpp_source.html +++ b/docs/html/tests_2main_8cpp_source.html @@ -105,13 +105,16 @@ $(document).ready(function(){initNavTree('tests_2main_8cpp_source.html',''); ini
          5int RunDecoderTests(int argc, char **argv);
          6int RunCoverageTests(int argc, char **argv);
          7
          -
          8int main(int argc, char **argv) {
          -
          9 QCoreApplication application(argc, argv);
          -
          10 const int parserResult = RunParserTests(argc, argv);
          -
          11 const int decoderResult = RunDecoderTests(argc, argv);
          -
          12 const int coverageResult = RunCoverageTests(argc, argv);
          -
          13 return parserResult | decoderResult | coverageResult;
          -
          14}
          +
          8int RunLifetimeTests(int argc, char **argv);
          +
          9
          +
          10int main(int argc, char **argv) {
          +
          11 QCoreApplication application(argc, argv);
          +
          12 const int parserResult = RunParserTests(argc, argv);
          +
          13 const int decoderResult = RunDecoderTests(argc, argv);
          +
          14 const int coverageResult = RunCoverageTests(argc, argv);
          +
          15 const int lifetimeResult = RunLifetimeTests(argc, argv);
          +
          16 return parserResult | decoderResult | coverageResult | lifetimeResult;
          +
          17}
          diff --git a/examples/main.cpp b/examples/main.cpp index 914869c..80ef304 100644 --- a/examples/main.cpp +++ b/examples/main.cpp @@ -121,8 +121,8 @@ int main(int argc, char *argv[]) { * Replace with live CAN frame or trace record later. */ RawCanFrame rawFrame; - rawFrame.canId = decodeDatabase.frames.empty() ? 0U : decodeDatabase.frames[0].canId; - rawFrame.isExtended = decodeDatabase.frames.empty() ? false : decodeDatabase.frames[0].isExtended; + rawFrame.canId = decodeDatabase.GetFrames().empty() ? 0U : decodeDatabase.GetFrames()[0].canId; + rawFrame.isExtended = decodeDatabase.GetFrames().empty() ? false : decodeDatabase.GetFrames()[0].isExtended; rawFrame.data.resize(8U, 0U); DbcDecoder decoder; diff --git a/tests/README.md b/tests/README.md index f4d1ac3..77e4d6d 100644 --- a/tests/README.md +++ b/tests/README.md @@ -24,7 +24,7 @@ make -j make check ``` -Or run `./tests/dbc_tests` directly. Parser, decoder, and additional coverage +Or run `./tests/dbc_tests` directly. Parser, decoder, lifetime, and additional coverage suites run, and the executable returns nonzero when any suite fails. Decoder cases appear as individual QtTest data rows; parser checks are grouped into named test slots. Checks also run in release builds. @@ -41,7 +41,7 @@ make check ``` `parser_tests.pri` and `decoder_tests.pri` include the original test sources; -`tests.pro` also includes `dbc_coverage_test.cpp`. +`tests.pro` also includes `dbc_coverage_test.cpp` and `dbc_lifetime_test.cpp`. `../core/core.pri` supplies the library include path and linkage. ## Decoder coverage @@ -120,3 +120,19 @@ API, verify source locations, and check that ambiguous targets receive no values All QtTest targets use Qt 6.8.2 and `QVERIFY_THROWS_EXCEPTION`. Exception tests explicitly discard `nodiscard` results when only the exception is being checked. The standalone tree test requires only a C++17 compiler. + +## Definition lifetime and reload coverage + +`dbc_lifetime_test.cpp` checks retained definitions and value-description strings +across reload, clear, and destruction; independently saved signal results; +copied/moved results and database copies; owning lookup handles; and release of +the old snapshot after its final owner is removed. Compile-time checks enforce +const access to runtime metadata. Reload fixtures change ordering, frame names, +scaling, units, and descriptions, remove definitions, and rename signals. + +Key tests check equality and hashing, standard/extended separation, the same +signal name in different frames, and missing lookups. Constructor tests reject +duplicate runtime keys, including manually supplied parsed metadata. Failed reload +leaves the active database intact; empty reload clears it. Invalid/unknown results +and insufficient payloads retain their documented ownership and status behavior. +Inactive branches and unavailable selectors also retain definitions across reload. diff --git a/tests/dbc_coverage_test.cpp b/tests/dbc_coverage_test.cpp index 276a259..30fbf35 100644 --- a/tests/dbc_coverage_test.cpp +++ b/tests/dbc_coverage_test.cpp @@ -21,13 +21,10 @@ namespace { } DecodeDatabase SingleSignal(const DecodeSignal &signal) { - DecodeDatabase database; DecodeFrame frame; frame.canId = 17U; frame.signals.push_back(signal); - database.frames.push_back(frame); - database.frameIndexByKey.emplace(FrameKey(17U, false), 0U); - return database; + return DecodeDatabase({frame}); } // Independent reference: collect the visited bits first, then weight them. @@ -115,14 +112,12 @@ void CoverageTest::frameLookup() { raw.canId = 18U; QVERIFY(!decoder.Decode(database, raw).valid); raw.canId = 17U; - database.frameIndexByKey.at(FrameKey(17U, false)) = database.frames.size(); - QVERIFY(decoder.FindFrame(database, 17U, false) == nullptr); - QVERIFY(!decoder.Decode(database, raw).valid); - database.frameIndexByKey.at(FrameKey(17U, false)) = 0U; - database.frames[0].signals.clear(); + DecodeFrame noSignals; + noSignals.canId = 17U; + database = DecodeDatabase({noSignals}); const DecodedFrameValue matched = decoder.Decode(database, raw); QVERIFY(matched.valid); - QCOMPARE(matched.definition, &database.frames[0]); + QCOMPARE(matched.definition.get(), &database.GetFrames()[0]); QVERIFY(matched.signals.empty()); } @@ -255,21 +250,28 @@ void CoverageTest::malformedRuntimeMultiplexing() { DecodeSignal selector; selector.length = 1U; selector.multiplexing.role = MultiplexRole::Selector; - DecodeDatabase database = SingleSignal(selector); + selector.name = "Selector"; + std::vector definitions = SingleSignal(selector).GetFrames(); DecodeSignal branch; + branch.name = "Branch"; branch.startBit = 8U; branch.length = 8U; branch.multiplexing.role = MultiplexRole::Branch; branch.multiplexing.value = 1U; - database.frames[0].signals.push_back(branch); + definitions[0].signals.push_back(branch); DecodeSignal ordinary; + ordinary.name = "Ordinary"; ordinary.startBit = 16U; ordinary.length = 8U; - database.frames[0].signals.push_back(ordinary); - if (kind == 0) database.frames[0].signals.push_back(selector); - if (kind == 1) database.frames[0].signals[0].valueType = ValueType::Signed; - if (kind == 2) database.frames[0].signals[0].length = 65U; - if (kind == 3) database.frames[0].signals[1].multiplexing.value = 2U; + definitions[0].signals.push_back(ordinary); + if (kind == 0) { + selector.name = "SecondSelector"; + definitions[0].signals.push_back(selector); + } + if (kind == 1) definitions[0].signals[0].valueType = ValueType::Signed; + if (kind == 2) definitions[0].signals[0].length = 65U; + if (kind == 3) definitions[0].signals[1].multiplexing.value = 2U; + const DecodeDatabase database(std::move(definitions)); RawCanFrame raw; raw.canId = 17U; raw.data = {1U, 42U, 99U}; @@ -491,8 +493,8 @@ void CoverageTest::missingFile() { void CoverageTest::builders() { const DecodeDatabase emptyRuntime = DbcDecodeBuilder().Build(DbcDatabase()); - QVERIFY(emptyRuntime.frames.empty()); - QVERIFY(emptyRuntime.frameIndexByKey.empty()); + QVERIFY(emptyRuntime.GetFrames().empty()); + QVERIFY(!emptyRuntime.FindFrame(FrameKey(0U, false))); const std::unique_ptr emptyTree = DbcTreeBuilder().Build(DbcDatabase()); QCOMPARE(emptyTree->GetType(), NodeType::Root); QCOMPARE(emptyTree->GetName(), std::string("dbc")); @@ -517,18 +519,17 @@ void CoverageTest::builders() { source.frames[0].signals[1].valueDescriptions.clear(); source.frames.clear(); } - QCOMPARE(runtime.frames.size(), expected.frames.size()); + QCOMPARE(runtime.GetFrames().size(), expected.frames.size()); QCOMPARE(tree->GetChildCount(), expected.frames.size()); - QCOMPARE(runtime.frameIndexByKey.size(), expected.frames.size()); for (std::size_t i = 0; i < expected.frames.size(); ++i) { const FrameInfo &frame = expected.frames[i]; - const DecodeFrame &decodedFrame = runtime.frames[i]; + const DecodeFrame &decodedFrame = runtime.GetFrames()[i]; const TreeNode *node = tree->GetChild(i); QVERIFY(node && node->GetFrame()); QCOMPARE(node->GetType(), NodeType::Frame); QCOMPARE(node->GetName(), frame.name); QVERIFY(node->GetSignal() == nullptr); - QCOMPARE(runtime.frameIndexByKey.at(FrameKey(frame.canId, frame.isExtended)), i); + QCOMPARE(runtime.FindFrame(FrameKey(frame.canId, frame.isExtended)).get(), &decodedFrame); const FrameInfo &copied = *node->GetFrame(); QCOMPARE(copied.name, frame.name); QCOMPARE(decodedFrame.name, frame.name); diff --git a/tests/dbc_decoder_test.cpp b/tests/dbc_decoder_test.cpp index 34ec8d1..dae43d4 100644 --- a/tests/dbc_decoder_test.cpp +++ b/tests/dbc_decoder_test.cpp @@ -68,19 +68,17 @@ void DbcDecoderTest::decode() { definition.canId = 0x123U; definition.dlc = static_cast(test.data.size()); definition.signals.push_back(signal); - DecodeDatabase database; - database.frames.push_back(definition); - database.frameIndexByKey.emplace(FrameKey(definition.canId, false), 0U); + const DecodeDatabase database({definition}); RawCanFrame frame; frame.canId = definition.canId; frame.data = test.data; const DecodedFrameValue result = DbcDecoder().Decode(database, frame); QVERIFY2(result.valid, test.name); - QCOMPARE(result.definition, &database.frames[0]); + QCOMPARE(result.definition.get(), &database.GetFrames()[0]); QCOMPARE(result.signals.size(), std::size_t(1U)); const DecodedSignalValue &decoded = result.signals[0]; - QCOMPARE(decoded.definition, &database.frames[0].signals[0]); + QCOMPARE(decoded.definition.get(), &database.GetFrames()[0].signals[0]); QCOMPARE(decoded.valid, test.valid); if (!test.valid) return; @@ -104,7 +102,6 @@ void DbcDecoderTest::boundaries() { std::uint64_t(0x8000000000000000ULL), std::uint64_t(0x8000000000000001ULL), std::uint64_t(0xFFFFFFFFFFFFFFFFULL)}) { - DecodeDatabase database; DecodeFrame definition; DecodeSignal signal; signal.startBit = order == ByteOrder::Intel ? 0U : 7U; @@ -114,8 +111,7 @@ void DbcDecoderTest::boundaries() { signal.factor = 0.5; signal.offset = 10.0; definition.signals.push_back(signal); - database.frames.push_back(definition); - database.frameIndexByKey.emplace(FrameKey(0U, false), 0U); + const DecodeDatabase database({definition}); RawCanFrame frame; for (unsigned byte = 0U; byte < 8U; ++byte) { const unsigned shift = (order == ByteOrder::Intel ? byte : 7U - byte) * 8U; diff --git a/tests/dbc_lifetime_test.cpp b/tests/dbc_lifetime_test.cpp new file mode 100644 index 0000000..5cb26d8 --- /dev/null +++ b/tests/dbc_lifetime_test.cpp @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: MIT +// Copyright (c) 2026 Dim Himro + +#include "dbc_decode_builder.h" +#include "dbc_decoder.h" +#include "dbc_parser.h" +#include +#include +#include +#include +#include +#include + +static_assert(std::is_same_v().GetFrames()), + const std::vector &>); +static_assert(std::is_same_v>); +static_assert(std::is_same_v>); + +namespace { + DecodeDatabase BuildText(const std::string &text) { + QTemporaryFile file; + if (!file.open() || + file.write(text.data(), static_cast(text.size())) != static_cast(text.size()) || + !file.flush()) + throw std::runtime_error("Cannot write reload fixture"); + return DbcDecodeBuilder().Build(DbcParser().ParseFile(file.fileName().toStdString())); + } + + const std::string firstDbc = + "BO_ 17 OldFrame: 2 ECU\n" + "SG_ State : 0|8@1+ (2,1) [1|511] \"old\" ECU\n" + "SG_ Removed : 8|8@1+ (1,0) [0|255] \"\" ECU\n" + "VAL_ 17 State 1 \"Old label\";\n" + "BO_ 18 Deleted: 1 ECU\n" + "SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n"; + const std::string secondDbc = + "BO_ 2147483665 Extended: 1 ECU\n" + "SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n" + "BO_ 17 NewFrame: 2 ECU\n" + "SG_ Renamed : 8|8@1+ (1,0) [0|255] \"\" ECU\n" + "SG_ State : 0|8@1+ (4,0) [0|1020] \"new\" ECU\n" + "VAL_ 17 State 1 \"New label\";\n"; +}// namespace + +class DbcLifetimeTest : public QObject { + Q_OBJECT +private Q_SLOTS: + void reload(); + void independentSignalLifetime(); + void lookupLifetime(); + void keys(); + void duplicateKeys(); + void failedReload(); + void invalidResults(); + void retainedMultiplexStatuses(); +}; + +void DbcLifetimeTest::reload() { + DecodeDatabase database = BuildText(firstDbc); + RawCanFrame raw; + raw.canId = 17U; + raw.data = {1U, 42U}; + DecodedFrameValue oldResult = DbcDecoder().Decode(database, raw); + const DecodedFrameValue copied = oldResult; + DecodedFrameValue moved = std::move(oldResult); + std::weak_ptr oldDefinition = moved.definition; + database = BuildText(secondDbc); + const DecodedFrameValue current = DbcDecoder().Decode(database, raw); + QVERIFY(current.valid && moved.valid && copied.valid); + QVERIFY(current.definition != moved.definition); + QVERIFY(current.key == moved.key); + QVERIFY(current.signals[1].key == moved.signals[0].key); + QCOMPARE(moved.definition->name, std::string("OldFrame")); + QCOMPARE(copied.definition, moved.definition); + QCOMPARE(moved.signals[0].physicalValue, 3.0); + QCOMPARE(current.signals[1].physicalValue, 4.0); + QCOMPARE(moved.signals[0].definition->unit, std::string("old")); + QCOMPARE(current.signals[1].definition->unit, std::string("new")); + QCOMPARE(*moved.signals[0].GetValueDescription(), std::string("Old label")); + QCOMPARE(*current.signals[1].GetValueDescription(), std::string("New label")); + QCOMPARE(moved.signals[1].definition->name, std::string("Removed")); + QVERIFY(!database.FindSignal(moved.signals[1].key)); + database = DecodeDatabase(); + QVERIFY(!oldDefinition.expired()); + QCOMPARE(current.definition->name, std::string("NewFrame")); + QCOMPARE(*current.signals[1].GetValueDescription(), std::string("New label")); +} + +void DbcLifetimeTest::independentSignalLifetime() { + DecodedSignalValue saved; + std::weak_ptr definition; + const std::string *label = nullptr; + { + DecodeDatabase database = BuildText(firstDbc); + RawCanFrame raw; + raw.canId = 17U; + raw.data = {1U, 0U}; + DecodedFrameValue result = DbcDecoder().Decode(database, raw); + saved = result.signals[0]; + definition = saved.definition; + label = saved.GetValueDescription(); + result = DecodedFrameValue(); + database = BuildText(secondDbc); + } + QVERIFY(!definition.expired()); + QVERIFY(label != nullptr); + QCOMPARE(*label, std::string("Old label")); + QCOMPARE(saved.definition->factor, 2.0); + DecodedSignalValue copied = saved; + DecodedSignalValue moved = std::move(saved); + QCOMPARE(moved.definition, copied.definition); + saved = DecodedSignalValue(); + moved = DecodedSignalValue(); + QVERIFY(!definition.expired()); + copied = DecodedSignalValue(); + QVERIFY(definition.expired()); +} + +void DbcLifetimeTest::lookupLifetime() { + std::shared_ptr frame; + std::shared_ptr signal; + std::weak_ptr released; + { + DecodeDatabase database = BuildText(firstDbc); + DecodeDatabase copy = database; + frame = DbcDecoder().FindFrame(database, 17U, false); + signal = copy.FindSignal(SignalKey(FrameKey(17U, false), "State")); + QVERIFY(frame && signal); + QCOMPARE(frame.get(), ©.GetFrames()[0]); + QCOMPARE(signal.get(), &frame->signals[0]); + released = frame; + database = BuildText(secondDbc); + DecodeDatabase moved = std::move(copy); + QVERIFY(copy.GetFrames().empty()); + QVERIFY(!copy.FindFrame(FrameKey(17U, false))); + QCOMPARE(moved.FindFrame(FrameKey(17U, false)), frame); + } + QCOMPARE(frame->name, std::string("OldFrame")); + frame.reset(); + QVERIFY(!released.expired()); + QCOMPARE(signal->name, std::string("State")); + signal.reset(); + QVERIFY(released.expired()); +} + +void DbcLifetimeTest::keys() { + const FrameKey frame(17U, false); + const SignalKey state(frame, "State"); + const DecodeDatabase first = BuildText(firstDbc); + const DecodeDatabase second = BuildText(secondDbc); + QVERIFY(first.FindFrame(frame)->GetKey() == second.FindFrame(frame)->GetKey()); + QVERIFY(first.FindSignal(state) && second.FindSignal(state)); + QVERIFY(!second.FindFrame(FrameKey(18U, false))); + QVERIFY(!second.FindSignal(SignalKey(frame, "Removed"))); + QVERIFY(second.FindSignal(SignalKey(frame, "Renamed"))); + QVERIFY(second.FindSignal(SignalKey(FrameKey(17U, true), "State"))); + QVERIFY(!second.FindSignal(SignalKey(FrameKey(999U, false), "State"))); + QVERIFY(first.FindSignal(SignalKey(FrameKey(18U, false), "State"))); + std::unordered_map frames; + frames.emplace(frame, 1); + frames.emplace(FrameKey(17U, true), 2); + QCOMPARE(frames.size(), std::size_t(2U)); + std::unordered_map signals; + signals.emplace(state, 1); + signals.emplace(SignalKey(FrameKey(17U, true), "State"), 2); + signals.emplace(SignalKey(frame, "Renamed"), 3); + signals.emplace(SignalKey(FrameKey(18U, false), "State"), 4); + QCOMPARE(signals.at(SignalKey(FrameKey(17U, false), "State")), 1); + QCOMPARE(signals.size(), std::size_t(4U)); +} + +void DbcLifetimeTest::duplicateKeys() { + DecodeFrame frame; + frame.canId = 17U; + QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (void) DecodeDatabase({frame, frame})); + DecodeSignal signal; + signal.name = "State"; + frame.signals = {signal, signal}; + QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (void) DecodeDatabase({frame})); + DbcDatabase parsed; + FrameInfo source; + source.canId = 17U; + parsed.frames = {source, source}; + QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (void) DbcDecodeBuilder().Build(parsed)); +} + +void DbcLifetimeTest::failedReload() { + DecodeDatabase database = BuildText(firstDbc); + const std::shared_ptr original = database.FindFrame(FrameKey(17U, false)); + QVERIFY_THROWS_EXCEPTION(std::runtime_error, database = BuildText("BO_ invalid\n")); + QCOMPARE(database.FindFrame(FrameKey(17U, false)), original); + database = BuildText(""); + QVERIFY(database.GetFrames().empty()); + QVERIFY(!database.FindFrame(FrameKey(17U, false))); + QCOMPARE(original->name, std::string("OldFrame")); +} + +void DbcLifetimeTest::invalidResults() { + RawCanFrame raw; + raw.canId = 17U; + DecodedFrameValue result = DbcDecoder().Decode(BuildText(firstDbc), raw); + QVERIFY(result.valid); + QVERIFY(!result.signals[0].valid); + QCOMPARE(result.signals[0].status, SignalDecodeStatus::InsufficientPayload); + QVERIFY(!result.signals[0].GetValueDescription()); + QCOMPARE(result.signals[0].definition->name, std::string("State")); + result = DbcDecoder().Decode(DecodeDatabase(), raw); + QVERIFY(!result.valid && !result.definition && result.signals.empty()); + QVERIFY(result.key == FrameKey(17U, false)); + QVERIFY(!DecodedSignalValue().GetValueDescription()); + QVERIFY(!DecodeDatabase().FindSignal(SignalKey(FrameKey(17U, false), "State"))); +} + +void DbcLifetimeTest::retainedMultiplexStatuses() { + const std::string text = + "BO_ 17 Frame: 2 ECU\n" + "SG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n" + "SG_ State m1 : 8|8@1+ (1,0) [0|255] \"\" ECU\n"; + const std::vector> payloads = {{0U}, {}, {1U}}; + const SignalDecodeStatus statuses[] = {SignalDecodeStatus::Inactive, + SignalDecodeStatus::SelectorUnavailable, + SignalDecodeStatus::InsufficientPayload}; + for (std::size_t index = 0U; index < payloads.size(); ++index) { + DecodeDatabase database = BuildText(text); + RawCanFrame raw; + raw.canId = 17U; + raw.data = payloads[index]; + const DecodedSignalValue saved = DbcDecoder().Decode(database, raw).signals[1]; + database = BuildText(secondDbc); + QCOMPARE(saved.status, statuses[index]); + QVERIFY(!saved.valid && !saved.GetValueDescription()); + QCOMPARE(saved.definition->multiplexing.role, MultiplexRole::Branch); + QVERIFY(saved.key == SignalKey(FrameKey(17U, false), "State")); + } +} + +int RunLifetimeTests(int argc, char **argv) { + DbcLifetimeTest test; + return QTest::qExec(&test, argc, argv); +} + +#include "dbc_lifetime_test.moc" diff --git a/tests/dbc_parser_test.cpp b/tests/dbc_parser_test.cpp index d146424..856b430 100644 --- a/tests/dbc_parser_test.cpp +++ b/tests/dbc_parser_test.cpp @@ -270,7 +270,7 @@ void DbcParserTest::diagnosticUnsupportedStatements() { CHECK(decoded.signals[0].GetValueDescription() && *decoded.signals[0].GetValueDescription() == "On", "Warnings preserve VAL_ descriptions"); - QCOMPARE(runtime.frames[0].signals[0].comment, std::string("Signal comment")); + QCOMPARE(runtime.GetFrames()[0].signals[0].comment, std::string("Signal comment")); } } @@ -588,7 +588,7 @@ void DbcParserTest::multiplexingBoundaries() { "SG_ Mode M : 7|64@0+ (0,5) [0|1] \"\" ECU\n"); const DbcDatabase parsed = DbcParser().ParseFile(fixture.path.string()); DecodeDatabase runtime = DbcDecodeBuilder().Build(parsed); - CHECK(runtime.frames[0].signals[0].multiplexing.value == std::numeric_limits::max(), + CHECK(runtime.GetFrames()[0].signals[0].multiplexing.value == std::numeric_limits::max(), "Exact uint64 branch metadata"); RawCanFrame raw; raw.canId = 1U; @@ -601,12 +601,15 @@ void DbcParserTest::multiplexingBoundaries() { result = DbcDecoder().Decode(runtime, raw); CHECK(result.signals[0].status == SignalDecodeStatus::Inactive, "Adjacent large integers remain distinct"); - runtime.frames[0].signals[1].length = 0U; + std::vector definitions = runtime.GetFrames(); + definitions[0].signals[1].length = 0U; + runtime = DecodeDatabase(definitions); result = DbcDecoder().Decode(runtime, raw); CHECK(result.signals[0].status == SignalDecodeStatus::InvalidDefinition && result.signals[1].status == SignalDecodeStatus::InvalidDefinition, "Malformed runtime selector distinguished from payload errors"); - runtime.frames[0].signals.pop_back(); + definitions[0].signals.pop_back(); + runtime = DecodeDatabase(definitions); result = DbcDecoder().Decode(runtime, raw); CHECK(result.signals[0].status == SignalDecodeStatus::InvalidDefinition, "Missing runtime selector"); @@ -788,12 +791,12 @@ void DbcParserTest::valueDescriptions() { for (std::size_t index = 0; index < parsed.frames.size(); ++index) { CHECK(tree->GetChild(index)->GetChild(0)->GetSignal()->valueDescriptions == parsed.frames[index].signals[0].valueDescriptions && - runtime.frames[index].signals[0].valueDescriptions == + runtime.GetFrames()[index].signals[0].valueDescriptions == parsed.frames[index].signals[0].valueDescriptions, "All mappings survive both builders"); } CHECK(tree->GetChild(0)->GetChild(0)->GetSignal()->valueDescriptions == - runtime.frames[0].signals[0].valueDescriptions, + runtime.GetFrames()[0].signals[0].valueDescriptions, "Both builders preserve descriptions"); RawCanFrame frame; frame.canId = 256; @@ -830,7 +833,7 @@ void DbcParserTest::valueDescriptions() { CHECK(decoded.GetValueDescription() && *decoded.GetValueDescription() == test.description, "Unsigned boundaries"); } - CHECK(FindValueDescription(runtime.frames[0].signals[0].valueDescriptions, std::int64_t(1)) != nullptr, + CHECK(FindValueDescription(runtime.GetFrames()[0].signals[0].valueDescriptions, std::int64_t(1)) != nullptr, "Nonnegative signed lookup matches unsigned key"); frame.data.clear(); CHECK(!DbcDecoder().Decode(runtime, frame).signals[0].GetValueDescription(), "Invalid decode has no description"); diff --git a/tests/main.cpp b/tests/main.cpp index b93038d..f8ea11d 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -5,10 +5,13 @@ int RunParserTests(int argc, char **argv); int RunDecoderTests(int argc, char **argv); int RunCoverageTests(int argc, char **argv); +int RunLifetimeTests(int argc, char **argv); + int main(int argc, char **argv) { QCoreApplication application(argc, argv); const int parserResult = RunParserTests(argc, argv); const int decoderResult = RunDecoderTests(argc, argv); const int coverageResult = RunCoverageTests(argc, argv); - return parserResult | decoderResult | coverageResult; + const int lifetimeResult = RunLifetimeTests(argc, argv); + return parserResult | decoderResult | coverageResult | lifetimeResult; } diff --git a/tests/tests.pro b/tests/tests.pro index e58e53e..69b0255 100644 --- a/tests/tests.pro +++ b/tests/tests.pro @@ -8,5 +8,5 @@ CONFIG -= app_bundle include(../core/core.pri) include(parser_tests.pri) include(decoder_tests.pri) -SOURCES += main.cpp dbc_coverage_test.cpp +SOURCES += main.cpp dbc_coverage_test.cpp dbc_lifetime_test.cpp CONFIG -= debug_and_release debug_and_release_target