This commit is contained in:
deeaitch committed 2026-10-06 16:54:02 -04:00
1 parent f17ddb6aad
commit 65142fdfe3
2 files changed
+200 -113

No files matched your search

+108 -113
View File
@@ -20,7 +20,13 @@ The implementation follows a simple and practical design:
- 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 Core and Qt Test are
required only for the regression tests. Live CAN acquisition, trace-file readers,
and a Qt model adapter are left to the consuming application.
See [changelog.md](changelog.md) for the release and development history,
[tests/README.md](tests/README.md) for test instructions, and
[generated API documentation](docs/html/index.html) for the API reference.
---
@@ -105,65 +111,24 @@ This avoids forcing UI-oriented structures into a decode role they were not mean
## Module Layout
### Parsed DBC structures
```text
core/ C++17 parser, statement handlers, metadata, tree, and decoder
examples/ Command-line demo (built separately)
tests/ QtTest parser and decoder regression suites
docs/ Generated Doxygen documentation
dbc.pro Root qmake project: core + tests
Doxyfile API documentation configuration
```
Files:
- `signal_info.h`
- `frame_info.h`
- `dbc_database.h`
These store a readable representation of the parsed DBC file.
### UI tree structures
Files:
- `tree_node.h`
- `tree_node.cpp`
- `dbc_tree_builder.h`
- `dbc_tree_builder.cpp`
These convert parsed DBC content into a tree hierarchy suitable for UI and model/view usage later.
### Runtime decode structures
Files:
- `decode_database.h`
- `dbc_decode_builder.h`
- `dbc_decode_builder.cpp`
These convert parsed DBC content into a structure optimized for decoding.
### Runtime decoder
Files:
- `dbc_decoder.h`
- `dbc_decoder.cpp`
These perform actual decoding of raw CAN frames using `DecodeDatabase`.
### Parser
Files:
- `dbc_parser.h`
- `dbc_parser.cpp`
- `dbc_statement_handler.h`
- `dbc_statement_handler.cpp`
- `typefactory.h`
The parser reads files and reports errors; registered statement handlers parse DBC constructs.
### Demo
File:
- `main.cpp`
Used as a small integration example.
| Component | Source files |
| --- | --- |
| Parsed metadata | `core/dbc_database.h`, `core/frame_info.h`, `core/signal_info.h` |
| Parser and dispatch | `core/dbc_parser.*`, `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.*` |
| Decoder | `core/dbc_decoder.*` |
| Demo | `examples/main.cpp`, `examples/demo.pro` |
| Build integration | `core/core.pro`, `core/core_files.pri`, `core/core.pri` |
---
@@ -264,7 +229,8 @@ dbc
└── Odometer
```
Each node stores either:
Frame and signal nodes store copies of the corresponding metadata; the root
has no metadata payload. The payload types are:
- `FrameInfo`
- `SignalInfo`
@@ -459,7 +425,14 @@ Fields:
- `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.
---
@@ -536,7 +509,7 @@ 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
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.
---
@@ -683,34 +656,44 @@ This is one of the main reasons why the runtime decode layer should be explicit
## Example Usage
## Parse DBC
Include the public headers from the `core/` include directory supplied by
`core/core.pri`:
```cpp
#include "dbc_parser.h"
#include "dbc_tree_builder.h"
#include "dbc_decode_builder.h"
#include "dbc_decoder.h"
```
### Parse DBC
```cpp
DbcParser parser;
DbcDatabase database = parser.ParseFile("example.dbc");
```
## Build UI tree
### Build UI tree
```cpp
DbcTreeBuilder treeBuilder;
std::unique_ptr<TreeNode> root = treeBuilder.Build(database);
```
## Build runtime decode database
### Build runtime decode database
```cpp
DbcDecodeBuilder decodeBuilder;
DecodeDatabase decodeDatabase = decodeBuilder.Build(database);
```
## Decode a raw frame
### Decode a raw frame
```cpp
RawCanFrame rawFrame;
rawFrame.canId = 0x123;
rawFrame.canId = 256; // EngineData from the DBC example above
rawFrame.isExtended = false;
rawFrame.data = {0x01, 0x02, 0x03, 0x04};
rawFrame.data = {0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
DbcDecoder decoder;
DecodedFrameValue decoded = decoder.Decode(decodeDatabase, rawFrame);
@@ -817,8 +800,8 @@ lines:
- `SG_` → `DbcSignalHandler`
- `CM_` → `DbcCommentHandler`
Grammar implementations live in `dbc_statement_handler.cpp`; their interface,
context, and dispatcher live in `dbc_statement_handler.h`. `typefactory.h`
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
@@ -861,7 +844,18 @@ Not supported yet:
- 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.
Additional behavior to account for:
- unregistered DBC keywords are ignored
- an `SG_` statement before the first frame is ignored
- duplicate frame and signal definitions are not rejected
- payload lengths are checked against storage bounds (`0..255`), 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
`7..0, 15..8, 23..16`. Regression tests cover aligned and unaligned signals,
byte boundaries, and 64-bit values.
---
@@ -916,13 +910,10 @@ Advanced functionality:
## Build Integration
The module does not depend on any specific build system.
It can be integrated with:
- CMake
- qmake
- Makefile
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.
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.
@@ -945,47 +936,51 @@ 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>`.
### Build core without Qt libraries
---
From the repository root:
## 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.
In short, the system now looks like this:
```text
DBC parser → DbcDatabase → DecodeDatabase → DbcDecoder
↘ TreeNode → future UI
```sh
mkdir -p build/core
cd build/core
qmake6 ../../core/core.pro
make -j
```
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.
qmake is still the build tool; this target does not link Qt libraries.
### Build and run the demo
After building core, run these commands from the repository root:
```sh
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.
### Generate API documentation
With Doxygen installed, run from the repository root:
```sh
doxygen Doxyfile
```
Open `docs/html/index.html` to view the generated reference.
---
## Regression tests
See [tests/README.md](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.
signal syntax and payload bounds, statement dispatch, signed and unsigned
64-bit boundaries, physical conversion, numeric output, and invalid signal
payloads.
+92
View File
@@ -0,0 +1,92 @@
# Changelog
This changelog summarizes the Git history through `f17ddb6`. Entries are listed
newest first. Dates follow the commit author dates. `v1.0` is the existing Git
tag; subsequent changes have no release tag and are listed as unreleased.
## Unreleased
### 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`)