]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Add Util::big_endian_to_int and Util::int_to_big_endian
authorJoel Rosdahl <joel@rosdahl.net>
Sun, 29 Sep 2019 13:07:55 +0000 (15:07 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Sat, 5 Oct 2019 21:16:46 +0000 (23:16 +0200)
src/Util.hpp
unittest/test_Util.cpp

index e2bd39574a4343557bf89d418013679f9181d3c4..f75a51ddad5f5f0391b8469418f6f0e687070d2d 100644 (file)
@@ -39,6 +39,36 @@ typedef std::function<void(const std::string& /*dir_path*/,
 // Get base name of path.
 std::string base_name(const std::string& path);
 
+// Get an integer value from bytes in big endian order.
+//
+// Parameters:
+// - buffer: Bytes to read.
+// - count: Number of bytes to read.
+template<typename T>
+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];
+}
+
 // Create a directory if needed, including its parents if needed.
 //
 // Returns true if the directory exists or could be created, otherwise false.
@@ -93,6 +123,35 @@ void get_level_1_files(const std::string& dir,
                        const ProgressReceiver& progress_receiver,
                        std::vector<std::shared_ptr<CacheFile>>& files);
 
+// Write bytes in big endian order from an integer value.
+//
+// Parameters:
+// - value: Integer value to read.
+// - buffer: Buffer to write bytes to.
+template<typename T>
+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;
+}
+
 // Parse a string into an integer.
 //
 // Throws Error on error.
index b6d2059235d12fac8fd383a7e2c7ef7c82258ab0..9d55a826bd4dd1f7120b9210c5f5b038607e8522 100644 (file)
@@ -32,6 +32,43 @@ 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::create_dir")
 {
   CHECK(Util::create_dir("/"));
@@ -165,6 +202,65 @@ TEST_CASE("Util::get_level_1_files")
   }
 }
 
+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::parse_int")
 {
   CHECK(Util::parse_int("0") == 0);