Tags: patch
Sorry, I think I must have run the close command on the wrong bug
number. The upstream bug report is still open, and libbgcode is still
failing to build on big-endian architectures, so I'm reopening this bug.
I have prepared a basic PR for libbgcode that adds big endian support:
https://github.com/prusa3d/libbgcode/pull/61
The attached version of the patch applies directly to the Debian sources.
It passes all unit tests on amd64 and sparc64.
--- a/src/LibBGCode/core/core.cpp
+++ b/src/LibBGCode/core/core.cpp
@@ -3,22 +3,37 @@
namespace bgcode { namespace core {
-template<class T>
-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<const void*>(data), 1, data_size, &file);
return !ferror(&file) && wsize == data_size;
}
template<class T>
-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<T>, "Type of output buffer cannot be const!");
+ std::array<std::byte, sizeof(T)> 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<void *>(data), 1, data_size, &file);
return !ferror(&file) && rsize == data_size;
}
+template<class T>
+static bool read_from_file_le(FILE& file, T &data)
+{
+ std::array<std::byte, sizeof(T)> temp;
+ if (!read_from_file(file, temp.data(), temp.size())) {
+ return false;
+ }
+ data = load_integer<T>(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 @@
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::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 @@
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::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 @@
}
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;
}
--- a/src/LibBGCode/binarize/binarize.cpp
+++ b/src/LibBGCode/binarize/binarize.cpp
@@ -18,22 +18,37 @@
namespace binarize {
-template<class T>
-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<const void*>(data), 1, data_size, &file);
return !ferror(&file) && wsize == data_size;
}
template<class T>
-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<T>, "Type of output buffer cannot be const!");
+ std::array<std::byte, sizeof(T)> 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<void *>(data), 1, data_size, &file);
return !ferror(&file) && rsize == data_size;
}
+template<class T>
+static bool read_from_file_le(FILE& file, T &data)
+{
+ std::array<std::byte, sizeof(T)> temp;
+ if (!read_from_file(file, temp.data(), temp.size())) {
+ return false;
+ }
+ data = load_integer<T>(temp.begin(), temp.end());
+ return true;
+}
+
void update_checksum(Checksum& checksum, const ThumbnailBlock &th)
{
checksum.append(th.params.format);
@@ -420,10 +435,10 @@
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<const std::byte*>(out_data.data()), out_data.size()))
return EResult::WriteError;
}
@@ -443,7 +458,7 @@
{
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 @@
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<std::byte*>(data.data()), data_size))
return EResult::ReadError;
}
@@ -603,7 +618,7 @@
return res;
}
- if (!write_to_file(file, data.data(), data.size()))
+ if (!write_to_file(file, reinterpret_cast<const std::byte*>(data.data()), data.size()))
return EResult::WriteError;
if (checksum_type != EChecksumType::None) {
@@ -638,7 +653,7 @@
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<std::byte*>(data.data()), block_header.uncompressed_size))
return EResult::ReadError;
const EChecksumType checksum_type = (EChecksumType)file_header.checksum_type;
@@ -683,10 +698,10 @@
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<const std::byte*>(out_data.data()), out_data.size()))
return EResult::WriteError;
}
@@ -696,8 +711,10 @@
// update checksum with block header
update_checksum(cs, block_header);
// update checksum with block payload
+ std::array<std::byte, sizeof(encoding_type)> swapped_encoding;
+ store_integer_le(encoding_type, swapped_encoding.data());
std::vector<uint8_t> data_to_encode =
- encode(reinterpret_cast<const std::byte*>(&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<unsigned char *>(out_data.data()), out_data.size());
@@ -713,7 +730,7 @@
{
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 @@
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<std::byte*>(data.data()), data_size))
return EResult::ReadError;
}
--- a/src/LibBGCode/core/core_impl.hpp
+++ b/src/LibBGCode/core/core_impl.hpp
@@ -120,7 +120,7 @@
// Append any aritmetic data to the checksum (shorthand for aritmetic types)
template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
- void append(T& data) { append(reinterpret_cast<const std::byte*>(&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 @@
}
}
+template<typename T, typename>
+void Checksum::append(T& data)
+{
+ std::array<std::byte, sizeof(T)> temp;
+ store_integer_le(data, temp.begin(), temp.size());
+ append(temp.data(), temp.size());
+}
+
static constexpr auto MAGICi32 = load_integer<uint32_t>(std::begin(MAGIC), std::end(MAGIC));
constexpr auto checksum_types_count() noexcept { auto v = to_underlying(EChecksumType::CRC32); ++v; return v;}