Removed unused files
This commit is contained in:
parent
d1c028aa06
commit
1ff538b8ce
12 changed files with 0 additions and 4952 deletions
|
@ -1,793 +0,0 @@
|
|||
/* LzFindMt.c -- multithreaded Match finder for LZ algorithms
|
||||
2009-09-20 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "LzHash.h"
|
||||
|
||||
#include "LzFindMt.h"
|
||||
|
||||
void MtSync_Construct(CMtSync *p)
|
||||
{
|
||||
p->wasCreated = False;
|
||||
p->csWasInitialized = False;
|
||||
p->csWasEntered = False;
|
||||
Thread_Construct(&p->thread);
|
||||
Event_Construct(&p->canStart);
|
||||
Event_Construct(&p->wasStarted);
|
||||
Event_Construct(&p->wasStopped);
|
||||
Semaphore_Construct(&p->freeSemaphore);
|
||||
Semaphore_Construct(&p->filledSemaphore);
|
||||
}
|
||||
|
||||
void MtSync_GetNextBlock(CMtSync *p)
|
||||
{
|
||||
if (p->needStart)
|
||||
{
|
||||
p->numProcessedBlocks = 1;
|
||||
p->needStart = False;
|
||||
p->stopWriting = False;
|
||||
p->exit = False;
|
||||
Event_Reset(&p->wasStarted);
|
||||
Event_Reset(&p->wasStopped);
|
||||
|
||||
Event_Set(&p->canStart);
|
||||
Event_Wait(&p->wasStarted);
|
||||
}
|
||||
else
|
||||
{
|
||||
CriticalSection_Leave(&p->cs);
|
||||
p->csWasEntered = False;
|
||||
p->numProcessedBlocks++;
|
||||
Semaphore_Release1(&p->freeSemaphore);
|
||||
}
|
||||
Semaphore_Wait(&p->filledSemaphore);
|
||||
CriticalSection_Enter(&p->cs);
|
||||
p->csWasEntered = True;
|
||||
}
|
||||
|
||||
/* MtSync_StopWriting must be called if Writing was started */
|
||||
|
||||
void MtSync_StopWriting(CMtSync *p)
|
||||
{
|
||||
UInt32 myNumBlocks = p->numProcessedBlocks;
|
||||
if (!Thread_WasCreated(&p->thread) || p->needStart)
|
||||
return;
|
||||
p->stopWriting = True;
|
||||
if (p->csWasEntered)
|
||||
{
|
||||
CriticalSection_Leave(&p->cs);
|
||||
p->csWasEntered = False;
|
||||
}
|
||||
Semaphore_Release1(&p->freeSemaphore);
|
||||
|
||||
Event_Wait(&p->wasStopped);
|
||||
|
||||
while (myNumBlocks++ != p->numProcessedBlocks)
|
||||
{
|
||||
Semaphore_Wait(&p->filledSemaphore);
|
||||
Semaphore_Release1(&p->freeSemaphore);
|
||||
}
|
||||
p->needStart = True;
|
||||
}
|
||||
|
||||
void MtSync_Destruct(CMtSync *p)
|
||||
{
|
||||
if (Thread_WasCreated(&p->thread))
|
||||
{
|
||||
MtSync_StopWriting(p);
|
||||
p->exit = True;
|
||||
if (p->needStart)
|
||||
Event_Set(&p->canStart);
|
||||
Thread_Wait(&p->thread);
|
||||
Thread_Close(&p->thread);
|
||||
}
|
||||
if (p->csWasInitialized)
|
||||
{
|
||||
CriticalSection_Delete(&p->cs);
|
||||
p->csWasInitialized = False;
|
||||
}
|
||||
|
||||
Event_Close(&p->canStart);
|
||||
Event_Close(&p->wasStarted);
|
||||
Event_Close(&p->wasStopped);
|
||||
Semaphore_Close(&p->freeSemaphore);
|
||||
Semaphore_Close(&p->filledSemaphore);
|
||||
|
||||
p->wasCreated = False;
|
||||
}
|
||||
|
||||
#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }
|
||||
|
||||
static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks)
|
||||
{
|
||||
if (p->wasCreated)
|
||||
return SZ_OK;
|
||||
|
||||
RINOK_THREAD(CriticalSection_Init(&p->cs));
|
||||
p->csWasInitialized = True;
|
||||
|
||||
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart));
|
||||
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStarted));
|
||||
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped));
|
||||
|
||||
RINOK_THREAD(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks));
|
||||
RINOK_THREAD(Semaphore_Create(&p->filledSemaphore, 0, numBlocks));
|
||||
|
||||
p->needStart = True;
|
||||
|
||||
RINOK_THREAD(Thread_Create(&p->thread, startAddress, obj));
|
||||
p->wasCreated = True;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static SRes MtSync_Create(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks)
|
||||
{
|
||||
SRes res = MtSync_Create2(p, startAddress, obj, numBlocks);
|
||||
if (res != SZ_OK)
|
||||
MtSync_Destruct(p);
|
||||
return res;
|
||||
}
|
||||
|
||||
void MtSync_Init(CMtSync *p) { p->needStart = True; }
|
||||
|
||||
#define kMtMaxValForNormalize 0xFFFFFFFF
|
||||
|
||||
#define DEF_GetHeads2(name, v, action) \
|
||||
static void GetHeads ## name(const Byte *p, UInt32 pos, \
|
||||
UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \
|
||||
{ action; for (; numHeads != 0; numHeads--) { \
|
||||
const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } }
|
||||
|
||||
#define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;)
|
||||
|
||||
DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc; )
|
||||
DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask)
|
||||
DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask)
|
||||
DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask)
|
||||
/* DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */
|
||||
|
||||
void HashThreadFunc(CMatchFinderMt *mt)
|
||||
{
|
||||
CMtSync *p = &mt->hashSync;
|
||||
for (;;)
|
||||
{
|
||||
UInt32 numProcessedBlocks = 0;
|
||||
Event_Wait(&p->canStart);
|
||||
Event_Set(&p->wasStarted);
|
||||
for (;;)
|
||||
{
|
||||
if (p->exit)
|
||||
return;
|
||||
if (p->stopWriting)
|
||||
{
|
||||
p->numProcessedBlocks = numProcessedBlocks;
|
||||
Event_Set(&p->wasStopped);
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
CMatchFinder *mf = mt->MatchFinder;
|
||||
if (MatchFinder_NeedMove(mf))
|
||||
{
|
||||
CriticalSection_Enter(&mt->btSync.cs);
|
||||
CriticalSection_Enter(&mt->hashSync.cs);
|
||||
{
|
||||
const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf);
|
||||
const Byte *afterPtr;
|
||||
MatchFinder_MoveBlock(mf);
|
||||
afterPtr = MatchFinder_GetPointerToCurrentPos(mf);
|
||||
mt->pointerToCurPos -= beforePtr - afterPtr;
|
||||
mt->buffer -= beforePtr - afterPtr;
|
||||
}
|
||||
CriticalSection_Leave(&mt->btSync.cs);
|
||||
CriticalSection_Leave(&mt->hashSync.cs);
|
||||
continue;
|
||||
}
|
||||
|
||||
Semaphore_Wait(&p->freeSemaphore);
|
||||
|
||||
MatchFinder_ReadIfRequired(mf);
|
||||
if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize))
|
||||
{
|
||||
UInt32 subValue = (mf->pos - mf->historySize - 1);
|
||||
MatchFinder_ReduceOffsets(mf, subValue);
|
||||
MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1);
|
||||
}
|
||||
{
|
||||
UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize;
|
||||
UInt32 num = mf->streamPos - mf->pos;
|
||||
heads[0] = 2;
|
||||
heads[1] = num;
|
||||
if (num >= mf->numHashBytes)
|
||||
{
|
||||
num = num - mf->numHashBytes + 1;
|
||||
if (num > kMtHashBlockSize - 2)
|
||||
num = kMtHashBlockSize - 2;
|
||||
mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc);
|
||||
heads[0] += num;
|
||||
}
|
||||
mf->pos += num;
|
||||
mf->buffer += num;
|
||||
}
|
||||
}
|
||||
|
||||
Semaphore_Release1(&p->filledSemaphore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
|
||||
{
|
||||
MtSync_GetNextBlock(&p->hashSync);
|
||||
p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize;
|
||||
p->hashBufPosLimit += p->hashBuf[p->hashBufPos++];
|
||||
p->hashNumAvail = p->hashBuf[p->hashBufPos++];
|
||||
}
|
||||
|
||||
#define kEmptyHashValue 0
|
||||
|
||||
/* #define MFMT_GM_INLINE */
|
||||
|
||||
#ifdef MFMT_GM_INLINE
|
||||
|
||||
#define NO_INLINE MY_FAST_CALL
|
||||
|
||||
Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,
|
||||
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
|
||||
UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes)
|
||||
{
|
||||
do
|
||||
{
|
||||
UInt32 *distances = _distances + 1;
|
||||
UInt32 curMatch = pos - *hash++;
|
||||
|
||||
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
|
||||
CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
|
||||
UInt32 len0 = 0, len1 = 0;
|
||||
UInt32 cutValue = _cutValue;
|
||||
UInt32 maxLen = _maxLen;
|
||||
for (;;)
|
||||
{
|
||||
UInt32 delta = pos - curMatch;
|
||||
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
|
||||
{
|
||||
*ptr0 = *ptr1 = kEmptyHashValue;
|
||||
break;
|
||||
}
|
||||
{
|
||||
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
|
||||
const Byte *pb = cur - delta;
|
||||
UInt32 len = (len0 < len1 ? len0 : len1);
|
||||
if (pb[len] == cur[len])
|
||||
{
|
||||
if (++len != lenLimit && pb[len] == cur[len])
|
||||
while (++len != lenLimit)
|
||||
if (pb[len] != cur[len])
|
||||
break;
|
||||
if (maxLen < len)
|
||||
{
|
||||
*distances++ = maxLen = len;
|
||||
*distances++ = delta - 1;
|
||||
if (len == lenLimit)
|
||||
{
|
||||
*ptr1 = pair[0];
|
||||
*ptr0 = pair[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pb[len] < cur[len])
|
||||
{
|
||||
*ptr1 = curMatch;
|
||||
ptr1 = pair + 1;
|
||||
curMatch = *ptr1;
|
||||
len1 = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr0 = curMatch;
|
||||
ptr0 = pair;
|
||||
curMatch = *ptr0;
|
||||
len0 = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
pos++;
|
||||
_cyclicBufferPos++;
|
||||
cur++;
|
||||
{
|
||||
UInt32 num = (UInt32)(distances - _distances);
|
||||
*_distances = num - 1;
|
||||
_distances += num;
|
||||
limit -= num;
|
||||
}
|
||||
}
|
||||
while (limit > 0 && --size != 0);
|
||||
*posRes = pos;
|
||||
return limit;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||
{
|
||||
UInt32 numProcessed = 0;
|
||||
UInt32 curPos = 2;
|
||||
UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2);
|
||||
distances[1] = p->hashNumAvail;
|
||||
while (curPos < limit)
|
||||
{
|
||||
if (p->hashBufPos == p->hashBufPosLimit)
|
||||
{
|
||||
MatchFinderMt_GetNextBlock_Hash(p);
|
||||
distances[1] = numProcessed + p->hashNumAvail;
|
||||
if (p->hashNumAvail >= p->numHashBytes)
|
||||
continue;
|
||||
for (; p->hashNumAvail != 0; p->hashNumAvail--)
|
||||
distances[curPos++] = 0;
|
||||
break;
|
||||
}
|
||||
{
|
||||
UInt32 size = p->hashBufPosLimit - p->hashBufPos;
|
||||
UInt32 lenLimit = p->matchMaxLen;
|
||||
UInt32 pos = p->pos;
|
||||
UInt32 cyclicBufferPos = p->cyclicBufferPos;
|
||||
if (lenLimit >= p->hashNumAvail)
|
||||
lenLimit = p->hashNumAvail;
|
||||
{
|
||||
UInt32 size2 = p->hashNumAvail - lenLimit + 1;
|
||||
if (size2 < size)
|
||||
size = size2;
|
||||
size2 = p->cyclicBufferSize - cyclicBufferPos;
|
||||
if (size2 < size)
|
||||
size = size2;
|
||||
}
|
||||
#ifndef MFMT_GM_INLINE
|
||||
while (curPos < limit && size-- != 0)
|
||||
{
|
||||
UInt32 *startDistances = distances + curPos;
|
||||
UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++],
|
||||
pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
|
||||
startDistances + 1, p->numHashBytes - 1) - startDistances);
|
||||
*startDistances = num - 1;
|
||||
curPos += num;
|
||||
cyclicBufferPos++;
|
||||
pos++;
|
||||
p->buffer++;
|
||||
}
|
||||
#else
|
||||
{
|
||||
UInt32 posRes;
|
||||
curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
|
||||
distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes);
|
||||
p->hashBufPos += posRes - pos;
|
||||
cyclicBufferPos += posRes - pos;
|
||||
p->buffer += posRes - pos;
|
||||
pos = posRes;
|
||||
}
|
||||
#endif
|
||||
|
||||
numProcessed += pos - p->pos;
|
||||
p->hashNumAvail -= pos - p->pos;
|
||||
p->pos = pos;
|
||||
if (cyclicBufferPos == p->cyclicBufferSize)
|
||||
cyclicBufferPos = 0;
|
||||
p->cyclicBufferPos = cyclicBufferPos;
|
||||
}
|
||||
}
|
||||
distances[0] = curPos;
|
||||
}
|
||||
|
||||
void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
|
||||
{
|
||||
CMtSync *sync = &p->hashSync;
|
||||
if (!sync->needStart)
|
||||
{
|
||||
CriticalSection_Enter(&sync->cs);
|
||||
sync->csWasEntered = True;
|
||||
}
|
||||
|
||||
BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize);
|
||||
|
||||
if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize)
|
||||
{
|
||||
UInt32 subValue = p->pos - p->cyclicBufferSize;
|
||||
MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2);
|
||||
p->pos -= subValue;
|
||||
}
|
||||
|
||||
if (!sync->needStart)
|
||||
{
|
||||
CriticalSection_Leave(&sync->cs);
|
||||
sync->csWasEntered = False;
|
||||
}
|
||||
}
|
||||
|
||||
void BtThreadFunc(CMatchFinderMt *mt)
|
||||
{
|
||||
CMtSync *p = &mt->btSync;
|
||||
for (;;)
|
||||
{
|
||||
UInt32 blockIndex = 0;
|
||||
Event_Wait(&p->canStart);
|
||||
Event_Set(&p->wasStarted);
|
||||
for (;;)
|
||||
{
|
||||
if (p->exit)
|
||||
return;
|
||||
if (p->stopWriting)
|
||||
{
|
||||
p->numProcessedBlocks = blockIndex;
|
||||
MtSync_StopWriting(&mt->hashSync);
|
||||
Event_Set(&p->wasStopped);
|
||||
break;
|
||||
}
|
||||
Semaphore_Wait(&p->freeSemaphore);
|
||||
BtFillBlock(mt, blockIndex++);
|
||||
Semaphore_Release1(&p->filledSemaphore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MatchFinderMt_Construct(CMatchFinderMt *p)
|
||||
{
|
||||
p->hashBuf = 0;
|
||||
MtSync_Construct(&p->hashSync);
|
||||
MtSync_Construct(&p->btSync);
|
||||
}
|
||||
|
||||
void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc)
|
||||
{
|
||||
alloc->Free(alloc, p->hashBuf);
|
||||
p->hashBuf = 0;
|
||||
}
|
||||
|
||||
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)
|
||||
{
|
||||
MtSync_Destruct(&p->hashSync);
|
||||
MtSync_Destruct(&p->btSync);
|
||||
MatchFinderMt_FreeMem(p, alloc);
|
||||
}
|
||||
|
||||
#define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks)
|
||||
#define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks)
|
||||
|
||||
static unsigned MY_STD_CALL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; }
|
||||
static unsigned MY_STD_CALL BtThreadFunc2(void *p)
|
||||
{
|
||||
Byte allocaDummy[0x180];
|
||||
int i = 0;
|
||||
for (i = 0; i < 16; i++)
|
||||
allocaDummy[i] = (Byte)i;
|
||||
BtThreadFunc((CMatchFinderMt *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
|
||||
UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc)
|
||||
{
|
||||
CMatchFinder *mf = p->MatchFinder;
|
||||
p->historySize = historySize;
|
||||
if (kMtBtBlockSize <= matchMaxLen * 4)
|
||||
return SZ_ERROR_PARAM;
|
||||
if (p->hashBuf == 0)
|
||||
{
|
||||
p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32));
|
||||
if (p->hashBuf == 0)
|
||||
return SZ_ERROR_MEM;
|
||||
p->btBuf = p->hashBuf + kHashBufferSize;
|
||||
}
|
||||
keepAddBufferBefore += (kHashBufferSize + kBtBufferSize);
|
||||
keepAddBufferAfter += kMtHashBlockSize;
|
||||
if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc))
|
||||
return SZ_ERROR_MEM;
|
||||
|
||||
RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks));
|
||||
RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks));
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
/* Call it after ReleaseStream / SetStream */
|
||||
void MatchFinderMt_Init(CMatchFinderMt *p)
|
||||
{
|
||||
CMatchFinder *mf = p->MatchFinder;
|
||||
p->btBufPos = p->btBufPosLimit = 0;
|
||||
p->hashBufPos = p->hashBufPosLimit = 0;
|
||||
MatchFinder_Init(mf);
|
||||
p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf);
|
||||
p->btNumAvailBytes = 0;
|
||||
p->lzPos = p->historySize + 1;
|
||||
|
||||
p->hash = mf->hash;
|
||||
p->fixedHashSize = mf->fixedHashSize;
|
||||
p->crc = mf->crc;
|
||||
|
||||
p->son = mf->son;
|
||||
p->matchMaxLen = mf->matchMaxLen;
|
||||
p->numHashBytes = mf->numHashBytes;
|
||||
p->pos = mf->pos;
|
||||
p->buffer = mf->buffer;
|
||||
p->cyclicBufferPos = mf->cyclicBufferPos;
|
||||
p->cyclicBufferSize = mf->cyclicBufferSize;
|
||||
p->cutValue = mf->cutValue;
|
||||
}
|
||||
|
||||
/* ReleaseStream is required to finish multithreading */
|
||||
void MatchFinderMt_ReleaseStream(CMatchFinderMt *p)
|
||||
{
|
||||
MtSync_StopWriting(&p->btSync);
|
||||
/* p->MatchFinder->ReleaseStream(); */
|
||||
}
|
||||
|
||||
void MatchFinderMt_Normalize(CMatchFinderMt *p)
|
||||
{
|
||||
MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize);
|
||||
p->lzPos = p->historySize + 1;
|
||||
}
|
||||
|
||||
void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
|
||||
{
|
||||
UInt32 blockIndex;
|
||||
MtSync_GetNextBlock(&p->btSync);
|
||||
blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask);
|
||||
p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize;
|
||||
p->btBufPosLimit += p->btBuf[p->btBufPos++];
|
||||
p->btNumAvailBytes = p->btBuf[p->btBufPos++];
|
||||
if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize)
|
||||
MatchFinderMt_Normalize(p);
|
||||
}
|
||||
|
||||
const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)
|
||||
{
|
||||
return p->pointerToCurPos;
|
||||
}
|
||||
|
||||
#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p);
|
||||
|
||||
UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p)
|
||||
{
|
||||
GET_NEXT_BLOCK_IF_REQUIRED;
|
||||
return p->btNumAvailBytes;
|
||||
}
|
||||
|
||||
Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index)
|
||||
{
|
||||
return p->pointerToCurPos[index];
|
||||
}
|
||||
|
||||
UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
||||
{
|
||||
UInt32 hash2Value, curMatch2;
|
||||
UInt32 *hash = p->hash;
|
||||
const Byte *cur = p->pointerToCurPos;
|
||||
UInt32 lzPos = p->lzPos;
|
||||
MT_HASH2_CALC
|
||||
|
||||
curMatch2 = hash[hash2Value];
|
||||
hash[hash2Value] = lzPos;
|
||||
|
||||
if (curMatch2 >= matchMinPos)
|
||||
if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
|
||||
{
|
||||
*distances++ = 2;
|
||||
*distances++ = lzPos - curMatch2 - 1;
|
||||
}
|
||||
return distances;
|
||||
}
|
||||
|
||||
UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
||||
{
|
||||
UInt32 hash2Value, hash3Value, curMatch2, curMatch3;
|
||||
UInt32 *hash = p->hash;
|
||||
const Byte *cur = p->pointerToCurPos;
|
||||
UInt32 lzPos = p->lzPos;
|
||||
MT_HASH3_CALC
|
||||
|
||||
curMatch2 = hash[ hash2Value];
|
||||
curMatch3 = hash[kFix3HashSize + hash3Value];
|
||||
|
||||
hash[ hash2Value] =
|
||||
hash[kFix3HashSize + hash3Value] =
|
||||
lzPos;
|
||||
|
||||
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
|
||||
{
|
||||
distances[1] = lzPos - curMatch2 - 1;
|
||||
if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
|
||||
{
|
||||
distances[0] = 3;
|
||||
return distances + 2;
|
||||
}
|
||||
distances[0] = 2;
|
||||
distances += 2;
|
||||
}
|
||||
if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
|
||||
{
|
||||
*distances++ = 3;
|
||||
*distances++ = lzPos - curMatch3 - 1;
|
||||
}
|
||||
return distances;
|
||||
}
|
||||
|
||||
/*
|
||||
UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
||||
{
|
||||
UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4;
|
||||
UInt32 *hash = p->hash;
|
||||
const Byte *cur = p->pointerToCurPos;
|
||||
UInt32 lzPos = p->lzPos;
|
||||
MT_HASH4_CALC
|
||||
|
||||
curMatch2 = hash[ hash2Value];
|
||||
curMatch3 = hash[kFix3HashSize + hash3Value];
|
||||
curMatch4 = hash[kFix4HashSize + hash4Value];
|
||||
|
||||
hash[ hash2Value] =
|
||||
hash[kFix3HashSize + hash3Value] =
|
||||
hash[kFix4HashSize + hash4Value] =
|
||||
lzPos;
|
||||
|
||||
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
|
||||
{
|
||||
distances[1] = lzPos - curMatch2 - 1;
|
||||
if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
|
||||
{
|
||||
distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;
|
||||
return distances + 2;
|
||||
}
|
||||
distances[0] = 2;
|
||||
distances += 2;
|
||||
}
|
||||
if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
|
||||
{
|
||||
distances[1] = lzPos - curMatch3 - 1;
|
||||
if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3])
|
||||
{
|
||||
distances[0] = 4;
|
||||
return distances + 2;
|
||||
}
|
||||
distances[0] = 3;
|
||||
distances += 2;
|
||||
}
|
||||
|
||||
if (curMatch4 >= matchMinPos)
|
||||
if (
|
||||
cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] &&
|
||||
cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3]
|
||||
)
|
||||
{
|
||||
*distances++ = 4;
|
||||
*distances++ = lzPos - curMatch4 - 1;
|
||||
}
|
||||
return distances;
|
||||
}
|
||||
*/
|
||||
|
||||
#define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++;
|
||||
|
||||
UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||
{
|
||||
const UInt32 *btBuf = p->btBuf + p->btBufPos;
|
||||
UInt32 len = *btBuf++;
|
||||
p->btBufPos += 1 + len;
|
||||
p->btNumAvailBytes--;
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < len; i += 2)
|
||||
{
|
||||
*distances++ = *btBuf++;
|
||||
*distances++ = *btBuf++;
|
||||
}
|
||||
}
|
||||
INCREASE_LZ_POS
|
||||
return len;
|
||||
}
|
||||
|
||||
UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||
{
|
||||
const UInt32 *btBuf = p->btBuf + p->btBufPos;
|
||||
UInt32 len = *btBuf++;
|
||||
p->btBufPos += 1 + len;
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
if (p->btNumAvailBytes-- >= 4)
|
||||
len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Condition: there are matches in btBuf with length < p->numHashBytes */
|
||||
UInt32 *distances2;
|
||||
p->btNumAvailBytes--;
|
||||
distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances);
|
||||
do
|
||||
{
|
||||
*distances2++ = *btBuf++;
|
||||
*distances2++ = *btBuf++;
|
||||
}
|
||||
while ((len -= 2) != 0);
|
||||
len = (UInt32)(distances2 - (distances));
|
||||
}
|
||||
INCREASE_LZ_POS
|
||||
return len;
|
||||
}
|
||||
|
||||
#define SKIP_HEADER2_MT do { GET_NEXT_BLOCK_IF_REQUIRED
|
||||
#define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;
|
||||
#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0);
|
||||
|
||||
void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num)
|
||||
{
|
||||
SKIP_HEADER2_MT { p->btNumAvailBytes--;
|
||||
SKIP_FOOTER_MT
|
||||
}
|
||||
|
||||
void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)
|
||||
{
|
||||
SKIP_HEADER_MT(2)
|
||||
UInt32 hash2Value;
|
||||
MT_HASH2_CALC
|
||||
hash[hash2Value] = p->lzPos;
|
||||
SKIP_FOOTER_MT
|
||||
}
|
||||
|
||||
void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)
|
||||
{
|
||||
SKIP_HEADER_MT(3)
|
||||
UInt32 hash2Value, hash3Value;
|
||||
MT_HASH3_CALC
|
||||
hash[kFix3HashSize + hash3Value] =
|
||||
hash[ hash2Value] =
|
||||
p->lzPos;
|
||||
SKIP_FOOTER_MT
|
||||
}
|
||||
|
||||
/*
|
||||
void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
|
||||
{
|
||||
SKIP_HEADER_MT(4)
|
||||
UInt32 hash2Value, hash3Value, hash4Value;
|
||||
MT_HASH4_CALC
|
||||
hash[kFix4HashSize + hash4Value] =
|
||||
hash[kFix3HashSize + hash3Value] =
|
||||
hash[ hash2Value] =
|
||||
p->lzPos;
|
||||
SKIP_FOOTER_MT
|
||||
}
|
||||
*/
|
||||
|
||||
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)
|
||||
{
|
||||
vTable->Init = (Mf_Init_Func)MatchFinderMt_Init;
|
||||
vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte;
|
||||
vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes;
|
||||
vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos;
|
||||
vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches;
|
||||
switch(p->MatchFinder->numHashBytes)
|
||||
{
|
||||
case 2:
|
||||
p->GetHeadsFunc = GetHeads2;
|
||||
p->MixMatchesFunc = (Mf_Mix_Matches)0;
|
||||
vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip;
|
||||
vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches;
|
||||
break;
|
||||
case 3:
|
||||
p->GetHeadsFunc = GetHeads3;
|
||||
p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2;
|
||||
vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip;
|
||||
break;
|
||||
default:
|
||||
/* case 4: */
|
||||
p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4;
|
||||
/* p->GetHeadsFunc = GetHeads4; */
|
||||
p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3;
|
||||
vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip;
|
||||
break;
|
||||
/*
|
||||
default:
|
||||
p->GetHeadsFunc = GetHeads5;
|
||||
p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4;
|
||||
vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip;
|
||||
break;
|
||||
*/
|
||||
}
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
/* LzFindMt.h -- multithreaded Match finder for LZ algorithms
|
||||
2009-02-07 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZ_FIND_MT_H
|
||||
#define __LZ_FIND_MT_H
|
||||
|
||||
#include "LzFind.h"
|
||||
#include "Threads.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define kMtHashBlockSize (1 << 13)
|
||||
#define kMtHashNumBlocks (1 << 3)
|
||||
#define kMtHashNumBlocksMask (kMtHashNumBlocks - 1)
|
||||
|
||||
#define kMtBtBlockSize (1 << 14)
|
||||
#define kMtBtNumBlocks (1 << 6)
|
||||
#define kMtBtNumBlocksMask (kMtBtNumBlocks - 1)
|
||||
|
||||
typedef struct _CMtSync
|
||||
{
|
||||
Bool wasCreated;
|
||||
Bool needStart;
|
||||
Bool exit;
|
||||
Bool stopWriting;
|
||||
|
||||
CThread thread;
|
||||
CAutoResetEvent canStart;
|
||||
CAutoResetEvent wasStarted;
|
||||
CAutoResetEvent wasStopped;
|
||||
CSemaphore freeSemaphore;
|
||||
CSemaphore filledSemaphore;
|
||||
Bool csWasInitialized;
|
||||
Bool csWasEntered;
|
||||
CCriticalSection cs;
|
||||
UInt32 numProcessedBlocks;
|
||||
} CMtSync;
|
||||
|
||||
typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances);
|
||||
|
||||
/* kMtCacheLineDummy must be >= size_of_CPU_cache_line */
|
||||
#define kMtCacheLineDummy 128
|
||||
|
||||
typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos,
|
||||
UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc);
|
||||
|
||||
typedef struct _CMatchFinderMt
|
||||
{
|
||||
/* LZ */
|
||||
const Byte *pointerToCurPos;
|
||||
UInt32 *btBuf;
|
||||
UInt32 btBufPos;
|
||||
UInt32 btBufPosLimit;
|
||||
UInt32 lzPos;
|
||||
UInt32 btNumAvailBytes;
|
||||
|
||||
UInt32 *hash;
|
||||
UInt32 fixedHashSize;
|
||||
UInt32 historySize;
|
||||
const UInt32 *crc;
|
||||
|
||||
Mf_Mix_Matches MixMatchesFunc;
|
||||
|
||||
/* LZ + BT */
|
||||
CMtSync btSync;
|
||||
Byte btDummy[kMtCacheLineDummy];
|
||||
|
||||
/* BT */
|
||||
UInt32 *hashBuf;
|
||||
UInt32 hashBufPos;
|
||||
UInt32 hashBufPosLimit;
|
||||
UInt32 hashNumAvail;
|
||||
|
||||
CLzRef *son;
|
||||
UInt32 matchMaxLen;
|
||||
UInt32 numHashBytes;
|
||||
UInt32 pos;
|
||||
Byte *buffer;
|
||||
UInt32 cyclicBufferPos;
|
||||
UInt32 cyclicBufferSize; /* it must be historySize + 1 */
|
||||
UInt32 cutValue;
|
||||
|
||||
/* BT + Hash */
|
||||
CMtSync hashSync;
|
||||
/* Byte hashDummy[kMtCacheLineDummy]; */
|
||||
|
||||
/* Hash */
|
||||
Mf_GetHeads GetHeadsFunc;
|
||||
CMatchFinder *MatchFinder;
|
||||
} CMatchFinderMt;
|
||||
|
||||
void MatchFinderMt_Construct(CMatchFinderMt *p);
|
||||
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc);
|
||||
SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
|
||||
UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc);
|
||||
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable);
|
||||
void MatchFinderMt_ReleaseStream(CMatchFinderMt *p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,477 +0,0 @@
|
|||
/* Lzma2Enc.c -- LZMA2 Encoder
|
||||
2010-09-24 : Igor Pavlov : Public domain */
|
||||
|
||||
/* #include <stdio.h> */
|
||||
#include <string.h>
|
||||
|
||||
/* #define _7ZIP_ST */
|
||||
|
||||
#include "Lzma2Enc.h"
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
#include "MtCoder.h"
|
||||
#else
|
||||
#define NUM_MT_CODER_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 */
|
||||
|
||||
/* ---------- CLzma2EncInt ---------- */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CLzmaEncHandle enc;
|
||||
UInt64 srcPos;
|
||||
Byte props;
|
||||
Bool needInitState;
|
||||
Bool needInitProp;
|
||||
} CLzma2EncInt;
|
||||
|
||||
static SRes Lzma2EncInt_Init(CLzma2EncInt *p, const CLzma2EncProps *props)
|
||||
{
|
||||
Byte propsEncoded[LZMA_PROPS_SIZE];
|
||||
SizeT propsSize = LZMA_PROPS_SIZE;
|
||||
RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps));
|
||||
RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize));
|
||||
p->srcPos = 0;
|
||||
p->props = propsEncoded[0];
|
||||
p->needInitState = True;
|
||||
p->needInitProp = True;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize,
|
||||
ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||
SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
|
||||
UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||
SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool 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);
|
||||
|
||||
|
||||
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);
|
||||
Bool 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 (outStream->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->props;
|
||||
|
||||
p->needInitProp = False;
|
||||
p->needInitState = False;
|
||||
destPos += packSize;
|
||||
p->srcPos += unpackSize;
|
||||
|
||||
if (outStream)
|
||||
if (outStream->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->numTotalThreads = -1;
|
||||
p->numBlockThreads = -1;
|
||||
p->blockSize = 0;
|
||||
}
|
||||
|
||||
void Lzma2EncProps_Normalize(CLzma2EncProps *p)
|
||||
{
|
||||
int t1, t1n, t2, t3;
|
||||
{
|
||||
CLzmaEncProps lzmaProps = p->lzmaProps;
|
||||
LzmaEncProps_Normalize(&lzmaProps);
|
||||
t1n = lzmaProps.numThreads;
|
||||
}
|
||||
|
||||
t1 = p->lzmaProps.numThreads;
|
||||
t2 = p->numBlockThreads;
|
||||
t3 = p->numTotalThreads;
|
||||
|
||||
if (t2 > NUM_MT_CODER_THREADS_MAX)
|
||||
t2 = NUM_MT_CODER_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 > NUM_MT_CODER_THREADS_MAX)
|
||||
t2 = NUM_MT_CODER_THREADS_MAX;
|
||||
}
|
||||
else if (t1 <= 0)
|
||||
{
|
||||
t1 = t3 / t2;
|
||||
if (t1 == 0)
|
||||
t1 = 1;
|
||||
}
|
||||
else
|
||||
t3 = t1n * t2;
|
||||
|
||||
p->lzmaProps.numThreads = t1;
|
||||
p->numBlockThreads = t2;
|
||||
p->numTotalThreads = t3;
|
||||
LzmaEncProps_Normalize(&p->lzmaProps);
|
||||
|
||||
if (p->blockSize == 0)
|
||||
{
|
||||
UInt32 dictSize = p->lzmaProps.dictSize;
|
||||
UInt64 blockSize = (UInt64)dictSize << 2;
|
||||
const UInt32 kMinSize = (UInt32)1 << 20;
|
||||
const UInt32 kMaxSize = (UInt32)1 << 28;
|
||||
if (blockSize < kMinSize) blockSize = kMinSize;
|
||||
if (blockSize > kMaxSize) blockSize = kMaxSize;
|
||||
if (blockSize < dictSize) blockSize = dictSize;
|
||||
p->blockSize = (size_t)blockSize;
|
||||
}
|
||||
}
|
||||
|
||||
static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
|
||||
{
|
||||
return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
|
||||
}
|
||||
|
||||
/* ---------- Lzma2 ---------- */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Byte propEncoded;
|
||||
CLzma2EncProps props;
|
||||
|
||||
Byte *outBuf;
|
||||
|
||||
ISzAlloc *alloc;
|
||||
ISzAlloc *allocBig;
|
||||
|
||||
CLzma2EncInt coders[NUM_MT_CODER_THREADS_MAX];
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
CMtCoder mtCoder;
|
||||
#endif
|
||||
|
||||
} CLzma2Enc;
|
||||
|
||||
|
||||
/* ---------- Lzma2EncThread ---------- */
|
||||
|
||||
static SRes Lzma2Enc_EncodeMt1(CLzma2EncInt *p, CLzma2Enc *mainEncoder,
|
||||
ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)
|
||||
{
|
||||
UInt64 packTotal = 0;
|
||||
SRes res = SZ_OK;
|
||||
|
||||
if (mainEncoder->outBuf == 0)
|
||||
{
|
||||
mainEncoder->outBuf = (Byte *)IAlloc_Alloc(mainEncoder->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);
|
||||
if (mainEncoder->outBuf == 0)
|
||||
return SZ_ERROR_MEM;
|
||||
}
|
||||
RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));
|
||||
RINOK(LzmaEnc_PrepareForLzma2(p->enc, inStream, LZMA2_KEEP_WINDOW_SIZE,
|
||||
mainEncoder->alloc, mainEncoder->allocBig));
|
||||
for (;;)
|
||||
{
|
||||
size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;
|
||||
res = Lzma2EncInt_EncodeSubblock(p, mainEncoder->outBuf, &packSize, outStream);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
packTotal += packSize;
|
||||
res = Progress(progress, p->srcPos, packTotal);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
if (packSize == 0)
|
||||
break;
|
||||
}
|
||||
LzmaEnc_Finish(p->enc);
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
Byte b = 0;
|
||||
if (outStream->Write(outStream, &b, 1) != 1)
|
||||
return SZ_ERROR_WRITE;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IMtCoderCallback funcTable;
|
||||
CLzma2Enc *lzma2Enc;
|
||||
} CMtCallbackImp;
|
||||
|
||||
static SRes MtCallbackImp_Code(void *pp, unsigned index, Byte *dest, size_t *destSize,
|
||||
const Byte *src, size_t srcSize, int finished)
|
||||
{
|
||||
CMtCallbackImp *imp = (CMtCallbackImp *)pp;
|
||||
CLzma2Enc *mainEncoder = imp->lzma2Enc;
|
||||
CLzma2EncInt *p = &mainEncoder->coders[index];
|
||||
|
||||
SRes res = SZ_OK;
|
||||
{
|
||||
size_t destLim = *destSize;
|
||||
*destSize = 0;
|
||||
|
||||
if (srcSize != 0)
|
||||
{
|
||||
RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));
|
||||
|
||||
RINOK(LzmaEnc_MemPrepare(p->enc, src, srcSize, LZMA2_KEEP_WINDOW_SIZE,
|
||||
mainEncoder->alloc, mainEncoder->allocBig));
|
||||
|
||||
while (p->srcPos < srcSize)
|
||||
{
|
||||
size_t packSize = destLim - *destSize;
|
||||
res = Lzma2EncInt_EncodeSubblock(p, dest + *destSize, &packSize, NULL);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
*destSize += packSize;
|
||||
|
||||
if (packSize == 0)
|
||||
{
|
||||
res = SZ_ERROR_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (MtProgress_Set(&mainEncoder->mtCoder.mtProgress, index, p->srcPos, *destSize) != SZ_OK)
|
||||
{
|
||||
res = SZ_ERROR_PROGRESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
LzmaEnc_Finish(p->enc);
|
||||
if (res != SZ_OK)
|
||||
return res;
|
||||
}
|
||||
if (finished)
|
||||
{
|
||||
if (*destSize == destLim)
|
||||
return SZ_ERROR_OUTPUT_EOF;
|
||||
dest[(*destSize)++] = 0;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ---------- Lzma2Enc ---------- */
|
||||
|
||||
CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig)
|
||||
{
|
||||
CLzma2Enc *p = (CLzma2Enc *)alloc->Alloc(alloc, sizeof(CLzma2Enc));
|
||||
if (p == 0)
|
||||
return NULL;
|
||||
Lzma2EncProps_Init(&p->props);
|
||||
Lzma2EncProps_Normalize(&p->props);
|
||||
p->outBuf = 0;
|
||||
p->alloc = alloc;
|
||||
p->allocBig = allocBig;
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
|
||||
p->coders[i].enc = 0;
|
||||
}
|
||||
#ifndef _7ZIP_ST
|
||||
MtCoder_Construct(&p->mtCoder);
|
||||
#endif
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void Lzma2Enc_Destroy(CLzma2EncHandle pp)
|
||||
{
|
||||
CLzma2Enc *p = (CLzma2Enc *)pp;
|
||||
unsigned i;
|
||||
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
|
||||
{
|
||||
CLzma2EncInt *t = &p->coders[i];
|
||||
if (t->enc)
|
||||
{
|
||||
LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig);
|
||||
t->enc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
MtCoder_Destruct(&p->mtCoder);
|
||||
#endif
|
||||
|
||||
IAlloc_Free(p->alloc, p->outBuf);
|
||||
IAlloc_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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
SRes Lzma2Enc_Encode(CLzma2EncHandle pp,
|
||||
ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)
|
||||
{
|
||||
CLzma2Enc *p = (CLzma2Enc *)pp;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < p->props.numBlockThreads; i++)
|
||||
{
|
||||
CLzma2EncInt *t = &p->coders[i];
|
||||
if (t->enc == NULL)
|
||||
{
|
||||
t->enc = LzmaEnc_Create(p->alloc);
|
||||
if (t->enc == NULL)
|
||||
return SZ_ERROR_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
if (p->props.numBlockThreads <= 1)
|
||||
#endif
|
||||
return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress);
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
|
||||
{
|
||||
CMtCallbackImp mtCallback;
|
||||
|
||||
mtCallback.funcTable.Code = MtCallbackImp_Code;
|
||||
mtCallback.lzma2Enc = p;
|
||||
|
||||
p->mtCoder.progress = progress;
|
||||
p->mtCoder.inStream = inStream;
|
||||
p->mtCoder.outStream = outStream;
|
||||
p->mtCoder.alloc = p->alloc;
|
||||
p->mtCoder.mtCallback = &mtCallback.funcTable;
|
||||
|
||||
p->mtCoder.blockSize = p->props.blockSize;
|
||||
p->mtCoder.destBlockSize = p->props.blockSize + (p->props.blockSize >> 10) + 16;
|
||||
p->mtCoder.numThreads = p->props.numBlockThreads;
|
||||
|
||||
return MtCoder_Code(&p->mtCoder);
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
/* Lzma2Enc.h -- LZMA2 Encoder
|
||||
2009-02-07 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMA2_ENC_H
|
||||
#define __LZMA2_ENC_H
|
||||
|
||||
#include "LzmaEnc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CLzmaEncProps lzmaProps;
|
||||
size_t blockSize;
|
||||
int numBlockThreads;
|
||||
int numTotalThreads;
|
||||
} CLzma2EncProps;
|
||||
|
||||
void Lzma2EncProps_Init(CLzma2EncProps *p);
|
||||
void Lzma2EncProps_Normalize(CLzma2EncProps *p);
|
||||
|
||||
/* ---------- CLzmaEnc2Handle Interface ---------- */
|
||||
|
||||
/* Lzma2Enc_* functions can return the following exit codes:
|
||||
Returns:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_PARAM - Incorrect paramater in props
|
||||
SZ_ERROR_WRITE - Write callback error
|
||||
SZ_ERROR_PROGRESS - some break from progress callback
|
||||
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
|
||||
*/
|
||||
|
||||
typedef void * CLzma2EncHandle;
|
||||
|
||||
CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||
void Lzma2Enc_Destroy(CLzma2EncHandle p);
|
||||
SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props);
|
||||
Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p);
|
||||
SRes Lzma2Enc_Encode(CLzma2EncHandle p,
|
||||
ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress);
|
||||
|
||||
/* ---------- One Call Interface ---------- */
|
||||
|
||||
/* Lzma2Encode
|
||||
Return code:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_PARAM - Incorrect paramater
|
||||
SZ_ERROR_OUTPUT_EOF - output buffer overflow
|
||||
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
|
||||
*/
|
||||
|
||||
/*
|
||||
SRes Lzma2Encode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
|
||||
const CLzmaEncProps *props, Byte *propsEncoded, int writeEndMark,
|
||||
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,108 +0,0 @@
|
|||
/* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder
|
||||
2009-08-14 : Igor Pavlov : Public domain */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "Lzma86.h"
|
||||
|
||||
#include "Alloc.h"
|
||||
#include "Bra.h"
|
||||
#include "LzmaEnc.h"
|
||||
|
||||
#define SZE_OUT_OVERFLOW SZE_DATA_ERROR
|
||||
|
||||
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
|
||||
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
|
||||
|
||||
int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
|
||||
int level, UInt32 dictSize, int filterMode)
|
||||
{
|
||||
ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||
size_t outSize2 = *destLen;
|
||||
Byte *filteredStream;
|
||||
Bool useFilter;
|
||||
int mainResult = SZ_ERROR_OUTPUT_EOF;
|
||||
CLzmaEncProps props;
|
||||
LzmaEncProps_Init(&props);
|
||||
props.level = level;
|
||||
props.dictSize = dictSize;
|
||||
|
||||
*destLen = 0;
|
||||
if (outSize2 < LZMA86_HEADER_SIZE)
|
||||
return SZ_ERROR_OUTPUT_EOF;
|
||||
|
||||
{
|
||||
int i;
|
||||
UInt64 t = srcLen;
|
||||
for (i = 0; i < 8; i++, t >>= 8)
|
||||
dest[LZMA86_SIZE_OFFSET + i] = (Byte)t;
|
||||
}
|
||||
|
||||
filteredStream = 0;
|
||||
useFilter = (filterMode != SZ_FILTER_NO);
|
||||
if (useFilter)
|
||||
{
|
||||
if (srcLen != 0)
|
||||
{
|
||||
filteredStream = (Byte *)MyAlloc(srcLen);
|
||||
if (filteredStream == 0)
|
||||
return SZ_ERROR_MEM;
|
||||
memcpy(filteredStream, src, srcLen);
|
||||
}
|
||||
{
|
||||
UInt32 x86State;
|
||||
x86_Convert_Init(x86State);
|
||||
x86_Convert(filteredStream, srcLen, 0, &x86State, 1);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
size_t minSize = 0;
|
||||
Bool bestIsFiltered = False;
|
||||
|
||||
/* passes for SZ_FILTER_AUTO:
|
||||
0 - BCJ + LZMA
|
||||
1 - LZMA
|
||||
2 - BCJ + LZMA agaian, if pass 0 (BCJ + LZMA) is better.
|
||||
*/
|
||||
int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < numPasses; i++)
|
||||
{
|
||||
size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE;
|
||||
size_t outPropsSize = 5;
|
||||
SRes curRes;
|
||||
Bool curModeIsFiltered = (numPasses > 1 && i == numPasses - 1);
|
||||
if (curModeIsFiltered && !bestIsFiltered)
|
||||
break;
|
||||
if (useFilter && i == 0)
|
||||
curModeIsFiltered = True;
|
||||
|
||||
curRes = LzmaEncode(dest + LZMA86_HEADER_SIZE, &outSizeProcessed,
|
||||
curModeIsFiltered ? filteredStream : src, srcLen,
|
||||
&props, dest + 1, &outPropsSize, 0,
|
||||
NULL, &g_Alloc, &g_Alloc);
|
||||
|
||||
if (curRes != SZ_ERROR_OUTPUT_EOF)
|
||||
{
|
||||
if (curRes != SZ_OK)
|
||||
{
|
||||
mainResult = curRes;
|
||||
break;
|
||||
}
|
||||
if (outSizeProcessed <= minSize || mainResult != SZ_OK)
|
||||
{
|
||||
minSize = outSizeProcessed;
|
||||
bestIsFiltered = curModeIsFiltered;
|
||||
mainResult = SZ_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
dest[0] = (bestIsFiltered ? 1 : 0);
|
||||
*destLen = LZMA86_HEADER_SIZE + minSize;
|
||||
}
|
||||
if (useFilter)
|
||||
MyFree(filteredStream);
|
||||
return mainResult;
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,327 +0,0 @@
|
|||
/* MtCoder.c -- Multi-thread Coder
|
||||
2010-09-24 : Igor Pavlov : Public domain */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "MtCoder.h"
|
||||
|
||||
void LoopThread_Construct(CLoopThread *p)
|
||||
{
|
||||
Thread_Construct(&p->thread);
|
||||
Event_Construct(&p->startEvent);
|
||||
Event_Construct(&p->finishedEvent);
|
||||
}
|
||||
|
||||
void LoopThread_Close(CLoopThread *p)
|
||||
{
|
||||
Thread_Close(&p->thread);
|
||||
Event_Close(&p->startEvent);
|
||||
Event_Close(&p->finishedEvent);
|
||||
}
|
||||
|
||||
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE LoopThreadFunc(void *pp)
|
||||
{
|
||||
CLoopThread *p = (CLoopThread *)pp;
|
||||
for (;;)
|
||||
{
|
||||
if (Event_Wait(&p->startEvent) != 0)
|
||||
return SZ_ERROR_THREAD;
|
||||
if (p->stop)
|
||||
return 0;
|
||||
p->res = p->func(p->param);
|
||||
if (Event_Set(&p->finishedEvent) != 0)
|
||||
return SZ_ERROR_THREAD;
|
||||
}
|
||||
}
|
||||
|
||||
WRes LoopThread_Create(CLoopThread *p)
|
||||
{
|
||||
p->stop = 0;
|
||||
RINOK(AutoResetEvent_CreateNotSignaled(&p->startEvent));
|
||||
RINOK(AutoResetEvent_CreateNotSignaled(&p->finishedEvent));
|
||||
return Thread_Create(&p->thread, LoopThreadFunc, p);
|
||||
}
|
||||
|
||||
WRes LoopThread_StopAndWait(CLoopThread *p)
|
||||
{
|
||||
p->stop = 1;
|
||||
if (Event_Set(&p->startEvent) != 0)
|
||||
return SZ_ERROR_THREAD;
|
||||
return Thread_Wait(&p->thread);
|
||||
}
|
||||
|
||||
WRes LoopThread_StartSubThread(CLoopThread *p) { return Event_Set(&p->startEvent); }
|
||||
WRes LoopThread_WaitSubThread(CLoopThread *p) { return Event_Wait(&p->finishedEvent); }
|
||||
|
||||
static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
|
||||
{
|
||||
return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
|
||||
}
|
||||
|
||||
static void MtProgress_Init(CMtProgress *p, ICompressProgress *progress)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
|
||||
p->inSizes[i] = p->outSizes[i] = 0;
|
||||
p->totalInSize = p->totalOutSize = 0;
|
||||
p->progress = progress;
|
||||
p->res = SZ_OK;
|
||||
}
|
||||
|
||||
static void MtProgress_Reinit(CMtProgress *p, unsigned index)
|
||||
{
|
||||
p->inSizes[index] = 0;
|
||||
p->outSizes[index] = 0;
|
||||
}
|
||||
|
||||
#define UPDATE_PROGRESS(size, prev, total) \
|
||||
if (size != (UInt64)(Int64)-1) { total += size - prev; prev = size; }
|
||||
|
||||
SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize)
|
||||
{
|
||||
SRes res;
|
||||
CriticalSection_Enter(&p->cs);
|
||||
UPDATE_PROGRESS(inSize, p->inSizes[index], p->totalInSize)
|
||||
UPDATE_PROGRESS(outSize, p->outSizes[index], p->totalOutSize)
|
||||
if (p->res == SZ_OK)
|
||||
p->res = Progress(p->progress, p->totalInSize, p->totalOutSize);
|
||||
res = p->res;
|
||||
CriticalSection_Leave(&p->cs);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void MtProgress_SetError(CMtProgress *p, SRes res)
|
||||
{
|
||||
CriticalSection_Enter(&p->cs);
|
||||
if (p->res == SZ_OK)
|
||||
p->res = res;
|
||||
CriticalSection_Leave(&p->cs);
|
||||
}
|
||||
|
||||
static void MtCoder_SetError(CMtCoder* p, SRes res)
|
||||
{
|
||||
CriticalSection_Enter(&p->cs);
|
||||
if (p->res == SZ_OK)
|
||||
p->res = res;
|
||||
CriticalSection_Leave(&p->cs);
|
||||
}
|
||||
|
||||
/* ---------- MtThread ---------- */
|
||||
|
||||
void CMtThread_Construct(CMtThread *p, CMtCoder *mtCoder)
|
||||
{
|
||||
p->mtCoder = mtCoder;
|
||||
p->outBuf = 0;
|
||||
p->inBuf = 0;
|
||||
Event_Construct(&p->canRead);
|
||||
Event_Construct(&p->canWrite);
|
||||
LoopThread_Construct(&p->thread);
|
||||
}
|
||||
|
||||
#define RINOK_THREAD(x) { if((x) != 0) return SZ_ERROR_THREAD; }
|
||||
|
||||
static void CMtThread_CloseEvents(CMtThread *p)
|
||||
{
|
||||
Event_Close(&p->canRead);
|
||||
Event_Close(&p->canWrite);
|
||||
}
|
||||
|
||||
static void CMtThread_Destruct(CMtThread *p)
|
||||
{
|
||||
CMtThread_CloseEvents(p);
|
||||
|
||||
if (Thread_WasCreated(&p->thread.thread))
|
||||
{
|
||||
LoopThread_StopAndWait(&p->thread);
|
||||
LoopThread_Close(&p->thread);
|
||||
}
|
||||
|
||||
if (p->mtCoder->alloc)
|
||||
IAlloc_Free(p->mtCoder->alloc, p->outBuf);
|
||||
p->outBuf = 0;
|
||||
|
||||
if (p->mtCoder->alloc)
|
||||
IAlloc_Free(p->mtCoder->alloc, p->inBuf);
|
||||
p->inBuf = 0;
|
||||
}
|
||||
|
||||
#define MY_BUF_ALLOC(buf, size, newSize) \
|
||||
if (buf == 0 || size != newSize) \
|
||||
{ IAlloc_Free(p->mtCoder->alloc, buf); \
|
||||
size = newSize; buf = (Byte *)IAlloc_Alloc(p->mtCoder->alloc, size); \
|
||||
if (buf == 0) return SZ_ERROR_MEM; }
|
||||
|
||||
static SRes CMtThread_Prepare(CMtThread *p)
|
||||
{
|
||||
MY_BUF_ALLOC(p->inBuf, p->inBufSize, p->mtCoder->blockSize)
|
||||
MY_BUF_ALLOC(p->outBuf, p->outBufSize, p->mtCoder->destBlockSize)
|
||||
|
||||
p->stopReading = False;
|
||||
p->stopWriting = False;
|
||||
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canRead));
|
||||
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canWrite));
|
||||
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static SRes FullRead(ISeqInStream *stream, Byte *data, size_t *processedSize)
|
||||
{
|
||||
size_t size = *processedSize;
|
||||
*processedSize = 0;
|
||||
while (size != 0)
|
||||
{
|
||||
size_t curSize = size;
|
||||
SRes res = stream->Read(stream, data, &curSize);
|
||||
*processedSize += curSize;
|
||||
data += curSize;
|
||||
size -= curSize;
|
||||
RINOK(res);
|
||||
if (curSize == 0)
|
||||
return SZ_OK;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
#define GET_NEXT_THREAD(p) &p->mtCoder->threads[p->index == p->mtCoder->numThreads - 1 ? 0 : p->index + 1]
|
||||
|
||||
static SRes MtThread_Process(CMtThread *p, Bool *stop)
|
||||
{
|
||||
CMtThread *next;
|
||||
*stop = True;
|
||||
if (Event_Wait(&p->canRead) != 0)
|
||||
return SZ_ERROR_THREAD;
|
||||
|
||||
next = GET_NEXT_THREAD(p);
|
||||
|
||||
if (p->stopReading)
|
||||
{
|
||||
next->stopReading = True;
|
||||
return Event_Set(&next->canRead) == 0 ? SZ_OK : SZ_ERROR_THREAD;
|
||||
}
|
||||
|
||||
{
|
||||
size_t size = p->mtCoder->blockSize;
|
||||
size_t destSize = p->outBufSize;
|
||||
|
||||
RINOK(FullRead(p->mtCoder->inStream, p->inBuf, &size));
|
||||
next->stopReading = *stop = (size != p->mtCoder->blockSize);
|
||||
if (Event_Set(&next->canRead) != 0)
|
||||
return SZ_ERROR_THREAD;
|
||||
|
||||
RINOK(p->mtCoder->mtCallback->Code(p->mtCoder->mtCallback, p->index,
|
||||
p->outBuf, &destSize, p->inBuf, size, *stop));
|
||||
|
||||
MtProgress_Reinit(&p->mtCoder->mtProgress, p->index);
|
||||
|
||||
if (Event_Wait(&p->canWrite) != 0)
|
||||
return SZ_ERROR_THREAD;
|
||||
if (p->stopWriting)
|
||||
return SZ_ERROR_FAIL;
|
||||
if (p->mtCoder->outStream->Write(p->mtCoder->outStream, p->outBuf, destSize) != destSize)
|
||||
return SZ_ERROR_WRITE;
|
||||
return Event_Set(&next->canWrite) == 0 ? SZ_OK : SZ_ERROR_THREAD;
|
||||
}
|
||||
}
|
||||
|
||||
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp)
|
||||
{
|
||||
CMtThread *p = (CMtThread *)pp;
|
||||
for (;;)
|
||||
{
|
||||
Bool stop;
|
||||
CMtThread *next = GET_NEXT_THREAD(p);
|
||||
SRes res = MtThread_Process(p, &stop);
|
||||
if (res != SZ_OK)
|
||||
{
|
||||
MtCoder_SetError(p->mtCoder, res);
|
||||
MtProgress_SetError(&p->mtCoder->mtProgress, res);
|
||||
next->stopReading = True;
|
||||
next->stopWriting = True;
|
||||
Event_Set(&next->canRead);
|
||||
Event_Set(&next->canWrite);
|
||||
return res;
|
||||
}
|
||||
if (stop)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MtCoder_Construct(CMtCoder* p)
|
||||
{
|
||||
unsigned i;
|
||||
p->alloc = 0;
|
||||
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
|
||||
{
|
||||
CMtThread *t = &p->threads[i];
|
||||
t->index = i;
|
||||
CMtThread_Construct(t, p);
|
||||
}
|
||||
CriticalSection_Init(&p->cs);
|
||||
CriticalSection_Init(&p->mtProgress.cs);
|
||||
}
|
||||
|
||||
void MtCoder_Destruct(CMtCoder* p)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
|
||||
CMtThread_Destruct(&p->threads[i]);
|
||||
CriticalSection_Delete(&p->cs);
|
||||
CriticalSection_Delete(&p->mtProgress.cs);
|
||||
}
|
||||
|
||||
SRes MtCoder_Code(CMtCoder *p)
|
||||
{
|
||||
unsigned i, numThreads = p->numThreads;
|
||||
SRes res = SZ_OK;
|
||||
p->res = SZ_OK;
|
||||
|
||||
MtProgress_Init(&p->mtProgress, p->progress);
|
||||
|
||||
for (i = 0; i < numThreads; i++)
|
||||
{
|
||||
RINOK(CMtThread_Prepare(&p->threads[i]));
|
||||
}
|
||||
|
||||
for (i = 0; i < numThreads; i++)
|
||||
{
|
||||
CMtThread *t = &p->threads[i];
|
||||
CLoopThread *lt = &t->thread;
|
||||
|
||||
if (!Thread_WasCreated(<->thread))
|
||||
{
|
||||
lt->func = ThreadFunc;
|
||||
lt->param = t;
|
||||
|
||||
if (LoopThread_Create(lt) != SZ_OK)
|
||||
{
|
||||
res = SZ_ERROR_THREAD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
unsigned j;
|
||||
for (i = 0; i < numThreads; i++)
|
||||
{
|
||||
CMtThread *t = &p->threads[i];
|
||||
if (LoopThread_StartSubThread(&t->thread) != SZ_OK)
|
||||
{
|
||||
res = SZ_ERROR_THREAD;
|
||||
p->threads[0].stopReading = True;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Event_Set(&p->threads[0].canWrite);
|
||||
Event_Set(&p->threads[0].canRead);
|
||||
|
||||
for (j = 0; j < i; j++)
|
||||
LoopThread_WaitSubThread(&p->threads[j].thread);
|
||||
}
|
||||
|
||||
for (i = 0; i < numThreads; i++)
|
||||
CMtThread_CloseEvents(&p->threads[i]);
|
||||
return (res == SZ_OK) ? p->res : res;
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
/* MtCoder.h -- Multi-thread Coder
|
||||
2009-11-19 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __MT_CODER_H
|
||||
#define __MT_CODER_H
|
||||
|
||||
#include "Threads.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CThread thread;
|
||||
CAutoResetEvent startEvent;
|
||||
CAutoResetEvent finishedEvent;
|
||||
int stop;
|
||||
|
||||
THREAD_FUNC_TYPE func;
|
||||
LPVOID param;
|
||||
THREAD_FUNC_RET_TYPE res;
|
||||
} CLoopThread;
|
||||
|
||||
void LoopThread_Construct(CLoopThread *p);
|
||||
void LoopThread_Close(CLoopThread *p);
|
||||
WRes LoopThread_Create(CLoopThread *p);
|
||||
WRes LoopThread_StopAndWait(CLoopThread *p);
|
||||
WRes LoopThread_StartSubThread(CLoopThread *p);
|
||||
WRes LoopThread_WaitSubThread(CLoopThread *p);
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
#define NUM_MT_CODER_THREADS_MAX 32
|
||||
#else
|
||||
#define NUM_MT_CODER_THREADS_MAX 1
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt64 totalInSize;
|
||||
UInt64 totalOutSize;
|
||||
ICompressProgress *progress;
|
||||
SRes res;
|
||||
CCriticalSection cs;
|
||||
UInt64 inSizes[NUM_MT_CODER_THREADS_MAX];
|
||||
UInt64 outSizes[NUM_MT_CODER_THREADS_MAX];
|
||||
} CMtProgress;
|
||||
|
||||
SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize);
|
||||
|
||||
struct _CMtCoder;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct _CMtCoder *mtCoder;
|
||||
Byte *outBuf;
|
||||
size_t outBufSize;
|
||||
Byte *inBuf;
|
||||
size_t inBufSize;
|
||||
unsigned index;
|
||||
CLoopThread thread;
|
||||
|
||||
Bool stopReading;
|
||||
Bool stopWriting;
|
||||
CAutoResetEvent canRead;
|
||||
CAutoResetEvent canWrite;
|
||||
} CMtThread;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SRes (*Code)(void *p, unsigned index, Byte *dest, size_t *destSize,
|
||||
const Byte *src, size_t srcSize, int finished);
|
||||
} IMtCoderCallback;
|
||||
|
||||
typedef struct _CMtCoder
|
||||
{
|
||||
size_t blockSize;
|
||||
size_t destBlockSize;
|
||||
unsigned numThreads;
|
||||
|
||||
ISeqInStream *inStream;
|
||||
ISeqOutStream *outStream;
|
||||
ICompressProgress *progress;
|
||||
ISzAlloc *alloc;
|
||||
|
||||
IMtCoderCallback *mtCallback;
|
||||
CCriticalSection cs;
|
||||
SRes res;
|
||||
|
||||
CMtProgress mtProgress;
|
||||
CMtThread threads[NUM_MT_CODER_THREADS_MAX];
|
||||
} CMtCoder;
|
||||
|
||||
void MtCoder_Construct(CMtCoder* p);
|
||||
void MtCoder_Destruct(CMtCoder* p);
|
||||
SRes MtCoder_Code(CMtCoder *p);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
|
@ -1,84 +0,0 @@
|
|||
/* Threads.c -- multithreading library
|
||||
2009-09-20 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef _WIN32_7Z_WCE
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
#include "Threads.h"
|
||||
|
||||
static WRes GetError()
|
||||
{
|
||||
DWORD res = GetLastError();
|
||||
return (res) ? (WRes)(res) : 1;
|
||||
}
|
||||
|
||||
WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); }
|
||||
WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); }
|
||||
|
||||
WRes HandlePtr_Close(HANDLE *p)
|
||||
{
|
||||
if (*p != NULL)
|
||||
if (!CloseHandle(*p))
|
||||
return GetError();
|
||||
*p = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
WRes Handle_WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); }
|
||||
|
||||
WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
|
||||
{
|
||||
unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
|
||||
*p =
|
||||
#ifdef UNDER_CE
|
||||
CreateThread(0, 0, func, param, 0, &threadId);
|
||||
#else
|
||||
(HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId);
|
||||
#endif
|
||||
/* maybe we must use errno here, but probably GetLastError() is also OK. */
|
||||
return HandleToWRes(*p);
|
||||
}
|
||||
|
||||
WRes Event_Create(CEvent *p, BOOL manualReset, int signaled)
|
||||
{
|
||||
*p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL);
|
||||
return HandleToWRes(*p);
|
||||
}
|
||||
|
||||
WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(*p)); }
|
||||
WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(*p)); }
|
||||
|
||||
WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) { return Event_Create(p, TRUE, signaled); }
|
||||
WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) { return Event_Create(p, FALSE, signaled); }
|
||||
WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); }
|
||||
WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); }
|
||||
|
||||
|
||||
WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount)
|
||||
{
|
||||
*p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL);
|
||||
return HandleToWRes(*p);
|
||||
}
|
||||
|
||||
static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount)
|
||||
{ return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); }
|
||||
WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num)
|
||||
{ return Semaphore_Release(p, (LONG)num, NULL); }
|
||||
WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); }
|
||||
|
||||
WRes CriticalSection_Init(CCriticalSection *p)
|
||||
{
|
||||
/* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */
|
||||
#ifdef _MSC_VER_
|
||||
__try
|
||||
#endif
|
||||
{
|
||||
InitializeCriticalSection(p);
|
||||
/* InitializeCriticalSectionAndSpinCount(p, 0); */
|
||||
}
|
||||
#ifdef _MSC_VER_
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) { return 1; }
|
||||
#endif
|
||||
return 0;
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
/* Threads.h -- multithreading library
|
||||
2009-03-27 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_THREADS_H
|
||||
#define __7Z_THREADS_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
WRes HandlePtr_Close(HANDLE *h);
|
||||
WRes Handle_WaitObject(HANDLE h);
|
||||
|
||||
typedef HANDLE CThread;
|
||||
#define Thread_Construct(p) *(p) = NULL
|
||||
#define Thread_WasCreated(p) (*(p) != NULL)
|
||||
#define Thread_Close(p) HandlePtr_Close(p)
|
||||
#define Thread_Wait(p) Handle_WaitObject(*(p))
|
||||
typedef unsigned THREAD_FUNC_RET_TYPE;
|
||||
#define THREAD_FUNC_CALL_TYPE MY_STD_CALL
|
||||
#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE
|
||||
typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *);
|
||||
WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param);
|
||||
|
||||
typedef HANDLE CEvent;
|
||||
typedef CEvent CAutoResetEvent;
|
||||
typedef CEvent CManualResetEvent;
|
||||
#define Event_Construct(p) *(p) = NULL
|
||||
#define Event_IsCreated(p) (*(p) != NULL)
|
||||
#define Event_Close(p) HandlePtr_Close(p)
|
||||
#define Event_Wait(p) Handle_WaitObject(*(p))
|
||||
WRes Event_Set(CEvent *p);
|
||||
WRes Event_Reset(CEvent *p);
|
||||
WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);
|
||||
WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);
|
||||
WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
|
||||
WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
|
||||
|
||||
typedef HANDLE CSemaphore;
|
||||
#define Semaphore_Construct(p) (*p) = NULL
|
||||
#define Semaphore_Close(p) HandlePtr_Close(p)
|
||||
#define Semaphore_Wait(p) Handle_WaitObject(*(p))
|
||||
WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
|
||||
WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
|
||||
WRes Semaphore_Release1(CSemaphore *p);
|
||||
|
||||
typedef CRITICAL_SECTION CCriticalSection;
|
||||
WRes CriticalSection_Init(CCriticalSection *p);
|
||||
#define CriticalSection_Delete(p) DeleteCriticalSection(p)
|
||||
#define CriticalSection_Enter(p) EnterCriticalSection(p)
|
||||
#define CriticalSection_Leave(p) LeaveCriticalSection(p)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,520 +0,0 @@
|
|||
/* XzEnc.c -- Xz Encode
|
||||
2011-02-07 : Igor Pavlov : Public domain */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "7zCrc.h"
|
||||
#include "Alloc.h"
|
||||
#include "Bra.h"
|
||||
#include "CpuArch.h"
|
||||
#ifdef USE_SUBBLOCK
|
||||
#include "Bcj3Enc.c"
|
||||
#include "SbFind.c"
|
||||
#include "SbEnc.c"
|
||||
#endif
|
||||
|
||||
#include "XzEnc.h"
|
||||
|
||||
static void *SzBigAlloc(void *p, size_t size) { p = p; return BigAlloc(size); }
|
||||
static void SzBigFree(void *p, void *address) { p = p; BigFree(address); }
|
||||
static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
|
||||
|
||||
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
|
||||
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
|
||||
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||
|
||||
#define XzBlock_ClearFlags(p) (p)->flags = 0;
|
||||
#define XzBlock_SetNumFilters(p, n) (p)->flags |= ((n) - 1);
|
||||
#define XzBlock_SetHasPackSize(p) (p)->flags |= XZ_BF_PACK_SIZE;
|
||||
#define XzBlock_SetHasUnpackSize(p) (p)->flags |= XZ_BF_UNPACK_SIZE;
|
||||
|
||||
static SRes WriteBytes(ISeqOutStream *s, const void *buf, UInt32 size)
|
||||
{
|
||||
return (s->Write(s, buf, size) == size) ? SZ_OK : SZ_ERROR_WRITE;
|
||||
}
|
||||
|
||||
static SRes WriteBytesAndCrc(ISeqOutStream *s, const void *buf, UInt32 size, UInt32 *crc)
|
||||
{
|
||||
*crc = CrcUpdate(*crc, buf, size);
|
||||
return WriteBytes(s, buf, size);
|
||||
}
|
||||
|
||||
SRes Xz_WriteHeader(CXzStreamFlags f, ISeqOutStream *s)
|
||||
{
|
||||
UInt32 crc;
|
||||
Byte header[XZ_STREAM_HEADER_SIZE];
|
||||
memcpy(header, XZ_SIG, XZ_SIG_SIZE);
|
||||
header[XZ_SIG_SIZE] = (Byte)(f >> 8);
|
||||
header[XZ_SIG_SIZE + 1] = (Byte)(f & 0xFF);
|
||||
crc = CrcCalc(header + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE);
|
||||
SetUi32(header + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE, crc);
|
||||
return WriteBytes(s, header, XZ_STREAM_HEADER_SIZE);
|
||||
}
|
||||
|
||||
SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStream *s)
|
||||
{
|
||||
Byte header[XZ_BLOCK_HEADER_SIZE_MAX];
|
||||
|
||||
unsigned pos = 1;
|
||||
int numFilters, i;
|
||||
header[pos++] = p->flags;
|
||||
|
||||
if (XzBlock_HasPackSize(p)) pos += Xz_WriteVarInt(header + pos, p->packSize);
|
||||
if (XzBlock_HasUnpackSize(p)) pos += Xz_WriteVarInt(header + pos, p->unpackSize);
|
||||
numFilters = XzBlock_GetNumFilters(p);
|
||||
for (i = 0; i < numFilters; i++)
|
||||
{
|
||||
const CXzFilter *f = &p->filters[i];
|
||||
pos += Xz_WriteVarInt(header + pos, f->id);
|
||||
pos += Xz_WriteVarInt(header + pos, f->propsSize);
|
||||
memcpy(header + pos, f->props, f->propsSize);
|
||||
pos += f->propsSize;
|
||||
}
|
||||
while((pos & 3) != 0)
|
||||
header[pos++] = 0;
|
||||
header[0] = (Byte)(pos >> 2);
|
||||
SetUi32(header + pos, CrcCalc(header, pos));
|
||||
return WriteBytes(s, header, pos + 4);
|
||||
}
|
||||
|
||||
SRes Xz_WriteFooter(CXzStream *p, ISeqOutStream *s)
|
||||
{
|
||||
Byte buf[32];
|
||||
UInt64 globalPos;
|
||||
{
|
||||
UInt32 crc = CRC_INIT_VAL;
|
||||
unsigned pos = 1 + Xz_WriteVarInt(buf + 1, p->numBlocks);
|
||||
size_t i;
|
||||
|
||||
globalPos = pos;
|
||||
buf[0] = 0;
|
||||
RINOK(WriteBytesAndCrc(s, buf, pos, &crc));
|
||||
for (i = 0; i < p->numBlocks; i++)
|
||||
{
|
||||
const CXzBlockSizes *block = &p->blocks[i];
|
||||
pos = Xz_WriteVarInt(buf, block->totalSize);
|
||||
pos += Xz_WriteVarInt(buf + pos, block->unpackSize);
|
||||
globalPos += pos;
|
||||
RINOK(WriteBytesAndCrc(s, buf, pos, &crc));
|
||||
}
|
||||
pos = ((unsigned)globalPos & 3);
|
||||
if (pos != 0)
|
||||
{
|
||||
buf[0] = buf[1] = buf[2] = 0;
|
||||
RINOK(WriteBytesAndCrc(s, buf, 4 - pos, &crc));
|
||||
globalPos += 4 - pos;
|
||||
}
|
||||
{
|
||||
SetUi32(buf, CRC_GET_DIGEST(crc));
|
||||
RINOK(WriteBytes(s, buf, 4));
|
||||
globalPos += 4;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
UInt32 indexSize = (UInt32)((globalPos >> 2) - 1);
|
||||
SetUi32(buf + 4, indexSize);
|
||||
buf[8] = (Byte)(p->flags >> 8);
|
||||
buf[9] = (Byte)(p->flags & 0xFF);
|
||||
SetUi32(buf, CrcCalc(buf + 4, 6));
|
||||
memcpy(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE);
|
||||
return WriteBytes(s, buf, 12);
|
||||
}
|
||||
}
|
||||
|
||||
SRes Xz_AddIndexRecord(CXzStream *p, UInt64 unpackSize, UInt64 totalSize, ISzAlloc *alloc)
|
||||
{
|
||||
if (p->blocks == 0 || p->numBlocksAllocated == p->numBlocks)
|
||||
{
|
||||
size_t num = (p->numBlocks + 1) * 2;
|
||||
size_t newSize = sizeof(CXzBlockSizes) * num;
|
||||
CXzBlockSizes *blocks;
|
||||
if (newSize / sizeof(CXzBlockSizes) != num)
|
||||
return SZ_ERROR_MEM;
|
||||
blocks = alloc->Alloc(alloc, newSize);
|
||||
if (blocks == 0)
|
||||
return SZ_ERROR_MEM;
|
||||
if (p->numBlocks != 0)
|
||||
{
|
||||
memcpy(blocks, p->blocks, p->numBlocks * sizeof(CXzBlockSizes));
|
||||
Xz_Free(p, alloc);
|
||||
}
|
||||
p->blocks = blocks;
|
||||
p->numBlocksAllocated = num;
|
||||
}
|
||||
{
|
||||
CXzBlockSizes *block = &p->blocks[p->numBlocks++];
|
||||
block->totalSize = totalSize;
|
||||
block->unpackSize = unpackSize;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
/* ---------- CSeqCheckInStream ---------- */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeqInStream p;
|
||||
ISeqInStream *realStream;
|
||||
UInt64 processed;
|
||||
CXzCheck check;
|
||||
} CSeqCheckInStream;
|
||||
|
||||
void SeqCheckInStream_Init(CSeqCheckInStream *p, int mode)
|
||||
{
|
||||
p->processed = 0;
|
||||
XzCheck_Init(&p->check, mode);
|
||||
}
|
||||
|
||||
void SeqCheckInStream_GetDigest(CSeqCheckInStream *p, Byte *digest)
|
||||
{
|
||||
XzCheck_Final(&p->check, digest);
|
||||
}
|
||||
|
||||
static SRes SeqCheckInStream_Read(void *pp, void *data, size_t *size)
|
||||
{
|
||||
CSeqCheckInStream *p = (CSeqCheckInStream *)pp;
|
||||
SRes res = p->realStream->Read(p->realStream, data, size);
|
||||
XzCheck_Update(&p->check, data, *size);
|
||||
p->processed += *size;
|
||||
return res;
|
||||
}
|
||||
|
||||
/* ---------- CSeqSizeOutStream ---------- */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeqOutStream p;
|
||||
ISeqOutStream *realStream;
|
||||
UInt64 processed;
|
||||
} CSeqSizeOutStream;
|
||||
|
||||
static size_t MyWrite(void *pp, const void *data, size_t size)
|
||||
{
|
||||
CSeqSizeOutStream *p = (CSeqSizeOutStream *)pp;
|
||||
size = p->realStream->Write(p->realStream, data, size);
|
||||
p->processed += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
/* ---------- CSeqInFilter ---------- */
|
||||
|
||||
#define FILTER_BUF_SIZE (1 << 20)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeqInStream p;
|
||||
ISeqInStream *realStream;
|
||||
IStateCoder StateCoder;
|
||||
Byte *buf;
|
||||
size_t curPos;
|
||||
size_t endPos;
|
||||
int srcWasFinished;
|
||||
} CSeqInFilter;
|
||||
|
||||
static SRes SeqInFilter_Read(void *pp, void *data, size_t *size)
|
||||
{
|
||||
CSeqInFilter *p = (CSeqInFilter *)pp;
|
||||
size_t sizeOriginal = *size;
|
||||
if (sizeOriginal == 0)
|
||||
return S_OK;
|
||||
*size = 0;
|
||||
for (;;)
|
||||
{
|
||||
if (!p->srcWasFinished && p->curPos == p->endPos)
|
||||
{
|
||||
p->curPos = 0;
|
||||
p->endPos = FILTER_BUF_SIZE;
|
||||
RINOK(p->realStream->Read(p->realStream, p->buf, &p->endPos));
|
||||
if (p->endPos == 0)
|
||||
p->srcWasFinished = 1;
|
||||
}
|
||||
{
|
||||
SizeT srcLen = p->endPos - p->curPos;
|
||||
int wasFinished;
|
||||
SRes res;
|
||||
*size = sizeOriginal;
|
||||
res = p->StateCoder.Code(p->StateCoder.p, data, size, p->buf + p->curPos, &srcLen,
|
||||
p->srcWasFinished, CODER_FINISH_ANY, &wasFinished);
|
||||
p->curPos += srcLen;
|
||||
if (*size != 0 || srcLen == 0 || res != 0)
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SeqInFilter_Construct(CSeqInFilter *p)
|
||||
{
|
||||
p->buf = NULL;
|
||||
p->p.Read = SeqInFilter_Read;
|
||||
}
|
||||
|
||||
static void SeqInFilter_Free(CSeqInFilter *p)
|
||||
{
|
||||
if (p->buf)
|
||||
{
|
||||
g_Alloc.Free(&g_Alloc, p->buf);
|
||||
p->buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAlloc *alloc);
|
||||
|
||||
static SRes SeqInFilter_Init(CSeqInFilter *p, const CXzFilter *props)
|
||||
{
|
||||
if (!p->buf)
|
||||
{
|
||||
p->buf = g_Alloc.Alloc(&g_Alloc, FILTER_BUF_SIZE);
|
||||
if (!p->buf)
|
||||
return SZ_ERROR_MEM;
|
||||
}
|
||||
p->curPos = p->endPos = 0;
|
||||
p->srcWasFinished = 0;
|
||||
RINOK(BraState_SetFromMethod(&p->StateCoder, props->id, 1, &g_Alloc));
|
||||
RINOK(p->StateCoder.SetProps(p->StateCoder.p, props->props, props->propsSize, &g_Alloc));
|
||||
p->StateCoder.Init(p->StateCoder.p);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/* ---------- CSbEncInStream ---------- */
|
||||
|
||||
#ifdef USE_SUBBLOCK
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeqInStream p;
|
||||
ISeqInStream *inStream;
|
||||
CSbEnc enc;
|
||||
} CSbEncInStream;
|
||||
|
||||
static SRes SbEncInStream_Read(void *pp, void *data, size_t *size)
|
||||
{
|
||||
CSbEncInStream *p = (CSbEncInStream *)pp;
|
||||
size_t sizeOriginal = *size;
|
||||
if (sizeOriginal == 0)
|
||||
return S_OK;
|
||||
for (;;)
|
||||
{
|
||||
if (p->enc.needRead && !p->enc.readWasFinished)
|
||||
{
|
||||
size_t processed = p->enc.needReadSizeMax;
|
||||
RINOK(p->inStream->Read(p->inStream, p->enc.buf + p->enc.readPos, &processed));
|
||||
p->enc.readPos += processed;
|
||||
if (processed == 0)
|
||||
{
|
||||
p->enc.readWasFinished = True;
|
||||
p->enc.isFinalFinished = True;
|
||||
}
|
||||
p->enc.needRead = False;
|
||||
}
|
||||
*size = sizeOriginal;
|
||||
RINOK(SbEnc_Read(&p->enc, data, size));
|
||||
if (*size != 0 || !p->enc.needRead)
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
void SbEncInStream_Construct(CSbEncInStream *p, ISzAlloc *alloc)
|
||||
{
|
||||
SbEnc_Construct(&p->enc, alloc);
|
||||
p->p.Read = SbEncInStream_Read;
|
||||
}
|
||||
|
||||
SRes SbEncInStream_Init(CSbEncInStream *p)
|
||||
{
|
||||
return SbEnc_Init(&p->enc);
|
||||
}
|
||||
|
||||
void SbEncInStream_Free(CSbEncInStream *p)
|
||||
{
|
||||
SbEnc_Free(&p->enc);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CLzma2EncHandle lzma2;
|
||||
#ifdef USE_SUBBLOCK
|
||||
CSbEncInStream sb;
|
||||
#endif
|
||||
CSeqInFilter filter;
|
||||
ISzAlloc *alloc;
|
||||
ISzAlloc *bigAlloc;
|
||||
} CLzma2WithFilters;
|
||||
|
||||
|
||||
static void Lzma2WithFilters_Construct(CLzma2WithFilters *p, ISzAlloc *alloc, ISzAlloc *bigAlloc)
|
||||
{
|
||||
p->alloc = alloc;
|
||||
p->bigAlloc = bigAlloc;
|
||||
p->lzma2 = NULL;
|
||||
#ifdef USE_SUBBLOCK
|
||||
SbEncInStream_Construct(&p->sb, alloc);
|
||||
#endif
|
||||
SeqInFilter_Construct(&p->filter);
|
||||
}
|
||||
|
||||
static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p)
|
||||
{
|
||||
p->lzma2 = Lzma2Enc_Create(p->alloc, p->bigAlloc);
|
||||
if (p->lzma2 == 0)
|
||||
return SZ_ERROR_MEM;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static void Lzma2WithFilters_Free(CLzma2WithFilters *p)
|
||||
{
|
||||
SeqInFilter_Free(&p->filter);
|
||||
#ifdef USE_SUBBLOCK
|
||||
SbEncInStream_Free(&p->sb);
|
||||
#endif
|
||||
if (p->lzma2)
|
||||
{
|
||||
Lzma2Enc_Destroy(p->lzma2);
|
||||
p->lzma2 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void XzProps_Init(CXzProps *p)
|
||||
{
|
||||
p->lzma2Props = 0;
|
||||
p->filterProps = 0;
|
||||
p->checkId = XZ_CHECK_CRC32;
|
||||
}
|
||||
|
||||
void XzFilterProps_Init(CXzFilterProps *p)
|
||||
{
|
||||
p->id = 0;
|
||||
p->delta = 0;
|
||||
p->ip= 0;
|
||||
p->ipDefined = False;
|
||||
}
|
||||
|
||||
static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf,
|
||||
ISeqOutStream *outStream, ISeqInStream *inStream,
|
||||
const CXzProps *props, ICompressProgress *progress)
|
||||
{
|
||||
xz->flags = (Byte)props->checkId;
|
||||
|
||||
RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, props->lzma2Props));
|
||||
RINOK(Xz_WriteHeader(xz->flags, outStream));
|
||||
|
||||
{
|
||||
CSeqCheckInStream checkInStream;
|
||||
CSeqSizeOutStream seqSizeOutStream;
|
||||
CXzBlock block;
|
||||
int filterIndex = 0;
|
||||
CXzFilter *filter = NULL;
|
||||
const CXzFilterProps *fp = props->filterProps;
|
||||
|
||||
XzBlock_ClearFlags(&block);
|
||||
XzBlock_SetNumFilters(&block, 1 + (fp ? 1 : 0));
|
||||
|
||||
if (fp)
|
||||
{
|
||||
filter = &block.filters[filterIndex++];
|
||||
filter->id = fp->id;
|
||||
filter->propsSize = 0;
|
||||
if (fp->id == XZ_ID_Delta)
|
||||
{
|
||||
filter->props[0] = (Byte)(fp->delta - 1);
|
||||
filter->propsSize = 1;
|
||||
}
|
||||
else if (fp->ipDefined)
|
||||
{
|
||||
SetUi32(filter->props, fp->ip);
|
||||
filter->propsSize = 4;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
CXzFilter *f = &block.filters[filterIndex++];
|
||||
f->id = XZ_ID_LZMA2;
|
||||
f->propsSize = 1;
|
||||
f->props[0] = Lzma2Enc_WriteProperties(lzmaf->lzma2);
|
||||
}
|
||||
|
||||
seqSizeOutStream.p.Write = MyWrite;
|
||||
seqSizeOutStream.realStream = outStream;
|
||||
seqSizeOutStream.processed = 0;
|
||||
|
||||
RINOK(XzBlock_WriteHeader(&block, &seqSizeOutStream.p));
|
||||
|
||||
checkInStream.p.Read = SeqCheckInStream_Read;
|
||||
checkInStream.realStream = inStream;
|
||||
SeqCheckInStream_Init(&checkInStream, XzFlags_GetCheckType(xz->flags));
|
||||
|
||||
if (fp)
|
||||
{
|
||||
#ifdef USE_SUBBLOCK
|
||||
if (fp->id == XZ_ID_Subblock)
|
||||
{
|
||||
lzmaf->sb.inStream = &checkInStream.p;
|
||||
RINOK(SbEncInStream_Init(&lzmaf->sb));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
lzmaf->filter.realStream = &checkInStream.p;
|
||||
RINOK(SeqInFilter_Init(&lzmaf->filter, filter));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
UInt64 packPos = seqSizeOutStream.processed;
|
||||
SRes res = Lzma2Enc_Encode(lzmaf->lzma2, &seqSizeOutStream.p,
|
||||
fp ?
|
||||
#ifdef USE_SUBBLOCK
|
||||
(fp->id == XZ_ID_Subblock) ? &lzmaf->sb.p:
|
||||
#endif
|
||||
&lzmaf->filter.p:
|
||||
&checkInStream.p,
|
||||
progress);
|
||||
RINOK(res);
|
||||
block.unpackSize = checkInStream.processed;
|
||||
block.packSize = seqSizeOutStream.processed - packPos;
|
||||
}
|
||||
|
||||
{
|
||||
unsigned padSize = 0;
|
||||
Byte buf[128];
|
||||
while((((unsigned)block.packSize + padSize) & 3) != 0)
|
||||
buf[padSize++] = 0;
|
||||
SeqCheckInStream_GetDigest(&checkInStream, buf + padSize);
|
||||
RINOK(WriteBytes(&seqSizeOutStream.p, buf, padSize + XzFlags_GetCheckSize(xz->flags)));
|
||||
RINOK(Xz_AddIndexRecord(xz, block.unpackSize, seqSizeOutStream.processed - padSize, &g_Alloc));
|
||||
}
|
||||
}
|
||||
return Xz_WriteFooter(xz, outStream);
|
||||
}
|
||||
|
||||
SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,
|
||||
const CXzProps *props, ICompressProgress *progress)
|
||||
{
|
||||
SRes res;
|
||||
CXzStream xz;
|
||||
CLzma2WithFilters lzmaf;
|
||||
Xz_Construct(&xz);
|
||||
Lzma2WithFilters_Construct(&lzmaf, &g_Alloc, &g_BigAlloc);
|
||||
res = Lzma2WithFilters_Create(&lzmaf);
|
||||
if (res == SZ_OK)
|
||||
res = Xz_Compress(&xz, &lzmaf, outStream, inStream, props, progress);
|
||||
Lzma2WithFilters_Free(&lzmaf);
|
||||
Xz_Free(&xz, &g_Alloc);
|
||||
return res;
|
||||
}
|
||||
|
||||
SRes Xz_EncodeEmpty(ISeqOutStream *outStream)
|
||||
{
|
||||
SRes res;
|
||||
CXzStream xz;
|
||||
Xz_Construct(&xz);
|
||||
res = Xz_WriteHeader(xz.flags, outStream);
|
||||
if (res == SZ_OK)
|
||||
res = Xz_WriteFooter(&xz, outStream);
|
||||
Xz_Free(&xz, &g_Alloc);
|
||||
return res;
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/* XzEnc.h -- Xz Encode
|
||||
2011-02-07 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __XZ_ENC_H
|
||||
#define __XZ_ENC_H
|
||||
|
||||
#include "Lzma2Enc.h"
|
||||
|
||||
#include "Xz.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 id;
|
||||
UInt32 delta;
|
||||
UInt32 ip;
|
||||
int ipDefined;
|
||||
} CXzFilterProps;
|
||||
|
||||
void XzFilterProps_Init(CXzFilterProps *p);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const CLzma2EncProps *lzma2Props;
|
||||
const CXzFilterProps *filterProps;
|
||||
unsigned checkId;
|
||||
} CXzProps;
|
||||
|
||||
void XzProps_Init(CXzProps *p);
|
||||
|
||||
SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,
|
||||
const CXzProps *props, ICompressProgress *progress);
|
||||
|
||||
SRes Xz_EncodeEmpty(ISeqOutStream *outStream);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue