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:
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...
Provides a basic bounded arbitrary length numeric (double, float, uint32, uint64, int32,...
Bitset encode() override
Encode an empty field.
unsigned size() override
The size of the encoded message in bits. Use TypedFieldCodec if the size depends on the data.
DCCL CRC-16 codec (CRC-16/IBM-3740 / CCITT-FALSE).
DCCL CRC-32 codec (CRC-32/ISO-HDLC).
DCCL CRC field codec base class. Computes a CRC over all bits encoded before this field (during encod...
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