From: Joel Rosdahl Date: Fri, 7 Jul 2023 14:31:31 +0000 (+0200) Subject: refactor: Move functions for endian conversion to util X-Git-Tag: v4.9~143 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=119e8fca780c332968487f4fb91d97db9ba52388;p=thirdparty%2Fccache.git refactor: Move functions for endian conversion to util --- diff --git a/src/InodeCache.cpp b/src/InodeCache.cpp index 4f17ebba3..44b713069 100644 --- a/src/InodeCache.cpp +++ b/src/InodeCache.cpp @@ -27,6 +27,8 @@ #include "Util.hpp" #include "fmtmacros.hpp" +#include + #include #include #include @@ -312,7 +314,7 @@ InodeCache::with_bucket(const Hash::Digest& key_digest, const BucketHandler& bucket_handler) { uint32_t hash; - Util::big_endian_to_int(key_digest.data(), hash); + util::big_endian_to_int(key_digest.data(), hash); const uint32_t index = hash % k_num_buckets; Bucket* bucket = &m_sr->buckets[index]; bool acquired_lock = spin_lock(bucket->owner_pid, m_self_pid); diff --git a/src/Util.hpp b/src/Util.hpp index 13e8bd2c2..2db92fdff 100644 --- a/src/Util.hpp +++ b/src/Util.hpp @@ -45,36 +45,6 @@ enum class UnlinkLog { log_failure, ignore_failure }; // Get base name of path. std::string_view base_name(std::string_view path); -// Get an integer value from bytes in big endian order. -// -// Parameters: -// - buffer: Bytes to read. -// - count: Number of bytes to read. -template -void -big_endian_to_int(const uint8_t* buffer, T& value) -{ - value = 0; - for (size_t i = 0; i < sizeof(T); ++i) { - value <<= 8; - value |= buffer[i]; - } -} - -template<> -inline void -big_endian_to_int(const uint8_t* buffer, int8_t& value) -{ - value = buffer[0]; -} - -template<> -inline void -big_endian_to_int(const uint8_t* buffer, uint8_t& value) -{ - value = buffer[0]; -} - // Remove the extension via `remove_extension()`, then add `new_ext`. `new_ext` // should start with a dot, no extra dot is inserted. std::string change_extension(std::string_view path, std::string_view new_ext); @@ -168,35 +138,6 @@ mode_t get_umask(); // Hard-link `oldpath` to `newpath`. Throws `core::Error` on error. void hard_link(const std::string& oldpath, const std::string& newpath); -// Write bytes in big endian order from an integer value. -// -// Parameters: -// - value: Integer value to read. -// - buffer: Buffer to write bytes to. -template -void -int_to_big_endian(T value, uint8_t* buffer) -{ - for (size_t i = 0; i < sizeof(T); ++i) { - buffer[sizeof(T) - i - 1] = value & 0xFF; - value >>= 8; - } -} - -template<> -inline void -int_to_big_endian(uint8_t value, uint8_t* buffer) -{ - buffer[0] = value; -} - -template<> -inline void -int_to_big_endian(int8_t value, uint8_t* buffer) -{ - buffer[0] = value; -} - // Determine if `path` is an absolute path with prefix, returning the split // point. std::optional is_absolute_path_with_prefix(std::string_view path); diff --git a/src/core/CacheEntryDataReader.hpp b/src/core/CacheEntryDataReader.hpp index b889a0025..cd6793f4a 100644 --- a/src/core/CacheEntryDataReader.hpp +++ b/src/core/CacheEntryDataReader.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2022 Joel Rosdahl and other contributors +// Copyright (C) 2022-2023 Joel Rosdahl and other contributors // // See doc/AUTHORS.adoc for a complete list of contributors. // @@ -18,9 +18,9 @@ #pragma once -#include #include #include +#include #include #include @@ -92,7 +92,7 @@ CacheEntryDataReader::read_int() { const auto buffer = read_bytes(sizeof(T)); T value; - Util::big_endian_to_int(buffer.data(), value); + util::big_endian_to_int(buffer.data(), value); return value; } diff --git a/src/core/CacheEntryDataWriter.hpp b/src/core/CacheEntryDataWriter.hpp index 92890f06c..8bbff8ca3 100644 --- a/src/core/CacheEntryDataWriter.hpp +++ b/src/core/CacheEntryDataWriter.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2022 Joel Rosdahl and other contributors +// Copyright (C) 2022-2023 Joel Rosdahl and other contributors // // See doc/AUTHORS.adoc for a complete list of contributors. // @@ -18,9 +18,9 @@ #pragma once -#include #include #include +#include #include #include @@ -65,7 +65,7 @@ inline void CacheEntryDataWriter::write_int(const T value) { uint8_t buffer[sizeof(T)]; - Util::int_to_big_endian(value, buffer); + util::int_to_big_endian(value, buffer); write_bytes(buffer); } diff --git a/src/util/XXH3_128.hpp b/src/util/XXH3_128.hpp index 309ac7cc3..13e3e207c 100644 --- a/src/util/XXH3_128.hpp +++ b/src/util/XXH3_128.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2021-2022 Joel Rosdahl and other contributors +// Copyright (C) 2021-2023 Joel Rosdahl and other contributors // // See doc/AUTHORS.adoc for a complete list of contributors. // @@ -18,8 +18,8 @@ #pragma once -#include #include +#include #include #ifdef USE_XXH_DISPATCH @@ -76,8 +76,8 @@ XXH3_128::digest() const { const auto result = XXH3_128bits_digest(m_state); util::Bytes digest(k_digest_size); - Util::int_to_big_endian(result.high64, &digest[0]); - Util::int_to_big_endian(result.low64, &digest[8]); + util::int_to_big_endian(result.high64, &digest[0]); + util::int_to_big_endian(result.low64, &digest[8]); return digest; } diff --git a/src/util/conversion.hpp b/src/util/conversion.hpp index 6592b3526..841892b79 100644 --- a/src/util/conversion.hpp +++ b/src/util/conversion.hpp @@ -30,6 +30,20 @@ namespace util { // --- Interface --- +// Get an integer value from bytes in big endian order. +// +// Parameters: +// - buffer: Bytes to read. +// - count: Number of bytes to read. +template void big_endian_to_int(const uint8_t* buffer, T& value); + +// Write bytes in big endian order from an integer value. +// +// Parameters: +// - value: Integer value to read. +// - buffer: Buffer to write bytes to. +template void int_to_big_endian(T value, uint8_t* buffer); + // Convert `data` to a `nonstd::span`. nonstd::span to_span(const void* data, size_t size); @@ -45,6 +59,55 @@ std::string_view to_string_view(nonstd::span data); // --- Inline implementations --- +template +void +big_endian_to_int(const uint8_t* buffer, T& value) +{ + value = 0; + for (size_t i = 0; i < sizeof(T); ++i) { + value <<= 8; + value |= buffer[i]; + } +} + +template<> +inline void +big_endian_to_int(const uint8_t* buffer, int8_t& value) +{ + value = buffer[0]; +} + +template<> +inline void +big_endian_to_int(const uint8_t* buffer, uint8_t& value) +{ + value = buffer[0]; +} + +template +void +int_to_big_endian(T value, uint8_t* buffer) +{ + for (size_t i = 0; i < sizeof(T); ++i) { + buffer[sizeof(T) - i - 1] = value & 0xFF; + value >>= 8; + } +} + +template<> +inline void +int_to_big_endian(uint8_t value, uint8_t* buffer) +{ + buffer[0] = value; +} + +template<> +inline void +int_to_big_endian(int8_t value, uint8_t* buffer) +{ + buffer[0] = value; +} + inline nonstd::span to_span(const void* data, size_t size) { diff --git a/unittest/test_Util.cpp b/unittest/test_Util.cpp index a5b6b00df..062bad5da 100644 --- a/unittest/test_Util.cpp +++ b/unittest/test_Util.cpp @@ -54,43 +54,6 @@ TEST_CASE("Util::base_name") CHECK(Util::base_name("/foo/bar/f.txt") == "f.txt"); } -TEST_CASE("Util::big_endian_to_int") -{ - uint8_t bytes[8] = {0x70, 0x9e, 0x9a, 0xbc, 0xd6, 0x54, 0x4b, 0xca}; - - uint8_t uint8; - Util::big_endian_to_int(bytes, uint8); - CHECK(uint8 == 0x70); - - int8_t int8; - Util::big_endian_to_int(bytes, int8); - CHECK(int8 == 0x70); - - uint16_t uint16; - Util::big_endian_to_int(bytes, uint16); - CHECK(uint16 == 0x709e); - - int16_t int16; - Util::big_endian_to_int(bytes, int16); - CHECK(int16 == 0x709e); - - uint32_t uint32; - Util::big_endian_to_int(bytes, uint32); - CHECK(uint32 == 0x709e9abc); - - int32_t int32; - Util::big_endian_to_int(bytes, int32); - CHECK(int32 == 0x709e9abc); - - uint64_t uint64; - Util::big_endian_to_int(bytes, uint64); - CHECK(uint64 == 0x709e9abcd6544bca); - - int64_t int64; - Util::big_endian_to_int(bytes, int64); - CHECK(int64 == 0x709e9abcd6544bca); -} - TEST_CASE("Util::change_extension") { CHECK(Util::change_extension("", "") == ""); @@ -315,65 +278,6 @@ TEST_CASE("Util::hard_link") } } -TEST_CASE("Util::int_to_big_endian") -{ - uint8_t bytes[8]; - - uint8_t uint8 = 0x70; - Util::int_to_big_endian(uint8, bytes); - CHECK(bytes[0] == 0x70); - - int8_t int8 = 0x70; - Util::int_to_big_endian(int8, bytes); - CHECK(bytes[0] == 0x70); - - uint16_t uint16 = 0x709e; - Util::int_to_big_endian(uint16, bytes); - CHECK(bytes[0] == 0x70); - CHECK(bytes[1] == 0x9e); - - int16_t int16 = 0x709e; - Util::int_to_big_endian(int16, bytes); - CHECK(bytes[0] == 0x70); - CHECK(bytes[1] == 0x9e); - - uint32_t uint32 = 0x709e9abc; - Util::int_to_big_endian(uint32, bytes); - CHECK(bytes[0] == 0x70); - CHECK(bytes[1] == 0x9e); - CHECK(bytes[2] == 0x9a); - CHECK(bytes[3] == 0xbc); - - int32_t int32 = 0x709e9abc; - Util::int_to_big_endian(int32, bytes); - CHECK(bytes[0] == 0x70); - CHECK(bytes[1] == 0x9e); - CHECK(bytes[2] == 0x9a); - CHECK(bytes[3] == 0xbc); - - uint64_t uint64 = 0x709e9abcd6544bca; - Util::int_to_big_endian(uint64, bytes); - CHECK(bytes[0] == 0x70); - CHECK(bytes[1] == 0x9e); - CHECK(bytes[2] == 0x9a); - CHECK(bytes[3] == 0xbc); - CHECK(bytes[4] == 0xd6); - CHECK(bytes[5] == 0x54); - CHECK(bytes[6] == 0x4b); - CHECK(bytes[7] == 0xca); - - int64_t int64 = 0x709e9abcd6544bca; - Util::int_to_big_endian(int64, bytes); - CHECK(bytes[0] == 0x70); - CHECK(bytes[1] == 0x9e); - CHECK(bytes[2] == 0x9a); - CHECK(bytes[3] == 0xbc); - CHECK(bytes[4] == 0xd6); - CHECK(bytes[5] == 0x54); - CHECK(bytes[6] == 0x4b); - CHECK(bytes[7] == 0xca); -} - TEST_CASE("Util::is_absolute_path_with_prefix") { CHECK(*Util::is_absolute_path_with_prefix("-I/c/foo") == 2); diff --git a/unittest/test_util_conversion.cpp b/unittest/test_util_conversion.cpp index 2daadaa2d..7eeca9e0c 100644 --- a/unittest/test_util_conversion.cpp +++ b/unittest/test_util_conversion.cpp @@ -25,6 +25,102 @@ TEST_SUITE_BEGIN("util"); +TEST_CASE("util::big_endian_to_int") +{ + uint8_t bytes[8] = {0x70, 0x9e, 0x9a, 0xbc, 0xd6, 0x54, 0x4b, 0xca}; + + uint8_t uint8; + util::big_endian_to_int(bytes, uint8); + CHECK(uint8 == 0x70); + + int8_t int8; + util::big_endian_to_int(bytes, int8); + CHECK(int8 == 0x70); + + uint16_t uint16; + util::big_endian_to_int(bytes, uint16); + CHECK(uint16 == 0x709e); + + int16_t int16; + util::big_endian_to_int(bytes, int16); + CHECK(int16 == 0x709e); + + uint32_t uint32; + util::big_endian_to_int(bytes, uint32); + CHECK(uint32 == 0x709e9abc); + + int32_t int32; + util::big_endian_to_int(bytes, int32); + CHECK(int32 == 0x709e9abc); + + uint64_t uint64; + util::big_endian_to_int(bytes, uint64); + CHECK(uint64 == 0x709e9abcd6544bca); + + int64_t int64; + util::big_endian_to_int(bytes, int64); + CHECK(int64 == 0x709e9abcd6544bca); +} + +TEST_CASE("util::int_to_big_endian") +{ + uint8_t bytes[8]; + + uint8_t uint8 = 0x70; + util::int_to_big_endian(uint8, bytes); + CHECK(bytes[0] == 0x70); + + int8_t int8 = 0x70; + util::int_to_big_endian(int8, bytes); + CHECK(bytes[0] == 0x70); + + uint16_t uint16 = 0x709e; + util::int_to_big_endian(uint16, bytes); + CHECK(bytes[0] == 0x70); + CHECK(bytes[1] == 0x9e); + + int16_t int16 = 0x709e; + util::int_to_big_endian(int16, bytes); + CHECK(bytes[0] == 0x70); + CHECK(bytes[1] == 0x9e); + + uint32_t uint32 = 0x709e9abc; + util::int_to_big_endian(uint32, bytes); + CHECK(bytes[0] == 0x70); + CHECK(bytes[1] == 0x9e); + CHECK(bytes[2] == 0x9a); + CHECK(bytes[3] == 0xbc); + + int32_t int32 = 0x709e9abc; + util::int_to_big_endian(int32, bytes); + CHECK(bytes[0] == 0x70); + CHECK(bytes[1] == 0x9e); + CHECK(bytes[2] == 0x9a); + CHECK(bytes[3] == 0xbc); + + uint64_t uint64 = 0x709e9abcd6544bca; + util::int_to_big_endian(uint64, bytes); + CHECK(bytes[0] == 0x70); + CHECK(bytes[1] == 0x9e); + CHECK(bytes[2] == 0x9a); + CHECK(bytes[3] == 0xbc); + CHECK(bytes[4] == 0xd6); + CHECK(bytes[5] == 0x54); + CHECK(bytes[6] == 0x4b); + CHECK(bytes[7] == 0xca); + + int64_t int64 = 0x709e9abcd6544bca; + util::int_to_big_endian(int64, bytes); + CHECK(bytes[0] == 0x70); + CHECK(bytes[1] == 0x9e); + CHECK(bytes[2] == 0x9a); + CHECK(bytes[3] == 0xbc); + CHECK(bytes[4] == 0xd6); + CHECK(bytes[5] == 0x54); + CHECK(bytes[6] == 0x4b); + CHECK(bytes[7] == 0xca); +} + TEST_CASE("util::to_string") { const uint8_t bytes[] = {'f', 'o', 'o'};