mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Start work on creating .xz files
This commit is contained in:
parent
63d9d6bca5
commit
d100eaeb9d
@ -69,6 +69,7 @@ extensions = [
|
|||||||
Extension('lzma_binding',
|
Extension('lzma_binding',
|
||||||
glob.glob(os.path.join(SRC, 'lzma', '*.c')),
|
glob.glob(os.path.join(SRC, 'lzma', '*.c')),
|
||||||
headers=glob.glob(os.path.join(SRC, 'lzma', '*.h')),
|
headers=glob.glob(os.path.join(SRC, 'lzma', '*.h')),
|
||||||
|
cflags=[('/' if iswindows else '-') + 'D' + x for x in ('_7ZIP_ST',)],
|
||||||
),
|
),
|
||||||
|
|
||||||
Extension('dukpy',
|
Extension('dukpy',
|
||||||
|
1034
src/lzma/LzFind.c
Normal file
1034
src/lzma/LzFind.c
Normal file
File diff suppressed because it is too large
Load Diff
109
src/lzma/LzFind.h
Normal file
109
src/lzma/LzFind.h
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/* LzFind.h -- Match finder for LZ algorithms
|
||||||
|
2015-05-01 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __LZ_FIND_H
|
||||||
|
#define __LZ_FIND_H
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
typedef UInt32 CLzRef;
|
||||||
|
|
||||||
|
typedef struct _CMatchFinder
|
||||||
|
{
|
||||||
|
Byte *buffer;
|
||||||
|
UInt32 pos;
|
||||||
|
UInt32 posLimit;
|
||||||
|
UInt32 streamPos;
|
||||||
|
UInt32 lenLimit;
|
||||||
|
|
||||||
|
UInt32 cyclicBufferPos;
|
||||||
|
UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
|
||||||
|
|
||||||
|
Byte streamEndWasReached;
|
||||||
|
Byte btMode;
|
||||||
|
Byte bigHash;
|
||||||
|
Byte directInput;
|
||||||
|
|
||||||
|
UInt32 matchMaxLen;
|
||||||
|
CLzRef *hash;
|
||||||
|
CLzRef *son;
|
||||||
|
UInt32 hashMask;
|
||||||
|
UInt32 cutValue;
|
||||||
|
|
||||||
|
Byte *bufferBase;
|
||||||
|
ISeqInStream *stream;
|
||||||
|
|
||||||
|
UInt32 blockSize;
|
||||||
|
UInt32 keepSizeBefore;
|
||||||
|
UInt32 keepSizeAfter;
|
||||||
|
|
||||||
|
UInt32 numHashBytes;
|
||||||
|
size_t directInputRem;
|
||||||
|
UInt32 historySize;
|
||||||
|
UInt32 fixedHashSize;
|
||||||
|
UInt32 hashSizeSum;
|
||||||
|
SRes result;
|
||||||
|
UInt32 crc[256];
|
||||||
|
size_t numRefs;
|
||||||
|
} CMatchFinder;
|
||||||
|
|
||||||
|
#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
|
||||||
|
|
||||||
|
#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
|
||||||
|
|
||||||
|
int MatchFinder_NeedMove(CMatchFinder *p);
|
||||||
|
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
|
||||||
|
void MatchFinder_MoveBlock(CMatchFinder *p);
|
||||||
|
void MatchFinder_ReadIfRequired(CMatchFinder *p);
|
||||||
|
|
||||||
|
void MatchFinder_Construct(CMatchFinder *p);
|
||||||
|
|
||||||
|
/* Conditions:
|
||||||
|
historySize <= 3 GB
|
||||||
|
keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB
|
||||||
|
*/
|
||||||
|
int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
|
||||||
|
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
|
||||||
|
ISzAlloc *alloc);
|
||||||
|
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
|
||||||
|
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems);
|
||||||
|
void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
|
||||||
|
|
||||||
|
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
|
||||||
|
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
|
||||||
|
UInt32 *distances, UInt32 maxLen);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Conditions:
|
||||||
|
Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.
|
||||||
|
Mf_GetPointerToCurrentPos_Func's result must be used only before any other function
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef void (*Mf_Init_Func)(void *object);
|
||||||
|
typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
|
||||||
|
typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
|
||||||
|
typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
|
||||||
|
typedef void (*Mf_Skip_Func)(void *object, UInt32);
|
||||||
|
|
||||||
|
typedef struct _IMatchFinder
|
||||||
|
{
|
||||||
|
Mf_Init_Func Init;
|
||||||
|
Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
|
||||||
|
Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
|
||||||
|
Mf_GetMatches_Func GetMatches;
|
||||||
|
Mf_Skip_Func Skip;
|
||||||
|
} IMatchFinder;
|
||||||
|
|
||||||
|
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
|
||||||
|
|
||||||
|
void MatchFinder_Init(CMatchFinder *p);
|
||||||
|
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
|
||||||
|
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
|
||||||
|
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
|
||||||
|
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
57
src/lzma/LzHash.h
Normal file
57
src/lzma/LzHash.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/* LzHash.h -- HASH functions for LZ algorithms
|
||||||
|
2015-04-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __LZ_HASH_H
|
||||||
|
#define __LZ_HASH_H
|
||||||
|
|
||||||
|
#define kHash2Size (1 << 10)
|
||||||
|
#define kHash3Size (1 << 16)
|
||||||
|
#define kHash4Size (1 << 20)
|
||||||
|
|
||||||
|
#define kFix3HashSize (kHash2Size)
|
||||||
|
#define kFix4HashSize (kHash2Size + kHash3Size)
|
||||||
|
#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
|
||||||
|
|
||||||
|
#define HASH2_CALC hv = cur[0] | ((UInt32)cur[1] << 8);
|
||||||
|
|
||||||
|
#define HASH3_CALC { \
|
||||||
|
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||||
|
h2 = temp & (kHash2Size - 1); \
|
||||||
|
hv = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
|
||||||
|
|
||||||
|
#define HASH4_CALC { \
|
||||||
|
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||||
|
h2 = temp & (kHash2Size - 1); \
|
||||||
|
temp ^= ((UInt32)cur[2] << 8); \
|
||||||
|
h3 = temp & (kHash3Size - 1); \
|
||||||
|
hv = (temp ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
|
||||||
|
|
||||||
|
#define HASH5_CALC { \
|
||||||
|
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||||
|
h2 = temp & (kHash2Size - 1); \
|
||||||
|
temp ^= ((UInt32)cur[2] << 8); \
|
||||||
|
h3 = temp & (kHash3Size - 1); \
|
||||||
|
temp ^= (p->crc[cur[3]] << 5); \
|
||||||
|
h4 = temp & (kHash4Size - 1); \
|
||||||
|
hv = (temp ^ (p->crc[cur[4]] << 3)) & p->hashMask; }
|
||||||
|
|
||||||
|
/* #define HASH_ZIP_CALC hv = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
|
||||||
|
#define HASH_ZIP_CALC hv = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
|
||||||
|
|
||||||
|
|
||||||
|
#define MT_HASH2_CALC \
|
||||||
|
h2 = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
|
||||||
|
|
||||||
|
#define MT_HASH3_CALC { \
|
||||||
|
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||||
|
h2 = temp & (kHash2Size - 1); \
|
||||||
|
h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
|
||||||
|
|
||||||
|
#define MT_HASH4_CALC { \
|
||||||
|
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||||
|
h2 = temp & (kHash2Size - 1); \
|
||||||
|
temp ^= ((UInt32)cur[2] << 8); \
|
||||||
|
h3 = temp & (kHash3Size - 1); \
|
||||||
|
h4 = (temp ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
|
||||||
|
|
||||||
|
#endif
|
493
src/lzma/Lzma2Enc.c
Normal file
493
src/lzma/Lzma2Enc.c
Normal file
@ -0,0 +1,493 @@
|
|||||||
|
/* Lzma2Enc.c -- LZMA2 Encoder
|
||||||
|
2012-06-19 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
/* #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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if (t2 > 1)
|
||||||
|
{
|
||||||
|
UInt64 temp = p->lzmaProps.reduceSize + p->blockSize - 1;
|
||||||
|
if (temp > p->lzmaProps.reduceSize)
|
||||||
|
{
|
||||||
|
UInt64 numBlocks = temp / p->blockSize;
|
||||||
|
if (numBlocks < (unsigned)t2)
|
||||||
|
{
|
||||||
|
t2 = (unsigned)numBlocks;
|
||||||
|
t3 = t1 * t2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p->numBlockThreads = t2;
|
||||||
|
p->numTotalThreads = t3;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
62
src/lzma/Lzma2Enc.h
Normal file
62
src/lzma/Lzma2Enc.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/* Lzma2Enc.h -- LZMA2 Encoder
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __LZMA2_ENC_H
|
||||||
|
#define __LZMA2_ENC_H
|
||||||
|
|
||||||
|
#include "LzmaEnc.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
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);
|
||||||
|
*/
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
2323
src/lzma/LzmaEnc.c
Normal file
2323
src/lzma/LzmaEnc.c
Normal file
File diff suppressed because it is too large
Load Diff
78
src/lzma/LzmaEnc.h
Normal file
78
src/lzma/LzmaEnc.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/* LzmaEnc.h -- LZMA Encoder
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __LZMA_ENC_H
|
||||||
|
#define __LZMA_ENC_H
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
#define LZMA_PROPS_SIZE 5
|
||||||
|
|
||||||
|
typedef struct _CLzmaEncProps
|
||||||
|
{
|
||||||
|
int level; /* 0 <= level <= 9 */
|
||||||
|
UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
|
||||||
|
(1 << 12) <= dictSize <= (1 << 30) for 64-bit version
|
||||||
|
default = (1 << 24) */
|
||||||
|
UInt64 reduceSize; /* estimated size of data that will be compressed. default = 0xFFFFFFFF.
|
||||||
|
Encoder uses this value to reduce dictionary size */
|
||||||
|
int lc; /* 0 <= lc <= 8, default = 3 */
|
||||||
|
int lp; /* 0 <= lp <= 4, default = 0 */
|
||||||
|
int pb; /* 0 <= pb <= 4, default = 2 */
|
||||||
|
int algo; /* 0 - fast, 1 - normal, default = 1 */
|
||||||
|
int fb; /* 5 <= fb <= 273, default = 32 */
|
||||||
|
int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
|
||||||
|
int numHashBytes; /* 2, 3 or 4, default = 4 */
|
||||||
|
UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */
|
||||||
|
unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
|
||||||
|
int numThreads; /* 1 or 2, default = 2 */
|
||||||
|
} CLzmaEncProps;
|
||||||
|
|
||||||
|
void LzmaEncProps_Init(CLzmaEncProps *p);
|
||||||
|
void LzmaEncProps_Normalize(CLzmaEncProps *p);
|
||||||
|
UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- CLzmaEncHandle Interface ---------- */
|
||||||
|
|
||||||
|
/* LzmaEnc_* 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 * CLzmaEncHandle;
|
||||||
|
|
||||||
|
CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc);
|
||||||
|
void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||||
|
SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
|
||||||
|
SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
|
||||||
|
SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,
|
||||||
|
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||||
|
SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
|
||||||
|
int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||||
|
|
||||||
|
/* ---------- One Call Interface ---------- */
|
||||||
|
|
||||||
|
/* LzmaEncode
|
||||||
|
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 LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
|
||||||
|
const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
|
||||||
|
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
@ -9,9 +9,11 @@
|
|||||||
#define UNICODE
|
#define UNICODE
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "Lzma2Dec.h"
|
#include "Lzma2Dec.h"
|
||||||
|
#include "Lzma2Enc.h"
|
||||||
|
#define UNUSED_VAR(x) (void)x;
|
||||||
|
|
||||||
static void *Alloc(void *p, size_t size) { p = p; return PyMem_Malloc(size); }
|
static void *Alloc(void *p, size_t size) { UNUSED_VAR(p); return PyMem_Malloc(size); }
|
||||||
static void Free(void *p, void *address) { p = p; PyMem_Free(address); }
|
static void Free(void *p, void *address) { UNUSED_VAR(p); PyMem_Free(address); }
|
||||||
static ISzAlloc allocator = { Alloc, Free };
|
static ISzAlloc allocator = { Alloc, Free };
|
||||||
static const char* error_codes[18] = {
|
static const char* error_codes[18] = {
|
||||||
"OK",
|
"OK",
|
||||||
@ -33,7 +35,27 @@ static const char* error_codes[18] = {
|
|||||||
};
|
};
|
||||||
#define SET_ERROR(x) PyErr_SetString(LZMAError, ((x) > 0 && (x) < 17) ? error_codes[(x)] : "UNKNOWN")
|
#define SET_ERROR(x) PyErr_SetString(LZMAError, ((x) > 0 && (x) < 17) ? error_codes[(x)] : "UNKNOWN")
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ISeqInStream stream;
|
||||||
|
PyObject *read;
|
||||||
|
PyThreadState **thread_state;
|
||||||
|
} InStream;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ISeqOutStream stream;
|
||||||
|
PyObject *write;
|
||||||
|
PyThreadState **thread_state;
|
||||||
|
} OutStream;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ICompressProgress progress;
|
||||||
|
PyObject *callback;
|
||||||
|
PyThreadState **thread_state;
|
||||||
|
} Progress;
|
||||||
|
|
||||||
static PyObject *LZMAError = NULL;
|
static PyObject *LZMAError = NULL;
|
||||||
|
|
||||||
|
// Utils {{{
|
||||||
static UInt64 crc64_table[256];
|
static UInt64 crc64_table[256];
|
||||||
|
|
||||||
static void init_crc_table() {
|
static void init_crc_table() {
|
||||||
@ -83,7 +105,9 @@ delta_decode(PyObject *self, PyObject *args) {
|
|||||||
}
|
}
|
||||||
return Py_BuildValue("B", pos);
|
return Py_BuildValue("B", pos);
|
||||||
}
|
}
|
||||||
|
// }}}
|
||||||
|
|
||||||
|
// LZMA2 decompress {{{
|
||||||
static PyObject *
|
static PyObject *
|
||||||
decompress2(PyObject *self, PyObject *args) {
|
decompress2(PyObject *self, PyObject *args) {
|
||||||
PyObject *read = NULL, *seek = NULL, *write = NULL, *rres = NULL;
|
PyObject *read = NULL, *seek = NULL, *write = NULL, *rres = NULL;
|
||||||
@ -145,7 +169,9 @@ exit:
|
|||||||
if (PyErr_Occurred()) return NULL;
|
if (PyErr_Occurred()) return NULL;
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
// }}}
|
||||||
|
|
||||||
|
// LZMA1 decompress {{{
|
||||||
static PyObject*
|
static PyObject*
|
||||||
decompress(PyObject *self, PyObject *args) {
|
decompress(PyObject *self, PyObject *args) {
|
||||||
PyObject *read = NULL, *seek = NULL, *write = NULL, *rres = NULL;
|
PyObject *read = NULL, *seek = NULL, *write = NULL, *rres = NULL;
|
||||||
@ -216,11 +242,136 @@ exit:
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// }}}
|
||||||
|
|
||||||
|
// LZMA2 Compress {{{
|
||||||
|
static void
|
||||||
|
init_props(CLzma2EncProps *props, int preset) {
|
||||||
|
int level = (preset < 0) ? 0 : ((preset > 9) ? 9 : preset);
|
||||||
|
props->blockSize = 0;
|
||||||
|
props->numBlockThreads = 1;
|
||||||
|
props->numTotalThreads = 1;
|
||||||
|
props->lzmaProps.numThreads = 1;
|
||||||
|
props->lzmaProps.writeEndMark = 1;
|
||||||
|
|
||||||
|
props->lzmaProps.level = level;
|
||||||
|
props->lzmaProps.dictSize = 0;
|
||||||
|
props->lzmaProps.reduceSize = 0xFFFFFFFF;
|
||||||
|
props->lzmaProps.lc = -1;
|
||||||
|
props->lzmaProps.lp = -1;
|
||||||
|
props->lzmaProps.pb = -1;
|
||||||
|
props->lzmaProps.algo = -1;
|
||||||
|
props->lzmaProps.fb = -1;
|
||||||
|
props->lzmaProps.btMode = -1;
|
||||||
|
props->lzmaProps.numHashBytes = -1;
|
||||||
|
props->lzmaProps.mc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ACQUIRE_GIL PyEval_RestoreThread(*(self->thread_state)); *(self->thread_state) = NULL;
|
||||||
|
#define RELEASE_GIL *(self->thread_state) = PyEval_SaveThread();
|
||||||
|
|
||||||
|
static SRes iread(void *p, void *buf, size_t *size) {
|
||||||
|
InStream *self = (InStream*)p;
|
||||||
|
PyObject *res = NULL;
|
||||||
|
char *str = NULL;
|
||||||
|
if (*size == 0) return SZ_OK;
|
||||||
|
ACQUIRE_GIL
|
||||||
|
res = PyObject_CallFunction(self->read, "n", size);
|
||||||
|
if (res == NULL) return SZ_ERROR_READ;
|
||||||
|
str = PyBytes_AsString(res);
|
||||||
|
if (str == NULL) { Py_DECREF(res); return SZ_ERROR_READ; }
|
||||||
|
*size = PyBytes_Size(res);
|
||||||
|
if(*size) memcpy(buf, str, *size);
|
||||||
|
Py_DECREF(res);
|
||||||
|
RELEASE_GIL
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t owrite(void *p, const void *buf, size_t size) {
|
||||||
|
OutStream *self = (OutStream*)p;
|
||||||
|
PyObject *res = NULL;
|
||||||
|
if (!size) return 0;
|
||||||
|
ACQUIRE_GIL
|
||||||
|
res = PyObject_CallFunction(self->write, "s#", buf, size);
|
||||||
|
if (res == NULL) return SZ_ERROR_WRITE;
|
||||||
|
Py_DECREF(res);
|
||||||
|
RELEASE_GIL
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes report_progress(void *p, UInt64 in_size, UInt64 out_size) {
|
||||||
|
Progress *self = (Progress*)p;
|
||||||
|
if (!self->callback) return SZ_OK;
|
||||||
|
ACQUIRE_GIL
|
||||||
|
PyObject *res = NULL;
|
||||||
|
res = PyObject_CallFunction(self->callback, "KK", in_size, out_size);
|
||||||
|
if (!res || !PyObject_IsTrue(res)) { Py_DECREF(res); return SZ_ERROR_PROGRESS; }
|
||||||
|
Py_DECREF(res);
|
||||||
|
RELEASE_GIL
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
compress(PyObject *self, PyObject *args) {
|
||||||
|
PyObject *read = NULL, *write = NULL, *progress_callback = NULL;
|
||||||
|
CLzma2EncHandle lzma2 = NULL;
|
||||||
|
CLzma2EncProps props;
|
||||||
|
int preset = 5;
|
||||||
|
InStream in_stream;
|
||||||
|
OutStream out_stream;
|
||||||
|
Progress progress;
|
||||||
|
SRes res = SZ_OK;
|
||||||
|
char dictsize = 0;
|
||||||
|
PyThreadState *ts = NULL;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "OO|Oi", &read, &write, &progress_callback, preset)) return NULL;
|
||||||
|
if (progress_callback && !PyCallable_Check(progress_callback)) progress_callback = NULL;
|
||||||
|
|
||||||
|
lzma2 = Lzma2Enc_Create(&allocator, &allocator);
|
||||||
|
if (lzma2 == NULL) { PyErr_NoMemory(); goto exit; }
|
||||||
|
|
||||||
|
// Initialize parameters based on the preset
|
||||||
|
init_props(&props, preset);
|
||||||
|
res = Lzma2Enc_SetProps(lzma2, &props);
|
||||||
|
if (res != SZ_OK) { SET_ERROR(res); goto exit; }
|
||||||
|
|
||||||
|
// Write the dict size to the output stream
|
||||||
|
dictsize = Lzma2Enc_WriteProperties(lzma2);
|
||||||
|
if (!PyObject_CallFunction(write, "c", &dictsize)) { goto exit; }
|
||||||
|
|
||||||
|
// Create the streams and progress callback
|
||||||
|
in_stream.stream.Read = iread;
|
||||||
|
in_stream.read = read;
|
||||||
|
out_stream.stream.Write = owrite;
|
||||||
|
out_stream.write = write;
|
||||||
|
progress.progress.Progress = report_progress;
|
||||||
|
progress.callback = progress_callback;
|
||||||
|
|
||||||
|
// Run the compressor
|
||||||
|
ts = PyEval_SaveThread();
|
||||||
|
in_stream.thread_state = &ts;
|
||||||
|
out_stream.thread_state = &ts;
|
||||||
|
progress.thread_state = &ts;
|
||||||
|
res = Lzma2Enc_Encode(lzma2, (ISeqOutStream*)&out_stream, (ISeqInStream*)&in_stream, (ICompressProgress*)&progress);
|
||||||
|
if (res != SZ_OK) if (!PyErr_Occurred()) SET_ERROR(res);
|
||||||
|
if (ts) PyEval_RestoreThread(ts);
|
||||||
|
exit:
|
||||||
|
if (lzma2) Lzma2Enc_Destroy(lzma2);
|
||||||
|
if (PyErr_Occurred()) return NULL;
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// }}}
|
||||||
|
|
||||||
static PyMethodDef lzma_binding_methods[] = {
|
static PyMethodDef lzma_binding_methods[] = {
|
||||||
{"decompress2", decompress2, METH_VARARGS,
|
{"decompress2", decompress2, METH_VARARGS,
|
||||||
"Decompress an LZMA2 encoded block, of unknown compressed size (reads till LZMA2 EOS marker)"
|
"Decompress an LZMA2 encoded block, of unknown compressed size (reads till LZMA2 EOS marker)"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{"compress", compress, METH_VARARGS,
|
||||||
|
"Compress data into an LZMA2 block"
|
||||||
|
},
|
||||||
|
|
||||||
{"decompress", decompress, METH_VARARGS,
|
{"decompress", decompress, METH_VARARGS,
|
||||||
"Decompress an LZMA encoded block, of (un)known size (reads till LZMA EOS marker when size unknown)"
|
"Decompress an LZMA encoded block, of (un)known size (reads till LZMA EOS marker when size unknown)"
|
||||||
},
|
},
|
||||||
@ -248,21 +399,6 @@ initlzma_binding(void) {
|
|||||||
);
|
);
|
||||||
Py_INCREF(LZMAError);
|
Py_INCREF(LZMAError);
|
||||||
PyModule_AddObject(m, "error", LZMAError);
|
PyModule_AddObject(m, "error", LZMAError);
|
||||||
PyModule_AddIntMacro(m, SZ_OK);
|
|
||||||
PyModule_AddIntMacro(m, SZ_ERROR_DATA);
|
|
||||||
PyModule_AddIntMacro(m, SZ_ERROR_MEM);
|
|
||||||
PyModule_AddIntMacro(m, SZ_ERROR_CRC);
|
|
||||||
PyModule_AddIntMacro(m, SZ_ERROR_UNSUPPORTED);
|
|
||||||
PyModule_AddIntMacro(m, SZ_ERROR_PARAM);
|
|
||||||
PyModule_AddIntMacro(m, SZ_ERROR_INPUT_EOF);
|
|
||||||
PyModule_AddIntMacro(m, SZ_ERROR_OUTPUT_EOF);
|
|
||||||
PyModule_AddIntMacro(m, SZ_ERROR_READ);
|
|
||||||
PyModule_AddIntMacro(m, SZ_ERROR_WRITE);
|
|
||||||
PyModule_AddIntMacro(m, SZ_ERROR_PROGRESS);
|
|
||||||
PyModule_AddIntMacro(m, SZ_ERROR_FAIL);
|
|
||||||
PyModule_AddIntMacro(m, SZ_ERROR_THREAD);
|
|
||||||
PyModule_AddIntMacro(m, SZ_ERROR_ARCHIVE);
|
|
||||||
PyModule_AddIntMacro(m, SZ_ERROR_NO_ARCHIVE);
|
|
||||||
|
|
||||||
if (m == NULL) return;
|
if (m == NULL) return;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user