/* * 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 #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; iSetCoderProperties(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