DCCL v5
Loading...
Searching...
No Matches
field_codec_crc.h
1// Copyright 2024:
2// GobySoft, LLC (2013-)
3// Community contributors (see AUTHORS file)
4// File authors:
5// Toby Schneider <toby@gobysoft.org>
6//
7//
8// This file is part of the Dynamic Compact Control Language Library
9// ("DCCL").
10//
11// DCCL is free software: you can redistribute it and/or modify
12// it under the terms of the GNU Lesser General Public License as published by
13// the Free Software Foundation, either version 2.1 of the License, or
14// (at your option) any later version.
15//
16// DCCL is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU Lesser General Public License for more details.
20//
21// You should have received a copy of the GNU Lesser General Public License
22// along with DCCL. If not, see <http://www.gnu.org/licenses/>.
23#ifndef DCCLV4FIELDCODECCRCN
24#define DCCLV4FIELDCODECCRCN
25
26#include <cstdint>
27#include <sstream>
28#include <string>
29
30#include "field_codec_default.h"
31
32namespace dccl
33{
34namespace v4
35{
36
43inline uint16_t crc16(const char* data, size_t size)
44{
45 uint16_t crc = 0xFFFF;
46 for (size_t i = 0; i < size; ++i)
47 {
48 crc ^= static_cast<uint16_t>(static_cast<uint8_t>(data[i])) << 8;
49 for (int bit = 0; bit < 8; ++bit)
50 {
51 if (crc & 0x8000)
52 crc = static_cast<uint16_t>((crc << 1) ^ 0x1021);
53 else
54 crc = static_cast<uint16_t>(crc << 1);
55 }
56 }
57 return crc;
58}
59
67inline uint32_t crc32(const char* data, size_t size)
68{
69 uint32_t crc = 0xFFFFFFFF;
70 for (size_t i = 0; i < size; ++i)
71 {
72 crc ^= static_cast<uint8_t>(data[i]);
73 for (int bit = 0; bit < 8; ++bit)
74 {
75 if (crc & 1)
76 crc = (crc >> 1) ^ 0xEDB88320;
77 else
78 crc >>= 1;
79 }
80 }
81 return crc ^ 0xFFFFFFFF;
82}
83
92template <int CRCBits> class CRCCodecBase : public v4::DefaultNumericFieldCodec<uint32>
93{
94 public:
95 CRCCodecBase() { this->set_force_use_required(); }
96
97 double min() override { return 0; }
98 double max() override { return (CRCBits == 32) ? static_cast<double>(0xFFFFFFFFu) : static_cast<double>(0xFFFFu); }
99
100 private:
101 Bitset encode() override
102 {
103 return this->v4::DefaultNumericFieldCodec<uint32>::encode(compute_crc_encode());
104 }
105
106 uint32 pre_encode(const uint32& /*field_value*/) override { return compute_crc_encode(); }
107
108 uint32 post_decode(const uint32& wire_value) override
109 {
110 uint32 expected = compute_crc_decode();
111 uint32 received = wire_value;
112 if (expected != received)
113 {
114 std::stringstream ss;
115 ss << "CRC mismatch. Expected: 0x" << std::hex << expected << ", received: 0x"
116 << received
117 << ". Message data may be corrupted.";
118 throw(Exception(ss.str(), this->root_descriptor()));
119 }
120 return wire_value;
121 }
122
123 void validate() override
124 {
125 // min() and max() are hardcoded - skip the parent's has_min/has_max checks and
126 // call validate_numeric_bounds() directly to verify type range constraints.
127 this->validate_numeric_bounds();
128 }
129
131 uint32 compute_crc_encode() const
132 {
133 const Bitset* bits = this->root_bitset();
134 if (!bits)
135 return 0;
136 Bitset bits_copy = *bits;
137 std::string byte_str = bits_copy.to_byte_string();
138 return compute_crc(byte_str.data(), byte_str.size());
139 }
140
146 uint32 compute_crc_decode() const
147 {
148 const Bitset* bits = this->root_bitset();
149 if (!bits)
150 return 0;
151 // decoded_bits_ already contains only the bits before the CRC field - no trimming needed.
152 Bitset bits_copy = *bits;
153 std::string byte_str = bits_copy.to_byte_string();
154 return compute_crc(byte_str.data(), byte_str.size());
155 }
156
157 static uint32 compute_crc(const char* data, size_t size)
158 {
159 if (CRCBits == 16)
160 return crc16(data, size);
161 else
162 return crc32(data, size);
163 }
164};
165
170class CRC16Codec : public CRCCodecBase<16>
171{
172};
173
178class CRC32Codec : public CRCCodecBase<32>
179{
180};
181
182} // namespace v4
183} // namespace dccl
184
185#endif
A variable size container of bits (subclassed from std::deque<bool>) with an optional hierarchy....
Definition bitset.h:43
std::string to_byte_string()
Returns the value of the Bitset to a byte string, where each character represents 8 bits of the Bitse...
Definition bitset.h:297
Exception class for DCCL.
Definition exception.h:47
const Bitset * root_bitset() const
Returns the root Bitset for the current encode or decode operation.
void set_force_use_required(bool force_required=true)
Force the codec to always use the "required" field encoding, regardless of the FieldDescriptor settin...
DCCL CRC-16 codec (CRC-16/IBM-3740 / CCITT-FALSE).
DCCL CRC-32 codec (CRC-32/ISO-HDLC).
DCCL version 4 default field codecs.
uint32_t crc32(const char *data, size_t size)
Computes a CRC-32/ISO-HDLC checksum (standard Ethernet/zlib CRC-32).
uint16_t crc16(const char *data, size_t size)
Computes a CRC-16/IBM-3740 (CRC-16/CCITT-FALSE) checksum.
Dynamic Compact Control Language namespace.
Definition any.h:28
google::protobuf::uint32 uint32
an unsigned 32 bit integer
Definition common.h:56