Lzma2Enc.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807
  1. /* Lzma2Enc.c -- LZMA2 Encoder
  2. : Igor Pavlov : Public domain */
  3. #include "Precomp.h"
  4. #include <string.h>
  5. /* #define Z7_ST */
  6. #include "Lzma2Enc.h"
  7. #ifndef Z7_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. ISeqInStreamPtr 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(ISeqInStreamPtr pp, void *data, size_t *size)
  40. {
  41. Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CLimitedSeqInStream)
  42. size_t size2 = *size;
  43. SRes res = SZ_OK;
  44. if (p->limit != (UInt64)(Int64)-1)
  45. {
  46. const 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 p, ISeqInStreamPtr inStream, UInt32 keepWindowSize,
  89. ISzAllocPtr alloc, ISzAllocPtr allocBig);
  90. SRes LzmaEnc_MemPrepare(CLzmaEncHandle p, const Byte *src, SizeT srcLen,
  91. UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig);
  92. SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle p, BoolInt reInit,
  93. Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);
  94. const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle p);
  95. void LzmaEnc_Finish(CLzmaEncHandle p);
  96. void LzmaEnc_SaveState(CLzmaEncHandle p);
  97. void LzmaEnc_RestoreState(CLzmaEncHandle p);
  98. /*
  99. UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle p);
  100. */
  101. static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
  102. size_t *packSizeRes, ISeqOutStreamPtr 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. const 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. const UInt32 u = unpackSize - 1;
  162. const UInt32 pm = (UInt32)(packSize - 1);
  163. const 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. p->numThreadGroups = 0;
  192. }
  193. void Lzma2EncProps_Normalize(CLzma2EncProps *p)
  194. {
  195. UInt64 fileSize;
  196. int t1, t1n, t2, t2r, t3;
  197. {
  198. CLzmaEncProps lzmaProps = p->lzmaProps;
  199. LzmaEncProps_Normalize(&lzmaProps);
  200. t1n = lzmaProps.numThreads;
  201. }
  202. t1 = p->lzmaProps.numThreads;
  203. t2 = p->numBlockThreads_Max;
  204. t3 = p->numTotalThreads;
  205. if (t2 > MTCODER_THREADS_MAX)
  206. t2 = MTCODER_THREADS_MAX;
  207. if (t3 <= 0)
  208. {
  209. if (t2 <= 0)
  210. t2 = 1;
  211. t3 = t1n * t2;
  212. }
  213. else if (t2 <= 0)
  214. {
  215. t2 = t3 / t1n;
  216. if (t2 == 0)
  217. {
  218. t1 = 1;
  219. t2 = t3;
  220. }
  221. if (t2 > MTCODER_THREADS_MAX)
  222. t2 = MTCODER_THREADS_MAX;
  223. }
  224. else if (t1 <= 0)
  225. {
  226. t1 = t3 / t2;
  227. if (t1 == 0)
  228. t1 = 1;
  229. }
  230. else
  231. t3 = t1n * t2;
  232. p->lzmaProps.numThreads = t1;
  233. t2r = t2;
  234. fileSize = p->lzmaProps.reduceSize;
  235. if ( p->blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID
  236. && p->blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO
  237. && (p->blockSize < fileSize || fileSize == (UInt64)(Int64)-1))
  238. p->lzmaProps.reduceSize = p->blockSize;
  239. LzmaEncProps_Normalize(&p->lzmaProps);
  240. p->lzmaProps.reduceSize = fileSize;
  241. t1 = p->lzmaProps.numThreads;
  242. if (p->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID)
  243. {
  244. t2r = t2 = 1;
  245. t3 = t1;
  246. }
  247. else if (p->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO && t2 <= 1)
  248. {
  249. /* if there is no block multi-threading, we use SOLID block */
  250. p->blockSize = LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID;
  251. }
  252. else
  253. {
  254. if (p->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO)
  255. {
  256. const UInt32 kMinSize = (UInt32)1 << 20;
  257. const UInt32 kMaxSize = (UInt32)1 << 28;
  258. const UInt32 dictSize = p->lzmaProps.dictSize;
  259. UInt64 blockSize = (UInt64)dictSize << 2;
  260. if (blockSize < kMinSize) blockSize = kMinSize;
  261. if (blockSize > kMaxSize) blockSize = kMaxSize;
  262. if (blockSize < dictSize) blockSize = dictSize;
  263. blockSize += (kMinSize - 1);
  264. blockSize &= ~(UInt64)(kMinSize - 1);
  265. p->blockSize = blockSize;
  266. }
  267. if (t2 > 1 && fileSize != (UInt64)(Int64)-1)
  268. {
  269. UInt64 numBlocks = fileSize / p->blockSize;
  270. if (numBlocks * p->blockSize != fileSize)
  271. numBlocks++;
  272. if (numBlocks < (unsigned)t2)
  273. {
  274. t2r = (int)numBlocks;
  275. if (t2r == 0)
  276. t2r = 1;
  277. t3 = t1 * t2r;
  278. }
  279. }
  280. }
  281. p->numBlockThreads_Max = t2;
  282. p->numBlockThreads_Reduced = t2r;
  283. p->numTotalThreads = t3;
  284. }
  285. static SRes Progress(ICompressProgressPtr p, UInt64 inSize, UInt64 outSize)
  286. {
  287. return (p && ICompressProgress_Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
  288. }
  289. /* ---------- Lzma2 ---------- */
  290. struct CLzma2Enc
  291. {
  292. Byte propEncoded;
  293. CLzma2EncProps props;
  294. UInt64 expectedDataSize;
  295. Byte *tempBufLzma;
  296. ISzAllocPtr alloc;
  297. ISzAllocPtr allocBig;
  298. CLzma2EncInt coders[MTCODER_THREADS_MAX];
  299. #ifndef Z7_ST
  300. ISeqOutStreamPtr outStream;
  301. Byte *outBuf;
  302. size_t outBuf_Rem; /* remainder in outBuf */
  303. size_t outBufSize; /* size of allocated outBufs[i] */
  304. size_t outBufsDataSizes[MTCODER_BLOCKS_MAX];
  305. BoolInt mtCoder_WasConstructed;
  306. CMtCoder mtCoder;
  307. Byte *outBufs[MTCODER_BLOCKS_MAX];
  308. #endif
  309. };
  310. CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig)
  311. {
  312. CLzma2Enc *p = (CLzma2Enc *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Enc));
  313. if (!p)
  314. return NULL;
  315. Lzma2EncProps_Init(&p->props);
  316. Lzma2EncProps_Normalize(&p->props);
  317. p->expectedDataSize = (UInt64)(Int64)-1;
  318. p->tempBufLzma = NULL;
  319. p->alloc = alloc;
  320. p->allocBig = allocBig;
  321. {
  322. unsigned i;
  323. for (i = 0; i < MTCODER_THREADS_MAX; i++)
  324. p->coders[i].enc = NULL;
  325. }
  326. #ifndef Z7_ST
  327. p->mtCoder_WasConstructed = False;
  328. {
  329. unsigned i;
  330. for (i = 0; i < MTCODER_BLOCKS_MAX; i++)
  331. p->outBufs[i] = NULL;
  332. p->outBufSize = 0;
  333. }
  334. #endif
  335. return (CLzma2EncHandle)p;
  336. }
  337. #ifndef Z7_ST
  338. static void Lzma2Enc_FreeOutBufs(CLzma2Enc *p)
  339. {
  340. unsigned i;
  341. for (i = 0; i < MTCODER_BLOCKS_MAX; i++)
  342. if (p->outBufs[i])
  343. {
  344. ISzAlloc_Free(p->alloc, p->outBufs[i]);
  345. p->outBufs[i] = NULL;
  346. }
  347. p->outBufSize = 0;
  348. }
  349. #endif
  350. // #define GET_CLzma2Enc_p CLzma2Enc *p = (CLzma2Enc *)(void *)p;
  351. void Lzma2Enc_Destroy(CLzma2EncHandle p)
  352. {
  353. // GET_CLzma2Enc_p
  354. unsigned i;
  355. for (i = 0; i < MTCODER_THREADS_MAX; i++)
  356. {
  357. CLzma2EncInt *t = &p->coders[i];
  358. if (t->enc)
  359. {
  360. LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig);
  361. t->enc = NULL;
  362. }
  363. }
  364. #ifndef Z7_ST
  365. if (p->mtCoder_WasConstructed)
  366. {
  367. MtCoder_Destruct(&p->mtCoder);
  368. p->mtCoder_WasConstructed = False;
  369. }
  370. Lzma2Enc_FreeOutBufs(p);
  371. #endif
  372. ISzAlloc_Free(p->alloc, p->tempBufLzma);
  373. p->tempBufLzma = NULL;
  374. ISzAlloc_Free(p->alloc, p);
  375. }
  376. SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props)
  377. {
  378. // GET_CLzma2Enc_p
  379. CLzmaEncProps lzmaProps = props->lzmaProps;
  380. LzmaEncProps_Normalize(&lzmaProps);
  381. if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX)
  382. return SZ_ERROR_PARAM;
  383. p->props = *props;
  384. Lzma2EncProps_Normalize(&p->props);
  385. return SZ_OK;
  386. }
  387. void Lzma2Enc_SetDataSize(CLzma2EncHandle p, UInt64 expectedDataSiize)
  388. {
  389. // GET_CLzma2Enc_p
  390. p->expectedDataSize = expectedDataSiize;
  391. }
  392. Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p)
  393. {
  394. // GET_CLzma2Enc_p
  395. unsigned i;
  396. UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps);
  397. for (i = 0; i < 40; i++)
  398. if (dicSize <= LZMA2_DIC_SIZE_FROM_PROP(i))
  399. break;
  400. return (Byte)i;
  401. }
  402. static SRes Lzma2Enc_EncodeMt1(
  403. CLzma2Enc *me,
  404. CLzma2EncInt *p,
  405. ISeqOutStreamPtr outStream,
  406. Byte *outBuf, size_t *outBufSize,
  407. ISeqInStreamPtr inStream,
  408. const Byte *inData, size_t inDataSize,
  409. int finished,
  410. ICompressProgressPtr progress)
  411. {
  412. UInt64 unpackTotal = 0;
  413. UInt64 packTotal = 0;
  414. size_t outLim = 0;
  415. CLimitedSeqInStream limitedInStream;
  416. if (outBuf)
  417. {
  418. outLim = *outBufSize;
  419. *outBufSize = 0;
  420. }
  421. if (!p->enc)
  422. {
  423. p->propsAreSet = False;
  424. p->enc = LzmaEnc_Create(me->alloc);
  425. if (!p->enc)
  426. return SZ_ERROR_MEM;
  427. }
  428. limitedInStream.realStream = inStream;
  429. if (inStream)
  430. {
  431. limitedInStream.vt.Read = LimitedSeqInStream_Read;
  432. }
  433. if (!outBuf)
  434. {
  435. // outStream version works only in one thread. So we use CLzma2Enc::tempBufLzma
  436. if (!me->tempBufLzma)
  437. {
  438. me->tempBufLzma = (Byte *)ISzAlloc_Alloc(me->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);
  439. if (!me->tempBufLzma)
  440. return SZ_ERROR_MEM;
  441. }
  442. }
  443. RINOK(Lzma2EncInt_InitStream(p, &me->props))
  444. for (;;)
  445. {
  446. SRes res = SZ_OK;
  447. SizeT inSizeCur = 0;
  448. Lzma2EncInt_InitBlock(p);
  449. LimitedSeqInStream_Init(&limitedInStream);
  450. limitedInStream.limit = me->props.blockSize;
  451. if (inStream)
  452. {
  453. UInt64 expected = (UInt64)(Int64)-1;
  454. // inStream version works only in one thread. So we use CLzma2Enc::expectedDataSize
  455. if (me->expectedDataSize != (UInt64)(Int64)-1
  456. && me->expectedDataSize >= unpackTotal)
  457. expected = me->expectedDataSize - unpackTotal;
  458. if (me->props.blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID
  459. && expected > me->props.blockSize)
  460. expected = (size_t)me->props.blockSize;
  461. LzmaEnc_SetDataSize(p->enc, expected);
  462. RINOK(LzmaEnc_PrepareForLzma2(p->enc,
  463. &limitedInStream.vt,
  464. LZMA2_KEEP_WINDOW_SIZE,
  465. me->alloc,
  466. me->allocBig))
  467. }
  468. else
  469. {
  470. inSizeCur = (SizeT)(inDataSize - (size_t)unpackTotal);
  471. if (me->props.blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID
  472. && inSizeCur > me->props.blockSize)
  473. inSizeCur = (SizeT)(size_t)me->props.blockSize;
  474. // LzmaEnc_SetDataSize(p->enc, inSizeCur);
  475. RINOK(LzmaEnc_MemPrepare(p->enc,
  476. inData + (size_t)unpackTotal, inSizeCur,
  477. LZMA2_KEEP_WINDOW_SIZE,
  478. me->alloc,
  479. me->allocBig))
  480. }
  481. for (;;)
  482. {
  483. size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;
  484. if (outBuf)
  485. packSize = outLim - (size_t)packTotal;
  486. res = Lzma2EncInt_EncodeSubblock(p,
  487. outBuf ? outBuf + (size_t)packTotal : me->tempBufLzma, &packSize,
  488. outBuf ? NULL : outStream);
  489. if (res != SZ_OK)
  490. break;
  491. packTotal += packSize;
  492. if (outBuf)
  493. *outBufSize = (size_t)packTotal;
  494. res = Progress(progress, unpackTotal + p->srcPos, packTotal);
  495. if (res != SZ_OK)
  496. break;
  497. /*
  498. if (LzmaEnc_GetNumAvailableBytes(p->enc) == 0)
  499. break;
  500. */
  501. if (packSize == 0)
  502. break;
  503. }
  504. LzmaEnc_Finish(p->enc);
  505. unpackTotal += p->srcPos;
  506. RINOK(res)
  507. if (p->srcPos != (inStream ? limitedInStream.processed : inSizeCur))
  508. return SZ_ERROR_FAIL;
  509. if (inStream ? limitedInStream.finished : (unpackTotal == inDataSize))
  510. {
  511. if (finished)
  512. {
  513. if (outBuf)
  514. {
  515. const size_t destPos = *outBufSize;
  516. if (destPos >= outLim)
  517. return SZ_ERROR_OUTPUT_EOF;
  518. outBuf[destPos] = LZMA2_CONTROL_EOF; // 0
  519. *outBufSize = destPos + 1;
  520. }
  521. else
  522. {
  523. const Byte b = LZMA2_CONTROL_EOF; // 0;
  524. if (ISeqOutStream_Write(outStream, &b, 1) != 1)
  525. return SZ_ERROR_WRITE;
  526. }
  527. }
  528. return SZ_OK;
  529. }
  530. }
  531. }
  532. #ifndef Z7_ST
  533. static SRes Lzma2Enc_MtCallback_Code(void *p, unsigned coderIndex, unsigned outBufIndex,
  534. const Byte *src, size_t srcSize, int finished)
  535. {
  536. CLzma2Enc *me = (CLzma2Enc *)p;
  537. size_t destSize = me->outBufSize;
  538. SRes res;
  539. CMtProgressThunk progressThunk;
  540. Byte *dest = me->outBufs[outBufIndex];
  541. me->outBufsDataSizes[outBufIndex] = 0;
  542. if (!dest)
  543. {
  544. dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize);
  545. if (!dest)
  546. return SZ_ERROR_MEM;
  547. me->outBufs[outBufIndex] = dest;
  548. }
  549. MtProgressThunk_CreateVTable(&progressThunk);
  550. progressThunk.mtProgress = &me->mtCoder.mtProgress;
  551. progressThunk.inSize = 0;
  552. progressThunk.outSize = 0;
  553. res = Lzma2Enc_EncodeMt1(me,
  554. &me->coders[coderIndex],
  555. NULL, dest, &destSize,
  556. NULL, src, srcSize,
  557. finished,
  558. &progressThunk.vt);
  559. me->outBufsDataSizes[outBufIndex] = destSize;
  560. return res;
  561. }
  562. static SRes Lzma2Enc_MtCallback_Write(void *p, unsigned outBufIndex)
  563. {
  564. CLzma2Enc *me = (CLzma2Enc *)p;
  565. size_t size = me->outBufsDataSizes[outBufIndex];
  566. const Byte *data = me->outBufs[outBufIndex];
  567. if (me->outStream)
  568. return ISeqOutStream_Write(me->outStream, data, size) == size ? SZ_OK : SZ_ERROR_WRITE;
  569. if (size > me->outBuf_Rem)
  570. return SZ_ERROR_OUTPUT_EOF;
  571. memcpy(me->outBuf, data, size);
  572. me->outBuf_Rem -= size;
  573. me->outBuf += size;
  574. return SZ_OK;
  575. }
  576. #endif
  577. SRes Lzma2Enc_Encode2(CLzma2EncHandle p,
  578. ISeqOutStreamPtr outStream,
  579. Byte *outBuf, size_t *outBufSize,
  580. ISeqInStreamPtr inStream,
  581. const Byte *inData, size_t inDataSize,
  582. ICompressProgressPtr progress)
  583. {
  584. // GET_CLzma2Enc_p
  585. if (inStream && inData)
  586. return SZ_ERROR_PARAM;
  587. if (outStream && outBuf)
  588. return SZ_ERROR_PARAM;
  589. {
  590. unsigned i;
  591. for (i = 0; i < MTCODER_THREADS_MAX; i++)
  592. p->coders[i].propsAreSet = False;
  593. }
  594. #ifndef Z7_ST
  595. if (p->props.numBlockThreads_Reduced > 1)
  596. {
  597. IMtCoderCallback2 vt;
  598. if (!p->mtCoder_WasConstructed)
  599. {
  600. p->mtCoder_WasConstructed = True;
  601. MtCoder_Construct(&p->mtCoder);
  602. }
  603. vt.Code = Lzma2Enc_MtCallback_Code;
  604. vt.Write = Lzma2Enc_MtCallback_Write;
  605. p->outStream = outStream;
  606. p->outBuf = NULL;
  607. p->outBuf_Rem = 0;
  608. if (!outStream)
  609. {
  610. p->outBuf = outBuf;
  611. p->outBuf_Rem = *outBufSize;
  612. *outBufSize = 0;
  613. }
  614. p->mtCoder.allocBig = p->allocBig;
  615. p->mtCoder.progress = progress;
  616. p->mtCoder.inStream = inStream;
  617. p->mtCoder.inData = inData;
  618. p->mtCoder.inDataSize = inDataSize;
  619. p->mtCoder.mtCallback = &vt;
  620. p->mtCoder.mtCallbackObject = p;
  621. p->mtCoder.blockSize = (size_t)p->props.blockSize;
  622. if (p->mtCoder.blockSize != p->props.blockSize)
  623. return SZ_ERROR_PARAM; /* SZ_ERROR_MEM */
  624. {
  625. const size_t destBlockSize = p->mtCoder.blockSize + (p->mtCoder.blockSize >> 10) + 16;
  626. if (destBlockSize < p->mtCoder.blockSize)
  627. return SZ_ERROR_PARAM;
  628. if (p->outBufSize != destBlockSize)
  629. Lzma2Enc_FreeOutBufs(p);
  630. p->outBufSize = destBlockSize;
  631. }
  632. p->mtCoder.numThreadsMax = (unsigned)p->props.numBlockThreads_Max;
  633. p->mtCoder.numThreadGroups = p->props.numThreadGroups;
  634. p->mtCoder.expectedDataSize = p->expectedDataSize;
  635. {
  636. const SRes res = MtCoder_Code(&p->mtCoder);
  637. if (!outStream)
  638. *outBufSize = (size_t)(p->outBuf - outBuf);
  639. return res;
  640. }
  641. }
  642. #endif
  643. return Lzma2Enc_EncodeMt1(p,
  644. &p->coders[0],
  645. outStream, outBuf, outBufSize,
  646. inStream, inData, inDataSize,
  647. True, /* finished */
  648. progress);
  649. }
  650. #undef PRF