From 1d858885802c6a0451f128baa583381535045a62 Mon Sep 17 00:00:00 2001 From: Gregor Riepl Date: Fri, 19 Dec 2025 13:02:38 +0100 Subject: [PATCH 1/2] Byte-swap integer I/O to support big endian architectures --- src/LibBGCode/binarize/binarize.cpp | 47 ++++++++++++++------- src/LibBGCode/core/core.cpp | 63 ++++++++++++++++++----------- src/LibBGCode/core/core_impl.hpp | 10 ++++- 3 files changed, 80 insertions(+), 40 deletions(-) diff --git a/src/LibBGCode/binarize/binarize.cpp b/src/LibBGCode/binarize/binarize.cpp index 4781ed6..2da25e4 100644 --- a/src/LibBGCode/binarize/binarize.cpp +++ b/src/LibBGCode/binarize/binarize.cpp @@ -18,22 +18,37 @@ using namespace core; namespace binarize { -template -static bool write_to_file(FILE& file, const T* data, size_t data_size) +static bool write_to_file(FILE& file, const std::byte* data, size_t data_size) { const size_t wsize = fwrite(static_cast(data), 1, data_size, &file); return !ferror(&file) && wsize == data_size; } template -static bool read_from_file(FILE& file, T *data, size_t data_size) +static bool write_to_file_le(FILE& file, const T &data) { - static_assert(!std::is_const_v, "Type of output buffer cannot be const!"); + std::array temp; + store_integer_le(data, temp.begin(), temp.size()); + return write_to_file(file, temp.data(), temp.size()); +} +static bool read_from_file(FILE& file, std::byte *data, size_t data_size) +{ const size_t rsize = fread(static_cast(data), 1, data_size, &file); return !ferror(&file) && rsize == data_size; } +template +static bool read_from_file_le(FILE& file, T &data) +{ + std::array temp; + if (!read_from_file(file, temp.data(), temp.size())) { + return false; + } + data = load_integer(temp.begin(), temp.end()); + return true; +} + void update_checksum(Checksum& checksum, const ThumbnailBlock &th) { checksum.append(th.params.format); @@ -420,10 +435,10 @@ core::EResult write(const BaseMetadataBlock &block, FILE& file, core::EBlockType return res; // write block payload - if (!write_to_file(file, &block.encoding_type, sizeof(block.encoding_type))) + if (!write_to_file_le(file, block.encoding_type)) return EResult::WriteError; if (!out_data.empty()) { - if (!write_to_file(file, out_data.data(), out_data.size())) + if (!write_to_file(file, reinterpret_cast(out_data.data()), out_data.size())) return EResult::WriteError; } @@ -443,7 +458,7 @@ EResult BaseMetadataBlock::read_data(FILE& file, const BlockHeader& block_header { const ECompressionType compression_type = (ECompressionType)block_header.compression; - if (!read_from_file(file, (void*)&encoding_type, sizeof(encoding_type))) + if (!read_from_file_le(file, encoding_type)) return EResult::ReadError; if (encoding_type > metadata_encoding_types_count()) return EResult::InvalidMetadataEncodingType; @@ -452,7 +467,7 @@ EResult BaseMetadataBlock::read_data(FILE& file, const BlockHeader& block_header const size_t data_size = (compression_type == ECompressionType::None) ? block_header.uncompressed_size : block_header.compressed_size; if (data_size > 0) { data.resize(data_size); - if (!read_from_file(file, (void*)data.data(), data_size)) + if (!read_from_file(file, reinterpret_cast(data.data()), data_size)) return EResult::ReadError; } @@ -603,7 +618,7 @@ EResult ThumbnailBlock::write(FILE& file, EChecksumType checksum_type) return res; } - if (!write_to_file(file, data.data(), data.size())) + if (!write_to_file(file, reinterpret_cast(data.data()), data.size())) return EResult::WriteError; if (checksum_type != EChecksumType::None) { @@ -638,7 +653,7 @@ EResult ThumbnailBlock::read_data(FILE& file, const FileHeader& file_header, con return EResult::InvalidThumbnailDataSize; data.resize(block_header.uncompressed_size); - if (!read_from_file(file, (void*)data.data(), block_header.uncompressed_size)) + if (!read_from_file(file, reinterpret_cast(data.data()), block_header.uncompressed_size)) return EResult::ReadError; const EChecksumType checksum_type = (EChecksumType)file_header.checksum_type; @@ -683,10 +698,10 @@ EResult GCodeBlock::write(FILE& file, ECompressionType compression_type, EChecks return res; // write block payload - if (!write_to_file(file, &encoding_type, sizeof(encoding_type))) + if (!write_to_file_le(file, encoding_type)) return EResult::WriteError; if (!out_data.empty()) { - if (!write_to_file(file, out_data.data(), out_data.size())) + if (!write_to_file(file, reinterpret_cast(out_data.data()), out_data.size())) return EResult::WriteError; } @@ -696,8 +711,10 @@ EResult GCodeBlock::write(FILE& file, ECompressionType compression_type, EChecks // update checksum with block header update_checksum(cs, block_header); // update checksum with block payload + std::array swapped_encoding; + store_integer_le(encoding_type, swapped_encoding.data()); std::vector data_to_encode = - encode(reinterpret_cast(&encoding_type), sizeof(encoding_type)); + encode(swapped_encoding.data(), swapped_encoding.size()); cs.append(data_to_encode.data(), data_to_encode.size()); if (!out_data.empty()) cs.append(static_cast(out_data.data()), out_data.size()); @@ -713,7 +730,7 @@ EResult GCodeBlock::read_data(FILE& file, const FileHeader& file_header, const B { const ECompressionType compression_type = (ECompressionType)block_header.compression; - if (!read_from_file(file, (void*)&encoding_type, sizeof(encoding_type))) + if (!read_from_file_le(file, encoding_type)) return EResult::ReadError; if (encoding_type > gcode_encoding_types_count()) return EResult::InvalidGCodeEncodingType; @@ -722,7 +739,7 @@ EResult GCodeBlock::read_data(FILE& file, const FileHeader& file_header, const B const size_t data_size = (compression_type == ECompressionType::None) ? block_header.uncompressed_size : block_header.compressed_size; if (data_size > 0) { data.resize(data_size); - if (!read_from_file(file, (void*)data.data(), data_size)) + if (!read_from_file(file, reinterpret_cast(data.data()), data_size)) return EResult::ReadError; } diff --git a/src/LibBGCode/core/core.cpp b/src/LibBGCode/core/core.cpp index 1080cfb..b16e881 100644 --- a/src/LibBGCode/core/core.cpp +++ b/src/LibBGCode/core/core.cpp @@ -3,22 +3,37 @@ namespace bgcode { namespace core { -template -static bool write_to_file(FILE& file, const T* data, size_t data_size) +static bool write_to_file(FILE& file, const std::byte* data, size_t data_size) { const size_t wsize = fwrite(static_cast(data), 1, data_size, &file); return !ferror(&file) && wsize == data_size; } template -static bool read_from_file(FILE& file, T *data, size_t data_size) +static bool write_to_file_le(FILE& file, const T &data) { - static_assert(!std::is_const_v, "Type of output buffer cannot be const!"); + std::array temp; + store_integer_le(data, temp.begin(), temp.size()); + return write_to_file(file, temp.data(), temp.size()); +} +static bool read_from_file(FILE& file, std::byte *data, size_t data_size) +{ const size_t rsize = fread(static_cast(data), 1, data_size, &file); return !ferror(&file) && rsize == data_size; } +template +static bool read_from_file_le(FILE& file, T &data) +{ + std::array temp; + if (!read_from_file(file, temp.data(), temp.size())) { + return false; + } + data = load_integer(temp.begin(), temp.end()); + return true; +} + EResult verify_block_checksum(FILE& file, const FileHeader& file_header, const BlockHeader& block_header, std::byte* buffer, size_t buffer_size) { @@ -112,11 +127,11 @@ EResult FileHeader::write(FILE& file) const if (checksum_type >= checksum_types_count()) return EResult::InvalidChecksumType; - if (!write_to_file(file, &magic, sizeof(magic))) + if (!write_to_file_le(file, magic)) return EResult::WriteError; - if (!write_to_file(file, &version, sizeof(version))) + if (!write_to_file_le(file, version)) return EResult::WriteError; - if (!write_to_file(file, &checksum_type, sizeof(checksum_type))) + if (!write_to_file_le(file, checksum_type)) return EResult::WriteError; return EResult::Success; @@ -124,17 +139,17 @@ EResult FileHeader::write(FILE& file) const EResult FileHeader::read(FILE& file, const uint32_t* const max_version) { - if (!read_from_file(file, &magic, sizeof(magic))) + if (!read_from_file_le(file, magic)) return EResult::ReadError; if (magic != MAGICi32) return EResult::InvalidMagicNumber; - if (!read_from_file(file, &version, sizeof(version))) + if (!read_from_file_le(file, version)) return EResult::ReadError; if (max_version != nullptr && version > *max_version) return EResult::InvalidVersionNumber; - if (!read_from_file(file, &checksum_type, sizeof(checksum_type))) + if (!read_from_file_le(file, checksum_type)) return EResult::ReadError; if (checksum_type >= checksum_types_count()) return EResult::InvalidChecksumType; @@ -157,14 +172,14 @@ long BlockHeader::get_position() const EResult BlockHeader::write(FILE& file) { m_position = ftell(&file); - if (!write_to_file(file, &type, sizeof(type))) + if (!write_to_file_le(file, type)) return EResult::WriteError; - if (!write_to_file(file, &compression, sizeof(compression))) + if (!write_to_file_le(file, compression)) return EResult::WriteError; - if (!write_to_file(file, &uncompressed_size, sizeof(uncompressed_size))) + if (!write_to_file_le(file, uncompressed_size)) return EResult::WriteError; if (compression != (uint16_t)ECompressionType::None) { - if (!write_to_file(file, &compressed_size, sizeof(compressed_size))) + if (!write_to_file_le(file, compressed_size)) return EResult::WriteError; } return EResult::Success; @@ -173,20 +188,20 @@ EResult BlockHeader::write(FILE& file) EResult BlockHeader::read(FILE& file) { m_position = ftell(&file); - if (!read_from_file(file, &type, sizeof(type))) + if (!read_from_file_le(file, type)) return EResult::ReadError; if (type >= block_types_count()) return EResult::InvalidBlockType; - if (!read_from_file(file, &compression, sizeof(compression))) + if (!read_from_file_le(file, compression)) return EResult::ReadError; if (compression >= compression_types_count()) return EResult::InvalidCompressionType; - if (!read_from_file(file, &uncompressed_size, sizeof(uncompressed_size))) + if (!read_from_file_le(file, uncompressed_size)) return EResult::ReadError; if (compression != (uint16_t)ECompressionType::None) { - if (!read_from_file(file, &compressed_size, sizeof(compressed_size))) + if (!read_from_file_le(file, compressed_size)) return EResult::ReadError; } @@ -199,21 +214,21 @@ size_t BlockHeader::get_size() const { } EResult ThumbnailParams::write(FILE& file) const { - if (!write_to_file(file, &format, sizeof(format))) + if (!write_to_file_le(file, format)) return EResult::WriteError; - if (!write_to_file(file, &width, sizeof(width))) + if (!write_to_file_le(file, width)) return EResult::WriteError; - if (!write_to_file(file, &height, sizeof(height))) + if (!write_to_file_le(file, height)) return EResult::WriteError; return EResult::Success; } EResult ThumbnailParams::read(FILE& file){ - if (!read_from_file(file, &format, sizeof(format))) + if (!read_from_file_le(file, format)) return EResult::ReadError; - if (!read_from_file(file, &width, sizeof(width))) + if (!read_from_file_le(file, width)) return EResult::ReadError; - if (!read_from_file(file, &height, sizeof(height))) + if (!read_from_file_le(file, height)) return EResult::ReadError; return EResult::Success; } diff --git a/src/LibBGCode/core/core_impl.hpp b/src/LibBGCode/core/core_impl.hpp index 2c38849..a946853 100644 --- a/src/LibBGCode/core/core_impl.hpp +++ b/src/LibBGCode/core/core_impl.hpp @@ -120,7 +120,7 @@ class BGCODE_CORE_EXPORT Checksum // Append any aritmetic data to the checksum (shorthand for aritmetic types) template::value, T>::type> - void append(T& data) { append(reinterpret_cast(&data), sizeof(data)); } + void append(T& data); // Returns true if the given checksum is equal to this one bool matches(Checksum& other); @@ -168,6 +168,14 @@ void Checksum::append(const BufT *data, size_t size) } } +template +void Checksum::append(T& data) +{ + std::array temp; + store_integer_le(data, temp.begin(), temp.size()); + append(temp.data(), temp.size()); +} + static constexpr auto MAGICi32 = load_integer(std::begin(MAGIC), std::end(MAGIC)); constexpr auto checksum_types_count() noexcept { auto v = to_underlying(EChecksumType::CRC32); ++v; return v;} From a9d300d2293b36cb0085b655cc57960951b3a128 Mon Sep 17 00:00:00 2001 From: Gregor Riepl Date: Sat, 20 Dec 2025 23:25:06 +0100 Subject: [PATCH 2/2] Remove duplicated I/O code --- src/LibBGCode/binarize/binarize.cpp | 43 ++++------------------------- src/LibBGCode/core/core.cpp | 31 --------------------- src/LibBGCode/core/core_impl.hpp | 33 ++++++++++++++++++++++ 3 files changed, 39 insertions(+), 68 deletions(-) diff --git a/src/LibBGCode/binarize/binarize.cpp b/src/LibBGCode/binarize/binarize.cpp index 2da25e4..ab44774 100644 --- a/src/LibBGCode/binarize/binarize.cpp +++ b/src/LibBGCode/binarize/binarize.cpp @@ -18,37 +18,6 @@ using namespace core; namespace binarize { -static bool write_to_file(FILE& file, const std::byte* data, size_t data_size) -{ - const size_t wsize = fwrite(static_cast(data), 1, data_size, &file); - return !ferror(&file) && wsize == data_size; -} - -template -static bool write_to_file_le(FILE& file, const T &data) -{ - std::array temp; - store_integer_le(data, temp.begin(), temp.size()); - return write_to_file(file, temp.data(), temp.size()); -} - -static bool read_from_file(FILE& file, std::byte *data, size_t data_size) -{ - const size_t rsize = fread(static_cast(data), 1, data_size, &file); - return !ferror(&file) && rsize == data_size; -} - -template -static bool read_from_file_le(FILE& file, T &data) -{ - std::array temp; - if (!read_from_file(file, temp.data(), temp.size())) { - return false; - } - data = load_integer(temp.begin(), temp.end()); - return true; -} - void update_checksum(Checksum& checksum, const ThumbnailBlock &th) { checksum.append(th.params.format); @@ -438,7 +407,7 @@ core::EResult write(const BaseMetadataBlock &block, FILE& file, core::EBlockType if (!write_to_file_le(file, block.encoding_type)) return EResult::WriteError; if (!out_data.empty()) { - if (!write_to_file(file, reinterpret_cast(out_data.data()), out_data.size())) + if (!write_to_file(file, out_data.data(), out_data.size())) return EResult::WriteError; } @@ -467,7 +436,7 @@ EResult BaseMetadataBlock::read_data(FILE& file, const BlockHeader& block_header const size_t data_size = (compression_type == ECompressionType::None) ? block_header.uncompressed_size : block_header.compressed_size; if (data_size > 0) { data.resize(data_size); - if (!read_from_file(file, reinterpret_cast(data.data()), data_size)) + if (!read_from_file(file, data.data(), data_size)) return EResult::ReadError; } @@ -618,7 +587,7 @@ EResult ThumbnailBlock::write(FILE& file, EChecksumType checksum_type) return res; } - if (!write_to_file(file, reinterpret_cast(data.data()), data.size())) + if (!write_to_file(file, data.data(), data.size())) return EResult::WriteError; if (checksum_type != EChecksumType::None) { @@ -653,7 +622,7 @@ EResult ThumbnailBlock::read_data(FILE& file, const FileHeader& file_header, con return EResult::InvalidThumbnailDataSize; data.resize(block_header.uncompressed_size); - if (!read_from_file(file, reinterpret_cast(data.data()), block_header.uncompressed_size)) + if (!read_from_file(file, data.data(), block_header.uncompressed_size)) return EResult::ReadError; const EChecksumType checksum_type = (EChecksumType)file_header.checksum_type; @@ -701,7 +670,7 @@ EResult GCodeBlock::write(FILE& file, ECompressionType compression_type, EChecks if (!write_to_file_le(file, encoding_type)) return EResult::WriteError; if (!out_data.empty()) { - if (!write_to_file(file, reinterpret_cast(out_data.data()), out_data.size())) + if (!write_to_file(file, out_data.data(), out_data.size())) return EResult::WriteError; } @@ -739,7 +708,7 @@ EResult GCodeBlock::read_data(FILE& file, const FileHeader& file_header, const B const size_t data_size = (compression_type == ECompressionType::None) ? block_header.uncompressed_size : block_header.compressed_size; if (data_size > 0) { data.resize(data_size); - if (!read_from_file(file, reinterpret_cast(data.data()), data_size)) + if (!read_from_file(file, data.data(), data_size)) return EResult::ReadError; } diff --git a/src/LibBGCode/core/core.cpp b/src/LibBGCode/core/core.cpp index b16e881..053c3e5 100644 --- a/src/LibBGCode/core/core.cpp +++ b/src/LibBGCode/core/core.cpp @@ -3,37 +3,6 @@ namespace bgcode { namespace core { -static bool write_to_file(FILE& file, const std::byte* data, size_t data_size) -{ - const size_t wsize = fwrite(static_cast(data), 1, data_size, &file); - return !ferror(&file) && wsize == data_size; -} - -template -static bool write_to_file_le(FILE& file, const T &data) -{ - std::array temp; - store_integer_le(data, temp.begin(), temp.size()); - return write_to_file(file, temp.data(), temp.size()); -} - -static bool read_from_file(FILE& file, std::byte *data, size_t data_size) -{ - const size_t rsize = fread(static_cast(data), 1, data_size, &file); - return !ferror(&file) && rsize == data_size; -} - -template -static bool read_from_file_le(FILE& file, T &data) -{ - std::array temp; - if (!read_from_file(file, temp.data(), temp.size())) { - return false; - } - data = load_integer(temp.begin(), temp.end()); - return true; -} - EResult verify_block_checksum(FILE& file, const FileHeader& file_header, const BlockHeader& block_header, std::byte* buffer, size_t buffer_size) { diff --git a/src/LibBGCode/core/core_impl.hpp b/src/LibBGCode/core/core_impl.hpp index a946853..ac0a91d 100644 --- a/src/LibBGCode/core/core_impl.hpp +++ b/src/LibBGCode/core/core_impl.hpp @@ -182,6 +182,39 @@ constexpr auto checksum_types_count() noexcept { auto v = to_underlying(EChecksu constexpr auto block_types_count() noexcept { auto v = to_underlying(EBlockType::Thumbnail); ++v; return v; } constexpr auto compression_types_count() noexcept { auto v = to_underlying(ECompressionType::Heatshrink_12_4); ++v; return v; } +template +static bool write_to_file(FILE& file, const BufT* data, size_t data_size) +{ + const size_t wsize = fwrite(static_cast(data), 1, data_size, &file); + return !ferror(&file) && wsize == data_size; +} + +template +static bool write_to_file_le(FILE& file, const T &data) +{ + std::array temp; + store_integer_le(data, temp.begin(), temp.size()); + return write_to_file(file, temp.data(), temp.size()); +} + +template +static bool read_from_file(FILE& file, BufT *data, size_t data_size) +{ + const size_t rsize = fread(static_cast(data), 1, data_size, &file); + return !ferror(&file) && rsize == data_size; +} + +template +static bool read_from_file_le(FILE& file, T &data) +{ + std::array temp; + if (!read_from_file(file, temp.data(), temp.size())) { + return false; + } + data = load_integer(temp.begin(), temp.end()); + return true; +} + } // namespace core } // namespace bgcode