From f6e6098f9005aca209bbb2542e0e2815346d685c Mon Sep 17 00:00:00 2001 From: Andrew Tribick Date: Sun, 2 Jun 2024 19:15:22 +0200 Subject: [PATCH] Update binaryread, binarywrite to depend on celcompat/bit.h - Add fromMemory* methods for buffered read support - Use new fromMemory* methods in stardb.cpp --- CMakeLists.txt | 3 - config.h.in | 1 - src/celengine/stardb.cpp | 64 +++------------- src/celutil/binaryread.h | 156 ++++++++++++++++++++------------------ src/celutil/binarywrite.h | 114 +++++++++------------------- 5 files changed, 129 insertions(+), 209 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f80a92b6f..e6fd37548d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -494,9 +494,6 @@ else() message(WARNING "C++ charconv is unusable!\nWill use own implementation.") endif() -include(TestBigEndian) -test_big_endian(WORDS_BIGENDIAN) - configure_file("config.h.in" "config.h") configure_file("celestia.cfg.in" "celestia.cfg") diff --git a/config.h.in b/config.h.in index e0d9b899cc..01c179ba8b 100644 --- a/config.h.in +++ b/config.h.in @@ -8,7 +8,6 @@ #cmakedefine HAVE_SINCOS #cmakedefine HAVE_APPLE_SINCOS #cmakedefine HAVE_CONSTEXPR_EMPTY_ARRAY -#cmakedefine WORDS_BIGENDIAN #ifdef HAVE_CONSTEXPR_CMATH #define CELESTIA_CMATH_CONSTEXPR constexpr diff --git a/src/celengine/stardb.cpp b/src/celengine/stardb.cpp index 74067a71e9..6b13e06ec3 100644 --- a/src/celengine/stardb.cpp +++ b/src/celengine/stardb.cpp @@ -25,9 +25,9 @@ #include #include -#include #include #include +#include #include #include #include @@ -106,46 +106,6 @@ constexpr inline AstroCatalog::IndexNumber TYC3_MAX = 3u; // from TYC2 constexpr inline AstroCatalog::IndexNumber TDSC_TYC3_MAX = 4u; constexpr inline AstroCatalog::IndexNumber TDSC_TYC3_MAX_RANGE_TYC1 = 2907u; - -template, int> = 0> -T -readIntLE(const char* src) -{ - using celestia::compat::byteswap; - using celestia::compat::endian; - - T result; - std::memcpy(&result, src, sizeof(T)); - if constexpr (endian::native == endian::little) - return result; - else - return celestia::compat::byteswap(result); -} - - -float -readFloatLE(const char* src) -{ - using celestia::compat::byteswap; - using celestia::compat::endian; - float result; - if constexpr (endian::native == endian::little) - { - std::memcpy(&result, src, sizeof(float)); - } - else - { - static_assert(sizeof(std::uint32_t) == sizeof(float)); - std::uint32_t temp; - std::memcpy(&temp, src, sizeof(float)); - temp = byteswap(temp); - std::memcpy(&result, &temp, sizeof(float)); - } - - return result; -} - - #pragma pack(push, 1) // stars.dat header structure struct StarsDatHeader @@ -716,14 +676,14 @@ StarDatabaseBuilder::loadBinary(std::istream& in) // Verify the version - if (auto version = readIntLE(header.data() + offsetof(StarsDatHeader, version)); + if (auto version = util::fromMemoryLE(header.data() + offsetof(StarsDatHeader, version)); version != StarDBVersion) { return false; } // Read the star count - nStarsInFile = readIntLE(header.data() + offsetof(StarsDatHeader, counter)); + nStarsInFile = util::fromMemoryLE(header.data() + offsetof(StarsDatHeader, counter)); } constexpr std::uint32_t BUFFER_RECORDS = UINT32_C(4096) / sizeof(StarsDatRecord); @@ -738,12 +698,12 @@ StarDatabaseBuilder::loadBinary(std::istream& in) const char* ptr = buffer.data(); for (std::uint32_t i = 0; i < recordsToRead; ++i) { - auto catNo = readIntLE(ptr + offsetof(StarsDatRecord, catNo)); - float x = readFloatLE(ptr + offsetof(StarsDatRecord, x)); - float y = readFloatLE(ptr + offsetof(StarsDatRecord, y)); - float z = readFloatLE(ptr + offsetof(StarsDatRecord, z)); - auto absMag = readIntLE(ptr + offsetof(StarsDatRecord, absMag)); - auto spectralType = readIntLE(ptr + offsetof(StarsDatRecord, spectralType)); + auto catNo = util::fromMemoryLE(ptr + offsetof(StarsDatRecord, catNo)); + auto x = util::fromMemoryLE(ptr + offsetof(StarsDatRecord, x)); + auto y = util::fromMemoryLE(ptr + offsetof(StarsDatRecord, y)); + auto z = util::fromMemoryLE(ptr + offsetof(StarsDatRecord, z)); + auto absMag = util::fromMemoryLE(ptr + offsetof(StarsDatRecord, absMag)); + auto spectralType = util::fromMemoryLE(ptr + offsetof(StarsDatRecord, spectralType)); Star star; star.setPosition(x, y, z); @@ -1070,7 +1030,7 @@ StarDatabaseBuilder::loadCrossIndex(StarCatalog catalog, std::istream& in) } // Verify the version - auto version = readIntLE(header.data() + offsetof(CrossIndexHeader, version)); + auto version = util::fromMemoryLE(header.data() + offsetof(CrossIndexHeader, version)); if (version != CrossIndexVersion) { GetLogger()->error(_("Bad version for cross index\n")); @@ -1115,8 +1075,8 @@ StarDatabaseBuilder::loadCrossIndex(StarCatalog catalog, std::istream& in) while (remainingRecords-- > 0) { StarDatabase::CrossIndexEntry& ent = xindex.emplace_back(); - ent.catalogNumber = readIntLE(ptr + offsetof(CrossIndexRecord, catalogNumber)); - ent.celCatalogNumber = readIntLE(ptr + offsetof(CrossIndexRecord, celCatalogNumber)); + ent.catalogNumber = util::fromMemoryLE(ptr + offsetof(CrossIndexRecord, catalogNumber)); + ent.celCatalogNumber = util::fromMemoryLE(ptr + offsetof(CrossIndexRecord, celCatalogNumber)); ptr += sizeof(CrossIndexRecord); } } diff --git a/src/celutil/binaryread.h b/src/celutil/binaryread.h index 34b15b1c65..1cdfd1ea77 100644 --- a/src/celutil/binaryread.h +++ b/src/celutil/binaryread.h @@ -1,122 +1,128 @@ #pragma once +#include +#include #include #include #include #include -#include - +#include namespace celestia::util { /*! Read a value stored in machine-native byte order from an input stream. */ -template::value>> -inline bool readNative(std::istream& in, T& value) +template, int> = 0> +inline bool +readNative(std::istream& in, T& value) { - char data[sizeof(T)]; - if (!in.read(data, sizeof(T)).good()) { return false; } - std::memcpy(&value, data, sizeof(T)); - return true; + return in.read(reinterpret_cast(&value), sizeof(T)).good(); /* Flawfinder: ignore */ //NOSONAR } -template<> -inline bool readNative(std::istream& in, char& value) +/*! Read a value stored in machine-native byte order from memory. + */ +template, int> = 0> +inline T +fromMemoryNative(const void* src) //NOSONAR { - return in.get(value).good(); + T value; + std::memcpy(&value, src, sizeof(T)); + return value; } -template<> -inline bool readNative(std::istream& in, signed char& value) +/*! Read a value stored opposite to machine-native byte order from an input stream. + */ +template, int> = 0> +inline bool +readReversed(std::istream& in, T& value) { - char c; - if (!in.get(c).good()) { return false; } - value = static_cast(c); - return true; -} + if constexpr (sizeof(T) == 1) + return readNative(in, value); -template<> -inline bool readNative(std::istream& in, unsigned char& value) -{ - char c; - if (!in.get(c).good()) { return false; } - value = static_cast(c); - return true; -} + std::array temp; + if (!in.read(temp.data(), sizeof(T)).good()) /* Flawfinder: ignore */ + return false; + constexpr auto halfSize = sizeof(T) / 2; + for (std::size_t i = 0; i < halfSize; ++i) + std::swap(temp[i], temp[sizeof(T) - i - 1]); -/*! Read a value stored opposite to machine-native byte order from an input stream - */ -template::value>> -inline bool readReversed(std::istream& in, T& value) -{ - char data[sizeof(T)]; - if (!in.read(data, sizeof(T)).good()) { return false; } - for (std::size_t i = 0; i < sizeof(T) / 2; ++i) - { - std::swap(data[i], data[sizeof(T) - i - 1]); - } - - std::memcpy(&value, data, sizeof(T)); + std::memcpy(&value, temp.data(), sizeof(T)); return true; } -template<> -inline bool readReversed(std::istream& in, char& value) -{ - return readNative(in, value); -} - -template<> -inline bool readReversed(std::istream& in, signed char& value) -{ - return readNative(in, value); -} - -template<> -inline bool readReversed(std::istream& in, unsigned char& value) +/*! Read a value stored opposite to machine-native byte order from memory. + */ +template, int> = 0> +inline T +fromMemoryReversed(const void* src) //NOSONAR { - return readNative(in, value); + if constexpr (sizeof(T) == 1) + return fromMemoryNative(src); + + std::array temp; + std::memcpy(temp.data(), src, sizeof(T)); + constexpr auto halfSize = sizeof(T) / 2; + for (std::size_t i = 0; i < halfSize; ++i) + std::swap(temp[i], temp[sizeof(T) - i - 1]); + + T value; + std::memcpy(&value, temp.data(), sizeof(T)); + return value; } -#ifdef WORDS_BIGENDIAN - /*! Read a value stored in little-endian byte order from an input stream. */ -template::value>> -inline bool readLE(std::istream& in, T& value) +template, int> = 0> +inline bool +readLE(std::istream& in, T& value) { - return readReversed(in, value); + using celestia::compat::endian; + if constexpr (endian::native == endian::little) + return readNative(in, value); + else + return readReversed(in, value); } -/*! Read a value stored in big-endian byte order from an input stream. +/*! Read a value stored in little-endian byte order from memory. */ -template::value>> -inline bool readBE(std::istream& in, T& value) +template, int> = 0> +inline T +fromMemoryLE(const void* src) //NOSONAR { - return readNative(in, value); + using celestia::compat::endian; + if constexpr (endian::native == endian::little) + return fromMemoryNative(src); + else + return fromMemoryReversed(src); } -#else - -/*! Read a value stored in little-endian byte order from an input stream. +/*! Read a value stored in big-endian byte order from an input stream. */ -template::value>> -inline bool readLE(std::istream& in, T& value) +template, int> = 0> +inline bool +readBE(std::istream& in, T& value) { - return readNative(in, value); + using celestia::compat::endian; + if constexpr (endian::native == endian::little) + return readReversed(in, value); + else + return readNative(in, value); } -/*! Read a value stored in big-endian byte order from an input stream. +/*! Read a value stored in big-endian byte order from memory. */ -template::value>> -inline bool readBE(std::istream& in, T& value) +template, int> = 0> +inline T +fromMemoryBE(const void* src) //NOSONAR { - return readReversed(in, value); + using celestia::compat::endian; + if constexpr (endian::native == endian::little) + return fromMemoryReversed(src); + else + return fromMemoryNative(src); } -#endif - } // end namespace celestia::util diff --git a/src/celutil/binarywrite.h b/src/celutil/binarywrite.h index 12b72c82ef..199b5cb2f4 100644 --- a/src/celutil/binarywrite.h +++ b/src/celutil/binarywrite.h @@ -1,113 +1,71 @@ #pragma once +#include +#include #include #include #include #include -#include - +#include namespace celestia::util { /*! Write a value to an output stream in machine-native byte order. */ -template::value>> -inline bool writeNative(std::ostream& out, T value) +template, int> = 0> +inline bool +writeNative(std::ostream& out, T value) { - char data[sizeof(T)]; - std::memcpy(data, &value, sizeof(T)); - return out.write(data, sizeof(T)).good(); + return out.write(reinterpret_cast(&value), sizeof(T)).good(); //NOSONAR } -template<> -inline bool writeNative(std::ostream& out, char value) -{ - return out.put(value).good(); -} - -template<> -inline bool writeNative(std::ostream& out, signed char value) -{ - return out.put(static_cast(value)).good(); -} - -template<> -inline bool writeNative(std::ostream& out, unsigned char value) -{ - return out.put(static_cast(value)).good(); -} - - /*! Write a value to an output stream with the opposite of machine-native byte order. */ -template::value>> -inline bool writeReversed(std::ostream& out, T value) -{ - char data[sizeof(T)]; - std::memcpy(data, &value, sizeof(T)); - for (std::size_t i = 0; i < sizeof(T) / 2; ++i) - { - std::swap(data[i], data[sizeof(T) - i - 1]); - } - return out.write(data, sizeof(T)).good(); -} - -template<> -inline bool writeReversed(std::ostream& out, char value) -{ - return writeNative(out, value); -} - -template<> -inline bool writeReversed(std::ostream& out, signed char value) +template, int> = 0> +inline bool +writeReversed(std::ostream& out, T value) { - return writeNative(out, value); -} + if constexpr (sizeof(T) == 1) + return writeNative(out, value); -template<> -inline bool writeReversed(std::ostream& out, unsigned char value) -{ - return writeNative(out, value); -} + std::array temp; + std::memcpy(temp.data(), &value, sizeof(T)); -#ifdef WORDS_BIGENDIAN - -/*! Write a value to an output stream in little-endian byte order - */ -template::value>> -inline bool writeLE(std::ostream& out, T value) -{ - return writeReversed(out, value); -} + constexpr auto halfSize = sizeof(T) / 2; + for (std::size_t i = 0; i < halfSize; ++i) + { + std::swap(temp[i], temp[sizeof(T) - i - 1]); + } -/*! Write a value to an output stream in big-endian byte order - */ -template::value>> -inline bool writeBE(std::ostream& out, T value) -{ - return writeNative(out, value); + return out.write(temp.data(), sizeof(T)).good(); } -#else - /*! Write a value to an output stream in little-endian byte order */ -template::value>> -inline bool writeLE(std::ostream& out, T value) +template, int> = 0> +inline bool +writeLE(std::ostream& out, T value) { - return writeNative(out, value); + using celestia::compat::endian; + if constexpr (endian::native == endian::little) + return writeNative(out, value); + else + return writeReversed(out, value); } /*! Write a value to an output stream in big-endian byte order */ -template::value>> -inline bool writeBE(std::ostream& out, T value) +template, int> = 0> +inline bool +writeBE(std::ostream& out, T value) { - return writeReversed(out, value); + using celestia::compat::endian; + if constexpr (endian::native == endian::little) + return writeReversed(out, value); + else + return writeNative(out, value); } -#endif - } // end namespace celestia::util