LCOV - code coverage report
Current view: top level - core - dbc_decoder.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 5 5
Test Date: 2026-10-20 13:34:58 Functions: 100.0 % 4 4
Branches: 75.0 % 4 3

             Branch data     Line data    Source code
       1                 :             : /**
       2                 :             :  * @file dbc_decoder.h
       3                 :             :  * @brief CAN frame decoding API and result types.
       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 DBC_DECODER_H
      13                 :             : #define DBC_DECODER_H
      14                 :             : 
      15                 :             : #include <cstdint>
      16                 :             : #include <variant>
      17                 :             : #include <vector>
      18                 :             : 
      19                 :             : #include "decode_database.h"
      20                 :             : 
      21                 :             : /**
      22                 :             :  * @brief Raw CAN frame used for runtime or trace decoding.
      23                 :             :  */
      24                 :             : struct RawCanFrame {
      25                 :             :     std::uint32_t canId = 0U;       /**< Normalized CAN ID. */
      26                 :             :     bool isExtended = false;        /**< true for extended frame. */
      27                 :             :     std::vector<std::uint8_t> data; /**< Payload bytes. */
      28                 :             : 
      29                 :        2220 :     RawCanFrame() = default;
      30                 :             : };
      31                 :             : 
      32                 :             : /** @brief Outcome of signal extraction and physical conversion. */
      33                 :             : enum class SignalDecodeStatus {
      34                 :             :     InvalidDefinition,
      35                 :             :     InsufficientPayload,
      36                 :             :     SelectorUnavailable,
      37                 :             :     Inactive,
      38                 :             :     Valid,
      39                 :             :     PhysicalConversionFailed
      40                 :             : };
      41                 :             : 
      42                 :             : /** Frame summary: short payload takes precedence over individual signal errors. */
      43                 :             : enum class FrameDecodeStatus {
      44                 :             :     UnknownFrame,
      45                 :             :     InsufficientPayload,
      46                 :             :     SignalErrors,
      47                 :             :     Valid,
      48                 :             :     AmbiguousFrame
      49                 :             : };
      50                 :             : 
      51                 :             : /**
      52                 :             :  * @brief One decoded signal value.
      53                 :             :  */
      54                 :             : struct DecodedSignalValue {
      55                 :             :     std::shared_ptr<const DecodeSignal> definition; /**< Owning immutable definition. */
      56                 :             :     SignalKey key;                                  /**< Stable application identifier. */
      57                 :             :     RawSignalValue rawValue = std::uint64_t(0U);    /**< Exact raw value for Valid or PhysicalConversionFailed. */
      58                 :             :     double physicalValue = 0.0;                     /**< Conversion result, possibly NaN/Inf on failure. */
      59                 :             :     bool valid = false;                             /**< true if decoding succeeded. */
      60                 :             :     SignalDecodeStatus status = SignalDecodeStatus::InvalidDefinition; /**< Detailed signal outcome. */
      61                 :             : 
      62                 :             :     /** Lookup using the raw integer; nullptr for invalid or unmapped values. */
      63                 :          79 :     const std::string *GetValueDescription() const {
      64   [ +  +  +  - ]:          79 :         return valid && definition ? FindValueDescription(definition->valueDescriptions, rawValue) : nullptr;
      65                 :             :     }
      66                 :             : 
      67                 :        6380 :     DecodedSignalValue() = default;
      68                 :             : };
      69                 :             : 
      70                 :             : /**
      71                 :             :  * @brief Fully decoded frame.
      72                 :             :  */
      73                 :             : struct DecodedFrameValue {
      74                 :             :     std::shared_ptr<const DecodeFrame> definition; /**< Owning immutable definition. */
      75                 :             :     FrameKey key;                                  /**< Matched definition key; received key if unmatched. */
      76                 :             :     std::vector<DecodedSignalValue> signals;       /**< Decoded signal values. */
      77                 :             :     bool valid = false;                            /**< true if frame was matched. */
      78                 :             :     FrameDecodeStatus status = FrameDecodeStatus::UnknownFrame; /**< Inspect signals for individual failures. */
      79                 :             : 
      80                 :        6409 :     DecodedFrameValue() = default;
      81                 :             : };
      82                 :             : 
      83                 :             : /**
      84                 :             :  * @brief Runtime CAN decoder using prebuilt decode database.
      85                 :             :  */
      86                 :             : class DbcDecoder {
      87                 :             : public:
      88                 :             :     /**
      89                 :             :      * @brief Find exact CAN ID first, then unique PGN among explicitly J1939 definitions.
      90                 :             :      * @param database Runtime decode database.
      91                 :             :      * @param canId Normalized CAN ID.
      92                 :             :      * @param isExtended true for extended frame.
      93                 :             :      * @return Owning immutable handle, or nullptr for missing/ambiguous matches. Safe across reload.
      94                 :             :      */
      95                 :             :     std::shared_ptr<const DecodeFrame> FindFrame(const DecodeDatabase &database,
      96                 :             :                                                  std::uint32_t canId,
      97                 :             :                                                  bool isExtended) const;
      98                 :             : 
      99                 :             :     /**
     100                 :             :      * @brief Decode one raw CAN frame.
     101                 :             :      * @param database Runtime decode database.
     102                 :             :      * @param frame Raw CAN frame.
     103                 :             :      * Short payloads decode available signals; bytes beyond declared DLC are ignored.
     104                 :             :      * @return Decoded frame value.
     105                 :             :      */
     106                 :             :     DecodedFrameValue Decode(const DecodeDatabase &database,
     107                 :             :                              const RawCanFrame &frame) const;
     108                 :             : 
     109                 :             :     /**
     110                 :             :      * @brief Decode selected signals in selection order using stable keys.
     111                 :             :      * An empty selection returns no signals. Multiplex selectors are read internally.
     112                 :             :      * Frame status summarizes selected signals; short payload still takes precedence.
     113                 :             :      * Unknown/ambiguous frames return before checking the selection.
     114                 :             :      * For PGN matches, selection keys must belong to the matched DBC definition.
     115                 :             :      * @throws std::invalid_argument for a foreign frame key, unknown signal, or duplicate key.
     116                 :             :      */
     117                 :             :     DecodedFrameValue Decode(const DecodeDatabase &database,
     118                 :             :                              const RawCanFrame &frame,
     119                 :             :                              const std::vector<SignalKey> &selection) const;
     120                 :             : 
     121                 :             : private:
     122                 :             :     static PgnLookupResult ResolveFrame(const DecodeDatabase &database,
     123                 :             :                                         std::uint32_t canId, bool isExtended);
     124                 :             : 
     125                 :             :     DecodedFrameValue DecodeImpl(const DecodeDatabase &database,
     126                 :             :                                  const RawCanFrame &frame,
     127                 :             :                                  const std::vector<SignalKey> *selection) const;
     128                 :             : 
     129                 :             :     static bool IsValidDefinition(const DecodeSignal &signal, std::uint8_t dlc);
     130                 :             : 
     131                 :             :     struct SelectorState {
     132                 :             :         const DecodeSignal *definition = nullptr;
     133                 :             :         bool valid = false;
     134                 :             :         bool available = false;
     135                 :             :         std::uint64_t value = 0U;
     136                 :             :     };
     137                 :             : 
     138                 :             :     static SelectorState ReadSelector(const DecodeFrame &definition, const RawCanFrame &frame);
     139                 :             :     static DecodedSignalValue DecodeOneSignal(const DecodeSignal &signal,
     140                 :             :                                               std::uint8_t dlc,
     141                 :             :                                               const RawCanFrame &frame,
     142                 :             :                                               const SelectorState &selector);
     143                 :             : 
     144                 :             :     static bool ExtractUnsigned(const std::vector<std::uint8_t> &data,
     145                 :             :                                 const DecodeSignal &signal,
     146                 :             :                                 std::uint64_t &value);
     147                 :             : 
     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);
     152                 :             : 
     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);
     157                 :             : 
     158                 :             :     static std::int64_t SignExtend(std::uint64_t value, std::uint32_t bitLength);
     159                 :             : };
     160                 :             : 
     161                 :             : #endif /* DBC_DECODER_H */
        

Generated by: LCOV version 2.0-1