/* * Lzma Compressor * (C) 2001 Peter J Jones * 2001-2007,2014 Jack Lloyd * 2006 Matt Johnston * 2012 Vojtech Kral * * Botan is released under the Simplified BSD License (see license.txt) */ #include #include #include #include namespace Botan { namespace { class LZMA_Stream : public Zlib_Style_Stream { public: LZMA_Stream() { auto a = new ::lzma_allocator; a->opaque = alloc(); a->alloc = Compression_Alloc_Info::malloc; a->free = Compression_Alloc_Info::free; streamp()->allocator = a; } ~LZMA_Stream() { ::lzma_end(streamp()); delete streamp()->allocator; } bool run(uint32_t flags) override { lzma_ret rc = ::lzma_code(streamp(), static_cast(flags)); if(rc == LZMA_MEM_ERROR) throw Exception("lzma memory allocation failed"); else if (rc != LZMA_OK && rc != LZMA_STREAM_END) throw Exception("Lzma error"); return (rc == LZMA_STREAM_END); } uint32_t run_flag() const override { return LZMA_RUN; } uint32_t flush_flag() const override { return LZMA_FULL_FLUSH; } uint32_t finish_flag() const override { return LZMA_FINISH; } }; class LZMA_Compression_Stream : public LZMA_Stream { public: explicit LZMA_Compression_Stream(size_t level) { if(level == 0) level = 6; // default else if(level > 9) level = 9; // clamp to maximum allowed value lzma_ret rc = ::lzma_easy_encoder(streamp(), level, LZMA_CHECK_CRC64); if(rc == LZMA_MEM_ERROR) throw Exception("lzma memory allocation failed"); else if(rc != LZMA_OK) throw Exception("lzma compress initialization failed"); } }; class LZMA_Decompression_Stream : public LZMA_Stream { public: LZMA_Decompression_Stream() { lzma_ret rc = ::lzma_stream_decoder(streamp(), UINT64_MAX, LZMA_TELL_UNSUPPORTED_CHECK); if(rc == LZMA_MEM_ERROR) throw Exception("lzma memory allocation failed"); else if(rc != LZMA_OK) throw Exception("Bad setting in lzma_stream_decoder"); } }; } Compression_Stream* LZMA_Compression::make_stream(size_t level) const { return new LZMA_Compression_Stream(level); } Compression_Stream* LZMA_Decompression::make_stream() const { return new LZMA_Decompression_Stream; } }