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