diff --git a/docs/dbcframework.tag b/docs/dbcframework.tag
index 6574055..5d274c9 100644
--- a/docs/dbcframework.tag
+++ b/docs/dbcframework.tag
@@ -234,6 +234,20 @@
(const DbcDatabase &database) const
+
+ DbcTreeModel
+ classDbcTreeModel.html
+
+
+ DbcUnsupportedMultiplexingHandler
+ classDbcUnsupportedMultiplexingHandler.html
+ DbcStatementHandler
+
+
+ DbcValueDescriptionHandler
+ classDbcValueDescriptionHandler.html
+ DbcStatementHandler
+ DecodeDatabasestructDecodeDatabase.html
@@ -266,6 +280,13 @@
DecodedSignalValuestructDecodedSignalValue.html
+
+ const std::string *
+ GetValueDescription
+ structDecodedSignalValue.html
+ affc38af1bf31bcb6f2c33044bce92bd2
+ () const
+ const DecodeSignal *definition
@@ -274,10 +295,10 @@
- std::variant< std::int64_t, std::uint64_t >
+ RawSignalValuerawValuestructDecodedSignalValue.html
- a95db4f7f93b5f311e8f272833e45055e
+ a503c90b4b1a610b8252c45e466367c28
@@ -442,6 +463,13 @@
abdbae62a64d2df716bf60c6b67b30eaa
+
+ ValueDescriptions
+ valueDescriptions
+ structDecodeSignal.html
+ a822155d9bf4ed5f3300c9e9befe606ff
+
+ std::stringcomment
@@ -525,6 +553,14 @@
FrameKeyHasherstructFrameKeyHasher.html
+
+ Multiplexing
+ structMultiplexing.html
+
+
+ PendingValueDescriptions
+ structPendingValueDescriptions.html
+ RawCanFramestructRawCanFrame.html
@@ -630,6 +666,13 @@
a2c95562fd0b29327a7fd7b1e6feee7f3
+
+ ValueDescriptions
+ valueDescriptions
+ structSignalInfo.html
+ a43f47d0433d0cc39076bd7278b46af9c
+
+ std::stringcomment
@@ -669,6 +712,20 @@
a6161f2ebb92184eab4215d121870e788(std::unique_ptr< TreeNode > child)
+
+ const TreeNode *
+ GetParent
+ classTreeNode.html
+ aa48fbc17903eb8cfa40353e29f853c6f
+ () const
+
+
+ std::size_t
+ GetRow
+ classTreeNode.html
+ ad501f97eeec7f7d3353bfae838fbb6a8
+ () const
+ std::size_tGetChildCount
@@ -754,6 +811,11 @@
(const ClassId &id) const
+
+ md_changelog
+ Changelog
+ md_changelog.html
+ md_READMEDBC Parser and Runtime Decode Module Documentation
diff --git a/docs/doxygen_warnings.log b/docs/doxygen_warnings.log
index b9602aa..efcd3df 100644
--- a/docs/doxygen_warnings.log
+++ b/docs/doxygen_warnings.log
@@ -1,24 +1,55 @@
-/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:38: warning: Compound DbcCommentHandler is not documented.
-/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:22: warning: Compound DbcFrameHandler is not documented.
-/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:30: warning: Compound DbcSignalHandler is not documented.
-/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:16: warning: Compound DbcStatementHandler is not documented.
-/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/examples/main.cpp:101: warning: Member main(int argc, char *argv[]) (function) of file examples/main.cpp is not documented.
-/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:40: warning: Member Handle(const std::string &line, DbcParseContext &context) const override (function) of class DbcCommentHandler is not documented.
-/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:24: warning: Member Handle(const std::string &line, DbcParseContext &context) const override (function) of class DbcFrameHandler is not documented.
-/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:12: warning: Member database (variable) of struct DbcParseContext is not documented.
-/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:13: warning: Member currentFrame (variable) of struct DbcParseContext is not documented.
-/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:32: warning: Member Handle(const std::string &line, DbcParseContext &context) const override (function) of class DbcSignalHandler is not documented.
-/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:52: warning: Member RegisterType(const std::string &keyword) (function) of class DbcStatementDispatcher is not documented.
-/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:19: warning: Member Handle(const std::string &line, DbcParseContext &context) const =0 (function) of class DbcStatementHandler is not documented.
-/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:112: warning: Member frames (variable) of struct DecodeDatabase is not documented.
-/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:113: warning: Member frameIndexByKey (variable) of struct DecodeDatabase is not documented.
-/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:88: warning: Member FrameKey(std::uint32_t id, bool extended) (function) of struct FrameKey is not documented.
-/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:92: warning: Member operator==(const FrameKey &other) const (function) of struct FrameKey is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:53: warning: Compound DbcCommentHandler is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:37: warning: Compound DbcFrameHandler is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:45: warning: Compound DbcSignalHandler is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:31: warning: Compound DbcStatementHandler is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:66: warning: Compound DbcUnsupportedMultiplexingHandler is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:61: warning: Compound DbcValueDescriptionHandler is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:10: warning: Compound PendingValueDescriptions is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_decoder.h:32: warning: Member SignalDecodeStatus (enumeration) of file dbc_decoder.h is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/examples/main.cpp:100: warning: Member main(int argc, char *argv[]) (function) of file examples/main.cpp is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/README.md:1314: warning: end of comment block while expecting command
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:55: warning: Member Handle(const std::string &line, DbcParseContext &context) const override (function) of class DbcCommentHandler is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:39: warning: Member Handle(const std::string &line, DbcParseContext &context) const override (function) of class DbcFrameHandler is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:26: warning: Member ValidateMultiplexing(const std::string &filePath) const (function) of struct DbcParseContext is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:28: warning: Member ResolveValueDescriptions(const std::string &filePath) (function) of struct DbcParseContext is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:20: warning: Member database (variable) of struct DbcParseContext is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:21: warning: Member currentFrame (variable) of struct DbcParseContext is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:22: warning: Member lineNumber (variable) of struct DbcParseContext is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:23: warning: Member pendingValues (variable) of struct DbcParseContext is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:25: warning: Member signalLines (variable) of struct DbcParseContext is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:47: warning: Member Handle(const std::string &line, DbcParseContext &context) const override (function) of class DbcSignalHandler is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:77: warning: Member RegisterType(const std::string &keyword) (function) of class DbcStatementDispatcher is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:34: warning: Member Handle(const std::string &line, DbcParseContext &context) const =0 (function) of class DbcStatementHandler is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/qt/dbc_tree_model.h:13: warning: Member Column (enumeration) of class DbcTreeModel is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/qt/dbc_tree_model.h:24: warning: Member Role (enumeration) of class DbcTreeModel is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/qt/dbc_tree_model.h:36: warning: Member DbcTreeModel(QObject *parent=nullptr) (function) of class DbcTreeModel is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/qt/dbc_tree_model.h:37: warning: Member SetTree(std::unique_ptr< TreeNode > root) (function) of class DbcTreeModel is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/qt/dbc_tree_model.h:38: warning: Member index(int row, int column, const QModelIndex &parent=QModelIndex()) const override (function) of class DbcTreeModel is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/qt/dbc_tree_model.h:39: warning: Member parent(const QModelIndex &child) const override (function) of class DbcTreeModel is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/qt/dbc_tree_model.h:40: warning: Member rowCount(const QModelIndex &parent=QModelIndex()) const override (function) of class DbcTreeModel is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/qt/dbc_tree_model.h:41: warning: Member columnCount(const QModelIndex &parent=QModelIndex()) const override (function) of class DbcTreeModel is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/qt/dbc_tree_model.h:42: warning: Member data(const QModelIndex &index, int role=Qt::DisplayRole) const override (function) of class DbcTreeModel is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/qt/dbc_tree_model.h:43: warning: Member headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override (function) of class DbcTreeModel is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/qt/dbc_tree_model.h:44: warning: Member flags(const QModelIndex &index) const override (function) of class DbcTreeModel is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:68: warning: Member Handle(const std::string &line, DbcParseContext &context) const override (function) of class DbcUnsupportedMultiplexingHandler is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:63: warning: Member Handle(const std::string &line, DbcParseContext &context) const override (function) of class DbcValueDescriptionHandler is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:110: warning: Member frames (variable) of struct DecodeDatabase is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:111: warning: Member frameIndexByKey (variable) of struct DecodeDatabase is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_decoder.h:48: warning: Member status (variable) of struct DecodedSignalValue is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:42: warning: Member multiplexing (variable) of struct DecodeSignal is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:86: warning: Member FrameKey(std::uint32_t id, bool extended) (function) of struct FrameKey is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:90: warning: Member operator==(const FrameKey &other) const (function) of struct FrameKey is not documented.
/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:81: warning: Member canId (variable) of struct FrameKey is not documented.
/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:82: warning: Member isExtended (variable) of struct FrameKey is not documented.
-/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:101: warning: Member operator()(const FrameKey &key) const (function) of struct FrameKeyHasher is not documented.
-/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/tree_node.h:59: warning: Member TreeNode(TreeNode &&)=default (function) of class TreeNode is not documented.
-/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/tree_node.h:60: warning: Member operator=(TreeNode &&)=default (function) of class TreeNode is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/decode_database.h:99: warning: Member operator()(const FrameKey &key) const (function) of struct FrameKeyHasher is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/multiplexing.h:15: warning: Member role (variable) of struct Multiplexing is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/multiplexing.h:16: warning: Member value (variable) of struct Multiplexing is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:11: warning: Member canId (variable) of struct PendingValueDescriptions is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:12: warning: Member isExtended (variable) of struct PendingValueDescriptions is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:13: warning: Member signalName (variable) of struct PendingValueDescriptions is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:14: warning: Member descriptions (variable) of struct PendingValueDescriptions is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/dbc_statement_handler.h:15: warning: Member lineNumber (variable) of struct PendingValueDescriptions is not documented.
+/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/signal_info.h:25: warning: Member multiplexing (variable) of struct SignalInfo is not documented.
/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/typefactory.h:61: warning: Member BasePtr (typedef) of class TypeFactory is not documented.
/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/typefactory.h:62: warning: Member CreatorFn (typedef) of class TypeFactory is not documented.
/home/deeaitch/work/3.projects/git.himro.ca/automotive/dbc/core/typefactory.h:110: warning: Member classes (variable) of class TypeFactory is not documented.
diff --git a/docs/html/annotated.html b/docs/html/annotated.html
index 8c4c0bf..107b0a9 100644
--- a/docs/html/annotated.html
+++ b/docs/html/annotated.html
@@ -106,18 +106,23 @@ $(document).ready(function(){initNavTree('annotated.html',''); initResizable();
on file or parse errors. Line parse errors include the file path and one-based line number.
+
std::runtime_error
on file or parse errors. Line parse errors include the file path and one-based line number. Duplicate normalized CAN IDs of the same frame type and duplicate signal names within a frame are rejected at the repeated definition's line.
diff --git a/docs/html/hierarchy.html b/docs/html/hierarchy.html
index fe782d1..6f9a9f6 100644
--- a/docs/html/hierarchy.html
+++ b/docs/html/hierarchy.html
@@ -107,6 +107,8 @@ This inheritance list is sorted roughly, but not completely, alphabetically:
DBC Parser and Runtime Decode Module Documentation
-
-
+
+
Overview
This module provides a minimal but extensible DBC parser and runtime decode foundation for the FrameTap project.
Its purpose is to:
@@ -113,12 +113,13 @@ Overview
Qt is not required at the parser or decoder level
the same decode engine can be reused for live traffic and trace replay
-
This is not a full production-grade DBC implementation yet, but it is a strong architectural base.
+
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/.
The tree is intended for browsing and later Qt model integration.
+
The tree supports browsing through the optional DbcTreeModel adapter.
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:
@@ -339,7 +311,7 @@ Purpose
This is better for decode code than passing around raw DBC characters.
-
+
<tt>ValueType</tt>
Numeric type enum:
@@ -348,7 +320,7 @@ Purpose
This is clearer than combining multiple boolean flags during runtime logic.
-
+
<tt>DecodeSignal</tt>
Represents one runtime-ready signal definition.
Fields:
@@ -368,7 +340,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:
@@ -385,7 +357,7 @@ Purpose
This structure is used directly by the decoder.
-
+
<tt>FrameKey</tt>
Fast lookup key for runtime frame matching.
Fields:
@@ -395,7 +367,7 @@ Purpose
This matters because the same numeric identifier must not be confused between standard and extended frames.
-
+
<tt>DecodeDatabase</tt>
Top-level runtime decode container.
Fields:
@@ -409,9 +381,9 @@ Purpose
└── unordered_map<FrameKey, index>
This gives the decoder fast access to a frame definition using CAN ID and frame type.
-
+
Decoder Layer
-
+
<tt>RawCanFrame</tt>
Represents a raw CAN frame to decode.
Fields:
@@ -427,7 +399,7 @@ Decoder Layer
unit tests
-
+
<tt>DecodedSignalValue</tt>
Represents one decoded signal result.
Fields:
@@ -436,13 +408,14 @@ Decoder Layer
rawValue
physicalValue
valid
+
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 value; an invalid result's default value is not decoded data.
+
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 value; an invalid result's default value is not decoded data.
Use std::get when the numeric type is known, or std::get_if to handle both:
-
if (constauto *value = std::get_if<std::int64_t>(&decodedSignal.rawValue)) {
+
if (const std::int64_t *value = std::get_if<std::int64_t>(&decodedSignal.rawValue)) {
@@ -450,7 +423,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:
@@ -459,15 +432,16 @@ Raw value representation and precision
signals
valid
-
This is the decoder output for one raw frame.
+
valid means a matching frame definition was found. Check each signal's valid separately: insufficient payload data can leave individual signals invalid even when the frame is valid. An unknown frame returns valid == false.
+
The frame and signal definition pointers refer into DecodeDatabase. Keep that database alive and avoid changes that invalidate its frame or signal storage while using decoded results. The decoder applies factor and offset; it does not clamp physical values to the declared minimum and maximum.
-
+
<tt>DbcDecoder</tt>
Main runtime decoder class.
Responsibilities:
find a frame definition by CAN ID
-
decode all signals in a frame
+
decode unconditional signals and the active multiplexed branch
extract raw values
sign-extend signed values
convert raw values into physical values
@@ -478,7 +452,7 @@ Raw value representation and precision
Decode(...)
-
+
Parser Support
The current parser supports the following DBC elements:
@@ -486,11 +460,13 @@ Parser Support
SG_
CM_ BO_
CM_ SG_
+
VAL_ signal value descriptions
+
basic M / mN multiplexing
-
+
Supported DBC Syntax
-
+
Frame definition
Example:
BO_ 256 EngineData: 8 EEC1
@@ -502,16 +478,16 @@ 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.
The payload length must fit uint8_t (0..255). This is a storage-range check, not CAN or CAN FD protocol validation; no new 8-byte or 64-byte limit is imposed.
Parsing stops at the first detected error. Exceptions raised while parsing a line are reported as std::runtime_error with the supplied file path and the one-based physical line number, including blank lines:
example.dbc:3: Invalid CAN ID: invalid
-
This change validates frame definitions. Signal definitions are also validated as described below; comprehensive DBC grammar coverage is still planned. File-open errors contain the path but have no line number.
+
Frame and signal definitions are validated as described here; comprehensive DBC grammar coverage is still planned. File-open errors contain the path but have no line number.
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.
-
Multiplexing markers (M, mN, and combinations) are currently rejected rather than interpreted as part of a signal name. Multiplexing support and duplicate frame/signal detection remain separate work.
+
Basic multiplexing markers M and mN are supported as described below. Overlapping signals are rejected unless their branch values differ. Duplicate frame/signal name detection remains separate work.
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
+
SG_ Temperature m1 : 8|8@1- (1,0) [-128|127] "C" ECU
+
SG_ Pressure m2 : 8|8@1+ (2,0) [0|510] "kPa" ECU
+
SG_ Counter : 16|8@1+ (1,0) [0|255] "" ECU
+
SignalInfo and DecodeSignal contain multiplexing: a MultiplexRole (Unconditional, Selector, or Branch) and an exact uint64_t branch value. Each frame may have one unsigned selector (M); a branch (mN) references that selector implicitly. The selector may appear after its branches. N must contain only decimal digits, fit uint64_t, and fit the selector's bit width. Leading zeros are accepted. A selector without branches is allowed. Signed selectors, missing selectors, multiple selectors, nested/combined markers, and extended SG_MUL_VAL_ statements are rejected with the originating path:line. The dispatcher registers the unsupported statement handler through TypeFactory.
+
Signal bits may overlap only between branches with different selector values. This validation uses Intel or Motorola bit traversal, including mixed byte orders. It also rejects overlapping unconditional signals. Metadata survives the runtime and tree builders; the optional Qt adapter does not add multiplexing roles yet.
+
The shared decoder extracts the selector before processing branches, compares its raw unsigned value, and leaves result order equal to definition order. Factor, offset, and VAL_ descriptions do not influence branch selection. Unconditional signals continue to decode. An unmapped selector value leaves all branches inactive.
+
Each result has SignalDecodeStatus status:
+
+
+
Status
Meaning
+
+
Valid
Raw and physical values are available; valid == true
+
+
Inactive
Selector is available and chooses another branch
+
+
SelectorUnavailable
Branch activation is unknown because selector bytes are missing
+
+
InsufficientPayload
Selected or unconditional signal bytes are missing
+
+
InvalidDefinition
Invalid bit length or missing/invalid selector in manually built runtime metadata
+
+
All statuses except Valid have valid == false; their numeric fields contain no decoded data and GetValueDescription() returns nullptr. Check status to distinguish inactive branches from errors. Consumers constructing runtime metadata manually must obey the same non-overlap rules as the parser. Extended and nested multiplexing are outside this stage and are explicitly rejected, rather than silently decoded as unconditional signals.
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:
RegisterType<DbcValueHandler>("VAL_"); // after implementing DbcValueHandler
-
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 remain ignored. SG_ accepts spaces and tabs after its keyword; CM_ retains its existing policy requiring a literal space.
+
RegisterType<MyCustomHandler>("CUSTOM_"); // after implementing MyCustomHandler
+
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 remain ignored. 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.
-
-Current Limitations
-
This is still a minimal implementation.
-
Not supported yet:
-
-
multiplexed signals
-
VAL_ tables
-
BA_ attributes
-
BA_DEF_ definitions
-
advanced comment handling
-
full DBC grammar coverage
-
full J1939 validation
-
extensive edge-case handling for unusual DBC formatting
-
-
Motorola extraction is implemented, but it should still be verified carefully against real-world DBC files and expected values.
The module does not depend on any specific build system.
-
It can be integrated with:
-
-
CMake
-
qmake
-
Makefile
-
-
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 (Qt 6; use qmake for Qt 5):
-
mkdir build
-
cd build
-
qmake6 ../dbc.pro
+
+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 and mapping remain alive and unchanged.
+
+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_md108 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
+- 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 ignored
+- 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_md110 Recommended Next Steps
+
+A practical development order would be:
+
+@subsection autotoc_md111 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_md112 Stage 2
+
+Recommended additions:
+
+- selective decoding of only chosen signals
+
+@subsection autotoc_md113 Stage 3
+
+Recommended additions:
+
+- basic multiplexing (implemented)
+- attribute parsing
+- richer J1939 support
+- CSV export of decoded traces
+- optimized filtering and signal selection
+
+@subsection autotoc_md114 Stage 4
+
+Advanced functionality:
+
+- live plot integration
+- signal subscriptions
+- per-signal trace decode pipelines
+- decoder-assisted export formats
+
+<hr>
+
+@section autotoc_md116 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_md117 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_md118 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:
+
+
+
Role
Node types
QVariant content
+
+
NodeTypeRole
Frame, signal
int corresponding to NodeType
+
+
CanIdRole, PayloadLengthRole, ExtendedRole
Frame
uint, int, bool
+
+
StartBitRole, BitLengthRole
Signal
uint
+
+
LittleEndianRole, SignedRole
Signal
bool
+
+
UnitRole
Signal
QString
+
+
CommentRole
Frame, signal
QString
+
+
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.
+
+
+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 \
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.
-
The former demonstration program is preserved in examples/main.cpp with examples/demo.pro. Build it separately after building core, using that same DBC_CORE_BUILD_DIR option; run dbc_demo <file.dbc>.
-
-
-Summary
-
This module is now split into two intentionally separate layers:
-
-Parsed representation
-
Used for:
-
-
storing parsed DBC content
-
browsing
-
UI tree generation
-
-
-Runtime decode representation
-
Used for:
-
-
fast frame lookup
-
live CAN decode
-
trace decode
-
physical value conversion
-
-
That separation is the main architectural improvement.
This gives FrameTap a much better foundation for real use, because both browsing and decoding are supported without forcing one representation to do the other's job.
-
+
./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.
+
+
+Generate API documentation
+
+
With Doxygen installed, run from the repository root:
+
doxygen Doxyfile
+
+
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, 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.
+
+
+Measuring code coverage
+
+
Coverage instrumentation is separate from the QtTest suite named CoverageTest: that suite runs extra regression checks, but coverage counters require a specially instrumented build. Use a separate build directory for each coverage tool.
GCC 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
+
+
qmake6 "$DBC_SOURCE_DIR/dbc.pro" \
+
CONFIG+=dbc_qt CONFIG+=debug CONFIG-=release \
+
'QMAKE_CXXFLAGS+=--coverage -fprofile-abs-path' \
+
'QMAKE_LFLAGS+=--coverage'
+
make -j4
+
+
# The standalone tree test is not a qmake target; instrument it separately.
+
mkdir -p standalone
+
c++ -std=c++17 -O0 -g --coverage -fprofile-abs-path \
+
-I"$DBC_SOURCE_DIR/core" \
+
"$DBC_SOURCE_DIR/tests/tree_node_test.cpp" \
+
"$DBC_SOURCE_DIR/core/tree_node.cpp" \
+
"$DBC_SOURCE_DIR/core/dbc_tree_builder.cpp" \
+
-o standalone/tree_node_tests
+
+
# Capture a zero-count baseline so unexecuted compiled code remains in the report.
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).
Run qmake and build the project. Both dbc_tests and dbc_model_tests must run to include coverage from the core and optional model adapter.
+
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.
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-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.
+
Added direct-handler and resolver tests for unsupported comments and ambiguous VAL_ references in manually constructed databases.
+
Documented GCC/gcov/LCOV instrumentation, Qt Creator setup, and HTML reports. Coverage after the added tests: 98.4% of lines and 71.4% of branches with GCC 14.2 and Qt 6.8.2, including the standalone tree test.
+
Basic M / mN multiplexing metadata in parsed, tree, and runtime definitions.
+
Deferred selector and overlap validation with source locations: one unsigned selector, representable branch values, and overlaps only between exclusive branches.
+
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.
+
Used explicit local types in the additional coverage and model tests. Functions retain explicit return types, and runtime handler selection uses TypeFactory without lambdas or extra factory layers for concrete objects.
+
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.
+
Accepted tabs after CM_ by using the comment parser's keyword extraction instead of requiring a literal-space prefix.
+
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.
+
Added optional read-only Qt Core DbcTreeModel with documented columns and metadata roles, exact VAL_ entries, exclusive tree ownership, and reset-based reload/clear support. Core remains independent of Qt.
+
Added QAbstractItemModelTester coverage, navigation/metadata/reset tests, a standalone Qt-free tree test, and adapter build and usage documentation.
+
Added VAL_ signal value descriptions through the statement dispatcher and factory, with complete syntax validation, exact signed/unsigned 64-bit keys, deferred reference resolution, duplicate detection, and source error locations. Distinct keys from multiple statements merge; standard and extended frames remain distinct under existing CAN ID normalization.
+
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)
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.
-
Build from the repository root with Qt 6 (use qmake for Qt 5):
+
For instrumented builds, LCOV HTML reports, and Qt Creator coverage configuration, see Measuring code coverage.
+
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
cd build
qmake6 ../dbc.pro
make -j
make check
-
Or run ./tests/dbc_tests directly. Both parser and decoder suites run, and the executable returns nonzero when either 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, 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:
parser_tests.pri and decoder_tests.pri include the test sources. ../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. ../core/core.pri supplies the library include path and linkage.
+
Decoder coverage
Coverage includes Motorola bit numbering within and across bytes, unaligned signals, signed values, scaling, 64-bit extraction, signed/unsigned boundary values (including INT64_MIN, INT64_MAX, and UINT64_MAX), numeric output, invalid lengths, insufficient payloads, and Intel regression cases. Frame validity means the definition was found; insufficient payloads are checked through signal validity.
-
+
Parser coverage
-
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. 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. 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.
+
Parser tests cover standard and extended CAN IDs, whitespace, payload storage boundaries, missing fields, malformed and overflowing numbers, reserved ID bits, error paths and line numbers, and integration with signals and comments. Duplicate definitions are rejected at their source lines, including equivalent extended ID encodings and repeated signal names within a frame. Standard and extended frames may share a numeric ID, and separate frames may reuse signal names. Signal tests cover complete syntax and numeric validation, scientific notation, finite physical parameters and ordered ranges, spaces and tabs, receiver lists, unsupported multiplexing, and Intel/Motorola declared-payload boundaries. Value-description tests cover full VAL_ syntax, whitespace, escaped quotes, empty text, exact integer boundaries, duplicate keys within and across statements, deferred and normalized frame references, missing targets, error locations, raw lookup with scaling, unknown/invalid values, and both database builders. Temporary DBC fixtures are created in the system temporary directory and removed automatically.
+
Dispatch tests also verify exact keyword matching, handler construction and reuse, unknown statements, and independent parsing sessions, including recovery after errors.
+
+Tree and optional model tests
+
tree_node_test.cpp is a standalone C++17 executable without Qt; see the root README for its compiler command. It checks parents, sibling positions, null children, bounds, and unique_ptr transfer.
+
Enable CONFIG+=dbc_qt in the root qmake invocation to build dbc_qt and dbc_model_tests alongside existing tests. Qt 6.8.2 is required. make check runs all suites. Model tests parse a temporary DBC fixture and use QAbstractItemModelTester, verify navigation across columns, invalid/foreign indexes, metadata and exact VAL_ integers, and persistent-index invalidation when reloading or clearing the tree. Their QGuiApplication registers graphical metatypes used by QAbstractItemModelTester, avoiding the invalid QPixmap type warning in Qt 6.8.2. The test executable defaults to QT_QPA_PLATFORM=offscreen when the variable is unset or empty, so no display server is needed. An explicit platform setting is preserved.
+
Basic multiplexing coverage includes selector declarations after branches, Intel/Motorola branch overlap, signed active values and VAL_ lookup, unconditional signals, inactive branches, missing selector/branch payloads, exact UINT64_MAX selector matching, malformed runtime selectors, source locations, and rejection of invalid markers, selector references/ranges, overlaps, and SG_MUL_VAL_.
+
+Additional regression coverage
+
dbc_coverage_test.cpp runs as part of dbc_tests. It covers signed boundaries below 64 bits, deterministic extraction comparisons for both byte orders across lengths 1–64, frame lookup failures, exact decode statuses, malformed runtime multiplexing, PGN boundaries, comment handling, file formatting, metadata copying and source lifetime, physical conversion, and TypeFactory registration/creation. Direct resolver tests construct ambiguous databases through the public metadata API, verify source locations, and check that ambiguous targets receive no values.
+
All QtTest targets use Qt 6.8.2 and QVERIFY_THROWS_EXCEPTION. Exception tests explicitly discard nodiscard results when only the exception is being checked. The standalone tree test requires only a C++17 compiler.