From ab006a33724b2f1e659f9b7d9b936e3e8ef9a11d Mon Sep 17 00:00:00 2001 From: harrand Date: Sat, 23 Sep 2023 02:00:43 +0100 Subject: [PATCH] [tz::core] added tz::big_endian and tz::little_endian aswell as a documentation pass over the new endian code --- src/tz/core/endian.hpp | 73 ++++++++++++++++++++++++++++++++++++++++++ src/tz/io/ttf.cpp | 39 ++++++---------------- 2 files changed, 82 insertions(+), 30 deletions(-) diff --git a/src/tz/core/endian.hpp b/src/tz/core/endian.hpp index 6b9945c70d..209ca5ccf4 100644 --- a/src/tz/core/endian.hpp +++ b/src/tz/core/endian.hpp @@ -1,17 +1,90 @@ #ifndef TOPAZ_CORE_ENDIAN_HPP #define TOPAZ_CORE_ENDIAN_HPP +#include namespace tz { + /** + * @ingroup tz_core + * Indicates the endianness of scalar types. + **/ enum class endian { + /// Little Endian little, + /// Big Endian big }; + /** + * @ingroup tz_core + * Query the endianness of the running machine. + * @return `endian::little` if machine is little-endian, or `endian::big` otherwise. + **/ endian get_local_machine_endianness(); + /** + * @ingroup tz_core + * Query as to whether the current system is big-endian. + * @note Equivalent to `tz::get_local_machine_endianness() == endian::big` + **/ bool is_big_endian(); + /** + * @ingroup tz_core + * Query as to whether the current system is littel-endian. + * @note Equivalent to `tz::get_local_machine_endianness() == endian::little` + **/ bool is_little_endian(); + + /** + * @ingroup tz_core + * Given an integral type, make a copy of the value, swap its bytes, and then return it. + * If the value for example is little-endian, then the result will be its big-endian variant. + * @param value Value to byte swap. + * @return Copy of value, with endianness swapped. + **/ + template + T endian_byte_swap(T value) + { + char* bytes = reinterpret_cast(&value); + std::size_t sz = sizeof(T); + for(std::size_t i = 0; i < sz / 2; i++) + { + std::swap(bytes[i], bytes[sz - i - 1]); + } + return value; + } + + /** + * @ingroup tz_core + * Retrieve a scalar value in big-endian form. If the system is detected to be big-endian, the value is unchanged. + * @param value The value to ensure is big-endian. + * @return Byte-swap of the value if the system is little-endian, otherwise the same value. + **/ + template + T big_endian(T value) + { + if(is_big_endian()) + { + return value; + } + return endian_byte_swap(value); + } + + /** + * @ingroup tz_core + * Retrieve a scalar value in little-endian form. If the system is detected to be little-endian, the value is unchanged. + * @param value The value to ensure is little-endian. + * @return Byte-swap of the value if the system is big-endian, otherwise the same value. + **/ + template + T little_endian(T value) + { + if(is_little_endian()) + { + return value; + } + return endian_byte_swap(value); + } } #endif // TOPAZ_CORE_ENDIAN_HPP \ No newline at end of file diff --git a/src/tz/io/ttf.cpp b/src/tz/io/ttf.cpp index 136af6adbe..3661d960f4 100644 --- a/src/tz/io/ttf.cpp +++ b/src/tz/io/ttf.cpp @@ -30,39 +30,18 @@ namespace tz::io this->parse_table_info(ttf_minus_header, ttf_data); } - std::uint32_t big_endian(std::uint32_t value) { - if(tz::is_big_endian()) - { - return value; - } - return ((value >> 24) & 0x000000FF) | // Move the first byte to the last position - ((value >> 8) & 0x0000FF00) | // Move the second byte to the second position - ((value << 8) & 0x00FF0000) | // Move the third byte to the third position - ((value << 24) & 0xFF000000); // Move the last byte to the first position - } - - std::uint16_t big_endian(std::uint16_t value) - { - if(tz::is_big_endian()) - { - return value; - } - return ((value >> 8) & 0x00FF) | // Swap the high byte and low byte - ((value << 8) & 0xFF00); - } - std::string_view ttf::parse_header(std::string_view str) { const char* ptr = str.data(); - this->header.scalar_type = big_endian(*reinterpret_cast(ptr)); + this->header.scalar_type = tz::big_endian(*reinterpret_cast(ptr)); ptr += sizeof(std::uint32_t); - this->header.num_tables = big_endian(*reinterpret_cast(ptr)); + this->header.num_tables = tz::big_endian(*reinterpret_cast(ptr)); ptr += sizeof(std::uint16_t); - this->header.search_range = big_endian(*reinterpret_cast(ptr)); + this->header.search_range = tz::big_endian(*reinterpret_cast(ptr)); ptr += sizeof(std::uint16_t); - this->header.entry_selector = big_endian(*reinterpret_cast(ptr)); + this->header.entry_selector = tz::big_endian(*reinterpret_cast(ptr)); ptr += sizeof(std::uint16_t); - this->header.range_shift = big_endian(*reinterpret_cast(ptr)); + this->header.range_shift = tz::big_endian(*reinterpret_cast(ptr)); ptr += sizeof(std::uint16_t); auto byte_diff = std::distance(str.data(), ptr); @@ -80,11 +59,11 @@ namespace tz::io ttf_table& tbl = this->tables.emplace_back(); std::memcpy(tbl.tag, ptr, 4); ptr += 4; - tbl.checksum = big_endian(*reinterpret_cast(ptr)); + tbl.checksum = tz::big_endian(*reinterpret_cast(ptr)); ptr += sizeof(std::uint32_t); - tbl.offset = big_endian(*reinterpret_cast(ptr)); + tbl.offset = tz::big_endian(*reinterpret_cast(ptr)); ptr += sizeof(std::uint32_t); - tbl.length = big_endian(*reinterpret_cast(ptr)); + tbl.length = tz::big_endian(*reinterpret_cast(ptr)); ptr += sizeof(std::uint32_t); if(tbl.tag[0] != 'h' || tbl.tag[1] != 'e' || tbl.tag[2] != 'a' || tbl.tag[3] != 'd') @@ -100,7 +79,7 @@ namespace tz::io std::uint32_t sum = 0u; for(std::size_t i = 0; i < length; i += sizeof(std::uint32_t)) { - sum += big_endian(*reinterpret_cast(data.data() + offset + i)); + sum += tz::big_endian(*reinterpret_cast(data.data() + offset + i)); } return sum; }