/src/lzma-fuzz/sdk/C/Lzma2Enc.c
Line  | Count  | Source  | 
1  |  | /* Lzma2Enc.c -- LZMA2 Encoder  | 
2  |  | 2018-07-04 : Igor Pavlov : Public domain */  | 
3  |  |  | 
4  |  | #include "Precomp.h"  | 
5  |  |  | 
6  |  | #include <string.h>  | 
7  |  |  | 
8  |  | /* #define _7ZIP_ST */  | 
9  |  |  | 
10  |  | #include "Lzma2Enc.h"  | 
11  |  |  | 
12  |  | #ifndef _7ZIP_ST  | 
13  |  | #include "MtCoder.h"  | 
14  |  | #else  | 
15  | 63.4k  | #define MTCODER__THREADS_MAX 1  | 
16  |  | #endif  | 
17  |  |  | 
18  | 6.99k  | #define LZMA2_CONTROL_LZMA (1 << 7)  | 
19  | 2.03k  | #define LZMA2_CONTROL_COPY_NO_RESET 2  | 
20  | 1.31k  | #define LZMA2_CONTROL_COPY_RESET_DIC 1  | 
21  |  | #define LZMA2_CONTROL_EOF 0  | 
22  |  |  | 
23  | 6.34k  | #define LZMA2_LCLP_MAX 4  | 
24  |  |  | 
25  | 158k  | #define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))  | 
26  |  |  | 
27  | 20.0k  | #define LZMA2_PACK_SIZE_MAX (1 << 16)  | 
28  | 3.34k  | #define LZMA2_COPY_CHUNK_SIZE LZMA2_PACK_SIZE_MAX  | 
29  | 16.6k  | #define LZMA2_UNPACK_SIZE_MAX (1 << 21)  | 
30  |  | #define LZMA2_KEEP_WINDOW_SIZE LZMA2_UNPACK_SIZE_MAX  | 
31  |  |  | 
32  | 16.6k  | #define LZMA2_CHUNK_SIZE_COMPRESSED_MAX ((1 << 16) + 16)  | 
33  |  |  | 
34  |  |  | 
35  |  | #define PRF(x) /* x */  | 
36  |  |  | 
37  |  |  | 
38  |  | /* ---------- CLimitedSeqInStream ---------- */  | 
39  |  |  | 
40  |  | typedef struct  | 
41  |  | { | 
42  |  |   ISeqInStream vt;  | 
43  |  |   ISeqInStream *realStream;  | 
44  |  |   UInt64 limit;  | 
45  |  |   UInt64 processed;  | 
46  |  |   int finished;  | 
47  |  | } CLimitedSeqInStream;  | 
48  |  |  | 
49  |  | static void LimitedSeqInStream_Init(CLimitedSeqInStream *p)  | 
50  | 6.34k  | { | 
51  | 6.34k  |   p->limit = (UInt64)(Int64)-1;  | 
52  | 6.34k  |   p->processed = 0;  | 
53  | 6.34k  |   p->finished = 0;  | 
54  | 6.34k  | }  | 
55  |  |  | 
56  |  | static SRes LimitedSeqInStream_Read(const ISeqInStream *pp, void *data, size_t *size)  | 
57  | 14.0k  | { | 
58  | 14.0k  |   CLimitedSeqInStream *p = CONTAINER_FROM_VTBL(pp, CLimitedSeqInStream, vt);  | 
59  | 14.0k  |   size_t size2 = *size;  | 
60  | 14.0k  |   SRes res = SZ_OK;  | 
61  |  |     | 
62  | 14.0k  |   if (p->limit != (UInt64)(Int64)-1)  | 
63  | 0  |   { | 
64  | 0  |     UInt64 rem = p->limit - p->processed;  | 
65  | 0  |     if (size2 > rem)  | 
66  | 0  |       size2 = (size_t)rem;  | 
67  | 0  |   }  | 
68  | 14.0k  |   if (size2 != 0)  | 
69  | 14.0k  |   { | 
70  | 14.0k  |     res = ISeqInStream_Read(p->realStream, data, &size2);  | 
71  | 14.0k  |     p->finished = (size2 == 0 ? 1 : 0);  | 
72  | 14.0k  |     p->processed += size2;  | 
73  | 14.0k  |   }  | 
74  | 14.0k  |   *size = size2;  | 
75  | 14.0k  |   return res;  | 
76  | 14.0k  | }  | 
77  |  |  | 
78  |  |  | 
79  |  | /* ---------- CLzma2EncInt ---------- */  | 
80  |  |  | 
81  |  | typedef struct  | 
82  |  | { | 
83  |  |   CLzmaEncHandle enc;  | 
84  |  |   Byte propsAreSet;  | 
85  |  |   Byte propsByte;  | 
86  |  |   Byte needInitState;  | 
87  |  |   Byte needInitProp;  | 
88  |  |   UInt64 srcPos;  | 
89  |  | } CLzma2EncInt;  | 
90  |  |  | 
91  |  |  | 
92  |  | static SRes Lzma2EncInt_InitStream(CLzma2EncInt *p, const CLzma2EncProps *props)  | 
93  | 6.34k  | { | 
94  | 6.34k  |   if (!p->propsAreSet)  | 
95  | 6.34k  |   { | 
96  | 6.34k  |     SizeT propsSize = LZMA_PROPS_SIZE;  | 
97  | 6.34k  |     Byte propsEncoded[LZMA_PROPS_SIZE];  | 
98  | 6.34k  |     RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps));  | 
99  | 6.34k  |     RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize));  | 
100  | 6.34k  |     p->propsByte = propsEncoded[0];  | 
101  | 6.34k  |     p->propsAreSet = True;  | 
102  | 6.34k  |   }  | 
103  | 6.34k  |   return SZ_OK;  | 
104  | 6.34k  | }  | 
105  |  |  | 
106  |  | static void Lzma2EncInt_InitBlock(CLzma2EncInt *p)  | 
107  | 6.34k  | { | 
108  | 6.34k  |   p->srcPos = 0;  | 
109  | 6.34k  |   p->needInitState = True;  | 
110  | 6.34k  |   p->needInitProp = True;  | 
111  | 6.34k  | }  | 
112  |  |  | 
113  |  |  | 
114  |  | SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize,  | 
115  |  |     ISzAllocPtr alloc, ISzAllocPtr allocBig);  | 
116  |  | SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,  | 
117  |  |     UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig);  | 
118  |  | SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit,  | 
119  |  |     Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);  | 
120  |  | const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp);  | 
121  |  | void LzmaEnc_Finish(CLzmaEncHandle pp);  | 
122  |  | void LzmaEnc_SaveState(CLzmaEncHandle pp);  | 
123  |  | void LzmaEnc_RestoreState(CLzmaEncHandle pp);  | 
124  |  |  | 
125  |  | /*  | 
126  |  | UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp);  | 
127  |  | */  | 
128  |  |  | 
129  |  | static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,  | 
130  |  |     size_t *packSizeRes, ISeqOutStream *outStream)  | 
131  | 16.6k  | { | 
132  | 16.6k  |   size_t packSizeLimit = *packSizeRes;  | 
133  | 16.6k  |   size_t packSize = packSizeLimit;  | 
134  | 16.6k  |   UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX;  | 
135  | 16.6k  |   unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0);  | 
136  | 16.6k  |   BoolInt useCopyBlock;  | 
137  | 16.6k  |   SRes res;  | 
138  |  |  | 
139  | 16.6k  |   *packSizeRes = 0;  | 
140  | 16.6k  |   if (packSize < lzHeaderSize)  | 
141  | 0  |     return SZ_ERROR_OUTPUT_EOF;  | 
142  | 16.6k  |   packSize -= lzHeaderSize;  | 
143  |  |     | 
144  | 16.6k  |   LzmaEnc_SaveState(p->enc);  | 
145  | 16.6k  |   res = LzmaEnc_CodeOneMemBlock(p->enc, p->needInitState,  | 
146  | 16.6k  |       outBuf + lzHeaderSize, &packSize, LZMA2_PACK_SIZE_MAX, &unpackSize);  | 
147  |  |     | 
148  | 16.6k  |   PRF(printf("\npackSize = %7d unpackSize = %7d  ", packSize, unpackSize)); | 
149  |  |  | 
150  | 16.6k  |   if (unpackSize == 0)  | 
151  | 6.34k  |     return res;  | 
152  |  |  | 
153  | 10.3k  |   if (res == SZ_OK)  | 
154  | 10.3k  |     useCopyBlock = (packSize + 2 >= unpackSize || packSize > (1 << 16));  | 
155  | 0  |   else  | 
156  | 0  |   { | 
157  | 0  |     if (res != SZ_ERROR_OUTPUT_EOF)  | 
158  | 0  |       return res;  | 
159  | 0  |     res = SZ_OK;  | 
160  | 0  |     useCopyBlock = True;  | 
161  | 0  |   }  | 
162  |  |  | 
163  | 10.3k  |   if (useCopyBlock)  | 
164  | 3.34k  |   { | 
165  | 3.34k  |     size_t destPos = 0;  | 
166  | 3.34k  |     PRF(printf("################# COPY           ")); | 
167  |  |  | 
168  | 6.68k  |     while (unpackSize > 0)  | 
169  | 3.34k  |     { | 
170  | 3.34k  |       UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE;  | 
171  | 3.34k  |       if (packSizeLimit - destPos < u + 3)  | 
172  | 0  |         return SZ_ERROR_OUTPUT_EOF;  | 
173  | 3.34k  |       outBuf[destPos++] = (Byte)(p->srcPos == 0 ? LZMA2_CONTROL_COPY_RESET_DIC : LZMA2_CONTROL_COPY_NO_RESET);  | 
174  | 3.34k  |       outBuf[destPos++] = (Byte)((u - 1) >> 8);  | 
175  | 3.34k  |       outBuf[destPos++] = (Byte)(u - 1);  | 
176  | 3.34k  |       memcpy(outBuf + destPos, LzmaEnc_GetCurBuf(p->enc) - unpackSize, u);  | 
177  | 3.34k  |       unpackSize -= u;  | 
178  | 3.34k  |       destPos += u;  | 
179  | 3.34k  |       p->srcPos += u;  | 
180  |  |         | 
181  | 3.34k  |       if (outStream)  | 
182  | 3.34k  |       { | 
183  | 3.34k  |         *packSizeRes += destPos;  | 
184  | 3.34k  |         if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos)  | 
185  | 0  |           return SZ_ERROR_WRITE;  | 
186  | 3.34k  |         destPos = 0;  | 
187  | 3.34k  |       }  | 
188  | 0  |       else  | 
189  | 0  |         *packSizeRes = destPos;  | 
190  |  |       /* needInitState = True; */  | 
191  | 3.34k  |     }  | 
192  |  |       | 
193  | 3.34k  |     LzmaEnc_RestoreState(p->enc);  | 
194  | 3.34k  |     return SZ_OK;  | 
195  | 3.34k  |   }  | 
196  |  |  | 
197  | 6.99k  |   { | 
198  | 6.99k  |     size_t destPos = 0;  | 
199  | 6.99k  |     UInt32 u = unpackSize - 1;  | 
200  | 6.99k  |     UInt32 pm = (UInt32)(packSize - 1);  | 
201  | 6.99k  |     unsigned mode = (p->srcPos == 0) ? 3 : (p->needInitState ? (p->needInitProp ? 2 : 1) : 0);  | 
202  |  |  | 
203  | 6.99k  |     PRF(printf("               ")); | 
204  |  |  | 
205  | 6.99k  |     outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | ((u >> 16) & 0x1F));  | 
206  | 6.99k  |     outBuf[destPos++] = (Byte)(u >> 8);  | 
207  | 6.99k  |     outBuf[destPos++] = (Byte)u;  | 
208  | 6.99k  |     outBuf[destPos++] = (Byte)(pm >> 8);  | 
209  | 6.99k  |     outBuf[destPos++] = (Byte)pm;  | 
210  |  |       | 
211  | 6.99k  |     if (p->needInitProp)  | 
212  | 5.13k  |       outBuf[destPos++] = p->propsByte;  | 
213  |  |       | 
214  | 6.99k  |     p->needInitProp = False;  | 
215  | 6.99k  |     p->needInitState = False;  | 
216  | 6.99k  |     destPos += packSize;  | 
217  | 6.99k  |     p->srcPos += unpackSize;  | 
218  |  |  | 
219  | 6.99k  |     if (outStream)  | 
220  | 6.99k  |       if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos)  | 
221  | 0  |         return SZ_ERROR_WRITE;  | 
222  |  |       | 
223  | 6.99k  |     *packSizeRes = destPos;  | 
224  | 6.99k  |     return SZ_OK;  | 
225  | 6.99k  |   }  | 
226  | 6.99k  | }  | 
227  |  |  | 
228  |  |  | 
229  |  | /* ---------- Lzma2 Props ---------- */  | 
230  |  |  | 
231  |  | void Lzma2EncProps_Init(CLzma2EncProps *p)  | 
232  | 19.0k  | { | 
233  | 19.0k  |   LzmaEncProps_Init(&p->lzmaProps);  | 
234  | 19.0k  |   p->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO;  | 
235  | 19.0k  |   p->numBlockThreads_Reduced = -1;  | 
236  | 19.0k  |   p->numBlockThreads_Max = -1;  | 
237  | 19.0k  |   p->numTotalThreads = -1;  | 
238  | 19.0k  | }  | 
239  |  |  | 
240  |  | void Lzma2EncProps_Normalize(CLzma2EncProps *p)  | 
241  | 25.3k  | { | 
242  | 25.3k  |   UInt64 fileSize;  | 
243  | 25.3k  |   int t1, t1n, t2, t2r, t3;  | 
244  | 25.3k  |   { | 
245  | 25.3k  |     CLzmaEncProps lzmaProps = p->lzmaProps;  | 
246  | 25.3k  |     LzmaEncProps_Normalize(&lzmaProps);  | 
247  | 25.3k  |     t1n = lzmaProps.numThreads;  | 
248  | 25.3k  |   }  | 
249  |  |  | 
250  | 25.3k  |   t1 = p->lzmaProps.numThreads;  | 
251  | 25.3k  |   t2 = p->numBlockThreads_Max;  | 
252  | 25.3k  |   t3 = p->numTotalThreads;  | 
253  |  |  | 
254  | 25.3k  |   if (t2 > MTCODER__THREADS_MAX)  | 
255  | 0  |     t2 = MTCODER__THREADS_MAX;  | 
256  |  |  | 
257  | 25.3k  |   if (t3 <= 0)  | 
258  | 25.3k  |   { | 
259  | 25.3k  |     if (t2 <= 0)  | 
260  | 19.0k  |       t2 = 1;  | 
261  | 25.3k  |     t3 = t1n * t2;  | 
262  | 25.3k  |   }  | 
263  | 0  |   else if (t2 <= 0)  | 
264  | 0  |   { | 
265  | 0  |     t2 = t3 / t1n;  | 
266  | 0  |     if (t2 == 0)  | 
267  | 0  |     { | 
268  | 0  |       t1 = 1;  | 
269  | 0  |       t2 = t3;  | 
270  | 0  |     }  | 
271  | 0  |     if (t2 > MTCODER__THREADS_MAX)  | 
272  | 0  |       t2 = MTCODER__THREADS_MAX;  | 
273  | 0  |   }  | 
274  | 0  |   else if (t1 <= 0)  | 
275  | 0  |   { | 
276  | 0  |     t1 = t3 / t2;  | 
277  | 0  |     if (t1 == 0)  | 
278  | 0  |       t1 = 1;  | 
279  | 0  |   }  | 
280  | 0  |   else  | 
281  | 0  |     t3 = t1n * t2;  | 
282  |  |  | 
283  | 25.3k  |   p->lzmaProps.numThreads = t1;  | 
284  |  |  | 
285  | 25.3k  |   t2r = t2;  | 
286  |  |  | 
287  | 25.3k  |   fileSize = p->lzmaProps.reduceSize;  | 
288  |  |  | 
289  | 25.3k  |   if (   p->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID  | 
290  | 19.0k  |       && p->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO  | 
291  | 0  |       && (p->blockSize < fileSize || fileSize == (UInt64)(Int64)-1))  | 
292  | 0  |     p->lzmaProps.reduceSize = p->blockSize;  | 
293  |  |  | 
294  | 25.3k  |   LzmaEncProps_Normalize(&p->lzmaProps);  | 
295  |  |  | 
296  | 25.3k  |   p->lzmaProps.reduceSize = fileSize;  | 
297  |  |  | 
298  | 25.3k  |   t1 = p->lzmaProps.numThreads;  | 
299  |  |  | 
300  | 25.3k  |   if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID)  | 
301  | 6.34k  |   { | 
302  | 6.34k  |     t2r = t2 = 1;  | 
303  | 6.34k  |     t3 = t1;  | 
304  | 6.34k  |   }  | 
305  | 19.0k  |   else if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO && t2 <= 1)  | 
306  | 19.0k  |   { | 
307  |  |     /* if there is no block multi-threading, we use SOLID block */  | 
308  | 19.0k  |     p->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID;  | 
309  | 19.0k  |   }  | 
310  | 0  |   else  | 
311  | 0  |   { | 
312  | 0  |     if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO)  | 
313  | 0  |     { | 
314  | 0  |       const UInt32 kMinSize = (UInt32)1 << 20;  | 
315  | 0  |       const UInt32 kMaxSize = (UInt32)1 << 28;  | 
316  | 0  |       const UInt32 dictSize = p->lzmaProps.dictSize;  | 
317  | 0  |       UInt64 blockSize = (UInt64)dictSize << 2;  | 
318  | 0  |       if (blockSize < kMinSize) blockSize = kMinSize;  | 
319  | 0  |       if (blockSize > kMaxSize) blockSize = kMaxSize;  | 
320  | 0  |       if (blockSize < dictSize) blockSize = dictSize;  | 
321  | 0  |       blockSize += (kMinSize - 1);  | 
322  | 0  |       blockSize &= ~(UInt64)(kMinSize - 1);  | 
323  | 0  |       p->blockSize = blockSize;  | 
324  | 0  |     }  | 
325  |  |       | 
326  | 0  |     if (t2 > 1 && fileSize != (UInt64)(Int64)-1)  | 
327  | 0  |     { | 
328  | 0  |       UInt64 numBlocks = fileSize / p->blockSize;  | 
329  | 0  |       if (numBlocks * p->blockSize != fileSize)  | 
330  | 0  |         numBlocks++;  | 
331  | 0  |       if (numBlocks < (unsigned)t2)  | 
332  | 0  |       { | 
333  | 0  |         t2r = (unsigned)numBlocks;  | 
334  | 0  |         if (t2r == 0)  | 
335  | 0  |           t2r = 1;  | 
336  | 0  |         t3 = t1 * t2r;  | 
337  | 0  |       }  | 
338  | 0  |     }  | 
339  | 0  |   }  | 
340  |  |     | 
341  | 25.3k  |   p->numBlockThreads_Max = t2;  | 
342  | 25.3k  |   p->numBlockThreads_Reduced = t2r;  | 
343  | 25.3k  |   p->numTotalThreads = t3;  | 
344  | 25.3k  | }  | 
345  |  |  | 
346  |  |  | 
347  |  | static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)  | 
348  | 16.6k  | { | 
349  | 16.6k  |   return (p && ICompressProgress_Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;  | 
350  | 16.6k  | }  | 
351  |  |  | 
352  |  |  | 
353  |  | /* ---------- Lzma2 ---------- */  | 
354  |  |  | 
355  |  | typedef struct  | 
356  |  | { | 
357  |  |   Byte propEncoded;  | 
358  |  |   CLzma2EncProps props;  | 
359  |  |   UInt64 expectedDataSize;  | 
360  |  |     | 
361  |  |   Byte *tempBufLzma;  | 
362  |  |  | 
363  |  |   ISzAllocPtr alloc;  | 
364  |  |   ISzAllocPtr allocBig;  | 
365  |  |  | 
366  |  |   CLzma2EncInt coders[MTCODER__THREADS_MAX];  | 
367  |  |  | 
368  |  |   #ifndef _7ZIP_ST  | 
369  |  |     | 
370  |  |   ISeqOutStream *outStream;  | 
371  |  |   Byte *outBuf;  | 
372  |  |   size_t outBuf_Rem;   /* remainder in outBuf */  | 
373  |  |  | 
374  |  |   size_t outBufSize;   /* size of allocated outBufs[i] */  | 
375  |  |   size_t outBufsDataSizes[MTCODER__BLOCKS_MAX];  | 
376  |  |   BoolInt mtCoder_WasConstructed;  | 
377  |  |   CMtCoder mtCoder;  | 
378  |  |   Byte *outBufs[MTCODER__BLOCKS_MAX];  | 
379  |  |  | 
380  |  |   #endif  | 
381  |  |  | 
382  |  | } CLzma2Enc;  | 
383  |  |  | 
384  |  |  | 
385  |  |  | 
386  |  | CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig)  | 
387  | 6.34k  | { | 
388  | 6.34k  |   CLzma2Enc *p = (CLzma2Enc *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Enc));  | 
389  | 6.34k  |   if (!p)  | 
390  | 0  |     return NULL;  | 
391  | 6.34k  |   Lzma2EncProps_Init(&p->props);  | 
392  | 6.34k  |   Lzma2EncProps_Normalize(&p->props);  | 
393  | 6.34k  |   p->expectedDataSize = (UInt64)(Int64)-1;  | 
394  | 6.34k  |   p->tempBufLzma = NULL;  | 
395  | 6.34k  |   p->alloc = alloc;  | 
396  | 6.34k  |   p->allocBig = allocBig;  | 
397  | 6.34k  |   { | 
398  | 6.34k  |     unsigned i;  | 
399  | 12.6k  |     for (i = 0; i < MTCODER__THREADS_MAX; i++)  | 
400  | 6.34k  |       p->coders[i].enc = NULL;  | 
401  | 6.34k  |   }  | 
402  |  |     | 
403  |  |   #ifndef _7ZIP_ST  | 
404  |  |   p->mtCoder_WasConstructed = False;  | 
405  |  |   { | 
406  |  |     unsigned i;  | 
407  |  |     for (i = 0; i < MTCODER__BLOCKS_MAX; i++)  | 
408  |  |       p->outBufs[i] = NULL;  | 
409  |  |     p->outBufSize = 0;  | 
410  |  |   }  | 
411  |  |   #endif  | 
412  |  |  | 
413  | 6.34k  |   return p;  | 
414  | 6.34k  | }  | 
415  |  |  | 
416  |  |  | 
417  |  | #ifndef _7ZIP_ST  | 
418  |  |  | 
419  |  | static void Lzma2Enc_FreeOutBufs(CLzma2Enc *p)  | 
420  |  | { | 
421  |  |   unsigned i;  | 
422  |  |   for (i = 0; i < MTCODER__BLOCKS_MAX; i++)  | 
423  |  |     if (p->outBufs[i])  | 
424  |  |     { | 
425  |  |       ISzAlloc_Free(p->alloc, p->outBufs[i]);  | 
426  |  |       p->outBufs[i] = NULL;  | 
427  |  |     }  | 
428  |  |   p->outBufSize = 0;  | 
429  |  | }  | 
430  |  |  | 
431  |  | #endif  | 
432  |  |  | 
433  |  |  | 
434  |  | void Lzma2Enc_Destroy(CLzma2EncHandle pp)  | 
435  | 6.34k  | { | 
436  | 6.34k  |   CLzma2Enc *p = (CLzma2Enc *)pp;  | 
437  | 6.34k  |   unsigned i;  | 
438  | 12.6k  |   for (i = 0; i < MTCODER__THREADS_MAX; i++)  | 
439  | 6.34k  |   { | 
440  | 6.34k  |     CLzma2EncInt *t = &p->coders[i];  | 
441  | 6.34k  |     if (t->enc)  | 
442  | 6.34k  |     { | 
443  | 6.34k  |       LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig);  | 
444  | 6.34k  |       t->enc = NULL;  | 
445  | 6.34k  |     }  | 
446  | 6.34k  |   }  | 
447  |  |  | 
448  |  |  | 
449  |  |   #ifndef _7ZIP_ST  | 
450  |  |   if (p->mtCoder_WasConstructed)  | 
451  |  |   { | 
452  |  |     MtCoder_Destruct(&p->mtCoder);  | 
453  |  |     p->mtCoder_WasConstructed = False;  | 
454  |  |   }  | 
455  |  |   Lzma2Enc_FreeOutBufs(p);  | 
456  |  |   #endif  | 
457  |  |  | 
458  | 6.34k  |   ISzAlloc_Free(p->alloc, p->tempBufLzma);  | 
459  | 6.34k  |   p->tempBufLzma = NULL;  | 
460  |  |  | 
461  | 6.34k  |   ISzAlloc_Free(p->alloc, pp);  | 
462  | 6.34k  | }  | 
463  |  |  | 
464  |  |  | 
465  |  | SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props)  | 
466  | 6.34k  | { | 
467  | 6.34k  |   CLzma2Enc *p = (CLzma2Enc *)pp;  | 
468  | 6.34k  |   CLzmaEncProps lzmaProps = props->lzmaProps;  | 
469  | 6.34k  |   LzmaEncProps_Normalize(&lzmaProps);  | 
470  | 6.34k  |   if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX)  | 
471  | 0  |     return SZ_ERROR_PARAM;  | 
472  | 6.34k  |   p->props = *props;  | 
473  | 6.34k  |   Lzma2EncProps_Normalize(&p->props);  | 
474  | 6.34k  |   return SZ_OK;  | 
475  | 6.34k  | }  | 
476  |  |  | 
477  |  |  | 
478  |  | void Lzma2Enc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize)  | 
479  | 0  | { | 
480  | 0  |   CLzma2Enc *p = (CLzma2Enc *)pp;  | 
481  | 0  |   p->expectedDataSize = expectedDataSiize;  | 
482  | 0  | }  | 
483  |  |  | 
484  |  |  | 
485  |  | Byte Lzma2Enc_WriteProperties(CLzma2EncHandle pp)  | 
486  | 6.34k  | { | 
487  | 6.34k  |   CLzma2Enc *p = (CLzma2Enc *)pp;  | 
488  | 6.34k  |   unsigned i;  | 
489  | 6.34k  |   UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps);  | 
490  | 158k  |   for (i = 0; i < 40; i++)  | 
491  | 158k  |     if (dicSize <= LZMA2_DIC_SIZE_FROM_PROP(i))  | 
492  | 6.34k  |       break;  | 
493  | 6.34k  |   return (Byte)i;  | 
494  | 6.34k  | }  | 
495  |  |  | 
496  |  |  | 
497  |  | static SRes Lzma2Enc_EncodeMt1(  | 
498  |  |     CLzma2Enc *me,  | 
499  |  |     CLzma2EncInt *p,  | 
500  |  |     ISeqOutStream *outStream,  | 
501  |  |     Byte *outBuf, size_t *outBufSize,  | 
502  |  |     ISeqInStream *inStream,  | 
503  |  |     const Byte *inData, size_t inDataSize,  | 
504  |  |     int finished,  | 
505  |  |     ICompressProgress *progress)  | 
506  | 6.34k  | { | 
507  | 6.34k  |   UInt64 unpackTotal = 0;  | 
508  | 6.34k  |   UInt64 packTotal = 0;  | 
509  | 6.34k  |   size_t outLim = 0;  | 
510  | 6.34k  |   CLimitedSeqInStream limitedInStream;  | 
511  |  |  | 
512  | 6.34k  |   if (outBuf)  | 
513  | 0  |   { | 
514  | 0  |     outLim = *outBufSize;  | 
515  | 0  |     *outBufSize = 0;  | 
516  | 0  |   }  | 
517  |  |  | 
518  | 6.34k  |   if (!p->enc)  | 
519  | 6.34k  |   { | 
520  | 6.34k  |     p->propsAreSet = False;  | 
521  | 6.34k  |     p->enc = LzmaEnc_Create(me->alloc);  | 
522  | 6.34k  |     if (!p->enc)  | 
523  | 0  |       return SZ_ERROR_MEM;  | 
524  | 6.34k  |   }  | 
525  |  |  | 
526  | 6.34k  |   limitedInStream.realStream = inStream;  | 
527  | 6.34k  |   if (inStream)  | 
528  | 6.34k  |   { | 
529  | 6.34k  |     limitedInStream.vt.Read = LimitedSeqInStream_Read;  | 
530  | 6.34k  |   }  | 
531  |  |     | 
532  | 6.34k  |   if (!outBuf)  | 
533  | 6.34k  |   { | 
534  |  |     // outStream version works only in one thread. So we use CLzma2Enc::tempBufLzma  | 
535  | 6.34k  |     if (!me->tempBufLzma)  | 
536  | 6.34k  |     { | 
537  | 6.34k  |       me->tempBufLzma = (Byte *)ISzAlloc_Alloc(me->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);  | 
538  | 6.34k  |       if (!me->tempBufLzma)  | 
539  | 0  |         return SZ_ERROR_MEM;  | 
540  | 6.34k  |     }  | 
541  | 6.34k  |   }  | 
542  |  |  | 
543  | 6.34k  |   RINOK(Lzma2EncInt_InitStream(p, &me->props));  | 
544  |  |  | 
545  | 6.34k  |   for (;;)  | 
546  | 6.34k  |   { | 
547  | 6.34k  |     SRes res = SZ_OK;  | 
548  | 6.34k  |     size_t inSizeCur = 0;  | 
549  |  |  | 
550  | 6.34k  |     Lzma2EncInt_InitBlock(p);  | 
551  |  |       | 
552  | 6.34k  |     LimitedSeqInStream_Init(&limitedInStream);  | 
553  | 6.34k  |     limitedInStream.limit = me->props.blockSize;  | 
554  |  |  | 
555  | 6.34k  |     if (inStream)  | 
556  | 6.34k  |     { | 
557  | 6.34k  |       UInt64 expected = (UInt64)(Int64)-1;  | 
558  |  |       // inStream version works only in one thread. So we use CLzma2Enc::expectedDataSize  | 
559  | 6.34k  |       if (me->expectedDataSize != (UInt64)(Int64)-1  | 
560  | 0  |           && me->expectedDataSize >= unpackTotal)  | 
561  | 0  |         expected = me->expectedDataSize - unpackTotal;  | 
562  | 6.34k  |       if (me->props.blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID  | 
563  | 0  |           && expected > me->props.blockSize)  | 
564  | 0  |         expected = (size_t)me->props.blockSize;  | 
565  |  |  | 
566  | 6.34k  |       LzmaEnc_SetDataSize(p->enc, expected);  | 
567  |  |  | 
568  | 6.34k  |       RINOK(LzmaEnc_PrepareForLzma2(p->enc,  | 
569  | 6.34k  |           &limitedInStream.vt,  | 
570  | 6.34k  |           LZMA2_KEEP_WINDOW_SIZE,  | 
571  | 6.34k  |           me->alloc,  | 
572  | 6.34k  |           me->allocBig));  | 
573  | 6.34k  |     }  | 
574  | 0  |     else  | 
575  | 0  |     { | 
576  | 0  |       inSizeCur = inDataSize - (size_t)unpackTotal;  | 
577  | 0  |       if (me->props.blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID  | 
578  | 0  |           && inSizeCur > me->props.blockSize)  | 
579  | 0  |         inSizeCur = (size_t)me->props.blockSize;  | 
580  |  |       | 
581  |  |       // LzmaEnc_SetDataSize(p->enc, inSizeCur);  | 
582  |  |         | 
583  | 0  |       RINOK(LzmaEnc_MemPrepare(p->enc,  | 
584  | 0  |           inData + (size_t)unpackTotal, inSizeCur,  | 
585  | 0  |           LZMA2_KEEP_WINDOW_SIZE,  | 
586  | 0  |           me->alloc,  | 
587  | 0  |           me->allocBig));  | 
588  | 0  |     }  | 
589  |  |  | 
590  | 6.34k  |     for (;;)  | 
591  | 16.6k  |     { | 
592  | 16.6k  |       size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;  | 
593  | 16.6k  |       if (outBuf)  | 
594  | 0  |         packSize = outLim - (size_t)packTotal;  | 
595  |  |         | 
596  | 16.6k  |       res = Lzma2EncInt_EncodeSubblock(p,  | 
597  | 16.6k  |           outBuf ? outBuf + (size_t)packTotal : me->tempBufLzma, &packSize,  | 
598  | 16.6k  |           outBuf ? NULL : outStream);  | 
599  |  |         | 
600  | 16.6k  |       if (res != SZ_OK)  | 
601  | 0  |         break;  | 
602  |  |  | 
603  | 16.6k  |       packTotal += packSize;  | 
604  | 16.6k  |       if (outBuf)  | 
605  | 0  |         *outBufSize = (size_t)packTotal;  | 
606  |  |         | 
607  | 16.6k  |       res = Progress(progress, unpackTotal + p->srcPos, packTotal);  | 
608  | 16.6k  |       if (res != SZ_OK)  | 
609  | 0  |         break;  | 
610  |  |  | 
611  |  |       /*  | 
612  |  |       if (LzmaEnc_GetNumAvailableBytes(p->enc) == 0)  | 
613  |  |         break;  | 
614  |  |       */  | 
615  |  |  | 
616  | 16.6k  |       if (packSize == 0)  | 
617  | 6.34k  |         break;  | 
618  | 16.6k  |     }  | 
619  |  |       | 
620  | 6.34k  |     LzmaEnc_Finish(p->enc);  | 
621  |  |       | 
622  | 6.34k  |     unpackTotal += p->srcPos;  | 
623  |  |       | 
624  | 6.34k  |     RINOK(res);  | 
625  |  |  | 
626  | 6.34k  |     if (p->srcPos != (inStream ? limitedInStream.processed : inSizeCur))  | 
627  | 0  |       return SZ_ERROR_FAIL;  | 
628  |  |       | 
629  | 6.34k  |     if (inStream ? limitedInStream.finished : (unpackTotal == inDataSize))  | 
630  | 6.34k  |     { | 
631  | 6.34k  |       if (finished)  | 
632  | 6.34k  |       { | 
633  | 6.34k  |         if (outBuf)  | 
634  | 0  |         { | 
635  | 0  |           size_t destPos = *outBufSize;  | 
636  | 0  |           if (destPos >= outLim)  | 
637  | 0  |             return SZ_ERROR_OUTPUT_EOF;  | 
638  | 0  |           outBuf[destPos] = 0;  | 
639  | 0  |           *outBufSize = destPos + 1;  | 
640  | 0  |         }  | 
641  | 6.34k  |         else  | 
642  | 6.34k  |         { | 
643  | 6.34k  |           Byte b = 0;  | 
644  | 6.34k  |           if (ISeqOutStream_Write(outStream, &b, 1) != 1)  | 
645  | 0  |             return SZ_ERROR_WRITE;  | 
646  | 6.34k  |         }  | 
647  | 6.34k  |       }  | 
648  | 6.34k  |       return SZ_OK;  | 
649  | 6.34k  |     }  | 
650  | 6.34k  |   }  | 
651  | 6.34k  | }  | 
652  |  |  | 
653  |  |  | 
654  |  |  | 
655  |  | #ifndef _7ZIP_ST  | 
656  |  |  | 
657  |  | static SRes Lzma2Enc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned outBufIndex,  | 
658  |  |     const Byte *src, size_t srcSize, int finished)  | 
659  |  | { | 
660  |  |   CLzma2Enc *me = (CLzma2Enc *)pp;  | 
661  |  |   size_t destSize = me->outBufSize;  | 
662  |  |   SRes res;  | 
663  |  |   CMtProgressThunk progressThunk;  | 
664  |  |  | 
665  |  |   Byte *dest = me->outBufs[outBufIndex];  | 
666  |  |  | 
667  |  |   me->outBufsDataSizes[outBufIndex] = 0;  | 
668  |  |  | 
669  |  |   if (!dest)  | 
670  |  |   { | 
671  |  |     dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize);  | 
672  |  |     if (!dest)  | 
673  |  |       return SZ_ERROR_MEM;  | 
674  |  |     me->outBufs[outBufIndex] = dest;  | 
675  |  |   }  | 
676  |  |  | 
677  |  |   MtProgressThunk_CreateVTable(&progressThunk);  | 
678  |  |   progressThunk.mtProgress = &me->mtCoder.mtProgress;  | 
679  |  |   progressThunk.inSize = 0;  | 
680  |  |   progressThunk.outSize = 0;  | 
681  |  |  | 
682  |  |   res = Lzma2Enc_EncodeMt1(me,  | 
683  |  |       &me->coders[coderIndex],  | 
684  |  |       NULL, dest, &destSize,  | 
685  |  |       NULL, src, srcSize,  | 
686  |  |       finished,  | 
687  |  |       &progressThunk.vt);  | 
688  |  |  | 
689  |  |   me->outBufsDataSizes[outBufIndex] = destSize;  | 
690  |  |  | 
691  |  |   return res;  | 
692  |  | }  | 
693  |  |  | 
694  |  |  | 
695  |  | static SRes Lzma2Enc_MtCallback_Write(void *pp, unsigned outBufIndex)  | 
696  |  | { | 
697  |  |   CLzma2Enc *me = (CLzma2Enc *)pp;  | 
698  |  |   size_t size = me->outBufsDataSizes[outBufIndex];  | 
699  |  |   const Byte *data = me->outBufs[outBufIndex];  | 
700  |  |     | 
701  |  |   if (me->outStream)  | 
702  |  |     return ISeqOutStream_Write(me->outStream, data, size) == size ? SZ_OK : SZ_ERROR_WRITE;  | 
703  |  |     | 
704  |  |   if (size > me->outBuf_Rem)  | 
705  |  |     return SZ_ERROR_OUTPUT_EOF;  | 
706  |  |   memcpy(me->outBuf, data, size);  | 
707  |  |   me->outBuf_Rem -= size;  | 
708  |  |   me->outBuf += size;  | 
709  |  |   return SZ_OK;  | 
710  |  | }  | 
711  |  |  | 
712  |  | #endif  | 
713  |  |  | 
714  |  |  | 
715  |  |  | 
716  |  | SRes Lzma2Enc_Encode2(CLzma2EncHandle pp,  | 
717  |  |     ISeqOutStream *outStream,  | 
718  |  |     Byte *outBuf, size_t *outBufSize,  | 
719  |  |     ISeqInStream *inStream,  | 
720  |  |     const Byte *inData, size_t inDataSize,  | 
721  |  |     ICompressProgress *progress)  | 
722  | 6.34k  | { | 
723  | 6.34k  |   CLzma2Enc *p = (CLzma2Enc *)pp;  | 
724  |  |  | 
725  | 6.34k  |   if (inStream && inData)  | 
726  | 0  |     return SZ_ERROR_PARAM;  | 
727  |  |  | 
728  | 6.34k  |   if (outStream && outBuf)  | 
729  | 0  |     return SZ_ERROR_PARAM;  | 
730  |  |  | 
731  | 6.34k  |   { | 
732  | 6.34k  |     unsigned i;  | 
733  | 12.6k  |     for (i = 0; i < MTCODER__THREADS_MAX; i++)  | 
734  | 6.34k  |       p->coders[i].propsAreSet = False;  | 
735  | 6.34k  |   }  | 
736  |  |  | 
737  |  |   #ifndef _7ZIP_ST  | 
738  |  |     | 
739  |  |   if (p->props.numBlockThreads_Reduced > 1)  | 
740  |  |   { | 
741  |  |     IMtCoderCallback2 vt;  | 
742  |  |  | 
743  |  |     if (!p->mtCoder_WasConstructed)  | 
744  |  |     { | 
745  |  |       p->mtCoder_WasConstructed = True;  | 
746  |  |       MtCoder_Construct(&p->mtCoder);  | 
747  |  |     }  | 
748  |  |  | 
749  |  |     vt.Code = Lzma2Enc_MtCallback_Code;  | 
750  |  |     vt.Write = Lzma2Enc_MtCallback_Write;  | 
751  |  |  | 
752  |  |     p->outStream = outStream;  | 
753  |  |     p->outBuf = NULL;  | 
754  |  |     p->outBuf_Rem = 0;  | 
755  |  |     if (!outStream)  | 
756  |  |     { | 
757  |  |       p->outBuf = outBuf;  | 
758  |  |       p->outBuf_Rem = *outBufSize;  | 
759  |  |       *outBufSize = 0;  | 
760  |  |     }  | 
761  |  |  | 
762  |  |     p->mtCoder.allocBig = p->allocBig;  | 
763  |  |     p->mtCoder.progress = progress;  | 
764  |  |     p->mtCoder.inStream = inStream;  | 
765  |  |     p->mtCoder.inData = inData;  | 
766  |  |     p->mtCoder.inDataSize = inDataSize;  | 
767  |  |     p->mtCoder.mtCallback = &vt;  | 
768  |  |     p->mtCoder.mtCallbackObject = p;  | 
769  |  |  | 
770  |  |     p->mtCoder.blockSize = (size_t)p->props.blockSize;  | 
771  |  |     if (p->mtCoder.blockSize != p->props.blockSize)  | 
772  |  |       return SZ_ERROR_PARAM; /* SZ_ERROR_MEM */  | 
773  |  |  | 
774  |  |     { | 
775  |  |       size_t destBlockSize = p->mtCoder.blockSize + (p->mtCoder.blockSize >> 10) + 16;  | 
776  |  |       if (destBlockSize < p->mtCoder.blockSize)  | 
777  |  |         return SZ_ERROR_PARAM;  | 
778  |  |       if (p->outBufSize != destBlockSize)  | 
779  |  |         Lzma2Enc_FreeOutBufs(p);  | 
780  |  |       p->outBufSize = destBlockSize;  | 
781  |  |     }  | 
782  |  |  | 
783  |  |     p->mtCoder.numThreadsMax = p->props.numBlockThreads_Max;  | 
784  |  |     p->mtCoder.expectedDataSize = p->expectedDataSize;  | 
785  |  |       | 
786  |  |     { | 
787  |  |       SRes res = MtCoder_Code(&p->mtCoder);  | 
788  |  |       if (!outStream)  | 
789  |  |         *outBufSize = p->outBuf - outBuf;  | 
790  |  |       return res;  | 
791  |  |     }  | 
792  |  |   }  | 
793  |  |  | 
794  |  |   #endif  | 
795  |  |  | 
796  |  |  | 
797  | 6.34k  |   return Lzma2Enc_EncodeMt1(p,  | 
798  | 6.34k  |       &p->coders[0],  | 
799  | 6.34k  |       outStream, outBuf, outBufSize,  | 
800  | 6.34k  |       inStream, inData, inDataSize,  | 
801  | 6.34k  |       True, /* finished */  | 
802  | 6.34k  |       progress);  | 
803  | 6.34k  | }  |