1 /**
2 * Bzip Compressor
3 * 
4 * Copyright:
5 * (C) 2001 Peter J Jones
6 *     2001-2007 Jack Lloyd
7 * (C) 2014-2015 Etienne Cimon
8 *
9 * License:
10 * Botan is released under the Simplified BSD License (see LICENSE.md)
11 */
12 module botan.compression.bzip2;
13 
14 import botan.constants;
15 static if (BOTAN_HAS_BZIP2):
16 
17 import botan.utils.exceptn;
18 import botan.compression.bzip2_hd;
19 import botan.compression.compress;
20 import std.exception;
21 import botan.algo_base.transform;
22 import botan.utils.types;
23 import core.exception;
24 
25 /**
26 * Bzip2 Compression
27 */
28 class Bzip2Compression : StreamCompression, Transformation
29 {
30 public:
31     /**
32       * @param block_size in 1024 KiB increments, in range from 1 to 9.
33       *
34       * Lowering this does not noticably modify the compression or
35       * decompression speed, though less memory is required for both
36       * compression and decompression.
37       */
38     this(size_t block_size = 9) 
39     {
40         m_block_size = block_size; 
41 
42     }
43     
44     override string name() const { return "Bzip2Compression"; }
45     
46 protected:
47     override CompressionStream makeStream() const
48     {
49         return new Bzip2CompressionStream(m_block_size);
50     }
51     
52     const size_t m_block_size;
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 * Bzip2 Deccompression
69 */
70 class Bzip2Decompression : StreamDecompression, Transformation
71 {
72 public:
73     override string name() const { return "Bzip2Decompression"; }
74 protected:
75     override CompressionStream makeStream() const
76     {
77         return new Bzip2DecompressionStream;
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 
95 class Bzip2Stream : ZlibStyleStream!(bz_stream, ubyte), CompressionStream
96 {
97 public:
98     this()
99     {
100         streamp().opaque = cast(void*)alloc();
101         streamp().bzalloc = &CompressionAllocInfo.malloc!int;
102         streamp().bzfree = &CompressionAllocInfo.free;
103     }
104     
105     override uint runFlag() const { return BZ_RUN; }
106     override uint flushFlag() const { return BZ_FLUSH; }
107     override uint finishFlag() const { return BZ_FINISH; }
108 
109 	override bool run(uint flags) { return false; }
110 	override void nextIn(ubyte* b, size_t len) { super.nextIn(b, len); }    
111 	override void nextOut(ubyte* b, size_t len) { super.nextOut(b, len); }    
112 	override size_t availIn() const { return super.availIn(); }    
113 	override size_t availOut() const { return super.availOut; }
114 }
115 
116 class Bzip2CompressionStream : Bzip2Stream, CompressionStream
117 {
118 public:
119     this(size_t block_size)
120     {
121         int rc = BZ2_bzCompressInit(streamp(), cast(int)block_size, 0, 0);
122         
123         if (rc == BZ_MEM_ERROR)
124             throw new InvalidMemoryOperationError();
125         else if (rc != BZ_OK)
126             throw new Exception("bzip compress initialization failed");
127     }
128     
129     ~this()
130     {
131         BZ2_bzCompressEnd(streamp());
132     }
133     
134     override bool run(uint flags)
135     {
136         int rc = BZ2_bzCompress(streamp(), flags);
137         
138         if (rc == BZ_MEM_ERROR)
139             throw new InvalidMemoryOperationError();
140         else if (rc < 0)
141             throw new Exception("bzip compress error");
142         
143         return (rc == BZ_STREAM_END);
144     }
145 
146 	override void nextIn(ubyte* b, size_t len) { super.nextIn(b, len); }    
147 	override void nextOut(ubyte* b, size_t len) { super.nextOut(b, len); }    
148 	override size_t availIn() const { return super.availIn(); }    
149 	override size_t availOut() const { return super.availOut; }
150 	override uint runFlag() const { return super.runFlag(); }
151 	override uint flushFlag() const { return super.flushFlag(); }
152 	override uint finishFlag() const { return super.finishFlag(); }
153 }
154 
155 class Bzip2DecompressionStream : Bzip2Stream, CompressionStream
156 {
157 public:
158     this()
159     {
160         int rc = BZ2_bzDecompressInit(streamp(), 0, 0);
161         
162         if (rc == BZ_MEM_ERROR)
163             throw new InvalidMemoryOperationError();
164         else if (rc != BZ_OK)
165             throw new Exception("bzip decompress initialization failed");
166     }
167     
168     ~this()
169     {
170         BZ2_bzDecompressEnd(streamp());
171     }
172     
173     override bool run(uint)
174     {
175         int rc = BZ2_bzDecompress(streamp());
176         
177         if (rc == BZ_MEM_ERROR)
178             throw new InvalidMemoryOperationError();
179         else if (rc != BZ_OK && rc != BZ_STREAM_END)
180             throw new Exception("bzip decompress error");
181         
182         return (rc == BZ_STREAM_END);
183     }
184 
185 	override void nextIn(ubyte* b, size_t len) { super.nextIn(b, len); }    
186 	override void nextOut(ubyte* b, size_t len) { super.nextOut(b, len); }    
187 	override size_t availIn() const { return super.availIn(); }    
188 	override size_t availOut() const { return super.availOut; }
189 	override uint runFlag() const { return super.runFlag(); }
190 	override uint flushFlag() const { return super.flushFlag(); }
191 	override uint finishFlag() const { return super.finishFlag(); }
192 }