180 lines
6.4 KiB
C++
180 lines
6.4 KiB
C++
/*
|
|
* Python Bindings for LZMA
|
|
*
|
|
* Copyright (c) 2004-2006 by Joachim Bauch, mail@joachim-bauch.de
|
|
* 7-Zip Copyright (C) 1999-2005 Igor Pavlov
|
|
* LZMA SDK Copyright (C) 1999-2005 Igor Pavlov
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
* $Id: pylzma_compress.cpp 104 2006-01-08 18:17:14Z jojo $
|
|
*
|
|
*/
|
|
|
|
#include <Python.h>
|
|
#include <7zip/Common/MyWindows.h>
|
|
#include <7zip/7zip/IStream.h>
|
|
#include <7zip/7zip/Compress/LZMA/LZMAEncoder.h>
|
|
|
|
#include "pylzma.h"
|
|
#include "pylzma_streams.h"
|
|
|
|
int set_encoder_properties(NCompress::NLZMA::CEncoder *encoder, int dictionary, int posBits,
|
|
int literalContextBits, int literalPosBits, int algorithm, int fastBytes, int eos,
|
|
int multithreading, const char *matchfinder)
|
|
{
|
|
wchar_t tmp[10];
|
|
unsigned int i;
|
|
encoder->SetWriteEndMarkerMode(eos ? true : false);
|
|
|
|
PROPID propIDs[] =
|
|
{
|
|
NCoderPropID::kDictionarySize,
|
|
NCoderPropID::kPosStateBits,
|
|
NCoderPropID::kLitContextBits,
|
|
NCoderPropID::kLitPosBits,
|
|
NCoderPropID::kAlgorithm,
|
|
NCoderPropID::kNumFastBytes,
|
|
NCoderPropID::kMatchFinder
|
|
#ifdef COMPRESS_MF_MT
|
|
, NCoderPropID::kMultiThread
|
|
#endif
|
|
};
|
|
const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
|
|
PROPVARIANT props[kNumProps];
|
|
// NCoderProp::kDictionarySize;
|
|
props[0].vt = VT_UI4;
|
|
props[0].ulVal = 1 << dictionary;
|
|
// NCoderProp::kPosStateBits;
|
|
props[1].vt = VT_UI4;
|
|
props[1].ulVal = posBits;
|
|
// NCoderProp::kLitContextBits;
|
|
props[2].vt = VT_UI4;
|
|
props[2].ulVal = literalContextBits;
|
|
// NCoderProp::kLitPosBits;
|
|
props[3].vt = VT_UI4;
|
|
props[3].ulVal = literalPosBits;
|
|
// NCoderProp::kAlgorithm;
|
|
props[4].vt = VT_UI4;
|
|
props[4].ulVal = algorithm;
|
|
// NCoderProp::kNumFastBytes;
|
|
props[5].vt = VT_UI4;
|
|
props[5].ulVal = fastBytes;
|
|
// NCoderProp::kMatchFinder;
|
|
if (strlen(matchfinder) > (sizeof(tmp)/2)-1)
|
|
return 1;
|
|
|
|
props[6].vt = VT_BSTR;
|
|
for (i=0; i<strlen(matchfinder); i++)
|
|
tmp[i] = matchfinder[i];
|
|
tmp[i] = 0;
|
|
props[6].bstrVal = (BSTR)(const wchar_t *)&tmp;
|
|
#ifdef COMPRESS_MF_MT
|
|
// NCoderPropID::kMultiThread
|
|
props[7].vt = VT_BOOL;
|
|
props[7].boolVal = (multithreading != 0) ? VARIANT_TRUE : VARIANT_FALSE;
|
|
#endif
|
|
|
|
return encoder->SetCoderProperties(propIDs, props, kNumProps);
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
extern "C"
|
|
#endif
|
|
const char doc_compress[] = \
|
|
"compress(string, dictionary=23, fastBytes=128, literalContextBits=3, literalPosBits=0, posBits=2, algorithm=2, eos=1, multithreading=1, matchfinder='bt4') -- Compress the data in string using the given parameters, returning a string containing the compressed data.";
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
PyObject *pylzma_compress(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
{
|
|
PyObject *result = NULL;
|
|
NCompress::NLZMA::CEncoder *encoder = NULL;
|
|
CInStream *inStream = NULL;
|
|
COutStream *outStream = NULL;
|
|
int res;
|
|
// possible keywords for this function
|
|
static char *kwlist[] = {"data", "dictionary", "fastBytes", "literalContextBits",
|
|
"literalPosBits", "posBits", "algorithm", "eos", "multithreading", "matchfinder", NULL};
|
|
int dictionary = 23; // [0,28], default 23 (8MB)
|
|
int fastBytes = 128; // [5,255], default 128
|
|
int literalContextBits = 3; // [0,8], default 3
|
|
int literalPosBits = 0; // [0,4], default 0
|
|
int posBits = 2; // [0,4], default 2
|
|
int eos = 1; // write "end of stream" marker?
|
|
int multithreading = 1; // use multithreading if available?
|
|
char *matchfinder = "bt4"; // matchfinder algorithm
|
|
int algorithm = 2;
|
|
char *data;
|
|
int length;
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|iiiiiiiis", kwlist, &data, &length, &dictionary, &fastBytes,
|
|
&literalContextBits, &literalPosBits, &posBits, &algorithm, &eos, &multithreading, &matchfinder))
|
|
return NULL;
|
|
|
|
CHECK_RANGE(dictionary, 0, 28, "dictionary must be between 0 and 28");
|
|
CHECK_RANGE(fastBytes, 5, 255, "fastBytes must be between 5 and 255");
|
|
CHECK_RANGE(literalContextBits, 0, 8, "literalContextBits must be between 0 and 8");
|
|
CHECK_RANGE(literalPosBits, 0, 4, "literalPosBits must be between 0 and 4");
|
|
CHECK_RANGE(posBits, 0, 4, "posBits must be between 0 and 4");
|
|
CHECK_RANGE(algorithm, 0, 2, "algorithm must be between 0 and 2");
|
|
|
|
encoder = new NCompress::NLZMA::CEncoder();
|
|
CHECK_NULL(encoder);
|
|
|
|
if ((res = set_encoder_properties(encoder, dictionary, posBits, literalContextBits, literalPosBits, algorithm, fastBytes, eos, multithreading, matchfinder) != 0))
|
|
{
|
|
PyErr_SetString(PyExc_TypeError, "can't set coder properties");
|
|
goto exit;
|
|
}
|
|
|
|
inStream = new CInStream((BYTE *)data, length);
|
|
CHECK_NULL(inStream);
|
|
outStream = new COutStream();
|
|
CHECK_NULL(outStream);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
encoder->SetStreams(inStream, outStream, 0, 0);
|
|
encoder->WriteCoderProperties(outStream);
|
|
while(true)
|
|
{
|
|
UInt64 processedInSize;
|
|
UInt64 processedOutSize;
|
|
Int32 finished;
|
|
if ((res = encoder->CodeOneBlock(&processedInSize, &processedOutSize, &finished)) != S_OK)
|
|
{
|
|
PyErr_Format(PyExc_TypeError, "Error during compressing: %d", res);
|
|
goto exit;
|
|
}
|
|
if (finished != 0)
|
|
break;
|
|
}
|
|
Py_END_ALLOW_THREADS
|
|
|
|
result = PyString_FromStringAndSize((const char *)outStream->getData(), outStream->getLength());
|
|
|
|
exit:
|
|
DELETE_AND_NULL(encoder);
|
|
DELETE_AND_NULL(inStream);
|
|
|
|
return result;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|