1 /* Xz.h - Xz interface
2 2010-09-17 : Igor Pavlov : Public domain */
3 
4 #ifndef __XZ_H
5 #define __XZ_H
6 
7 #include "Types.h"
8 
9 #define SHA256_DIGEST_SIZE 32
10 
11 EXTERN_C_BEGIN
12 
13 #define XZ_ID_Subblock 1
14 #define XZ_ID_Delta 3
15 #define XZ_ID_X86 4
16 #define XZ_ID_PPC 5
17 #define XZ_ID_IA64 6
18 #define XZ_ID_ARM 7
19 #define XZ_ID_ARMT 8
20 #define XZ_ID_SPARC 9
21 #define XZ_ID_LZMA2 0x21
22 
23 unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value);
24 unsigned Xz_WriteVarInt(Byte *buf, UInt64 v);
25 
26 /* ---------- xz block ---------- */
27 
28 #define XZ_BLOCK_HEADER_SIZE_MAX 1024
29 
30 #define XZ_NUM_FILTERS_MAX 4
31 #define XZ_BF_NUM_FILTERS_MASK 3
32 #define XZ_BF_PACK_SIZE (1 << 6)
33 #define XZ_BF_UNPACK_SIZE (1 << 7)
34 
35 #define XZ_FILTER_PROPS_SIZE_MAX 20
36 
37 typedef struct
38 {
39   UInt64 id;
40   UInt32 propsSize;
41   Byte props[XZ_FILTER_PROPS_SIZE_MAX];
42 } CXzFilter;
43 
44 typedef struct
45 {
46   UInt64 packSize;
47   UInt64 unpackSize;
48   Byte flags;
49   CXzFilter filters[XZ_NUM_FILTERS_MAX];
50 } CXzBlock;
51 
52 #define XzBlock_GetNumFilters(p) (((p)->flags & XZ_BF_NUM_FILTERS_MASK) + 1)
53 #define XzBlock_HasPackSize(p)   (((p)->flags & XZ_BF_PACK_SIZE) != 0)
54 #define XzBlock_HasUnpackSize(p) (((p)->flags & XZ_BF_UNPACK_SIZE) != 0)
55 
56 SRes XzBlock_Parse(CXzBlock *p, const Byte *header);
57 SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt32 *headerSizeRes);
58 
59 /* ---------- xz stream ---------- */
60 
61 #define XZ_SIG_SIZE 6
62 #define XZ_FOOTER_SIG_SIZE 2
63 
64 extern Byte XZ_SIG[XZ_SIG_SIZE];
65 extern Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE];
66 
67 #define XZ_STREAM_FLAGS_SIZE 2
68 #define XZ_STREAM_CRC_SIZE 4
69 
70 #define XZ_STREAM_HEADER_SIZE (XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE)
71 #define XZ_STREAM_FOOTER_SIZE (XZ_FOOTER_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE + 4)
72 
73 #define XZ_CHECK_MASK 0xF
74 #define XZ_CHECK_NO 0
75 #define XZ_CHECK_CRC32 1
76 #define XZ_CHECK_CRC64 4
77 #define XZ_CHECK_SHA256 10
78 
79 typedef struct
80 {
81   int mode;
82   UInt32 crc;
83   UInt64 crc64;
84   void *sha;
85 } CXzCheck;
86 
87 void XzCheck_Init(CXzCheck *p, int mode);
88 void XzCheck_Update(CXzCheck *p, const void *data, size_t size);
89 int XzCheck_Final(CXzCheck *p, Byte *digest);
90 
91 typedef UInt16 CXzStreamFlags;
92 
93 #define XzFlags_IsSupported(f) ((f) <= XZ_CHECK_MASK)
94 #define XzFlags_GetCheckType(f) ((f) & XZ_CHECK_MASK)
95 #define XzFlags_HasDataCrc32(f) (Xz_GetCheckType(f) == XZ_CHECK_CRC32)
96 unsigned XzFlags_GetCheckSize(CXzStreamFlags f);
97 
98 SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf);
99 SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream);
100 
101 typedef struct
102 {
103   UInt64 unpackSize;
104   UInt64 totalSize;
105 } CXzBlockSizes;
106 
107 typedef struct
108 {
109   CXzStreamFlags flags;
110   size_t numBlocks;
111   size_t numBlocksAllocated;
112   CXzBlockSizes *blocks;
113   UInt64 startOffset;
114 } CXzStream;
115 
116 void Xz_Construct(CXzStream *p);
117 void Xz_Free(CXzStream *p, ISzAlloc *alloc);
118 
119 #define XZ_SIZE_OVERFLOW ((UInt64)(Int64)-1)
120 
121 UInt64 Xz_GetUnpackSize(const CXzStream *p);
122 UInt64 Xz_GetPackSize(const CXzStream *p);
123 
124 typedef struct
125 {
126   size_t num;
127   size_t numAllocated;
128   CXzStream *streams;
129 } CXzs;
130 
131 void Xzs_Construct(CXzs *p);
132 void Xzs_Free(CXzs *p, ISzAlloc *alloc);
133 SRes Xzs_ReadBackward(CXzs *p, ILookInStream *inStream, Int64 *startOffset, ICompressProgress *progress, ISzAlloc *alloc);
134 
135 UInt64 Xzs_GetNumBlocks(const CXzs *p);
136 UInt64 Xzs_GetUnpackSize(const CXzs *p);
137 
138 typedef enum
139 {
140   CODER_STATUS_NOT_SPECIFIED,               /* use main error code instead */
141   CODER_STATUS_FINISHED_WITH_MARK,          /* stream was finished with end mark. */
142   CODER_STATUS_NOT_FINISHED,                /* stream was not finished */
143   CODER_STATUS_NEEDS_MORE_INPUT             /* you must provide more input bytes */
144 } ECoderStatus;
145 
146 typedef enum
147 {
148   CODER_FINISH_ANY,   /* finish at any point */
149   CODER_FINISH_END    /* block must be finished at the end */
150 } ECoderFinishMode;
151 
152 typedef struct _IStateCoder
153 {
154   void *p;
155   void (*Free)(void *p, ISzAlloc *alloc);
156   SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAlloc *alloc);
157   void (*Init)(void *p);
158   SRes (*Code)(void *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
159       int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished);
160 } IStateCoder;
161 
162 #define MIXCODER_NUM_FILTERS_MAX 4
163 
164 typedef struct
165 {
166   ISzAlloc *alloc;
167   Byte *buf;
168   int numCoders;
169   int finished[MIXCODER_NUM_FILTERS_MAX - 1];
170   size_t pos[MIXCODER_NUM_FILTERS_MAX - 1];
171   size_t size[MIXCODER_NUM_FILTERS_MAX - 1];
172   UInt64 ids[MIXCODER_NUM_FILTERS_MAX];
173   IStateCoder coders[MIXCODER_NUM_FILTERS_MAX];
174 } CMixCoder;
175 
176 void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc);
177 void MixCoder_Free(CMixCoder *p);
178 void MixCoder_Init(CMixCoder *p);
179 SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId);
180 SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
181     const Byte *src, SizeT *srcLen, int srcWasFinished,
182     ECoderFinishMode finishMode, ECoderStatus *status);
183 
184 typedef enum
185 {
186   XZ_STATE_STREAM_HEADER,
187   XZ_STATE_STREAM_INDEX,
188   XZ_STATE_STREAM_INDEX_CRC,
189   XZ_STATE_STREAM_FOOTER,
190   XZ_STATE_STREAM_PADDING,
191   XZ_STATE_BLOCK_HEADER,
192   XZ_STATE_BLOCK,
193   XZ_STATE_BLOCK_FOOTER
194 } EXzState;
195 
196 typedef struct
197 {
198   EXzState state;
199   UInt32 pos;
200   unsigned alignPos;
201   unsigned indexPreSize;
202 
203   CXzStreamFlags streamFlags;
204 
205   UInt32 blockHeaderSize;
206   UInt64 packSize;
207   UInt64 unpackSize;
208 
209   UInt64 numBlocks;
210   UInt64 indexSize;
211   UInt64 indexPos;
212   UInt64 padSize;
213 
214   UInt64 numStreams;
215 
216   UInt32 crc;
217   CMixCoder decoder;
218   CXzBlock block;
219   CXzCheck check;
220   void *sha;
221   Byte shaDigest[SHA256_DIGEST_SIZE];
222   Byte buf[XZ_BLOCK_HEADER_SIZE_MAX];
223 } CXzUnpacker;
224 
225 SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc);
226 void XzUnpacker_Free(CXzUnpacker *p);
227 
228 /*
229 finishMode:
230   It has meaning only if the decoding reaches output limit (*destLen).
231   LZMA_FINISH_ANY - use smallest number of input bytes
232   LZMA_FINISH_END - read EndOfStream marker after decoding
233 
234 Returns:
235   SZ_OK
236     status:
237       LZMA_STATUS_FINISHED_WITH_MARK
238       LZMA_STATUS_NOT_FINISHED
239   SZ_ERROR_DATA - Data error
240   SZ_ERROR_MEM  - Memory allocation error
241   SZ_ERROR_UNSUPPORTED - Unsupported properties
242   SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
243 */
244 
245 
246 SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
247     const Byte *src, SizeT *srcLen, /* int srcWasFinished, */ int finishMode,
248     ECoderStatus *status);
249 
250 Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p);
251 
252 EXTERN_C_END
253 
254 #endif
255