2 2018-07-04 : Igor Pavlov : Public domain */
11 #define XZ_ID_Subblock 1
19 #define XZ_ID_LZMA2 0x21
21 unsigned Xz_ReadVarInt(const Byte
*p
, size_t maxSize
, UInt64
*value
);
22 unsigned Xz_WriteVarInt(Byte
*buf
, UInt64 v
);
24 /* ---------- xz block ---------- */
26 #define XZ_BLOCK_HEADER_SIZE_MAX 1024
28 #define XZ_NUM_FILTERS_MAX 4
29 #define XZ_BF_NUM_FILTERS_MASK 3
30 #define XZ_BF_PACK_SIZE (1 << 6)
31 #define XZ_BF_UNPACK_SIZE (1 << 7)
33 #define XZ_FILTER_PROPS_SIZE_MAX 20
39 Byte props
[XZ_FILTER_PROPS_SIZE_MAX
];
47 CXzFilter filters
[XZ_NUM_FILTERS_MAX
];
50 #define XzBlock_GetNumFilters(p) (((p)->flags & XZ_BF_NUM_FILTERS_MASK) + 1)
51 #define XzBlock_HasPackSize(p) (((p)->flags & XZ_BF_PACK_SIZE) != 0)
52 #define XzBlock_HasUnpackSize(p) (((p)->flags & XZ_BF_UNPACK_SIZE) != 0)
53 #define XzBlock_HasUnsupportedFlags(p) (((p)->flags & ~(XZ_BF_NUM_FILTERS_MASK | XZ_BF_PACK_SIZE | XZ_BF_UNPACK_SIZE)) != 0)
55 SRes
XzBlock_Parse(CXzBlock
*p
, const Byte
*header
);
56 SRes
XzBlock_ReadHeader(CXzBlock
*p
, ISeqInStream
*inStream
, BoolInt
*isIndex
, UInt32
*headerSizeRes
);
58 /* ---------- xz stream ---------- */
61 #define XZ_FOOTER_SIG_SIZE 2
63 extern const Byte XZ_SIG
[XZ_SIG_SIZE
];
66 extern const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE];
69 #define XZ_FOOTER_SIG_0 'Y'
70 #define XZ_FOOTER_SIG_1 'Z'
72 #define XZ_STREAM_FLAGS_SIZE 2
73 #define XZ_STREAM_CRC_SIZE 4
75 #define XZ_STREAM_HEADER_SIZE (XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE)
76 #define XZ_STREAM_FOOTER_SIZE (XZ_FOOTER_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE + 4)
78 #define XZ_CHECK_MASK 0xF
80 #define XZ_CHECK_CRC32 1
81 #define XZ_CHECK_CRC64 4
82 #define XZ_CHECK_SHA256 10
92 void XzCheck_Init(CXzCheck
*p
, unsigned mode
);
93 void XzCheck_Update(CXzCheck
*p
, const void *data
, size_t size
);
94 int XzCheck_Final(CXzCheck
*p
, Byte
*digest
);
96 typedef UInt16 CXzStreamFlags
;
98 #define XzFlags_IsSupported(f) ((f) <= XZ_CHECK_MASK)
99 #define XzFlags_GetCheckType(f) ((f) & XZ_CHECK_MASK)
100 #define XzFlags_HasDataCrc32(f) (Xz_GetCheckType(f) == XZ_CHECK_CRC32)
101 unsigned XzFlags_GetCheckSize(CXzStreamFlags f
);
103 SRes
Xz_ParseHeader(CXzStreamFlags
*p
, const Byte
*buf
);
104 SRes
Xz_ReadHeader(CXzStreamFlags
*p
, ISeqInStream
*inStream
);
114 CXzStreamFlags flags
;
116 CXzBlockSizes
*blocks
;
120 void Xz_Construct(CXzStream
*p
);
121 void Xz_Free(CXzStream
*p
, ISzAllocPtr alloc
);
123 #define XZ_SIZE_OVERFLOW ((UInt64)(Int64)-1)
125 UInt64
Xz_GetUnpackSize(const CXzStream
*p
);
126 UInt64
Xz_GetPackSize(const CXzStream
*p
);
135 void Xzs_Construct(CXzs
*p
);
136 void Xzs_Free(CXzs
*p
, ISzAllocPtr alloc
);
137 SRes
Xzs_ReadBackward(CXzs
*p
, ILookInStream
*inStream
, Int64
*startOffset
, ICompressProgress
*progress
, ISzAllocPtr alloc
);
139 UInt64
Xzs_GetNumBlocks(const CXzs
*p
);
140 UInt64
Xzs_GetUnpackSize(const CXzs
*p
);
143 // ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder
147 CODER_STATUS_NOT_SPECIFIED
, /* use main error code instead */
148 CODER_STATUS_FINISHED_WITH_MARK
, /* stream was finished with end mark. */
149 CODER_STATUS_NOT_FINISHED
, /* stream was not finished */
150 CODER_STATUS_NEEDS_MORE_INPUT
/* you must provide more input bytes */
154 // ECoderFinishMode values are identical to ELzmaFinishMode
158 CODER_FINISH_ANY
, /* finish at any point */
159 CODER_FINISH_END
/* block must be finished at the end */
163 typedef struct _IStateCoder
166 void (*Free
)(void *p
, ISzAllocPtr alloc
);
167 SRes (*SetProps
)(void *p
, const Byte
*props
, size_t propSize
, ISzAllocPtr alloc
);
168 void (*Init
)(void *p
);
169 SRes (*Code2
)(void *p
, Byte
*dest
, SizeT
*destLen
, const Byte
*src
, SizeT
*srcLen
,
170 int srcWasFinished
, ECoderFinishMode finishMode
,
172 ECoderStatus
*status
);
173 SizeT (*Filter
)(void *p
, Byte
*data
, SizeT size
);
178 #define MIXCODER_NUM_FILTERS_MAX 4
188 size_t outWritten
; // is equal to lzmaDecoder.dicPos (in outBuf mode)
192 // BoolInt SingleBufMode;
194 int finished
[MIXCODER_NUM_FILTERS_MAX
- 1];
195 size_t pos
[MIXCODER_NUM_FILTERS_MAX
- 1];
196 size_t size
[MIXCODER_NUM_FILTERS_MAX
- 1];
197 UInt64 ids
[MIXCODER_NUM_FILTERS_MAX
];
198 SRes results
[MIXCODER_NUM_FILTERS_MAX
];
199 IStateCoder coders
[MIXCODER_NUM_FILTERS_MAX
];
205 XZ_STATE_STREAM_HEADER
,
206 XZ_STATE_STREAM_INDEX
,
207 XZ_STATE_STREAM_INDEX_CRC
,
208 XZ_STATE_STREAM_FOOTER
,
209 XZ_STATE_STREAM_PADDING
,
210 XZ_STATE_BLOCK_HEADER
,
212 XZ_STATE_BLOCK_FOOTER
221 unsigned indexPreSize
;
223 CXzStreamFlags streamFlags
;
225 UInt32 blockHeaderSize
;
229 UInt64 numBlocks
; // number of finished blocks in current stream
234 UInt64 numStartedStreams
;
235 UInt64 numFinishedStreams
;
236 UInt64 numTotalBlocks
;
245 BoolInt headerParsedOk
;
246 BoolInt decodeToStreamSignature
;
247 unsigned decodeOnlyOneBlock
;
251 size_t outDataWritten
; // the size of data in (outBuf) that were fully unpacked
253 Byte shaDigest
[SHA256_DIGEST_SIZE
];
254 Byte buf
[XZ_BLOCK_HEADER_SIZE_MAX
];
257 /* alloc : aligned for cache line allocation is better */
258 void XzUnpacker_Construct(CXzUnpacker
*p
, ISzAllocPtr alloc
);
259 void XzUnpacker_Init(CXzUnpacker
*p
);
260 void XzUnpacker_SetOutBuf(CXzUnpacker
*p
, Byte
*outBuf
, size_t outBufSize
);
261 void XzUnpacker_Free(CXzUnpacker
*p
);
265 The sequence for decoding functions:
267 XzUnpacker_Construct()
274 There are 3 types of interfaces for [Decoding_Calls] calls:
276 Interface-1 : Partial output buffers:
283 Interface-2 : Direct output buffer:
284 Use it, if you know exact size of decoded data, and you need
285 whole xz unpacked data in one output buffer.
286 xz unpacker doesn't allocate additional buffer for lzma2 dictionary in that mode.
289 XzUnpacker_SetOutBufMode(); // to set output buffer and size
291 XzUnpacker_Code(); // (dest = NULL) in XzUnpacker_Code()
294 Interface-3 : Direct output buffer : One call full decoding
295 It unpacks whole input buffer to output buffer in one call.
296 It uses Interface-2 internally.
298 XzUnpacker_CodeFull()
304 It has meaning only if the decoding reaches output limit (*destLen).
305 CODER_FINISH_ANY - use smallest number of input bytes
306 CODER_FINISH_END - read EndOfStream marker after decoding
311 CODER_STATUS_NOT_FINISHED,
312 CODER_STATUS_NEEDS_MORE_INPUT - maybe there are more xz streams,
313 call XzUnpacker_IsStreamWasFinished to check that current stream was finished
314 SZ_ERROR_MEM - Memory allocation error
315 SZ_ERROR_DATA - Data error
316 SZ_ERROR_UNSUPPORTED - Unsupported method or method properties
317 SZ_ERROR_CRC - CRC error
318 // SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
320 SZ_ERROR_NO_ARCHIVE - the error with xz Stream Header with one of the following reasons:
321 - xz Stream Signature failure
322 - CRC32 of xz Stream Header is failed
323 - The size of Stream padding is not multiple of four bytes.
324 It's possible to get that error, if xz stream was finished and the stream
325 contains some another data. In that case you can call XzUnpacker_GetExtraSize()
326 function to get real size of xz stream.
330 SRes
XzUnpacker_Code(CXzUnpacker
*p
, Byte
*dest
, SizeT
*destLen
,
331 const Byte
*src
, SizeT
*srcLen
, int srcFinished
,
332 ECoderFinishMode finishMode
, ECoderStatus
*status
);
334 SRes
XzUnpacker_CodeFull(CXzUnpacker
*p
, Byte
*dest
, SizeT
*destLen
,
335 const Byte
*src
, SizeT
*srcLen
,
336 ECoderFinishMode finishMode
, ECoderStatus
*status
);
338 BoolInt
XzUnpacker_IsStreamWasFinished(const CXzUnpacker
*p
);
341 XzUnpacker_GetExtraSize() returns then number of uncofirmed bytes,
342 if it's in (XZ_STATE_STREAM_HEADER) state or in (XZ_STATE_STREAM_PADDING) state.
343 These bytes can be some bytes after xz archive, or
344 it can be start of new xz stream.
346 Call XzUnpacker_GetExtraSize() after XzUnpacker_Code() function to detect real size of
347 xz stream in two cases, if XzUnpacker_Code() returns:
348 res == SZ_OK && status == CODER_STATUS_NEEDS_MORE_INPUT
349 res == SZ_ERROR_NO_ARCHIVE
352 UInt64
XzUnpacker_GetExtraSize(const CXzUnpacker
*p
);
356 for random block decoding:
358 set CXzUnpacker::streamFlags
359 XzUnpacker_PrepareToRandomBlockDecoding()
363 XzUnpacker_IsBlockFinished()
367 void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker
*p
);
368 BoolInt
XzUnpacker_IsBlockFinished(const CXzUnpacker
*p
);
370 #define XzUnpacker_GetPackSizeForIndex(p) ((p)->packSize + (p)->blockHeaderSize + XzFlags_GetCheckSize((p)->streamFlags))
374 /* ---------- Multi Threading Decoding ---------- */
381 BoolInt ignoreErrors
;
390 void XzDecMtProps_Init(CXzDecMtProps
*p
);
393 typedef void * CXzDecMtHandle
;
396 alloc : XzDecMt uses CAlignOffsetAlloc for addresses allocated by (alloc).
397 allocMid : for big allocations, aligned allocation is better
400 CXzDecMtHandle
XzDecMt_Create(ISzAllocPtr alloc
, ISzAllocPtr allocMid
);
401 void XzDecMt_Destroy(CXzDecMtHandle p
);
406 Byte UnpackSize_Defined
;
407 Byte NumStreams_Defined
;
408 Byte NumBlocks_Defined
;
411 Byte DecodingTruncated
; // Decoding was Truncated, we need only partial output data
413 UInt64 InSize
; // pack size processed
423 SRes CombinedRes_Type
;
427 void XzStatInfo_Clear(CXzStatInfo
*p
);
433 SZ_ERROR_MEM - Memory allocation error
434 SZ_ERROR_NO_ARCHIVE - is not xz archive
435 SZ_ERROR_ARCHIVE - Headers error
436 SZ_ERROR_DATA - Data Error
437 SZ_ERROR_CRC - CRC Error
438 SZ_ERROR_INPUT_EOF - it needs more input data
439 SZ_ERROR_WRITE - ISeqOutStream error
440 (SZ_ERROR_READ) - ISeqInStream errors
441 (SZ_ERROR_PROGRESS) - ICompressProgress errors
442 // SZ_ERROR_THREAD - error in multi-threading functions
443 MY_SRes_HRESULT_FROM_WRes(WRes_error) - error in multi-threading function
446 SRes
XzDecMt_Decode(CXzDecMtHandle p
,
447 const CXzDecMtProps
*props
,
448 const UInt64
*outDataSize
, // NULL means undefined
449 int finishMode
, // 0 - partial unpacking is allowed, 1 - xz stream(s) must be finished
450 ISeqOutStream
*outStream
,
451 // Byte *outBuf, size_t *outBufSize,
452 ISeqInStream
*inStream
,
453 // const Byte *inData, size_t inDataSize,
455 int *isMT
, // 0 means that ST (Single-Thread) version was used
456 ICompressProgress
*progress
);