rlm@1: /* LzmaDec.h -- LZMA Decoder rlm@1: 2008-10-04 : Igor Pavlov : Public domain */ rlm@1: rlm@1: #ifndef __LZMADEC_H rlm@1: #define __LZMADEC_H rlm@1: rlm@1: #include "Types.h" rlm@1: rlm@1: /* #define _LZMA_PROB32 */ rlm@1: /* _LZMA_PROB32 can increase the speed on some CPUs, rlm@1: but memory usage for CLzmaDec::probs will be doubled in that case */ rlm@1: rlm@1: #ifdef _LZMA_PROB32 rlm@1: #define CLzmaProb UInt32 rlm@1: #else rlm@1: #define CLzmaProb UInt16 rlm@1: #endif rlm@1: rlm@1: rlm@1: /* ---------- LZMA Properties ---------- */ rlm@1: rlm@1: #define LZMA_PROPS_SIZE 5 rlm@1: rlm@1: typedef struct _CLzmaProps rlm@1: { rlm@1: unsigned lc, lp, pb; rlm@1: UInt32 dicSize; rlm@1: } CLzmaProps; rlm@1: rlm@1: /* LzmaProps_Decode - decodes properties rlm@1: Returns: rlm@1: SZ_OK rlm@1: SZ_ERROR_UNSUPPORTED - Unsupported properties rlm@1: */ rlm@1: rlm@1: SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); rlm@1: rlm@1: rlm@1: /* ---------- LZMA Decoder state ---------- */ rlm@1: rlm@1: /* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. rlm@1: Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ rlm@1: rlm@1: #define LZMA_REQUIRED_INPUT_MAX 20 rlm@1: rlm@1: typedef struct rlm@1: { rlm@1: CLzmaProps prop; rlm@1: CLzmaProb *probs; rlm@1: Byte *dic; rlm@1: const Byte *buf; rlm@1: UInt32 range, code; rlm@1: SizeT dicPos; rlm@1: SizeT dicBufSize; rlm@1: UInt32 processedPos; rlm@1: UInt32 checkDicSize; rlm@1: unsigned state; rlm@1: UInt32 reps[4]; rlm@1: unsigned remainLen; rlm@1: int needFlush; rlm@1: int needInitState; rlm@1: UInt32 numProbs; rlm@1: unsigned tempBufSize; rlm@1: Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; rlm@1: } CLzmaDec; rlm@1: rlm@1: #define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } rlm@1: rlm@1: void LzmaDec_Init(CLzmaDec *p); rlm@1: rlm@1: /* There are two types of LZMA streams: rlm@1: 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. rlm@1: 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ rlm@1: rlm@1: typedef enum rlm@1: { rlm@1: LZMA_FINISH_ANY, /* finish at any point */ rlm@1: LZMA_FINISH_END /* block must be finished at the end */ rlm@1: } ELzmaFinishMode; rlm@1: rlm@1: /* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! rlm@1: rlm@1: You must use LZMA_FINISH_END, when you know that current output buffer rlm@1: covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. rlm@1: rlm@1: If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, rlm@1: and output value of destLen will be less than output buffer size limit. rlm@1: You can check status result also. rlm@1: rlm@1: You can use multiple checks to test data integrity after full decompression: rlm@1: 1) Check Result and "status" variable. rlm@1: 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. rlm@1: 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. rlm@1: You must use correct finish mode in that case. */ rlm@1: rlm@1: typedef enum rlm@1: { rlm@1: LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ rlm@1: LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ rlm@1: LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ rlm@1: LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ rlm@1: LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ rlm@1: } ELzmaStatus; rlm@1: rlm@1: /* ELzmaStatus is used only as output value for function call */ rlm@1: rlm@1: rlm@1: /* ---------- Interfaces ---------- */ rlm@1: rlm@1: /* There are 3 levels of interfaces: rlm@1: 1) Dictionary Interface rlm@1: 2) Buffer Interface rlm@1: 3) One Call Interface rlm@1: You can select any of these interfaces, but don't mix functions from different rlm@1: groups for same object. */ rlm@1: rlm@1: rlm@1: /* There are two variants to allocate state for Dictionary Interface: rlm@1: 1) LzmaDec_Allocate / LzmaDec_Free rlm@1: 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs rlm@1: You can use variant 2, if you set dictionary buffer manually. rlm@1: For Buffer Interface you must always use variant 1. rlm@1: rlm@1: LzmaDec_Allocate* can return: rlm@1: SZ_OK rlm@1: SZ_ERROR_MEM - Memory allocation error rlm@1: SZ_ERROR_UNSUPPORTED - Unsupported properties rlm@1: */ rlm@1: rlm@1: SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); rlm@1: void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); rlm@1: rlm@1: SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); rlm@1: void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); rlm@1: rlm@1: /* ---------- Dictionary Interface ---------- */ rlm@1: rlm@1: /* You can use it, if you want to eliminate the overhead for data copying from rlm@1: dictionary to some other external buffer. rlm@1: You must work with CLzmaDec variables directly in this interface. rlm@1: rlm@1: STEPS: rlm@1: LzmaDec_Constr() rlm@1: LzmaDec_Allocate() rlm@1: for (each new stream) rlm@1: { rlm@1: LzmaDec_Init() rlm@1: while (it needs more decompression) rlm@1: { rlm@1: LzmaDec_DecodeToDic() rlm@1: use data from CLzmaDec::dic and update CLzmaDec::dicPos rlm@1: } rlm@1: } rlm@1: LzmaDec_Free() rlm@1: */ rlm@1: rlm@1: /* LzmaDec_DecodeToDic rlm@1: rlm@1: The decoding to internal dictionary buffer (CLzmaDec::dic). rlm@1: You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! rlm@1: rlm@1: finishMode: rlm@1: It has meaning only if the decoding reaches output limit (dicLimit). rlm@1: LZMA_FINISH_ANY - Decode just dicLimit bytes. rlm@1: LZMA_FINISH_END - Stream must be finished after dicLimit. rlm@1: rlm@1: Returns: rlm@1: SZ_OK rlm@1: status: rlm@1: LZMA_STATUS_FINISHED_WITH_MARK rlm@1: LZMA_STATUS_NOT_FINISHED rlm@1: LZMA_STATUS_NEEDS_MORE_INPUT rlm@1: LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK rlm@1: SZ_ERROR_DATA - Data error rlm@1: */ rlm@1: rlm@1: SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, rlm@1: const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); rlm@1: rlm@1: rlm@1: /* ---------- Buffer Interface ---------- */ rlm@1: rlm@1: /* It's zlib-like interface. rlm@1: See LzmaDec_DecodeToDic description for information about STEPS and return results, rlm@1: but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need rlm@1: to work with CLzmaDec variables manually. rlm@1: rlm@1: finishMode: rlm@1: It has meaning only if the decoding reaches output limit (*destLen). rlm@1: LZMA_FINISH_ANY - Decode just destLen bytes. rlm@1: LZMA_FINISH_END - Stream must be finished after (*destLen). rlm@1: */ rlm@1: rlm@1: SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, rlm@1: const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); rlm@1: rlm@1: rlm@1: /* ---------- One Call Interface ---------- */ rlm@1: rlm@1: /* LzmaDecode rlm@1: rlm@1: finishMode: rlm@1: It has meaning only if the decoding reaches output limit (*destLen). rlm@1: LZMA_FINISH_ANY - Decode just destLen bytes. rlm@1: LZMA_FINISH_END - Stream must be finished after (*destLen). rlm@1: rlm@1: Returns: rlm@1: SZ_OK rlm@1: status: rlm@1: LZMA_STATUS_FINISHED_WITH_MARK rlm@1: LZMA_STATUS_NOT_FINISHED rlm@1: LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK rlm@1: SZ_ERROR_DATA - Data error rlm@1: SZ_ERROR_MEM - Memory allocation error rlm@1: SZ_ERROR_UNSUPPORTED - Unsupported properties rlm@1: SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). rlm@1: */ rlm@1: rlm@1: SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, rlm@1: const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, rlm@1: ELzmaStatus *status, ISzAlloc *alloc); rlm@1: rlm@1: #endif