1 /*
2 * Lzma Compressor
3 * (C) 2001 Peter J Jones
4 *     2001-2007,2014 Jack Lloyd
5 *     2006 Matt Johnston
6 *     2012 Vojtech Kral
7 *
8 * Botan is released under the Simplified BSD License (see license.txt)
9 */
10 
11 #include <botan/lzma.h>
12 #include <botan/internal/compress_utils.h>
13 #include <botan/exceptn.h>
14 #include <lzma.h>
15 
16 namespace Botan {
17 
18 namespace {
19 
20 class LZMA_Stream : public Zlib_Style_Stream<lzma_stream, uint8_t>
21    {
22    public:
LZMA_Stream()23       LZMA_Stream()
24          {
25          m_allocator.opaque = alloc();
26          m_allocator.alloc = Compression_Alloc_Info::malloc<size_t>;
27          m_allocator.free = Compression_Alloc_Info::free;
28          streamp()->allocator = &m_allocator;
29          }
30 
~LZMA_Stream()31       ~LZMA_Stream()
32          {
33          ::lzma_end(streamp());
34          }
35 
run(uint32_t flags)36       bool run(uint32_t flags) override
37          {
38          lzma_ret rc = ::lzma_code(streamp(), static_cast<lzma_action>(flags));
39 
40          if(rc != LZMA_OK && rc != LZMA_STREAM_END)
41             throw Compression_Error("lzma_code", ErrorType::LzmaError, rc);
42 
43          return (rc == LZMA_STREAM_END);
44          }
45 
run_flag() const46       uint32_t run_flag() const override { return LZMA_RUN; }
flush_flag() const47       uint32_t flush_flag() const override { return LZMA_FULL_FLUSH; }
finish_flag() const48       uint32_t finish_flag() const override { return LZMA_FINISH; }
49    private:
50       ::lzma_allocator m_allocator;
51    };
52 
53 class LZMA_Compression_Stream final : public LZMA_Stream
54    {
55    public:
LZMA_Compression_Stream(size_t level)56       explicit LZMA_Compression_Stream(size_t level)
57          {
58          if(level == 0)
59             level = 6; // default
60          else if(level > 9)
61             level = 9; // clamp to maximum allowed value
62 
63          lzma_ret rc = ::lzma_easy_encoder(streamp(), level, LZMA_CHECK_CRC64);
64 
65          if(rc != LZMA_OK)
66             throw Compression_Error("lzam_easy_encoder", ErrorType::LzmaError, rc);
67          }
68    };
69 
70 class LZMA_Decompression_Stream final : public LZMA_Stream
71    {
72    public:
LZMA_Decompression_Stream()73       LZMA_Decompression_Stream()
74          {
75          lzma_ret rc = ::lzma_stream_decoder(streamp(), UINT64_MAX,
76                                              LZMA_TELL_UNSUPPORTED_CHECK);
77 
78          if(rc != LZMA_OK)
79             throw Compression_Error("lzma_stream_decoder", ErrorType::LzmaError, rc);
80          }
81    };
82 
83 }
84 
make_stream(size_t level) const85 Compression_Stream* LZMA_Compression::make_stream(size_t level) const
86    {
87    return new LZMA_Compression_Stream(level);
88    }
89 
make_stream() const90 Compression_Stream* LZMA_Decompression::make_stream() const
91    {
92    return new LZMA_Decompression_Stream;
93    }
94 
95 }
96