Line data Source code
1 : /**
2 : * @file decode_database.h
3 : * @brief Runtime definitions and immutable indexed database.
4 : *
5 : * Created: 2026-03-13
6 : * Author: Deeaitch (Dim. Himro)
7 : *
8 : * Licensed under the MIT License.
9 : * See LICENSE file in the project root for full license text.
10 : */
11 :
12 : #ifndef DECODE_DATABASE_H
13 : #define DECODE_DATABASE_H
14 :
15 : #include "attributes.h"
16 : #include "definition_key.h"
17 : #include "multiplexing.h"
18 : #include "value_descriptions.h"
19 : #include <cstdint>
20 : #include <memory>
21 : #include <string>
22 : #include <unordered_map>
23 : #include <vector>
24 :
25 : /**
26 : * @brief Signal byte order used for runtime decoding.
27 : */
28 : enum class ByteOrder {
29 : Intel,
30 : Motorola
31 : };
32 :
33 : /**
34 : * @brief Signal numeric type.
35 : */
36 : enum class ValueType {
37 : Unsigned,
38 : Signed
39 : };
40 :
41 : /**
42 : * @brief Runtime-ready signal definition.
43 : */
44 : struct DecodeSignal {
45 : Multiplexing multiplexing; /**< Selector role and branch value. */
46 : std::string name; /**< Signal name. */
47 : std::uint32_t startBit = 0U; /**< DBC start bit. */
48 : std::uint32_t length = 0U; /**< Signal length in bits. */
49 : ByteOrder byteOrder = ByteOrder::Intel; /**< Intel or Motorola. */
50 : ValueType valueType = ValueType::Unsigned; /**< Signed or unsigned. */
51 : double factor = 1.0; /**< Scaling factor. */
52 : double offset = 0.0; /**< Physical offset. */
53 : double minimum = 0.0; /**< Minimum physical value. */
54 : double maximum = 0.0; /**< Maximum physical value. */
55 : std::string unit; /**< Physical unit. */
56 : std::vector<std::string> receivers; /**< Receivers. */
57 : ValueDescriptions valueDescriptions; /**< Raw integer state descriptions. */
58 : std::string comment; /**< Comment. */
59 :
60 : AttributeMap attributes; /**< Effective attributes after defaults and overrides. */
61 :
62 2438 : DecodeSignal() = default;
63 : };
64 :
65 : /**
66 : * @brief Runtime-ready frame definition.
67 : */
68 : struct DecodeFrame {
69 : std::string name; /**< Frame name. */
70 : std::uint32_t canId = 0U; /**< Normalized CAN ID. */
71 : bool isExtended = false; /**< true for extended frame. */
72 : std::uint8_t dlc = 0U; /**< Payload length. */
73 : std::uint32_t pgn = 0U; /**< PGN if available. */
74 : bool hasPgn = false; /**< Explicit J1939 opt-in; pgn must match canId. */
75 : std::string transmitter; /**< Transmitter ECU. */
76 : std::string comment; /**< Frame comment. */
77 : std::vector<DecodeSignal> signals; /**< Signal definitions. */
78 :
79 : AttributeMap attributes; /**< Effective attributes after defaults and overrides. */
80 : std::optional<std::string> frameFormat; /**< VFrameFormat label, when declared. */
81 : std::optional<std::uint32_t> cycleTimeMs; /**< GenMsgCycleTime in milliseconds, when declared. */
82 :
83 2400 : DecodeFrame() = default;
84 :
85 : /** @brief Return the stable normalized frame identifier. */
86 11038 : FrameKey GetKey() const {
87 11038 : return FrameKey(canId, isExtended);
88 : }
89 : };
90 :
91 : /** A PGN lookup rejects multiple definitions rather than choosing by order. */
92 : struct PgnLookupResult {
93 : std::shared_ptr<const DecodeFrame> definition; /**< Owning matched definition; empty if missing or ambiguous. */
94 : bool ambiguous = false; /**< True when multiple definitions share the requested PGN. */
95 : };
96 :
97 : /**
98 : * @brief Immutable runtime snapshot. Copies share storage; reload replaces a snapshot.
99 : * Owning lookup handles and decoded results keep old definitions alive.
100 : */
101 : class DecodeDatabase {
102 : public:
103 21 : DecodeDatabase() = default;
104 : /**
105 : * Copy and validate definitions before building the frame index.
106 : * Input aliases cannot modify the snapshot, even for rvalue input.
107 : * @throws std::invalid_argument for invalid metadata or duplicate keys.
108 : */
109 : explicit DecodeDatabase(const std::vector<DecodeFrame> &frames);
110 :
111 : /** Borrowed view, valid while this snapshot remains alive and unchanged. */
112 : const std::vector<DecodeFrame> &GetFrames() const;
113 : /** Owning handles retain the entire snapshot across reload or destruction. */
114 : std::shared_ptr<const DecodeFrame> FindFrame(const FrameKey &key) const;
115 : /** Only explicitly marked hasPgn frames participate; ambiguous results have no definition. */
116 : PgnLookupResult FindFrameByPgn(std::uint32_t pgn) const;
117 : /** @brief Return an owning signal handle, or an empty handle for a missing key. */
118 : std::shared_ptr<const DecodeSignal> FindSignal(const SignalKey &key) const;
119 :
120 : private:
121 : struct Storage {
122 : std::vector<DecodeFrame> frames;
123 : std::unordered_map<FrameKey, std::size_t, FrameKeyHasher> frameIndexByKey;
124 :
125 : std::unordered_map<std::uint32_t, std::vector<std::size_t>> frameIndicesByPgn;
126 :
127 : explicit Storage(const std::vector<DecodeFrame> &definitions);
128 : };
129 :
130 : std::shared_ptr<const Storage> storage;
131 : };
132 :
133 : #endif /* DECODE_DATABASE_H */
|