1 /** 2 * Lzma Compressor 3 * 4 * Copyright: 5 * (C) 2001 Peter J Jones 6 * 2001-2007 Jack Lloyd 7 * 2012 Vojtech Kral 8 * (C) 2014-2015 Etienne Cimon 9 * 10 * License: 11 * Botan is released under the Simplified BSD License (see LICENSE.md) 12 */ 13 module botan.compression.lzma; 14 15 import botan.constants; 16 static if (BOTAN_HAS_LZMA): 17 18 import botan.filters.filter; 19 20 import botan.utils.exceptn; 21 import std.exception; 22 import botan.compression.lzma_hd; 23 import botan.compression.compress; 24 import botan.algo_base.transform; 25 import botan.utils.types; 26 import core.exception; 27 28 /** 29 * LZMA Compression 30 */ 31 class LZMACompression : StreamCompression, Transformation 32 { 33 public: 34 /** 35 * @param level how much effort to use on compressing (0 to 9); 36 * higher levels are slower but tend to give better 37 * compression 38 */ 39 this(size_t level = 6) { 40 m_level = level; 41 } 42 43 override string name() const { return "LZMACompression"; } 44 45 protected: 46 override CompressionStream makeStream() const 47 { 48 return new LZMACompressionStream(m_level); 49 } 50 51 52 const size_t m_level; 53 // interface fall-through 54 override void flush(ref SecureVector!ubyte buf, size_t offset) { super.flush(buf, offset); } 55 override string provider() const { return "core"; } 56 override size_t updateGranularity() const { return 1; } 57 override size_t minimumFinalSize() const { return 0; } 58 override size_t defaultNonceLength() const { return 0; } 59 override bool validNonceLength(size_t nonce_len) const { return nonce_len == 0; } 60 override SecureVector!ubyte startRaw(const(ubyte)* data, size_t data_len) { return super.startRaw(data, data_len); } 61 override void update(ref SecureVector!ubyte buf, size_t offset) { super.update(buf, offset); } 62 override void finish(ref SecureVector!ubyte buf, size_t offset) { super.finish(buf, offset); } 63 override size_t outputLength(size_t input_length) const { return super.outputLength(input_length); } 64 override void clear() { return super.clear(); } 65 } 66 67 /** 68 * LZMA Deccompression 69 */ 70 class LZMADecompression : StreamDecompression, Transformation 71 { 72 public: 73 override string name() const { return "LZMADecompression"; } 74 protected: 75 override CompressionStream makeStream() const 76 { 77 return new LZMADecompressionStream; 78 } 79 80 // interface fall-through 81 override void flush(ref SecureVector!ubyte buf, size_t offset) { super.flush(buf, offset); } 82 override string provider() const { return "core"; } 83 override size_t updateGranularity() const { return 1; } 84 override size_t minimumFinalSize() const { return 0; } 85 override size_t defaultNonceLength() const { return 0; } 86 override bool validNonceLength(size_t nonce_len) const { return nonce_len == 0; } 87 override SecureVector!ubyte startRaw(const(ubyte)* data, size_t data_len) { return super.startRaw(data, data_len); } 88 override void update(ref SecureVector!ubyte buf, size_t offset) { super.update(buf, offset); } 89 override void finish(ref SecureVector!ubyte buf, size_t offset) { super.finish(buf, offset); } 90 override size_t outputLength(size_t input_length) const { return super.outputLength(input_length); } 91 override void clear() { return super.clear(); } 92 } 93 94 class LZMAStream : ZlibStyleStream!(lzma_stream, ubyte), CompressionStream 95 { 96 public: 97 this() 98 { 99 auto a = new .lzma_allocator; 100 a.opaque = cast(void*)alloc(); 101 a.alloc = &CompressionAllocInfo.malloc!size_t; 102 a.free = &CompressionAllocInfo.free; 103 streamp().allocator = a; 104 } 105 106 ~this() 107 { 108 .lzma_end(streamp()); 109 delete streamp().allocator; 110 } 111 112 override bool run(uint flags) 113 { 114 lzma_ret rc = .lzma_code(streamp(), cast(lzma_action)(flags)); 115 116 if (rc == LZMA_MEM_ERROR) 117 throw new InvalidMemoryOperationError(); 118 else if (rc != LZMA_OK && rc != LZMA_STREAM_END) 119 throw new Exception("Lzma error"); 120 121 return (rc == LZMA_STREAM_END); 122 } 123 124 override uint runFlag() const { return LZMA_RUN; } 125 override uint flushFlag() const { return LZMA_FULL_FLUSH; } 126 override uint finishFlag() const { return LZMA_FINISH; } 127 128 override void nextIn(ubyte* b, size_t len) { super.nextIn(b, len); } 129 override void nextOut(ubyte* b, size_t len) { super.nextOut(b, len); } 130 override size_t availIn() const { return super.availIn(); } 131 override size_t availOut() const { return super.availOut; } 132 } 133 134 class LZMACompressionStream : LZMAStream 135 { 136 public: 137 this(size_t level) 138 { 139 lzma_ret rc = .lzma_easy_encoder(streamp(), cast(uint) level, LZMA_CHECK_CRC64); 140 141 if (rc == LZMA_MEM_ERROR) 142 throw new InvalidMemoryOperationError(); 143 else if (rc != LZMA_OK) 144 throw new Exception("lzma compress initialization failed: " ~ rc.to!string); 145 } 146 } 147 148 class LZMADecompressionStream : LZMAStream 149 { 150 public: 151 this() 152 { 153 lzma_ret rc = .lzma_stream_decoder(streamp(), ulong.max, 154 LZMA_TELL_UNSUPPORTED_CHECK); 155 156 if (rc == LZMA_MEM_ERROR) 157 throw new InvalidMemoryOperationError(); 158 else if (rc != LZMA_OK) 159 throw new Exception("Bad setting in lzma_stream_decoder"); 160 } 161 }