Lzma2Enc.c 19 KB

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