/src/abseil-cpp/absl/crc/crc32c.h
Line | Count | Source |
1 | | // Copyright 2022 The Abseil Authors |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of 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, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | // |
15 | | // ----------------------------------------------------------------------------- |
16 | | // File: crc32c.h |
17 | | // ----------------------------------------------------------------------------- |
18 | | // |
19 | | // This header file defines the API for computing CRC32C values as checksums |
20 | | // for arbitrary sequences of bytes provided as a string buffer. |
21 | | // |
22 | | // The API includes the basic functions for computing such CRC32C values and |
23 | | // some utility functions for performing more efficient mathematical |
24 | | // computations using an existing checksum. |
25 | | #ifndef ABSL_CRC_CRC32C_H_ |
26 | | #define ABSL_CRC_CRC32C_H_ |
27 | | |
28 | | #include <cstddef> |
29 | | #include <cstdint> |
30 | | #include <ostream> |
31 | | |
32 | | #include "absl/base/config.h" |
33 | | #include "absl/crc/internal/crc32c_inline.h" |
34 | | #include "absl/strings/str_format.h" |
35 | | #include "absl/strings/string_view.h" |
36 | | |
37 | | namespace absl { |
38 | | ABSL_NAMESPACE_BEGIN |
39 | | |
40 | | //----------------------------------------------------------------------------- |
41 | | // crc32c_t |
42 | | //----------------------------------------------------------------------------- |
43 | | |
44 | | // `crc32c_t` defines a strongly-typed integer for holding a CRC32C value. |
45 | | // |
46 | | // Some operators are intentionally omitted. Only equality operators are defined |
47 | | // so that `crc32c_t` can be directly compared. Methods for putting `crc32c_t` |
48 | | // directly into a set are omitted because this is bug-prone due to checksum |
49 | | // collisions. Use an explicit conversion to the `uint32_t` space for operations |
50 | | // that treat `crc32c_t` as an integer. |
51 | | class crc32c_t final { |
52 | | public: |
53 | | crc32c_t() = default; |
54 | 0 | constexpr explicit crc32c_t(uint32_t crc) : crc_(crc) {} |
55 | | |
56 | | crc32c_t(const crc32c_t&) = default; |
57 | | crc32c_t& operator=(const crc32c_t&) = default; |
58 | | |
59 | 0 | explicit operator uint32_t() const { return crc_; } |
60 | | |
61 | 0 | friend bool operator==(crc32c_t lhs, crc32c_t rhs) { |
62 | 0 | return static_cast<uint32_t>(lhs) == static_cast<uint32_t>(rhs); |
63 | 0 | } |
64 | | |
65 | 0 | friend bool operator!=(crc32c_t lhs, crc32c_t rhs) { return !(lhs == rhs); } |
66 | | |
67 | | template <typename Sink> |
68 | | friend void AbslStringify(Sink& sink, crc32c_t crc) { |
69 | | absl::Format(&sink, "%08x", static_cast<uint32_t>(crc)); |
70 | | } |
71 | | |
72 | | private: |
73 | | uint32_t crc_; |
74 | | }; |
75 | | |
76 | | |
77 | | namespace crc_internal { |
78 | | // Non-inline code path for `absl::ExtendCrc32c()`. Do not call directly. |
79 | | // Call `absl::ExtendCrc32c()` (defined below) instead. |
80 | | crc32c_t ExtendCrc32cInternal(crc32c_t initial_crc, |
81 | | absl::string_view buf_to_add); |
82 | | } // namespace crc_internal |
83 | | |
84 | | // ----------------------------------------------------------------------------- |
85 | | // CRC32C Computation Functions |
86 | | // ----------------------------------------------------------------------------- |
87 | | |
88 | | // ExtendCrc32c() |
89 | | // |
90 | | // Computes a CRC32C value from an `initial_crc` CRC32C value including the |
91 | | // `buf_to_add` bytes of an additional buffer. Using this function is more |
92 | | // efficient than computing a CRC32C value for the combined buffer from |
93 | | // scratch. |
94 | | // |
95 | | // Note: `ExtendCrc32c` with an initial_crc of 0 is equivalent to |
96 | | // `ComputeCrc32c`. |
97 | | // |
98 | | // This operation has a runtime cost of O(`buf_to_add.size()`) |
99 | | inline crc32c_t ExtendCrc32c(crc32c_t initial_crc, |
100 | 0 | absl::string_view buf_to_add) { |
101 | 0 | // Approximately 75% of calls have size <= 64. |
102 | 0 | if (buf_to_add.size() <= 64) { |
103 | 0 | uint32_t crc = static_cast<uint32_t>(initial_crc); |
104 | 0 | if (crc_internal::ExtendCrc32cInline(&crc, buf_to_add.data(), |
105 | 0 | buf_to_add.size())) { |
106 | 0 | return crc32c_t{crc}; |
107 | 0 | } |
108 | 0 | } |
109 | 0 | return crc_internal::ExtendCrc32cInternal(initial_crc, buf_to_add); |
110 | 0 | } |
111 | | |
112 | | // ComputeCrc32c() |
113 | | // |
114 | | // Returns the CRC32C value of the provided string. |
115 | 0 | inline crc32c_t ComputeCrc32c(absl::string_view buf) { |
116 | 0 | return ExtendCrc32c(crc32c_t{0}, buf); |
117 | 0 | } |
118 | | |
119 | | // ExtendCrc32cByZeroes() |
120 | | // |
121 | | // Computes a CRC32C value for a buffer with an `initial_crc` CRC32C value, |
122 | | // where `length` bytes with a value of 0 are appended to the buffer. Using this |
123 | | // function is more efficient than computing a CRC32C value for the combined |
124 | | // buffer from scratch. |
125 | | // |
126 | | // This operation has a runtime cost of O(log(`length`)) |
127 | | crc32c_t ExtendCrc32cByZeroes(crc32c_t initial_crc, size_t length); |
128 | | |
129 | | // MemcpyCrc32c() |
130 | | // |
131 | | // Copies `src` to `dest` using `memcpy()` semantics, returning the CRC32C |
132 | | // value of the copied buffer. |
133 | | // |
134 | | // Using `MemcpyCrc32c()` is potentially faster than performing the `memcpy()` |
135 | | // and `ComputeCrc32c()` operations separately. |
136 | | crc32c_t MemcpyCrc32c(void* dest, const void* src, size_t count, |
137 | | crc32c_t initial_crc = crc32c_t{0}); |
138 | | |
139 | | // ----------------------------------------------------------------------------- |
140 | | // CRC32C Arithmetic Functions |
141 | | // ----------------------------------------------------------------------------- |
142 | | |
143 | | // The following functions perform arithmetic on CRC32C values, which are |
144 | | // generally more efficient than recalculating any given result's CRC32C value. |
145 | | |
146 | | // ConcatCrc32c() |
147 | | // |
148 | | // Calculates the CRC32C value of two buffers with known CRC32C values |
149 | | // concatenated together. |
150 | | // |
151 | | // Given a buffer with CRC32C value `crc1` and a buffer with |
152 | | // CRC32C value `crc2` and length, `crc2_length`, returns the CRC32C value of |
153 | | // the concatenation of these two buffers. |
154 | | // |
155 | | // This operation has a runtime cost of O(log(`crc2_length`)). |
156 | | crc32c_t ConcatCrc32c(crc32c_t crc1, crc32c_t crc2, size_t crc2_length); |
157 | | |
158 | | // RemoveCrc32cPrefix() |
159 | | // |
160 | | // Calculates the CRC32C value of an existing buffer with a series of bytes |
161 | | // (the prefix) removed from the beginning of that buffer. |
162 | | // |
163 | | // Given the CRC32C value of an existing buffer, `full_string_crc`; The CRC32C |
164 | | // value of a prefix of that buffer, `prefix_crc`; and the length of the buffer |
165 | | // with the prefix removed, `remaining_string_length` , return the CRC32C |
166 | | // value of the buffer with the prefix removed. |
167 | | // |
168 | | // This operation has a runtime cost of O(log(`remaining_string_length`)). |
169 | | crc32c_t RemoveCrc32cPrefix(crc32c_t prefix_crc, crc32c_t full_string_crc, |
170 | | size_t remaining_string_length); |
171 | | // RemoveCrc32cSuffix() |
172 | | // |
173 | | // Calculates the CRC32C value of an existing buffer with a series of bytes |
174 | | // (the suffix) removed from the end of that buffer. |
175 | | // |
176 | | // Given a CRC32C value of an existing buffer `full_string_crc`, the CRC32C |
177 | | // value of the suffix to remove `suffix_crc`, and the length of that suffix |
178 | | // `suffix_len`, returns the CRC32C value of the buffer with suffix removed. |
179 | | // |
180 | | // This operation has a runtime cost of O(log(`suffix_len`)) |
181 | | crc32c_t RemoveCrc32cSuffix(crc32c_t full_string_crc, crc32c_t suffix_crc, |
182 | | size_t suffix_length); |
183 | | |
184 | | // operator<< |
185 | | // |
186 | | // Streams the CRC32C value `crc` to the stream `os`. |
187 | 0 | inline std::ostream& operator<<(std::ostream& os, crc32c_t crc) { |
188 | 0 | return os << absl::StreamFormat("%08x", static_cast<uint32_t>(crc)); |
189 | 0 | } |
190 | | |
191 | | ABSL_NAMESPACE_END |
192 | | } // namespace absl |
193 | | |
194 | | #endif // ABSL_CRC_CRC32C_H_ |