1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 // Provides an implementation of the CRC-16-CCITT or CRC-CCITT checksum, which
16 // uses the polynomial 0x1021:
17 //
18 //   x^16 + x^12 + x^5 + 1
19 //
20 // with initial value 0xFFFF. See https://www.zlib.net/crc_v3.txt.
21 #pragma once
22 
23 #include <stddef.h>
24 #include <stdint.h>
25 
26 #ifdef __cplusplus
27 extern "C" {
28 #endif  // __cplusplus
29 
30 // C API for calculating the CRC-16-CCITT of an array of data.
31 uint16_t pw_checksum_Crc16Ccitt(const void* data,
32                                 size_t size_bytes,
33                                 uint16_t initial_value);
34 
35 #ifdef __cplusplus
36 }  // extern "C"
37 
38 #include <span>
39 
40 #include "pw_bytes/span.h"
41 
42 namespace pw::checksum {
43 
44 // Calculates the CRC-16-CCITT for all data passed to Update.
45 class Crc16Ccitt {
46  public:
47   static constexpr uint16_t kInitialValue = 0xFFFF;
48 
49   // Calculates the CRC-16-CCITT for the provided data and returns it as a
50   // uint16_t. To update a CRC in multiple calls, use an instance of the
51   // Crc16Ccitt class or pass the previous value as the initial_value argument.
52   static uint16_t Calculate(std::span<const std::byte> data,
53                             uint16_t initial_value = kInitialValue) {
54     return pw_checksum_Crc16Ccitt(
55         data.data(), data.size_bytes(), initial_value);
56   }
57 
58   static uint16_t Calculate(std::byte data,
59                             uint16_t initial_value = kInitialValue) {
60     return Calculate(ConstByteSpan(&data, 1), initial_value);
61   }
62 
Crc16Ccitt()63   constexpr Crc16Ccitt() : value_(kInitialValue) {}
64 
Update(std::span<const std::byte> data)65   void Update(std::span<const std::byte> data) {
66     value_ = Calculate(data, value_);
67   }
68 
Update(std::byte data)69   void Update(std::byte data) { Update(ByteSpan(&data, 1)); }
70 
71   // Returns the value of the CRC-16-CCITT for all data passed to Update.
value()72   uint16_t value() const { return value_; }
73 
74   // Resets the CRC to the initial value.
clear()75   void clear() { value_ = kInitialValue; }
76 
77  private:
78   uint16_t value_;
79 };
80 
81 }  // namespace pw::checksum
82 
83 #endif  // __cplusplus
84