Node2
-
+
DbcStatementHandler
@@ -34,9 +34,9 @@
~DbcStatementHandler()
+
Handle()
-
-
-
+
+
+
diff --git a/docs/html/classDbcStatementDispatcher-members.html b/docs/html/classDbcStatementDispatcher-members.html
index 05dab39..ab82a1f 100644
--- a/docs/html/classDbcStatementDispatcher-members.html
+++ b/docs/html/classDbcStatementDispatcher-members.html
@@ -96,9 +96,9 @@ $(document).ready(function(){initNavTree('classDbcStatementDispatcher.html','');
This is the complete list of members for DbcStatementDispatcher , including all inherited members.
diff --git a/docs/html/classDbcStatementDispatcher.html b/docs/html/classDbcStatementDispatcher.html
index 00d2224..3c85e1e 100644
--- a/docs/html/classDbcStatementDispatcher.html
+++ b/docs/html/classDbcStatementDispatcher.html
@@ -101,8 +101,12 @@ $(document).ready(function(){initNavTree('classDbcStatementDispatcher.html','');
@@ -158,7 +164,11 @@ template<class Handler >
@@ -189,9 +199,9 @@ template<class Handler >
diff --git a/docs/html/classDbcStatementDispatcher.js b/docs/html/classDbcStatementDispatcher.js
index f7ab546..d1e0e02 100644
--- a/docs/html/classDbcStatementDispatcher.js
+++ b/docs/html/classDbcStatementDispatcher.js
@@ -1,4 +1,6 @@
var classDbcStatementDispatcher =
[
+ [ "DbcStatementDispatcher", "classDbcStatementDispatcher.html#a2f064359b59d8644b8a8196653d47482", null ],
+ [ "RegisterType", "classDbcStatementDispatcher.html#a2c6e9a614ed747275d43bcccc50d0b2d", null ],
[ "Dispatch", "classDbcStatementDispatcher.html#a495c2d5c7ebb8103b1987cdd87c142ed", null ]
];
\ No newline at end of file
diff --git a/docs/html/classDbcStatementHandler-members.html b/docs/html/classDbcStatementHandler-members.html
index 072b98b..c06827d 100644
--- a/docs/html/classDbcStatementHandler-members.html
+++ b/docs/html/classDbcStatementHandler-members.html
@@ -96,7 +96,7 @@ $(document).ready(function(){initNavTree('classDbcStatementHandler.html',''); in
This is the complete list of members for DbcStatementHandler , including all inherited members.
diff --git a/docs/html/classDbcStatementHandler.html b/docs/html/classDbcStatementHandler.html
index df2826e..d8bf2c1 100644
--- a/docs/html/classDbcStatementHandler.html
+++ b/docs/html/classDbcStatementHandler.html
@@ -96,6 +96,11 @@ $(document).ready(function(){initNavTree('classDbcStatementHandler.html',''); in
+
+
Interface for processing a registered DBC statement.
+ More...
+
+
#include <dbc_statement_handler.h >
@@ -106,14 +111,56 @@ $(document).ready(function(){initNavTree('classDbcStatementHandler.html',''); in
-
-virtual void Handle (const std::string &line, DbcParseContext &context) const =0
+virtual void Handle (const std::string &line, DbcParseContext &context) const =0
+ Process a trimmed statement using state belonging to this parse.
-
-
Definition at line 44 of file dbc_statement_handler.h .
-
The documentation for this class was generated from the following file:
diff --git a/docs/html/classDbcStatementHandler.js b/docs/html/classDbcStatementHandler.js
new file mode 100644
index 0000000..d918539
--- /dev/null
+++ b/docs/html/classDbcStatementHandler.js
@@ -0,0 +1,4 @@
+var classDbcStatementHandler =
+[
+ [ "Handle", "classDbcStatementHandler.html#a3de86e1e27e9bcb0fe6f1460a8ba5739", null ]
+];
\ No newline at end of file
diff --git a/docs/html/classDbcStatementHandler__inherit__graph.map b/docs/html/classDbcStatementHandler__inherit__graph.map
index d40520d..6f4e529 100644
--- a/docs/html/classDbcStatementHandler__inherit__graph.map
+++ b/docs/html/classDbcStatementHandler__inherit__graph.map
@@ -1,17 +1,19 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/html/classDbcStatementHandler__inherit__graph.md5 b/docs/html/classDbcStatementHandler__inherit__graph.md5
index e4afaae..42a56ec 100644
--- a/docs/html/classDbcStatementHandler__inherit__graph.md5
+++ b/docs/html/classDbcStatementHandler__inherit__graph.md5
@@ -1 +1 @@
-9968b812b5276c7cad7a358f5120f96a
\ No newline at end of file
+5f027bd277d1b10d4e4195710b2631a3
\ No newline at end of file
diff --git a/docs/html/classDbcStatementHandler__inherit__graph.svg b/docs/html/classDbcStatementHandler__inherit__graph.svg
index d2e54f9..64daf18 100644
--- a/docs/html/classDbcStatementHandler__inherit__graph.svg
+++ b/docs/html/classDbcStatementHandler__inherit__graph.svg
@@ -46,7 +46,7 @@
@@ -57,17 +57,17 @@ var sectionId = 'dynsection-0';
Node1
-
-
-DbcStatementHandler
-
-+
-~DbcStatementHandler()
-+
-Handle()
-
-
-
+
+
+DbcStatementHandler
+
++
+~DbcStatementHandler()
++
+Handle()
+
+
+
@@ -96,23 +96,23 @@ var sectionId = 'dynsection-0';
Node1->Node2
-
-
+
+
Node3
-
-
-DbcCommentHandler
-
-+
-Handle()
-
-
-
+
+
+DbcAttributeHandler
+
++
+Handle()
+
+
+
@@ -120,23 +120,23 @@ var sectionId = 'dynsection-0';
Node1->Node3
-
-
+
+
Node4
-
-
-DbcFrameHandler
-
-+
-Handle()
-
-
-
+
+
+DbcCommentHandler
+
++
+Handle()
+
+
+
@@ -144,23 +144,23 @@ var sectionId = 'dynsection-0';
Node1->Node4
-
-
+
+
Node5
-
-
-DbcHeaderHandler
-
-+
-Handle()
-
-
-
+
+
+DbcFrameHandler
+
++
+Handle()
+
+
+
@@ -168,23 +168,23 @@ var sectionId = 'dynsection-0';
Node1->Node5
-
-
+
+
Node6
-
-
-DbcSignalHandler
-
-+
-Handle()
-
-
-
+
+
+DbcHeaderHandler
+
++
+Handle()
+
+
+
@@ -192,24 +192,23 @@ var sectionId = 'dynsection-0';
Node1->Node6
-
-
+
+
Node7
-
-
-DbcUnsupportedMultiplexing
-Handler
-
-+
-Handle()
-
-
-
+
+
+DbcSignalHandler
+
++
+Handle()
+
+
+
@@ -217,23 +216,24 @@ var sectionId = 'dynsection-0';
Node1->Node7
-
-
+
+
Node8
-
-
-DbcValueDescriptionHandler
-
-+
-Handle()
-
-
-
+
+
+DbcUnsupportedMultiplexing
+Handler
+
++
+Handle()
+
+
+
@@ -241,8 +241,32 @@ var sectionId = 'dynsection-0';
Node1->Node8
-
-
+
+
+
+
+
+
+
+Node9
+
+
+DbcValueDescriptionHandler
+
++
+Handle()
+
+
+
+
+
+
+
+
+Node1->Node9
+
+
+
diff --git a/docs/html/classDbcStatementHandler__inherit__graph_org.svg b/docs/html/classDbcStatementHandler__inherit__graph_org.svg
index 54a5175..f5a4ec6 100644
--- a/docs/html/classDbcStatementHandler__inherit__graph_org.svg
+++ b/docs/html/classDbcStatementHandler__inherit__graph_org.svg
@@ -4,24 +4,24 @@
-
+
DbcStatementHandler
Node1
-
-
-DbcStatementHandler
-
-+
-~DbcStatementHandler()
-+
-Handle()
-
-
-
+
+
+DbcStatementHandler
+
++
+~DbcStatementHandler()
++
+Handle()
+
+
+
@@ -50,23 +50,23 @@
Node1->Node2
-
-
+
+
Node3
-
-
-DbcCommentHandler
-
-+
-Handle()
-
-
-
+
+
+DbcAttributeHandler
+
++
+Handle()
+
+
+
@@ -74,23 +74,23 @@
Node1->Node3
-
-
+
+
Node4
-
-
-DbcFrameHandler
-
-+
-Handle()
-
-
-
+
+
+DbcCommentHandler
+
++
+Handle()
+
+
+
@@ -98,23 +98,23 @@
Node1->Node4
-
-
+
+
Node5
-
-
-DbcHeaderHandler
-
-+
-Handle()
-
-
-
+
+
+DbcFrameHandler
+
++
+Handle()
+
+
+
@@ -122,23 +122,23 @@
Node1->Node5
-
-
+
+
Node6
-
-
-DbcSignalHandler
-
-+
-Handle()
-
-
-
+
+
+DbcHeaderHandler
+
++
+Handle()
+
+
+
@@ -146,24 +146,23 @@
Node1->Node6
-
-
+
+
Node7
-
-
-DbcUnsupportedMultiplexing
-Handler
-
-+
-Handle()
-
-
-
+
+
+DbcSignalHandler
+
++
+Handle()
+
+
+
@@ -171,23 +170,24 @@
Node1->Node7
-
-
+
+
Node8
-
-
-DbcValueDescriptionHandler
-
-+
-Handle()
-
-
-
+
+
+DbcUnsupportedMultiplexing
+Handler
+
++
+Handle()
+
+
+
@@ -195,8 +195,32 @@
Node1->Node8
-
-
+
+
+
+
+
+
+
+Node9
+
+
+DbcValueDescriptionHandler
+
++
+Handle()
+
+
+
+
+
+
+
+
+Node1->Node9
+
+
+
diff --git a/docs/html/classDbcTreeBuilder.html b/docs/html/classDbcTreeBuilder.html
index 9924650..8d77592 100644
--- a/docs/html/classDbcTreeBuilder.html
+++ b/docs/html/classDbcTreeBuilder.html
@@ -142,6 +142,8 @@ Public Member Functions
References DbcDatabase::frames .
+Referenced by main() .
+
The documentation for this class was generated from the following files:
diff --git a/docs/html/classDbcTreeModel-members.html b/docs/html/classDbcTreeModel-members.html
index 0e260b9..cf9d3ec 100644
--- a/docs/html/classDbcTreeModel-members.html
+++ b/docs/html/classDbcTreeModel-members.html
@@ -101,26 +101,26 @@ $(document).ready(function(){initNavTree('classDbcTreeModel.html',''); initResiz
ByteOrder enum value (defined in DbcTreeModel )DbcTreeModel
CanId enum value (defined in DbcTreeModel )DbcTreeModel
CanIdRole enum value (defined in DbcTreeModel )DbcTreeModel
- Column enum name (defined in DbcTreeModel )DbcTreeModel
- columnCount (const QModelIndex &parent=QModelIndex()) const override (defined in DbcTreeModel )DbcTreeModel
+ Column enum nameDbcTreeModel
+ columnCount (const QModelIndex &parent=QModelIndex()) const overrideDbcTreeModel
ColumnCount enum value (defined in DbcTreeModel )DbcTreeModel
Comment enum value (defined in DbcTreeModel )DbcTreeModel
CommentRole enum value (defined in DbcTreeModel )DbcTreeModel
- data (const QModelIndex &index, int role=Qt::DisplayRole) const override (defined in DbcTreeModel )DbcTreeModel
- DbcTreeModel (QObject *parent=nullptr) (defined in DbcTreeModel )DbcTreeModel explicit
+ data (const QModelIndex &index, int role=Qt::DisplayRole) const overrideDbcTreeModel
+ DbcTreeModel (QObject *parent=nullptr)DbcTreeModel explicit
ExtendedRole enum value (defined in DbcTreeModel )DbcTreeModel
- flags (const QModelIndex &index) const override (defined in DbcTreeModel )DbcTreeModel
- headerData (int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override (defined in DbcTreeModel )DbcTreeModel
- index (int row, int column, const QModelIndex &parent=QModelIndex()) const override (defined in DbcTreeModel )DbcTreeModel
+ flags (const QModelIndex &index) const overrideDbcTreeModel
+ headerData (int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const overrideDbcTreeModel
+ index (int row, int column, const QModelIndex &parent=QModelIndex()) const overrideDbcTreeModel
LittleEndianRole enum value (defined in DbcTreeModel )DbcTreeModel
Name enum value (defined in DbcTreeModel )DbcTreeModel
NodeTypeRole enum value (defined in DbcTreeModel )DbcTreeModel
- parent (const QModelIndex &child) const override (defined in DbcTreeModel )DbcTreeModel
+ parent (const QModelIndex &child) const overrideDbcTreeModel
PayloadLength enum value (defined in DbcTreeModel )DbcTreeModel
PayloadLengthRole enum value (defined in DbcTreeModel )DbcTreeModel
- Role enum name (defined in DbcTreeModel )DbcTreeModel
- rowCount (const QModelIndex &parent=QModelIndex()) const override (defined in DbcTreeModel )DbcTreeModel
- SetTree (std::unique_ptr< TreeNode > root) (defined in DbcTreeModel )DbcTreeModel
+ Role enum nameDbcTreeModel
+ rowCount (const QModelIndex &parent=QModelIndex()) const overrideDbcTreeModel
+ SetTree (std::unique_ptr< TreeNode > root)DbcTreeModel
Signed enum value (defined in DbcTreeModel )DbcTreeModel
SignedRole enum value (defined in DbcTreeModel )DbcTreeModel
StartBit enum value (defined in DbcTreeModel )DbcTreeModel
diff --git a/docs/html/classDbcTreeModel.html b/docs/html/classDbcTreeModel.html
index 1145b35..d413220 100644
--- a/docs/html/classDbcTreeModel.html
+++ b/docs/html/classDbcTreeModel.html
@@ -109,7 +109,7 @@ $(document).ready(function(){initNavTree('classDbcTreeModel.html',''); initResiz
-enum Column {
+enum Column {
Name
, CanId
, PayloadLength
@@ -124,8 +124,9 @@ Public Types
, ColumnCount
}
+ Display columns for frame and signal metadata. More...
-enum Role {
+enum Role {
NodeTypeRole = Qt::UserRole + 1
, CanIdRole
, PayloadLengthRole
@@ -141,31 +142,41 @@ Public Types
, ExtendedRole
}
+ Typed metadata roles in addition to Qt display roles. More...
- DbcTreeModel (QObject *parent=nullptr)
+ DbcTreeModel (QObject *parent =nullptr)
+ Create an empty read-only model.
void SetTree (std::unique_ptr< TreeNode > root)
+ Replace the tree and invalidate indexes; reject roots with a parent or non-root type.
-QModelIndex index (int row, int column, const QModelIndex &parent=QModelIndex()) const override
+QModelIndex index (int row, int column, const QModelIndex &parent =QModelIndex()) const override
+ Return a child index; only column zero can have children.
QModelIndex parent (const QModelIndex &child) const override
+ Return the parent in column zero, or an invalid index for frames.
-int rowCount (const QModelIndex &parent=QModelIndex()) const override
+int rowCount (const QModelIndex &parent =QModelIndex()) const override
+ Return the child count, capped at the Qt integer limit.
-int columnCount (const QModelIndex &parent=QModelIndex()) const override
+int columnCount (const QModelIndex &parent =QModelIndex()) const override
+ Return the fixed metadata column count for this model.
-QVariant data (const QModelIndex &index, int role=Qt::DisplayRole) const override
+QVariant data (const QModelIndex &index , int role=Qt::DisplayRole) const override
+ Return display text or typed metadata for an index.
QVariant headerData (int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
+ Return horizontal display column titles.
-Qt::ItemFlags flags (const QModelIndex &index) const override
+Qt::ItemFlags flags (const QModelIndex &index ) const override
+ Allow selecting and enabling valid indexes without editing.
-Read-only model. Owns an immutable tree; all indexes expire on SetTree(). Use QPersistentModelIndex to observe reset invalidation. Call on the model thread.
+
Read-only model. Owns an immutable tree; all indexes expire on SetTree() . Use QPersistentModelIndex to observe reset invalidation. Call on the model thread.
Definition at line 11 of file dbc_tree_model.h .
@@ -176,12 +187,14 @@ Public Member Functions
@@ -192,12 +205,14 @@ Public Member Functions
@@ -226,6 +241,8 @@ Public Member Functions
@@ -247,6 +264,8 @@ Public Member Functions
+
Replace the tree and invalidate indexes; reject roots with a parent or non-root type.
+
Definition at line 27 of file dbc_tree_model.cpp .
@@ -291,8 +310,12 @@ Public Member Functions
@@ -319,8 +342,12 @@ Public Member Functions
@@ -347,8 +374,12 @@ Public Member Functions
@@ -375,6 +406,8 @@ Public Member Functions
+
Return the fixed metadata column count for this model.
+
Definition at line 70 of file dbc_tree_model.cpp .
@@ -413,8 +446,12 @@ Public Member Functions
+
Return display text or typed metadata for an index.
+
Definition at line 74 of file dbc_tree_model.cpp .
+
References FrameInfo::canId , FrameInfo::comment , SignalInfo::comment , FrameInfo::dlc , TreeNode::GetFrame() , TreeNode::GetName() , TreeNode::GetSignal() , TreeNode::GetType() , FrameInfo::isExtended , SignalInfo::isLittleEndian , SignalInfo::isSigned , SignalInfo::length , SignalInfo::startBit , SignalInfo::unit , and SignalInfo::valueDescriptions .
+
@@ -457,6 +494,8 @@ Public Member Functions
@@ -485,6 +524,8 @@ Public Member Functions
+
Allow selecting and enabling valid indexes without editing.
+
Definition at line 145 of file dbc_tree_model.cpp .
diff --git a/docs/html/classDbcTreeModel.js b/docs/html/classDbcTreeModel.js
new file mode 100644
index 0000000..e997d67
--- /dev/null
+++ b/docs/html/classDbcTreeModel.js
@@ -0,0 +1,37 @@
+var classDbcTreeModel =
+[
+ [ "Column", "classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069ae", [
+ [ "Name", "classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069aea656b55f10472395261871ff7ef3f4484", null ],
+ [ "CanId", "classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069aeaa74a27fd4ea0e2d561c6ba9b15640010", null ],
+ [ "PayloadLength", "classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069aea8bc7de06cffddca5470da004741ed939", null ],
+ [ "StartBit", "classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069aeaa87659982bb22d7598c49cc08cd36c65", null ],
+ [ "BitLength", "classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069aea657c7487a591debd704e4f7e4536b207", null ],
+ [ "ByteOrder", "classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069aea391e0095b1fac0d05fde0d5cb5edda85", null ],
+ [ "Signed", "classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069aea5baf88846401000c49679f46e619ef87", null ],
+ [ "Unit", "classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069aeaa154ab92b4d4ef65526238428ae3cace", null ],
+ [ "Comment", "classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069aea01cbc280578dad3fea144b98755b7ef3", null ],
+ [ "ColumnCount", "classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069aea58500e460c83ab951d9271b3b795f234", null ]
+ ] ],
+ [ "Role", "classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfd", [
+ [ "NodeTypeRole", "classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfdabe2c2768f230f994534963c6d32230d7", null ],
+ [ "CanIdRole", "classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfda66d77c4244f1fcbae2ff66aff2be85d4", null ],
+ [ "PayloadLengthRole", "classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfdaf8574caf8d0986f7d6d6d7923a7bdaa0", null ],
+ [ "StartBitRole", "classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfdae702dc1611c58e76e36ee280091be1d8", null ],
+ [ "BitLengthRole", "classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfda716858f9cb0b60a665214362afd210ca", null ],
+ [ "LittleEndianRole", "classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfda9df090ff74d5110d75df22a0b2e507e8", null ],
+ [ "SignedRole", "classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfdad1c30e9d3e9ade5edbc5262a2131007b", null ],
+ [ "UnitRole", "classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfda55cc6538817898e455ae2cbd4cd7e755", null ],
+ [ "CommentRole", "classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfdaee6045bcb658e9feefff87ca7d9e57ff", null ],
+ [ "ValueDescriptionsRole", "classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfda8a5d5985c970c7c04290a7b0f3aa05f0", null ],
+ [ "ExtendedRole", "classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfda155fbc1aa36cd7f15711f4461720fa1d", null ]
+ ] ],
+ [ "DbcTreeModel", "classDbcTreeModel.html#a4f7214b727d812885bf077352ec9ece1", null ],
+ [ "SetTree", "classDbcTreeModel.html#a8cb5a81d456cdead42b75fd3462ee00a", null ],
+ [ "index", "classDbcTreeModel.html#a8caeb5ec6141eb3e446e48df3c70b3ad", null ],
+ [ "parent", "classDbcTreeModel.html#ae40bb8b8a26d205f178c6dd1134ff4b3", null ],
+ [ "rowCount", "classDbcTreeModel.html#a30bed0d65342917c19d9183da55af452", null ],
+ [ "columnCount", "classDbcTreeModel.html#a397f885e7fd45c387825b4357b875c10", null ],
+ [ "data", "classDbcTreeModel.html#aca81d05c81cc48c1185fc36659e96e5b", null ],
+ [ "headerData", "classDbcTreeModel.html#aad5834e8edb00808cbfa498ea8c63fe9", null ],
+ [ "flags", "classDbcTreeModel.html#a8f7842a79144bdb24fa9c5fbdcd37295", null ]
+];
\ No newline at end of file
diff --git a/docs/html/classDbcUnsupportedMultiplexingHandler-members.html b/docs/html/classDbcUnsupportedMultiplexingHandler-members.html
index 17cc679..582a168 100644
--- a/docs/html/classDbcUnsupportedMultiplexingHandler-members.html
+++ b/docs/html/classDbcUnsupportedMultiplexingHandler-members.html
@@ -96,7 +96,7 @@ $(document).ready(function(){initNavTree('classDbcUnsupportedMultiplexingHandler
This is the complete list of members for DbcUnsupportedMultiplexingHandler , including all inherited members.
diff --git a/docs/html/classDbcUnsupportedMultiplexingHandler.html b/docs/html/classDbcUnsupportedMultiplexingHandler.html
index 55053a8..7d65c5f 100644
--- a/docs/html/classDbcUnsupportedMultiplexingHandler.html
+++ b/docs/html/classDbcUnsupportedMultiplexingHandler.html
@@ -96,6 +96,11 @@ $(document).ready(function(){initNavTree('classDbcUnsupportedMultiplexingHandler
+
+
Reject unsupported extended multiplexing statements.
+ More...
+
+
#include <dbc_statement_handler.h >
@@ -107,11 +112,13 @@ $(document).ready(function(){initNavTree('classDbcUnsupportedMultiplexingHandler
void Handle (const std::string &line, DbcParseContext &context) const override
+
Process a trimmed statement using state belonging to this parse.
-
-
Definition at line 79 of file dbc_statement_handler.h .
+
Reject unsupported extended multiplexing statements.
+
+
Definition at line 118 of file dbc_statement_handler.h .
◆ Handle()
@@ -147,9 +154,11 @@ Public Member Functions
diff --git a/docs/html/classDbcUnsupportedMultiplexingHandler.js b/docs/html/classDbcUnsupportedMultiplexingHandler.js
new file mode 100644
index 0000000..c276078
--- /dev/null
+++ b/docs/html/classDbcUnsupportedMultiplexingHandler.js
@@ -0,0 +1,4 @@
+var classDbcUnsupportedMultiplexingHandler =
+[
+ [ "Handle", "classDbcUnsupportedMultiplexingHandler.html#a9853fd67465f92ef587792986ea179ac", null ]
+];
\ No newline at end of file
diff --git a/docs/html/classDbcUnsupportedMultiplexingHandler__inherit__graph.map b/docs/html/classDbcUnsupportedMultiplexingHandler__inherit__graph.map
index f041dc7..f962729 100644
--- a/docs/html/classDbcUnsupportedMultiplexingHandler__inherit__graph.map
+++ b/docs/html/classDbcUnsupportedMultiplexingHandler__inherit__graph.map
@@ -1,5 +1,5 @@
-
-
+
+
diff --git a/docs/html/classDbcUnsupportedMultiplexingHandler__inherit__graph.md5 b/docs/html/classDbcUnsupportedMultiplexingHandler__inherit__graph.md5
index 3fb8761..cf87320 100644
--- a/docs/html/classDbcUnsupportedMultiplexingHandler__inherit__graph.md5
+++ b/docs/html/classDbcUnsupportedMultiplexingHandler__inherit__graph.md5
@@ -1 +1 @@
-1ace6705ea51cc639d0122e87818555f
\ No newline at end of file
+1f2e8b51bbe924941f117d0a9d6518af
\ No newline at end of file
diff --git a/docs/html/classDbcUnsupportedMultiplexingHandler__inherit__graph.svg b/docs/html/classDbcUnsupportedMultiplexingHandler__inherit__graph.svg
index 19a19bb..e175c96 100644
--- a/docs/html/classDbcUnsupportedMultiplexingHandler__inherit__graph.svg
+++ b/docs/html/classDbcUnsupportedMultiplexingHandler__inherit__graph.svg
@@ -21,7 +21,7 @@
Node1
-
+
DbcUnsupportedMultiplexing
Handler
@@ -37,7 +37,7 @@
Node2
-
+
DbcStatementHandler
@@ -45,9 +45,9 @@
~DbcStatementHandler()
+
Handle()
-
-
-
+
+
+
diff --git a/docs/html/classDbcUnsupportedMultiplexingHandler__inherit__graph_org.svg b/docs/html/classDbcUnsupportedMultiplexingHandler__inherit__graph_org.svg
index 80013e4..55e2803 100644
--- a/docs/html/classDbcUnsupportedMultiplexingHandler__inherit__graph_org.svg
+++ b/docs/html/classDbcUnsupportedMultiplexingHandler__inherit__graph_org.svg
@@ -11,7 +11,7 @@
Node1
-
+
DbcUnsupportedMultiplexing
Handler
@@ -27,7 +27,7 @@
Node2
-
+
DbcStatementHandler
@@ -35,9 +35,9 @@
~DbcStatementHandler()
+
Handle()
-
-
-
+
+
+
diff --git a/docs/html/classDbcValueDescriptionHandler-members.html b/docs/html/classDbcValueDescriptionHandler-members.html
index 5593ca2..8b770dc 100644
--- a/docs/html/classDbcValueDescriptionHandler-members.html
+++ b/docs/html/classDbcValueDescriptionHandler-members.html
@@ -96,7 +96,7 @@ $(document).ready(function(){initNavTree('classDbcValueDescriptionHandler.html',
This is the complete list of members for DbcValueDescriptionHandler , including all inherited members.
diff --git a/docs/html/classDbcValueDescriptionHandler.html b/docs/html/classDbcValueDescriptionHandler.html
index d9168bb..9d9e218 100644
--- a/docs/html/classDbcValueDescriptionHandler.html
+++ b/docs/html/classDbcValueDescriptionHandler.html
@@ -96,6 +96,11 @@ $(document).ready(function(){initNavTree('classDbcValueDescriptionHandler.html',
+
+
Defer raw value descriptions for target resolution.
+ More...
+
+
#include <dbc_statement_handler.h >
@@ -107,11 +112,13 @@ $(document).ready(function(){initNavTree('classDbcValueDescriptionHandler.html',
void Handle (const std::string &line, DbcParseContext &context) const override
+
Process a trimmed statement using state belonging to this parse.
-
-
Definition at line 74 of file dbc_statement_handler.h .
+
Defer raw value descriptions for target resolution.
+
+
Definition at line 112 of file dbc_statement_handler.h .
◆ Handle()
@@ -147,9 +154,13 @@ Public Member Functions
diff --git a/docs/html/classDbcValueDescriptionHandler.js b/docs/html/classDbcValueDescriptionHandler.js
new file mode 100644
index 0000000..ae407f8
--- /dev/null
+++ b/docs/html/classDbcValueDescriptionHandler.js
@@ -0,0 +1,4 @@
+var classDbcValueDescriptionHandler =
+[
+ [ "Handle", "classDbcValueDescriptionHandler.html#a653e13364f396b54244edc2c0fdd831a", null ]
+];
\ No newline at end of file
diff --git a/docs/html/classDbcValueDescriptionHandler__inherit__graph.map b/docs/html/classDbcValueDescriptionHandler__inherit__graph.map
index 1ac2738..372c9cd 100644
--- a/docs/html/classDbcValueDescriptionHandler__inherit__graph.map
+++ b/docs/html/classDbcValueDescriptionHandler__inherit__graph.map
@@ -1,5 +1,5 @@
-
-
+
+
diff --git a/docs/html/classDbcValueDescriptionHandler__inherit__graph.md5 b/docs/html/classDbcValueDescriptionHandler__inherit__graph.md5
index 70105ba..37d143f 100644
--- a/docs/html/classDbcValueDescriptionHandler__inherit__graph.md5
+++ b/docs/html/classDbcValueDescriptionHandler__inherit__graph.md5
@@ -1 +1 @@
-4e812f2e61b60e6fd25b2da8062e2440
\ No newline at end of file
+8f2173a95b2682d924bc583343a1615c
\ No newline at end of file
diff --git a/docs/html/classDbcValueDescriptionHandler__inherit__graph.svg b/docs/html/classDbcValueDescriptionHandler__inherit__graph.svg
index c479d6f..99f84a7 100644
--- a/docs/html/classDbcValueDescriptionHandler__inherit__graph.svg
+++ b/docs/html/classDbcValueDescriptionHandler__inherit__graph.svg
@@ -21,7 +21,7 @@
Node1
-
+
DbcValueDescriptionHandler
@@ -36,7 +36,7 @@
Node2
-
+
DbcStatementHandler
@@ -44,9 +44,9 @@
~DbcStatementHandler()
+
Handle()
-
-
-
+
+
+
diff --git a/docs/html/classDbcValueDescriptionHandler__inherit__graph_org.svg b/docs/html/classDbcValueDescriptionHandler__inherit__graph_org.svg
index f7bcebc..9ed2cf3 100644
--- a/docs/html/classDbcValueDescriptionHandler__inherit__graph_org.svg
+++ b/docs/html/classDbcValueDescriptionHandler__inherit__graph_org.svg
@@ -11,7 +11,7 @@
Node1
-
+
DbcValueDescriptionHandler
@@ -26,7 +26,7 @@
Node2
-
+
DbcStatementHandler
@@ -34,9 +34,9 @@
~DbcStatementHandler()
+
Handle()
-
-
-
+
+
+
diff --git a/docs/html/classDecodeDatabase-members.html b/docs/html/classDecodeDatabase-members.html
index 1ae36f9..6a01ce6 100644
--- a/docs/html/classDecodeDatabase-members.html
+++ b/docs/html/classDecodeDatabase-members.html
@@ -99,8 +99,9 @@ $(document).ready(function(){initNavTree('classDecodeDatabase.html',''); initRes
DecodeDatabase ()=default (defined in DecodeDatabase )DecodeDatabase
DecodeDatabase (const std::vector< DecodeFrame > &frames)DecodeDatabase explicit
FindFrame (const FrameKey &key) constDecodeDatabase
- FindSignal (const SignalKey &key) const (defined in DecodeDatabase )DecodeDatabase
- GetFrames () constDecodeDatabase
+ FindFrameByPgn (std::uint32_t pgn) constDecodeDatabase
+ FindSignal (const SignalKey &key) constDecodeDatabase
+ GetFrames () constDecodeDatabase
diff --git a/docs/html/classDecodeDatabase.html b/docs/html/classDecodeDatabase.html
index ad643ce..d306822 100644
--- a/docs/html/classDecodeDatabase.html
+++ b/docs/html/classDecodeDatabase.html
@@ -111,13 +111,16 @@ Public Member Functions
std::shared_ptr< const DecodeFrame > FindFrame (const FrameKey &key) const
+PgnLookupResult FindFrameByPgn (std::uint32_t pgn) const
+
std::shared_ptr< const DecodeSignal > FindSignal (const SignalKey &key) const
+ Return an owning signal handle, or an empty handle for a missing key.
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 .
+
Definition at line 101 of file decode_database.h .
◆ DecodeDatabase()
@@ -149,7 +152,7 @@ Public Member Functions
-Definition at line 101 of file decode_database.cpp .
+Definition at line 111 of file decode_database.cpp .
@@ -170,7 +173,9 @@ Public Member Functions
@@ -191,9 +196,32 @@ Public Member Functions
+
+
+◆ FindFrameByPgn()
+
+
+
+
+
+ PgnLookupResult DecodeDatabase::FindFrameByPgn
+ (
+ std::uint32_t
+ pgn )
+ const
+
+
+
@@ -213,7 +241,11 @@ Public Member Functions
diff --git a/docs/html/classDecodeDatabase.js b/docs/html/classDecodeDatabase.js
index 37b8471..98291ef 100644
--- a/docs/html/classDecodeDatabase.js
+++ b/docs/html/classDecodeDatabase.js
@@ -2,5 +2,7 @@ var classDecodeDatabase =
[
[ "DecodeDatabase", "classDecodeDatabase.html#a51a44cf7c3f23c98ec8781afe0097c0c", null ],
[ "GetFrames", "classDecodeDatabase.html#aa034c1510984a85f60ad6c0bd744d6e8", null ],
- [ "FindFrame", "classDecodeDatabase.html#a780d6e747a48b10a5eb0ab85448d2970", null ]
+ [ "FindFrame", "classDecodeDatabase.html#a780d6e747a48b10a5eb0ab85448d2970", null ],
+ [ "FindFrameByPgn", "classDecodeDatabase.html#aa96b62b4f3fff68ab651674760f60d6d", null ],
+ [ "FindSignal", "classDecodeDatabase.html#a0af5b15b9953a4f6551c27ee9ae8b514", null ]
];
\ No newline at end of file
diff --git a/docs/html/classTreeNode-members.html b/docs/html/classTreeNode-members.html
index 1aca818..fb09e64 100644
--- a/docs/html/classTreeNode-members.html
+++ b/docs/html/classTreeNode-members.html
@@ -96,15 +96,17 @@ $(document).ready(function(){initNavTree('classTreeNode.html',''); initResizable
This is the complete list of members for TreeNode , including all inherited members.
- AddChild (std::unique_ptr< TreeNode > child)TreeNode
+ AddChild (std::unique_ptr< TreeNode > &&child)TreeNode
GetChild (std::size_t index) constTreeNode
GetChild (std::size_t index)TreeNode
GetChildCount () constTreeNode
GetFrame () constTreeNode
- GetName () constTreeNode
- GetParent () constTreeNode
- GetRow () constTreeNode
- GetSignal () constTreeNode
+ GetFrameKey () constTreeNode
+ GetName () constTreeNode
+ GetParent () constTreeNode
+ GetRow () constTreeNode
+ GetSignal () constTreeNode
+ GetSignalKey () constTreeNode
GetType () constTreeNode
operator= (const TreeNode &)=delete (defined in TreeNode )TreeNode
operator= (TreeNode &&)=delete (defined in TreeNode )TreeNode
diff --git a/docs/html/classTreeNode.html b/docs/html/classTreeNode.html
index 8c47c7b..2265ceb 100644
--- a/docs/html/classTreeNode.html
+++ b/docs/html/classTreeNode.html
@@ -125,13 +125,17 @@ Public Member Functions
TreeNode & operator= (TreeNode &&)=delete
-void AddChild (std::unique_ptr< TreeNode > child)
- Add child node.
-
+void AddChild (std::unique_ptr< TreeNode > &&child)
+ Add child node.
+
const TreeNode * GetParent () const
std::size_t GetRow () const
+std::optional< FrameKey > GetFrameKey () const
+
+std::optional< SignalKey > GetSignalKey () const
+
std::size_t GetChildCount () const
Get child count.
@@ -157,7 +161,7 @@ Public Member Functions
Tree node for later use in model/view or other hierarchy consumers.
-
Definition at line 35 of file tree_node.h .
+
Definition at line 37 of file tree_node.h .
◆ TreeNode() [1/3]
@@ -176,7 +180,7 @@ Public Member Functions
Create root node.
-Definition at line 14 of file tree_node.cpp .
+Definition at line 15 of file tree_node.cpp .
@@ -212,7 +216,7 @@ Public Member Functions
-Definition at line 18 of file tree_node.cpp .
+Definition at line 19 of file tree_node.cpp .
@@ -248,13 +252,13 @@ Public Member Functions
-Definition at line 22 of file tree_node.cpp .
+Definition at line 23 of file tree_node.cpp .
-
-◆ AddChild()
+
+◆ AddChild()
@@ -262,7 +266,7 @@ Public Member Functions
void TreeNode::AddChild
(
- std::unique_ptr< TreeNode >
+ std::unique_ptr< TreeNode > &&
child )
@@ -272,12 +276,18 @@ Public Member Functions
Add child node.
Parameters
- child Child node to add.
+ child Child node to add. A null child is ignored. Existing children keep their addresses and rows. Ownership must be exclusive; attached nodes cannot be reparented.
+
+
+
+
Exceptions
+
+ std::invalid_argument for self/ancestor insertion or an attached child. Rejected ownership remains with the caller.
-
Definition at line 26 of file tree_node.cpp .
+
Definition at line 27 of file tree_node.cpp .
@@ -297,7 +307,9 @@ Public Member Functions
@@ -317,7 +329,55 @@ Public Member Functions
+
+
+◆ GetFrameKey()
+
+
+
+
+
+ std::optional< FrameKey > TreeNode::GetFrameKey
+ (
+ )
+ const
+
+
+
+
+
+◆ GetSignalKey()
+
+
+
+
+
+ std::optional< SignalKey > TreeNode::GetSignalKey
+ (
+ )
+ const
+
+
+
+
Signal identity (owning frame key and name); empty for other/detached nodes.
+
+
Definition at line 91 of file tree_node.cpp .
+
+
References GetFrameKey() .
@@ -339,7 +399,9 @@ Public Member Functions
Get child count.
Returns Number of children.
-Definition at line 34 of file tree_node.cpp .
+Definition at line 41 of file tree_node.cpp .
+
+Referenced by DbcTreeModel::rowCount() .
@@ -368,7 +430,9 @@ Public Member Functions
Returns Child pointer or nullptr if index is invalid.
-Definition at line 38 of file tree_node.cpp .
+Definition at line 45 of file tree_node.cpp .
+
+Referenced by DbcTreeModel::index() .
@@ -397,7 +461,7 @@ Public Member Functions
Returns Child pointer or nullptr if index is invalid.
-Definition at line 45 of file tree_node.cpp .
+Definition at line 52 of file tree_node.cpp .
@@ -419,7 +483,9 @@ Public Member Functions
Get node type.
Returns Node type.
-Definition at line 52 of file tree_node.cpp .
+Definition at line 59 of file tree_node.cpp .
+
+Referenced by DbcTreeModel::data() , and GetFrameKey() .
@@ -441,7 +507,9 @@ Public Member Functions
Get display name.
Returns Node name.
-Definition at line 56 of file tree_node.cpp .
+Definition at line 63 of file tree_node.cpp .
+
+Referenced by DbcTreeModel::data() .
@@ -463,7 +531,9 @@ Public Member Functions
Get frame payload if node is frame.
Returns Pointer to frame info or nullptr.
-Definition at line 60 of file tree_node.cpp .
+Definition at line 67 of file tree_node.cpp .
+
+Referenced by DbcTreeModel::data() .
@@ -485,7 +555,9 @@ Public Member Functions
Get signal payload if node is signal.
Returns Pointer to signal info or nullptr.
-Definition at line 64 of file tree_node.cpp .
+Definition at line 71 of file tree_node.cpp .
+
+Referenced by DbcTreeModel::data() .
diff --git a/docs/html/classTreeNode.js b/docs/html/classTreeNode.js
index e8df1cf..3dd1ca9 100644
--- a/docs/html/classTreeNode.js
+++ b/docs/html/classTreeNode.js
@@ -3,9 +3,11 @@ var classTreeNode =
[ "TreeNode", "classTreeNode.html#a984a98d5ccf7ef1f5a18094c6821f35d", null ],
[ "TreeNode", "classTreeNode.html#a8e38dd591d8801d7ee3a7dbad90c67fc", null ],
[ "TreeNode", "classTreeNode.html#ab9f00f5253d56461bb2d420fd639c5ae", null ],
- [ "AddChild", "classTreeNode.html#a6161f2ebb92184eab4215d121870e788", null ],
+ [ "AddChild", "classTreeNode.html#af87331684d4b40240aec75e3286921d3", null ],
[ "GetParent", "classTreeNode.html#aa48fbc17903eb8cfa40353e29f853c6f", null ],
[ "GetRow", "classTreeNode.html#ad501f97eeec7f7d3353bfae838fbb6a8", null ],
+ [ "GetFrameKey", "classTreeNode.html#af4e6e916c48c024a3dfeadac8174b527", null ],
+ [ "GetSignalKey", "classTreeNode.html#a1eb94f7b6e7962c9d867a120772dfe6e", null ],
[ "GetChildCount", "classTreeNode.html#abdd82460187dca8d3e5d66f5d5c529ea", null ],
[ "GetChild", "classTreeNode.html#a4727ff801a2d1b9323c5ae50a35457a6", null ],
[ "GetChild", "classTreeNode.html#a81047bd7d2a4cc96b9ef5e20d0d63b5f", null ],
diff --git a/docs/html/classTypeFactory-members.html b/docs/html/classTypeFactory-members.html
index d55762f..643f13a 100644
--- a/docs/html/classTypeFactory-members.html
+++ b/docs/html/classTypeFactory-members.html
@@ -96,12 +96,12 @@ $(document).ready(function(){initNavTree('classTypeFactory.html',''); initResiza
This is the complete list of members for TypeFactory< ClassId, BaseClass, Args > , including all inherited members.
- BasePtr typedef (defined in TypeFactory< ClassId, BaseClass, Args > )TypeFactory< ClassId, BaseClass, Args >
- classes (defined in TypeFactory< ClassId, BaseClass, Args > )TypeFactory< ClassId, BaseClass, Args > protected
+ BasePtr typedefTypeFactory< ClassId, BaseClass, Args >
+ classes TypeFactory< ClassId, BaseClass, Args > protected
contains (const ClassId &id) constTypeFactory< ClassId, BaseClass, Args > inline
create (const ClassId &id, Args... args) constTypeFactory< ClassId, BaseClass, Args > inline
creator (const ClassId &id) constTypeFactory< ClassId, BaseClass, Args > inline
- CreatorFn typedef (defined in TypeFactory< ClassId, BaseClass, Args > )TypeFactory< ClassId, BaseClass, Args >
+ CreatorFn typedefTypeFactory< ClassId, BaseClass, Args >
registerType (const ClassId &id)TypeFactory< ClassId, BaseClass, Args > inline
TypeFactory ()=default (defined in TypeFactory< ClassId, BaseClass, Args > )TypeFactory< ClassId, BaseClass, Args >
diff --git a/docs/html/classTypeFactory.html b/docs/html/classTypeFactory.html
index 1d661ea..06b1eb6 100644
--- a/docs/html/classTypeFactory.html
+++ b/docs/html/classTypeFactory.html
@@ -114,8 +114,10 @@ $(document).ready(function(){initNavTree('classTypeFactory.html',''); initResiza
using BasePtr = std::shared_ptr< BaseClass >
+ Shared ownership handle returned for created instances.
-using CreatorFn = BasePtr(*)(Args...)
+using CreatorFn = BasePtr (*)(Args...)
+ Registered creator function signature.
void registerType (const ClassId &id)
Registers a Derived type under the given id.
-CreatorFn creator (const ClassId &id) const
+CreatorFn creator (const ClassId &id) const
Returns creator function for the given id.
-BasePtr create (const ClassId &id, Args... args) const
+BasePtr create (const ClassId &id, Args... args) const
Creates an instance for the given id using provided arguments.
bool contains (const ClassId &id) const
@@ -136,7 +138,8 @@ Public Member Functions
-std::unordered_map< ClassId, CreatorFn > classes
+std::unordered_map< ClassId, CreatorFn > classes
+ Registered creators; accessible to derived factories.
@@ -150,9 +153,9 @@ class TypeFactory< ClassId, BaseClass, Args >Registry-based facto
Template Parameters
- ClassId -Unique class identifier type (e.g. std::string, int, enum).
- BaseClass -Base type for all created objects.
- Arg - Constructor arguments forwarded to registered derived types (by value).
+ ClassId Unique class identifier type (e.g. std::string, int, enum).
+ BaseClass Base type for all created objects.
+ Args Constructor arguments forwarded to registered derived types (by value).
@@ -185,9 +188,9 @@ class TypeFactory< ClassId, BaseClass, Args >Registry-based facto
(void)a->get();
(void)b->get();
Registry-based factory for creating objects by runtime identifier.
-BasePtr create(const ClassId &id, Args... args) const
Creates an instance for the given id using provided arguments.
-void registerType(const ClassId &id)
Registers a Derived type under the given id.
-CreatorFn creator(const ClassId &id) const
Returns creator function for the given id.
+BasePtr create(const ClassId &id, Args... args) const
Creates an instance for the given id using provided arguments.
+void registerType(const ClassId &id)
Registers a Derived type under the given id.
+CreatorFn creator(const ClassId &id) const
Returns creator function for the given id.
Definition at line 59 of file typefactory.h .
@@ -205,7 +208,9 @@ template<class ClassId , class BaseClass , class... Args>
-
Definition at line 61 of file typefactory.h .
+
Shared ownership handle returned for created instances.
+
+
Definition at line 62 of file typefactory.h .
@@ -218,12 +223,14 @@ template<class ClassId , class BaseClass , class... Args>
template<class ClassId , class BaseClass , class... Args>
- using TypeFactory < ClassId, BaseClass, Args >::CreatorFn = BasePtr (*)(Args...)
+ using TypeFactory < ClassId, BaseClass, Args >::CreatorFn = BasePtr (*)(Args...)
@@ -263,7 +270,11 @@ template<class Derived >
Re-registering the same id overwrites the previous entry ("last wins").
-Definition at line 76 of file typefactory.h .
+Definition at line 78 of file typefactory.h .
+
+References TypeFactory< ClassId, BaseClass, Args >::classes .
+
+Referenced by DbcStatementDispatcher::RegisterType() .
@@ -279,7 +290,7 @@ template<class ClassId , class BaseClass , class... Args>
- CreatorFn TypeFactory < ClassId, BaseClass, Args >::creator
+ CreatorFn TypeFactory < ClassId, BaseClass, Args >::creator
(
const ClassId &
id )
@@ -301,9 +312,11 @@ template<class ClassId , class BaseClass , class... Args>
-Definition at line 89 of file typefactory.h .
+Definition at line 91 of file typefactory.h .
-Referenced by TypeFactory< ClassId, BaseClass, Args >::create() .
+References TypeFactory< ClassId, BaseClass, Args >::classes .
+
+Referenced by TypeFactory< ClassId, BaseClass, Args >::create() .
@@ -319,7 +332,7 @@ template<class ClassId , class BaseClass , class... Args>
- BasePtr TypeFactory < ClassId, BaseClass, Args >::create
+ BasePtr TypeFactory < ClassId, BaseClass, Args >::create
(
const ClassId &
id ,
@@ -351,9 +364,11 @@ template<class ClassId , class BaseClass , class... Args>
-Definition at line 97 of file typefactory.h .
+Definition at line 99 of file typefactory.h .
-References TypeFactory< ClassId, BaseClass, Args >::creator() .
+References TypeFactory< ClassId, BaseClass, Args >::creator() .
+
+Referenced by DbcStatementDispatcher::RegisterType() .
@@ -385,7 +400,9 @@ template<class ClassId , class BaseClass , class... Args>
Checks whether an id is registered.
-Definition at line 104 of file typefactory.h .
+Definition at line 106 of file typefactory.h .
+
+References TypeFactory< ClassId, BaseClass, Args >::classes .
@@ -402,7 +419,7 @@ template<class ClassId , class BaseClass , class... Args>
- std::unordered_map<ClassId, CreatorFn> TypeFactory < ClassId, BaseClass, Args >::classes
+ std::unordered_map<ClassId, CreatorFn > TypeFactory < ClassId, BaseClass, Args >::classes
@@ -412,7 +429,11 @@ template<class ClassId , class BaseClass , class... Args>
diff --git a/docs/html/classTypeFactory.js b/docs/html/classTypeFactory.js
index 7c6b089..81c3e3f 100644
--- a/docs/html/classTypeFactory.js
+++ b/docs/html/classTypeFactory.js
@@ -1,7 +1,10 @@
var classTypeFactory =
[
+ [ "BasePtr", "classTypeFactory.html#a33b404da3e19ea7e1245b8a4975721bf", null ],
+ [ "CreatorFn", "classTypeFactory.html#a650022aac1e2f30af5bc554a5663939f", null ],
[ "registerType", "classTypeFactory.html#ad6d85795285ee21193ac03e1b24762d3", null ],
[ "creator", "classTypeFactory.html#ad82f537569ece3d3a4a376523fa94473", null ],
[ "create", "classTypeFactory.html#a3f43b03d6e3a0fd503fdec01ecf62e9f", null ],
- [ "contains", "classTypeFactory.html#a1a119ad2956abe146213c6ca124d8dd4", null ]
+ [ "contains", "classTypeFactory.html#a1a119ad2956abe146213c6ca124d8dd4", null ],
+ [ "classes", "classTypeFactory.html#a5f119fe61c1cb9f4725ce746e4a047b3", null ]
];
\ No newline at end of file
diff --git a/docs/html/classes.html b/docs/html/classes.html
index a397671..67735e7 100644
--- a/docs/html/classes.html
+++ b/docs/html/classes.html
@@ -93,27 +93,30 @@ $(document).ready(function(){initNavTree('classes.html',''); initResizable(); })
-
+
diff --git a/docs/html/dbc__attributes_8cpp_source.html b/docs/html/dbc__attributes_8cpp_source.html
new file mode 100644
index 0000000..251e450
--- /dev/null
+++ b/docs/html/dbc__attributes_8cpp_source.html
@@ -0,0 +1,479 @@
+
+
+
+
+
+
+
+
DBC Framework: dbc_attributes.cpp Source File
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DBC Framework
+
+ DBC parsing and CAN signal decoding framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+
+
+
+
+
2 #include "dbc_statement_handler.h"
+
+
+
+
+
+
+
+
+
+
+
+
14 std::vector<Token> Tokenize(
const std::string &text) {
+
15 std::vector<Token> tokens;
+
16 std::size_t index = 0U;
+
17 while (index < text.size()) {
+
18 const char character = text[index++];
+
19 if (character ==
' ' || character ==
'\t' )
+
+
+
22 if (character ==
'"' ) {
+
+
+
25 while (index < text.size()) {
+
26 char next = text[index++];
+
+
+
+
+
+
32 if (index == text.size())
+
33 throw std::runtime_error(
"Incomplete attribute escape." );
+
+
35 if (next !=
'"' && next !=
'\\' )
+
36 throw std::runtime_error(
"Invalid attribute escape." );
+
+
+
+
+
41 throw std::runtime_error(
"Unterminated attribute string." );
+
42 if (index < text.size() && text[index] !=
' ' && text[index] !=
'\t' &&
+
43 text[index] !=
',' && text[index] !=
';' )
+
44 throw std::runtime_error(
"Missing separator after attribute string." );
+
45 }
else if (character ==
';' || character ==
',' ) {
+
46 token.text = character;
+
+
48 token.text = character;
+
49 while (index < text.size() && text[index] !=
' ' && text[index] !=
'\t' &&
+
50 text[index] !=
';' && text[index] !=
',' ) {
+
51 if (text[index] ==
'"' )
+
52 throw std::runtime_error(
"Missing separator before attribute string." );
+
53 token.text += text[index++];
+
+
+
56 tokens.push_back(token);
+
+
58 if (tokens.empty() || tokens.back().quoted || tokens.back().text !=
";" )
+
59 throw std::runtime_error(
"Attribute statement requires a semicolon." );
+
+
+
+
+
64 class AttributeTokens {
+
+
66 explicit AttributeTokens(
const std::string &line) : tokens(Tokenize(line)) {}
+
+
68 if (position == tokens.size())
+
69 throw std::runtime_error(
"Incomplete attribute statement." );
+
70 return tokens[position++];
+
+
+
73 const Token token = Take();
+
74 if (token.quoted || token.text ==
"," || token.text ==
";" )
+
75 throw std::runtime_error(
"Expected an attribute keyword or number." );
+
+
+
78 std::string Quoted() {
+
79 const Token token = Take();
+
+
81 throw std::runtime_error(
"Expected a quoted attribute name or string." );
+
+
+
84 bool Empty()
const {
return position == tokens.size(); }
+
+
+
87 throw std::runtime_error(
"Unexpected trailing attribute fields." );
+
+
+
+
91 std::vector<Token> tokens;
+
92 std::size_t position = 0U;
+
+
+
95 bool IsScope(
const std::string &text) {
+
96 return text ==
"BO_" || text ==
"SG_" || text ==
"BU_" || text ==
"EV_" ;
+
+
+
99 AttributeScope ParseScope(
const std::string &text) {
+
100 if (text ==
"BO_" )
return AttributeScope::Frame;
+
101 if (text ==
"SG_" )
return AttributeScope::Signal;
+
102 if (text ==
"BU_" )
return AttributeScope::Node;
+
103 if (text ==
"EV_" )
return AttributeScope::Environment;
+
104 throw std::runtime_error(
"Unsupported attribute scope: " + text);
+
+
+
107 template <
class Numeric>
+
108 Numeric ParseNumber(
const std::string &text) {
+
109 const char *begin = text.data();
+
110 const char *end = begin + text.size();
+
111 if (begin != end && *begin ==
'+' ) {
+
+
113 if (begin != end && (*begin ==
'-' || *begin ==
'+' ))
+
114 throw std::runtime_error(
"Invalid attribute number: " + text);
+
+
+
117 const std::from_chars_result parsed = std::from_chars(begin, end, value);
+
118 if (begin == end || parsed.ec != std::errc() || parsed.ptr != end || !std::isfinite(value))
+
119 throw std::runtime_error(
"Invalid attribute number: " + text);
+
+
+
+
123 AttributeValue Value(
const Token &token,
const AttributeDefinition &definition,
bool isDefault) {
+
124 if (definition.
type == AttributeType::String) {
+
125 if (!token.quoted)
throw std::runtime_error(
"Attribute STRING requires quoted text." );
+
+
+
128 if (definition.
type == AttributeType::Enum && isDefault && token.quoted) {
+
129 for (std::size_t index = 0U; index < definition.
enumValues .size(); ++index) {
+
130 if (definition.
enumValues [index] == token.text)
+
131 return static_cast< std::int64_t
> (index);
+
+
133 throw std::runtime_error(
"Unknown attribute ENUM default label." );
+
+
135 if (token.quoted)
throw std::runtime_error(
"Numeric attribute requires an unquoted number." );
+
136 if (definition.
type == AttributeType::Float) {
+
137 const double value = ParseNumber<double>(token.text);
+
138 if (value < definition.minimum || value > definition.
maximum )
+
139 throw std::runtime_error(
"Attribute FLOAT value outside definition range." );
+
+
+
142 const std::int64_t value = ParseNumber<std::int64_t>(token.text);
+
143 if (value < definition.integerMinimum || value > definition.
integerMaximum )
+
144 throw std::runtime_error(
"Attribute integer/ENUM value outside definition range." );
+
+
+
+
148 void Define(AttributeTokens &tokens,
DbcDatabase &database) {
+
+
150 const Token first = tokens.Take();
+
151 std::string name = first.text;
+
+
153 definition.
scope = ParseScope(first.text);
+
154 name = tokens.Quoted();
+
+
156 if (name.empty())
throw std::runtime_error(
"Empty attribute name." );
+
157 const std::string type = tokens.Word();
+
158 if (type ==
"INT" || type ==
"HEX" ) {
+
159 definition.
type = type ==
"INT" ? AttributeType::Integer : AttributeType::Hex;
+
160 definition.
integerMinimum = ParseNumber<std::int64_t>(tokens.Word());
+
161 definition.
integerMaximum = ParseNumber<std::int64_t>(tokens.Word());
+
+
163 throw std::runtime_error(
"Reversed attribute integer range." );
+
164 }
else if (type ==
"FLOAT" ) {
+
165 definition.
type = AttributeType::Float;
+
166 definition.
minimum = ParseNumber<double>(tokens.Word());
+
167 definition.
maximum = ParseNumber<double>(tokens.Word());
+
+
169 throw std::runtime_error(
"Reversed attribute FLOAT range." );
+
170 }
else if (type ==
"STRING" ) {
+
171 definition.
type = AttributeType::String;
+
172 }
else if (type ==
"ENUM" ) {
+
173 definition.
type = AttributeType::Enum;
+
174 std::set<std::string> labels;
+
+
176 const std::string label = tokens.Quoted();
+
177 if (!labels.insert(label).second)
+
178 throw std::runtime_error(
"Duplicate attribute ENUM label." );
+
+
180 if (tokens.Empty())
break ;
+
181 const Token separator = tokens.Take();
+
182 if (separator.quoted || separator.text !=
"," )
throw std::runtime_error(
"Expected ENUM comma." );
+
+
+
+
186 throw std::runtime_error(
"Unsupported attribute definition type: " + type);
+
+
+
189 if (name ==
"VFrameFormat" && (definition.
scope != AttributeScope::Frame || definition.
type != AttributeType::Enum))
+
190 throw std::runtime_error(
"VFrameFormat requires a BO_ ENUM definition." );
+
191 if (name ==
"GenMsgCycleTime" && (definition.
scope != AttributeScope::Frame ||
+
192 (definition.
type != AttributeType::Integer && definition.
type != AttributeType::Hex)))
+
193 throw std::runtime_error(
"GenMsgCycleTime requires a BO_ integer definition." );
+
+
195 throw std::runtime_error(
"Duplicate attribute definition: " + name);
+
+
+
+
199 const std::map<std::string, AttributeDefinition>::iterator found = database.
attributeDefinitions .find(name);
+
+
201 throw std::runtime_error(
"Undefined attribute: " + name);
+
202 return found->second;
+
+
+
+
206 const std::int64_t raw = ParseNumber<std::int64_t>(text);
+
207 if (raw < 0 || raw > std::numeric_limits<std::uint32_t>::max() || (raw & 0x60000000U) != 0)
+
208 throw std::runtime_error(
"Invalid attribute CAN ID." );
+
209 const std::uint32_t
id =
static_cast< std::uint32_t
> (raw);
+
210 assignment.
canId =
id & 0x1fffffffU;
+
211 assignment.
isExtended = (
id & 0x80000000U) != 0U ||
id > 0x7ffU;
+
+
+
+
215 if (assignment.
scope == AttributeScope::Database)
return database.
attributes ;
+
216 for (
FrameInfo &frame: database.frames) {
+
217 if (frame.canId != assignment.
canId || frame.isExtended != assignment.
isExtended )
continue ;
+
218 if (assignment.
scope == AttributeScope::Frame)
return frame.attributes;
+
+
220 if (signal.name == assignment.
targetName )
return signal.attributes;
+
+
222 throw std::runtime_error(
"Unresolved attribute signal: " + assignment.
targetName );
+
+
224 throw std::runtime_error(
"Unresolved attribute frame." );
+
+
+
227 void ValidateCycleTime(
const std::string &name,
const AttributeValue &value) {
+
228 if (name !=
"GenMsgCycleTime" )
return ;
+
229 const std::int64_t milliseconds = std::get<std::int64_t>(value);
+
230 if (milliseconds < 0 || milliseconds > std::numeric_limits<std::uint32_t>::max())
+
231 throw std::runtime_error(
"GenMsgCycleTime must fit unsigned 32-bit milliseconds." );
+
+
+
+
+
236 if (definition.
scope == AttributeScope::Database) {
+
+
+
+
240 if (definition.
scope != AttributeScope::Frame && definition.
scope != AttributeScope::Signal)
+
+
242 for (
FrameInfo &frame: database.frames) {
+
243 if (definition.
scope == AttributeScope::Frame) frame.attributes[name] = *definition.
defaultValue ;
+
244 if (definition.
scope == AttributeScope::Signal) {
+
245 for (
SignalInfo &signal: frame.signals) signal.attributes[name] = *definition.defaultValue;
+
+
+
+
+
+
+
+
+
+
256 std::map<std::string, std::size_t> defaultLines;
+
257 std::vector<std::size_t> assignmentLines;
+
+
259 const char *keywords[] = {
"BA_DEF_" ,
"BA_DEF_DEF_" ,
"BA_" };
+
260 for (
const char *phase: keywords) {
+
+
262 const std::string keyword = pending.statement.substr(0U, pending.statement.find_first_of(
" \t" ));
+
263 if (keyword != phase)
continue ;
+
+
265 AttributeTokens tokens(pending.statement);
+
+
267 if (keyword ==
"BA_DEF_" ) {
+
+
+
+
271 const std::string name = tokens.Quoted();
+
+
273 if (keyword ==
"BA_DEF_DEF_" ) {
+
274 if (definition.
defaultValue )
throw std::runtime_error(
"Duplicate attribute default: " + name);
+
275 definition.
defaultValue = Value(tokens.Take(), definition,
true );
+
+
+
278 defaultLines[name] = pending.lineNumber;
+
279 ApplyDefault(
database , name, definition);
+
+
+
+
283 assignment.
name = name;
+
284 Token value = tokens.Take();
+
285 if (!value.quoted && IsScope(value.text)) {
+
286 assignment.
scope = ParseScope(value.text);
+
287 if (assignment.
scope == AttributeScope::Frame || assignment.
scope == AttributeScope::Signal)
+
288 ParseId(tokens.Word(), assignment);
+
289 if (assignment.
scope != AttributeScope::Frame)
+
+
291 value = tokens.Take();
+
+
293 if (assignment.
scope != definition.
scope )
throw std::runtime_error(
"Attribute assignment scope differs from definition." );
+
294 assignment.
value = Value(value, definition,
false );
+
295 ValidateCycleTime(name, assignment.
value );
+
+
+
298 if (assignment.
scope != AttributeScope::Node && assignment.
scope != AttributeScope::Environment)
+
+
+
301 assignmentLines.push_back(pending.lineNumber);
+
302 }
catch (
const std::exception &error) {
+
303 throw DbcDiagnosticError (DbcDiagnosticCode::InvalidAttribute, filePath, pending.lineNumber, error.what());
+
+
+
+
+
308 for (
const AttributeMap::value_type &attribute: frame.attributes) {
+
309 if (attribute.first !=
"VFrameFormat" && attribute.first !=
"GenMsgCycleTime" )
continue ;
+
310 std::size_t line = defaultLines[attribute.first];
+
+
+
313 if (assignment.
name == attribute.first && assignment.
scope == AttributeScope::Frame &&
+
314 assignment.
canId == frame.canId && assignment.
isExtended == frame.isExtended)
+
315 line = assignmentLines[index];
+
+
317 const std::int64_t value = std::get<std::int64_t>(attribute.second);
+
318 if (attribute.first ==
"GenMsgCycleTime" ) {
+
319 frame.cycleTimeMs =
static_cast< std::uint32_t
> (value);
+
+
+
+
323 const std::string &format = *frame.frameFormat;
+
+
325 if (format !=
"StandardCAN" && format !=
"ExtendedCAN" )
+
326 warning =
"Unsupported VFrameFormat '" + format +
"' is preserved; decoding may be incomplete." ;
+
327 else if ((format ==
"ExtendedCAN" ) != frame.isExtended)
+
328 warning =
"VFrameFormat '" + format +
"' conflicts with the BO_ CAN ID; ID interpretation is unchanged." ;
+
329 if (!warning.empty())
+
330 diagnostics.push_back({DbcDiagnosticSeverity::Warning, DbcDiagnosticCode::UnsupportedAttribute, filePath, line, warning});
+
+
+
+
+
void Handle(const std::string &line, DbcParseContext &context) const override
Process a trimmed statement using state belonging to this parse.
+
+
Explicit assignment; defaults remain on definitions.
+
+
+
+
+
+
+
Attribute type, permitted range, and optional default.
+
+
std::vector< std::string > enumValues
+
std::int64_t integerMaximum
+
+
+
+
std::int64_t integerMinimum
+
std::optional< AttributeValue > defaultValue
+
Parsed DBC content stored in a simple internal form.
+
std::map< std::string, AttributeDefinition > attributeDefinitions
+
std::vector< FrameInfo > frames
+
+
std::vector< AttributeAssignment > attributeAssignments
+
+
void ResolveAttributes(const std::string &filePath, std::vector< DbcDiagnostic > &diagnostics)
Resolve definitions, defaults, then assignments; append format warnings.
+
+
+
std::vector< PendingAttribute > pendingAttributes
+
Describes one CAN frame from a DBC file.
+
Attribute statement retained for ordered resolution.
+
Describes one signal inside a DBC frame.
+
+
+
+
+
+ core dbc_attributes.cpp
+
+
+
+
+
diff --git a/docs/html/dbc__coverage__test_8cpp_source.html b/docs/html/dbc__coverage__test_8cpp_source.html
index b23af99..fb1f876 100644
--- a/docs/html/dbc__coverage__test_8cpp_source.html
+++ b/docs/html/dbc__coverage__test_8cpp_source.html
@@ -112,12 +112,12 @@ $(document).ready(function(){initNavTree('dbc__coverage__test_8cpp_source.html',
-
+
15 DbcDatabase ParseText(
const std::string &text,
bool enableJ1939 =
false ) {
17 if (!file.open())
throw std::runtime_error(
"Cannot create DBC fixture" );
18 if (file.write(text.data(),
static_cast< qint64
> (text.size())) !=
static_cast< qint64
> (text.size()) || !file.flush())
19 throw std::runtime_error(
"Cannot write DBC fixture" );
-
+
@@ -173,761 +173,930 @@ $(document).ready(function(){initNavTree('dbc__coverage__test_8cpp_source.html',
73 void malformedRuntimeMultiplexing();
-
-
-
78 void ignoredCommentStatements_data();
-
79 void ignoredCommentStatements();
-
80 void ambiguousValueReferences_data();
-
81 void ambiguousValueReferences();
-
82 void valueReferenceScope();
-
83 void fileFormatting_data();
-
84 void fileFormatting();
-
-
-
87 void physicalConversion_data();
-
88 void physicalConversion();
-
89 void multiplexingScenarios();
-
90 void multiplexingErrorLocations_data();
-
91 void multiplexingErrorLocations();
-
92 void escapedValueDescriptions();
-
-
-
-
96 void CoverageTest::frameLookup() {
-
-
-
-
-
101 QVERIFY(decoder.
FindFrame (empty, 17U,
false ) ==
nullptr );
-
-
103 QVERIFY(!absent.
valid );
-
-
105 QVERIFY(absent.signals.empty());
-
-
-
-
109 QVERIFY(decoder.
FindFrame (database, 18U,
false ) ==
nullptr );
-
110 QVERIFY(decoder.
FindFrame (database, 17U,
true ) ==
nullptr );
-
-
-
-
-
-
-
-
118 noSignals.
canId = 17U;
-
-
-
121 QVERIFY(matched.valid);
-
122 QCOMPARE(matched.definition.get(), &database.
GetFrames ()[0]);
-
123 QVERIFY(matched.signals.empty());
-
-
-
126 void CoverageTest::signedBoundaries_data() {
-
127 QTest::addColumn<int>(
"order" );
-
128 QTest::addColumn<unsigned>(
"length" );
-
129 QTest::addColumn<qlonglong>(
"expected" );
-
130 for (
int order = 0; order < 2; ++order) {
-
131 for (
unsigned length: {1U, 2U, 7U, 8U, 31U, 32U, 63U}) {
-
132 const std::int64_t half = std::int64_t(1) << (length - 1U);
-
133 const std::array<std::int64_t, 4> values{{0, -1, -half, half - 1}};
-
134 for (
unsigned index = 0; index < values.size(); ++index) {
-
135 const QByteArray name = QByteArray::number(order) +
"-" + QByteArray::number(length) +
"-" + QByteArray::number(index);
-
136 QTest::newRow(name.constData()) << order << length << qlonglong(values[index]);
-
-
-
-
-
-
142 void CoverageTest::signedBoundaries() {
-
-
144 QFETCH(
unsigned , length);
-
145 QFETCH(qlonglong, expected);
-
-
147 signal.
byteOrder = order == 0 ? ByteOrder::Intel : ByteOrder::Motorola;
-
148 signal.
startBit = order == 0 ? 0U : 7U;
-
-
-
-
-
153 raw.
data .assign(8U, 0U);
-
154 const std::uint64_t bits =
static_cast< std::uint64_t
> (expected);
-
155 for (
unsigned i = 0; i < length; ++i) {
-
156 const unsigned weight = order == 0 ? i : length - 1U - i;
-
157 const unsigned position = order == 0 ? i % 8U : 7U - i % 8U;
-
158 raw.
data [i / 8U] |=
static_cast< std::uint8_t
> (((bits >> weight) & 1U) << position);
-
-
-
-
162 QVERIFY(result.signals[0].
valid );
-
163 QVERIFY(std::holds_alternative<std::int64_t>(result.signals[0].rawValue));
-
164 QCOMPARE(std::get<std::int64_t>(result.signals[0].rawValue),
static_cast< std::int64_t
> (expected));
-
-
-
167 void CoverageTest::extraction_data() {
-
168 QTest::addColumn<int>(
"order" );
-
169 QTest::addColumn<unsigned>(
"start" );
-
170 QTest::addColumn<unsigned>(
"length" );
-
171 for (
int order = 0; order < 2; ++order)
-
172 for (
unsigned start = 0; start < 16U; ++start)
-
173 for (
unsigned length = 1; length <= 64U; ++length) {
-
174 const QByteArray name = QByteArray::number(order) +
"-" + QByteArray::number(start) +
"-" + QByteArray::number(length);
-
175 QTest::newRow(name.constData()) << order << start << length;
-
-
-
-
179 void CoverageTest::extraction() {
-
-
181 QFETCH(
unsigned , start);
-
182 QFETCH(
unsigned , length);
-
-
184 signal.
byteOrder = order == 0 ? ByteOrder::Intel : ByteOrder::Motorola;
-
-
-
-
-
-
190 const std::vector<std::vector<std::uint8_t>> patterns = {
-
191 std::vector<std::uint8_t>(10U, 0U),
-
192 std::vector<std::uint8_t>(10U, 255U),
-
193 {0xA5, 0x3C, 0x81, 0x7E, 0x12, 0xD4, 0x69, 0xB0, 0x5A, 0xC3}};
-
194 for (
const std::vector<std::uint8_t> &data: patterns) {
-
-
196 const unsigned firstCoordinate = order == 0 ? start : (start / 8U) * 8U + 7U - start % 8U;
-
197 raw.
data .resize((firstCoordinate + length + 7U) / 8U);
-
-
199 QVERIFY(decoded.signals[0].
valid );
-
200 QCOMPARE(std::get<std::uint64_t>(decoded.signals[0].rawValue), ReferenceExtract(data, signal.
byteOrder , start, length));
-
-
-
-
204 void CoverageTest::invalidSignalStatus_data() {
-
205 QTest::addColumn<int>(
"order" );
-
206 QTest::addColumn<unsigned>(
"start" );
-
207 QTest::addColumn<unsigned>(
"length" );
-
208 QTest::addColumn<unsigned>(
"bytes" );
-
209 QTest::addColumn<int>(
"status" );
-
210 for (
int order = 0; order < 2; ++order) {
-
211 const unsigned start = order == 0 ? 0U : 7U;
-
212 const QByteArray prefix = QByteArray::number(order);
-
213 QTest::newRow((prefix +
"-zero" ).constData()) << order << start << 0U << 1U << int(SignalDecodeStatus::InvalidDefinition);
-
214 QTest::newRow((prefix +
"-65" ).constData()) << order << start << 65U << 9U << int(SignalDecodeStatus::InvalidDefinition);
-
215 QTest::newRow((prefix +
"-empty" ).constData()) << order << start << 8U << 0U << int(SignalDecodeStatus::InsufficientPayload);
-
216 QTest::newRow((prefix +
"-short" ).constData()) << order << start << 16U << 1U << int(SignalDecodeStatus::InsufficientPayload);
-
217 QTest::newRow((prefix +
"-large-start" ).constData()) << order << std::numeric_limits<unsigned>::max() << 8U << 1U <<
int (SignalDecodeStatus::InvalidDefinition);
-
-
-
-
221 void CoverageTest::invalidSignalStatus() {
-
-
223 QFETCH(
unsigned , start);
-
224 QFETCH(
unsigned , length);
-
225 QFETCH(
unsigned , bytes);
-
-
-
-
-
230 signal.
byteOrder = order == 0 ? ByteOrder::Intel : ByteOrder::Motorola;
-
231 if (status ==
int (SignalDecodeStatus::InvalidDefinition)) {
-
232 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (
void ) SingleSignal(signal));
-
-
-
-
-
-
238 raw.
data .assign(bytes, 255U);
-
-
240 QVERIFY(decoded.
valid );
-
241 QVERIFY(!decoded.signals[0].
valid );
-
242 QCOMPARE(
int (decoded.signals[0].
status ), status);
-
243 QVERIFY(decoded.signals[0].GetValueDescription() ==
nullptr );
-
-
-
246 void CoverageTest::malformedRuntimeMultiplexing_data() {
-
247 QTest::addColumn<int>(
"kind" );
-
248 QTest::newRow(
"two-selectors" ) << 0;
-
249 QTest::newRow(
"signed-selector" ) << 1;
-
250 QTest::newRow(
"65-bit-selector" ) << 2;
-
251 QTest::newRow(
"branch-out-of-range" ) << 3;
-
-
-
254 void CoverageTest::malformedRuntimeMultiplexing() {
-
-
-
-
258 selector.multiplexing.role = MultiplexRole::Selector;
-
259 selector.
name =
"Selector" ;
-
260 std::vector<DecodeFrame> definitions = SingleSignal(selector).GetFrames();
-
-
262 branch.
name =
"Branch" ;
-
-
-
265 branch.multiplexing.role = MultiplexRole::Branch;
-
266 branch.multiplexing.value = 1U;
-
267 definitions[0].signals.push_back(branch);
-
-
269 ordinary.
name =
"Ordinary" ;
-
-
-
272 definitions[0].signals.push_back(ordinary);
-
-
274 selector.
name =
"SecondSelector" ;
-
275 definitions[0].signals.push_back(selector);
-
-
277 if (kind == 1) definitions[0].signals[0].valueType = ValueType::Signed;
-
278 if (kind == 2) definitions[0].signals[0].length = 65U;
-
279 if (kind == 3) definitions[0].signals[1].multiplexing.value = 2U;
-
280 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (
void )
DecodeDatabase (definitions));
-
-
-
283 void CoverageTest::pgn_data() {
-
284 QTest::addColumn<unsigned>(
"id" );
-
285 QTest::addColumn<unsigned>(
"expected" );
-
286 QTest::addColumn<bool>(
"hasPgn" );
-
287 QTest::newRow(
"standard" ) << 0x7FFU << 0U <<
false ;
-
288 for (
unsigned dp: {0U, 1U})
-
289 for (
unsigned pf: {239U, 240U})
-
290 for (
unsigned ps: {0U, 0xABU}) {
-
291 const unsigned id = 0x80000000U | (dp << 24U) | (pf << 16U) | (ps << 8U) | 0x42U;
-
292 const unsigned expected = (dp << 16U) | (pf == 239U ? 0xEF00U : 0xF000U | ps);
-
293 const QByteArray name = QByteArray::number(dp) +
"-" + QByteArray::number(pf) +
"-" + QByteArray::number(ps);
-
294 QTest::newRow(name.constData()) <<
id << expected <<
true ;
-
-
-
-
298 void CoverageTest::pgn() {
-
299 QFETCH(
unsigned ,
id );
-
300 QFETCH(
unsigned , expected);
-
301 QFETCH(
bool , hasPgn);
-
302 const DbcDatabase parsed = ParseText(
"BO_ " + std::to_string(
id ) +
" Frame: 8 ECU\n" );
-
303 QCOMPARE(parsed.
frames [0].hasPgn, hasPgn);
-
304 QCOMPARE(parsed.
frames [0].pgn, expected);
-
-
-
307 void CoverageTest::comments_data() {
-
308 QTest::addColumn<QString>(
"before" );
-
309 QTest::addColumn<QString>(
"after" );
-
310 QTest::addColumn<QString>(
"frameComment" );
-
311 QTest::addColumn<QString>(
"signalComment" );
-
312 QTest::newRow(
"tabs" ) << QString::fromUtf8(
"" ) << QString::fromUtf8(
"CM_\tBO_ 1 \"Frame\";\nCM_\tSG_ 1 State \"Signal\";\n" ) << QString::fromUtf8(
"Frame" ) << QString::fromUtf8(
"Signal" );
-
313 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(
"" );
-
314 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" );
-
315 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(
"" );
-
-
317 QTest::newRow(
"before-definitions" ) << QString::fromUtf8(
"CM_ BO_ 1 \"Early\";\nCM_ SG_ 1 State \"Early\";\n" ) << QString::fromUtf8(
"" ) << QString::fromUtf8(
"" ) << QString::fromUtf8(
"" );
-
318 QTest::newRow(
"missing-quotes" ) << QString::fromUtf8(
"" ) << QString::fromUtf8(
"CM_ BO_ 1 Missing;\nCM_ SG_ 1 State \"Unclosed;\n" ) << QString::fromUtf8(
"" ) << QString::fromUtf8(
"" );
-
-
-
321 void CoverageTest::comments() {
-
322 QFETCH(QString, before);
-
323 QFETCH(QString, after);
-
324 QFETCH(QString, frameComment);
-
325 QFETCH(QString, signalComment);
-
326 const DbcDatabase parsed = ParseText(before.toStdString() +
"BO_ 1 Frame: 1 ECU\nSG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n" + after.toStdString());
-
327 QCOMPARE(parsed.
frames [0].comment, frameComment.toStdString());
-
328 QCOMPARE(parsed.
frames [0].signals[0].comment, signalComment.toStdString());
-
-
-
331 void CoverageTest::ignoredCommentStatements_data() {
-
332 QTest::addColumn<QString>(
"statement" );
-
333 QTest::newRow(
"empty" ) << QString();
-
334 QTest::newRow(
"wrong-keyword" ) << QStringLiteral(
"OTHER_ BO_ 1 \"Ignored\";" );
-
335 QTest::newRow(
"keyword-prefix" ) << QStringLiteral(
"CM_OTHER BO_ 1 \"Ignored\";" );
-
336 QTest::newRow(
"frame-without-cm" ) << QStringLiteral(
"BO_ 1 \"Ignored\";" );
-
337 QTest::newRow(
"missing-subtype" ) << QStringLiteral(
"CM_" );
-
338 QTest::newRow(
"global-comment" ) << QStringLiteral(
"CM_ \"Ignored\";" );
-
339 QTest::newRow(
"node-comment" ) << QStringLiteral(
"CM_ BU_ ECU \"Ignored\";" );
-
340 QTest::newRow(
"environment-comment" ) << QStringLiteral(
"CM_ EV_ State \"Ignored\";" );
-
341 QTest::newRow(
"unknown-subtype" ) << QStringLiteral(
"CM_ OTHER_ 1 \"Ignored\";" );
-
-
-
344 void CoverageTest::ignoredCommentStatements() {
-
345 QFETCH(QString, statement);
-
-
-
-
349 frame.
name =
"Frame" ;
-
350 frame.
comment =
"Existing frame comment" ;
-
-
352 signal.
name =
"State" ;
-
353 signal.
comment =
"Existing signal comment" ;
-
354 frame.signals.push_back(signal);
-
355 database.
frames .push_back(frame);
-
-
-
-
-
-
361 QCOMPARE(database.
frames .size(), std::size_t(1));
-
362 QCOMPARE(database.
frames [0].canId, 1U);
-
363 QCOMPARE(database.
frames [0].name, frame.
name );
-
-
365 QCOMPARE(database.
frames [0].signals.size(), std::size_t(1));
-
366 QCOMPARE(database.
frames [0].signals[0].name, signal.
name );
-
367 QCOMPARE(database.
frames [0].signals[0].comment, signal.
comment );
-
368 QCOMPARE(context.currentFrame, &database.
frames [0]);
-
-
-
371 void CoverageTest::ambiguousValueReferences_data() {
-
372 QTest::addColumn<bool>(
"duplicateFrames" );
-
373 QTest::addColumn<bool>(
"extended" );
-
374 QTest::newRow(
"duplicate-standard-frames" ) <<
true <<
false ;
-
375 QTest::newRow(
"duplicate-extended-frames" ) <<
true <<
true ;
-
376 QTest::newRow(
"duplicate-signals-in-standard-frame" ) <<
false <<
false ;
-
377 QTest::newRow(
"duplicate-signals-in-extended-frame" ) <<
false <<
true ;
-
+
76 void j1939Lookup_data();
+
+
78 void j1939Ambiguity_data();
+
79 void j1939Ambiguity();
+
80 void j1939MetadataValidation();
+
+
+
83 void ignoredCommentStatements_data();
+
84 void ignoredCommentStatements();
+
85 void ambiguousValueReferences_data();
+
86 void ambiguousValueReferences();
+
87 void valueReferenceScope();
+
88 void fileFormatting_data();
+
89 void fileFormatting();
+
+
+
92 void physicalConversion_data();
+
93 void physicalConversion();
+
94 void multiplexingScenarios();
+
95 void multiplexingErrorLocations_data();
+
96 void multiplexingErrorLocations();
+
97 void escapedValueDescriptions();
+
+
+
+
101 void CoverageTest::frameLookup() {
+
+
+
+
+
106 QVERIFY(decoder.
FindFrame (empty, 17U,
false ) ==
nullptr );
+
+
108 QVERIFY(!absent.
valid );
+
+
110 QVERIFY(absent.signals.empty());
+
+
+
+
114 QVERIFY(decoder.
FindFrame (database, 18U,
false ) ==
nullptr );
+
115 QVERIFY(decoder.
FindFrame (database, 17U,
true ) ==
nullptr );
+
+
+
+
+
+
+
+
123 noSignals.
canId = 17U;
+
+
+
126 QVERIFY(matched.valid);
+
127 QCOMPARE(matched.definition.get(), &database.
GetFrames ()[0]);
+
128 QVERIFY(matched.signals.empty());
+
+
+
131 void CoverageTest::signedBoundaries_data() {
+
132 QTest::addColumn<int>(
"order" );
+
133 QTest::addColumn<unsigned>(
"length" );
+
134 QTest::addColumn<qlonglong>(
"expected" );
+
135 for (
int order = 0; order < 2; ++order) {
+
136 for (
unsigned length: {1U, 2U, 7U, 8U, 31U, 32U, 63U}) {
+
137 const std::int64_t half = std::int64_t(1) << (length - 1U);
+
138 const std::array<std::int64_t, 4> values{{0, -1, -half, half - 1}};
+
139 for (
unsigned index = 0; index < values.size(); ++index) {
+
140 const QByteArray name = QByteArray::number(order) +
"-" + QByteArray::number(length) +
"-" + QByteArray::number(index);
+
141 QTest::newRow(name.constData()) << order << length << qlonglong(values[index]);
+
+
+
+
+
+
147 void CoverageTest::signedBoundaries() {
+
+
149 QFETCH(
unsigned , length);
+
150 QFETCH(qlonglong, expected);
+
+
152 signal.
byteOrder = order == 0 ? ByteOrder::Intel : ByteOrder::Motorola;
+
153 signal.
startBit = order == 0 ? 0U : 7U;
+
+
+
+
+
158 raw.
data .assign(8U, 0U);
+
159 const std::uint64_t bits =
static_cast< std::uint64_t
> (expected);
+
160 for (
unsigned i = 0; i < length; ++i) {
+
161 const unsigned weight = order == 0 ? i : length - 1U - i;
+
162 const unsigned position = order == 0 ? i % 8U : 7U - i % 8U;
+
163 raw.
data [i / 8U] |=
static_cast< std::uint8_t
> (((bits >> weight) & 1U) << position);
+
+
+
+
167 QVERIFY(result.signals[0].
valid );
+
168 QVERIFY(std::holds_alternative<std::int64_t>(result.signals[0].rawValue));
+
169 QCOMPARE(std::get<std::int64_t>(result.signals[0].rawValue),
static_cast< std::int64_t
> (expected));
+
+
+
172 void CoverageTest::extraction_data() {
+
173 QTest::addColumn<int>(
"order" );
+
174 QTest::addColumn<unsigned>(
"start" );
+
175 QTest::addColumn<unsigned>(
"length" );
+
176 for (
int order = 0; order < 2; ++order)
+
177 for (
unsigned start = 0; start < 16U; ++start)
+
178 for (
unsigned length = 1; length <= 64U; ++length) {
+
179 const QByteArray name = QByteArray::number(order) +
"-" + QByteArray::number(start) +
"-" + QByteArray::number(length);
+
180 QTest::newRow(name.constData()) << order << start << length;
+
+
+
+
184 void CoverageTest::extraction() {
+
+
186 QFETCH(
unsigned , start);
+
187 QFETCH(
unsigned , length);
+
+
189 signal.
byteOrder = order == 0 ? ByteOrder::Intel : ByteOrder::Motorola;
+
+
+
+
+
+
195 const std::vector<std::vector<std::uint8_t>> patterns = {
+
196 std::vector<std::uint8_t>(10U, 0U),
+
197 std::vector<std::uint8_t>(10U, 255U),
+
198 {0xA5, 0x3C, 0x81, 0x7E, 0x12, 0xD4, 0x69, 0xB0, 0x5A, 0xC3}};
+
199 for (
const std::vector<std::uint8_t> &data: patterns) {
+
+
201 const unsigned firstCoordinate = order == 0 ? start : (start / 8U) * 8U + 7U - start % 8U;
+
202 raw.
data .resize((firstCoordinate + length + 7U) / 8U);
+
+
204 QVERIFY(decoded.signals[0].
valid );
+
205 QCOMPARE(std::get<std::uint64_t>(decoded.signals[0].rawValue), ReferenceExtract(data, signal.
byteOrder , start, length));
+
+
+
+
209 void CoverageTest::invalidSignalStatus_data() {
+
210 QTest::addColumn<int>(
"order" );
+
211 QTest::addColumn<unsigned>(
"start" );
+
212 QTest::addColumn<unsigned>(
"length" );
+
213 QTest::addColumn<unsigned>(
"bytes" );
+
214 QTest::addColumn<int>(
"status" );
+
215 for (
int order = 0; order < 2; ++order) {
+
216 const unsigned start = order == 0 ? 0U : 7U;
+
217 const QByteArray prefix = QByteArray::number(order);
+
218 QTest::newRow((prefix +
"-zero" ).constData()) << order << start << 0U << 1U << int(SignalDecodeStatus::InvalidDefinition);
+
219 QTest::newRow((prefix +
"-65" ).constData()) << order << start << 65U << 9U << int(SignalDecodeStatus::InvalidDefinition);
+
220 QTest::newRow((prefix +
"-empty" ).constData()) << order << start << 8U << 0U << int(SignalDecodeStatus::InsufficientPayload);
+
221 QTest::newRow((prefix +
"-short" ).constData()) << order << start << 16U << 1U << int(SignalDecodeStatus::InsufficientPayload);
+
222 QTest::newRow((prefix +
"-large-start" ).constData()) << order << std::numeric_limits<unsigned>::max() << 8U << 1U <<
int (SignalDecodeStatus::InvalidDefinition);
+
+
+
+
226 void CoverageTest::invalidSignalStatus() {
+
+
228 QFETCH(
unsigned , start);
+
229 QFETCH(
unsigned , length);
+
230 QFETCH(
unsigned , bytes);
+
+
+
+
+
235 signal.
byteOrder = order == 0 ? ByteOrder::Intel : ByteOrder::Motorola;
+
236 if (status ==
int (SignalDecodeStatus::InvalidDefinition)) {
+
237 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (
void ) SingleSignal(signal));
+
+
+
+
+
+
243 raw.
data .assign(bytes, 255U);
+
+
245 QVERIFY(decoded.
valid );
+
246 QVERIFY(!decoded.signals[0].
valid );
+
247 QCOMPARE(
int (decoded.signals[0].
status ), status);
+
248 QVERIFY(decoded.signals[0].GetValueDescription() ==
nullptr );
+
+
+
251 void CoverageTest::malformedRuntimeMultiplexing_data() {
+
252 QTest::addColumn<int>(
"kind" );
+
253 QTest::newRow(
"two-selectors" ) << 0;
+
254 QTest::newRow(
"signed-selector" ) << 1;
+
255 QTest::newRow(
"65-bit-selector" ) << 2;
+
256 QTest::newRow(
"branch-out-of-range" ) << 3;
+
+
+
259 void CoverageTest::malformedRuntimeMultiplexing() {
+
+
+
+
+
264 selector.
name =
"Selector" ;
+
265 std::vector<DecodeFrame> definitions = SingleSignal(selector).GetFrames();
+
+
267 branch.
name =
"Branch" ;
+
+
+
+
+
272 definitions[0].signals.push_back(branch);
+
+
274 ordinary.
name =
"Ordinary" ;
+
+
+
277 definitions[0].signals.push_back(ordinary);
+
+
279 selector.
name =
"SecondSelector" ;
+
280 definitions[0].signals.push_back(selector);
+
+
282 if (kind == 1) definitions[0].signals[0].valueType = ValueType::Signed;
+
283 if (kind == 2) definitions[0].signals[0].length = 65U;
+
284 if (kind == 3) definitions[0].signals[1].multiplexing.value = 2U;
+
285 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (
void )
DecodeDatabase (definitions));
+
+
+
288 void CoverageTest::pgn_data() {
+
289 QTest::addColumn<unsigned>(
"id" );
+
290 QTest::addColumn<unsigned>(
"expected" );
+
291 QTest::addColumn<bool>(
"hasPgn" );
+
292 QTest::newRow(
"standard" ) << 0x7FFU << 0U <<
false ;
+
293 for (
unsigned dp: {0U, 1U, 2U, 3U})
+
294 for (
unsigned pf: {239U, 240U})
+
295 for (
unsigned ps: {0U, 0xABU}) {
+
296 const unsigned id = 0x80000000U | (dp << 24U) | (pf << 16U) | (ps << 8U) | 0x42U;
+
297 const unsigned expected = (dp << 16U) | (pf == 239U ? 0xEF00U : 0xF000U | ps);
+
298 const QByteArray name = QByteArray::number(dp) +
"-" + QByteArray::number(pf) +
"-" + QByteArray::number(ps);
+
299 QTest::newRow(name.constData()) <<
id << expected <<
true ;
+
+
+
+
303 void CoverageTest::pgn() {
+
304 QFETCH(
unsigned ,
id );
+
305 QFETCH(
unsigned , expected);
+
306 QFETCH(
bool , hasPgn);
+
307 const std::string text =
"BO_ " + std::to_string(
id ) +
" Frame: 8 ECU\n" ;
+
+
309 QVERIFY(!generic.frames[0].hasPgn);
+
310 QCOMPARE(generic.frames[0].pgn, 0U);
+
+
312 QCOMPARE(parsed.
frames [0].hasPgn, hasPgn);
+
313 QCOMPARE(parsed.
frames [0].pgn, expected);
+
+
+
316 void CoverageTest::j1939Lookup_data() {
+
317 QTest::addColumn<unsigned>(
"definitionId" );
+
318 QTest::addColumn<unsigned>(
"receivedId" );
+
319 QTest::addColumn<unsigned>(
"pgn" );
+
320 QTest::addColumn<bool>(
"matches" );
+
321 QTest::newRow(
"pdu1-source" ) << 0x18EF1242U << 0x18EF1299U << 0xEF00U <<
true ;
+
322 QTest::newRow(
"pdu1-destination-priority" ) << 0x18EF1242U << 0x0CEF3499U << 0xEF00U <<
true ;
+
323 QTest::newRow(
"pdu2-source-priority" ) << 0x18F00442U << 0x0CF00499U << 0xF004U <<
true ;
+
324 QTest::newRow(
"pdu2-group-extension" ) << 0x18F00442U << 0x18F00599U << 0xF004U <<
false ;
+
325 QTest::newRow(
"data-page" ) << 0x18F00442U << 0x19F00499U << 0xF004U <<
false ;
+
326 QTest::newRow(
"extended-data-page" ) << 0x18F00442U << 0x1AF00499U << 0xF004U <<
false ;
+
327 QTest::newRow(
"pgn-zero" ) << 0x80000123U << 0x00000456U << 0U <<
true ;
+
+
+
330 void CoverageTest::j1939Lookup() {
+
331 QFETCH(
unsigned , definitionId);
+
332 QFETCH(
unsigned , receivedId);
+
333 QFETCH(
unsigned , pgn);
+
334 QFETCH(
bool , matches);
+
335 const std::string text =
"BO_ " + std::to_string(definitionId) +
" Frame: 1 ECU\n"
+
336 "SG_ Value : 0|8@1+ (2,1) [0|511] \"\" ECU\n" ;
+
+
+
339 raw.
canId = receivedId;
+
+
+
+
343 QVERIFY(!decoder.
FindFrame (generic, receivedId,
true ));
+
344 QCOMPARE(decoder.
Decode (generic, raw).
status , FrameDecodeStatus::UnknownFrame);
+
345 QVERIFY(!generic.FindFrameByPgn(pgn).definition);
+
+
+
348 const FrameKey key(definitionId & 0x1FFFFFFFU,
true );
+
+
+
+
+
+
354 QCOMPARE(result.
valid , matches);
+
+
356 QCOMPARE(
bool (decoder.
FindFrame (database, receivedId,
true )), matches);
+
+
358 QVERIFY(result.
key == key);
+
+
360 QCOMPARE(result.signals.size(), std::size_t(1));
+
361 QVERIFY(result.signals[0].
key ==
SignalKey (key,
"Value" ));
+
362 QCOMPARE(std::get<std::uint64_t>(result.signals[0].rawValue), std::uint64_t(7));
+
363 QCOMPARE(result.signals[0].physicalValue, 15.0);
+
+
365 QCOMPARE(selected.
status , FrameDecodeStatus::Valid);
+
366 QVERIFY(selected.signals[0].
key == result.signals[0].
key );
+
367 QVERIFY_THROWS_EXCEPTION(std::invalid_argument,
+
368 decoder.
Decode (database, raw, {SignalKey(FrameKey(receivedId, true),
"Value" )}));
+
+
+
+
372 QVERIFY(result.signals.empty());
+
+
+
375 QCOMPARE(decoder.
Decode (database, raw).
status , FrameDecodeStatus::UnknownFrame);
+
+
377 raw.
canId = receivedId | 0x80000000U;
+
378 QCOMPARE(decoder.
Decode (database, raw).
status , FrameDecodeStatus::UnknownFrame);
-
380 void CoverageTest::ambiguousValueReferences() {
-
381 QFETCH(
bool , duplicateFrames);
-
382 QFETCH(
bool , extended);
-
-
-
-
386 frame.
name =
"Frame" ;
-
-
-
389 signal.
name =
"State" ;
-
390 frame.signals.push_back(signal);
-
391 if (!duplicateFrames) frame.signals.push_back(signal);
-
392 database.
frames .push_back(frame);
-
393 if (duplicateFrames) database.
frames .push_back(frame);
+
+
+
+
+
+
+
386 void CoverageTest::j1939Ambiguity_data() {
+
387 QTest::addColumn<unsigned>(
"firstId" );
+
388 QTest::addColumn<unsigned>(
"secondId" );
+
389 QTest::addColumn<unsigned>(
"receivedId" );
+
390 QTest::addColumn<unsigned>(
"pgn" );
+
391 QTest::newRow(
"pdu1" ) << 0x18EF1242U << 0x18EF3443U << 0x18EF5699U << 0xEF00U;
+
392 QTest::newRow(
"pdu2" ) << 0x18F00442U << 0x0CF00443U << 0x18F00499U << 0xF004U;
+
-
-
-
-
398 context.lineNumber = 37U;
-
399 const std::string rawId = extended ?
"2147483649" :
"1" ;
-
-
401 QCOMPARE(context.pendingValues.size(), std::size_t(1));
-
402 QCOMPARE(context.pendingValues[0].lineNumber, std::size_t(37));
-
403 const std::string path =
"manual database.dbc" ;
-
-
405 context.ResolveValueDescriptions(path);
-
406 QFAIL(
"The resolver must reject an ambiguous target" );
-
407 }
catch (
const std::runtime_error &error) {
-
408 const std::string message = duplicateFrames ?
"Ambiguous VAL_ frame reference."
-
409 :
"Ambiguous VAL_ signal reference: State" ;
-
410 QCOMPARE(std::string(error.what()), path +
":37: " + message);
-
-
-
413 for (
const FrameInfo &candidate: database.frames)
-
414 for (const
SignalInfo &candidateSignal: candidate.signals)
-
415 QVERIFY(candidateSignal.valueDescriptions.empty());
-
-
-
418 void CoverageTest::valueReferenceScope() {
-
-
-
-
-
423 signal.
name =
"State" ;
-
424 frame.signals.push_back(signal);
-
425 database.
frames .push_back(frame);
-
-
427 database.
frames .push_back(frame);
-
-
-
430 database.
frames .push_back(frame);
-
-
-
-
434 context.lineNumber = 3U;
-
435 handler.Handle(
"VAL_ 1 State 0 \"Standard\";" , context);
-
436 context.lineNumber = 7U;
-
437 handler.Handle(
"VAL_ 2147483649 State 0 \"Extended\";" , context);
-
438 context.ResolveValueDescriptions(
"manual database.dbc" );
-
-
440 const std::string *standard = FindValueDescription(database.
frames [0].signals[0].valueDescriptions, std::uint64_t(0));
-
441 const std::string *extended = FindValueDescription(database.
frames [1].signals[0].valueDescriptions, std::uint64_t(0));
-
442 QVERIFY(standard !=
nullptr );
-
443 QVERIFY(extended !=
nullptr );
-
444 QCOMPARE(*standard, std::string(
"Standard" ));
-
445 QCOMPARE(*extended, std::string(
"Extended" ));
-
446 QVERIFY(database.
frames [2].signals[0].valueDescriptions.empty());
-
-
-
449 void CoverageTest::fileFormatting_data() {
-
450 QTest::addColumn<QString>(
"text" );
-
451 QTest::addColumn<unsigned>(
"frames" );
-
452 QTest::newRow(
"empty" ) << QString::fromUtf8(
"" ) << 0U;
-
453 QTest::newRow(
"whitespace" ) << QString::fromUtf8(
" \t\r\n\n\t" ) << 0U;
-
454 QTest::newRow(
"unknown-only" ) << QString::fromUtf8(
"VERSION \"test\"\nBU_: ECU\nUNKNOWN_ data\n" ) << 0U;
-
455 QTest::newRow(
"no-final-newline" ) << QString::fromUtf8(
"BO_ 1 Frame: 1 ECU\nSG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU" ) << 1U;
-
456 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;
-
-
-
459 void CoverageTest::fileFormatting() {
-
460 QFETCH(QString, text);
-
461 QFETCH(
unsigned , frames);
-
462 const DbcDatabase parsed = ParseText(text.toStdString());
-
463 QCOMPARE(parsed.
frames .size(), std::size_t(frames));
-
-
465 QCOMPARE(parsed.
frames [0].signals.size(), std::size_t(1));
-
466 if (text.contains(
"\r\nBO_" )) {
-
467 QCOMPARE(parsed.
frames [0].comment, std::string(
"Comment" ));
-
468 const std::string *description = FindValueDescription(parsed.
frames [0].signals[0].valueDescriptions, std::uint64_t(0));
-
469 QVERIFY(description !=
nullptr );
-
470 QCOMPARE(*description, std::string(
"Off" ));
-
-
+
395 void CoverageTest::j1939Ambiguity() {
+
396 QFETCH(
unsigned , firstId);
+
397 QFETCH(
unsigned , secondId);
+
398 QFETCH(
unsigned , receivedId);
+
399 QFETCH(
unsigned , pgn);
+
+
401 first.
canId = firstId;
+
+
+
+
+
406 second.
canId = secondId;
+
+
408 raw.
canId = receivedId;
+
+
+
411 for (
const std::vector<DecodeFrame> &frames: {std::vector<DecodeFrame>{first, second},
+
412 std::vector<DecodeFrame>{second, first}}) {
+
+
+
+
+
417 QVERIFY(!decoder.
FindFrame (database, receivedId,
true ));
+
+
419 QCOMPARE(result.
status , FrameDecodeStatus::AmbiguousFrame);
+
420 QVERIFY(!result.
valid );
+
+
422 QVERIFY(result.signals.empty());
+
+
424 QCOMPARE(decoder.
Decode (database, raw, {SignalKey(first.GetKey(),
"Missing" )}).
status ,
+
425 FrameDecodeStatus::AmbiguousFrame);
+
+
+
428 QCOMPARE(exact.
status , FrameDecodeStatus::Valid);
+
+
430 raw.
canId = receivedId;
+
+
+
+
434 second.
canId = receivedId;
+
+
436 QVERIFY(!mixed.FindFrameByPgn(pgn).ambiguous);
+
437 QCOMPARE(mixed.FindFrameByPgn(pgn).definition->canId, firstId);
+
+
439 raw.
canId = receivedId ^ 1U;
+
+
+
+
443 void CoverageTest::j1939MetadataValidation() {
+
+
445 frame.
canId = 0x18F00442U;
+
+
+
+
449 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (
void )
DecodeDatabase ({frame}));
+
+
+
+
+
+
+
456 source.
frames .push_back(metadata);
+
457 QVERIFY_THROWS_EXCEPTION(std::invalid_argument,
DbcDecodeBuilder ().Build(source));
+
+
+
+
461 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (
void )
DecodeDatabase ({frame}));
+
+
+
464 void CoverageTest::comments_data() {
+
465 QTest::addColumn<QString>(
"before" );
+
466 QTest::addColumn<QString>(
"after" );
+
467 QTest::addColumn<QString>(
"frameComment" );
+
468 QTest::addColumn<QString>(
"signalComment" );
+
469 QTest::newRow(
"tabs" ) << QString::fromUtf8(
"" ) << QString::fromUtf8(
"CM_\tBO_ 1 \"Frame\";\nCM_\tSG_ 1 State \"Signal\";\n" ) << QString::fromUtf8(
"Frame" ) << QString::fromUtf8(
"Signal" );
+
470 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(
"" );
+
471 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" );
+
472 QTest::newRow(
"before-definitions" ) << QString::fromUtf8(
"CM_ BO_ 1 \"Early\";\nCM_ SG_ 1 State \"Early\";\n" ) << QString::fromUtf8(
"" ) << QString::fromUtf8(
"Early" ) << QString::fromUtf8(
"Early" );
-
475 void CoverageTest::missingFile() {
-
-
477 QVERIFY(file.open());
-
478 const QString path = file.fileName();
-
479 QVERIFY(file.remove());
-
-
-
482 QFAIL(
"Missing file must throw" );
-
483 }
catch (
const std::runtime_error &error) {
-
484 QCOMPARE(std::string(error.what()),
"Failed to open DBC file: " + path.toStdString());
-
-
-
-
488 void CoverageTest::builders() {
-
-
490 QVERIFY(emptyRuntime.
GetFrames ().empty());
-
-
-
493 QCOMPARE(emptyTree->GetType(), NodeType::Root);
-
494 QCOMPARE(emptyTree->GetName(), std::string(
"dbc" ));
-
495 QCOMPARE(emptyTree->GetChildCount(), std::size_t(0));
-
496 QVERIFY(emptyTree->GetFrame() ==
nullptr && emptyTree->GetSignal() ==
nullptr );
-
-
498 "BO_ 256 Standard: 3 ECU1\n"
-
499 "SG_ Mode M : 0|8@1+ (2,3) [0|513] \"mode\" ECU1,ECU2\n"
-
500 "SG_ Branch m1 : 15|8@0- (-2,5) [-249|261] \"rpm\" ECU2,ECU3\n"
-
501 "SG_ Always : 16|8@1+ (0.25,-1) [-1|62.75] \"V\" ECU3\n"
-
502 "CM_ BO_ 256 \"Frame comment\";\nCM_ SG_ 256 Branch \"Branch comment\";\n"
-
503 "VAL_ 256 Branch -1 \"Negative\" 1 \"Positive\";\n"
-
504 "BO_ 2163212866 Extended: 8 ECU4\n" );
-
-
506 std::unique_ptr<TreeNode> tree;
-
-
-
-
-
511 source.
frames [0].name =
"Changed" ;
-
512 source.
frames [0].signals[1].receivers.clear();
-
513 source.
frames [0].signals[1].valueDescriptions.clear();
-
-
-
-
517 QCOMPARE(tree->GetChildCount(), expected.
frames .size());
-
518 for (std::size_t i = 0; i < expected.
frames .size(); ++i) {
-
-
-
-
-
523 QCOMPARE(node->
GetType (), NodeType::Frame);
-
-
-
-
-
-
529 QCOMPARE(decodedFrame.
name , frame.
name );
-
-
-
-
-
534 QCOMPARE(copied.
dlc , frame.
dlc );
-
535 QCOMPARE(decodedFrame.
dlc , frame.
dlc );
-
536 QCOMPARE(copied.
pgn , frame.
pgn );
-
537 QCOMPARE(decodedFrame.
pgn , frame.
pgn );
-
-
-
-
-
-
-
-
545 QCOMPARE(copied.signals.size(), frame.signals.size());
-
546 QCOMPARE(decodedFrame.signals.size(), frame.signals.size());
-
547 for (std::size_t j = 0; j < frame.signals.size(); ++j) {
-
548 const SignalInfo &original = frame.signals[j];
-
-
-
-
552 QCOMPARE(leaf->
GetType (), NodeType::Signal);
-
-
554 QVERIFY(leaf->
GetFrame () ==
nullptr );
-
-
-
557 QCOMPARE(copy->name, original.
name );
-
558 QCOMPARE(copy->startBit, original.
startBit );
-
559 QCOMPARE(copy->length, original.
length );
-
-
561 QCOMPARE(copy->isSigned, original.
isSigned );
-
562 QCOMPARE(copy->factor, original.
factor );
-
563 QCOMPARE(copy->offset, original.
offset );
-
564 QCOMPARE(copy->minimum, original.
minimum );
-
565 QCOMPARE(copy->maximum, original.
maximum );
-
566 QCOMPARE(copy->unit, original.
unit );
-
567 QCOMPARE(copy->comment, original.
comment );
-
568 QVERIFY(copy->receivers == original.
receivers );
-
-
570 QCOMPARE(copy->multiplexing.role, original.multiplexing.role);
-
571 QCOMPARE(copy->multiplexing.value, original.multiplexing.value);
-
-
573 QCOMPARE(target.
name , original.
name );
-
-
-
-
-
-
-
-
-
582 QCOMPARE(target.
unit , original.
unit );
-
-
-
-
586 QCOMPARE(target.multiplexing.role, original.multiplexing.role);
-
587 QCOMPARE(target.multiplexing.value, original.multiplexing.value);
-
-
-
-
-
592 void CoverageTest::physicalConversion_data() {
-
593 QTest::addColumn<double>(
"factor" );
-
594 QTest::addColumn<double>(
"offset" );
-
595 QTest::addColumn<double>(
"expected" );
-
596 QTest::newRow(
"zero-factor" ) << 0.0 << 7.0 << 7.0;
-
597 QTest::newRow(
"negative-factor" ) << -2.0 << 5.0 << -15.0;
-
598 QTest::newRow(
"above-declared-range" ) << 2.0 << 3.0 << 23.0;
-
-
-
601 void CoverageTest::physicalConversion() {
-
602 QFETCH(
double , factor);
-
603 QFETCH(
double , offset);
-
604 QFETCH(
double , expected);
-
-
-
-
-
-
-
-
-
-
-
-
616 QVERIFY(decoded.signals[0].
valid );
-
617 QCOMPARE(std::get<std::uint64_t>(decoded.signals[0].rawValue), std::uint64_t(10));
-
618 QCOMPARE(decoded.signals[0].physicalValue, expected);
-
-
-
621 void CoverageTest::multiplexingScenarios() {
-
-
623 "BO_ 1 Frame: 1 ECU\nSG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n" ));
-
-
-
-
-
628 QCOMPARE(only.signals.size(), std::size_t(1));
-
629 QVERIFY(only.signals[0].
valid );
-
-
631 "BO_ 1 First: 3 ECU\n"
-
632 "SG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n"
-
633 "SG_ A m0 : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
-
634 "SG_ B m0 : 16|8@1+ (1,0) [0|255] \"\" ECU\n"
-
635 "BO_ 2 Second: 2 ECU\n"
-
636 "SG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n"
-
637 "SG_ A m1 : 8|8@1+ (1,0) [0|255] \"\" ECU\n" ));
-
638 raw.
data = {0U, 42U, 99U};
-
-
640 QVERIFY(first.signals[1].
valid && first.signals[2].
valid );
-
641 QCOMPARE(std::get<std::uint64_t>(first.signals[1].rawValue), std::uint64_t(42));
-
642 QCOMPARE(std::get<std::uint64_t>(first.signals[2].rawValue), std::uint64_t(99));
-
-
-
645 QCOMPARE(secondInactive.signals[1].
status , SignalDecodeStatus::Inactive);
-
-
647 QVERIFY(
DbcDecoder ().Decode(database, raw).signals[1].valid);
-
-
-
650 QCOMPARE(firstInactive.signals[1].
status , SignalDecodeStatus::Inactive);
-
651 QCOMPARE(firstInactive.signals[2].
status , SignalDecodeStatus::Inactive);
-
-
-
654 void CoverageTest::multiplexingErrorLocations_data() {
-
655 QTest::addColumn<QString>(
"text" );
-
656 QTest::addColumn<unsigned>(
"line" );
-
657 QTest::addColumn<QString>(
"message" );
-
658 const QString header =
"BO_ 1 Frame: 3 ECU\n\n" ;
-
659 const QString selector =
"SG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n" ;
-
660 const QString branch =
"SG_ A m1 : 8|8@1+ (1,0) [0|255] \"\" ECU\n" ;
-
661 QTest::newRow(
"missing-selector" ) << header + branch << 3U << QString::fromUtf8(
"Multiplexed branch has no selector." );
-
662 QTest::newRow(
"second-selector" ) << header + selector +
"\nSG_ Other M : 16|1@1+ (1,0) [0|1] \"\" ECU\n"
-
663 << 5U << QString::fromUtf8(
"Multiplexing requires one unsigned selector per frame." );
-
664 QTest::newRow(
"signed-selector" ) << header +
"SG_ Mode M : 0|1@1- (1,0) [-1|0] \"\" ECU\n"
-
665 << 3U << QString::fromUtf8(
"Multiplexing requires one unsigned selector per frame." );
-
666 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." );
-
667 QTest::newRow(
"same-branch-overlap" ) << header + selector + branch +
"SG_ B m1 : 15|8@0+ (1,0) [0|255] \"\" ECU\n"
-
668 << 5U << QString::fromUtf8(
"Signals overlap without mutually exclusive multiplexing conditions." );
-
669 QTest::newRow(
"selector-overlap" ) << header + selector +
"SG_ A m1 : 0|1@1+ (1,0) [0|1] \"\" ECU\n"
-
670 << 4U << QString::fromUtf8(
"Signals overlap without mutually exclusive multiplexing conditions." );
-
671 QTest::newRow(
"unconditional-overlap" ) << header + selector + branch +
"SG_ Always : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
-
672 << 5U << QString::fromUtf8(
"Signals overlap without mutually exclusive multiplexing conditions." );
-
673 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"
-
674 << 4U << QString::fromUtf8(
"Signals overlap without mutually exclusive multiplexing conditions." );
-
675 QTest::newRow(
"extended-multiplexing" ) << header +
"SG_MUL_VAL_ 1 A Mode 1-2;\n"
-
676 << 3U << QString::fromUtf8(
"Extended and nested multiplexing are unsupported." );
-
677 QTest::newRow(
"nested-marker" ) << header +
"SG_ A m1M : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
-
678 << 3U << QString::fromUtf8(
"Invalid or unsupported multiplexing marker." );
-
-
-
681 void CoverageTest::multiplexingErrorLocations() {
-
682 QFETCH(QString, text);
-
683 QFETCH(
unsigned , line);
-
684 QFETCH(QString, message);
-
-
686 QVERIFY(file.open());
-
687 const QByteArray content = text.toUtf8();
-
688 QCOMPARE(file.write(content), qint64(content.size()));
-
689 QVERIFY(file.flush());
-
-
-
692 QFAIL(
"Expected multiplexing rejection" );
-
693 }
catch (
const std::runtime_error &error) {
-
694 QCOMPARE(QString::fromStdString(error.what()), file.fileName() +
":" + QString::number(line) +
": " + message);
-
-
-
-
698 void CoverageTest::escapedValueDescriptions() {
-
-
700 "BO_ 1 Frame: 1 ECU\nSG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
-
701 R
"dbc(VAL_ 1 State -0 "Ноль" 1 "C:\\trace" 2 "\\\"quoted\"\\";)dbc"
-
-
703 const ValueDescriptions &values = parsed.
frames [0].signals[0].valueDescriptions;
-
704 QCOMPARE(values.size(), std::size_t(3));
-
705 QVERIFY(values.find(RawSignalValue(std::int64_t(0))) == values.end());
-
706 const std::string *zero = FindValueDescription(values, std::int64_t(0));
-
707 const std::string *path = FindValueDescription(values, std::uint64_t(1));
-
708 const std::string *quoted = FindValueDescription(values, std::uint64_t(2));
-
709 QVERIFY(zero && path && quoted);
-
710 QCOMPARE(*zero, std::string(
"Ноль" ));
-
711 QCOMPARE(*path, std::string(
"C:\\trace" ));
-
712 QCOMPARE(*quoted, std::string(
"\\\"quoted\"\\" ));
-
713 QVERIFY(NormalizeValueKey(RawSignalValue(std::int64_t(0))) == RawSignalValue(std::uint64_t(0)));
-
714 QVERIFY(NormalizeValueKey(RawSignalValue(std::int64_t(-1))) == RawSignalValue(std::int64_t(-1)));
-
-
-
717 void CoverageTest::factory() {
-
-
719 QVERIFY(!factory.
contains (
"value" ));
-
720 QVERIFY_THROWS_EXCEPTION(std::out_of_range,
static_cast< void > (factory.
creator (
"missing" )));
-
721 QVERIFY_THROWS_EXCEPTION(std::out_of_range,
static_cast< void > (factory.
create (
"missing" , std::make_unique<int>(1))));
-
-
-
724 std::unique_ptr<int> argument = std::make_unique<int>(42);
-
725 const std::shared_ptr<FactoryBase> first = factory.
create (
"value" , std::move(argument));
-
726 QVERIFY(argument ==
nullptr );
-
727 QCOMPARE(first->Value(), 42);
-
-
729 QCOMPARE(creator(std::make_unique<int>(7))->Value(), 7);
-
-
731 QCOMPARE(factory.
create (
"value" , std::make_unique<int>(42))->Value(), 43);
-
732 QCOMPARE(first->Value(), 42);
-
733 QCOMPARE(creator(std::make_unique<int>(7))->Value(), 7);
-
-
-
736 int RunCoverageTests(
int argc,
char **argv) {
-
-
738 return QTest::qExec(&tests, argc, argv);
-
-
740 #include "dbc_coverage_test.moc"
-
+
475 void CoverageTest::comments() {
+
476 QFETCH(QString, before);
+
477 QFETCH(QString, after);
+
478 QFETCH(QString, frameComment);
+
479 QFETCH(QString, signalComment);
+
480 const DbcDatabase parsed = ParseText(before.toStdString() +
"BO_ 1 Frame: 1 ECU\nSG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n" + after.toStdString());
+
481 QCOMPARE(parsed.
frames [0].comment, frameComment.toStdString());
+
482 QCOMPARE(parsed.
frames [0].signals[0].comment, signalComment.toStdString());
+
+
+
485 void CoverageTest::ignoredCommentStatements_data() {
+
486 QTest::addColumn<QString>(
"statement" );
+
487 QTest::newRow(
"empty" ) << QString();
+
488 QTest::newRow(
"wrong-keyword" ) << QStringLiteral(
"OTHER_ BO_ 1 \"Ignored\";" );
+
489 QTest::newRow(
"keyword-prefix" ) << QStringLiteral(
"CM_OTHER BO_ 1 \"Ignored\";" );
+
490 QTest::newRow(
"frame-without-cm" ) << QStringLiteral(
"BO_ 1 \"Ignored\";" );
+
491 QTest::newRow(
"missing-subtype" ) << QStringLiteral(
"CM_" );
+
492 QTest::newRow(
"global-comment" ) << QStringLiteral(
"CM_ \"Ignored\";" );
+
493 QTest::newRow(
"node-comment" ) << QStringLiteral(
"CM_ BU_ ECU \"Ignored\";" );
+
494 QTest::newRow(
"environment-comment" ) << QStringLiteral(
"CM_ EV_ State \"Ignored\";" );
+
495 QTest::newRow(
"unknown-subtype" ) << QStringLiteral(
"CM_ OTHER_ 1 \"Ignored\";" );
+
+
+
498 void CoverageTest::ignoredCommentStatements() {
+
499 QFETCH(QString, statement);
+
+
+
+
503 frame.
name =
"Frame" ;
+
504 frame.
comment =
"Existing frame comment" ;
+
+
506 signal.
name =
"State" ;
+
507 signal.
comment =
"Existing signal comment" ;
+
508 frame.signals.push_back(signal);
+
509 database.
frames .push_back(frame);
+
+
+
+
+
+
515 QCOMPARE(database.
frames .size(), std::size_t(1));
+
516 QCOMPARE(database.
frames [0].canId, 1U);
+
517 QCOMPARE(database.
frames [0].name, frame.
name );
+
+
519 QCOMPARE(database.
frames [0].signals.size(), std::size_t(1));
+
520 QCOMPARE(database.
frames [0].signals[0].name, signal.
name );
+
521 QCOMPARE(database.
frames [0].signals[0].comment, signal.
comment );
+
522 QCOMPARE(context.currentFrame, &database.
frames [0]);
+
+
+
525 void CoverageTest::ambiguousValueReferences_data() {
+
526 QTest::addColumn<bool>(
"duplicateFrames" );
+
527 QTest::addColumn<bool>(
"extended" );
+
528 QTest::newRow(
"duplicate-standard-frames" ) <<
true <<
false ;
+
529 QTest::newRow(
"duplicate-extended-frames" ) <<
true <<
true ;
+
530 QTest::newRow(
"duplicate-signals-in-standard-frame" ) <<
false <<
false ;
+
531 QTest::newRow(
"duplicate-signals-in-extended-frame" ) <<
false <<
true ;
+
+
+
534 void CoverageTest::ambiguousValueReferences() {
+
535 QFETCH(
bool , duplicateFrames);
+
536 QFETCH(
bool , extended);
+
+
+
+
540 frame.
name =
"Frame" ;
+
+
+
543 signal.
name =
"State" ;
+
544 frame.signals.push_back(signal);
+
545 if (!duplicateFrames) frame.signals.push_back(signal);
+
546 database.
frames .push_back(frame);
+
547 if (duplicateFrames) database.
frames .push_back(frame);
+
+
+
+
+
552 context.lineNumber = 37U;
+
553 const std::string rawId = extended ?
"2147483649" :
"1" ;
+
+
555 QCOMPARE(context.pendingValues.size(), std::size_t(1));
+
556 QCOMPARE(context.pendingValues[0].lineNumber, std::size_t(37));
+
557 const std::string path =
"manual database.dbc" ;
+
+
559 context.ResolveValueDescriptions(path);
+
560 QFAIL(
"The resolver must reject an ambiguous target" );
+
561 }
catch (
const std::runtime_error &error) {
+
562 const std::string message = duplicateFrames ?
"Ambiguous VAL_ frame reference."
+
563 :
"Ambiguous VAL_ signal reference: State" ;
+
564 QCOMPARE(std::string(error.what()), path +
":37: " + message);
+
+
+
567 for (
const FrameInfo &candidate: database.frames)
+
568 for (const
SignalInfo &candidateSignal: candidate.signals)
+
569 QVERIFY(candidateSignal.valueDescriptions.empty());
+
+
+
572 void CoverageTest::valueReferenceScope() {
+
+
+
+
+
577 signal.
name =
"State" ;
+
578 frame.signals.push_back(signal);
+
579 database.
frames .push_back(frame);
+
+
581 database.
frames .push_back(frame);
+
+
+
584 database.
frames .push_back(frame);
+
+
+
+
588 context.lineNumber = 3U;
+
589 handler.
Handle (
"VAL_ 1 State 0 \"Standard\";" , context);
+
590 context.lineNumber = 7U;
+
591 handler.
Handle (
"VAL_ 2147483649 State 0 \"Extended\";" , context);
+
592 context.ResolveValueDescriptions(
"manual database.dbc" );
+
+
594 const std::string *standard = FindValueDescription(database.
frames [0].signals[0].valueDescriptions, std::uint64_t(0));
+
595 const std::string *extended = FindValueDescription(database.
frames [1].signals[0].valueDescriptions, std::uint64_t(0));
+
596 QVERIFY(standard !=
nullptr );
+
597 QVERIFY(extended !=
nullptr );
+
598 QCOMPARE(*standard, std::string(
"Standard" ));
+
599 QCOMPARE(*extended, std::string(
"Extended" ));
+
600 QVERIFY(database.
frames [2].signals[0].valueDescriptions.empty());
+
+
+
603 void CoverageTest::fileFormatting_data() {
+
604 QTest::addColumn<QString>(
"text" );
+
605 QTest::addColumn<unsigned>(
"frames" );
+
606 QTest::newRow(
"empty" ) << QString::fromUtf8(
"" ) << 0U;
+
607 QTest::newRow(
"whitespace" ) << QString::fromUtf8(
" \t\r\n\n\t" ) << 0U;
+
608 QTest::newRow(
"unknown-only" ) << QString::fromUtf8(
"VERSION \"test\"\nBU_: ECU\nUNKNOWN_ data\n" ) << 0U;
+
609 QTest::newRow(
"no-final-newline" ) << QString::fromUtf8(
"BO_ 1 Frame: 1 ECU\nSG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU" ) << 1U;
+
610 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;
+
+
+
613 void CoverageTest::fileFormatting() {
+
614 QFETCH(QString, text);
+
615 QFETCH(
unsigned , frames);
+
616 const DbcDatabase parsed = ParseText(text.toStdString());
+
617 QCOMPARE(parsed.
frames .size(), std::size_t(frames));
+
+
619 QCOMPARE(parsed.
frames [0].signals.size(), std::size_t(1));
+
620 if (text.contains(
"\r\nBO_" )) {
+
621 QCOMPARE(parsed.
frames [0].comment, std::string(
"Comment" ));
+
622 const std::string *description = FindValueDescription(parsed.
frames [0].signals[0].valueDescriptions, std::uint64_t(0));
+
623 QVERIFY(description !=
nullptr );
+
624 QCOMPARE(*description, std::string(
"Off" ));
+
+
+
+
+
629 void CoverageTest::missingFile() {
+
+
631 QVERIFY(file.open());
+
632 const QString path = file.fileName();
+
633 QVERIFY(file.remove());
+
+
+
636 QFAIL(
"Missing file must throw" );
+
637 }
catch (
const std::runtime_error &error) {
+
638 QCOMPARE(std::string(error.what()),
"Failed to open DBC file: " + path.toStdString());
+
+
+
+
642 void CoverageTest::builders() {
+
+
644 QVERIFY(emptyRuntime.
GetFrames ().empty());
+
+
+
647 QCOMPARE(emptyTree->GetType(), NodeType::Root);
+
648 QCOMPARE(emptyTree->GetName(), std::string(
"dbc" ));
+
649 QCOMPARE(emptyTree->GetChildCount(), std::size_t(0));
+
650 QVERIFY(emptyTree->GetFrame() ==
nullptr && emptyTree->GetSignal() ==
nullptr );
+
+
652 "BO_ 256 Standard: 3 ECU1\n"
+
653 "SG_ Mode M : 0|8@1+ (2,3) [0|513] \"mode\" ECU1,ECU2\n"
+
654 "SG_ Branch m1 : 15|8@0- (-2,5) [-249|261] \"rpm\" ECU2,ECU3\n"
+
655 "SG_ Always : 16|8@1+ (0.25,-1) [-1|62.75] \"V\" ECU3\n"
+
656 "CM_ BO_ 256 \"Frame comment\";\nCM_ SG_ 256 Branch \"Branch comment\";\n"
+
657 "VAL_ 256 Branch -1 \"Negative\" 1 \"Positive\";\n"
+
658 "BO_ 2163212866 Extended: 8 ECU4\n" );
+
+
660 std::unique_ptr<TreeNode> tree;
+
+
+
+
+
665 source.
frames [0].name =
"Changed" ;
+
666 source.
frames [0].signals[1].receivers.clear();
+
667 source.
frames [0].signals[1].valueDescriptions.clear();
+
+
+
+
671 QCOMPARE(tree->GetChildCount(), expected.
frames .size());
+
672 for (std::size_t i = 0; i < expected.
frames .size(); ++i) {
+
+
+
+
+
677 QCOMPARE(node->
GetType (), NodeType::Frame);
+
+
+
+
+
+
683 QCOMPARE(decodedFrame.
name , frame.
name );
+
+
+
+
+
688 QCOMPARE(copied.
dlc , frame.
dlc );
+
689 QCOMPARE(decodedFrame.
dlc , frame.
dlc );
+
690 QCOMPARE(copied.
pgn , frame.
pgn );
+
691 QCOMPARE(decodedFrame.
pgn , frame.
pgn );
+
+
+
+
+
+
+
+
699 QCOMPARE(copied.signals.size(), frame.signals.size());
+
700 QCOMPARE(decodedFrame.signals.size(), frame.signals.size());
+
701 for (std::size_t j = 0; j < frame.signals.size(); ++j) {
+
702 const SignalInfo &original = frame.signals[j];
+
+
+
+
706 QCOMPARE(leaf->
GetType (), NodeType::Signal);
+
+
708 QVERIFY(leaf->
GetFrame () ==
nullptr );
+
+
+
711 QCOMPARE(copy->name, original.
name );
+
712 QCOMPARE(copy->startBit, original.
startBit );
+
713 QCOMPARE(copy->length, original.
length );
+
+
715 QCOMPARE(copy->isSigned, original.
isSigned );
+
716 QCOMPARE(copy->factor, original.
factor );
+
717 QCOMPARE(copy->offset, original.
offset );
+
718 QCOMPARE(copy->minimum, original.
minimum );
+
719 QCOMPARE(copy->maximum, original.
maximum );
+
720 QCOMPARE(copy->unit, original.
unit );
+
721 QCOMPARE(copy->comment, original.
comment );
+
722 QVERIFY(copy->receivers == original.
receivers );
+
+
+
+
+
727 QCOMPARE(target.
name , original.
name );
+
+
+
+
+
+
+
+
+
736 QCOMPARE(target.
unit , original.
unit );
+
+
+
+
+
+
+
+
+
+
746 void CoverageTest::physicalConversion_data() {
+
747 QTest::addColumn<double>(
"factor" );
+
748 QTest::addColumn<double>(
"offset" );
+
749 QTest::addColumn<double>(
"expected" );
+
750 QTest::newRow(
"zero-factor" ) << 0.0 << 7.0 << 7.0;
+
751 QTest::newRow(
"negative-factor" ) << -2.0 << 5.0 << -15.0;
+
752 QTest::newRow(
"above-declared-range" ) << 2.0 << 3.0 << 23.0;
+
+
+
755 void CoverageTest::physicalConversion() {
+
756 QFETCH(
double , factor);
+
757 QFETCH(
double , offset);
+
758 QFETCH(
double , expected);
+
+
+
+
+
+
+
+
+
+
+
+
770 QVERIFY(decoded.signals[0].
valid );
+
771 QCOMPARE(std::get<std::uint64_t>(decoded.signals[0].rawValue), std::uint64_t(10));
+
772 QCOMPARE(decoded.signals[0].physicalValue, expected);
+
+
+
775 void CoverageTest::multiplexingScenarios() {
+
+
777 "BO_ 1 Frame: 1 ECU\nSG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n" ));
+
+
+
+
+
782 QCOMPARE(only.signals.size(), std::size_t(1));
+
783 QVERIFY(only.signals[0].
valid );
+
+
785 "BO_ 1 First: 3 ECU\n"
+
786 "SG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n"
+
787 "SG_ A m0 : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
+
788 "SG_ B m0 : 16|8@1+ (1,0) [0|255] \"\" ECU\n"
+
789 "BO_ 2 Second: 2 ECU\n"
+
790 "SG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n"
+
791 "SG_ A m1 : 8|8@1+ (1,0) [0|255] \"\" ECU\n" ));
+
792 raw.
data = {0U, 42U, 99U};
+
+
794 QVERIFY(first.signals[1].
valid && first.signals[2].
valid );
+
795 QCOMPARE(std::get<std::uint64_t>(first.signals[1].rawValue), std::uint64_t(42));
+
796 QCOMPARE(std::get<std::uint64_t>(first.signals[2].rawValue), std::uint64_t(99));
+
+
+
799 QCOMPARE(secondInactive.signals[1].
status , SignalDecodeStatus::Inactive);
+
+
801 QVERIFY(
DbcDecoder ().Decode(database, raw).signals[1].valid);
+
+
+
804 QCOMPARE(firstInactive.signals[1].
status , SignalDecodeStatus::Inactive);
+
805 QCOMPARE(firstInactive.signals[2].
status , SignalDecodeStatus::Inactive);
+
+
+
808 void CoverageTest::multiplexingErrorLocations_data() {
+
809 QTest::addColumn<QString>(
"text" );
+
810 QTest::addColumn<unsigned>(
"line" );
+
811 QTest::addColumn<QString>(
"message" );
+
812 const QString header =
"BO_ 1 Frame: 3 ECU\n\n" ;
+
813 const QString selector =
"SG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n" ;
+
814 const QString branch =
"SG_ A m1 : 8|8@1+ (1,0) [0|255] \"\" ECU\n" ;
+
815 QTest::newRow(
"missing-selector" ) << header + branch << 3U << QString::fromUtf8(
"Multiplexed branch has no selector." );
+
816 QTest::newRow(
"second-selector" ) << header + selector +
"\nSG_ Other M : 16|1@1+ (1,0) [0|1] \"\" ECU\n"
+
817 << 5U << QString::fromUtf8(
"Multiplexing requires one unsigned selector per frame." );
+
818 QTest::newRow(
"signed-selector" ) << header +
"SG_ Mode M : 0|1@1- (1,0) [-1|0] \"\" ECU\n"
+
819 << 3U << QString::fromUtf8(
"Multiplexing requires one unsigned selector per frame." );
+
820 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." );
+
821 QTest::newRow(
"same-branch-overlap" ) << header + selector + branch +
"SG_ B m1 : 15|8@0+ (1,0) [0|255] \"\" ECU\n"
+
822 << 5U << QString::fromUtf8(
"Signals overlap without mutually exclusive multiplexing conditions." );
+
823 QTest::newRow(
"selector-overlap" ) << header + selector +
"SG_ A m1 : 0|1@1+ (1,0) [0|1] \"\" ECU\n"
+
824 << 4U << QString::fromUtf8(
"Signals overlap without mutually exclusive multiplexing conditions." );
+
825 QTest::newRow(
"unconditional-overlap" ) << header + selector + branch +
"SG_ Always : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
+
826 << 5U << QString::fromUtf8(
"Signals overlap without mutually exclusive multiplexing conditions." );
+
827 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"
+
828 << 4U << QString::fromUtf8(
"Signals overlap without mutually exclusive multiplexing conditions." );
+
829 QTest::newRow(
"extended-multiplexing" ) << header +
"SG_MUL_VAL_ 1 A Mode 1-2;\n"
+
830 << 3U << QString::fromUtf8(
"Extended and nested multiplexing are unsupported." );
+
831 QTest::newRow(
"nested-marker" ) << header +
"SG_ A m1M : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
+
832 << 3U << QString::fromUtf8(
"Invalid or unsupported multiplexing marker." );
+
+
+
835 void CoverageTest::multiplexingErrorLocations() {
+
836 QFETCH(QString, text);
+
837 QFETCH(
unsigned , line);
+
838 QFETCH(QString, message);
+
+
840 QVERIFY(file.open());
+
841 const QByteArray content = text.toUtf8();
+
842 QCOMPARE(file.write(content), qint64(content.size()));
+
843 QVERIFY(file.flush());
+
+
+
846 QFAIL(
"Expected multiplexing rejection" );
+
847 }
catch (
const std::runtime_error &error) {
+
848 QCOMPARE(QString::fromStdString(error.what()), file.fileName() +
":" + QString::number(line) +
": " + message);
+
+
+
+
852 void CoverageTest::escapedValueDescriptions() {
+
+
854 "BO_ 1 Frame: 1 ECU\nSG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
+
855 R
"dbc(VAL_ 1 State -0 "Ноль" 1 "C:\\trace" 2 "\\\"quoted\"\\";)dbc"
+
+
857 const ValueDescriptions &values = parsed.
frames [0].signals[0].valueDescriptions;
+
858 QCOMPARE(values.size(), std::size_t(3));
+
859 QVERIFY(values.find(RawSignalValue(std::int64_t(0))) == values.end());
+
860 const std::string *zero = FindValueDescription(values, std::int64_t(0));
+
861 const std::string *path = FindValueDescription(values, std::uint64_t(1));
+
862 const std::string *quoted = FindValueDescription(values, std::uint64_t(2));
+
863 QVERIFY(zero && path && quoted);
+
864 QCOMPARE(*zero, std::string(
"Ноль" ));
+
865 QCOMPARE(*path, std::string(
"C:\\trace" ));
+
866 QCOMPARE(*quoted, std::string(
"\\\"quoted\"\\" ));
+
867 QVERIFY(NormalizeValueKey(RawSignalValue(std::int64_t(0))) == RawSignalValue(std::uint64_t(0)));
+
868 QVERIFY(NormalizeValueKey(RawSignalValue(std::int64_t(-1))) == RawSignalValue(std::int64_t(-1)));
+
+
+
871 void CoverageTest::factory() {
+
+
873 QVERIFY(!factory.
contains (
"value" ));
+
874 QVERIFY_THROWS_EXCEPTION(std::out_of_range,
static_cast< void > (factory.
creator (
"missing" )));
+
875 QVERIFY_THROWS_EXCEPTION(std::out_of_range,
static_cast< void > (factory.
create (
"missing" , std::make_unique<int>(1))));
+
+
+
878 std::unique_ptr<int> argument = std::make_unique<int>(42);
+
879 const std::shared_ptr<FactoryBase> first = factory.
create (
"value" , std::move(argument));
+
880 QVERIFY(argument ==
nullptr );
+
881 QCOMPARE(first->Value(), 42);
+
+
883 QCOMPARE(creator(std::make_unique<int>(7))->Value(), 7);
+
+
885 QCOMPARE(factory.
create (
"value" , std::make_unique<int>(42))->Value(), 43);
+
886 QCOMPARE(first->Value(), 42);
+
887 QCOMPARE(creator(std::make_unique<int>(7))->Value(), 7);
+
+
+
890 int RunCoverageTests(
int argc,
char **argv) {
+
+
892 return QTest::qExec(&tests, argc, argv);
+
+
894 #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.
-
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.
-
-
DbcDatabase ParseFile(const std::string &filePath) const
Parse DBC file.
+
Runtime CAN decoder using prebuilt decode database.
+
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 exact CAN ID first, then unique PGN among explicitly J1939 definitions.
+
+
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.
-
const SignalInfo * GetSignal() const
Get signal payload if node is signal.
-
const TreeNode * GetChild(std::size_t index) const
Get child by index.
-
const std::string & GetName() const
Get display name.
-
std::size_t GetChildCount() const
Get child count.
-
NodeType GetType() const
Get node type.
-
const FrameInfo * GetFrame() const
Get frame payload if node is frame.
+
Defer raw value descriptions for target resolution.
+
void Handle(const std::string &line, DbcParseContext &context) const override
Process a trimmed statement using state belonging to this parse.
+
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
+
PgnLookupResult FindFrameByPgn(std::uint32_t pgn) const
+
Tree node for later use in model/view or other hierarchy consumers.
+
const SignalInfo * GetSignal() const
Get signal payload if node is signal.
+
const TreeNode * GetChild(std::size_t index) const
Get child by index.
+
const std::string & GetName() const
Get display name.
+
std::size_t GetChildCount() const
Get child count.
+
NodeType GetType() const
Get node type.
+
const FrameInfo * GetFrame() const
Get frame payload if node is frame.
Registry-based factory for creating objects by runtime identifier.
-
bool contains(const ClassId &id) const
Checks whether an id is registered.
-
BasePtr create(const ClassId &id, Args... args) const
Creates an instance for the given id using provided arguments.
-
void registerType(const ClassId &id)
Registers a Derived type under the given id.
-
CreatorFn creator(const ClassId &id) const
Returns creator function for the given id.
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
-
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.
+
bool contains(const ClassId &id) const
Checks whether an id is registered.
+
BasePtr create(const ClassId &id, Args... args) const
Creates an instance for the given id using provided arguments.
+
void registerType(const ClassId &id)
Registers a Derived type under the given id.
+
CreatorFn creator(const ClassId &id) const
Returns creator function for the given id.
+
Runtime decode database builder.
+
CAN frame decoding API and result types.
+
+
DBC file parser and interpretation options.
+
+
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-ready frame definition.
-
-
-
-
-
-
-
-
-
Runtime-ready signal definition.
-
-
-
-
-
-
ValueDescriptions valueDescriptions
-
-
-
-
std::vector< std::string > receivers
-
-
-
-
-
std::shared_ptr< const DecodeFrame > definition
-
-
-
Describes one CAN frame from a DBC file.
-
-
-
-
-
-
-
-
+
+
+
Runtime-ready frame definition.
+
FrameKey GetKey() const
Return the stable normalized frame identifier.
+
+
+
+
+
+
+
+
+
Runtime-ready signal definition.
+
+
+
+
+
+
ValueDescriptions valueDescriptions
+
+
+
+
std::vector< std::string > receivers
+
+
+
+
Multiplexing multiplexing
+
+
+
std::shared_ptr< const DecodeFrame > definition
+
+
+
Describes one CAN frame from a DBC file.
+
+
+
+
+
+
+
+
Stable frame identifier: normalized CAN ID and frame type.
+
+
+
+
+
std::shared_ptr< const DecodeFrame > definition
Raw CAN frame used for runtime or trace decoding.
std::vector< std::uint8_t > data
-
Describes one signal inside a DBC frame.
-
-
-
std::vector< std::string > receivers
-
-
ValueDescriptions valueDescriptions
-
-
-
-
-
-
-
-
+
Describes one signal inside a DBC frame.
+
+
+
std::vector< std::string > receivers
+
+
ValueDescriptions valueDescriptions
+
+
Multiplexing multiplexing
+
+
+
+
+
+
+
+
diff --git a/docs/html/dbc__database_8h.html b/docs/html/dbc__database_8h.html
index 0756b17..a4ed480 100644
--- a/docs/html/dbc__database_8h.html
+++ b/docs/html/dbc__database_8h.html
@@ -96,7 +96,7 @@ $(document).ready(function(){initNavTree('dbc__database_8h.html',''); initResiza
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Parsed DBC database and attribute metadata.
More...
#include <vector>
#include "frame_info.h "
@@ -110,7 +110,8 @@ Classes
-Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Parsed DBC database and attribute metadata.
+
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Licensed under the MIT License. See LICENSE file in the project root for full license text.
Definition in file dbc_database.h .
diff --git a/docs/html/dbc__database_8h_source.html b/docs/html/dbc__database_8h_source.html
index d9baf55..7047815 100644
--- a/docs/html/dbc__database_8h_source.html
+++ b/docs/html/dbc__database_8h_source.html
@@ -109,13 +109,19 @@ $(document).ready(function(){initNavTree('dbc__database_8h_source.html',''); ini
-
-
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
+
+
Parsed CAN frame metadata.
Parsed DBC content stored in a simple internal form.
+
std::map< std::string, AttributeDefinition > attributeDefinitions
std::vector< FrameInfo > frames
+
+
std::vector< AttributeAssignment > attributeAssignments
diff --git a/docs/html/dbc__decode__builder_8cpp.html b/docs/html/dbc__decode__builder_8cpp.html
index 7e51f3b..9f992eb 100644
--- a/docs/html/dbc__decode__builder_8cpp.html
+++ b/docs/html/dbc__decode__builder_8cpp.html
@@ -94,14 +94,15 @@ $(document).ready(function(){initNavTree('dbc__decode__builder_8cpp.html',''); i
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Conversion of parsed metadata to runtime definitions.
More...
#include "dbc_decode_builder.h "
#include <utility>
Go to the source code of this file.
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Conversion of parsed metadata to runtime definitions.
+
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Licensed under the MIT License. See LICENSE file in the project root for full license text.
Definition in file dbc_decode_builder.cpp .
diff --git a/docs/html/dbc__decode__builder_8cpp_source.html b/docs/html/dbc__decode__builder_8cpp_source.html
index beb7ec0..d26faa2 100644
--- a/docs/html/dbc__decode__builder_8cpp_source.html
+++ b/docs/html/dbc__decode__builder_8cpp_source.html
@@ -110,73 +110,82 @@ $(document).ready(function(){initNavTree('dbc__decode__builder_8cpp_source.html'
-
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;
-
-
29 targetFrame.
comment = sourceFrame.comment;
-
-
31 targetFrame.signals.reserve(sourceFrame.signals.size());
-
32 for (
const SignalInfo &sourceSignal: sourceFrame.signals) {
-
-
-
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;
-
-
-
50 targetFrame.signals.push_back(std::move(targetSignal));
-
-
-
53 frames.push_back(std::move(targetFrame));
-
-
-
-
+
22 targetFrame.
attributes = sourceFrame.attributes;
+
+
+
25 targetFrame.
name = sourceFrame.name;
+
26 targetFrame.
canId = sourceFrame.canId;
+
27 targetFrame.
isExtended = sourceFrame.isExtended;
+
28 targetFrame.
dlc = sourceFrame.dlc;
+
29 targetFrame.
pgn = sourceFrame.pgn;
+
30 targetFrame.
hasPgn = sourceFrame.hasPgn;
+
+
32 targetFrame.
comment = sourceFrame.comment;
+
+
34 targetFrame.signals.reserve(sourceFrame.signals.size());
+
35 for (
const SignalInfo &sourceSignal: sourceFrame.signals) {
+
+
+
38 targetSignal.
attributes = sourceSignal.attributes;
+
+
40 targetSignal.
name = sourceSignal.name;
+
41 targetSignal.
startBit = sourceSignal.startBit;
+
42 targetSignal.
length = sourceSignal.length;
+
43 targetSignal.
byteOrder = sourceSignal.isLittleEndian ? ByteOrder::Intel : ByteOrder::Motorola;
+
44 targetSignal.
valueType = sourceSignal.isSigned ? ValueType::Signed : ValueType::Unsigned;
+
45 targetSignal.
factor = sourceSignal.factor;
+
46 targetSignal.
offset = sourceSignal.offset;
+
47 targetSignal.
minimum = sourceSignal.minimum;
+
48 targetSignal.
maximum = sourceSignal.maximum;
+
49 targetSignal.
unit = sourceSignal.unit;
+
50 targetSignal.
receivers = sourceSignal.receivers;
+
51 targetSignal.
comment = sourceSignal.comment;
+
+
+
54 targetFrame.signals.push_back(std::move(targetSignal));
+
+
+
57 frames.push_back(std::move(targetFrame));
+
+
+
+
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)
+
Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles a...
+
Runtime decode database builder.
Parsed DBC content stored in a simple internal form.
std::vector< FrameInfo > frames
-
Runtime-ready frame definition.
-
-
-
-
-
-
-
-
-
Runtime-ready signal definition.
-
-
-
-
-
-
ValueDescriptions valueDescriptions
-
-
-
-
std::vector< std::string > receivers
-
-
-
-
Describes one CAN frame from a DBC file.
-
Describes one signal inside a DBC frame.
+
Runtime-ready frame definition.
+
+
+
+
+
std::optional< std::string > frameFormat
+
+
+
std::optional< std::uint32_t > cycleTimeMs
+
+
+
+
Runtime-ready signal definition.
+
+
+
+
+
+
+
ValueDescriptions valueDescriptions
+
+
+
+
std::vector< std::string > receivers
+
+
+
+
Multiplexing multiplexing
+
Describes one CAN frame from a DBC file.
+
Describes one signal inside a DBC frame.
diff --git a/docs/html/dbc__decode__builder_8h.html b/docs/html/dbc__decode__builder_8h.html
index 5cb0a9e..94d2f78 100644
--- a/docs/html/dbc__decode__builder_8h.html
+++ b/docs/html/dbc__decode__builder_8h.html
@@ -96,7 +96,7 @@ $(document).ready(function(){initNavTree('dbc__decode__builder_8h.html',''); ini
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Runtime decode database builder.
More...
#include "dbc_database.h "
#include "decode_database.h "
@@ -110,7 +110,8 @@ Classes
-Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Runtime decode database builder.
+
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Licensed under the MIT License. See LICENSE file in the project root for full license text.
Definition in file dbc_decode_builder.h .
diff --git a/docs/html/dbc__decode__builder_8h_source.html b/docs/html/dbc__decode__builder_8h_source.html
index d2858de..279f214 100644
--- a/docs/html/dbc__decode__builder_8h_source.html
+++ b/docs/html/dbc__decode__builder_8h_source.html
@@ -115,9 +115,9 @@ $(document).ready(function(){initNavTree('dbc__decode__builder_8h_source.html','
Converts parsed DBC data into 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)
+
Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles a...
+
Parsed DBC database and attribute metadata.
+
Runtime definitions and immutable indexed database.
Parsed DBC content stored in a simple internal form.
diff --git a/docs/html/dbc__decoder_8cpp.html b/docs/html/dbc__decoder_8cpp.html
index f3b5822..05fe284 100644
--- a/docs/html/dbc__decoder_8cpp.html
+++ b/docs/html/dbc__decoder_8cpp.html
@@ -94,16 +94,20 @@ $(document).ready(function(){initNavTree('dbc__decoder_8cpp.html',''); initResiz
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
CAN signal extraction and physical value conversion.
More...
#include "dbc_decoder.h "
+
#include "j1939.h"
#include "signal_layout.h"
#include <cmath>
+
#include <stdexcept>
+
#include <unordered_set>
#include <utility>
Go to the source code of this file.
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
CAN signal extraction and physical value conversion.
+
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Licensed under the MIT License. See LICENSE file in the project root for full license text.
Definition in file dbc_decoder.cpp .
diff --git a/docs/html/dbc__decoder_8cpp_source.html b/docs/html/dbc__decoder_8cpp_source.html
index 1df1057..43989dc 100644
--- a/docs/html/dbc__decoder_8cpp_source.html
+++ b/docs/html/dbc__decoder_8cpp_source.html
@@ -100,249 +100,308 @@ $(document).ready(function(){initNavTree('dbc__decoder_8cpp_source.html',''); in
Go to the documentation of this file.
-
13 #include "signal_layout.h"
-
-
-
-
-
-
-
19 bool isExtended)
const {
-
-
+
+
14 #include "signal_layout.h"
+
+
+
17 #include <unordered_set>
+
+
+
+
+
+
22 bool isExtended)
const {
+
23 return ResolveFrame(database, canId, isExtended).
definition ;
+
-
-
-
-
-
-
-
-
-
29 if (definition ==
nullptr )
-
-
-
-
-
34 result.
status = frame.
data .size() < definition->dlc
-
35 ? FrameDecodeStatus::InsufficientPayload
-
36 : FrameDecodeStatus::Valid;
-
-
38 const SelectorState selector = ReadSelector(*definition, frame);
-
39 result.signals.reserve(definition->signals.size());
-
-
41 DecodedSignalValue decoded = DecodeOneSignal(signal, definition->dlc, frame, selector);
-
42 if (!decoded.
valid && decoded.status != SignalDecodeStatus::Inactive &&
-
43 result.
status == FrameDecodeStatus::Valid)
-
44 result.
status = FrameDecodeStatus::SignalErrors;
-
45 decoded.
definition = std::shared_ptr<const DecodeSignal>(definition, &signal);
-
-
47 result.signals.push_back(std::move(decoded));
-
-
-
-
+
+
+
27 std::uint32_t canId,
bool isExtended) {
+
28 const std::shared_ptr<const DecodeFrame> exact = database.
FindFrame (
FrameKey (canId, isExtended));
+
+
30 return {exact,
false };
+
31 if (!isExtended || canId > 0x1FFFFFFFU)
+
+
+
+
+
+
+
+
38 return DecodeImpl(database, frame,
nullptr );
+
-
-
53 bool DbcDecoder::IsValidDefinition(
const DecodeSignal &signal, std::uint8_t dlc) {
-
-
-
-
57 (signal.multiplexing.role != MultiplexRole::Unconditional &&
-
58 signal.multiplexing.role != MultiplexRole::Selector &&
-
59 signal.multiplexing.role != MultiplexRole::Branch))
-
+
+
+
+
+
43 const std::vector<SignalKey> &selection)
const {
+
44 return DecodeImpl(database, frame, &selection);
+
+
+
+
+
+
49 const std::vector<SignalKey> *selection)
const {
+
+
+
+
+
54 result.
status = FrameDecodeStatus::AmbiguousFrame;
+
+
+
57 const std::shared_ptr<const DecodeFrame> definition = match.
definition ;
+
58 if (definition ==
nullptr )
+
+
60 result.
key = definition->GetKey();
-
-
63 signal.
byteOrder == ByteOrder::Intel, dlc);
-
-
-
66 DbcDecoder::SelectorState DbcDecoder::ReadSelector(
const DecodeFrame &definition,
-
-
68 SelectorState selector;
-
69 std::size_t count = 0U;
-
-
71 if (signal.multiplexing.role == MultiplexRole::Selector) {
-
72 selector.definition = &signal;
-
-
-
-
-
-
-
-
80 selector.valid = signal.
valueType == ValueType::Unsigned &&
-
81 IsValidDefinition(signal, definition.
dlc );
-
82 selector.available = selector.valid && ExtractUnsigned(frame.
data , signal, selector.value);
-
-
-
-
-
-
-
89 const SelectorState &selector) {
-
-
91 std::uint64_t unsignedValue = 0U;
-
-
93 if (!IsValidDefinition(signal, dlc) ||
-
94 (signal.multiplexing.role != MultiplexRole::Unconditional && !selector.valid)) {
-
+
62 std::vector<const DecodeSignal *> selected;
+
63 if (selection !=
nullptr ) {
+
64 selected.reserve(selection->size());
+
65 std::unordered_set<SignalKey, SignalKeyHasher> keys;
+
+
67 if (!(key.frame == result.
key ))
+
68 throw std::invalid_argument(
"Selected signal belongs to another frame: " + key.name);
+
69 if (!keys.insert(key).second)
+
70 throw std::invalid_argument(
"Duplicate selected signal: " + key.name);
+
71 const std::shared_ptr<const DecodeSignal> signal = database.
FindSignal (key);
+
+
73 throw std::invalid_argument(
"Unknown selected signal: " + key.name);
+
74 selected.push_back(signal.get());
+
+
+
+
+
+
80 result.
status = frame.
data .size() < definition->dlc
+
81 ? FrameDecodeStatus::InsufficientPayload
+
82 : FrameDecodeStatus::Valid;
+
+
84 const SelectorState selector = ReadSelector(*definition, frame);
+
85 const std::size_t count = selection !=
nullptr ? selected.size() : definition->signals.size();
+
86 result.signals.reserve(count);
+
87 for (std::size_t index = 0U; index < count; ++index) {
+
88 const DecodeSignal &signal = selection !=
nullptr ? *selected[index] : definition->signals[index];
+
89 DecodedSignalValue decoded = DecodeOneSignal(signal, definition->dlc, frame, selector);
+
90 if (!decoded.
valid && decoded.
status != SignalDecodeStatus::Inactive &&
+
91 result.
status == FrameDecodeStatus::Valid)
+
92 result.
status = FrameDecodeStatus::SignalErrors;
+
93 decoded.
definition = std::shared_ptr<const DecodeSignal>(definition, &signal);
+
+
95 result.signals.push_back(std::move(decoded));
-
97 if (signal.multiplexing.role == MultiplexRole::Branch) {
-
98 if (selector.definition->length < 64U && signal.multiplexing.value >= (std::uint64_t(1U) << selector.definition->length)) {
-
-
-
101 if (!selector.available) {
-
102 decoded.status = SignalDecodeStatus::SelectorUnavailable;
-
-
-
105 if (signal.multiplexing.value != selector.value) {
-
106 decoded.status = SignalDecodeStatus::Inactive;
-
-
-
-
110 if (!ExtractUnsigned(frame.
data , signal, unsignedValue)) {
-
111 decoded.status = SignalDecodeStatus::InsufficientPayload;
-
-
-
-
115 if (signal.
valueType == ValueType::Signed)
-
-
-
-
-
-
121 if (
const std::int64_t *signedValue = std::get_if<std::int64_t>(&decoded.
rawValue ))
-
122 numericValue =
static_cast< double > (*signedValue);
-
-
124 numericValue =
static_cast< double > (std::get<std::uint64_t>(decoded.
rawValue ));
-
-
-
127 decoded.status = SignalDecodeStatus::PhysicalConversionFailed;
-
-
-
130 decoded.
valid =
true ;
-
131 decoded.status = SignalDecodeStatus::Valid;
+
+
+
+
+
101 bool DbcDecoder::IsValidDefinition(
const DecodeSignal &signal, std::uint8_t dlc) {
+
102 if ((signal.
byteOrder != ByteOrder::Intel && signal.
byteOrder != ByteOrder::Motorola) ||
+
+
+
+
+
+
+
+
110 signal.
byteOrder == ByteOrder::Intel, dlc);
+
+
+
113 DbcDecoder::SelectorState DbcDecoder::ReadSelector(
const DecodeFrame &definition,
+
+
115 SelectorState selector;
+
116 std::size_t count = 0U;
+
+
+
119 selector.definition = &signal;
+
+
+
+
+
+
+
+
127 selector.valid = signal.
valueType == ValueType::Unsigned &&
+
128 IsValidDefinition(signal, definition.
dlc );
+
129 selector.available = selector.valid && ExtractUnsigned(frame.
data , signal, selector.value);
+
+
-
-
-
-
136 bool DbcDecoder::ExtractUnsigned(
const std::vector<std::uint8_t> &data,
-
-
138 std::uint64_t &value) {
-
-
-
-
142 if (signal.
byteOrder == ByteOrder::Intel)
-
-
-
145 return ExtractMotorola(data, signal.
startBit , signal.
length , value);
-
-
-
148 bool DbcDecoder::ExtractIntel(
const std::vector<std::uint8_t> &data,
-
149 std::uint32_t startBit,
-
150 std::uint32_t length,
-
151 std::uint64_t &value) {
-
-
-
154 for (std::uint32_t bitIndex = 0U; bitIndex < length; ++bitIndex) {
-
155 const std::uint64_t absoluteBit = std::uint64_t(startBit) + bitIndex;
-
156 const std::uint64_t byteIndex = absoluteBit / 8U;
-
157 const std::uint32_t bitInByte = absoluteBit % 8U;
-
-
159 if (byteIndex >= data.size())
-
+
+
+
+
136 const SelectorState &selector) {
+
+
138 std::uint64_t unsignedValue = 0U;
+
+
140 if (!IsValidDefinition(signal, dlc) ||
+
141 (signal.
multiplexing .
role != MultiplexRole::Unconditional && !selector.valid)) {
+
+
+
+
145 if (selector.definition->length < 64U && signal.
multiplexing .
value >= (std::uint64_t(1U) << selector.definition->length)) {
+
+
+
148 if (!selector.available) {
+
149 decoded.
status = SignalDecodeStatus::SelectorUnavailable;
+
+
+
+
153 decoded.
status = SignalDecodeStatus::Inactive;
+
+
+
+
157 if (!ExtractUnsigned(frame.
data , signal, unsignedValue)) {
+
158 decoded.
status = SignalDecodeStatus::InsufficientPayload;
+
+
-
162 const std::uint64_t bitValue =
-
163 (
static_cast< std::uint64_t
> ((data[byteIndex] >> bitInByte) & 0x01U) << bitIndex);
-
-
-
-
-
-
-
-
171 bool DbcDecoder::ExtractMotorola(
const std::vector<std::uint8_t> &data,
-
172 std::uint32_t startBit,
-
173 std::uint32_t length,
-
174 std::uint64_t &value) {
-
-
-
-
-
-
-
+
162 if (signal.
valueType == ValueType::Signed)
+
+
+
+
+
+
168 if (
const std::int64_t *signedValue = std::get_if<std::int64_t>(&decoded.
rawValue ))
+
169 numericValue =
static_cast< double > (*signedValue);
+
+
171 numericValue =
static_cast< double > (std::get<std::uint64_t>(decoded.
rawValue ));
+
+
+
174 decoded.
status = SignalDecodeStatus::PhysicalConversionFailed;
+
+
+
177 decoded.
valid =
true ;
+
178 decoded.
status = SignalDecodeStatus::Valid;
+
+
+
-
-
-
185 std::size_t byteIndex = startBit / 8U;
-
186 std::uint32_t bitInByte = startBit % 8U;
-
-
188 for (std::uint32_t bitIndex = 0U; bitIndex < length; ++bitIndex) {
-
189 if (byteIndex >= data.size())
-
+
183 bool DbcDecoder::ExtractUnsigned(
const std::vector<std::uint8_t> &data,
+
+
185 std::uint64_t &value) {
+
+
+
+
189 if (signal.
byteOrder == ByteOrder::Intel)
+
-
-
193 value |=
static_cast< std::uint64_t
> ((data[byteIndex] >> bitInByte) & 0x01U);
+
192 return ExtractMotorola(data, signal.
startBit , signal.
length , value);
+
-
195 if (bitInByte == 0U) {
-
-
-
-
-
-
-
-
-
-
205 std::int64_t DbcDecoder::SignExtend(std::uint64_t value, std::uint32_t bitLength) {
-
206 if ((bitLength == 0U) || (bitLength > 64U))
-
+
195 bool DbcDecoder::ExtractIntel(
const std::vector<std::uint8_t> &data,
+
196 std::uint32_t startBit,
+
197 std::uint32_t length,
+
198 std::uint64_t &value) {
+
+
+
201 for (std::uint32_t bitIndex = 0U; bitIndex < length; ++bitIndex) {
+
202 const std::uint64_t absoluteBit = std::uint64_t(startBit) + bitIndex;
+
203 const std::uint64_t byteIndex = absoluteBit / 8U;
+
204 const std::uint32_t bitInByte = absoluteBit % 8U;
+
+
206 if (byteIndex >= data.size())
+
-
209 const std::uint64_t signMask = std::uint64_t(1U) << (bitLength - 1U);
-
210 const std::uint64_t valueMask = (bitLength == 64U)
-
-
212 : (std::uint64_t(1U) << bitLength) - 1U;
-
+
209 const std::uint64_t bitValue =
+
210 (
static_cast< std::uint64_t
> ((data[byteIndex] >> bitInByte) & 0x01U) << bitIndex);
+
+
+
-
215 if ((value & signMask) == 0U)
-
216 return static_cast< std::int64_t
> (value);
+
+
-
-
219 return -1 -
static_cast< std::int64_t
> ((~value) & valueMask);
-
-
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-ready frame definition.
-
-
Runtime-ready signal definition.
-
-
-
-
-
-
-
-
-
std::shared_ptr< const DecodeFrame > definition
-
-
-
One decoded signal value.
-
-
-
-
std::shared_ptr< const DecodeSignal > definition
-
+
218 bool DbcDecoder::ExtractMotorola(
const std::vector<std::uint8_t> &data,
+
219 std::uint32_t startBit,
+
220 std::uint32_t length,
+
221 std::uint64_t &value) {
+
+
+
+
+
+
+
+
+
+
+
232 std::size_t byteIndex = startBit / 8U;
+
233 std::uint32_t bitInByte = startBit % 8U;
+
+
235 for (std::uint32_t bitIndex = 0U; bitIndex < length; ++bitIndex) {
+
236 if (byteIndex >= data.size())
+
+
+
+
240 value |=
static_cast< std::uint64_t
> ((data[byteIndex] >> bitInByte) & 0x01U);
+
+
242 if (bitInByte == 0U) {
+
+
+
+
+
+
+
+
+
+
252 std::int64_t DbcDecoder::SignExtend(std::uint64_t value, std::uint32_t bitLength) {
+
253 if ((bitLength == 0U) || (bitLength > 64U))
+
+
+
256 const std::uint64_t signMask = std::uint64_t(1U) << (bitLength - 1U);
+
257 const std::uint64_t valueMask = (bitLength == 64U)
+
+
259 : (std::uint64_t(1U) << bitLength) - 1U;
+
+
+
262 if ((value & signMask) == 0U)
+
263 return static_cast< std::int64_t
> (value);
+
+
+
266 return -1 -
static_cast< std::int64_t
> ((~value) & valueMask);
+
+
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 exact CAN ID first, then unique PGN among explicitly J1939 definitions.
+
Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles a...
+
std::shared_ptr< const DecodeSignal > FindSignal(const SignalKey &key) const
Return an owning signal handle, or an empty handle for a missing key.
+
std::shared_ptr< const DecodeFrame > FindFrame(const FrameKey &key) const
+
PgnLookupResult FindFrameByPgn(std::uint32_t pgn) const
+
CAN frame decoding API and result types.
+
Runtime-ready frame definition.
+
+
Runtime-ready signal definition.
+
+
+
+
+
+
+
+
Multiplexing multiplexing
+
+
+
std::shared_ptr< const DecodeFrame > definition
+
+
+
One decoded signal value.
+
+
+
+
std::shared_ptr< const DecodeSignal > definition
+
SignalDecodeStatus status
+
Stable frame identifier: normalized CAN ID and frame type.
+
+
+
+
+
std::shared_ptr< const DecodeFrame > definition
Raw CAN frame used for runtime or trace decoding.
std::vector< std::uint8_t > data
-
+
diff --git a/docs/html/dbc__decoder_8h.html b/docs/html/dbc__decoder_8h.html
index dd09886..d990ecf 100644
--- a/docs/html/dbc__decoder_8h.html
+++ b/docs/html/dbc__decoder_8h.html
@@ -97,7 +97,7 @@ $(document).ready(function(){initNavTree('dbc__decoder_8h.html',''); initResizab
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
CAN frame decoding API and result types.
More...
#include <cstdint>
#include <variant>
@@ -123,7 +123,7 @@ Classes
-enum class SignalDecodeStatus {
+enum class SignalDecodeStatus {
InvalidDefinition
, InsufficientPayload
, SelectorUnavailable
@@ -133,16 +133,22 @@ Enumerations
, PhysicalConversionFailed
}
+ Outcome of signal extraction and physical conversion. More...
-enum class FrameDecodeStatus { UnknownFrame
+enum class FrameDecodeStatus {
+ UnknownFrame
, InsufficientPayload
, SignalErrors
, Valid
+,
+ AmbiguousFrame
+
}
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
CAN frame decoding API and result types.
+
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Licensed under the MIT License. See LICENSE file in the project root for full license text.
Definition in file dbc_decoder.h .
@@ -157,7 +163,7 @@ Enumerations
@@ -167,7 +173,9 @@ Enumerations
@@ -192,7 +200,7 @@ Enumerations
Frame summary: short payload takes precedence over individual signal errors.
-
Definition at line 42 of file dbc_decoder.h .
+
Definition at line 43 of file dbc_decoder.h .
diff --git a/docs/html/dbc__decoder_8h.js b/docs/html/dbc__decoder_8h.js
index 8c0b117..b69e73f 100644
--- a/docs/html/dbc__decoder_8h.js
+++ b/docs/html/dbc__decoder_8h.js
@@ -4,10 +4,19 @@ var dbc__decoder_8h =
[ "DecodedSignalValue", "structDecodedSignalValue.html", "structDecodedSignalValue" ],
[ "DecodedFrameValue", "structDecodedFrameValue.html", "structDecodedFrameValue" ],
[ "DbcDecoder", "classDbcDecoder.html", "classDbcDecoder" ],
+ [ "SignalDecodeStatus", "dbc__decoder_8h.html#a5f4a41ee2810487020135b45e8d7559a", [
+ [ "InvalidDefinition", "dbc__decoder_8h.html#a5f4a41ee2810487020135b45e8d7559aaa20a6f8fa79aa562f9d3392c0060df54", null ],
+ [ "InsufficientPayload", "dbc__decoder_8h.html#a5f4a41ee2810487020135b45e8d7559aa7c9fa088a1e7db1fc83cb62aefd3ea7f", null ],
+ [ "SelectorUnavailable", "dbc__decoder_8h.html#a5f4a41ee2810487020135b45e8d7559aa6e43305edb6a91f66811f9af70346d81", null ],
+ [ "Inactive", "dbc__decoder_8h.html#a5f4a41ee2810487020135b45e8d7559aa3cab03c00dbd11bc3569afa0748013f0", null ],
+ [ "Valid", "dbc__decoder_8h.html#a5f4a41ee2810487020135b45e8d7559aa3ac705f2acd51a4613f9188c05c91d0d", null ],
+ [ "PhysicalConversionFailed", "dbc__decoder_8h.html#a5f4a41ee2810487020135b45e8d7559aae7d6c26841c7125dc32c49f3bbc8a436", null ]
+ ] ],
[ "FrameDecodeStatus", "dbc__decoder_8h.html#a855b2bc36cb18bfbae5ff30a2394e961", [
[ "UnknownFrame", "dbc__decoder_8h.html#a855b2bc36cb18bfbae5ff30a2394e961a85f5d387f9a01dce258470e1a5a23332", null ],
[ "InsufficientPayload", "dbc__decoder_8h.html#a855b2bc36cb18bfbae5ff30a2394e961a7c9fa088a1e7db1fc83cb62aefd3ea7f", null ],
[ "SignalErrors", "dbc__decoder_8h.html#a855b2bc36cb18bfbae5ff30a2394e961aedeb8da96660592dfe0853f212b77469", null ],
- [ "Valid", "dbc__decoder_8h.html#a855b2bc36cb18bfbae5ff30a2394e961a3ac705f2acd51a4613f9188c05c91d0d", null ]
+ [ "Valid", "dbc__decoder_8h.html#a855b2bc36cb18bfbae5ff30a2394e961a3ac705f2acd51a4613f9188c05c91d0d", null ],
+ [ "AmbiguousFrame", "dbc__decoder_8h.html#a855b2bc36cb18bfbae5ff30a2394e961a88db09d74e14ac6c0a3bc7cd91b45358", null ]
] ]
];
\ No newline at end of file
diff --git a/docs/html/dbc__decoder_8h_source.html b/docs/html/dbc__decoder_8h_source.html
index f7888b1..315aa09 100644
--- a/docs/html/dbc__decoder_8h_source.html
+++ b/docs/html/dbc__decoder_8h_source.html
@@ -117,125 +117,141 @@ $(document).ready(function(){initNavTree('dbc__decoder_8h_source.html',''); init
-
32 enum class SignalDecodeStatus {
-
-
-
-
-
-
38 PhysicalConversionFailed
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
39 PhysicalConversionFailed
+
-
-
-
-
-
-
-
-
-
58 SignalDecodeStatus status = SignalDecodeStatus::InvalidDefinition;
-
-
-
-
-
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
74 std::vector<DecodedSignalValue> signals;
-
-
-
-
+
+
+
-
-
-
-
-
-
-
95 bool isExtended)
const ;
-
-
-
-
-
-
108 static bool IsValidDefinition(
const DecodeSignal &signal, std::uint8_t dlc);
-
-
110 struct SelectorState {
-
-
-
113 bool available =
false ;
-
114 std::uint64_t value = 0U;
-
-
-
-
-
-
-
121 const SelectorState &selector);
-
-
123 static bool ExtractUnsigned(
const std::vector<std::uint8_t> &data,
-
-
125 std::uint64_t &value);
-
-
127 static bool ExtractIntel(
const std::vector<std::uint8_t> &data,
-
128 std::uint32_t startBit,
-
129 std::uint32_t length,
-
130 std::uint64_t &value);
-
-
132 static bool ExtractMotorola(
const std::vector<std::uint8_t> &data,
-
133 std::uint32_t startBit,
-
134 std::uint32_t length,
-
135 std::uint64_t &value);
-
-
137 static std::int64_t SignExtend(std::uint64_t value, std::uint32_t bitLength);
-
+
+
+
+
+
+
76 std::vector<DecodedSignalValue> signals;
+
+
+
+
-
-
-
Runtime CAN decoder using prebuilt decode database.
-
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-ready frame definition.
-
Runtime-ready signal definition.
-
-
-
std::shared_ptr< const DecodeFrame > definition
-
-
-
One decoded signal value.
-
-
-
-
std::shared_ptr< const DecodeSignal > definition
-
-
const std::string * GetValueDescription() const
+
+
+
+
+
+
+
97 bool isExtended)
const ;
+
+
+
+
+
+
+
119 const std::vector<SignalKey> &selection)
const ;
+
+
+
+
123 std::uint32_t canId,
bool isExtended);
+
+
+
+
127 const std::vector<SignalKey> *selection)
const ;
+
+
129 static bool IsValidDefinition(
const DecodeSignal &signal, std::uint8_t dlc);
+
+
131 struct SelectorState {
+
+
+
134 bool available =
false ;
+
135 std::uint64_t value = 0U;
+
+
+
+
+
+
+
142 const SelectorState &selector);
+
+
144 static bool ExtractUnsigned(
const std::vector<std::uint8_t> &data,
+
+
146 std::uint64_t &value);
+
+
148 static bool ExtractIntel(
const std::vector<std::uint8_t> &data,
+
149 std::uint32_t startBit,
+
150 std::uint32_t length,
+
151 std::uint64_t &value);
+
+
153 static bool ExtractMotorola(
const std::vector<std::uint8_t> &data,
+
154 std::uint32_t startBit,
+
155 std::uint32_t length,
+
156 std::uint64_t &value);
+
+
158 static std::int64_t SignExtend(std::uint64_t value, std::uint32_t bitLength);
+
+
+
+
+
Runtime CAN decoder using prebuilt decode database.
+
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 exact CAN ID first, then unique PGN among explicitly J1939 definitions.
+
Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles a...
+
SignalDecodeStatus
Outcome of signal extraction and physical conversion.
+
+
Runtime definitions and immutable indexed database.
+
Runtime-ready frame definition.
+
Runtime-ready signal definition.
+
+
+
std::shared_ptr< const DecodeFrame > definition
+
+
+
One decoded signal value.
+
+
+
+
std::shared_ptr< const DecodeSignal > definition
+
SignalDecodeStatus status
+
+
const std::string * GetValueDescription() const
Stable frame identifier: normalized CAN ID and frame type.
+
Raw CAN frame used for runtime or trace decoding.
std::vector< std::uint8_t > data
-
+
diff --git a/docs/html/dbc__decoder__test_8cpp_source.html b/docs/html/dbc__decoder__test_8cpp_source.html
index e507fca..dcb76c7 100644
--- a/docs/html/dbc__decoder__test_8cpp_source.html
+++ b/docs/html/dbc__decoder__test_8cpp_source.html
@@ -301,7 +301,7 @@ $(document).ready(function(){initNavTree('dbc__decoder__test_8cpp_source.html','
201 QCOMPARE(result.signals.size(), std::size_t(2U));
202 for (std::size_t index = 0U; index < result.signals.size(); ++index) {
-
204 QCOMPARE(value.status, bytes > index ? SignalDecodeStatus::Valid : SignalDecodeStatus::InsufficientPayload);
+
205 QCOMPARE(value.
valid , bytes > index);
207 QCOMPARE(std::get<std::uint64_t>(value.
rawValue ), std::uint64_t(42U));
@@ -354,8 +354,8 @@ $(document).ready(function(){initNavTree('dbc__decoder__test_8cpp_source.html','
254 case 3: bad.
startBit = std::numeric_limits<std::uint32_t>::max();
break ;
-
257 case 6: bad.multiplexing.role =
static_cast< MultiplexRole
> (99);
break ;
-
258 case 7: bad.multiplexing.role = MultiplexRole::Branch;
break ;
+
+
260 definition.signals = {bad, good};
261 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (
void )
DecodeDatabase ({definition}));
@@ -412,7 +412,7 @@ $(document).ready(function(){initNavTree('dbc__decoder__test_8cpp_source.html','
314 QCOMPARE(scaled.
valid , finite);
-
315 QCOMPARE(scaled.status, finite ? SignalDecodeStatus::Valid : SignalDecodeStatus::PhysicalConversionFailed);
+
317 if (type == ValueType::Signed)
318 QCOMPARE(std::get<std::int64_t>(scaled.
rawValue ), std::int64_t(2));
@@ -435,14 +435,14 @@ $(document).ready(function(){initNavTree('dbc__decoder__test_8cpp_source.html','
336 selector.
name =
"Selector" ;
-
338 selector.multiplexing.role = MultiplexRole::Selector;
+
339 selector.
factor = std::numeric_limits<double>::max();
341 branch.
name =
"Branch" ;
-
344 branch.multiplexing.role = MultiplexRole::Branch;
-
345 branch.multiplexing.value = 2U;
+
+
346 definition.signals = {branch, selector};
@@ -481,38 +481,43 @@ $(document).ready(function(){initNavTree('dbc__decoder__test_8cpp_source.html','
383 #include "dbc_decoder_test.moc"
-
Runtime CAN decoder using prebuilt decode database.
-
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-ready frame definition.
-
-
-
-
Runtime-ready signal definition.
-
-
-
ValueDescriptions valueDescriptions
-
-
-
-
-
-
-
-
std::shared_ptr< const DecodeFrame > definition
-
-
-
One decoded signal value.
-
-
-
std::shared_ptr< const DecodeSignal > definition
-
-
const std::string * GetValueDescription() const
+
Runtime CAN decoder using prebuilt decode database.
+
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...
+
CAN frame decoding API and result types.
+
SignalDecodeStatus
Outcome of signal extraction and physical conversion.
+
+
ByteOrder
Signal byte order used for runtime decoding.
+
ValueType
Signal numeric type.
+
Runtime-ready frame definition.
+
+
+
+
Runtime-ready signal definition.
+
+
+
ValueDescriptions valueDescriptions
+
+
+
+
+
+
Multiplexing multiplexing
+
+
+
std::shared_ptr< const DecodeFrame > definition
+
+
+
One decoded signal value.
+
+
+
std::shared_ptr< const DecodeSignal > definition
+
SignalDecodeStatus status
+
+
const std::string * GetValueDescription() const
Stable frame identifier: normalized CAN ID and frame type.
+
+
Raw CAN frame used for runtime or trace decoding.
std::vector< std::uint8_t > data
diff --git a/docs/html/dbc__diagnostic_8h_source.html b/docs/html/dbc__diagnostic_8h_source.html
index 99156c7..e10709f 100644
--- a/docs/html/dbc__diagnostic_8h_source.html
+++ b/docs/html/dbc__diagnostic_8h_source.html
@@ -107,50 +107,61 @@ $(document).ready(function(){initNavTree('dbc__diagnostic_8h_source.html',''); i
-
10 enum class DbcDiagnosticSeverity {
-
-
-
-
-
16 enum class DbcDiagnosticCode {
-
-
-
-
20 InvalidValueDescription,
-
-
-
-
-
-
-
26 DbcDiagnosticSeverity severity;
-
27 DbcDiagnosticCode code;
-
-
29 std::size_t lineNumber;
-
-
+
11 enum class DbcDiagnosticSeverity {
+
+
+
+
+
17 enum class DbcDiagnosticCode {
+
+
+
+
21 InvalidValueDescription,
+
+
+
+
+
+
+
-
-
-
-
-
35 std::vector<DbcDiagnostic> diagnostics;
-
37 bool HasErrors()
const {
-
-
39 if (diagnostic.severity == DbcDiagnosticSeverity::Error)
-
-
-
-
-
+
+
+
+
+
+
+
+
45 if (diagnostic.severity == DbcDiagnosticSeverity::Error)
+
+
+
+
-
-
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
+
+
+
+
Parsed DBC database and attribute metadata.
Parsed DBC content stored in a simple internal form.
-
-
+
Diagnostic message and physical source location.
+
+
DbcDiagnosticSeverity severity
+
+
+
+
Parsed database and diagnostics; the database is empty on error.
+
std::vector< DbcDiagnostic > diagnostics
+
bool HasErrors() const
Return whether any diagnostic has error severity.
+
diff --git a/docs/html/dbc__lifetime__test_8cpp_source.html b/docs/html/dbc__lifetime__test_8cpp_source.html
index ed41a1b..70ff69e 100644
--- a/docs/html/dbc__lifetime__test_8cpp_source.html
+++ b/docs/html/dbc__lifetime__test_8cpp_source.html
@@ -179,7 +179,7 @@ $(document).ready(function(){initNavTree('dbc__lifetime__test_8cpp_source.html',
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 ));
+
84 QVERIFY(!oldDefinition.expired());
85 QCOMPARE(current.
definition ->name, std::string(
"NewFrame" ));
@@ -224,7 +224,7 @@ $(document).ready(function(){initNavTree('dbc__lifetime__test_8cpp_source.html',
-
+
128 QVERIFY(frame && signal);
129 QCOMPARE(frame.get(), ©.
GetFrames ()[0]);
130 QCOMPARE(signal.get(), &frame->signals[0]);
@@ -249,13 +249,13 @@ $(document).ready(function(){initNavTree('dbc__lifetime__test_8cpp_source.html',
-
152 QVERIFY(first.FindSignal(state) && second.FindSignal(state));
+
-
154 QVERIFY(!second.FindSignal(
SignalKey (frame,
"Removed" )));
-
155 QVERIFY(second.FindSignal(
SignalKey (frame,
"Renamed" )));
-
-
-
+
+
+
+
+
159 std::unordered_map<FrameKey, int, FrameKeyHasher> frames;
160 frames.emplace(frame, 1);
161 frames.emplace(
FrameKey (17U,
true ), 2);
@@ -319,7 +319,7 @@ $(document).ready(function(){initNavTree('dbc__lifetime__test_8cpp_source.html',
219 "SG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n"
220 "SG_ State m1 : 8|8@1+ (1,0) [0|255] \"\" ECU\n" ;
221 const std::vector<std::vector<std::uint8_t>> payloads = {{0U}, {}, {1U}};
-
222 const SignalDecodeStatus statuses[] = {SignalDecodeStatus::Inactive,
+
223 SignalDecodeStatus::SelectorUnavailable,
224 SignalDecodeStatus::InsufficientPayload};
225 for (std::size_t index = 0U; index < payloads.size(); ++index) {
@@ -329,7 +329,7 @@ $(document).ready(function(){initNavTree('dbc__lifetime__test_8cpp_source.html',
229 raw.
data = payloads[index];
231 database = BuildText(secondDbc);
-
232 QCOMPARE(saved.status, statuses[index]);
+
232 QCOMPARE(saved.
status , statuses[index]);
234 QCOMPARE(saved.
definition ->multiplexing.role, MultiplexRole::Branch);
@@ -344,41 +344,44 @@ $(document).ready(function(){initNavTree('dbc__lifetime__test_8cpp_source.html',
244 #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.
-
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
-
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)
+
Runtime CAN decoder using prebuilt decode database.
+
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 exact CAN ID first, then unique PGN among explicitly J1939 definitions.
+
+
Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles a...
+
std::shared_ptr< const DecodeSignal > FindSignal(const SignalKey &key) const
Return an owning signal handle, or an empty handle for a missing key.
+
std::shared_ptr< const DecodeFrame > FindFrame(const FrameKey &key) const
+
const std::vector< DecodeFrame > & GetFrames() const
+
Runtime decode database builder.
+
CAN frame decoding API and result types.
+
SignalDecodeStatus
Outcome of signal extraction and physical conversion.
+
DBC file parser and interpretation options.
Parsed DBC content stored in a simple internal form.
std::vector< FrameInfo > frames
-
Runtime-ready frame definition.
-
-
-
Runtime-ready signal definition.
-
-
-
-
-
std::shared_ptr< const DecodeFrame > definition
-
-
-
One decoded signal value.
-
-
std::shared_ptr< const DecodeSignal > definition
-
-
const std::string * GetValueDescription() const
-
Describes one CAN frame from a DBC file.
-
+
Runtime-ready frame definition.
+
+
+
Runtime-ready signal definition.
+
+
+
+
+
std::shared_ptr< const DecodeFrame > definition
+
+
+
One decoded signal value.
+
+
std::shared_ptr< const DecodeSignal > definition
+
SignalDecodeStatus status
+
+
const std::string * GetValueDescription() const
+
Describes one CAN frame from a DBC file.
+
Stable frame identifier: normalized CAN ID and frame type.
Raw CAN frame used for runtime or trace decoding.
std::vector< std::uint8_t > data
-
+
diff --git a/docs/html/dbc__parser_8cpp.html b/docs/html/dbc__parser_8cpp.html
index f8f5d70..bbe612c 100644
--- a/docs/html/dbc__parser_8cpp.html
+++ b/docs/html/dbc__parser_8cpp.html
@@ -94,7 +94,7 @@ $(document).ready(function(){initNavTree('dbc__parser_8cpp.html',''); initResiza
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
DBC file reading and diagnostic collection.
More...
#include "dbc_parser.h "
#include "dbc_statement_handler.h"
@@ -106,7 +106,8 @@ $(document).ready(function(){initNavTree('dbc__parser_8cpp.html',''); initResiza
Go to the source code of this file.
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
DBC file reading and diagnostic collection.
+
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Licensed under the MIT License. See LICENSE file in the project root for full license text.
Definition in file dbc_parser.cpp .
diff --git a/docs/html/dbc__parser_8cpp_source.html b/docs/html/dbc__parser_8cpp_source.html
index 5d591db..1ffcf22 100644
--- a/docs/html/dbc__parser_8cpp_source.html
+++ b/docs/html/dbc__parser_8cpp_source.html
@@ -109,109 +109,155 @@ $(document).ready(function(){initNavTree('dbc__parser_8cpp_source.html',''); ini
-
22 DbcDiagnosticCode StatementErrorCode(
const std::string &keyword) {
-
23 if (keyword ==
"SG_MUL_VAL_" )
-
24 return DbcDiagnosticCode::UnsupportedStatement;
-
25 if (keyword ==
"VAL_" )
-
26 return DbcDiagnosticCode::InvalidValueDescription;
-
27 return DbcDiagnosticCode::InvalidStatement;
-
-
-
-
-
-
-
-
34 if (diagnostic.severity == DbcDiagnosticSeverity::Error) {
-
35 if (diagnostic.lineNumber == 0U)
-
36 throw std::runtime_error(diagnostic.message);
-
37 throw std::runtime_error(diagnostic.filePath +
":" +
-
38 std::to_string(diagnostic.lineNumber) +
": " + diagnostic.message);
-
-
-
41 return std::move(result.database);
-
+
+
23 void ReadCommentLines(std::ifstream &input, std::string &statement,
+
24 std::size_t &lineNumber) {
+
+
+
27 std::string part = statement;
+
+
29 for (
const char character: part) {
+
+
+
32 }
else if (inQuote && character ==
'\\' ) {
+
+
34 }
else if (character ==
'"' ) {
+
+
+
+
+
+
40 if (!inQuote || !std::getline(input, part))
+
+
+
43 if (!part.empty() && part.back() ==
'\r' )
+
+
+
+
+
+
+
+
+
52 DbcDiagnosticCode StatementErrorCode(
const std::string &keyword) {
+
53 if (keyword ==
"SG_MUL_VAL_" )
+
54 return DbcDiagnosticCode::UnsupportedStatement;
+
55 if (keyword ==
"VAL_" )
+
56 return DbcDiagnosticCode::InvalidValueDescription;
+
57 return DbcDiagnosticCode::InvalidStatement;
+
+
+
+
+
+
+
+
64 if (diagnostic.severity == DbcDiagnosticSeverity::Error) {
+
65 if (diagnostic.lineNumber == 0U)
+
66 throw std::runtime_error(diagnostic.message);
+
67 throw std::runtime_error(diagnostic.filePath +
":" +
+
68 std::to_string(diagnostic.lineNumber) +
": " + diagnostic.message);
+
+
+
+
-
-
-
-
-
46 std::ifstream input(filePath.c_str());
-
47 if (!input.is_open()) {
-
48 result.diagnostics.push_back({DbcDiagnosticSeverity::Error,
-
49 DbcDiagnosticCode::FileOpenError, filePath, 0U,
-
50 "Failed to open DBC file: " + filePath});
-
-
-
-
-
-
-
57 bool inNamespace =
false ;
-
58 std::size_t lineNumber = 0U;
-
-
60 while (std::getline(input, line)) {
-
-
62 line = dbc_detail::TrimText(line);
-
-
-
-
66 std::istringstream tokens(line);
-
-
-
-
70 const bool hasArgument =
static_cast< bool > (tokens >> argument);
-
71 if (inNamespace && !hasArgument && keyword !=
"BO_" && keyword !=
"SG_" &&
-
72 keyword !=
"BS_" && keyword !=
"BS_:" &&
-
73 keyword !=
"BU_" && keyword !=
"BU_:" )
-
-
75 inNamespace = keyword ==
"NS_" || keyword ==
"NS_:" ;
-
-
-
78 context.lineNumber = lineNumber;
-
79 if (!dispatcher.
Dispatch (line, context)) {
-
80 result.diagnostics.push_back({DbcDiagnosticSeverity::Warning,
-
81 DbcDiagnosticCode::UnsupportedStatement,
-
-
83 "Unsupported statement '" + keyword +
-
84 "' is ignored; decoding or metadata may be incomplete." });
-
-
86 }
catch (
const std::exception &error) {
-
87 result.diagnostics.push_back({DbcDiagnosticSeverity::Error,
-
88 StatementErrorCode(keyword), filePath,
-
89 lineNumber, error.what()});
-
-
-
-
-
94 if (input.bad() || !input.eof()) {
-
95 result.diagnostics.push_back({DbcDiagnosticSeverity::Error,
-
96 DbcDiagnosticCode::FileReadError, filePath, 0U,
-
97 "Failed to read DBC file: " + filePath});
-
-
+
+
+
+
+
76 std::ifstream input(filePath.c_str());
+
77 if (!input.is_open()) {
+
78 result.
diagnostics .push_back({DbcDiagnosticSeverity::Error,
+
79 DbcDiagnosticCode::FileOpenError, filePath, 0U,
+
80 "Failed to open DBC file: " + filePath});
+
+
+
+
+
+
+
+
88 bool inNamespace =
false ;
+
89 std::size_t lineNumber = 0U;
+
+
91 while (std::getline(input, line)) {
+
+
93 if (!line.empty() && line.back() ==
'\r' )
+
+
95 const std::string rawLine = line;
+
96 const std::size_t statementLine = lineNumber;
+
97 line = dbc_detail::TrimText(line);
+
+
-
-
102 context.ResolveValueDescriptions(filePath);
-
103 context.ValidateMultiplexing(filePath);
-
-
105 result.diagnostics.push_back(error.diagnostic);
-
-
-
108 result.database = std::move(database);
-
-
+
101 std::istringstream tokens(line);
+
+
103 std::string argument;
+
+
105 const bool hasArgument =
static_cast< bool > (tokens >> argument);
+
106 if (inNamespace && !hasArgument && keyword !=
"BO_" && keyword !=
"SG_" &&
+
107 keyword !=
"BS_" && keyword !=
"BS_:" &&
+
108 keyword !=
"BU_" && keyword !=
"BU_:" )
+
+
110 inNamespace = keyword ==
"NS_" || keyword ==
"NS_:" ;
+
+
112 if (keyword ==
"CM_" ) {
+
+
114 ReadCommentLines(input, line, lineNumber);
+
+
+
+
118 context.lineNumber = statementLine;
+
119 if (!dispatcher.
Dispatch (line, context)) {
+
120 result.
diagnostics .push_back({DbcDiagnosticSeverity::Warning,
+
121 DbcDiagnosticCode::UnsupportedStatement,
+
122 filePath, statementLine,
+
123 "Unsupported statement '" + keyword +
+
124 "' is ignored; decoding or metadata may be incomplete." });
+
+
126 }
catch (
const std::exception &error) {
+
127 result.
diagnostics .push_back({DbcDiagnosticSeverity::Error,
+
128 StatementErrorCode(keyword), filePath,
+
129 statementLine, error.what()});
+
+
+
+
+
134 if (input.bad() || !input.eof()) {
+
135 result.
diagnostics .push_back({DbcDiagnosticSeverity::Error,
+
136 DbcDiagnosticCode::FileReadError, filePath, 0U,
+
137 "Failed to read DBC file: " + filePath});
+
+
+
+
+
142 context.ResolveComments(filePath);
+
143 context.ResolveValueDescriptions(filePath);
+
144 context.ValidateMultiplexing(filePath);
+
145 context.ResolveAttributes(filePath, result.
diagnostics );
+
+
+
+
+
150 result.
database = std::move(database);
+
+
-
-
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.
-
-
bool Dispatch(const std::string &line, DbcParseContext &context) const
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
+
+
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.
+
+
bool Dispatch(const std::string &line, DbcParseContext &context) const
+
DBC file parser and interpretation options.
Parsed DBC content stored in a simple internal form.
-
-
-
+
Diagnostic message and physical source location.
+
+
Parsed database and diagnostics; the database is empty on error.
+
std::vector< DbcDiagnostic > diagnostics
+
+
diff --git a/docs/html/dbc__parser_8h.html b/docs/html/dbc__parser_8h.html
index d446179..8b5b924 100644
--- a/docs/html/dbc__parser_8h.html
+++ b/docs/html/dbc__parser_8h.html
@@ -96,7 +96,7 @@ $(document).ready(function(){initNavTree('dbc__parser_8h.html',''); initResizabl
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
DBC file parser and interpretation options.
More...
#include <string>
#include "dbc_diagnostic.h"
@@ -105,12 +105,15 @@ $(document).ready(function(){initNavTree('dbc__parser_8h.html',''); initResizabl
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
DBC file parser and interpretation options.
+
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Licensed under the MIT License. See LICENSE file in the project root for full license text.
Definition in file dbc_parser.h .
diff --git a/docs/html/dbc__parser_8h.js b/docs/html/dbc__parser_8h.js
index 1eb44b1..96e2428 100644
--- a/docs/html/dbc__parser_8h.js
+++ b/docs/html/dbc__parser_8h.js
@@ -1,4 +1,5 @@
var dbc__parser_8h =
[
+ [ "DbcParserOptions", "structDbcParserOptions.html", "structDbcParserOptions" ],
[ "DbcParser", "classDbcParser.html", "classDbcParser" ]
];
\ No newline at end of file
diff --git a/docs/html/dbc__parser_8h_source.html b/docs/html/dbc__parser_8h_source.html
index d55f09e..de40db0 100644
--- a/docs/html/dbc__parser_8h_source.html
+++ b/docs/html/dbc__parser_8h_source.html
@@ -106,22 +106,35 @@ $(document).ready(function(){initNavTree('dbc__parser_8h_source.html',''); initR
17 #include "dbc_diagnostic.h"
-
-
-
-
-
-
-
-
+
-
-
-
-
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.
+
+
+
+
+
+
DbcParseResult ParseFileWithDiagnostics(const std::string &filePath) const
Parse with warnings and a structured first error instead of throwing.
+
DbcParser(DbcParserOptions options={})
Create a parser with explicit extended-frame interpretation options.
+
DbcDatabase ParseFile(const std::string &filePath) const
Parse DBC file.
Parsed DBC content stored in a simple internal form.
-
+
Parsed database and diagnostics; the database is empty on error.
+
+
diff --git a/docs/html/dbc__parser__test_8cpp_source.html b/docs/html/dbc__parser__test_8cpp_source.html
index 1d39be9..76e0ff7 100644
--- a/docs/html/dbc__parser__test_8cpp_source.html
+++ b/docs/html/dbc__parser__test_8cpp_source.html
@@ -103,945 +103,1370 @@ $(document).ready(function(){initNavTree('dbc__parser__test_8cpp_source.html',''
4 #include "dbc_statement_handler.h"
-
-
-
-
-
-
-
-
13 #define CHECK(condition, name) QVERIFY2((condition), std::string(name).c_str())
-
+
+
+
+
+
+
+
+
+
-
-
17 std::filesystem::path path = std::filesystem::temp_directory_path() /
-
18 (
"dbc_parser_test_" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count()) +
".dbc" );
-
-
20 std::error_code error;
-
21 std::filesystem::remove(path, error);
-
-
23 void Write(
const std::string &text)
const {
-
24 std::ofstream output(path);
-
-
-
27 throw std::runtime_error(
"Cannot write test fixture." );
-
-
-
-
-
-
33 inline static int instances = 0;
-
34 inline static int calls = 0;
-
35 CountingHandler() { ++instances; }
-
36 void Handle(
const std::string &,
DbcParseContext &context)
const override {
-
-
38 context.database.
frames .emplace_back();
-
-
-
-
42 std::string SignalLine(
const std::string &start,
const std::string &length,
-
43 const std::string &order,
const std::string &factor,
-
44 const std::string &offset,
const std::string &minimum,
-
45 const std::string &maximum,
const std::string &name =
"Value" ) {
-
46 return "SG_ " + name +
" : " + start +
"|" + length +
"@" + order +
-
47 " (" + factor +
"," + offset +
") [" + minimum +
"|" + maximum +
"] \"\" ECU" ;
-
+
16 #define CHECK(condition, name) QVERIFY2((condition), std::string(name).c_str())
+
+
+
+
20 std::filesystem::path path = std::filesystem::temp_directory_path() /
+
21 (
"dbc_parser_test_" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count()) +
".dbc" );
+
+
23 std::error_code error;
+
24 std::filesystem::remove(path, error);
+
+
26 void Write(
const std::string &text)
const {
+
27 std::ofstream output(path);
+
+
+
30 throw std::runtime_error(
"Cannot write test fixture." );
+
+
+
+
34 class CommaDecimalPunctuation :
public std::numpunct<char> {
+
+
36 char do_decimal_point()
const override {
return ',' ; }
+
37 char do_thousands_sep()
const override {
return '.' ; }
+
38 std::string do_grouping()
const override {
return "\3" ; }
+
+
+
41 class ApplicationLocaleGuard {
+
+
43 ApplicationLocaleGuard()
+
44 : previousCppLocale(std::locale()), previousCLocale(std::setlocale(LC_ALL, nullptr)) {}
+
45 ~ApplicationLocaleGuard() {
+
46 std::locale::global(previousCppLocale);
+
47 std::setlocale(LC_ALL, previousCLocale.c_str());
+
-
50 class DbcParserTest :
public QObject {
-
-
-
53 void RejectSignal(
const Fixture &fixture,
const std::string &line,
unsigned payload = 8U) {
-
54 fixture.Write(
"BO_ 1 Frame: " + std::to_string(payload) +
" ECU\n\n" + line +
"\n" );
-
-
-
57 CHECK(
false ,
"Reject " + line);
-
58 }
catch (
const std::runtime_error &error) {
-
59 const std::string prefix = fixture.path.string() +
":3: " ;
-
60 CHECK(std::string(error.what()).find(prefix) == 0U &&
-
61 std::string(error.what()).size() > prefix.size(),
-
-
-
-
-
-
67 void diagnosticErrors();
-
68 void diagnosticUnsupportedStatements();
-
69 void diagnosticNamespaceBoundaries();
-
70 void diagnosticFormatting();
-
-
72 void multiplexingBoundaries();
-
-
-
75 void duplicateFrames();
-
76 void duplicateSignals();
-
77 void distinctDefinitions();
-
-
79 void invalidSignals();
-
-
-
82 void independentSessions();
-
83 void valueDescriptions();
-
84 void invalidValueDescriptions();
-
-
-
87 void DbcParserTest::diagnostics() {
-
-
89 fixture.Write(
"VERSION \"test\"\n"
-
-
-
-
-
-
-
-
97 "BO_ 1 Frame: 1 ECU\n"
-
98 "SG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
-
99 "SIG_VALTYPE_ 1 Value : 1;\n"
-
100 "BA_ \"SignalType\" SG_ 1 Value 1;\n"
-
101 "VENDOR_EXTENSION_ data;\n" );
-
-
103 CHECK(!result.HasErrors() && result.database.
frames .size() == 1U,
-
104 "Warnings preserve the supported database" );
-
105 QCOMPARE(result.diagnostics.size(), std::size_t(3U));
-
106 for (std::size_t index = 0U; index < result.diagnostics.size(); ++index) {
-
-
108 CHECK(diagnostic.severity == DbcDiagnosticSeverity::Warning &&
-
109 diagnostic.code == DbcDiagnosticCode::UnsupportedStatement,
-
110 "Unsupported statements have structured warning severity and code" );
-
111 QCOMPARE(diagnostic.filePath, fixture.path.string());
-
112 QCOMPARE(diagnostic.lineNumber, 12U + index);
-
113 CHECK(diagnostic.message.find(
"ignored" ) != std::string::npos,
-
114 "Warning explains unsupported syntax" );
-
-
116 CHECK(
DbcParser ().ParseFile(fixture.path.string()).frames.size() == 1U,
-
117 "Legacy API accepts files with warnings" );
-
118 fixture.Write(
"VERSION \"\"\nNS_:\nSIG_VALTYPE_\n\tBA_\n BS_ :\n BU_ : ECU\n" );
-
-
120 CHECK(headers.diagnostics.empty(),
"Common header variants stay quiet" );
-
121 fixture.Write(
"NS_ :\n BA_\n BO_\n" );
-
122 CHECK(
DbcParser ().ParseFileWithDiagnostics(fixture.path.string()).HasErrors(),
-
123 "Namespace handling does not swallow a malformed frame" );
-
-
-
126 void DbcParserTest::diagnosticErrors() {
-
-
-
-
130 DbcDiagnosticCode code;
-
-
-
133 const ErrorCase cases[] = {
-
134 {
"UNKNOWN_ data;\n\nBO_ invalid Frame: 1 ECU\n" ,
-
135 DbcDiagnosticCode::InvalidStatement, 3U},
-
136 {
"BO_ 1 Frame: 1 ECU\nSG_MUL_VAL_ 1 Value Mode 1-2;\n" ,
-
137 DbcDiagnosticCode::UnsupportedStatement, 2U},
-
138 {
"BO_ 1 Frame: 1 ECU\nVAL_ 1 Missing 0 \"Off\";\n" ,
-
139 DbcDiagnosticCode::InvalidValueDescription, 2U},
-
140 {
"BO_ 1 Frame: 1 ECU\nSG_ Value m1 : 0|8@1+ (1,0) [0|255] \"\" ECU\n" ,
-
141 DbcDiagnosticCode::InvalidMultiplexing, 2U},
-
142 {
"BO_ 1 Frame: 1 ECU\nSG_ Mode M : 0|8@1- (1,0) [-128|127] \"\" ECU\n" ,
-
143 DbcDiagnosticCode::InvalidMultiplexing, 2U},
-
144 {
"VAL_ broken\n" , DbcDiagnosticCode::InvalidValueDescription, 1U},
-
145 {
"SG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU\n" ,
-
146 DbcDiagnosticCode::InvalidStatement, 1U},
-
147 {
"BO_ 1 Frame: 1 ECU\nBO_ 1 Duplicate: 1 ECU\n" ,
-
148 DbcDiagnosticCode::InvalidStatement, 2U},
-
149 {
"BO_ 1 Frame: 1 ECU\nSG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
-
150 "SG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU\n" ,
-
151 DbcDiagnosticCode::InvalidStatement, 3U},
-
152 {
"BO_ 1 Frame: 1 ECU\nSG_ Value : 8|8@1+ (1,0) [0|255] \"\" ECU\n" ,
-
153 DbcDiagnosticCode::InvalidStatement, 2U},
-
154 {
"BO_ 1 Frame: 1 ECU\nVAL_ 2 Missing 0 \"Off\";\n" ,
-
155 DbcDiagnosticCode::InvalidValueDescription, 2U},
-
156 {
"BO_ 1 Frame: 1 ECU\nSG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
-
157 "VAL_ 1 Value 0 \"Off\";\nVAL_ 1 Value 0 \"Duplicate\";\n" ,
-
158 DbcDiagnosticCode::InvalidValueDescription, 4U},
-
159 {
"BO_ 1 Frame: 2 ECU\nSG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n"
-
160 "SG_ Value m2 : 8|8@1+ (1,0) [0|255] \"\" ECU\n" ,
-
161 DbcDiagnosticCode::InvalidMultiplexing, 3U},
-
162 {
"BO_ 1 Frame: 2 ECU\nSG_ Mode M : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
-
163 "SG_ Other M : 8|8@1+ (1,0) [0|255] \"\" ECU\n" ,
-
164 DbcDiagnosticCode::InvalidMultiplexing, 3U},
-
165 {
"BO_ 1 Frame: 1 ECU\nSG_ First : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
-
166 "SG_ Second : 7|8@0+ (1,0) [0|255] \"\" ECU\n" ,
-
167 DbcDiagnosticCode::InvalidMultiplexing, 3U}
-
-
169 for (
const ErrorCase &test : cases) {
-
170 fixture.Write(test.text);
-
-
172 CHECK(result.HasErrors() && result.database.
frames .empty(),
-
173 "Failed parse never returns a partial database" );
-
-
175 CHECK(diagnostic.severity == DbcDiagnosticSeverity::Error && diagnostic.code == test.code,
-
176 "Error has expected severity and code" );
-
177 QCOMPARE(diagnostic.filePath, fixture.path.string());
-
178 QCOMPARE(diagnostic.lineNumber, test.line);
-
179 CHECK(!diagnostic.message.empty(),
"Error includes a message" );
-
180 const bool hasWarning = std::string(test.text).find(
"UNKNOWN_" ) == 0U;
-
181 QCOMPARE(result.diagnostics.size(), hasWarning ? std::size_t(2U) : std::size_t(1U));
-
-
-
184 CHECK(
false ,
"Legacy parser must throw" );
-
185 }
catch (
const std::runtime_error &error) {
-
186 QCOMPARE(std::string(error.what()), fixture.path.string() +
":" +
-
187 std::to_string(test.line) +
": " + diagnostic.message);
-
-
-
190 const std::string missingPath = fixture.path.string() +
".missing" ;
-
-
192 CHECK(missing.HasErrors() && missing.database.
frames .empty(),
"Missing file returns error" );
-
193 QCOMPARE(missing.diagnostics.size(), std::size_t(1U));
-
194 CHECK(missing.diagnostics[0].code == DbcDiagnosticCode::FileOpenError,
-
195 "Missing file has a distinct code" );
-
196 QCOMPARE(missing.diagnostics[0].lineNumber, std::size_t(0U));
-
197 QCOMPARE(missing.diagnostics[0].filePath, missingPath);
-
198 QCOMPARE(missing.diagnostics[0].message,
"Failed to open DBC file: " + missingPath);
-
-
-
201 CHECK(
false ,
"Legacy API throws on missing file" );
-
202 }
catch (
const std::runtime_error &error) {
-
203 QCOMPARE(std::string(error.what()), missing.diagnostics[0].message);
-
-
205 const std::string directoryPath = fixture.path.parent_path().string();
-
-
207 CHECK(directory.HasErrors() && directory.database.
frames .empty(),
-
208 "Directory cannot be parsed as a file" );
-
209 QCOMPARE(directory.diagnostics.size(), std::size_t(1U));
-
210 CHECK(directory.diagnostics[0].code == DbcDiagnosticCode::FileReadError ||
-
211 directory.diagnostics[0].code == DbcDiagnosticCode::FileOpenError,
-
212 "Directory produces a file-level error on supported platforms" );
-
213 QCOMPARE(directory.diagnostics[0].lineNumber, std::size_t(0U));
-
214 QCOMPARE(directory.diagnostics[0].filePath, directoryPath);
-
-
216 CHECK(directory.diagnostics[0].code == DbcDiagnosticCode::FileReadError,
-
217 "Linux directory input exercises the read-error path" );
-
218 QCOMPARE(directory.diagnostics[0].message,
"Failed to read DBC file: " + directoryPath);
-
-
-
-
222 CHECK(
false ,
"Legacy API throws on unreadable input" );
-
223 }
catch (
const std::runtime_error &error) {
-
224 QCOMPARE(std::string(error.what()), directory.diagnostics[0].message);
-
-
226 fixture.Write(
"BO_ 1 Frame: 1 ECU\n" );
-
227 CHECK(
DbcParser ().ParseFileWithDiagnostics(fixture.path.string()).diagnostics.empty(),
-
228 "Diagnostics belong to an independent parse session" );
-
-
-
231 void DbcParserTest::diagnosticUnsupportedStatements() {
-
-
233 const std::string definitions =
-
234 "BO_ 1 Frame: 1 ECU\nSG_ Value : 0|8@1+ (2,10) [10|520] \"V\" ECU\n"
-
235 "CM_ SG_ 1 Value \"Signal comment\";\nVAL_ 1 Value 1 \"On\";\n" ;
-
236 const std::vector<std::string> statements = {
-
237 "SIG_VALTYPE_ 1 Value : 1;" ,
"SIG_VALTYPE_ 1 Value : 2;" ,
-
238 "BA_ \"SignalType\" SG_ 1 Value 1;" ,
-
239 "BA_DEF_ SG_ \"SignalType\" INT 0 1;" ,
-
240 "BA_DEF_DEF_ \"SignalType\" 0;" ,
-
241 "BA_DEF_REL_ BU_SG_REL_ \"Relation\" INT 0 1;" ,
-
242 "BA_REL_ \"Relation\" BU_SG_REL_ ECU SG_ 1 Value 1;" ,
-
243 "SGTYPE_ Type : 8@1+ (1,0) [0|255] \"\" 0, Table;" ,
-
244 "SIG_TYPE_REF_ 1 Value : Type;" ,
-
245 "EV_ Environment : 0 [0|1] \"\" 0 1 DUMMY_NODE_VECTOR0 ECU;" ,
-
246 "ENVVAR_DATA_ Environment : 4;" ,
-
247 "VAL_TABLE_ Table 0 \"Off\" 1 \"On\";" ,
-
248 "BO_TX_BU_ 1 : ECU;" ,
"VENDOR_EXTENSION_ data;" ,
"UNKNOWN_"
-
-
250 for (
const std::string &statement : statements) {
-
251 fixture.Write(definitions + statement +
'\n' );
-
-
253 CHECK(!result.HasErrors(), statement);
-
254 QCOMPARE(result.diagnostics.size(), std::size_t(1U));
-
-
256 CHECK(warning.severity == DbcDiagnosticSeverity::Warning &&
-
257 warning.code == DbcDiagnosticCode::UnsupportedStatement, statement);
-
258 QCOMPARE(warning.filePath, fixture.path.string());
-
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);
-
-
-
-
-
-
267 CHECK(decoded.
valid && decoded.signals.size() == 1U && decoded.signals[0].
valid ,
-
268 "Warnings preserve supported signal decoding" );
-
269 QCOMPARE(decoded.signals[0].physicalValue, 12.0);
-
270 CHECK(decoded.signals[0].GetValueDescription() &&
-
271 *decoded.signals[0].GetValueDescription() ==
"On" ,
-
272 "Warnings preserve VAL_ descriptions" );
-
273 QCOMPARE(runtime.
GetFrames ()[0].signals[0].comment, std::string(
"Signal comment" ));
-
-
-
-
277 void DbcParserTest::diagnosticNamespaceBoundaries() {
-
-
279 const std::vector<std::string> endings = {
-
280 "BS_\n" ,
"BS_:\n" ,
"BS_ :\n" ,
"BU_\n" ,
"BU_:\n" ,
"BU_ : ECU\n" ,
-
281 "BO_ 1 Frame: 1 ECU\n" ,
"VENDOR_EXTENSION_ data;\n"
-
-
283 for (
const std::string &ending : endings) {
-
284 fixture.Write(
"NS_ :\n\tSG_MUL_VAL_\n\nBA_\n" + ending +
"SIG_VALTYPE_\n" );
-
-
286 CHECK(!result.HasErrors(), ending);
-
287 const std::size_t expectedWarnings = ending.find(
"VENDOR_" ) == 0U ? 2U : 1U;
-
288 QCOMPARE(result.diagnostics.size(), expectedWarnings);
-
289 QCOMPARE(result.diagnostics.back().lineNumber, std::size_t(6U));
-
290 CHECK(result.diagnostics.back().message.find(
"SIG_VALTYPE_" ) != std::string::npos,
-
291 "Unsupported keyword outside NS_ must produce a warning" );
-
-
293 for (
const std::string &definition : {std::string(
"BO_" ), std::string(
"SG_" )}) {
-
294 fixture.Write(
"NS_:\n\tBA_\n\t" + definition +
'\n' );
-
-
296 CHECK(result.HasErrors(),
"Malformed definition ends NS_ instead of being hidden" );
-
297 QCOMPARE(result.diagnostics.size(), std::size_t(1U));
-
298 QCOMPARE(result.diagnostics[0].lineNumber, std::size_t(3U));
-
-
-
-
302 void DbcParserTest::diagnosticFormatting() {
-
-
304 fixture.path +=
" with spaces" ;
-
-
306 for (
const std::string &text : {std::string(), std::string(
" \t\r\n\n" )}) {
-
-
-
309 CHECK(!empty.HasErrors() && empty.diagnostics.empty() && empty.database.
frames .empty(),
-
310 "Empty and whitespace-only inputs are valid" );
-
-
312 fixture.Write(
"\r\n\tVENDOR_EXTENSION_ data;\r\n\r\nUNKNOWN_" );
-
313 const std::string relativePath = std::filesystem::relative(fixture.path).string();
-
-
315 CHECK(!warnings.HasErrors() && warnings.database.
frames .empty(),
"Warnings-only input" );
-
316 QCOMPARE(warnings.diagnostics.size(), std::size_t(2U));
-
317 QCOMPARE(warnings.diagnostics[0].lineNumber, std::size_t(2U));
-
318 QCOMPARE(warnings.diagnostics[1].lineNumber, std::size_t(4U));
-
-
320 QCOMPARE(warning.filePath, relativePath);
-
-
322 fixture.Write(
"UNKNOWN_ first;\nBO_ invalid Frame: 1 ECU\n"
-
323 "UNKNOWN_ after_error;\nSG_ broken\n" );
-
-
325 CHECK(stopped.HasErrors() && stopped.database.
frames .empty(),
"First error stops parsing" );
-
326 QCOMPARE(stopped.diagnostics.size(), std::size_t(2U));
-
327 QCOMPARE(stopped.diagnostics[0].lineNumber, std::size_t(1U));
-
328 QCOMPARE(stopped.diagnostics[1].lineNumber, std::size_t(2U));
-
329 QCOMPARE(stopped.diagnostics[1].filePath, relativePath);
-
-
331 fixture.Write(
"VAL_ 1 Missing 0 \"Off\";\nBO_ 1 Frame: 1 ECU\nUNKNOWN_ data;\n" );
-
-
333 CHECK(deferred.HasErrors() && deferred.database.
frames .empty(),
"Deferred error rejects database" );
-
334 QCOMPARE(deferred.diagnostics.size(), std::size_t(2U));
-
335 CHECK(deferred.diagnostics[0].severity == DbcDiagnosticSeverity::Warning &&
-
336 deferred.diagnostics[1].severity == DbcDiagnosticSeverity::Error,
-
337 "Deferred errors follow warnings in detection order" );
-
338 QCOMPARE(deferred.diagnostics[0].lineNumber, std::size_t(3U));
-
339 QCOMPARE(deferred.diagnostics[1].lineNumber, std::size_t(1U));
-
340 QCOMPARE(deferred.diagnostics[1].filePath, relativePath);
-
341 fixture.Write(
"BO_ 1 Frame: 1 ECU" );
-
-
343 CHECK(!recovered.HasErrors() && recovered.diagnostics.empty() && recovered.database.
frames .size() == 1U,
-
344 "Same parser has clean state after errors and accepts missing final newline" );
-
-
-
347 void DbcParserTest::validFrames() {
-
-
-
-
-
-
-
-
355 const ValidCase valid[] = {
-
356 {
"BO_ 0 Frame: 0 ECU" , 0U,
false , 0U},
-
357 {
"BO_ 2047 Frame: 8 ECU" , 2047U,
false , 8U},
-
358 {
"BO_ 2048 Frame: 64 ECU" , 2048U,
true , 64U},
-
359 {
"BO_ 536870911 Frame: 255 ECU" , 0x1FFFFFFFU,
true , 255U},
-
360 {
"BO_ 2147483649 Frame: 8 ECU" , 1U,
true , 8U},
-
361 {
"BO_ 2684354559 Frame: 8 ECU" , 0x1FFFFFFFU,
true , 8U},
-
362 {
" BO_\t256\tFrame :\t8\tECU \r" , 256U,
false , 8U}};
-
363 for (
const ValidCase &test: valid) {
-
364 fixture.Write(std::string(test.line) +
'\n' );
-
-
-
367 QCOMPARE(database.
frames .size(), std::size_t(1U));
-
-
369 QCOMPARE(frame.
name , std::string(
"Frame" ));
-
370 QCOMPARE(frame.
canId , test.id);
-
-
372 QCOMPARE(
static_cast< unsigned > (frame.
dlc ), test.length);
-
-
374 }
catch (
const std::exception &error) { CHECK(
false , error.what()); }
-
-
-
-
378 void DbcParserTest::invalidFrames() {
-
-
380 const char *invalid[] = {
-
381 "BO_ invalid" ,
"BO_" ,
"BO_ 1" ,
"BO_ 1 : 8 ECU" ,
"BO_ 1 Frame 8 ECU" ,
-
382 "BO_ 1 Frame:" ,
"BO_ 1 Frame: 8" ,
"BO_ 1 Frame: 8 ECU extra" ,
-
383 "BO_ 1 Two Names: 8 ECU" ,
"BO_ -1 Frame: 8 ECU" ,
"BO_ +1 Frame: 8 ECU" ,
-
384 "BO_ 1x Frame: 8 ECU" ,
"BO_ 0x123 Frame: 8 ECU" ,
"BO_ 1.5 Frame: 8 ECU" ,
-
385 "BO_ 4294967296 Frame: 8 ECU" ,
"BO_ 999999999999999999999 Frame: 8 ECU" ,
-
386 "BO_ 536870912 Frame: 8 ECU" ,
"BO_ 1073741824 Frame: 8 ECU" ,
-
387 "BO_ 2684354560 Frame: 8 ECU" ,
"BO_ 4294967295 Frame: 8 ECU" ,
-
388 "BO_ 1 Frame: -1 ECU" ,
"BO_ 1 Frame: +8 ECU" ,
"BO_ 1 Frame: 8x ECU" ,
-
389 "BO_ 1 Frame: 8.5 ECU" ,
"BO_ 1 Frame: 256 ECU" ,
-
390 "BO_ 1 Frame: 4294967296 ECU" ,
"BO_\tinvalid" };
-
391 for (
const char *line: invalid) {
-
392 fixture.Write(std::string(
"VERSION \"test\"\n\n" ) + line +
'\n' );
-
-
-
-
396 }
catch (
const std::runtime_error &error) {
-
397 const std::string prefix = fixture.path.string() +
":3: " ;
-
398 CHECK(std::string(error.what()).find(prefix) == 0U &&
-
399 std::string(error.what()).size() > prefix.size(),
-
-
-
-
-
-
405 void DbcParserTest::duplicateFrames() {
-
-
407 struct DuplicateCase {
-
-
409 const char *duplicateId;
-
-
-
412 const DuplicateCase cases[] = {
-
413 {
"1" ,
"1" ,
"Duplicate standard frame CAN ID: 1" },
-
414 {
"2147483649" ,
"2147483649" ,
"Duplicate extended frame CAN ID: 1" },
-
415 {
"2048" ,
"2147485696" ,
"Duplicate extended frame CAN ID: 2048" },
-
416 {
"2147485696" ,
"2048" ,
"Duplicate extended frame CAN ID: 2048" },
-
417 {
"536870911" ,
"2684354559" ,
"Duplicate extended frame CAN ID: 536870911" }
-
-
-
420 for (
const DuplicateCase &test : cases) {
-
421 fixture.Write(
"BO_ " + std::string(test.firstId) +
" First: 8 ECU\n"
-
422 "BO_ 2 Other: 8 ECU\n\n"
-
423 " BO_\t" + test.duplicateId +
"\tSecond: 8 ECU\n" );
-
-
-
426 CHECK(
false ,
"Duplicate frame must be rejected" );
-
427 }
catch (
const std::runtime_error &error) {
-
428 QCOMPARE(std::string(error.what()), fixture.path.string() +
":4: " + test.message);
-
-
-
431 fixture.Write(
"BO_ 1 First: 8 ECU\n" );
-
432 QCOMPARE(parser.
ParseFile (fixture.path.string()).
frames .size(), std::size_t(1U));
-
-
-
435 void DbcParserTest::duplicateSignals() {
-
-
437 const std::string first =
"SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n" ;
-
438 const std::string duplicates[] = {
-
-
440 " SG_\tState : 16|8@1+ (2,1) [0|511] \"V\" ECU\n" ,
-
441 "SG_ State m1 : 16|8@1+ (1,0) [0|255] \"\" ECU\n"
-
-
443 for (
const std::string &duplicate : duplicates) {
-
444 fixture.Write(
"BO_ 1 Frame: 8 ECU\n" + first +
-
445 "SG_ Other : 8|8@1+ (1,0) [0|255] \"\" ECU\n\n" + duplicate);
-
-
-
448 CHECK(
false ,
"Duplicate signal must be rejected" );
-
449 }
catch (
const std::runtime_error &error) {
-
450 QCOMPARE(std::string(error.what()), fixture.path.string() +
-
451 ":5: Duplicate signal name 'State' in frame 'Frame'." );
-
-
-
-
-
456 void DbcParserTest::distinctDefinitions() {
-
-
458 fixture.Write(
"BO_ 1 Shared: 1 ECU\n"
-
459 "SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
-
460 "BO_ 2147483649 Shared: 1 ECU\n"
-
461 "SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
-
462 "BO_ 2 Shared: 2 ECU\n"
-
463 "SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
-
464 "SG_ state : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
-
465 "CM_ BO_ 1 \"Standard\";\n"
-
466 "CM_ BO_ 2147483649 \"Extended\";\n"
-
467 "CM_ SG_ 1 State \"Standard state\";\n"
-
468 "CM_ SG_ 2147483649 State \"Extended state\";\n" );
-
-
470 QCOMPARE(parsed.
frames .size(), std::size_t(3U));
-
471 QCOMPARE(parsed.
frames [0].canId, parsed.
frames [1].canId);
-
472 CHECK(!parsed.
frames [0].isExtended && parsed.
frames [1].isExtended,
-
473 "Standard and extended frames with the same numeric ID remain distinct" );
-
474 QCOMPARE(parsed.
frames [0].comment, std::string(
"Standard" ));
-
475 QCOMPARE(parsed.
frames [1].comment, std::string(
"Extended" ));
-
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));
-
-
-
-
-
-
484 QVERIFY(standard.
valid );
-
485 QCOMPARE(standard.
definition ->comment, std::string(
"Standard" ));
-
-
-
488 QVERIFY(extended.
valid );
-
489 QCOMPARE(extended.
definition ->comment, std::string(
"Extended" ));
-
-
-
492 void DbcParserTest::integration() {
-
-
-
495 "BO_TX_BU_ 256 : ECU;\nBO_ 256 Frame: 8 ECU\n"
-
496 " SG_ Speed : 0|16@1+ (0.5,1) [0|100] \"rpm\" ECU\n"
-
497 "CM_ BO_ 256 \"Frame comment\";\nCM_ SG_ 256 Speed \"Signal comment\";\n"
-
498 "BO_ 257 Second: 8 ECU\n" );
-
-
500 CHECK(database.
frames .size() == 2U && database.
frames [0].signals.size() == 1U &&
-
501 database.
frames [0].comment ==
"Frame comment" &&
-
502 database.
frames [0].signals[0].comment ==
"Signal comment" ,
-
-
504 fixture.Write(
"\nSG_ Speed : invalid\n" );
-
-
-
507 CHECK(
false ,
"Signal error location" );
-
508 }
catch (
const std::runtime_error &error) {
-
509 CHECK(std::string(error.what()).find(fixture.path.string() +
":2: " ) == 0U,
-
510 "Signal error location" );
-
-
-
-
514 void DbcParserTest::multiplexing() {
-
-
516 const std::string selector =
"SG_ Mode M : 0|8@1+ (10,3) [0|255] \"\" ECU\n" ;
-
517 const std::string first =
"SG_ First m1 : 8|8@1- (2,0) [-128|127] \"V\" ECU\n" ;
-
518 const std::string second =
"SG_ Second m2 : 15|8@0+ (1,0) [0|255] \"\" ECU\n" ;
-
519 const std::string common =
"SG_ Common : 16|8@1+ (1,0) [0|255] \"\" ECU\n" ;
-
520 fixture.Write(
"BO_ 1 Frame: 3 ECU\n" + first + second + common + selector +
-
521 "VAL_ 1 First -1 \"Negative\";\n" );
-
-
-
524 CHECK(parsed.
frames [0].signals[3].multiplexing.role == MultiplexRole::Selector,
-
525 "Selector declared after branches" );
-
-
527 CHECK(tree->GetChild(0U)->GetChild(0U)->GetSignal()->multiplexing.value == 1U,
-
528 "Tree preserves multiplexing" );
-
-
-
531 raw.
data = {1U, 255U, 7U};
-
-
533 CHECK(result.signals[0].
valid && std::get<std::int64_t>(result.signals[0].rawValue) == -1 &&
-
534 result.signals[0].physicalValue == -2 && *result.signals[0].GetValueDescription() ==
"Negative" ,
-
535 "Active signed branch and VAL_ use exact raw selector" );
-
536 CHECK(!result.signals[1].
valid && result.signals[1].
status == SignalDecodeStatus::Inactive &&
-
537 result.signals[1].GetValueDescription() ==
nullptr && result.signals[2].
valid ,
-
538 "Inactive branch and unconditional signal" );
-
-
-
541 CHECK(result.signals[0].
status == SignalDecodeStatus::Inactive && result.signals[1].
valid &&
-
542 std::get<std::uint64_t>(result.signals[1].rawValue) == 255U,
-
543 "Motorola branch becomes active" );
-
-
-
546 CHECK(result.signals[0].
status == SignalDecodeStatus::Inactive &&
-
547 result.signals[1].
status == SignalDecodeStatus::Inactive &&
-
548 result.signals[2].
status == SignalDecodeStatus::InsufficientPayload,
-
549 "Unmapped selector leaves branches inactive even with missing bytes" );
-
-
-
552 CHECK(result.signals[0].
status == SignalDecodeStatus::InsufficientPayload,
-
553 "Active branch requires payload" );
-
-
-
556 CHECK(result.signals[0].
status == SignalDecodeStatus::SelectorUnavailable &&
-
557 result.signals[3].
status == SignalDecodeStatus::InsufficientPayload,
-
558 "Unavailable selector does not imply inactive branch" );
-
-
560 const std::vector<std::string> invalid = {
-
-
562 selector +
"SG_ Other M : 16|8@1+ (1,0) [0|255] \"\" ECU\n" ,
-
563 "SG_ Mode M : 0|8@1- (1,0) [-128|127] \"\" ECU\n" ,
-
564 selector +
"SG_ TooLarge m256 : 8|8@1+ (1,0) [0|255] \"\" ECU\n" ,
-
565 selector + first +
"SG_ Same m1 : 15|8@0+ (1,0) [0|255] \"\" ECU\n" ,
-
566 selector +
"SG_ Collision m1 : 0|8@1+ (1,0) [0|255] \"\" ECU\n" ,
-
567 selector + first +
"SG_ Always : 8|8@1+ (1,0) [0|255] \"\" ECU\n" ,
-
568 "SG_MUL_VAL_ 1 First Mode 1-2;\n"
-
-
570 for (
const std::string &signals : invalid) {
-
571 fixture.Write(
"BO_ 1 Frame: 3 ECU\n" + signals);
-
572 bool rejected =
false ;
-
-
-
575 }
catch (
const std::runtime_error &error) {
-
576 rejected = std::string(error.what()).find(fixture.path.string() +
":" ) == 0U;
-
-
578 CHECK(rejected,
"Invalid multiplexing rejected with location" );
-
-
580 for (
const std::string marker : {
"m" ,
"m-1" ,
"m+1" ,
"m1M" ,
"m18446744073709551616" ,
"M m1" })
-
581 RejectSignal(fixture,
"SG_ Bad " + marker +
" : 8|8@1+ (1,0) [0|255] \"\" ECU" );
-
-
-
584 void DbcParserTest::multiplexingBoundaries() {
-
-
586 fixture.Write(
"BO_ 1 Frame: 9 ECU\n"
-
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" );
-
-
-
591 CHECK(runtime.
GetFrames ()[0].signals[0].multiplexing.value == std::numeric_limits<std::uint64_t>::max(),
-
592 "Exact uint64 branch metadata" );
-
-
-
595 raw.
data = std::vector<std::uint8_t>(9U, 255U);
-
-
597 CHECK(result.signals[0].
valid && result.signals[1].
valid &&
-
598 std::get<std::uint64_t>(result.signals[1].rawValue) == std::numeric_limits<std::uint64_t>::max(),
-
599 "Motorola uint64 selector compares raw value before zero scaling" );
-
-
-
602 CHECK(result.signals[0].
status == SignalDecodeStatus::Inactive,
-
603 "Adjacent large integers remain distinct" );
-
604 std::vector<DecodeFrame> definitions = runtime.
GetFrames ();
-
605 definitions[0].signals[1].length = 0U;
-
606 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, runtime =
DecodeDatabase (definitions));
-
607 definitions[0].signals.pop_back();
-
608 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, runtime =
DecodeDatabase (definitions));
-
609 fixture.Write(
"BO_ 1 Frame: 2 ECU\n\n"
-
610 "SG_ Branch m2 : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
-
611 "SG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n" );
-
612 bool rejected =
false ;
-
-
-
615 }
catch (
const std::runtime_error &error) {
-
616 rejected = std::string(error.what()).find(fixture.path.string() +
":3: " ) == 0U;
-
-
618 CHECK(rejected,
"Deferred validation reports branch source line" );
-
619 fixture.Write(
"BO_ 1 Frame: 2 ECU\n"
-
620 "SG_ A : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
-
621 "SG_ B : 15|8@0+ (1,0) [0|255] \"\" ECU\n" );
-
-
-
-
625 }
catch (
const std::runtime_error &) {
-
-
-
628 CHECK(rejected,
"Ordinary overlapping signals rejected" );
-
-
-
631 void DbcParserTest::invalidSignals() {
-
-
633 const std::string ordinary = SignalLine(
"0" ,
"8" ,
"1+" ,
"1" ,
"0" ,
"0" ,
"255" );
-
634 for (
const std::string value: {
"-1" ,
"+1" ,
"0junk" ,
"0x10" ,
"1.5" ,
-
635 "4294967296" ,
"999999999999999999999" }) {
-
636 RejectSignal(fixture, SignalLine(value,
"8" ,
"1+" ,
"1" ,
"0" ,
"0" ,
"255" ));
-
637 RejectSignal(fixture, SignalLine(
"0" , value,
"1+" ,
"1" ,
"0" ,
"0" ,
"255" ));
-
-
639 for (
const std::string length: {
"0" ,
"65" })
-
640 RejectSignal(fixture, SignalLine(
"0" , length,
"1+" ,
"1" ,
"0" ,
"0" ,
"255" ));
-
641 for (
const std::string order: {
"2+" ,
"9-" ,
"1" ,
"1x" ,
"1++" ,
"01+" })
-
642 RejectSignal(fixture, SignalLine(
"0" ,
"8" , order,
"1" ,
"0" ,
"0" ,
"255" ));
-
643 for (
const std::string value: {
"1junk" ,
"nan" ,
"NaN" ,
"inf" ,
"-inf" ,
"1e999" ,
"1e-999" ,
"0x1p2" ,
"" ,
"1e" ,
"1.2.3" }) {
-
644 RejectSignal(fixture, SignalLine(
"0" ,
"8" ,
"1+" , value,
"0" ,
"0" ,
"255" ));
-
645 RejectSignal(fixture, SignalLine(
"0" ,
"8" ,
"1+" ,
"1" , value,
"0" ,
"255" ));
-
646 RejectSignal(fixture, SignalLine(
"0" ,
"8" ,
"1+" ,
"1" ,
"0" , value,
"255" ));
-
647 RejectSignal(fixture, SignalLine(
"0" ,
"8" ,
"1+" ,
"1" ,
"0" ,
"0" , value));
-
-
649 RejectSignal(fixture, SignalLine(
"0" ,
"8" ,
"1+" ,
"1" ,
"0" ,
"2" ,
"1" ));
-
650 for (
const std::string name: {
"" ,
"Two Names" ,
"Value m1M" }) {
-
651 std::string line = ordinary;
-
652 line.replace(4U, 5U, name);
-
653 RejectSignal(fixture, line);
-
-
655 for (
const std::string broken: {
-
656 "SG_" ,
"SG_ Value" ,
"SG_ Value : 0|8@1+ (1,0) [0|255] ECU" ,
-
657 "SG_ Value : 0|8@1+ (1,0) [0|255] \"\"" ,
-
658 "SG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU," ,
-
659 "SG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU extra" })
-
660 RejectSignal(fixture, broken);
-
661 RejectSignal(fixture, SignalLine(
"64" ,
"1" ,
"1+" ,
"1" ,
"0" ,
"0" ,
"1" ));
-
662 RejectSignal(fixture, SignalLine(
"63" ,
"2" ,
"1+" ,
"1" ,
"0" ,
"0" ,
"3" ));
-
663 RejectSignal(fixture, SignalLine(
"56" ,
"2" ,
"0+" ,
"1" ,
"0" ,
"0" ,
"3" ));
-
664 RejectSignal(fixture, SignalLine(
"4294967295" ,
"64" ,
"1+" ,
"1" ,
"0" ,
"0" ,
"1" ));
-
665 RejectSignal(fixture, ordinary, 0U);
-
666 for (
const char delimiter: {
'|' ,
'@' ,
'(' ,
')' ,
'[' ,
']' ,
'"' }) {
-
667 std::string line = ordinary;
-
668 line.erase(line.find(delimiter), 1U);
-
669 RejectSignal(fixture, line);
-
-
-
-
673 void DbcParserTest::validSignals() {
-
-
-
676 fixture.Write(
"BO_ 1 Frame: 8 ECU\n" +
-
677 SignalLine(
"0" ,
"8" ,
"1+" ,
"0" ,
"0" ,
"0" ,
"0" ) +
"\n" +
-
678 SignalLine(
"8" ,
"8" ,
"1-" ,
"-1" ,
"0" ,
"-255" ,
"0" ,
"Negative" ) +
"\n" );
-
-
680 CHECK(factors.
frames [0].signals.size() == 2U &&
-
681 factors.
frames [0].signals[0].factor == 0.0 &&
-
682 factors.
frames [0].signals[1].factor == -1.0,
-
683 "Zero and negative factors and equal range boundaries" );
-
-
-
-
-
-
-
-
691 const SignalCase validSignals[] = {
-
692 {
"0" ,
"1" ,
"1+" , 1U},
-
693 {
"7" ,
"1" ,
"0-" , 1U},
-
694 {
"0" ,
"64" ,
"1+" , 8U},
-
695 {
"7" ,
"64" ,
"0-" , 8U},
-
696 {
"63" ,
"1" ,
"1+" , 8U},
-
697 {
"56" ,
"1" ,
"0+" , 8U},
-
698 {
"3" ,
"12" ,
"0+" , 2U},
-
699 {
"2039" ,
"1" ,
"1+" , 255U}};
-
700 for (
const SignalCase &test: validSignals) {
-
701 fixture.Write(
"BO_ 1 Frame: " + std::to_string(test.payload) +
" ECU\n" +
-
702 SignalLine(test.start, test.length, test.order,
".5e+1" ,
"-2.5E-1" ,
"-1." ,
"+2e2" ) +
"\n" );
-
-
-
-
706 QCOMPARE(signal.
startBit ,
static_cast< std::uint32_t
> (std::stoul(test.start)));
-
707 QCOMPARE(signal.
length ,
static_cast< std::uint32_t
> (std::stoul(test.length)));
-
-
709 QCOMPARE(signal.
isSigned , test.order[1] ==
'-' );
-
710 QCOMPARE(signal.
factor , 5.0);
-
711 QCOMPARE(signal.
offset , -0.25);
-
712 QCOMPARE(signal.
minimum , -1.0);
-
713 QCOMPARE(signal.
maximum , 200.0);
-
714 }
catch (
const std::exception &error) { CHECK(
false , error.what()); }
-
-
716 fixture.Write(
"BO_ 1 Frame: 8 ECU\n"
-
717 "SG_\tValue\t:\t0 | 8 @1+ ( 1 , 0 ) [ 0 | 255 ] \"rpm\" ECU1,\tECU2\n" );
-
-
-
-
721 CHECK(signal.
name ==
"Value" && signal.
unit ==
"rpm" &&
-
722 signal.
receivers == std::vector<std::string>({
"ECU1" ,
"ECU2" }),
-
723 "Signal tabs, spaces, and receiver list" );
-
724 }
catch (
const std::exception &error) { CHECK(
false , error.what()); }
-
-
-
727 void DbcParserTest::dispatch() {
-
728 CountingHandler::instances = 0;
-
729 CountingHandler::calls = 0;
-
-
-
-
733 dispatcher.RegisterType<CountingHandler>(
"TEST_" );
-
734 CHECK(dispatcher.
Dispatch (
"TEST_ first" , context) &&
-
735 dispatcher.
Dispatch (
"TEST_ second" , context) &&
-
736 CountingHandler::instances == 1 && CountingHandler::calls == 2 &&
-
737 dispatchDatabase.
frames .size() == 2U,
-
738 "Factory dispatch and handler reuse" );
-
739 CHECK(!dispatcher.
Dispatch (
"TEST_OTHER data" , context) &&
-
740 !dispatcher.
Dispatch (
"BO_TX_BU_ 1 : ECU;" , context) &&
-
741 !dispatcher.
Dispatch (
"VAL_TABLE_ States 0 \"Stopped\";" , context) &&
-
742 CountingHandler::calls == 2,
-
743 "Exact and unknown keyword dispatch" );
-
-
-
746 void DbcParserTest::independentSessions() {
-
-
-
749 fixture.Write(
"BO_ 1 First: 8 ECU\n" );
-
750 CHECK(parser.
ParseFile (fixture.path.string()).
frames .size() == 1U,
"First parse" );
-
751 fixture.Write(
"SG_ Speed : invalid\n" );
-
-
-
754 CHECK(
false ,
"Independent parse context" );
-
755 }
catch (
const std::runtime_error &error) {
-
756 CHECK(std::string(error.what()).find(
"Signal found before any frame" ) !=
-
-
758 "Independent parse context" );
-
-
760 fixture.Write(
"BO_ 2 Second: 8 ECU\n" );
-
-
762 CHECK(recovered.
frames .size() == 1U && recovered.
frames [0].canId == 2U,
-
763 "Fresh parse after error" );
-
-
-
-
767 void DbcParserTest::valueDescriptions() {
-
-
-
770 "VAL_\t256\tState\t0\t\"Off\"\t1 \"On\" 2 \"Error with spaces; and \\\"quotes\\\"\";\n"
-
771 "BO_ 256 Status: 8 ECU\n"
-
772 "SG_ State : 0|8@1+ (2,10) [0|520] \"\" ECU\n"
-
773 "VAL_ 256 State 3 \"\";\n"
-
774 "VAL_ 2147483904 State -9223372036854775808 \"Minimum\" -1 \"Negative\" 9223372036854775807 \"Maximum\";\n"
-
775 "BO_ 2147483904 Extended: 8 ECU\n"
-
776 "SG_ State : 0|64@1- (1,0) [-1e20|1e20] \"\" ECU\n"
-
777 "BO_ 2048 Unsigned: 8 ECU\n"
-
778 "SG_ State : 0|64@1+ (1,0) [0|2e20] \"\" ECU\n"
-
779 "VAL_ 2147485696 State 9223372036854775808 \"High\" 18446744073709551615 \"Full\";\n" );
-
-
-
-
783 CHECK(tree->GetChild(0)->GetSignal() ==
nullptr ,
"Frame node" );
-
784 for (std::size_t index = 0; index < parsed.
frames .size(); ++index) {
-
785 CHECK(tree->GetChild(index)->GetChild(0)->GetSignal()->valueDescriptions ==
-
786 parsed.
frames [index].signals[0].valueDescriptions &&
-
787 runtime.
GetFrames ()[index].signals[0].valueDescriptions ==
-
788 parsed.
frames [index].signals[0].valueDescriptions,
-
789 "All mappings survive both builders" );
-
-
791 CHECK(tree->GetChild(0)->GetChild(0)->GetSignal()->valueDescriptions ==
-
792 runtime.
GetFrames ()[0].signals[0].valueDescriptions,
-
793 "Both builders preserve descriptions" );
-
-
-
796 frame.
data .resize(8);
-
797 const std::string expected[] = {
"Off" ,
"On" ,
"Error with spaces; and \"quotes\"" ,
"" };
-
798 for (
unsigned value = 0; value < 5; ++value) {
-
799 frame.
data [0] = value;
-
-
801 CHECK(decoded.
valid && decoded.
physicalValue == value * 2 + 10,
"Numeric scaling unchanged" );
-
-
803 CHECK(value < 4 ? description && *description == expected[value] : !description,
-
804 "Raw lookup and unknown value" );
-
-
-
-
-
809 const char *description;
-
-
811 for (
const Boundary &test: {Boundary{0x8000000000000000ULL,
"Minimum" },
-
812 Boundary{0xFFFFFFFFFFFFFFFFULL,
"Negative" },
-
813 Boundary{0x7FFFFFFFFFFFFFFFULL,
"Maximum" }}) {
-
814 for (
unsigned byte = 0;
byte < 8; ++byte)
-
815 frame.
data [
byte ] =
static_cast< std::uint8_t
> (test.bits >> (
byte * 8));
-
-
-
818 "Signed boundaries and distinct extended frame" );
-
-
-
821 for (
const Boundary &test: {Boundary{0x8000000000000000ULL,
"High" },
-
822 Boundary{0xFFFFFFFFFFFFFFFFULL,
"Full" }}) {
-
823 for (
unsigned byte = 0;
byte < 8; ++byte)
-
824 frame.
data [
byte ] =
static_cast< std::uint8_t
> (test.bits >> (
byte * 8));
-
-
-
827 "Unsigned boundaries" );
-
-
829 CHECK(FindValueDescription(runtime.
GetFrames ()[0].signals[0].valueDescriptions, std::int64_t(1)) !=
nullptr ,
-
830 "Nonnegative signed lookup matches unsigned key" );
-
-
832 CHECK(!
DbcDecoder ().Decode(runtime, frame).signals[0].GetValueDescription(),
"Invalid decode has no description" );
-
-
-
835 void DbcParserTest::invalidValueDescriptions() {
-
-
837 const std::string definitions =
"BO_ 1 Frame: 8 ECU\nSG_ State : 0|64@1+ (1,0) [0|2e20] \"\" ECU\n" ;
-
838 for (
const std::string statement: {
-
839 "VAL_" ,
"VAL_ 1 State;" ,
"VAL_ 1 State ;" ,
"VAL_ 1 State 0 \"Off\"" ,
-
840 "VAL_ 1 State 0 \"Off\"; junk" ,
"VAL_ 1 State 0 Off;" ,
-
841 "VAL_ 1 State 0 \"Unclosed;" ,
"VAL_ 1 State 0 \"Off\"1 \"On\";" ,
-
842 "VAL_ 1 State 0 \"Off\" 00 \"Duplicate\";" ,
-
843 "VAL_ 1 State 0 \"Off\" -0 \"Duplicate\";" ,
-
844 "VAL_ 1 State 0 \"Off\";\nVAL_ 1 State 0 \"Duplicate\";" ,
-
845 "VAL_ 2 State 0 \"Missing frame\";" ,
"VAL_ 1 Missing 0 \"Missing signal\";" ,
-
846 "VAL_ -1 State 0 \"Bad ID\";" ,
"VAL_ 536870912 State 0 \"Bad ID\";" ,
-
847 "VAL_ 4294967296 State 0 \"Bad ID\";" ,
"VAL_ Environment 0 \"Unsupported\";" ,
-
848 "VAL_ 1 State 0 \"Bad\\q escape\";" }) {
-
849 fixture.Write(definitions + statement +
'\n' );
-
850 const int line = statement.find(
'\n' ) == std::string::npos ? 3 : 4;
-
-
-
853 CHECK(
false , statement);
-
854 }
catch (
const std::runtime_error &error) {
-
855 CHECK(std::string(error.what()).find(fixture.path.string() +
":" + std::to_string(line) +
": " ) == 0,
-
856 statement +
" " + error.what());
-
-
-
859 for (
const std::string suffix: {
-
860 "BO_ 1 Other: 8 ECU\n" ,
-
861 "SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n" ,
-
-
863 fixture.Write(
"VAL_ 1 " + std::string(suffix.empty() ?
"Missing" :
"State" ) +
-
864 " 0 \"Description\";\n" + definitions + suffix);
-
-
-
867 CHECK(
false ,
"Missing reference or duplicate definition" );
-
868 }
catch (
const std::runtime_error &error) {
-
869 const std::string line = suffix.empty() ?
"1" :
"4" ;
-
870 CHECK(std::string(error.what()).find(fixture.path.string() +
":" + line +
": " ) == 0,
-
871 "Error retains the reference or duplicate definition source location" );
-
-
-
874 for (
const std::string number: {
"+1" ,
"1x" ,
"0x10" ,
"1.5" ,
"1e2" ,
"--1" ,
-
875 "-9223372036854775809" ,
"18446744073709551616" }) {
-
876 fixture.Write(
"VAL_ 1 State " + number +
" \"Bad\";\n" + definitions);
-
-
-
879 CHECK(
false , number);
-
880 }
catch (
const std::runtime_error &error) {
-
881 CHECK(std::string(error.what()).find(fixture.path.string() +
":1: " ) == 0, number);
-
-
-
-
-
886 int RunParserTests(
int argc,
char **argv) {
-
-
888 return QTest::qExec(&tests, argc, argv);
-
-
-
891 #include "dbc_parser_test.moc"
+
+
51 std::locale previousCppLocale;
+
52 std::string previousCLocale;
+
+
+
+
+
57 inline static int instances = 0;
+
58 inline static int calls = 0;
+
59 CountingHandler() { ++instances; }
+
+
+
+
+
+
+
66 std::string SignalLine(
const std::string &start,
const std::string &length,
+
67 const std::string &order,
const std::string &factor,
+
68 const std::string &offset,
const std::string &minimum,
+
69 const std::string &maximum,
const std::string &name =
"Value" ) {
+
70 return "SG_ " + name +
" : " + start +
"|" + length +
"@" + order +
+
71 " (" + factor +
"," + offset +
") [" + minimum +
"|" + maximum +
"] \"\" ECU" ;
+
+
+
74 class DbcParserTest :
public QObject {
+
+
+
77 void CheckPhysicalNumbers();
+
78 void RejectSignal(
const Fixture &fixture,
const std::string &line,
unsigned payload = 8U) {
+
79 fixture.Write(
"BO_ 1 Frame: " + std::to_string(payload) +
" ECU\n\n" + line +
"\n" );
+
+
+
82 CHECK(
false ,
"Reject " + line);
+
83 }
catch (
const std::runtime_error &error) {
+
84 const std::string prefix = fixture.path.string() +
":3: " ;
+
85 CHECK(std::string(error.what()).find(prefix) == 0U &&
+
86 std::string(error.what()).size() > prefix.size(),
+
+
+
+
+
+
92 void invalidAttributes();
+
93 void attributeNumbers();
+
94 void invalidAttributeNumbers_data();
+
95 void invalidAttributeNumbers();
+
96 void attributeWarnings();
+
+
98 void diagnosticErrors();
+
99 void diagnosticUnsupportedStatements();
+
100 void diagnosticNamespaceBoundaries();
+
101 void diagnosticFormatting();
+
+
103 void multiplexingBoundaries();
+
+
105 void invalidFrames();
+
106 void duplicateFrames();
+
107 void duplicateSignals();
+
108 void distinctDefinitions();
+
+
110 void invalidComments_data();
+
111 void invalidComments();
+
+
113 void invalidSignals();
+
+
115 void physicalNumbersCppLocale();
+
116 void physicalNumbersCLocale();
+
+
118 void independentSessions();
+
119 void valueDescriptions();
+
120 void invalidValueDescriptions();
+
+
+
123 void DbcParserTest::attributes() {
+
+
+
126 "BA_ \"GenMsgCycleTime\" BO_ 1 25;\n"
+
127 "BA_ \"VFrameFormat\" BO_ 2147483649 1;\n"
+
128 "BA_ \"Label\" SG_ 1 Value \"a\\\"b\\\\c\";\n"
+
129 "BA_ \"NodeLabel\" BU_ ECU \"node\";\n"
+
130 "BA_ \"Environment\" EV_ Env 2;\n"
+
131 "BA_DEF_DEF_ \"GenMsgCycleTime\" 100;\n"
+
132 "BA_DEF_DEF_ \"VFrameFormat\" \"StandardCAN\";\n"
+
133 "BA_DEF_DEF_ \"Label\" \"default\";\n"
+
134 "BA_DEF_DEF_ \"BusLabel\" \"CAN\";\n"
+
135 "BA_DEF_DEF_ \"Ratio\" 1.5e-1;\n"
+
136 "BA_DEF_ BO_ \"GenMsgCycleTime\" INT 0 10000;\n"
+
137 "BA_DEF_ BO_ \"VFrameFormat\" ENUM \"StandardCAN\",\"ExtendedCAN\",\"StandardCAN_FD\";\n"
+
138 "BA_DEF_ SG_ \"Label\" STRING;\n"
+
139 "BA_DEF_ \"BusLabel\" STRING;\n"
+
140 "BA_DEF_ BO_ \"Ratio\" FLOAT -1 1;\n"
+
141 "BA_DEF_ BU_ \"NodeLabel\" STRING;\n"
+
142 "BA_DEF_ EV_ \"Environment\" HEX 0 255;\n"
+
143 "BO_ 1 Standard: 1 ECU\n"
+
144 "SG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
+
145 "BO_ 2147483649 Extended: 1 ECU\n"
+
146 "SG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU\n" );
+
+
+
+
+
+
+
153 QCOMPARE(std::get<std::string>(database.
attributes .at(
"BusLabel" )), std::string(
"CAN" ));
+
154 QCOMPARE(database.
frames [0].cycleTimeMs.value(), 25U);
+
155 QCOMPARE(database.
frames [1].cycleTimeMs.value(), 100U);
+
156 QCOMPARE(database.
frames [1].frameFormat.value(), std::string(
"ExtendedCAN" ));
+
157 QVERIFY(!database.
frames [1].hasPgn);
+
158 QCOMPARE(std::get<double>(database.
frames [0].attributes.at(
"Ratio" )), 0.15);
+
159 QCOMPARE(std::get<std::string>(database.
frames [0].signals[0].attributes.at(
"Label" )), std::string(
"a\"b\\c" ));
+
160 QCOMPARE(std::get<std::string>(database.
frames [1].signals[0].attributes.at(
"Label" )), std::string(
"default" ));
+
+
162 QCOMPARE(runtime.
GetFrames ()[0].cycleTimeMs.value(), 25U);
+
163 QCOMPARE(runtime.
GetFrames ()[1].frameFormat.value(), std::string(
"ExtendedCAN" ));
+
164 QCOMPARE(runtime.
GetFrames ()[0].signals[0].attributes, database.
frames [0].signals[0].attributes);
+
+
166 QCOMPARE(tree->GetChild(0)->GetFrame()->cycleTimeMs.value(), 25U);
+
167 QCOMPARE(tree->GetChild(0)->GetChild(0)->GetSignal()->attributes, database.
frames [0].signals[0].attributes);
+
168 fixture.Write(
"BA_DEF_ BO_ \"Period\" INT 0 10;\nBA_DEF_DEF_ \"Period\" 1;\n"
+
169 "BA_ \"Period\" BO_ 1 2;\nBA_ \"Period\" BO_ 1 3;\nBO_ 1 F: 0 ECU\n" );
+
+
171 QCOMPARE(std::get<std::int64_t>(repeated.
frames [0].attributes.at(
"Period" )), std::int64_t(3));
+
+
173 fixture.Write(
"BA_DEF_ BO_ \"GenMsgCycleTime\" INT 0 4294967295;\n"
+
174 "BA_DEF_DEF_ \"GenMsgCycleTime\" 0;\n"
+
175 "BA_ \"GenMsgCycleTime\" BO_ 1 4294967295;\n"
+
176 "BA_DEF_ \"Wide\" INT -9223372036854775808 9223372036854775807;\n"
+
177 "BA_DEF_DEF_ \"Wide\" -9223372036854775808;\n"
+
178 "BA_DEF_ SG_ \"State\" ENUM \"off\",\"on\";\n"
+
179 "BA_DEF_DEF_ \"State\" 1;\n"
+
180 "BO_ 1 F: 0 ECU\nBO_ 2 Empty: 0 ECU\n" );
+
+
182 QCOMPARE(boundaries.
frames [0].cycleTimeMs.value(), std::numeric_limits<std::uint32_t>::max());
+
183 QCOMPARE(boundaries.
frames [1].cycleTimeMs.value(), 0U);
+
184 QVERIFY(!boundaries.
frames [0].frameFormat);
+
185 QCOMPARE(std::get<std::int64_t>(boundaries.
attributes .at(
"Wide" )), std::numeric_limits<std::int64_t>::min());
+
186 QCOMPARE(std::get<std::int64_t>(*boundaries.
attributeDefinitions .at(
"State" ).defaultValue), std::int64_t(1));
+
+
+
189 void DbcParserTest::invalidAttributes() {
+
+
191 const std::vector<std::string> invalid = {
+
192 "BA_DEF_ BO_ \"A\"STRING;" ,
+
193 "BA_DEF_ BO_\"A\" STRING;" ,
+
194 "BA_DEF_ BO_ \"A\" \"STRING\";" ,
+
195 "BA_DEF_ BO_ A STRING;" ,
+
196 "BA_DEF_ ZZ_ \"A\" STRING;" ,
+
197 "BA_DEF_ BO_ \"A\" BLOB;" ,
+
198 "BA_DEF_ BO_ \"A\" FLOAT 2 1;" ,
+
199 "BA_DEF_ BO_ \"A\" STRING;\nBA_ \"A\" BO_ 1 0;" ,
+
200 "BA_DEF_ BO_ \"A\" FLOAT 0 1;\nBA_ \"A\" BO_ 1 2;" ,
+
201 "BA_DEF_ BO_ \"A\" INT 0 1;\nBA_ \"A\" BO_ -1 0;" ,
+
202 "BA_DEF_ BO_ \"A\" INT 0 1;\nBA_ \"A\" BO_ 4294967296 0;" ,
+
203 "BA_DEF_ BO_ \"A\" INT 0 1;\nBA_ \"A\" BO_ 536870912 0;" ,
+
204 "BA_DEF_ BO_ \"A\" INT 2 1;" ,
+
205 "BA_DEF_ BO_ \"A\" FLOAT nan 1;" ,
+
206 "BA_DEF_ BO_ \"A\" FLOAT 0 inf;" ,
+
207 "BA_DEF_ BO_ \"A\" INT 0 9223372036854775808;" ,
+
208 "BA_DEF_ BO_ \"A\" STRING; trailing" ,
+
209 "BA_DEF_ BO_ \"A\" ENUM;" ,
+
210 "BA_DEF_ BO_ \"A\" ENUM \"one\",;" ,
+
211 "BA_DEF_ BO_ \"A\" ENUM \"one\",\"one\";" ,
+
212 "BA_DEF_ BO_ \"VFrameFormat\" STRING;" ,
+
213 "BA_DEF_ SG_ \"GenMsgCycleTime\" INT 0 10;" ,
+
214 "BA_ \"Unknown\" BO_ 1 0;" ,
+
215 "BA_DEF_DEF_ \"Unknown\" 0;" ,
+
216 "BA_DEF_ BO_ \"A\" INT 0 1;\nBA_ \"A\" BO_ 1 2;" ,
+
217 "BA_DEF_ BO_ \"A\" INT 0 1;\nBA_ \"A\" BO_ 1 \"0\";" ,
+
218 "BA_DEF_ BO_ \"A\" INT 0 1;\nBA_ \"A\" SG_ 1 S 0;" ,
+
219 "BA_DEF_ BO_ \"A\" INT 0 1;\nBA_ \"A\" BO_ 2 0;" ,
+
220 "BA_DEF_ SG_ \"A\" INT 0 1;\nBA_ \"A\" SG_ 1 Missing 0;" ,
+
221 "BA_DEF_ BO_ \"A\" INT 0 1;\nBA_DEF_ BO_ \"A\" INT 0 1;" ,
+
222 "BA_DEF_ BO_ \"A\" INT 0 1;\nBA_DEF_DEF_ \"A\" 0;\nBA_DEF_DEF_ \"A\" 1;" ,
+
223 "BA_DEF_ BO_ \"A\" STRING;\nBA_ \"A\" BO_ 1 \"bad\\q\";" ,
+
224 "BA_DEF_ BO_ \"A\" STRING;\nBA_ \"A\" BO_ 1 \"unterminated;" ,
+
225 "BA_DEF_ BO_ \"A\" ENUM \"one\";\nBA_DEF_DEF_ \"A\" \"missing\";" ,
+
226 "BA_DEF_ BO_ \"A\" ENUM \"one\";\nBA_ \"A\" BO_ 1 1;" ,
+
227 "BA_DEF_ BO_ \"GenMsgCycleTime\" INT -1 4294967296;\nBA_DEF_DEF_ \"GenMsgCycleTime\" -1;" ,
+
228 "BA_DEF_ BO_ \"GenMsgCycleTime\" INT 0 4294967296;\nBA_ \"GenMsgCycleTime\" BO_ 1 4294967296;" };
+
229 for (
const std::string &statement: invalid) {
+
230 fixture.Write(
"BO_ 1 F: 0 ECU\n" + statement +
'\n' );
+
+
232 QVERIFY2(result.
HasErrors (), statement.c_str());
+
+
234 QCOMPARE(result.
diagnostics .back().code, DbcDiagnosticCode::InvalidAttribute);
+
235 QCOMPARE(result.
diagnostics .back().lineNumber, std::size_t(2 + std::count(statement.begin(), statement.end(),
'\n' )));
+
236 QVERIFY_THROWS_EXCEPTION(std::runtime_error,
DbcParser ().ParseFile(fixture.path.string()));
+
+
+
+
240 void DbcParserTest::attributeNumbers() {
+
241 ApplicationLocaleGuard guard;
+
242 std::locale::global(std::locale(std::locale::classic(),
new CommaDecimalPunctuation));
+
+
244 fixture.Write(
"BA_DEF_ \"I\" INT -9223372036854775808 +9223372036854775807;\n"
+
245 "BA_DEF_DEF_ \"I\" -9223372036854775808;\n"
+
246 "BA_ \"I\" +9223372036854775807;\n"
+
247 "BA_DEF_ \"H\" HEX -10 +10;\n"
+
248 "BA_DEF_DEF_ \"H\" +0;\n"
+
+
250 "BA_DEF_ \"F\" FLOAT -1.25e+2 +2.5E2;\n"
+
251 "BA_DEF_DEF_ \"F\" +.5;\n"
+
252 "BA_ \"F\" -1.25e+2;\n"
+
253 "BA_DEF_ BU_ \"NodeDefault\" INT 0 10;\n"
+
254 "BA_DEF_DEF_ \"NodeDefault\" 5;\n"
+
255 "BA_DEF_ EV_ \"EnvironmentDefault\" STRING;\n"
+
256 "BA_DEF_DEF_ \"EnvironmentDefault\" \"default\";\n" );
+
+
+
+
+
261 QCOMPARE(std::get<std::int64_t>(result.
database .
attributes .at(
"I" )), std::numeric_limits<std::int64_t>::max());
+
+
263 QCOMPARE(std::get<std::int64_t>(result.
database .
attributes .at(
"H" )), std::int64_t(-10));
+
+
+
+
+
+
+
+
271 void DbcParserTest::invalidAttributeNumbers_data() {
+
272 QTest::addColumn<QString>(
"type" );
+
273 QTest::addColumn<QString>(
"number" );
+
274 const char *types[] = {
"INT" ,
"HEX" ,
"FLOAT" };
+
275 const char *invalid[] = {
"+" ,
"-" ,
"++1" ,
"+-1" ,
"--1" ,
"1x" ,
"0x10" ,
+
276 "nan" ,
"inf" ,
"-inf" ,
"1e9999" ,
"1e-9999" };
+
277 for (
const char *type: types) {
+
278 for (
const char *number: invalid) {
+
279 const std::string name = std::string(type) +
'-' + number;
+
280 QTest::newRow(name.c_str()) << QString(type) << QString(number);
+
+
+
283 QTest::newRow(
"integer-overflow" ) << QString(
"INT" ) << QString(
"9223372036854775808" );
+
284 QTest::newRow(
"integer-underflow" ) << QString(
"INT" ) << QString(
"-9223372036854775809" );
+
285 QTest::newRow(
"integer-fraction" ) << QString(
"INT" ) << QString(
"1.5" );
+
+
+
288 void DbcParserTest::invalidAttributeNumbers() {
+
289 QFETCH(QString, type);
+
290 QFETCH(QString, number);
+
291 const std::string kind = type.toStdString();
+
292 const std::string text = number.toStdString();
+
293 const std::string definition =
"BA_DEF_ \"A\" " + kind +
" -10 10;\n" ;
+
294 const std::string statements[] = {
+
295 "BA_DEF_ \"A\" " + kind +
' ' + text +
" 10;\n" ,
+
296 "BA_DEF_ \"A\" " + kind +
" -10 " + text +
";\n" ,
+
297 definition +
"BA_DEF_DEF_ \"A\" " + text +
";\n" ,
+
298 definition +
"BA_ \"A\" " + text +
";\n" };
+
+
300 for (
const std::string &statement: statements) {
+
301 fixture.Write(statement);
+
+
303 QVERIFY2(result.
HasErrors (), statement.c_str());
+
+
305 QCOMPARE(result.
diagnostics .back().code, DbcDiagnosticCode::InvalidAttribute);
+
+
307 static_cast< std::size_t
> (std::count(statement.begin(), statement.end(),
'\n' )));
+
308 QVERIFY_THROWS_EXCEPTION(std::runtime_error,
DbcParser ().ParseFile(fixture.path.string()));
+
+
+
+
312 void DbcParserTest::attributeWarnings() {
+
+
314 fixture.Write(
"BA_DEF_ BO_ \"VFrameFormat\" ENUM \"StandardCAN\",\"ExtendedCAN\",\"J1939PG\",\"StandardCAN_FD\";\n"
+
315 "BA_DEF_DEF_ \"VFrameFormat\" \"StandardCAN_FD\";\n"
+
316 "BA_ \"VFrameFormat\" BO_ 1 2;\n"
+
317 "BA_ \"VFrameFormat\" BO_ 2147483649 0;\n"
+
318 "BO_ 1 F: 0 ECU\nBO_ 2147483649 E: 0 ECU\nBO_ 2 Default: 0 ECU\n" );
+
+
+
321 QCOMPARE(result.
diagnostics .size(), std::size_t(3));
+
322 const std::size_t lines[] = {3U, 4U, 2U};
+
323 for (std::size_t index = 0; index < 3U; ++index) {
+
324 QCOMPARE(result.
diagnostics [index].code, DbcDiagnosticCode::UnsupportedAttribute);
+
325 QCOMPARE(result.
diagnostics [index].severity, DbcDiagnosticSeverity::Warning);
+
326 QCOMPARE(result.
diagnostics [index].lineNumber, lines[index]);
+
327 QCOMPARE(result.
diagnostics [index].filePath, fixture.path.string());
+
+
329 QCOMPARE(result.
database .
frames [0].frameFormat.value(), std::string(
"J1939PG" ));
+
+
+
+
+
334 void DbcParserTest::diagnostics() {
+
+
336 fixture.Write(
"VERSION \"test\"\n"
+
+
+
+
+
+
+
+
344 "BO_ 1 Frame: 1 ECU\n"
+
345 "SG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
+
346 "SIG_VALTYPE_ 1 Value : 1;\n"
+
347 "BA_REL_ \"SignalType\" SG_ 1 Value 1;\n"
+
348 "VENDOR_EXTENSION_ data;\n" );
+
+
+
351 "Warnings preserve the supported database" );
+
352 QCOMPARE(result.
diagnostics .size(), std::size_t(3U));
+
353 for (std::size_t index = 0U; index < result.
diagnostics .size(); ++index) {
+
+
355 CHECK(diagnostic.
severity == DbcDiagnosticSeverity::Warning &&
+
356 diagnostic.
code == DbcDiagnosticCode::UnsupportedStatement,
+
357 "Unsupported statements have structured warning severity and code" );
+
358 QCOMPARE(diagnostic.
filePath , fixture.path.string());
+
+
360 CHECK(diagnostic.
message .find(
"ignored" ) != std::string::npos,
+
361 "Warning explains unsupported syntax" );
+
+
363 CHECK(
DbcParser ().ParseFile(fixture.path.string()).frames.size() == 1U,
+
364 "Legacy API accepts files with warnings" );
+
365 fixture.Write(
"VERSION \"\"\nNS_:\nSIG_VALTYPE_\n\tBA_\n BS_ :\n BU_ : ECU\n" );
+
+
367 CHECK(headers.
diagnostics .empty(),
"Common header variants stay quiet" );
+
368 fixture.Write(
"NS_ :\n BA_\n BO_\n" );
+
369 CHECK(
DbcParser ().ParseFileWithDiagnostics(fixture.path.string()).HasErrors(),
+
370 "Namespace handling does not swallow a malformed frame" );
+
+
+
373 void DbcParserTest::diagnosticErrors() {
+
+
+
+
377 DbcDiagnosticCode code;
+
+
+
380 const ErrorCase cases[] = {
+
381 {
"UNKNOWN_ data;\n\nBO_ invalid Frame: 1 ECU\n" ,
+
382 DbcDiagnosticCode::InvalidStatement, 3U},
+
383 {
"BO_ 1 Frame: 1 ECU\nSG_MUL_VAL_ 1 Value Mode 1-2;\n" ,
+
384 DbcDiagnosticCode::UnsupportedStatement, 2U},
+
385 {
"BO_ 1 Frame: 1 ECU\nVAL_ 1 Missing 0 \"Off\";\n" ,
+
386 DbcDiagnosticCode::InvalidValueDescription, 2U},
+
387 {
"BO_ 1 Frame: 1 ECU\nSG_ Value m1 : 0|8@1+ (1,0) [0|255] \"\" ECU\n" ,
+
388 DbcDiagnosticCode::InvalidMultiplexing, 2U},
+
389 {
"BO_ 1 Frame: 1 ECU\nSG_ Mode M : 0|8@1- (1,0) [-128|127] \"\" ECU\n" ,
+
390 DbcDiagnosticCode::InvalidMultiplexing, 2U},
+
391 {
"VAL_ broken\n" , DbcDiagnosticCode::InvalidValueDescription, 1U},
+
392 {
"SG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU\n" ,
+
393 DbcDiagnosticCode::InvalidStatement, 1U},
+
394 {
"BO_ 1 Frame: 1 ECU\nBO_ 1 Duplicate: 1 ECU\n" ,
+
395 DbcDiagnosticCode::InvalidStatement, 2U},
+
396 {
"BO_ 1 Frame: 1 ECU\nSG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
+
397 "SG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU\n" ,
+
398 DbcDiagnosticCode::InvalidStatement, 3U},
+
399 {
"BO_ 1 Frame: 1 ECU\nSG_ Value : 8|8@1+ (1,0) [0|255] \"\" ECU\n" ,
+
400 DbcDiagnosticCode::InvalidStatement, 2U},
+
401 {
"BO_ 1 Frame: 1 ECU\nVAL_ 2 Missing 0 \"Off\";\n" ,
+
402 DbcDiagnosticCode::InvalidValueDescription, 2U},
+
403 {
"BO_ 1 Frame: 1 ECU\nSG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
+
404 "VAL_ 1 Value 0 \"Off\";\nVAL_ 1 Value 0 \"Duplicate\";\n" ,
+
405 DbcDiagnosticCode::InvalidValueDescription, 4U},
+
406 {
"BO_ 1 Frame: 2 ECU\nSG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n"
+
407 "SG_ Value m2 : 8|8@1+ (1,0) [0|255] \"\" ECU\n" ,
+
408 DbcDiagnosticCode::InvalidMultiplexing, 3U},
+
409 {
"BO_ 1 Frame: 2 ECU\nSG_ Mode M : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
+
410 "SG_ Other M : 8|8@1+ (1,0) [0|255] \"\" ECU\n" ,
+
411 DbcDiagnosticCode::InvalidMultiplexing, 3U},
+
412 {
"BO_ 1 Frame: 1 ECU\nSG_ First : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
+
413 "SG_ Second : 7|8@0+ (1,0) [0|255] \"\" ECU\n" ,
+
414 DbcDiagnosticCode::InvalidMultiplexing, 3U}
+
+
416 for (
const ErrorCase &test : cases) {
+
417 fixture.Write(test.text);
+
+
+
420 "Failed parse never returns a partial database" );
+
+
422 CHECK(diagnostic.
severity == DbcDiagnosticSeverity::Error && diagnostic.
code == test.code,
+
423 "Error has expected severity and code" );
+
424 QCOMPARE(diagnostic.
filePath , fixture.path.string());
+
+
426 CHECK(!diagnostic.
message .empty(),
"Error includes a message" );
+
427 const bool hasWarning = std::string(test.text).find(
"UNKNOWN_" ) == 0U;
+
428 QCOMPARE(result.
diagnostics .size(), hasWarning ? std::size_t(2U) : std::size_t(1U));
+
+
+
431 CHECK(
false ,
"Legacy parser must throw" );
+
432 }
catch (
const std::runtime_error &error) {
+
433 QCOMPARE(std::string(error.what()), fixture.path.string() +
":" +
+
434 std::to_string(test.line) +
": " + diagnostic.
message );
+
+
+
437 const std::string missingPath = fixture.path.string() +
".missing" ;
+
+
+
440 QCOMPARE(missing.
diagnostics .size(), std::size_t(1U));
+
441 CHECK(missing.
diagnostics [0].code == DbcDiagnosticCode::FileOpenError,
+
442 "Missing file has a distinct code" );
+
443 QCOMPARE(missing.
diagnostics [0].lineNumber, std::size_t(0U));
+
444 QCOMPARE(missing.
diagnostics [0].filePath, missingPath);
+
445 QCOMPARE(missing.
diagnostics [0].message,
"Failed to open DBC file: " + missingPath);
+
+
+
448 CHECK(
false ,
"Legacy API throws on missing file" );
+
449 }
catch (
const std::runtime_error &error) {
+
450 QCOMPARE(std::string(error.what()), missing.
diagnostics [0].message);
+
+
452 const std::string directoryPath = fixture.path.parent_path().string();
+
+
+
455 "Directory cannot be parsed as a file" );
+
456 QCOMPARE(directory.
diagnostics .size(), std::size_t(1U));
+
457 CHECK(directory.
diagnostics [0].code == DbcDiagnosticCode::FileReadError ||
+
458 directory.
diagnostics [0].code == DbcDiagnosticCode::FileOpenError,
+
459 "Directory produces a file-level error on supported platforms" );
+
460 QCOMPARE(directory.
diagnostics [0].lineNumber, std::size_t(0U));
+
461 QCOMPARE(directory.
diagnostics [0].filePath, directoryPath);
+
+
463 CHECK(directory.
diagnostics [0].code == DbcDiagnosticCode::FileReadError,
+
464 "Linux directory input exercises the read-error path" );
+
465 QCOMPARE(directory.
diagnostics [0].message,
"Failed to read DBC file: " + directoryPath);
+
+
+
+
469 CHECK(
false ,
"Legacy API throws on unreadable input" );
+
470 }
catch (
const std::runtime_error &error) {
+
471 QCOMPARE(std::string(error.what()), directory.
diagnostics [0].message);
+
+
473 fixture.Write(
"BO_ 1 Frame: 1 ECU\n" );
+
474 CHECK(
DbcParser ().ParseFileWithDiagnostics(fixture.path.string()).diagnostics.empty(),
+
475 "Diagnostics belong to an independent parse session" );
+
+
+
478 void DbcParserTest::diagnosticUnsupportedStatements() {
+
+
480 const std::string definitions =
+
481 "BO_ 1 Frame: 1 ECU\nSG_ Value : 0|8@1+ (2,10) [10|520] \"V\" ECU\n"
+
482 "CM_ SG_ 1 Value \"Signal comment\";\nVAL_ 1 Value 1 \"On\";\n" ;
+
483 const std::vector<std::string> statements = {
+
484 "SIG_VALTYPE_ 1 Value : 1;" ,
"SIG_VALTYPE_ 1 Value : 2;" ,
+
485 "BA_REL_ \"SignalType\" SG_ 1 Value 1;" ,
+
486 "BA_DEF_REL_ BU_SG_REL_ \"Relation\" INT 0 1;" ,
+
487 "BA_REL_ \"Relation\" BU_SG_REL_ ECU SG_ 1 Value 1;" ,
+
488 "SGTYPE_ Type : 8@1+ (1,0) [0|255] \"\" 0, Table;" ,
+
489 "SIG_TYPE_REF_ 1 Value : Type;" ,
+
490 "EV_ Environment : 0 [0|1] \"\" 0 1 DUMMY_NODE_VECTOR0 ECU;" ,
+
491 "ENVVAR_DATA_ Environment : 4;" ,
+
492 "VAL_TABLE_ Table 0 \"Off\" 1 \"On\";" ,
+
493 "BO_TX_BU_ 1 : ECU;" ,
"VENDOR_EXTENSION_ data;" ,
"UNKNOWN_"
+
+
495 for (
const std::string &statement : statements) {
+
496 fixture.Write(definitions + statement +
'\n' );
+
+
+
499 QCOMPARE(result.
diagnostics .size(), std::size_t(1U));
+
+
501 CHECK(warning.
severity == DbcDiagnosticSeverity::Warning &&
+
502 warning.
code == DbcDiagnosticCode::UnsupportedStatement, statement);
+
503 QCOMPARE(warning.
filePath , fixture.path.string());
+
504 QCOMPARE(warning.
lineNumber , std::size_t(5U));
+
505 const std::string keyword = statement.substr(0U, statement.find(
' ' ));
+
506 CHECK(warning.
message .find(
"'" + keyword +
"'" ) != std::string::npos, statement);
+
+
+
+
+
+
512 CHECK(decoded.
valid && decoded.signals.size() == 1U && decoded.signals[0].
valid ,
+
513 "Warnings preserve supported signal decoding" );
+
514 QCOMPARE(decoded.signals[0].physicalValue, 12.0);
+
515 CHECK(decoded.signals[0].GetValueDescription() &&
+
516 *decoded.signals[0].GetValueDescription() ==
"On" ,
+
517 "Warnings preserve VAL_ descriptions" );
+
518 QCOMPARE(runtime.
GetFrames ()[0].signals[0].comment, std::string(
"Signal comment" ));
+
+
+
+
522 void DbcParserTest::diagnosticNamespaceBoundaries() {
+
+
524 const std::vector<std::string> endings = {
+
525 "BS_\n" ,
"BS_:\n" ,
"BS_ :\n" ,
"BU_\n" ,
"BU_:\n" ,
"BU_ : ECU\n" ,
+
526 "BO_ 1 Frame: 1 ECU\n" ,
"VENDOR_EXTENSION_ data;\n"
+
+
528 for (
const std::string &ending : endings) {
+
529 fixture.Write(
"NS_ :\n\tSG_MUL_VAL_\n\nBA_\n" + ending +
"SIG_VALTYPE_\n" );
+
+
+
532 const std::size_t expectedWarnings = ending.find(
"VENDOR_" ) == 0U ? 2U : 1U;
+
533 QCOMPARE(result.
diagnostics .size(), expectedWarnings);
+
534 QCOMPARE(result.
diagnostics .back().lineNumber, std::size_t(6U));
+
535 CHECK(result.
diagnostics .back().message.find(
"SIG_VALTYPE_" ) != std::string::npos,
+
536 "Unsupported keyword outside NS_ must produce a warning" );
+
+
538 for (
const std::string &definition : {std::string(
"BO_" ), std::string(
"SG_" )}) {
+
539 fixture.Write(
"NS_:\n\tBA_\n\t" + definition +
'\n' );
+
+
541 CHECK(result.
HasErrors (),
"Malformed definition ends NS_ instead of being hidden" );
+
542 QCOMPARE(result.
diagnostics .size(), std::size_t(1U));
+
543 QCOMPARE(result.
diagnostics [0].lineNumber, std::size_t(3U));
+
+
+
+
547 void DbcParserTest::diagnosticFormatting() {
+
+
549 fixture.path +=
" with spaces" ;
+
+
551 for (
const std::string &text : {std::string(), std::string(
" \t\r\n\n" )}) {
+
+
+
+
555 "Empty and whitespace-only inputs are valid" );
+
+
557 fixture.Write(
"\r\n\tVENDOR_EXTENSION_ data;\r\n\r\nUNKNOWN_" );
+
558 const std::string relativePath = std::filesystem::relative(fixture.path).string();
+
+
+
561 QCOMPARE(warnings.
diagnostics .size(), std::size_t(2U));
+
562 QCOMPARE(warnings.
diagnostics [0].lineNumber, std::size_t(2U));
+
563 QCOMPARE(warnings.
diagnostics [1].lineNumber, std::size_t(4U));
+
+
565 QCOMPARE(warning.filePath, relativePath);
+
+
567 fixture.Write(
"UNKNOWN_ first;\nBO_ invalid Frame: 1 ECU\n"
+
568 "UNKNOWN_ after_error;\nSG_ broken\n" );
+
+
+
571 QCOMPARE(stopped.
diagnostics .size(), std::size_t(2U));
+
572 QCOMPARE(stopped.
diagnostics [0].lineNumber, std::size_t(1U));
+
573 QCOMPARE(stopped.
diagnostics [1].lineNumber, std::size_t(2U));
+
574 QCOMPARE(stopped.
diagnostics [1].filePath, relativePath);
+
+
576 fixture.Write(
"VAL_ 1 Missing 0 \"Off\";\nBO_ 1 Frame: 1 ECU\nUNKNOWN_ data;\n" );
+
+
+
579 QCOMPARE(deferred.
diagnostics .size(), std::size_t(2U));
+
580 CHECK(deferred.
diagnostics [0].severity == DbcDiagnosticSeverity::Warning &&
+
581 deferred.
diagnostics [1].severity == DbcDiagnosticSeverity::Error,
+
582 "Deferred errors follow warnings in detection order" );
+
583 QCOMPARE(deferred.
diagnostics [0].lineNumber, std::size_t(3U));
+
584 QCOMPARE(deferred.
diagnostics [1].lineNumber, std::size_t(1U));
+
585 QCOMPARE(deferred.
diagnostics [1].filePath, relativePath);
+
586 fixture.Write(
"BO_ 1 Frame: 1 ECU" );
+
+
+
589 "Same parser has clean state after errors and accepts missing final newline" );
+
+
+
592 void DbcParserTest::validFrames() {
+
+
+
+
+
+
+
+
600 const ValidCase valid[] = {
+
601 {
"BO_ 0 Frame: 0 ECU" , 0U,
false , 0U},
+
602 {
"BO_ 2047 Frame: 8 ECU" , 2047U,
false , 8U},
+
603 {
"BO_ 2048 Frame: 64 ECU" , 2048U,
true , 64U},
+
604 {
"BO_ 536870911 Frame: 255 ECU" , 0x1FFFFFFFU,
true , 255U},
+
605 {
"BO_ 2147483649 Frame: 8 ECU" , 1U,
true , 8U},
+
606 {
"BO_ 2684354559 Frame: 8 ECU" , 0x1FFFFFFFU,
true , 8U},
+
607 {
" BO_\t256\tFrame :\t8\tECU \r" , 256U,
false , 8U}};
+
608 for (
const ValidCase &test: valid) {
+
609 fixture.Write(std::string(test.line) +
'\n' );
+
+
+
612 QCOMPARE(database.
frames .size(), std::size_t(1U));
+
+
614 QCOMPARE(frame.
name , std::string(
"Frame" ));
+
615 QCOMPARE(frame.
canId , test.id);
+
+
617 QCOMPARE(
static_cast< unsigned > (frame.
dlc ), test.length);
+
+
619 }
catch (
const std::exception &error) { CHECK(
false , error.what()); }
+
+
+
+
623 void DbcParserTest::invalidFrames() {
+
+
625 const char *invalid[] = {
+
626 "BO_ invalid" ,
"BO_" ,
"BO_ 1" ,
"BO_ 1 : 8 ECU" ,
"BO_ 1 Frame 8 ECU" ,
+
627 "BO_ 1 Frame:" ,
"BO_ 1 Frame: 8" ,
"BO_ 1 Frame: 8 ECU extra" ,
+
628 "BO_ 1 Two Names: 8 ECU" ,
"BO_ -1 Frame: 8 ECU" ,
"BO_ +1 Frame: 8 ECU" ,
+
629 "BO_ 1x Frame: 8 ECU" ,
"BO_ 0x123 Frame: 8 ECU" ,
"BO_ 1.5 Frame: 8 ECU" ,
+
630 "BO_ 4294967296 Frame: 8 ECU" ,
"BO_ 999999999999999999999 Frame: 8 ECU" ,
+
631 "BO_ 536870912 Frame: 8 ECU" ,
"BO_ 1073741824 Frame: 8 ECU" ,
+
632 "BO_ 2684354560 Frame: 8 ECU" ,
"BO_ 4294967295 Frame: 8 ECU" ,
+
633 "BO_ 1 Frame: -1 ECU" ,
"BO_ 1 Frame: +8 ECU" ,
"BO_ 1 Frame: 8x ECU" ,
+
634 "BO_ 1 Frame: 8.5 ECU" ,
"BO_ 1 Frame: 256 ECU" ,
+
635 "BO_ 1 Frame: 4294967296 ECU" ,
"BO_\tinvalid" };
+
636 for (
const char *line: invalid) {
+
637 fixture.Write(std::string(
"VERSION \"test\"\n\n" ) + line +
'\n' );
+
+
+
+
641 }
catch (
const std::runtime_error &error) {
+
642 const std::string prefix = fixture.path.string() +
":3: " ;
+
643 CHECK(std::string(error.what()).find(prefix) == 0U &&
+
644 std::string(error.what()).size() > prefix.size(),
+
+
+
+
+
+
650 void DbcParserTest::duplicateFrames() {
+
+
652 struct DuplicateCase {
+
+
654 const char *duplicateId;
+
+
+
657 const DuplicateCase cases[] = {
+
658 {
"1" ,
"1" ,
"Duplicate standard frame CAN ID: 1" },
+
659 {
"2147483649" ,
"2147483649" ,
"Duplicate extended frame CAN ID: 1" },
+
660 {
"2048" ,
"2147485696" ,
"Duplicate extended frame CAN ID: 2048" },
+
661 {
"2147485696" ,
"2048" ,
"Duplicate extended frame CAN ID: 2048" },
+
662 {
"536870911" ,
"2684354559" ,
"Duplicate extended frame CAN ID: 536870911" }
+
+
+
665 for (
const DuplicateCase &test : cases) {
+
666 fixture.Write(
"BO_ " + std::string(test.firstId) +
" First: 8 ECU\n"
+
667 "BO_ 2 Other: 8 ECU\n\n"
+
668 " BO_\t" + test.duplicateId +
"\tSecond: 8 ECU\n" );
+
+
+
671 CHECK(
false ,
"Duplicate frame must be rejected" );
+
672 }
catch (
const std::runtime_error &error) {
+
673 QCOMPARE(std::string(error.what()), fixture.path.string() +
":4: " + test.message);
+
+
+
676 fixture.Write(
"BO_ 1 First: 8 ECU\n" );
+
677 QCOMPARE(parser.
ParseFile (fixture.path.string()).
frames .size(), std::size_t(1U));
+
+
+
680 void DbcParserTest::duplicateSignals() {
+
+
682 const std::string first =
"SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n" ;
+
683 const std::string duplicates[] = {
+
+
685 " SG_\tState : 16|8@1+ (2,1) [0|511] \"V\" ECU\n" ,
+
686 "SG_ State m1 : 16|8@1+ (1,0) [0|255] \"\" ECU\n"
+
+
688 for (
const std::string &duplicate : duplicates) {
+
689 fixture.Write(
"BO_ 1 Frame: 8 ECU\n" + first +
+
690 "SG_ Other : 8|8@1+ (1,0) [0|255] \"\" ECU\n\n" + duplicate);
+
+
+
693 CHECK(
false ,
"Duplicate signal must be rejected" );
+
694 }
catch (
const std::runtime_error &error) {
+
695 QCOMPARE(std::string(error.what()), fixture.path.string() +
+
696 ":5: Duplicate signal name 'State' in frame 'Frame'." );
+
+
+
+
+
701 void DbcParserTest::distinctDefinitions() {
+
+
703 fixture.Write(
"BO_ 1 Shared: 1 ECU\n"
+
704 "SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
+
705 "BO_ 2147483649 Shared: 1 ECU\n"
+
706 "SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
+
707 "BO_ 2 Shared: 2 ECU\n"
+
708 "SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
+
709 "SG_ state : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
+
710 "CM_ BO_ 1 \"Standard\";\n"
+
711 "CM_ BO_ 2147483649 \"Extended\";\n"
+
712 "CM_ SG_ 1 State \"Standard state\";\n"
+
713 "CM_ SG_ 2147483649 State \"Extended state\";\n" );
+
+
715 QCOMPARE(parsed.
frames .size(), std::size_t(3U));
+
716 QCOMPARE(parsed.
frames [0].canId, parsed.
frames [1].canId);
+
717 CHECK(!parsed.
frames [0].isExtended && parsed.
frames [1].isExtended,
+
718 "Standard and extended frames with the same numeric ID remain distinct" );
+
719 QCOMPARE(parsed.
frames [0].comment, std::string(
"Standard" ));
+
720 QCOMPARE(parsed.
frames [1].comment, std::string(
"Extended" ));
+
721 QCOMPARE(parsed.
frames [0].signals[0].comment, std::string(
"Standard state" ));
+
722 QCOMPARE(parsed.
frames [1].signals[0].comment, std::string(
"Extended state" ));
+
723 QCOMPARE(parsed.
frames [2].signals.size(), std::size_t(2U));
+
+
+
+
+
+
729 QVERIFY(standard.
valid );
+
730 QCOMPARE(standard.
definition ->comment, std::string(
"Standard" ));
+
+
+
733 QVERIFY(extended.
valid );
+
734 QCOMPARE(extended.
definition ->comment, std::string(
"Extended" ));
+
+
+
737 void DbcParserTest::comments() {
+
+
+
740 "CM_\tBO_\t1\t\"First\";\r\n"
+
741 "CM_\tSG_\t1\tState\t\" Line one \r\n"
+
+
743 "\tBO_ is text; \\\"quoted\\\" and \\\\slash\"\t;\r\n"
+
744 "CM_ BO_ 2147483649 \"Extended\";\r\n"
+
745 "CM_ SG_ 2147483649 State \"Extended signal\";\r\n"
+
746 "BO_ 1 Standard: 1 ECU\r\n"
+
747 "CM_ BO_ 1 \"Last\";\r\n"
+
748 "SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\r\n"
+
749 "BO_ 2147483649 Extended: 1 ECU\r\n"
+
750 "SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU" );
+
+
+
+
+
+
+
757 std::string(
" Line one \n\n\tBO_ is text; \"quoted\" and \\slash" ));
+
758 QCOMPARE(result.
database .
frames [1].comment, std::string(
"Extended" ));
+
759 QCOMPARE(result.
database .
frames [1].signals[0].comment, std::string(
"Extended signal" ));
+
+
761 const std::string ids[][2] = {
+
+
+
764 {
"2048" ,
"2147485696" },
+
765 {
"536870911" ,
"2684354559" },
+
766 {
"2684354559" ,
"536870911" }};
+
767 for (
const std::string(&
id )[2]: ids) {
+
768 fixture.Write(
"CM_ BO_ " +
id [0] +
" \"Frame\";\nCM_ SG_ " +
id [0] +
+
769 " State \"Signal\";\nBO_ " +
id [1] +
" Frame: 1 ECU\n"
+
770 "SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n" );
+
+
772 QCOMPARE(database.
frames [0].comment, std::string(
"Frame" ));
+
773 QCOMPARE(database.
frames [0].signals[0].comment, std::string(
"Signal" ));
+
+
775 fixture.Write(
"CM_ BO_ 1 \"Line one\nLine two\";\n"
+
776 "BO_ 1 Frame: 0 ECU\nUNKNOWN_ value\nBO_ bad Frame: 0 ECU\n" );
+
+
+
779 QCOMPARE(following.
diagnostics .size(), std::size_t(2));
+
780 QCOMPARE(following.
diagnostics [0].lineNumber, std::size_t(4));
+
781 QCOMPARE(following.
diagnostics [1].lineNumber, std::size_t(5));
+
+
+
784 void DbcParserTest::invalidComments_data() {
+
785 QTest::addColumn<QString>(
"statement" );
+
786 const char *ids[] = {
"-1" ,
"+1" ,
"1x" ,
"0x1" ,
"4294967296" ,
"536870912" ,
+
787 "1073741824" ,
"2684354560" ,
"4294967295" };
+
788 for (
const char *
id : ids) {
+
789 const std::string frameRow = std::string(
"frame-id-" ) + id;
+
790 const std::string signalRow = std::string(
"signal-id-" ) + id;
+
791 QTest::newRow(frameRow.c_str()) << QString::fromStdString(
"CM_ BO_ " + std::string(
id ) +
" \"Text\";" );
+
792 QTest::newRow(signalRow.c_str()) << QString::fromStdString(
"CM_ SG_ " + std::string(
id ) +
" State \"Text\";" );
+
+
794 QTest::newRow(
"missing-id" ) << QStringLiteral(
"CM_ BO_" );
+
795 QTest::newRow(
"missing-signal" ) << QStringLiteral(
"CM_ SG_ 1 \"Text\";" );
+
796 QTest::newRow(
"missing-quote" ) << QStringLiteral(
"CM_ BO_ 1 Text;" );
+
797 QTest::newRow(
"unclosed" ) << QStringLiteral(
"CM_ SG_ 1 State \"Text\n More" );
+
798 QTest::newRow(
"invalid-escape" ) << QStringLiteral(
"CM_ BO_ 1 \"bad\\q\";" );
+
799 QTest::newRow(
"dangling-escape" ) << QStringLiteral(
"CM_ BO_ 1 \"bad\\" );
+
800 QTest::newRow(
"missing-semicolon" ) << QStringLiteral(
"CM_ SG_ 1 State \"Text\"" );
+
801 QTest::newRow(
"trailing-text" ) << QStringLiteral(
"CM_ BO_ 1 \"Text\"; garbage" );
+
802 QTest::newRow(
"extra-header" ) << QStringLiteral(
"CM_ BO_ 1 extra \"Text\";" );
+
803 QTest::newRow(
"extra-string" ) << QStringLiteral(
"CM_ BO_ 1 \"Text\" \"More\";" );
+
804 QTest::newRow(
"missing-frame" ) << QStringLiteral(
"CM_ BO_ 2 \"Text\";" );
+
805 QTest::newRow(
"missing-signal-frame" ) << QStringLiteral(
"CM_ SG_ 2 State \"Text\";" );
+
806 QTest::newRow(
"missing-signal-reference" ) << QStringLiteral(
"CM_ SG_ 1 Missing \"Text\";" );
+
807 QTest::newRow(
"different-frame-type" ) << QStringLiteral(
"CM_ BO_ 2147483649 \"Text\";" );
+
808 QTest::newRow(
"missing-multiline-reference" ) << QStringLiteral(
"CM_ SG_ 1 Missing \"Text\nMore\";" );
+
+
+
811 void DbcParserTest::invalidComments() {
+
812 QFETCH(QString, statement);
+
+
814 fixture.Write(
"BO_ 1 Frame: 1 ECU\nSG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n\n" +
+
815 statement.toStdString());
+
+
+
+
819 QCOMPARE(result.
diagnostics .size(), std::size_t(1));
+
+
821 QCOMPARE(error.
severity , DbcDiagnosticSeverity::Error);
+
822 QCOMPARE(error.
code , DbcDiagnosticCode::InvalidStatement);
+
823 QCOMPARE(error.
filePath , fixture.path.string());
+
+
825 QVERIFY(!error.
message .empty());
+
+
+
828 QFAIL(
"Malformed or unresolved comment must throw." );
+
829 }
catch (
const std::runtime_error &exception) {
+
830 QVERIFY(std::string(exception.what()).find(fixture.path.string() +
":4: " ) == 0U);
+
+
+
+
834 void DbcParserTest::integration() {
+
+
+
837 "BO_TX_BU_ 256 : ECU;\nBO_ 256 Frame: 8 ECU\n"
+
838 " SG_ Speed : 0|16@1+ (0.5,1) [0|100] \"rpm\" ECU\n"
+
839 "CM_ BO_ 256 \"Frame comment\";\nCM_ SG_ 256 Speed \"Signal comment\";\n"
+
840 "BO_ 257 Second: 8 ECU\n" );
+
+
842 CHECK(database.
frames .size() == 2U && database.
frames [0].signals.size() == 1U &&
+
843 database.
frames [0].comment ==
"Frame comment" &&
+
844 database.
frames [0].signals[0].comment ==
"Signal comment" ,
+
+
846 fixture.Write(
"\nSG_ Speed : invalid\n" );
+
+
+
849 CHECK(
false ,
"Signal error location" );
+
850 }
catch (
const std::runtime_error &error) {
+
851 CHECK(std::string(error.what()).find(fixture.path.string() +
":2: " ) == 0U,
+
852 "Signal error location" );
+
+
+
+
856 void DbcParserTest::multiplexing() {
+
+
858 const std::string selector =
"SG_ Mode M : 0|8@1+ (10,3) [0|255] \"\" ECU\n" ;
+
859 const std::string first =
"SG_ First m1 : 8|8@1- (2,0) [-128|127] \"V\" ECU\n" ;
+
860 const std::string second =
"SG_ Second m2 : 15|8@0+ (1,0) [0|255] \"\" ECU\n" ;
+
861 const std::string common =
"SG_ Common : 16|8@1+ (1,0) [0|255] \"\" ECU\n" ;
+
862 fixture.Write(
"BO_ 1 Frame: 3 ECU\n" + first + second + common + selector +
+
863 "VAL_ 1 First -1 \"Negative\";\n" );
+
+
+
866 CHECK(parsed.
frames [0].signals[3].multiplexing.role == MultiplexRole::Selector,
+
867 "Selector declared after branches" );
+
+
869 CHECK(tree->GetChild(0U)->GetChild(0U)->GetSignal()->multiplexing.value == 1U,
+
870 "Tree preserves multiplexing" );
+
+
+
873 raw.
data = {1U, 255U, 7U};
+
+
875 CHECK(result.signals[0].
valid && std::get<std::int64_t>(result.signals[0].rawValue) == -1 &&
+
876 result.signals[0].physicalValue == -2 && *result.signals[0].GetValueDescription() ==
"Negative" ,
+
877 "Active signed branch and VAL_ use exact raw selector" );
+
878 CHECK(!result.signals[1].
valid && result.signals[1].
status == SignalDecodeStatus::Inactive &&
+
879 result.signals[1].GetValueDescription() ==
nullptr && result.signals[2].
valid ,
+
880 "Inactive branch and unconditional signal" );
+
+
+
883 CHECK(result.signals[0].
status == SignalDecodeStatus::Inactive && result.signals[1].
valid &&
+
884 std::get<std::uint64_t>(result.signals[1].rawValue) == 255U,
+
885 "Motorola branch becomes active" );
+
+
+
888 CHECK(result.signals[0].
status == SignalDecodeStatus::Inactive &&
+
889 result.signals[1].
status == SignalDecodeStatus::Inactive &&
+
890 result.signals[2].
status == SignalDecodeStatus::InsufficientPayload,
+
891 "Unmapped selector leaves branches inactive even with missing bytes" );
+
+
+
894 CHECK(result.signals[0].
status == SignalDecodeStatus::InsufficientPayload,
+
895 "Active branch requires payload" );
+
+
+
898 CHECK(result.signals[0].
status == SignalDecodeStatus::SelectorUnavailable &&
+
899 result.signals[3].
status == SignalDecodeStatus::InsufficientPayload,
+
900 "Unavailable selector does not imply inactive branch" );
+
+
902 const std::vector<std::string> invalid = {
+
+
904 selector +
"SG_ Other M : 16|8@1+ (1,0) [0|255] \"\" ECU\n" ,
+
905 "SG_ Mode M : 0|8@1- (1,0) [-128|127] \"\" ECU\n" ,
+
906 selector +
"SG_ TooLarge m256 : 8|8@1+ (1,0) [0|255] \"\" ECU\n" ,
+
907 selector + first +
"SG_ Same m1 : 15|8@0+ (1,0) [0|255] \"\" ECU\n" ,
+
908 selector +
"SG_ Collision m1 : 0|8@1+ (1,0) [0|255] \"\" ECU\n" ,
+
909 selector + first +
"SG_ Always : 8|8@1+ (1,0) [0|255] \"\" ECU\n" ,
+
910 "SG_MUL_VAL_ 1 First Mode 1-2;\n"
+
+
912 for (
const std::string &signals : invalid) {
+
913 fixture.Write(
"BO_ 1 Frame: 3 ECU\n" + signals);
+
914 bool rejected =
false ;
+
+
+
917 }
catch (
const std::runtime_error &error) {
+
918 rejected = std::string(error.what()).find(fixture.path.string() +
":" ) == 0U;
+
+
920 CHECK(rejected,
"Invalid multiplexing rejected with location" );
+
+
922 for (
const std::string marker : {
"m" ,
"m-1" ,
"m+1" ,
"m1M" ,
"m18446744073709551616" ,
"M m1" })
+
923 RejectSignal(fixture,
"SG_ Bad " + marker +
" : 8|8@1+ (1,0) [0|255] \"\" ECU" );
+
+
+
926 void DbcParserTest::multiplexingBoundaries() {
+
+
928 fixture.Write(
"BO_ 1 Frame: 9 ECU\n"
+
929 "SG_ Branch m18446744073709551615 : 64|8@1+ (1,0) [0|255] \"\" ECU\n"
+
930 "SG_ Mode M : 7|64@0+ (0,5) [0|1] \"\" ECU\n" );
+
+
+
933 CHECK(runtime.
GetFrames ()[0].signals[0].multiplexing.value == std::numeric_limits<std::uint64_t>::max(),
+
934 "Exact uint64 branch metadata" );
+
+
+
937 raw.
data = std::vector<std::uint8_t>(9U, 255U);
+
+
939 CHECK(result.signals[0].
valid && result.signals[1].
valid &&
+
940 std::get<std::uint64_t>(result.signals[1].rawValue) == std::numeric_limits<std::uint64_t>::max(),
+
941 "Motorola uint64 selector compares raw value before zero scaling" );
+
+
+
944 CHECK(result.signals[0].
status == SignalDecodeStatus::Inactive,
+
945 "Adjacent large integers remain distinct" );
+
946 std::vector<DecodeFrame> definitions = runtime.
GetFrames ();
+
947 definitions[0].signals[1].length = 0U;
+
948 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, runtime =
DecodeDatabase (definitions));
+
949 definitions[0].signals.pop_back();
+
950 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, runtime =
DecodeDatabase (definitions));
+
951 fixture.Write(
"BO_ 1 Frame: 2 ECU\n\n"
+
952 "SG_ Branch m2 : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
+
953 "SG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n" );
+
954 bool rejected =
false ;
+
+
+
957 }
catch (
const std::runtime_error &error) {
+
958 rejected = std::string(error.what()).find(fixture.path.string() +
":3: " ) == 0U;
+
+
960 CHECK(rejected,
"Deferred validation reports branch source line" );
+
961 fixture.Write(
"BO_ 1 Frame: 2 ECU\n"
+
962 "SG_ A : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
+
963 "SG_ B : 15|8@0+ (1,0) [0|255] \"\" ECU\n" );
+
+
+
+
967 }
catch (
const std::runtime_error &) {
+
+
+
970 CHECK(rejected,
"Ordinary overlapping signals rejected" );
+
+
+
973 void DbcParserTest::invalidSignals() {
+
+
975 const std::string ordinary = SignalLine(
"0" ,
"8" ,
"1+" ,
"1" ,
"0" ,
"0" ,
"255" );
+
976 for (
const std::string value: {
"-1" ,
"+1" ,
"0junk" ,
"0x10" ,
"1.5" ,
+
977 "4294967296" ,
"999999999999999999999" }) {
+
978 RejectSignal(fixture, SignalLine(value,
"8" ,
"1+" ,
"1" ,
"0" ,
"0" ,
"255" ));
+
979 RejectSignal(fixture, SignalLine(
"0" , value,
"1+" ,
"1" ,
"0" ,
"0" ,
"255" ));
+
+
981 for (
const std::string length: {
"0" ,
"65" })
+
982 RejectSignal(fixture, SignalLine(
"0" , length,
"1+" ,
"1" ,
"0" ,
"0" ,
"255" ));
+
983 for (
const std::string order: {
"2+" ,
"9-" ,
"1" ,
"1x" ,
"1++" ,
"01+" })
+
984 RejectSignal(fixture, SignalLine(
"0" ,
"8" , order,
"1" ,
"0" ,
"0" ,
"255" ));
+
985 for (
const std::string value: {
"1junk" ,
"nan" ,
"NaN" ,
"inf" ,
"-inf" ,
"1e999" ,
"1e-999" ,
"0x1p2" ,
"" ,
"1e" ,
"1.2.3" }) {
+
986 RejectSignal(fixture, SignalLine(
"0" ,
"8" ,
"1+" , value,
"0" ,
"0" ,
"255" ));
+
987 RejectSignal(fixture, SignalLine(
"0" ,
"8" ,
"1+" ,
"1" , value,
"0" ,
"255" ));
+
988 RejectSignal(fixture, SignalLine(
"0" ,
"8" ,
"1+" ,
"1" ,
"0" , value,
"255" ));
+
989 RejectSignal(fixture, SignalLine(
"0" ,
"8" ,
"1+" ,
"1" ,
"0" ,
"0" , value));
+
+
991 RejectSignal(fixture, SignalLine(
"0" ,
"8" ,
"1+" ,
"1" ,
"0" ,
"2" ,
"1" ));
+
992 for (
const std::string name: {
"" ,
"Two Names" ,
"Value m1M" }) {
+
993 std::string line = ordinary;
+
994 line.replace(4U, 5U, name);
+
995 RejectSignal(fixture, line);
+
+
997 for (
const std::string broken: {
+
998 "SG_" ,
"SG_ Value" ,
"SG_ Value : 0|8@1+ (1,0) [0|255] ECU" ,
+
999 "SG_ Value : 0|8@1+ (1,0) [0|255] \"\"" ,
+
1000 "SG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU," ,
+
1001 "SG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU extra" })
+
1002 RejectSignal(fixture, broken);
+
1003 RejectSignal(fixture, SignalLine(
"64" ,
"1" ,
"1+" ,
"1" ,
"0" ,
"0" ,
"1" ));
+
1004 RejectSignal(fixture, SignalLine(
"63" ,
"2" ,
"1+" ,
"1" ,
"0" ,
"0" ,
"3" ));
+
1005 RejectSignal(fixture, SignalLine(
"56" ,
"2" ,
"0+" ,
"1" ,
"0" ,
"0" ,
"3" ));
+
1006 RejectSignal(fixture, SignalLine(
"4294967295" ,
"64" ,
"1+" ,
"1" ,
"0" ,
"0" ,
"1" ));
+
1007 RejectSignal(fixture, ordinary, 0U);
+
1008 for (
const char delimiter: {
'|' ,
'@' ,
'(' ,
')' ,
'[' ,
']' ,
'"' }) {
+
1009 std::string line = ordinary;
+
1010 line.erase(line.find(delimiter), 1U);
+
1011 RejectSignal(fixture, line);
+
+
+
+
1015 void DbcParserTest::validSignals() {
+
+
+
1018 fixture.Write(
"BO_ 1 Frame: 8 ECU\n" +
+
1019 SignalLine(
"0" ,
"8" ,
"1+" ,
"0" ,
"0" ,
"0" ,
"0" ) +
"\n" +
+
1020 SignalLine(
"8" ,
"8" ,
"1-" ,
"-1" ,
"0" ,
"-255" ,
"0" ,
"Negative" ) +
"\n" );
+
+
1022 CHECK(factors.
frames [0].signals.size() == 2U &&
+
1023 factors.
frames [0].signals[0].factor == 0.0 &&
+
1024 factors.
frames [0].signals[1].factor == -1.0,
+
1025 "Zero and negative factors and equal range boundaries" );
+
+
+
+
+
+
+
+
1033 const SignalCase validSignals[] = {
+
1034 {
"0" ,
"1" ,
"1+" , 1U},
+
1035 {
"7" ,
"1" ,
"0-" , 1U},
+
1036 {
"0" ,
"64" ,
"1+" , 8U},
+
1037 {
"7" ,
"64" ,
"0-" , 8U},
+
1038 {
"63" ,
"1" ,
"1+" , 8U},
+
1039 {
"56" ,
"1" ,
"0+" , 8U},
+
1040 {
"3" ,
"12" ,
"0+" , 2U},
+
1041 {
"2039" ,
"1" ,
"1+" , 255U}};
+
1042 for (
const SignalCase &test: validSignals) {
+
1043 fixture.Write(
"BO_ 1 Frame: " + std::to_string(test.payload) +
" ECU\n" +
+
1044 SignalLine(test.start, test.length, test.order,
".5e+1" ,
"-2.5E-1" ,
"-1." ,
"+2e2" ) +
"\n" );
+
+
+
+
1048 QCOMPARE(signal.
startBit ,
static_cast< std::uint32_t
> (std::stoul(test.start)));
+
1049 QCOMPARE(signal.
length ,
static_cast< std::uint32_t
> (std::stoul(test.length)));
+
+
1051 QCOMPARE(signal.
isSigned , test.order[1] ==
'-' );
+
1052 QCOMPARE(signal.
factor , 5.0);
+
1053 QCOMPARE(signal.
offset , -0.25);
+
1054 QCOMPARE(signal.
minimum , -1.0);
+
1055 QCOMPARE(signal.
maximum , 200.0);
+
1056 }
catch (
const std::exception &error) { CHECK(
false , error.what()); }
+
+
1058 fixture.Write(
"BO_ 1 Frame: 8 ECU\n"
+
1059 "SG_\tValue\t:\t0 | 8 @1+ ( 1 , 0 ) [ 0 | 255 ] \"rpm\" ECU1,\tECU2\n" );
+
+
+
+
1063 CHECK(signal.
name ==
"Value" && signal.
unit ==
"rpm" &&
+
1064 signal.
receivers == std::vector<std::string>({
"ECU1" ,
"ECU2" }),
+
1065 "Signal tabs, spaces, and receiver list" );
+
1066 }
catch (
const std::exception &error) { CHECK(
false , error.what()); }
+
+
+
1069 void DbcParserTest::CheckPhysicalNumbers() {
+
+
1071 struct PhysicalCase {
+
+
+
1074 const char *minimum;
+
1075 const char *maximum;
+
1076 double expectedFactor;
+
1077 double expectedOffset;
+
1078 double expectedMinimum;
+
1079 double expectedMaximum;
+
+
1081 const PhysicalCase valid[] = {
+
1082 {
"+1.25" ,
"-0.5" ,
"-2.75" ,
"255.5" , 1.25, -0.5, -2.75, 255.5},
+
1083 {
"+.5e+1" ,
"-2.5E-1" ,
"-1." ,
"+2e2" , 5.0, -0.25, -1.0, 200.0},
+
1084 {
"0e-999" ,
"+0." ,
"-.0" ,
".0e+999" , 0.0, 0.0, 0.0, 0.0},
+
1085 {
"1.7976931348623157e308" ,
"2.2250738585072014e-308" ,
"-1e308" ,
"+1e308" ,
+
1086 std::numeric_limits<double>::max(), std::numeric_limits<double>::min(), -1e308, 1e308}};
+
1087 for (
const PhysicalCase &test: valid) {
+
1088 fixture.Write(
"BO_ 1 Frame: 1 ECU\n" +
+
1089 SignalLine(
"0" ,
"8" ,
"1+" , test.factor, test.offset, test.minimum, test.maximum) +
"\n" );
+
+
+
+
+
+
1095 QCOMPARE(signal.
factor , test.expectedFactor);
+
1096 QCOMPARE(signal.
offset , test.expectedOffset);
+
1097 QCOMPARE(signal.
minimum , test.expectedMinimum);
+
1098 QCOMPARE(signal.
maximum , test.expectedMaximum);
+
+
+
1101 const char *invalid[] = {
"1,5" ,
"1.234,5" ,
"1,234.5" ,
"1junk" ,
"nan" ,
"inf" ,
"-inf" ,
+
1102 "1e999" ,
"1e-999" ,
"1e-320" ,
"-1e-320" ,
"0x1p2" ,
"1e" ,
"1.2.3" };
+
1103 for (
const char *value: invalid) {
+
1104 RejectSignal(fixture, SignalLine(
"0" ,
"8" ,
"1+" , value,
"0" ,
"0" ,
"255" ));
+
1105 RejectSignal(fixture, SignalLine(
"0" ,
"8" ,
"1+" ,
"1" , value,
"0" ,
"255" ));
+
1106 RejectSignal(fixture, SignalLine(
"0" ,
"8" ,
"1+" ,
"1" ,
"0" , value,
"255" ));
+
1107 RejectSignal(fixture, SignalLine(
"0" ,
"8" ,
"1+" ,
"1" ,
"0" ,
"0" , value));
+
+
1109 RejectSignal(fixture, SignalLine(
"0" ,
"8" ,
"1+" ,
"1.25" ,
"0" ,
"2.5" ,
"1.5" ));
+
+
+
1112 void DbcParserTest::physicalNumbersCppLocale() {
+
1113 const ApplicationLocaleGuard guard;
+
1114 std::locale::global(std::locale(std::locale::classic(),
new CommaDecimalPunctuation));
+
1115 QCOMPARE(std::use_facet<std::numpunct<char>>(std::locale()).decimal_point(),
',' );
+
1116 CheckPhysicalNumbers();
+
1117 QCOMPARE(std::use_facet<std::numpunct<char>>(std::locale()).decimal_point(),
',' );
+
+
+
1120 void DbcParserTest::physicalNumbersCLocale() {
+
1121 const ApplicationLocaleGuard guard;
+
+
1123 const char *names[] = {
"de_DE.UTF-8" ,
"de_DE.utf8" ,
"fr_FR.UTF-8" ,
"fr_FR.utf8" ,
+
1124 "German_Germany.1252" ,
"French_France.1252" };
+
1125 for (
const char *name: names) {
+
1126 if (std::setlocale(LC_NUMERIC, name) && std::string(std::localeconv()->decimal_point) ==
"," ) {
+
+
+
+
+
+
1132 QSKIP(
"No named comma-decimal C locale is installed; generate de_DE.UTF-8 and set LOCPATH." );
+
1133 QCOMPARE(std::string(std::localeconv()->decimal_point), std::string(
"," ));
+
1134 CheckPhysicalNumbers();
+
1135 QCOMPARE(std::string(std::localeconv()->decimal_point), std::string(
"," ));
+
+
+
1138 void DbcParserTest::dispatch() {
+
1139 CountingHandler::instances = 0;
+
1140 CountingHandler::calls = 0;
+
+
+
+
+
1145 CHECK(dispatcher.
Dispatch (
"TEST_ first" , context) &&
+
1146 dispatcher.
Dispatch (
"TEST_ second" , context) &&
+
1147 CountingHandler::instances == 1 && CountingHandler::calls == 2 &&
+
1148 dispatchDatabase.
frames .size() == 2U,
+
1149 "Factory dispatch and handler reuse" );
+
1150 CHECK(!dispatcher.
Dispatch (
"TEST_OTHER data" , context) &&
+
1151 !dispatcher.
Dispatch (
"BO_TX_BU_ 1 : ECU;" , context) &&
+
1152 !dispatcher.
Dispatch (
"VAL_TABLE_ States 0 \"Stopped\";" , context) &&
+
1153 CountingHandler::calls == 2,
+
1154 "Exact and unknown keyword dispatch" );
+
+
+
1157 void DbcParserTest::independentSessions() {
+
+
+
1160 fixture.Write(
"BO_ 1 First: 8 ECU\n" );
+
1161 CHECK(parser.
ParseFile (fixture.path.string()).
frames .size() == 1U,
"First parse" );
+
1162 fixture.Write(
"SG_ Speed : invalid\n" );
+
+
1164 parser.
ParseFile (fixture.path.string());
+
1165 CHECK(
false ,
"Independent parse context" );
+
1166 }
catch (
const std::runtime_error &error) {
+
1167 CHECK(std::string(error.what()).find(
"Signal found before any frame" ) !=
+
+
1169 "Independent parse context" );
+
+
1171 fixture.Write(
"BO_ 2 Second: 8 ECU\n" );
+
+
1173 CHECK(recovered.
frames .size() == 1U && recovered.
frames [0].canId == 2U,
+
1174 "Fresh parse after error" );
+
+
+
+
1178 void DbcParserTest::valueDescriptions() {
+
+
+
1181 "VAL_\t256\tState\t0\t\"Off\"\t1 \"On\" 2 \"Error with spaces; and \\\"quotes\\\"\";\n"
+
1182 "BO_ 256 Status: 8 ECU\n"
+
1183 "SG_ State : 0|8@1+ (2,10) [0|520] \"\" ECU\n"
+
1184 "VAL_ 256 State 3 \"\";\n"
+
1185 "VAL_ 2147483904 State -9223372036854775808 \"Minimum\" -1 \"Negative\" 9223372036854775807 \"Maximum\";\n"
+
1186 "BO_ 2147483904 Extended: 8 ECU\n"
+
1187 "SG_ State : 0|64@1- (1,0) [-1e20|1e20] \"\" ECU\n"
+
1188 "BO_ 2048 Unsigned: 8 ECU\n"
+
1189 "SG_ State : 0|64@1+ (1,0) [0|2e20] \"\" ECU\n"
+
1190 "VAL_ 2147485696 State 9223372036854775808 \"High\" 18446744073709551615 \"Full\";\n" );
+
+
+
+
1194 CHECK(tree->GetChild(0)->GetSignal() ==
nullptr ,
"Frame node" );
+
1195 for (std::size_t index = 0; index < parsed.
frames .size(); ++index) {
+
1196 CHECK(tree->GetChild(index)->GetChild(0)->GetSignal()->valueDescriptions ==
+
1197 parsed.
frames [index].signals[0].valueDescriptions &&
+
1198 runtime.
GetFrames ()[index].signals[0].valueDescriptions ==
+
1199 parsed.
frames [index].signals[0].valueDescriptions,
+
1200 "All mappings survive both builders" );
+
+
1202 CHECK(tree->GetChild(0)->GetChild(0)->GetSignal()->valueDescriptions ==
+
1203 runtime.
GetFrames ()[0].signals[0].valueDescriptions,
+
1204 "Both builders preserve descriptions" );
+
+
+
1207 frame.
data .resize(8);
+
1208 const std::string expected[] = {
"Off" ,
"On" ,
"Error with spaces; and \"quotes\"" ,
"" };
+
1209 for (
unsigned value = 0; value < 5; ++value) {
+
1210 frame.
data [0] = value;
+
+
1212 CHECK(decoded.
valid && decoded.
physicalValue == value * 2 + 10,
"Numeric scaling unchanged" );
+
+
1214 CHECK(value < 4 ? description && *description == expected[value] : !description,
+
1215 "Raw lookup and unknown value" );
+
+
+
+
+
1220 const char *description;
+
+
1222 for (
const Boundary &test: {Boundary{0x8000000000000000ULL,
"Minimum" },
+
1223 Boundary{0xFFFFFFFFFFFFFFFFULL,
"Negative" },
+
1224 Boundary{0x7FFFFFFFFFFFFFFFULL,
"Maximum" }}) {
+
1225 for (
unsigned byte = 0;
byte < 8; ++byte)
+
1226 frame.
data [
byte ] =
static_cast< std::uint8_t
> (test.bits >> (
byte * 8));
+
+
+
1229 "Signed boundaries and distinct extended frame" );
+
+
+
1232 for (
const Boundary &test: {Boundary{0x8000000000000000ULL,
"High" },
+
1233 Boundary{0xFFFFFFFFFFFFFFFFULL,
"Full" }}) {
+
1234 for (
unsigned byte = 0;
byte < 8; ++byte)
+
1235 frame.
data [
byte ] =
static_cast< std::uint8_t
> (test.bits >> (
byte * 8));
+
+
+
1238 "Unsigned boundaries" );
+
+
1240 CHECK(FindValueDescription(runtime.
GetFrames ()[0].signals[0].valueDescriptions, std::int64_t(1)) !=
nullptr ,
+
1241 "Nonnegative signed lookup matches unsigned key" );
+
+
1243 CHECK(!
DbcDecoder ().Decode(runtime, frame).signals[0].GetValueDescription(),
"Invalid decode has no description" );
+
+
+
1246 void DbcParserTest::invalidValueDescriptions() {
+
+
1248 const std::string definitions =
"BO_ 1 Frame: 8 ECU\nSG_ State : 0|64@1+ (1,0) [0|2e20] \"\" ECU\n" ;
+
1249 for (
const std::string statement: {
+
1250 "VAL_" ,
"VAL_ 1 State;" ,
"VAL_ 1 State ;" ,
"VAL_ 1 State 0 \"Off\"" ,
+
1251 "VAL_ 1 State 0 \"Off\"; junk" ,
"VAL_ 1 State 0 Off;" ,
+
1252 "VAL_ 1 State 0 \"Unclosed;" ,
"VAL_ 1 State 0 \"Off\"1 \"On\";" ,
+
1253 "VAL_ 1 State 0 \"Off\" 00 \"Duplicate\";" ,
+
1254 "VAL_ 1 State 0 \"Off\" -0 \"Duplicate\";" ,
+
1255 "VAL_ 1 State 0 \"Off\";\nVAL_ 1 State 0 \"Duplicate\";" ,
+
1256 "VAL_ 2 State 0 \"Missing frame\";" ,
"VAL_ 1 Missing 0 \"Missing signal\";" ,
+
1257 "VAL_ -1 State 0 \"Bad ID\";" ,
"VAL_ 536870912 State 0 \"Bad ID\";" ,
+
1258 "VAL_ 4294967296 State 0 \"Bad ID\";" ,
"VAL_ Environment 0 \"Unsupported\";" ,
+
1259 "VAL_ 1 State 0 \"Bad\\q escape\";" }) {
+
1260 fixture.Write(definitions + statement +
'\n' );
+
1261 const int line = statement.find(
'\n' ) == std::string::npos ? 3 : 4;
+
+
+
1264 CHECK(
false , statement);
+
1265 }
catch (
const std::runtime_error &error) {
+
1266 CHECK(std::string(error.what()).find(fixture.path.string() +
":" + std::to_string(line) +
": " ) == 0,
+
1267 statement +
" " + error.what());
+
+
+
1270 for (
const std::string suffix: {
+
1271 "BO_ 1 Other: 8 ECU\n" ,
+
1272 "SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n" ,
+
+
1274 fixture.Write(
"VAL_ 1 " + std::string(suffix.empty() ?
"Missing" :
"State" ) +
+
1275 " 0 \"Description\";\n" + definitions + suffix);
+
+
+
1278 CHECK(
false ,
"Missing reference or duplicate definition" );
+
1279 }
catch (
const std::runtime_error &error) {
+
1280 const std::string line = suffix.empty() ?
"1" :
"4" ;
+
1281 CHECK(std::string(error.what()).find(fixture.path.string() +
":" + line +
": " ) == 0,
+
1282 "Error retains the reference or duplicate definition source location" );
+
+
+
1285 for (
const std::string number: {
"+1" ,
"1x" ,
"0x10" ,
"1.5" ,
"1e2" ,
"--1" ,
+
1286 "-9223372036854775809" ,
"18446744073709551616" }) {
+
1287 fixture.Write(
"VAL_ 1 State " + number +
" \"Bad\";\n" + definitions);
+
+
+
1290 CHECK(
false , number);
+
1291 }
catch (
const std::runtime_error &error) {
+
1292 CHECK(std::string(error.what()).find(fixture.path.string() +
":1: " ) == 0, number);
+
+
+
+
+
1297 int RunParserTests(
int argc,
char **argv) {
+
1298 DbcParserTest tests;
+
1299 return QTest::qExec(&tests, argc, argv);
+
+
+
1302 #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.
-
DecodedFrameValue Decode(const DecodeDatabase &database, const RawCanFrame &frame) const
Decode one raw CAN frame.
-
-
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.
-
-
bool Dispatch(const std::string &line, DbcParseContext &context) const
-
+
Runtime CAN decoder using prebuilt decode database.
+
DecodedFrameValue Decode(const DecodeDatabase &database, const RawCanFrame &frame) const
Decode one raw CAN frame.
+
+
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.
+
+
void RegisterType(const std::string &keyword)
Register or replace a handler and create its reusable instance.
+
bool Dispatch(const std::string &line, DbcParseContext &context) const
+
Interface for processing a registered DBC statement.
+
virtual void Handle(const std::string &line, DbcParseContext &context) const =0
Process a trimmed statement using state belonging to this parse.
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)
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles a...
+
const std::vector< DecodeFrame > & GetFrames() const
+
Runtime decode database builder.
+
CAN frame decoding API and result types.
+
DBC file parser and interpretation options.
+
Parsed DBC content stored in a simple internal form.
+
std::map< std::string, AttributeDefinition > attributeDefinitions
std::vector< FrameInfo > frames
-
-
-
-
-
std::shared_ptr< const DecodeFrame > definition
-
-
-
One decoded signal value.
-
-
-
const std::string * GetValueDescription() const
-
Describes one CAN frame from a DBC file.
-
-
-
-
-
+
+
std::vector< AttributeAssignment > attributeAssignments
+
Diagnostic message and physical source location.
+
+
DbcDiagnosticSeverity severity
+
+
+
+
+
+
Parsed database and diagnostics; the database is empty on error.
+
std::vector< DbcDiagnostic > diagnostics
+
bool HasErrors() const
Return whether any diagnostic has error severity.
+
+
+
std::shared_ptr< const DecodeFrame > definition
+
+
+
One decoded signal value.
+
+
+
const std::string * GetValueDescription() const
+
Describes one CAN frame from a DBC file.
+
+
+
+
+
Raw CAN frame used for runtime or trace decoding.
std::vector< std::uint8_t > data
-
Describes one signal inside a DBC frame.
-
-
-
std::vector< std::string > receivers
-
-
-
-
-
-
-
-
+
Describes one signal inside a DBC frame.
+
+
+
std::vector< std::string > receivers
+
+
+
+
+
+
+
+
diff --git a/docs/html/dbc__pipeline__test_8cpp_source.html b/docs/html/dbc__pipeline__test_8cpp_source.html
new file mode 100644
index 0000000..f68c510
--- /dev/null
+++ b/docs/html/dbc__pipeline__test_8cpp_source.html
@@ -0,0 +1,584 @@
+
+
+
+
+
+
+
+DBC Framework: dbc_pipeline_test.cpp Source File
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DBC Framework
+
+ DBC parsing and CAN signal decoding framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+
+
+
+
+
+
+
+
5 #include <QTemporaryFile>
+
+
+
+
+
+
11 const std::string fixture = R
"DBC(BO_ 291 Standard: 2 SenderA
+
12 SG_ Mode M : 0|8@1+ (1,0) [0|255] "" ReceiverA
+
13 SG_ State m3 : 8|8@1+ (2,1) [1|511] "km/h" ReceiverA,ReceiverB
+
14 BO_ 2147483939 Extended: 1 SenderB
+
15 SG_ State : 7|8@0- (0.5,-3) [-67|60.5] "deg C" ReceiverB
+
16 BO_ 2565866562 J1939: 0 SenderC
+
17 CM_ BO_ 291 "Standard frame comment";
+
18 CM_ SG_ 291 Mode "Selector comment";
+
19 CM_ SG_ 291 State "Standard signal comment";
+
20 CM_ BO_ 2147483939 "Extended frame comment";
+
21 CM_ SG_ 2147483939 State "Extended signal comment";
+
22 VAL_ 291 Mode 3 "Selected";
+
23 VAL_ 291 State 4 "Standard four";
+
24 VAL_ 2147483939 State -2 "Extended minus two";
+
+
+
+
+
29 if (!file.open())
throw std::runtime_error(
"Cannot create DBC fixture" );
+
30 if (file.write(text.data(),
static_cast< qint64
> (text.size())) !=
static_cast< qint64
> (text.size()) || !file.flush())
+
31 throw std::runtime_error(
"Cannot write DBC fixture" );
+
+
+
+
+
+
+
+
39 standard.
name =
"Standard" ;
+
40 standard.
canId = 291U;
+
+
+
43 standard.
comment =
"Standard frame comment" ;
+
+
+
+
+
+
+
50 mode.
comment =
"Selector comment" ;
+
+
+
+
+
+
+
+
+
+
+
+
+
63 state.
receivers = {
"ReceiverA" ,
"ReceiverB" };
+
64 state.
comment =
"Standard signal comment" ;
+
+
66 standard.signals = {mode, state};
+
+
+
69 extended.
name =
"Extended" ;
+
70 extended.
canId = 291U;
+
+
+
+
+
75 extended.
comment =
"Extended frame comment" ;
+
+
+
+
+
+
+
+
+
+
+
86 state.
comment =
"Extended signal comment" ;
+
+
88 extended.signals = {state};
+
+
+
+
92 j1939.
canId = 0x18F00442U;
+
+
+
+
+
+
+
+
100 template <
class Signal>
+
101 void CheckSignalMetadata(
const Signal &actual,
const SignalInfo &expected) {
+
102 QCOMPARE(actual.name, expected.
name );
+
103 QCOMPARE(actual.startBit, expected.
startBit );
+
104 QCOMPARE(actual.length, expected.
length );
+
105 QCOMPARE(actual.factor, expected.
factor );
+
106 QCOMPARE(actual.offset, expected.
offset );
+
107 QCOMPARE(actual.minimum, expected.
minimum );
+
108 QCOMPARE(actual.maximum, expected.
maximum );
+
109 QCOMPARE(actual.unit, expected.
unit );
+
110 QVERIFY(actual.receivers == expected.
receivers );
+
111 QCOMPARE(actual.comment, expected.
comment );
+
+
+
+
+
+
+
118 CheckSignalMetadata(actual, expected);
+
+
+
+
+
+
124 CheckSignalMetadata(actual, expected);
+
+
+
+
+
129 template <
class Frame>
+
130 void CheckFrame(
const Frame &actual,
const FrameInfo &expected) {
+
131 QCOMPARE(actual.name, expected.
name );
+
132 QCOMPARE(actual.canId, expected.
canId );
+
133 QCOMPARE(actual.isExtended, expected.
isExtended );
+
134 QCOMPARE(actual.dlc, expected.
dlc );
+
135 QCOMPARE(actual.pgn, expected.
pgn );
+
136 QCOMPARE(actual.hasPgn, expected.
hasPgn );
+
137 QCOMPARE(actual.transmitter, expected.
transmitter );
+
138 QCOMPARE(actual.comment, expected.
comment );
+
139 QCOMPARE(actual.signals.size(), expected.signals.size());
+
140 for (std::size_t i = 0; i < expected.signals.size(); ++i)
+
141 CheckSignal(actual.signals[i], expected.signals[i]);
+
+
+
+
145 QCOMPARE(root.
GetType (), NodeType::Root);
+
+
147 QVERIFY(root.
GetFrame () ==
nullptr );
+
+
+
150 for (std::size_t i = 0; i < expected.
frames .size(); ++i) {
+
+
152 QVERIFY(frame !=
nullptr );
+
153 QCOMPARE(frame->
GetType (), NodeType::Frame);
+
+
155 QCOMPARE(frame->
GetRow (), i);
+
+
157 QVERIFY(frame->
GetFrame () !=
nullptr );
+
+
+
+
+
+
163 QVERIFY(signal !=
nullptr );
+
164 QCOMPARE(signal->
GetType (), NodeType::Signal);
+
+
166 QCOMPARE(signal->
GetRow (), j);
+
167 QCOMPARE(signal->
GetName (), expected.
frames [i].signals[j].name);
+
+
169 QVERIFY(signal->
GetFrame () ==
nullptr );
+
+
+
+
+
+
+
+
+
+
179 QVERIFY(runtime.
FindFrame (key) ==
nullptr );
+
+
181 QVERIFY(
DbcDecoder ().FindFrame(runtime, key.canId, key.isExtended) ==
nullptr );
+
+
183 raw.
canId = key.canId;
+
+
+
+
187 QVERIFY(!decoded.
valid );
+
188 QCOMPARE(decoded.
status , FrameDecodeStatus::UnknownFrame);
+
+
190 QVERIFY(decoded.signals.empty());
+
191 QVERIFY(decoded.
key == key);
+
+
+
+
195 class PipelineTest :
public QObject {
+
+
+
198 void metadataLookupDecodeAndTree();
+
199 void emptyDatabase_data();
+
200 void emptyDatabase();
+
201 void databaseReplacement();
+
+
+
204 void PipelineTest::metadataLookupDecodeAndTree() {
+
+
+
+
+
+
+
+
+
213 QVERIFY(tree !=
nullptr );
+
214 CheckTree(*tree, expected);
+
215 for (std::size_t i = 0; i < expected.
frames .size(); ++i) {
+
+
+
+
219 const std::shared_ptr<const DecodeFrame> found = runtime.
FindFrame (key);
+
220 QVERIFY(found !=
nullptr );
+
221 QCOMPARE(found.get(), &runtime.
GetFrames ()[i]);
+
222 QCOMPARE(
DbcDecoder ().FindFrame(runtime, key.canId, key.isExtended).get(), found.get());
+
223 for (std::size_t j = 0; j < found->signals.size(); ++j) {
+
224 const std::shared_ptr<const DecodeSignal> signal = runtime.
FindSignal (
SignalKey (key, found->signals[j].name));
+
225 QVERIFY(signal !=
nullptr );
+
226 QCOMPARE(signal.get(), &found->signals[j]);
+
+
+
+
+
+
+
+
+
+
236 QVERIFY(standard.
valid );
+
237 QCOMPARE(standard.
status , FrameDecodeStatus::Valid);
+
+
+
240 QCOMPARE(standard.signals.size(), std::size_t(2));
+
241 for (std::size_t i = 0; i < standard.signals.size(); ++i) {
+
+
243 QVERIFY(signal.
valid );
+
244 QCOMPARE(signal.
status , SignalDecodeStatus::Valid);
+
245 QVERIFY(signal.
key ==
SignalKey (standard.
key , i == 0 ?
"Mode" :
"State" ));
+
+
247 QCOMPARE(std::get<std::uint64_t>(signal.
rawValue ), i == 0 ? 3U : 4U);
+
+
+
250 QCOMPARE(*signal.
GetValueDescription (), std::string(i == 0 ?
"Selected" :
"Standard four" ));
+
+
+
+
+
255 QVERIFY(extended.
valid );
+
256 QCOMPARE(extended.
status , FrameDecodeStatus::Valid);
+
+
+
259 QCOMPARE(extended.signals.size(), std::size_t(1));
+
+
261 QVERIFY(signal.
valid );
+
262 QCOMPARE(signal.
status , SignalDecodeStatus::Valid);
+
+
+
265 QCOMPARE(std::get<std::int64_t>(signal.
rawValue ), std::int64_t(-2));
+
+
+
+
+
270 raw.
canId = 0x18F00442U;
+
+
+
273 QVERIFY(j1939.
valid );
+
274 QCOMPARE(j1939.
status , FrameDecodeStatus::Valid);
+
+
+
277 QVERIFY(j1939.signals.empty());
+
+
+
280 void PipelineTest::emptyDatabase_data() {
+
281 QTest::addColumn<QString>(
"text" );
+
282 QTest::newRow(
"empty-file" ) << QString();
+
283 QTest::newRow(
"headers-only" ) << QString::fromUtf8(
"VERSION \"empty\"\nNS_ :\nBS_:\nBU_: Sender\n" );
+
+
+
286 void PipelineTest::emptyDatabase() {
+
287 QFETCH(QString, text);
+
+
+
+
+
+
+
294 CheckUnknown(runtime,
false );
+
295 CheckUnknown(runtime,
true );
+
+
297 QVERIFY(tree !=
nullptr );
+
+
+
+
301 void PipelineTest::databaseReplacement() {
+
+
+
+
+
+
+
+
+
310 QVERIFY(saved.
valid );
+
311 QCOMPARE(saved.signals.size(), std::size_t(2));
+
312 QVERIFY(tree !=
nullptr );
+
313 std::unique_ptr<TreeNode> savedTree = std::move(tree);
+
+
315 parsed = ParseFixture(R
"DBC(BO_ 291 Replacement: 1 NewSender
+
316 SG_ NewState : 0|8@1+ (3,-1) [-1|764] "V" NewReceiver
+
317 CM_ BO_ 291 "Replacement frame";
+
318 CM_ SG_ 291 NewState "Replacement signal";
+
319 VAL_ 291 NewState 4 "New four";
+
+
+
+
+
324 replacement.name = "Replacement" ;
+
325 replacement.
canId = 291U;
+
326 replacement.
dlc = 1U;
+
+
328 replacement.
comment =
"Replacement frame" ;
+
+
330 state.
name =
"NewState" ;
+
+
+
+
+
+
+
+
338 state.
comment =
"Replacement signal" ;
+
+
340 replacement.signals = {state};
+
+
+
+
+
+
346 QVERIFY(tree !=
nullptr );
+
347 QCOMPARE(runtime.
GetFrames ().size(), std::size_t(1));
+
348 CheckFrame(runtime.
GetFrames ()[0], replacement);
+
349 CheckTree(*tree, expected);
+
350 CheckUnknown(runtime,
true );
+
+
+
+
+
+
356 QVERIFY(current.
valid );
+
357 QCOMPARE(current.
status , FrameDecodeStatus::Valid);
+
358 QCOMPARE(current.signals.size(), std::size_t(1));
+
359 QVERIFY(current.signals[0].
valid );
+
+
+
362 QCOMPARE(std::get<std::uint64_t>(current.signals[0].rawValue), std::uint64_t(4));
+
363 QCOMPARE(current.signals[0].physicalValue, 11.0);
+
364 QVERIFY(current.signals[0].GetValueDescription() !=
nullptr );
+
365 QCOMPARE(*current.signals[0].GetValueDescription(), std::string(
"New four" ));
+
+
367 parsed = ParseFixture(
"" );
+
+
+
+
+
372 QVERIFY(tree !=
nullptr );
+
+
374 CheckUnknown(runtime,
false );
+
375 CheckUnknown(runtime,
true );
+
+
377 QVERIFY(runtime.
FindSignal (current.signals[0].
key ) ==
nullptr );
+
+
379 CheckFrame(*saved.
definition , ExpectedMetadata().frames[0]);
+
380 CheckTree(*savedTree, ExpectedMetadata());
+
381 QCOMPARE(saved.signals[1].physicalValue, 9.0);
+
382 QVERIFY(saved.signals[1].GetValueDescription() !=
nullptr );
+
383 QCOMPARE(*saved.signals[1].GetValueDescription(), std::string(
"Standard four" ));
+
+
+
386 int RunPipelineTests(
int argc,
char **argv) {
+
+
388 return QTest::qExec(&test, argc, argv);
+
+
+
391 #include "dbc_pipeline_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.
+
DecodedFrameValue Decode(const DecodeDatabase &database, const RawCanFrame &frame) const
Decode one raw CAN frame.
+
+
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 DecodeSignal > FindSignal(const SignalKey &key) const
Return an owning signal handle, or an empty handle for a missing key.
+
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.
+
const SignalInfo * GetSignal() const
Get signal payload if node is signal.
+
const TreeNode * GetChild(std::size_t index) const
Get child by index.
+
const TreeNode * GetParent() const
+
const std::string & GetName() const
Get display name.
+
std::size_t GetChildCount() const
Get child count.
+
std::size_t GetRow() const
+
NodeType GetType() const
Get node type.
+
const FrameInfo * GetFrame() const
Get frame payload if node is frame.
+
Runtime decode database builder.
+
CAN frame decoding API and result types.
+
DBC file parser and interpretation options.
+
+
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
+
Parsed database and diagnostics; the database is empty on error.
+
std::vector< DbcDiagnostic > diagnostics
+
bool HasErrors() const
Return whether any diagnostic has error severity.
+
+
+
Runtime-ready signal definition.
+
+
+
+
+
std::shared_ptr< const DecodeFrame > definition
+
+
+
One decoded signal value.
+
+
+
+
std::shared_ptr< const DecodeSignal > definition
+
SignalDecodeStatus status
+
+
const std::string * GetValueDescription() const
+
Describes one CAN frame from a DBC file.
+
+
+
+
+
+
+
+
+
Stable frame identifier: normalized CAN ID and frame type.
+
+
+
+
Raw CAN frame used for runtime or trace decoding.
+
std::vector< std::uint8_t > data
+
+
+
Describes one signal inside a DBC frame.
+
+
+
std::vector< std::string > receivers
+
+
ValueDescriptions valueDescriptions
+
+
Multiplexing multiplexing
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tests dbc_pipeline_test.cpp
+
+
+
+
+
diff --git a/docs/html/dbc__statement__handler_8cpp_source.html b/docs/html/dbc__statement__handler_8cpp_source.html
index 90324bd..4f14eea 100644
--- a/docs/html/dbc__statement__handler_8cpp_source.html
+++ b/docs/html/dbc__statement__handler_8cpp_source.html
@@ -100,564 +100,616 @@ $(document).ready(function(){initNavTree('dbc__statement__handler_8cpp_source.ht
2 #include "dbc_statement_handler.h"
-
-
4 #include "signal_layout.h"
-
-
-
-
-
-
-
-
-
13 std::uint32_t ParseDecimal(
const std::string &text,
-
14 std::uint32_t maximum,
-
-
16 std::uint32_t value = 0U;
-
17 const std::from_chars_result parsed = std::from_chars(text.data(), text.data() + text.size(), value);
-
18 if (text.empty() || parsed.ec != std::errc() ||
-
19 parsed.ptr != text.data() + text.size() || value > maximum)
-
20 throw std::runtime_error(std::string(
"Invalid " ) + field +
": " + text);
-
-
-
-
24 double ParsePhysicalValue(
const std::string &text,
const char *field) {
-
25 static const std::regex number(
-
26 R
"(^[+-]?(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)(?:[eE][+-]?[0-9]+)?$)");
-
27 if (!std::regex_match(text, number))
-
28 throw std::runtime_error(std::string(
"Invalid " ) + field +
": " + text);
-
29 std::size_t consumed = 0U;
-
-
-
32 value = std::stod(text, &consumed);
-
33 }
catch (
const std::exception &) {
-
34 throw std::runtime_error(std::string(
"Invalid " ) + field +
": " + text);
-
-
36 if (consumed != text.size() || !std::isfinite(value))
-
37 throw std::runtime_error(std::string(
"Invalid " ) + field +
": " + text);
-
-
-
-
41 Multiplexing ParseMultiplexingMarker(
const std::string &marker) {
-
-
-
44 result.role = MultiplexRole::Selector;
-
45 else if (!marker.empty()) {
-
-
47 throw std::runtime_error(
"Unsupported multiplexing marker." );
-
48 const std::string value = marker.substr(1U);
-
49 const std::from_chars_result parsed =
-
50 std::from_chars(value.data(), value.data() + value.size(), result.value);
-
51 if (value.empty() || parsed.ec != std::errc() || parsed.ptr != value.data() + value.size())
-
52 throw std::runtime_error(
"Invalid or unsupported multiplexing marker." );
-
53 result.role = MultiplexRole::Branch;
-
-
-
-
-
-
59 RawSignalValue ParseValueKey(
const std::string &number) {
-
-
61 if (!number.empty() && number[0] ==
'-' ) {
-
62 std::int64_t value = 0;
+
+
+
5 #include "signal_layout.h"
+
+
+
+
+
+
+
+
+
14 std::uint32_t ParseDecimal(
const std::string &text,
+
15 std::uint32_t maximum,
+
+
17 std::uint32_t value = 0U;
+
18 const std::from_chars_result parsed = std::from_chars(text.data(), text.data() + text.size(), value);
+
19 if (text.empty() || parsed.ec != std::errc() ||
+
20 parsed.ptr != text.data() + text.size() || value > maximum)
+
21 throw std::runtime_error(std::string(
"Invalid " ) + field +
": " + text);
+
+
+
+
25 std::uint32_t ParseCanId(
const std::string &text) {
+
26 const std::uint32_t rawId = ParseDecimal(
+
27 text, std::numeric_limits<std::uint32_t>::max(),
"CAN ID" );
+
+
29 if ((rawId & 0x60000000U) != 0U)
+
30 throw std::runtime_error(
"CAN ID exceeds the 29-bit identifier range." );
+
+
+
+
34 double ParsePhysicalValue(
const std::string &text,
const char *field) {
+
35 static const std::regex number(
+
36 R
"(^[+-]?(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)(?:[eE][+-]?[0-9]+)?$)");
+
37 if (!std::regex_match(text, number))
+
38 throw std::runtime_error(std::string(
"Invalid " ) + field +
": " + text);
+
+
+
41 const char *begin = text.data();
+
42 const char *end = begin + text.size();
+
+
+
+
46 const std::from_chars_result parsed =
+
47 std::from_chars(begin, end, value, std::chars_format::general);
+
+
49 if (parsed.ec != std::errc() || parsed.ptr != end || !std::isfinite(value) ||
+
50 std::fpclassify(value) == FP_SUBNORMAL)
+
51 throw std::runtime_error(std::string(
"Invalid " ) + field +
": " + text);
+
+
+
+
55 Multiplexing ParseMultiplexingMarker(
const std::string &marker) {
+
+
+
58 result.
role = MultiplexRole::Selector;
+
59 else if (!marker.empty()) {
+
+
61 throw std::runtime_error(
"Unsupported multiplexing marker." );
+
62 const std::string value = marker.substr(1U);
63 const std::from_chars_result parsed =
-
64 std::from_chars(number.data(), number.data() + number.size(), value);
-
65 if (parsed.ec != std::errc() || parsed.ptr != number.data() + number.size())
-
66 throw std::runtime_error(
"Invalid VAL_ integer: " + number);
-
67 key = NormalizeValueKey(RawSignalValue(value));
-
-
69 std::uint64_t value = 0;
-
70 const std::from_chars_result parsed =
-
71 std::from_chars(number.data(), number.data() + number.size(), value);
-
72 if (number.empty() || parsed.ec != std::errc() || parsed.ptr != number.data() + number.size())
-
73 throw std::runtime_error(
"Invalid VAL_ integer: " + number);
-
-
-
-
-
-
79 std::string UnescapeDescription(
const std::string "ed) {
-
80 std::string description;
-
81 for (std::size_t i = 0; i < quoted.size(); ++i) {
-
82 if (quoted[i] ==
'\\' )
-
-
84 description += quoted[i];
-
-
-
-
-
-
-
91 for (
FrameInfo &candidate : database.frames) {
-
92 if (candidate.canId == canId && candidate.isExtended == isExtended) {
-
-
94 throw std::runtime_error(
"Ambiguous VAL_ frame reference." );
-
-
-
-
-
99 throw std::runtime_error(
"Unresolved VAL_ frame reference." );
-
+
64 std::from_chars(value.data(), value.data() + value.size(), result.
value );
+
65 if (value.empty() || parsed.ec != std::errc() || parsed.ptr != value.data() + value.size())
+
66 throw std::runtime_error(
"Invalid or unsupported multiplexing marker." );
+
67 result.
role = MultiplexRole::Branch;
+
+
+
+
+
+
73 RawSignalValue ParseValueKey(
const std::string &number) {
+
+
75 if (!number.empty() && number[0] ==
'-' ) {
+
76 std::int64_t value = 0;
+
77 const std::from_chars_result parsed =
+
78 std::from_chars(number.data(), number.data() + number.size(), value);
+
79 if (parsed.ec != std::errc() || parsed.ptr != number.data() + number.size())
+
80 throw std::runtime_error(
"Invalid VAL_ integer: " + number);
+
81 key = NormalizeValueKey(RawSignalValue(value));
+
+
83 std::uint64_t value = 0;
+
84 const std::from_chars_result parsed =
+
85 std::from_chars(number.data(), number.data() + number.size(), value);
+
86 if (number.empty() || parsed.ec != std::errc() || parsed.ptr != number.data() + number.size())
+
87 throw std::runtime_error(
"Invalid VAL_ integer: " + number);
+
+
+
+
+
+
93 std::string UnescapeDescription(
const std::string "ed) {
+
94 std::string description;
+
95 for (std::size_t i = 0; i < quoted.size(); ++i) {
+
96 if (quoted[i] ==
'\\' )
+
+
98 description += quoted[i];
+
+
-
-
-
-
106 if (candidate.name == signalName) {
-
-
108 throw std::runtime_error(
"Ambiguous VAL_ signal reference: " + signalName);
-
+
+
+
105 for (
FrameInfo &candidate : database.frames) {
+
106 if (candidate.canId == canId && candidate.isExtended == isExtended) {
+
+
108 throw std::runtime_error(
"Ambiguous VAL_ frame reference." );
+
-
-
113 throw std::runtime_error(
"Unresolved VAL_ signal reference: " + signalName);
-
+
+
113 throw std::runtime_error(
"Unresolved VAL_ frame reference." );
+
-
117 std::uint64_t NextSignalBit(std::uint64_t bit,
bool isLittleEndian) {
-
-
-
-
121 return bit % 8U == 0U ? bit + 15U : bit - 1U;
-
-
-
-
-
-
-
-
129 std::vector<std::string> SplitReceivers(
const std::string &text) {
-
130 std::vector<std::string> receivers;
-
-
132 std::istringstream stream(text);
-
-
134 while (std::getline(stream, token,
',' )) {
-
135 token = dbc_detail::TrimText(token);
-
-
137 receivers.push_back(token);
-
-
-
-
-
-
143 void NormalizeCanId(std::uint32_t rawCanId, std::uint32_t &normalizedCanId,
bool &isExtended) {
-
-
-
-
-
-
149 if ((rawCanId & 0x80000000U) != 0U) {
-
-
151 normalizedCanId = (rawCanId & 0x1FFFFFFFU);
-
-
153 isExtended = (rawCanId > 0x7FFU);
-
154 normalizedCanId = rawCanId;
-
-
-
-
158 std::uint32_t TryExtractPgn(std::uint32_t canId,
bool isExtended,
bool &hasPgn) {
-
-
-
-
-
-
164 if ((canId & 0x1FFFFFFFU) != canId)
-
-
-
167 const std::uint32_t pf = (canId >> 16U) & 0xFFU;
-
168 const std::uint32_t ps = (canId >> 8U) & 0xFFU;
-
169 const std::uint32_t dp = (canId >> 24U) & 0x01U;
-
-
171 std::uint32_t pgn = 0U;
-
-
-
174 pgn = (dp << 16U) | (pf << 8U);
-
-
176 pgn = (dp << 16U) | (pf << 8U) | ps;
-
-
-
-
+
+
+
+
120 if (candidate.name == signalName) {
+
+
122 throw std::runtime_error(
"Ambiguous VAL_ signal reference: " + signalName);
+
+
+
+
+
127 throw std::runtime_error(
"Unresolved VAL_ signal reference: " + signalName);
+
+
+
+
131 std::uint64_t NextSignalBit(std::uint64_t bit,
bool isLittleEndian) {
+
+
+
+
135 return bit % 8U == 0U ? bit + 15U : bit - 1U;
+
+
+
+
+
+
+
+
143 std::vector<std::string> SplitReceivers(
const std::string &text) {
+
144 std::vector<std::string> receivers;
+
+
146 std::istringstream stream(text);
+
+
148 while (std::getline(stream, token,
',' )) {
+
149 token = dbc_detail::TrimText(token);
+
+
151 receivers.push_back(token);
+
+
+
+
+
+
157 void NormalizeCanId(std::uint32_t rawCanId, std::uint32_t &normalizedCanId,
bool &isExtended) {
+
+
+
+
+
+
163 isExtended = (rawCanId & 0x80000000U) != 0U || rawCanId > 0x7FFU;
+
164 normalizedCanId = rawCanId & 0x1FFFFFFFU;
+
+
+
+
168 FrameInfo DbcFrameHandler::ParseFrameLine(
const std::string &line) {
+
+
+
+
+
+
174 std::istringstream stream(line);
+
+
+
177 if (!(stream >> keyword >> idText) || keyword !=
"BO_" )
+
178 throw std::runtime_error(
"Missing CAN ID in frame definition." );
+
+
180 const std::uint32_t rawCanId = ParseCanId(idText);
-
-
-
184 FrameInfo DbcFrameHandler::ParseFrameLine(
const std::string &line) {
-
-
-
-
-
-
190 std::istringstream stream(line);
-
-
-
193 if (!(stream >> keyword >> idText) || keyword !=
"BO_" )
-
194 throw std::runtime_error(
"Missing CAN ID in frame definition." );
-
-
196 const std::uint32_t rawCanId = ParseDecimal(
-
197 idText, std::numeric_limits<std::uint32_t>::max(),
"CAN ID" );
-
-
199 if ((rawCanId & 0x60000000U) != 0U)
-
200 throw std::runtime_error(
"CAN ID exceeds the 29-bit identifier range." );
-
-
202 std::string nameText;
-
203 if (!std::getline(stream, nameText,
':' ) || stream.eof())
-
204 throw std::runtime_error(
"Missing ':' in frame definition." );
-
205 std::istringstream nameStream(nameText);
-
-
-
208 if (!(nameStream >> frame.
name ) || (nameStream >> extra))
-
209 throw std::runtime_error(
"Missing or invalid frame name." );
-
-
211 std::string lengthText;
-
212 if (!(stream >> lengthText))
-
213 throw std::runtime_error(
"Missing payload length in frame definition." );
-
214 frame.
dlc =
static_cast< std::uint8_t
> (ParseDecimal(
-
215 lengthText, std::numeric_limits<std::uint8_t>::max(),
"payload length" ));
-
-
217 throw std::runtime_error(
"Missing transmitter in frame definition." );
-
-
219 throw std::runtime_error(
"Unexpected trailing field in frame definition: " + extra);
-
-
-
-
-
-
+
182 std::string nameText;
+
183 if (!std::getline(stream, nameText,
':' ) || stream.eof())
+
184 throw std::runtime_error(
"Missing ':' in frame definition." );
+
185 std::istringstream nameStream(nameText);
+
+
+
188 if (!(nameStream >> frame.
name ) || (nameStream >> extra))
+
189 throw std::runtime_error(
"Missing or invalid frame name." );
+
+
191 std::string lengthText;
+
192 if (!(stream >> lengthText))
+
193 throw std::runtime_error(
"Missing payload length in frame definition." );
+
194 frame.
dlc =
static_cast< std::uint8_t
> (ParseDecimal(
+
195 lengthText, std::numeric_limits<std::uint8_t>::max(),
"payload length" ));
+
+
197 throw std::runtime_error(
"Missing transmitter in frame definition." );
+
+
199 throw std::runtime_error(
"Unexpected trailing field in frame definition: " + extra);
+
+
+
+
+
+
+
206 SignalInfo DbcSignalHandler::ParseSignalLine(
const std::string &line) {
+
+
+
209 NameAndMarker = 1, StartBit, BitLength,
ByteOrder , Signedness,
+
210 Factor, Offset, Minimum, Maximum, Unit, Receivers
+
+
212 static const std::regex syntax(
+
+
214 R
"dbc(^SG_[ \t]+([^:]+):[ \t]*)dbc"
+
+
216 R
"dbc(([^| \t]+)[ \t]*\|[ \t]*([^@ \t]+)[ \t]*@[ \t]*([01])([+-])[ \t]*)dbc"
+
+
218 R
"dbc(\([ \t]*([^, \t]+)[ \t]*,[ \t]*([^ )\t]+)[ \t]*\)[ \t]*)dbc"
+
+
220 R
"dbc(\[[ \t]*([^| \t]+)[ \t]*\|[ \t]*([^\] \t]+)[ \t]*\][ \t]*)dbc"
+
+
222 R
"dbc("([^"\r\n]*)"[ \t]+([^ \t,]+(?:[ \t]*,[ \t]*[^ \t,]+)*)[ \t]*$)dbc");
+
+
224 if (!std::regex_match(line, fields, syntax))
+
225 throw std::runtime_error(
"Malformed or unsupported SG_ signal definition." );
-
227 SignalInfo DbcSignalHandler::ParseSignalLine(
const std::string &line) {
-
-
-
230 NameAndMarker = 1, StartBit, BitLength,
ByteOrder , Signedness,
-
231 Factor, Offset, Minimum, Maximum, Unit, Receivers
-
-
233 static const std::regex syntax(
-
-
235 R
"dbc(^SG_[ \t]+([^:]+):[ \t]*)dbc"
-
-
237 R
"dbc(([^| \t]+)[ \t]*\|[ \t]*([^@ \t]+)[ \t]*@[ \t]*([01])([+-])[ \t]*)dbc"
-
-
239 R
"dbc(\([ \t]*([^, \t]+)[ \t]*,[ \t]*([^ )\t]+)[ \t]*\)[ \t]*)dbc"
-
-
241 R
"dbc(\[[ \t]*([^| \t]+)[ \t]*\|[ \t]*([^\] \t]+)[ \t]*\][ \t]*)dbc"
-
-
243 R
"dbc("([^"\r\n]*)"[ \t]+([^ \t,]+(?:[ \t]*,[ \t]*[^ \t,]+)*)[ \t]*$)dbc");
-
-
245 if (!std::regex_match(line, fields, syntax))
-
246 throw std::runtime_error(
"Malformed or unsupported SG_ signal definition." );
-
-
-
249 std::istringstream nameFields(fields[NameAndMarker].str());
-
-
-
252 nameFields >> signal.
name >> marker;
-
253 if (signal.
name .empty() || (nameFields >> extra))
-
254 throw std::runtime_error(
"Invalid signal name or multiplexing marker." );
-
255 signal.multiplexing = ParseMultiplexingMarker(marker);
-
-
257 signal.
startBit = ParseDecimal(fields[StartBit].str(),
-
258 std::numeric_limits<std::uint32_t>::max(),
"signal start bit" );
-
259 signal.
length = ParseDecimal(fields[BitLength].str(), 64U,
"signal length" );
-
-
261 throw std::runtime_error(
"Signal length must be within 1..64 bits." );
-
-
263 signal.
isSigned = fields[Signedness].str() ==
"-" ;
+
+
228 std::istringstream nameFields(fields[NameAndMarker].str());
+
+
+
231 nameFields >> signal.
name >> marker;
+
232 if (signal.
name .empty() || (nameFields >> extra))
+
233 throw std::runtime_error(
"Invalid signal name or multiplexing marker." );
+
+
+
236 signal.
startBit = ParseDecimal(fields[StartBit].str(),
+
237 std::numeric_limits<std::uint32_t>::max(),
"signal start bit" );
+
238 signal.
length = ParseDecimal(fields[BitLength].str(), 64U,
"signal length" );
+
+
240 throw std::runtime_error(
"Signal length must be within 1..64 bits." );
+
+
242 signal.
isSigned = fields[Signedness].str() ==
"-" ;
+
+
244 signal.
factor = ParsePhysicalValue(fields[Factor].str(),
"signal factor" );
+
245 signal.
offset = ParsePhysicalValue(fields[Offset].str(),
"signal offset" );
+
246 signal.
minimum = ParsePhysicalValue(fields[Minimum].str(),
"signal minimum" );
+
247 signal.
maximum = ParsePhysicalValue(fields[Maximum].str(),
"signal maximum" );
+
+
249 throw std::runtime_error(
"Signal minimum exceeds maximum." );
+
250 signal.
unit = fields[Unit].str();
+
251 signal.
receivers = SplitReceivers(fields[Receivers].str());
+
+
+
+
+
+
+
+
+
260 for (
FrameInfo &frame : database.frames) {
+
+
+
-
265 signal.
factor = ParsePhysicalValue(fields[Factor].str(),
"signal factor" );
-
266 signal.
offset = ParsePhysicalValue(fields[Offset].str(),
"signal offset" );
-
267 signal.
minimum = ParsePhysicalValue(fields[Minimum].str(),
"signal minimum" );
-
268 signal.
maximum = ParsePhysicalValue(fields[Maximum].str(),
"signal maximum" );
-
-
270 throw std::runtime_error(
"Signal minimum exceeds maximum." );
-
271 signal.
unit = fields[Unit].str();
-
272 signal.
receivers = SplitReceivers(fields[Receivers].str());
-
-
-
-
276 void DbcCommentHandler::ParseCommentLine(
const std::string &line,
DbcDatabase &database) {
-
-
-
-
-
-
-
283 std::istringstream stream(line);
-
-
-
-
-
-
-
-
291 if (token !=
"BO_" && token !=
"SG_" )
-
-
-
294 std::uint32_t rawCanId = 0U;
-
295 std::uint32_t canId = 0U;
-
296 bool isExtended =
false ;
-
297 std::string signalName;
-
-
-
300 stream >> signalName;
-
301 NormalizeCanId(rawCanId, canId, isExtended);
-
-
303 const std::string::size_type quoteBegin = line.find(
'"' );
-
304 const std::string::size_type quoteEnd = line.rfind(
'"' );
-
305 if (quoteBegin == std::string::npos || quoteEnd == std::string::npos || quoteEnd <= quoteBegin)
-
-
-
308 FrameInfo *frame = FindFrameById(database, canId, isExtended);
-
309 if (frame ==
nullptr )
-
-
311 const std::string comment = line.substr(quoteBegin + 1U, quoteEnd - quoteBegin - 1U);
-
312 if (token ==
"BO_" ) {
-
-
-
-
316 SignalInfo *signal = FindSignalByName(*frame, signalName);
-
317 if (signal !=
nullptr )
-
-
-
-
-
-
-
-
325 for (
FrameInfo &frame : database.frames) {
-
-
-
-
-
-
-
-
-
-
335 if (signal.
name == signalName)
-
-
-
-
-
-
-
-
343 void DbcFrameHandler::Handle(
const std::string &line,
DbcParseContext &context)
const {
-
-
345 if (FindFrameById(context.database, frame.
canId , frame.
isExtended ) !=
nullptr )
-
346 throw std::runtime_error(
"Duplicate " + std::string(frame.
isExtended ?
"extended" :
"standard" ) +
-
347 " frame CAN ID: " + std::to_string(frame.canId));
-
348 context.database.
frames .push_back(std::move(frame));
-
349 context.currentFrame = &context.database.
frames .back();
-
350 context.signalLines.emplace_back();
-
-
-
353 void DbcSignalHandler::Handle(
const std::string &line,
DbcParseContext &context)
const {
-
354 if (context.currentFrame ==
nullptr )
-
355 throw std::runtime_error(
"Signal found before any frame definition." );
-
-
357 if (FindSignalByName(*context.currentFrame, signal.
name ) !=
nullptr )
-
358 throw std::runtime_error(
"Duplicate signal name '" + signal.
name +
-
359 "' in frame '" + context.currentFrame->
name +
"'." );
-
-
361 context.currentFrame->
dlc ))
-
362 throw std::runtime_error(
"Signal exceeds the frame payload length." );
-
363 context.currentFrame->signals.push_back(std::move(signal));
-
364 context.signalLines.back().push_back(context.lineNumber);
-
-
-
367 void DbcCommentHandler::Handle(
const std::string &line,
DbcParseContext &context)
const {
-
368 ParseCommentLine(line, context.database);
-
-
-
371 DbcStatementDispatcher::DbcStatementDispatcher() {
-
372 RegisterType<DbcHeaderHandler>(
"VERSION" );
-
373 RegisterType<DbcHeaderHandler>(
"NS_" );
-
374 RegisterType<DbcHeaderHandler>(
"NS_:" );
-
375 RegisterType<DbcHeaderHandler>(
"BS_" );
-
376 RegisterType<DbcHeaderHandler>(
"BS_:" );
-
377 RegisterType<DbcHeaderHandler>(
"BU_" );
-
378 RegisterType<DbcHeaderHandler>(
"BU_:" );
-
379 RegisterType<DbcUnsupportedMultiplexingHandler>(
"SG_MUL_VAL_" );
-
380 RegisterType<DbcFrameHandler>(
"BO_" );
-
381 RegisterType<DbcSignalHandler>(
"SG_" );
-
382 RegisterType<DbcCommentHandler>(
"CM_" );
-
383 RegisterType<DbcValueDescriptionHandler>(
"VAL_" );
-
-
-
386 void DbcHeaderHandler::Handle(
const std::string &,
DbcParseContext &)
const {}
-
-
-
-
-
390 std::istringstream stream(line);
-
-
-
393 const HandlerMap::const_iterator handler = m_handlers.find(keyword);
-
394 if (handler == m_handlers.end())
-
-
396 handler->second->Handle(line, context);
-
-
+
+
+
+
+
+
270 if (signal.
name == signalName)
+
+
+
+
+
+
+
+
+
+
+
+
+
282 frame.
pgn = ExtractJ1939Pgn(frame.
canId );
+
+
+
285 throw std::runtime_error(
"Duplicate " + std::string(frame.
isExtended ?
"extended" :
"standard" ) +
+
286 " frame CAN ID: " + std::to_string(frame.
canId ));
+
+
+
+
-
-
400 void DbcValueDescriptionHandler::Handle(
const std::string &line,
DbcParseContext &context)
const {
-
401 static const std::regex header(R
"(^VAL_[ \t]+([^ \t]+)[ \t]+([^ \t;]+)[ \t]+(.*)$)");
-
402 static const std::regex pair(R
"dbc(^([^ \t]+)[ \t]+"((?:[^"\\]|\\["\\])*)")dbc");
-
-
404 if (!std::regex_match(line, fields, header))
-
405 throw std::runtime_error(
"Malformed or unsupported VAL_ statement." );
-
406 const std::uint32_t rawId = ParseDecimal(fields[1].str(), std::numeric_limits<std::uint32_t>::max(),
"VAL_ CAN ID" );
-
407 if ((rawId & 0x60000000U) != 0U)
-
408 throw std::runtime_error(
"VAL_ CAN ID exceeds the 29-bit identifier range." );
-
-
410 NormalizeCanId(rawId, pending.canId, pending.isExtended);
-
411 pending.signalName = fields[2].str();
-
412 pending.lineNumber = context.lineNumber;
-
413 std::string rest = fields[3].str();
-
414 while (rest !=
";" ) {
-
415 if (!std::regex_search(rest, fields, pair))
-
416 throw std::runtime_error(
"Malformed VAL_ value/description pair or missing semicolon." );
-
417 const std::string number = fields[1].str();
-
418 const RawSignalValue key = ParseValueKey(number);
-
419 const std::string description = UnescapeDescription(fields[2].str());
-
420 if (!pending.descriptions.emplace(key, description).second)
-
421 throw std::runtime_error(
"Duplicate VAL_ value key: " + number);
-
422 const std::size_t consumed =
static_cast< std::size_t
> (fields.length());
-
423 rest.erase(0, consumed);
-
424 if (!rest.empty() && rest[0] !=
';' && rest[0] !=
' ' && rest[0] !=
'\t' )
-
425 throw std::runtime_error(
"Missing whitespace between VAL_ pairs." );
-
426 rest = dbc_detail::TrimText(rest);
-
-
428 if (pending.descriptions.empty())
-
429 throw std::runtime_error(
"VAL_ requires at least one value/description pair." );
-
430 context.pendingValues.push_back(std::move(pending));
-
-
-
433 void DbcParseContext::ResolveValueDescriptions(
const std::string &filePath) {
-
-
-
436 FrameInfo *frame = FindUniqueFrame(database, pending.canId, pending.isExtended);
-
437 SignalInfo *signal = FindUniqueSignal(*frame, pending.signalName);
-
438 for (
const ValueDescriptions::value_type &entry: pending.descriptions) {
-
-
440 throw std::runtime_error(
"Duplicate VAL_ value key for signal: " + pending.signalName);
-
-
442 }
catch (
const std::exception &error) {
-
-
444 filePath, pending.lineNumber, error.what());
-
-
-
-
-
449 void DbcUnsupportedMultiplexingHandler::Handle(
const std::string &,
DbcParseContext &)
const {
-
450 throw std::runtime_error(
"Extended and nested multiplexing are unsupported." );
-
-
-
-
454 std::vector<std::uint64_t> SignalBits(
const SignalInfo &signal) {
-
455 std::vector<std::uint64_t> bits;
-
456 std::uint64_t bit = signal.
startBit ;
-
457 for (std::uint32_t index = 0U; index < signal.
length ; ++index) {
-
-
-
-
-
-
-
-
465 return first.multiplexing.role == MultiplexRole::Branch &&
-
466 second.multiplexing.role == MultiplexRole::Branch &&
-
467 first.multiplexing.value != second.multiplexing.value;
-
-
-
-
471 if (signal.multiplexing.role != MultiplexRole::Branch)
-
-
473 if (selector ==
nullptr )
-
474 return "Multiplexed branch has no selector." ;
-
475 if (selector->
length < 64U && signal.multiplexing.value >= (std::uint64_t(1U) << selector->
length ))
-
476 return "Branch value exceeds selector raw range." ;
-
-
-
-
-
481 const std::vector<std::size_t> &lines,
-
482 const std::string &filePath) {
-
-
484 for (std::size_t index = 0U; index < frame.signals.size(); ++index) {
-
485 const SignalInfo &signal = frame.signals[index];
-
486 if (signal.multiplexing.role != MultiplexRole::Selector)
-
-
488 if (selector !=
nullptr || signal.
isSigned )
-
-
490 filePath, lines[index],
-
491 "Multiplexing requires one unsigned selector per frame." );
-
-
-
-
-
-
-
498 const std::vector<std::uint64_t> firstBits = SignalBits(first);
-
499 const std::vector<std::uint64_t> secondBits = SignalBits(second);
-
500 for (
const std::uint64_t firstBit : firstBits) {
-
501 for (
const std::uint64_t secondBit : secondBits) {
-
502 if (firstBit == secondBit)
-
-
-
-
-
-
-
-
510 void DbcParseContext::ValidateMultiplexing(
const std::string &filePath)
const {
-
511 for (std::size_t frameIndex = 0U; frameIndex < database.
frames .size(); ++frameIndex) {
-
-
513 const SignalInfo *selector = FindSelector(frame, signalLines[frameIndex], filePath);
-
514 for (std::size_t index = 0U; index < frame.signals.size(); ++index) {
-
515 const SignalInfo &signal = frame.signals[index];
-
516 std::string error = ValidateBranch(signal, selector);
-
517 for (std::size_t previous = 0U; previous < index && error.empty(); ++previous) {
-
518 const SignalInfo &other = frame.signals[previous];
-
519 if (!AreMutuallyExclusive(signal, other) && SignalsOverlap(signal, other))
-
520 error =
"Signals overlap without mutually exclusive multiplexing conditions." ;
-
-
-
-
524 filePath, signalLines[frameIndex][index], error);
-
-
-
-
-
bool Dispatch(const std::string &line, DbcParseContext &context) const
-
ByteOrder
Signal byte order used for runtime decoding.
+
+
+
+
+
294 throw std::runtime_error(
"Signal found before any frame definition." );
+
+
+
297 throw std::runtime_error(
"Duplicate signal name '" + signal.
name +
+
+
+
+
301 throw std::runtime_error(
"Signal exceeds the frame payload length." );
+
302 context.
currentFrame ->signals.push_back(std::move(signal));
+
+
+
+
+
+
+
307 std::istringstream stream(line);
+
+
+
310 stream >> keyword >> target;
+
311 if (keyword !=
"CM_" || (target !=
"BO_" && target !=
"SG_" ))
+
+
+
+
+
+
+
318 if (!(stream >> idText))
+
319 throw std::runtime_error(
"Missing CAN ID in CM_ statement." );
+
+
+
322 pending.
signalName .find_first_of(
"\";" ) != std::string::npos))
+
323 throw std::runtime_error(
"Missing or invalid signal name in CM_ statement." );
+
+
+
326 if (stream.get() !=
'"' )
+
327 throw std::runtime_error(
"Missing opening quote in CM_ statement." );
+
+
+
330 while (stream.get(character)) {
+
331 if (character ==
'"' ) {
+
+
+
+
335 if (character ==
'\\' ) {
+
336 if (!stream.get(character) || (character !=
'"' && character !=
'\\' ))
+
337 throw std::runtime_error(
"Invalid escape in CM_ statement." );
+
+
+
+
+
342 throw std::runtime_error(
"Unterminated CM_ comment." );
+
+
344 if (stream.get() !=
';' )
+
345 throw std::runtime_error(
"Missing semicolon in CM_ statement." );
+
+
+
348 throw std::runtime_error(
"Unexpected trailing text in CM_ statement." );
+
+
+
+
+
+
+
+
+
+
+
357 pending.lineNumber,
"Unresolved CM_ frame reference." );
+
358 if (pending.isSignal) {
+
359 SignalInfo *signal = FindSignalByName(*frame, pending.signalName);
+
+
+
362 pending.lineNumber,
"Unresolved CM_ signal reference: " + pending.signalName);
+
363 signal->
comment = pending.comment;
+
+
365 frame->
comment = pending.comment;
+
+
+
+
+
+
+
+
371 RegisterType<DbcHeaderHandler>(
"VERSION" );
+
372 RegisterType<DbcHeaderHandler>(
"NS_" );
+
373 RegisterType<DbcHeaderHandler>(
"NS_:" );
+
374 RegisterType<DbcHeaderHandler>(
"BS_" );
+
375 RegisterType<DbcHeaderHandler>(
"BS_:" );
+
376 RegisterType<DbcHeaderHandler>(
"BU_" );
+
377 RegisterType<DbcHeaderHandler>(
"BU_:" );
+
378 RegisterType<DbcUnsupportedMultiplexingHandler>(
"SG_MUL_VAL_" );
+
379 RegisterType<DbcFrameHandler>(
"BO_" );
+
380 RegisterType<DbcSignalHandler>(
"SG_" );
+
381 RegisterType<DbcCommentHandler>(
"CM_" );
+
382 RegisterType<DbcValueDescriptionHandler>(
"VAL_" );
+
383 RegisterType<DbcAttributeHandler>(
"BA_DEF_" );
+
384 RegisterType<DbcAttributeHandler>(
"BA_DEF_DEF_" );
+
385 RegisterType<DbcAttributeHandler>(
"BA_" );
+
+
+
+
+
+
+
+
+
392 std::istringstream stream(line);
+
+
+
395 const HandlerMap::const_iterator handler = m_handlers.find(keyword);
+
396 if (handler == m_handlers.end())
+
+
398 handler->second->Handle(line, context);
+
+
+
+
+
+
+
403 static const std::regex header(R
"(^VAL_[ \t]+([^ \t]+)[ \t]+([^ \t;]+)[ \t]+(.*)$)");
+
404 static const std::regex pair(R
"dbc(^([^ \t]+)[ \t]+"((?:[^"\\]|\\["\\])*)")dbc");
+
+
406 if (!std::regex_match(line, fields, header))
+
407 throw std::runtime_error(
"Malformed or unsupported VAL_ statement." );
+
408 const std::uint32_t rawId = ParseDecimal(fields[1].str(), std::numeric_limits<std::uint32_t>::max(),
"VAL_ CAN ID" );
+
409 if ((rawId & 0x60000000U) != 0U)
+
410 throw std::runtime_error(
"VAL_ CAN ID exceeds the 29-bit identifier range." );
+
+
+
+
+
415 std::string rest = fields[3].str();
+
416 while (rest !=
";" ) {
+
417 if (!std::regex_search(rest, fields, pair))
+
418 throw std::runtime_error(
"Malformed VAL_ value/description pair or missing semicolon." );
+
419 const std::string number = fields[1].str();
+
420 const RawSignalValue key = ParseValueKey(number);
+
421 const std::string description = UnescapeDescription(fields[2].str());
+
422 if (!pending.
descriptions .emplace(key, description).second)
+
423 throw std::runtime_error(
"Duplicate VAL_ value key: " + number);
+
424 const std::size_t consumed =
static_cast< std::size_t
> (fields.length());
+
425 rest.erase(0, consumed);
+
426 if (!rest.empty() && rest[0] !=
';' && rest[0] !=
' ' && rest[0] !=
'\t' )
+
427 throw std::runtime_error(
"Missing whitespace between VAL_ pairs." );
+
428 rest = dbc_detail::TrimText(rest);
+
+
+
431 throw std::runtime_error(
"VAL_ requires at least one value/description pair." );
+
+
+
+
+
+
+
+
+
+
439 SignalInfo *signal = FindUniqueSignal(*frame, pending.signalName);
+
440 for (
const ValueDescriptions::value_type &entry: pending.descriptions) {
+
+
442 throw std::runtime_error(
"Duplicate VAL_ value key for signal: " + pending.signalName);
+
+
444 }
catch (
const std::exception &error) {
+
+
446 filePath, pending.lineNumber, error.what());
+
+
+
+
+
+
+
+
452 throw std::runtime_error(
"Extended and nested multiplexing are unsupported." );
+
+
+
+
+
456 std::vector<std::uint64_t> SignalBits(
const SignalInfo &signal) {
+
457 std::vector<std::uint64_t> bits;
+
458 std::uint64_t bit = signal.
startBit ;
+
459 for (std::uint32_t index = 0U; index < signal.
length ; ++index) {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
475 if (selector ==
nullptr )
+
476 return "Multiplexed branch has no selector." ;
+
+
478 return "Branch value exceeds selector raw range." ;
+
+
+
+
+
483 const std::vector<std::size_t> &lines,
+
484 const std::string &filePath) {
+
+
486 for (std::size_t index = 0U; index < frame.signals.size(); ++index) {
+
487 const SignalInfo &signal = frame.signals[index];
+
+
+
490 if (selector !=
nullptr || signal.
isSigned )
+
+
492 filePath, lines[index],
+
493 "Multiplexing requires one unsigned selector per frame." );
+
+
+
+
+
+
+
500 const std::vector<std::uint64_t> firstBits = SignalBits(first);
+
501 const std::vector<std::uint64_t> secondBits = SignalBits(second);
+
502 for (
const std::uint64_t firstBit : firstBits) {
+
503 for (
const std::uint64_t secondBit : secondBits) {
+
504 if (firstBit == secondBit)
+
+
+
+
+
+
+
+
+
+
513 for (std::size_t frameIndex = 0U; frameIndex <
database .
frames .size(); ++frameIndex) {
+
+
+
516 for (std::size_t index = 0U; index < frame.signals.size(); ++index) {
+
517 const SignalInfo &signal = frame.signals[index];
+
518 std::string error = ValidateBranch(signal, selector);
+
519 for (std::size_t previous = 0U; previous < index && error.empty(); ++previous) {
+
520 const SignalInfo &other = frame.signals[previous];
+
521 if (!AreMutuallyExclusive(signal, other) && SignalsOverlap(signal, other))
+
522 error =
"Signals overlap without mutually exclusive multiplexing conditions." ;
+
+
+
+
+
+
+
+
+
+
+
void Handle(const std::string &line, DbcParseContext &context) const override
Process a trimmed statement using state belonging to this parse.
+
void Handle(const std::string &line, DbcParseContext &context) const override
Process a trimmed statement using state belonging to this parse.
+
void Handle(const std::string &line, DbcParseContext &context) const override
Process a trimmed statement using state belonging to this parse.
+
DbcStatementDispatcher()
Register supported statement handlers through TypeFactory.
+
bool Dispatch(const std::string &line, DbcParseContext &context) const
+
void Handle(const std::string &line, DbcParseContext &context) const override
Process a trimmed statement using state belonging to this parse.
+
void Handle(const std::string &line, DbcParseContext &context) const override
Process a trimmed statement using state belonging to this parse.
+
ByteOrder
Signal byte order used for runtime decoding.
Parsed DBC content stored in a simple internal form.
std::vector< FrameInfo > frames
-
-
Describes one CAN frame from a DBC file.
-
-
-
-
-
-
-
-
-
-
-
Describes one signal inside a DBC frame.
-
-
-
std::vector< std::string > receivers
-
-
ValueDescriptions valueDescriptions
-
-
-
-
-
-
-
-
+
+
+
+
std::vector< PendingComment > pendingComments
+
void ValidateMultiplexing(const std::string &filePath) const
Validate selectors, branch ranges, and signal overlap.
+
+
void ResolveValueDescriptions(const std::string &filePath)
Resolve deferred raw descriptions against unique targets.
+
std::vector< PendingValueDescriptions > pendingValues
+
void ResolveComments(const std::string &filePath)
Resolve deferred comments after all definitions are known.
+
+
std::vector< std::vector< std::size_t > > signalLines
+
Describes one CAN frame from a DBC file.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Deferred raw value descriptions and their target.
+
ValueDescriptions descriptions
+
+
+
+
+
Describes one signal inside a DBC frame.
+
+
+
std::vector< std::string > receivers
+
+
ValueDescriptions valueDescriptions
+
+
Multiplexing multiplexing
+
+
+
+
+
+
+
diff --git a/docs/html/dbc__statement__handler_8h_source.html b/docs/html/dbc__statement__handler_8h_source.html
index c7c5f46..5c2850e 100644
--- a/docs/html/dbc__statement__handler_8h_source.html
+++ b/docs/html/dbc__statement__handler_8h_source.html
@@ -109,142 +109,214 @@ $(document).ready(function(){initNavTree('dbc__statement__handler_8h_source.html
10 #include <unordered_map>
-
-
-
-
-
15 std::string signalName;
-
16 ValueDescriptions descriptions;
-
17 std::size_t lineNumber;
-
+
-
-
-
-
-
-
24 std::size_t lineNumber,
const std::string &message)
-
25 : std::runtime_error(filePath +
":" + std::to_string(lineNumber) +
": " + message),
-
26 diagnostic{DbcDiagnosticSeverity::Error, code, filePath, lineNumber, message} {}
-
-
+
+
-
-
-
-
35 std::size_t lineNumber = 0U;
-
36 std::vector<PendingValueDescriptions> pendingValues = {};
-
-
38 std::vector<std::vector<std::size_t>> signalLines = {};
-
39 void ValidateMultiplexing(
const std::string &filePath)
const ;
-
-
41 void ResolveValueDescriptions(
const std::string &filePath);
-
+
+
+
+
+
36 std::size_t lineNumber,
const std::string &message)
+
37 : std::runtime_error(filePath +
":" + std::to_string(lineNumber) +
": " + message),
+
38 diagnostic {DbcDiagnosticSeverity::Error, code, filePath, lineNumber, message} {}
-
+
+
+
+
+
-
-
-
-
47 virtual void Handle(
const std::string &line,
DbcParseContext &context)
const = 0;
-
+
+
+
+
-
+
-
-
-
52 void Handle(
const std::string &line,
DbcParseContext &context)
const override ;
-
-
-
55 static FrameInfo ParseFrameLine(
const std::string &line);
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
67 void ResolveAttributes (
const std::string &filePath, std::vector<DbcDiagnostic> &diagnostics);
+
+
+
-
-
-
-
-
60 void Handle(
const std::string &line,
DbcParseContext &context)
const override ;
-
-
-
63 static SignalInfo ParseSignalLine(
const std::string &line);
-
-
-
-
-
-
-
68 void Handle(
const std::string &line,
DbcParseContext &context)
const override ;
-
-
-
71 static void ParseCommentLine(
const std::string &line,
DbcDatabase &database);
-
-
-
+
-
+
-
76 void Handle(
const std::string &line,
DbcParseContext &context)
const override ;
-
+
+
+
-
-
-
-
-
81 void Handle(
const std::string &line,
DbcParseContext &context)
const override ;
-
-
-
-
-
-
-
87 void Handle(
const std::string &line,
DbcParseContext &context)
const override ;
+
+
+
+
+
+
+
+
87 static FrameInfo ParseFrameLine(
const std::string &line);
-
+
-
+
-
95 template <
class Handler>
-
96 void RegisterType(
const std::string &keyword) {
-
-
98 m_handlers.insert_or_assign(keyword, m_factory.
create (keyword));
-
-
-
-
-
-
105 using HandlerMap = std::unordered_map<std::string, std::shared_ptr<DbcStatementHandler>>;
-
-
107 HandlerMap m_handlers;
-
+
+
96 static SignalInfo ParseSignalLine(
const std::string &line);
+
-
-
-
-
-
-
-
-
-
bool Dispatch(const std::string &line, DbcParseContext &context) const
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
136 template <
class Handler>
+
+
+
+
139 m_handlers.insert_or_assign(keyword, m_factory.
create (keyword));
+
+
+
+
+
+
+
146 using HandlerMap = std::unordered_map<std::string, std::shared_ptr<DbcStatementHandler>>;
+
+
148 HandlerMap m_handlers;
+
+
+
+
+
Defer typed attribute statements for resolution.
+
void Handle(const std::string &line, DbcParseContext &context) const override
Process a trimmed statement using state belonging to this parse.
+
+
+
+
DbcDiagnosticError(DbcDiagnosticCode code, const std::string &filePath, std::size_t lineNumber, const std::string &message)
Create an exception with a structured source diagnostic.
+
+
Parse and append frame definitions.
+
void Handle(const std::string &line, DbcParseContext &context) const override
Process a trimmed statement using state belonging to this parse.
+
+
void Handle(const std::string &line, DbcParseContext &context) const override
Process a trimmed statement using state belonging to this parse.
+
Parse and append signals to the current frame.
+
void Handle(const std::string &line, DbcParseContext &context) const override
Process a trimmed statement using state belonging to this parse.
+
+
void RegisterType(const std::string &keyword)
Register or replace a handler and create its reusable instance.
+
DbcStatementDispatcher()
Register supported statement handlers through TypeFactory.
+
bool Dispatch(const std::string &line, DbcParseContext &context) const
+
Interface for processing a registered DBC statement.
+
virtual void Handle(const std::string &line, DbcParseContext &context) const =0
Process a trimmed statement using state belonging to this parse.
+
Reject unsupported extended multiplexing statements.
+
void Handle(const std::string &line, DbcParseContext &context) const override
Process a trimmed statement using state belonging to this parse.
+
Defer raw value descriptions for target resolution.
+
void Handle(const std::string &line, DbcParseContext &context) const override
Process a trimmed statement using state belonging to this parse.
Registry-based factory for creating objects by runtime identifier.
-
BasePtr create(const ClassId &id, Args... args) const
Creates an instance for the given id using provided arguments.
-
void registerType(const ClassId &id)
Registers a Derived type under the given id.
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
BasePtr create(const ClassId &id, Args... args) const
Creates an instance for the given id using provided arguments.
+
void registerType(const ClassId &id)
Registers a Derived type under the given id.
+
Parsed DBC database and attribute metadata.
Parsed DBC content stored in a simple internal form.
-
-
-
Describes one CAN frame from a DBC file.
-
-
Describes one signal inside a DBC frame.
+
Diagnostic message and physical source location.
+
+
void ResolveAttributes(const std::string &filePath, std::vector< DbcDiagnostic > &diagnostics)
Resolve definitions, defaults, then assignments; append format warnings.
+
+
+
std::vector< PendingComment > pendingComments
+
void ValidateMultiplexing(const std::string &filePath) const
Validate selectors, branch ranges, and signal overlap.
+
+
void ResolveValueDescriptions(const std::string &filePath)
Resolve deferred raw descriptions against unique targets.
+
std::vector< PendingValueDescriptions > pendingValues
+
void ResolveComments(const std::string &filePath)
Resolve deferred comments after all definitions are known.
+
+
std::vector< std::vector< std::size_t > > signalLines
+
std::vector< PendingAttribute > pendingAttributes
+
Describes one CAN frame from a DBC file.
+
Attribute statement retained for ordered resolution.
+
+
+
+
+
+
+
+
+
+
Deferred raw value descriptions and their target.
+
ValueDescriptions descriptions
+
+
+
+
+
Describes one signal inside a DBC frame.
diff --git a/docs/html/dbc__tree__builder_8cpp.html b/docs/html/dbc__tree__builder_8cpp.html
index f4a1ec9..88ce219 100644
--- a/docs/html/dbc__tree__builder_8cpp.html
+++ b/docs/html/dbc__tree__builder_8cpp.html
@@ -94,13 +94,14 @@ $(document).ready(function(){initNavTree('dbc__tree__builder_8cpp.html',''); ini
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Construction of frame and signal metadata trees.
More...
Go to the source code of this file.
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Construction of frame and signal metadata trees.
+
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Licensed under the MIT License. See LICENSE file in the project root for full license text.
Definition in file dbc_tree_builder.cpp .
diff --git a/docs/html/dbc__tree__builder_8cpp_source.html b/docs/html/dbc__tree__builder_8cpp_source.html
index 8916c8a..772b7f2 100644
--- a/docs/html/dbc__tree__builder_8cpp_source.html
+++ b/docs/html/dbc__tree__builder_8cpp_source.html
@@ -120,11 +120,11 @@ $(document).ready(function(){initNavTree('dbc__tree__builder_8cpp_source.html','
std::unique_ptr< TreeNode > Build(const DbcDatabase &database) const
Build tree representation of parsed DBC data.
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Parsed DBC content stored in a simple internal form.
std::vector< FrameInfo > frames
-
Describes one CAN frame from a DBC file.
-
Describes one signal inside a DBC frame.
+
Describes one CAN frame from a DBC file.
+
Describes one signal inside a DBC frame.
diff --git a/docs/html/dbc__tree__builder_8h.html b/docs/html/dbc__tree__builder_8h.html
index ac29a67..0fd20ee 100644
--- a/docs/html/dbc__tree__builder_8h.html
+++ b/docs/html/dbc__tree__builder_8h.html
@@ -96,7 +96,7 @@ $(document).ready(function(){initNavTree('dbc__tree__builder_8h.html',''); initR
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Metadata tree builder.
More...
#include <memory>
#include "dbc_database.h "
@@ -111,7 +111,8 @@ Classes
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Metadata tree builder.
+
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Licensed under the MIT License. See LICENSE file in the project root for full license text.
Definition in file dbc_tree_builder.h .
diff --git a/docs/html/dbc__tree__builder_8h_source.html b/docs/html/dbc__tree__builder_8h_source.html
index 4a45bf4..745999e 100644
--- a/docs/html/dbc__tree__builder_8h_source.html
+++ b/docs/html/dbc__tree__builder_8h_source.html
@@ -117,9 +117,9 @@ $(document).ready(function(){initNavTree('dbc__tree__builder_8h_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.
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Parsed DBC database and attribute metadata.
Parsed DBC content stored in a simple internal form.
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Qt-independent metadata tree nodes.
diff --git a/docs/html/dbc__tree__model_8cpp_source.html b/docs/html/dbc__tree__model_8cpp_source.html
index 86d598a..e8eabb4 100644
--- a/docs/html/dbc__tree__model_8cpp_source.html
+++ b/docs/html/dbc__tree__model_8cpp_source.html
@@ -122,24 +122,27 @@ $(document).ready(function(){initNavTree('dbc__tree__model_8cpp_source.html','')
-
25 DbcTreeModel::DbcTreeModel(QObject *parent) : QAbstractItemModel(parent) {}
+
-
27 void DbcTreeModel::SetTree(std::unique_ptr<TreeNode> root) {
+
+
28 if (root && (root->GetType() != NodeType::Root || root->GetParent()))
29 throw std::invalid_argument(
"Model requires a detached root node" );
31 m_root = std::move(root);
+
35 const TreeNode *DbcTreeModel::Node(
const QModelIndex &index)
const {
-
36 if (!index.isValid() || index.model() !=
this || index.column() < 0 ||
-
37 index.column() >= ColumnCount || index.row() < 0)
+
+
37 index .column() >= ColumnCount ||
index .row() < 0)
-
39 return static_cast< const TreeNode *
> (index.internalPointer());
+
39 return static_cast< const TreeNode *
> (
index .internalPointer());
-
42 QModelIndex DbcTreeModel::index(
int row,
int column,
const QModelIndex &parentIndex)
const {
+
+
43 if (row < 0 || column < 0 || column >= ColumnCount ||
44 (parentIndex.isValid() && parentIndex.column() != 0))
@@ -149,16 +152,20 @@ $(document).ready(function(){initNavTree('dbc__tree__model_8cpp_source.html','')
50 return child ? createIndex(row, column,
const_cast< TreeNode *
> (child)) : QModelIndex();
+
-
53 QModelIndex DbcTreeModel::parent(
const QModelIndex &childIndex)
const {
+
+
54 const TreeNode *child = Node(childIndex);
56 if (!owner || owner == m_root.get())
58 return createIndex(
static_cast< int > (owner->
GetRow ()), 0,
const_cast< TreeNode *
> (owner));
+
-
61 int DbcTreeModel::rowCount(
const QModelIndex &parentIndex)
const {
+
+
62 if (parentIndex.isValid() && parentIndex.column() != 0)
64 const TreeNode *owner = parentIndex.isValid() ? Node(parentIndex) : m_root.get();
@@ -166,12 +173,16 @@ $(document).ready(function(){initNavTree('dbc__tree__model_8cpp_source.html','')
67 return static_cast< int > (qMin(owner->
GetChildCount (),
static_cast< std::size_t
> (std::numeric_limits<int>::max())));
+
-
70 int DbcTreeModel::columnCount(
const QModelIndex &parentIndex)
const {
+
+
71 return parentIndex.isValid() && !Node(parentIndex) ? 0 : ColumnCount;
+
-
74 QVariant DbcTreeModel::data(
const QModelIndex &item,
int role)
const {
+
+
@@ -234,40 +245,54 @@ $(document).ready(function(){initNavTree('dbc__tree__model_8cpp_source.html','')
+
-
138 QVariant DbcTreeModel::headerData(
int section, Qt::Orientation orientation,
int role)
const {
+
+
139 static const char *
const headers[] = {
"Name" ,
"CAN ID" ,
"Payload (bytes)" ,
"Start bit" ,
"Length (bits)" ,
"Byte order" ,
"Signedness" ,
"Unit" ,
"Comment" };
140 if (orientation != Qt::Horizontal || role != Qt::DisplayRole || section < 0 || section >= ColumnCount)
142 return QString::fromLatin1(headers[section]);
+
-
145 Qt::ItemFlags DbcTreeModel::flags(
const QModelIndex &item)
const {
+
+
146 return Node(item) ? Qt::ItemIsEnabled | Qt::ItemIsSelectable : Qt::NoItemFlags;
-
Tree node for later use in model/view or other hierarchy consumers.
-
const SignalInfo * GetSignal() const
Get signal payload if node is signal.
-
const TreeNode * GetChild(std::size_t index) const
Get child by index.
-
const TreeNode * GetParent() const
-
const std::string & GetName() const
Get display name.
-
std::size_t GetChildCount() const
Get child count.
-
std::size_t GetRow() const
-
NodeType GetType() const
Get node type.
-
const FrameInfo * GetFrame() const
Get frame payload if node is frame.
-
ByteOrder
Signal byte order used for runtime decoding.
-
Describes one CAN frame from a DBC file.
-
-
-
-
-
Describes one signal inside a DBC frame.
-
-
-
ValueDescriptions valueDescriptions
-
-
-
-
+
+
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Return the child count, capped at the Qt integer limit.
+
int columnCount(const QModelIndex &parent=QModelIndex()) const override
Return the fixed metadata column count for this model.
+
DbcTreeModel(QObject *parent=nullptr)
Create an empty read-only model.
+
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Return a child index; only column zero can have children.
+
void SetTree(std::unique_ptr< TreeNode > root)
Replace the tree and invalidate indexes; reject roots with a parent or non-root type.
+
Qt::ItemFlags flags(const QModelIndex &index) const override
Allow selecting and enabling valid indexes without editing.
+
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
Return horizontal display column titles.
+
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Return display text or typed metadata for an index.
+
QModelIndex parent(const QModelIndex &child) const override
Return the parent in column zero, or an invalid index for frames.
+
Tree node for later use in model/view or other hierarchy consumers.
+
const SignalInfo * GetSignal() const
Get signal payload if node is signal.
+
const TreeNode * GetChild(std::size_t index) const
Get child by index.
+
const TreeNode * GetParent() const
+
const std::string & GetName() const
Get display name.
+
std::size_t GetChildCount() const
Get child count.
+
std::size_t GetRow() const
+
NodeType GetType() const
Get node type.
+
const FrameInfo * GetFrame() const
Get frame payload if node is frame.
+
ByteOrder
Signal byte order used for runtime decoding.
+
Describes one CAN frame from a DBC file.
+
+
+
+
+
Describes one signal inside a DBC frame.
+
+
+
ValueDescriptions valueDescriptions
+
+
+
+
diff --git a/docs/html/dbc__tree__model_8h_source.html b/docs/html/dbc__tree__model_8h_source.html
index a3390c4..13b31f7 100644
--- a/docs/html/dbc__tree__model_8h_source.html
+++ b/docs/html/dbc__tree__model_8h_source.html
@@ -108,49 +108,63 @@ $(document).ready(function(){initNavTree('dbc__tree__model_8h_source.html','');
-
-
-
-
-
-
-
-
-
-
-
-
24 enum Role { NodeTypeRole = Qt::UserRole + 1,
-
-
-
-
-
-
-
-
-
33 ValueDescriptionsRole,
-
-
-
-
37 void SetTree(std::unique_ptr<TreeNode> root);
-
38 QModelIndex index(
int row,
int column,
const QModelIndex &parent = QModelIndex())
const override ;
-
39 QModelIndex parent(
const QModelIndex &child)
const override ;
-
40 int rowCount(
const QModelIndex &parent = QModelIndex())
const override ;
-
41 int columnCount(
const QModelIndex &parent = QModelIndex())
const override ;
-
42 QVariant data(
const QModelIndex &index,
int role = Qt::DisplayRole)
const override ;
-
43 QVariant headerData(
int section, Qt::Orientation orientation,
int role = Qt::DisplayRole)
const override ;
-
44 Qt::ItemFlags flags(
const QModelIndex &index)
const override ;
-
-
-
47 const TreeNode *Node(
const QModelIndex &index)
const ;
-
48 std::unique_ptr<TreeNode> m_root;
-
+
-
+
+
+
26 enum Role { NodeTypeRole = Qt::UserRole + 1,
+
+
+
+
+
+
+
+
+
35 ValueDescriptionsRole,
+
+
+
+
+
41 void SetTree (std::unique_ptr<TreeNode> root);
+
43 QModelIndex
index (
int row,
int column,
const QModelIndex &
parent = QModelIndex())
const override ;
+
45 QModelIndex
parent (
const QModelIndex &child)
const override ;
+
47 int rowCount (
const QModelIndex &
parent = QModelIndex())
const override ;
+
+
51 QVariant
data (
const QModelIndex &
index ,
int role = Qt::DisplayRole)
const override ;
+
53 QVariant
headerData (
int section, Qt::Orientation orientation,
int role = Qt::DisplayRole)
const override ;
+
55 Qt::ItemFlags
flags (
const QModelIndex &
index )
const override ;
+
+
+
+
59 std::unique_ptr<TreeNode> m_root;
+
+
+
-Tree node for later use in model/view or other hierarchy consumers.
-ByteOrder
Signal byte order used for runtime decoding.
-Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+Role
Typed metadata roles in addition to Qt display roles.
+int rowCount(const QModelIndex &parent=QModelIndex()) const override
Return the child count, capped at the Qt integer limit.
+int columnCount(const QModelIndex &parent=QModelIndex()) const override
Return the fixed metadata column count for this model.
+Column
Display columns for frame and signal metadata.
+QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Return a child index; only column zero can have children.
+void SetTree(std::unique_ptr< TreeNode > root)
Replace the tree and invalidate indexes; reject roots with a parent or non-root type.
+Qt::ItemFlags flags(const QModelIndex &index) const override
Allow selecting and enabling valid indexes without editing.
+QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
Return horizontal display column titles.
+QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Return display text or typed metadata for an index.
+QModelIndex parent(const QModelIndex &child) const override
Return the parent in column zero, or an invalid index for frames.
+Tree node for later use in model/view or other hierarchy consumers.
+ByteOrder
Signal byte order used for runtime decoding.
+Qt-independent metadata tree nodes.
diff --git a/docs/html/dbc__tree__model__test_8cpp_source.html b/docs/html/dbc__tree__model__test_8cpp_source.html
index 86ccde7..a926825 100644
--- a/docs/html/dbc__tree__model__test_8cpp_source.html
+++ b/docs/html/dbc__tree__model__test_8cpp_source.html
@@ -143,168 +143,168 @@ $(document).ready(function(){initNavTree('dbc__tree__model__test_8cpp_source.htm
43 frame.signals.push_back(signal);
44 database.
frames .push_back(frame);
-
- 47 const QModelIndex parent = model.index(0, 0);
- 48 QCOMPARE(model.data(model.index(0, DbcTreeModel::ByteOrder, parent)).toString(), QString(
"Motorola" ));
- 49 QCOMPARE(model.data(model.index(0, DbcTreeModel::Signed, parent)).toString(), QString(
"Signed" ));
- 50 QCOMPARE(model.data(model.index(0, DbcTreeModel::CanId)).toString(), QString(
"0X18F00442" ));
+
+ 47 const QModelIndex parent = model.
index (0, 0);
+ 48 QCOMPARE(model.
data (model.
index (0, DbcTreeModel::ByteOrder, parent)).toString(), QString(
"Motorola" ));
+ 49 QCOMPARE(model.
data (model.
index (0, DbcTreeModel::Signed, parent)).toString(), QString(
"Signed" ));
+ 50 QCOMPARE(model.
data (model.
index (0, DbcTreeModel::CanId)).toString(), QString(
"0X18F00442" ));
51 const QStringList headers = {
"Name" ,
"CAN ID" ,
"Payload (bytes)" ,
"Start bit" ,
52 "Length (bits)" ,
"Byte order" ,
"Signedness" ,
"Unit" ,
"Comment" };
- 53 for (
int column = 0; column < model.columnCount(); ++column) {
- 54 const QModelIndex frameIndex = model.index(0, column);
- 55 const QModelIndex signalIndex = model.index(0, column, parent);
- 56 QCOMPARE(model.headerData(column, Qt::Horizontal).toString(), headers.at(column));
- 57 QVERIFY(!model.headerData(column, Qt::Horizontal, Qt::ToolTipRole).isValid());
- 58 QCOMPARE(model.data(frameIndex, Qt::ToolTipRole).toString(), QString(
"Frame tooltip" ));
- 59 QCOMPARE(model.data(signalIndex, Qt::ToolTipRole).toString(), QString(
"Signal tooltip" ));
- 60 QCOMPARE(model.data(frameIndex, DbcTreeModel::CommentRole).toString(), QString(
"Frame tooltip" ));
- 61 QCOMPARE(model.data(signalIndex, DbcTreeModel::CommentRole).toString(), QString(
"Signal tooltip" ));
- 62 QCOMPARE(model.data(frameIndex, DbcTreeModel::CanIdRole).toUInt(), frame.
canId );
- 63 QCOMPARE(model.data(frameIndex, DbcTreeModel::PayloadLengthRole).toInt(), 8);
- 64 QCOMPARE(model.data(frameIndex, DbcTreeModel::ExtendedRole).toBool(),
true );
- 65 QCOMPARE(model.data(signalIndex, DbcTreeModel::StartBitRole).toUInt(), 7U);
- 66 QCOMPARE(model.data(signalIndex, DbcTreeModel::BitLengthRole).toUInt(), 16U);
- 67 QCOMPARE(model.data(signalIndex, DbcTreeModel::LittleEndianRole).toBool(),
false );
- 68 QCOMPARE(model.data(signalIndex, DbcTreeModel::SignedRole).toBool(),
true );
- 69 QCOMPARE(model.data(signalIndex, DbcTreeModel::UnitRole).toString(), QString(
"rpm" ));
- 70 const QVariant descriptions = model.data(signalIndex, DbcTreeModel::ValueDescriptionsRole);
+ 53 for (
int column = 0; column < model.
columnCount (); ++column) {
+ 54 const QModelIndex frameIndex = model.
index (0, column);
+ 55 const QModelIndex signalIndex = model.
index (0, column, parent);
+ 56 QCOMPARE(model.
headerData (column, Qt::Horizontal).toString(), headers.at(column));
+ 57 QVERIFY(!model.
headerData (column, Qt::Horizontal, Qt::ToolTipRole).isValid());
+ 58 QCOMPARE(model.
data (frameIndex, Qt::ToolTipRole).toString(), QString(
"Frame tooltip" ));
+ 59 QCOMPARE(model.
data (signalIndex, Qt::ToolTipRole).toString(), QString(
"Signal tooltip" ));
+ 60 QCOMPARE(model.
data (frameIndex, DbcTreeModel::CommentRole).toString(), QString(
"Frame tooltip" ));
+ 61 QCOMPARE(model.
data (signalIndex, DbcTreeModel::CommentRole).toString(), QString(
"Signal tooltip" ));
+ 62 QCOMPARE(model.
data (frameIndex, DbcTreeModel::CanIdRole).toUInt(), frame.
canId );
+ 63 QCOMPARE(model.
data (frameIndex, DbcTreeModel::PayloadLengthRole).toInt(), 8);
+ 64 QCOMPARE(model.
data (frameIndex, DbcTreeModel::ExtendedRole).toBool(),
true );
+ 65 QCOMPARE(model.
data (signalIndex, DbcTreeModel::StartBitRole).toUInt(), 7U);
+ 66 QCOMPARE(model.
data (signalIndex, DbcTreeModel::BitLengthRole).toUInt(), 16U);
+ 67 QCOMPARE(model.
data (signalIndex, DbcTreeModel::LittleEndianRole).toBool(),
false );
+ 68 QCOMPARE(model.
data (signalIndex, DbcTreeModel::SignedRole).toBool(),
true );
+ 69 QCOMPARE(model.
data (signalIndex, DbcTreeModel::UnitRole).toString(), QString(
"rpm" ));
+ 70 const QVariant descriptions = model.
data (signalIndex, DbcTreeModel::ValueDescriptionsRole);
71 QVERIFY(descriptions.isValid());
72 QVERIFY(descriptions.toList().isEmpty());
- 73 QVERIFY(!model.data(frameIndex, Qt::UserRole + 1000).isValid());
- 74 QVERIFY(!model.data(signalIndex, Qt::UserRole + 1000).isValid());
+ 73 QVERIFY(!model.
data (frameIndex, Qt::UserRole + 1000).isValid());
+ 74 QVERIFY(!model.
data (signalIndex, Qt::UserRole + 1000).isValid());
75 QVERIFY(!model.setData(frameIndex,
"Changed" , Qt::EditRole));
76 QVERIFY(!model.setData(signalIndex,
"Changed" , Qt::EditRole));
- 78 QCOMPARE(model.data(parent).toString(), QString(
"Extended" ));
- 79 QCOMPARE(model.data(model.index(0, 0, parent)).toString(), QString(
"SignedMotorola" ));
+ 78 QCOMPARE(model.
data (parent).toString(), QString(
"Extended" ));
+ 79 QCOMPARE(model.
data (model.
index (0, 0, parent)).toString(), QString(
"SignedMotorola" ));
81 void emptyRootAndRejectedReplacement() {
83 QAbstractItemModelTester tester(&model, QAbstractItemModelTester::FailureReportingMode::QtTest);
- 84 model.SetTree(ParsedTree());
- 85 QPersistentModelIndex retained(model.index(0, 0));
+
+ 85 QPersistentModelIndex retained(model.
index (0, 0));
86 QSignalSpy resets(&model, &QAbstractItemModel::modelReset);
- 87 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, model.SetTree(std::make_unique<TreeNode>(
SignalInfo ())));
+ 87 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, model.
SetTree (std::make_unique<TreeNode>(
SignalInfo ())));
88 QCOMPARE(resets.count(), 0);
89 QVERIFY(retained.isValid());
- 90 QCOMPARE(model.rowCount(), 2);
-
+
+
92 QCOMPARE(resets.count(), 1);
93 QVERIFY(!retained.isValid());
- 94 QCOMPARE(model.rowCount(), 0);
- 95 QVERIFY(!model.index(0, 0).isValid());
+
+ 95 QVERIFY(!model.
index (0, 0).isValid());
99 QAbstractItemModelTester tester(&model, QAbstractItemModelTester::FailureReportingMode::QtTest);
- 100 QCOMPARE(model.rowCount(), 0);
- 101 model.SetTree(ParsedTree());
- 102 QCOMPARE(model.rowCount(), 2);
- 103 for (
int row = 0; row < model.rowCount(); ++row) {
- 104 const QModelIndex frame = model.index(row, 0);
- 105 for (
int column = 0; column < model.columnCount(); ++column) {
- 106 const QModelIndex frameColumn = model.index(row, column);
- 107 QVERIFY(!model.parent(frameColumn).isValid());
- 108 QCOMPARE(model.rowCount(frameColumn), column == 0 ? (row == 0 ? 2 : 1) : 0);
- 109 for (
int signalRow = 0; signalRow < model.rowCount(frame); ++signalRow) {
- 110 const QModelIndex signal = model.index(signalRow, column, frame);
- 111 QCOMPARE(model.parent(signal), frame);
- 112 QCOMPARE(model.rowCount(signal), 0);
- 113 QVERIFY(!model.index(0, 0, signal).isValid());
- 114 QCOMPARE(model.flags(signal), Qt::ItemIsEnabled | Qt::ItemIsSelectable);
+
+
+
+ 103 for (
int row = 0; row < model.
rowCount (); ++row) {
+ 104 const QModelIndex frame = model.
index (row, 0);
+ 105 for (
int column = 0; column < model.
columnCount (); ++column) {
+ 106 const QModelIndex frameColumn = model.
index (row, column);
+ 107 QVERIFY(!model.
parent (frameColumn).isValid());
+ 108 QCOMPARE(model.
rowCount (frameColumn), column == 0 ? (row == 0 ? 2 : 1) : 0);
+ 109 for (
int signalRow = 0; signalRow < model.
rowCount (frame); ++signalRow) {
+ 110 const QModelIndex signal = model.
index (signalRow, column, frame);
+ 111 QCOMPARE(model.
parent (signal), frame);
+ 112 QCOMPARE(model.
rowCount (signal), 0);
+ 113 QVERIFY(!model.
index (0, 0, signal).isValid());
+ 114 QCOMPARE(model.
flags (signal), Qt::ItemIsEnabled | Qt::ItemIsSelectable);
- 118 QVERIFY(!model.index(-1, 0).isValid());
- 119 QVERIFY(!model.index(2, 0).isValid());
- 120 QVERIFY(!model.index(0, -1).isValid());
- 121 QVERIFY(!model.index(0, model.columnCount()).isValid());
- 122 QVERIFY(!model.index(0, 0, model.index(0, 1)).isValid());
- 123 QVERIFY(!model.parent({}).isValid());
- 124 QVERIFY(!model.data({}).isValid());
- 125 QCOMPARE(model.flags({}), Qt::NoItemFlags);
+ 118 QVERIFY(!model.
index (-1, 0).isValid());
+ 119 QVERIFY(!model.
index (2, 0).isValid());
+ 120 QVERIFY(!model.
index (0, -1).isValid());
+
+ 122 QVERIFY(!model.
index (0, 0, model.
index (0, 1)).isValid());
+ 123 QVERIFY(!model.
parent ({}).isValid());
+ 124 QVERIFY(!model.
data ({}).isValid());
+ 125 QCOMPARE(model.
flags ({}), Qt::NoItemFlags);
- 127 other.SetTree(ParsedTree());
- 128 const QModelIndex foreign = other.index(0, 0);
- 129 QVERIFY(!model.index(0, 0, foreign).isValid());
- 130 QVERIFY(!model.parent(foreign).isValid());
- 131 QCOMPARE(model.rowCount(foreign), 0);
- 132 QCOMPARE(model.columnCount(foreign), 0);
- 133 QVERIFY(!model.data(foreign).isValid());
- 134 QCOMPARE(model.flags(foreign), Qt::NoItemFlags);
+
+ 128 const QModelIndex foreign = other.
index (0, 0);
+ 129 QVERIFY(!model.
index (0, 0, foreign).isValid());
+ 130 QVERIFY(!model.
parent (foreign).isValid());
+ 131 QCOMPARE(model.
rowCount (foreign), 0);
+
+ 133 QVERIFY(!model.
data (foreign).isValid());
+ 134 QCOMPARE(model.
flags (foreign), Qt::NoItemFlags);
- 138 model.SetTree(ParsedTree());
- 139 const QModelIndex frame = model.index(0, 0);
- 140 const QModelIndex signal = model.index(0, 0, frame);
- 141 QCOMPARE(model.data(frame).toString(), QString(
"Status" ));
- 142 QCOMPARE(model.data(model.index(0, DbcTreeModel::CanId)).toString(), QString(
"0X100" ));
- 143 QCOMPARE(model.data(frame, DbcTreeModel::CanIdRole).toUInt(), 256U);
- 144 QCOMPARE(model.data(frame, DbcTreeModel::PayloadLengthRole).toInt(), 8);
- 145 QCOMPARE(model.data(signal, DbcTreeModel::UnitRole).toString(), QString(
"rpm" ));
+
+ 139 const QModelIndex frame = model.
index (0, 0);
+ 140 const QModelIndex signal = model.
index (0, 0, frame);
+ 141 QCOMPARE(model.
data (frame).toString(), QString(
"Status" ));
+ 142 QCOMPARE(model.
data (model.
index (0, DbcTreeModel::CanId)).toString(), QString(
"0X100" ));
+ 143 QCOMPARE(model.
data (frame, DbcTreeModel::CanIdRole).toUInt(), 256U);
+ 144 QCOMPARE(model.
data (frame, DbcTreeModel::PayloadLengthRole).toInt(), 8);
+ 145 QCOMPARE(model.
data (signal, DbcTreeModel::UnitRole).toString(), QString(
"rpm" ));
146 const QVariantList expectedSignal = {
"State" , QVariant(), QVariant(), 0U, 8U,
147 "Intel" ,
"Unsigned" ,
"rpm" ,
"Signal comment" };
148 const QVariantList expectedFrame = {
"Status" ,
"0X100" , 8, QVariant(), QVariant(),
149 QVariant(), QVariant(), QVariant(),
"Frame comment" };
- 150 for (
int column = 0; column < model.columnCount(); ++column) {
- 151 QCOMPARE(model.data(model.index(0, column, frame)), expectedSignal.at(column));
- 152 QCOMPARE(model.data(model.index(0, column)), expectedFrame.at(column));
+ 150 for (
int column = 0; column < model.
columnCount (); ++column) {
+ 151 QCOMPARE(model.
data (model.
index (0, column, frame)), expectedSignal.at(column));
+ 152 QCOMPARE(model.
data (model.
index (0, column)), expectedFrame.at(column));
- 154 QCOMPARE(model.data(frame, DbcTreeModel::NodeTypeRole).toInt(),
static_cast< int > (NodeType::Frame));
- 155 QCOMPARE(model.data(signal, DbcTreeModel::NodeTypeRole).toInt(),
static_cast< int > (NodeType::Signal));
- 156 QCOMPARE(model.data(frame, DbcTreeModel::ExtendedRole).toBool(),
false );
- 157 QVERIFY(!model.data(frame, DbcTreeModel::ValueDescriptionsRole).isValid());
- 158 QVERIFY(model.data(model.index(1, 0, frame), DbcTreeModel::ValueDescriptionsRole).toList().isEmpty());
+ 154 QCOMPARE(model.
data (frame, DbcTreeModel::NodeTypeRole).toInt(),
static_cast< int > (NodeType::Frame));
+ 155 QCOMPARE(model.
data (signal, DbcTreeModel::NodeTypeRole).toInt(),
static_cast< int > (NodeType::Signal));
+ 156 QCOMPARE(model.
data (frame, DbcTreeModel::ExtendedRole).toBool(),
false );
+ 157 QVERIFY(!model.
data (frame, DbcTreeModel::ValueDescriptionsRole).isValid());
+ 158 QVERIFY(model.
data (model.
index (1, 0, frame), DbcTreeModel::ValueDescriptionsRole).toList().isEmpty());
- 160 QCOMPARE(model.data(signal, Qt::ToolTipRole).toString(), QString(
"Signal comment" ));
- 161 QCOMPARE(model.data(signal, DbcTreeModel::StartBitRole).toUInt(), 0U);
- 162 QCOMPARE(model.data(signal, DbcTreeModel::BitLengthRole).toUInt(), 8U);
- 163 QCOMPARE(model.data(signal, DbcTreeModel::LittleEndianRole).toBool(),
true );
- 164 QCOMPARE(model.data(signal, DbcTreeModel::SignedRole).toBool(),
false );
- 165 QVERIFY(!model.data(signal, DbcTreeModel::CanIdRole).isValid());
- 166 QVERIFY(!model.data(frame, DbcTreeModel::UnitRole).isValid());
- 167 QVERIFY(!model.data(frame, Qt::EditRole).isValid());
- 168 const QVariantList values = model.data(signal, DbcTreeModel::ValueDescriptionsRole).toList();
+ 160 QCOMPARE(model.
data (signal, Qt::ToolTipRole).toString(), QString(
"Signal comment" ));
+ 161 QCOMPARE(model.
data (signal, DbcTreeModel::StartBitRole).toUInt(), 0U);
+ 162 QCOMPARE(model.
data (signal, DbcTreeModel::BitLengthRole).toUInt(), 8U);
+ 163 QCOMPARE(model.
data (signal, DbcTreeModel::LittleEndianRole).toBool(),
true );
+ 164 QCOMPARE(model.
data (signal, DbcTreeModel::SignedRole).toBool(),
false );
+ 165 QVERIFY(!model.
data (signal, DbcTreeModel::CanIdRole).isValid());
+ 166 QVERIFY(!model.
data (frame, DbcTreeModel::UnitRole).isValid());
+ 167 QVERIFY(!model.
data (frame, Qt::EditRole).isValid());
+ 168 const QVariantList values = model.
data (signal, DbcTreeModel::ValueDescriptionsRole).toList();
169 QCOMPARE(values.size(), 3);
170 QCOMPARE(values.at(0).toMap().value(
"value" ).toLongLong(), -1LL);
171 QCOMPARE(values.at(2).toMap().value(
"value" ).toULongLong(), std::numeric_limits<qulonglong>::max());
172 QCOMPARE(values.at(2).toMap().value(
"description" ).toString(), QString(
"Maximum" ));
- 173 for (
int column = 0; column < model.columnCount(); ++column) {
- 174 QVERIFY(model.headerData(column, Qt::Horizontal).isValid());
- 175 QCOMPARE(model.data(model.index(0, column, frame), DbcTreeModel::ValueDescriptionsRole), QVariant(values));
+ 173 for (
int column = 0; column < model.
columnCount (); ++column) {
+ 174 QVERIFY(model.
headerData (column, Qt::Horizontal).isValid());
+ 175 QCOMPARE(model.
data (model.
index (0, column, frame), DbcTreeModel::ValueDescriptionsRole), QVariant(values));
- 177 QVERIFY(!model.headerData(-1, Qt::Horizontal).isValid());
- 178 QVERIFY(!model.headerData(model.columnCount(), Qt::Horizontal).isValid());
- 179 QVERIFY(!model.headerData(0, Qt::Vertical).isValid());
+ 177 QVERIFY(!model.
headerData (-1, Qt::Horizontal).isValid());
+
+ 179 QVERIFY(!model.
headerData (0, Qt::Vertical).isValid());
183 QAbstractItemModelTester tester(&model, QAbstractItemModelTester::FailureReportingMode::QtTest);
184 QSignalSpy resets(&model, &QAbstractItemModel::modelReset);
- 185 model.SetTree(ParsedTree());
- 186 QPersistentModelIndex frame(model.index(0, 0));
- 187 QPersistentModelIndex signal(model.index(0, 4, frame));
- 188 model.SetTree(ParsedTree());
+
+ 186 QPersistentModelIndex frame(model.
index (0, 0));
+ 187 QPersistentModelIndex signal(model.
index (0, 4, frame));
+
189 QVERIFY(!frame.isValid());
190 QVERIFY(!signal.isValid());
- 191 QCOMPARE(model.rowCount(), 2);
- 192 QPersistentModelIndex replacement(model.index(1, 0));
- 193 model.SetTree(
nullptr );
+
+ 192 QPersistentModelIndex replacement(model.
index (1, 0));
+
194 QVERIFY(!replacement.isValid());
- 195 QCOMPARE(model.rowCount(), 0);
- 196 QVERIFY(!model.index(0, 0).isValid());
- 197 model.SetTree(
nullptr );
+
+ 196 QVERIFY(!model.
index (0, 0).isValid());
+
198 QCOMPARE(resets.count(), 4);
-
+
201 QFAIL(
"A frame cannot be the invisible model root" );
202 }
catch (
const std::invalid_argument &) {
204 QCOMPARE(resets.count(), 4);
- 207 int main(
int argc,
char **argv) {
+ 207 int main (
int argc,
char **argv) {
209 if (qEnvironmentVariableIsEmpty(
"QT_QPA_PLATFORM" ))
210 qputenv(
"QT_QPA_PLATFORM" ,
"offscreen" );
@@ -313,29 +313,38 @@ $(document).ready(function(){initNavTree('dbc__tree__model__test_8cpp_source.htm
213 return QTest::qExec(&tests, argc, argv);
215 #include "dbc_tree_model_test.moc"
-
+
Builds a simple tree from parsed DBC database.
std::unique_ptr< TreeNode > Build(const DbcDatabase &database) const
Build tree representation of parsed DBC data.
-Tree node for later use in model/view or other hierarchy consumers.
-Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
-Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+int rowCount(const QModelIndex &parent=QModelIndex()) const override
Return the child count, capped at the Qt integer limit.
+int columnCount(const QModelIndex &parent=QModelIndex()) const override
Return the fixed metadata column count for this model.
+QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Return a child index; only column zero can have children.
+void SetTree(std::unique_ptr< TreeNode > root)
Replace the tree and invalidate indexes; reject roots with a parent or non-root type.
+Qt::ItemFlags flags(const QModelIndex &index) const override
Allow selecting and enabling valid indexes without editing.
+QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
Return horizontal display column titles.
+QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Return display text or typed metadata for an index.
+QModelIndex parent(const QModelIndex &child) const override
Return the parent in column zero, or an invalid index for frames.
+Tree node for later use in model/view or other hierarchy consumers.
+DBC file parser and interpretation options.
+
+int main(int argc, char *argv[])
Parse a DBC file and demonstrate metadata lookup and CAN decoding.
Parsed DBC content stored in a simple internal form.
std::vector< FrameInfo > frames
-Describes one CAN frame from a DBC file.
-
-
-
-
-
-Describes one signal inside a DBC frame.
-
-
-
-
-
-
-
+Describes one CAN frame from a DBC file.
+
+
+
+
+
+Describes one signal inside a DBC frame.
+
+
+
+
+
+
+
diff --git a/docs/html/dbc__validation__test_8cpp_source.html b/docs/html/dbc__validation__test_8cpp_source.html
index d2c978f..5a5dd96 100644
--- a/docs/html/dbc__validation__test_8cpp_source.html
+++ b/docs/html/dbc__validation__test_8cpp_source.html
@@ -101,398 +101,462 @@ $(document).ready(function(){initNavTree('dbc__validation__test_8cpp_source.html
-
-
-
-
-
-
-
-
-
-
-
-
15 signal.
name =
"Value" ;
-
-
17 frame.signals.push_back(signal);
-
-
-
-
21 DbcDatabase ParsedDefinitions(
const std::vector<DecodeFrame> &frames) {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
39 copy.multiplexing = signal.multiplexing;
-
40 target.signals.push_back(copy);
-
-
42 database.
frames .push_back(target);
-
-
-
-
-
-
48 class DbcValidationTest :
public QObject {
-
-
-
51 void invalidMetadata_data();
-
52 void invalidMetadata();
-
53 void numericParameters_data();
-
54 void numericParameters();
-
55 void validBoundaries();
-
56 void multiplexingBoundaries();
-
57 void independentSnapshot();
-
58 void failedReplacement();
-
-
-
61 void DbcValidationTest::invalidMetadata_data() {
-
62 QTest::addColumn<int>(
"kind" );
-
63 QTest::newRow(
"standard-id" ) << 0;
-
64 QTest::newRow(
"extended-id" ) << 1;
-
65 QTest::newRow(
"encoded-id" ) << 2;
-
66 QTest::newRow(
"duplicate-frame" ) << 3;
-
67 QTest::newRow(
"duplicate-signal" ) << 4;
-
68 QTest::newRow(
"zero-length" ) << 5;
-
69 QTest::newRow(
"65-bits" ) << 6;
-
70 QTest::newRow(
"length-overflow" ) << 7;
-
71 QTest::newRow(
"intel-start-overflow" ) << 8;
-
72 QTest::newRow(
"motorola-start-overflow" ) << 9;
-
73 QTest::newRow(
"intel-outside-payload" ) << 10;
-
74 QTest::newRow(
"motorola-outside-payload" ) << 11;
-
75 QTest::newRow(
"zero-payload" ) << 12;
-
76 QTest::newRow(
"inverted-range" ) << 13;
-
77 QTest::newRow(
"byte-order" ) << 14;
-
78 QTest::newRow(
"value-type" ) << 15;
-
79 QTest::newRow(
"multiplex-role" ) << 16;
-
80 QTest::newRow(
"missing-selector" ) << 17;
-
81 QTest::newRow(
"signed-selector" ) << 18;
-
82 QTest::newRow(
"two-selectors" ) << 19;
-
83 QTest::newRow(
"branch-range" ) << 20;
-
84 QTest::newRow(
"unconditional-overlap" ) << 21;
-
85 QTest::newRow(
"mixed-order-overlap" ) << 22;
-
86 QTest::newRow(
"same-branch-overlap" ) << 23;
-
87 QTest::newRow(
"selector-branch-overlap" ) << 24;
-
88 QTest::newRow(
"maximum-can-id" ) << 25;
-
-
-
91 void DbcValidationTest::invalidMetadata() {
-
-
93 std::vector<DecodeFrame> frames = {ValidFrame()};
-
-
-
-
-
-
-
100 frame.
canId = 0x800U;
-
-
-
-
104 frame.
canId = 0x20000000U;
-
-
-
-
108 frame.
canId = 0x80000123U;
-
-
-
111 frames.push_back(frame);
+
4 #include "signal_layout.h"
+
+
+
+
+
+
+
+
+
+
+
+
16 signal.
name =
"Value" ;
+
+
18 frame.signals.push_back(signal);
+
+
+
+
22 DbcDatabase ParsedDefinitions(
const std::vector<DecodeFrame> &frames) {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
41 target.signals.push_back(copy);
+
+
43 database.
frames .push_back(target);
+
+
+
+
+
+
49 class DbcValidationTest :
public QObject {
+
+
+
52 void invalidMetadata_data();
+
53 void invalidMetadata();
+
54 void numericParameters_data();
+
55 void numericParameters();
+
56 void validBoundaries();
+
57 void layoutBoundaries();
+
58 void builderSnapshot();
+
59 void multiplexingBoundaries();
+
60 void independentSnapshot();
+
61 void failedReplacement();
+
+
+
64 void DbcValidationTest::invalidMetadata_data() {
+
65 QTest::addColumn<int>(
"kind" );
+
66 QTest::newRow(
"standard-id" ) << 0;
+
67 QTest::newRow(
"extended-id" ) << 1;
+
68 QTest::newRow(
"encoded-id" ) << 2;
+
69 QTest::newRow(
"duplicate-frame" ) << 3;
+
70 QTest::newRow(
"duplicate-signal" ) << 4;
+
71 QTest::newRow(
"zero-length" ) << 5;
+
72 QTest::newRow(
"65-bits" ) << 6;
+
73 QTest::newRow(
"length-overflow" ) << 7;
+
74 QTest::newRow(
"intel-start-overflow" ) << 8;
+
75 QTest::newRow(
"motorola-start-overflow" ) << 9;
+
76 QTest::newRow(
"intel-outside-payload" ) << 10;
+
77 QTest::newRow(
"motorola-outside-payload" ) << 11;
+
78 QTest::newRow(
"zero-payload" ) << 12;
+
79 QTest::newRow(
"inverted-range" ) << 13;
+
80 QTest::newRow(
"byte-order" ) << 14;
+
81 QTest::newRow(
"value-type" ) << 15;
+
82 QTest::newRow(
"multiplex-role" ) << 16;
+
83 QTest::newRow(
"missing-selector" ) << 17;
+
84 QTest::newRow(
"signed-selector" ) << 18;
+
85 QTest::newRow(
"two-selectors" ) << 19;
+
86 QTest::newRow(
"branch-range" ) << 20;
+
87 QTest::newRow(
"unconditional-overlap" ) << 21;
+
88 QTest::newRow(
"mixed-order-overlap" ) << 22;
+
89 QTest::newRow(
"same-branch-overlap" ) << 23;
+
90 QTest::newRow(
"selector-branch-overlap" ) << 24;
+
91 QTest::newRow(
"maximum-can-id" ) << 25;
+
+
+
94 void DbcValidationTest::invalidMetadata() {
+
+
96 std::vector<DecodeFrame> frames = {ValidFrame()};
+
+
+
+
100 other.
name =
"Other" ;
+
+
+
103 frame.
canId = 0x800U;
+
+
+
+
107 frame.
canId = 0x20000000U;
+
+
+
+
111 frame.
canId = 0x80000123U;
-
-
114 frame.signals.push_back(signal);
+
+
114 frames.push_back(frame);
-
-
+
+
117 frame.signals.push_back(signal);
-
-
+
+
-
-
123 signal.
length = std::numeric_limits<std::uint32_t>::max();
+
+
-
-
126 signal.
startBit = std::numeric_limits<std::uint32_t>::max();
+
+
126 signal.
length = std::numeric_limits<std::uint32_t>::max();
-
-
-
130 signal.
startBit = std::numeric_limits<std::uint32_t>::max();
-
-
-
+
+
129 signal.
startBit = std::numeric_limits<std::uint32_t>::max();
+
+
+
+
133 signal.
startBit = std::numeric_limits<std::uint32_t>::max();
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+
-
-
153 signal.multiplexing.role =
static_cast< MultiplexRole
> (99);
+
+
-
-
156 signal.multiplexing.role = MultiplexRole::Branch;
+
+
-
-
159 signal.multiplexing.role = MultiplexRole::Selector;
-
-
-
-
163 signal.multiplexing.role = MultiplexRole::Selector;
-
164 other.multiplexing.role = MultiplexRole::Selector;
-
-
166 frame.signals.push_back(other);
-
-
-
-
-
171 signal.multiplexing.role = MultiplexRole::Selector;
-
172 other.multiplexing.role = MultiplexRole::Branch;
-
173 other.
startBit = kind == 24 ? 0U : 8U;
-
174 other.multiplexing.value = kind == 20 ? 256U : 1U;
-
175 frame.signals.push_back(other);
-
-
177 other.
name =
"Third" ;
-
178 frame.signals.push_back(other);
-
-
-
-
182 frame.signals.push_back(other);
+
+
+
+
+
+
+
+
+
+
+
+
169 frame.signals.push_back(other);
+
+
+
+
+
+
+
176 other.
startBit = kind == 24 ? 0U : 8U;
+
+
178 frame.signals.push_back(other);
+
+
180 other.
name =
"Third" ;
+
181 frame.signals.push_back(other);
+
-
-
-
-
187 frame.signals.push_back(other);
-
-
-
190 frame.
canId = std::numeric_limits<std::uint32_t>::max();
+
+
185 frame.signals.push_back(other);
+
+
+
+
+
190 frame.signals.push_back(other);
-
-
193 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (
void )
DecodeDatabase (frames));
-
-
-
196 if (kind != 14 && kind != 15)
-
197 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (
void )
DbcDecodeBuilder ().Build(ParsedDefinitions(frames)));
-
-
-
200 void DbcValidationTest::numericParameters_data() {
-
201 QTest::addColumn<int>(
"field" );
-
202 QTest::addColumn<double>(
"value" );
-
203 const double values[] = {std::numeric_limits<double>::quiet_NaN(),
-
204 std::numeric_limits<double>::infinity(),
-
205 -std::numeric_limits<double>::infinity()};
-
206 for (
int field = 0; field < 4; ++field) {
-
207 for (
int index = 0; index < 3; ++index) {
-
208 const QByteArray name = QByteArray::number(field) +
"-" + QByteArray::number(index);
-
209 QTest::newRow(name.constData()) << field << values[index];
-
-
-
-
-
214 void DbcValidationTest::numericParameters() {
-
-
216 QFETCH(
double , value);
-
-
-
-
-
-
-
-
+
+
193 frame.
canId = std::numeric_limits<std::uint32_t>::max();
+
+
+
196 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (
void )
DecodeDatabase (frames));
+
+
+
199 if (kind != 14 && kind != 15)
+
200 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (
void )
DbcDecodeBuilder ().Build(ParsedDefinitions(frames)));
+
+
+
203 void DbcValidationTest::numericParameters_data() {
+
204 QTest::addColumn<int>(
"field" );
+
205 QTest::addColumn<double>(
"value" );
+
206 const double values[] = {std::numeric_limits<double>::quiet_NaN(),
+
207 std::numeric_limits<double>::infinity(),
+
208 -std::numeric_limits<double>::infinity()};
+
209 for (
int field = 0; field < 4; ++field) {
+
210 for (
int index = 0; index < 3; ++index) {
+
211 const QByteArray name = QByteArray::number(field) +
"-" + QByteArray::number(index);
+
212 QTest::newRow(name.constData()) << field << values[index];
+
+
+
+
+
217 void DbcValidationTest::numericParameters() {
+
+
219 QFETCH(
double , value);
+
+
+
+
+
-
-
+
+
-
-
+
+
-
-
233 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (
void )
DecodeDatabase ({frame}));
-
234 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (
void )
DbcDecodeBuilder ().Build(ParsedDefinitions({frame})));
-
-
-
237 void DbcValidationTest::validBoundaries() {
-
238 for (
ByteOrder order: {ByteOrder::Intel, ByteOrder::Motorola}) {
-
239 for (std::uint8_t dlc: {std::uint8_t(8U), std::uint8_t(64U), std::uint8_t(255U)}) {
-
-
241 standard.
canId = 0x7FFU;
-
-
-
-
245 signal.
startBit = (std::uint32_t(dlc) - 8U) * 8U + (order == ByteOrder::Intel ? 0U : 7U);
-
-
-
248 signal.
offset = std::numeric_limits<double>::max();
-
249 signal.
minimum = -std::numeric_limits<double>::max();
-
250 signal.
maximum = std::numeric_limits<double>::max();
-
-
-
-
254 maximum.
canId = 0x1FFFFFFFU;
-
255 const std::vector<DecodeFrame> frames = {standard, extended, maximum};
-
-
-
-
259 QVERIFY(direct.FindFrame(frame.GetKey()));
-
260 QVERIFY(built.FindSignal(
SignalKey (frame.GetKey(),
"Value" )));
-
-
-
-
-
-
-
-
-
-
270 void DbcValidationTest::multiplexingBoundaries() {
-
-
-
-
-
275 selector.multiplexing.role = MultiplexRole::Selector;
-
-
277 first.
name =
"First" ;
-
-
-
280 first.multiplexing.role = MultiplexRole::Branch;
-
281 first.multiplexing.value = std::numeric_limits<std::uint64_t>::max();
-
-
283 second.
name =
"Second" ;
-
-
-
286 second.multiplexing.value = 0U;
-
287 frame.signals.push_back(first);
-
288 frame.signals.push_back(second);
-
-
-
-
-
293 raw.
data .assign(9U, 255U);
-
-
-
296 QCOMPARE(result.signals[1].
status , SignalDecodeStatus::Valid);
-
297 QCOMPARE(result.signals[2].
status , SignalDecodeStatus::Inactive);
+
+
+
+
+
236 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (
void )
DecodeDatabase ({frame}));
+
237 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (
void )
DbcDecodeBuilder ().Build(ParsedDefinitions({frame})));
+
+
+
240 void DbcValidationTest::validBoundaries() {
+
241 for (
ByteOrder order: {ByteOrder::Intel, ByteOrder::Motorola}) {
+
242 for (std::uint8_t dlc: {std::uint8_t(8U), std::uint8_t(64U), std::uint8_t(255U)}) {
+
+
244 standard.
canId = 0x7FFU;
+
+
+
+
248 signal.
startBit = (std::uint32_t(dlc) - 8U) * 8U + (order == ByteOrder::Intel ? 0U : 7U);
+
+
+
251 signal.
offset = std::numeric_limits<double>::max();
+
252 signal.
minimum = -std::numeric_limits<double>::max();
+
253 signal.
maximum = std::numeric_limits<double>::max();
+
+
+
+
257 maximum.
canId = 0x1FFFFFFFU;
+
258 const std::vector<DecodeFrame> frames = {standard, extended, maximum};
+
+
+
+
262 QVERIFY(direct.FindFrame(frame.
GetKey ()));
+
+
+
+
+
+
+
+
+
+
+
273 void DbcValidationTest::layoutBoundaries() {
+
+
275 for (
const std::uint8_t dlc: {std::uint8_t(0U), std::uint8_t(1U), std::uint8_t(8U),
+
276 std::uint8_t(64U), std::uint8_t(255U)}) {
+
277 const std::uint64_t payloadBits = std::uint64_t(dlc) * 8U;
+
278 for (
const bool littleEndian: {
true ,
false }) {
+
279 for (std::uint32_t start = 0U; start < payloadBits + 8U; ++start) {
+
280 std::uint64_t bit = start;
+
+
282 QVERIFY(!IsValidSignalLayout(start, 0U, littleEndian, dlc));
+
283 for (std::uint32_t length = 1U; length <= 64U; ++length) {
+
284 fits = fits && bit < payloadBits;
+
285 QCOMPARE(IsValidSignalLayout(start, length, littleEndian, dlc), fits);
+
+
+
+
289 bit = bit % 8U == 0U ? bit + 15U : bit - 1U;
+
+
291 QVERIFY(!IsValidSignalLayout(start, 65U, littleEndian, dlc));
+
+
293 const std::uint32_t maximum = std::numeric_limits<std::uint32_t>::max();
+
294 QVERIFY(!IsValidSignalLayout(maximum, 1U, littleEndian, dlc));
+
295 QVERIFY(!IsValidSignalLayout(maximum, maximum, littleEndian, dlc));
+
296 QVERIFY(!IsValidSignalLayout(0U, maximum, littleEndian, dlc));
+
-
301 void DbcValidationTest::independentSnapshot() {
-
302 std::vector<DecodeFrame> frames = {ValidFrame()};
-
-
-
-
-
307 const FrameKey key = alias.GetKey();
-
-
-
310 signalAlias.
name =
"Changed" ;
-
311 signalAlias.
startBit = std::numeric_limits<std::uint32_t>::max();
-
312 descriptionAlias =
"Changed" ;
-
313 const std::shared_ptr<const DecodeFrame> saved = database.FindFrame(key);
-
-
315 QCOMPARE(saved->canId, key.canId);
-
316 QVERIFY(!database.FindFrame(
FrameKey (456U,
false )));
-
317 const std::shared_ptr<const DecodeSignal> signal = database.FindSignal(
SignalKey (key,
"Value" ));
-
-
319 QCOMPARE(signal->startBit, 0U);
-
320 QCOMPARE(signal->valueDescriptions.begin()->second, std::string(
"One" ));
-
-
-
323 void DbcValidationTest::failedReplacement() {
-
-
-
326 const std::shared_ptr<const DecodeFrame> original = database.FindFrame(valid.GetKey());
-
-
328 invalid.
canId = 0x800U;
-
329 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, database =
DecodeDatabase ({invalid}));
-
330 QCOMPARE(database.FindFrame(valid.GetKey()).get(), original.get());
-
-
332 invalid.signals[0].factor = std::numeric_limits<double>::infinity();
-
333 QVERIFY_THROWS_EXCEPTION(std::invalid_argument,
-
-
335 QCOMPARE(database.FindFrame(valid.GetKey()).get(), original.get());
-
336 QCOMPARE(database.GetFrames().size(), std::size_t(1U));
-
-
338 QVERIFY(database.GetFrames().empty());
-
339 QVERIFY(!database.FindFrame(valid.GetKey()));
-
-
-
-
343 int RunValidationTests(
int argc,
char **argv) {
-
344 DbcValidationTest tests;
-
345 return QTest::qExec(&tests, argc, argv);
+
301 void DbcValidationTest::builderSnapshot() {
+
302 DbcDatabase source = ParsedDefinitions({ValidFrame()});
+
303 source.
frames [0].signals[0].valueDescriptions.emplace(std::uint64_t(1U),
"One" );
+
+
+
306 source.
frames [0].canId = 0x800U;
+
307 source.
frames [0].signals[0].name =
"Changed" ;
+
308 source.
frames [0].signals[0].valueDescriptions.begin()->second =
"Changed" ;
+
+
310 const std::shared_ptr<const DecodeSignal> signal = database.
FindSignal (
SignalKey (key,
"Value" ));
+
+
312 QCOMPARE(signal->valueDescriptions.begin()->second, std::string(
"One" ));
+
+
+
+
+
317 void DbcValidationTest::multiplexingBoundaries() {
+
+
+
+
+
+
+
324 first.
name =
"First" ;
+
+
+
+
+
+
330 second.
name =
"Second" ;
+
+
+
+
334 frame.signals.push_back(first);
+
335 frame.signals.push_back(second);
+
+
+
+
+
340 raw.
data .assign(9U, 255U);
+
+
+
343 QCOMPARE(result.signals[1].
status , SignalDecodeStatus::Valid);
+
344 QCOMPARE(result.signals[2].
status , SignalDecodeStatus::Inactive);
+
-
348 #include "dbc_validation_test.moc"
+
348 void DbcValidationTest::independentSnapshot() {
+
349 std::vector<DecodeFrame> frames = {ValidFrame()};
+
+
+
+
+
+
+
+
357 signalAlias.
name =
"Changed" ;
+
358 signalAlias.
startBit = std::numeric_limits<std::uint32_t>::max();
+
359 descriptionAlias =
"Changed" ;
+
360 const std::shared_ptr<const DecodeFrame> saved = database.
FindFrame (key);
+
+
362 QCOMPARE(saved->canId, key.
canId );
+
+
364 const std::shared_ptr<const DecodeSignal> signal = database.
FindSignal (
SignalKey (key,
"Value" ));
+
+
366 QCOMPARE(signal->startBit, 0U);
+
367 QCOMPARE(signal->valueDescriptions.begin()->second, std::string(
"One" ));
+
+
+
370 void DbcValidationTest::failedReplacement() {
+
+
+
373 const std::shared_ptr<const DecodeFrame> original = database.
FindFrame (valid.
GetKey ());
+
+
375 invalid.
canId = 0x800U;
+
376 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, database =
DecodeDatabase ({invalid}));
+
+
+
379 invalid.signals[0].factor = std::numeric_limits<double>::infinity();
+
380 QVERIFY_THROWS_EXCEPTION(std::invalid_argument,
+
+
+
383 QVERIFY_THROWS_EXCEPTION(std::invalid_argument, database =
DecodeDatabase ({valid, valid}));
+
+
+
386 invalid.signals.push_back(invalid.signals[0]);
+
387 QVERIFY_THROWS_EXCEPTION(std::invalid_argument,
+
+
+
+
391 QCOMPARE(database.
GetFrames ().size(), std::size_t(1U));
+
+
+
+
+
+
+
398 int RunValidationTests(
int argc,
char **argv) {
+
399 DbcValidationTest tests;
+
400 return QTest::qExec(&tests, argc, argv);
+
+
+
403 #include "dbc_validation_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.
-
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)
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
-
ByteOrder
Signal byte order used for runtime decoding.
-
ValueType
Signal numeric type.
+
Runtime CAN decoder using prebuilt decode database.
+
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...
+
std::shared_ptr< const DecodeSignal > FindSignal(const SignalKey &key) const
Return an owning signal handle, or an empty handle for a missing key.
+
std::shared_ptr< const DecodeFrame > FindFrame(const FrameKey &key) const
+
const std::vector< DecodeFrame > & GetFrames() const
+
Runtime decode database builder.
+
CAN frame decoding API and result types.
+
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-ready frame definition.
-
-
-
-
Runtime-ready signal definition.
-
-
-
-
-
ValueDescriptions valueDescriptions
-
-
-
-
-
-
-
-
Describes one CAN frame from a DBC file.
-
-
-
+
Runtime-ready frame definition.
+
FrameKey GetKey() const
Return the stable normalized frame identifier.
+
+
+
+
Runtime-ready signal definition.
+
+
+
+
+
ValueDescriptions valueDescriptions
+
+
+
+
+
+
Multiplexing multiplexing
+
+
+
Describes one CAN frame from a DBC file.
+
+
+
Stable frame identifier: normalized CAN ID and frame type.
+
+
+
Raw CAN frame used for runtime or trace decoding.
std::vector< std::uint8_t > data
-
Describes one signal inside a DBC frame.
-
-
-
-
-
-
-
-
-
-
+
Describes one signal inside a DBC frame.
+
+
+
+
Multiplexing multiplexing
+
+
+
+
+
+
+
diff --git a/docs/html/decode__database_8cpp_source.html b/docs/html/decode__database_8cpp_source.html
index 6f4572a..ac2a324 100644
--- a/docs/html/decode__database_8cpp_source.html
+++ b/docs/html/decode__database_8cpp_source.html
@@ -102,156 +102,200 @@ $(document).ready(function(){initNavTree('decode__database_8cpp_source.html','')
- 5 #include "signal_layout.h"
-
-
-
-
- 10 #include <unordered_set>
-
-
- 13 constexpr std::size_t MaximumPayloadBits = std::numeric_limits<std::uint8_t>::max() * 8U;
- 14 using SignalBits = std::bitset<MaximumPayloadBits>;
-
- 16 void ValidateSignal(
const DecodeSignal &signal, std::uint8_t dlc) {
-
- 18 throw std::invalid_argument(
"Invalid signal byte order: " + signal.
name );
-
- 20 throw std::invalid_argument(
"Invalid signal value type: " + signal.
name );
- 21 if (signal.multiplexing.role != MultiplexRole::Unconditional &&
- 22 signal.multiplexing.role != MultiplexRole::Selector &&
- 23 signal.multiplexing.role != MultiplexRole::Branch)
- 24 throw std::invalid_argument(
"Invalid multiplexing role: " + signal.
name );
-
- 26 signal.
byteOrder == ByteOrder::Intel, dlc))
- 27 throw std::invalid_argument(
"Invalid signal length or payload position: " + signal.
name );
- 28 if (!std::isfinite(signal.
factor ) || !std::isfinite(signal.
offset ) ||
- 29 !std::isfinite(signal.
minimum ) || !std::isfinite(signal.
maximum ) ||
-
- 31 throw std::invalid_argument(
"Invalid signal numeric parameters: " + signal.
name );
-
-
-
-
- 36 const bool littleEndian = signal.
byteOrder == ByteOrder::Intel;
- 37 const std::uint64_t start = SignalStartCoordinate(signal.
startBit , littleEndian);
- 38 for (std::uint32_t index = 0U; index < signal.
length ; ++index) {
- 39 const std::uint64_t coordinate = start + index;
- 40 const std::uint64_t bit = littleEndian ? coordinate
- 41 : coordinate / 8U * 8U + 7U - coordinate % 8U;
- 42 bits.set(
static_cast< std::size_t
> (bit));
-
-
-
-
-
- 48 return first.multiplexing.role == MultiplexRole::Branch &&
- 49 second.multiplexing.role == MultiplexRole::Branch &&
- 50 first.multiplexing.value != second.multiplexing.value;
-
-
-
- 54 const std::uint32_t maximumId = frame.
isExtended ? 0x1FFFFFFFU : 0x7FFU;
- 55 if (frame.
canId > maximumId)
- 56 throw std::invalid_argument(
"Invalid normalized CAN ID: " + std::to_string(frame.
canId ));
-
- 58 std::unordered_set<std::string> names;
-
-
- 61 if (!names.insert(signal.
name ).second)
- 62 throw std::invalid_argument(
"Duplicate runtime signal key: " + signal.
name );
- 63 ValidateSignal(signal, frame.
dlc );
- 64 if (signal.multiplexing.role == MultiplexRole::Selector) {
- 65 if (selector !=
nullptr || signal.
valueType != ValueType::Unsigned)
- 66 throw std::invalid_argument(
"Multiplexing requires one unsigned selector per frame" );
-
-
-
-
- 71 std::vector<SignalBits> layouts;
- 72 layouts.reserve(frame.signals.size());
- 73 for (std::size_t index = 0U; index < frame.signals.size(); ++index) {
-
- 75 if (signal.multiplexing.role == MultiplexRole::Branch &&
- 76 (selector ==
nullptr ||
- 77 (selector->
length < 64U && signal.multiplexing.value >= (std::uint64_t(1U) << selector->
length ))))
- 78 throw std::invalid_argument(
"Missing selector or branch value outside selector range: " + signal.
name );
- 79 const SignalBits bits = GetSignalBits(signal);
- 80 for (std::size_t previous = 0U; previous < index; ++previous) {
- 81 if (!AreMutuallyExclusive(signal, frame.signals[previous]) && (bits & layouts[previous]).any())
- 82 throw std::invalid_argument(
"Overlapping signals: " + signal.
name );
-
- 84 layouts.push_back(bits);
-
-
-
-
- 89 DecodeDatabase::Storage::Storage(
const std::vector<DecodeFrame> &definitions)
- 90 : frames(definitions) {
-
-
-
- 94 frameIndexByKey.reserve(frames.size());
- 95 for (std::size_t index = 0U; index < frames.size(); ++index) {
- 96 if (!frameIndexByKey.emplace(frames[index].GetKey(), index).second)
- 97 throw std::invalid_argument(
"Duplicate runtime frame key" );
-
-
-
-
-
101 DecodeDatabase::DecodeDatabase(
const std::vector<DecodeFrame> &frames)
-
102 : storage(std::make_shared<const Storage>(frames)) {
-
+
+
6 #include "signal_layout.h"
+
+
+
+
+
11 #include <unordered_set>
+
+
+
14 constexpr std::size_t MaximumPayloadBits = std::numeric_limits<std::uint8_t>::max() * 8U;
+
15 using SignalBits = std::bitset<MaximumPayloadBits>;
+
+
17 void ValidateSignal(
const DecodeSignal &signal, std::uint8_t dlc) {
+
+
19 throw std::invalid_argument(
"Invalid signal byte order: " + signal.
name );
+
+
21 throw std::invalid_argument(
"Invalid signal value type: " + signal.
name );
+
+
+
+
25 throw std::invalid_argument(
"Invalid multiplexing role: " + signal.
name );
+
+
27 signal.
byteOrder == ByteOrder::Intel, dlc))
+
28 throw std::invalid_argument(
"Invalid signal length or payload position: " + signal.
name );
+
29 if (!std::isfinite(signal.
factor ) || !std::isfinite(signal.
offset ) ||
+
30 !std::isfinite(signal.
minimum ) || !std::isfinite(signal.
maximum ) ||
+
+
32 throw std::invalid_argument(
"Invalid signal numeric parameters: " + signal.
name );
+
+
+
+
+
37 const bool littleEndian = signal.
byteOrder == ByteOrder::Intel;
+
38 const std::uint64_t start = SignalStartCoordinate(signal.
startBit , littleEndian);
+
39 for (std::uint32_t index = 0U; index < signal.
length ; ++index) {
+
40 const std::uint64_t coordinate = start + index;
+
41 const std::uint64_t bit = littleEndian ? coordinate
+
42 : coordinate / 8U * 8U + 7U - coordinate % 8U;
+
43 bits.set(
static_cast< std::size_t
> (bit));
+
+
+
+
+
+
+
+
+
+
+
+
55 const std::uint32_t maximumId = frame.
isExtended ? 0x1FFFFFFFU : 0x7FFU;
+
56 if (frame.
canId > maximumId)
+
57 throw std::invalid_argument(
"Invalid normalized CAN ID: " + std::to_string(frame.
canId ));
+
+
+
60 throw std::invalid_argument(
"Invalid J1939 PGN metadata: " + frame.
name );
+
+
62 std::unordered_set<std::string> names;
+
+
+
65 if (!names.insert(signal.
name ).second)
+
66 throw std::invalid_argument(
"Duplicate runtime signal key: " + signal.
name );
+
67 ValidateSignal(signal, frame.
dlc );
+
+
69 if (selector !=
nullptr || signal.
valueType != ValueType::Unsigned)
+
70 throw std::invalid_argument(
"Multiplexing requires one unsigned selector per frame" );
+
+
+
+
+
75 std::vector<SignalBits> layouts;
+
76 layouts.reserve(frame.signals.size());
+
77 for (std::size_t index = 0U; index < frame.signals.size(); ++index) {
+
+
+
80 (selector ==
nullptr ||
+
+
82 throw std::invalid_argument(
"Missing selector or branch value outside selector range: " + signal.
name );
+
83 const SignalBits bits = GetSignalBits(signal);
+
84 for (std::size_t previous = 0U; previous < index; ++previous) {
+
85 if (!AreMutuallyExclusive(signal, frame.signals[previous]) && (bits & layouts[previous]).any())
+
86 throw std::invalid_argument(
"Overlapping signals: " + signal.
name );
+
+
88 layouts.push_back(bits);
+
+
+
+
+
93 DecodeDatabase::Storage::Storage(
const std::vector<DecodeFrame> &definitions)
+
94 : frames(definitions) {
+
+
96 std::unordered_set<FrameKey, FrameKeyHasher> keys;
+
97 keys.reserve(frames.size());
+
+
+
100 if (!keys.insert(frame.
GetKey ()).second)
+
101 throw std::invalid_argument(
"Duplicate runtime frame key" );
+
+
103 frameIndexByKey.reserve(frames.size());
+
104 for (std::size_t index = 0U; index < frames.size(); ++index) {
+
105 frameIndexByKey.emplace(frames[index].GetKey(), index);
+
106 if (frames[index].hasPgn)
+
107 frameIndicesByPgn[frames[index].pgn].push_back(index);
+
+
+
+
+
111 DecodeDatabase::DecodeDatabase(
const std::vector<DecodeFrame> &frames)
+
112 : storage(std::make_shared<const Storage>(frames)) {
+
-
-
-
-
106 static const std::vector<DecodeFrame> empty;
-
107 return storage ? storage->frames : empty;
-
-
-
-
-
-
-
-
113 const std::unordered_map<FrameKey, std::size_t, FrameKeyHasher>::const_iterator it =
-
114 storage->frameIndexByKey.find(key);
-
115 if (it == storage->frameIndexByKey.end())
-
-
117 return std::shared_ptr<const DecodeFrame>(storage, &storage->frames[it->second]);
+
+
+
+
116 static const std::vector<DecodeFrame> empty;
+
117 return storage ? storage->frames : empty;
-
120 std::shared_ptr<const DecodeSignal> DecodeDatabase::FindSignal(
const SignalKey &key)
const {
-
121 const std::shared_ptr<const DecodeFrame> frame =
FindFrame (key.frame);
-
-
-
-
125 if (signal.
name == key.name)
-
126 return std::shared_ptr<const DecodeSignal>(frame, &signal);
-
-
-
-
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.
-
-
-
-
-
-
-
-
-
+
+
+
+
+
123 const std::unordered_map<FrameKey, std::size_t, FrameKeyHasher>::const_iterator it =
+
124 storage->frameIndexByKey.find(key);
+
125 if (it == storage->frameIndexByKey.end())
+
+
127 return std::shared_ptr<const DecodeFrame>(storage, &storage->frames[it->second]);
+
+
+
+
+
+
+
+
+
134 const std::unordered_map<std::uint32_t, std::vector<std::size_t>>::const_iterator it =
+
135 storage->frameIndicesByPgn.find(pgn);
+
136 if (it == storage->frameIndicesByPgn.end())
+
+
138 if (it->second.size() != 1U) {
+
+
+
+
142 result.
definition = std::shared_ptr<const DecodeFrame>(storage, &storage->frames[it->second[0]]);
+
+
+
+
+
+
+
147 const std::shared_ptr<const DecodeFrame> frame =
FindFrame (key.
frame );
+
+
+
+
+
152 return std::shared_ptr<const DecodeSignal>(frame, &signal);
+
+
+
+
+
std::shared_ptr< const DecodeSignal > FindSignal(const SignalKey &key) const
Return an owning signal handle, or an empty handle for a missing key.
+
std::shared_ptr< const DecodeFrame > FindFrame(const FrameKey &key) const
+
const std::vector< DecodeFrame > & GetFrames() const
+
PgnLookupResult FindFrameByPgn(std::uint32_t pgn) const
+
Runtime definitions and immutable indexed database.
+
Runtime-ready frame definition.
+
FrameKey GetKey() const
Return the stable normalized frame identifier.
+
+
+
+
+
+
+
Runtime-ready signal definition.
+
+
+
+
+
+
+
+
+
+
Multiplexing multiplexing
Stable frame identifier: normalized CAN ID and frame type.
-
+
+
+
+
+
std::shared_ptr< const DecodeFrame > definition
+
+
+
diff --git a/docs/html/decode__database_8h.html b/docs/html/decode__database_8h.html
index 7a90096..af068db 100644
--- a/docs/html/decode__database_8h.html
+++ b/docs/html/decode__database_8h.html
@@ -97,9 +97,10 @@ $(document).ready(function(){initNavTree('decode__database_8h.html',''); initRes
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Runtime definitions and immutable indexed database.
More...
-
#include "definition_key.h"
+
#include "attributes.h"
+
#include "definition_key.h"
#include "multiplexing.h"
#include "value_descriptions.h"
#include <cstdint>
@@ -118,6 +119,8 @@ Classes
struct DecodeFrame
Runtime-ready frame definition. More...
+
struct PgnLookupResult
+
class DecodeDatabase
Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles and decoded results keep old definitions alive. More...
@@ -136,7 +139,8 @@ Enumerations
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Runtime definitions and immutable indexed database.
+
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Licensed under the MIT License. See LICENSE file in the project root for full license text.
Definition in file decode_database.h .
@@ -163,7 +167,7 @@ Enumerations
Signal byte order used for runtime decoding.
-
Definition at line 27 of file decode_database.h .
+
Definition at line 28 of file decode_database.h .
@@ -189,7 +193,7 @@ Enumerations
Signal numeric type.
-
Definition at line 35 of file decode_database.h .
+
Definition at line 36 of file decode_database.h .
diff --git a/docs/html/decode__database_8h.js b/docs/html/decode__database_8h.js
index fad6f3e..e571a45 100644
--- a/docs/html/decode__database_8h.js
+++ b/docs/html/decode__database_8h.js
@@ -2,6 +2,7 @@ var decode__database_8h =
[
[ "DecodeSignal", "structDecodeSignal.html", "structDecodeSignal" ],
[ "DecodeFrame", "structDecodeFrame.html", "structDecodeFrame" ],
+ [ "PgnLookupResult", "structPgnLookupResult.html", "structPgnLookupResult" ],
[ "DecodeDatabase", "classDecodeDatabase.html", "classDecodeDatabase" ],
[ "ByteOrder", "decode__database_8h.html#aaeb92d42f5a6e27b8ba19f18d69d142b", [
[ "Intel", "decode__database_8h.html#aaeb92d42f5a6e27b8ba19f18d69d142baff97a9fdede09eaf6e1c8ec9f6a61dd5", null ],
diff --git a/docs/html/decode__database_8h_source.html b/docs/html/decode__database_8h_source.html
index 1b57aff..f549c04 100644
--- a/docs/html/decode__database_8h_source.html
+++ b/docs/html/decode__database_8h_source.html
@@ -102,122 +102,150 @@ $(document).ready(function(){initNavTree('decode__database_8h_source.html','');
12 #ifndef DECODE_DATABASE_H
13 #define DECODE_DATABASE_H
-
15 #include "definition_key.h"
-
16 #include "multiplexing.h"
-
17 #include "value_descriptions.h"
-
-
-
-
21 #include <unordered_map>
-
-
-
-
-
-
-
+
15 #include "attributes.h"
+
16 #include "definition_key.h"
+
17 #include "multiplexing.h"
+
18 #include "value_descriptions.h"
+
+
+
+
22 #include <unordered_map>
+
+
+
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
69 std::uint8_t
dlc = 0U;
-
70 std::uint32_t
pgn = 0U;
-
-
-
-
74 std::vector<DecodeSignal> signals;
-
-
-
-
-
-
+
+
+
+
+
+
+
72 std::uint8_t
dlc = 0U;
+
73 std::uint32_t
pgn = 0U;
+
+
+
+
77 std::vector<DecodeSignal> signals;
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
98 const std::vector<DecodeFrame> &
GetFrames ()
const ;
-
-
101 std::shared_ptr<const DecodeSignal> FindSignal(
const SignalKey &key)
const ;
-
-
-
-
105 std::vector<DecodeFrame> frames;
-
106 std::unordered_map<FrameKey, std::size_t, FrameKeyHasher> frameIndexByKey;
-
-
108 explicit Storage(
const std::vector<DecodeFrame> &definitions);
-
+
+
+
+
+
-
111 std::shared_ptr<const Storage> storage;
-
+
112 const std::vector<DecodeFrame> &
GetFrames ()
const ;
+
+
+
+
+
+
+
122 std::vector<DecodeFrame> frames;
+
123 std::unordered_map<FrameKey, std::size_t, FrameKeyHasher> frameIndexByKey;
+
+
125 std::unordered_map<std::uint32_t, std::vector<std::size_t>> frameIndicesByPgn;
+
+
127 explicit Storage(
const std::vector<DecodeFrame> &definitions);
+
+
+
130 std::shared_ptr<const Storage> storage;
+
-
-
-
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.
-
-
-
-
-
-
-
-
-
Runtime-ready signal definition.
-
-
-
-
-
-
ValueDescriptions valueDescriptions
-
-
-
-
std::vector< std::string > receivers
-
-
-
+
+
+
Immutable runtime snapshot. Copies share storage; reload replaces a snapshot. Owning lookup handles a...
+
std::shared_ptr< const DecodeSignal > FindSignal(const SignalKey &key) const
Return an owning signal handle, or an empty handle for a missing key.
+
std::shared_ptr< const DecodeFrame > FindFrame(const FrameKey &key) const
+
const std::vector< DecodeFrame > & GetFrames() const
+
PgnLookupResult FindFrameByPgn(std::uint32_t pgn) const
+
ByteOrder
Signal byte order used for runtime decoding.
+
ValueType
Signal numeric type.
+
Runtime-ready frame definition.
+
FrameKey GetKey() const
Return the stable normalized frame identifier.
+
+
+
+
+
std::optional< std::string > frameFormat
+
+
+
std::optional< std::uint32_t > cycleTimeMs
+
+
+
+
Runtime-ready signal definition.
+
+
+
+
+
+
+
ValueDescriptions valueDescriptions
+
+
+
+
std::vector< std::string > receivers
+
+
+
+
Multiplexing multiplexing
Stable frame identifier: normalized CAN ID and frame type.
-
-
+
+
+
+
std::shared_ptr< const DecodeFrame > definition
+
diff --git a/docs/html/definition__key_8h_source.html b/docs/html/definition__key_8h_source.html
index a9d0490..01496ef 100644
--- a/docs/html/definition__key_8h_source.html
+++ b/docs/html/definition__key_8h_source.html
@@ -111,60 +111,80 @@ $(document).ready(function(){initNavTree('definition__key_8h_source.html',''); i
-
16 std::uint32_t canId = 0U;
-
17 bool isExtended =
false ;
-
+
+
-
21 FrameKey (std::uint32_t
id ,
bool extended)
-
22 : canId(
id ), isExtended(extended) {
-
-
-
25 bool operator==(
const FrameKey &other)
const {
-
26 return (canId == other.canId) && (isExtended == other.isExtended);
-
-
+
-
-
-
-
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;
-
-
+
+
-
-
-
-
-
-
-
-
-
48 : frame(frameKey), name(std::move(signalName)) {
-
-
-
51 bool operator==(
const SignalKey &other)
const {
-
52 return frame == other.frame && name == other.name;
+
+
+
+
+
+
+
+
38 const std::size_t a =
static_cast< std::size_t
> (key.
canId );
+
39 const std::size_t b = key.
isExtended ? 1U : 0U;
+
40 return (a * 1315423911U) ^ b;
+
+
+
+
+
+
+
+
+
+
+
+
+
52 :
frame (frameKey),
name (std::move(signalName)) {
-
-
-
-
-
57 std::size_t operator()(
const SignalKey &key)
const {
-
58 return FrameKeyHasher ()(key.frame) ^ (std::hash<std::string>()(key.name) << 1U);
-
-
+
+
-
-
-
+
+
+
+
+
+
+
+
std::size_t operator()(const FrameKey &key) const
Hash the logical identity fields.
Stable frame identifier: normalized CAN ID and frame type.
-
-
+
+
FrameKey(std::uint32_t id, bool extended)
Create a key from a normalized identifier and frame type.
+
+
bool operator==(const FrameKey &other) const
Compare all logical identity fields.
+
Hasher for stable signal keys.
+
std::size_t operator()(const SignalKey &key) const
Hash the logical identity fields.
+
+
bool operator==(const SignalKey &other) const
Compare all logical identity fields.
+
+
SignalKey(FrameKey frameKey, std::string signalName)
Create a signal key from its frame identity and name.
+
diff --git a/docs/html/dir_4270bfced15e0e73154b13468c7c9ad9.html b/docs/html/dir_4270bfced15e0e73154b13468c7c9ad9.html
index 5f1cf25..a03594c 100644
--- a/docs/html/dir_4270bfced15e0e73154b13468c7c9ad9.html
+++ b/docs/html/dir_4270bfced15e0e73154b13468c7c9ad9.html
@@ -96,63 +96,69 @@ $(document).ready(function(){initNavTree('dir_4270bfced15e0e73154b13468c7c9ad9.h
+ attributes.h
+
+ dbc_attributes.cpp
+
dbc_database.h
- Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+ Parsed DBC database and attribute metadata.
dbc_decode_builder.cpp
- Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+ Conversion of parsed metadata to runtime definitions.
dbc_decode_builder.h
- Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+ Runtime decode database builder.
dbc_decoder.cpp
- Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+ CAN signal extraction and physical value conversion.
dbc_decoder.h
- Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+ CAN frame decoding API and result types.
dbc_diagnostic.h
dbc_parser.cpp
- Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+ DBC file reading and diagnostic collection.
dbc_parser.h
- Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+ DBC file parser and interpretation options.
dbc_statement_handler.cpp
dbc_statement_handler.h
dbc_tree_builder.cpp
- Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+ Construction of frame and signal metadata trees.
dbc_tree_builder.h
- Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+ Metadata tree builder.
decode_database.cpp
decode_database.h
- Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+ Runtime definitions and immutable indexed database.
definition_key.h
frame_info.h
- Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+ Parsed CAN frame metadata.
+
+ j1939.h
multiplexing.h
signal_info.h
- Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+ Parsed CAN signal metadata.
signal_layout.h
text_utils.h
tree_node.cpp
- Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+ Tree node ownership and navigation.
tree_node.h
- Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+ Qt-independent metadata tree nodes.
typefactory.h
diff --git a/docs/html/dir_4270bfced15e0e73154b13468c7c9ad9.js b/docs/html/dir_4270bfced15e0e73154b13468c7c9ad9.js
index a13e40a..5a6d627 100644
--- a/docs/html/dir_4270bfced15e0e73154b13468c7c9ad9.js
+++ b/docs/html/dir_4270bfced15e0e73154b13468c7c9ad9.js
@@ -1,5 +1,7 @@
var dir_4270bfced15e0e73154b13468c7c9ad9 =
[
+ [ "attributes.h", "attributes_8h_source.html", null ],
+ [ "dbc_attributes.cpp", "dbc__attributes_8cpp_source.html", null ],
[ "dbc_database.h", "dbc__database_8h.html", "dbc__database_8h" ],
[ "dbc_decode_builder.cpp", "dbc__decode__builder_8cpp.html", null ],
[ "dbc_decode_builder.h", "dbc__decode__builder_8h.html", "dbc__decode__builder_8h" ],
@@ -16,6 +18,7 @@ var dir_4270bfced15e0e73154b13468c7c9ad9 =
[ "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" ],
+ [ "j1939.h", "j1939_8h_source.html", null ],
[ "multiplexing.h", "multiplexing_8h_source.html", null ],
[ "signal_info.h", "signal__info_8h.html", "signal__info_8h" ],
[ "signal_layout.h", "signal__layout_8h_source.html", null ],
diff --git a/docs/html/dir_59425e443f801f1f2fd8bbe4959a3ccf.html b/docs/html/dir_59425e443f801f1f2fd8bbe4959a3ccf.html
index a00fa04..5207138 100644
--- a/docs/html/dir_59425e443f801f1f2fd8bbe4959a3ccf.html
+++ b/docs/html/dir_59425e443f801f1f2fd8bbe4959a3ccf.html
@@ -104,6 +104,8 @@ Files
dbc_parser_test.cpp
+ dbc_pipeline_test.cpp
+
dbc_tree_model_test.cpp
dbc_validation_test.cpp
diff --git a/docs/html/dir_59425e443f801f1f2fd8bbe4959a3ccf.js b/docs/html/dir_59425e443f801f1f2fd8bbe4959a3ccf.js
index 946b274..4fc2bf7 100644
--- a/docs/html/dir_59425e443f801f1f2fd8bbe4959a3ccf.js
+++ b/docs/html/dir_59425e443f801f1f2fd8bbe4959a3ccf.js
@@ -4,6 +4,7 @@ var dir_59425e443f801f1f2fd8bbe4959a3ccf =
[ "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_pipeline_test.cpp", "dbc__pipeline__test_8cpp_source.html", null ],
[ "dbc_tree_model_test.cpp", "dbc__tree__model__test_8cpp_source.html", null ],
[ "dbc_validation_test.cpp", "dbc__validation__test_8cpp_source.html", null ],
[ "tests/main.cpp", "tests_2main_8cpp_source.html", null ],
diff --git a/docs/html/dir_d28a4824dc47e487b107a5db32ef43c4.js b/docs/html/dir_d28a4824dc47e487b107a5db32ef43c4.js
index be6e0e7..3d2bb81 100644
--- a/docs/html/dir_d28a4824dc47e487b107a5db32ef43c4.js
+++ b/docs/html/dir_d28a4824dc47e487b107a5db32ef43c4.js
@@ -1,4 +1,4 @@
var dir_d28a4824dc47e487b107a5db32ef43c4 =
[
- [ "main.cpp", "examples_2main_8cpp.html", null ]
+ [ "main.cpp", "examples_2main_8cpp.html", "examples_2main_8cpp" ]
];
\ No newline at end of file
diff --git a/docs/html/examples_2main_8cpp.html b/docs/html/examples_2main_8cpp.html
index 3228246..5b399b9 100644
--- a/docs/html/examples_2main_8cpp.html
+++ b/docs/html/examples_2main_8cpp.html
@@ -113,6 +113,7 @@ $(document).ready(function(){initNavTree('examples_2main_8cpp.html',''); initRes
int main (int argc, char *argv[])
+ Parse a DBC file and demonstrate metadata lookup and CAN decoding.
@@ -147,7 +148,13 @@ Functions
diff --git a/docs/html/examples_2main_8cpp.js b/docs/html/examples_2main_8cpp.js
new file mode 100644
index 0000000..13cd388
--- /dev/null
+++ b/docs/html/examples_2main_8cpp.js
@@ -0,0 +1,4 @@
+var examples_2main_8cpp =
+[
+ [ "main", "examples_2main_8cpp.html#a0ddf1224851353fc92bfbff6f499fa97", null ]
+];
\ No newline at end of file
diff --git a/docs/html/examples_2main_8cpp_source.html b/docs/html/examples_2main_8cpp_source.html
index 250bff9..08cf399 100644
--- a/docs/html/examples_2main_8cpp_source.html
+++ b/docs/html/examples_2main_8cpp_source.html
@@ -187,87 +187,90 @@ $(document).ready(function(){initNavTree('examples_2main_8cpp_source.html','');
-
100 int main(
int argc,
char *argv[]) {
-
-
102 std::cerr <<
"Usage: dbc_demo <file.dbc>\n" ;
-
-
-
-
-
-
-
-
-
111 std::unique_ptr<TreeNode> root = treeBuilder.
Build (database);
-
-
113 std::cout <<
"=== Parsed tree ===\n" ;
-
114 PrintTree(root.get(), 0);
-
-
-
-
-
-
-
-
-
-
-
-
126 rawFrame.
data .resize(8U, 0U);
-
-
-
-
-
131 std::cout <<
"\n=== Decoded frame ===\n" ;
-
132 PrintDecodedFrame(decoded);
-
133 }
catch (
const std::exception &ex) {
-
134 std::cerr <<
"Error: " << ex.what() <<
"\n" ;
-
-
-
-
-
+
+
101 int main (
int argc,
char *argv[]) {
+
+
103 std::cerr <<
"Usage: dbc_demo <file.dbc>\n" ;
+
+
+
+
+
+
+
+
+
112 std::unique_ptr<TreeNode> root = treeBuilder.
Build (database);
+
+
114 std::cout <<
"=== Parsed tree ===\n" ;
+
115 PrintTree(root.get(), 0);
+
+
+
+
+
+
+
+
+
+
+
+
127 rawFrame.
data .resize(8U, 0U);
+
+
+
+
+
132 std::cout <<
"\n=== Decoded frame ===\n" ;
+
133 PrintDecodedFrame(decoded);
+
134 }
catch (
const std::exception &ex) {
+
135 std::cerr <<
"Error: " << ex.what() <<
"\n" ;
+
+
+
+
+
+
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.
-
DecodedFrameValue Decode(const DecodeDatabase &database, const RawCanFrame &frame) const
Decode one raw CAN frame.
-
-
DbcDatabase ParseFile(const std::string &filePath) const
Parse DBC file.
+
Runtime CAN decoder using prebuilt decode database.
+
DecodedFrameValue Decode(const DecodeDatabase &database, const RawCanFrame &frame) const
Decode one raw CAN frame.
+
+
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.
-
const SignalInfo * GetSignal() const
Get signal payload if node is signal.
-
const TreeNode * GetChild(std::size_t index) const
Get child by index.
-
const std::string & GetName() const
Get display name.
-
std::size_t GetChildCount() const
Get child count.
-
NodeType GetType() const
Get node type.
-
const FrameInfo * GetFrame() const
Get frame payload if node is frame.
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
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.
+
const SignalInfo * GetSignal() const
Get signal payload if node is signal.
+
const TreeNode * GetChild(std::size_t index) const
Get child by index.
+
const std::string & GetName() const
Get display name.
+
std::size_t GetChildCount() const
Get child count.
+
NodeType GetType() const
Get node type.
+
const FrameInfo * GetFrame() const
Get frame payload if node is frame.
+
Runtime decode database builder.
+
CAN frame decoding API and result types.
+
DBC file parser and interpretation options.
+
+
int main(int argc, char *argv[])
Parse a DBC file and demonstrate metadata lookup and CAN decoding.
Parsed DBC content stored in a simple internal form.
-
-
std::shared_ptr< const DecodeFrame > definition
-
-
One decoded signal value.
-
Describes one CAN frame from a DBC file.
-
-
-
-
-
+
+
std::shared_ptr< const DecodeFrame > definition
+
+
One decoded signal value.
+
Describes one CAN frame from a DBC file.
+
+
+
+
+
Raw CAN frame used for runtime or trace decoding.
std::vector< std::uint8_t > data
-
Describes one signal inside a DBC frame.
-
-
-
-
+
Describes one signal inside a DBC frame.
+
+
+
+
diff --git a/docs/html/files.html b/docs/html/files.html
index 528438e..5795b0d 100644
--- a/docs/html/files.html
+++ b/docs/html/files.html
@@ -96,44 +96,48 @@ $(document).ready(function(){initNavTree('files.html',''); initResizable(); });
Here is a list of all documented files with brief descriptions:
[detail level 1 2 ]
▼ core
- dbc_database.h Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
- dbc_decode_builder.cpp Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
- dbc_decode_builder.h Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
- dbc_decoder.cpp Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
- dbc_decoder.h Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
- dbc_diagnostic.h
- dbc_parser.cpp Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
- dbc_parser.h Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
- dbc_statement_handler.cpp
- dbc_statement_handler.h
- dbc_tree_builder.cpp Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
- 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)
- multiplexing.h
- signal_info.h Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
- signal_layout.h
- text_utils.h
- tree_node.cpp Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
- tree_node.h Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
- typefactory.h
- value_descriptions.h
- ▼ examples
- main.cpp Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
- ▼ qt
- dbc_tree_model.cpp
- dbc_tree_model.h
- ▼ tests
- dbc_coverage_test.cpp
- dbc_decoder_test.cpp
- dbc_lifetime_test.cpp
- dbc_parser_test.cpp
- dbc_tree_model_test.cpp
- dbc_validation_test.cpp
- main.cpp
- tree_node_test.cpp
+ attributes.h
+ dbc_attributes.cpp
+ dbc_database.h Parsed DBC database and attribute metadata
+ dbc_decode_builder.cpp Conversion of parsed metadata to runtime definitions
+ dbc_decode_builder.h Runtime decode database builder
+ dbc_decoder.cpp CAN signal extraction and physical value conversion
+ dbc_decoder.h CAN frame decoding API and result types
+ dbc_diagnostic.h
+ dbc_parser.cpp DBC file reading and diagnostic collection
+ dbc_parser.h DBC file parser and interpretation options
+ dbc_statement_handler.cpp
+ dbc_statement_handler.h
+ dbc_tree_builder.cpp Construction of frame and signal metadata trees
+ dbc_tree_builder.h Metadata tree builder
+ decode_database.cpp
+ decode_database.h Runtime definitions and immutable indexed database
+ definition_key.h
+ frame_info.h Parsed CAN frame metadata
+ j1939.h
+ multiplexing.h
+ signal_info.h Parsed CAN signal metadata
+ signal_layout.h
+ text_utils.h
+ tree_node.cpp Tree node ownership and navigation
+ tree_node.h Qt-independent metadata tree nodes
+ typefactory.h
+ value_descriptions.h
+ ▼ examples
+ main.cpp Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+ ▼ qt
+ dbc_tree_model.cpp
+ dbc_tree_model.h
+ ▼ tests
+ dbc_coverage_test.cpp
+ dbc_decoder_test.cpp
+ dbc_lifetime_test.cpp
+ dbc_parser_test.cpp
+ dbc_pipeline_test.cpp
+ dbc_tree_model_test.cpp
+ dbc_validation_test.cpp
+ main.cpp
+ tree_node_test.cpp
diff --git a/docs/html/frame__info_8h.html b/docs/html/frame__info_8h.html
index 9979bd2..f89092e 100644
--- a/docs/html/frame__info_8h.html
+++ b/docs/html/frame__info_8h.html
@@ -96,9 +96,10 @@ $(document).ready(function(){initNavTree('frame__info_8h.html',''); initResizabl
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Parsed CAN frame metadata.
More...
-
#include <cstdint>
+
#include "attributes.h"
+
#include <cstdint>
#include <string>
#include <vector>
#include "signal_info.h "
@@ -112,7 +113,8 @@ Classes
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Parsed CAN frame metadata.
+
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Licensed under the MIT License. See LICENSE file in the project root for full license text.
Definition in file frame_info.h .
diff --git a/docs/html/frame__info_8h_source.html b/docs/html/frame__info_8h_source.html
index e5b3f91..06044fb 100644
--- a/docs/html/frame__info_8h_source.html
+++ b/docs/html/frame__info_8h_source.html
@@ -102,38 +102,45 @@ $(document).ready(function(){initNavTree('frame__info_8h_source.html',''); initR
-
-
-
-
-
-
-
-
-
-
-
-
28 std::uint32_t
pgn = 0U;
-
-
30 std::uint8_t
dlc = 0U;
-
-
-
33 std::vector<SignalInfo> signals;
-
-
+
15 #include "attributes.h"
+
+
+
+
+
+
+
+
+
+
+
+
29 std::uint32_t
pgn = 0U;
+
+
31 std::uint8_t
dlc = 0U;
+
+
+
34 std::vector<SignalInfo> signals;
+
+
+
+
+
-
-
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
-
Describes one CAN frame from a DBC file.
-
-
-
-
-
-
-
-
+
+
+
Parsed CAN signal metadata.
+
Describes one CAN frame from a DBC file.
+
std::optional< std::uint32_t > cycleTimeMs
+
+
std::optional< std::string > frameFormat
+
+
+
+
+
+
+
+
diff --git a/docs/html/functions.html b/docs/html/functions.html
index 678024f..7485471 100644
--- a/docs/html/functions.html
+++ b/docs/html/functions.html
@@ -93,38 +93,72 @@ $(document).ready(function(){initNavTree('functions.html',''); initResizable();
Here is a list of all documented class members with links to the class documentation for each member:
- a -
- b -
- c -
-canId : DecodeFrame , FrameInfo , RawCanFrame
-comment : DecodeFrame , DecodeSignal , FrameInfo , SignalInfo
+canId : AttributeAssignment , DecodeFrame , FrameInfo , FrameKey , PendingComment , PendingValueDescriptions , RawCanFrame
+classes : TypeFactory< ClassId, BaseClass, Args >
+code : DbcDiagnostic
+Column : DbcTreeModel
+columnCount() : DbcTreeModel
+comment : DecodeFrame , DecodeSignal , FrameInfo , PendingComment , SignalInfo
contains() : TypeFactory< ClassId, BaseClass, Args >
create() : TypeFactory< ClassId, BaseClass, Args >
creator() : TypeFactory< ClassId, BaseClass, Args >
+CreatorFn : TypeFactory< ClassId, BaseClass, Args >
+currentFrame : DbcParseContext
+cycleTimeMs : DecodeFrame , FrameInfo
- d -
+
- e -
+
+
- f -
@@ -133,24 +167,34 @@ $(document).ready(function(){initNavTree('functions.html',''); initResizable();
GetChild() : TreeNode
GetChildCount() : TreeNode
GetFrame() : TreeNode
+
GetFrameKey() : TreeNode
GetFrames() : DecodeDatabase
+
GetKey() : DecodeFrame
GetName() : TreeNode
GetParent() : TreeNode
GetRow() : TreeNode
GetSignal() : TreeNode
+
GetSignalKey() : TreeNode
GetType() : TreeNode
GetValueDescription() : DecodedSignalValue
- h -
- i -
@@ -162,28 +206,37 @@ $(document).ready(function(){initNavTree('functions.html',''); initResizable();
- l -
- m -
- n -
- o -
- p -
+parent() : DbcTreeModel
ParseFile() : DbcParser
ParseFileWithDiagnostics() : DbcParser
+pendingAttributes : DbcParseContext
+pendingComments : DbcParseContext
+pendingValues : DbcParseContext
pgn : DecodeFrame , FrameInfo
physicalValue : DecodedSignalValue
public : DecodedFrameValue , DecodeFrame , FrameInfo
@@ -193,19 +246,35 @@ $(document).ready(function(){initNavTree('functions.html',''); initResizable();
- r -
- s -
- t -
@@ -216,6 +285,8 @@ $(document).ready(function(){initNavTree('functions.html',''); initResizable();
- v -
diff --git a/docs/html/functions_enum.html b/docs/html/functions_enum.html
new file mode 100644
index 0000000..864b33d
--- /dev/null
+++ b/docs/html/functions_enum.html
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+DBC Framework: Class Members - Enumerations
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DBC Framework
+
+ DBC parsing and CAN signal decoding framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+
+
+
Here is a list of all documented enums with links to the class documentation for each member:
+
+
+
+
+
+
diff --git a/docs/html/functions_func.html b/docs/html/functions_func.html
index b780cb9..4125f06 100644
--- a/docs/html/functions_func.html
+++ b/docs/html/functions_func.html
@@ -90,31 +90,113 @@ $(document).ready(function(){initNavTree('functions_func.html',''); initResizabl
-
Here is a list of all documented functions with links to the class documentation for each member:
diff --git a/docs/html/functions_type.html b/docs/html/functions_type.html
new file mode 100644
index 0000000..12d3402
--- /dev/null
+++ b/docs/html/functions_type.html
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
DBC Framework: Class Members - Typedefs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DBC Framework
+
+ DBC parsing and CAN signal decoding framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+
+
+
Here is a list of all documented typedefs with links to the class documentation for each member:
+
+
+
+
+
+
diff --git a/docs/html/functions_vars.html b/docs/html/functions_vars.html
index 5e15ff6..1c1c075 100644
--- a/docs/html/functions_vars.html
+++ b/docs/html/functions_vars.html
@@ -92,26 +92,52 @@ $(document).ready(function(){initNavTree('functions_vars.html',''); initResizabl
Here is a list of all documented variables with links to the class documentation for each member:
+
- a -
+
+
- b -
- c -
-canId : DecodeFrame , FrameInfo , RawCanFrame
-comment : DecodeFrame , DecodeSignal , FrameInfo , SignalInfo
+canId : AttributeAssignment , DecodeFrame , FrameInfo , FrameKey , PendingComment , PendingValueDescriptions , RawCanFrame
+classes : TypeFactory< ClassId, BaseClass, Args >
+code : DbcDiagnostic
+comment : DecodeFrame , DecodeSignal , FrameInfo , PendingComment , SignalInfo
+currentFrame : DbcParseContext
+cycleTimeMs : DecodeFrame , FrameInfo
- d -
+
- e -
+
+
- f -
@@ -122,8 +148,11 @@ $(document).ready(function(){initNavTree('functions_vars.html',''); initResizabl
- i -
@@ -135,17 +164,20 @@ $(document).ready(function(){initNavTree('functions_vars.html',''); initResizabl
- l -
- m -
- n -
@@ -155,6 +187,9 @@ $(document).ready(function(){initNavTree('functions_vars.html',''); initResizabl
- p -
diff --git a/docs/html/globals_enum.html b/docs/html/globals_enum.html
index 5886d5d..ddd5771 100644
--- a/docs/html/globals_enum.html
+++ b/docs/html/globals_enum.html
@@ -94,6 +94,7 @@ $(document).ready(function(){initNavTree('globals_enum.html',''); initResizable(
ByteOrder : decode_database.h
FrameDecodeStatus : dbc_decoder.h
NodeType : tree_node.h
+
SignalDecodeStatus : dbc_decoder.h
ValueType : decode_database.h
diff --git a/docs/html/globals_func.html b/docs/html/globals_func.html
index 9f96630..31093a6 100644
--- a/docs/html/globals_func.html
+++ b/docs/html/globals_func.html
@@ -1,14 +1,21 @@
-
+
-
+
-DBC framework: File Members
+DBC Framework: File Members
+
+
+
+
+
+
+
@@ -18,48 +25,81 @@
- DBC framework
+
DBC Framework
+
DBC parsing and CAN signal decoding framework
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+
+
-
+
diff --git a/docs/html/hierarchy.html b/docs/html/hierarchy.html
index 8c64f68..c9fb965 100644
--- a/docs/html/hierarchy.html
+++ b/docs/html/hierarchy.html
@@ -97,44 +97,51 @@ $(document).ready(function(){initNavTree('hierarchy.html',''); initResizable();
Go to the graphical class hierarchy
This inheritance list is sorted roughly, but not completely, alphabetically:
diff --git a/docs/html/hierarchy.js b/docs/html/hierarchy.js
index 9a2cd08..5037d23 100644
--- a/docs/html/hierarchy.js
+++ b/docs/html/hierarchy.js
@@ -1,5 +1,7 @@
var hierarchy =
[
+ [ "AttributeAssignment", "structAttributeAssignment.html", null ],
+ [ "AttributeDefinition", "structAttributeDefinition.html", null ],
[ "DbcDatabase", "structDbcDatabase.html", null ],
[ "DbcDecodeBuilder", "classDbcDecodeBuilder.html", null ],
[ "DbcDecoder", "classDbcDecoder.html", null ],
@@ -7,8 +9,10 @@ var hierarchy =
[ "DbcParseContext", "structDbcParseContext.html", null ],
[ "DbcParser", "classDbcParser.html", null ],
[ "DbcParseResult", "structDbcParseResult.html", null ],
+ [ "DbcParserOptions", "structDbcParserOptions.html", null ],
[ "DbcStatementDispatcher", "classDbcStatementDispatcher.html", null ],
[ "DbcStatementHandler", "classDbcStatementHandler.html", [
+ [ "DbcAttributeHandler", "classDbcAttributeHandler.html", null ],
[ "DbcCommentHandler", "classDbcCommentHandler.html", null ],
[ "DbcFrameHandler", "classDbcFrameHandler.html", null ],
[ "DbcHeaderHandler", "classDbcHeaderHandler.html", null ],
@@ -31,7 +35,10 @@ var hierarchy =
[ "FrameKey", "structFrameKey.html", null ],
[ "FrameKeyHasher", "structFrameKeyHasher.html", null ],
[ "Multiplexing", "structMultiplexing.html", null ],
+ [ "PendingAttribute", "structPendingAttribute.html", null ],
+ [ "PendingComment", "structPendingComment.html", null ],
[ "PendingValueDescriptions", "structPendingValueDescriptions.html", null ],
+ [ "PgnLookupResult", "structPgnLookupResult.html", null ],
[ "QAbstractItemModel", null, [
[ "DbcTreeModel", "classDbcTreeModel.html", null ]
] ],
diff --git a/docs/html/index.qhp b/docs/html/index.qhp
index fc1be5a..3d6ed70 100644
--- a/docs/html/index.qhp
+++ b/docs/html/index.qhp
@@ -12,139 +12,188 @@
doxygen
+
-
-
-
-
+
+
-
-
-
+
-
-
-
-
+
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
-
-
-
+
+
-
-
-
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
@@ -152,43 +201,114 @@
+
+
@@ -215,8 +337,12 @@
+
+
+
@@ -241,14 +368,45 @@
+
+
+
+
+
+
+
@@ -269,18 +428,26 @@
+
-
+
+
+
@@ -290,14 +457,19 @@
+
+
@@ -305,8 +477,10 @@
+
+
@@ -329,7 +503,10 @@
+
+
+
@@ -345,14 +522,21 @@
+
+
+
+
@@ -375,6 +559,7 @@
+
+
@@ -413,6 +612,7 @@
+
@@ -437,11 +639,20 @@
+
+
+
+
+
@@ -464,11 +675,16 @@
+
+
+
+
@@ -492,9 +709,11 @@
-
+
+
+
@@ -514,6 +733,7 @@
@@ -525,6 +745,7 @@
+
@@ -533,12 +754,16 @@
+
+
+
@@ -550,6 +775,7 @@
+
@@ -566,7 +792,10 @@
+
+
+
@@ -574,16 +803,47 @@
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -594,53 +854,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -652,18 +982,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -675,18 +1038,31 @@
+
+
+
+
+
+
+
+
+
annotated.html
+attributes_8h_source.html
bc_s.png
bc_sd.png
+classDbcAttributeHandler-members.html
+classDbcAttributeHandler.html
+classDbcAttributeHandler__inherit__graph.svg
classDbcCommentHandler-members.html
classDbcCommentHandler.html
classDbcCommentHandler__inherit__graph.svg
@@ -733,6 +1109,7 @@
classTypeFactory__inherit__graph.svg
classes.html
closed.png
+dbc__attributes_8cpp_source.html
dbc__coverage__test_8cpp_source.html
dbc__database_8h.html
dbc__database_8h_source.html
@@ -752,6 +1129,7 @@
dbc__parser_8h.html
dbc__parser_8h_source.html
dbc__parser__test_8cpp_source.html
+dbc__pipeline__test_8cpp_source.html
dbc__statement__handler_8cpp_source.html
dbc__statement__handler_8h_source.html
dbc__tree__builder_8cpp.html
@@ -779,10 +1157,13 @@
frame__info_8h.html
frame__info_8h_source.html
functions.html
+functions_enum.html
functions_func.html
+functions_type.html
functions_vars.html
globals.html
globals_enum.html
+globals_func.html
graph_legend.html
graph_legend.svg
hierarchy.html
@@ -809,7 +1190,13 @@
inherit_graph_26.svg
inherit_graph_27.svg
inherit_graph_28.svg
+inherit_graph_29.svg
inherit_graph_3.svg
+inherit_graph_30.svg
+inherit_graph_31.svg
+inherit_graph_32.svg
+inherit_graph_33.svg
+inherit_graph_34.svg
inherit_graph_4.svg
inherit_graph_5.svg
inherit_graph_6.svg
@@ -817,7 +1204,9 @@
inherit_graph_8.svg
inherit_graph_9.svg
inherits.html
+j1939_8h_source.html
jquery.js
+md_AGENTS.html
md_README.html
md_changelog.html
md_tests_2README.html
@@ -845,7 +1234,18 @@
search/all_19.js
search/all_1a.js
search/all_1b.js
+search/all_1c.js
+search/all_1d.js
+search/all_1e.js
+search/all_1f.js
search/all_2.js
+search/all_20.js
+search/all_21.js
+search/all_22.js
+search/all_23.js
+search/all_24.js
+search/all_25.js
+search/all_26.js
search/all_3.js
search/all_4.js
search/all_5.js
@@ -866,11 +1266,15 @@
search/classes_4.js
search/classes_5.js
search/classes_6.js
+search/classes_7.js
search/close.svg
search/enums_0.js
search/enums_1.js
search/enums_2.js
search/enums_3.js
+search/enums_4.js
+search/enums_5.js
+search/enums_6.js
search/files_0.js
search/files_1.js
search/files_2.js
@@ -885,6 +1289,12 @@
search/functions_6.js
search/functions_7.js
search/functions_8.js
+search/functions_9.js
+search/functions_a.js
+search/functions_b.js
+search/functions_c.js
+search/functions_d.js
+search/functions_e.js
search/mag.svg
search/mag_d.svg
search/mag_sel.svg
@@ -897,12 +1307,21 @@
search/pages_5.js
search/pages_6.js
search/pages_7.js
+search/pages_8.js
+search/pages_9.js
+search/pages_a.js
+search/pages_b.js
+search/pages_c.js
search/search.css
search/search.js
search/searchdata.js
+search/typedefs_0.js
+search/typedefs_1.js
search/variables_0.js
search/variables_1.js
search/variables_10.js
+search/variables_11.js
+search/variables_12.js
search/variables_2.js
search/variables_3.js
search/variables_4.js
@@ -922,6 +1341,10 @@
signal__layout_8h_source.html
splitbar.png
splitbard.png
+structAttributeAssignment-members.html
+structAttributeAssignment.html
+structAttributeDefinition-members.html
+structAttributeDefinition.html
structDbcDatabase-members.html
structDbcDatabase.html
structDbcDiagnostic-members.html
@@ -930,6 +1353,8 @@
structDbcParseContext.html
structDbcParseResult-members.html
structDbcParseResult.html
+structDbcParserOptions-members.html
+structDbcParserOptions.html
structDecodeFrame-members.html
structDecodeFrame.html
structDecodeSignal-members.html
@@ -946,8 +1371,14 @@
structFrameKeyHasher.html
structMultiplexing-members.html
structMultiplexing.html
+structPendingAttribute-members.html
+structPendingAttribute.html
+structPendingComment-members.html
+structPendingComment.html
structPendingValueDescriptions-members.html
structPendingValueDescriptions.html
+structPgnLookupResult-members.html
+structPgnLookupResult.html
structRawCanFrame-members.html
structRawCanFrame.html
structSignalInfo-members.html
diff --git a/docs/html/inherit_graph_0.map b/docs/html/inherit_graph_0.map
index f58dca1..a09c775 100644
--- a/docs/html/inherit_graph_0.map
+++ b/docs/html/inherit_graph_0.map
@@ -1,3 +1,3 @@
-
+
diff --git a/docs/html/inherit_graph_0.md5 b/docs/html/inherit_graph_0.md5
index a9ceb1f..66ec95b 100644
--- a/docs/html/inherit_graph_0.md5
+++ b/docs/html/inherit_graph_0.md5
@@ -1 +1 @@
-5a23bb52193266f734c783753a86fc4c
\ No newline at end of file
+b5f4c2d24a5c4743758b969b564da15e
\ No newline at end of file
diff --git a/docs/html/inherit_graph_0.svg b/docs/html/inherit_graph_0.svg
index ba79d61..75770c5 100644
--- a/docs/html/inherit_graph_0.svg
+++ b/docs/html/inherit_graph_0.svg
@@ -4,16 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-DbcDatabase
+
+
+AttributeAssignment
diff --git a/docs/html/inherit_graph_1.map b/docs/html/inherit_graph_1.map
index f285d3c..c664e2b 100644
--- a/docs/html/inherit_graph_1.map
+++ b/docs/html/inherit_graph_1.map
@@ -1,3 +1,3 @@
-
+
diff --git a/docs/html/inherit_graph_1.md5 b/docs/html/inherit_graph_1.md5
index 6cb3465..8f56605 100644
--- a/docs/html/inherit_graph_1.md5
+++ b/docs/html/inherit_graph_1.md5
@@ -1 +1 @@
-7d795e7bc503adfea7e85901c61a030d
\ No newline at end of file
+6f115143b61d0f25786194a09a0f0de2
\ No newline at end of file
diff --git a/docs/html/inherit_graph_1.svg b/docs/html/inherit_graph_1.svg
index d2e224c..0f6f803 100644
--- a/docs/html/inherit_graph_1.svg
+++ b/docs/html/inherit_graph_1.svg
@@ -11,9 +11,9 @@
Node0
-
+
-DbcDecodeBuilder
+AttributeDefinition
diff --git a/docs/html/inherit_graph_10.map b/docs/html/inherit_graph_10.map
index 42b5434..5fb9bd5 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 3eb9292..89aeb1e 100644
--- a/docs/html/inherit_graph_10.md5
+++ b/docs/html/inherit_graph_10.md5
@@ -1 +1 @@
-69d61ee297cd29b98a4f18e2423d5426
\ No newline at end of file
+e32f14f6883118a9bd63a5fa32e3e6db
\ No newline at end of file
diff --git a/docs/html/inherit_graph_10.svg b/docs/html/inherit_graph_10.svg
index d024b33..ed39b7b 100644
--- a/docs/html/inherit_graph_10.svg
+++ b/docs/html/inherit_graph_10.svg
@@ -4,16 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-DecodeDatabase
+
+
+DbcStatementDispatcher
diff --git a/docs/html/inherit_graph_11.map b/docs/html/inherit_graph_11.map
index c4d2de0..1415f0c 100644
--- a/docs/html/inherit_graph_11.map
+++ b/docs/html/inherit_graph_11.map
@@ -1,3 +1,17 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/html/inherit_graph_11.md5 b/docs/html/inherit_graph_11.md5
index 63d3ebd..21587d3 100644
--- a/docs/html/inherit_graph_11.md5
+++ b/docs/html/inherit_graph_11.md5
@@ -1 +1 @@
-f4d6da699c0f627067cdac840c9a773b
\ No newline at end of file
+5de84b208b213a2dcbbf7269d24a6341
\ No newline at end of file
diff --git a/docs/html/inherit_graph_11.svg b/docs/html/inherit_graph_11.svg
index 7695237..6c47714 100644
--- a/docs/html/inherit_graph_11.svg
+++ b/docs/html/inherit_graph_11.svg
@@ -4,16 +4,143 @@
-
-
+
+
Graphical Class Hierarchy
Node0
-
-
-DecodedFrameValue
+
+
+DbcStatementHandler
+
+
+
+
+
+Node1
+
+
+DbcAttributeHandler
+
+
+
+
+
+Node0->Node1
+
+
+
+
+
+
+
+
+Node2
+
+
+DbcCommentHandler
+
+
+
+
+
+Node0->Node2
+
+
+
+
+
+
+
+
+Node3
+
+
+DbcFrameHandler
+
+
+
+
+
+Node0->Node3
+
+
+
+
+
+
+
+
+Node4
+
+
+DbcHeaderHandler
+
+
+
+
+
+Node0->Node4
+
+
+
+
+
+
+
+
+Node5
+
+
+DbcSignalHandler
+
+
+
+
+
+Node0->Node5
+
+
+
+
+
+
+
+
+Node6
+
+
+DbcUnsupportedMultiplexing
+Handler
+
+
+
+
+
+Node0->Node6
+
+
+
+
+
+
+
+
+Node7
+
+
+DbcValueDescriptionHandler
+
+
+
+
+
+Node0->Node7
+
+
+
diff --git a/docs/html/inherit_graph_12.map b/docs/html/inherit_graph_12.map
index 7c65891..7cbafa0 100644
--- a/docs/html/inherit_graph_12.map
+++ b/docs/html/inherit_graph_12.map
@@ -1,3 +1,3 @@
-
+
diff --git a/docs/html/inherit_graph_12.md5 b/docs/html/inherit_graph_12.md5
index c9a02c7..f202ac5 100644
--- a/docs/html/inherit_graph_12.md5
+++ b/docs/html/inherit_graph_12.md5
@@ -1 +1 @@
-b05671a6a0ebf993e1d536e18c8222f0
\ No newline at end of file
+caff685aaef8276b6a7bdc7c6f2f9efa
\ No newline at end of file
diff --git a/docs/html/inherit_graph_12.svg b/docs/html/inherit_graph_12.svg
index ae6af8c..0044598 100644
--- a/docs/html/inherit_graph_12.svg
+++ b/docs/html/inherit_graph_12.svg
@@ -4,16 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-DecodedSignalValue
+
+
+DbcTreeBuilder
diff --git a/docs/html/inherit_graph_13.map b/docs/html/inherit_graph_13.map
index c05e6d1..42b5434 100644
--- a/docs/html/inherit_graph_13.map
+++ b/docs/html/inherit_graph_13.map
@@ -1,3 +1,3 @@
-
+
diff --git a/docs/html/inherit_graph_13.md5 b/docs/html/inherit_graph_13.md5
index 3bb982e..3eb9292 100644
--- a/docs/html/inherit_graph_13.md5
+++ b/docs/html/inherit_graph_13.md5
@@ -1 +1 @@
-d60a3b51249015f2f62123f47f8f38c1
\ No newline at end of file
+69d61ee297cd29b98a4f18e2423d5426
\ No newline at end of file
diff --git a/docs/html/inherit_graph_13.svg b/docs/html/inherit_graph_13.svg
index 4795e2c..d024b33 100644
--- a/docs/html/inherit_graph_13.svg
+++ b/docs/html/inherit_graph_13.svg
@@ -4,16 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-DecodeFrame
+
+
+DecodeDatabase
diff --git a/docs/html/inherit_graph_14.map b/docs/html/inherit_graph_14.map
index 3c6225b..c4d2de0 100644
--- a/docs/html/inherit_graph_14.map
+++ b/docs/html/inherit_graph_14.map
@@ -1,3 +1,3 @@
-
+
diff --git a/docs/html/inherit_graph_14.md5 b/docs/html/inherit_graph_14.md5
index 36d0d9e..63d3ebd 100644
--- a/docs/html/inherit_graph_14.md5
+++ b/docs/html/inherit_graph_14.md5
@@ -1 +1 @@
-b82865126817889e464d1e7bbdc44e1d
\ No newline at end of file
+f4d6da699c0f627067cdac840c9a773b
\ No newline at end of file
diff --git a/docs/html/inherit_graph_14.svg b/docs/html/inherit_graph_14.svg
index cba2eae..7695237 100644
--- a/docs/html/inherit_graph_14.svg
+++ b/docs/html/inherit_graph_14.svg
@@ -4,16 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-DecodeSignal
+
+
+DecodedFrameValue
diff --git a/docs/html/inherit_graph_15.map b/docs/html/inherit_graph_15.map
index e9866f7..7c65891 100644
--- a/docs/html/inherit_graph_15.map
+++ b/docs/html/inherit_graph_15.map
@@ -1,3 +1,3 @@
-
+
diff --git a/docs/html/inherit_graph_15.md5 b/docs/html/inherit_graph_15.md5
index 32124be..c9a02c7 100644
--- a/docs/html/inherit_graph_15.md5
+++ b/docs/html/inherit_graph_15.md5
@@ -1 +1 @@
-628e8fa4bf75287517a27c2bb42129ea
\ No newline at end of file
+b05671a6a0ebf993e1d536e18c8222f0
\ No newline at end of file
diff --git a/docs/html/inherit_graph_15.svg b/docs/html/inherit_graph_15.svg
index 97171b9..ae6af8c 100644
--- a/docs/html/inherit_graph_15.svg
+++ b/docs/html/inherit_graph_15.svg
@@ -4,16 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-FrameInfo
+
+
+DecodedSignalValue
diff --git a/docs/html/inherit_graph_16.map b/docs/html/inherit_graph_16.map
index f4a18a3..c05e6d1 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 e33d4ca..3bb982e 100644
--- a/docs/html/inherit_graph_16.md5
+++ b/docs/html/inherit_graph_16.md5
@@ -1 +1 @@
-d9608cce91db8bae16d0a4008a468656
\ No newline at end of file
+d60a3b51249015f2f62123f47f8f38c1
\ No newline at end of file
diff --git a/docs/html/inherit_graph_16.svg b/docs/html/inherit_graph_16.svg
index 5c70634..4795e2c 100644
--- a/docs/html/inherit_graph_16.svg
+++ b/docs/html/inherit_graph_16.svg
@@ -4,16 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-FrameKey
+
+
+DecodeFrame
diff --git a/docs/html/inherit_graph_17.map b/docs/html/inherit_graph_17.map
index 4cf64cb..3c6225b 100644
--- a/docs/html/inherit_graph_17.map
+++ b/docs/html/inherit_graph_17.map
@@ -1,3 +1,3 @@
-
+
diff --git a/docs/html/inherit_graph_17.md5 b/docs/html/inherit_graph_17.md5
index 0b133d4..36d0d9e 100644
--- a/docs/html/inherit_graph_17.md5
+++ b/docs/html/inherit_graph_17.md5
@@ -1 +1 @@
-03ff8d0fe772fd10da3721a519f78bc4
\ No newline at end of file
+b82865126817889e464d1e7bbdc44e1d
\ No newline at end of file
diff --git a/docs/html/inherit_graph_17.svg b/docs/html/inherit_graph_17.svg
index afe2243..cba2eae 100644
--- a/docs/html/inherit_graph_17.svg
+++ b/docs/html/inherit_graph_17.svg
@@ -4,16 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-FrameKeyHasher
+
+
+DecodeSignal
diff --git a/docs/html/inherit_graph_18.map b/docs/html/inherit_graph_18.map
index 6d8239d..e9866f7 100644
--- a/docs/html/inherit_graph_18.map
+++ b/docs/html/inherit_graph_18.map
@@ -1,3 +1,3 @@
-
+
diff --git a/docs/html/inherit_graph_18.md5 b/docs/html/inherit_graph_18.md5
index 4493996..32124be 100644
--- a/docs/html/inherit_graph_18.md5
+++ b/docs/html/inherit_graph_18.md5
@@ -1 +1 @@
-9c7c19c49bb06cf85d4a0f4383b32c46
\ No newline at end of file
+628e8fa4bf75287517a27c2bb42129ea
\ No newline at end of file
diff --git a/docs/html/inherit_graph_18.svg b/docs/html/inherit_graph_18.svg
index 427ad14..97171b9 100644
--- a/docs/html/inherit_graph_18.svg
+++ b/docs/html/inherit_graph_18.svg
@@ -4,16 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-Multiplexing
+
+
+FrameInfo
diff --git a/docs/html/inherit_graph_19.map b/docs/html/inherit_graph_19.map
index ad0caff..f4a18a3 100644
--- a/docs/html/inherit_graph_19.map
+++ b/docs/html/inherit_graph_19.map
@@ -1,3 +1,3 @@
-
+
diff --git a/docs/html/inherit_graph_19.md5 b/docs/html/inherit_graph_19.md5
index d203585..e33d4ca 100644
--- a/docs/html/inherit_graph_19.md5
+++ b/docs/html/inherit_graph_19.md5
@@ -1 +1 @@
-1e7e1326294370b50e12696033f3e108
\ No newline at end of file
+d9608cce91db8bae16d0a4008a468656
\ No newline at end of file
diff --git a/docs/html/inherit_graph_19.svg b/docs/html/inherit_graph_19.svg
index 049d797..5c70634 100644
--- a/docs/html/inherit_graph_19.svg
+++ b/docs/html/inherit_graph_19.svg
@@ -4,16 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-PendingValueDescriptions
+
+
+FrameKey
diff --git a/docs/html/inherit_graph_2.map b/docs/html/inherit_graph_2.map
index 187a40e..f58dca1 100644
--- a/docs/html/inherit_graph_2.map
+++ b/docs/html/inherit_graph_2.map
@@ -1,3 +1,3 @@
-
+
diff --git a/docs/html/inherit_graph_2.md5 b/docs/html/inherit_graph_2.md5
index 12e14d4..a9ceb1f 100644
--- a/docs/html/inherit_graph_2.md5
+++ b/docs/html/inherit_graph_2.md5
@@ -1 +1 @@
-bd2e795449505b56edb925aefd194571
\ No newline at end of file
+5a23bb52193266f734c783753a86fc4c
\ No newline at end of file
diff --git a/docs/html/inherit_graph_2.svg b/docs/html/inherit_graph_2.svg
index d8bc254..ba79d61 100644
--- a/docs/html/inherit_graph_2.svg
+++ b/docs/html/inherit_graph_2.svg
@@ -4,16 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-DbcDecoder
+
+
+DbcDatabase
diff --git a/docs/html/inherit_graph_20.map b/docs/html/inherit_graph_20.map
index d2e07bb..4cf64cb 100644
--- a/docs/html/inherit_graph_20.map
+++ b/docs/html/inherit_graph_20.map
@@ -1,5 +1,3 @@
-
-
-
+
diff --git a/docs/html/inherit_graph_20.md5 b/docs/html/inherit_graph_20.md5
index b51d107..0b133d4 100644
--- a/docs/html/inherit_graph_20.md5
+++ b/docs/html/inherit_graph_20.md5
@@ -1 +1 @@
-ad47da0d18c55e4eff4ff453c2dbe21f
\ No newline at end of file
+03ff8d0fe772fd10da3721a519f78bc4
\ No newline at end of file
diff --git a/docs/html/inherit_graph_20.svg b/docs/html/inherit_graph_20.svg
index 2afd5db..afe2243 100644
--- a/docs/html/inherit_graph_20.svg
+++ b/docs/html/inherit_graph_20.svg
@@ -4,34 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-QAbstractItemModel
-
-
-
-
-
-Node1
-
-
-DbcTreeModel
-
-
-
-
-
-Node0->Node1
-
-
-
+
+
+FrameKeyHasher
diff --git a/docs/html/inherit_graph_21.map b/docs/html/inherit_graph_21.map
index baccc4c..6d8239d 100644
--- a/docs/html/inherit_graph_21.map
+++ b/docs/html/inherit_graph_21.map
@@ -1,3 +1,3 @@
-
+
diff --git a/docs/html/inherit_graph_21.md5 b/docs/html/inherit_graph_21.md5
index 8e49fd2..4493996 100644
--- a/docs/html/inherit_graph_21.md5
+++ b/docs/html/inherit_graph_21.md5
@@ -1 +1 @@
-a0ca65c977c3eeaa49d3a753e2b425f7
\ No newline at end of file
+9c7c19c49bb06cf85d4a0f4383b32c46
\ No newline at end of file
diff --git a/docs/html/inherit_graph_21.svg b/docs/html/inherit_graph_21.svg
index ac9b694..427ad14 100644
--- a/docs/html/inherit_graph_21.svg
+++ b/docs/html/inherit_graph_21.svg
@@ -4,16 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-RawCanFrame
+
+
+Multiplexing
diff --git a/docs/html/inherit_graph_22.map b/docs/html/inherit_graph_22.map
index 27221de..367a0d9 100644
--- a/docs/html/inherit_graph_22.map
+++ b/docs/html/inherit_graph_22.map
@@ -1,3 +1,3 @@
-
+
diff --git a/docs/html/inherit_graph_22.md5 b/docs/html/inherit_graph_22.md5
index c4410a4..7cdfdf7 100644
--- a/docs/html/inherit_graph_22.md5
+++ b/docs/html/inherit_graph_22.md5
@@ -1 +1 @@
-f2e229631b6e08e3f933a80cf3a704df
\ No newline at end of file
+fe6cc341e61396f97e24e7f79efa07ff
\ No newline at end of file
diff --git a/docs/html/inherit_graph_22.svg b/docs/html/inherit_graph_22.svg
index 7b67e3e..f5b7ab8 100644
--- a/docs/html/inherit_graph_22.svg
+++ b/docs/html/inherit_graph_22.svg
@@ -4,16 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-SignalInfo
+
+
+PendingAttribute
diff --git a/docs/html/inherit_graph_23.map b/docs/html/inherit_graph_23.map
index 1e0f215..634f08d 100644
--- a/docs/html/inherit_graph_23.map
+++ b/docs/html/inherit_graph_23.map
@@ -1,3 +1,3 @@
-
+
diff --git a/docs/html/inherit_graph_23.md5 b/docs/html/inherit_graph_23.md5
index a182027..b7123a8 100644
--- a/docs/html/inherit_graph_23.md5
+++ b/docs/html/inherit_graph_23.md5
@@ -1 +1 @@
-7431f1cf350c15283d4994c7ea7fd895
\ No newline at end of file
+6247ecc186884bd9c53f7d45d3bd5d9d
\ No newline at end of file
diff --git a/docs/html/inherit_graph_23.svg b/docs/html/inherit_graph_23.svg
index 39da555..6d21e68 100644
--- a/docs/html/inherit_graph_23.svg
+++ b/docs/html/inherit_graph_23.svg
@@ -4,16 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-SignalKey
+
+
+PendingComment
diff --git a/docs/html/inherit_graph_24.map b/docs/html/inherit_graph_24.map
index f5ce2c8..1235b32 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 1631bc5..cb3bf10 100644
--- a/docs/html/inherit_graph_24.md5
+++ b/docs/html/inherit_graph_24.md5
@@ -1 +1 @@
-9cbeda36cad4be0f515a467c983bc7c5
\ No newline at end of file
+84cdd50f066ae7b7351893097b492e8a
\ No newline at end of file
diff --git a/docs/html/inherit_graph_24.svg b/docs/html/inherit_graph_24.svg
index ac54809..faee2ab 100644
--- a/docs/html/inherit_graph_24.svg
+++ b/docs/html/inherit_graph_24.svg
@@ -4,16 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-SignalKeyHasher
+
+
+PendingValueDescriptions
diff --git a/docs/html/inherit_graph_25.map b/docs/html/inherit_graph_25.map
index f17e7e3..1e37c63 100644
--- a/docs/html/inherit_graph_25.map
+++ b/docs/html/inherit_graph_25.map
@@ -1,7 +1,3 @@
-
-
-
-
-
+
diff --git a/docs/html/inherit_graph_25.md5 b/docs/html/inherit_graph_25.md5
index 9cbfdde..2185b68 100644
--- a/docs/html/inherit_graph_25.md5
+++ b/docs/html/inherit_graph_25.md5
@@ -1 +1 @@
-fcc3a46e0f291589c12d6b87f268a06f
\ No newline at end of file
+b0f82caebb3c32505175aab7ae2d7d70
\ No newline at end of file
diff --git a/docs/html/inherit_graph_25.svg b/docs/html/inherit_graph_25.svg
index f99f5c0..c6b0455 100644
--- a/docs/html/inherit_graph_25.svg
+++ b/docs/html/inherit_graph_25.svg
@@ -4,52 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-std::exception
-
-
-
-
-
-Node1
-
-
-std::runtime_error
-
-
-
-
-
-Node0->Node1
-
-
-
-
-
-
-
-
-Node2
-
-
-DbcDiagnosticError
-
-
-
-
-
-Node1->Node2
-
-
-
+
+
+PgnLookupResult
diff --git a/docs/html/inherit_graph_26.map b/docs/html/inherit_graph_26.map
index d2067d8..b666546 100644
--- a/docs/html/inherit_graph_26.map
+++ b/docs/html/inherit_graph_26.map
@@ -1,3 +1,5 @@
-
+
+
+
diff --git a/docs/html/inherit_graph_26.md5 b/docs/html/inherit_graph_26.md5
index 53a15e0..95afcce 100644
--- a/docs/html/inherit_graph_26.md5
+++ b/docs/html/inherit_graph_26.md5
@@ -1 +1 @@
-0e692ac66fcc5782f37efa2f3d64c466
\ No newline at end of file
+135d8c5ec586c0414ce0a7492f17be7a
\ No newline at end of file
diff --git a/docs/html/inherit_graph_26.svg b/docs/html/inherit_graph_26.svg
index a741e27..8aaf7b6 100644
--- a/docs/html/inherit_graph_26.svg
+++ b/docs/html/inherit_graph_26.svg
@@ -4,16 +4,34 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-TreeNode
+
+
+QAbstractItemModel
+
+
+
+
+
+Node1
+
+
+DbcTreeModel
+
+
+
+
+
+Node0->Node1
+
+
+
diff --git a/docs/html/inherit_graph_27.map b/docs/html/inherit_graph_27.map
index cc8fd2d..baccc4c 100644
--- a/docs/html/inherit_graph_27.map
+++ b/docs/html/inherit_graph_27.map
@@ -1,3 +1,3 @@
-
+
diff --git a/docs/html/inherit_graph_27.md5 b/docs/html/inherit_graph_27.md5
index feef5c8..8e49fd2 100644
--- a/docs/html/inherit_graph_27.md5
+++ b/docs/html/inherit_graph_27.md5
@@ -1 +1 @@
-fd991ac56e8b35f6def7a3942058b044
\ No newline at end of file
+a0ca65c977c3eeaa49d3a753e2b425f7
\ No newline at end of file
diff --git a/docs/html/inherit_graph_27.svg b/docs/html/inherit_graph_27.svg
index 1e19eb8..ac9b694 100644
--- a/docs/html/inherit_graph_27.svg
+++ b/docs/html/inherit_graph_27.svg
@@ -4,17 +4,16 @@
-
-
+
+
Graphical Class Hierarchy
Node0
-
-
-TypeFactory< ClassId,
- BaseClass, Args >
+
+
+RawCanFrame
diff --git a/docs/html/inherit_graph_28.map b/docs/html/inherit_graph_28.map
index f89295a..27221de 100644
--- a/docs/html/inherit_graph_28.map
+++ b/docs/html/inherit_graph_28.map
@@ -1,3 +1,3 @@
-
+
diff --git a/docs/html/inherit_graph_28.md5 b/docs/html/inherit_graph_28.md5
index 0956862..c4410a4 100644
--- a/docs/html/inherit_graph_28.md5
+++ b/docs/html/inherit_graph_28.md5
@@ -1 +1 @@
-2e92ed9cb6b5a27ab688cfd97eafecca
\ No newline at end of file
+f2e229631b6e08e3f933a80cf3a704df
\ No newline at end of file
diff --git a/docs/html/inherit_graph_28.svg b/docs/html/inherit_graph_28.svg
index cb57a17..7b67e3e 100644
--- a/docs/html/inherit_graph_28.svg
+++ b/docs/html/inherit_graph_28.svg
@@ -4,17 +4,16 @@
-
-
+
+
Graphical Class Hierarchy
Node0
-
-
-TypeFactory< std::string,
- DbcStatementHandler >
+
+
+SignalInfo
diff --git a/docs/html/inherit_graph_29.map b/docs/html/inherit_graph_29.map
new file mode 100644
index 0000000..1e0f215
--- /dev/null
+++ b/docs/html/inherit_graph_29.map
@@ -0,0 +1,3 @@
+
+
+
diff --git a/docs/html/inherit_graph_29.md5 b/docs/html/inherit_graph_29.md5
new file mode 100644
index 0000000..a182027
--- /dev/null
+++ b/docs/html/inherit_graph_29.md5
@@ -0,0 +1 @@
+7431f1cf350c15283d4994c7ea7fd895
\ No newline at end of file
diff --git a/docs/html/inherit_graph_29.svg b/docs/html/inherit_graph_29.svg
new file mode 100644
index 0000000..39da555
--- /dev/null
+++ b/docs/html/inherit_graph_29.svg
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+Graphical Class Hierarchy
+
+
+Node0
+
+
+SignalKey
+
+
+
+
+
diff --git a/docs/html/inherit_graph_3.map b/docs/html/inherit_graph_3.map
index d893319..f285d3c 100644
--- a/docs/html/inherit_graph_3.map
+++ b/docs/html/inherit_graph_3.map
@@ -1,3 +1,3 @@
-
+
diff --git a/docs/html/inherit_graph_3.md5 b/docs/html/inherit_graph_3.md5
index a2a10b1..6cb3465 100644
--- a/docs/html/inherit_graph_3.md5
+++ b/docs/html/inherit_graph_3.md5
@@ -1 +1 @@
-d6d90b711187d0d808df175139af753e
\ No newline at end of file
+7d795e7bc503adfea7e85901c61a030d
\ No newline at end of file
diff --git a/docs/html/inherit_graph_3.svg b/docs/html/inherit_graph_3.svg
index 1d59989..d2e224c 100644
--- a/docs/html/inherit_graph_3.svg
+++ b/docs/html/inherit_graph_3.svg
@@ -4,16 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-DbcDiagnostic
+
+
+DbcDecodeBuilder
diff --git a/docs/html/inherit_graph_30.map b/docs/html/inherit_graph_30.map
new file mode 100644
index 0000000..c9f4584
--- /dev/null
+++ b/docs/html/inherit_graph_30.map
@@ -0,0 +1,3 @@
+
+
+
diff --git a/docs/html/inherit_graph_30.md5 b/docs/html/inherit_graph_30.md5
new file mode 100644
index 0000000..73e0dbd
--- /dev/null
+++ b/docs/html/inherit_graph_30.md5
@@ -0,0 +1 @@
+62eb1b3d89eef70066f0ed689f1cacfa
\ No newline at end of file
diff --git a/docs/html/inherit_graph_30.svg b/docs/html/inherit_graph_30.svg
new file mode 100644
index 0000000..277d09a
--- /dev/null
+++ b/docs/html/inherit_graph_30.svg
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+Graphical Class Hierarchy
+
+
+Node0
+
+
+SignalKeyHasher
+
+
+
+
+
diff --git a/docs/html/inherit_graph_31.map b/docs/html/inherit_graph_31.map
new file mode 100644
index 0000000..5ae3dbf
--- /dev/null
+++ b/docs/html/inherit_graph_31.map
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/docs/html/inherit_graph_31.md5 b/docs/html/inherit_graph_31.md5
new file mode 100644
index 0000000..0eccec7
--- /dev/null
+++ b/docs/html/inherit_graph_31.md5
@@ -0,0 +1 @@
+4701cdaa94ff57f56036e0aefb1b0118
\ No newline at end of file
diff --git a/docs/html/inherit_graph_31.svg b/docs/html/inherit_graph_31.svg
new file mode 100644
index 0000000..c1cee58
--- /dev/null
+++ b/docs/html/inherit_graph_31.svg
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+Graphical Class Hierarchy
+
+
+Node0
+
+
+std::exception
+
+
+
+
+
+Node1
+
+
+std::runtime_error
+
+
+
+
+
+Node0->Node1
+
+
+
+
+
+
+
+
+Node2
+
+
+DbcDiagnosticError
+
+
+
+
+
+Node1->Node2
+
+
+
+
+
+
+
+
diff --git a/docs/html/inherit_graph_32.map b/docs/html/inherit_graph_32.map
new file mode 100644
index 0000000..d2067d8
--- /dev/null
+++ b/docs/html/inherit_graph_32.map
@@ -0,0 +1,3 @@
+
+
+
diff --git a/docs/html/inherit_graph_32.md5 b/docs/html/inherit_graph_32.md5
new file mode 100644
index 0000000..53a15e0
--- /dev/null
+++ b/docs/html/inherit_graph_32.md5
@@ -0,0 +1 @@
+0e692ac66fcc5782f37efa2f3d64c466
\ No newline at end of file
diff --git a/docs/html/inherit_graph_32.svg b/docs/html/inherit_graph_32.svg
new file mode 100644
index 0000000..a741e27
--- /dev/null
+++ b/docs/html/inherit_graph_32.svg
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+Graphical Class Hierarchy
+
+
+Node0
+
+
+TreeNode
+
+
+
+
+
diff --git a/docs/html/inherit_graph_33.map b/docs/html/inherit_graph_33.map
new file mode 100644
index 0000000..cc8fd2d
--- /dev/null
+++ b/docs/html/inherit_graph_33.map
@@ -0,0 +1,3 @@
+
+
+
diff --git a/docs/html/inherit_graph_33.md5 b/docs/html/inherit_graph_33.md5
new file mode 100644
index 0000000..feef5c8
--- /dev/null
+++ b/docs/html/inherit_graph_33.md5
@@ -0,0 +1 @@
+fd991ac56e8b35f6def7a3942058b044
\ No newline at end of file
diff --git a/docs/html/inherit_graph_33.svg b/docs/html/inherit_graph_33.svg
new file mode 100644
index 0000000..1e19eb8
--- /dev/null
+++ b/docs/html/inherit_graph_33.svg
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+Graphical Class Hierarchy
+
+
+Node0
+
+
+TypeFactory< ClassId,
+ BaseClass, Args >
+
+
+
+
+
diff --git a/docs/html/inherit_graph_34.map b/docs/html/inherit_graph_34.map
new file mode 100644
index 0000000..f89295a
--- /dev/null
+++ b/docs/html/inherit_graph_34.map
@@ -0,0 +1,3 @@
+
+
+
diff --git a/docs/html/inherit_graph_34.md5 b/docs/html/inherit_graph_34.md5
new file mode 100644
index 0000000..0956862
--- /dev/null
+++ b/docs/html/inherit_graph_34.md5
@@ -0,0 +1 @@
+2e92ed9cb6b5a27ab688cfd97eafecca
\ No newline at end of file
diff --git a/docs/html/inherit_graph_34.svg b/docs/html/inherit_graph_34.svg
new file mode 100644
index 0000000..cb57a17
--- /dev/null
+++ b/docs/html/inherit_graph_34.svg
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+Graphical Class Hierarchy
+
+
+Node0
+
+
+TypeFactory< std::string,
+ DbcStatementHandler >
+
+
+
+
+
diff --git a/docs/html/inherit_graph_4.map b/docs/html/inherit_graph_4.map
index 4590e15..187a40e 100644
--- a/docs/html/inherit_graph_4.map
+++ b/docs/html/inherit_graph_4.map
@@ -1,3 +1,3 @@
-
+
diff --git a/docs/html/inherit_graph_4.md5 b/docs/html/inherit_graph_4.md5
index ffd6e48..12e14d4 100644
--- a/docs/html/inherit_graph_4.md5
+++ b/docs/html/inherit_graph_4.md5
@@ -1 +1 @@
-2674130f4d66049ef34375ec57054882
\ No newline at end of file
+bd2e795449505b56edb925aefd194571
\ No newline at end of file
diff --git a/docs/html/inherit_graph_4.svg b/docs/html/inherit_graph_4.svg
index ad34d29..d8bc254 100644
--- a/docs/html/inherit_graph_4.svg
+++ b/docs/html/inherit_graph_4.svg
@@ -4,16 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-DbcParseContext
+
+
+DbcDecoder
diff --git a/docs/html/inherit_graph_5.map b/docs/html/inherit_graph_5.map
index 1af950d..669d087 100644
--- a/docs/html/inherit_graph_5.map
+++ b/docs/html/inherit_graph_5.map
@@ -1,3 +1,3 @@
-
+
diff --git a/docs/html/inherit_graph_5.md5 b/docs/html/inherit_graph_5.md5
index 63d492a..b2ed405 100644
--- a/docs/html/inherit_graph_5.md5
+++ b/docs/html/inherit_graph_5.md5
@@ -1 +1 @@
-debfb9bdb327669e1f39bd750d473c06
\ No newline at end of file
+f3ea21db5a8dc0b166384a9f9d74accb
\ No newline at end of file
diff --git a/docs/html/inherit_graph_5.svg b/docs/html/inherit_graph_5.svg
index 47e2173..d46782e 100644
--- a/docs/html/inherit_graph_5.svg
+++ b/docs/html/inherit_graph_5.svg
@@ -4,16 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-DbcParser
+
+
+DbcDiagnostic
diff --git a/docs/html/inherit_graph_6.map b/docs/html/inherit_graph_6.map
index c552d7b..4590e15 100644
--- a/docs/html/inherit_graph_6.map
+++ b/docs/html/inherit_graph_6.map
@@ -1,3 +1,3 @@
-
+
diff --git a/docs/html/inherit_graph_6.md5 b/docs/html/inherit_graph_6.md5
index 044d2e6..ffd6e48 100644
--- a/docs/html/inherit_graph_6.md5
+++ b/docs/html/inherit_graph_6.md5
@@ -1 +1 @@
-f92f99071c369af7be9b6720e317d236
\ No newline at end of file
+2674130f4d66049ef34375ec57054882
\ No newline at end of file
diff --git a/docs/html/inherit_graph_6.svg b/docs/html/inherit_graph_6.svg
index 7776a12..ad34d29 100644
--- a/docs/html/inherit_graph_6.svg
+++ b/docs/html/inherit_graph_6.svg
@@ -4,16 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-DbcParseResult
+
+
+DbcParseContext
diff --git a/docs/html/inherit_graph_7.map b/docs/html/inherit_graph_7.map
index 5fb9bd5..1af950d 100644
--- a/docs/html/inherit_graph_7.map
+++ b/docs/html/inherit_graph_7.map
@@ -1,3 +1,3 @@
-
+
diff --git a/docs/html/inherit_graph_7.md5 b/docs/html/inherit_graph_7.md5
index 89aeb1e..63d492a 100644
--- a/docs/html/inherit_graph_7.md5
+++ b/docs/html/inherit_graph_7.md5
@@ -1 +1 @@
-e32f14f6883118a9bd63a5fa32e3e6db
\ No newline at end of file
+debfb9bdb327669e1f39bd750d473c06
\ No newline at end of file
diff --git a/docs/html/inherit_graph_7.svg b/docs/html/inherit_graph_7.svg
index ed39b7b..47e2173 100644
--- a/docs/html/inherit_graph_7.svg
+++ b/docs/html/inherit_graph_7.svg
@@ -4,16 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-DbcStatementDispatcher
+
+
+DbcParser
diff --git a/docs/html/inherit_graph_8.map b/docs/html/inherit_graph_8.map
index 8fac8e4..259b74c 100644
--- a/docs/html/inherit_graph_8.map
+++ b/docs/html/inherit_graph_8.map
@@ -1,15 +1,3 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/docs/html/inherit_graph_8.md5 b/docs/html/inherit_graph_8.md5
index 49aad1c..db56851 100644
--- a/docs/html/inherit_graph_8.md5
+++ b/docs/html/inherit_graph_8.md5
@@ -1 +1 @@
-50d8eccddc248eb5342377b1e19abb04
\ No newline at end of file
+c93d9faec3ab727c3e1156aadb2b7a96
\ No newline at end of file
diff --git a/docs/html/inherit_graph_8.svg b/docs/html/inherit_graph_8.svg
index 3df3846..3fb192c 100644
--- a/docs/html/inherit_graph_8.svg
+++ b/docs/html/inherit_graph_8.svg
@@ -4,125 +4,16 @@
-
-
+
+
Graphical Class Hierarchy
Node0
-
-
-DbcStatementHandler
-
-
-
-
-
-Node1
-
-
-DbcCommentHandler
-
-
-
-
-
-Node0->Node1
-
-
-
-
-
-
-
-
-Node2
-
-
-DbcFrameHandler
-
-
-
-
-
-Node0->Node2
-
-
-
-
-
-
-
-
-Node3
-
-
-DbcHeaderHandler
-
-
-
-
-
-Node0->Node3
-
-
-
-
-
-
-
-
-Node4
-
-
-DbcSignalHandler
-
-
-
-
-
-Node0->Node4
-
-
-
-
-
-
-
-
-Node5
-
-
-DbcUnsupportedMultiplexing
-Handler
-
-
-
-
-
-Node0->Node5
-
-
-
-
-
-
-
-
-Node6
-
-
-DbcValueDescriptionHandler
-
-
-
-
-
-Node0->Node6
-
-
-
+
+
+DbcParseResult
diff --git a/docs/html/inherit_graph_9.map b/docs/html/inherit_graph_9.map
index 7cbafa0..e3ebdad 100644
--- a/docs/html/inherit_graph_9.map
+++ b/docs/html/inherit_graph_9.map
@@ -1,3 +1,3 @@
-
+
diff --git a/docs/html/inherit_graph_9.md5 b/docs/html/inherit_graph_9.md5
index f202ac5..846cbfe 100644
--- a/docs/html/inherit_graph_9.md5
+++ b/docs/html/inherit_graph_9.md5
@@ -1 +1 @@
-caff685aaef8276b6a7bdc7c6f2f9efa
\ No newline at end of file
+a4e1942ba0a8d4954dd8e07140223feb
\ No newline at end of file
diff --git a/docs/html/inherit_graph_9.svg b/docs/html/inherit_graph_9.svg
index 0044598..319ed3b 100644
--- a/docs/html/inherit_graph_9.svg
+++ b/docs/html/inherit_graph_9.svg
@@ -4,16 +4,16 @@
-
+
Graphical Class Hierarchy
Node0
-
-
-DbcTreeBuilder
+
+
+DbcParserOptions
diff --git a/docs/html/inherits.html b/docs/html/inherits.html
index 4ea50dc..19d2d6a 100644
--- a/docs/html/inherits.html
+++ b/docs/html/inherits.html
@@ -96,35 +96,41 @@ $(document).ready(function(){initNavTree('hierarchy.html',''); initResizable();
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/html/j1939_8h_source.html b/docs/html/j1939_8h_source.html
new file mode 100644
index 0000000..c302a07
--- /dev/null
+++ b/docs/html/j1939_8h_source.html
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+DBC Framework: j1939.h Source File
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DBC Framework
+
+ DBC parsing and CAN signal decoding framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+
+
+
+
+
+
+
+
+
+
11 inline std::uint32_t ExtractJ1939Pgn(std::uint32_t canId) {
+
12 const std::uint32_t pf = (canId >> 16U) & 0xFFU;
+
13 const std::uint32_t pgn = (canId >> 8U) & 0x3FFFFU;
+
14 return pf < 240U ? pgn & 0x3FF00U : pgn;
+
+
+
+
+
+
+
+
+
diff --git a/docs/html/md_AGENTS.html b/docs/html/md_AGENTS.html
new file mode 100644
index 0000000..365aefe
--- /dev/null
+++ b/docs/html/md_AGENTS.html
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+DBC Framework: Инструкции для работы с проектом
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DBC Framework
+
+ DBC parsing and CAN signal decoding framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+
+
+
+
+
+О проекте
+
Проект — библиотека C++17 для разбора DBC, декодирования CAN-кадров и построения дерева метаданных.
+
+core/ — библиотека без зависимости от Qt.
+qt/ — необязательный адаптер для Qt.
+tests/ — тесты парсера, декодера, метаданных и дерева.
+examples/ — примеры использования.
+
+
Сборка выполняется через qmake. Qt-зависимые цели требуют Qt 6.8.2.
+
+Формат задания
+
+В начальном сообщении с заданием первая непустая строка перед пустой строкой — точное название issue в Gitea и требуемое название чата. Описание задания начинается после этой пустой строки.
+Для названия чата используй первую строку дословно: сохраняй язык, формулировку и номер issue (#20 и т. п.). Не переводи, не перефразируй, не добавляй описание задания, план работы или итоги.
+Например, для сообщения Support signal value descriptions #20, за которым следуют пустая строка и описание, название чата должно быть ровно Support signal value descriptions #20.
+Применяй это правило при создании или переименовании чата, если интерфейс предоставляет такую возможность. Если управление названием недоступно, не утверждай, что чат переименован: инструкции в AGENTS.md сами по себе не управляют автоматическим названием в интерфейсе.
+Последующие уточнения и сообщения в текущем чате не меняют выбранное название, если пользователь явно не попросил его изменить.
+
+
+Правила кода
+
+Используй TypeFactory везде, где это уместно.
+Не используй auto как возвращаемый тип функций.
+Не используй lambda.
+Придерживайся KISS.
+Пиши читаемый код, который легко понять.
+Соблюдай существующий стиль и настройки .clang-format.
+Сохраняй независимость core/ от Qt.
+
+
+Тестирование
+
+Добавляй необходимые тесты для изменённого поведения.
+При исправлении ошибки добавляй тест, воспроизводящий её.
+Подключай новые тестовые файлы к соответствующей цели qmake.
+Перед завершением работы запускай применимые тесты.
+Если проверку выполнить невозможно, сообщи причину.
+
+
Основная сборка и тесты из корня репозитория:
+
mkdir -p build
+
cd build
+
qmake6 ../dbc.pro
+
make -j4
+
make check
+
Для изменений Qt-адаптера включай model-тесты:
+
mkdir -p build-qt
+
cd build-qt
+
qmake6 ../dbc.pro CONFIG+=dbc_qt
+
make -j4
+
make check
+
Для изменений дерева запускай также standalone-тест из корня репозитория:
+
c++ -std=c++17 -Icore tests/tree_node_test.cpp core/tree_node.cpp \
+
core/dbc_tree_builder.cpp -o /tmp/dbc_tree_node_test
+
/tmp/dbc_tree_node_test
+
Используй отдельные каталоги для разных конфигураций сборки.
+
+Документация
+
+Актуализируй README.md и changelog.md при изменениях проекта.
+При изменении тестов актуализируй tests/README.md.
+Описывай фактическое поведение и выполненные проверки.
+
+
+
+
+
+
+
+
diff --git a/docs/html/md_README.html b/docs/html/md_README.html
index 034f8ba..4f065a6 100644
--- a/docs/html/md_README.html
+++ b/docs/html/md_README.html
@@ -93,8 +93,8 @@ $(document).ready(function(){initNavTree('md_README.html',''); initResizable();
-
-
+
+
Overview
This module provides a minimal but extensible DBC parser and runtime decode foundation for the FrameTap project.
Its purpose is to:
@@ -115,11 +115,12 @@ Overview
The core library uses C++17 and has no Qt dependency. Qt integration targets the installed Qt 6.8.2, which is the only supported Qt version. Qt Core and Qt Test are used by the regression tests; model tests also link QtGui for graphical metatypes. The optional adapter requires only Qt Core. Live CAN acquisition, trace-file readers, are left to the consuming application. An optional Qt Core model adapter is provided in qt/.
See changelog.md for the release and development history, tests/README.md for test instructions, and generated API documentation for the API reference.
+
AGENTS.md contains project instructions for coding agents, including code style, build and test commands, and documentation requirements.
-
+
High-Level Architecture
The module is divided into two main paths.
-
+
1. Parse and UI path
Used for:
@@ -139,7 +140,7 @@ High-Level Architecture
TreeNode hierarchy
↓
DbcTreeModel → Qt views
-
+
2. Runtime decode path
Used for:
@@ -164,7 +165,7 @@ High-Level Architecture
This separation is intentional.
The tree is useful for UI, but it is not the main data structure for runtime decoding.
-
+
Why the Runtime Decode Layer Exists
A tree structure is convenient for browsing, but a runtime decoder needs something different:
@@ -181,7 +182,7 @@ Why the Runtime Decode Layer Exists
This avoids forcing UI-oriented structures into a decode role they were not meant for.
-
+
Module Layout
core/ C++17 parser, statement handlers, metadata, tree, and decoder
examples/ Command-line demo (built separately)
@@ -194,13 +195,13 @@ Module Layout
Component Source files
-Parsed metadata core/dbc_database.h , core/frame_info.h , core/signal_info.h
+
Parsed metadata core/dbc_database.h , core/frame_info.h , core/signal_info.h
Parser and dispatch core/dbc_parser.*, core/dbc_diagnostic.h , core/dbc_statement_handler.*, core/typefactory.h
UI tree core/tree_node.*, core/dbc_tree_builder.*
-Runtime database core/decode_database.h , core/dbc_decode_builder.*
+
Runtime database core/decode_database.h , core/dbc_decode_builder.*
Decoder core/dbc_decoder.*
@@ -209,9 +210,9 @@ Module Layout
Build integration core/core.pro, core/core_files.pri, core/core.pri
-
+
Parsed Data Structures
-
+
<tt>SignalInfo</tt>
Represents one signal as parsed from the DBC file.
Fields:
@@ -238,7 +239,7 @@ Parsed Data Structures
Physical value rule:
physical = raw * factor + offset
-
+
<tt>FrameInfo</tt>
Represents one frame as parsed from the DBC file.
Fields:
@@ -257,10 +258,10 @@ Parsed Data Structures
signals is a list of SignalInfo
isExtended is determined during CAN ID normalization
-pgn is derived using simplified J1939 logic when applicable
+pgn is derived for extended frames only with explicit J1939 opt-in (see below)
-
+
<tt>DbcDatabase</tt>
Top-level parsed DBC container.
Conceptually:
@@ -268,9 +269,9 @@ Parsed Data Structures
└── vector<FrameInfo>
This is the central structure produced by DbcParser .
-
+
UI Tree Layer
-
+
<tt>TreeNode</tt>
The UI tree contains three node types:
-The tree supports browsing through the optional DbcTreeModel adapter.
+The tree is independent of Qt and supports browsing through the optional DbcTreeModel adapter. GetParent() returns a non-owning parent pointer; GetRow() returns the zero-based sibling position (zero for a detached node or root). GetChild() returns nullptr outside the child range, and AddChild() ignores null children. Appending children preserves existing addresses and rows.
+Nodes cannot be copied or moved. Transfer their std::unique_ptr ownership to preserve parent links and addresses. AddChild() accepts an rvalue ownership handle and rejects self/ancestor insertion and already-attached children with std::invalid_argument before consuming ownership. There is no detach or reparent operation; callers must supply exclusive ownership.
+GetFrameKey() returns std::optional<FrameKey > for frame nodes and signals directly attached to a frame. GetSignalKey() returns std::optional<SignalKey > for those signals. Roots, detached signals, and signals without a frame parent have no key. Keys use normalized CAN ID plus standard/extended type, and signal keys also include the signal name. They match runtime definition keys, remain independent of row order and frame display names, and survive source-database changes or destruction. Renaming a signal changes its logical identity. Returned keys are values and may be retained after destroying the tree.
It is not the primary runtime decode structure.
-
+
Runtime Decode Layer
-
+
Purpose
The decode layer exists so that decoding can be fast and independent from UI concerns.
Instead of searching a tree, the decoder uses a prepared database with direct lookup.
-
+
<tt>ByteOrder</tt>
Runtime byte order enum:
@@ -311,7 +314,7 @@ Purpose
This is better for decode code than passing around raw DBC characters.
-
+
<tt>ValueType</tt>
Numeric type enum:
@@ -320,7 +323,7 @@ Purpose
This is clearer than combining multiple boolean flags during runtime logic.
-
+
<tt>DecodeSignal</tt>
Represents one runtime-ready signal definition.
Fields:
@@ -340,7 +343,7 @@ Purpose
This structure contains all information required for extracting and converting a signal value from raw frame data.
-
+
<tt>DecodeFrame</tt>
Represents one runtime-ready frame definition.
Fields:
@@ -357,7 +360,7 @@ Purpose
This structure is used directly by the decoder.
-
+
<tt>FrameKey</tt>
Stable identifier for runtime frame matching and application state.
Fields:
@@ -367,9 +370,9 @@ Purpose
This matters because the same numeric identifier must not be confused between standard and extended frames.
-
+
<tt>DecodeDatabase</tt>
-Immutable runtime snapshot with a private frame index. Build it with DbcDecodeBuilder::Build(parsed) or construct it from std::vector<DecodeFrame >. Construction validates all definitions before publishing the snapshot and throws std::invalid_argument for invalid metadata, including manually supplied data:
+Immutable runtime snapshot with a private frame index. Build it with DbcDecodeBuilder::Build(parsed) or construct it from std::vector<DecodeFrame >. Construction validates all definitions and duplicate keys before building the lookup index or publishing the snapshot, and throws std::invalid_argument for invalid metadata, including manually supplied data:
Normalized CAN IDs must fit 11 bits for standard frames or 29 bits for extended frames. DBC's bit-31 encoding flag must already be removed.
Frame keys must be unique; signal names must be unique within their frame.
@@ -388,9 +391,9 @@ Purpose
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
-
+
<tt>RawCanFrame</tt>
Represents a raw CAN frame to decode.
Fields:
@@ -406,7 +409,7 @@ Decoder Layer
unit tests
-
+
<tt>DecodedSignalValue</tt>
Represents one decoded signal result.
Fields:
@@ -419,7 +422,7 @@ Decoder Layer
status
-
+
Raw value representation and precision
DecodedSignalValue::rawValue is a C++17 std::variant<std::int64_t, std::uint64_t>. For a valid signal, signed definitions produce the int64_t alternative and unsigned definitions produce the uint64_t alternative. Raw values remain exact across their full 64-bit ranges. Check valid before using the physical value. Raw data is also available when status == PhysicalConversionFailed; other invalid results have no decoded numeric data.
Use std::get when the numeric type is known, or std::get_if to handle both:
@@ -431,7 +434,7 @@ Raw value representation and precision
This replaces the previous int64_t field: consumers that read or print rawValue directly must handle the variant.
Physical conversion uses the active numeric type: physicalValue = static_cast<double>(raw) * factor + offset. physicalValue remains a double and is approximate for large integers. On usual IEEE 754 binary64 implementations, integers are exactly representable through 2^53; above that, some integers round to the same floating-point value. For example, unsigned UINT64_MAX remains exact in rawValue, but converts to approximately 18446744073709551616 in binary64 before scaling. Use rawValue whenever exact integer values are required.
-
+
<tt>DecodedFrameValue</tt>
Represents one decoded frame result.
Fields:
@@ -442,32 +445,34 @@ Raw value representation and precision
valid
status
-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, a null definition, its requested key, and an empty signal list.
+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 or ambiguous frame returns valid == false, a null definition, its requested key, and an empty signal list. A successful PGN match uses the DBC definition key for the frame and its signals.
FrameDecodeStatus summarizes the result:
Status Meaning
-UnknownFrame No definition matches both CAN ID and standard/extended type
+UnknownFrame No exact CAN ID/type match or eligible PGN match
-InsufficientPayload Actual byte count is less than the declared dlc
+AmbiguousFrame No exact match and multiple J1939 definitions share the PGN
-SignalErrors Payload is long enough, but at least one signal failed
+InsufficientPayload Actual byte count is less than the declared dlc
+SignalErrors Payload is long enough, but at least one signal failed
+
Valid Payload is long enough and every signal is valid or inactive
Short-payload status takes precedence over signal errors; inspect each signal's status for the individual cause. valid retains its existing meaning of a matched definition and does not imply status == FrameDecodeStatus::Valid.
Payload policy uses dlc as a byte count, including for CAN FD; it is not the encoded wire DLC. A shorter payload is never padded: all signals whose bytes are available still decode, even if other signals fail. A longer payload is accepted; bytes beyond dlc are ignored. Signal bit layouts must fit the declared dlc, so extra bytes cannot rescue an invalid definition. Empty payloads and zero-byte frame definitions follow the same rules. Results include every signal in definition order, preserving successful values and definition handles on partial failures.
The decoder applies factor and offset; it does not clamp physical values to the declared minimum and maximum. Non-finite conversion results (NaN or positive/ negative infinity), including overflow with finite factor/offset, produce PhysicalConversionFailed. The exact raw value and non-finite physicalValue remain available, while signal valid is false. Non-finite numeric parameters are rejected during database construction. Finite parameters can still overflow during conversion; conversion failure of a selector does not prevent raw branch selection.
-
+
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. Constructor input is copied and may be changed independently afterward. 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.
+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.
@@ -475,22 +480,23 @@ Stable frame and signal identifiers
-
std::shared_ptr<const DecodeSignal> current = runtime.FindSignal(selection);
+
std::shared_ptr<const DecodeSignal> current = runtime.
FindSignal (selection);
}
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.
-
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...
-
-
-
One decoded signal value.
-
-
-
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.
+Runtime CAN decoder using prebuilt decode database.
+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...
+std::shared_ptr< const DecodeSignal > FindSignal(const SignalKey &key) const
Return an owning signal handle, or an empty handle for a missing key.
+
+
+One decoded signal value.
+
+
+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:
@@ -507,7 +513,7 @@ Stable frame and signal identifiers
Decode(...)
-
+
Parser Support
The current parser supports the following DBC elements:
@@ -518,23 +524,25 @@ 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.
+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.
std::cerr << diagnostic.filePath << ":" << diagnostic.lineNumber
<< ": " << diagnostic.message << '\n' ;
}
-
if (!result.HasErrors()) {
-
+
+
}
-
-
DbcParseResult ParseFileWithDiagnostics(const std::string &filePath) const
Parse with warnings and a structured first error instead of throwing.
-
-
+
+
DbcParseResult ParseFileWithDiagnostics(const std::string &filePath) const
Parse with warnings and a structured first error instead of throwing.
+
Diagnostic message and physical source location.
+
Parsed database and diagnostics; the database is empty on error.
+
bool HasErrors() const
Return whether any diagnostic has error severity.
+
Severity / code Meaning
@@ -543,7 +551,7 @@ Structured diagnostics
Error / FileReadError Input cannot be read completely
-Error / InvalidStatement Invalid frame/signal definition, duplicate, or payload violation
+Error / InvalidStatement Invalid frame/signal definition or comment, unresolved comment reference, duplicate, or payload violation
Error / InvalidValueDescription Invalid VAL_ syntax, duplicate value, or unresolved reference
@@ -553,14 +561,25 @@ Structured diagnostics
Error / UnsupportedStatement Extended multiplexing (SG_MUL_VAL_) rejected
-Parsing stops at the first error and returns an empty database, together with any preceding warnings and the error. Deferred VAL_ and multiplexing errors retain their original source lines. Invalid signal markers use InvalidStatement. HasErrors() checks severity; warnings alone do not make a parse fail.
-Unknown statements are reported conservatively, including SIG_VALTYPE_, attributes (BA_, BA_DEF_, defaults and relation forms), signal types/references, environment variables, named VAL_TABLE_ tables, and vendor extensions. For example, ignoring SIG_VALTYPE_ may decode a floating-point signal as an integer. The parser does not implement the warned features; consumers should review warnings.
-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.
+Parsing stops at the first error and returns an empty database, together with any preceding warnings and the error. Deferred comment, VAL_, and multiplexing errors retain their original source lines. Invalid signal markers use InvalidStatement. HasErrors() checks severity; warnings alone do not make a parse fail.
+Unknown statements are reported conservatively, including SIG_VALTYPE_, attribute relation forms (BA_REL_, BA_DEF_REL_), signal types/references, environment variables, named VAL_TABLE_ tables, and vendor extensions. For example, ignoring SIG_VALTYPE_ may decode a floating-point signal as an integer. The parser does not implement the warned features; consumers should review warnings.
+
+Attributes and frame metadata
+BA_DEF_, BA_DEF_DEF_, and BA_ support database, BO_, SG_, BU_, and EV_ scopes with INT, HEX, FLOAT, STRING, and ENUM definitions. Integer/HEX values use decimal signed 64-bit numbers; floating values are finite and locale independent. ENUM assignments use zero-based indices; defaults accept an index or a quoted label. Strings support escaped quotes and backslashes. Each statement occupies one physical line and ends with ;.
+BA_DEF_ BO_ "VFrameFormat" ENUM "StandardCAN","ExtendedCAN","StandardCAN_FD";
+
BA_DEF_DEF_ "VFrameFormat" "StandardCAN";
+
BA_DEF_ BO_ "GenMsgCycleTime" INT 0 10000;
+
BA_DEF_DEF_ "GenMsgCycleTime" 100;
+
BA_ "GenMsgCycleTime" BO_ 256 20;
+
Definitions, defaults, assignments, and frame/signal declarations may appear in any order. Defaults apply to every object of the defined scope; explicit values override them, with the last repeated assignment winning. Duplicate definitions or defaults, undefined names, wrong types/scopes, out-of-range values, and missing frame/signal targets produce Error / InvalidAttribute at the source line.
+DbcDatabase::attributeDefinitions retains types, ranges, enum labels, and defaults; attributeAssignments retains explicit values and targets. Effective values are available in attributes on the database, frames and signals. Node/environment assignments are retained by name without checking declarations; their defaults remain on the definitions. Frame/signal attributes are copied into runtime snapshots and tree payloads. Other valid attributes remain available as metadata without changing decoding.
+FrameInfo and DecodeFrame expose optional frameFormat (the enum label) and cycleTimeMs (GenMsgCycleTime, unsigned 32-bit milliseconds). Missing values remain unset; zero cycle time means unspecified. StandardCAN and ExtendedCAN are recognized. Other format labels, including CAN FD and J1939PG, are preserved with Warning / UnsupportedAttribute when effective on a frame. A supported format conflicting with the encoded BO_ ID also warns. Warnings identify the assignment or default line. Attributes do not change CAN ID normalization or automatically enable CAN FD or J1939 decoding; J1939 still requires parser opt-in. Use ParseFileWithDiagnostics() to review these warnings.
+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. Frame and signal comments may span physical lines and resolve after definitions are read; other supported statements 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
@@ -572,7 +591,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.
@@ -581,7 +600,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
@@ -600,15 +619,15 @@ 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.
-
Factor, offset, minimum, and maximum accept signed decimal numbers, fractions, and scientific notation. The entire numeric token must be valid; hexadecimal numbers, NaN, infinity, conversion overflow, and conversion underflow are rejected. Minimum must not exceed maximum. Zero and negative factors are allowed.
+
Factor, offset, minimum, and maximum accept signed decimal numbers, fractions, and scientific notation. Conversion is independent of the application's C and C++ locales: the decimal separator is always a dot (.), and comma decimals and digit grouping are rejected. The entire numeric token must be valid; hexadecimal numbers, NaN, infinity, conversion overflow, and conversion underflow (including subnormal values) are rejected. Minimum must not exceed maximum. Zero and negative factors are allowed.
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
@@ -637,7 +656,7 @@ Basic multiplexing
All statuses except Valid have valid == false and GetValueDescription() returns nullptr. PhysicalConversionFailed preserves extracted raw data and the non-finite conversion result; other invalid statuses have no decoded numeric data. Check status to distinguish inactive branches from errors. Consumers constructing runtime metadata manually receive the same selector and non-overlap validation as parsed files. 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";
@@ -648,8 +667,10 @@ Comments
FrameInfo::comment
SignalInfo::comment
+
Comments accept spaces and tabs between fields, quotes and backslashes escaped with a preceding backslash, and text spanning multiple physical lines. Newlines, blank lines, and indentation inside quoted text are preserved; CRLF becomes LF. Comments may appear before their frame or signal definitions. References use the same decimal CAN ID validation and normalization as BO_, including reserved-bit and overflow checks and distinct standard/extended targets. Repeated comments apply in statement order, so the last comment wins, including empty text.
+
Malformed supported comments (including invalid escapes, missing quotes or semicolon, and trailing text) and missing frame/signal references produce an InvalidStatement error at the comment's starting line. Failed parses return an empty database; ParseFile throws with the same source location.
-
+
CAN ID Normalization
The parser normalizes frame identifiers.
Common DBC behavior:
@@ -664,18 +685,29 @@ 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:
+
+J1939 Opt-in and PGN Lookup
+
Extended CAN identifiers do not imply J1939. The default parser leaves hasPgn false and pgn zero, and decoding uses exact normalized CAN ID and frame type. Enable J1939 interpretation explicitly for a file:
+
+
+
+
+
DbcDatabase ParseFile(const std::string &filePath) const
Parse DBC file.
+
Parsed DBC content stored in a simple internal form.
+
+
+
Both parser entry points honor this option. Standard frames remain ordinary CAN. For mixed-protocol files, parse with the default options, then set hasPgn = true and pgn = ExtractJ1939Pgn(frame.canId) (from j1939.h ) only on known J1939 extended definitions before building the runtime snapshot. The same explicit metadata enables J1939 for manually constructed DecodeFrame definitions. Runtime construction rejects hasPgn on standard frames or an inconsistent PGN. No DBC attribute automatically enables J1939 interpretation.
+
PGN extraction retains both data-page bits (CAN ID bits 25–24) and PF:
-pf
-ps
-dp
+PDU1 (PF < 240): PS is the destination address and is zeroed in the PGN.
+PDU2 (PF >= 240): PS is the group extension and remains part of the PGN.
+Priority and source address are excluded in both cases. This follows the Linux J1939 PGN layout .
-
This is enough for a practical start but should not be treated as full J1939 validation.
+
DecodeDatabase::FindFrame(FrameKey) stays an exact lookup. FindFrameByPgn(pgn) returns a PgnLookupResult with an owning definition handle for one eligible definition. No match returns a null handle with ambiguous == false; multiple definitions return a null handle with ambiguous == true. Copies and returned handles retain the immutable snapshot.
+
DbcDecoder::FindFrame and both Decode overloads first try the exact ID/type. Only when that fails for a valid normalized extended ID do they try PGN lookup among definitions with hasPgn == true. A unique PGN can therefore match a changed source address or priority, and for PDU1 a changed destination address. A changed PDU2 group extension does not match. Exact matches win even when the PGN is ambiguous, including exact matches to ordinary extended CAN definitions. Multiple PGN candidates are never resolved by order, source, or payload: FindFrame returns null and Decode returns AmbiguousFrame without decoding signals or validating the selection. Missing candidates return UnknownFrame.
+
On success, decoded frame/signal keys belong to the matched DBC definition; selected-signal decoding also expects those definition keys. Keep the input RawCanFrame if the received address/ID is needed separately. This feature does not implement transport-protocol reassembly, address claiming, or full J1939 validation.
-
+
Decode Flow
Typical runtime decode flow:
RawCanFrame
@@ -690,7 +722,7 @@ Decode Flow
↓
DecodedFrameValue
-
+
Intel and Motorola Extraction
The decoder currently has separate extraction paths:
@@ -701,34 +733,32 @@ 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:
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
-
+Runtime decode database builder.
+CAN frame decoding API and result types.
+DBC file parser and interpretation options.
+
+
Parse DBC
-
DbcDatabase ParseFile(const std::string &filePath) const
Parse DBC file.
-
Parsed DBC content stored in a simple internal form.
-
+
Build UI tree
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
+
Decode a raw frame
@@ -742,7 +772,7 @@ Decode a raw frame
-
+
Unified Decode Strategy
A key design goal is that the same decoder should work for both:
@@ -750,7 +780,7 @@ Unified Decode Strategy
trace replay frames
That means this architecture supports:
-
+
live path
live CAN input
↓
@@ -759,7 +789,7 @@ live path
DbcDecoder
↓
decoded signal values
-
+
trace path
trace reader
↓
@@ -770,7 +800,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:
@@ -796,7 +826,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.
@@ -808,302 +838,188 @@ Why the Tree Is Not Enough
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:
+The dispatcher uses TypeFactory <std::string, DbcStatementHandler > to create registered handlers once per parsing session, then reuses them for all matching lines:
Grammar implementations live in core/dbc_statement_handler.cpp ; their interface, context, and dispatcher live in core/dbc_statement_handler.h . core/typefactory.h provides the generic registry and object creation.
-To add a construct, implement a default-constructible handler deriving from DbcStatementHandler with:
+To add a construct, implement a default-constructible handler deriving from DbcStatementHandler with:
void Handle(
const std::string &line,
DbcParseContext &context)
const override ;
-
+
Register it in the dispatcher constructor:
RegisterType<MyCustomHandler>("CUSTOM_" );
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
SG_ State : 0|8@1+ (1,0) [0|255] "" ECU
VAL_ 256 State 0 "Off" 1 "On" 2 "Error";
-
Each statement must occupy one physical line, contain at least one integer/text pair, and end with a semicolon. Spaces and tabs are accepted between fields; descriptions may contain whitespace, semicolons, and empty text. Inside quoted text, \"</tt> and <tt>\\\\</tt> represent a quote and a backslash; other escapes are rejected.
-Keys are decimal integers in <tt>INT64_MIN..UINT64_MAX</tt>, with an optional minus
-sign; plus signs, fractions, hexadecimal numbers, exponents, and overflow are
-rejected. Keys never pass through <tt>double</tt>.
-
-<tt>VAL_</tt> may appear before or after its frame and signal declarations. References
-are resolved after reading the file using the same CAN ID normalization as
-<tt>BO_</tt>, including bit 31 for extended identifiers. Standard and extended frames
-with the same normalized ID remain distinct. Missing or ambiguous references,
-malformed statements, and duplicate integer keys produce <tt>path:line: description</tt>
-errors at the originating <tt>VAL_</tt> line. Distinct keys from multiple statements
-are merged; <tt>0</tt>, <tt>00</tt>, and <tt>-0</tt> are the same key. Keys need not fit the referenced
-signal's bit width or signedness; unreachable keys simply cannot match a decode.
-
-Mappings are available as <tt>SignalInfo::valueDescriptions</tt> and
-<tt>DecodeSignal::valueDescriptions</tt>, and survive both database builders, including
-<tt>TreeNode::GetSignal()</tt>. Consumers can look up a decoded result directly:
-
-@icode{cpp}
-const DecodedSignalValue &value = decodedFrame.signals.at(0);
-if (const std::string *description = value.GetValueDescription()) {
- std::cout << *description;
-}
-@endicode
-
-<tt>GetValueDescription()</tt> uses the exact raw integer before factor/offset scaling.
-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 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
-<tt>RawSignalValue</tt> (<tt>std::variant\<std::int64_t, std::uint64_t\></tt>). The helper matches
-nonnegative signed and unsigned values identically and keeps negative values
-distinct from large unsigned values. Stored keys use negative <tt>int64_t</tt> and
-nonnegative <tt>uint64_t</tt>; when constructing mappings manually, normalize keys
-with <tt>NormalizeValueKey()</tt> before insertion.
-
-Named <tt>VAL_TABLE_</tt> tables, environment-variable mappings, multiline statements,
-are outside this implementation; the optional Qt adapter exposes signal mappings.
-
-<hr>
-
-@section autotoc_md117 Current Limitations
-
-This is still a minimal implementation.
-
-Not supported yet:
-
-- extended and nested multiplexing (<tt>SG_MUL_VAL_</tt>, <tt>mNM</tt>)
-- named <tt>VAL_TABLE_</tt> tables and environment-variable value descriptions
-- <tt>BA_</tt> attributes
-- <tt>BA_DEF_</tt> definitions and attribute defaults
-- <tt>SIG_VALTYPE_</tt> floating-point signal types
-- signal types/references (<tt>SGTYPE_</tt>, <tt>SIG_TYPE_REF_</tt>) and environment variables
-- advanced comment handling
-- full DBC grammar coverage
-- full J1939 validation
-- extensive edge-case handling for unusual DBC formatting
-
-Additional behavior to account for:
-
-- unregistered DBC keywords are skipped with warnings in the diagnostic API
-- an <tt>SG_</tt> statement before the first frame is rejected
-- duplicate frame keys (normalized CAN ID and frame type) and repeated signal
- names within a frame are rejected at their definition lines; manually created
- databases are also checked for ambiguous <tt>VAL_</tt> references during resolution
-- payload lengths are checked against storage bounds (<tt>0..255</tt>), rather than
- CAN or CAN FD protocol limits
-- comment handling is limited to the supported forms and already parsed targets
-
-Motorola extraction uses DBC sawtooth numbering: a start bit of 7 traverses
-<tt>7..0, 15..8, 23..16</tt>. Regression tests cover aligned and unaligned signals,
-byte boundaries, and 64-bit values.
-
-<hr>
-
-@section autotoc_md119 Recommended Next Steps
-
-A practical development order would be:
-
-@subsection autotoc_md120 Stage 1 - already implemented
-
-- <tt>BO_</tt>
-- <tt>SG_</tt>
-- <tt>CM_</tt>
-- <tt>VAL_</tt> signal value descriptions
-- normalized CAN ID
-- <tt>isExtended</tt>
-- transmitter
-- receivers
-- comments
-- tree representation
-- runtime decode database
-- runtime decoder
-
-@subsection autotoc_md121 Stage 2
-
-Recommended additions:
-
-- selective decoding of only chosen signals
-
-@subsection autotoc_md122 Stage 3
-
-Recommended additions:
-
-- basic multiplexing (implemented)
-- attribute parsing
-- richer J1939 support
-- CSV export of decoded traces
-- optimized filtering and signal selection
-
-@subsection autotoc_md123 Stage 4
-
-Advanced functionality:
-
-- live plot integration
-- signal subscriptions
-- per-signal trace decode pipelines
-- decoder-assisted export formats
-
-<hr>
-
-@section autotoc_md125 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
-systems can compile the sources listed in <tt>core/core_files.pri</tt>; no CMake
-configuration is currently provided.
-
-Qt-dependent qmake targets share <tt>qt/qt_version.pri</tt>, which rejects Qt versions
-other than 6.8.2. The core library remains independent of Qt libraries.
-
-Open <tt>dbc.pro</tt> in Qt Creator to see two subprojects: <tt>core</tt> and <tt>tests</tt>.
-<tt>core/core.pro</tt> builds the C++17 static library <tt>dbc_core</tt> without a Qt dependency.
-<tt>tests/tests.pro</tt> builds the QtTest executable <tt>dbc_tests</tt> and links that library.
-The root project declares <tt>tests.depends = core</tt> for parallel builds.
-
-Build out of source with Qt 6.8.2:
-
-@icode{sh}
-mkdir build
-cd build
-qmake6 ../dbc.pro
-make -j
-make check
-@endicode
-
-<tt>core/core_files.pri</tt> lists the library sources and headers.
-Consumers include <tt>core/core.pri</tt> for include paths and library linkage; the test
-source lists live in <tt>tests/parser_tests.pri</tt> and <tt>tests/decoder_tests.pri</tt>.
-When building a consumer separately, pass
-<tt>DBC_CORE_BUILD_DIR=/absolute/path/to/build/core</tt> to qmake.
-
-@subsection autotoc_md126 Build core without Qt libraries
-
-From the repository root:
-
-@icode{sh}
-mkdir -p build/core
-cd build/core
-qmake6 ../../core/core.pro
-make -j
-@endicode
-
-qmake is still the build tool; this target does not link Qt libraries.
-
-@subsection autotoc_md127 Optional Qt model adapter
-
-The adapter and its <tt>QAbstractItemModelTester</tt> suite use Qt 6.8.2.
-The adapter itself links only Qt Core.
-
-The model test executable additionally links QtGui and uses QGuiApplication so
-QAbstractItemModelTester can resolve graphical metatypes such as QPixmap. It
-defaults to the <tt>offscreen</tt> platform when <tt>QT_QPA_PLATFORM</tt> is unset or empty;
-no display server is required. An explicit platform setting is preserved.
-
-Enable its library and focused QtTest suite:
-
-@icode{sh}
-mkdir -p build-qt
-cd build-qt
-qmake6 ../dbc.pro CONFIG+=dbc_qt
-make -j
-make check
-@endicode
-
-Consumers include <tt>qt/qt.pri</tt> instead of <tt>core/core.pri</tt>, and set
-<tt>DBC_CORE_BUILD_DIR</tt> and <tt>DBC_QT_BUILD_DIR</tt> to the corresponding library build
-directories when building separately. A widget application also needs <tt>QT += widgets</tt>. The adapter integration enables
-<tt>no_keywords</tt>, because core metadata has a <tt>signals</tt> member; use <tt>Q_SIGNALS</tt>,
-<tt>Q_SLOTS</tt>, and <tt>Q_EMIT</tt> in consuming Qt classes.
-
-@icode{cpp}
-#include "dbc_parser.h "
-#include "dbc_tree_builder.h "
-#include "dbc_tree_model.h "
-#include <QTreeView>
-
-// Run after constructing QApplication; view owns the model through QObject.
-QTreeView view;
-DbcTreeModel *model = new DbcTreeModel(&view);
-model->SetTree(DbcTreeBuilder().Build(DbcParser().ParseFile("example.dbc")));
-view.setModel(model);
-view.expandAll();
-view.show();
-// On reload, pass a newly built tree to SetTree(); to clear:
-// model->SetTree(nullptr);
-@endicode
-
-The root is invisible: frames are top-level rows, signals are their children.
-Only column zero has children. <tt>parent()</tt> always returns column zero.
-The model takes exclusive ownership of the tree; do not retain mutable aliases.
-Metadata is copied by the tree builder, so the parsed database may be destroyed.
-<tt>TreeNode::GetParent()</tt> is non-owning and <tt>GetRow()</tt> gives the zero-based sibling
-position (zero for a detached node/root). Nodes cannot be copied or moved;
-transferring their <tt>unique_ptr</tt> ownership preserves addresses and navigation.
-
-Call <tt>SetTree()</tt> on the model's thread. It accepts a detached Root or nullptr,
-uses <tt>beginResetModel()</tt>/<tt>endResetModel()</tt>, and destroys the previous tree during
-reset. All ordinary QModelIndex values expire on reset and must not be reused;
-QPersistentModelIndex values are invalidated by Qt. Destroying the model also
-invalidates indexes. Invalid and foreign indexes return no data/flags/children.
-Valid items are enabled and selectable, with no editing support.
-
-<table class="markdownTable">
- <tr class="markdownTableHead"> <th class="markdownTableHeadNone"> Column (zero-based enum)
- Frame display
- Signal display
-
- 0 Name
- Name
- Name
-
- 1 CanId
- Normalized hexadecimal ID
- Empty
-
- 2 PayloadLength
- Bytes
- Empty
-
- 3 StartBit
- Empty
- DBC start bit
-
- 4 BitLength
- Empty
- Bit count
-
- 5 ByteOrder
- Empty
- Intel / Motorola
-
- 6 Signed
- Empty
- Signed / Unsigned
-
- 7 Unit
- Empty
- Unit
-
- 8 Comment
- Comment
- Comment
-
-Horizontal DisplayRole headers describe these columns; other header requests return invalid QVariant. ToolTipRole returns the comment on every column. Custom roles also apply on every column; inapplicable roles return invalid QVariant:
-
+Each statement must occupy one physical line, contain at least one integer/text pair, and end with a semicolon. Spaces and tabs are accepted between fields; descriptions may contain whitespace, semicolons, and empty text. Inside quoted text, escape a quote or a backslash with a preceding backslash; other escapes are rejected. Keys are decimal integers in INT64_MIN..UINT64_MAX, with an optional minus sign; plus signs, fractions, hexadecimal numbers, exponents, and overflow are rejected. Keys never pass through double.
+VAL_ may appear before or after its frame and signal declarations. References are resolved after reading the file using the same CAN ID normalization as BO_, including bit 31 for extended identifiers. Standard and extended frames with the same normalized ID remain distinct. Missing or ambiguous references, malformed statements, and duplicate integer keys produce path:line: description errors at the originating VAL_ line. Distinct keys from multiple statements are merged; 0, 00, and -0 are the same key. Keys need not fit the referenced signal's bit width or signedness; unreachable keys simply cannot match a decode.
+Mappings are available as SignalInfo::valueDescriptions and DecodeSignal::valueDescriptions , and survive both database builders, including TreeNode::GetSignal() . Consumers can look up a decoded result directly:
+
+
+
std::cout << *description;
+
}
+
const std::string * GetValueDescription() const
+
GetValueDescription() uses the exact raw integer before factor/offset scaling. 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 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 RawSignalValue (std::variant<std::int64_t, std::uint64_t>). The helper matches nonnegative signed and unsigned values identically and keeps negative values distinct from large unsigned values. Stored keys use negative int64_t and nonnegative uint64_t; when constructing mappings manually, normalize keys with NormalizeValueKey() before insertion.
+Named VAL_TABLE_ tables, environment-variable mappings, multiline statements, are outside this implementation; the optional Qt adapter exposes signal mappings.
+
+
+Current Limitations
+This is still a minimal implementation.
+Not supported yet:
+
+extended and nested multiplexing (SG_MUL_VAL_, mNM)
+named VAL_TABLE_ tables and environment-variable value descriptions
+attribute relation forms (BA_REL_, BA_DEF_REL_)
+SIG_VALTYPE_ floating-point signal types
+signal types/references (SGTYPE_, SIG_TYPE_REF_) and environment variables
+advanced comment handling
+full DBC grammar coverage
+full J1939 validation
+extensive edge-case handling for unusual DBC formatting
+
+Additional behavior to account for:
+
+unregistered DBC keywords are skipped with warnings in the diagnostic API
+an SG_ statement before the first frame is rejected
+duplicate frame keys (normalized CAN ID and frame type) and repeated signal names within a frame are rejected at their definition lines; manually created databases are also checked for ambiguous VAL_ references during resolution
+payload lengths are checked against storage bounds (0..255), rather than CAN or CAN FD protocol limits
+comment handling is limited to frame and signal comments; references resolve after definitions are read
+
+Motorola extraction uses DBC sawtooth numbering: a start bit of 7 traverses 7..0, 15..8, 23..16. Regression tests cover aligned and unaligned signals, byte boundaries, and 64-bit values.
+
+
+Recommended Next Steps
+A practical development order would be:
+
+Stage 1 - already implemented
+
+BO_
+SG_
+CM_
+VAL_ signal value descriptions
+normalized CAN ID
+isExtended
+transmitter
+receivers
+comments
+tree representation
+runtime decode database
+runtime decoder
+
+
+Stage 2
+Recommended additions:
+
+selective decoding of only chosen signals
+
+
+Stage 3
+Recommended additions:
+
+basic multiplexing (implemented)
+attribute parsing (implemented for definitions, defaults and values)
+richer J1939 support
+CSV export of decoded traces
+optimized filtering and signal selection
+
+
+Stage 4
+Advanced functionality:
+
+live plot integration
+signal subscriptions
+per-signal trace decode pipelines
+decoder-assisted export formats
+
+
+
+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 systems can compile the sources listed in core/core_files.pri; no CMake configuration is currently provided.
+Qt-dependent qmake targets share qt/qt_version.pri, which rejects Qt versions other than 6.8.2. The core library remains independent of Qt libraries.
+Open dbc.pro in Qt Creator to see two subprojects: core and tests. core/core.pro builds the C++17 static library dbc_core without a Qt dependency. tests/tests.pro builds the QtTest executable dbc_tests and links that library. The root project declares tests.depends = core for parallel builds.
+Build out of source with Qt 6.8.2:
+mkdir build
+
cd build
+
qmake6 ../dbc.pro
+
make -j
+
make check
+
core/core_files.pri lists the library sources and headers. Consumers include core/core.pri for include paths and library linkage; the test source lists live in tests/parser_tests.pri and tests/decoder_tests.pri. When building a consumer separately, pass DBC_CORE_BUILD_DIR=/absolute/path/to/build/core to qmake.
+
+Build core without Qt libraries
+From the repository root:
+mkdir -p build/core
+
cd build/core
+
qmake6 ../../core/core.pro
+
make -j
+
qmake is still the build tool; this target does not link Qt libraries.
+
+Optional Qt model adapter
+The adapter and its QAbstractItemModelTester suite use Qt 6.8.2. The adapter itself links only Qt Core.
+The model test executable additionally links QtGui and uses QGuiApplication so QAbstractItemModelTester can resolve graphical metatypes such as QPixmap. It defaults to the offscreen platform when QT_QPA_PLATFORM is unset or empty; no display server is required. An explicit platform setting is preserved.
+Enable its library and focused QtTest suite:
+mkdir -p build-qt
+
cd build-qt
+
qmake6 ../dbc.pro CONFIG+=dbc_qt
+
make -j
+
make check
+
Consumers include qt/qt.pri instead of core/core.pri, and set DBC_CORE_BUILD_DIR and DBC_QT_BUILD_DIR to the corresponding library build directories when building separately. A widget application also needs QT += widgets. The adapter integration enables no_keywords, because core metadata has a signals member; use Q_SIGNALS, Q_SLOTS, and Q_EMIT in consuming Qt classes.
+
+
+
#include "dbc_tree_model.h"
+
#include <QTreeView>
+
+
+
QTreeView view;
+
+
+
view.setModel(model);
+
view.expandAll();
+
view.show();
+
+
+
+
void SetTree(std::unique_ptr< TreeNode > root)
Replace the tree and invalidate indexes; reject roots with a parent or non-root type.
+
The root is invisible: frames are top-level rows, signals are their children. Only column zero has children. parent() always returns column zero. The model takes exclusive ownership of the tree; do not retain mutable aliases. Metadata is copied by the tree builder, so the parsed database may be destroyed. TreeNode::GetParent() is non-owning and GetRow() gives the zero-based sibling position (zero for a detached node/root). Nodes cannot be copied or moved; transferring their unique_ptr ownership preserves addresses and navigation.
+Call SetTree() on the model's thread. It accepts a detached Root or nullptr, uses beginResetModel()/endResetModel(), and destroys the previous tree during reset. All ordinary QModelIndex values expire on reset and must not be reused; QPersistentModelIndex values are invalidated by Qt. Destroying the model also invalidates indexes. Invalid and foreign indexes return no data/flags/children. Valid items are enabled and selectable, with no editing support.
+
+
+Column (zero-based enum) Frame display Signal display
+
+0 Name Name Name
+
+1 CanId Normalized hexadecimal ID Empty
+
+2 PayloadLength Bytes Empty
+
+3 StartBit Empty DBC start bit
+
+4 BitLength Empty Bit count
+
+5 ByteOrder Empty Intel / Motorola
+
+6 Signed Empty Signed / Unsigned
+
+7 Unit Empty Unit
+
+8 Comment Comment Comment
+
+Horizontal DisplayRole headers describe these columns; other header requests return invalid QVariant. ToolTipRole returns the comment on every column. Custom roles also apply on every column; inapplicable roles return invalid QVariant:
+
Role Node types QVariant content
@@ -1121,61 +1037,47 @@ Valid items are enabled and selectable, with no editing support.
ValueDescriptionsRole Signal QVariantList of QVariantMap entries
-
-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.
-
-
+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:
-
c++ -std=c++17 -Icore tests/tree_node_test.cpp core/tree_node.cpp \
+
From the repository root, use only a C++17 compiler:
+
c++ -std=c++17 -Icore tests/tree_node_test.cpp core/tree_node.cpp \
core/dbc_tree_builder.cpp -o /tmp/dbc_tree_node_test
/tmp/dbc_tree_node_test
-
-
-
+
Build and run the demo
-
-After building core, run these commands from the repository root:
-
mkdir -p build/examples
+
After building core, run these commands from the repository root:
+
mkdir -p build/examples
cd build/examples
qmake6 ../../examples/demo.pro DBC_CORE_BUILD_DIR=../core
make -j
./dbc_demo /absolute/path/to/example.dbc
-
-
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.
-
-
+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:
-
-Open docs/html/index.html to view the generated reference.
-
-
-
-
+With Doxygen installed, run from the repository root:
+Open docs/html/index.html to view the generated reference.
+
+
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.
-
-
+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. dbc_pipeline_test.cpp follows temporary DBC fixtures through parsed metadata, runtime frame/signal lookups, decoded raw/physical values and descriptions, and tree nodes. It verifies all supported metadata in both builders, standard and extended frames sharing a numeric ID, empty databases, comments, and replacement with another fixture or an empty database.
+
+Code review and additional checks
+Attribute numeric parsing shares one locale-independent converter for integer and floating-point values. Default application skips unrelated scopes, CAN ID normalization uses the validated identifier mask, and signal layout validation owns the length checks. Statement handlers continue to use TypeFactory . Core, adapter, example, and test C++ sources use explicit return types and contain no lambdas. Public metadata and parser-state comments use Doxygen descriptions.
+See tests/README.md for attribute boundary regressions, sanitizer commands, and the latest validation results.
+
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.
-
-
+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:
-
sudo apt install build-essential qt6-base-dev qt6-base-dev-tools qmake6 lcov
+
Install the build and report tools:
+
sudo apt install build-essential qt6-base-dev qt6-base-dev-tools qmake6 lcov
# Optional IDE:
sudo apt install qtcreator
-
-
GCC supplies gcov; the lcov package supplies lcov and genhtml. Use the gcov version matching the GCC used by the selected Qt Creator kit. These instructions use GCC and Qt 6.8.2.
-
From the repository root, create a fresh coverage build. --coverage must be passed to both compilation and linking; Debug avoids optimization that can make source-level results harder to interpret. -fprofile-abs-path makes source paths in the coverage data independent of the compilation working directory.
-
DBC_SOURCE_DIR="$(pwd)"
+
GCC supplies gcov; the lcov package supplies lcov and genhtml. Use the gcov version matching the GCC used by the selected Qt Creator kit. These instructions use GCC and Qt 6.8.2.
+
From the repository root, create a fresh coverage build. --coverage must be passed to both compilation and linking; Debug avoids optimization that can make source-level results harder to interpret. -fprofile-abs-path makes source paths in the coverage data independent of the compilation working directory.
+
DBC_SOURCE_DIR="$(pwd)"
mkdir -p build-coverage
cd build-coverage
@@ -1212,17 +1114,14 @@ GCC, gcov, and LCOV on Debian/Ubuntu
genhtml coverage.info --branch-coverage --demangle-cpp --output-directory html
lcov --summary coverage.info --branch-coverage
-
-
Open build-coverage/html/index.html in a browser. The report includes the library's core/ and qt/ sources and instantiated header code; test sources, generated moc files, and Qt/STL headers are excluded. Click a filename to inspect execution counts, uncovered lines, and branch outcomes. Branch coverage is a separate metric: executing a line does not necessarily exercise every outcome. C++ branch data can also include compiler-generated exception paths.
-
For another run with unchanged sources, repeat the reset, test execution, capture, merge, and HTML generation steps. After changing sources or compiler flags, rebuild and regenerate baseline.info before measuring again. A fresh build directory avoids mixing old profiling data with a different build.
-
An initial measurement with GCC 14.2 and Qt 6.8.2 on 2026-10-07, including both QtTest executables and the standalone tree test, yielded 97.8% line coverage (724/740) and 70.7% branch coverage (833/1178). These are a snapshot, not fixed expected values for later changes or other toolchains.
-
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 .
-
-
+Open build-coverage/html/index.html in a browser. The report includes the library's core/ and qt/ sources and instantiated header code; test sources, generated moc files, and Qt/STL headers are excluded. Click a filename to inspect execution counts, uncovered lines, and branch outcomes. Branch coverage is a separate metric: executing a line does not necessarily exercise every outcome. C++ branch data can also include compiler-generated exception paths.
+For another run with unchanged sources, repeat the reset, test execution, capture, merge, and HTML generation steps. After changing sources or compiler flags, rebuild and regenerate baseline.info before measuring again. A fresh build directory avoids mixing old profiling data with a different build.
+An initial measurement with GCC 14.2 and Qt 6.8.2 on 2026-10-07, including both QtTest executables and the standalone tree test, yielded 97.8% line coverage (724/740) and 70.7% branch coverage (833/1178). These are a snapshot, not fixed expected values for later changes or other toolchains.
+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
-
-
+
Open dbc.pro and select a GCC kit with Qt 6.8.2.
In Projects > Build Settings , clone Debug as Coverage .
Choose a separate build directory, such as build-coverage.
@@ -1233,14 +1132,11 @@ Configure the GCC coverage build in Qt Creator
In a terminal in the coverage build directory, compile the standalone test and run the LCOV/report commands above. Set DBC_SOURCE_DIR to the absolute repository path if using a new terminal. make check runs both QtTest executables; the standalone tree executable must be run separately.
View html/index.html in a browser. This workflow produces HTML reports; it does not require a licensed coverage toolchain.
-
-
-
+
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.
-The local configuration set uses these independent build directories:
-
+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.
+The local configuration set uses these independent build directories:
+
Configuration Build directory example Purpose
@@ -1264,10 +1160,9 @@ Configure all build variants in Qt Creator
Demo /tmp/build/dbc/Desktop-Demo Core library and command-line demo
-
-The temporary paths are examples; choose permanent build directories if desired. Do not share a build directory between these configurations.
-To add the ordinary qmake configurations:
-
+The temporary paths are examples; choose permanent build directories if desired. Do not share a build directory between these configurations.
+To add the ordinary qmake configurations:
+
Open dbc.pro with a GCC/Qt 6.8.2 kit.
Go to Projects > Build Settings . Keep the existing Debug, Release, and Profile configurations. Remove or disable a Coco build step if one remains.
Select Debug, press Clone , and name the clone Debug Qt Models . Set its build directory from the table and add CONFIG+=dbc_qt to the qmake step's Additional arguments .
@@ -1278,8 +1173,7 @@ Configure all build variants in Qt Creator
For Coverage, select Add Build Step > Custom Process Step after qmake and Make, then set:
-
-
+
Field Value
@@ -1289,15 +1183,13 @@ Configure all build variants in Qt Creator
Working directory %{buildDir}
-
- This script compiles the standalone tree test, resets counters, runs both QtTest executables and the tree test, and generates %{buildDir}/html/index.html. It stops if any test fails. Therefore building Coverage also executes tests. lcov and genhtml must be installed. Use this configuration with the GCC kit; gcov and the compiler used for the standalone test must match that kit.
+This script compiles the standalone tree test, resets counters, runs both QtTest executables and the tree test, and generates %{buildDir}/html/index.html. It stops if any test fails. Therefore building Coverage also executes tests. lcov and genhtml must be installed. Use this configuration with the GCC kit; gcov and the compiler used for the standalone test must match that kit.
Run qmake and build each new configuration once. The default root builds expose dbc_tests; model configurations also expose dbc_model_tests.
-
-Qt Creator expands %{sourceDir} and %{buildDir} in custom steps to the source and active build directories. Use the field's variable chooser if needed.
-For the three independent builds, clone Debug, assign the name and build directory from the table, and replace its qmake/Make build steps with the custom process steps below. These steps are local IDE settings and do not change dbc.pro. Give each step a descriptive name and retain the listed order.
-For Core Only :
-
+Qt Creator expands %{sourceDir} and %{buildDir} in custom steps to the source and active build directories. Use the field's variable chooser if needed.
+For the three independent builds, clone Debug, assign the name and build directory from the table, and replace its qmake/Make build steps with the custom process steps below. These steps are local IDE settings and do not change dbc.pro. Give each step a descriptive name and retain the listed order.
+For Core Only :
+
Command Arguments Working directory
@@ -1307,19 +1199,17 @@ Configure all build variants in Qt Creator
/usr/bin/make -j4 %{buildDir}
-
-Keep a clean step with make clean in %{buildDir}. Core Only creates a static library, so there is no executable to run.
-For Tree Tests :
-
+Keep a clean step with make clean in %{buildDir}. Core Only creates a static library, so there is no executable to run.
+For Tree Tests :
+
Add a custom step with command /usr/bin/mkdir, arguments -p "%{buildDir}", and working directory %{sourceDir}.
Add a custom step with command /usr/bin/c++, working directory %{buildDir}, and these arguments:
-std=c++17 -O0 -g -I"%{sourceDir}/core" "%{sourceDir}/tests/tree_node_test.cpp" "%{sourceDir}/core/tree_node.cpp" "%{sourceDir}/core/dbc_tree_builder.cpp" -o "%{buildDir}/tree_node_tests"
Remove the default Make clean step: this direct compiler build creates no Makefile. Run the resulting executable as described below.
-
-For Demo :
-
+For Demo :
+
Command Arguments Working directory
@@ -1333,10 +1223,9 @@ Configure all build variants in Qt Creator
/usr/bin/make -j4 %{buildDir}/examples
-
-Replace the default clean step with two custom steps: /usr/bin/make with arguments clean, first in %{buildDir}/examples, then in %{buildDir}/core.
-To configure execution and switch variants:
-
+Replace the default clean step with two custom steps: /usr/bin/make with arguments clean, first in %{buildDir}/examples, then in %{buildDir}/core.
+To configure execution and switch variants:
+
Go to Projects > Run Settings and select the appropriate qmake target: dbc_tests for ordinary builds or dbc_model_tests for model builds.
To run all QtTest suites together, add a Custom Executable named All QtTest suites , with executable /usr/bin/make, arguments check, and working directory %{buildDir}. Use it with an ordinary or model qmake configuration. Coverage already runs every test in its final build step.
For Tree Tests, add a Custom Executable named Standalone tree test , executable %{buildDir}/tree_node_tests, working directory %{buildDir}, and no arguments.
@@ -1345,8 +1234,7 @@ Configure all build variants in Qt Creator
Use the kit/build/run selector above the Run button to choose the build configuration and its corresponding executable. Build with Ctrl+B , then run with Ctrl+R . The Build Settings configuration list can also switch the active build.
If .user was edited externally, close and reopen the project so Qt Creator reads the new settings. Do not edit it while the project is open, because Qt Creator can overwrite external changes when saving its session.
-
-See Qt Creator's build configuration guide and run configuration guide .
+See Qt Creator's build configuration guide and run configuration guide .
diff --git a/docs/html/md_changelog.html b/docs/html/md_changelog.html
index 3a04722..453136e 100644
--- a/docs/html/md_changelog.html
+++ b/docs/html/md_changelog.html
@@ -93,12 +93,69 @@ $(document).ready(function(){initNavTree('md_changelog.html',''); initResizable(
-
This changelog summarizes release and development history. Entries are listed newest first. Historical dates follow the commit author dates. v1.0 is the existing Git tag; subsequent changes are listed as unreleased.
-
+ This changelog summarizes release and development history. Entries are listed newest first. Historical dates follow the commit author dates. v1.0 is the existing Git tag; subsequent changes are listed as unreleased.
+
Unreleased
-
+
+2026-10-20
+
+Maintenance
+
+Share attribute number conversion, skip unrelated default scopes, simplify CAN ID normalization, and remove duplicate signal length checks. Keep explicit return types, lambda-free code, and the existing TypeFactory dispatch.
+Add numeric boundary/locale and malformed-attribute regressions, including diagnostics for invalid definitions, defaults, assignments, and CAN references.
+Fill empty Doxygen file summaries, correct TypeFactory template parameter documentation, and document public metadata, parser state, and Qt model methods. Reword escape examples that caused a Doxygen Markdown warning.
+
+
+Added
+
+Parse typed BA_DEF_, BA_DEF_DEF_, and BA_ attributes with deferred definitions/references, validated ranges, defaults, and explicit overrides. Preserve definitions and assignments plus effective database/frame/signal values.
+Expose optional frame format and cycle time metadata in parsed frames, runtime snapshots, and tree payloads. Preserve unknown frame format labels with source warnings, and report format/ID conflicts without changing ID or J1939 behavior.
+Add attribute syntax, scope, reference, numeric, override, diagnostics, and metadata propagation regressions; document supported forms and limitations. Verified the qmake build, all six QtTest suites, the qmake tree target, and the standalone C++17 tree test. The existing named C locale test skipped because the required locale is not installed.
+
+
+Changed
+
+J1939 interpretation now requires DbcParserOptions::enableJ1939 (default off) or explicit per-frame hasPgn metadata. Extended CAN alone no longer derives PGN metadata. Runtime construction validates opted-in PGNs against frame IDs.
+Add indexed PGN lookup with PDU1 destination exclusion, PDU2 group extension, and both data-page bits. Decoder exact-ID matches take precedence; otherwise one J1939 PGN candidate is accepted and multiple candidates return AmbiguousFrame. Result and selection keys identify the DBC definition.
+Add opt-in, PDU1/PDU2, address/priority changes, ambiguity, exact precedence, metadata validation, selected decode, and snapshot-lifetime regressions. Verified with qmake6 ../dbc.pro, make -j4, and make check in build/: all six QtTest suites and the Qt-free tree target passed; the existing named comma-decimal C locale test skipped because that locale is not installed.
+
+
+Added
+
+Expose stable frame and signal keys from Qt-free tree nodes using the existing runtime identifier types. Document missing-key cases and identity rules.
+Expand standalone navigation tests and add a Qt-free qmake test target covering ownership transfer, vector growth, bounds, key identity, and cycle rejection.
+
+
+Fixed
+
+Reject self/ancestor insertion before consuming child ownership, preventing cycles while preserving parent links. Keep node copying and movement disabled.
+
+
+2026-10-14
+
+Fixed
+
+Issue #19: parse signal factor, offset, minimum, and maximum independently of C/C++ application locales with std::from_chars, retaining signed decimals, scientific notation, complete-token validation, and range/finite checks.
+Added custom C++ and named C comma-decimal locale regressions for valid physical values and invalid syntax, grouping, overflow/underflow, and reversed ranges. Documented portable test coverage and Linux locale generation. Verified with qmake6, make -j4, and LOCPATH=/tmp/dbc-issue19-locales make check: all six suites passed without skips. The named C locale regression fails with the old std::stod converter.
+Issue #18: frame/signal comments share frame-definition CAN ID validation and resolve after definitions are read. Support tabs, escaped quotes/backslashes, and multiline text while preserving whitespace and starting source locations.
+Report malformed comments and missing references as InvalidStatement errors; keep statement-order overwrites, including empty comments. Added regression coverage and updated parser/test documentation. Verified with qmake6, make -j4, and make check: all six regression suites passed.
+
+
+Changed
+
+Validate duplicate frame keys before building the runtime lookup index, alongside CAN IDs, signal layouts, numeric parameters, and multiplexing metadata.
+
+
+Added
+
+Root AGENTS.md with project coding rules, build/test commands, and documentation requirements, based on the existing .project_rules.
+End-to-end DBC fixture tests for parsed metadata, runtime frame/signal lookup, raw and physical decoding, value descriptions, and tree nodes. Both builders preserve supported metadata across same-numeric standard/extended IDs, comments, empty databases, and database replacement.
+Exhaustive layout checks for both byte orders at representative payload sizes (0, 1, 8, 64, and 255 bytes), including invalid lengths and uint32 overflow inputs.
+Regression coverage for builder input mutation/destruction and failed replacement with duplicate frame or signal keys, preserving existing lookups.
+
+
2026-10-13
-
+
Added
Issue #16: construction-time validation for both manual runtime definitions and DbcDecodeBuilder input: normalized CAN IDs, duplicate keys, signal lengths and positions, enums, finite numeric parameters, ordered ranges, selectors, branch ranges, and overlaps.
@@ -107,7 +164,7 @@ Added
SignalDecodeStatus::PhysicalConversionFailed reports NaN/Inf results, retaining exact raw values and the non-finite physical result.
Regression tests for payload-length policy, partial results, invalid runtime metadata, physical overflow/non-finite parameters, and raw branch selection when selector physical conversion fails.
-
+
Changed
Runtime construction rejects invalid definitions with std::invalid_argument before publishing a snapshot. Decoder tests now expect construction failures for malformed definitions; finite arithmetic overflow remains a decode status.
@@ -117,33 +174,33 @@ Changed
Runtime signal validation checks enum values and bit layouts against declared DLC using overflow-safe coordinates. Extra bytes cannot rescue invalid layouts.
Documented frame/signal status meanings, value availability, and payload policy.
-
+
2026-10-11
-
+
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.
+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.
Regression tests for warning locations, header handling, immediate/deferred errors, file errors, empty results on failure, and legacy exception compatibility.
-
+
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.
+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.
Audited diagnostic coverage and added unsupported-statement variants, namespace termination, formatting/path handling, first-error stopping, deferred diagnostic order, duplicate/overlap errors, and supported decoding preservation tests. Linux file-read errors and legacy file-error messages are checked explicitly.
-
+
2026-10-07
-
+
Added
Added regression coverage for signed bit-length boundaries, deterministic Intel/Motorola extraction, lookup failures, runtime validation, PGN, comments, file formatting, metadata copying/lifetime, and TypeFactory behavior.
@@ -155,7 +212,7 @@ Added
Selector-first decoding using exact raw values, preserving definition order and unconditional signals. Explicit statuses distinguish inactive branches, missing selector data, insufficient payloads, and malformed runtime metadata.
Registered SG_MUL_VAL_ rejection through TypeFactory ; extended and nested multiplexing remain unsupported. Added parser/decoder regression coverage and documented supported syntax and consumer behavior.
-
+
Changed
Qt-dependent targets now require the installed Qt 6.8.2 through a shared qmake version check; removed Qt 5 compatibility instructions. Core remains Qt-free.
@@ -163,7 +220,7 @@ Changed
Coverage documentation now describes the selected open GCC/LCOV toolchain.
Overlapping unconditional signals are now rejected during parsing.
-
+
Fixed
Linked QtGui only in the optional model tests and used QGuiApplication with an offscreen default, resolving the QAbstractItemModelTester invalid QPixmap metatype warning without adding QtGui to the adapter library.
@@ -171,9 +228,9 @@ Fixed
Removed test compiler warnings by using QVERIFY_THROWS_EXCEPTION and explicitly discarding nodiscard return values in exception checks.
Reject duplicate frames by normalized CAN ID and frame type, including equivalent extended ID encodings, and duplicate signal names within a frame. Errors report the file path and line of the repeated definition. Standard and extended frames may share a numeric ID; separate frames may reuse signal names. Added regression coverage and updated parser documentation.
-
+
2026-10-06
-
+
Added
Added non-owning TreeNode parent navigation and stable sibling positions; disabled node moves to preserve links while retaining unique_ptr ownership.
@@ -183,61 +240,61 @@ Added
Preserved descriptions in parsed metadata, runtime decode definitions, and UI tree metadata. Added DecodedSignalValue::GetValueDescription() and FindValueDescription() for raw integer lookup before physical scaling. Unknown values retain normal numeric decoding.
Added regression coverage for syntax, quoting, whitespace, integer boundaries, declaration order, invalid references, duplicates, scaling, and both builders; documented syntax, lookup behavior, and limitations in README.
-
+
2026-10-05
-
+
Changed
Split the qmake project into a reusable static library in core/, a demo in examples/, and a combined regression test executable in tests/. Added shared .pri files and updated build instructions. (f17ddb6, #11)
Added .clang-format and applied consistent formatting to the source code and tests. (b91cf4a, #7)
Replaced lambdas with explicit functions and simpler code in statement handlers, the decoder, the demo, and regression tests. (03dc8f2)
-
+
Fixed
Added complete validation of SG_ signal statements, including syntax, receivers, numeric fields, lengths of 1–64 bits, physical ranges, and signal bounds within the declared frame payload for Intel and Motorola bit order. Invalid definitions report the file path and line number. Multiplexing markers are explicitly rejected. Added regression tests and documentation. (8d82b13, #6)
-
+
Documentation and maintenance
Regenerated Doxygen documentation after code changes and the project restructuring. (6cd9976, 0067cb4, f17ddb6)
Removed the temporary signal-validation issue document. (1163277)
-
+
2026-10-01
-
+
Changed
Moved DBC statement parsing into TypeFactory -registered handlers for BO_, SG_, and CM_, with a shared parse context and keyword dispatcher. Added tests for dispatch and handler replacement, and documented how to register additional handlers. (88b5883, #4)
API change: DecodedSignalValue::rawValue now uses std::variant<std::int64_t, std::uint64_t> instead of int64_t. Consumers must handle the appropriate variant alternative. Physical values remain double and may lose precision for large integers. (69074e3, #2)
-
+
Fixed
Corrected Motorola signal extraction within bytes and across byte boundaries using DBC sawtooth bit numbering. Added decoder regression tests and build instructions; introduced the TypeFactory utility. (2c057b6)
Preserved the full unsigned 64-bit raw-value range, including values above INT64_MAX, and updated physical conversion and demo output. Added tests for signed and unsigned boundaries and numeric output. (69074e3, #2)
Validated BO_ frame syntax, CAN identifiers, payload lengths, numeric overflow, and unexpected trailing fields. Parsing errors now include the file path and physical line number. Added parser regression tests. (3bd9339, #3)
-
+
v1.0 — 2026-06-14
Tag v1.0 points to 38ce043 and includes the initial implementation below.
-
+
Documentation
Added source-file headers with author information and MIT license references. (e2ffa97)
Added and subsequently simplified the Doxygen configuration. (e2c07dd, 4c8af9f)
Generated API documentation and refreshed the generated documentation. (dfec39d, 38ce043)
-
+
Initial implementation — 2026-03-13
-
+
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)
-
+
Documentation and maintenance
Added .gitignore and expanded the README with architecture, data structures, parsing behavior, decoding examples, and usage documentation. (efc57d6, f2aa10c, cb20f5f, f0e7065)
diff --git a/docs/html/md_tests_2README.html b/docs/html/md_tests_2README.html
index f065bcc..2503496 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
-
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, lifetime, validation, 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, pipeline, lifetime, validation, 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,31 +109,58 @@ $(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 , dbc_lifetime_test.cpp , and dbc_validation_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 , dbc_lifetime_test.cpp , dbc_validation_test.cpp , and dbc_pipeline_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; frame status reports unknown frames, short payloads, and signal errors. Tests exercise empty/short/exact/long payloads, ignored trailing bytes, signals outside declared DLC, invalid enum metadata and overflowing start bits rejected at construction, and preservation of successful signals on partial payloads. Physical conversion checks cover NaN/Inf parameters rejected at construction, multiplication/addition overflow, finite limits, signed/unsigned raw retention, and raw selector activation after physical conversion failure.
-
+
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.
+
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 13 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. Comment regressions cover tabs, escaped quotes/backslashes, multiline text with blank lines and indentation, CRLF, missing final newlines, comments preceding frame/signal definitions, last-wins and empty overwrites, normalized ID boundaries, standard/extended separation, malformed syntax/IDs, and missing targets. Errors verify both structured diagnostics and the throwing API at the starting line. 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. Physical-number tests apply a custom comma-decimal C++ locale and an available named comma-decimal C numeric locale. They check all four physical fields, leading signs, fractions, scientific notation, finite boundaries, zero, malformed numbers, comma/grouped numbers, overflow/underflow, and reversed ranges. Locale changes are restored after each test. The named C locale case skips if none of the supported locale names are installed; the custom C++ locale case always runs. On Linux with locale sources and localedef, run both cases without installing a system locale:
+
mkdir -p /tmp/dbc-test-locales
+
localedef --no-archive -i de_DE -f UTF-8 /tmp/dbc-test-locales/de_DE.UTF-8
+
LOCPATH=/tmp/dbc-test-locales make check
+
Run make check from the build directory as usual. 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.
+
tree_node_test.cpp is a standalone C++17 executable without Qt; see the root README for its compiler command. It is also built as dbc_tree_tests and run by qmake's make check, without Qt linkage. It checks empty trees, parent/child round trips, sibling positions, const/mutable bounds, null children, vector growth, and unique_ptr transfer. Compile-time checks reject node copying and movement. Self/ancestor insertion must throw without consuming ownership or changing links. Key tests cover frame/signal identity, standard/extended separation, repeated signal names across frames, missing keys, source replacement, and row-independent identity.
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, construction rejection of 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.
+
J1939 regressions in dbc_coverage_test.cpp verify explicit parser opt-in and ordinary extended CAN defaults, PF 239/240 and all data-page combinations, PGN zero, PDU1 destination exclusion, PDU2 group-extension matching, changed source and priority, standard/invalid-ID exclusion, and inconsistent manual metadata. They also cover exact-ID precedence, order-independent ambiguous PGNs for both PDU formats, mixed ordinary/J1939 definitions, selected-signal definition keys, raw/physical values, and owning PGN handles across snapshot replacement. The pipeline fixture explicitly enables J1939 through the diagnostic parser API. Verified in build/ with qmake6 ../dbc.pro, make -j4, and make check: all six QtTest suites and the Qt-free tree target passed. The existing named comma-decimal C locale regression skipped because that locale is not installed.
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.
-
+
Database validation coverage
-dbc_validation_test.cpp checks direct construction and manually assembled DbcDatabase input to DbcDecodeBuilder : standard/extended CAN ID limits, encoded/reserved ID bits, duplicate keys, lengths 0/1–64/65/UINT32_MAX, Intel/Motorola payload boundaries and overflowing start bits, invalid enums, NaN and both infinities in every numeric parameter, and reversed physical ranges. Selector tests include missing, duplicate, and signed selectors, branch ranges, UINT64_MAX selection, mixed-order overlaps, and exclusive branches sharing bits. Valid definitions cover the full byte-count storage range, including zero-byte frames without signals and 255-byte frames. Existing extraction tests cover lengths 1–64. Snapshot tests mutate retained frame, signal, and description aliases after rvalue construction, and verify unchanged lookups and metadata. Failed constructor/builder replacement preserves the active snapshot; clear removes its index while saved handles remain alive.
+
dbc_validation_test.cpp checks direct construction and manually assembled DbcDatabase input to DbcDecodeBuilder : standard/extended CAN ID limits, encoded/reserved ID bits, duplicate keys, lengths 0/1–64/65/UINT32_MAX, Intel/Motorola payload boundaries and overflowing start bits, invalid enums, NaN and both infinities in every numeric parameter, and reversed physical ranges. Selector tests include missing, duplicate, and signed selectors, branch ranges, UINT64_MAX selection, mixed-order overlaps, and exclusive branches sharing bits. Valid definitions cover the full byte-count storage range, including zero-byte frames without signals and 255-byte frames. Existing extraction tests cover lengths 1–64. Snapshot tests mutate retained frame, signal, and description aliases after rvalue construction, and verify unchanged lookups and metadata. Failed constructor/builder replacement preserves the active snapshot; clear removes its index while saved handles remain alive.
+
Layout validation is also compared with independent DBC bit traversal for every start position through one byte beyond payload sizes 0, 1, 8, 64, and 255, and all lengths 1–64, for both byte orders. Zero/65-bit lengths and uint32 maximum inputs are rejected. Builder snapshots survive input mutation and destruction; failed replacement with duplicate frame or signal keys preserves the existing frame and signal lookups.
+
+End-to-end pipeline coverage
+
dbc_pipeline_test.cpp parses temporary DBC files and checks independent expected metadata against the parser, runtime builder, and tree builder. It exercises standard and extended frames with the same numeric ID and signal name, Intel and signed Motorola decoding, scaling, raw value descriptions, basic multiplexing, PGN metadata, receivers, units, ranges, and frame/signal comments. Tree checks include node types, payloads, parents, rows, names, and child counts.
+
Empty and headers-only fixtures produce an empty runtime database and a valid empty tree root. Replacement fixtures change definitions, metadata and decoded values, remove old lookup keys, and then clear both outputs through an empty fixture. Saved decoded results and trees retain their original metadata.
+
+Attribute coverage
+
Parser slots attributes, invalidAttributes, and attributeWarnings cover all five scopes and types, deferred definitions/defaults/targets, explicit values overriding defaults, repeated assignments, escaped strings, typed range/scope errors, duplicate definitions/defaults, unknown attributes and missing targets. They check source diagnostics and the throwing API, distinct standard/extended targets, frame cycle times and enum labels, unsupported formats and ID conflicts, unchanged J1939 opt-in, and runtime/tree propagation. Existing unsupported-statement checks now use relation forms, which remain unsupported, instead of supported attribute forms.
+
Attribute changes were verified with qmake6 ../dbc.pro, make -j4, and make check in build/: all six QtTest suites and the qmake tree target passed. The standalone C++17 tree test also passed. The existing named comma-decimal C locale test skipped because the locale is not installed.
+
+Extended validation
+
attributeNumbers checks signed 64-bit limits, leading plus signs, decimal HEX values, FLOAT fractions/exponents, and default overrides under a comma-decimal C++ locale. Node/environment defaults remain on definitions without becoming database attributes. invalidAttributeNumbers supplies 39 data rows, each checked in both definition bounds, a default, and an explicit assignment. The throwing and diagnostic APIs must reject malformed signs, trailing text, hexadecimal notation, non-finite values, overflow, and underflow with the correct error line. Additional malformed-attribute cases cover token separators, scope/type names, reversed FLOAT bounds, value types/ranges, and invalid CAN references.
+
Run AddressSanitizer and UndefinedBehaviorSanitizer in a separate directory:
+
mkdir -p build-sanitize
+
cd build-sanitize
+
qmake6 ../dbc.pro CONFIG+=dbc_qt CONFIG+=debug CONFIG-=release \
+
'QMAKE_CXXFLAGS+=-fsanitize=address,undefined -fno-omit-frame-pointer' \
+
'QMAKE_LFLAGS+=-fsanitize=address,undefined'
+
make -j4
+
ASAN_OPTIONS=detect_leaks=0 UBSAN_OPTIONS=halt_on_error=1 \
+
QT_FATAL_WARNINGS=1 LOCPATH=/tmp/dbc-test-locales make check
+
Generate the optional German locale as described above before setting LOCPATH. LeakSanitizer cannot run under this environment's tracer: detect_leaks=1 completes the core QtTest suites but fails during leak checking with the message that LeakSanitizer does not work under ptrace. Disabling leak checking retains AddressSanitizer and UndefinedBehaviorSanitizer checks; it does not verify leaks.
diff --git a/docs/html/menudata.js b/docs/html/menudata.js
index df4e015..2539c7c 100644
--- a/docs/html/menudata.js
+++ b/docs/html/menudata.js
@@ -35,6 +35,7 @@ var menudata={children:[
{text:"b",url:"functions.html#index_b"},
{text:"c",url:"functions.html#index_c"},
{text:"d",url:"functions.html#index_d"},
+{text:"e",url:"functions.html#index_e"},
{text:"f",url:"functions.html#index_f"},
{text:"g",url:"functions.html#index_g"},
{text:"h",url:"functions.html#index_h"},
@@ -50,11 +51,27 @@ var menudata={children:[
{text:"t",url:"functions.html#index_t"},
{text:"u",url:"functions.html#index_u"},
{text:"v",url:"functions.html#index_v"}]},
-{text:"Functions",url:"functions_func.html"},
+{text:"Functions",url:"functions_func.html",children:[
+{text:"a",url:"functions_func.html#index_a"},
+{text:"b",url:"functions_func.html#index_b"},
+{text:"c",url:"functions_func.html#index_c"},
+{text:"d",url:"functions_func.html#index_d"},
+{text:"f",url:"functions_func.html#index_f"},
+{text:"g",url:"functions_func.html#index_g"},
+{text:"h",url:"functions_func.html#index_h"},
+{text:"i",url:"functions_func.html#index_i"},
+{text:"o",url:"functions_func.html#index_o"},
+{text:"p",url:"functions_func.html#index_p"},
+{text:"r",url:"functions_func.html#index_r"},
+{text:"s",url:"functions_func.html#index_s"},
+{text:"t",url:"functions_func.html#index_t"},
+{text:"v",url:"functions_func.html#index_v"}]},
{text:"Variables",url:"functions_vars.html",children:[
+{text:"a",url:"functions_vars.html#index_a"},
{text:"b",url:"functions_vars.html#index_b"},
{text:"c",url:"functions_vars.html#index_c"},
{text:"d",url:"functions_vars.html#index_d"},
+{text:"e",url:"functions_vars.html#index_e"},
{text:"f",url:"functions_vars.html#index_f"},
{text:"h",url:"functions_vars.html#index_h"},
{text:"i",url:"functions_vars.html#index_i"},
@@ -68,9 +85,12 @@ var menudata={children:[
{text:"s",url:"functions_vars.html#index_s"},
{text:"t",url:"functions_vars.html#index_t"},
{text:"u",url:"functions_vars.html#index_u"},
-{text:"v",url:"functions_vars.html#index_v"}]}]}]},
+{text:"v",url:"functions_vars.html#index_v"}]},
+{text:"Typedefs",url:"functions_type.html"},
+{text:"Enumerations",url:"functions_enum.html"}]}]},
{text:"Files",url:"files.html",children:[
{text:"File List",url:"files.html"},
{text:"File Members",url:"globals.html",children:[
{text:"All",url:"globals.html"},
+{text:"Functions",url:"globals_func.html"},
{text:"Enumerations",url:"globals_enum.html"}]}]}]}
diff --git a/docs/html/multiplexing_8h_source.html b/docs/html/multiplexing_8h_source.html
index 33c87dc..042bc17 100644
--- a/docs/html/multiplexing_8h_source.html
+++ b/docs/html/multiplexing_8h_source.html
@@ -104,21 +104,23 @@ $(document).ready(function(){initNavTree('multiplexing_8h_source.html',''); init
- 7 enum class MultiplexRole {
-
-
-
-
-
-
-
-
15 MultiplexRole role = MultiplexRole::Unconditional;
-
16 std::uint64_t value = 0U;
-
+
8 enum class MultiplexRole {
+
+
+
+
+
+
+
+
16 MultiplexRole
role = MultiplexRole::Unconditional;
+
+
-
-
-
+
+
+
+
+
diff --git a/docs/html/navtreedata.js b/docs/html/navtreedata.js
index 0d7e452..95c5774 100644
--- a/docs/html/navtreedata.js
+++ b/docs/html/navtreedata.js
@@ -25,132 +25,156 @@
var NAVTREE =
[
[ "DBC Framework", "index.html", [
+ [ "Инструкции для работы с проектом", "md_AGENTS.html", [
+ [ "О проекте", "md_AGENTS.html#autotoc_md1", null ],
+ [ "Формат задания", "md_AGENTS.html#autotoc_md2", null ],
+ [ "Правила кода", "md_AGENTS.html#autotoc_md3", null ],
+ [ "Тестирование", "md_AGENTS.html#autotoc_md4", null ],
+ [ "Документация", "md_AGENTS.html#autotoc_md5", null ]
+ ] ],
[ "Changelog", "md_changelog.html", [
- [ "Unreleased", "md_changelog.html#autotoc_md1", [
- [ "2026-10-13", "md_changelog.html#autotoc_md2", [
- [ "Added", "md_changelog.html#autotoc_md3", null ],
- [ "Changed", "md_changelog.html#autotoc_md4", null ]
+ [ "Unreleased", "md_changelog.html#autotoc_md7", [
+ [ "2026-10-20", "md_changelog.html#autotoc_md8", [
+ [ "Maintenance", "md_changelog.html#autotoc_md9", null ],
+ [ "Added", "md_changelog.html#autotoc_md10", null ],
+ [ "Changed", "md_changelog.html#autotoc_md11", null ],
+ [ "Added", "md_changelog.html#autotoc_md12", null ],
+ [ "Fixed", "md_changelog.html#autotoc_md13", null ]
] ],
- [ "2026-10-11", "md_changelog.html#autotoc_md5", [
- [ "Added", "md_changelog.html#autotoc_md6", null ],
- [ "Changed", "md_changelog.html#autotoc_md7", null ]
+ [ "2026-10-14", "md_changelog.html#autotoc_md14", [
+ [ "Fixed", "md_changelog.html#autotoc_md15", null ],
+ [ "Changed", "md_changelog.html#autotoc_md16", null ],
+ [ "Added", "md_changelog.html#autotoc_md17", null ]
] ],
- [ "2026-10-07", "md_changelog.html#autotoc_md8", [
- [ "Added", "md_changelog.html#autotoc_md9", null ],
- [ "Changed", "md_changelog.html#autotoc_md10", null ],
- [ "Fixed", "md_changelog.html#autotoc_md11", null ]
+ [ "2026-10-13", "md_changelog.html#autotoc_md18", [
+ [ "Added", "md_changelog.html#autotoc_md19", null ],
+ [ "Changed", "md_changelog.html#autotoc_md20", null ]
] ],
- [ "2026-10-06", "md_changelog.html#autotoc_md12", [
- [ "Added", "md_changelog.html#autotoc_md13", null ]
+ [ "2026-10-11", "md_changelog.html#autotoc_md21", [
+ [ "Added", "md_changelog.html#autotoc_md22", null ],
+ [ "Changed", "md_changelog.html#autotoc_md23", null ]
] ],
- [ "2026-10-05", "md_changelog.html#autotoc_md14", [
- [ "Changed", "md_changelog.html#autotoc_md15", null ],
- [ "Fixed", "md_changelog.html#autotoc_md16", null ],
- [ "Documentation and maintenance", "md_changelog.html#autotoc_md17", null ]
+ [ "2026-10-07", "md_changelog.html#autotoc_md24", [
+ [ "Added", "md_changelog.html#autotoc_md25", null ],
+ [ "Changed", "md_changelog.html#autotoc_md26", null ],
+ [ "Fixed", "md_changelog.html#autotoc_md27", null ]
] ],
- [ "2026-10-01", "md_changelog.html#autotoc_md18", [
- [ "Changed", "md_changelog.html#autotoc_md19", null ],
- [ "Fixed", "md_changelog.html#autotoc_md20", null ]
+ [ "2026-10-06", "md_changelog.html#autotoc_md28", [
+ [ "Added", "md_changelog.html#autotoc_md29", null ]
+ ] ],
+ [ "2026-10-05", "md_changelog.html#autotoc_md30", [
+ [ "Changed", "md_changelog.html#autotoc_md31", null ],
+ [ "Fixed", "md_changelog.html#autotoc_md32", null ],
+ [ "Documentation and maintenance", "md_changelog.html#autotoc_md33", null ]
+ ] ],
+ [ "2026-10-01", "md_changelog.html#autotoc_md34", [
+ [ "Changed", "md_changelog.html#autotoc_md35", null ],
+ [ "Fixed", "md_changelog.html#autotoc_md36", null ]
] ]
] ],
- [ "v1.0 — 2026-06-14", "md_changelog.html#autotoc_md21", [
- [ "Documentation", "md_changelog.html#autotoc_md22", null ],
- [ "Initial implementation — 2026-03-13", "md_changelog.html#autotoc_md23", [
- [ "Added", "md_changelog.html#autotoc_md24", null ],
- [ "Documentation and maintenance", "md_changelog.html#autotoc_md25", null ]
+ [ "v1.0 — 2026-06-14", "md_changelog.html#autotoc_md37", [
+ [ "Documentation", "md_changelog.html#autotoc_md38", null ],
+ [ "Initial implementation — 2026-03-13", "md_changelog.html#autotoc_md39", [
+ [ "Added", "md_changelog.html#autotoc_md40", null ],
+ [ "Documentation and maintenance", "md_changelog.html#autotoc_md41", null ]
] ]
] ]
] ],
[ "DBC Parser and Runtime Decode Module Documentation", "md_README.html", [
- [ "Overview", "md_README.html#autotoc_md27", null ],
- [ "High-Level Architecture", "md_README.html#autotoc_md29", [
- [ "1. Parse and UI path", "md_README.html#autotoc_md30", null ],
- [ "2. Runtime decode path", "md_README.html#autotoc_md31", null ]
+ [ "Overview", "md_README.html#autotoc_md43", null ],
+ [ "High-Level Architecture", "md_README.html#autotoc_md45", [
+ [ "1. Parse and UI path", "md_README.html#autotoc_md46", null ],
+ [ "2. Runtime decode path", "md_README.html#autotoc_md47", null ]
] ],
- [ "Why the Runtime Decode Layer Exists", "md_README.html#autotoc_md33", null ],
- [ "Module Layout", "md_README.html#autotoc_md35", null ],
- [ "Parsed Data Structures", "md_README.html#autotoc_md37", null ],
- [ "SignalInfo ", "md_README.html#autotoc_md38", null ],
- [ "FrameInfo ", "md_README.html#autotoc_md40", null ],
- [ "DbcDatabase ", "md_README.html#autotoc_md42", null ],
- [ "UI Tree Layer", "md_README.html#autotoc_md44", null ],
- [ "TreeNode ", "md_README.html#autotoc_md45", null ],
- [ "Runtime Decode Layer", "md_README.html#autotoc_md47", null ],
- [ "Purpose", "md_README.html#autotoc_md48", null ],
- [ "ByteOrder ", "md_README.html#autotoc_md50", null ],
- [ "ValueType ", "md_README.html#autotoc_md52", null ],
- [ "DecodeSignal ", "md_README.html#autotoc_md54", null ],
- [ "DecodeFrame ", "md_README.html#autotoc_md56", null ],
- [ "FrameKey ", "md_README.html#autotoc_md58", null ],
- [ "DecodeDatabase ", "md_README.html#autotoc_md60", null ],
- [ "Decoder Layer", "md_README.html#autotoc_md62", null ],
- [ "RawCanFrame ", "md_README.html#autotoc_md63", null ],
- [ "DecodedSignalValue ", "md_README.html#autotoc_md65", [
- [ "Raw value representation and precision", "md_README.html#autotoc_md67", null ]
+ [ "Why the Runtime Decode Layer Exists", "md_README.html#autotoc_md49", null ],
+ [ "Module Layout", "md_README.html#autotoc_md51", null ],
+ [ "Parsed Data Structures", "md_README.html#autotoc_md53", null ],
+ [ "SignalInfo ", "md_README.html#autotoc_md54", null ],
+ [ "FrameInfo ", "md_README.html#autotoc_md56", null ],
+ [ "DbcDatabase ", "md_README.html#autotoc_md58", null ],
+ [ "UI Tree Layer", "md_README.html#autotoc_md60", null ],
+ [ "TreeNode ", "md_README.html#autotoc_md61", null ],
+ [ "Runtime Decode Layer", "md_README.html#autotoc_md63", null ],
+ [ "Purpose", "md_README.html#autotoc_md64", null ],
+ [ "ByteOrder ", "md_README.html#autotoc_md66", null ],
+ [ "ValueType ", "md_README.html#autotoc_md68", null ],
+ [ "DecodeSignal ", "md_README.html#autotoc_md70", null ],
+ [ "DecodeFrame ", "md_README.html#autotoc_md72", null ],
+ [ "FrameKey ", "md_README.html#autotoc_md74", null ],
+ [ "DecodeDatabase ", "md_README.html#autotoc_md76", null ],
+ [ "Decoder Layer", "md_README.html#autotoc_md78", null ],
+ [ "RawCanFrame ", "md_README.html#autotoc_md79", null ],
+ [ "DecodedSignalValue ", "md_README.html#autotoc_md81", [
+ [ "Raw value representation and precision", "md_README.html#autotoc_md83", null ]
] ],
- [ "DecodedFrameValue ", "md_README.html#autotoc_md69", [
- [ "Definition ownership and reload", "md_README.html#autotoc_md70", null ],
- [ "Stable frame and signal identifiers", "md_README.html#autotoc_md71", null ]
+ [ "DecodedFrameValue ", "md_README.html#autotoc_md85", [
+ [ "Definition ownership and reload", "md_README.html#autotoc_md86", null ],
+ [ "Stable frame and signal identifiers", "md_README.html#autotoc_md87", null ]
] ],
- [ "DbcDecoder ", "md_README.html#autotoc_md73", null ],
- [ "Parser Support", "md_README.html#autotoc_md75", [
- [ "Structured diagnostics", "md_README.html#autotoc_md76", null ]
+ [ "DbcDecoder ", "md_README.html#autotoc_md89", null ],
+ [ "Parser Support", "md_README.html#autotoc_md91", [
+ [ "Structured diagnostics", "md_README.html#autotoc_md92", null ],
+ [ "Attributes and frame metadata", "md_README.html#autotoc_md93", null ]
] ],
- [ "Supported DBC Syntax", "md_README.html#autotoc_md78", null ],
- [ "Frame definition", "md_README.html#autotoc_md79", [
- [ "Frame validation and parse errors", "md_README.html#autotoc_md81", null ]
+ [ "Supported DBC Syntax", "md_README.html#autotoc_md95", null ],
+ [ "Frame definition", "md_README.html#autotoc_md96", [
+ [ "Frame validation and parse errors", "md_README.html#autotoc_md98", null ]
] ],
- [ "Signal definition", "md_README.html#autotoc_md83", [
- [ "Signal validation and parse errors", "md_README.html#autotoc_md85", null ]
+ [ "Signal definition", "md_README.html#autotoc_md100", [
+ [ "Signal validation and parse errors", "md_README.html#autotoc_md102", null ]
] ],
- [ "Basic multiplexing", "md_README.html#autotoc_md87", null ],
- [ "Comments", "md_README.html#autotoc_md89", null ],
- [ "CAN ID Normalization", "md_README.html#autotoc_md91", null ],
- [ "PGN Extraction", "md_README.html#autotoc_md93", null ],
- [ "Decode Flow", "md_README.html#autotoc_md95", null ],
- [ "Intel and Motorola Extraction", "md_README.html#autotoc_md97", null ],
- [ "Example Usage", "md_README.html#autotoc_md99", [
- [ "Parse DBC", "md_README.html#autotoc_md100", null ],
- [ "Build UI tree", "md_README.html#autotoc_md101", null ],
- [ "Build runtime decode database", "md_README.html#autotoc_md102", null ],
- [ "Decode a raw frame", "md_README.html#autotoc_md103", null ]
+ [ "Basic multiplexing", "md_README.html#autotoc_md104", null ],
+ [ "Comments", "md_README.html#autotoc_md106", null ],
+ [ "CAN ID Normalization", "md_README.html#autotoc_md108", null ],
+ [ "J1939 Opt-in and PGN Lookup", "md_README.html#autotoc_md110", null ],
+ [ "Decode Flow", "md_README.html#autotoc_md112", null ],
+ [ "Intel and Motorola Extraction", "md_README.html#autotoc_md114", null ],
+ [ "Example Usage", "md_README.html#autotoc_md116", [
+ [ "Parse DBC", "md_README.html#autotoc_md117", null ],
+ [ "Build UI tree", "md_README.html#autotoc_md118", null ],
+ [ "Build runtime decode database", "md_README.html#autotoc_md119", null ],
+ [ "Decode a raw frame", "md_README.html#autotoc_md120", null ]
] ],
- [ "Unified Decode Strategy", "md_README.html#autotoc_md105", [
- [ "live path", "md_README.html#autotoc_md106", null ],
- [ "trace path", "md_README.html#autotoc_md107", null ]
+ [ "Unified Decode Strategy", "md_README.html#autotoc_md122", [
+ [ "live path", "md_README.html#autotoc_md123", null ],
+ [ "trace path", "md_README.html#autotoc_md124", null ]
] ],
- [ "Intended Use in FrameTap", "md_README.html#autotoc_md109", null ],
- [ "Why the Tree Is Not Enough", "md_README.html#autotoc_md111", null ],
- [ "Statement Handler Factory", "md_README.html#autotoc_md113", null ],
- [ "Signal value descriptions (VAL_ )", "md_README.html#autotoc_md115", null ],
- [ "Current Limitations", "md_README.html#autotoc_md117", null ],
- [ "Recommended Next Steps", "md_README.html#autotoc_md119", [
- [ "Stage 1 - already implemented", "md_README.html#autotoc_md120", null ],
- [ "Stage 2", "md_README.html#autotoc_md121", null ],
- [ "Stage 3", "md_README.html#autotoc_md122", null ],
- [ "Stage 4", "md_README.html#autotoc_md123", null ]
+ [ "Intended Use in FrameTap", "md_README.html#autotoc_md126", null ],
+ [ "Why the Tree Is Not Enough", "md_README.html#autotoc_md128", null ],
+ [ "Statement Handler Factory", "md_README.html#autotoc_md130", null ],
+ [ "Signal value descriptions (VAL_ )", "md_README.html#autotoc_md132", null ],
+ [ "Current Limitations", "md_README.html#autotoc_md134", null ],
+ [ "Recommended Next Steps", "md_README.html#autotoc_md136", [
+ [ "Stage 1 - already implemented", "md_README.html#autotoc_md137", null ],
+ [ "Stage 2", "md_README.html#autotoc_md138", null ],
+ [ "Stage 3", "md_README.html#autotoc_md139", null ],
+ [ "Stage 4", "md_README.html#autotoc_md140", null ]
] ],
- [ "Build Integration", "md_README.html#autotoc_md125", [
- [ "Build core without Qt libraries", "md_README.html#autotoc_md126", null ],
- [ "Optional Qt model adapter", "md_README.html#autotoc_md127", null ],
- [ "Standalone tree tests without Qt", "md_README.html#autotoc_md128", null ],
- [ "Build and run the demo", "md_README.html#autotoc_md129", null ],
- [ "Generate API documentation", "md_README.html#autotoc_md130", null ]
+ [ "Build Integration", "md_README.html#autotoc_md142", [
+ [ "Build core without Qt libraries", "md_README.html#autotoc_md143", null ],
+ [ "Optional Qt model adapter", "md_README.html#autotoc_md144", null ],
+ [ "Standalone tree tests without Qt", "md_README.html#autotoc_md145", null ],
+ [ "Build and run the demo", "md_README.html#autotoc_md146", null ],
+ [ "Generate API documentation", "md_README.html#autotoc_md147", null ]
] ],
- [ "Regression tests", "md_README.html#autotoc_md132", null ],
- [ "Measuring code coverage", "md_README.html#autotoc_md133", [
- [ "GCC, gcov, and LCOV on Debian/Ubuntu", "md_README.html#autotoc_md134", null ],
- [ "Configure the GCC coverage build in Qt Creator", "md_README.html#autotoc_md135", null ],
- [ "Configure all build variants in Qt Creator", "md_README.html#autotoc_md136", null ]
+ [ "Regression tests", "md_README.html#autotoc_md149", null ],
+ [ "Code review and additional checks", "md_README.html#autotoc_md150", null ],
+ [ "Measuring code coverage", "md_README.html#autotoc_md151", [
+ [ "GCC, gcov, and LCOV on Debian/Ubuntu", "md_README.html#autotoc_md152", null ],
+ [ "Configure the GCC coverage build in Qt Creator", "md_README.html#autotoc_md153", null ],
+ [ "Configure all build variants in Qt Creator", "md_README.html#autotoc_md154", null ]
] ]
] ],
[ "QtTest regression tests", "md_tests_2README.html", [
- [ "Decoder coverage", "md_tests_2README.html#autotoc_md138", null ],
- [ "Parser coverage", "md_tests_2README.html#autotoc_md139", null ],
- [ "Tree and optional model tests", "md_tests_2README.html#autotoc_md140", null ],
- [ "Additional regression coverage", "md_tests_2README.html#autotoc_md141", null ],
- [ "Definition lifetime and reload coverage", "md_tests_2README.html#autotoc_md142", null ],
- [ "Database validation coverage", "md_tests_2README.html#autotoc_md143", null ]
+ [ "Decoder coverage", "md_tests_2README.html#autotoc_md156", null ],
+ [ "Parser coverage", "md_tests_2README.html#autotoc_md157", null ],
+ [ "Tree and optional model tests", "md_tests_2README.html#autotoc_md158", null ],
+ [ "Additional regression coverage", "md_tests_2README.html#autotoc_md159", null ],
+ [ "Definition lifetime and reload coverage", "md_tests_2README.html#autotoc_md160", null ],
+ [ "Database validation coverage", "md_tests_2README.html#autotoc_md161", null ],
+ [ "End-to-end pipeline coverage", "md_tests_2README.html#autotoc_md162", null ],
+ [ "Attribute coverage", "md_tests_2README.html#autotoc_md163", null ],
+ [ "Extended validation", "md_tests_2README.html#autotoc_md164", null ]
] ],
[ "Classes", "annotated.html", [
[ "Class List", "annotated.html", "annotated_dup" ],
@@ -159,13 +183,16 @@ var NAVTREE =
[ "Class Members", "functions.html", [
[ "All", "functions.html", null ],
[ "Functions", "functions_func.html", null ],
- [ "Variables", "functions_vars.html", null ]
+ [ "Variables", "functions_vars.html", null ],
+ [ "Typedefs", "functions_type.html", null ],
+ [ "Enumerations", "functions_enum.html", null ]
] ]
] ],
[ "Files", "files.html", [
[ "File List", "files.html", "files_dup" ],
[ "File Members", "globals.html", [
[ "All", "globals.html", null ],
+ [ "Functions", "globals_func.html", null ],
[ "Enumerations", "globals_enum.html", null ]
] ]
] ]
@@ -175,7 +202,7 @@ var NAVTREE =
var NAVTREEINDEX =
[
"annotated.html",
-"structDecodedSignalValue.html"
+"md_README.html#autotoc_md92"
];
var SYNCONMSG = 'click to disable panel synchronisation';
diff --git a/docs/html/navtreeindex0.js b/docs/html/navtreeindex0.js
index 0b0cec4..4cc7e05 100644
--- a/docs/html/navtreeindex0.js
+++ b/docs/html/navtreeindex0.js
@@ -1,253 +1,253 @@
var NAVTREEINDEX0 =
{
-"annotated.html":[3,0],
-"classDbcCommentHandler.html":[3,0,0],
-"classDbcDecodeBuilder.html":[3,0,2],
-"classDbcDecodeBuilder.html#a2bc6386dfb5e58976c42e22c19ec471b":[3,0,2,0],
-"classDbcDecoder.html":[3,0,3],
-"classDbcDecoder.html#a345951ffe5d943a70d3a1ea1f39e74f7":[3,0,3,1],
-"classDbcDecoder.html#a4005c4311f57b7faf21c0cb31463039c":[3,0,3,0],
-"classDbcDiagnosticError.html":[3,0,5],
-"classDbcFrameHandler.html":[3,0,6],
-"classDbcHeaderHandler.html":[3,0,7],
-"classDbcParser.html":[3,0,9],
-"classDbcParser.html#a0e915ce79c2e3d4c95a5aaf2bf0409bc":[3,0,9,1],
-"classDbcParser.html#aef72826942c9095d653fafa435855e56":[3,0,9,0],
-"classDbcSignalHandler.html":[3,0,11],
-"classDbcStatementDispatcher.html":[3,0,12],
-"classDbcStatementDispatcher.html#a495c2d5c7ebb8103b1987cdd87c142ed":[3,0,12,0],
-"classDbcStatementHandler.html":[3,0,13],
-"classDbcTreeBuilder.html":[3,0,14],
-"classDbcTreeBuilder.html#a7e57d067d831b14b383947fd125edd4b":[3,0,14,0],
-"classDbcTreeModel.html":[3,0,15],
-"classDbcUnsupportedMultiplexingHandler.html":[3,0,16],
-"classDbcValueDescriptionHandler.html":[3,0,17],
-"classDecodeDatabase.html":[3,0,18],
-"classDecodeDatabase.html#a51a44cf7c3f23c98ec8781afe0097c0c":[3,0,18,0],
-"classDecodeDatabase.html#a780d6e747a48b10a5eb0ab85448d2970":[3,0,18,2],
-"classDecodeDatabase.html#aa034c1510984a85f60ad6c0bd744d6e8":[3,0,18,1],
-"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],
-"dbc__database_8h_source.html":[4,0,0,0],
-"dbc__decode__builder_8cpp.html":[4,0,0,1],
-"dbc__decode__builder_8cpp_source.html":[4,0,0,1],
-"dbc__decode__builder_8h.html":[4,0,0,2],
-"dbc__decode__builder_8h_source.html":[4,0,0,2],
-"dbc__decoder_8cpp.html":[4,0,0,3],
-"dbc__decoder_8cpp_source.html":[4,0,0,3],
-"dbc__decoder_8h.html":[4,0,0,4],
-"dbc__decoder_8h.html#a855b2bc36cb18bfbae5ff30a2394e961":[4,0,0,4,4],
-"dbc__decoder_8h.html#a855b2bc36cb18bfbae5ff30a2394e961a3ac705f2acd51a4613f9188c05c91d0d":[4,0,0,4,4,3],
-"dbc__decoder_8h.html#a855b2bc36cb18bfbae5ff30a2394e961a7c9fa088a1e7db1fc83cb62aefd3ea7f":[4,0,0,4,4,1],
-"dbc__decoder_8h.html#a855b2bc36cb18bfbae5ff30a2394e961a85f5d387f9a01dce258470e1a5a23332":[4,0,0,4,4,0],
-"dbc__decoder_8h.html#a855b2bc36cb18bfbae5ff30a2394e961aedeb8da96660592dfe0853f212b77469":[4,0,0,4,4,2],
-"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,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],
-"dbc__tree__builder_8cpp_source.html":[4,0,0,10],
-"dbc__tree__builder_8h.html":[4,0,0,11],
-"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,4],
-"dbc__validation__test_8cpp_source.html":[4,0,3,5],
-"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],
-"dir_d28a4824dc47e487b107a5db32ef43c4.html":[4,0,1],
-"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,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],
-"globals.html":[4,1,0],
-"globals_enum.html":[4,1,1],
-"hierarchy.html":[3,2],
+"annotated.html":[4,0],
+"attributes_8h_source.html":[5,0,0,0],
+"classDbcAttributeHandler.html":[4,0,2],
+"classDbcAttributeHandler.html#a397f23259b7ff79abb4b5141489caa83":[4,0,2,0],
+"classDbcCommentHandler.html":[4,0,3],
+"classDbcCommentHandler.html#aa4fce77b585a441d251d8535ef7a51a6":[4,0,3,0],
+"classDbcDecodeBuilder.html":[4,0,5],
+"classDbcDecodeBuilder.html#a2bc6386dfb5e58976c42e22c19ec471b":[4,0,5,0],
+"classDbcDecoder.html":[4,0,6],
+"classDbcDecoder.html#a345951ffe5d943a70d3a1ea1f39e74f7":[4,0,6,1],
+"classDbcDecoder.html#a4005c4311f57b7faf21c0cb31463039c":[4,0,6,0],
+"classDbcDecoder.html#ade48a94b6fcda6563bd1b2c6ff49439e":[4,0,6,2],
+"classDbcDiagnosticError.html":[4,0,8],
+"classDbcDiagnosticError.html#aa9997368f79a9a0723481aaeffc44618":[4,0,8,0],
+"classDbcDiagnosticError.html#ab3965082f01d66b6d5c20525af44235d":[4,0,8,1],
+"classDbcFrameHandler.html":[4,0,9],
+"classDbcFrameHandler.html#a0d3f43bbcc5e191460bc31827e74ce89":[4,0,9,0],
+"classDbcHeaderHandler.html":[4,0,10],
+"classDbcHeaderHandler.html#a1e43a9dcf157f4d4418032d9e9711693":[4,0,10,0],
+"classDbcParser.html":[4,0,12],
+"classDbcParser.html#a0e915ce79c2e3d4c95a5aaf2bf0409bc":[4,0,12,2],
+"classDbcParser.html#a46bc3afcd103e704dc58bb4b073da73c":[4,0,12,0],
+"classDbcParser.html#aef72826942c9095d653fafa435855e56":[4,0,12,1],
+"classDbcSignalHandler.html":[4,0,15],
+"classDbcSignalHandler.html#ad7d891ec1414fb645f85ccd410f2737b":[4,0,15,0],
+"classDbcStatementDispatcher.html":[4,0,16],
+"classDbcStatementDispatcher.html#a2c6e9a614ed747275d43bcccc50d0b2d":[4,0,16,1],
+"classDbcStatementDispatcher.html#a2f064359b59d8644b8a8196653d47482":[4,0,16,0],
+"classDbcStatementDispatcher.html#a495c2d5c7ebb8103b1987cdd87c142ed":[4,0,16,2],
+"classDbcStatementHandler.html":[4,0,17],
+"classDbcStatementHandler.html#a3de86e1e27e9bcb0fe6f1460a8ba5739":[4,0,17,0],
+"classDbcTreeBuilder.html":[4,0,18],
+"classDbcTreeBuilder.html#a7e57d067d831b14b383947fd125edd4b":[4,0,18,0],
+"classDbcTreeModel.html":[4,0,19],
+"classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfd":[4,0,19,1],
+"classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfda155fbc1aa36cd7f15711f4461720fa1d":[4,0,19,1,10],
+"classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfda55cc6538817898e455ae2cbd4cd7e755":[4,0,19,1,7],
+"classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfda66d77c4244f1fcbae2ff66aff2be85d4":[4,0,19,1,1],
+"classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfda716858f9cb0b60a665214362afd210ca":[4,0,19,1,4],
+"classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfda8a5d5985c970c7c04290a7b0f3aa05f0":[4,0,19,1,9],
+"classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfda9df090ff74d5110d75df22a0b2e507e8":[4,0,19,1,5],
+"classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfdabe2c2768f230f994534963c6d32230d7":[4,0,19,1,0],
+"classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfdad1c30e9d3e9ade5edbc5262a2131007b":[4,0,19,1,6],
+"classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfdae702dc1611c58e76e36ee280091be1d8":[4,0,19,1,3],
+"classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfdaee6045bcb658e9feefff87ca7d9e57ff":[4,0,19,1,8],
+"classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfdaf8574caf8d0986f7d6d6d7923a7bdaa0":[4,0,19,1,2],
+"classDbcTreeModel.html#a30bed0d65342917c19d9183da55af452":[4,0,19,6],
+"classDbcTreeModel.html#a397f885e7fd45c387825b4357b875c10":[4,0,19,7],
+"classDbcTreeModel.html#a4f7214b727d812885bf077352ec9ece1":[4,0,19,2],
+"classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069ae":[4,0,19,0],
+"classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069aea01cbc280578dad3fea144b98755b7ef3":[4,0,19,0,8],
+"classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069aea391e0095b1fac0d05fde0d5cb5edda85":[4,0,19,0,5],
+"classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069aea58500e460c83ab951d9271b3b795f234":[4,0,19,0,9],
+"classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069aea5baf88846401000c49679f46e619ef87":[4,0,19,0,6],
+"classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069aea656b55f10472395261871ff7ef3f4484":[4,0,19,0,0],
+"classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069aea657c7487a591debd704e4f7e4536b207":[4,0,19,0,4],
+"classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069aea8bc7de06cffddca5470da004741ed939":[4,0,19,0,2],
+"classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069aeaa154ab92b4d4ef65526238428ae3cace":[4,0,19,0,7],
+"classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069aeaa74a27fd4ea0e2d561c6ba9b15640010":[4,0,19,0,1],
+"classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069aeaa87659982bb22d7598c49cc08cd36c65":[4,0,19,0,3],
+"classDbcTreeModel.html#a8caeb5ec6141eb3e446e48df3c70b3ad":[4,0,19,4],
+"classDbcTreeModel.html#a8cb5a81d456cdead42b75fd3462ee00a":[4,0,19,3],
+"classDbcTreeModel.html#a8f7842a79144bdb24fa9c5fbdcd37295":[4,0,19,10],
+"classDbcTreeModel.html#aad5834e8edb00808cbfa498ea8c63fe9":[4,0,19,9],
+"classDbcTreeModel.html#aca81d05c81cc48c1185fc36659e96e5b":[4,0,19,8],
+"classDbcTreeModel.html#ae40bb8b8a26d205f178c6dd1134ff4b3":[4,0,19,5],
+"classDbcUnsupportedMultiplexingHandler.html":[4,0,20],
+"classDbcUnsupportedMultiplexingHandler.html#a9853fd67465f92ef587792986ea179ac":[4,0,20,0],
+"classDbcValueDescriptionHandler.html":[4,0,21],
+"classDbcValueDescriptionHandler.html#a653e13364f396b54244edc2c0fdd831a":[4,0,21,0],
+"classDecodeDatabase.html":[4,0,22],
+"classDecodeDatabase.html#a0af5b15b9953a4f6551c27ee9ae8b514":[4,0,22,4],
+"classDecodeDatabase.html#a51a44cf7c3f23c98ec8781afe0097c0c":[4,0,22,0],
+"classDecodeDatabase.html#a780d6e747a48b10a5eb0ab85448d2970":[4,0,22,2],
+"classDecodeDatabase.html#aa034c1510984a85f60ad6c0bd744d6e8":[4,0,22,1],
+"classDecodeDatabase.html#aa96b62b4f3fff68ab651674760f60d6d":[4,0,22,3],
+"classTreeNode.html":[4,0,39],
+"classTreeNode.html#a1eb94f7b6e7962c9d867a120772dfe6e":[4,0,39,7],
+"classTreeNode.html#a226518612d0d00b5988a2c44fc21d3f1":[4,0,39,14],
+"classTreeNode.html#a4727ff801a2d1b9323c5ae50a35457a6":[4,0,39,9],
+"classTreeNode.html#a81047bd7d2a4cc96b9ef5e20d0d63b5f":[4,0,39,10],
+"classTreeNode.html#a8e38dd591d8801d7ee3a7dbad90c67fc":[4,0,39,1],
+"classTreeNode.html#a984a98d5ccf7ef1f5a18094c6821f35d":[4,0,39,0],
+"classTreeNode.html#aa48fbc17903eb8cfa40353e29f853c6f":[4,0,39,4],
+"classTreeNode.html#aaac5b8d9dc9e5ae1f367d1adbcf20e18":[4,0,39,12],
+"classTreeNode.html#ab9f00f5253d56461bb2d420fd639c5ae":[4,0,39,2],
+"classTreeNode.html#abdd82460187dca8d3e5d66f5d5c529ea":[4,0,39,8],
+"classTreeNode.html#ad501f97eeec7f7d3353bfae838fbb6a8":[4,0,39,5],
+"classTreeNode.html#af4e6e916c48c024a3dfeadac8174b527":[4,0,39,6],
+"classTreeNode.html#af87331684d4b40240aec75e3286921d3":[4,0,39,3],
+"classTreeNode.html#afa2f4b0aafa12d3d41ed00df8e0250c9":[4,0,39,11],
+"classTreeNode.html#afc503b40004764163605d6dbdb4ef811":[4,0,39,13],
+"classTypeFactory.html":[4,0,40],
+"classTypeFactory.html#a1a119ad2956abe146213c6ca124d8dd4":[4,0,40,5],
+"classTypeFactory.html#a33b404da3e19ea7e1245b8a4975721bf":[4,0,40,0],
+"classTypeFactory.html#a3f43b03d6e3a0fd503fdec01ecf62e9f":[4,0,40,4],
+"classTypeFactory.html#a5f119fe61c1cb9f4725ce746e4a047b3":[4,0,40,6],
+"classTypeFactory.html#a650022aac1e2f30af5bc554a5663939f":[4,0,40,1],
+"classTypeFactory.html#ad6d85795285ee21193ac03e1b24762d3":[4,0,40,2],
+"classTypeFactory.html#ad82f537569ece3d3a4a376523fa94473":[4,0,40,3],
+"classes.html":[4,1],
+"dbc__attributes_8cpp_source.html":[5,0,0,1],
+"dbc__coverage__test_8cpp_source.html":[5,0,3,0],
+"dbc__database_8h.html":[5,0,0,2],
+"dbc__database_8h_source.html":[5,0,0,2],
+"dbc__decode__builder_8cpp.html":[5,0,0,3],
+"dbc__decode__builder_8cpp_source.html":[5,0,0,3],
+"dbc__decode__builder_8h.html":[5,0,0,4],
+"dbc__decode__builder_8h_source.html":[5,0,0,4],
+"dbc__decoder_8cpp.html":[5,0,0,5],
+"dbc__decoder_8cpp_source.html":[5,0,0,5],
+"dbc__decoder_8h.html":[5,0,0,6],
+"dbc__decoder_8h.html#a5f4a41ee2810487020135b45e8d7559a":[5,0,0,6,4],
+"dbc__decoder_8h.html#a5f4a41ee2810487020135b45e8d7559aa3ac705f2acd51a4613f9188c05c91d0d":[5,0,0,6,4,4],
+"dbc__decoder_8h.html#a5f4a41ee2810487020135b45e8d7559aa3cab03c00dbd11bc3569afa0748013f0":[5,0,0,6,4,3],
+"dbc__decoder_8h.html#a5f4a41ee2810487020135b45e8d7559aa6e43305edb6a91f66811f9af70346d81":[5,0,0,6,4,2],
+"dbc__decoder_8h.html#a5f4a41ee2810487020135b45e8d7559aa7c9fa088a1e7db1fc83cb62aefd3ea7f":[5,0,0,6,4,1],
+"dbc__decoder_8h.html#a5f4a41ee2810487020135b45e8d7559aaa20a6f8fa79aa562f9d3392c0060df54":[5,0,0,6,4,0],
+"dbc__decoder_8h.html#a5f4a41ee2810487020135b45e8d7559aae7d6c26841c7125dc32c49f3bbc8a436":[5,0,0,6,4,5],
+"dbc__decoder_8h.html#a855b2bc36cb18bfbae5ff30a2394e961":[5,0,0,6,5],
+"dbc__decoder_8h.html#a855b2bc36cb18bfbae5ff30a2394e961a3ac705f2acd51a4613f9188c05c91d0d":[5,0,0,6,5,3],
+"dbc__decoder_8h.html#a855b2bc36cb18bfbae5ff30a2394e961a7c9fa088a1e7db1fc83cb62aefd3ea7f":[5,0,0,6,5,1],
+"dbc__decoder_8h.html#a855b2bc36cb18bfbae5ff30a2394e961a85f5d387f9a01dce258470e1a5a23332":[5,0,0,6,5,0],
+"dbc__decoder_8h.html#a855b2bc36cb18bfbae5ff30a2394e961a88db09d74e14ac6c0a3bc7cd91b45358":[5,0,0,6,5,4],
+"dbc__decoder_8h.html#a855b2bc36cb18bfbae5ff30a2394e961aedeb8da96660592dfe0853f212b77469":[5,0,0,6,5,2],
+"dbc__decoder_8h_source.html":[5,0,0,6],
+"dbc__decoder__test_8cpp_source.html":[5,0,3,1],
+"dbc__diagnostic_8h_source.html":[5,0,0,7],
+"dbc__lifetime__test_8cpp_source.html":[5,0,3,2],
+"dbc__parser_8cpp.html":[5,0,0,8],
+"dbc__parser_8cpp_source.html":[5,0,0,8],
+"dbc__parser_8h.html":[5,0,0,9],
+"dbc__parser_8h_source.html":[5,0,0,9],
+"dbc__parser__test_8cpp_source.html":[5,0,3,3],
+"dbc__pipeline__test_8cpp_source.html":[5,0,3,4],
+"dbc__statement__handler_8cpp_source.html":[5,0,0,10],
+"dbc__statement__handler_8h_source.html":[5,0,0,11],
+"dbc__tree__builder_8cpp.html":[5,0,0,12],
+"dbc__tree__builder_8cpp_source.html":[5,0,0,12],
+"dbc__tree__builder_8h.html":[5,0,0,13],
+"dbc__tree__builder_8h_source.html":[5,0,0,13],
+"dbc__tree__model_8cpp_source.html":[5,0,2,0],
+"dbc__tree__model_8h_source.html":[5,0,2,1],
+"dbc__tree__model__test_8cpp_source.html":[5,0,3,5],
+"dbc__validation__test_8cpp_source.html":[5,0,3,6],
+"decode__database_8cpp_source.html":[5,0,0,14],
+"decode__database_8h.html":[5,0,0,15],
+"decode__database_8h.html#aaeb92d42f5a6e27b8ba19f18d69d142b":[5,0,0,15,4],
+"decode__database_8h.html#aaeb92d42f5a6e27b8ba19f18d69d142ba2ed1afe3c9215523e4272f46e6186b31":[5,0,0,15,4,1],
+"decode__database_8h.html#aaeb92d42f5a6e27b8ba19f18d69d142baff97a9fdede09eaf6e1c8ec9f6a61dd5":[5,0,0,15,4,0],
+"decode__database_8h.html#ad9971b6ef33e02ba2c75d19c1d2518a1":[5,0,0,15,5],
+"decode__database_8h.html#ad9971b6ef33e02ba2c75d19c1d2518a1a71fed0c3428bf1a2e19af257c4bac379":[5,0,0,15,5,1],
+"decode__database_8h.html#ad9971b6ef33e02ba2c75d19c1d2518a1aa1a914735b205424ba6c40b85528d78a":[5,0,0,15,5,0],
+"decode__database_8h_source.html":[5,0,0,15],
+"definition__key_8h_source.html":[5,0,0,16],
+"dir_0f63d6441a2c250919e1e8723011eb2f.html":[5,0,2],
+"dir_4270bfced15e0e73154b13468c7c9ad9.html":[5,0,0],
+"dir_59425e443f801f1f2fd8bbe4959a3ccf.html":[5,0,3],
+"dir_d28a4824dc47e487b107a5db32ef43c4.html":[5,0,1],
+"examples_2main_8cpp.html":[5,0,1,0],
+"examples_2main_8cpp.html#a0ddf1224851353fc92bfbff6f499fa97":[5,0,1,0,0],
+"examples_2main_8cpp_source.html":[5,0,1,0],
+"files.html":[5,0],
+"frame__info_8h.html":[5,0,0,17],
+"frame__info_8h_source.html":[5,0,0,17],
+"functions.html":[4,3,0],
+"functions_enum.html":[4,3,4],
+"functions_func.html":[4,3,1],
+"functions_type.html":[4,3,3],
+"functions_vars.html":[4,3,2],
+"globals.html":[5,1,0],
+"globals_enum.html":[5,1,2],
+"globals_func.html":[5,1,1],
+"hierarchy.html":[4,2],
"index.html":[],
-"md_README.html":[1],
-"md_README.html#autotoc_md100":[1,33,0],
-"md_README.html#autotoc_md101":[1,33,1],
-"md_README.html#autotoc_md102":[1,33,2],
-"md_README.html#autotoc_md103":[1,33,3],
-"md_README.html#autotoc_md105":[1,34],
-"md_README.html#autotoc_md106":[1,34,0],
-"md_README.html#autotoc_md107":[1,34,1],
-"md_README.html#autotoc_md109":[1,35],
-"md_README.html#autotoc_md111":[1,36],
-"md_README.html#autotoc_md113":[1,37],
-"md_README.html#autotoc_md115":[1,38],
-"md_README.html#autotoc_md117":[1,39],
-"md_README.html#autotoc_md119":[1,40],
-"md_README.html#autotoc_md120":[1,40,0],
-"md_README.html#autotoc_md121":[1,40,1],
-"md_README.html#autotoc_md122":[1,40,2],
-"md_README.html#autotoc_md123":[1,40,3],
-"md_README.html#autotoc_md125":[1,41],
-"md_README.html#autotoc_md126":[1,41,0],
-"md_README.html#autotoc_md127":[1,41,1],
-"md_README.html#autotoc_md128":[1,41,2],
-"md_README.html#autotoc_md129":[1,41,3],
-"md_README.html#autotoc_md130":[1,41,4],
-"md_README.html#autotoc_md132":[1,42],
-"md_README.html#autotoc_md133":[1,43],
-"md_README.html#autotoc_md134":[1,43,0],
-"md_README.html#autotoc_md135":[1,43,1],
-"md_README.html#autotoc_md136":[1,43,2],
-"md_README.html#autotoc_md27":[1,0],
-"md_README.html#autotoc_md29":[1,1],
-"md_README.html#autotoc_md30":[1,1,0],
-"md_README.html#autotoc_md31":[1,1,1],
-"md_README.html#autotoc_md33":[1,2],
-"md_README.html#autotoc_md35":[1,3],
-"md_README.html#autotoc_md37":[1,4],
-"md_README.html#autotoc_md38":[1,5],
-"md_README.html#autotoc_md40":[1,6],
-"md_README.html#autotoc_md42":[1,7],
-"md_README.html#autotoc_md44":[1,8],
-"md_README.html#autotoc_md45":[1,9],
-"md_README.html#autotoc_md47":[1,10],
-"md_README.html#autotoc_md48":[1,11],
-"md_README.html#autotoc_md50":[1,12],
-"md_README.html#autotoc_md52":[1,13],
-"md_README.html#autotoc_md54":[1,14],
-"md_README.html#autotoc_md56":[1,15],
-"md_README.html#autotoc_md58":[1,16],
-"md_README.html#autotoc_md60":[1,17],
-"md_README.html#autotoc_md62":[1,18],
-"md_README.html#autotoc_md63":[1,19],
-"md_README.html#autotoc_md65":[1,20],
-"md_README.html#autotoc_md67":[1,20,0],
-"md_README.html#autotoc_md69":[1,21],
-"md_README.html#autotoc_md70":[1,21,0],
-"md_README.html#autotoc_md71":[1,21,1],
-"md_README.html#autotoc_md73":[1,22],
-"md_README.html#autotoc_md75":[1,23],
-"md_README.html#autotoc_md76":[1,23,0],
-"md_README.html#autotoc_md78":[1,24],
-"md_README.html#autotoc_md79":[1,25],
-"md_README.html#autotoc_md81":[1,25,0],
-"md_README.html#autotoc_md83":[1,26],
-"md_README.html#autotoc_md85":[1,26,0],
-"md_README.html#autotoc_md87":[1,27],
-"md_README.html#autotoc_md89":[1,28],
-"md_README.html#autotoc_md91":[1,29],
-"md_README.html#autotoc_md93":[1,30],
-"md_README.html#autotoc_md95":[1,31],
-"md_README.html#autotoc_md97":[1,32],
-"md_README.html#autotoc_md99":[1,33],
-"md_changelog.html":[0],
-"md_changelog.html#autotoc_md1":[0,0],
-"md_changelog.html#autotoc_md10":[0,0,2,1],
-"md_changelog.html#autotoc_md11":[0,0,2,2],
-"md_changelog.html#autotoc_md12":[0,0,3],
-"md_changelog.html#autotoc_md13":[0,0,3,0],
-"md_changelog.html#autotoc_md14":[0,0,4],
-"md_changelog.html#autotoc_md15":[0,0,4,0],
-"md_changelog.html#autotoc_md16":[0,0,4,1],
-"md_changelog.html#autotoc_md17":[0,0,4,2],
-"md_changelog.html#autotoc_md18":[0,0,5],
-"md_changelog.html#autotoc_md19":[0,0,5,0],
-"md_changelog.html#autotoc_md2":[0,0,0],
-"md_changelog.html#autotoc_md20":[0,0,5,1],
-"md_changelog.html#autotoc_md21":[0,1],
-"md_changelog.html#autotoc_md22":[0,1,0],
-"md_changelog.html#autotoc_md23":[0,1,1],
-"md_changelog.html#autotoc_md24":[0,1,1,0],
-"md_changelog.html#autotoc_md25":[0,1,1,1],
-"md_changelog.html#autotoc_md3":[0,0,0,0],
-"md_changelog.html#autotoc_md4":[0,0,0,1],
-"md_changelog.html#autotoc_md5":[0,0,1],
-"md_changelog.html#autotoc_md6":[0,0,1,0],
-"md_changelog.html#autotoc_md7":[0,0,1,1],
-"md_changelog.html#autotoc_md8":[0,0,2],
-"md_changelog.html#autotoc_md9":[0,0,2,0],
-"md_tests_2README.html":[2],
-"md_tests_2README.html#autotoc_md138":[2,0],
-"md_tests_2README.html#autotoc_md139":[2,1],
-"md_tests_2README.html#autotoc_md140":[2,2],
-"md_tests_2README.html#autotoc_md141":[2,3],
-"md_tests_2README.html#autotoc_md142":[2,4],
-"md_tests_2README.html#autotoc_md143":[2,5],
-"multiplexing_8h_source.html":[4,0,0,16],
-"pages.html":[],
-"signal__info_8h.html":[4,0,0,17],
-"signal__info_8h_source.html":[4,0,0,17],
-"signal__layout_8h_source.html":[4,0,0,18],
-"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],
-"structDecodeFrame.html":[3,0,21],
-"structDecodeFrame.html#a1d3c54055c0cbceb73adf551f7067f23":[3,0,21,4],
-"structDecodeFrame.html#a2551102670c4a540fced4c71da0b369d":[3,0,21,5],
-"structDecodeFrame.html#a25819ef907a32391af5c9f7cae9cdb22":[3,0,21,7],
-"structDecodeFrame.html#a3ee2348d781f8f15aaf87e8dcf57ec41":[3,0,21,2],
-"structDecodeFrame.html#a51111ac13988be372d5673d12cf3e060":[3,0,21,3],
-"structDecodeFrame.html#a52e10215388db7df8b541b9d9909edcf":[3,0,21,1],
-"structDecodeFrame.html#a7f4e71bbdec3f424b625e724e3dfbf14":[3,0,21,8],
-"structDecodeFrame.html#aa0a7f8fd5bfde2148dfd0d838328f579":[3,0,21,0],
-"structDecodeFrame.html#ad78241dc40c793aabb8495b6989b81a9":[3,0,21,6],
-"structDecodeSignal.html":[3,0,22],
-"structDecodeSignal.html#a0fb84e19a0ab3bd50b6f65c1075ebc25":[3,0,22,7],
-"structDecodeSignal.html#a38eed9ca7581423fd8bfbedcffc12092":[3,0,22,9],
-"structDecodeSignal.html#a428c39913a366a8476dd291061354391":[3,0,22,5],
-"structDecodeSignal.html#a4a6ba87142a9badbf0ca830e9e709cb7":[3,0,22,8],
-"structDecodeSignal.html#a58cf5844f2272a23dcb9687d912e4780":[3,0,22,0],
-"structDecodeSignal.html#a822155d9bf4ed5f3300c9e9befe606ff":[3,0,22,11],
-"structDecodeSignal.html#a92db637af4e224a0ae70173050dc3f74":[3,0,22,6],
-"structDecodeSignal.html#a9d37638129263b8902ba5be59baf39a8":[3,0,22,4],
-"structDecodeSignal.html#aaf5d7527ddf65b6355c2b4f3626df22d":[3,0,22,1],
-"structDecodeSignal.html#abdbae62a64d2df716bf60c6b67b30eaa":[3,0,22,10],
-"structDecodeSignal.html#abdc4c4bb4a67a6d61d6ca81e8a52833d":[3,0,22,3],
-"structDecodeSignal.html#acd4ef5ee30421d117b5756854302debb":[3,0,22,2],
-"structDecodeSignal.html#ae28c905d4a2bc86419c2a8361bfea473":[3,0,22,12],
-"structDecodedFrameValue.html":[3,0,19],
-"structDecodedFrameValue.html#a32143efe2023a1ecd977a9ae93e50b73":[3,0,19,1],
-"structDecodedFrameValue.html#a33e971ba10030506007aa201c89f351d":[3,0,19,0],
-"structDecodedFrameValue.html#a4f51c31110dba1f73a763c596372beb0":[3,0,19,3],
-"structDecodedFrameValue.html#a645f433798d48a2787e7f00dfbb7dff9":[3,0,19,4],
-"structDecodedFrameValue.html#adae123ac7fbb4a5c314b64b01109f4a8":[3,0,19,2]
+"j1939_8h_source.html":[5,0,0,18],
+"md_AGENTS.html":[0],
+"md_AGENTS.html#autotoc_md1":[0,0],
+"md_AGENTS.html#autotoc_md2":[0,1],
+"md_AGENTS.html#autotoc_md3":[0,2],
+"md_AGENTS.html#autotoc_md4":[0,3],
+"md_AGENTS.html#autotoc_md5":[0,4],
+"md_README.html":[2],
+"md_README.html#autotoc_md100":[2,26],
+"md_README.html#autotoc_md102":[2,26,0],
+"md_README.html#autotoc_md104":[2,27],
+"md_README.html#autotoc_md106":[2,28],
+"md_README.html#autotoc_md108":[2,29],
+"md_README.html#autotoc_md110":[2,30],
+"md_README.html#autotoc_md112":[2,31],
+"md_README.html#autotoc_md114":[2,32],
+"md_README.html#autotoc_md116":[2,33],
+"md_README.html#autotoc_md117":[2,33,0],
+"md_README.html#autotoc_md118":[2,33,1],
+"md_README.html#autotoc_md119":[2,33,2],
+"md_README.html#autotoc_md120":[2,33,3],
+"md_README.html#autotoc_md122":[2,34],
+"md_README.html#autotoc_md123":[2,34,0],
+"md_README.html#autotoc_md124":[2,34,1],
+"md_README.html#autotoc_md126":[2,35],
+"md_README.html#autotoc_md128":[2,36],
+"md_README.html#autotoc_md130":[2,37],
+"md_README.html#autotoc_md132":[2,38],
+"md_README.html#autotoc_md134":[2,39],
+"md_README.html#autotoc_md136":[2,40],
+"md_README.html#autotoc_md137":[2,40,0],
+"md_README.html#autotoc_md138":[2,40,1],
+"md_README.html#autotoc_md139":[2,40,2],
+"md_README.html#autotoc_md140":[2,40,3],
+"md_README.html#autotoc_md142":[2,41],
+"md_README.html#autotoc_md143":[2,41,0],
+"md_README.html#autotoc_md144":[2,41,1],
+"md_README.html#autotoc_md145":[2,41,2],
+"md_README.html#autotoc_md146":[2,41,3],
+"md_README.html#autotoc_md147":[2,41,4],
+"md_README.html#autotoc_md149":[2,42],
+"md_README.html#autotoc_md150":[2,43],
+"md_README.html#autotoc_md151":[2,44],
+"md_README.html#autotoc_md152":[2,44,0],
+"md_README.html#autotoc_md153":[2,44,1],
+"md_README.html#autotoc_md154":[2,44,2],
+"md_README.html#autotoc_md43":[2,0],
+"md_README.html#autotoc_md45":[2,1],
+"md_README.html#autotoc_md46":[2,1,0],
+"md_README.html#autotoc_md47":[2,1,1],
+"md_README.html#autotoc_md49":[2,2],
+"md_README.html#autotoc_md51":[2,3],
+"md_README.html#autotoc_md53":[2,4],
+"md_README.html#autotoc_md54":[2,5],
+"md_README.html#autotoc_md56":[2,6],
+"md_README.html#autotoc_md58":[2,7],
+"md_README.html#autotoc_md60":[2,8],
+"md_README.html#autotoc_md61":[2,9],
+"md_README.html#autotoc_md63":[2,10],
+"md_README.html#autotoc_md64":[2,11],
+"md_README.html#autotoc_md66":[2,12],
+"md_README.html#autotoc_md68":[2,13],
+"md_README.html#autotoc_md70":[2,14],
+"md_README.html#autotoc_md72":[2,15],
+"md_README.html#autotoc_md74":[2,16],
+"md_README.html#autotoc_md76":[2,17],
+"md_README.html#autotoc_md78":[2,18],
+"md_README.html#autotoc_md79":[2,19],
+"md_README.html#autotoc_md81":[2,20],
+"md_README.html#autotoc_md83":[2,20,0],
+"md_README.html#autotoc_md85":[2,21],
+"md_README.html#autotoc_md86":[2,21,0],
+"md_README.html#autotoc_md87":[2,21,1],
+"md_README.html#autotoc_md89":[2,22],
+"md_README.html#autotoc_md91":[2,23]
};
diff --git a/docs/html/navtreeindex1.js b/docs/html/navtreeindex1.js
index e0fec52..13a45b3 100644
--- a/docs/html/navtreeindex1.js
+++ b/docs/html/navtreeindex1.js
@@ -1,57 +1,231 @@
var NAVTREEINDEX1 =
{
-"structDecodedSignalValue.html":[3,0,20],
-"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],
-"structRawCanFrame.html#a2d0e7fa0e3d5c20bbed55ed8f7888ff4":[3,0,28,0],
-"structRawCanFrame.html#a462193d275adc1dba8bd18ffa0e36bb7":[3,0,28,1],
-"structSignalInfo.html":[3,0,29],
-"structSignalInfo.html#a1008b5201f71848177217bd52fb84baa":[3,0,29,2],
-"structSignalInfo.html#a1f214f03e94ef5794de2d3367bfcbd01":[3,0,29,9],
-"structSignalInfo.html#a2c95562fd0b29327a7fd7b1e6feee7f3":[3,0,29,10],
-"structSignalInfo.html#a379e422a00cad56f896cacf60455b088":[3,0,29,0],
-"structSignalInfo.html#a43f47d0433d0cc39076bd7278b46af9c":[3,0,29,11],
-"structSignalInfo.html#a52a52b320eef92fbcb4626307f9a498f":[3,0,29,4],
-"structSignalInfo.html#ab7d0769f47aa540656b22e4e49db517e":[3,0,29,6],
-"structSignalInfo.html#ac99ba7563a5dad01e39c4257216953f5":[3,0,29,12],
-"structSignalInfo.html#ace290724f9801521609aedaa946d61f1":[3,0,29,1],
-"structSignalInfo.html#ada7bf94fbeaa26bd08c73982b5af255b":[3,0,29,7],
-"structSignalInfo.html#adf1c4331b9eabced0d7fdda40ff0eb52":[3,0,29,8],
-"structSignalInfo.html#ae4f78d99a2750aa564d7eba860171499":[3,0,29,5],
-"structSignalInfo.html#af363b1563fb4c7cc8973f9a80c06846c":[3,0,29,3],
-"structSignalKey.html":[3,0,30],
-"structSignalKeyHasher.html":[3,0,31],
-"tests_2main_8cpp_source.html":[4,0,3,6],
-"text__utils_8h_source.html":[4,0,0,19],
-"tree__node_8cpp.html":[4,0,0,20],
-"tree__node_8cpp_source.html":[4,0,0,20],
-"tree__node_8h.html":[4,0,0,21],
-"tree__node_8h.html#acac9cbaeea226ed297804c012dc12b16":[4,0,0,21,1],
-"tree__node_8h.html#acac9cbaeea226ed297804c012dc12b16a085fea7abdc5d904fe69a3081efd7398":[4,0,0,21,1,2],
-"tree__node_8h.html#acac9cbaeea226ed297804c012dc12b16a3bb3e8c8a24891ba0f7608bcc96f8b0a":[4,0,0,21,1,1],
-"tree__node_8h.html#acac9cbaeea226ed297804c012dc12b16afa03eb688ad8aa1db593d33dabd89bad":[4,0,0,21,1,0],
-"tree__node_8h_source.html":[4,0,0,21],
-"tree__node__test_8cpp_source.html":[4,0,3,7],
-"typefactory_8h_source.html":[4,0,0,22],
-"value__descriptions_8h_source.html":[4,0,0,23]
+"md_README.html#autotoc_md92":[2,23,0],
+"md_README.html#autotoc_md93":[2,23,1],
+"md_README.html#autotoc_md95":[2,24],
+"md_README.html#autotoc_md96":[2,25],
+"md_README.html#autotoc_md98":[2,25,0],
+"md_changelog.html":[1],
+"md_changelog.html#autotoc_md10":[1,0,0,1],
+"md_changelog.html#autotoc_md11":[1,0,0,2],
+"md_changelog.html#autotoc_md12":[1,0,0,3],
+"md_changelog.html#autotoc_md13":[1,0,0,4],
+"md_changelog.html#autotoc_md14":[1,0,1],
+"md_changelog.html#autotoc_md15":[1,0,1,0],
+"md_changelog.html#autotoc_md16":[1,0,1,1],
+"md_changelog.html#autotoc_md17":[1,0,1,2],
+"md_changelog.html#autotoc_md18":[1,0,2],
+"md_changelog.html#autotoc_md19":[1,0,2,0],
+"md_changelog.html#autotoc_md20":[1,0,2,1],
+"md_changelog.html#autotoc_md21":[1,0,3],
+"md_changelog.html#autotoc_md22":[1,0,3,0],
+"md_changelog.html#autotoc_md23":[1,0,3,1],
+"md_changelog.html#autotoc_md24":[1,0,4],
+"md_changelog.html#autotoc_md25":[1,0,4,0],
+"md_changelog.html#autotoc_md26":[1,0,4,1],
+"md_changelog.html#autotoc_md27":[1,0,4,2],
+"md_changelog.html#autotoc_md28":[1,0,5],
+"md_changelog.html#autotoc_md29":[1,0,5,0],
+"md_changelog.html#autotoc_md30":[1,0,6],
+"md_changelog.html#autotoc_md31":[1,0,6,0],
+"md_changelog.html#autotoc_md32":[1,0,6,1],
+"md_changelog.html#autotoc_md33":[1,0,6,2],
+"md_changelog.html#autotoc_md34":[1,0,7],
+"md_changelog.html#autotoc_md35":[1,0,7,0],
+"md_changelog.html#autotoc_md36":[1,0,7,1],
+"md_changelog.html#autotoc_md37":[1,1],
+"md_changelog.html#autotoc_md38":[1,1,0],
+"md_changelog.html#autotoc_md39":[1,1,1],
+"md_changelog.html#autotoc_md40":[1,1,1,0],
+"md_changelog.html#autotoc_md41":[1,1,1,1],
+"md_changelog.html#autotoc_md7":[1,0],
+"md_changelog.html#autotoc_md8":[1,0,0],
+"md_changelog.html#autotoc_md9":[1,0,0,0],
+"md_tests_2README.html":[3],
+"md_tests_2README.html#autotoc_md156":[3,0],
+"md_tests_2README.html#autotoc_md157":[3,1],
+"md_tests_2README.html#autotoc_md158":[3,2],
+"md_tests_2README.html#autotoc_md159":[3,3],
+"md_tests_2README.html#autotoc_md160":[3,4],
+"md_tests_2README.html#autotoc_md161":[3,5],
+"md_tests_2README.html#autotoc_md162":[3,6],
+"md_tests_2README.html#autotoc_md163":[3,7],
+"md_tests_2README.html#autotoc_md164":[3,8],
+"multiplexing_8h_source.html":[5,0,0,19],
+"pages.html":[],
+"signal__info_8h.html":[5,0,0,20],
+"signal__info_8h_source.html":[5,0,0,20],
+"signal__layout_8h_source.html":[5,0,0,21],
+"structAttributeAssignment.html":[4,0,0],
+"structAttributeAssignment.html#a024a249cc63dbfbf337eea395fe3471e":[4,0,0,3],
+"structAttributeAssignment.html#a330ae1a34c342b0352115a83dd31aab8":[4,0,0,2],
+"structAttributeAssignment.html#a50059e42e5e5b944050f3290ce84ac66":[4,0,0,4],
+"structAttributeAssignment.html#a50405e8db9e4536015f9adc5ba360270":[4,0,0,1],
+"structAttributeAssignment.html#a93de8c51c5154219bf18beadcec5708f":[4,0,0,5],
+"structAttributeAssignment.html#aa8707eddd2d3a2de559fe44354a514cc":[4,0,0,0],
+"structAttributeDefinition.html":[4,0,1],
+"structAttributeDefinition.html#a18245dba995929a61fd6de1fcdbc8a89":[4,0,1,4],
+"structAttributeDefinition.html#a547fe17f6cfc631528f9156e4a509c66":[4,0,1,6],
+"structAttributeDefinition.html#a5ca8f41ea3e921f54d81b8760c1dcfb3":[4,0,1,3],
+"structAttributeDefinition.html#a5de5484174a8c5f6b309041089d20afc":[4,0,1,1],
+"structAttributeDefinition.html#a5f109f0ec94eb04c3f52c116366aefdf":[4,0,1,0],
+"structAttributeDefinition.html#aa02fe74b5420c2e67c13e610b6bc9713":[4,0,1,5],
+"structAttributeDefinition.html#aaf87153bac0b228ad87b88e96f303210":[4,0,1,2],
+"structAttributeDefinition.html#ae0949edf67f9d4e60e4cb376a95da4f2":[4,0,1,7],
+"structDbcDatabase.html":[4,0,4],
+"structDbcDatabase.html#a14862245081989f2abf126b5ea6dfdfa":[4,0,4,1],
+"structDbcDatabase.html#a2cade5d0234ee816132127542f8c612b":[4,0,4,0],
+"structDbcDatabase.html#a321839ad81af176444358eb23114eaee":[4,0,4,3],
+"structDbcDatabase.html#aa7bdf56eb8b7ab5b873e1c096b46d8b6":[4,0,4,2],
+"structDbcDiagnostic.html":[4,0,7],
+"structDbcDiagnostic.html#a124bae82eebeaef46426bd124685ef1b":[4,0,7,4],
+"structDbcDiagnostic.html#a75040a94f0313a606478020b0491f81d":[4,0,7,0],
+"structDbcDiagnostic.html#aa315a4a40b15f2e8cb34264d94a0f914":[4,0,7,1],
+"structDbcDiagnostic.html#ac9f02705ed6a633cbb9526d0e392fb95":[4,0,7,2],
+"structDbcDiagnostic.html#adb201de8d32b768d5f559bed21e8f819":[4,0,7,3],
+"structDbcParseContext.html":[4,0,11],
+"structDbcParseContext.html#a1ac7f4a54550aaddef08749806f87001":[4,0,11,2],
+"structDbcParseContext.html#a57f5a7f613ecd0dadbafa7af736b7e54":[4,0,11,7],
+"structDbcParseContext.html#a79bad0b8302e2156670461bab529259c":[4,0,11,4],
+"structDbcParseContext.html#a854abba7bbf4adfc948554c254156e60":[4,0,11,10],
+"structDbcParseContext.html#a908056de0a97316a4ebecb3f99cc400b":[4,0,11,0],
+"structDbcParseContext.html#a93f8ece0f3d16bd79f631ae07afa7b54":[4,0,11,6],
+"structDbcParseContext.html#ab5552dad944fde7fa6add6464ddb5369":[4,0,11,3],
+"structDbcParseContext.html#ac22cba614ada3a28c7dcc1ea338b0e01":[4,0,11,8],
+"structDbcParseContext.html#aeae343c57a244634489a0e0b960155d7":[4,0,11,1],
+"structDbcParseContext.html#af31b56247edff7f025957ae023a56913":[4,0,11,5],
+"structDbcParseContext.html#af8b411c938a2ea9100c4aaae452e6546":[4,0,11,9],
+"structDbcParseContext.html#afbfa4b26a58b41ada3dabc619066035c":[4,0,11,11],
+"structDbcParseResult.html":[4,0,13],
+"structDbcParseResult.html#a3a1987b4381bb1e0a34dc09e31483679":[4,0,13,2],
+"structDbcParseResult.html#a4da8641de3f6b55c7447c4421e05d20d":[4,0,13,0],
+"structDbcParseResult.html#abfa765d29a4397e8ddaf771bae21993e":[4,0,13,1],
+"structDbcParserOptions.html":[4,0,14],
+"structDbcParserOptions.html#ab31534f5c0853461b46cbb38149c33f9":[4,0,14,0],
+"structDecodeFrame.html":[4,0,25],
+"structDecodeFrame.html#a05e3d1c6143367553c2c3beba82a5c34":[4,0,25,0],
+"structDecodeFrame.html#a1d3c54055c0cbceb73adf551f7067f23":[4,0,25,5],
+"structDecodeFrame.html#a2551102670c4a540fced4c71da0b369d":[4,0,25,6],
+"structDecodeFrame.html#a25819ef907a32391af5c9f7cae9cdb22":[4,0,25,8],
+"structDecodeFrame.html#a3ee2348d781f8f15aaf87e8dcf57ec41":[4,0,25,3],
+"structDecodeFrame.html#a475e669f390491a4d99383d3fee51300":[4,0,25,11],
+"structDecodeFrame.html#a51111ac13988be372d5673d12cf3e060":[4,0,25,4],
+"structDecodeFrame.html#a52e10215388db7df8b541b9d9909edcf":[4,0,25,2],
+"structDecodeFrame.html#a732c2f6853d55ce8253db61207fc21d3":[4,0,25,12],
+"structDecodeFrame.html#a7f4e71bbdec3f424b625e724e3dfbf14":[4,0,25,9],
+"structDecodeFrame.html#aa0a7f8fd5bfde2148dfd0d838328f579":[4,0,25,1],
+"structDecodeFrame.html#ad506b03108a40df7e8005638c9c59653":[4,0,25,10],
+"structDecodeFrame.html#ad78241dc40c793aabb8495b6989b81a9":[4,0,25,7],
+"structDecodeSignal.html":[4,0,26],
+"structDecodeSignal.html#a0fb84e19a0ab3bd50b6f65c1075ebc25":[4,0,26,8],
+"structDecodeSignal.html#a204f65c7ea45a2c148f19c12d922f99b":[4,0,26,14],
+"structDecodeSignal.html#a38eed9ca7581423fd8bfbedcffc12092":[4,0,26,10],
+"structDecodeSignal.html#a428c39913a366a8476dd291061354391":[4,0,26,6],
+"structDecodeSignal.html#a4a6ba87142a9badbf0ca830e9e709cb7":[4,0,26,9],
+"structDecodeSignal.html#a58cf5844f2272a23dcb9687d912e4780":[4,0,26,1],
+"structDecodeSignal.html#a822155d9bf4ed5f3300c9e9befe606ff":[4,0,26,12],
+"structDecodeSignal.html#a92db637af4e224a0ae70173050dc3f74":[4,0,26,7],
+"structDecodeSignal.html#a9d37638129263b8902ba5be59baf39a8":[4,0,26,5],
+"structDecodeSignal.html#aaf5d7527ddf65b6355c2b4f3626df22d":[4,0,26,2],
+"structDecodeSignal.html#abdbae62a64d2df716bf60c6b67b30eaa":[4,0,26,11],
+"structDecodeSignal.html#abdc4c4bb4a67a6d61d6ca81e8a52833d":[4,0,26,4],
+"structDecodeSignal.html#acd4ef5ee30421d117b5756854302debb":[4,0,26,3],
+"structDecodeSignal.html#ae28c905d4a2bc86419c2a8361bfea473":[4,0,26,13],
+"structDecodeSignal.html#aea41c055cb255fe7bd178ed5727f28c9":[4,0,26,0],
+"structDecodedFrameValue.html":[4,0,23],
+"structDecodedFrameValue.html#a32143efe2023a1ecd977a9ae93e50b73":[4,0,23,1],
+"structDecodedFrameValue.html#a33e971ba10030506007aa201c89f351d":[4,0,23,0],
+"structDecodedFrameValue.html#a4f51c31110dba1f73a763c596372beb0":[4,0,23,3],
+"structDecodedFrameValue.html#a645f433798d48a2787e7f00dfbb7dff9":[4,0,23,4],
+"structDecodedFrameValue.html#adae123ac7fbb4a5c314b64b01109f4a8":[4,0,23,2],
+"structDecodedSignalValue.html":[4,0,24],
+"structDecodedSignalValue.html#a33df0fcd92b23b3e08539906fc6b4c4a":[4,0,24,2],
+"structDecodedSignalValue.html#a503c90b4b1a610b8252c45e466367c28":[4,0,24,3],
+"structDecodedSignalValue.html#a6847d05b3cb00d5e0f6c611968f57978":[4,0,24,4],
+"structDecodedSignalValue.html#a828b5ef7faefc14fbf5dbd46249bcad2":[4,0,24,1],
+"structDecodedSignalValue.html#a94161a80412b3961da8fd2fec43c25f6":[4,0,24,6],
+"structDecodedSignalValue.html#aac0ed361af545cde48d0e6f41a859686":[4,0,24,5],
+"structDecodedSignalValue.html#affc38af1bf31bcb6f2c33044bce92bd2":[4,0,24,0],
+"structFrameInfo.html":[4,0,27],
+"structFrameInfo.html#a099f02a77adfb9ac23e286ce75f4eef4":[4,0,27,10],
+"structFrameInfo.html#a34b726afaad2ac5c697fdb2ac070cdaf":[4,0,27,2],
+"structFrameInfo.html#a35bf839519ef3f48b5f52dd9bcd7e9ac":[4,0,27,9],
+"structFrameInfo.html#a3f7e25d67ddae22f2ed50823a5a26084":[4,0,27,8],
+"structFrameInfo.html#a4737a5420213ad4304724e39f3a4e55d":[4,0,27,4],
+"structFrameInfo.html#a92749ec3798d4211a505860fb389a9e8":[4,0,27,6],
+"structFrameInfo.html#a9ef2736053b593cf34ba2608cf8275c0":[4,0,27,11],
+"structFrameInfo.html#aa2b198ea0f55e560c123d35e7b3ecab9":[4,0,27,5],
+"structFrameInfo.html#abb53a7f93ed7abc0ea1ae4a8ccafcdcb":[4,0,27,0],
+"structFrameInfo.html#ace75121294f9d89b762080ab5643293c":[4,0,27,7],
+"structFrameInfo.html#aee518b33f1000bf0b7f6e4a87474c943":[4,0,27,3],
+"structFrameInfo.html#af470b0742c05bfbffc31c51a68f5c05e":[4,0,27,1],
+"structFrameKey.html":[4,0,28],
+"structFrameKey.html#a022917652b4d3c2f2dfcc5a13ab7caa4":[4,0,28,2],
+"structFrameKey.html#a33bde405c7ea53000d54b3dd6e058670":[4,0,28,0],
+"structFrameKey.html#aa3179b709d02ef70cf0e736f040a2145":[4,0,28,3],
+"structFrameKey.html#aaaec9f914e127787247fcda5e183b01f":[4,0,28,1],
+"structFrameKeyHasher.html":[4,0,29],
+"structFrameKeyHasher.html#a1612ce56b513790e3ed4c06ec7d28b9f":[4,0,29,0],
+"structMultiplexing.html":[4,0,30],
+"structMultiplexing.html#a62b70a0e3f2a9c7a457b3694ce8625c3":[4,0,30,0],
+"structMultiplexing.html#a79158d4fdbfd68a3d51a8ce79d34fd67":[4,0,30,1],
+"structPendingAttribute.html":[4,0,31],
+"structPendingAttribute.html#a0ec62fc577e3a2d5f63d926f829e2ab8":[4,0,31,0],
+"structPendingAttribute.html#a9a68a0a54c313c3e43dfdcd6e7a55da9":[4,0,31,1],
+"structPendingComment.html":[4,0,32],
+"structPendingComment.html#a29a3733e0a4c8ae341695db3d21d9249":[4,0,32,5],
+"structPendingComment.html#a6d1c3b1e149bb602a95224446709c771":[4,0,32,0],
+"structPendingComment.html#a9abd7e15ed59eb4534c66ff74f276e07":[4,0,32,1],
+"structPendingComment.html#aa344393f67770e12449a4f14f6fcf10b":[4,0,32,4],
+"structPendingComment.html#ac03903ffb042d27ad66012eb18ea1437":[4,0,32,2],
+"structPendingComment.html#ae7b5aea9c252a4ab87e02915d24fee27":[4,0,32,3],
+"structPendingValueDescriptions.html":[4,0,33],
+"structPendingValueDescriptions.html#a10ecbaeaed2cc3ac82fada73e7e041dd":[4,0,33,3],
+"structPendingValueDescriptions.html#a5c19cff09b0e83bd3cd6085213c17da8":[4,0,33,4],
+"structPendingValueDescriptions.html#a5f0082ceeaee77e2f823661547aad844":[4,0,33,0],
+"structPendingValueDescriptions.html#a60f185e8d91010927c4aa3b4a750c9f4":[4,0,33,1],
+"structPendingValueDescriptions.html#ac35446db10ebda5a12349759613f8c90":[4,0,33,2],
+"structPgnLookupResult.html":[4,0,34],
+"structPgnLookupResult.html#a6158833782348b3cc26037c2091fcc36":[4,0,34,1],
+"structPgnLookupResult.html#aa5b79b61d2aef48fd6ae070cf5f901c1":[4,0,34,0],
+"structRawCanFrame.html":[4,0,35],
+"structRawCanFrame.html#a0acb487612104c99c9907344c035df83":[4,0,35,2],
+"structRawCanFrame.html#a2d0e7fa0e3d5c20bbed55ed8f7888ff4":[4,0,35,0],
+"structRawCanFrame.html#a462193d275adc1dba8bd18ffa0e36bb7":[4,0,35,1],
+"structSignalInfo.html":[4,0,36],
+"structSignalInfo.html#a1008b5201f71848177217bd52fb84baa":[4,0,36,3],
+"structSignalInfo.html#a1f214f03e94ef5794de2d3367bfcbd01":[4,0,36,10],
+"structSignalInfo.html#a2c95562fd0b29327a7fd7b1e6feee7f3":[4,0,36,11],
+"structSignalInfo.html#a379e422a00cad56f896cacf60455b088":[4,0,36,1],
+"structSignalInfo.html#a43f47d0433d0cc39076bd7278b46af9c":[4,0,36,12],
+"structSignalInfo.html#a52a52b320eef92fbcb4626307f9a498f":[4,0,36,5],
+"structSignalInfo.html#a781766eddbf6641071623c8e5b9acb4a":[4,0,36,14],
+"structSignalInfo.html#a8a2e29f307c75926a1bd824266d23ca8":[4,0,36,0],
+"structSignalInfo.html#ab7d0769f47aa540656b22e4e49db517e":[4,0,36,7],
+"structSignalInfo.html#ac99ba7563a5dad01e39c4257216953f5":[4,0,36,13],
+"structSignalInfo.html#ace290724f9801521609aedaa946d61f1":[4,0,36,2],
+"structSignalInfo.html#ada7bf94fbeaa26bd08c73982b5af255b":[4,0,36,8],
+"structSignalInfo.html#adf1c4331b9eabced0d7fdda40ff0eb52":[4,0,36,9],
+"structSignalInfo.html#ae4f78d99a2750aa564d7eba860171499":[4,0,36,6],
+"structSignalInfo.html#af363b1563fb4c7cc8973f9a80c06846c":[4,0,36,4],
+"structSignalKey.html":[4,0,37],
+"structSignalKey.html#a17525dc0116be7f4f58f3c3fae1022e2":[4,0,37,1],
+"structSignalKey.html#a25f4ece1bf685791b576f68e23d8ccc7":[4,0,37,2],
+"structSignalKey.html#aa4221b34e75469bf5aa939976c334f46":[4,0,37,0],
+"structSignalKey.html#abab371cce740f05111fd3b4013ca6944":[4,0,37,3],
+"structSignalKeyHasher.html":[4,0,38],
+"structSignalKeyHasher.html#af8869bcb714857af7ad005fbd13bea80":[4,0,38,0],
+"tests_2main_8cpp_source.html":[5,0,3,7],
+"text__utils_8h_source.html":[5,0,0,22],
+"tree__node_8cpp.html":[5,0,0,23],
+"tree__node_8cpp_source.html":[5,0,0,23],
+"tree__node_8h.html":[5,0,0,24],
+"tree__node_8h.html#acac9cbaeea226ed297804c012dc12b16":[5,0,0,24,1],
+"tree__node_8h.html#acac9cbaeea226ed297804c012dc12b16a085fea7abdc5d904fe69a3081efd7398":[5,0,0,24,1,2],
+"tree__node_8h.html#acac9cbaeea226ed297804c012dc12b16a3bb3e8c8a24891ba0f7608bcc96f8b0a":[5,0,0,24,1,1],
+"tree__node_8h.html#acac9cbaeea226ed297804c012dc12b16afa03eb688ad8aa1db593d33dabd89bad":[5,0,0,24,1,0],
+"tree__node_8h_source.html":[5,0,0,24],
+"tree__node__test_8cpp_source.html":[5,0,3,8],
+"typefactory_8h_source.html":[5,0,0,25],
+"value__descriptions_8h_source.html":[5,0,0,26]
};
diff --git a/docs/html/pages.html b/docs/html/pages.html
index dc49921..f06f641 100644
--- a/docs/html/pages.html
+++ b/docs/html/pages.html
@@ -95,9 +95,10 @@ $(document).ready(function(){initNavTree('pages.html',''); initResizable(); });
Here is a list of all related documentation pages:
diff --git a/docs/html/search/all_0.js b/docs/html/search/all_0.js
index c279849..7c8683e 100644
--- a/docs/html/search/all_0.js
+++ b/docs/html/search/all_0.js
@@ -1,10 +1,10 @@
var searchData=
[
- ['0_20—_202026_2006_2014_0',['v1.0 — 2026-06-14',['../md_changelog.html#autotoc_md21',1,'']]],
- ['01_1',['2026-10-01',['../md_changelog.html#autotoc_md18',1,'']]],
- ['03_2013_2',['Initial implementation — 2026-03-13',['../md_changelog.html#autotoc_md23',1,'']]],
- ['05_3',['2026-10-05',['../md_changelog.html#autotoc_md14',1,'']]],
- ['06_4',['2026-10-06',['../md_changelog.html#autotoc_md12',1,'']]],
- ['06_2014_5',['v1.0 — 2026-06-14',['../md_changelog.html#autotoc_md21',1,'']]],
- ['07_6',['2026-10-07',['../md_changelog.html#autotoc_md8',1,'']]]
+ ['0_20—_202026_2006_2014_0',['v1.0 — 2026-06-14',['../md_changelog.html#autotoc_md37',1,'']]],
+ ['01_1',['2026-10-01',['../md_changelog.html#autotoc_md34',1,'']]],
+ ['03_2013_2',['Initial implementation — 2026-03-13',['../md_changelog.html#autotoc_md39',1,'']]],
+ ['05_3',['2026-10-05',['../md_changelog.html#autotoc_md30',1,'']]],
+ ['06_4',['2026-10-06',['../md_changelog.html#autotoc_md28',1,'']]],
+ ['06_2014_5',['v1.0 — 2026-06-14',['../md_changelog.html#autotoc_md37',1,'']]],
+ ['07_6',['2026-10-07',['../md_changelog.html#autotoc_md24',1,'']]]
];
diff --git a/docs/html/search/all_1.js b/docs/html/search/all_1.js
index b4d0879..557e2f6 100644
--- a/docs/html/search/all_1.js
+++ b/docs/html/search/all_1.js
@@ -1,14 +1,16 @@
var searchData=
[
- ['1_20already_20implemented_0',['Stage 1 - already implemented',['../md_README.html#autotoc_md120',1,'']]],
- ['1_20parse_20and_20ui_20path_1',['1. Parse and UI path',['../md_README.html#autotoc_md30',1,'']]],
- ['10_2001_2',['2026-10-01',['../md_changelog.html#autotoc_md18',1,'']]],
- ['10_2005_3',['2026-10-05',['../md_changelog.html#autotoc_md14',1,'']]],
- ['10_2006_4',['2026-10-06',['../md_changelog.html#autotoc_md12',1,'']]],
- ['10_2007_5',['2026-10-07',['../md_changelog.html#autotoc_md8',1,'']]],
- ['10_2011_6',['2026-10-11',['../md_changelog.html#autotoc_md5',1,'']]],
- ['10_2013_7',['2026-10-13',['../md_changelog.html#autotoc_md2',1,'']]],
- ['11_8',['2026-10-11',['../md_changelog.html#autotoc_md5',1,'']]],
- ['13_9',['13',['../md_changelog.html#autotoc_md2',1,'2026-10-13'],['../md_changelog.html#autotoc_md23',1,'Initial implementation — 2026-03-13']]],
- ['14_10',['v1.0 — 2026-06-14',['../md_changelog.html#autotoc_md21',1,'']]]
+ ['1_20already_20implemented_0',['Stage 1 - already implemented',['../md_README.html#autotoc_md137',1,'']]],
+ ['1_20parse_20and_20ui_20path_1',['1. Parse and UI path',['../md_README.html#autotoc_md46',1,'']]],
+ ['10_2001_2',['2026-10-01',['../md_changelog.html#autotoc_md34',1,'']]],
+ ['10_2005_3',['2026-10-05',['../md_changelog.html#autotoc_md30',1,'']]],
+ ['10_2006_4',['2026-10-06',['../md_changelog.html#autotoc_md28',1,'']]],
+ ['10_2007_5',['2026-10-07',['../md_changelog.html#autotoc_md24',1,'']]],
+ ['10_2011_6',['2026-10-11',['../md_changelog.html#autotoc_md21',1,'']]],
+ ['10_2013_7',['2026-10-13',['../md_changelog.html#autotoc_md18',1,'']]],
+ ['10_2014_8',['2026-10-14',['../md_changelog.html#autotoc_md14',1,'']]],
+ ['10_2020_9',['2026-10-20',['../md_changelog.html#autotoc_md8',1,'']]],
+ ['11_10',['2026-10-11',['../md_changelog.html#autotoc_md21',1,'']]],
+ ['13_11',['13',['../md_changelog.html#autotoc_md18',1,'2026-10-13'],['../md_changelog.html#autotoc_md39',1,'Initial implementation — 2026-03-13']]],
+ ['14_12',['14',['../md_changelog.html#autotoc_md14',1,'2026-10-14'],['../md_changelog.html#autotoc_md37',1,'v1.0 — 2026-06-14']]]
];
diff --git a/docs/html/search/all_10.js b/docs/html/search/all_10.js
index 069ea5d..8c2397b 100644
--- a/docs/html/search/all_10.js
+++ b/docs/html/search/all_10.js
@@ -1,13 +1,15 @@
var searchData=
[
- ['maintenance_0',['maintenance',['../md_changelog.html#autotoc_md17',1,'Documentation and maintenance'],['../md_changelog.html#autotoc_md25',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_md133',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_md127',1,'']]],
- ['model_20tests_5',['Tree and optional model tests',['../md_tests_2README.html#autotoc_md140',1,'']]],
- ['module_20documentation_6',['DBC Parser and Runtime Decode Module Documentation',['../md_README.html',1,'']]],
- ['module_20layout_7',['Module Layout',['../md_README.html#autotoc_md35',1,'']]],
- ['motorola_20extraction_8',['Intel and Motorola Extraction',['../md_README.html#autotoc_md97',1,'']]],
- ['multiplexing_9',['multiplexing',['../md_README.html#autotoc_md87',1,'Basic multiplexing'],['../structMultiplexing.html',1,'Multiplexing']]]
+ ['layer_0',['layer',['../md_README.html#autotoc_md78',1,'Decoder Layer'],['../md_README.html#autotoc_md63',1,'Runtime Decode Layer'],['../md_README.html#autotoc_md60',1,'UI Tree Layer']]],
+ ['layer_20exists_1',['Why the Runtime Decode Layer Exists',['../md_README.html#autotoc_md49',1,'']]],
+ ['layout_2',['Module Layout',['../md_README.html#autotoc_md51',1,'']]],
+ ['lcov_20on_20debian_20ubuntu_3',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md152',1,'']]],
+ ['length_4',['length',['../structSignalInfo.html#a1008b5201f71848177217bd52fb84baa',1,'SignalInfo::length'],['../structDecodeSignal.html#acd4ef5ee30421d117b5756854302debb',1,'DecodeSignal::length']]],
+ ['level_20architecture_5',['High-Level Architecture',['../md_README.html#autotoc_md45',1,'']]],
+ ['libraries_6',['Build core without Qt libraries',['../md_README.html#autotoc_md143',1,'']]],
+ ['lifetime_20and_20reload_20coverage_7',['Definition lifetime and reload coverage',['../md_tests_2README.html#autotoc_md160',1,'']]],
+ ['limitations_8',['Current Limitations',['../md_README.html#autotoc_md134',1,'']]],
+ ['linenumber_9',['linenumber',['../structDbcParseContext.html#a57f5a7f613ecd0dadbafa7af736b7e54',1,'DbcParseContext::lineNumber'],['../structPendingAttribute.html#a9a68a0a54c313c3e43dfdcd6e7a55da9',1,'PendingAttribute::lineNumber'],['../structPendingComment.html#a29a3733e0a4c8ae341695db3d21d9249',1,'PendingComment::lineNumber'],['../structPendingValueDescriptions.html#a5c19cff09b0e83bd3cd6085213c17da8',1,'PendingValueDescriptions::lineNumber'],['../structDbcDiagnostic.html#adb201de8d32b768d5f559bed21e8f819',1,'DbcDiagnostic::lineNumber']]],
+ ['live_20path_10',['live path',['../md_README.html#autotoc_md123',1,'']]],
+ ['lookup_11',['J1939 Opt-in and PGN Lookup',['../md_README.html#autotoc_md110',1,'']]]
];
diff --git a/docs/html/search/all_11.js b/docs/html/search/all_11.js
index f5cd7b1..4cad4de 100644
--- a/docs/html/search/all_11.js
+++ b/docs/html/search/all_11.js
@@ -1,8 +1,16 @@
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_md119',1,'']]],
- ['nodetype_2',['NodeType',['../tree__node_8h.html#acac9cbaeea226ed297804c012dc12b16',1,'tree_node.h']]],
- ['normalization_3',['CAN ID Normalization',['../md_README.html#autotoc_md91',1,'']]],
- ['not_20enough_4',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md111',1,'']]]
+ ['main_0',['main',['../examples_2main_8cpp.html#a0ddf1224851353fc92bfbff6f499fa97',1,'main.cpp']]],
+ ['maintenance_1',['maintenance',['../md_changelog.html#autotoc_md33',1,'Documentation and maintenance'],['../md_changelog.html#autotoc_md41',1,'Documentation and maintenance'],['../md_changelog.html#autotoc_md9',1,'Maintenance']]],
+ ['maximum_2',['maximum',['../structAttributeDefinition.html#aa02fe74b5420c2e67c13e610b6bc9713',1,'AttributeDefinition::maximum'],['../structDecodeSignal.html#a4a6ba87142a9badbf0ca830e9e709cb7',1,'DecodeSignal::maximum'],['../structSignalInfo.html#adf1c4331b9eabced0d7fdda40ff0eb52',1,'SignalInfo::maximum']]],
+ ['measuring_20code_20coverage_3',['Measuring code coverage',['../md_README.html#autotoc_md151',1,'']]],
+ ['message_4',['message',['../structDbcDiagnostic.html#a124bae82eebeaef46426bd124685ef1b',1,'DbcDiagnostic']]],
+ ['metadata_5',['Attributes and frame metadata',['../md_README.html#autotoc_md93',1,'']]],
+ ['minimum_6',['minimum',['../structAttributeDefinition.html#a18245dba995929a61fd6de1fcdbc8a89',1,'AttributeDefinition::minimum'],['../structDecodeSignal.html#a0fb84e19a0ab3bd50b6f65c1075ebc25',1,'DecodeSignal::minimum'],['../structSignalInfo.html#ada7bf94fbeaa26bd08c73982b5af255b',1,'SignalInfo::minimum']]],
+ ['model_20adapter_7',['Optional Qt model adapter',['../md_README.html#autotoc_md144',1,'']]],
+ ['model_20tests_8',['Tree and optional model tests',['../md_tests_2README.html#autotoc_md158',1,'']]],
+ ['module_20documentation_9',['DBC Parser and Runtime Decode Module Documentation',['../md_README.html',1,'']]],
+ ['module_20layout_10',['Module Layout',['../md_README.html#autotoc_md51',1,'']]],
+ ['motorola_20extraction_11',['Intel and Motorola Extraction',['../md_README.html#autotoc_md114',1,'']]],
+ ['multiplexing_12',['multiplexing',['../md_README.html#autotoc_md104',1,'Basic multiplexing'],['../structSignalInfo.html#a8a2e29f307c75926a1bd824266d23ca8',1,'SignalInfo::multiplexing'],['../structDecodeSignal.html#aea41c055cb255fe7bd178ed5727f28c9',1,'DecodeSignal::multiplexing'],['../structMultiplexing.html',1,'Multiplexing']]]
];
diff --git a/docs/html/search/all_12.js b/docs/html/search/all_12.js
index 8af7674..79c88d9 100644
--- a/docs/html/search/all_12.js
+++ b/docs/html/search/all_12.js
@@ -1,9 +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_md134',1,'']]],
- ['optional_20model_20tests_2',['Tree and optional model tests',['../md_tests_2README.html#autotoc_md140',1,'']]],
- ['optional_20qt_20model_20adapter_3',['Optional Qt model adapter',['../md_README.html#autotoc_md127',1,'']]],
- ['overview_4',['Overview',['../md_README.html#autotoc_md27',1,'']]],
- ['ownership_20and_20reload_5',['Definition ownership and reload',['../md_README.html#autotoc_md70',1,'']]]
+ ['name_0',['name',['../structAttributeAssignment.html#aa8707eddd2d3a2de559fe44354a514cc',1,'AttributeAssignment::name'],['../structDecodeSignal.html#a58cf5844f2272a23dcb9687d912e4780',1,'DecodeSignal::name'],['../structDecodeFrame.html#aa0a7f8fd5bfde2148dfd0d838328f579',1,'DecodeFrame::name'],['../structSignalKey.html#abab371cce740f05111fd3b4013ca6944',1,'SignalKey::name'],['../structFrameInfo.html#abb53a7f93ed7abc0ea1ae4a8ccafcdcb',1,'FrameInfo::name'],['../structSignalInfo.html#a379e422a00cad56f896cacf60455b088',1,'SignalInfo::name']]],
+ ['next_20steps_1',['Recommended Next Steps',['../md_README.html#autotoc_md136',1,'']]],
+ ['nodetype_2',['NodeType',['../tree__node_8h.html#acac9cbaeea226ed297804c012dc12b16',1,'tree_node.h']]],
+ ['normalization_3',['CAN ID Normalization',['../md_README.html#autotoc_md108',1,'']]],
+ ['not_20enough_4',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md128',1,'']]]
];
diff --git a/docs/html/search/all_13.js b/docs/html/search/all_13.js
index e8497e2..9961e80 100644
--- a/docs/html/search/all_13.js
+++ b/docs/html/search/all_13.js
@@ -1,20 +1,12 @@
var searchData=
[
- ['parse_20and_20ui_20path_0',['1. Parse and UI path',['../md_README.html#autotoc_md30',1,'']]],
- ['parse_20dbc_1',['Parse DBC',['../md_README.html#autotoc_md100',1,'']]],
- ['parse_20errors_2',['parse errors',['../md_README.html#autotoc_md81',1,'Frame validation and parse errors'],['../md_README.html#autotoc_md85',1,'Signal validation and parse errors']]],
- ['parsed_20data_20structures_3',['Parsed Data Structures',['../md_README.html#autotoc_md37',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_md139',1,'']]],
- ['parser_20support_8',['Parser Support',['../md_README.html#autotoc_md75',1,'']]],
- ['path_9',['path',['../md_README.html#autotoc_md30',1,'1. Parse and UI path'],['../md_README.html#autotoc_md31',1,'2. Runtime decode path'],['../md_README.html#autotoc_md106',1,'live path'],['../md_README.html#autotoc_md107',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_md93',1,'']]],
- ['physicalvalue_13',['physicalValue',['../structDecodedSignalValue.html#a6847d05b3cb00d5e0f6c611968f57978',1,'DecodedSignalValue']]],
- ['precision_14',['Raw value representation and precision',['../md_README.html#autotoc_md67',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_md48',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_md152',1,'']]],
+ ['operator_28_29_2',['operator()',['../structFrameKeyHasher.html#a1612ce56b513790e3ed4c06ec7d28b9f',1,'FrameKeyHasher::operator()()'],['../structSignalKeyHasher.html#af8869bcb714857af7ad005fbd13bea80',1,'SignalKeyHasher::operator()()']]],
+ ['operator_3d_3d_3',['operator==',['../structFrameKey.html#aaaec9f914e127787247fcda5e183b01f',1,'FrameKey::operator==()'],['../structSignalKey.html#a17525dc0116be7f4f58f3c3fae1022e2',1,'SignalKey::operator==()']]],
+ ['opt_20in_20and_20pgn_20lookup_4',['J1939 Opt-in and PGN Lookup',['../md_README.html#autotoc_md110',1,'']]],
+ ['optional_20model_20tests_5',['Tree and optional model tests',['../md_tests_2README.html#autotoc_md158',1,'']]],
+ ['optional_20qt_20model_20adapter_6',['Optional Qt model adapter',['../md_README.html#autotoc_md144',1,'']]],
+ ['overview_7',['Overview',['../md_README.html#autotoc_md43',1,'']]],
+ ['ownership_20and_20reload_8',['Definition ownership and reload',['../md_README.html#autotoc_md86',1,'']]]
];
diff --git a/docs/html/search/all_14.js b/docs/html/search/all_14.js
index a35e146..59860d0 100644
--- a/docs/html/search/all_14.js
+++ b/docs/html/search/all_14.js
@@ -1,8 +1,28 @@
var searchData=
[
- ['qt_0',['Standalone tree tests without Qt',['../md_README.html#autotoc_md128',1,'']]],
- ['qt_20creator_1',['qt creator',['../md_README.html#autotoc_md136',1,'Configure all build variants in Qt Creator'],['../md_README.html#autotoc_md135',1,'Configure the GCC coverage build in Qt Creator']]],
- ['qt_20libraries_2',['Build core without Qt libraries',['../md_README.html#autotoc_md126',1,'']]],
- ['qt_20model_20adapter_3',['Optional Qt model adapter',['../md_README.html#autotoc_md127',1,'']]],
- ['qttest_20regression_20tests_4',['QtTest regression tests',['../md_tests_2README.html',1,'']]]
+ ['parent_0',['parent',['../classDbcTreeModel.html#ae40bb8b8a26d205f178c6dd1134ff4b3',1,'DbcTreeModel']]],
+ ['parse_20and_20ui_20path_1',['1. Parse and UI path',['../md_README.html#autotoc_md46',1,'']]],
+ ['parse_20dbc_2',['Parse DBC',['../md_README.html#autotoc_md117',1,'']]],
+ ['parse_20errors_3',['parse errors',['../md_README.html#autotoc_md98',1,'Frame validation and parse errors'],['../md_README.html#autotoc_md102',1,'Signal validation and parse errors']]],
+ ['parsed_20data_20structures_4',['Parsed Data Structures',['../md_README.html#autotoc_md53',1,'']]],
+ ['parsefile_5',['ParseFile',['../classDbcParser.html#aef72826942c9095d653fafa435855e56',1,'DbcParser']]],
+ ['parsefilewithdiagnostics_6',['ParseFileWithDiagnostics',['../classDbcParser.html#a0e915ce79c2e3d4c95a5aaf2bf0409bc',1,'DbcParser']]],
+ ['parser_20and_20runtime_20decode_20module_20documentation_7',['DBC Parser and Runtime Decode Module Documentation',['../md_README.html',1,'']]],
+ ['parser_20coverage_8',['Parser coverage',['../md_tests_2README.html#autotoc_md157',1,'']]],
+ ['parser_20support_9',['Parser Support',['../md_README.html#autotoc_md91',1,'']]],
+ ['path_10',['path',['../md_README.html#autotoc_md46',1,'1. Parse and UI path'],['../md_README.html#autotoc_md47',1,'2. Runtime decode path'],['../md_README.html#autotoc_md123',1,'live path'],['../md_README.html#autotoc_md124',1,'trace path']]],
+ ['pendingattribute_11',['PendingAttribute',['../structPendingAttribute.html',1,'']]],
+ ['pendingattributes_12',['pendingAttributes',['../structDbcParseContext.html#afbfa4b26a58b41ada3dabc619066035c',1,'DbcParseContext']]],
+ ['pendingcomment_13',['PendingComment',['../structPendingComment.html',1,'']]],
+ ['pendingcomments_14',['pendingComments',['../structDbcParseContext.html#a854abba7bbf4adfc948554c254156e60',1,'DbcParseContext']]],
+ ['pendingvaluedescriptions_15',['PendingValueDescriptions',['../structPendingValueDescriptions.html',1,'']]],
+ ['pendingvalues_16',['pendingValues',['../structDbcParseContext.html#ac22cba614ada3a28c7dcc1ea338b0e01',1,'DbcParseContext']]],
+ ['pgn_17',['pgn',['../structFrameInfo.html#aee518b33f1000bf0b7f6e4a87474c943',1,'FrameInfo::pgn'],['../structDecodeFrame.html#a1d3c54055c0cbceb73adf551f7067f23',1,'DecodeFrame::pgn']]],
+ ['pgn_20lookup_18',['J1939 Opt-in and PGN Lookup',['../md_README.html#autotoc_md110',1,'']]],
+ ['pgnlookupresult_19',['PgnLookupResult',['../structPgnLookupResult.html',1,'']]],
+ ['physicalvalue_20',['physicalValue',['../structDecodedSignalValue.html#a6847d05b3cb00d5e0f6c611968f57978',1,'DecodedSignalValue']]],
+ ['pipeline_20coverage_21',['End-to-end pipeline coverage',['../md_tests_2README.html#autotoc_md162',1,'']]],
+ ['precision_22',['Raw value representation and precision',['../md_README.html#autotoc_md83',1,'']]],
+ ['public_23',['public',['../structFrameInfo.html#a3f7e25d67ddae22f2ed50823a5a26084',1,'FrameInfo::public'],['../structDecodeFrame.html#a7f4e71bbdec3f424b625e724e3dfbf14',1,'DecodeFrame::public'],['../structDecodedFrameValue.html#adae123ac7fbb4a5c314b64b01109f4a8',1,'DecodedFrameValue::public']]],
+ ['purpose_24',['Purpose',['../md_README.html#autotoc_md64',1,'']]]
];
diff --git a/docs/html/search/all_15.js b/docs/html/search/all_15.js
index 9d997aa..d18cb30 100644
--- a/docs/html/search/all_15.js
+++ b/docs/html/search/all_15.js
@@ -1,22 +1,8 @@
var searchData=
[
- ['raw_20frame_0',['Decode a raw frame',['../md_README.html#autotoc_md103',1,'']]],
- ['raw_20value_20representation_20and_20precision_1',['Raw value representation and precision',['../md_README.html#autotoc_md67',1,'']]],
- ['rawcanframe_2',['RawCanFrame',['../structRawCanFrame.html',1,'']]],
- ['rawcanframe_20tt_3',['<tt>RawCanFrame</tt>',['../md_README.html#autotoc_md63',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_md119',1,'']]],
- ['registertype_7',['registerType',['../classTypeFactory.html#ad6d85795285ee21193ac03e1b24762d3',1,'TypeFactory']]],
- ['regression_20coverage_8',['Additional regression coverage',['../md_tests_2README.html#autotoc_md141',1,'']]],
- ['regression_20tests_9',['regression tests',['../md_tests_2README.html',1,'QtTest regression tests'],['../md_README.html#autotoc_md132',1,'Regression tests']]],
- ['reload_10',['Definition ownership and reload',['../md_README.html#autotoc_md70',1,'']]],
- ['reload_20coverage_11',['Definition lifetime and reload coverage',['../md_tests_2README.html#autotoc_md142',1,'']]],
- ['representation_20and_20precision_12',['Raw value representation and precision',['../md_README.html#autotoc_md67',1,'']]],
- ['run_20the_20demo_13',['Build and run the demo',['../md_README.html#autotoc_md129',1,'']]],
- ['runtime_20decode_20database_14',['Build runtime decode database',['../md_README.html#autotoc_md102',1,'']]],
- ['runtime_20decode_20layer_15',['Runtime Decode Layer',['../md_README.html#autotoc_md47',1,'']]],
- ['runtime_20decode_20layer_20exists_16',['Why the Runtime Decode Layer Exists',['../md_README.html#autotoc_md33',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_md31',1,'']]]
+ ['qt_0',['Standalone tree tests without Qt',['../md_README.html#autotoc_md145',1,'']]],
+ ['qt_20creator_1',['qt creator',['../md_README.html#autotoc_md154',1,'Configure all build variants in Qt Creator'],['../md_README.html#autotoc_md153',1,'Configure the GCC coverage build in Qt Creator']]],
+ ['qt_20libraries_2',['Build core without Qt libraries',['../md_README.html#autotoc_md143',1,'']]],
+ ['qt_20model_20adapter_3',['Optional Qt model adapter',['../md_README.html#autotoc_md144',1,'']]],
+ ['qttest_20regression_20tests_4',['QtTest regression tests',['../md_tests_2README.html',1,'']]]
];
diff --git a/docs/html/search/all_16.js b/docs/html/search/all_16.js
index 2f2fa1a..dbac0ed 100644
--- a/docs/html/search/all_16.js
+++ b/docs/html/search/all_16.js
@@ -1,28 +1,28 @@
var searchData=
[
- ['signal_20definition_0',['Signal definition',['../md_README.html#autotoc_md83',1,'']]],
- ['signal_20identifiers_1',['Stable frame and signal identifiers',['../md_README.html#autotoc_md71',1,'']]],
- ['signal_20validation_20and_20parse_20errors_2',['Signal validation and parse errors',['../md_README.html#autotoc_md85',1,'']]],
- ['signal_20value_20descriptions_20tt_20val_5f_20tt_3',['Signal value descriptions (<tt>VAL_</tt>)',['../md_README.html#autotoc_md115',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_md38',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_md71',1,'']]],
- ['stage_201_20already_20implemented_10',['Stage 1 - already implemented',['../md_README.html#autotoc_md120',1,'']]],
- ['stage_202_11',['Stage 2',['../md_README.html#autotoc_md121',1,'']]],
- ['stage_203_12',['Stage 3',['../md_README.html#autotoc_md122',1,'']]],
- ['stage_204_13',['Stage 4',['../md_README.html#autotoc_md123',1,'']]],
- ['standalone_20tree_20tests_20without_20qt_14',['Standalone tree tests without Qt',['../md_README.html#autotoc_md128',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_md113',1,'']]],
- ['status_17',['status',['../structDecodedFrameValue.html#a645f433798d48a2787e7f00dfbb7dff9',1,'DecodedFrameValue']]],
- ['steps_18',['Recommended Next Steps',['../md_README.html#autotoc_md119',1,'']]],
- ['strategy_19',['Unified Decode Strategy',['../md_README.html#autotoc_md105',1,'']]],
- ['structured_20diagnostics_20',['Structured diagnostics',['../md_README.html#autotoc_md76',1,'']]],
- ['structures_21',['Parsed Data Structures',['../md_README.html#autotoc_md37',1,'']]],
- ['support_22',['Parser Support',['../md_README.html#autotoc_md75',1,'']]],
- ['supported_20dbc_20syntax_23',['Supported DBC Syntax',['../md_README.html#autotoc_md78',1,'']]],
- ['syntax_24',['Supported DBC Syntax',['../md_README.html#autotoc_md78',1,'']]]
+ ['raw_20frame_0',['Decode a raw frame',['../md_README.html#autotoc_md120',1,'']]],
+ ['raw_20value_20representation_20and_20precision_1',['Raw value representation and precision',['../md_README.html#autotoc_md83',1,'']]],
+ ['rawcanframe_2',['RawCanFrame',['../structRawCanFrame.html',1,'']]],
+ ['rawcanframe_20tt_3',['<tt>RawCanFrame</tt>',['../md_README.html#autotoc_md79',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_md136',1,'']]],
+ ['registertype_7',['registertype',['../classTypeFactory.html#ad6d85795285ee21193ac03e1b24762d3',1,'TypeFactory::registerType()'],['../classDbcStatementDispatcher.html#a2c6e9a614ed747275d43bcccc50d0b2d',1,'DbcStatementDispatcher::RegisterType()']]],
+ ['regression_20coverage_8',['Additional regression coverage',['../md_tests_2README.html#autotoc_md159',1,'']]],
+ ['regression_20tests_9',['regression tests',['../md_tests_2README.html',1,'QtTest regression tests'],['../md_README.html#autotoc_md149',1,'Regression tests']]],
+ ['reload_10',['Definition ownership and reload',['../md_README.html#autotoc_md86',1,'']]],
+ ['reload_20coverage_11',['Definition lifetime and reload coverage',['../md_tests_2README.html#autotoc_md160',1,'']]],
+ ['representation_20and_20precision_12',['Raw value representation and precision',['../md_README.html#autotoc_md83',1,'']]],
+ ['resolveattributes_13',['ResolveAttributes',['../structDbcParseContext.html#a1ac7f4a54550aaddef08749806f87001',1,'DbcParseContext']]],
+ ['resolvecomments_14',['ResolveComments',['../structDbcParseContext.html#aeae343c57a244634489a0e0b960155d7',1,'DbcParseContext']]],
+ ['resolvevaluedescriptions_15',['ResolveValueDescriptions',['../structDbcParseContext.html#ab5552dad944fde7fa6add6464ddb5369',1,'DbcParseContext']]],
+ ['review_20and_20additional_20checks_16',['Code review and additional checks',['../md_README.html#autotoc_md150',1,'']]],
+ ['role_17',['role',['../classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfd',1,'DbcTreeModel::Role'],['../structMultiplexing.html#a62b70a0e3f2a9c7a457b3694ce8625c3',1,'Multiplexing::role']]],
+ ['rowcount_18',['rowCount',['../classDbcTreeModel.html#a30bed0d65342917c19d9183da55af452',1,'DbcTreeModel']]],
+ ['run_20the_20demo_19',['Build and run the demo',['../md_README.html#autotoc_md146',1,'']]],
+ ['runtime_20decode_20database_20',['Build runtime decode database',['../md_README.html#autotoc_md119',1,'']]],
+ ['runtime_20decode_20layer_21',['Runtime Decode Layer',['../md_README.html#autotoc_md63',1,'']]],
+ ['runtime_20decode_20layer_20exists_22',['Why the Runtime Decode Layer Exists',['../md_README.html#autotoc_md49',1,'']]],
+ ['runtime_20decode_20module_20documentation_23',['DBC Parser and Runtime Decode Module Documentation',['../md_README.html',1,'']]],
+ ['runtime_20decode_20path_24',['2. Runtime decode path',['../md_README.html#autotoc_md47',1,'']]]
];
diff --git a/docs/html/search/all_17.js b/docs/html/search/all_17.js
index 950b235..89d3df5 100644
--- a/docs/html/search/all_17.js
+++ b/docs/html/search/all_17.js
@@ -1,37 +1,35 @@
var searchData=
[
- ['tests_0',['tests',['../md_tests_2README.html',1,'QtTest regression tests'],['../md_README.html#autotoc_md132',1,'Regression tests'],['../md_tests_2README.html#autotoc_md140',1,'Tree and optional model tests']]],
- ['tests_20without_20qt_1',['Standalone tree tests without Qt',['../md_README.html#autotoc_md128',1,'']]],
- ['the_20demo_2',['Build and run the demo',['../md_README.html#autotoc_md129',1,'']]],
- ['the_20gcc_20coverage_20build_20in_20qt_20creator_3',['Configure the GCC coverage build in Qt Creator',['../md_README.html#autotoc_md135',1,'']]],
- ['the_20runtime_20decode_20layer_20exists_4',['Why the Runtime Decode Layer Exists',['../md_README.html#autotoc_md33',1,'']]],
- ['the_20tree_20is_20not_20enough_5',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md111',1,'']]],
- ['trace_20path_6',['trace path',['../md_README.html#autotoc_md107',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_md101',1,'']]],
- ['tree_20and_20optional_20model_20tests_9',['Tree and optional model tests',['../md_tests_2README.html#autotoc_md140',1,'']]],
- ['tree_20is_20not_20enough_10',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md111',1,'']]],
- ['tree_20layer_11',['UI Tree Layer',['../md_README.html#autotoc_md44',1,'']]],
- ['tree_20tests_20without_20qt_12',['Standalone tree tests without Qt',['../md_README.html#autotoc_md128',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_md45',1,'']]],
- ['tt_20byteorder_20tt_17',['<tt>ByteOrder</tt>',['../md_README.html#autotoc_md50',1,'']]],
- ['tt_20dbcdatabase_20tt_18',['<tt>DbcDatabase</tt>',['../md_README.html#autotoc_md42',1,'']]],
- ['tt_20dbcdecoder_20tt_19',['<tt>DbcDecoder</tt>',['../md_README.html#autotoc_md73',1,'']]],
- ['tt_20decodedatabase_20tt_20',['<tt>DecodeDatabase</tt>',['../md_README.html#autotoc_md60',1,'']]],
- ['tt_20decodedframevalue_20tt_21',['<tt>DecodedFrameValue</tt>',['../md_README.html#autotoc_md69',1,'']]],
- ['tt_20decodedsignalvalue_20tt_22',['<tt>DecodedSignalValue</tt>',['../md_README.html#autotoc_md65',1,'']]],
- ['tt_20decodeframe_20tt_23',['<tt>DecodeFrame</tt>',['../md_README.html#autotoc_md56',1,'']]],
- ['tt_20decodesignal_20tt_24',['<tt>DecodeSignal</tt>',['../md_README.html#autotoc_md54',1,'']]],
- ['tt_20frameinfo_20tt_25',['<tt>FrameInfo</tt>',['../md_README.html#autotoc_md40',1,'']]],
- ['tt_20framekey_20tt_26',['<tt>FrameKey</tt>',['../md_README.html#autotoc_md58',1,'']]],
- ['tt_20rawcanframe_20tt_27',['<tt>RawCanFrame</tt>',['../md_README.html#autotoc_md63',1,'']]],
- ['tt_20signalinfo_20tt_28',['<tt>SignalInfo</tt>',['../md_README.html#autotoc_md38',1,'']]],
- ['tt_20treenode_20tt_29',['<tt>TreeNode</tt>',['../md_README.html#autotoc_md45',1,'']]],
- ['tt_20val_5f_20tt_30',['Signal value descriptions (<tt>VAL_</tt>)',['../md_README.html#autotoc_md115',1,'']]],
- ['tt_20valuetype_20tt_31',['<tt>ValueType</tt>',['../md_README.html#autotoc_md52',1,'']]],
- ['typefactory_32',['TypeFactory',['../classTypeFactory.html',1,'']]],
- ['typefactory_3c_20std_3a_3astring_2c_20dbcstatementhandler_20_3e_33',['TypeFactory< std::string, DbcStatementHandler >',['../classTypeFactory.html',1,'']]]
+ ['scope_0',['scope',['../structAttributeDefinition.html#a5f109f0ec94eb04c3f52c116366aefdf',1,'AttributeDefinition::scope'],['../structAttributeAssignment.html#a50405e8db9e4536015f9adc5ba360270',1,'AttributeAssignment::scope']]],
+ ['settree_1',['SetTree',['../classDbcTreeModel.html#a8cb5a81d456cdead42b75fd3462ee00a',1,'DbcTreeModel']]],
+ ['severity_2',['severity',['../structDbcDiagnostic.html#a75040a94f0313a606478020b0491f81d',1,'DbcDiagnostic']]],
+ ['signal_20definition_3',['Signal definition',['../md_README.html#autotoc_md100',1,'']]],
+ ['signal_20identifiers_4',['Stable frame and signal identifiers',['../md_README.html#autotoc_md87',1,'']]],
+ ['signal_20validation_20and_20parse_20errors_5',['Signal validation and parse errors',['../md_README.html#autotoc_md102',1,'']]],
+ ['signal_20value_20descriptions_20tt_20val_5f_20tt_6',['Signal value descriptions (<tt>VAL_</tt>)',['../md_README.html#autotoc_md132',1,'']]],
+ ['signal_5finfo_2eh_7',['signal_info.h',['../signal__info_8h.html',1,'']]],
+ ['signaldecodestatus_8',['SignalDecodeStatus',['../dbc__decoder_8h.html#a5f4a41ee2810487020135b45e8d7559a',1,'dbc_decoder.h']]],
+ ['signalinfo_9',['SignalInfo',['../structSignalInfo.html',1,'']]],
+ ['signalinfo_20tt_10',['<tt>SignalInfo</tt>',['../md_README.html#autotoc_md54',1,'']]],
+ ['signalkey_11',['signalkey',['../structSignalKey.html#aa4221b34e75469bf5aa939976c334f46',1,'SignalKey::SignalKey()'],['../structSignalKey.html',1,'SignalKey']]],
+ ['signalkeyhasher_12',['SignalKeyHasher',['../structSignalKeyHasher.html',1,'']]],
+ ['signallines_13',['signalLines',['../structDbcParseContext.html#af8b411c938a2ea9100c4aaae452e6546',1,'DbcParseContext']]],
+ ['signalname_14',['signalname',['../structPendingComment.html#ae7b5aea9c252a4ab87e02915d24fee27',1,'PendingComment::signalName'],['../structPendingValueDescriptions.html#ac35446db10ebda5a12349759613f8c90',1,'PendingValueDescriptions::signalName']]],
+ ['stable_20frame_20and_20signal_20identifiers_15',['Stable frame and signal identifiers',['../md_README.html#autotoc_md87',1,'']]],
+ ['stage_201_20already_20implemented_16',['Stage 1 - already implemented',['../md_README.html#autotoc_md137',1,'']]],
+ ['stage_202_17',['Stage 2',['../md_README.html#autotoc_md138',1,'']]],
+ ['stage_203_18',['Stage 3',['../md_README.html#autotoc_md139',1,'']]],
+ ['stage_204_19',['Stage 4',['../md_README.html#autotoc_md140',1,'']]],
+ ['standalone_20tree_20tests_20without_20qt_20',['Standalone tree tests without Qt',['../md_README.html#autotoc_md145',1,'']]],
+ ['startbit_21',['startbit',['../structSignalInfo.html#ace290724f9801521609aedaa946d61f1',1,'SignalInfo::startBit'],['../structDecodeSignal.html#aaf5d7527ddf65b6355c2b4f3626df22d',1,'DecodeSignal::startBit']]],
+ ['statement_22',['statement',['../structPendingAttribute.html#a0ec62fc577e3a2d5f63d926f829e2ab8',1,'PendingAttribute']]],
+ ['statement_20handler_20factory_23',['Statement Handler Factory',['../md_README.html#autotoc_md130',1,'']]],
+ ['status_24',['status',['../structDecodedFrameValue.html#a645f433798d48a2787e7f00dfbb7dff9',1,'DecodedFrameValue::status'],['../structDecodedSignalValue.html#a94161a80412b3961da8fd2fec43c25f6',1,'DecodedSignalValue::status']]],
+ ['steps_25',['Recommended Next Steps',['../md_README.html#autotoc_md136',1,'']]],
+ ['strategy_26',['Unified Decode Strategy',['../md_README.html#autotoc_md122',1,'']]],
+ ['structured_20diagnostics_27',['Structured diagnostics',['../md_README.html#autotoc_md92',1,'']]],
+ ['structures_28',['Parsed Data Structures',['../md_README.html#autotoc_md53',1,'']]],
+ ['support_29',['Parser Support',['../md_README.html#autotoc_md91',1,'']]],
+ ['supported_20dbc_20syntax_30',['Supported DBC Syntax',['../md_README.html#autotoc_md95',1,'']]],
+ ['syntax_31',['Supported DBC Syntax',['../md_README.html#autotoc_md95',1,'']]]
];
diff --git a/docs/html/search/all_18.js b/docs/html/search/all_18.js
index dc3b4a8..bc3eaa8 100644
--- a/docs/html/search/all_18.js
+++ b/docs/html/search/all_18.js
@@ -1,12 +1,40 @@
var searchData=
[
- ['ubuntu_0',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md134',1,'']]],
- ['ui_20path_1',['1. Parse and UI path',['../md_README.html#autotoc_md30',1,'']]],
- ['ui_20tree_2',['Build UI tree',['../md_README.html#autotoc_md101',1,'']]],
- ['ui_20tree_20layer_3',['UI Tree Layer',['../md_README.html#autotoc_md44',1,'']]],
- ['unified_20decode_20strategy_4',['Unified Decode Strategy',['../md_README.html#autotoc_md105',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_md99',1,'']]],
- ['use_20in_20frametap_8',['Intended Use in FrameTap',['../md_README.html#autotoc_md109',1,'']]]
+ ['targetname_0',['targetName',['../structAttributeAssignment.html#a50059e42e5e5b944050f3290ce84ac66',1,'AttributeAssignment']]],
+ ['tests_1',['tests',['../md_tests_2README.html',1,'QtTest regression tests'],['../md_README.html#autotoc_md149',1,'Regression tests'],['../md_tests_2README.html#autotoc_md158',1,'Tree and optional model tests']]],
+ ['tests_20without_20qt_2',['Standalone tree tests without Qt',['../md_README.html#autotoc_md145',1,'']]],
+ ['the_20demo_3',['Build and run the demo',['../md_README.html#autotoc_md146',1,'']]],
+ ['the_20gcc_20coverage_20build_20in_20qt_20creator_4',['Configure the GCC coverage build in Qt Creator',['../md_README.html#autotoc_md153',1,'']]],
+ ['the_20runtime_20decode_20layer_20exists_5',['Why the Runtime Decode Layer Exists',['../md_README.html#autotoc_md49',1,'']]],
+ ['the_20tree_20is_20not_20enough_6',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md128',1,'']]],
+ ['to_20end_20pipeline_20coverage_7',['End-to-end pipeline coverage',['../md_tests_2README.html#autotoc_md162',1,'']]],
+ ['trace_20path_8',['trace path',['../md_README.html#autotoc_md124',1,'']]],
+ ['transmitter_9',['transmitter',['../structDecodeFrame.html#ad78241dc40c793aabb8495b6989b81a9',1,'DecodeFrame::transmitter'],['../structFrameInfo.html#a92749ec3798d4211a505860fb389a9e8',1,'FrameInfo::transmitter']]],
+ ['tree_10',['Build UI tree',['../md_README.html#autotoc_md118',1,'']]],
+ ['tree_20and_20optional_20model_20tests_11',['Tree and optional model tests',['../md_tests_2README.html#autotoc_md158',1,'']]],
+ ['tree_20is_20not_20enough_12',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md128',1,'']]],
+ ['tree_20layer_13',['UI Tree Layer',['../md_README.html#autotoc_md60',1,'']]],
+ ['tree_20tests_20without_20qt_14',['Standalone tree tests without Qt',['../md_README.html#autotoc_md145',1,'']]],
+ ['tree_5fnode_2ecpp_15',['tree_node.cpp',['../tree__node_8cpp.html',1,'']]],
+ ['tree_5fnode_2eh_16',['tree_node.h',['../tree__node_8h.html',1,'']]],
+ ['treenode_17',['treenode',['../classTreeNode.html#a8e38dd591d8801d7ee3a7dbad90c67fc',1,'TreeNode::TreeNode(const FrameInfo &frame)'],['../classTreeNode.html#a984a98d5ccf7ef1f5a18094c6821f35d',1,'TreeNode::TreeNode()'],['../classTreeNode.html#ab9f00f5253d56461bb2d420fd639c5ae',1,'TreeNode::TreeNode(const SignalInfo &signal)'],['../classTreeNode.html',1,'TreeNode']]],
+ ['treenode_20tt_18',['<tt>TreeNode</tt>',['../md_README.html#autotoc_md61',1,'']]],
+ ['tt_20byteorder_20tt_19',['<tt>ByteOrder</tt>',['../md_README.html#autotoc_md66',1,'']]],
+ ['tt_20dbcdatabase_20tt_20',['<tt>DbcDatabase</tt>',['../md_README.html#autotoc_md58',1,'']]],
+ ['tt_20dbcdecoder_20tt_21',['<tt>DbcDecoder</tt>',['../md_README.html#autotoc_md89',1,'']]],
+ ['tt_20decodedatabase_20tt_22',['<tt>DecodeDatabase</tt>',['../md_README.html#autotoc_md76',1,'']]],
+ ['tt_20decodedframevalue_20tt_23',['<tt>DecodedFrameValue</tt>',['../md_README.html#autotoc_md85',1,'']]],
+ ['tt_20decodedsignalvalue_20tt_24',['<tt>DecodedSignalValue</tt>',['../md_README.html#autotoc_md81',1,'']]],
+ ['tt_20decodeframe_20tt_25',['<tt>DecodeFrame</tt>',['../md_README.html#autotoc_md72',1,'']]],
+ ['tt_20decodesignal_20tt_26',['<tt>DecodeSignal</tt>',['../md_README.html#autotoc_md70',1,'']]],
+ ['tt_20frameinfo_20tt_27',['<tt>FrameInfo</tt>',['../md_README.html#autotoc_md56',1,'']]],
+ ['tt_20framekey_20tt_28',['<tt>FrameKey</tt>',['../md_README.html#autotoc_md74',1,'']]],
+ ['tt_20rawcanframe_20tt_29',['<tt>RawCanFrame</tt>',['../md_README.html#autotoc_md79',1,'']]],
+ ['tt_20signalinfo_20tt_30',['<tt>SignalInfo</tt>',['../md_README.html#autotoc_md54',1,'']]],
+ ['tt_20treenode_20tt_31',['<tt>TreeNode</tt>',['../md_README.html#autotoc_md61',1,'']]],
+ ['tt_20val_5f_20tt_32',['Signal value descriptions (<tt>VAL_</tt>)',['../md_README.html#autotoc_md132',1,'']]],
+ ['tt_20valuetype_20tt_33',['<tt>ValueType</tt>',['../md_README.html#autotoc_md68',1,'']]],
+ ['type_34',['type',['../structAttributeDefinition.html#a5de5484174a8c5f6b309041089d20afc',1,'AttributeDefinition']]],
+ ['typefactory_35',['TypeFactory',['../classTypeFactory.html',1,'']]],
+ ['typefactory_3c_20std_3a_3astring_2c_20dbcstatementhandler_20_3e_36',['TypeFactory< std::string, DbcStatementHandler >',['../classTypeFactory.html',1,'']]]
];
diff --git a/docs/html/search/all_19.js b/docs/html/search/all_19.js
index d1f71fb..2ebc53c 100644
--- a/docs/html/search/all_19.js
+++ b/docs/html/search/all_19.js
@@ -1,14 +1,12 @@
var searchData=
[
- ['v1_200_20—_202026_2006_2014_0',['v1.0 — 2026-06-14',['../md_changelog.html#autotoc_md21',1,'']]],
- ['val_5f_20tt_1',['Signal value descriptions (<tt>VAL_</tt>)',['../md_README.html#autotoc_md115',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_md81',1,'Frame validation and parse errors'],['../md_README.html#autotoc_md85',1,'Signal validation and parse errors']]],
- ['validation_20coverage_4',['Database validation coverage',['../md_tests_2README.html#autotoc_md143',1,'']]],
- ['value_20descriptions_20tt_20val_5f_20tt_5',['Signal value descriptions (<tt>VAL_</tt>)',['../md_README.html#autotoc_md115',1,'']]],
- ['value_20representation_20and_20precision_6',['Raw value representation and precision',['../md_README.html#autotoc_md67',1,'']]],
- ['valuedescriptions_7',['valuedescriptions',['../structDecodeSignal.html#a822155d9bf4ed5f3300c9e9befe606ff',1,'DecodeSignal::valueDescriptions'],['../structSignalInfo.html#a43f47d0433d0cc39076bd7278b46af9c',1,'SignalInfo::valueDescriptions']]],
- ['valuetype_8',['valuetype',['../structDecodeSignal.html#a9d37638129263b8902ba5be59baf39a8',1,'DecodeSignal::valueType'],['../decode__database_8h.html#ad9971b6ef33e02ba2c75d19c1d2518a1',1,'ValueType: decode_database.h']]],
- ['valuetype_20tt_9',['<tt>ValueType</tt>',['../md_README.html#autotoc_md52',1,'']]],
- ['variants_20in_20qt_20creator_10',['Configure all build variants in Qt Creator',['../md_README.html#autotoc_md136',1,'']]]
+ ['ubuntu_0',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md152',1,'']]],
+ ['ui_20path_1',['1. Parse and UI path',['../md_README.html#autotoc_md46',1,'']]],
+ ['ui_20tree_2',['Build UI tree',['../md_README.html#autotoc_md118',1,'']]],
+ ['ui_20tree_20layer_3',['UI Tree Layer',['../md_README.html#autotoc_md60',1,'']]],
+ ['unified_20decode_20strategy_4',['Unified Decode Strategy',['../md_README.html#autotoc_md122',1,'']]],
+ ['unit_5',['unit',['../structDecodeSignal.html#a38eed9ca7581423fd8bfbedcffc12092',1,'DecodeSignal::unit'],['../structSignalInfo.html#a1f214f03e94ef5794de2d3367bfcbd01',1,'SignalInfo::unit']]],
+ ['unreleased_6',['Unreleased',['../md_changelog.html#autotoc_md7',1,'']]],
+ ['usage_7',['Example Usage',['../md_README.html#autotoc_md116',1,'']]],
+ ['use_20in_20frametap_8',['Intended Use in FrameTap',['../md_README.html#autotoc_md126',1,'']]]
];
diff --git a/docs/html/search/all_1a.js b/docs/html/search/all_1a.js
index eb8f4c2..c1ae1f6 100644
--- a/docs/html/search/all_1a.js
+++ b/docs/html/search/all_1a.js
@@ -1,7 +1,17 @@
var searchData=
[
- ['why_20the_20runtime_20decode_20layer_20exists_0',['Why the Runtime Decode Layer Exists',['../md_README.html#autotoc_md33',1,'']]],
- ['why_20the_20tree_20is_20not_20enough_1',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md111',1,'']]],
- ['without_20qt_2',['Standalone tree tests without Qt',['../md_README.html#autotoc_md128',1,'']]],
- ['without_20qt_20libraries_3',['Build core without Qt libraries',['../md_README.html#autotoc_md126',1,'']]]
+ ['v1_200_20—_202026_2006_2014_0',['v1.0 — 2026-06-14',['../md_changelog.html#autotoc_md37',1,'']]],
+ ['val_5f_20tt_1',['Signal value descriptions (<tt>VAL_</tt>)',['../md_README.html#autotoc_md132',1,'']]],
+ ['valid_2',['valid',['../structDecodedFrameValue.html#a4f51c31110dba1f73a763c596372beb0',1,'DecodedFrameValue::valid'],['../structDecodedSignalValue.html#aac0ed361af545cde48d0e6f41a859686',1,'DecodedSignalValue::valid']]],
+ ['validatemultiplexing_3',['ValidateMultiplexing',['../structDbcParseContext.html#a908056de0a97316a4ebecb3f99cc400b',1,'DbcParseContext']]],
+ ['validation_4',['Extended validation',['../md_tests_2README.html#autotoc_md164',1,'']]],
+ ['validation_20and_20parse_20errors_5',['validation and parse errors',['../md_README.html#autotoc_md98',1,'Frame validation and parse errors'],['../md_README.html#autotoc_md102',1,'Signal validation and parse errors']]],
+ ['validation_20coverage_6',['Database validation coverage',['../md_tests_2README.html#autotoc_md161',1,'']]],
+ ['value_7',['value',['../structAttributeAssignment.html#a93de8c51c5154219bf18beadcec5708f',1,'AttributeAssignment::value'],['../structMultiplexing.html#a79158d4fdbfd68a3d51a8ce79d34fd67',1,'Multiplexing::value']]],
+ ['value_20descriptions_20tt_20val_5f_20tt_8',['Signal value descriptions (<tt>VAL_</tt>)',['../md_README.html#autotoc_md132',1,'']]],
+ ['value_20representation_20and_20precision_9',['Raw value representation and precision',['../md_README.html#autotoc_md83',1,'']]],
+ ['valuedescriptions_10',['valuedescriptions',['../structDecodeSignal.html#a822155d9bf4ed5f3300c9e9befe606ff',1,'DecodeSignal::valueDescriptions'],['../structSignalInfo.html#a43f47d0433d0cc39076bd7278b46af9c',1,'SignalInfo::valueDescriptions']]],
+ ['valuetype_11',['valuetype',['../structDecodeSignal.html#a9d37638129263b8902ba5be59baf39a8',1,'DecodeSignal::valueType'],['../decode__database_8h.html#ad9971b6ef33e02ba2c75d19c1d2518a1',1,'ValueType: decode_database.h']]],
+ ['valuetype_20tt_12',['<tt>ValueType</tt>',['../md_README.html#autotoc_md68',1,'']]],
+ ['variants_20in_20qt_20creator_13',['Configure all build variants in Qt Creator',['../md_README.html#autotoc_md154',1,'']]]
];
diff --git a/docs/html/search/all_1b.js b/docs/html/search/all_1b.js
index b63d920..7c0a1cd 100644
--- a/docs/html/search/all_1b.js
+++ b/docs/html/search/all_1b.js
@@ -1,5 +1,7 @@
var searchData=
[
- ['—_202026_2003_2013_0',['Initial implementation — 2026-03-13',['../md_changelog.html#autotoc_md23',1,'']]],
- ['—_202026_2006_2014_1',['v1.0 — 2026-06-14',['../md_changelog.html#autotoc_md21',1,'']]]
+ ['why_20the_20runtime_20decode_20layer_20exists_0',['Why the Runtime Decode Layer Exists',['../md_README.html#autotoc_md49',1,'']]],
+ ['why_20the_20tree_20is_20not_20enough_1',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md128',1,'']]],
+ ['without_20qt_2',['Standalone tree tests without Qt',['../md_README.html#autotoc_md145',1,'']]],
+ ['without_20qt_20libraries_3',['Build core without Qt libraries',['../md_README.html#autotoc_md143',1,'']]]
];
diff --git a/docs/html/search/all_1c.js b/docs/html/search/all_1c.js
new file mode 100644
index 0000000..c8914d3
--- /dev/null
+++ b/docs/html/search/all_1c.js
@@ -0,0 +1,5 @@
+var searchData=
+[
+ ['для_20работы_20с_20проектом_0',['Инструкции для работы с проектом',['../md_AGENTS.html',1,'']]],
+ ['документация_1',['Документация',['../md_AGENTS.html#autotoc_md5',1,'']]]
+];
diff --git a/docs/html/search/all_1d.js b/docs/html/search/all_1d.js
new file mode 100644
index 0000000..b15d28b
--- /dev/null
+++ b/docs/html/search/all_1d.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['задания_0',['Формат задания',['../md_AGENTS.html#autotoc_md2',1,'']]]
+];
diff --git a/docs/html/search/all_1e.js b/docs/html/search/all_1e.js
new file mode 100644
index 0000000..135e5d7
--- /dev/null
+++ b/docs/html/search/all_1e.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['инструкции_20для_20работы_20с_20проектом_0',['Инструкции для работы с проектом',['../md_AGENTS.html',1,'']]]
+];
diff --git a/docs/html/search/all_1f.js b/docs/html/search/all_1f.js
new file mode 100644
index 0000000..61ec7c0
--- /dev/null
+++ b/docs/html/search/all_1f.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['кода_0',['Правила кода',['../md_AGENTS.html#autotoc_md3',1,'']]]
+];
diff --git a/docs/html/search/all_2.js b/docs/html/search/all_2.js
index 54d8527..f1818a7 100644
--- a/docs/html/search/all_2.js
+++ b/docs/html/search/all_2.js
@@ -1,13 +1,16 @@
var searchData=
[
- ['2_0',['Stage 2',['../md_README.html#autotoc_md121',1,'']]],
- ['2_20runtime_20decode_20path_1',['2. Runtime decode path',['../md_README.html#autotoc_md31',1,'']]],
- ['2026_2003_2013_2',['Initial implementation — 2026-03-13',['../md_changelog.html#autotoc_md23',1,'']]],
- ['2026_2006_2014_3',['v1.0 — 2026-06-14',['../md_changelog.html#autotoc_md21',1,'']]],
- ['2026_2010_2001_4',['2026-10-01',['../md_changelog.html#autotoc_md18',1,'']]],
- ['2026_2010_2005_5',['2026-10-05',['../md_changelog.html#autotoc_md14',1,'']]],
- ['2026_2010_2006_6',['2026-10-06',['../md_changelog.html#autotoc_md12',1,'']]],
- ['2026_2010_2007_7',['2026-10-07',['../md_changelog.html#autotoc_md8',1,'']]],
- ['2026_2010_2011_8',['2026-10-11',['../md_changelog.html#autotoc_md5',1,'']]],
- ['2026_2010_2013_9',['2026-10-13',['../md_changelog.html#autotoc_md2',1,'']]]
+ ['2_0',['Stage 2',['../md_README.html#autotoc_md138',1,'']]],
+ ['2_20runtime_20decode_20path_1',['2. Runtime decode path',['../md_README.html#autotoc_md47',1,'']]],
+ ['20_2',['2026-10-20',['../md_changelog.html#autotoc_md8',1,'']]],
+ ['2026_2003_2013_3',['Initial implementation — 2026-03-13',['../md_changelog.html#autotoc_md39',1,'']]],
+ ['2026_2006_2014_4',['v1.0 — 2026-06-14',['../md_changelog.html#autotoc_md37',1,'']]],
+ ['2026_2010_2001_5',['2026-10-01',['../md_changelog.html#autotoc_md34',1,'']]],
+ ['2026_2010_2005_6',['2026-10-05',['../md_changelog.html#autotoc_md30',1,'']]],
+ ['2026_2010_2006_7',['2026-10-06',['../md_changelog.html#autotoc_md28',1,'']]],
+ ['2026_2010_2007_8',['2026-10-07',['../md_changelog.html#autotoc_md24',1,'']]],
+ ['2026_2010_2011_9',['2026-10-11',['../md_changelog.html#autotoc_md21',1,'']]],
+ ['2026_2010_2013_10',['2026-10-13',['../md_changelog.html#autotoc_md18',1,'']]],
+ ['2026_2010_2014_11',['2026-10-14',['../md_changelog.html#autotoc_md14',1,'']]],
+ ['2026_2010_2020_12',['2026-10-20',['../md_changelog.html#autotoc_md8',1,'']]]
];
diff --git a/docs/html/search/all_20.js b/docs/html/search/all_20.js
new file mode 100644
index 0000000..6578492
--- /dev/null
+++ b/docs/html/search/all_20.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['о_20проекте_0',['О проекте',['../md_AGENTS.html#autotoc_md1',1,'']]]
+];
diff --git a/docs/html/search/all_21.js b/docs/html/search/all_21.js
new file mode 100644
index 0000000..e6fea3b
--- /dev/null
+++ b/docs/html/search/all_21.js
@@ -0,0 +1,6 @@
+var searchData=
+[
+ ['правила_20кода_0',['Правила кода',['../md_AGENTS.html#autotoc_md3',1,'']]],
+ ['проекте_1',['О проекте',['../md_AGENTS.html#autotoc_md1',1,'']]],
+ ['проектом_2',['Инструкции для работы с проектом',['../md_AGENTS.html',1,'']]]
+];
diff --git a/docs/html/search/all_22.js b/docs/html/search/all_22.js
new file mode 100644
index 0000000..95e1996
--- /dev/null
+++ b/docs/html/search/all_22.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['работы_20с_20проектом_0',['Инструкции для работы с проектом',['../md_AGENTS.html',1,'']]]
+];
diff --git a/docs/html/search/all_23.js b/docs/html/search/all_23.js
new file mode 100644
index 0000000..3da798f
--- /dev/null
+++ b/docs/html/search/all_23.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['с_20проектом_0',['Инструкции для работы с проектом',['../md_AGENTS.html',1,'']]]
+];
diff --git a/docs/html/search/all_24.js b/docs/html/search/all_24.js
new file mode 100644
index 0000000..5e89ca0
--- /dev/null
+++ b/docs/html/search/all_24.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['тестирование_0',['Тестирование',['../md_AGENTS.html#autotoc_md4',1,'']]]
+];
diff --git a/docs/html/search/all_25.js b/docs/html/search/all_25.js
new file mode 100644
index 0000000..2cb18de
--- /dev/null
+++ b/docs/html/search/all_25.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['формат_20задания_0',['Формат задания',['../md_AGENTS.html#autotoc_md2',1,'']]]
+];
diff --git a/docs/html/search/all_26.js b/docs/html/search/all_26.js
new file mode 100644
index 0000000..c6bbc0c
--- /dev/null
+++ b/docs/html/search/all_26.js
@@ -0,0 +1,5 @@
+var searchData=
+[
+ ['—_202026_2003_2013_0',['Initial implementation — 2026-03-13',['../md_changelog.html#autotoc_md39',1,'']]],
+ ['—_202026_2006_2014_1',['v1.0 — 2026-06-14',['../md_changelog.html#autotoc_md37',1,'']]]
+];
diff --git a/docs/html/search/all_3.js b/docs/html/search/all_3.js
index 19455c4..83df580 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_md122',1,'']]]
+ ['3_0',['Stage 3',['../md_README.html#autotoc_md139',1,'']]]
];
diff --git a/docs/html/search/all_4.js b/docs/html/search/all_4.js
index 4a84df0..dad824d 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_md123',1,'']]]
+ ['4_0',['Stage 4',['../md_README.html#autotoc_md140',1,'']]]
];
diff --git a/docs/html/search/all_5.js b/docs/html/search/all_5.js
index 2d9658f..6e4cfb3 100644
--- a/docs/html/search/all_5.js
+++ b/docs/html/search/all_5.js
@@ -1,24 +1,36 @@
var searchData=
[
- ['a_20raw_20frame_0',['Decode a raw frame',['../md_README.html#autotoc_md103',1,'']]],
- ['adapter_1',['Optional Qt model adapter',['../md_README.html#autotoc_md127',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_md9',1,'Added'],['../md_changelog.html#autotoc_md13',1,'Added'],['../md_changelog.html#autotoc_md24',1,'Added']]],
- ['additional_20regression_20coverage_4',['Additional regression coverage',['../md_tests_2README.html#autotoc_md141',1,'']]],
- ['all_20build_20variants_20in_20qt_20creator_5',['Configure all build variants in Qt Creator',['../md_README.html#autotoc_md136',1,'']]],
- ['already_20implemented_6',['Stage 1 - already implemented',['../md_README.html#autotoc_md120',1,'']]],
- ['and_20lcov_20on_20debian_20ubuntu_7',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md134',1,'']]],
- ['and_20maintenance_8',['and maintenance',['../md_changelog.html#autotoc_md25',1,'Documentation and maintenance'],['../md_changelog.html#autotoc_md17',1,'Documentation and maintenance']]],
- ['and_20motorola_20extraction_9',['Intel and Motorola Extraction',['../md_README.html#autotoc_md97',1,'']]],
- ['and_20optional_20model_20tests_10',['Tree and optional model tests',['../md_tests_2README.html#autotoc_md140',1,'']]],
- ['and_20parse_20errors_11',['and parse errors',['../md_README.html#autotoc_md81',1,'Frame validation and parse errors'],['../md_README.html#autotoc_md85',1,'Signal validation and parse errors']]],
- ['and_20precision_12',['Raw value representation and precision',['../md_README.html#autotoc_md67',1,'']]],
- ['and_20reload_13',['Definition ownership and reload',['../md_README.html#autotoc_md70',1,'']]],
- ['and_20reload_20coverage_14',['Definition lifetime and reload coverage',['../md_tests_2README.html#autotoc_md142',1,'']]],
- ['and_20run_20the_20demo_15',['Build and run the demo',['../md_README.html#autotoc_md129',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_md71',1,'']]],
- ['and_20ui_20path_18',['1. Parse and UI path',['../md_README.html#autotoc_md30',1,'']]],
- ['api_20documentation_19',['Generate API documentation',['../md_README.html#autotoc_md130',1,'']]],
- ['architecture_20',['High-Level Architecture',['../md_README.html#autotoc_md29',1,'']]]
+ ['a_20raw_20frame_0',['Decode a raw frame',['../md_README.html#autotoc_md120',1,'']]],
+ ['adapter_1',['Optional Qt model adapter',['../md_README.html#autotoc_md144',1,'']]],
+ ['addchild_2',['AddChild',['../classTreeNode.html#af87331684d4b40240aec75e3286921d3',1,'TreeNode']]],
+ ['added_3',['added',['../md_changelog.html#autotoc_md29',1,'Added'],['../md_changelog.html#autotoc_md40',1,'Added'],['../md_changelog.html#autotoc_md25',1,'Added'],['../md_changelog.html#autotoc_md22',1,'Added'],['../md_changelog.html#autotoc_md19',1,'Added'],['../md_changelog.html#autotoc_md17',1,'Added'],['../md_changelog.html#autotoc_md12',1,'Added'],['../md_changelog.html#autotoc_md10',1,'Added']]],
+ ['additional_20checks_4',['Code review and additional checks',['../md_README.html#autotoc_md150',1,'']]],
+ ['additional_20regression_20coverage_5',['Additional regression coverage',['../md_tests_2README.html#autotoc_md159',1,'']]],
+ ['all_20build_20variants_20in_20qt_20creator_6',['Configure all build variants in Qt Creator',['../md_README.html#autotoc_md154',1,'']]],
+ ['already_20implemented_7',['Stage 1 - already implemented',['../md_README.html#autotoc_md137',1,'']]],
+ ['ambiguous_8',['ambiguous',['../structPgnLookupResult.html#a6158833782348b3cc26037c2091fcc36',1,'PgnLookupResult']]],
+ ['and_20additional_20checks_9',['Code review and additional checks',['../md_README.html#autotoc_md150',1,'']]],
+ ['and_20frame_20metadata_10',['Attributes and frame metadata',['../md_README.html#autotoc_md93',1,'']]],
+ ['and_20lcov_20on_20debian_20ubuntu_11',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md152',1,'']]],
+ ['and_20maintenance_12',['and maintenance',['../md_changelog.html#autotoc_md33',1,'Documentation and maintenance'],['../md_changelog.html#autotoc_md41',1,'Documentation and maintenance']]],
+ ['and_20motorola_20extraction_13',['Intel and Motorola Extraction',['../md_README.html#autotoc_md114',1,'']]],
+ ['and_20optional_20model_20tests_14',['Tree and optional model tests',['../md_tests_2README.html#autotoc_md158',1,'']]],
+ ['and_20parse_20errors_15',['and parse errors',['../md_README.html#autotoc_md98',1,'Frame validation and parse errors'],['../md_README.html#autotoc_md102',1,'Signal validation and parse errors']]],
+ ['and_20pgn_20lookup_16',['J1939 Opt-in and PGN Lookup',['../md_README.html#autotoc_md110',1,'']]],
+ ['and_20precision_17',['Raw value representation and precision',['../md_README.html#autotoc_md83',1,'']]],
+ ['and_20reload_18',['Definition ownership and reload',['../md_README.html#autotoc_md86',1,'']]],
+ ['and_20reload_20coverage_19',['Definition lifetime and reload coverage',['../md_tests_2README.html#autotoc_md160',1,'']]],
+ ['and_20run_20the_20demo_20',['Build and run the demo',['../md_README.html#autotoc_md146',1,'']]],
+ ['and_20runtime_20decode_20module_20documentation_21',['DBC Parser and Runtime Decode Module Documentation',['../md_README.html',1,'']]],
+ ['and_20signal_20identifiers_22',['Stable frame and signal identifiers',['../md_README.html#autotoc_md87',1,'']]],
+ ['and_20ui_20path_23',['1. Parse and UI path',['../md_README.html#autotoc_md46',1,'']]],
+ ['api_20documentation_24',['Generate API documentation',['../md_README.html#autotoc_md147',1,'']]],
+ ['architecture_25',['High-Level Architecture',['../md_README.html#autotoc_md45',1,'']]],
+ ['attribute_20coverage_26',['Attribute coverage',['../md_tests_2README.html#autotoc_md163',1,'']]],
+ ['attributeassignment_27',['AttributeAssignment',['../structAttributeAssignment.html',1,'']]],
+ ['attributeassignments_28',['attributeAssignments',['../structDbcDatabase.html#aa7bdf56eb8b7ab5b873e1c096b46d8b6',1,'DbcDatabase']]],
+ ['attributedefinition_29',['AttributeDefinition',['../structAttributeDefinition.html',1,'']]],
+ ['attributedefinitions_30',['attributeDefinitions',['../structDbcDatabase.html#a14862245081989f2abf126b5ea6dfdfa',1,'DbcDatabase']]],
+ ['attributes_31',['attributes',['../structSignalInfo.html#a781766eddbf6641071623c8e5b9acb4a',1,'SignalInfo::attributes'],['../structFrameInfo.html#a9ef2736053b593cf34ba2608cf8275c0',1,'FrameInfo::attributes'],['../structDecodeFrame.html#ad506b03108a40df7e8005638c9c59653',1,'DecodeFrame::attributes'],['../structDecodeSignal.html#a204f65c7ea45a2c148f19c12d922f99b',1,'DecodeSignal::attributes'],['../structDbcDatabase.html#a321839ad81af176444358eb23114eaee',1,'DbcDatabase::attributes']]],
+ ['attributes_20and_20frame_20metadata_32',['Attributes and frame metadata',['../md_README.html#autotoc_md93',1,'']]]
];
diff --git a/docs/html/search/all_6.js b/docs/html/search/all_6.js
index bfddede..07ec2e1 100644
--- a/docs/html/search/all_6.js
+++ b/docs/html/search/all_6.js
@@ -1,14 +1,15 @@
var searchData=
[
- ['basic_20multiplexing_0',['Basic multiplexing',['../md_README.html#autotoc_md87',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_md129',1,'']]],
- ['build_20core_20without_20qt_20libraries_3',['Build core without Qt libraries',['../md_README.html#autotoc_md126',1,'']]],
- ['build_20in_20qt_20creator_4',['Configure the GCC coverage build in Qt Creator',['../md_README.html#autotoc_md135',1,'']]],
- ['build_20integration_5',['Build Integration',['../md_README.html#autotoc_md125',1,'']]],
- ['build_20runtime_20decode_20database_6',['Build runtime decode database',['../md_README.html#autotoc_md102',1,'']]],
- ['build_20ui_20tree_7',['Build UI tree',['../md_README.html#autotoc_md101',1,'']]],
- ['build_20variants_20in_20qt_20creator_8',['Configure all build variants in Qt Creator',['../md_README.html#autotoc_md136',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_md50',1,'']]]
+ ['baseptr_0',['BasePtr',['../classTypeFactory.html#a33b404da3e19ea7e1245b8a4975721bf',1,'TypeFactory']]],
+ ['basic_20multiplexing_1',['Basic multiplexing',['../md_README.html#autotoc_md104',1,'']]],
+ ['build_2',['build',['../classDbcDecodeBuilder.html#a2bc6386dfb5e58976c42e22c19ec471b',1,'DbcDecodeBuilder::Build()'],['../classDbcTreeBuilder.html#a7e57d067d831b14b383947fd125edd4b',1,'DbcTreeBuilder::Build()']]],
+ ['build_20and_20run_20the_20demo_3',['Build and run the demo',['../md_README.html#autotoc_md146',1,'']]],
+ ['build_20core_20without_20qt_20libraries_4',['Build core without Qt libraries',['../md_README.html#autotoc_md143',1,'']]],
+ ['build_20in_20qt_20creator_5',['Configure the GCC coverage build in Qt Creator',['../md_README.html#autotoc_md153',1,'']]],
+ ['build_20integration_6',['Build Integration',['../md_README.html#autotoc_md142',1,'']]],
+ ['build_20runtime_20decode_20database_7',['Build runtime decode database',['../md_README.html#autotoc_md119',1,'']]],
+ ['build_20ui_20tree_8',['Build UI tree',['../md_README.html#autotoc_md118',1,'']]],
+ ['build_20variants_20in_20qt_20creator_9',['Configure all build variants in Qt Creator',['../md_README.html#autotoc_md154',1,'']]],
+ ['byteorder_10',['byteorder',['../structDecodeSignal.html#abdc4c4bb4a67a6d61d6ca81e8a52833d',1,'DecodeSignal::byteOrder'],['../decode__database_8h.html#aaeb92d42f5a6e27b8ba19f18d69d142b',1,'ByteOrder: decode_database.h']]],
+ ['byteorder_20tt_11',['<tt>ByteOrder</tt>',['../md_README.html#autotoc_md66',1,'']]]
];
diff --git a/docs/html/search/all_7.js b/docs/html/search/all_7.js
index c29213b..7f053fd 100644
--- a/docs/html/search/all_7.js
+++ b/docs/html/search/all_7.js
@@ -1,19 +1,28 @@
var searchData=
[
- ['can_20id_20normalization_0',['CAN ID Normalization',['../md_README.html#autotoc_md91',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_md4',1,'Changed'],['../md_changelog.html#autotoc_md7',1,'Changed'],['../md_changelog.html#autotoc_md10',1,'Changed'],['../md_changelog.html#autotoc_md15',1,'Changed'],['../md_changelog.html#autotoc_md19',1,'Changed']]],
+ ['can_20id_20normalization_0',['CAN ID Normalization',['../md_README.html#autotoc_md108',1,'']]],
+ ['canid_1',['canid',['../structRawCanFrame.html#a2d0e7fa0e3d5c20bbed55ed8f7888ff4',1,'RawCanFrame::canId'],['../structPendingValueDescriptions.html#a5f0082ceeaee77e2f823661547aad844',1,'PendingValueDescriptions::canId'],['../structPendingComment.html#a6d1c3b1e149bb602a95224446709c771',1,'PendingComment::canId'],['../structDecodeFrame.html#a52e10215388db7df8b541b9d9909edcf',1,'DecodeFrame::canId'],['../structFrameKey.html#a022917652b4d3c2f2dfcc5a13ab7caa4',1,'FrameKey::canId'],['../structFrameInfo.html#af470b0742c05bfbffc31c51a68f5c05e',1,'FrameInfo::canId'],['../structAttributeAssignment.html#a330ae1a34c342b0352115a83dd31aab8',1,'AttributeAssignment::canId']]],
+ ['changed_2',['changed',['../md_changelog.html#autotoc_md16',1,'Changed'],['../md_changelog.html#autotoc_md35',1,'Changed'],['../md_changelog.html#autotoc_md31',1,'Changed'],['../md_changelog.html#autotoc_md26',1,'Changed'],['../md_changelog.html#autotoc_md23',1,'Changed'],['../md_changelog.html#autotoc_md20',1,'Changed'],['../md_changelog.html#autotoc_md11',1,'Changed']]],
['changelog_3',['Changelog',['../md_changelog.html',1,'']]],
- ['code_20coverage_4',['Measuring code coverage',['../md_README.html#autotoc_md133',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_md89',1,'']]],
- ['configure_20all_20build_20variants_20in_20qt_20creator_7',['Configure all build variants in Qt Creator',['../md_README.html#autotoc_md136',1,'']]],
- ['configure_20the_20gcc_20coverage_20build_20in_20qt_20creator_8',['Configure the GCC coverage build in Qt Creator',['../md_README.html#autotoc_md135',1,'']]],
- ['contains_9',['contains',['../classTypeFactory.html#a1a119ad2956abe146213c6ca124d8dd4',1,'TypeFactory']]],
- ['core_20without_20qt_20libraries_10',['Build core without Qt libraries',['../md_README.html#autotoc_md126',1,'']]],
- ['coverage_11',['coverage',['../md_tests_2README.html#autotoc_md141',1,'Additional regression coverage'],['../md_tests_2README.html#autotoc_md143',1,'Database validation coverage'],['../md_tests_2README.html#autotoc_md138',1,'Decoder coverage'],['../md_tests_2README.html#autotoc_md142',1,'Definition lifetime and reload coverage'],['../md_README.html#autotoc_md133',1,'Measuring code coverage'],['../md_tests_2README.html#autotoc_md139',1,'Parser coverage']]],
- ['coverage_20build_20in_20qt_20creator_12',['Configure the GCC coverage build in Qt Creator',['../md_README.html#autotoc_md135',1,'']]],
- ['create_13',['create',['../classTypeFactory.html#a3f43b03d6e3a0fd503fdec01ecf62e9f',1,'TypeFactory']]],
- ['creator_14',['creator',['../md_README.html#autotoc_md136',1,'Configure all build variants in Qt Creator'],['../md_README.html#autotoc_md135',1,'Configure the GCC coverage build in Qt Creator'],['../classTypeFactory.html#ad82f537569ece3d3a4a376523fa94473',1,'TypeFactory::creator()']]],
- ['current_20limitations_15',['Current Limitations',['../md_README.html#autotoc_md117',1,'']]]
+ ['checks_4',['Code review and additional checks',['../md_README.html#autotoc_md150',1,'']]],
+ ['classes_5',['classes',['../classTypeFactory.html#a5f119fe61c1cb9f4725ce746e4a047b3',1,'TypeFactory']]],
+ ['code_6',['code',['../structDbcDiagnostic.html#aa315a4a40b15f2e8cb34264d94a0f914',1,'DbcDiagnostic']]],
+ ['code_20coverage_7',['Measuring code coverage',['../md_README.html#autotoc_md151',1,'']]],
+ ['code_20review_20and_20additional_20checks_8',['Code review and additional checks',['../md_README.html#autotoc_md150',1,'']]],
+ ['column_9',['Column',['../classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069ae',1,'DbcTreeModel']]],
+ ['columncount_10',['columnCount',['../classDbcTreeModel.html#a397f885e7fd45c387825b4357b875c10',1,'DbcTreeModel']]],
+ ['comment_11',['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'],['../structPendingComment.html#aa344393f67770e12449a4f14f6fcf10b',1,'PendingComment::comment']]],
+ ['comments_12',['Comments',['../md_README.html#autotoc_md106',1,'']]],
+ ['configure_20all_20build_20variants_20in_20qt_20creator_13',['Configure all build variants in Qt Creator',['../md_README.html#autotoc_md154',1,'']]],
+ ['configure_20the_20gcc_20coverage_20build_20in_20qt_20creator_14',['Configure the GCC coverage build in Qt Creator',['../md_README.html#autotoc_md153',1,'']]],
+ ['contains_15',['contains',['../classTypeFactory.html#a1a119ad2956abe146213c6ca124d8dd4',1,'TypeFactory']]],
+ ['core_20without_20qt_20libraries_16',['Build core without Qt libraries',['../md_README.html#autotoc_md143',1,'']]],
+ ['coverage_17',['coverage',['../md_tests_2README.html#autotoc_md159',1,'Additional regression coverage'],['../md_tests_2README.html#autotoc_md163',1,'Attribute coverage'],['../md_tests_2README.html#autotoc_md161',1,'Database validation coverage'],['../md_tests_2README.html#autotoc_md156',1,'Decoder coverage'],['../md_tests_2README.html#autotoc_md160',1,'Definition lifetime and reload coverage'],['../md_tests_2README.html#autotoc_md162',1,'End-to-end pipeline coverage'],['../md_README.html#autotoc_md151',1,'Measuring code coverage'],['../md_tests_2README.html#autotoc_md157',1,'Parser coverage']]],
+ ['coverage_20build_20in_20qt_20creator_18',['Configure the GCC coverage build in Qt Creator',['../md_README.html#autotoc_md153',1,'']]],
+ ['create_19',['create',['../classTypeFactory.html#a3f43b03d6e3a0fd503fdec01ecf62e9f',1,'TypeFactory']]],
+ ['creator_20',['creator',['../md_README.html#autotoc_md154',1,'Configure all build variants in Qt Creator'],['../md_README.html#autotoc_md153',1,'Configure the GCC coverage build in Qt Creator'],['../classTypeFactory.html#ad82f537569ece3d3a4a376523fa94473',1,'TypeFactory::creator(const ClassId &id) const']]],
+ ['creatorfn_21',['CreatorFn',['../classTypeFactory.html#a650022aac1e2f30af5bc554a5663939f',1,'TypeFactory']]],
+ ['current_20limitations_22',['Current Limitations',['../md_README.html#autotoc_md134',1,'']]],
+ ['currentframe_23',['currentFrame',['../structDbcParseContext.html#af31b56247edff7f025957ae023a56913',1,'DbcParseContext']]],
+ ['cycletimems_24',['cycletimems',['../structFrameInfo.html#a099f02a77adfb9ac23e286ce75f4eef4',1,'FrameInfo::cycleTimeMs'],['../structDecodeFrame.html#a732c2f6853d55ce8253db61207fc21d3',1,'DecodeFrame::cycleTimeMs']]]
];
diff --git a/docs/html/search/all_8.js b/docs/html/search/all_8.js
index ecb8ff9..6d3457e 100644
--- a/docs/html/search/all_8.js
+++ b/docs/html/search/all_8.js
@@ -1,12 +1,12 @@
var searchData=
[
- ['data_0',['data',['../structRawCanFrame.html#a0acb487612104c99c9907344c035df83',1,'RawCanFrame']]],
- ['data_20structures_1',['Parsed Data Structures',['../md_README.html#autotoc_md37',1,'']]],
- ['database_2',['Build runtime decode database',['../md_README.html#autotoc_md102',1,'']]],
- ['database_20validation_20coverage_3',['Database validation coverage',['../md_tests_2README.html#autotoc_md143',1,'']]],
- ['dbc_4',['Parse DBC',['../md_README.html#autotoc_md100',1,'']]],
+ ['data_0',['data',['../structRawCanFrame.html#a0acb487612104c99c9907344c035df83',1,'RawCanFrame::data'],['../classDbcTreeModel.html#aca81d05c81cc48c1185fc36659e96e5b',1,'DbcTreeModel::data()']]],
+ ['data_20structures_1',['Parsed Data Structures',['../md_README.html#autotoc_md53',1,'']]],
+ ['database_2',['database',['../md_README.html#autotoc_md119',1,'Build runtime decode database'],['../structDbcParseContext.html#a79bad0b8302e2156670461bab529259c',1,'DbcParseContext::database'],['../structDbcParseResult.html#abfa765d29a4397e8ddaf771bae21993e',1,'DbcParseResult::database']]],
+ ['database_20validation_20coverage_3',['Database validation coverage',['../md_tests_2README.html#autotoc_md161',1,'']]],
+ ['dbc_4',['Parse DBC',['../md_README.html#autotoc_md117',1,'']]],
['dbc_20parser_20and_20runtime_20decode_20module_20documentation_5',['DBC Parser and Runtime Decode Module Documentation',['../md_README.html',1,'']]],
- ['dbc_20syntax_6',['Supported DBC Syntax',['../md_README.html#autotoc_md78',1,'']]],
+ ['dbc_20syntax_6',['Supported DBC Syntax',['../md_README.html#autotoc_md95',1,'']]],
['dbc_5fdatabase_2eh_7',['dbc_database.h',['../dbc__database_8h.html',1,'']]],
['dbc_5fdecode_5fbuilder_2ecpp_8',['dbc_decode_builder.cpp',['../dbc__decode__builder_8cpp.html',1,'']]],
['dbc_5fdecode_5fbuilder_2eh_9',['dbc_decode_builder.h',['../dbc__decode__builder_8h.html',1,'']]],
@@ -16,57 +16,62 @@ var searchData=
['dbc_5fparser_2eh_13',['dbc_parser.h',['../dbc__parser_8h.html',1,'']]],
['dbc_5ftree_5fbuilder_2ecpp_14',['dbc_tree_builder.cpp',['../dbc__tree__builder_8cpp.html',1,'']]],
['dbc_5ftree_5fbuilder_2eh_15',['dbc_tree_builder.h',['../dbc__tree__builder_8h.html',1,'']]],
- ['dbccommenthandler_16',['DbcCommentHandler',['../classDbcCommentHandler.html',1,'']]],
- ['dbcdatabase_17',['DbcDatabase',['../structDbcDatabase.html',1,'']]],
- ['dbcdatabase_20tt_18',['<tt>DbcDatabase</tt>',['../md_README.html#autotoc_md42',1,'']]],
- ['dbcdecodebuilder_19',['DbcDecodeBuilder',['../classDbcDecodeBuilder.html',1,'']]],
- ['dbcdecoder_20',['DbcDecoder',['../classDbcDecoder.html',1,'']]],
- ['dbcdecoder_20tt_21',['<tt>DbcDecoder</tt>',['../md_README.html#autotoc_md73',1,'']]],
- ['dbcdiagnostic_22',['DbcDiagnostic',['../structDbcDiagnostic.html',1,'']]],
- ['dbcdiagnosticerror_23',['DbcDiagnosticError',['../classDbcDiagnosticError.html',1,'']]],
- ['dbcframehandler_24',['DbcFrameHandler',['../classDbcFrameHandler.html',1,'']]],
- ['dbcheaderhandler_25',['DbcHeaderHandler',['../classDbcHeaderHandler.html',1,'']]],
- ['dbcparsecontext_26',['DbcParseContext',['../structDbcParseContext.html',1,'']]],
- ['dbcparser_27',['DbcParser',['../classDbcParser.html',1,'']]],
- ['dbcparseresult_28',['DbcParseResult',['../structDbcParseResult.html',1,'']]],
- ['dbcsignalhandler_29',['DbcSignalHandler',['../classDbcSignalHandler.html',1,'']]],
- ['dbcstatementdispatcher_30',['DbcStatementDispatcher',['../classDbcStatementDispatcher.html',1,'']]],
- ['dbcstatementhandler_31',['DbcStatementHandler',['../classDbcStatementHandler.html',1,'']]],
- ['dbctreebuilder_32',['DbcTreeBuilder',['../classDbcTreeBuilder.html',1,'']]],
- ['dbctreemodel_33',['DbcTreeModel',['../classDbcTreeModel.html',1,'']]],
- ['dbcunsupportedmultiplexinghandler_34',['DbcUnsupportedMultiplexingHandler',['../classDbcUnsupportedMultiplexingHandler.html',1,'']]],
- ['dbcvaluedescriptionhandler_35',['DbcValueDescriptionHandler',['../classDbcValueDescriptionHandler.html',1,'']]],
- ['debian_20ubuntu_36',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md134',1,'']]],
- ['decode_37',['Decode',['../classDbcDecoder.html#a345951ffe5d943a70d3a1ea1f39e74f7',1,'DbcDecoder']]],
- ['decode_20a_20raw_20frame_38',['Decode a raw frame',['../md_README.html#autotoc_md103',1,'']]],
- ['decode_20database_39',['Build runtime decode database',['../md_README.html#autotoc_md102',1,'']]],
- ['decode_20flow_40',['Decode Flow',['../md_README.html#autotoc_md95',1,'']]],
- ['decode_20layer_41',['Runtime Decode Layer',['../md_README.html#autotoc_md47',1,'']]],
- ['decode_20layer_20exists_42',['Why the Runtime Decode Layer Exists',['../md_README.html#autotoc_md33',1,'']]],
- ['decode_20module_20documentation_43',['DBC Parser and Runtime Decode Module Documentation',['../md_README.html',1,'']]],
- ['decode_20path_44',['2. Runtime decode path',['../md_README.html#autotoc_md31',1,'']]],
- ['decode_20strategy_45',['Unified Decode Strategy',['../md_README.html#autotoc_md105',1,'']]],
- ['decode_5fdatabase_2eh_46',['decode_database.h',['../decode__database_8h.html',1,'']]],
- ['decodedatabase_47',['decodedatabase',['../classDecodeDatabase.html',1,'DecodeDatabase'],['../classDecodeDatabase.html#a51a44cf7c3f23c98ec8781afe0097c0c',1,'DecodeDatabase::DecodeDatabase()']]],
- ['decodedatabase_20tt_48',['<tt>DecodeDatabase</tt>',['../md_README.html#autotoc_md60',1,'']]],
- ['decodedframevalue_49',['DecodedFrameValue',['../structDecodedFrameValue.html',1,'']]],
- ['decodedframevalue_20tt_50',['<tt>DecodedFrameValue</tt>',['../md_README.html#autotoc_md69',1,'']]],
- ['decodedsignalvalue_51',['DecodedSignalValue',['../structDecodedSignalValue.html',1,'']]],
- ['decodedsignalvalue_20tt_52',['<tt>DecodedSignalValue</tt>',['../md_README.html#autotoc_md65',1,'']]],
- ['decodeframe_53',['DecodeFrame',['../structDecodeFrame.html',1,'']]],
- ['decodeframe_20tt_54',['<tt>DecodeFrame</tt>',['../md_README.html#autotoc_md56',1,'']]],
- ['decoder_20coverage_55',['Decoder coverage',['../md_tests_2README.html#autotoc_md138',1,'']]],
- ['decoder_20layer_56',['Decoder Layer',['../md_README.html#autotoc_md62',1,'']]],
- ['decodesignal_57',['DecodeSignal',['../structDecodeSignal.html',1,'']]],
- ['decodesignal_20tt_58',['<tt>DecodeSignal</tt>',['../md_README.html#autotoc_md54',1,'']]],
- ['definition_59',['definition',['../structDecodedFrameValue.html#a33e971ba10030506007aa201c89f351d',1,'DecodedFrameValue::definition'],['../structDecodedSignalValue.html#a828b5ef7faefc14fbf5dbd46249bcad2',1,'DecodedSignalValue::definition'],['../md_README.html#autotoc_md79',1,'Frame definition'],['../md_README.html#autotoc_md83',1,'Signal definition']]],
- ['definition_20lifetime_20and_20reload_20coverage_60',['Definition lifetime and reload coverage',['../md_tests_2README.html#autotoc_md142',1,'']]],
- ['definition_20ownership_20and_20reload_61',['Definition ownership and reload',['../md_README.html#autotoc_md70',1,'']]],
- ['demo_62',['Build and run the demo',['../md_README.html#autotoc_md129',1,'']]],
- ['descriptions_20tt_20val_5f_20tt_63',['Signal value descriptions (<tt>VAL_</tt>)',['../md_README.html#autotoc_md115',1,'']]],
- ['diagnostics_64',['Structured diagnostics',['../md_README.html#autotoc_md76',1,'']]],
- ['dispatch_65',['Dispatch',['../classDbcStatementDispatcher.html#a495c2d5c7ebb8103b1987cdd87c142ed',1,'DbcStatementDispatcher']]],
- ['dlc_66',['dlc',['../structDecodeFrame.html#a51111ac13988be372d5673d12cf3e060',1,'DecodeFrame::dlc'],['../structFrameInfo.html#aa2b198ea0f55e560c123d35e7b3ecab9',1,'FrameInfo::dlc']]],
- ['documentation_67',['documentation',['../md_README.html',1,'DBC Parser and Runtime Decode Module Documentation'],['../md_changelog.html#autotoc_md22',1,'Documentation'],['../md_README.html#autotoc_md130',1,'Generate API documentation']]],
- ['documentation_20and_20maintenance_68',['documentation and maintenance',['../md_changelog.html#autotoc_md17',1,'Documentation and maintenance'],['../md_changelog.html#autotoc_md25',1,'Documentation and maintenance']]]
+ ['dbcattributehandler_16',['DbcAttributeHandler',['../classDbcAttributeHandler.html',1,'']]],
+ ['dbccommenthandler_17',['DbcCommentHandler',['../classDbcCommentHandler.html',1,'']]],
+ ['dbcdatabase_18',['DbcDatabase',['../structDbcDatabase.html',1,'']]],
+ ['dbcdatabase_20tt_19',['<tt>DbcDatabase</tt>',['../md_README.html#autotoc_md58',1,'']]],
+ ['dbcdecodebuilder_20',['DbcDecodeBuilder',['../classDbcDecodeBuilder.html',1,'']]],
+ ['dbcdecoder_21',['DbcDecoder',['../classDbcDecoder.html',1,'']]],
+ ['dbcdecoder_20tt_22',['<tt>DbcDecoder</tt>',['../md_README.html#autotoc_md89',1,'']]],
+ ['dbcdiagnostic_23',['DbcDiagnostic',['../structDbcDiagnostic.html',1,'']]],
+ ['dbcdiagnosticerror_24',['dbcdiagnosticerror',['../classDbcDiagnosticError.html',1,'DbcDiagnosticError'],['../classDbcDiagnosticError.html#aa9997368f79a9a0723481aaeffc44618',1,'DbcDiagnosticError::DbcDiagnosticError()']]],
+ ['dbcframehandler_25',['DbcFrameHandler',['../classDbcFrameHandler.html',1,'']]],
+ ['dbcheaderhandler_26',['DbcHeaderHandler',['../classDbcHeaderHandler.html',1,'']]],
+ ['dbcparsecontext_27',['DbcParseContext',['../structDbcParseContext.html',1,'']]],
+ ['dbcparser_28',['dbcparser',['../classDbcParser.html',1,'DbcParser'],['../classDbcParser.html#a46bc3afcd103e704dc58bb4b073da73c',1,'DbcParser::DbcParser()']]],
+ ['dbcparseresult_29',['DbcParseResult',['../structDbcParseResult.html',1,'']]],
+ ['dbcparseroptions_30',['DbcParserOptions',['../structDbcParserOptions.html',1,'']]],
+ ['dbcsignalhandler_31',['DbcSignalHandler',['../classDbcSignalHandler.html',1,'']]],
+ ['dbcstatementdispatcher_32',['dbcstatementdispatcher',['../classDbcStatementDispatcher.html',1,'DbcStatementDispatcher'],['../classDbcStatementDispatcher.html#a2f064359b59d8644b8a8196653d47482',1,'DbcStatementDispatcher::DbcStatementDispatcher()']]],
+ ['dbcstatementhandler_33',['DbcStatementHandler',['../classDbcStatementHandler.html',1,'']]],
+ ['dbctreebuilder_34',['DbcTreeBuilder',['../classDbcTreeBuilder.html',1,'']]],
+ ['dbctreemodel_35',['dbctreemodel',['../classDbcTreeModel.html#a4f7214b727d812885bf077352ec9ece1',1,'DbcTreeModel::DbcTreeModel()'],['../classDbcTreeModel.html',1,'DbcTreeModel']]],
+ ['dbcunsupportedmultiplexinghandler_36',['DbcUnsupportedMultiplexingHandler',['../classDbcUnsupportedMultiplexingHandler.html',1,'']]],
+ ['dbcvaluedescriptionhandler_37',['DbcValueDescriptionHandler',['../classDbcValueDescriptionHandler.html',1,'']]],
+ ['debian_20ubuntu_38',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md152',1,'']]],
+ ['decode_39',['decode',['../classDbcDecoder.html#a345951ffe5d943a70d3a1ea1f39e74f7',1,'DbcDecoder::Decode(const DecodeDatabase &database, const RawCanFrame &frame) const'],['../classDbcDecoder.html#ade48a94b6fcda6563bd1b2c6ff49439e',1,'DbcDecoder::Decode(const DecodeDatabase &database, const RawCanFrame &frame, const std::vector< SignalKey > &selection) const']]],
+ ['decode_20a_20raw_20frame_40',['Decode a raw frame',['../md_README.html#autotoc_md120',1,'']]],
+ ['decode_20database_41',['Build runtime decode database',['../md_README.html#autotoc_md119',1,'']]],
+ ['decode_20flow_42',['Decode Flow',['../md_README.html#autotoc_md112',1,'']]],
+ ['decode_20layer_43',['Runtime Decode Layer',['../md_README.html#autotoc_md63',1,'']]],
+ ['decode_20layer_20exists_44',['Why the Runtime Decode Layer Exists',['../md_README.html#autotoc_md49',1,'']]],
+ ['decode_20module_20documentation_45',['DBC Parser and Runtime Decode Module Documentation',['../md_README.html',1,'']]],
+ ['decode_20path_46',['2. Runtime decode path',['../md_README.html#autotoc_md47',1,'']]],
+ ['decode_20strategy_47',['Unified Decode Strategy',['../md_README.html#autotoc_md122',1,'']]],
+ ['decode_5fdatabase_2eh_48',['decode_database.h',['../decode__database_8h.html',1,'']]],
+ ['decodedatabase_49',['decodedatabase',['../classDecodeDatabase.html',1,'DecodeDatabase'],['../classDecodeDatabase.html#a51a44cf7c3f23c98ec8781afe0097c0c',1,'DecodeDatabase::DecodeDatabase()']]],
+ ['decodedatabase_20tt_50',['<tt>DecodeDatabase</tt>',['../md_README.html#autotoc_md76',1,'']]],
+ ['decodedframevalue_51',['DecodedFrameValue',['../structDecodedFrameValue.html',1,'']]],
+ ['decodedframevalue_20tt_52',['<tt>DecodedFrameValue</tt>',['../md_README.html#autotoc_md85',1,'']]],
+ ['decodedsignalvalue_53',['DecodedSignalValue',['../structDecodedSignalValue.html',1,'']]],
+ ['decodedsignalvalue_20tt_54',['<tt>DecodedSignalValue</tt>',['../md_README.html#autotoc_md81',1,'']]],
+ ['decodeframe_55',['DecodeFrame',['../structDecodeFrame.html',1,'']]],
+ ['decodeframe_20tt_56',['<tt>DecodeFrame</tt>',['../md_README.html#autotoc_md72',1,'']]],
+ ['decoder_20coverage_57',['Decoder coverage',['../md_tests_2README.html#autotoc_md156',1,'']]],
+ ['decoder_20layer_58',['Decoder Layer',['../md_README.html#autotoc_md78',1,'']]],
+ ['decodesignal_59',['DecodeSignal',['../structDecodeSignal.html',1,'']]],
+ ['decodesignal_20tt_60',['<tt>DecodeSignal</tt>',['../md_README.html#autotoc_md70',1,'']]],
+ ['defaultvalue_61',['defaultValue',['../structAttributeDefinition.html#ae0949edf67f9d4e60e4cb376a95da4f2',1,'AttributeDefinition']]],
+ ['definition_62',['definition',['../structDecodedSignalValue.html#a828b5ef7faefc14fbf5dbd46249bcad2',1,'DecodedSignalValue::definition'],['../structDecodedFrameValue.html#a33e971ba10030506007aa201c89f351d',1,'DecodedFrameValue::definition'],['../structPgnLookupResult.html#aa5b79b61d2aef48fd6ae070cf5f901c1',1,'PgnLookupResult::definition'],['../md_README.html#autotoc_md96',1,'Frame definition'],['../md_README.html#autotoc_md100',1,'Signal definition']]],
+ ['definition_20lifetime_20and_20reload_20coverage_63',['Definition lifetime and reload coverage',['../md_tests_2README.html#autotoc_md160',1,'']]],
+ ['definition_20ownership_20and_20reload_64',['Definition ownership and reload',['../md_README.html#autotoc_md86',1,'']]],
+ ['demo_65',['Build and run the demo',['../md_README.html#autotoc_md146',1,'']]],
+ ['descriptions_66',['descriptions',['../structPendingValueDescriptions.html#a10ecbaeaed2cc3ac82fada73e7e041dd',1,'PendingValueDescriptions']]],
+ ['descriptions_20tt_20val_5f_20tt_67',['Signal value descriptions (<tt>VAL_</tt>)',['../md_README.html#autotoc_md132',1,'']]],
+ ['diagnostic_68',['diagnostic',['../classDbcDiagnosticError.html#ab3965082f01d66b6d5c20525af44235d',1,'DbcDiagnosticError']]],
+ ['diagnostics_69',['diagnostics',['../structDbcParseResult.html#a3a1987b4381bb1e0a34dc09e31483679',1,'DbcParseResult::diagnostics'],['../md_README.html#autotoc_md92',1,'Structured diagnostics']]],
+ ['dispatch_70',['Dispatch',['../classDbcStatementDispatcher.html#a495c2d5c7ebb8103b1987cdd87c142ed',1,'DbcStatementDispatcher']]],
+ ['dlc_71',['dlc',['../structDecodeFrame.html#a51111ac13988be372d5673d12cf3e060',1,'DecodeFrame::dlc'],['../structFrameInfo.html#aa2b198ea0f55e560c123d35e7b3ecab9',1,'FrameInfo::dlc']]],
+ ['documentation_72',['documentation',['../md_README.html',1,'DBC Parser and Runtime Decode Module Documentation'],['../md_changelog.html#autotoc_md38',1,'Documentation'],['../md_README.html#autotoc_md147',1,'Generate API documentation']]],
+ ['documentation_20and_20maintenance_73',['documentation and maintenance',['../md_changelog.html#autotoc_md33',1,'Documentation and maintenance'],['../md_changelog.html#autotoc_md41',1,'Documentation and maintenance']]]
];
diff --git a/docs/html/search/all_9.js b/docs/html/search/all_9.js
index 81bcfa1..c541a1c 100644
--- a/docs/html/search/all_9.js
+++ b/docs/html/search/all_9.js
@@ -1,9 +1,14 @@
var searchData=
[
- ['enough_0',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md111',1,'']]],
- ['errors_1',['errors',['../md_README.html#autotoc_md81',1,'Frame validation and parse errors'],['../md_README.html#autotoc_md85',1,'Signal validation and parse errors']]],
- ['example_20usage_2',['Example Usage',['../md_README.html#autotoc_md99',1,'']]],
- ['examples_2fmain_2ecpp_3',['main.cpp',['../examples_2main_8cpp.html',1,'']]],
- ['exists_4',['Why the Runtime Decode Layer Exists',['../md_README.html#autotoc_md33',1,'']]],
- ['extraction_5',['extraction',['../md_README.html#autotoc_md97',1,'Intel and Motorola Extraction'],['../md_README.html#autotoc_md93',1,'PGN Extraction']]]
+ ['enablej1939_0',['enablej1939',['../structDbcParserOptions.html#ab31534f5c0853461b46cbb38149c33f9',1,'DbcParserOptions::enableJ1939'],['../structDbcParseContext.html#a93f8ece0f3d16bd79f631ae07afa7b54',1,'DbcParseContext::enableJ1939']]],
+ ['end_20pipeline_20coverage_1',['End-to-end pipeline coverage',['../md_tests_2README.html#autotoc_md162',1,'']]],
+ ['end_20to_20end_20pipeline_20coverage_2',['End-to-end pipeline coverage',['../md_tests_2README.html#autotoc_md162',1,'']]],
+ ['enough_3',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md128',1,'']]],
+ ['enumvalues_4',['enumValues',['../structAttributeDefinition.html#a547fe17f6cfc631528f9156e4a509c66',1,'AttributeDefinition']]],
+ ['errors_5',['errors',['../md_README.html#autotoc_md98',1,'Frame validation and parse errors'],['../md_README.html#autotoc_md102',1,'Signal validation and parse errors']]],
+ ['example_20usage_6',['Example Usage',['../md_README.html#autotoc_md116',1,'']]],
+ ['examples_2fmain_2ecpp_7',['main.cpp',['../examples_2main_8cpp.html',1,'']]],
+ ['exists_8',['Why the Runtime Decode Layer Exists',['../md_README.html#autotoc_md49',1,'']]],
+ ['extended_20validation_9',['Extended validation',['../md_tests_2README.html#autotoc_md164',1,'']]],
+ ['extraction_10',['Intel and Motorola Extraction',['../md_README.html#autotoc_md114',1,'']]]
];
diff --git a/docs/html/search/all_a.js b/docs/html/search/all_a.js
index d54b9a2..ccb642e 100644
--- a/docs/html/search/all_a.js
+++ b/docs/html/search/all_a.js
@@ -1,21 +1,27 @@
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_md113',1,'']]],
- ['findframe_2',['findframe',['../classDbcDecoder.html#a4005c4311f57b7faf21c0cb31463039c',1,'DbcDecoder::FindFrame()'],['../classDecodeDatabase.html#a780d6e747a48b10a5eb0ab85448d2970',1,'DecodeDatabase::FindFrame()']]],
- ['fixed_3',['fixed',['../md_changelog.html#autotoc_md16',1,'Fixed'],['../md_changelog.html#autotoc_md20',1,'Fixed'],['../md_changelog.html#autotoc_md11',1,'Fixed']]],
- ['flow_4',['Decode Flow',['../md_README.html#autotoc_md95',1,'']]],
- ['frame_5',['Decode a raw frame',['../md_README.html#autotoc_md103',1,'']]],
- ['frame_20and_20signal_20identifiers_6',['Stable frame and signal identifiers',['../md_README.html#autotoc_md71',1,'']]],
- ['frame_20definition_7',['Frame definition',['../md_README.html#autotoc_md79',1,'']]],
- ['frame_20validation_20and_20parse_20errors_8',['Frame validation and parse errors',['../md_README.html#autotoc_md81',1,'']]],
- ['frame_5finfo_2eh_9',['frame_info.h',['../frame__info_8h.html',1,'']]],
- ['framedecodestatus_10',['FrameDecodeStatus',['../dbc__decoder_8h.html#a855b2bc36cb18bfbae5ff30a2394e961',1,'dbc_decoder.h']]],
- ['frameinfo_11',['FrameInfo',['../structFrameInfo.html',1,'']]],
- ['frameinfo_20tt_12',['<tt>FrameInfo</tt>',['../md_README.html#autotoc_md40',1,'']]],
- ['framekey_13',['FrameKey',['../structFrameKey.html',1,'']]],
- ['framekey_20tt_14',['<tt>FrameKey</tt>',['../md_README.html#autotoc_md58',1,'']]],
- ['framekeyhasher_15',['FrameKeyHasher',['../structFrameKeyHasher.html',1,'']]],
- ['frames_16',['frames',['../structDbcDatabase.html#a2cade5d0234ee816132127542f8c612b',1,'DbcDatabase']]],
- ['frametap_17',['Intended Use in FrameTap',['../md_README.html#autotoc_md109',1,'']]]
+ ['factory_1',['Statement Handler Factory',['../md_README.html#autotoc_md130',1,'']]],
+ ['filepath_2',['filePath',['../structDbcDiagnostic.html#ac9f02705ed6a633cbb9526d0e392fb95',1,'DbcDiagnostic']]],
+ ['findframe_3',['findframe',['../classDbcDecoder.html#a4005c4311f57b7faf21c0cb31463039c',1,'DbcDecoder::FindFrame()'],['../classDecodeDatabase.html#a780d6e747a48b10a5eb0ab85448d2970',1,'DecodeDatabase::FindFrame(const FrameKey &key) const']]],
+ ['findframebypgn_4',['FindFrameByPgn',['../classDecodeDatabase.html#aa96b62b4f3fff68ab651674760f60d6d',1,'DecodeDatabase']]],
+ ['findsignal_5',['FindSignal',['../classDecodeDatabase.html#a0af5b15b9953a4f6551c27ee9ae8b514',1,'DecodeDatabase']]],
+ ['fixed_6',['fixed',['../md_changelog.html#autotoc_md13',1,'Fixed'],['../md_changelog.html#autotoc_md15',1,'Fixed'],['../md_changelog.html#autotoc_md27',1,'Fixed'],['../md_changelog.html#autotoc_md32',1,'Fixed'],['../md_changelog.html#autotoc_md36',1,'Fixed']]],
+ ['flags_7',['flags',['../classDbcTreeModel.html#a8f7842a79144bdb24fa9c5fbdcd37295',1,'DbcTreeModel']]],
+ ['flow_8',['Decode Flow',['../md_README.html#autotoc_md112',1,'']]],
+ ['frame_9',['frame',['../md_README.html#autotoc_md120',1,'Decode a raw frame'],['../structSignalKey.html#a25f4ece1bf685791b576f68e23d8ccc7',1,'SignalKey::frame']]],
+ ['frame_20and_20signal_20identifiers_10',['Stable frame and signal identifiers',['../md_README.html#autotoc_md87',1,'']]],
+ ['frame_20definition_11',['Frame definition',['../md_README.html#autotoc_md96',1,'']]],
+ ['frame_20metadata_12',['Attributes and frame metadata',['../md_README.html#autotoc_md93',1,'']]],
+ ['frame_20validation_20and_20parse_20errors_13',['Frame validation and parse errors',['../md_README.html#autotoc_md98',1,'']]],
+ ['frame_5finfo_2eh_14',['frame_info.h',['../frame__info_8h.html',1,'']]],
+ ['framedecodestatus_15',['FrameDecodeStatus',['../dbc__decoder_8h.html#a855b2bc36cb18bfbae5ff30a2394e961',1,'dbc_decoder.h']]],
+ ['frameformat_16',['frameformat',['../structFrameInfo.html#a35bf839519ef3f48b5f52dd9bcd7e9ac',1,'FrameInfo::frameFormat'],['../structDecodeFrame.html#a475e669f390491a4d99383d3fee51300',1,'DecodeFrame::frameFormat']]],
+ ['frameinfo_17',['FrameInfo',['../structFrameInfo.html',1,'']]],
+ ['frameinfo_20tt_18',['<tt>FrameInfo</tt>',['../md_README.html#autotoc_md56',1,'']]],
+ ['framekey_19',['framekey',['../structFrameKey.html',1,'FrameKey'],['../structFrameKey.html#a33bde405c7ea53000d54b3dd6e058670',1,'FrameKey::FrameKey()']]],
+ ['framekey_20tt_20',['<tt>FrameKey</tt>',['../md_README.html#autotoc_md74',1,'']]],
+ ['framekeyhasher_21',['FrameKeyHasher',['../structFrameKeyHasher.html',1,'']]],
+ ['frames_22',['frames',['../structDbcDatabase.html#a2cade5d0234ee816132127542f8c612b',1,'DbcDatabase']]],
+ ['frametap_23',['Intended Use in FrameTap',['../md_README.html#autotoc_md126',1,'']]]
];
diff --git a/docs/html/search/all_b.js b/docs/html/search/all_b.js
index ee72eff..029b961 100644
--- a/docs/html/search/all_b.js
+++ b/docs/html/search/all_b.js
@@ -1,17 +1,20 @@
var searchData=
[
- ['gcc_20coverage_20build_20in_20qt_20creator_0',['Configure the GCC coverage build in Qt Creator',['../md_README.html#autotoc_md135',1,'']]],
- ['gcc_20gcov_20and_20lcov_20on_20debian_20ubuntu_1',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md134',1,'']]],
- ['gcov_20and_20lcov_20on_20debian_20ubuntu_2',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md134',1,'']]],
- ['generate_20api_20documentation_3',['Generate API documentation',['../md_README.html#autotoc_md130',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)']]],
+ ['gcc_20coverage_20build_20in_20qt_20creator_0',['Configure the GCC coverage build in Qt Creator',['../md_README.html#autotoc_md153',1,'']]],
+ ['gcc_20gcov_20and_20lcov_20on_20debian_20ubuntu_1',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md152',1,'']]],
+ ['gcov_20and_20lcov_20on_20debian_20ubuntu_2',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md152',1,'']]],
+ ['generate_20api_20documentation_3',['Generate API documentation',['../md_README.html#autotoc_md147',1,'']]],
+ ['getchild_4',['getchild',['../classTreeNode.html#a81047bd7d2a4cc96b9ef5e20d0d63b5f',1,'TreeNode::GetChild(std::size_t index)'],['../classTreeNode.html#a4727ff801a2d1b9323c5ae50a35457a6',1,'TreeNode::GetChild(std::size_t index) const']]],
['getchildcount_5',['GetChildCount',['../classTreeNode.html#abdd82460187dca8d3e5d66f5d5c529ea',1,'TreeNode']]],
['getframe_6',['GetFrame',['../classTreeNode.html#afc503b40004764163605d6dbdb4ef811',1,'TreeNode']]],
- ['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']]]
+ ['getframekey_7',['GetFrameKey',['../classTreeNode.html#af4e6e916c48c024a3dfeadac8174b527',1,'TreeNode']]],
+ ['getframes_8',['GetFrames',['../classDecodeDatabase.html#aa034c1510984a85f60ad6c0bd744d6e8',1,'DecodeDatabase']]],
+ ['getkey_9',['GetKey',['../structDecodeFrame.html#a05e3d1c6143367553c2c3beba82a5c34',1,'DecodeFrame']]],
+ ['getname_10',['GetName',['../classTreeNode.html#aaac5b8d9dc9e5ae1f367d1adbcf20e18',1,'TreeNode']]],
+ ['getparent_11',['GetParent',['../classTreeNode.html#aa48fbc17903eb8cfa40353e29f853c6f',1,'TreeNode']]],
+ ['getrow_12',['GetRow',['../classTreeNode.html#ad501f97eeec7f7d3353bfae838fbb6a8',1,'TreeNode']]],
+ ['getsignal_13',['GetSignal',['../classTreeNode.html#a226518612d0d00b5988a2c44fc21d3f1',1,'TreeNode']]],
+ ['getsignalkey_14',['GetSignalKey',['../classTreeNode.html#a1eb94f7b6e7962c9d867a120772dfe6e',1,'TreeNode']]],
+ ['gettype_15',['GetType',['../classTreeNode.html#afa2f4b0aafa12d3d41ed00df8e0250c9',1,'TreeNode']]],
+ ['getvaluedescription_16',['GetValueDescription',['../structDecodedSignalValue.html#affc38af1bf31bcb6f2c33044bce92bd2',1,'DecodedSignalValue']]]
];
diff --git a/docs/html/search/all_c.js b/docs/html/search/all_c.js
index acd3563..2987215 100644
--- a/docs/html/search/all_c.js
+++ b/docs/html/search/all_c.js
@@ -1,6 +1,9 @@
var searchData=
[
- ['handler_20factory_0',['Statement Handler Factory',['../md_README.html#autotoc_md113',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_md29',1,'']]]
+ ['handle_0',['handle',['../classDbcStatementHandler.html#a3de86e1e27e9bcb0fe6f1460a8ba5739',1,'DbcStatementHandler::Handle()'],['../classDbcFrameHandler.html#a0d3f43bbcc5e191460bc31827e74ce89',1,'DbcFrameHandler::Handle()'],['../classDbcSignalHandler.html#ad7d891ec1414fb645f85ccd410f2737b',1,'DbcSignalHandler::Handle()'],['../classDbcCommentHandler.html#aa4fce77b585a441d251d8535ef7a51a6',1,'DbcCommentHandler::Handle()'],['../classDbcAttributeHandler.html#a397f23259b7ff79abb4b5141489caa83',1,'DbcAttributeHandler::Handle()'],['../classDbcValueDescriptionHandler.html#a653e13364f396b54244edc2c0fdd831a',1,'DbcValueDescriptionHandler::Handle()'],['../classDbcUnsupportedMultiplexingHandler.html#a9853fd67465f92ef587792986ea179ac',1,'DbcUnsupportedMultiplexingHandler::Handle()'],['../classDbcHeaderHandler.html#a1e43a9dcf157f4d4418032d9e9711693',1,'DbcHeaderHandler::Handle()']]],
+ ['handler_20factory_1',['Statement Handler Factory',['../md_README.html#autotoc_md130',1,'']]],
+ ['haserrors_2',['HasErrors',['../structDbcParseResult.html#a4da8641de3f6b55c7447c4421e05d20d',1,'DbcParseResult']]],
+ ['haspgn_3',['haspgn',['../structDecodeFrame.html#a2551102670c4a540fced4c71da0b369d',1,'DecodeFrame::hasPgn'],['../structFrameInfo.html#a4737a5420213ad4304724e39f3a4e55d',1,'FrameInfo::hasPgn']]],
+ ['headerdata_4',['headerData',['../classDbcTreeModel.html#aad5834e8edb00808cbfa498ea8c63fe9',1,'DbcTreeModel']]],
+ ['high_20level_20architecture_5',['High-Level Architecture',['../md_README.html#autotoc_md45',1,'']]]
];
diff --git a/docs/html/search/all_d.js b/docs/html/search/all_d.js
index ea248c5..b3d8824 100644
--- a/docs/html/search/all_d.js
+++ b/docs/html/search/all_d.js
@@ -1,17 +1,22 @@
var searchData=
[
- ['id_20normalization_0',['CAN ID Normalization',['../md_README.html#autotoc_md91',1,'']]],
- ['identifiers_1',['Stable frame and signal identifiers',['../md_README.html#autotoc_md71',1,'']]],
- ['implementation_20—_202026_2003_2013_2',['Initial implementation — 2026-03-13',['../md_changelog.html#autotoc_md23',1,'']]],
- ['implemented_3',['Stage 1 - already implemented',['../md_README.html#autotoc_md120',1,'']]],
- ['in_20frametap_4',['Intended Use in FrameTap',['../md_README.html#autotoc_md109',1,'']]],
- ['in_20qt_20creator_5',['in qt creator',['../md_README.html#autotoc_md136',1,'Configure all build variants in Qt Creator'],['../md_README.html#autotoc_md135',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_md23',1,'']]],
- ['integration_7',['Build Integration',['../md_README.html#autotoc_md125',1,'']]],
- ['intel_20and_20motorola_20extraction_8',['Intel and Motorola Extraction',['../md_README.html#autotoc_md97',1,'']]],
- ['intended_20use_20in_20frametap_9',['Intended Use in FrameTap',['../md_README.html#autotoc_md109',1,'']]],
- ['is_20not_20enough_10',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md111',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']]]
+ ['id_20normalization_0',['CAN ID Normalization',['../md_README.html#autotoc_md108',1,'']]],
+ ['identifiers_1',['Stable frame and signal identifiers',['../md_README.html#autotoc_md87',1,'']]],
+ ['implementation_20—_202026_2003_2013_2',['Initial implementation — 2026-03-13',['../md_changelog.html#autotoc_md39',1,'']]],
+ ['implemented_3',['Stage 1 - already implemented',['../md_README.html#autotoc_md137',1,'']]],
+ ['in_20and_20pgn_20lookup_4',['J1939 Opt-in and PGN Lookup',['../md_README.html#autotoc_md110',1,'']]],
+ ['in_20frametap_5',['Intended Use in FrameTap',['../md_README.html#autotoc_md126',1,'']]],
+ ['in_20qt_20creator_6',['in qt creator',['../md_README.html#autotoc_md154',1,'Configure all build variants in Qt Creator'],['../md_README.html#autotoc_md153',1,'Configure the GCC coverage build in Qt Creator']]],
+ ['index_7',['index',['../classDbcTreeModel.html#a8caeb5ec6141eb3e446e48df3c70b3ad',1,'DbcTreeModel']]],
+ ['initial_20implementation_20—_202026_2003_2013_8',['Initial implementation — 2026-03-13',['../md_changelog.html#autotoc_md39',1,'']]],
+ ['integermaximum_9',['integerMaximum',['../structAttributeDefinition.html#a5ca8f41ea3e921f54d81b8760c1dcfb3',1,'AttributeDefinition']]],
+ ['integerminimum_10',['integerMinimum',['../structAttributeDefinition.html#aaf87153bac0b228ad87b88e96f303210',1,'AttributeDefinition']]],
+ ['integration_11',['Build Integration',['../md_README.html#autotoc_md142',1,'']]],
+ ['intel_20and_20motorola_20extraction_12',['Intel and Motorola Extraction',['../md_README.html#autotoc_md114',1,'']]],
+ ['intended_20use_20in_20frametap_13',['Intended Use in FrameTap',['../md_README.html#autotoc_md126',1,'']]],
+ ['is_20not_20enough_14',['Why the Tree Is Not Enough',['../md_README.html#autotoc_md128',1,'']]],
+ ['isextended_15',['isextended',['../structFrameInfo.html#a34b726afaad2ac5c697fdb2ac070cdaf',1,'FrameInfo::isExtended'],['../structFrameKey.html#aa3179b709d02ef70cf0e736f040a2145',1,'FrameKey::isExtended'],['../structDecodeFrame.html#a3ee2348d781f8f15aaf87e8dcf57ec41',1,'DecodeFrame::isExtended'],['../structPendingComment.html#a9abd7e15ed59eb4534c66ff74f276e07',1,'PendingComment::isExtended'],['../structPendingValueDescriptions.html#a60f185e8d91010927c4aa3b4a750c9f4',1,'PendingValueDescriptions::isExtended'],['../structRawCanFrame.html#a462193d275adc1dba8bd18ffa0e36bb7',1,'RawCanFrame::isExtended'],['../structAttributeAssignment.html#a024a249cc63dbfbf337eea395fe3471e',1,'AttributeAssignment::isExtended']]],
+ ['islittleendian_16',['isLittleEndian',['../structSignalInfo.html#af363b1563fb4c7cc8973f9a80c06846c',1,'SignalInfo']]],
+ ['issignal_17',['isSignal',['../structPendingComment.html#ac03903ffb042d27ad66012eb18ea1437',1,'PendingComment']]],
+ ['issigned_18',['isSigned',['../structSignalInfo.html#a52a52b320eef92fbcb4626307f9a498f',1,'SignalInfo']]]
];
diff --git a/docs/html/search/all_e.js b/docs/html/search/all_e.js
index 199fcb0..ba11adf 100644
--- a/docs/html/search/all_e.js
+++ b/docs/html/search/all_e.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['key_0',['key',['../structDecodedSignalValue.html#a33df0fcd92b23b3e08539906fc6b4c4a',1,'DecodedSignalValue::key'],['../structDecodedFrameValue.html#a32143efe2023a1ecd977a9ae93e50b73',1,'DecodedFrameValue::key']]]
+ ['j1939_20opt_20in_20and_20pgn_20lookup_0',['J1939 Opt-in and PGN Lookup',['../md_README.html#autotoc_md110',1,'']]]
];
diff --git a/docs/html/search/all_f.js b/docs/html/search/all_f.js
index b182bdf..199fcb0 100644
--- a/docs/html/search/all_f.js
+++ b/docs/html/search/all_f.js
@@ -1,13 +1,4 @@
var searchData=
[
- ['layer_0',['layer',['../md_README.html#autotoc_md62',1,'Decoder Layer'],['../md_README.html#autotoc_md47',1,'Runtime Decode Layer'],['../md_README.html#autotoc_md44',1,'UI Tree Layer']]],
- ['layer_20exists_1',['Why the Runtime Decode Layer Exists',['../md_README.html#autotoc_md33',1,'']]],
- ['layout_2',['Module Layout',['../md_README.html#autotoc_md35',1,'']]],
- ['lcov_20on_20debian_20ubuntu_3',['GCC, gcov, and LCOV on Debian/Ubuntu',['../md_README.html#autotoc_md134',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_md29',1,'']]],
- ['libraries_6',['Build core without Qt libraries',['../md_README.html#autotoc_md126',1,'']]],
- ['lifetime_20and_20reload_20coverage_7',['Definition lifetime and reload coverage',['../md_tests_2README.html#autotoc_md142',1,'']]],
- ['limitations_8',['Current Limitations',['../md_README.html#autotoc_md117',1,'']]],
- ['live_20path_9',['live path',['../md_README.html#autotoc_md106',1,'']]]
+ ['key_0',['key',['../structDecodedSignalValue.html#a33df0fcd92b23b3e08539906fc6b4c4a',1,'DecodedSignalValue::key'],['../structDecodedFrameValue.html#a32143efe2023a1ecd977a9ae93e50b73',1,'DecodedFrameValue::key']]]
];
diff --git a/docs/html/search/classes_0.js b/docs/html/search/classes_0.js
index 3331d21..74f5fcc 100644
--- a/docs/html/search/classes_0.js
+++ b/docs/html/search/classes_0.js
@@ -1,26 +1,5 @@
var searchData=
[
- ['dbccommenthandler_0',['DbcCommentHandler',['../classDbcCommentHandler.html',1,'']]],
- ['dbcdatabase_1',['DbcDatabase',['../structDbcDatabase.html',1,'']]],
- ['dbcdecodebuilder_2',['DbcDecodeBuilder',['../classDbcDecodeBuilder.html',1,'']]],
- ['dbcdecoder_3',['DbcDecoder',['../classDbcDecoder.html',1,'']]],
- ['dbcdiagnostic_4',['DbcDiagnostic',['../structDbcDiagnostic.html',1,'']]],
- ['dbcdiagnosticerror_5',['DbcDiagnosticError',['../classDbcDiagnosticError.html',1,'']]],
- ['dbcframehandler_6',['DbcFrameHandler',['../classDbcFrameHandler.html',1,'']]],
- ['dbcheaderhandler_7',['DbcHeaderHandler',['../classDbcHeaderHandler.html',1,'']]],
- ['dbcparsecontext_8',['DbcParseContext',['../structDbcParseContext.html',1,'']]],
- ['dbcparser_9',['DbcParser',['../classDbcParser.html',1,'']]],
- ['dbcparseresult_10',['DbcParseResult',['../structDbcParseResult.html',1,'']]],
- ['dbcsignalhandler_11',['DbcSignalHandler',['../classDbcSignalHandler.html',1,'']]],
- ['dbcstatementdispatcher_12',['DbcStatementDispatcher',['../classDbcStatementDispatcher.html',1,'']]],
- ['dbcstatementhandler_13',['DbcStatementHandler',['../classDbcStatementHandler.html',1,'']]],
- ['dbctreebuilder_14',['DbcTreeBuilder',['../classDbcTreeBuilder.html',1,'']]],
- ['dbctreemodel_15',['DbcTreeModel',['../classDbcTreeModel.html',1,'']]],
- ['dbcunsupportedmultiplexinghandler_16',['DbcUnsupportedMultiplexingHandler',['../classDbcUnsupportedMultiplexingHandler.html',1,'']]],
- ['dbcvaluedescriptionhandler_17',['DbcValueDescriptionHandler',['../classDbcValueDescriptionHandler.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,'']]],
- ['decodesignal_22',['DecodeSignal',['../structDecodeSignal.html',1,'']]]
+ ['attributeassignment_0',['AttributeAssignment',['../structAttributeAssignment.html',1,'']]],
+ ['attributedefinition_1',['AttributeDefinition',['../structAttributeDefinition.html',1,'']]]
];
diff --git a/docs/html/search/classes_1.js b/docs/html/search/classes_1.js
index 4259dc9..b58041c 100644
--- a/docs/html/search/classes_1.js
+++ b/docs/html/search/classes_1.js
@@ -1,6 +1,28 @@
var searchData=
[
- ['frameinfo_0',['FrameInfo',['../structFrameInfo.html',1,'']]],
- ['framekey_1',['FrameKey',['../structFrameKey.html',1,'']]],
- ['framekeyhasher_2',['FrameKeyHasher',['../structFrameKeyHasher.html',1,'']]]
+ ['dbcattributehandler_0',['DbcAttributeHandler',['../classDbcAttributeHandler.html',1,'']]],
+ ['dbccommenthandler_1',['DbcCommentHandler',['../classDbcCommentHandler.html',1,'']]],
+ ['dbcdatabase_2',['DbcDatabase',['../structDbcDatabase.html',1,'']]],
+ ['dbcdecodebuilder_3',['DbcDecodeBuilder',['../classDbcDecodeBuilder.html',1,'']]],
+ ['dbcdecoder_4',['DbcDecoder',['../classDbcDecoder.html',1,'']]],
+ ['dbcdiagnostic_5',['DbcDiagnostic',['../structDbcDiagnostic.html',1,'']]],
+ ['dbcdiagnosticerror_6',['DbcDiagnosticError',['../classDbcDiagnosticError.html',1,'']]],
+ ['dbcframehandler_7',['DbcFrameHandler',['../classDbcFrameHandler.html',1,'']]],
+ ['dbcheaderhandler_8',['DbcHeaderHandler',['../classDbcHeaderHandler.html',1,'']]],
+ ['dbcparsecontext_9',['DbcParseContext',['../structDbcParseContext.html',1,'']]],
+ ['dbcparser_10',['DbcParser',['../classDbcParser.html',1,'']]],
+ ['dbcparseresult_11',['DbcParseResult',['../structDbcParseResult.html',1,'']]],
+ ['dbcparseroptions_12',['DbcParserOptions',['../structDbcParserOptions.html',1,'']]],
+ ['dbcsignalhandler_13',['DbcSignalHandler',['../classDbcSignalHandler.html',1,'']]],
+ ['dbcstatementdispatcher_14',['DbcStatementDispatcher',['../classDbcStatementDispatcher.html',1,'']]],
+ ['dbcstatementhandler_15',['DbcStatementHandler',['../classDbcStatementHandler.html',1,'']]],
+ ['dbctreebuilder_16',['DbcTreeBuilder',['../classDbcTreeBuilder.html',1,'']]],
+ ['dbctreemodel_17',['DbcTreeModel',['../classDbcTreeModel.html',1,'']]],
+ ['dbcunsupportedmultiplexinghandler_18',['DbcUnsupportedMultiplexingHandler',['../classDbcUnsupportedMultiplexingHandler.html',1,'']]],
+ ['dbcvaluedescriptionhandler_19',['DbcValueDescriptionHandler',['../classDbcValueDescriptionHandler.html',1,'']]],
+ ['decodedatabase_20',['DecodeDatabase',['../classDecodeDatabase.html',1,'']]],
+ ['decodedframevalue_21',['DecodedFrameValue',['../structDecodedFrameValue.html',1,'']]],
+ ['decodedsignalvalue_22',['DecodedSignalValue',['../structDecodedSignalValue.html',1,'']]],
+ ['decodeframe_23',['DecodeFrame',['../structDecodeFrame.html',1,'']]],
+ ['decodesignal_24',['DecodeSignal',['../structDecodeSignal.html',1,'']]]
];
diff --git a/docs/html/search/classes_2.js b/docs/html/search/classes_2.js
index 731f810..4259dc9 100644
--- a/docs/html/search/classes_2.js
+++ b/docs/html/search/classes_2.js
@@ -1,4 +1,6 @@
var searchData=
[
- ['multiplexing_0',['Multiplexing',['../structMultiplexing.html',1,'']]]
+ ['frameinfo_0',['FrameInfo',['../structFrameInfo.html',1,'']]],
+ ['framekey_1',['FrameKey',['../structFrameKey.html',1,'']]],
+ ['framekeyhasher_2',['FrameKeyHasher',['../structFrameKeyHasher.html',1,'']]]
];
diff --git a/docs/html/search/classes_3.js b/docs/html/search/classes_3.js
index 9fdab5b..731f810 100644
--- a/docs/html/search/classes_3.js
+++ b/docs/html/search/classes_3.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['pendingvaluedescriptions_0',['PendingValueDescriptions',['../structPendingValueDescriptions.html',1,'']]]
+ ['multiplexing_0',['Multiplexing',['../structMultiplexing.html',1,'']]]
];
diff --git a/docs/html/search/classes_4.js b/docs/html/search/classes_4.js
index ee60254..34a0261 100644
--- a/docs/html/search/classes_4.js
+++ b/docs/html/search/classes_4.js
@@ -1,4 +1,7 @@
var searchData=
[
- ['rawcanframe_0',['RawCanFrame',['../structRawCanFrame.html',1,'']]]
+ ['pendingattribute_0',['PendingAttribute',['../structPendingAttribute.html',1,'']]],
+ ['pendingcomment_1',['PendingComment',['../structPendingComment.html',1,'']]],
+ ['pendingvaluedescriptions_2',['PendingValueDescriptions',['../structPendingValueDescriptions.html',1,'']]],
+ ['pgnlookupresult_3',['PgnLookupResult',['../structPgnLookupResult.html',1,'']]]
];
diff --git a/docs/html/search/classes_5.js b/docs/html/search/classes_5.js
index b92fb16..ee60254 100644
--- a/docs/html/search/classes_5.js
+++ b/docs/html/search/classes_5.js
@@ -1,6 +1,4 @@
var searchData=
[
- ['signalinfo_0',['SignalInfo',['../structSignalInfo.html',1,'']]],
- ['signalkey_1',['SignalKey',['../structSignalKey.html',1,'']]],
- ['signalkeyhasher_2',['SignalKeyHasher',['../structSignalKeyHasher.html',1,'']]]
+ ['rawcanframe_0',['RawCanFrame',['../structRawCanFrame.html',1,'']]]
];
diff --git a/docs/html/search/classes_6.js b/docs/html/search/classes_6.js
index 5c7d392..b92fb16 100644
--- a/docs/html/search/classes_6.js
+++ b/docs/html/search/classes_6.js
@@ -1,6 +1,6 @@
var searchData=
[
- ['treenode_0',['TreeNode',['../classTreeNode.html',1,'']]],
- ['typefactory_1',['TypeFactory',['../classTypeFactory.html',1,'']]],
- ['typefactory_3c_20std_3a_3astring_2c_20dbcstatementhandler_20_3e_2',['TypeFactory< std::string, DbcStatementHandler >',['../classTypeFactory.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/classes_7.js b/docs/html/search/classes_7.js
new file mode 100644
index 0000000..5c7d392
--- /dev/null
+++ b/docs/html/search/classes_7.js
@@ -0,0 +1,6 @@
+var searchData=
+[
+ ['treenode_0',['TreeNode',['../classTreeNode.html',1,'']]],
+ ['typefactory_1',['TypeFactory',['../classTypeFactory.html',1,'']]],
+ ['typefactory_3c_20std_3a_3astring_2c_20dbcstatementhandler_20_3e_2',['TypeFactory< std::string, DbcStatementHandler >',['../classTypeFactory.html',1,'']]]
+];
diff --git a/docs/html/search/enums_1.js b/docs/html/search/enums_1.js
index ed50e83..04f6b78 100644
--- a/docs/html/search/enums_1.js
+++ b/docs/html/search/enums_1.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['framedecodestatus_0',['FrameDecodeStatus',['../dbc__decoder_8h.html#a855b2bc36cb18bfbae5ff30a2394e961',1,'dbc_decoder.h']]]
+ ['column_0',['Column',['../classDbcTreeModel.html#a5e31be609fae4d7dfdd79140f56069ae',1,'DbcTreeModel']]]
];
diff --git a/docs/html/search/enums_2.js b/docs/html/search/enums_2.js
index 07a6d2a..ed50e83 100644
--- a/docs/html/search/enums_2.js
+++ b/docs/html/search/enums_2.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['nodetype_0',['NodeType',['../tree__node_8h.html#acac9cbaeea226ed297804c012dc12b16',1,'tree_node.h']]]
+ ['framedecodestatus_0',['FrameDecodeStatus',['../dbc__decoder_8h.html#a855b2bc36cb18bfbae5ff30a2394e961',1,'dbc_decoder.h']]]
];
diff --git a/docs/html/search/enums_3.js b/docs/html/search/enums_3.js
index 9189d7f..07a6d2a 100644
--- a/docs/html/search/enums_3.js
+++ b/docs/html/search/enums_3.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['valuetype_0',['ValueType',['../decode__database_8h.html#ad9971b6ef33e02ba2c75d19c1d2518a1',1,'decode_database.h']]]
+ ['nodetype_0',['NodeType',['../tree__node_8h.html#acac9cbaeea226ed297804c012dc12b16',1,'tree_node.h']]]
];
diff --git a/docs/html/search/enums_4.js b/docs/html/search/enums_4.js
new file mode 100644
index 0000000..02f8bce
--- /dev/null
+++ b/docs/html/search/enums_4.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['role_0',['Role',['../classDbcTreeModel.html#a0f360d424848c6c39f2312e6209b0dfd',1,'DbcTreeModel']]]
+];
diff --git a/docs/html/search/enums_5.js b/docs/html/search/enums_5.js
new file mode 100644
index 0000000..4f8750a
--- /dev/null
+++ b/docs/html/search/enums_5.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['signaldecodestatus_0',['SignalDecodeStatus',['../dbc__decoder_8h.html#a5f4a41ee2810487020135b45e8d7559a',1,'dbc_decoder.h']]]
+];
diff --git a/docs/html/search/enums_6.js b/docs/html/search/enums_6.js
new file mode 100644
index 0000000..9189d7f
--- /dev/null
+++ b/docs/html/search/enums_6.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['valuetype_0',['ValueType',['../decode__database_8h.html#ad9971b6ef33e02ba2c75d19c1d2518a1',1,'decode_database.h']]]
+];
diff --git a/docs/html/search/functions_0.js b/docs/html/search/functions_0.js
index ca215cf..ace761a 100644
--- a/docs/html/search/functions_0.js
+++ b/docs/html/search/functions_0.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['addchild_0',['AddChild',['../classTreeNode.html#a6161f2ebb92184eab4215d121870e788',1,'TreeNode']]]
+ ['addchild_0',['AddChild',['../classTreeNode.html#af87331684d4b40240aec75e3286921d3',1,'TreeNode']]]
];
diff --git a/docs/html/search/functions_2.js b/docs/html/search/functions_2.js
index 807421d..eff8f3c 100644
--- a/docs/html/search/functions_2.js
+++ b/docs/html/search/functions_2.js
@@ -1,6 +1,7 @@
var searchData=
[
- ['contains_0',['contains',['../classTypeFactory.html#a1a119ad2956abe146213c6ca124d8dd4',1,'TypeFactory']]],
- ['create_1',['create',['../classTypeFactory.html#a3f43b03d6e3a0fd503fdec01ecf62e9f',1,'TypeFactory']]],
- ['creator_2',['creator',['../classTypeFactory.html#ad82f537569ece3d3a4a376523fa94473',1,'TypeFactory']]]
+ ['columncount_0',['columnCount',['../classDbcTreeModel.html#a397f885e7fd45c387825b4357b875c10',1,'DbcTreeModel']]],
+ ['contains_1',['contains',['../classTypeFactory.html#a1a119ad2956abe146213c6ca124d8dd4',1,'TypeFactory']]],
+ ['create_2',['create',['../classTypeFactory.html#a3f43b03d6e3a0fd503fdec01ecf62e9f',1,'TypeFactory']]],
+ ['creator_3',['creator',['../classTypeFactory.html#ad82f537569ece3d3a4a376523fa94473',1,'TypeFactory']]]
];
diff --git a/docs/html/search/functions_3.js b/docs/html/search/functions_3.js
index 6a0b96c..a4f49e2 100644
--- a/docs/html/search/functions_3.js
+++ b/docs/html/search/functions_3.js
@@ -1,6 +1,11 @@
var searchData=
[
- ['decode_0',['Decode',['../classDbcDecoder.html#a345951ffe5d943a70d3a1ea1f39e74f7',1,'DbcDecoder']]],
- ['decodedatabase_1',['DecodeDatabase',['../classDecodeDatabase.html#a51a44cf7c3f23c98ec8781afe0097c0c',1,'DecodeDatabase']]],
- ['dispatch_2',['Dispatch',['../classDbcStatementDispatcher.html#a495c2d5c7ebb8103b1987cdd87c142ed',1,'DbcStatementDispatcher']]]
+ ['data_0',['data',['../classDbcTreeModel.html#aca81d05c81cc48c1185fc36659e96e5b',1,'DbcTreeModel']]],
+ ['dbcdiagnosticerror_1',['DbcDiagnosticError',['../classDbcDiagnosticError.html#aa9997368f79a9a0723481aaeffc44618',1,'DbcDiagnosticError']]],
+ ['dbcparser_2',['DbcParser',['../classDbcParser.html#a46bc3afcd103e704dc58bb4b073da73c',1,'DbcParser']]],
+ ['dbcstatementdispatcher_3',['DbcStatementDispatcher',['../classDbcStatementDispatcher.html#a2f064359b59d8644b8a8196653d47482',1,'DbcStatementDispatcher']]],
+ ['dbctreemodel_4',['DbcTreeModel',['../classDbcTreeModel.html#a4f7214b727d812885bf077352ec9ece1',1,'DbcTreeModel']]],
+ ['decode_5',['decode',['../classDbcDecoder.html#a345951ffe5d943a70d3a1ea1f39e74f7',1,'DbcDecoder::Decode(const DecodeDatabase &database, const RawCanFrame &frame) const'],['../classDbcDecoder.html#ade48a94b6fcda6563bd1b2c6ff49439e',1,'DbcDecoder::Decode(const DecodeDatabase &database, const RawCanFrame &frame, const std::vector< SignalKey > &selection) const']]],
+ ['decodedatabase_6',['DecodeDatabase',['../classDecodeDatabase.html#a51a44cf7c3f23c98ec8781afe0097c0c',1,'DecodeDatabase']]],
+ ['dispatch_7',['Dispatch',['../classDbcStatementDispatcher.html#a495c2d5c7ebb8103b1987cdd87c142ed',1,'DbcStatementDispatcher']]]
];
diff --git a/docs/html/search/functions_4.js b/docs/html/search/functions_4.js
index 27deb57..b12af4f 100644
--- a/docs/html/search/functions_4.js
+++ b/docs/html/search/functions_4.js
@@ -1,4 +1,8 @@
var searchData=
[
- ['findframe_0',['findframe',['../classDbcDecoder.html#a4005c4311f57b7faf21c0cb31463039c',1,'DbcDecoder::FindFrame()'],['../classDecodeDatabase.html#a780d6e747a48b10a5eb0ab85448d2970',1,'DecodeDatabase::FindFrame()']]]
+ ['findframe_0',['findframe',['../classDbcDecoder.html#a4005c4311f57b7faf21c0cb31463039c',1,'DbcDecoder::FindFrame()'],['../classDecodeDatabase.html#a780d6e747a48b10a5eb0ab85448d2970',1,'DecodeDatabase::FindFrame(const FrameKey &key) const']]],
+ ['findframebypgn_1',['FindFrameByPgn',['../classDecodeDatabase.html#aa96b62b4f3fff68ab651674760f60d6d',1,'DecodeDatabase']]],
+ ['findsignal_2',['FindSignal',['../classDecodeDatabase.html#a0af5b15b9953a4f6551c27ee9ae8b514',1,'DecodeDatabase']]],
+ ['flags_3',['flags',['../classDbcTreeModel.html#a8f7842a79144bdb24fa9c5fbdcd37295',1,'DbcTreeModel']]],
+ ['framekey_4',['FrameKey',['../structFrameKey.html#a33bde405c7ea53000d54b3dd6e058670',1,'FrameKey']]]
];
diff --git a/docs/html/search/functions_5.js b/docs/html/search/functions_5.js
index 09c3f1c..9c6936e 100644
--- a/docs/html/search/functions_5.js
+++ b/docs/html/search/functions_5.js
@@ -3,11 +3,14 @@ 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']]],
- ['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']]]
+ ['getframekey_3',['GetFrameKey',['../classTreeNode.html#af4e6e916c48c024a3dfeadac8174b527',1,'TreeNode']]],
+ ['getframes_4',['GetFrames',['../classDecodeDatabase.html#aa034c1510984a85f60ad6c0bd744d6e8',1,'DecodeDatabase']]],
+ ['getkey_5',['GetKey',['../structDecodeFrame.html#a05e3d1c6143367553c2c3beba82a5c34',1,'DecodeFrame']]],
+ ['getname_6',['GetName',['../classTreeNode.html#aaac5b8d9dc9e5ae1f367d1adbcf20e18',1,'TreeNode']]],
+ ['getparent_7',['GetParent',['../classTreeNode.html#aa48fbc17903eb8cfa40353e29f853c6f',1,'TreeNode']]],
+ ['getrow_8',['GetRow',['../classTreeNode.html#ad501f97eeec7f7d3353bfae838fbb6a8',1,'TreeNode']]],
+ ['getsignal_9',['GetSignal',['../classTreeNode.html#a226518612d0d00b5988a2c44fc21d3f1',1,'TreeNode']]],
+ ['getsignalkey_10',['GetSignalKey',['../classTreeNode.html#a1eb94f7b6e7962c9d867a120772dfe6e',1,'TreeNode']]],
+ ['gettype_11',['GetType',['../classTreeNode.html#afa2f4b0aafa12d3d41ed00df8e0250c9',1,'TreeNode']]],
+ ['getvaluedescription_12',['GetValueDescription',['../structDecodedSignalValue.html#affc38af1bf31bcb6f2c33044bce92bd2',1,'DecodedSignalValue']]]
];
diff --git a/docs/html/search/functions_6.js b/docs/html/search/functions_6.js
index 3aebbee..4c76e30 100644
--- a/docs/html/search/functions_6.js
+++ b/docs/html/search/functions_6.js
@@ -1,5 +1,6 @@
var searchData=
[
- ['parsefile_0',['ParseFile',['../classDbcParser.html#aef72826942c9095d653fafa435855e56',1,'DbcParser']]],
- ['parsefilewithdiagnostics_1',['ParseFileWithDiagnostics',['../classDbcParser.html#a0e915ce79c2e3d4c95a5aaf2bf0409bc',1,'DbcParser']]]
+ ['handle_0',['handle',['../classDbcStatementHandler.html#a3de86e1e27e9bcb0fe6f1460a8ba5739',1,'DbcStatementHandler::Handle()'],['../classDbcFrameHandler.html#a0d3f43bbcc5e191460bc31827e74ce89',1,'DbcFrameHandler::Handle()'],['../classDbcSignalHandler.html#ad7d891ec1414fb645f85ccd410f2737b',1,'DbcSignalHandler::Handle()'],['../classDbcCommentHandler.html#aa4fce77b585a441d251d8535ef7a51a6',1,'DbcCommentHandler::Handle()'],['../classDbcAttributeHandler.html#a397f23259b7ff79abb4b5141489caa83',1,'DbcAttributeHandler::Handle()'],['../classDbcValueDescriptionHandler.html#a653e13364f396b54244edc2c0fdd831a',1,'DbcValueDescriptionHandler::Handle()'],['../classDbcUnsupportedMultiplexingHandler.html#a9853fd67465f92ef587792986ea179ac',1,'DbcUnsupportedMultiplexingHandler::Handle()'],['../classDbcHeaderHandler.html#a1e43a9dcf157f4d4418032d9e9711693',1,'DbcHeaderHandler::Handle()']]],
+ ['haserrors_1',['HasErrors',['../structDbcParseResult.html#a4da8641de3f6b55c7447c4421e05d20d',1,'DbcParseResult']]],
+ ['headerdata_2',['headerData',['../classDbcTreeModel.html#aad5834e8edb00808cbfa498ea8c63fe9',1,'DbcTreeModel']]]
];
diff --git a/docs/html/search/functions_7.js b/docs/html/search/functions_7.js
index 576a822..2626989 100644
--- a/docs/html/search/functions_7.js
+++ b/docs/html/search/functions_7.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['registertype_0',['registerType',['../classTypeFactory.html#ad6d85795285ee21193ac03e1b24762d3',1,'TypeFactory']]]
+ ['index_0',['index',['../classDbcTreeModel.html#a8caeb5ec6141eb3e446e48df3c70b3ad',1,'DbcTreeModel']]]
];
diff --git a/docs/html/search/functions_8.js b/docs/html/search/functions_8.js
index a2d0239..42f1eaa 100644
--- a/docs/html/search/functions_8.js
+++ b/docs/html/search/functions_8.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['treenode_0',['treenode',['../classTreeNode.html#a984a98d5ccf7ef1f5a18094c6821f35d',1,'TreeNode::TreeNode()'],['../classTreeNode.html#a8e38dd591d8801d7ee3a7dbad90c67fc',1,'TreeNode::TreeNode(const FrameInfo &frame)'],['../classTreeNode.html#ab9f00f5253d56461bb2d420fd639c5ae',1,'TreeNode::TreeNode(const SignalInfo &signal)']]]
+ ['main_0',['main',['../examples_2main_8cpp.html#a0ddf1224851353fc92bfbff6f499fa97',1,'main.cpp']]]
];
diff --git a/docs/html/search/functions_9.js b/docs/html/search/functions_9.js
new file mode 100644
index 0000000..e11e408
--- /dev/null
+++ b/docs/html/search/functions_9.js
@@ -0,0 +1,5 @@
+var searchData=
+[
+ ['operator_28_29_0',['operator()',['../structFrameKeyHasher.html#a1612ce56b513790e3ed4c06ec7d28b9f',1,'FrameKeyHasher::operator()()'],['../structSignalKeyHasher.html#af8869bcb714857af7ad005fbd13bea80',1,'SignalKeyHasher::operator()()']]],
+ ['operator_3d_3d_1',['operator==',['../structFrameKey.html#aaaec9f914e127787247fcda5e183b01f',1,'FrameKey::operator==()'],['../structSignalKey.html#a17525dc0116be7f4f58f3c3fae1022e2',1,'SignalKey::operator==()']]]
+];
diff --git a/docs/html/search/functions_a.js b/docs/html/search/functions_a.js
new file mode 100644
index 0000000..594cc9b
--- /dev/null
+++ b/docs/html/search/functions_a.js
@@ -0,0 +1,6 @@
+var searchData=
+[
+ ['parent_0',['parent',['../classDbcTreeModel.html#ae40bb8b8a26d205f178c6dd1134ff4b3',1,'DbcTreeModel']]],
+ ['parsefile_1',['ParseFile',['../classDbcParser.html#aef72826942c9095d653fafa435855e56',1,'DbcParser']]],
+ ['parsefilewithdiagnostics_2',['ParseFileWithDiagnostics',['../classDbcParser.html#a0e915ce79c2e3d4c95a5aaf2bf0409bc',1,'DbcParser']]]
+];
diff --git a/docs/html/search/functions_b.js b/docs/html/search/functions_b.js
new file mode 100644
index 0000000..be5983e
--- /dev/null
+++ b/docs/html/search/functions_b.js
@@ -0,0 +1,8 @@
+var searchData=
+[
+ ['registertype_0',['registertype',['../classTypeFactory.html#ad6d85795285ee21193ac03e1b24762d3',1,'TypeFactory::registerType()'],['../classDbcStatementDispatcher.html#a2c6e9a614ed747275d43bcccc50d0b2d',1,'DbcStatementDispatcher::RegisterType()']]],
+ ['resolveattributes_1',['ResolveAttributes',['../structDbcParseContext.html#a1ac7f4a54550aaddef08749806f87001',1,'DbcParseContext']]],
+ ['resolvecomments_2',['ResolveComments',['../structDbcParseContext.html#aeae343c57a244634489a0e0b960155d7',1,'DbcParseContext']]],
+ ['resolvevaluedescriptions_3',['ResolveValueDescriptions',['../structDbcParseContext.html#ab5552dad944fde7fa6add6464ddb5369',1,'DbcParseContext']]],
+ ['rowcount_4',['rowCount',['../classDbcTreeModel.html#a30bed0d65342917c19d9183da55af452',1,'DbcTreeModel']]]
+];
diff --git a/docs/html/search/functions_c.js b/docs/html/search/functions_c.js
new file mode 100644
index 0000000..ca501f6
--- /dev/null
+++ b/docs/html/search/functions_c.js
@@ -0,0 +1,5 @@
+var searchData=
+[
+ ['settree_0',['SetTree',['../classDbcTreeModel.html#a8cb5a81d456cdead42b75fd3462ee00a',1,'DbcTreeModel']]],
+ ['signalkey_1',['SignalKey',['../structSignalKey.html#aa4221b34e75469bf5aa939976c334f46',1,'SignalKey']]]
+];
diff --git a/docs/html/search/functions_d.js b/docs/html/search/functions_d.js
new file mode 100644
index 0000000..a2d0239
--- /dev/null
+++ b/docs/html/search/functions_d.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['treenode_0',['treenode',['../classTreeNode.html#a984a98d5ccf7ef1f5a18094c6821f35d',1,'TreeNode::TreeNode()'],['../classTreeNode.html#a8e38dd591d8801d7ee3a7dbad90c67fc',1,'TreeNode::TreeNode(const FrameInfo &frame)'],['../classTreeNode.html#ab9f00f5253d56461bb2d420fd639c5ae',1,'TreeNode::TreeNode(const SignalInfo &signal)']]]
+];
diff --git a/docs/html/search/functions_e.js b/docs/html/search/functions_e.js
new file mode 100644
index 0000000..10a6e0d
--- /dev/null
+++ b/docs/html/search/functions_e.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['validatemultiplexing_0',['ValidateMultiplexing',['../structDbcParseContext.html#a908056de0a97316a4ebecb3f99cc400b',1,'DbcParseContext']]]
+];
diff --git a/docs/html/search/pages_8.js b/docs/html/search/pages_8.js
new file mode 100644
index 0000000..6bb5e38
--- /dev/null
+++ b/docs/html/search/pages_8.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['для_20работы_20с_20проектом_0',['Инструкции для работы с проектом',['../md_AGENTS.html',1,'']]]
+];
diff --git a/docs/html/search/pages_9.js b/docs/html/search/pages_9.js
new file mode 100644
index 0000000..135e5d7
--- /dev/null
+++ b/docs/html/search/pages_9.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['инструкции_20для_20работы_20с_20проектом_0',['Инструкции для работы с проектом',['../md_AGENTS.html',1,'']]]
+];
diff --git a/docs/html/search/pages_a.js b/docs/html/search/pages_a.js
new file mode 100644
index 0000000..9370f90
--- /dev/null
+++ b/docs/html/search/pages_a.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['проектом_0',['Инструкции для работы с проектом',['../md_AGENTS.html',1,'']]]
+];
diff --git a/docs/html/search/pages_b.js b/docs/html/search/pages_b.js
new file mode 100644
index 0000000..95e1996
--- /dev/null
+++ b/docs/html/search/pages_b.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['работы_20с_20проектом_0',['Инструкции для работы с проектом',['../md_AGENTS.html',1,'']]]
+];
diff --git a/docs/html/search/pages_c.js b/docs/html/search/pages_c.js
new file mode 100644
index 0000000..3da798f
--- /dev/null
+++ b/docs/html/search/pages_c.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['с_20проектом_0',['Инструкции для работы с проектом',['../md_AGENTS.html',1,'']]]
+];
diff --git a/docs/html/search/searchdata.js b/docs/html/search/searchdata.js
index 72d1a64..80faa6b 100644
--- a/docs/html/search/searchdata.js
+++ b/docs/html/search/searchdata.js
@@ -1,12 +1,13 @@
var indexSectionsWithContent =
{
- 0: "01234abcdefghiklmnopqrstuvw—",
- 1: "dfmprst",
+ 0: "01234abcdefghijklmnopqrstuvwдзикопрстф—",
+ 1: "adfmprst",
2: "defst",
- 3: "abcdfgprt",
- 4: "bcdfhiklmnoprstuv",
- 5: "bfnv",
- 6: "acdmpqrt"
+ 3: "abcdfghimoprstv",
+ 4: "abcdefhiklmnoprstuv",
+ 5: "bc",
+ 6: "bcfnrsv",
+ 7: "acdmpqrtдипрс"
};
var indexSectionNames =
@@ -16,8 +17,9 @@ var indexSectionNames =
2: "files",
3: "functions",
4: "variables",
- 5: "enums",
- 6: "pages"
+ 5: "typedefs",
+ 6: "enums",
+ 7: "pages"
};
var indexSectionLabels =
@@ -27,7 +29,8 @@ var indexSectionLabels =
2: "Files",
3: "Functions",
4: "Variables",
- 5: "Enumerations",
- 6: "Pages"
+ 5: "Typedefs",
+ 6: "Enumerations",
+ 7: "Pages"
};
diff --git a/docs/html/search/typedefs_0.js b/docs/html/search/typedefs_0.js
new file mode 100644
index 0000000..12b936c
--- /dev/null
+++ b/docs/html/search/typedefs_0.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['baseptr_0',['BasePtr',['../classTypeFactory.html#a33b404da3e19ea7e1245b8a4975721bf',1,'TypeFactory']]]
+];
diff --git a/docs/html/search/typedefs_1.js b/docs/html/search/typedefs_1.js
new file mode 100644
index 0000000..d628bb3
--- /dev/null
+++ b/docs/html/search/typedefs_1.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['creatorfn_0',['CreatorFn',['../classTypeFactory.html#a650022aac1e2f30af5bc554a5663939f',1,'TypeFactory']]]
+];
diff --git a/docs/html/search/variables_0.js b/docs/html/search/variables_0.js
index b7fd3e2..768d2bc 100644
--- a/docs/html/search/variables_0.js
+++ b/docs/html/search/variables_0.js
@@ -1,4 +1,7 @@
var searchData=
[
- ['byteorder_0',['byteOrder',['../structDecodeSignal.html#abdc4c4bb4a67a6d61d6ca81e8a52833d',1,'DecodeSignal']]]
+ ['ambiguous_0',['ambiguous',['../structPgnLookupResult.html#a6158833782348b3cc26037c2091fcc36',1,'PgnLookupResult']]],
+ ['attributeassignments_1',['attributeAssignments',['../structDbcDatabase.html#aa7bdf56eb8b7ab5b873e1c096b46d8b6',1,'DbcDatabase']]],
+ ['attributedefinitions_2',['attributeDefinitions',['../structDbcDatabase.html#a14862245081989f2abf126b5ea6dfdfa',1,'DbcDatabase']]],
+ ['attributes_3',['attributes',['../structDbcDatabase.html#a321839ad81af176444358eb23114eaee',1,'DbcDatabase::attributes'],['../structDecodeSignal.html#a204f65c7ea45a2c148f19c12d922f99b',1,'DecodeSignal::attributes'],['../structDecodeFrame.html#ad506b03108a40df7e8005638c9c59653',1,'DecodeFrame::attributes'],['../structFrameInfo.html#a9ef2736053b593cf34ba2608cf8275c0',1,'FrameInfo::attributes'],['../structSignalInfo.html#a781766eddbf6641071623c8e5b9acb4a',1,'SignalInfo::attributes']]]
];
diff --git a/docs/html/search/variables_1.js b/docs/html/search/variables_1.js
index 855c3ef..b7fd3e2 100644
--- a/docs/html/search/variables_1.js
+++ b/docs/html/search/variables_1.js
@@ -1,5 +1,4 @@
var searchData=
[
- ['canid_0',['canid',['../structRawCanFrame.html#a2d0e7fa0e3d5c20bbed55ed8f7888ff4',1,'RawCanFrame::canId'],['../structDecodeFrame.html#a52e10215388db7df8b541b9d9909edcf',1,'DecodeFrame::canId'],['../structFrameInfo.html#af470b0742c05bfbffc31c51a68f5c05e',1,'FrameInfo::canId']]],
- ['comment_1',['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']]]
+ ['byteorder_0',['byteOrder',['../structDecodeSignal.html#abdc4c4bb4a67a6d61d6ca81e8a52833d',1,'DecodeSignal']]]
];
diff --git a/docs/html/search/variables_10.js b/docs/html/search/variables_10.js
index d699763..1ea9419 100644
--- a/docs/html/search/variables_10.js
+++ b/docs/html/search/variables_10.js
@@ -1,6 +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']]]
+ ['targetname_0',['targetName',['../structAttributeAssignment.html#a50059e42e5e5b944050f3290ce84ac66',1,'AttributeAssignment']]],
+ ['transmitter_1',['transmitter',['../structDecodeFrame.html#ad78241dc40c793aabb8495b6989b81a9',1,'DecodeFrame::transmitter'],['../structFrameInfo.html#a92749ec3798d4211a505860fb389a9e8',1,'FrameInfo::transmitter']]],
+ ['type_2',['type',['../structAttributeDefinition.html#a5de5484174a8c5f6b309041089d20afc',1,'AttributeDefinition']]]
];
diff --git a/docs/html/search/variables_11.js b/docs/html/search/variables_11.js
new file mode 100644
index 0000000..7a9aea0
--- /dev/null
+++ b/docs/html/search/variables_11.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['unit_0',['unit',['../structDecodeSignal.html#a38eed9ca7581423fd8bfbedcffc12092',1,'DecodeSignal::unit'],['../structSignalInfo.html#a1f214f03e94ef5794de2d3367bfcbd01',1,'SignalInfo::unit']]]
+];
diff --git a/docs/html/search/variables_12.js b/docs/html/search/variables_12.js
new file mode 100644
index 0000000..9ba44c4
--- /dev/null
+++ b/docs/html/search/variables_12.js
@@ -0,0 +1,7 @@
+var searchData=
+[
+ ['valid_0',['valid',['../structDecodedSignalValue.html#aac0ed361af545cde48d0e6f41a859686',1,'DecodedSignalValue::valid'],['../structDecodedFrameValue.html#a4f51c31110dba1f73a763c596372beb0',1,'DecodedFrameValue::valid']]],
+ ['value_1',['value',['../structAttributeAssignment.html#a93de8c51c5154219bf18beadcec5708f',1,'AttributeAssignment::value'],['../structMultiplexing.html#a79158d4fdbfd68a3d51a8ce79d34fd67',1,'Multiplexing::value']]],
+ ['valuedescriptions_2',['valuedescriptions',['../structDecodeSignal.html#a822155d9bf4ed5f3300c9e9befe606ff',1,'DecodeSignal::valueDescriptions'],['../structSignalInfo.html#a43f47d0433d0cc39076bd7278b46af9c',1,'SignalInfo::valueDescriptions']]],
+ ['valuetype_3',['valueType',['../structDecodeSignal.html#a9d37638129263b8902ba5be59baf39a8',1,'DecodeSignal']]]
+];
diff --git a/docs/html/search/variables_2.js b/docs/html/search/variables_2.js
index 0c18c8f..37e7164 100644
--- a/docs/html/search/variables_2.js
+++ b/docs/html/search/variables_2.js
@@ -1,6 +1,9 @@
var searchData=
[
- ['data_0',['data',['../structRawCanFrame.html#a0acb487612104c99c9907344c035df83',1,'RawCanFrame']]],
- ['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']]]
+ ['canid_0',['canid',['../structRawCanFrame.html#a2d0e7fa0e3d5c20bbed55ed8f7888ff4',1,'RawCanFrame::canId'],['../structPendingValueDescriptions.html#a5f0082ceeaee77e2f823661547aad844',1,'PendingValueDescriptions::canId'],['../structPendingComment.html#a6d1c3b1e149bb602a95224446709c771',1,'PendingComment::canId'],['../structDecodeFrame.html#a52e10215388db7df8b541b9d9909edcf',1,'DecodeFrame::canId'],['../structFrameKey.html#a022917652b4d3c2f2dfcc5a13ab7caa4',1,'FrameKey::canId'],['../structFrameInfo.html#af470b0742c05bfbffc31c51a68f5c05e',1,'FrameInfo::canId'],['../structAttributeAssignment.html#a330ae1a34c342b0352115a83dd31aab8',1,'AttributeAssignment::canId']]],
+ ['classes_1',['classes',['../classTypeFactory.html#a5f119fe61c1cb9f4725ce746e4a047b3',1,'TypeFactory']]],
+ ['code_2',['code',['../structDbcDiagnostic.html#aa315a4a40b15f2e8cb34264d94a0f914',1,'DbcDiagnostic']]],
+ ['comment_3',['comment',['../structPendingComment.html#aa344393f67770e12449a4f14f6fcf10b',1,'PendingComment::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']]],
+ ['currentframe_4',['currentFrame',['../structDbcParseContext.html#af31b56247edff7f025957ae023a56913',1,'DbcParseContext']]],
+ ['cycletimems_5',['cycletimems',['../structDecodeFrame.html#a732c2f6853d55ce8253db61207fc21d3',1,'DecodeFrame::cycleTimeMs'],['../structFrameInfo.html#a099f02a77adfb9ac23e286ce75f4eef4',1,'FrameInfo::cycleTimeMs']]]
];
diff --git a/docs/html/search/variables_3.js b/docs/html/search/variables_3.js
index e5bede5..cfea131 100644
--- a/docs/html/search/variables_3.js
+++ b/docs/html/search/variables_3.js
@@ -1,5 +1,11 @@
var searchData=
[
- ['factor_0',['factor',['../structDecodeSignal.html#a428c39913a366a8476dd291061354391',1,'DecodeSignal::factor'],['../structSignalInfo.html#ae4f78d99a2750aa564d7eba860171499',1,'SignalInfo::factor']]],
- ['frames_1',['frames',['../structDbcDatabase.html#a2cade5d0234ee816132127542f8c612b',1,'DbcDatabase']]]
+ ['data_0',['data',['../structRawCanFrame.html#a0acb487612104c99c9907344c035df83',1,'RawCanFrame']]],
+ ['database_1',['database',['../structDbcParseResult.html#abfa765d29a4397e8ddaf771bae21993e',1,'DbcParseResult::database'],['../structDbcParseContext.html#a79bad0b8302e2156670461bab529259c',1,'DbcParseContext::database']]],
+ ['defaultvalue_2',['defaultValue',['../structAttributeDefinition.html#ae0949edf67f9d4e60e4cb376a95da4f2',1,'AttributeDefinition']]],
+ ['definition_3',['definition',['../structDecodedSignalValue.html#a828b5ef7faefc14fbf5dbd46249bcad2',1,'DecodedSignalValue::definition'],['../structDecodedFrameValue.html#a33e971ba10030506007aa201c89f351d',1,'DecodedFrameValue::definition'],['../structPgnLookupResult.html#aa5b79b61d2aef48fd6ae070cf5f901c1',1,'PgnLookupResult::definition']]],
+ ['descriptions_4',['descriptions',['../structPendingValueDescriptions.html#a10ecbaeaed2cc3ac82fada73e7e041dd',1,'PendingValueDescriptions']]],
+ ['diagnostic_5',['diagnostic',['../classDbcDiagnosticError.html#ab3965082f01d66b6d5c20525af44235d',1,'DbcDiagnosticError']]],
+ ['diagnostics_6',['diagnostics',['../structDbcParseResult.html#a3a1987b4381bb1e0a34dc09e31483679',1,'DbcParseResult']]],
+ ['dlc_7',['dlc',['../structDecodeFrame.html#a51111ac13988be372d5673d12cf3e060',1,'DecodeFrame::dlc'],['../structFrameInfo.html#aa2b198ea0f55e560c123d35e7b3ecab9',1,'FrameInfo::dlc']]]
];
diff --git a/docs/html/search/variables_4.js b/docs/html/search/variables_4.js
index 2c8ae39..356a2b1 100644
--- a/docs/html/search/variables_4.js
+++ b/docs/html/search/variables_4.js
@@ -1,4 +1,5 @@
var searchData=
[
- ['haspgn_0',['haspgn',['../structDecodeFrame.html#a2551102670c4a540fced4c71da0b369d',1,'DecodeFrame::hasPgn'],['../structFrameInfo.html#a4737a5420213ad4304724e39f3a4e55d',1,'FrameInfo::hasPgn']]]
+ ['enablej1939_0',['enablej1939',['../structDbcParserOptions.html#ab31534f5c0853461b46cbb38149c33f9',1,'DbcParserOptions::enableJ1939'],['../structDbcParseContext.html#a93f8ece0f3d16bd79f631ae07afa7b54',1,'DbcParseContext::enableJ1939']]],
+ ['enumvalues_1',['enumValues',['../structAttributeDefinition.html#a547fe17f6cfc631528f9156e4a509c66',1,'AttributeDefinition']]]
];
diff --git a/docs/html/search/variables_5.js b/docs/html/search/variables_5.js
index 350f52f..838b2d5 100644
--- a/docs/html/search/variables_5.js
+++ b/docs/html/search/variables_5.js
@@ -1,6 +1,8 @@
var searchData=
[
- ['isextended_0',['isextended',['../structRawCanFrame.html#a462193d275adc1dba8bd18ffa0e36bb7',1,'RawCanFrame::isExtended'],['../structDecodeFrame.html#a3ee2348d781f8f15aaf87e8dcf57ec41',1,'DecodeFrame::isExtended'],['../structFrameInfo.html#a34b726afaad2ac5c697fdb2ac070cdaf',1,'FrameInfo::isExtended']]],
- ['islittleendian_1',['isLittleEndian',['../structSignalInfo.html#af363b1563fb4c7cc8973f9a80c06846c',1,'SignalInfo']]],
- ['issigned_2',['isSigned',['../structSignalInfo.html#a52a52b320eef92fbcb4626307f9a498f',1,'SignalInfo']]]
+ ['factor_0',['factor',['../structDecodeSignal.html#a428c39913a366a8476dd291061354391',1,'DecodeSignal::factor'],['../structSignalInfo.html#ae4f78d99a2750aa564d7eba860171499',1,'SignalInfo::factor']]],
+ ['filepath_1',['filePath',['../structDbcDiagnostic.html#ac9f02705ed6a633cbb9526d0e392fb95',1,'DbcDiagnostic']]],
+ ['frame_2',['frame',['../structSignalKey.html#a25f4ece1bf685791b576f68e23d8ccc7',1,'SignalKey']]],
+ ['frameformat_3',['frameformat',['../structDecodeFrame.html#a475e669f390491a4d99383d3fee51300',1,'DecodeFrame::frameFormat'],['../structFrameInfo.html#a35bf839519ef3f48b5f52dd9bcd7e9ac',1,'FrameInfo::frameFormat']]],
+ ['frames_4',['frames',['../structDbcDatabase.html#a2cade5d0234ee816132127542f8c612b',1,'DbcDatabase']]]
];
diff --git a/docs/html/search/variables_6.js b/docs/html/search/variables_6.js
index 199fcb0..2c8ae39 100644
--- a/docs/html/search/variables_6.js
+++ b/docs/html/search/variables_6.js
@@ -1,4 +1,4 @@
var searchData=
[
- ['key_0',['key',['../structDecodedSignalValue.html#a33df0fcd92b23b3e08539906fc6b4c4a',1,'DecodedSignalValue::key'],['../structDecodedFrameValue.html#a32143efe2023a1ecd977a9ae93e50b73',1,'DecodedFrameValue::key']]]
+ ['haspgn_0',['haspgn',['../structDecodeFrame.html#a2551102670c4a540fced4c71da0b369d',1,'DecodeFrame::hasPgn'],['../structFrameInfo.html#a4737a5420213ad4304724e39f3a4e55d',1,'FrameInfo::hasPgn']]]
];
diff --git a/docs/html/search/variables_7.js b/docs/html/search/variables_7.js
index 52fc426..7b6b348 100644
--- a/docs/html/search/variables_7.js
+++ b/docs/html/search/variables_7.js
@@ -1,4 +1,9 @@
var searchData=
[
- ['length_0',['length',['../structDecodeSignal.html#acd4ef5ee30421d117b5756854302debb',1,'DecodeSignal::length'],['../structSignalInfo.html#a1008b5201f71848177217bd52fb84baa',1,'SignalInfo::length']]]
+ ['integermaximum_0',['integerMaximum',['../structAttributeDefinition.html#a5ca8f41ea3e921f54d81b8760c1dcfb3',1,'AttributeDefinition']]],
+ ['integerminimum_1',['integerMinimum',['../structAttributeDefinition.html#aaf87153bac0b228ad87b88e96f303210',1,'AttributeDefinition']]],
+ ['isextended_2',['isextended',['../structAttributeAssignment.html#a024a249cc63dbfbf337eea395fe3471e',1,'AttributeAssignment::isExtended'],['../structRawCanFrame.html#a462193d275adc1dba8bd18ffa0e36bb7',1,'RawCanFrame::isExtended'],['../structPendingValueDescriptions.html#a60f185e8d91010927c4aa3b4a750c9f4',1,'PendingValueDescriptions::isExtended'],['../structPendingComment.html#a9abd7e15ed59eb4534c66ff74f276e07',1,'PendingComment::isExtended'],['../structDecodeFrame.html#a3ee2348d781f8f15aaf87e8dcf57ec41',1,'DecodeFrame::isExtended'],['../structFrameKey.html#aa3179b709d02ef70cf0e736f040a2145',1,'FrameKey::isExtended'],['../structFrameInfo.html#a34b726afaad2ac5c697fdb2ac070cdaf',1,'FrameInfo::isExtended']]],
+ ['islittleendian_3',['isLittleEndian',['../structSignalInfo.html#af363b1563fb4c7cc8973f9a80c06846c',1,'SignalInfo']]],
+ ['issignal_4',['isSignal',['../structPendingComment.html#ac03903ffb042d27ad66012eb18ea1437',1,'PendingComment']]],
+ ['issigned_5',['isSigned',['../structSignalInfo.html#a52a52b320eef92fbcb4626307f9a498f',1,'SignalInfo']]]
];
diff --git a/docs/html/search/variables_8.js b/docs/html/search/variables_8.js
index 8c626f1..199fcb0 100644
--- a/docs/html/search/variables_8.js
+++ b/docs/html/search/variables_8.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']]]
+ ['key_0',['key',['../structDecodedSignalValue.html#a33df0fcd92b23b3e08539906fc6b4c4a',1,'DecodedSignalValue::key'],['../structDecodedFrameValue.html#a32143efe2023a1ecd977a9ae93e50b73',1,'DecodedFrameValue::key']]]
];
diff --git a/docs/html/search/variables_9.js b/docs/html/search/variables_9.js
index 16390c6..88a8152 100644
--- a/docs/html/search/variables_9.js
+++ b/docs/html/search/variables_9.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']]]
+ ['length_0',['length',['../structDecodeSignal.html#acd4ef5ee30421d117b5756854302debb',1,'DecodeSignal::length'],['../structSignalInfo.html#a1008b5201f71848177217bd52fb84baa',1,'SignalInfo::length']]],
+ ['linenumber_1',['linenumber',['../structDbcDiagnostic.html#adb201de8d32b768d5f559bed21e8f819',1,'DbcDiagnostic::lineNumber'],['../structPendingValueDescriptions.html#a5c19cff09b0e83bd3cd6085213c17da8',1,'PendingValueDescriptions::lineNumber'],['../structPendingComment.html#a29a3733e0a4c8ae341695db3d21d9249',1,'PendingComment::lineNumber'],['../structPendingAttribute.html#a9a68a0a54c313c3e43dfdcd6e7a55da9',1,'PendingAttribute::lineNumber'],['../structDbcParseContext.html#a57f5a7f613ecd0dadbafa7af736b7e54',1,'DbcParseContext::lineNumber']]]
];
diff --git a/docs/html/search/variables_a.js b/docs/html/search/variables_a.js
index ee45616..b661498 100644
--- a/docs/html/search/variables_a.js
+++ b/docs/html/search/variables_a.js
@@ -1,4 +1,7 @@
var searchData=
[
- ['offset_0',['offset',['../structDecodeSignal.html#a92db637af4e224a0ae70173050dc3f74',1,'DecodeSignal::offset'],['../structSignalInfo.html#ab7d0769f47aa540656b22e4e49db517e',1,'SignalInfo::offset']]]
+ ['maximum_0',['maximum',['../structAttributeDefinition.html#aa02fe74b5420c2e67c13e610b6bc9713',1,'AttributeDefinition::maximum'],['../structDecodeSignal.html#a4a6ba87142a9badbf0ca830e9e709cb7',1,'DecodeSignal::maximum'],['../structSignalInfo.html#adf1c4331b9eabced0d7fdda40ff0eb52',1,'SignalInfo::maximum']]],
+ ['message_1',['message',['../structDbcDiagnostic.html#a124bae82eebeaef46426bd124685ef1b',1,'DbcDiagnostic']]],
+ ['minimum_2',['minimum',['../structAttributeDefinition.html#a18245dba995929a61fd6de1fcdbc8a89',1,'AttributeDefinition::minimum'],['../structDecodeSignal.html#a0fb84e19a0ab3bd50b6f65c1075ebc25',1,'DecodeSignal::minimum'],['../structSignalInfo.html#ada7bf94fbeaa26bd08c73982b5af255b',1,'SignalInfo::minimum']]],
+ ['multiplexing_3',['multiplexing',['../structDecodeSignal.html#aea41c055cb255fe7bd178ed5727f28c9',1,'DecodeSignal::multiplexing'],['../structSignalInfo.html#a8a2e29f307c75926a1bd824266d23ca8',1,'SignalInfo::multiplexing']]]
];
diff --git a/docs/html/search/variables_b.js b/docs/html/search/variables_b.js
index bf8a391..06cb3fa 100644
--- a/docs/html/search/variables_b.js
+++ b/docs/html/search/variables_b.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']]]
+ ['name_0',['name',['../structAttributeAssignment.html#aa8707eddd2d3a2de559fe44354a514cc',1,'AttributeAssignment::name'],['../structDecodeSignal.html#a58cf5844f2272a23dcb9687d912e4780',1,'DecodeSignal::name'],['../structDecodeFrame.html#aa0a7f8fd5bfde2148dfd0d838328f579',1,'DecodeFrame::name'],['../structSignalKey.html#abab371cce740f05111fd3b4013ca6944',1,'SignalKey::name'],['../structFrameInfo.html#abb53a7f93ed7abc0ea1ae4a8ccafcdcb',1,'FrameInfo::name'],['../structSignalInfo.html#a379e422a00cad56f896cacf60455b088',1,'SignalInfo::name']]]
];
diff --git a/docs/html/search/variables_c.js b/docs/html/search/variables_c.js
index 52b5519..ee45616 100644
--- a/docs/html/search/variables_c.js
+++ b/docs/html/search/variables_c.js
@@ -1,5 +1,4 @@
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']]]
+ ['offset_0',['offset',['../structDecodeSignal.html#a92db637af4e224a0ae70173050dc3f74',1,'DecodeSignal::offset'],['../structSignalInfo.html#ab7d0769f47aa540656b22e4e49db517e',1,'SignalInfo::offset']]]
];
diff --git a/docs/html/search/variables_d.js b/docs/html/search/variables_d.js
index 2e397eb..75be524 100644
--- a/docs/html/search/variables_d.js
+++ b/docs/html/search/variables_d.js
@@ -1,5 +1,9 @@
var searchData=
[
- ['startbit_0',['startbit',['../structDecodeSignal.html#aaf5d7527ddf65b6355c2b4f3626df22d',1,'DecodeSignal::startBit'],['../structSignalInfo.html#ace290724f9801521609aedaa946d61f1',1,'SignalInfo::startBit']]],
- ['status_1',['status',['../structDecodedFrameValue.html#a645f433798d48a2787e7f00dfbb7dff9',1,'DecodedFrameValue']]]
+ ['pendingattributes_0',['pendingAttributes',['../structDbcParseContext.html#afbfa4b26a58b41ada3dabc619066035c',1,'DbcParseContext']]],
+ ['pendingcomments_1',['pendingComments',['../structDbcParseContext.html#a854abba7bbf4adfc948554c254156e60',1,'DbcParseContext']]],
+ ['pendingvalues_2',['pendingValues',['../structDbcParseContext.html#ac22cba614ada3a28c7dcc1ea338b0e01',1,'DbcParseContext']]],
+ ['pgn_3',['pgn',['../structDecodeFrame.html#a1d3c54055c0cbceb73adf551f7067f23',1,'DecodeFrame::pgn'],['../structFrameInfo.html#aee518b33f1000bf0b7f6e4a87474c943',1,'FrameInfo::pgn']]],
+ ['physicalvalue_4',['physicalValue',['../structDecodedSignalValue.html#a6847d05b3cb00d5e0f6c611968f57978',1,'DecodedSignalValue']]],
+ ['public_5',['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_e.js b/docs/html/search/variables_e.js
index 3733358..90d9513 100644
--- a/docs/html/search/variables_e.js
+++ b/docs/html/search/variables_e.js
@@ -1,4 +1,6 @@
var searchData=
[
- ['transmitter_0',['transmitter',['../structDecodeFrame.html#ad78241dc40c793aabb8495b6989b81a9',1,'DecodeFrame::transmitter'],['../structFrameInfo.html#a92749ec3798d4211a505860fb389a9e8',1,'FrameInfo::transmitter']]]
+ ['rawvalue_0',['rawValue',['../structDecodedSignalValue.html#a503c90b4b1a610b8252c45e466367c28',1,'DecodedSignalValue']]],
+ ['receivers_1',['receivers',['../structDecodeSignal.html#abdbae62a64d2df716bf60c6b67b30eaa',1,'DecodeSignal::receivers'],['../structSignalInfo.html#a2c95562fd0b29327a7fd7b1e6feee7f3',1,'SignalInfo::receivers']]],
+ ['role_2',['role',['../structMultiplexing.html#a62b70a0e3f2a9c7a457b3694ce8625c3',1,'Multiplexing']]]
];
diff --git a/docs/html/search/variables_f.js b/docs/html/search/variables_f.js
index 7a9aea0..f2ede46 100644
--- a/docs/html/search/variables_f.js
+++ b/docs/html/search/variables_f.js
@@ -1,4 +1,10 @@
var searchData=
[
- ['unit_0',['unit',['../structDecodeSignal.html#a38eed9ca7581423fd8bfbedcffc12092',1,'DecodeSignal::unit'],['../structSignalInfo.html#a1f214f03e94ef5794de2d3367bfcbd01',1,'SignalInfo::unit']]]
+ ['scope_0',['scope',['../structAttributeDefinition.html#a5f109f0ec94eb04c3f52c116366aefdf',1,'AttributeDefinition::scope'],['../structAttributeAssignment.html#a50405e8db9e4536015f9adc5ba360270',1,'AttributeAssignment::scope']]],
+ ['severity_1',['severity',['../structDbcDiagnostic.html#a75040a94f0313a606478020b0491f81d',1,'DbcDiagnostic']]],
+ ['signallines_2',['signalLines',['../structDbcParseContext.html#af8b411c938a2ea9100c4aaae452e6546',1,'DbcParseContext']]],
+ ['signalname_3',['signalname',['../structPendingValueDescriptions.html#ac35446db10ebda5a12349759613f8c90',1,'PendingValueDescriptions::signalName'],['../structPendingComment.html#ae7b5aea9c252a4ab87e02915d24fee27',1,'PendingComment::signalName']]],
+ ['startbit_4',['startbit',['../structDecodeSignal.html#aaf5d7527ddf65b6355c2b4f3626df22d',1,'DecodeSignal::startBit'],['../structSignalInfo.html#ace290724f9801521609aedaa946d61f1',1,'SignalInfo::startBit']]],
+ ['statement_5',['statement',['../structPendingAttribute.html#a0ec62fc577e3a2d5f63d926f829e2ab8',1,'PendingAttribute']]],
+ ['status_6',['status',['../structDecodedSignalValue.html#a94161a80412b3961da8fd2fec43c25f6',1,'DecodedSignalValue::status'],['../structDecodedFrameValue.html#a645f433798d48a2787e7f00dfbb7dff9',1,'DecodedFrameValue::status']]]
];
diff --git a/docs/html/signal__info_8h.html b/docs/html/signal__info_8h.html
index 539a0b0..2132cb2 100644
--- a/docs/html/signal__info_8h.html
+++ b/docs/html/signal__info_8h.html
@@ -96,10 +96,11 @@ $(document).ready(function(){initNavTree('signal__info_8h.html',''); initResizab
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Parsed CAN signal metadata.
More...
-
#include "value_descriptions.h"
+
#include "attributes.h"
#include "multiplexing.h"
+#include "value_descriptions.h"
#include <cstdint>
#include <string>
#include <vector>
@@ -113,7 +114,8 @@ Classes
-Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Parsed CAN signal metadata.
+
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Licensed under the MIT License. See LICENSE file in the project root for full license text.
Definition in file signal_info.h .
diff --git a/docs/html/signal__info_8h_source.html b/docs/html/signal__info_8h_source.html
index be85141..63647fc 100644
--- a/docs/html/signal__info_8h_source.html
+++ b/docs/html/signal__info_8h_source.html
@@ -102,48 +102,52 @@ $(document).ready(function(){initNavTree('signal__info_8h_source.html',''); init
-
15 #include "value_descriptions.h"
+
15 #include "attributes.h"
16 #include "multiplexing.h"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
17 #include "value_descriptions.h"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
Describes one signal inside a DBC frame.
-
-
-
std::vector< std::string > receivers
-
-
ValueDescriptions valueDescriptions
-
-
-
-
-
-
-
-
+
+
+
+
Describes one signal inside a DBC frame.
+
+
+
std::vector< std::string > receivers
+
+
ValueDescriptions valueDescriptions
+
+
+
Multiplexing multiplexing
+
+
+
+
+
+
+
diff --git a/docs/html/structAttributeAssignment-members.html b/docs/html/structAttributeAssignment-members.html
new file mode 100644
index 0000000..41cf19d
--- /dev/null
+++ b/docs/html/structAttributeAssignment-members.html
@@ -0,0 +1,114 @@
+
+
+
+
+
+
+
+DBC Framework: Member List
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DBC Framework
+
+ DBC parsing and CAN signal decoding framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+
+
+
+
+
This is the complete list of members for AttributeAssignment , including all inherited members.
+
+
+
+
+
+
diff --git a/docs/html/structAttributeAssignment.html b/docs/html/structAttributeAssignment.html
new file mode 100644
index 0000000..3b8f173
--- /dev/null
+++ b/docs/html/structAttributeAssignment.html
@@ -0,0 +1,253 @@
+
+
+
+
+
+
+
+DBC Framework: AttributeAssignment Struct Reference
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DBC Framework
+
+ DBC parsing and CAN signal decoding framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+
+
+
+
+
Explicit assignment; defaults remain on definitions.
+ More...
+
+
#include <attributes.h >
+
+
+
Explicit assignment; defaults remain on definitions.
+
Named nodes/environment variables are retained without validating declarations, which are not parsed.
+
+
Definition at line 59 of file attributes.h .
+
+
+
◆ name
+
+
+
+
+
+ std::string AttributeAssignment::name
+
+
+
+
+
+
◆ scope
+
+
+
+
+
+ AttributeScope AttributeAssignment::scope = AttributeScope::Database
+
+
+
+
+
+
◆ canId
+
+
+
+
+
+ std::uint32_t AttributeAssignment::canId = 0U
+
+
+
+
+
+
◆ isExtended
+
+
+
+
+
+ bool AttributeAssignment::isExtended = false
+
+
+
+
+
+
◆ targetName
+
+
+
+
+
+ std::string AttributeAssignment::targetName
+
+
+
+
+
+
◆ value
+
+
+
+
+
+ AttributeValue AttributeAssignment::value
+
+
+
+
+
The documentation for this struct was generated from the following file:
+
+
+
+
+
+
diff --git a/docs/html/structAttributeAssignment.js b/docs/html/structAttributeAssignment.js
new file mode 100644
index 0000000..28f4733
--- /dev/null
+++ b/docs/html/structAttributeAssignment.js
@@ -0,0 +1,9 @@
+var structAttributeAssignment =
+[
+ [ "name", "structAttributeAssignment.html#aa8707eddd2d3a2de559fe44354a514cc", null ],
+ [ "scope", "structAttributeAssignment.html#a50405e8db9e4536015f9adc5ba360270", null ],
+ [ "canId", "structAttributeAssignment.html#a330ae1a34c342b0352115a83dd31aab8", null ],
+ [ "isExtended", "structAttributeAssignment.html#a024a249cc63dbfbf337eea395fe3471e", null ],
+ [ "targetName", "structAttributeAssignment.html#a50059e42e5e5b944050f3290ce84ac66", null ],
+ [ "value", "structAttributeAssignment.html#a93de8c51c5154219bf18beadcec5708f", null ]
+];
\ No newline at end of file
diff --git a/docs/html/structAttributeDefinition-members.html b/docs/html/structAttributeDefinition-members.html
new file mode 100644
index 0000000..fe87c24
--- /dev/null
+++ b/docs/html/structAttributeDefinition-members.html
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+DBC Framework: Member List
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DBC Framework
+
+ DBC parsing and CAN signal decoding framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+
+
+
+
+
This is the complete list of members for AttributeDefinition , including all inherited members.
+
+
+
+
+
+
diff --git a/docs/html/structAttributeDefinition.html b/docs/html/structAttributeDefinition.html
new file mode 100644
index 0000000..13b6d44
--- /dev/null
+++ b/docs/html/structAttributeDefinition.html
@@ -0,0 +1,282 @@
+
+
+
+
+
+
+
+DBC Framework: AttributeDefinition Struct Reference
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DBC Framework
+
+ DBC parsing and CAN signal decoding framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+
+
+
+
+
Attribute type, permitted range, and optional default.
+ More...
+
+
#include <attributes.h >
+
+
+
Attribute type, permitted range, and optional default.
+
+
Definition at line 42 of file attributes.h .
+
+
+
◆ scope
+
+
+
+
+
+ AttributeScope AttributeDefinition::scope = AttributeScope::Database
+
+
+
+
+
+
◆ type
+
+
+
+
+
+ AttributeType AttributeDefinition::type = AttributeType::String
+
+
+
+
Type used to validate values.
+
+
Definition at line 44 of file attributes.h .
+
+
+
+
+
◆ integerMinimum
+
+
+
+
+
+ std::int64_t AttributeDefinition::integerMinimum = 0
+
+
+
+
Inclusive INT, HEX, or ENUM lower bound.
+
+
Definition at line 45 of file attributes.h .
+
+
+
+
+
◆ integerMaximum
+
+
+
+
+
+ std::int64_t AttributeDefinition::integerMaximum = 0
+
+
+
+
Inclusive INT, HEX, or ENUM upper bound.
+
+
Definition at line 46 of file attributes.h .
+
+
+
+
+
◆ minimum
+
+
+
+
+
+ double AttributeDefinition::minimum = 0.0
+
+
+
+
Inclusive FLOAT lower bound.
+
+
Definition at line 47 of file attributes.h .
+
+
+
+
+
◆ maximum
+
+
+
+
+
+ double AttributeDefinition::maximum = 0.0
+
+
+
+
Inclusive FLOAT upper bound.
+
+
Definition at line 48 of file attributes.h .
+
+
+
+
+
◆ enumValues
+
+
+
+
+
+ std::vector<std::string> AttributeDefinition::enumValues
+
+
+
+
ENUM labels in index order.
+
+
Definition at line 49 of file attributes.h .
+
+
+
+
+
◆ defaultValue
+
+
+
+
+
+ std::optional<AttributeValue> AttributeDefinition::defaultValue
+
+
+
+
+
The documentation for this struct was generated from the following file:
+
+
+
+
+
+
diff --git a/docs/html/structAttributeDefinition.js b/docs/html/structAttributeDefinition.js
new file mode 100644
index 0000000..e372881
--- /dev/null
+++ b/docs/html/structAttributeDefinition.js
@@ -0,0 +1,11 @@
+var structAttributeDefinition =
+[
+ [ "scope", "structAttributeDefinition.html#a5f109f0ec94eb04c3f52c116366aefdf", null ],
+ [ "type", "structAttributeDefinition.html#a5de5484174a8c5f6b309041089d20afc", null ],
+ [ "integerMinimum", "structAttributeDefinition.html#aaf87153bac0b228ad87b88e96f303210", null ],
+ [ "integerMaximum", "structAttributeDefinition.html#a5ca8f41ea3e921f54d81b8760c1dcfb3", null ],
+ [ "minimum", "structAttributeDefinition.html#a18245dba995929a61fd6de1fcdbc8a89", null ],
+ [ "maximum", "structAttributeDefinition.html#aa02fe74b5420c2e67c13e610b6bc9713", null ],
+ [ "enumValues", "structAttributeDefinition.html#a547fe17f6cfc631528f9156e4a509c66", null ],
+ [ "defaultValue", "structAttributeDefinition.html#ae0949edf67f9d4e60e4cb376a95da4f2", null ]
+];
\ No newline at end of file
diff --git a/docs/html/structDbcDatabase-members.html b/docs/html/structDbcDatabase-members.html
index de8d7ea..715b6cd 100644
--- a/docs/html/structDbcDatabase-members.html
+++ b/docs/html/structDbcDatabase-members.html
@@ -96,7 +96,10 @@ $(document).ready(function(){initNavTree('structDbcDatabase.html',''); initResiz
This is the complete list of members for DbcDatabase , including all inherited members.
diff --git a/docs/html/structDbcDatabase.html b/docs/html/structDbcDatabase.html
index fabc5df..7902c73 100644
--- a/docs/html/structDbcDatabase.html
+++ b/docs/html/structDbcDatabase.html
@@ -106,6 +106,12 @@ $(document).ready(function(){initNavTree('structDbcDatabase.html',''); initResiz
Public Attributes
std::vector< FrameInfo > frames
+std::map< std::string, AttributeDefinition > attributeDefinitions = {}
+
+std::vector< AttributeAssignment > attributeAssignments = {}
+
+AttributeMap attributes = {}
+
+
+
+◆ attributeDefinitions
+
+
+
+◆ attributeAssignments
+
+
+
+◆ attributes
+
+
+
+
+
+ AttributeMap DbcDatabase::attributes = {}
+
+
+
+
Effective database attributes.
+
+
Definition at line 26 of file dbc_database.h .
diff --git a/docs/html/structDbcDatabase.js b/docs/html/structDbcDatabase.js
index 43ad455..3bb1d53 100644
--- a/docs/html/structDbcDatabase.js
+++ b/docs/html/structDbcDatabase.js
@@ -1,4 +1,7 @@
var structDbcDatabase =
[
- [ "frames", "structDbcDatabase.html#a2cade5d0234ee816132127542f8c612b", null ]
+ [ "frames", "structDbcDatabase.html#a2cade5d0234ee816132127542f8c612b", null ],
+ [ "attributeDefinitions", "structDbcDatabase.html#a14862245081989f2abf126b5ea6dfdfa", null ],
+ [ "attributeAssignments", "structDbcDatabase.html#aa7bdf56eb8b7ab5b873e1c096b46d8b6", null ],
+ [ "attributes", "structDbcDatabase.html#a321839ad81af176444358eb23114eaee", null ]
];
\ No newline at end of file
diff --git a/docs/html/structDbcDiagnostic-members.html b/docs/html/structDbcDiagnostic-members.html
index 3d4eb3f..cddaa5c 100644
--- a/docs/html/structDbcDiagnostic-members.html
+++ b/docs/html/structDbcDiagnostic-members.html
@@ -96,11 +96,11 @@ $(document).ready(function(){initNavTree('structDbcDiagnostic.html',''); initRes
This is the complete list of members for DbcDiagnostic , including all inherited members.
diff --git a/docs/html/structDbcDiagnostic.html b/docs/html/structDbcDiagnostic.html
index 07fa2e2..2219948 100644
--- a/docs/html/structDbcDiagnostic.html
+++ b/docs/html/structDbcDiagnostic.html
@@ -96,6 +96,11 @@ $(document).ready(function(){initNavTree('structDbcDiagnostic.html',''); initRes
+
+
Diagnostic message and physical source location.
+ More...
+
+
#include <dbc_diagnostic.h >
@@ -111,8 +116,9 @@ Public Attributes
-
-
Definition at line 25 of file dbc_diagnostic.h .
+
Diagnostic message and physical source location.
+
+
Definition at line 29 of file dbc_diagnostic.h .
◆ severity
@@ -125,8 +131,9 @@ Public Attributes
@@ -141,8 +148,9 @@ Public Attributes
@@ -157,8 +165,9 @@ Public Attributes
@@ -173,8 +182,9 @@ Public Attributes
@@ -189,8 +199,9 @@ Public Attributes
diff --git a/docs/html/structDbcDiagnostic.js b/docs/html/structDbcDiagnostic.js
new file mode 100644
index 0000000..dbc7f4d
--- /dev/null
+++ b/docs/html/structDbcDiagnostic.js
@@ -0,0 +1,8 @@
+var structDbcDiagnostic =
+[
+ [ "severity", "structDbcDiagnostic.html#a75040a94f0313a606478020b0491f81d", null ],
+ [ "code", "structDbcDiagnostic.html#aa315a4a40b15f2e8cb34264d94a0f914", null ],
+ [ "filePath", "structDbcDiagnostic.html#ac9f02705ed6a633cbb9526d0e392fb95", null ],
+ [ "lineNumber", "structDbcDiagnostic.html#adb201de8d32b768d5f559bed21e8f819", null ],
+ [ "message", "structDbcDiagnostic.html#a124bae82eebeaef46426bd124685ef1b", null ]
+];
\ No newline at end of file
diff --git a/docs/html/structDbcParseContext-members.html b/docs/html/structDbcParseContext-members.html
index dbb3931..98fdcad 100644
--- a/docs/html/structDbcParseContext-members.html
+++ b/docs/html/structDbcParseContext-members.html
@@ -96,13 +96,18 @@ $(document).ready(function(){initNavTree('structDbcParseContext.html',''); initR
This is the complete list of members for DbcParseContext , including all inherited members.
diff --git a/docs/html/structDbcParseContext.html b/docs/html/structDbcParseContext.html
index ec2e68b..3f48e49 100644
--- a/docs/html/structDbcParseContext.html
+++ b/docs/html/structDbcParseContext.html
@@ -103,8 +103,16 @@ $(document).ready(function(){initNavTree('structDbcParseContext.html',''); initR
void ValidateMultiplexing (const std::string &filePath) const
+ Validate selectors, branch ranges, and signal overlap.
+void ResolveComments (const std::string &filePath)
+ Resolve deferred comments after all definitions are known.
+
+void ResolveAttributes (const std::string &filePath, std::vector< DbcDiagnostic > &diagnostics)
+ Resolve definitions, defaults, then assignments; append format warnings.
+
void ResolveValueDescriptions (const std::string &filePath)
+ Resolve deferred raw descriptions against unique targets.
Mutable state belonging to one file parse. Handlers do not retain it.
-
Definition at line 32 of file dbc_statement_handler.h .
+
Definition at line 50 of file dbc_statement_handler.h .
◆ ValidateMultiplexing()
@@ -141,7 +155,69 @@ Public Attributes
+
+
+◆ ResolveComments()
+
+
+
+
+
+ void DbcParseContext::ResolveComments
+ (
+ const std::string &
+ filePath )
+
+
+
+
+
+
+◆ ResolveAttributes()
+
+
+
+
+
+ void DbcParseContext::ResolveAttributes
+ (
+ const std::string &
+ filePath ,
+
+
+
+
+ std::vector< DbcDiagnostic > &
+ diagnostics
+
+
+
+ )
+
+
+
+
+
+
Resolve definitions, defaults, then assignments; append format warnings.
+
+
Definition at line 255 of file dbc_attributes.cpp .
+
+
References DbcDatabase::attributeAssignments , DbcDatabase::attributeDefinitions , AttributeAssignment::canId , database , AttributeDefinition::defaultValue , DbcDatabase::frames , AttributeAssignment::isExtended , AttributeAssignment::name , pendingAttributes , AttributeDefinition::scope , AttributeAssignment::scope , AttributeAssignment::targetName , and AttributeAssignment::value .
@@ -161,7 +237,11 @@ Public Attributes
@@ -177,8 +257,11 @@ Public Attributes
@@ -193,8 +276,30 @@ Public Attributes
+
+
+◆ enableJ1939
+
+
+
+
+
+ bool DbcParseContext::enableJ1939 = false
+
+
+
@@ -209,8 +314,11 @@ Public Attributes
@@ -225,8 +333,11 @@ Public Attributes
@@ -241,13 +352,55 @@ Public Attributes
+
+
+◆ pendingComments
+
+
+
+
+
+ std::vector<PendingComment > DbcParseContext::pendingComments = {}
+
+
+
+
+
+◆ pendingAttributes
+
+
The documentation for this struct was generated from the following files:
diff --git a/docs/html/structDbcParseContext.js b/docs/html/structDbcParseContext.js
new file mode 100644
index 0000000..3568938
--- /dev/null
+++ b/docs/html/structDbcParseContext.js
@@ -0,0 +1,15 @@
+var structDbcParseContext =
+[
+ [ "ValidateMultiplexing", "structDbcParseContext.html#a908056de0a97316a4ebecb3f99cc400b", null ],
+ [ "ResolveComments", "structDbcParseContext.html#aeae343c57a244634489a0e0b960155d7", null ],
+ [ "ResolveAttributes", "structDbcParseContext.html#a1ac7f4a54550aaddef08749806f87001", null ],
+ [ "ResolveValueDescriptions", "structDbcParseContext.html#ab5552dad944fde7fa6add6464ddb5369", null ],
+ [ "database", "structDbcParseContext.html#a79bad0b8302e2156670461bab529259c", null ],
+ [ "currentFrame", "structDbcParseContext.html#af31b56247edff7f025957ae023a56913", null ],
+ [ "enableJ1939", "structDbcParseContext.html#a93f8ece0f3d16bd79f631ae07afa7b54", null ],
+ [ "lineNumber", "structDbcParseContext.html#a57f5a7f613ecd0dadbafa7af736b7e54", null ],
+ [ "pendingValues", "structDbcParseContext.html#ac22cba614ada3a28c7dcc1ea338b0e01", null ],
+ [ "signalLines", "structDbcParseContext.html#af8b411c938a2ea9100c4aaae452e6546", null ],
+ [ "pendingComments", "structDbcParseContext.html#a854abba7bbf4adfc948554c254156e60", null ],
+ [ "pendingAttributes", "structDbcParseContext.html#afbfa4b26a58b41ada3dabc619066035c", null ]
+];
\ No newline at end of file
diff --git a/docs/html/structDbcParseResult-members.html b/docs/html/structDbcParseResult-members.html
index c5524e3..09de48a 100644
--- a/docs/html/structDbcParseResult-members.html
+++ b/docs/html/structDbcParseResult-members.html
@@ -96,9 +96,9 @@ $(document).ready(function(){initNavTree('structDbcParseResult.html',''); initRe
This is the complete list of members for DbcParseResult , including all inherited members.
diff --git a/docs/html/structDbcParseResult.html b/docs/html/structDbcParseResult.html
index b3125de..59323e0 100644
--- a/docs/html/structDbcParseResult.html
+++ b/docs/html/structDbcParseResult.html
@@ -97,10 +97,16 @@ $(document).ready(function(){initNavTree('structDbcParseResult.html',''); initRe
+
+
Parsed database and diagnostics; the database is empty on error.
+ More...
+
+
#include <dbc_diagnostic.h >
bool HasErrors () const
+ Return whether any diagnostic has error severity.
-
-
Definition at line 33 of file dbc_diagnostic.h .
+
Parsed database and diagnostics; the database is empty on error.
+
+
Definition at line 38 of file dbc_diagnostic.h .
◆ HasErrors()
@@ -137,7 +144,11 @@ Public Attributes
@@ -153,8 +164,11 @@ Public Attributes
@@ -169,8 +183,11 @@ Public Attributes
diff --git a/docs/html/structDbcParseResult.js b/docs/html/structDbcParseResult.js
new file mode 100644
index 0000000..99b15bc
--- /dev/null
+++ b/docs/html/structDbcParseResult.js
@@ -0,0 +1,6 @@
+var structDbcParseResult =
+[
+ [ "HasErrors", "structDbcParseResult.html#a4da8641de3f6b55c7447c4421e05d20d", null ],
+ [ "database", "structDbcParseResult.html#abfa765d29a4397e8ddaf771bae21993e", null ],
+ [ "diagnostics", "structDbcParseResult.html#a3a1987b4381bb1e0a34dc09e31483679", null ]
+];
\ No newline at end of file
diff --git a/docs/html/structDbcParserOptions-members.html b/docs/html/structDbcParserOptions-members.html
new file mode 100644
index 0000000..57afb8e
--- /dev/null
+++ b/docs/html/structDbcParserOptions-members.html
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+DBC Framework: Member List
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DBC Framework
+
+ DBC parsing and CAN signal decoding framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+
+
+
+
+
This is the complete list of members for DbcParserOptions , including all inherited members.
+
+
+
+
+
+
diff --git a/docs/html/structDbcParserOptions.html b/docs/html/structDbcParserOptions.html
new file mode 100644
index 0000000..e400804
--- /dev/null
+++ b/docs/html/structDbcParserOptions.html
@@ -0,0 +1,144 @@
+
+
+
+
+
+
+
+DBC Framework: DbcParserOptions Struct Reference
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DBC Framework
+
+ DBC parsing and CAN signal decoding framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+
+
+
+
+
#include <dbc_parser.h >
+
+
+
Explicit interpretation applied to extended frames in this file.
+
+
Definition at line 20 of file dbc_parser.h .
+
+
+
◆ enableJ1939
+
+
+
+
+
+ bool DbcParserOptions::enableJ1939 = false
+
+
+
+
+
The documentation for this struct was generated from the following file:
+
+
+
+
+
+
diff --git a/docs/html/structDbcParserOptions.js b/docs/html/structDbcParserOptions.js
new file mode 100644
index 0000000..2f4e50b
--- /dev/null
+++ b/docs/html/structDbcParserOptions.js
@@ -0,0 +1,4 @@
+var structDbcParserOptions =
+[
+ [ "enableJ1939", "structDbcParserOptions.html#ab31534f5c0853461b46cbb38149c33f9", null ]
+];
\ No newline at end of file
diff --git a/docs/html/structDecodeFrame-members.html b/docs/html/structDecodeFrame-members.html
index 6d0a9dc..f6b4740 100644
--- a/docs/html/structDecodeFrame-members.html
+++ b/docs/html/structDecodeFrame-members.html
@@ -96,17 +96,20 @@ $(document).ready(function(){initNavTree('structDecodeFrame.html',''); initResiz
This is the complete list of members for DecodeFrame , including all inherited members.
diff --git a/docs/html/structDecodeFrame.html b/docs/html/structDecodeFrame.html
index bb60520..6b4b1ac 100644
--- a/docs/html/structDecodeFrame.html
+++ b/docs/html/structDecodeFrame.html
@@ -106,6 +106,7 @@ $(document).ready(function(){initNavTree('structDecodeFrame.html',''); initResiz
FrameKey GetKey () const
+ Return the stable normalized frame identifier.
Runtime-ready frame definition.
-
Definition at line 65 of file decode_database.h .
+
Definition at line 68 of file decode_database.h .
◆ GetKey()
@@ -157,7 +164,11 @@ Public Attributes
@@ -175,7 +186,7 @@ Public Attributes
@@ -213,9 +224,9 @@ Public Attributes
@@ -232,7 +243,7 @@ Public Attributes
+
+
+◆ attributes
+
+
+
+
+
+ AttributeMap DecodeFrame::attributes
+
+
+
+
+
+◆ frameFormat
+
+
+
+
+
+ std::optional<std::string> DecodeFrame::frameFormat
+
+
+
+
+
+◆ cycleTimeMs
+
+
+
+
+
+ std::optional<std::uint32_t> DecodeFrame::cycleTimeMs
+
+
+
diff --git a/docs/html/structDecodeFrame.js b/docs/html/structDecodeFrame.js
index a662af7..00be175 100644
--- a/docs/html/structDecodeFrame.js
+++ b/docs/html/structDecodeFrame.js
@@ -1,5 +1,6 @@
var structDecodeFrame =
[
+ [ "GetKey", "structDecodeFrame.html#a05e3d1c6143367553c2c3beba82a5c34", null ],
[ "name", "structDecodeFrame.html#aa0a7f8fd5bfde2148dfd0d838328f579", null ],
[ "canId", "structDecodeFrame.html#a52e10215388db7df8b541b9d9909edcf", null ],
[ "isExtended", "structDecodeFrame.html#a3ee2348d781f8f15aaf87e8dcf57ec41", null ],
@@ -8,5 +9,8 @@ var structDecodeFrame =
[ "hasPgn", "structDecodeFrame.html#a2551102670c4a540fced4c71da0b369d", null ],
[ "transmitter", "structDecodeFrame.html#ad78241dc40c793aabb8495b6989b81a9", null ],
[ "comment", "structDecodeFrame.html#a25819ef907a32391af5c9f7cae9cdb22", null ],
- [ "public", "structDecodeFrame.html#a7f4e71bbdec3f424b625e724e3dfbf14", null ]
+ [ "public", "structDecodeFrame.html#a7f4e71bbdec3f424b625e724e3dfbf14", null ],
+ [ "attributes", "structDecodeFrame.html#ad506b03108a40df7e8005638c9c59653", null ],
+ [ "frameFormat", "structDecodeFrame.html#a475e669f390491a4d99383d3fee51300", null ],
+ [ "cycleTimeMs", "structDecodeFrame.html#a732c2f6853d55ce8253db61207fc21d3", null ]
];
\ No newline at end of file
diff --git a/docs/html/structDecodeSignal-members.html b/docs/html/structDecodeSignal-members.html
index 9dbd912..41e7356 100644
--- a/docs/html/structDecodeSignal-members.html
+++ b/docs/html/structDecodeSignal-members.html
@@ -96,21 +96,22 @@ $(document).ready(function(){initNavTree('structDecodeSignal.html',''); initResi
This is the complete list of members for DecodeSignal , including all inherited members.
diff --git a/docs/html/structDecodeSignal.html b/docs/html/structDecodeSignal.html
index 919b78b..e72e8c0 100644
--- a/docs/html/structDecodeSignal.html
+++ b/docs/html/structDecodeSignal.html
@@ -132,11 +132,13 @@ Public Attributes
std::string comment
+AttributeMap attributes
+
Runtime-ready signal definition.
-
Definition at line 43 of file decode_database.h .
+
Definition at line 44 of file decode_database.h .
◆ multiplexing
@@ -149,8 +151,11 @@ Public Attributes
@@ -167,9 +172,9 @@ Public Attributes
@@ -186,7 +191,7 @@ Public Attributes
+
+
+◆ attributes
+
+
+
+
+
+ AttributeMap DecodeSignal::attributes
+
+
+
+
Effective attributes after defaults and overrides.
+
+
Definition at line 60 of file decode_database.h .
Referenced by DbcDecodeBuilder::Build() .
diff --git a/docs/html/structDecodeSignal.js b/docs/html/structDecodeSignal.js
index 6284253..7483880 100644
--- a/docs/html/structDecodeSignal.js
+++ b/docs/html/structDecodeSignal.js
@@ -1,5 +1,6 @@
var structDecodeSignal =
[
+ [ "multiplexing", "structDecodeSignal.html#aea41c055cb255fe7bd178ed5727f28c9", null ],
[ "name", "structDecodeSignal.html#a58cf5844f2272a23dcb9687d912e4780", null ],
[ "startBit", "structDecodeSignal.html#aaf5d7527ddf65b6355c2b4f3626df22d", null ],
[ "length", "structDecodeSignal.html#acd4ef5ee30421d117b5756854302debb", null ],
@@ -12,5 +13,6 @@ var structDecodeSignal =
[ "unit", "structDecodeSignal.html#a38eed9ca7581423fd8bfbedcffc12092", null ],
[ "receivers", "structDecodeSignal.html#abdbae62a64d2df716bf60c6b67b30eaa", null ],
[ "valueDescriptions", "structDecodeSignal.html#a822155d9bf4ed5f3300c9e9befe606ff", null ],
- [ "comment", "structDecodeSignal.html#ae28c905d4a2bc86419c2a8361bfea473", null ]
+ [ "comment", "structDecodeSignal.html#ae28c905d4a2bc86419c2a8361bfea473", null ],
+ [ "attributes", "structDecodeSignal.html#a204f65c7ea45a2c148f19c12d922f99b", null ]
];
\ No newline at end of file
diff --git a/docs/html/structDecodedFrameValue.html b/docs/html/structDecodedFrameValue.html
index 1bf8f23..0961705 100644
--- a/docs/html/structDecodedFrameValue.html
+++ b/docs/html/structDecodedFrameValue.html
@@ -118,7 +118,7 @@ Public Attributes
Fully decoded frame.
-
Definition at line 71 of file dbc_decoder.h .
+
Definition at line 73 of file dbc_decoder.h .
◆ definition
@@ -133,9 +133,7 @@ Public Attributes
@@ -150,11 +148,9 @@ Public Attributes
@@ -171,7 +167,7 @@ Public Attributes
@@ -188,9 +184,7 @@ Public Attributes
@@ -207,9 +201,7 @@ Public Attributes
diff --git a/docs/html/structDecodedSignalValue-members.html b/docs/html/structDecodedSignalValue-members.html
index 4f8c9e7..da6a3c5 100644
--- a/docs/html/structDecodedSignalValue-members.html
+++ b/docs/html/structDecodedSignalValue-members.html
@@ -102,7 +102,7 @@ $(document).ready(function(){initNavTree('structDecodedSignalValue.html',''); in
key DecodedSignalValue
physicalValue DecodedSignalValue
rawValue DecodedSignalValue
- status (defined in DecodedSignalValue )DecodedSignalValue
+ status DecodedSignalValue
valid DecodedSignalValue
diff --git a/docs/html/structDecodedSignalValue.html b/docs/html/structDecodedSignalValue.html
index 047d310..f4ca269 100644
--- a/docs/html/structDecodedSignalValue.html
+++ b/docs/html/structDecodedSignalValue.html
@@ -120,13 +120,13 @@ Public Attributes
bool valid = false
-SignalDecodeStatus status = SignalDecodeStatus::InvalidDefinition
+SignalDecodeStatus status = SignalDecodeStatus::InvalidDefinition
One decoded signal value.
-
Definition at line 52 of file dbc_decoder.h .
+
Definition at line 54 of file dbc_decoder.h .
◆ GetValueDescription()
@@ -152,9 +152,9 @@ Public Attributes
@@ -172,9 +172,9 @@ Public Attributes
@@ -191,9 +191,7 @@ Public Attributes
@@ -210,9 +208,9 @@ Public Attributes
@@ -229,7 +227,7 @@ Public Attributes
@@ -246,9 +244,9 @@ Public Attributes
@@ -259,12 +257,13 @@ Public Attributes
- SignalDecodeStatus DecodedSignalValue::status = SignalDecodeStatus::InvalidDefinition
+ SignalDecodeStatus DecodedSignalValue::status = SignalDecodeStatus::InvalidDefinition
diff --git a/docs/html/structDecodedSignalValue.js b/docs/html/structDecodedSignalValue.js
index cb0464d..2679dfa 100644
--- a/docs/html/structDecodedSignalValue.js
+++ b/docs/html/structDecodedSignalValue.js
@@ -5,5 +5,6 @@ var structDecodedSignalValue =
[ "key", "structDecodedSignalValue.html#a33df0fcd92b23b3e08539906fc6b4c4a", null ],
[ "rawValue", "structDecodedSignalValue.html#a503c90b4b1a610b8252c45e466367c28", null ],
[ "physicalValue", "structDecodedSignalValue.html#a6847d05b3cb00d5e0f6c611968f57978", null ],
- [ "valid", "structDecodedSignalValue.html#aac0ed361af545cde48d0e6f41a859686", null ]
+ [ "valid", "structDecodedSignalValue.html#aac0ed361af545cde48d0e6f41a859686", null ],
+ [ "status", "structDecodedSignalValue.html#a94161a80412b3961da8fd2fec43c25f6", null ]
];
\ No newline at end of file
diff --git a/docs/html/structFrameInfo-members.html b/docs/html/structFrameInfo-members.html
index 76b58f3..0c1bc58 100644
--- a/docs/html/structFrameInfo-members.html
+++ b/docs/html/structFrameInfo-members.html
@@ -96,16 +96,19 @@ $(document).ready(function(){initNavTree('structFrameInfo.html',''); initResizab
This is the complete list of members for FrameInfo , including all inherited members.
diff --git a/docs/html/structFrameInfo.html b/docs/html/structFrameInfo.html
index d0d3cca..9d04ac9 100644
--- a/docs/html/structFrameInfo.html
+++ b/docs/html/structFrameInfo.html
@@ -122,11 +122,17 @@ Public Attributes
std::vector< SignalInfo > public
+std::optional< std::string > frameFormat
+
+std::optional< std::uint32_t > cycleTimeMs
+
+AttributeMap attributes
+
Describes one CAN frame from a DBC file.
-
Definition at line 24 of file frame_info.h .
+
Definition at line 25 of file frame_info.h .
◆ name
@@ -141,7 +147,9 @@ Public Attributes
@@ -158,7 +166,9 @@ Public Attributes
@@ -175,7 +185,9 @@ Public Attributes
@@ -192,7 +204,9 @@ Public Attributes
@@ -207,9 +221,11 @@ Public Attributes
@@ -226,7 +242,9 @@ Public Attributes
@@ -243,7 +261,7 @@ Public Attributes
@@ -260,7 +278,9 @@ Public Attributes
@@ -277,7 +297,58 @@ Public Attributes
+
+
+◆ frameFormat
+
+
+
+
+
+ std::optional<std::string> FrameInfo::frameFormat
+
+
+
+
VFrameFormat label, when declared. VFrameFormat enum label.
+
+
Definition at line 36 of file frame_info.h .
+
+
+
+
+◆ cycleTimeMs
+
+
+
+
+
+ std::optional<std::uint32_t> FrameInfo::cycleTimeMs
+
+
+
+
GenMsgCycleTime in milliseconds, when declared. GenMsgCycleTime; zero means unspecified.
+
+
Definition at line 37 of file frame_info.h .
+
+
+
+
+◆ attributes
+
+
+
+
+
+ AttributeMap FrameInfo::attributes
+
+
+
+
Effective attributes after defaults and overrides. Effective values, including defaults.
+
+
Definition at line 39 of file frame_info.h .
diff --git a/docs/html/structFrameInfo.js b/docs/html/structFrameInfo.js
index 7a9f055..cc2fc6f 100644
--- a/docs/html/structFrameInfo.js
+++ b/docs/html/structFrameInfo.js
@@ -8,5 +8,8 @@ var structFrameInfo =
[ "dlc", "structFrameInfo.html#aa2b198ea0f55e560c123d35e7b3ecab9", null ],
[ "transmitter", "structFrameInfo.html#a92749ec3798d4211a505860fb389a9e8", null ],
[ "comment", "structFrameInfo.html#ace75121294f9d89b762080ab5643293c", null ],
- [ "public", "structFrameInfo.html#a3f7e25d67ddae22f2ed50823a5a26084", null ]
+ [ "public", "structFrameInfo.html#a3f7e25d67ddae22f2ed50823a5a26084", null ],
+ [ "frameFormat", "structFrameInfo.html#a35bf839519ef3f48b5f52dd9bcd7e9ac", null ],
+ [ "cycleTimeMs", "structFrameInfo.html#a099f02a77adfb9ac23e286ce75f4eef4", null ],
+ [ "attributes", "structFrameInfo.html#a9ef2736053b593cf34ba2608cf8275c0", null ]
];
\ No newline at end of file
diff --git a/docs/html/structFrameKey-members.html b/docs/html/structFrameKey-members.html
index 7700119..d906881 100644
--- a/docs/html/structFrameKey-members.html
+++ b/docs/html/structFrameKey-members.html
@@ -96,11 +96,11 @@ $(document).ready(function(){initNavTree('structFrameKey.html',''); initResizabl
This is the complete list of members for FrameKey , including all inherited members.
diff --git a/docs/html/structFrameKey.html b/docs/html/structFrameKey.html
index 298d52b..8667a87 100644
--- a/docs/html/structFrameKey.html
+++ b/docs/html/structFrameKey.html
@@ -106,8 +106,10 @@ $(document).ready(function(){initNavTree('structFrameKey.html',''); initResizabl
FrameKey (std::uint32_t id, bool extended)
+ Create a key from a normalized identifier and frame type.
bool operator== (const FrameKey &other) const
+ Compare all logical identity fields.
@@ -185,7 +189,11 @@ Public Attributes
@@ -201,9 +209,12 @@ Public Attributes
@@ -217,9 +228,12 @@ Public Attributes
The documentation for this struct was generated from the following file:
diff --git a/docs/html/structFrameKey.js b/docs/html/structFrameKey.js
new file mode 100644
index 0000000..eca1c1f
--- /dev/null
+++ b/docs/html/structFrameKey.js
@@ -0,0 +1,7 @@
+var structFrameKey =
+[
+ [ "FrameKey", "structFrameKey.html#a33bde405c7ea53000d54b3dd6e058670", null ],
+ [ "operator==", "structFrameKey.html#aaaec9f914e127787247fcda5e183b01f", null ],
+ [ "canId", "structFrameKey.html#a022917652b4d3c2f2dfcc5a13ab7caa4", null ],
+ [ "isExtended", "structFrameKey.html#aa3179b709d02ef70cf0e736f040a2145", null ]
+];
\ No newline at end of file
diff --git a/docs/html/structFrameKeyHasher-members.html b/docs/html/structFrameKeyHasher-members.html
index 171aca7..c365064 100644
--- a/docs/html/structFrameKeyHasher-members.html
+++ b/docs/html/structFrameKeyHasher-members.html
@@ -96,7 +96,7 @@ $(document).ready(function(){initNavTree('structFrameKeyHasher.html',''); initRe
This is the complete list of members for FrameKeyHasher , including all inherited members.
diff --git a/docs/html/structFrameKeyHasher.html b/docs/html/structFrameKeyHasher.html
index 59772b4..3aa34d0 100644
--- a/docs/html/structFrameKeyHasher.html
+++ b/docs/html/structFrameKeyHasher.html
@@ -105,12 +105,13 @@ $(document).ready(function(){initNavTree('structFrameKeyHasher.html',''); initRe
std::size_t operator() (const FrameKey &key) const
+ Hash the logical identity fields.
Hasher for frame key.
-
Definition at line 33 of file definition_key.h .
+
Definition at line 35 of file definition_key.h .
◆ operator()()
@@ -136,7 +137,11 @@ Public Member Functions
diff --git a/docs/html/structFrameKeyHasher.js b/docs/html/structFrameKeyHasher.js
new file mode 100644
index 0000000..24a652a
--- /dev/null
+++ b/docs/html/structFrameKeyHasher.js
@@ -0,0 +1,4 @@
+var structFrameKeyHasher =
+[
+ [ "operator()", "structFrameKeyHasher.html#a1612ce56b513790e3ed4c06ec7d28b9f", null ]
+];
\ No newline at end of file
diff --git a/docs/html/structMultiplexing-members.html b/docs/html/structMultiplexing-members.html
index b623616..20de77f 100644
--- a/docs/html/structMultiplexing-members.html
+++ b/docs/html/structMultiplexing-members.html
@@ -96,8 +96,8 @@ $(document).ready(function(){initNavTree('structMultiplexing.html',''); initResi
This is the complete list of members for Multiplexing , including all inherited members.
diff --git a/docs/html/structMultiplexing.html b/docs/html/structMultiplexing.html
index 27a00c2..8298b5c 100644
--- a/docs/html/structMultiplexing.html
+++ b/docs/html/structMultiplexing.html
@@ -109,7 +109,7 @@ Public Attributes
Basic multiplexing: one unsigned selector per frame, one raw value per branch.
-
Definition at line 14 of file multiplexing.h .
+
Definition at line 15 of file multiplexing.h .
◆ role
@@ -122,8 +122,9 @@ Public Attributes
@@ -138,8 +139,9 @@ Public Attributes
diff --git a/docs/html/structMultiplexing.js b/docs/html/structMultiplexing.js
new file mode 100644
index 0000000..53dc9ce
--- /dev/null
+++ b/docs/html/structMultiplexing.js
@@ -0,0 +1,5 @@
+var structMultiplexing =
+[
+ [ "role", "structMultiplexing.html#a62b70a0e3f2a9c7a457b3694ce8625c3", null ],
+ [ "value", "structMultiplexing.html#a79158d4fdbfd68a3d51a8ce79d34fd67", null ]
+];
\ No newline at end of file
diff --git a/docs/html/structPendingAttribute-members.html b/docs/html/structPendingAttribute-members.html
new file mode 100644
index 0000000..725264b
--- /dev/null
+++ b/docs/html/structPendingAttribute-members.html
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+DBC Framework: Member List
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DBC Framework
+
+ DBC parsing and CAN signal decoding framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+
+
+
+
+
This is the complete list of members for PendingAttribute , including all inherited members.
+
+
+
+
+
+
diff --git a/docs/html/structPendingAttribute.html b/docs/html/structPendingAttribute.html
new file mode 100644
index 0000000..7158e2e
--- /dev/null
+++ b/docs/html/structPendingAttribute.html
@@ -0,0 +1,164 @@
+
+
+
+
+
+
+
+DBC Framework: PendingAttribute Struct Reference
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DBC Framework
+
+ DBC parsing and CAN signal decoding framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+
+
+
+
+
Attribute statement retained for ordered resolution.
+ More...
+
+
#include <dbc_statement_handler.h >
+
+
+
Attribute statement retained for ordered resolution.
+
+
Definition at line 44 of file dbc_statement_handler.h .
+
+
+
◆ statement
+
+
+
+
+
+ std::string PendingAttribute::statement
+
+
+
+
+
+
◆ lineNumber
+
+
+
+
+
+ std::size_t PendingAttribute::lineNumber
+
+
+
+
+
The documentation for this struct was generated from the following file:
+
+
+
+
+
+
diff --git a/docs/html/structPendingAttribute.js b/docs/html/structPendingAttribute.js
new file mode 100644
index 0000000..b833c84
--- /dev/null
+++ b/docs/html/structPendingAttribute.js
@@ -0,0 +1,5 @@
+var structPendingAttribute =
+[
+ [ "statement", "structPendingAttribute.html#a0ec62fc577e3a2d5f63d926f829e2ab8", null ],
+ [ "lineNumber", "structPendingAttribute.html#a9a68a0a54c313c3e43dfdcd6e7a55da9", null ]
+];
\ No newline at end of file
diff --git a/docs/html/structPendingComment-members.html b/docs/html/structPendingComment-members.html
new file mode 100644
index 0000000..d435cfa
--- /dev/null
+++ b/docs/html/structPendingComment-members.html
@@ -0,0 +1,114 @@
+
+
+
+
+
+
+
+DBC Framework: Member List
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DBC Framework
+
+ DBC parsing and CAN signal decoding framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+
+
+
+
+
This is the complete list of members for PendingComment , including all inherited members.
+
+
+
+
+
+
diff --git a/docs/html/structPendingComment.html b/docs/html/structPendingComment.html
new file mode 100644
index 0000000..4f3eab2
--- /dev/null
+++ b/docs/html/structPendingComment.html
@@ -0,0 +1,252 @@
+
+
+
+
+
+
+
+DBC Framework: PendingComment Struct Reference
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DBC Framework
+
+ DBC parsing and CAN signal decoding framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+
+
+
+
+
Deferred frame or signal comment and its source location.
+ More...
+
+
#include <dbc_statement_handler.h >
+
+
+
Deferred frame or signal comment and its source location.
+
+
Definition at line 22 of file dbc_statement_handler.h .
+
+
+
◆ canId
+
+
+
+
+
+ std::uint32_t PendingComment::canId
+
+
+
+
+
+
◆ isExtended
+
+
+
+
+
+ bool PendingComment::isExtended
+
+
+
+
+
+
◆ isSignal
+
+
+
+
+
+ bool PendingComment::isSignal
+
+
+
+
+
+
◆ signalName
+
+
+
+
+
+ std::string PendingComment::signalName
+
+
+
+
+
+
◆ comment
+
+
+
+
+
+ std::string PendingComment::comment
+
+
+
+
+
+
◆ lineNumber
+
+
+
+
+
+ std::size_t PendingComment::lineNumber
+
+
+
+
+
The documentation for this struct was generated from the following file:
+
+
+
+
+
+
diff --git a/docs/html/structPendingComment.js b/docs/html/structPendingComment.js
new file mode 100644
index 0000000..bdf78cc
--- /dev/null
+++ b/docs/html/structPendingComment.js
@@ -0,0 +1,9 @@
+var structPendingComment =
+[
+ [ "canId", "structPendingComment.html#a6d1c3b1e149bb602a95224446709c771", null ],
+ [ "isExtended", "structPendingComment.html#a9abd7e15ed59eb4534c66ff74f276e07", null ],
+ [ "isSignal", "structPendingComment.html#ac03903ffb042d27ad66012eb18ea1437", null ],
+ [ "signalName", "structPendingComment.html#ae7b5aea9c252a4ab87e02915d24fee27", null ],
+ [ "comment", "structPendingComment.html#aa344393f67770e12449a4f14f6fcf10b", null ],
+ [ "lineNumber", "structPendingComment.html#a29a3733e0a4c8ae341695db3d21d9249", null ]
+];
\ No newline at end of file
diff --git a/docs/html/structPendingValueDescriptions-members.html b/docs/html/structPendingValueDescriptions-members.html
index a91c4eb..76a78e6 100644
--- a/docs/html/structPendingValueDescriptions-members.html
+++ b/docs/html/structPendingValueDescriptions-members.html
@@ -96,11 +96,11 @@ $(document).ready(function(){initNavTree('structPendingValueDescriptions.html','
This is the complete list of members for PendingValueDescriptions , including all inherited members.
diff --git a/docs/html/structPendingValueDescriptions.html b/docs/html/structPendingValueDescriptions.html
index 8015830..9d96929 100644
--- a/docs/html/structPendingValueDescriptions.html
+++ b/docs/html/structPendingValueDescriptions.html
@@ -96,6 +96,11 @@ $(document).ready(function(){initNavTree('structPendingValueDescriptions.html','
+
+
Deferred raw value descriptions and their target.
+ More...
+
+
#include <dbc_statement_handler.h >
@@ -111,8 +116,9 @@ Public Attributes
-
-
Definition at line 12 of file dbc_statement_handler.h .
+
Deferred raw value descriptions and their target.
+
+
Definition at line 13 of file dbc_statement_handler.h .
◆ canId
@@ -125,8 +131,11 @@ Public Attributes
@@ -141,8 +150,11 @@ Public Attributes
@@ -157,8 +169,11 @@ Public Attributes
@@ -173,8 +188,11 @@ Public Attributes
@@ -189,8 +207,11 @@ Public Attributes
diff --git a/docs/html/structPendingValueDescriptions.js b/docs/html/structPendingValueDescriptions.js
new file mode 100644
index 0000000..a54a2fd
--- /dev/null
+++ b/docs/html/structPendingValueDescriptions.js
@@ -0,0 +1,8 @@
+var structPendingValueDescriptions =
+[
+ [ "canId", "structPendingValueDescriptions.html#a5f0082ceeaee77e2f823661547aad844", null ],
+ [ "isExtended", "structPendingValueDescriptions.html#a60f185e8d91010927c4aa3b4a750c9f4", null ],
+ [ "signalName", "structPendingValueDescriptions.html#ac35446db10ebda5a12349759613f8c90", null ],
+ [ "descriptions", "structPendingValueDescriptions.html#a10ecbaeaed2cc3ac82fada73e7e041dd", null ],
+ [ "lineNumber", "structPendingValueDescriptions.html#a5c19cff09b0e83bd3cd6085213c17da8", null ]
+];
\ No newline at end of file
diff --git a/docs/html/structPgnLookupResult-members.html b/docs/html/structPgnLookupResult-members.html
new file mode 100644
index 0000000..3693407
--- /dev/null
+++ b/docs/html/structPgnLookupResult-members.html
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+DBC Framework: Member List
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DBC Framework
+
+ DBC parsing and CAN signal decoding framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+
+
+
+
+
This is the complete list of members for PgnLookupResult , including all inherited members.
+
+
+
+
+
+
diff --git a/docs/html/structPgnLookupResult.html b/docs/html/structPgnLookupResult.html
new file mode 100644
index 0000000..bc592a7
--- /dev/null
+++ b/docs/html/structPgnLookupResult.html
@@ -0,0 +1,165 @@
+
+
+
+
+
+
+
+DBC Framework: PgnLookupResult Struct Reference
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DBC Framework
+
+ DBC parsing and CAN signal decoding framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+
+
+
+
+
#include <decode_database.h >
+
+
+
A PGN lookup rejects multiple definitions rather than choosing by order.
+
+
Definition at line 92 of file decode_database.h .
+
+
+
◆ definition
+
+
+
+
+
+ std::shared_ptr<const DecodeFrame > PgnLookupResult::definition
+
+
+
+
+
+
◆ ambiguous
+
+
+
+
+
+ bool PgnLookupResult::ambiguous = false
+
+
+
+
+
The documentation for this struct was generated from the following file:
+
+
+
+
+
+
diff --git a/docs/html/structPgnLookupResult.js b/docs/html/structPgnLookupResult.js
new file mode 100644
index 0000000..47d1747
--- /dev/null
+++ b/docs/html/structPgnLookupResult.js
@@ -0,0 +1,5 @@
+var structPgnLookupResult =
+[
+ [ "definition", "structPgnLookupResult.html#aa5b79b61d2aef48fd6ae070cf5f901c1", null ],
+ [ "ambiguous", "structPgnLookupResult.html#a6158833782348b3cc26037c2091fcc36", null ]
+];
\ No newline at end of file
diff --git a/docs/html/structRawCanFrame.html b/docs/html/structRawCanFrame.html
index 200138c..e054567 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 main() .
@@ -150,7 +150,7 @@ Public Attributes
Definition at line 26 of file dbc_decoder.h .
-Referenced by DbcDecoder::Decode() .
+Referenced by main() .
@@ -169,7 +169,7 @@ Public Attributes
Definition at line 27 of file dbc_decoder.h .
-Referenced by DbcDecoder::Decode() .
+Referenced by main() .
diff --git a/docs/html/structSignalInfo-members.html b/docs/html/structSignalInfo-members.html
index 6557d7f..4784da9 100644
--- a/docs/html/structSignalInfo-members.html
+++ b/docs/html/structSignalInfo-members.html
@@ -96,21 +96,22 @@ $(document).ready(function(){initNavTree('structSignalInfo.html',''); initResiza
This is the complete list of members for SignalInfo , including all inherited members.
diff --git a/docs/html/structSignalInfo.html b/docs/html/structSignalInfo.html
index 227c4e4..f7cacbb 100644
--- a/docs/html/structSignalInfo.html
+++ b/docs/html/structSignalInfo.html
@@ -132,11 +132,13 @@ Public Attributes
std::string comment
+AttributeMap attributes
+
Describes one signal inside a DBC frame.
-
Definition at line 24 of file signal_info.h .
+
Definition at line 25 of file signal_info.h .
◆ multiplexing
@@ -149,8 +151,9 @@ Public Attributes
@@ -167,7 +170,9 @@ Public Attributes
@@ -184,7 +189,9 @@ Public Attributes
@@ -201,7 +208,9 @@ Public Attributes
@@ -218,7 +227,9 @@ Public Attributes
@@ -235,7 +246,9 @@ Public Attributes
@@ -252,7 +265,7 @@ Public Attributes
@@ -269,7 +282,7 @@ Public Attributes
@@ -286,7 +299,7 @@ Public Attributes
@@ -303,7 +316,7 @@ Public Attributes
@@ -320,7 +333,9 @@ Public Attributes
@@ -337,7 +352,7 @@ Public Attributes
@@ -354,7 +369,9 @@ Public Attributes
@@ -371,7 +388,26 @@ Public Attributes
+
+
+◆ attributes
+
+
+
+
+
+ AttributeMap SignalInfo::attributes
+
+
+
+
Effective attributes after defaults and overrides. Effective values, including defaults.
+
+
Definition at line 41 of file signal_info.h .
diff --git a/docs/html/structSignalInfo.js b/docs/html/structSignalInfo.js
index 8cfee27..80495e0 100644
--- a/docs/html/structSignalInfo.js
+++ b/docs/html/structSignalInfo.js
@@ -1,5 +1,6 @@
var structSignalInfo =
[
+ [ "multiplexing", "structSignalInfo.html#a8a2e29f307c75926a1bd824266d23ca8", null ],
[ "name", "structSignalInfo.html#a379e422a00cad56f896cacf60455b088", null ],
[ "startBit", "structSignalInfo.html#ace290724f9801521609aedaa946d61f1", null ],
[ "length", "structSignalInfo.html#a1008b5201f71848177217bd52fb84baa", null ],
@@ -12,5 +13,6 @@ var structSignalInfo =
[ "unit", "structSignalInfo.html#a1f214f03e94ef5794de2d3367bfcbd01", null ],
[ "receivers", "structSignalInfo.html#a2c95562fd0b29327a7fd7b1e6feee7f3", null ],
[ "valueDescriptions", "structSignalInfo.html#a43f47d0433d0cc39076bd7278b46af9c", null ],
- [ "comment", "structSignalInfo.html#ac99ba7563a5dad01e39c4257216953f5", null ]
+ [ "comment", "structSignalInfo.html#ac99ba7563a5dad01e39c4257216953f5", null ],
+ [ "attributes", "structSignalInfo.html#a781766eddbf6641071623c8e5b9acb4a", null ]
];
\ No newline at end of file
diff --git a/docs/html/structSignalKey-members.html b/docs/html/structSignalKey-members.html
index 50aa8b0..eec532b 100644
--- a/docs/html/structSignalKey-members.html
+++ b/docs/html/structSignalKey-members.html
@@ -96,11 +96,11 @@ $(document).ready(function(){initNavTree('structSignalKey.html',''); initResizab
This is the complete list of members for SignalKey , including all inherited members.
diff --git a/docs/html/structSignalKey.html b/docs/html/structSignalKey.html
index cb917f3..50864c1 100644
--- a/docs/html/structSignalKey.html
+++ b/docs/html/structSignalKey.html
@@ -103,8 +103,10 @@ $(document).ready(function(){initNavTree('structSignalKey.html',''); initResizab
SignalKey (FrameKey frameKey, std::string signalName)
+ Create a signal key from its frame identity and name.
bool operator== (const SignalKey &other) const
+ Compare all logical identity fields.
Stable signal identifier within one logical DBC database.
-
Definition at line 42 of file definition_key.h .
+
Definition at line 45 of file definition_key.h .
◆ SignalKey()
@@ -153,7 +155,9 @@ Public Attributes
@@ -182,7 +186,11 @@ Public Attributes
@@ -198,8 +206,11 @@ Public Attributes
@@ -214,8 +225,11 @@ Public Attributes
diff --git a/docs/html/structSignalKey.js b/docs/html/structSignalKey.js
new file mode 100644
index 0000000..e05ce26
--- /dev/null
+++ b/docs/html/structSignalKey.js
@@ -0,0 +1,7 @@
+var structSignalKey =
+[
+ [ "SignalKey", "structSignalKey.html#aa4221b34e75469bf5aa939976c334f46", null ],
+ [ "operator==", "structSignalKey.html#a17525dc0116be7f4f58f3c3fae1022e2", null ],
+ [ "frame", "structSignalKey.html#a25f4ece1bf685791b576f68e23d8ccc7", null ],
+ [ "name", "structSignalKey.html#abab371cce740f05111fd3b4013ca6944", null ]
+];
\ No newline at end of file
diff --git a/docs/html/structSignalKeyHasher-members.html b/docs/html/structSignalKeyHasher-members.html
index 59ac5f9..c7785ad 100644
--- a/docs/html/structSignalKeyHasher-members.html
+++ b/docs/html/structSignalKeyHasher-members.html
@@ -96,7 +96,7 @@ $(document).ready(function(){initNavTree('structSignalKeyHasher.html',''); initR
This is the complete list of members for SignalKeyHasher , including all inherited members.
diff --git a/docs/html/structSignalKeyHasher.html b/docs/html/structSignalKeyHasher.html
index 0d7dfe1..5dfd658 100644
--- a/docs/html/structSignalKeyHasher.html
+++ b/docs/html/structSignalKeyHasher.html
@@ -96,15 +96,22 @@ $(document).ready(function(){initNavTree('structSignalKeyHasher.html',''); initR
+
+
Hasher for stable signal keys.
+ More...
+
+
#include <definition_key.h >
-
-
Definition at line 56 of file definition_key.h .
+
Hasher for stable signal keys.
+
+
Definition at line 62 of file definition_key.h .
◆ operator()()
@@ -130,7 +137,11 @@ Public Member Functions
diff --git a/docs/html/structSignalKeyHasher.js b/docs/html/structSignalKeyHasher.js
new file mode 100644
index 0000000..9db2749
--- /dev/null
+++ b/docs/html/structSignalKeyHasher.js
@@ -0,0 +1,4 @@
+var structSignalKeyHasher =
+[
+ [ "operator()", "structSignalKeyHasher.html#af8869bcb714857af7ad005fbd13bea80", null ]
+];
\ No newline at end of file
diff --git a/docs/html/tests_2main_8cpp_source.html b/docs/html/tests_2main_8cpp_source.html
index b86748e..d5a1ffe 100644
--- a/docs/html/tests_2main_8cpp_source.html
+++ b/docs/html/tests_2main_8cpp_source.html
@@ -109,15 +109,19 @@ $(document).ready(function(){initNavTree('tests_2main_8cpp_source.html',''); ini
10 int RunValidationTests(
int argc,
char **argv);
- 12 int main(
int argc,
char **argv) {
- 13 QCoreApplication application(argc, argv);
- 14 const int parserResult = RunParserTests(argc, argv);
- 15 const int decoderResult = RunDecoderTests(argc, argv);
- 16 const int coverageResult = RunCoverageTests(argc, argv);
- 17 const int lifetimeResult = RunLifetimeTests(argc, argv);
- 18 const int validationResult = RunValidationTests(argc, argv);
- 19 return validationResult | parserResult | decoderResult | coverageResult | lifetimeResult;
-
+ 12 int RunPipelineTests(
int argc,
char **argv);
+
+ 14 int main (
int argc,
char **argv) {
+ 15 QCoreApplication application(argc, argv);
+ 16 const int parserResult = RunParserTests(argc, argv);
+ 17 const int decoderResult = RunDecoderTests(argc, argv);
+ 18 const int coverageResult = RunCoverageTests(argc, argv);
+ 19 const int lifetimeResult = RunLifetimeTests(argc, argv);
+ 20 const int validationResult = RunValidationTests(argc, argv);
+ 21 const int pipelineResult = RunPipelineTests(argc, argv);
+ 22 return pipelineResult | validationResult | parserResult | decoderResult | coverageResult | lifetimeResult;
+
+int main(int argc, char *argv[])
Parse a DBC file and demonstrate metadata lookup and CAN decoding.
diff --git a/docs/html/tree__node_8cpp.html b/docs/html/tree__node_8cpp.html
index 3c9924c..f469d94 100644
--- a/docs/html/tree__node_8cpp.html
+++ b/docs/html/tree__node_8cpp.html
@@ -94,13 +94,15 @@ $(document).ready(function(){initNavTree('tree__node_8cpp.html',''); initResizab
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Tree node ownership and navigation.
More...
#include "tree_node.h "
+
#include <stdexcept>
Go to the source code of this file.
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Tree node ownership and navigation.
+
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Licensed under the MIT License. See LICENSE file in the project root for full license text.
Definition in file tree_node.cpp .
diff --git a/docs/html/tree__node_8cpp_source.html b/docs/html/tree__node_8cpp_source.html
index da12f4d..928cb47 100644
--- a/docs/html/tree__node_8cpp_source.html
+++ b/docs/html/tree__node_8cpp_source.html
@@ -100,52 +100,50 @@ $(document).ready(function(){initNavTree('tree__node_8cpp_source.html',''); init
Go to the documentation of this file.
-
-
-
-
15 : m_type(
NodeType ::Root), m_name(
"dbc" ) {
-
+
+
+
+
+
16 : m_type(
NodeType ::Root), m_name(
"dbc" ) {
+
-
-
-
-
19 : m_type(
NodeType ::Frame), m_name(frame.name), m_frame(std::make_unique<
FrameInfo >(frame)) {
-
+
+
+
+
20 : m_type(
NodeType ::Frame), m_name(frame.name), m_frame(std::make_unique<
FrameInfo >(frame)) {
+
-
-
-
-
23 : m_type(
NodeType ::Signal), m_name(signal.name), m_signal(std::make_unique<
SignalInfo >(signal)) {
-
+
+
+
+
24 : m_type(
NodeType ::Signal), m_name(signal.name), m_signal(std::make_unique<
SignalInfo >(signal)) {
+
-
-
-
-
-
28 m_children.push_back(std::move(child));
-
29 m_children.back()->m_parent =
this ;
-
30 m_children.back()->m_row = m_children.size() - 1U;
-
-
+
+
+
+
+
29 for (
const TreeNode *ancestor =
this ; ancestor; ancestor = ancestor->m_parent) {
+
30 if (ancestor == child.get())
+
31 throw std::invalid_argument(
"Cannot insert a node into its own subtree" );
+
+
+
34 throw std::invalid_argument(
"Child is already attached" );
+
35 m_children.push_back(std::move(child));
+
36 m_children.back()->m_parent =
this ;
+
37 m_children.back()->m_row = m_children.size() - 1U;
+
+
-
-
-
-
35 return m_children.size();
-
-
-
-
-
-
39 if (index >= m_children.size())
-
-
-
42 return m_children[index].get();
+
+
+
+
42 return m_children.size();
-
+
46 if (index >= m_children.size())
@@ -154,55 +152,87 @@ $(document).ready(function(){initNavTree('tree__node_8cpp_source.html',''); init
+
+
53 if (index >= m_children.size())
+
-
-
-
-
+
56 return m_children[index].get();
+
-
-
-
-
-
+
+
-
-
-
-
65 return m_signal.get();
-
+
+
-
-
-
-
-
+
+
-
-
-
-
-
+
+
+
+
72 return m_signal.get();
+
-
Tree node for later use in model/view or other hierarchy consumers.
-
const SignalInfo * GetSignal() const
Get signal payload if node is signal.
-
const TreeNode * GetChild(std::size_t index) const
Get child by index.
-
void AddChild(std::unique_ptr< TreeNode > child)
Add child node.
-
TreeNode()
Create root node.
-
const TreeNode * GetParent() const
-
const std::string & GetName() const
Get display name.
-
std::size_t GetChildCount() const
Get child count.
-
std::size_t GetRow() const
-
NodeType GetType() const
Get node type.
-
const FrameInfo * GetFrame() const
Get frame payload if node is frame.
-
Describes one CAN frame from a DBC file.
-
Describes one signal inside a DBC frame.
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
-
NodeType
Type of a tree node.
+
+
+
+
+
+
+
+
+
85 return FrameKey (m_frame->canId, m_frame->isExtended);
+
86 if (m_signal && m_parent && m_parent->
GetType () == NodeType::Frame)
+
+
+
+
+
+
+
+
92 const std::optional<FrameKey> frame =
GetFrameKey ();
+
93 if (m_signal && frame)
+
+
+
+
+
Tree node for later use in model/view or other hierarchy consumers.
+
std::optional< SignalKey > GetSignalKey() const
+
const SignalInfo * GetSignal() const
Get signal payload if node is signal.
+
const TreeNode * GetChild(std::size_t index) const
Get child by index.
+
TreeNode()
Create root node.
+
const TreeNode * GetParent() const
+
const std::string & GetName() const
Get display name.
+
std::size_t GetChildCount() const
Get child count.
+
std::size_t GetRow() const
+
std::optional< FrameKey > GetFrameKey() const
+
void AddChild(std::unique_ptr< TreeNode > &&child)
Add child node.
+
NodeType GetType() const
Get node type.
+
const FrameInfo * GetFrame() const
Get frame payload if node is frame.
+
Describes one CAN frame from a DBC file.
+
Stable frame identifier: normalized CAN ID and frame type.
+
Describes one signal inside a DBC frame.
+
+
Qt-independent metadata tree nodes.
+
NodeType
Type of a tree node.
diff --git a/docs/html/tree__node_8h.html b/docs/html/tree__node_8h.html
index 6b7e3ca..a974e6a 100644
--- a/docs/html/tree__node_8h.html
+++ b/docs/html/tree__node_8h.html
@@ -97,12 +97,14 @@ $(document).ready(function(){initNavTree('tree__node_8h.html',''); initResizable
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Qt-independent metadata tree nodes.
More...
#include <cstddef>
#include <memory>
+
#include <optional>
#include <string>
#include <vector>
+
#include "definition_key.h"
#include "frame_info.h "
#include "signal_info.h "
@@ -124,7 +126,8 @@ Enumerations
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Qt-independent metadata tree nodes.
+
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
Licensed under the MIT License. See LICENSE file in the project root for full license text.
Definition in file tree_node.h .
@@ -151,7 +154,7 @@ Enumerations
Type of a tree node.
-
Definition at line 26 of file tree_node.h .
+
Definition at line 28 of file tree_node.h .
diff --git a/docs/html/tree__node_8h_source.html b/docs/html/tree__node_8h_source.html
index 0d8ba1e..ad1f594 100644
--- a/docs/html/tree__node_8h_source.html
+++ b/docs/html/tree__node_8h_source.html
@@ -104,85 +104,94 @@ $(document).ready(function(){initNavTree('tree__node_8h_source.html',''); initRe
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
21 #include "definition_key.h"
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
66 void AddChild (std::unique_ptr<TreeNode> child);
-
-
-
-
72 std::size_t
GetRow ()
const ;
-
-
-
-
+
+
+
+
+
+
+
+
+
+
73 void AddChild (std::unique_ptr<TreeNode> &&child);
+
+
+
+
79 std::size_t
GetRow ()
const ;
+
+
+
+
-
-
-
+
+
+
-
104 const std::string &
GetName ()
const ;
-
-
-
-
-
-
-
-
120 std::size_t m_row = 0U;
-
-
-
123 std::vector<std::unique_ptr<TreeNode>> m_children;
-
124 std::unique_ptr<FrameInfo> m_frame;
-
125 std::unique_ptr<SignalInfo> m_signal;
-
+
+
+
+
+
117 const std::string &
GetName ()
const ;
+
+
+
+
+
+
+
+
133 std::size_t m_row = 0U;
+
+
+
136 std::vector<std::unique_ptr<TreeNode>> m_children;
+
137 std::unique_ptr<FrameInfo> m_frame;
+
138 std::unique_ptr<SignalInfo> m_signal;
+
-
-
-
Tree node for later use in model/view or other hierarchy consumers.
-
const SignalInfo * GetSignal() const
Get signal payload if node is signal.
-
const TreeNode * GetChild(std::size_t index) const
Get child by index.
-
void AddChild(std::unique_ptr< TreeNode > child)
Add child node.
-
TreeNode()
Create root node.
-
const TreeNode * GetParent() const
-
const std::string & GetName() const
Get display name.
-
std::size_t GetChildCount() const
Get child count.
-
std::size_t GetRow() const
-
NodeType GetType() const
Get node type.
-
const FrameInfo * GetFrame() const
Get frame payload if node is frame.
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
-
Describes one CAN frame from a DBC file.
-
Describes one signal inside a DBC frame.
-
NodeType
Type of a tree node.
+
+
+
Tree node for later use in model/view or other hierarchy consumers.
+
std::optional< SignalKey > GetSignalKey() const
+
const SignalInfo * GetSignal() const
Get signal payload if node is signal.
+
const TreeNode * GetChild(std::size_t index) const
Get child by index.
+
TreeNode()
Create root node.
+
const TreeNode * GetParent() const
+
const std::string & GetName() const
Get display name.
+
std::size_t GetChildCount() const
Get child count.
+
std::size_t GetRow() const
+
std::optional< FrameKey > GetFrameKey() const
+
void AddChild(std::unique_ptr< TreeNode > &&child)
Add child node.
+
NodeType GetType() const
Get node type.
+
const FrameInfo * GetFrame() const
Get frame payload if node is frame.
+
Parsed CAN frame metadata.
+
Parsed CAN signal metadata.
+
Describes one CAN frame from a DBC file.
+
Describes one signal inside a DBC frame.
+
NodeType
Type of a tree node.
diff --git a/docs/html/tree__node__test_8cpp_source.html b/docs/html/tree__node__test_8cpp_source.html
index 91d7fb2..539ce1d 100644
--- a/docs/html/tree__node__test_8cpp_source.html
+++ b/docs/html/tree__node__test_8cpp_source.html
@@ -100,49 +100,126 @@ $(document).ready(function(){initNavTree('tree__node__test_8cpp_source.html','')
-
-
-
-
6 static void Check(
bool condition) {
-
7 if (!condition)
throw std::runtime_error(
"Tree navigation test failed" );
-
-
-
-
11 static_assert (!std::is_move_constructible<TreeNode>::value,
"Node addresses must be stable" );
-
-
-
-
15 frame.signals.push_back(signal);
-
16 frame.signals.push_back(signal);
-
17 database.
frames .push_back(frame);
-
18 database.
frames .push_back(frame);
-
-
20 Check(root->GetParent() ==
nullptr && root->GetRow() == 0);
-
21 root->AddChild(
nullptr );
-
22 Check(root->GetChildCount() == 2 && !root->GetChild(2));
-
23 for (std::size_t row = 0; row < root->GetChildCount(); ++row) {
-
-
-
26 for (std::size_t position = 0; position < child->
GetChildCount (); ++position) {
-
-
-
-
-
31 std::unique_ptr<TreeNode> transferred = std::move(root);
-
32 Check(transferred->GetChild(0)->GetParent() == transferred.get());
-
+
+
+
+
+
7 static void Check(
bool condition) {
+
8 if (!condition)
throw std::runtime_error(
"Tree navigation test failed" );
+
+
+
11 static void CheckNavigation(
const TreeNode &node) {
+
12 for (std::size_t row = 0; row < node.
GetChildCount (); ++row) {
+
+
+
+
16 CheckNavigation(*child);
+
+
+
19 Check(!node.
GetChild (std::numeric_limits<std::size_t>::max()));
+
+
+
22 static void CheckRejectedInsertion(
TreeNode &parent, std::unique_ptr<TreeNode> &owner) {
+
23 const TreeNode *original = owner.get();
+
24 bool rejected =
false ;
+
+
+
27 }
catch (
const std::invalid_argument &) {
+
+
+
30 Check(rejected && owner.get() == original);
+
31 CheckNavigation(*owner);
+
+
+
+
35 static_assert (!std::is_copy_constructible<TreeNode>::value,
"Nodes have exclusive ownership" );
+
36 static_assert (!std::is_copy_assignable<TreeNode>::value,
"Nodes have exclusive ownership" );
+
37 static_assert (!std::is_move_constructible<TreeNode>::value,
"Node addresses must be stable" );
+
38 static_assert (!std::is_move_assignable<TreeNode>::value,
"Node addresses must be stable" );
+
+
+
+
+
+
+
+
46 signal.
name =
"Value" ;
+
47 frame.signals.push_back(signal);
+
48 signal.
name =
"Other" ;
+
49 frame.signals.push_back(signal);
+
50 database.
frames .push_back(frame);
+
+
52 database.
frames .push_back(frame);
+
+
54 Check(root->GetParent() ==
nullptr && root->GetRow() == 0);
+
55 Check(!root->GetFrameKey() && !root->GetSignalKey());
+
56 root->AddChild(
nullptr );
+
57 Check(root->GetChildCount() == 2 && !root->GetChild(2));
+
58 Check(!root->GetChild(std::numeric_limits<std::size_t>::max()));
+
59 CheckNavigation(*root);
+
+
+
+
63 const FrameKey standard(123U,
false );
+
+
+
+
+
+
69 Check(root->GetChild(1)->GetFrameKey() == extended);
+
70 Check(root->GetChild(1)->GetChild(0)->GetSignalKey() ==
SignalKey (extended,
"Value" ));
+
+
+
73 Check(!detached.GetFrameKey() && !detached.GetSignalKey());
+
74 Check(!detached.GetParent() && detached.GetRow() == 0);
+
+
76 Check(detachedFrame.GetFrameKey() == extended && !detachedFrame.GetSignalKey());
+
+
+
+
80 database.
frames .push_back(frame);
+
+
82 Check(replacement->GetChild(0)->GetFrameKey() == root->GetChild(1)->GetFrameKey());
+
+
+
+
86 for (std::size_t index = 0; index < 64; ++index) {
+
87 root->AddChild(std::make_unique<TreeNode>(frame));
+
88 root->GetChild(0)->AddChild(std::make_unique<TreeNode>(signal));
+
+
90 Check(root->GetChild(0) == firstFrame && firstFrame->
GetChild (0) == firstSignal);
+
91 CheckNavigation(*root);
+
92 CheckRejectedInsertion(*root, root);
+
93 CheckRejectedInsertion(*root->GetChild(0)->GetChild(0), root);
+
+
95 const TreeNode *original = root.get();
+
96 std::unique_ptr<TreeNode> transferred = std::move(root);
+
97 Check(!root && transferred.get() == original);
+
98 CheckNavigation(*transferred);
+
+
Builds a simple tree from parsed DBC database.
std::unique_ptr< TreeNode > Build(const DbcDatabase &database) const
Build tree representation of parsed DBC data.
-
Tree node for later use in model/view or other hierarchy consumers.
-
const TreeNode * GetChild(std::size_t index) const
Get child by index.
-
const TreeNode * GetParent() const
-
std::size_t GetChildCount() const
Get child count.
-
std::size_t GetRow() const
-
Created: 2026-03-13 Author: Deeaitch (Dim. Himro)
+
Tree node for later use in model/view or other hierarchy consumers.
+
std::optional< SignalKey > GetSignalKey() const
+
const TreeNode * GetChild(std::size_t index) const
Get child by index.
+
const TreeNode * GetParent() const
+
std::size_t GetChildCount() const
Get child count.
+
std::size_t GetRow() const
+
std::optional< FrameKey > GetFrameKey() const
+
void AddChild(std::unique_ptr< TreeNode > &&child)
Add child node.
+
+
int main(int argc, char *argv[])
Parse a DBC file and demonstrate metadata lookup and CAN decoding.
Parsed DBC content stored in a simple internal form.
std::vector< FrameInfo > frames
-
Describes one CAN frame from a DBC file.
-
Describes one signal inside a DBC frame.
+
Describes one CAN frame from a DBC file.
+
+
+
+
Stable frame identifier: normalized CAN ID and frame type.
+
Describes one signal inside a DBC frame.
+
+
diff --git a/docs/html/typefactory_8h_source.html b/docs/html/typefactory_8h_source.html
index 5d8b258..26ef7cb 100644
--- a/docs/html/typefactory_8h_source.html
+++ b/docs/html/typefactory_8h_source.html
@@ -113,58 +113,60 @@ $(document).ready(function(){initNavTree('typefactory_8h_source.html',''); initR
-
61 using BasePtr = std::shared_ptr<BaseClass>;
-
62 using CreatorFn = BasePtr (*)(Args...);
-
-
+
62 using BasePtr = std::shared_ptr<BaseClass>;
+
-
75 template <
class Derived>
-
-
-
77 static_assert (std::is_base_of_v<BaseClass, Derived>,
-
78 "Derived must inherit from BaseClass" );
-
79 static_assert (std::is_constructible_v<Derived, Args...>,
-
80 "Derived must be constructible from Args..." );
-
-
82 classes.insert_or_assign(
id , &instantiate<Derived>);
-
+
+
+
77 template <
class Derived>
+
+
+
79 static_assert (std::is_base_of_v<BaseClass, Derived>,
+
80 "Derived must inherit from BaseClass" );
+
81 static_assert (std::is_constructible_v<Derived, Args...>,
+
82 "Derived must be constructible from Args..." );
+
+
84 classes .insert_or_assign(
id , &instantiate<Derived>);
+
-
-
-
89 [[nodiscard]] CreatorFn
creator (
const ClassId &
id )
const {
-
90 return classes.at(
id );
-
+
+
-
-
-
97 [[nodiscard]] BasePtr
create (
const ClassId &
id , Args... args)
const {
-
98 return creator (
id )(std::move(args)...);
-
+
+
+
+
100 return creator (
id )(std::move(args)...);
+
-
-
-
104 [[nodiscard]]
bool contains (
const ClassId &
id )
const {
-
105 return classes.find(
id ) != classes.end();
-
+
+
+
106 [[nodiscard]]
bool contains (
const ClassId &
id )
const {
+
+
-
-
-
-
110 std::unordered_map<ClassId, CreatorFn> classes;
-
-
-
113 template <
class Derived>
-
114 static BasePtr instantiate(Args... args) {
-
115 return std::make_shared<Derived>(std::move(args)...);
-
-
+
+
+
112 std::unordered_map<ClassId, CreatorFn>
classes ;
+
+
+
115 template <
class Derived>
+
116 static BasePtr instantiate(Args... args) {
+
117 return std::make_shared<Derived>(std::move(args)...);
+
+
-
+
Registry-based factory for creating objects by runtime identifier.
-
bool contains(const ClassId &id) const
Checks whether an id is registered.
-
BasePtr create(const ClassId &id, Args... args) const
Creates an instance for the given id using provided arguments.
-
void registerType(const ClassId &id)
Registers a Derived type under the given id.
-
CreatorFn creator(const ClassId &id) const
Returns creator function for the given id.
+
bool contains(const ClassId &id) const
Checks whether an id is registered.
+
std::shared_ptr< BaseClass > BasePtr
Shared ownership handle returned for created instances.
+
BasePtr create(const ClassId &id, Args... args) const
Creates an instance for the given id using provided arguments.
+
std::unordered_map< ClassId, CreatorFn > classes
Registered creators; accessible to derived factories.
+
BasePtr(*)(Args...) CreatorFn
Registered creator function signature.
+
void registerType(const ClassId &id)
Registers a Derived type under the given id.
+
CreatorFn creator(const ClassId &id) const
Returns creator function for the given id.