Closes #14
This commit is contained in:
1 parent
51fcdb88ac
commit
0708316a37
155 files changed
+5190
-2691
No files matched your search
@@ -321,7 +321,7 @@ This structure is used directly by the decoder.
|
||||
|
||||
## `FrameKey`
|
||||
|
||||
Fast lookup key for runtime frame matching.
|
||||
Stable identifier for runtime frame matching and application state.
|
||||
|
||||
Fields:
|
||||
|
||||
@@ -334,22 +334,20 @@ This matters because the same numeric identifier must not be confused between st
|
||||
|
||||
## `DecodeDatabase`
|
||||
|
||||
Top-level runtime decode container.
|
||||
Immutable runtime snapshot with a private frame index. Build it with
|
||||
`DbcDecodeBuilder::Build(parsed)` or construct it from `std::vector<DecodeFrame>`.
|
||||
Construction rejects duplicate frame keys and duplicate signal names within a
|
||||
frame with `std::invalid_argument`, including manually supplied metadata.
|
||||
|
||||
Fields:
|
||||
- `GetFrames()` returns a borrowed `const std::vector<DecodeFrame>&`.
|
||||
- `FindFrame(FrameKey)` returns `std::shared_ptr<const DecodeFrame>`.
|
||||
- `FindSignal(SignalKey)` returns `std::shared_ptr<const DecodeSignal>`.
|
||||
- Missing definitions return an empty handle.
|
||||
- Copying a database shares its snapshot; replacing it installs another snapshot.
|
||||
|
||||
- `frames`
|
||||
- `frameIndexByKey`
|
||||
|
||||
Conceptually:
|
||||
|
||||
```text
|
||||
DecodeDatabase
|
||||
├── vector<DecodeFrame>
|
||||
└── unordered_map<FrameKey, index>
|
||||
```
|
||||
|
||||
This gives the decoder fast access to a frame definition using CAN ID and frame type.
|
||||
Frame lookup uses a hash index; signal lookup scans the matched frame's signals.
|
||||
Decoding shares the snapshot without copying definitions or allocating ownership
|
||||
objects per signal.
|
||||
|
||||
---
|
||||
|
||||
@@ -380,6 +378,7 @@ Represents one decoded signal result.
|
||||
Fields:
|
||||
|
||||
- `definition`
|
||||
- `key`
|
||||
- `rawValue`
|
||||
- `physicalValue`
|
||||
- `valid`
|
||||
@@ -426,6 +425,7 @@ Represents one decoded frame result.
|
||||
Fields:
|
||||
|
||||
- `definition`
|
||||
- `key`
|
||||
- `signals`
|
||||
- `valid`
|
||||
|
||||
@@ -433,10 +433,77 @@ Fields:
|
||||
`valid` separately: insufficient payload data can leave individual signals
|
||||
invalid even when the frame is valid. An unknown frame returns `valid == false`.
|
||||
|
||||
The frame and signal `definition` pointers refer into `DecodeDatabase`. Keep
|
||||
that database alive and avoid changes that invalidate its frame or signal
|
||||
storage while using decoded results. The decoder applies factor and offset;
|
||||
it does not clamp physical values to the declared minimum and maximum.
|
||||
The decoder applies factor and offset; it does not clamp physical values to the
|
||||
declared minimum and maximum.
|
||||
|
||||
### Definition ownership and reload
|
||||
|
||||
`DecodedFrameValue::definition` and `DecodedSignalValue::definition` are owning
|
||||
`std::shared_ptr<const ...>` handles. Each handle retains the immutable runtime
|
||||
snapshot. Definitions remain valid until the last database copy, lookup handle,
|
||||
or decoded result owning that snapshot is released. An independently copied
|
||||
signal result retains its definition even after the parent frame result is
|
||||
removed. Copying or moving results preserves ownership.
|
||||
|
||||
Reload by assigning a newly built database. Stored results continue to describe
|
||||
the old DBC, including its units, scaling, comments, and `VAL_` descriptions;
|
||||
subsequent decoding uses the new DBC. Removed definitions cannot be found in the
|
||||
new database, but old results safely retain their old definitions. Keeping even
|
||||
one signal handle retains the whole old snapshot; release stored results when
|
||||
that metadata is no longer needed.
|
||||
|
||||
`GetFrames()` is a borrowed view. References, iterators, and raw pointers obtained
|
||||
from it or from a handle's `.get()` do not retain ownership. Keep an owning handle
|
||||
or an unchanged database copy while using them. Do not retain mutable aliases
|
||||
into a vector moved into the database constructor. The raw string pointer from
|
||||
`GetValueDescription()` follows the same rule: keep the signal definition handle
|
||||
alive while using the string.
|
||||
|
||||
Parsed `DbcDatabase`/`FrameInfo`/`SignalInfo` remain ordinary mutable value
|
||||
containers: borrowed pointers follow standard vector invalidation rules. Builders
|
||||
copy their metadata, so parsed input may be changed or destroyed after building.
|
||||
Tree nodes own metadata copies; the Qt model owns its tree and invalidates model
|
||||
indexes on reset. Runtime handles do not depend on the parsed database or tree.
|
||||
Synchronize replacement of a shared database variable with decoding; immutable
|
||||
snapshots do not make concurrent assignment to the same object safe.
|
||||
|
||||
### Stable frame and signal identifiers
|
||||
|
||||
`DecodedFrameValue::key` is a `FrameKey` (normalized `canId`, `isExtended`), also
|
||||
available through `DecodeFrame::GetKey()`. `DecodedSignalValue::key` is a
|
||||
`SignalKey` (frame key, exact case-sensitive signal name). Both are value types
|
||||
with equality and hashers (`FrameKeyHasher`, `SignalKeyHasher`) for application
|
||||
maps and saved selections. Construct the same keys from parsed metadata when
|
||||
needed; do not use addresses or vector positions as identifiers.
|
||||
|
||||
Keys stay equal across reloads and reordering when their components stay equal.
|
||||
Frame renaming and changes to units, bit layout, scaling, or descriptions do not
|
||||
change a key. Changing a CAN ID/frame type or renaming a signal produces a new
|
||||
key. The same name in different frames and standard/extended frames with the
|
||||
same numeric CAN ID remain distinct. Keys identify definitions within one logical
|
||||
DBC database; applications combining databases must add their own database ID.
|
||||
A key is not a version identifier: matching keys in different snapshots may have
|
||||
different metadata. Use `valid`/the definition handle to distinguish a matched
|
||||
result; default keys alone do not indicate successful decoding.
|
||||
|
||||
```cpp
|
||||
DecodeDatabase runtime = DbcDecodeBuilder().Build(parsed);
|
||||
DecodedFrameValue stored = DbcDecoder().Decode(runtime, rawFrame);
|
||||
if (stored.valid && !stored.signals.empty()) {
|
||||
DecodedSignalValue saved = stored.signals.front();
|
||||
SignalKey selection = saved.key;
|
||||
runtime = DbcDecodeBuilder().Build(parser.ParseFile("updated.dbc"));
|
||||
std::shared_ptr<const DecodeSignal> current = runtime.FindSignal(selection);
|
||||
// saved.definition retains old metadata; current holds new metadata or is empty.
|
||||
}
|
||||
```
|
||||
|
||||
**API migration:** replace reads of `runtime.frames` with `runtime.GetFrames()`.
|
||||
To edit runtime definitions, prepare a vector and construct a new database;
|
||||
`frameIndexByKey` is now private and built automatically. `DbcDecoder::FindFrame`
|
||||
and result `definition` fields now use owning handles instead of raw pointers;
|
||||
`definition->name`, boolean/null checks, and existing decode calls remain usable.
|
||||
Use `.get()` only for temporary raw-pointer interoperation with an owner alive.
|
||||
|
||||
---
|
||||
|
||||
@@ -986,7 +1053,7 @@ if (const std::string *description = value.GetValueDescription()) {
|
||||
It returns `nullptr` for an invalid decode or an unknown value; numeric decoding
|
||||
and `physicalValue` are unchanged. A mapped empty string returns a non-null
|
||||
pointer. The pointer belongs to the signal definition and stays valid while that
|
||||
definition and mapping remain alive and unchanged.
|
||||
definition remains alive. A decoded signal owns its immutable definition across reload.
|
||||
|
||||
For metadata or standalone raw values, use
|
||||
`FindValueDescription(signal.valueDescriptions, rawValue)`, where `rawValue` is
|
||||
|
||||
Reference in new issue
Block a user