/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/crc32_x86_arm_combined_simd.h" |
34 | | #include "absl/crc/internal/crc32c_inline.h" |
35 | | #include "absl/strings/str_format.h" |
36 | | #include "absl/strings/string_view.h" |
37 | | |
38 | | namespace absl { |
39 | | ABSL_NAMESPACE_BEGIN |
40 | | |
41 | | //----------------------------------------------------------------------------- |
42 | | // crc32c_t |
43 | | //----------------------------------------------------------------------------- |
44 | | |
45 | | // `crc32c_t` defines a strongly-typed integer for holding a CRC32C value. |
46 | | // |
47 | | // Some operators are intentionally omitted. Only equality operators are defined |
48 | | // so that `crc32c_t` can be directly compared. Methods for putting `crc32c_t` |
49 | | // directly into a set are omitted because this is bug-prone due to checksum |
50 | | // collisions. Use an explicit conversion to the `uint32_t` space for operations |
51 | | // that treat `crc32c_t` as an integer. |
52 | | class crc32c_t final { |
53 | | public: |
54 | | crc32c_t() = default; |
55 | 0 | constexpr explicit crc32c_t(uint32_t crc) : crc_(crc) {} |
56 | | |
57 | | crc32c_t(const crc32c_t&) = default; |
58 | | crc32c_t& operator=(const crc32c_t&) = default; |
59 | | |
60 | 0 | explicit operator uint32_t() const { return crc_; } |
61 | | |
62 | 0 | friend bool operator==(crc32c_t lhs, crc32c_t rhs) { |
63 | 0 | return static_cast<uint32_t>(lhs) == static_cast<uint32_t>(rhs); |
64 | 0 | } |
65 | | |
66 | 0 | friend bool operator!=(crc32c_t lhs, crc32c_t rhs) { return !(lhs == rhs); } |
67 | | |
68 | | template <typename Sink> |
69 | | friend void AbslStringify(Sink& sink, crc32c_t crc) { |
70 | | absl::Format(&sink, "%08x", static_cast<uint32_t>(crc)); |
71 | | } |
72 | | |
73 | | private: |
74 | | uint32_t crc_; |
75 | | }; |
76 | | |
77 | | |
78 | | namespace crc_internal { |
79 | | // Non-inline code path for `absl::ExtendCrc32c()`. Do not call directly. |
80 | | // Call `absl::ExtendCrc32c()` (defined below) instead. |
81 | | crc32c_t ExtendCrc32cInternal(crc32c_t initial_crc, |
82 | | absl::string_view buf_to_add); |
83 | | } // namespace crc_internal |
84 | | |
85 | | // ----------------------------------------------------------------------------- |
86 | | // CRC32C Computation Functions |
87 | | // ----------------------------------------------------------------------------- |
88 | | |
89 | | // ExtendCrc32c() |
90 | | // |
91 | | // Computes a CRC32C value from an `initial_crc` CRC32C value including the |
92 | | // `buf_to_add` bytes of an additional buffer. Using this function is more |
93 | | // efficient than computing a CRC32C value for the combined buffer from |
94 | | // scratch. |
95 | | // |
96 | | // Note: `ExtendCrc32c` with an initial_crc of 0 is equivalent to |
97 | | // `ComputeCrc32c`. |
98 | | // |
99 | | // This operation has a runtime cost of O(`buf_to_add.size()`) |
100 | | inline crc32c_t ExtendCrc32c(crc32c_t initial_crc, |
101 | 0 | absl::string_view buf_to_add) { |
102 | 0 | // Short inputs are faster to process inline with a simple serial loop. |
103 | 0 | if (buf_to_add.size() < crc_internal::kSmallCutoff) { |
104 | 0 | uint32_t crc = static_cast<uint32_t>(initial_crc); |
105 | 0 | if (crc_internal::ExtendCrc32cInline(&crc, buf_to_add.data(), |
106 | 0 | buf_to_add.size())) { |
107 | 0 | return crc32c_t{crc}; |
108 | 0 | } |
109 | 0 | } |
110 | 0 | return crc_internal::ExtendCrc32cInternal(initial_crc, buf_to_add); |
111 | 0 | } |
112 | | |
113 | | // ComputeCrc32c() |
114 | | // |
115 | | // Returns the CRC32C value of the provided string. |
116 | 0 | inline crc32c_t ComputeCrc32c(absl::string_view buf) { |
117 | 0 | return ExtendCrc32c(crc32c_t{0}, buf); |
118 | 0 | } |
119 | | |
120 | | // ExtendCrc32cByZeroes() |
121 | | // |
122 | | // Computes a CRC32C value for a buffer with an `initial_crc` CRC32C value, |
123 | | // where `length` bytes with a value of 0 are appended to the buffer. Using this |
124 | | // function is more efficient than computing a CRC32C value for the combined |
125 | | // buffer from scratch. |
126 | | // |
127 | | // This operation has a runtime cost of O(log(`length`)) |
128 | | crc32c_t ExtendCrc32cByZeroes(crc32c_t initial_crc, size_t length); |
129 | | |
130 | | // MemcpyCrc32c() |
131 | | // |
132 | | // Copies `src` to `dest` using `memcpy()` semantics, returning the CRC32C |
133 | | // value of the copied buffer. |
134 | | // |
135 | | // Using `MemcpyCrc32c()` is potentially faster than performing the `memcpy()` |
136 | | // and `ComputeCrc32c()` operations separately. |
137 | | crc32c_t MemcpyCrc32c(void* dest, const void* src, size_t count, |
138 | | crc32c_t initial_crc = crc32c_t{0}); |
139 | | |
140 | | // ----------------------------------------------------------------------------- |
141 | | // CRC32C Arithmetic Functions |
142 | | // ----------------------------------------------------------------------------- |
143 | | |
144 | | // The following functions perform arithmetic on CRC32C values, which are |
145 | | // generally more efficient than recalculating any given result's CRC32C value. |
146 | | |
147 | | // ConcatCrc32c() |
148 | | // |
149 | | // Calculates the CRC32C value of two buffers with known CRC32C values |
150 | | // concatenated together. |
151 | | // |
152 | | // Given a buffer with CRC32C value `crc1` and a buffer with |
153 | | // CRC32C value `crc2` and length, `crc2_length`, returns the CRC32C value of |
154 | | // the concatenation of these two buffers. |
155 | | // |
156 | | // This operation has a runtime cost of O(log(`crc2_length`)). |
157 | | crc32c_t ConcatCrc32c(crc32c_t crc1, crc32c_t crc2, size_t crc2_length); |
158 | | |
159 | | // RemoveCrc32cPrefix() |
160 | | // |
161 | | // Calculates the CRC32C value of an existing buffer with a series of bytes |
162 | | // (the prefix) removed from the beginning of that buffer. |
163 | | // |
164 | | // Given the CRC32C value of an existing buffer, `full_string_crc`; The CRC32C |
165 | | // value of a prefix of that buffer, `prefix_crc`; and the length of the buffer |
166 | | // with the prefix removed, `remaining_string_length` , return the CRC32C |
167 | | // value of the buffer with the prefix removed. |
168 | | // |
169 | | // This operation has a runtime cost of O(log(`remaining_string_length`)). |
170 | | crc32c_t RemoveCrc32cPrefix(crc32c_t prefix_crc, crc32c_t full_string_crc, |
171 | | size_t remaining_string_length); |
172 | | // RemoveCrc32cSuffix() |
173 | | // |
174 | | // Calculates the CRC32C value of an existing buffer with a series of bytes |
175 | | // (the suffix) removed from the end of that buffer. |
176 | | // |
177 | | // Given a CRC32C value of an existing buffer `full_string_crc`, the CRC32C |
178 | | // value of the suffix to remove `suffix_crc`, and the length of that suffix |
179 | | // `suffix_len`, returns the CRC32C value of the buffer with suffix removed. |
180 | | // |
181 | | // This operation has a runtime cost of O(log(`suffix_len`)) |
182 | | crc32c_t RemoveCrc32cSuffix(crc32c_t full_string_crc, crc32c_t suffix_crc, |
183 | | size_t suffix_length); |
184 | | |
185 | | // operator<< |
186 | | // |
187 | | // Streams the CRC32C value `crc` to the stream `os`. |
188 | 0 | inline std::ostream& operator<<(std::ostream& os, crc32c_t crc) { |
189 | 0 | return os << absl::StreamFormat("%08x", static_cast<uint32_t>(crc)); |
190 | 0 | } |
191 | | |
192 | | ABSL_NAMESPACE_END |
193 | | } // namespace absl |
194 | | |
195 | | #endif // ABSL_CRC_CRC32C_H_ |