diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-02-10 16:44:39 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:39 +0300 |
commit | e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (patch) | |
tree | 64175d5cadab313b3e7039ebaa06c5bc3295e274 /contrib/libs/lzmasdk/Lzma2Enc.c | |
parent | 2598ef1d0aee359b4b6d5fdd1758916d5907d04f (diff) | |
download | ydb-e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0.tar.gz |
Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/libs/lzmasdk/Lzma2Enc.c')
-rw-r--r-- | contrib/libs/lzmasdk/Lzma2Enc.c | 1606 |
1 files changed, 803 insertions, 803 deletions
diff --git a/contrib/libs/lzmasdk/Lzma2Enc.c b/contrib/libs/lzmasdk/Lzma2Enc.c index a6fb10daac..5c1ad49312 100644 --- a/contrib/libs/lzmasdk/Lzma2Enc.c +++ b/contrib/libs/lzmasdk/Lzma2Enc.c @@ -1,803 +1,803 @@ -/* Lzma2Enc.c -- LZMA2 Encoder -2018-07-04 : Igor Pavlov : Public domain */ - -#include "Precomp.h" - -#include <string.h> - -/* #define _7ZIP_ST */ - -#include "Lzma2Enc.h" - -#ifndef _7ZIP_ST -#include "MtCoder.h" -#else -#define MTCODER__THREADS_MAX 1 -#endif - -#define LZMA2_CONTROL_LZMA (1 << 7) -#define LZMA2_CONTROL_COPY_NO_RESET 2 -#define LZMA2_CONTROL_COPY_RESET_DIC 1 -#define LZMA2_CONTROL_EOF 0 - -#define LZMA2_LCLP_MAX 4 - -#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)) - -#define LZMA2_PACK_SIZE_MAX (1 << 16) -#define LZMA2_COPY_CHUNK_SIZE LZMA2_PACK_SIZE_MAX -#define LZMA2_UNPACK_SIZE_MAX (1 << 21) -#define LZMA2_KEEP_WINDOW_SIZE LZMA2_UNPACK_SIZE_MAX - -#define LZMA2_CHUNK_SIZE_COMPRESSED_MAX ((1 << 16) + 16) - - -#define PRF(x) /* x */ - - -/* ---------- CLimitedSeqInStream ---------- */ - -typedef struct -{ - ISeqInStream vt; - ISeqInStream *realStream; - UInt64 limit; - UInt64 processed; - int finished; -} CLimitedSeqInStream; - -static void LimitedSeqInStream_Init(CLimitedSeqInStream *p) -{ - p->limit = (UInt64)(Int64)-1; - p->processed = 0; - p->finished = 0; -} - -static SRes LimitedSeqInStream_Read(const ISeqInStream *pp, void *data, size_t *size) -{ - CLimitedSeqInStream *p = CONTAINER_FROM_VTBL(pp, CLimitedSeqInStream, vt); - size_t size2 = *size; - SRes res = SZ_OK; - - if (p->limit != (UInt64)(Int64)-1) - { - UInt64 rem = p->limit - p->processed; - if (size2 > rem) - size2 = (size_t)rem; - } - if (size2 != 0) - { - res = ISeqInStream_Read(p->realStream, data, &size2); - p->finished = (size2 == 0 ? 1 : 0); - p->processed += size2; - } - *size = size2; - return res; -} - - -/* ---------- CLzma2EncInt ---------- */ - -typedef struct -{ - CLzmaEncHandle enc; - Byte propsAreSet; - Byte propsByte; - Byte needInitState; - Byte needInitProp; - UInt64 srcPos; -} CLzma2EncInt; - - -static SRes Lzma2EncInt_InitStream(CLzma2EncInt *p, const CLzma2EncProps *props) -{ - if (!p->propsAreSet) - { - SizeT propsSize = LZMA_PROPS_SIZE; - Byte propsEncoded[LZMA_PROPS_SIZE]; - RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps)); - RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize)); - p->propsByte = propsEncoded[0]; - p->propsAreSet = True; - } - return SZ_OK; -} - -static void Lzma2EncInt_InitBlock(CLzma2EncInt *p) -{ - p->srcPos = 0; - p->needInitState = True; - p->needInitProp = True; -} - - -SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize, - ISzAllocPtr alloc, ISzAllocPtr allocBig); -SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, - UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig); -SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit, - Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize); -const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp); -void LzmaEnc_Finish(CLzmaEncHandle pp); -void LzmaEnc_SaveState(CLzmaEncHandle pp); -void LzmaEnc_RestoreState(CLzmaEncHandle pp); - -/* -UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp); -*/ - -static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf, - size_t *packSizeRes, ISeqOutStream *outStream) -{ - size_t packSizeLimit = *packSizeRes; - size_t packSize = packSizeLimit; - UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX; - unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0); - BoolInt useCopyBlock; - SRes res; - - *packSizeRes = 0; - if (packSize < lzHeaderSize) - return SZ_ERROR_OUTPUT_EOF; - packSize -= lzHeaderSize; - - LzmaEnc_SaveState(p->enc); - res = LzmaEnc_CodeOneMemBlock(p->enc, p->needInitState, - outBuf + lzHeaderSize, &packSize, LZMA2_PACK_SIZE_MAX, &unpackSize); - - PRF(printf("\npackSize = %7d unpackSize = %7d ", packSize, unpackSize)); - - if (unpackSize == 0) - return res; - - if (res == SZ_OK) - useCopyBlock = (packSize + 2 >= unpackSize || packSize > (1 << 16)); - else - { - if (res != SZ_ERROR_OUTPUT_EOF) - return res; - res = SZ_OK; - useCopyBlock = True; - } - - if (useCopyBlock) - { - size_t destPos = 0; - PRF(printf("################# COPY ")); - - while (unpackSize > 0) - { - UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE; - if (packSizeLimit - destPos < u + 3) - return SZ_ERROR_OUTPUT_EOF; - outBuf[destPos++] = (Byte)(p->srcPos == 0 ? LZMA2_CONTROL_COPY_RESET_DIC : LZMA2_CONTROL_COPY_NO_RESET); - outBuf[destPos++] = (Byte)((u - 1) >> 8); - outBuf[destPos++] = (Byte)(u - 1); - memcpy(outBuf + destPos, LzmaEnc_GetCurBuf(p->enc) - unpackSize, u); - unpackSize -= u; - destPos += u; - p->srcPos += u; - - if (outStream) - { - *packSizeRes += destPos; - if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos) - return SZ_ERROR_WRITE; - destPos = 0; - } - else - *packSizeRes = destPos; - /* needInitState = True; */ - } - - LzmaEnc_RestoreState(p->enc); - return SZ_OK; - } - - { - size_t destPos = 0; - UInt32 u = unpackSize - 1; - UInt32 pm = (UInt32)(packSize - 1); - unsigned mode = (p->srcPos == 0) ? 3 : (p->needInitState ? (p->needInitProp ? 2 : 1) : 0); - - PRF(printf(" ")); - - outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | ((u >> 16) & 0x1F)); - outBuf[destPos++] = (Byte)(u >> 8); - outBuf[destPos++] = (Byte)u; - outBuf[destPos++] = (Byte)(pm >> 8); - outBuf[destPos++] = (Byte)pm; - - if (p->needInitProp) - outBuf[destPos++] = p->propsByte; - - p->needInitProp = False; - p->needInitState = False; - destPos += packSize; - p->srcPos += unpackSize; - - if (outStream) - if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos) - return SZ_ERROR_WRITE; - - *packSizeRes = destPos; - return SZ_OK; - } -} - - -/* ---------- Lzma2 Props ---------- */ - -void Lzma2EncProps_Init(CLzma2EncProps *p) -{ - LzmaEncProps_Init(&p->lzmaProps); - p->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO; - p->numBlockThreads_Reduced = -1; - p->numBlockThreads_Max = -1; - p->numTotalThreads = -1; -} - -void Lzma2EncProps_Normalize(CLzma2EncProps *p) -{ - UInt64 fileSize; - int t1, t1n, t2, t2r, t3; - { - CLzmaEncProps lzmaProps = p->lzmaProps; - LzmaEncProps_Normalize(&lzmaProps); - t1n = lzmaProps.numThreads; - } - - t1 = p->lzmaProps.numThreads; - t2 = p->numBlockThreads_Max; - t3 = p->numTotalThreads; - - if (t2 > MTCODER__THREADS_MAX) - t2 = MTCODER__THREADS_MAX; - - if (t3 <= 0) - { - if (t2 <= 0) - t2 = 1; - t3 = t1n * t2; - } - else if (t2 <= 0) - { - t2 = t3 / t1n; - if (t2 == 0) - { - t1 = 1; - t2 = t3; - } - if (t2 > MTCODER__THREADS_MAX) - t2 = MTCODER__THREADS_MAX; - } - else if (t1 <= 0) - { - t1 = t3 / t2; - if (t1 == 0) - t1 = 1; - } - else - t3 = t1n * t2; - - p->lzmaProps.numThreads = t1; - - t2r = t2; - - fileSize = p->lzmaProps.reduceSize; - - if ( p->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID - && p->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO - && (p->blockSize < fileSize || fileSize == (UInt64)(Int64)-1)) - p->lzmaProps.reduceSize = p->blockSize; - - LzmaEncProps_Normalize(&p->lzmaProps); - - p->lzmaProps.reduceSize = fileSize; - - t1 = p->lzmaProps.numThreads; - - if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID) - { - t2r = t2 = 1; - t3 = t1; - } - else if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO && t2 <= 1) - { - /* if there is no block multi-threading, we use SOLID block */ - p->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID; - } - else - { - if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO) - { - const UInt32 kMinSize = (UInt32)1 << 20; - const UInt32 kMaxSize = (UInt32)1 << 28; - const UInt32 dictSize = p->lzmaProps.dictSize; - UInt64 blockSize = (UInt64)dictSize << 2; - if (blockSize < kMinSize) blockSize = kMinSize; - if (blockSize > kMaxSize) blockSize = kMaxSize; - if (blockSize < dictSize) blockSize = dictSize; - blockSize += (kMinSize - 1); - blockSize &= ~(UInt64)(kMinSize - 1); - p->blockSize = blockSize; - } - - if (t2 > 1 && fileSize != (UInt64)(Int64)-1) - { - UInt64 numBlocks = fileSize / p->blockSize; - if (numBlocks * p->blockSize != fileSize) - numBlocks++; - if (numBlocks < (unsigned)t2) - { - t2r = (unsigned)numBlocks; - if (t2r == 0) - t2r = 1; - t3 = t1 * t2r; - } - } - } - - p->numBlockThreads_Max = t2; - p->numBlockThreads_Reduced = t2r; - p->numTotalThreads = t3; -} - - -static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize) -{ - return (p && ICompressProgress_Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK; -} - - -/* ---------- Lzma2 ---------- */ - -typedef struct -{ - Byte propEncoded; - CLzma2EncProps props; - UInt64 expectedDataSize; - - Byte *tempBufLzma; - - ISzAllocPtr alloc; - ISzAllocPtr allocBig; - - CLzma2EncInt coders[MTCODER__THREADS_MAX]; - - #ifndef _7ZIP_ST - - ISeqOutStream *outStream; - Byte *outBuf; - size_t outBuf_Rem; /* remainder in outBuf */ - - size_t outBufSize; /* size of allocated outBufs[i] */ - size_t outBufsDataSizes[MTCODER__BLOCKS_MAX]; - BoolInt mtCoder_WasConstructed; - CMtCoder mtCoder; - Byte *outBufs[MTCODER__BLOCKS_MAX]; - - #endif - -} CLzma2Enc; - - - -CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig) -{ - CLzma2Enc *p = (CLzma2Enc *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Enc)); - if (!p) - return NULL; - Lzma2EncProps_Init(&p->props); - Lzma2EncProps_Normalize(&p->props); - p->expectedDataSize = (UInt64)(Int64)-1; - p->tempBufLzma = NULL; - p->alloc = alloc; - p->allocBig = allocBig; - { - unsigned i; - for (i = 0; i < MTCODER__THREADS_MAX; i++) - p->coders[i].enc = NULL; - } - - #ifndef _7ZIP_ST - p->mtCoder_WasConstructed = False; - { - unsigned i; - for (i = 0; i < MTCODER__BLOCKS_MAX; i++) - p->outBufs[i] = NULL; - p->outBufSize = 0; - } - #endif - - return p; -} - - -#ifndef _7ZIP_ST - -static void Lzma2Enc_FreeOutBufs(CLzma2Enc *p) -{ - unsigned i; - for (i = 0; i < MTCODER__BLOCKS_MAX; i++) - if (p->outBufs[i]) - { - ISzAlloc_Free(p->alloc, p->outBufs[i]); - p->outBufs[i] = NULL; - } - p->outBufSize = 0; -} - -#endif - - -void Lzma2Enc_Destroy(CLzma2EncHandle pp) -{ - CLzma2Enc *p = (CLzma2Enc *)pp; - unsigned i; - for (i = 0; i < MTCODER__THREADS_MAX; i++) - { - CLzma2EncInt *t = &p->coders[i]; - if (t->enc) - { - LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig); - t->enc = NULL; - } - } - - - #ifndef _7ZIP_ST - if (p->mtCoder_WasConstructed) - { - MtCoder_Destruct(&p->mtCoder); - p->mtCoder_WasConstructed = False; - } - Lzma2Enc_FreeOutBufs(p); - #endif - - ISzAlloc_Free(p->alloc, p->tempBufLzma); - p->tempBufLzma = NULL; - - ISzAlloc_Free(p->alloc, pp); -} - - -SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props) -{ - CLzma2Enc *p = (CLzma2Enc *)pp; - CLzmaEncProps lzmaProps = props->lzmaProps; - LzmaEncProps_Normalize(&lzmaProps); - if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX) - return SZ_ERROR_PARAM; - p->props = *props; - Lzma2EncProps_Normalize(&p->props); - return SZ_OK; -} - - -void Lzma2Enc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize) -{ - CLzma2Enc *p = (CLzma2Enc *)pp; - p->expectedDataSize = expectedDataSiize; -} - - -Byte Lzma2Enc_WriteProperties(CLzma2EncHandle pp) -{ - CLzma2Enc *p = (CLzma2Enc *)pp; - unsigned i; - UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps); - for (i = 0; i < 40; i++) - if (dicSize <= LZMA2_DIC_SIZE_FROM_PROP(i)) - break; - return (Byte)i; -} - - -static SRes Lzma2Enc_EncodeMt1( - CLzma2Enc *me, - CLzma2EncInt *p, - ISeqOutStream *outStream, - Byte *outBuf, size_t *outBufSize, - ISeqInStream *inStream, - const Byte *inData, size_t inDataSize, - int finished, - ICompressProgress *progress) -{ - UInt64 unpackTotal = 0; - UInt64 packTotal = 0; - size_t outLim = 0; - CLimitedSeqInStream limitedInStream; - - if (outBuf) - { - outLim = *outBufSize; - *outBufSize = 0; - } - - if (!p->enc) - { - p->propsAreSet = False; - p->enc = LzmaEnc_Create(me->alloc); - if (!p->enc) - return SZ_ERROR_MEM; - } - - limitedInStream.realStream = inStream; - if (inStream) - { - limitedInStream.vt.Read = LimitedSeqInStream_Read; - } - - if (!outBuf) - { - // outStream version works only in one thread. So we use CLzma2Enc::tempBufLzma - if (!me->tempBufLzma) - { - me->tempBufLzma = (Byte *)ISzAlloc_Alloc(me->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX); - if (!me->tempBufLzma) - return SZ_ERROR_MEM; - } - } - - RINOK(Lzma2EncInt_InitStream(p, &me->props)); - - for (;;) - { - SRes res = SZ_OK; - size_t inSizeCur = 0; - - Lzma2EncInt_InitBlock(p); - - LimitedSeqInStream_Init(&limitedInStream); - limitedInStream.limit = me->props.blockSize; - - if (inStream) - { - UInt64 expected = (UInt64)(Int64)-1; - // inStream version works only in one thread. So we use CLzma2Enc::expectedDataSize - if (me->expectedDataSize != (UInt64)(Int64)-1 - && me->expectedDataSize >= unpackTotal) - expected = me->expectedDataSize - unpackTotal; - if (me->props.blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID - && expected > me->props.blockSize) - expected = (size_t)me->props.blockSize; - - LzmaEnc_SetDataSize(p->enc, expected); - - RINOK(LzmaEnc_PrepareForLzma2(p->enc, - &limitedInStream.vt, - LZMA2_KEEP_WINDOW_SIZE, - me->alloc, - me->allocBig)); - } - else - { - inSizeCur = inDataSize - (size_t)unpackTotal; - if (me->props.blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID - && inSizeCur > me->props.blockSize) - inSizeCur = (size_t)me->props.blockSize; - - // LzmaEnc_SetDataSize(p->enc, inSizeCur); - - RINOK(LzmaEnc_MemPrepare(p->enc, - inData + (size_t)unpackTotal, inSizeCur, - LZMA2_KEEP_WINDOW_SIZE, - me->alloc, - me->allocBig)); - } - - for (;;) - { - size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX; - if (outBuf) - packSize = outLim - (size_t)packTotal; - - res = Lzma2EncInt_EncodeSubblock(p, - outBuf ? outBuf + (size_t)packTotal : me->tempBufLzma, &packSize, - outBuf ? NULL : outStream); - - if (res != SZ_OK) - break; - - packTotal += packSize; - if (outBuf) - *outBufSize = (size_t)packTotal; - - res = Progress(progress, unpackTotal + p->srcPos, packTotal); - if (res != SZ_OK) - break; - - /* - if (LzmaEnc_GetNumAvailableBytes(p->enc) == 0) - break; - */ - - if (packSize == 0) - break; - } - - LzmaEnc_Finish(p->enc); - - unpackTotal += p->srcPos; - - RINOK(res); - - if (p->srcPos != (inStream ? limitedInStream.processed : inSizeCur)) - return SZ_ERROR_FAIL; - - if (inStream ? limitedInStream.finished : (unpackTotal == inDataSize)) - { - if (finished) - { - if (outBuf) - { - size_t destPos = *outBufSize; - if (destPos >= outLim) - return SZ_ERROR_OUTPUT_EOF; - outBuf[destPos] = 0; - *outBufSize = destPos + 1; - } - else - { - Byte b = 0; - if (ISeqOutStream_Write(outStream, &b, 1) != 1) - return SZ_ERROR_WRITE; - } - } - return SZ_OK; - } - } -} - - - -#ifndef _7ZIP_ST - -static SRes Lzma2Enc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned outBufIndex, - const Byte *src, size_t srcSize, int finished) -{ - CLzma2Enc *me = (CLzma2Enc *)pp; - size_t destSize = me->outBufSize; - SRes res; - CMtProgressThunk progressThunk; - - Byte *dest = me->outBufs[outBufIndex]; - - me->outBufsDataSizes[outBufIndex] = 0; - - if (!dest) - { - dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize); - if (!dest) - return SZ_ERROR_MEM; - me->outBufs[outBufIndex] = dest; - } - - MtProgressThunk_CreateVTable(&progressThunk); - progressThunk.mtProgress = &me->mtCoder.mtProgress; - progressThunk.inSize = 0; - progressThunk.outSize = 0; - - res = Lzma2Enc_EncodeMt1(me, - &me->coders[coderIndex], - NULL, dest, &destSize, - NULL, src, srcSize, - finished, - &progressThunk.vt); - - me->outBufsDataSizes[outBufIndex] = destSize; - - return res; -} - - -static SRes Lzma2Enc_MtCallback_Write(void *pp, unsigned outBufIndex) -{ - CLzma2Enc *me = (CLzma2Enc *)pp; - size_t size = me->outBufsDataSizes[outBufIndex]; - const Byte *data = me->outBufs[outBufIndex]; - - if (me->outStream) - return ISeqOutStream_Write(me->outStream, data, size) == size ? SZ_OK : SZ_ERROR_WRITE; - - if (size > me->outBuf_Rem) - return SZ_ERROR_OUTPUT_EOF; - memcpy(me->outBuf, data, size); - me->outBuf_Rem -= size; - me->outBuf += size; - return SZ_OK; -} - -#endif - - - -SRes Lzma2Enc_Encode2(CLzma2EncHandle pp, - ISeqOutStream *outStream, - Byte *outBuf, size_t *outBufSize, - ISeqInStream *inStream, - const Byte *inData, size_t inDataSize, - ICompressProgress *progress) -{ - CLzma2Enc *p = (CLzma2Enc *)pp; - - if (inStream && inData) - return SZ_ERROR_PARAM; - - if (outStream && outBuf) - return SZ_ERROR_PARAM; - - { - unsigned i; - for (i = 0; i < MTCODER__THREADS_MAX; i++) - p->coders[i].propsAreSet = False; - } - - #ifndef _7ZIP_ST - - if (p->props.numBlockThreads_Reduced > 1) - { - IMtCoderCallback2 vt; - - if (!p->mtCoder_WasConstructed) - { - p->mtCoder_WasConstructed = True; - MtCoder_Construct(&p->mtCoder); - } - - vt.Code = Lzma2Enc_MtCallback_Code; - vt.Write = Lzma2Enc_MtCallback_Write; - - p->outStream = outStream; - p->outBuf = NULL; - p->outBuf_Rem = 0; - if (!outStream) - { - p->outBuf = outBuf; - p->outBuf_Rem = *outBufSize; - *outBufSize = 0; - } - - p->mtCoder.allocBig = p->allocBig; - p->mtCoder.progress = progress; - p->mtCoder.inStream = inStream; - p->mtCoder.inData = inData; - p->mtCoder.inDataSize = inDataSize; - p->mtCoder.mtCallback = &vt; - p->mtCoder.mtCallbackObject = p; - - p->mtCoder.blockSize = (size_t)p->props.blockSize; - if (p->mtCoder.blockSize != p->props.blockSize) - return SZ_ERROR_PARAM; /* SZ_ERROR_MEM */ - - { - size_t destBlockSize = p->mtCoder.blockSize + (p->mtCoder.blockSize >> 10) + 16; - if (destBlockSize < p->mtCoder.blockSize) - return SZ_ERROR_PARAM; - if (p->outBufSize != destBlockSize) - Lzma2Enc_FreeOutBufs(p); - p->outBufSize = destBlockSize; - } - - p->mtCoder.numThreadsMax = p->props.numBlockThreads_Max; - p->mtCoder.expectedDataSize = p->expectedDataSize; - - { - SRes res = MtCoder_Code(&p->mtCoder); - if (!outStream) - *outBufSize = p->outBuf - outBuf; - return res; - } - } - - #endif - - - return Lzma2Enc_EncodeMt1(p, - &p->coders[0], - outStream, outBuf, outBufSize, - inStream, inData, inDataSize, - True, /* finished */ - progress); -} +/* Lzma2Enc.c -- LZMA2 Encoder +2018-07-04 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include <string.h> + +/* #define _7ZIP_ST */ + +#include "Lzma2Enc.h" + +#ifndef _7ZIP_ST +#include "MtCoder.h" +#else +#define MTCODER__THREADS_MAX 1 +#endif + +#define LZMA2_CONTROL_LZMA (1 << 7) +#define LZMA2_CONTROL_COPY_NO_RESET 2 +#define LZMA2_CONTROL_COPY_RESET_DIC 1 +#define LZMA2_CONTROL_EOF 0 + +#define LZMA2_LCLP_MAX 4 + +#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)) + +#define LZMA2_PACK_SIZE_MAX (1 << 16) +#define LZMA2_COPY_CHUNK_SIZE LZMA2_PACK_SIZE_MAX +#define LZMA2_UNPACK_SIZE_MAX (1 << 21) +#define LZMA2_KEEP_WINDOW_SIZE LZMA2_UNPACK_SIZE_MAX + +#define LZMA2_CHUNK_SIZE_COMPRESSED_MAX ((1 << 16) + 16) + + +#define PRF(x) /* x */ + + +/* ---------- CLimitedSeqInStream ---------- */ + +typedef struct +{ + ISeqInStream vt; + ISeqInStream *realStream; + UInt64 limit; + UInt64 processed; + int finished; +} CLimitedSeqInStream; + +static void LimitedSeqInStream_Init(CLimitedSeqInStream *p) +{ + p->limit = (UInt64)(Int64)-1; + p->processed = 0; + p->finished = 0; +} + +static SRes LimitedSeqInStream_Read(const ISeqInStream *pp, void *data, size_t *size) +{ + CLimitedSeqInStream *p = CONTAINER_FROM_VTBL(pp, CLimitedSeqInStream, vt); + size_t size2 = *size; + SRes res = SZ_OK; + + if (p->limit != (UInt64)(Int64)-1) + { + UInt64 rem = p->limit - p->processed; + if (size2 > rem) + size2 = (size_t)rem; + } + if (size2 != 0) + { + res = ISeqInStream_Read(p->realStream, data, &size2); + p->finished = (size2 == 0 ? 1 : 0); + p->processed += size2; + } + *size = size2; + return res; +} + + +/* ---------- CLzma2EncInt ---------- */ + +typedef struct +{ + CLzmaEncHandle enc; + Byte propsAreSet; + Byte propsByte; + Byte needInitState; + Byte needInitProp; + UInt64 srcPos; +} CLzma2EncInt; + + +static SRes Lzma2EncInt_InitStream(CLzma2EncInt *p, const CLzma2EncProps *props) +{ + if (!p->propsAreSet) + { + SizeT propsSize = LZMA_PROPS_SIZE; + Byte propsEncoded[LZMA_PROPS_SIZE]; + RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps)); + RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize)); + p->propsByte = propsEncoded[0]; + p->propsAreSet = True; + } + return SZ_OK; +} + +static void Lzma2EncInt_InitBlock(CLzma2EncInt *p) +{ + p->srcPos = 0; + p->needInitState = True; + p->needInitProp = True; +} + + +SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize, + ISzAllocPtr alloc, ISzAllocPtr allocBig); +SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, + UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig); +SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit, + Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize); +const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp); +void LzmaEnc_Finish(CLzmaEncHandle pp); +void LzmaEnc_SaveState(CLzmaEncHandle pp); +void LzmaEnc_RestoreState(CLzmaEncHandle pp); + +/* +UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp); +*/ + +static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf, + size_t *packSizeRes, ISeqOutStream *outStream) +{ + size_t packSizeLimit = *packSizeRes; + size_t packSize = packSizeLimit; + UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX; + unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0); + BoolInt useCopyBlock; + SRes res; + + *packSizeRes = 0; + if (packSize < lzHeaderSize) + return SZ_ERROR_OUTPUT_EOF; + packSize -= lzHeaderSize; + + LzmaEnc_SaveState(p->enc); + res = LzmaEnc_CodeOneMemBlock(p->enc, p->needInitState, + outBuf + lzHeaderSize, &packSize, LZMA2_PACK_SIZE_MAX, &unpackSize); + + PRF(printf("\npackSize = %7d unpackSize = %7d ", packSize, unpackSize)); + + if (unpackSize == 0) + return res; + + if (res == SZ_OK) + useCopyBlock = (packSize + 2 >= unpackSize || packSize > (1 << 16)); + else + { + if (res != SZ_ERROR_OUTPUT_EOF) + return res; + res = SZ_OK; + useCopyBlock = True; + } + + if (useCopyBlock) + { + size_t destPos = 0; + PRF(printf("################# COPY ")); + + while (unpackSize > 0) + { + UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE; + if (packSizeLimit - destPos < u + 3) + return SZ_ERROR_OUTPUT_EOF; + outBuf[destPos++] = (Byte)(p->srcPos == 0 ? LZMA2_CONTROL_COPY_RESET_DIC : LZMA2_CONTROL_COPY_NO_RESET); + outBuf[destPos++] = (Byte)((u - 1) >> 8); + outBuf[destPos++] = (Byte)(u - 1); + memcpy(outBuf + destPos, LzmaEnc_GetCurBuf(p->enc) - unpackSize, u); + unpackSize -= u; + destPos += u; + p->srcPos += u; + + if (outStream) + { + *packSizeRes += destPos; + if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos) + return SZ_ERROR_WRITE; + destPos = 0; + } + else + *packSizeRes = destPos; + /* needInitState = True; */ + } + + LzmaEnc_RestoreState(p->enc); + return SZ_OK; + } + + { + size_t destPos = 0; + UInt32 u = unpackSize - 1; + UInt32 pm = (UInt32)(packSize - 1); + unsigned mode = (p->srcPos == 0) ? 3 : (p->needInitState ? (p->needInitProp ? 2 : 1) : 0); + + PRF(printf(" ")); + + outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | ((u >> 16) & 0x1F)); + outBuf[destPos++] = (Byte)(u >> 8); + outBuf[destPos++] = (Byte)u; + outBuf[destPos++] = (Byte)(pm >> 8); + outBuf[destPos++] = (Byte)pm; + + if (p->needInitProp) + outBuf[destPos++] = p->propsByte; + + p->needInitProp = False; + p->needInitState = False; + destPos += packSize; + p->srcPos += unpackSize; + + if (outStream) + if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos) + return SZ_ERROR_WRITE; + + *packSizeRes = destPos; + return SZ_OK; + } +} + + +/* ---------- Lzma2 Props ---------- */ + +void Lzma2EncProps_Init(CLzma2EncProps *p) +{ + LzmaEncProps_Init(&p->lzmaProps); + p->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO; + p->numBlockThreads_Reduced = -1; + p->numBlockThreads_Max = -1; + p->numTotalThreads = -1; +} + +void Lzma2EncProps_Normalize(CLzma2EncProps *p) +{ + UInt64 fileSize; + int t1, t1n, t2, t2r, t3; + { + CLzmaEncProps lzmaProps = p->lzmaProps; + LzmaEncProps_Normalize(&lzmaProps); + t1n = lzmaProps.numThreads; + } + + t1 = p->lzmaProps.numThreads; + t2 = p->numBlockThreads_Max; + t3 = p->numTotalThreads; + + if (t2 > MTCODER__THREADS_MAX) + t2 = MTCODER__THREADS_MAX; + + if (t3 <= 0) + { + if (t2 <= 0) + t2 = 1; + t3 = t1n * t2; + } + else if (t2 <= 0) + { + t2 = t3 / t1n; + if (t2 == 0) + { + t1 = 1; + t2 = t3; + } + if (t2 > MTCODER__THREADS_MAX) + t2 = MTCODER__THREADS_MAX; + } + else if (t1 <= 0) + { + t1 = t3 / t2; + if (t1 == 0) + t1 = 1; + } + else + t3 = t1n * t2; + + p->lzmaProps.numThreads = t1; + + t2r = t2; + + fileSize = p->lzmaProps.reduceSize; + + if ( p->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID + && p->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO + && (p->blockSize < fileSize || fileSize == (UInt64)(Int64)-1)) + p->lzmaProps.reduceSize = p->blockSize; + + LzmaEncProps_Normalize(&p->lzmaProps); + + p->lzmaProps.reduceSize = fileSize; + + t1 = p->lzmaProps.numThreads; + + if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID) + { + t2r = t2 = 1; + t3 = t1; + } + else if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO && t2 <= 1) + { + /* if there is no block multi-threading, we use SOLID block */ + p->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID; + } + else + { + if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO) + { + const UInt32 kMinSize = (UInt32)1 << 20; + const UInt32 kMaxSize = (UInt32)1 << 28; + const UInt32 dictSize = p->lzmaProps.dictSize; + UInt64 blockSize = (UInt64)dictSize << 2; + if (blockSize < kMinSize) blockSize = kMinSize; + if (blockSize > kMaxSize) blockSize = kMaxSize; + if (blockSize < dictSize) blockSize = dictSize; + blockSize += (kMinSize - 1); + blockSize &= ~(UInt64)(kMinSize - 1); + p->blockSize = blockSize; + } + + if (t2 > 1 && fileSize != (UInt64)(Int64)-1) + { + UInt64 numBlocks = fileSize / p->blockSize; + if (numBlocks * p->blockSize != fileSize) + numBlocks++; + if (numBlocks < (unsigned)t2) + { + t2r = (unsigned)numBlocks; + if (t2r == 0) + t2r = 1; + t3 = t1 * t2r; + } + } + } + + p->numBlockThreads_Max = t2; + p->numBlockThreads_Reduced = t2r; + p->numTotalThreads = t3; +} + + +static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize) +{ + return (p && ICompressProgress_Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK; +} + + +/* ---------- Lzma2 ---------- */ + +typedef struct +{ + Byte propEncoded; + CLzma2EncProps props; + UInt64 expectedDataSize; + + Byte *tempBufLzma; + + ISzAllocPtr alloc; + ISzAllocPtr allocBig; + + CLzma2EncInt coders[MTCODER__THREADS_MAX]; + + #ifndef _7ZIP_ST + + ISeqOutStream *outStream; + Byte *outBuf; + size_t outBuf_Rem; /* remainder in outBuf */ + + size_t outBufSize; /* size of allocated outBufs[i] */ + size_t outBufsDataSizes[MTCODER__BLOCKS_MAX]; + BoolInt mtCoder_WasConstructed; + CMtCoder mtCoder; + Byte *outBufs[MTCODER__BLOCKS_MAX]; + + #endif + +} CLzma2Enc; + + + +CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + CLzma2Enc *p = (CLzma2Enc *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Enc)); + if (!p) + return NULL; + Lzma2EncProps_Init(&p->props); + Lzma2EncProps_Normalize(&p->props); + p->expectedDataSize = (UInt64)(Int64)-1; + p->tempBufLzma = NULL; + p->alloc = alloc; + p->allocBig = allocBig; + { + unsigned i; + for (i = 0; i < MTCODER__THREADS_MAX; i++) + p->coders[i].enc = NULL; + } + + #ifndef _7ZIP_ST + p->mtCoder_WasConstructed = False; + { + unsigned i; + for (i = 0; i < MTCODER__BLOCKS_MAX; i++) + p->outBufs[i] = NULL; + p->outBufSize = 0; + } + #endif + + return p; +} + + +#ifndef _7ZIP_ST + +static void Lzma2Enc_FreeOutBufs(CLzma2Enc *p) +{ + unsigned i; + for (i = 0; i < MTCODER__BLOCKS_MAX; i++) + if (p->outBufs[i]) + { + ISzAlloc_Free(p->alloc, p->outBufs[i]); + p->outBufs[i] = NULL; + } + p->outBufSize = 0; +} + +#endif + + +void Lzma2Enc_Destroy(CLzma2EncHandle pp) +{ + CLzma2Enc *p = (CLzma2Enc *)pp; + unsigned i; + for (i = 0; i < MTCODER__THREADS_MAX; i++) + { + CLzma2EncInt *t = &p->coders[i]; + if (t->enc) + { + LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig); + t->enc = NULL; + } + } + + + #ifndef _7ZIP_ST + if (p->mtCoder_WasConstructed) + { + MtCoder_Destruct(&p->mtCoder); + p->mtCoder_WasConstructed = False; + } + Lzma2Enc_FreeOutBufs(p); + #endif + + ISzAlloc_Free(p->alloc, p->tempBufLzma); + p->tempBufLzma = NULL; + + ISzAlloc_Free(p->alloc, pp); +} + + +SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props) +{ + CLzma2Enc *p = (CLzma2Enc *)pp; + CLzmaEncProps lzmaProps = props->lzmaProps; + LzmaEncProps_Normalize(&lzmaProps); + if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX) + return SZ_ERROR_PARAM; + p->props = *props; + Lzma2EncProps_Normalize(&p->props); + return SZ_OK; +} + + +void Lzma2Enc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize) +{ + CLzma2Enc *p = (CLzma2Enc *)pp; + p->expectedDataSize = expectedDataSiize; +} + + +Byte Lzma2Enc_WriteProperties(CLzma2EncHandle pp) +{ + CLzma2Enc *p = (CLzma2Enc *)pp; + unsigned i; + UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps); + for (i = 0; i < 40; i++) + if (dicSize <= LZMA2_DIC_SIZE_FROM_PROP(i)) + break; + return (Byte)i; +} + + +static SRes Lzma2Enc_EncodeMt1( + CLzma2Enc *me, + CLzma2EncInt *p, + ISeqOutStream *outStream, + Byte *outBuf, size_t *outBufSize, + ISeqInStream *inStream, + const Byte *inData, size_t inDataSize, + int finished, + ICompressProgress *progress) +{ + UInt64 unpackTotal = 0; + UInt64 packTotal = 0; + size_t outLim = 0; + CLimitedSeqInStream limitedInStream; + + if (outBuf) + { + outLim = *outBufSize; + *outBufSize = 0; + } + + if (!p->enc) + { + p->propsAreSet = False; + p->enc = LzmaEnc_Create(me->alloc); + if (!p->enc) + return SZ_ERROR_MEM; + } + + limitedInStream.realStream = inStream; + if (inStream) + { + limitedInStream.vt.Read = LimitedSeqInStream_Read; + } + + if (!outBuf) + { + // outStream version works only in one thread. So we use CLzma2Enc::tempBufLzma + if (!me->tempBufLzma) + { + me->tempBufLzma = (Byte *)ISzAlloc_Alloc(me->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX); + if (!me->tempBufLzma) + return SZ_ERROR_MEM; + } + } + + RINOK(Lzma2EncInt_InitStream(p, &me->props)); + + for (;;) + { + SRes res = SZ_OK; + size_t inSizeCur = 0; + + Lzma2EncInt_InitBlock(p); + + LimitedSeqInStream_Init(&limitedInStream); + limitedInStream.limit = me->props.blockSize; + + if (inStream) + { + UInt64 expected = (UInt64)(Int64)-1; + // inStream version works only in one thread. So we use CLzma2Enc::expectedDataSize + if (me->expectedDataSize != (UInt64)(Int64)-1 + && me->expectedDataSize >= unpackTotal) + expected = me->expectedDataSize - unpackTotal; + if (me->props.blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID + && expected > me->props.blockSize) + expected = (size_t)me->props.blockSize; + + LzmaEnc_SetDataSize(p->enc, expected); + + RINOK(LzmaEnc_PrepareForLzma2(p->enc, + &limitedInStream.vt, + LZMA2_KEEP_WINDOW_SIZE, + me->alloc, + me->allocBig)); + } + else + { + inSizeCur = inDataSize - (size_t)unpackTotal; + if (me->props.blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID + && inSizeCur > me->props.blockSize) + inSizeCur = (size_t)me->props.blockSize; + + // LzmaEnc_SetDataSize(p->enc, inSizeCur); + + RINOK(LzmaEnc_MemPrepare(p->enc, + inData + (size_t)unpackTotal, inSizeCur, + LZMA2_KEEP_WINDOW_SIZE, + me->alloc, + me->allocBig)); + } + + for (;;) + { + size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX; + if (outBuf) + packSize = outLim - (size_t)packTotal; + + res = Lzma2EncInt_EncodeSubblock(p, + outBuf ? outBuf + (size_t)packTotal : me->tempBufLzma, &packSize, + outBuf ? NULL : outStream); + + if (res != SZ_OK) + break; + + packTotal += packSize; + if (outBuf) + *outBufSize = (size_t)packTotal; + + res = Progress(progress, unpackTotal + p->srcPos, packTotal); + if (res != SZ_OK) + break; + + /* + if (LzmaEnc_GetNumAvailableBytes(p->enc) == 0) + break; + */ + + if (packSize == 0) + break; + } + + LzmaEnc_Finish(p->enc); + + unpackTotal += p->srcPos; + + RINOK(res); + + if (p->srcPos != (inStream ? limitedInStream.processed : inSizeCur)) + return SZ_ERROR_FAIL; + + if (inStream ? limitedInStream.finished : (unpackTotal == inDataSize)) + { + if (finished) + { + if (outBuf) + { + size_t destPos = *outBufSize; + if (destPos >= outLim) + return SZ_ERROR_OUTPUT_EOF; + outBuf[destPos] = 0; + *outBufSize = destPos + 1; + } + else + { + Byte b = 0; + if (ISeqOutStream_Write(outStream, &b, 1) != 1) + return SZ_ERROR_WRITE; + } + } + return SZ_OK; + } + } +} + + + +#ifndef _7ZIP_ST + +static SRes Lzma2Enc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned outBufIndex, + const Byte *src, size_t srcSize, int finished) +{ + CLzma2Enc *me = (CLzma2Enc *)pp; + size_t destSize = me->outBufSize; + SRes res; + CMtProgressThunk progressThunk; + + Byte *dest = me->outBufs[outBufIndex]; + + me->outBufsDataSizes[outBufIndex] = 0; + + if (!dest) + { + dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize); + if (!dest) + return SZ_ERROR_MEM; + me->outBufs[outBufIndex] = dest; + } + + MtProgressThunk_CreateVTable(&progressThunk); + progressThunk.mtProgress = &me->mtCoder.mtProgress; + progressThunk.inSize = 0; + progressThunk.outSize = 0; + + res = Lzma2Enc_EncodeMt1(me, + &me->coders[coderIndex], + NULL, dest, &destSize, + NULL, src, srcSize, + finished, + &progressThunk.vt); + + me->outBufsDataSizes[outBufIndex] = destSize; + + return res; +} + + +static SRes Lzma2Enc_MtCallback_Write(void *pp, unsigned outBufIndex) +{ + CLzma2Enc *me = (CLzma2Enc *)pp; + size_t size = me->outBufsDataSizes[outBufIndex]; + const Byte *data = me->outBufs[outBufIndex]; + + if (me->outStream) + return ISeqOutStream_Write(me->outStream, data, size) == size ? SZ_OK : SZ_ERROR_WRITE; + + if (size > me->outBuf_Rem) + return SZ_ERROR_OUTPUT_EOF; + memcpy(me->outBuf, data, size); + me->outBuf_Rem -= size; + me->outBuf += size; + return SZ_OK; +} + +#endif + + + +SRes Lzma2Enc_Encode2(CLzma2EncHandle pp, + ISeqOutStream *outStream, + Byte *outBuf, size_t *outBufSize, + ISeqInStream *inStream, + const Byte *inData, size_t inDataSize, + ICompressProgress *progress) +{ + CLzma2Enc *p = (CLzma2Enc *)pp; + + if (inStream && inData) + return SZ_ERROR_PARAM; + + if (outStream && outBuf) + return SZ_ERROR_PARAM; + + { + unsigned i; + for (i = 0; i < MTCODER__THREADS_MAX; i++) + p->coders[i].propsAreSet = False; + } + + #ifndef _7ZIP_ST + + if (p->props.numBlockThreads_Reduced > 1) + { + IMtCoderCallback2 vt; + + if (!p->mtCoder_WasConstructed) + { + p->mtCoder_WasConstructed = True; + MtCoder_Construct(&p->mtCoder); + } + + vt.Code = Lzma2Enc_MtCallback_Code; + vt.Write = Lzma2Enc_MtCallback_Write; + + p->outStream = outStream; + p->outBuf = NULL; + p->outBuf_Rem = 0; + if (!outStream) + { + p->outBuf = outBuf; + p->outBuf_Rem = *outBufSize; + *outBufSize = 0; + } + + p->mtCoder.allocBig = p->allocBig; + p->mtCoder.progress = progress; + p->mtCoder.inStream = inStream; + p->mtCoder.inData = inData; + p->mtCoder.inDataSize = inDataSize; + p->mtCoder.mtCallback = &vt; + p->mtCoder.mtCallbackObject = p; + + p->mtCoder.blockSize = (size_t)p->props.blockSize; + if (p->mtCoder.blockSize != p->props.blockSize) + return SZ_ERROR_PARAM; /* SZ_ERROR_MEM */ + + { + size_t destBlockSize = p->mtCoder.blockSize + (p->mtCoder.blockSize >> 10) + 16; + if (destBlockSize < p->mtCoder.blockSize) + return SZ_ERROR_PARAM; + if (p->outBufSize != destBlockSize) + Lzma2Enc_FreeOutBufs(p); + p->outBufSize = destBlockSize; + } + + p->mtCoder.numThreadsMax = p->props.numBlockThreads_Max; + p->mtCoder.expectedDataSize = p->expectedDataSize; + + { + SRes res = MtCoder_Code(&p->mtCoder); + if (!outStream) + *outBufSize = p->outBuf - outBuf; + return res; + } + } + + #endif + + + return Lzma2Enc_EncodeMt1(p, + &p->coders[0], + outStream, outBuf, outBufSize, + inStream, inData, inDataSize, + True, /* finished */ + progress); +} |