dlzma: small fixes; added "vanilized" streaming codec expample
[iv.d.git] / dlzma / package.d
blob20005ba40783061128dcfb479ab0245682d3dae5
1 /* converted by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
2 * Understanding is not required. Only obedience.
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, version 3 of the License ONLY.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // conversion of LZMA SDK 2103 (lzma2103.7z)
17 module iv.dlzma;
18 public:
21 // ////////////////////////////////////////////////////////////////////////// //
22 static if (!is(typeof(usize))) public alias usize = size_t;
25 // ////////////////////////////////////////////////////////////////////////// //
26 /* LZMA_PROB32 can increase the speed on some CPUs,
27 but memory usage for CLzmaDec::probs will be doubled in that case */
28 //version = LZMA_PROB32;
30 version(LZMA_PROB32) {
31 alias CLzmaProb = uint;
32 } else {
33 alias CLzmaProb = ushort;
37 // ////////////////////////////////////////////////////////////////////////// //
38 enum {
39 SZ_OK = 0,
41 SZ_ERROR_DATA = 1,
42 SZ_ERROR_MEM = 2,
43 // SZ_ERROR_CRC = 3,
44 SZ_ERROR_UNSUPPORTED = 4,
45 SZ_ERROR_PARAM = 5,
46 SZ_ERROR_INPUT_EOF = 6,
47 SZ_ERROR_OUTPUT_EOF = 7,
48 SZ_ERROR_READ = 8,
49 SZ_ERROR_WRITE = 9,
50 SZ_ERROR_PROGRESS = 10,
51 SZ_ERROR_FAIL = 11,
55 alias SRes = int;
56 alias WRes = int;
59 /* The following interfaces use first parameter as pointer to structure */
61 struct ISeqInStream {
62 SRes delegate (/*const*/ISeqInStream* p, void* buf, usize* size) nothrow Read;
63 /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
64 (output(*size) < input(*size)) is allowed */
68 struct ISeqOutStream {
69 usize delegate (/*const*/ISeqOutStream* p, const(void)* buf, usize size) nothrow Write;
70 /* Returns: result - the number of actually written bytes.
71 (result < size) means error */
75 struct ICompressProgress {
76 SRes delegate (/*const*/ICompressProgress* p, ulong inSize, ulong outSize) nothrow Progress;
77 /* Returns: result. (result != SZ_OK) means break.
78 Value (ulong)(long)-1 for size means unknown value. */
82 alias ISzAllocPtr = ISzAlloc*;
83 struct ISzAlloc {
84 void *delegate (ISzAllocPtr p, usize size) nothrow Alloc;
85 void delegate (ISzAllocPtr p, void *address) nothrow Free; /* address can be 0 */
88 public void *ISzAlloc_Alloc (ISzAllocPtr p, usize size) nothrow {
89 pragma(inline, true);
90 return p.Alloc(p, size);
93 public void ISzAlloc_Free (ISzAllocPtr p, void *address) nothrow {
94 pragma(inline, true);
95 p.Free(p, address);
99 // ////////////////////////////////////////////////////////////////////////// //
100 __gshared ISzAlloc lzmaDefAllocator = ISzAlloc(
101 delegate void* (ISzAllocPtr p, usize size) nothrow {
102 import core.stdc.stdlib : malloc;
103 size += !size;
104 return malloc(size);
106 delegate void (ISzAllocPtr p, void* address) nothrow {
107 import core.stdc.stdlib : free;
108 if (address !is null) free(address);
113 // ////////////////////////////////////////////////////////////////////////// //
114 enum LZMA_PROPS_SIZE = 5;
117 //**************************************************************************
119 // encoder API
121 //**************************************************************************
123 struct CLzmaEncProps {
124 int level; /* 0 <= level <= 9 */
125 uint dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
126 (1 << 12) <= dictSize <= (3 << 29) for 64-bit version
127 default = (1 << 24) */
128 int lc; /* 0 <= lc <= 8, default = 3 */
129 int lp; /* 0 <= lp <= 4, default = 0 */
130 int pb; /* 0 <= pb <= 4, default = 2 */
131 int algo; /* 0 - fast, 1 - normal, default = 1 */
132 int fb; /* 5 <= fb <= 273, default = 32 */
133 int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
134 int numHashBytes; /* 2, 3 or 4, default = 4 */
135 uint mc; /* 1 <= mc <= (1 << 30), default = 32 */
136 uint writeEndMark;/* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
138 ulong reduceSize; /* estimated size of data that will be compressed. default = (ulong)(long)-1.
139 Encoder uses this value to reduce dictionary size */
142 alias CLzmaEncHandle = void*;
144 version(none) {
145 public void LzmaEncProps_Init (CLzmaEncProps* p) @nogc;
146 public void LzmaEncProps_Normalize (CLzmaEncProps* p) @nogc;
147 public uint LzmaEncProps_GetDictSize (const(CLzmaEncProps)* props2) @nogc;
149 /* LzmaEnc* functions can return the following exit codes:
150 SRes:
151 SZ_OK - OK
152 SZ_ERROR_MEM - Memory allocation error
153 SZ_ERROR_PARAM - Incorrect paramater in props
154 SZ_ERROR_WRITE - ISeqOutStream write callback error
155 SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (ubyte *) output
156 SZ_ERROR_PROGRESS - some break from progress callback
159 public CLzmaEncHandle LzmaEnc_Create (ISzAllocPtr alloc);
160 public void LzmaEnc_Destroy (CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig);
162 public SRes LzmaEnc_SetProps (CLzmaEncHandle pp, const(CLzmaEncProps)* props2) @nogc;
163 public void LzmaEnc_SetDataSize (CLzmaEncHandle pp, ulong expectedDataSiize) @nogc;
164 public SRes LzmaEnc_WriteProperties (CLzmaEncHandle pp, ubyte* props, uint* size) @nogc;
165 public uint LzmaEnc_IsWriteEndMark (CLzmaEncHandle pp) @nogc;
167 public SRes LzmaEnc_MemEncode (CLzmaEncHandle pp, ubyte* dest, usize* destLen, const(ubyte)* src, usize srcLen,
168 int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
170 public SRes LzmaEnc_Encode (CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream,
171 ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
173 /* ---------- One Call Interface ---------- */
174 public SRes LzmaEncode (ubyte* dest, usize* destLen, const(ubyte)* src, usize srcLen,
175 const(CLzmaEncProps)* props, ubyte* propsEncoded, usize* propsSize,
176 int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
181 //**************************************************************************
183 // decoder API
185 //**************************************************************************
186 struct CLzmaProps {
187 ubyte lc;
188 ubyte lp;
189 ubyte pb;
190 ubyte _pad_;
191 uint dicSize;
194 /* LzmaProps_Decode - decodes properties
195 Returns:
196 SZ_OK
197 SZ_ERROR_UNSUPPORTED - Unsupported properties
200 //SRes LzmaProps_Decode(CLzmaProps *p, const uint8_t *data, unsigned size);
203 /* ---------- LZMA Decoder state ---------- */
205 /* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
206 Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
208 enum LZMA_REQUIRED_INPUT_MAX = 20;
210 struct CLzmaDec {
211 CLzmaProps prop;
212 CLzmaProb *probs;
213 CLzmaProb *probs_1664;
214 ubyte *dic;
215 usize dicBufSize;
216 usize dicPos;
217 const(ubyte)* buf;
218 uint range;
219 uint code;
220 uint processedPos;
221 uint checkDicSize;
222 uint[4] reps;
223 uint state;
224 uint remainLen;
226 uint numProbs;
227 uint tempBufSize;
228 ubyte[LZMA_REQUIRED_INPUT_MAX] tempBuf = void;
231 //#define LzmaDec_Construct(p) { (p)->dic = NULL; (p)->probs = NULL; }
233 //public void LzmaDec_Construct (CLzmaDec *p) nothrow @nogc { p.dic = null; p.probs = null; }
235 /* There are two types of LZMA streams:
236 - Stream with end mark. That end mark adds about 6 bytes to compressed size.
237 - Stream without end mark. You must know exact uncompressed size to decompress such stream. */
239 alias ELzmaFinishMode = int;
240 enum {
241 LZMA_FINISH_ANY, /* finish at any point */
242 LZMA_FINISH_END /* block must be finished at the end */
245 /* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
247 You must use LZMA_FINISH_END, when you know that current output buffer
248 covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
250 If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
251 and output value of destLen will be less than output buffer size limit.
252 You can check status result also.
254 You can use multiple checks to test data integrity after full decompression:
255 1) Check Result and "status" variable.
256 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
257 3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
258 You must use correct finish mode in that case. */
260 alias ELzmaStatus = int;
261 enum {
262 LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
263 LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
264 LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
265 LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
266 LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
269 /* ELzmaStatus is used only as output value for function call */
272 /* ---------- Interfaces ---------- */
274 /* There are 3 levels of interfaces:
275 1) Dictionary Interface
276 2) Buffer Interface
277 3) One Call Interface
278 You can select any of these interfaces, but don't mix functions from different
279 groups for same object. */
282 /* There are two variants to allocate state for Dictionary Interface:
283 1) LzmaDec_Allocate / LzmaDec_Free
284 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
285 You can use variant 2, if you set dictionary buffer manually.
286 For Buffer Interface you must always use variant 1.
288 LzmaDec_Allocate* can return:
289 SZ_OK
290 SZ_ERROR_MEM - Memory allocation error
291 SZ_ERROR_UNSUPPORTED - Unsupported properties
294 version(none) {
295 // you can use this to check and decode properties
296 public SRes LzmaProps_Decode (CLzmaProps* p, const(ubyte)* data, uint size) @nogc;
298 public void LzmaDec_Init (CLzmaDec* p) @nogc;
300 public SRes LzmaDec_Allocate (CLzmaDec* p, const(ubyte)* props, uint propsSize, ISzAllocPtr alloc);
301 public void LzmaDec_Free (CLzmaDec* p, ISzAllocPtr alloc);
303 //k8: the following two functions are used for... something, i don't know.
304 //k8: you don't need to call them, `LzmaDec_Allocate()` and `LzmaDec_Free()` will do it for you.
305 public SRes LzmaDec_AllocateProbs (CLzmaDec* p, const(ubyte)* props, uint propsSize, ISzAllocPtr alloc);
306 public void LzmaDec_FreeProbs (CLzmaDec *p, ISzAllocPtr alloc);
308 /* ---------- Dictionary Interface ---------- */
310 /* You can use it, if you want to eliminate the overhead for data copying from
311 dictionary to some other external buffer.
312 You must work with CLzmaDec variables directly in this interface.
314 STEPS:
315 LzmaDec_Construct()
316 LzmaDec_Allocate()
317 for (each new stream)
319 LzmaDec_Init()
320 while (it needs more decompression)
322 LzmaDec_DecodeToDic()
323 use data from CLzmaDec::dic and update CLzmaDec::dicPos
326 LzmaDec_Free()
329 /* LzmaDec_DecodeToDic
331 The decoding to internal dictionary buffer (CLzmaDec::dic).
332 You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
334 finishMode:
335 It has meaning only if the decoding reaches output limit (dicLimit).
336 LZMA_FINISH_ANY - Decode just dicLimit bytes.
337 LZMA_FINISH_END - Stream must be finished after dicLimit.
339 Returns:
340 SZ_OK
341 status:
342 LZMA_STATUS_FINISHED_WITH_MARK
343 LZMA_STATUS_NOT_FINISHED
344 LZMA_STATUS_NEEDS_MORE_INPUT
345 LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
346 SZ_ERROR_DATA - Data error
347 SZ_ERROR_FAIL - Some unexpected error: internal error of code, memory corruption or hardware failure
350 public SRes LzmaDec_DecodeToDic (CLzmaDec* p, usize dicLimit, const(ubyte)* src, usize *srcLen,
351 ELzmaFinishMode finishMode, ELzmaStatus *status) @nogc;
354 /* ---------- Buffer Interface ---------- */
356 /* It's zlib-like interface.
357 See LzmaDec_DecodeToDic description for information about STEPS and return results,
358 but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
359 to work with CLzmaDec variables manually.
361 finishMode:
362 It has meaning only if the decoding reaches output limit (*destLen).
363 LZMA_FINISH_ANY - Decode just destLen bytes.
364 LZMA_FINISH_END - Stream must be finished after (*destLen).
367 public SRes LzmaDec_DecodeToBuf (CLzmaDec* p, ubyte* dest, usize* destLen, const(ubyte)* src, usize *srcLen,
368 ELzmaFinishMode finishMode, ELzmaStatus *status) @nogc;
371 /* ---------- One Call Interface ---------- */
373 /* LzmaDecode
375 finishMode:
376 It has meaning only if the decoding reaches output limit (*destLen).
377 LZMA_FINISH_ANY - Decode just destLen bytes.
378 LZMA_FINISH_END - Stream must be finished after (*destLen).
380 Returns:
381 SZ_OK
382 status:
383 LZMA_STATUS_FINISHED_WITH_MARK
384 LZMA_STATUS_NOT_FINISHED
385 LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
386 SZ_ERROR_DATA - Data error
387 SZ_ERROR_MEM - Memory allocation error
388 SZ_ERROR_UNSUPPORTED - Unsupported properties
389 SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
390 SZ_ERROR_FAIL - Some unexpected error: internal error of code, memory corruption or hardware failure
393 public SRes LzmaDecode (ubyte* dest, usize* destLen, const(ubyte)* src, usize *srcLen,
394 const(ubyte)* propData, uint propSize, ELzmaFinishMode finishMode,
395 ELzmaStatus *status, ISzAllocPtr alloc);
399 public import iv.dlzma.dec;
400 public import iv.dlzma.enc;