summaryrefslogtreecommitdiff
path: root/absl/crc/crc32c.h
diff options
context:
space:
mode:
authorGravatar Derek Mauro <dmauro@google.com>2022-11-29 09:19:04 -0800
committerGravatar Copybara-Service <copybara-worker@google.com>2022-11-29 09:19:57 -0800
commitd03cced7d552ece168c6db92acb3a7c379aae0c0 (patch)
treef5975b279620e410ad017ee09bceaee4c676fec1 /absl/crc/crc32c.h
parent82196f059f213c50738142a799bb166b2971950d (diff)
CRC: Make crc32c_t as a class for explicit control of operators
The motivation is to explicitly remove and document dangerous operations like adding crc32c_t to a set, because equality is not enough to guarantee uniqueness. PiperOrigin-RevId: 491656425 Change-Id: I7b4dadc1a59ea9861e6ec7a929d64b5746467832
Diffstat (limited to 'absl/crc/crc32c.h')
-rw-r--r--absl/crc/crc32c.h46
1 files changed, 27 insertions, 19 deletions
diff --git a/absl/crc/crc32c.h b/absl/crc/crc32c.h
index 8b030732..7be42be5 100644
--- a/absl/crc/crc32c.h
+++ b/absl/crc/crc32c.h
@@ -39,24 +39,32 @@ ABSL_NAMESPACE_BEGIN
// crc32c_t
//-----------------------------------------------------------------------------
-// `crc32c_t` defines a strongly typed integer type for holding a CRC32C value.
-enum class crc32c_t : uint32_t {};
-
-// ToCrc32c()
-//
-// Converts a uint32_t value to crc32c_t. This API is necessary in C++14
-// and earlier. Code targeting C++17-or-later can instead use `crc32c_t{n}`.
-inline crc32c_t ToCrc32c(uint32_t n) {
- return static_cast<crc32c_t>(n);
-}
-// operator^
+// `crc32c_t` defines a strongly-typed integer for holding a CRC32C value.
//
-// Performs a bitwise XOR on two CRC32C values
-inline crc32c_t operator^(crc32c_t lhs, crc32c_t rhs) {
- const auto lhs_int = static_cast<uint32_t>(lhs);
- const auto rhs_int = static_cast<uint32_t>(rhs);
- return ToCrc32c(lhs_int ^ rhs_int);
-}
+// Some operators are intentionally omitted. Only equality operators are defined
+// so that `crc32c_t` can be directly compared. Methods for putting `crc32c_t`
+// directly into a set are omitted because this is bug-prone due to checksum
+// collisions. Use an explicit conversion to the `uint32_t` space for operations
+// that treat `crc32c_t` as an integer.
+class crc32c_t final {
+ public:
+ crc32c_t() = default;
+ constexpr explicit crc32c_t(uint32_t crc) : crc_(crc) {}
+
+ crc32c_t(const crc32c_t&) = default;
+ crc32c_t& operator=(const crc32c_t&) = default;
+
+ explicit operator uint32_t() const { return crc_; }
+
+ friend bool operator==(crc32c_t lhs, crc32c_t rhs) {
+ return static_cast<uint32_t>(lhs) == static_cast<uint32_t>(rhs);
+ }
+
+ friend bool operator!=(crc32c_t lhs, crc32c_t rhs) { return !(lhs == rhs); }
+
+ private:
+ uint32_t crc_;
+};
namespace crc_internal {
// Non-inline code path for `absl::ExtendCrc32c()`. Do not call directly.
@@ -92,7 +100,7 @@ inline crc32c_t ExtendCrc32c(crc32c_t initial_crc,
uint32_t crc = static_cast<uint32_t>(initial_crc);
if (crc_internal::ExtendCrc32cInline(&crc, buf_to_add.data(),
buf_to_add.size())) {
- return ToCrc32c(crc);
+ return crc32c_t{crc};
}
}
return crc_internal::ExtendCrc32cInternal(initial_crc, buf_to_add);
@@ -116,7 +124,7 @@ crc32c_t ExtendCrc32cByZeroes(crc32c_t initial_crc, size_t length);
// Using `MemcpyCrc32c()` is potentially faster than performing the `memcpy()`
// and `ComputeCrc32c()` operations separately.
crc32c_t MemcpyCrc32c(void* dest, const void* src, size_t count,
- crc32c_t initial_crc = ToCrc32c(0));
+ crc32c_t initial_crc = crc32c_t{0});
// -----------------------------------------------------------------------------
// CRC32C Arithmetic Functions