diff --git a/components/core/src/clp/streaming_compression/lzma/Compressor.cpp b/components/core/src/clp/streaming_compression/lzma/Compressor.cpp index f10ec915b..7bb13e5d3 100644 --- a/components/core/src/clp/streaming_compression/lzma/Compressor.cpp +++ b/components/core/src/clp/streaming_compression/lzma/Compressor.cpp @@ -1,34 +1,22 @@ #include "Compressor.hpp" -// spdlog #include +// Compression libraries +#include +#include + // Project headers #include "../../Defs.h" -// File-scope constants -static constexpr size_t cCompressedStreamBlockBufferSize = 4096; // 4KiB - -namespace streaming_compression::lzma { +namespace clp::streaming_compression::lzma { Compressor::LzmaOption Compressor::m_option; -Compressor::Compressor() - : ::streaming_compression::Compressor(CompressorType::LZMA), - m_compression_stream_contains_data(false), - m_compressed_stream_file_writer(nullptr), - m_compression_stream(nullptr) { - m_compressed_stream_block_buffer = std::make_unique(cCompressedStreamBlockBufferSize); - m_compression_stream = new lzma_stream; - memset(m_compression_stream, 0, sizeof(lzma_stream)); -} - -Compressor::~Compressor() { - if (nullptr != m_compression_stream) { - delete m_compression_stream; - } +Compressor::Compressor() { + memset(m_compression_stream.get(), 0, sizeof(LzmaStream)); } -void Compressor::init_lzma_encoder(lzma_stream* strm) { +void Compressor::init_lzma_encoder(LzmaStream* strm) { lzma_options_lzma options; if (lzma_lzma_preset(&options, m_option.get_compression_level())) { SPDLOG_ERROR("Failed to initialize LZMA options."); @@ -44,10 +32,10 @@ void Compressor::init_lzma_encoder(lzma_stream* strm) { // to CRC64, which is the default in the xz command line tool. If // the .xz file needs to be decompressed with XZ Embedded, use // LZMA_CHECK_CRC32 instead. - lzma_ret ret = lzma_stream_encoder(strm, filters, LZMA_CHECK_CRC64); + auto const ret = lzma_stream_encoder(strm, filters, LZMA_CHECK_CRC64); // Return successfully if the initialization went fine. - if (ret == LZMA_OK) { + if (LZMA_OK == ret) { return; } @@ -96,12 +84,12 @@ void Compressor::open(FileWriter& file_writer, int compression_level) { m_option.set_compression_level(compression_level); } - init_lzma_encoder(m_compression_stream); + init_lzma_encoder(m_compression_stream.get()); // Setup compressed stream parameters m_compression_stream->next_in = nullptr; m_compression_stream->avail_in = 0; - m_compression_stream->next_out = m_compressed_stream_block_buffer.get(); - m_compression_stream->avail_out = cCompressedStreamBlockBufferSize; + m_compression_stream->next_out = m_compressed_stream_block_buffer.data(); + m_compression_stream->avail_out = m_compressed_stream_block_buffer.size(); m_compressed_stream_file_writer = &file_writer; @@ -136,7 +124,7 @@ void Compressor::write(char const* data, size_t data_length) { // Compress all data bool hit_input_eof = false; while (!hit_input_eof) { - lzma_ret return_value = lzma_code(m_compression_stream, action); + auto const return_value = lzma_code(m_compression_stream.get(), action); switch (return_value) { case LZMA_OK: case LZMA_BUF_ERROR: @@ -157,10 +145,10 @@ void Compressor::write(char const* data, size_t data_length) { // Write output buffer to file if it's full if (0 == m_compression_stream->avail_out) { m_compressed_stream_file_writer->write( - reinterpret_cast(m_compressed_stream_block_buffer.get()), + reinterpret_cast(m_compressed_stream_block_buffer.data()), cCompressedStreamBlockBufferSize ); - m_compression_stream->next_out = m_compressed_stream_block_buffer.get(); + m_compression_stream->next_out = m_compressed_stream_block_buffer.data(); m_compression_stream->avail_out = cCompressedStreamBlockBufferSize; } } @@ -168,10 +156,10 @@ void Compressor::write(char const* data, size_t data_length) { // Write any compressed data if (m_compression_stream->avail_out < cCompressedStreamBlockBufferSize) { m_compressed_stream_file_writer->write( - reinterpret_cast(m_compressed_stream_block_buffer.get()), + reinterpret_cast(m_compressed_stream_block_buffer.data()), cCompressedStreamBlockBufferSize - m_compression_stream->avail_out ); - m_compression_stream->next_out = m_compressed_stream_block_buffer.get(); + m_compression_stream->next_out = m_compressed_stream_block_buffer.data(); m_compression_stream->avail_out = cCompressedStreamBlockBufferSize; } @@ -200,7 +188,7 @@ void Compressor::flush() { bool flush_complete = false; while (true) { - lzma_ret return_value = lzma_code(m_compression_stream, LZMA_SYNC_FLUSH); + auto const return_value = lzma_code(m_compression_stream.get(), LZMA_SYNC_FLUSH); switch (return_value) { case LZMA_STREAM_END: flush_complete = true; @@ -219,10 +207,10 @@ void Compressor::flush() { // Write output buffer to file if it's full if (0 == m_compression_stream->avail_out) { m_compressed_stream_file_writer->write( - reinterpret_cast(m_compressed_stream_block_buffer.get()), + reinterpret_cast(m_compressed_stream_block_buffer.data()), cCompressedStreamBlockBufferSize ); - m_compression_stream->next_out = m_compressed_stream_block_buffer.get(); + m_compression_stream->next_out = m_compressed_stream_block_buffer.data(); m_compression_stream->avail_out = cCompressedStreamBlockBufferSize; } } @@ -230,10 +218,10 @@ void Compressor::flush() { // Write any compressed data if (m_compression_stream->avail_out < cCompressedStreamBlockBufferSize) { m_compressed_stream_file_writer->write( - reinterpret_cast(m_compressed_stream_block_buffer.get()), + reinterpret_cast(m_compressed_stream_block_buffer.data()), cCompressedStreamBlockBufferSize - m_compression_stream->avail_out ); - m_compression_stream->next_out = m_compressed_stream_block_buffer.get(); + m_compression_stream->next_out = m_compressed_stream_block_buffer.data(); m_compression_stream->avail_out = cCompressedStreamBlockBufferSize; } @@ -256,7 +244,7 @@ void Compressor::flush_and_close_compression_stream() { bool flush_complete = false; while (true) { - lzma_ret return_value = lzma_code(m_compression_stream, LZMA_FINISH); + lzma_ret return_value = lzma_code(m_compression_stream.get(), LZMA_FINISH); switch (return_value) { case LZMA_OK: case LZMA_BUF_ERROR: @@ -276,10 +264,10 @@ void Compressor::flush_and_close_compression_stream() { // Write output buffer to file if it's full if (0 == m_compression_stream->avail_out) { m_compressed_stream_file_writer->write( - reinterpret_cast(m_compressed_stream_block_buffer.get()), + reinterpret_cast(m_compressed_stream_block_buffer.data()), cCompressedStreamBlockBufferSize ); - m_compression_stream->next_out = m_compressed_stream_block_buffer.get(); + m_compression_stream->next_out = m_compressed_stream_block_buffer.data(); m_compression_stream->avail_out = cCompressedStreamBlockBufferSize; } } @@ -287,17 +275,17 @@ void Compressor::flush_and_close_compression_stream() { // Write any compressed data if (m_compression_stream->avail_out < cCompressedStreamBlockBufferSize) { m_compressed_stream_file_writer->write( - reinterpret_cast(m_compressed_stream_block_buffer.get()), + reinterpret_cast(m_compressed_stream_block_buffer.data()), cCompressedStreamBlockBufferSize - m_compression_stream->avail_out ); - m_compression_stream->next_out = m_compressed_stream_block_buffer.get(); + m_compression_stream->next_out = m_compressed_stream_block_buffer.data(); m_compression_stream->avail_out = cCompressedStreamBlockBufferSize; } m_compression_stream_contains_data = false; - lzma_end(m_compression_stream); + lzma_end(m_compression_stream.get()); m_compression_stream->avail_out = 0; m_compression_stream->next_out = nullptr; } -} // namespace streaming_compression::lzma +} // namespace clp::streaming_compression::lzma diff --git a/components/core/src/clp/streaming_compression/lzma/Compressor.hpp b/components/core/src/clp/streaming_compression/lzma/Compressor.hpp index d31c7687e..53f82b139 100644 --- a/components/core/src/clp/streaming_compression/lzma/Compressor.hpp +++ b/components/core/src/clp/streaming_compression/lzma/Compressor.hpp @@ -1,22 +1,22 @@ -#ifndef STREAMING_COMPRESSION_LZMA_COMPRESSOR_HPP -#define STREAMING_COMPRESSION_LZMA_COMPRESSOR_HPP +#ifndef CLP_STREAMING_COMPRESSION_LZMA_COMPRESSOR_HPP +#define CLP_STREAMING_COMPRESSION_LZMA_COMPRESSOR_HPP -// C++ standard libraries +#include +#include #include -#include -// ZLIB library #include -#include +#include -// Project headers +#include "../../Array.hpp" +#include "../../ErrorCode.hpp" #include "../../FileWriter.hpp" #include "../../TraceableException.hpp" #include "../Compressor.hpp" #include "Constants.hpp" -namespace streaming_compression::lzma { -class Compressor : public ::streaming_compression::Compressor { +namespace clp::streaming_compression::lzma { +class Compressor : public ::clp::streaming_compression::Compressor { public: // Types class OperationFailed : public TraceableException { @@ -26,8 +26,8 @@ class Compressor : public ::streaming_compression::Compressor { : TraceableException(error_code, filename, line_number) {} // Methods - char const* what() const noexcept override { - return "streaming_compression::gzip::Compressor operation failed"; + [[nodiscard]] auto what() const noexcept -> char const* override { + return "streaming_compression::lzma::Compressor operation failed"; } }; @@ -38,10 +38,10 @@ class Compressor : public ::streaming_compression::Compressor { m_dict_size{cDefaultDictionarySize} {} auto set_compression_level(int compression_level) -> void { - if (0 > compression_level) { - m_compression_level = 0; - } else if (9 < compression_level) { - m_compression_level = 9; + if (compression_level < cMinCompressionLevel) { + m_compression_level = cMinCompressionLevel; + } else if (compression_level > cMaxCompressionLevel) { + m_compression_level = cMaxCompressionLevel; } else { m_compression_level = compression_level; } @@ -62,11 +62,15 @@ class Compressor : public ::streaming_compression::Compressor { Compressor(); // Destructor - ~Compressor(); + ~Compressor() override = default; - // Explicitly disable copy and move constructor/assignment + // Delete copy constructor and assignment operator Compressor(Compressor const&) = delete; - Compressor& operator=(Compressor const&) = delete; + auto operator=(Compressor const&) -> Compressor& = delete; + + // Default move constructor and assignment operator + Compressor(Compressor&&) noexcept = default; + auto operator=(Compressor&&) noexcept -> Compressor& = default; // Methods implementing the WriterInterface /** @@ -74,11 +78,12 @@ class Compressor : public ::streaming_compression::Compressor { * @param data * @param data_length */ - void write(char const* data, size_t data_length) override; + auto write(char const* data, size_t data_length) -> void override; + /** * Writes any internally buffered data to file and ends the current frame */ - void flush() override; + auto flush() -> void override; /** * Tries to get the current position of the write head @@ -86,20 +91,28 @@ class Compressor : public ::streaming_compression::Compressor { * @return ErrorCode_NotInit if the compressor is not open * @return ErrorCode_Success on success */ - ErrorCode try_get_pos(size_t& pos) const override; + auto try_get_pos(size_t& pos) const -> ErrorCode override; + + /** + * Closes the compressor + */ + auto close() -> void override; // Methods implementing the Compressor interface /** - * Initialize streaming compressor + * Initializes the compression stream with the default compression level * @param file_writer - * @param compression_level */ - void open(FileWriter& file_writer, int compression_level) override; + auto open(FileWriter& file_writer) -> void override { + this->open(file_writer, cDefaultCompressionLevel); + } /** - * Closes the compressor + * Initializes the compression stream with the given compression level + * @param file_writer + * @param compression_level */ - void close() override; + auto open(FileWriter& file_writer, int compression_level) -> void; // Methods static auto set_compression_level(int compression_level) -> void { @@ -109,25 +122,28 @@ class Compressor : public ::streaming_compression::Compressor { static auto set_dict_size(uint32_t dict_size) -> void { m_option.set_dict_size(dict_size); } private: + using LzmaStream = lzma_stream; + /** * Flushes the stream and closes it */ void flush_and_close_compression_stream(); - static void init_lzma_encoder(lzma_stream* strm); + static void init_lzma_encoder(LzmaStream* strm); static LzmaOption m_option; + static constexpr size_t cCompressedStreamBlockBufferSize{4096}; // 4KiB // Variables - FileWriter* m_compressed_stream_file_writer; + FileWriter* m_compressed_stream_file_writer{nullptr}; // Compressed stream variables - lzma_stream* m_compression_stream; - bool m_compression_stream_contains_data; + std::unique_ptr m_compression_stream{std::make_unique()}; + bool m_compression_stream_contains_data{false}; - std::unique_ptr m_compressed_stream_block_buffer; + Array m_compressed_stream_block_buffer{cCompressedStreamBlockBufferSize}; - size_t m_uncompressed_stream_pos; + size_t m_uncompressed_stream_pos{0}; }; -} // namespace streaming_compression::lzma +} // namespace clp::streaming_compression::lzma -#endif // STREAMING_COMPRESSION_LZMA_COMPRESSOR_HPP +#endif // CLP_STREAMING_COMPRESSION_LZMA_COMPRESSOR_HPP diff --git a/components/core/src/clp/streaming_compression/lzma/Constants.hpp b/components/core/src/clp/streaming_compression/lzma/Constants.hpp index 959c09f47..4e261187a 100644 --- a/components/core/src/clp/streaming_compression/lzma/Constants.hpp +++ b/components/core/src/clp/streaming_compression/lzma/Constants.hpp @@ -1,15 +1,15 @@ #ifndef STREAMING_COMPRESSION_LZMA_CONSTANTS_HPP #define STREAMING_COMPRESSION_LZMA_CONSTANTS_HPP -#include - -// C++ libraries -#include #include -namespace streaming_compression::lzma { +#include + +namespace clp::streaming_compression::lzma { constexpr int cDefaultCompressionLevel{3}; +constexpr int cMinCompressionLevel{0}; +constexpr int cMaxCompressionLevel{9}; constexpr uint32_t cDefaultDictionarySize{LZMA_DICT_SIZE_DEFAULT}; -} // namespace streaming_compression::lzma +} // namespace clp::streaming_compression::lzma #endif // STREAMING_COMPRESSION_LZMA_CONSTANTS_HPP diff --git a/components/core/src/clp/streaming_compression/lzma/Decompressor.cpp b/components/core/src/clp/streaming_compression/lzma/Decompressor.cpp index a2ed4d466..b6a10b418 100644 --- a/components/core/src/clp/streaming_compression/lzma/Decompressor.cpp +++ b/components/core/src/clp/streaming_compression/lzma/Decompressor.cpp @@ -12,9 +12,9 @@ // Project headers #include "../../Defs.h" -namespace streaming_compression::lzma { +namespace clp::streaming_compression::lzma { Decompressor::Decompressor() - : ::streaming_compression::Decompressor(CompressorType::LZMA), + : ::clp::streaming_compression::Decompressor(CompressorType::LZMA), m_input_type(InputType::NotInitialized), m_decompression_stream(nullptr), m_file_reader(nullptr), @@ -359,4 +359,4 @@ void Decompressor::reset_stream() { m_decompressed_stream_pos = 0; init_decoder(m_decompression_stream); } -} // namespace streaming_compression::lzma +} // namespace clp::streaming_compression::lzma diff --git a/components/core/src/clp/streaming_compression/lzma/Decompressor.hpp b/components/core/src/clp/streaming_compression/lzma/Decompressor.hpp index 996663e44..5e90f5942 100644 --- a/components/core/src/clp/streaming_compression/lzma/Decompressor.hpp +++ b/components/core/src/clp/streaming_compression/lzma/Decompressor.hpp @@ -1,13 +1,14 @@ -#ifndef STREAMING_COMPRESSION_LZMA_DECOMPRESSOR_HPP -#define STREAMING_COMPRESSION_LZMA_DECOMPRESSOR_HPP +#ifndef CLP_STREAMING_COMPRESSION_LZMA_DECOMPRESSOR_HPP +#define CLP_STREAMING_COMPRESSION_LZMA_DECOMPRESSOR_HPP // C++ standard libraries #include #include // ZLIB library -#include #include + +#include // Boost libraries #include @@ -16,8 +17,8 @@ #include "../../TraceableException.hpp" #include "../Decompressor.hpp" -namespace streaming_compression::lzma { -class Decompressor : public ::streaming_compression::Decompressor { +namespace clp::streaming_compression::lzma { +class Decompressor : public ::clp::streaming_compression::Decompressor { public: // Types class OperationFailed : public TraceableException { @@ -158,5 +159,5 @@ class Decompressor : public ::streaming_compression::Decompressor { char const* m_compressed_stream_block; size_t m_compressed_stream_block_size; }; -} // namespace streaming_compression::lzma -#endif // STREAMING_COMPRESSION_LZMA_DECOMPRESSOR_HPP +} // namespace clp::streaming_compression::lzma +#endif // CLP_STREAMING_COMPRESSION_LZMA_DECOMPRESSOR_HPP diff --git a/components/core/tests/test-StreamingCompression.cpp b/components/core/tests/test-StreamingCompression.cpp index d632510fc..d58d4c1ce 100644 --- a/components/core/tests/test-StreamingCompression.cpp +++ b/components/core/tests/test-StreamingCompression.cpp @@ -16,6 +16,7 @@ #include "../src/clp/streaming_compression/Compressor.hpp" #include "../src/clp/streaming_compression/Decompressor.hpp" #include "../src/clp/streaming_compression/lzma/Compressor.hpp" +#include "../src/clp/streaming_compression/lzma/Decompressor.hpp" #include "../src/clp/streaming_compression/passthrough/Compressor.hpp" #include "../src/clp/streaming_compression/passthrough/Decompressor.hpp" #include "../src/clp/streaming_compression/zstd/Compressor.hpp" @@ -56,6 +57,11 @@ TEST_CASE("StreamingCompression", "[StreamingCompression]") { decompressor = std::make_unique(); } + SECTION("LZMA compression") { + compressor = std::make_unique(); + decompressor = std::make_unique(); + } + // Initialize buffers Array uncompressed_buffer{cBufferSize}; for (size_t i{0}; i < cBufferSize; ++i) {