255 lines
9.3 KiB
C++
255 lines
9.3 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_compressfile.cpp 104 2006-01-08 18:17:14Z jojo $
|
|
*
|
|
*/
|
|
|
|
#include <Python.h>
|
|
#include <cStringIO.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"
|
|
#include "pylzma_compress.h"
|
|
#include "pylzma_compressfile.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);
|
|
|
|
typedef struct {
|
|
PyObject_HEAD
|
|
NCompress::NLZMA::CEncoder *encoder;
|
|
CInStream *inStream;
|
|
COutStream *outStream;
|
|
PyObject *inFile;
|
|
} CCompressionFileObject;
|
|
|
|
static char *doc_compfile_read = \
|
|
"docstring is todo\n";
|
|
|
|
static PyObject *pylzma_compfile_read(CCompressionFileObject *self, PyObject *args)
|
|
{
|
|
PyObject *result = NULL;
|
|
int length, bufsize=0;
|
|
|
|
if (!PyArg_ParseTuple(args, "|l", &bufsize))
|
|
return NULL;
|
|
|
|
while (!bufsize || self->outStream->getMaxRead() < bufsize)
|
|
{
|
|
UInt64 processedInSize;
|
|
UInt64 processedOutSize;
|
|
INT32 finished;
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
self->encoder->CodeOneBlock(&processedInSize, &processedOutSize, &finished);
|
|
Py_END_ALLOW_THREADS
|
|
if (finished)
|
|
break;
|
|
}
|
|
|
|
if (bufsize)
|
|
length = min(bufsize, self->outStream->getMaxRead());
|
|
else
|
|
length = self->outStream->getMaxRead();
|
|
result = PyString_FromStringAndSize((const char *)self->outStream->getReadPtr(), length);
|
|
if (result == NULL) {
|
|
PyErr_NoMemory();
|
|
goto exit;
|
|
}
|
|
self->outStream->increaseReadPos(length);
|
|
|
|
exit:
|
|
return result;
|
|
}
|
|
|
|
static PyMethodDef pylzma_compfile_methods[] = {
|
|
{"read", (PyCFunction)pylzma_compfile_read, METH_VARARGS, doc_compfile_read},
|
|
{NULL, NULL},
|
|
};
|
|
|
|
static void pylzma_compfile_dealloc(CCompressionFileObject *self)
|
|
{
|
|
DEC_AND_NULL(self->inFile);
|
|
DELETE_AND_NULL(self->encoder);
|
|
DELETE_AND_NULL(self->inStream);
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
static PyObject* pylzma_compfile_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
CCompressionFileObject *self;
|
|
|
|
self = (CCompressionFileObject*)type->tp_alloc(type, 0);
|
|
if (self != NULL) {
|
|
self->encoder = NULL;
|
|
self->inStream = NULL;
|
|
self->outStream = NULL;
|
|
self->inFile = NULL;
|
|
}
|
|
|
|
return (PyObject*)self;
|
|
}
|
|
|
|
int pylzma_compfile_init(CCompressionFileObject *self, PyObject *args, PyObject *kwargs)
|
|
{
|
|
PyObject *inFile;
|
|
NCompress::NLZMA::CEncoder *encoder;
|
|
int result = -1;
|
|
|
|
// possible keywords for this function
|
|
static char *kwlist[] = {"infile", "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;
|
|
int res;
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iiiiiiiis", kwlist, &inFile, &dictionary, &fastBytes,
|
|
&literalContextBits, &literalPosBits, &posBits, &algorithm, &eos, &multithreading, &matchfinder))
|
|
return -1;
|
|
|
|
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");
|
|
|
|
if (PyString_Check(inFile)) {
|
|
// create new cStringIO object from string
|
|
inFile = PycStringIO->NewInput(inFile);
|
|
if (inFile == NULL)
|
|
{
|
|
PyErr_NoMemory();
|
|
return -1;
|
|
}
|
|
} else if (!PyObject_HasAttrString(inFile, "read")) {
|
|
PyErr_SetString(PyExc_ValueError, "first parameter must be a file-like object");
|
|
return -1;
|
|
} else
|
|
// protect object from being refcounted out...
|
|
Py_XINCREF(inFile);
|
|
|
|
encoder = new NCompress::NLZMA::CEncoder();
|
|
CHECK_NULL(encoder);
|
|
|
|
if ((res = set_encoder_properties(encoder, dictionary, posBits, literalContextBits, literalPosBits, algorithm, fastBytes, eos, multithreading, matchfinder) != 0))
|
|
{
|
|
Py_XDECREF(inFile);
|
|
DELETE_AND_NULL(encoder);
|
|
PyErr_SetString(PyExc_TypeError, "can't set coder properties");
|
|
goto exit;
|
|
}
|
|
|
|
self->inFile = inFile;
|
|
self->encoder = encoder;
|
|
self->inStream = new CInStream(inFile);
|
|
if (self->inStream == NULL)
|
|
{
|
|
DEC_AND_NULL(self->inFile);
|
|
DELETE_AND_NULL(encoder);
|
|
DEC_AND_NULL(self);
|
|
PyErr_NoMemory();
|
|
goto exit;
|
|
}
|
|
self->outStream = new COutStream();
|
|
if (self->outStream == NULL)
|
|
{
|
|
DEC_AND_NULL(self->inFile);
|
|
DELETE_AND_NULL(encoder);
|
|
DELETE_AND_NULL(self->inStream);
|
|
DEC_AND_NULL(self);
|
|
PyErr_NoMemory();
|
|
goto exit;
|
|
}
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
encoder->SetStreams(self->inStream, self->outStream, 0, 0);
|
|
encoder->WriteCoderProperties(self->outStream);
|
|
Py_END_ALLOW_THREADS
|
|
result = 0;
|
|
|
|
exit:
|
|
return result;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
PyTypeObject CCompressionFileObject_Type = {
|
|
//PyObject_HEAD_INIT(&PyType_Type)
|
|
PyObject_HEAD_INIT(NULL)
|
|
0,
|
|
"LZMACompressFile", /* char *tp_name; */
|
|
sizeof(CCompressionFileObject), /* int tp_basicsize; */
|
|
0, /* int tp_itemsize; // not used much */
|
|
(destructor)pylzma_compfile_dealloc, /* destructor tp_dealloc; */
|
|
NULL, /* printfunc tp_print; */
|
|
NULL, /* getattrfunc tp_getattr; // __getattr__ */
|
|
NULL, /* setattrfunc tp_setattr; // __setattr__ */
|
|
NULL, /* cmpfunc tp_compare; // __cmp__ */
|
|
NULL, /* reprfunc tp_repr; // __repr__ */
|
|
NULL, /* PyNumberMethods *tp_as_number; */
|
|
NULL, /* PySequenceMethods *tp_as_sequence; */
|
|
NULL, /* PyMappingMethods *tp_as_mapping; */
|
|
NULL, /* hashfunc tp_hash; // __hash__ */
|
|
NULL, /* ternaryfunc tp_call; // __call__ */
|
|
NULL, /* reprfunc tp_str; // __str__ */
|
|
0, /* tp_getattro*/
|
|
0, /* tp_setattro*/
|
|
0, /* tp_as_buffer*/
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
|
|
"File compression class", /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
pylzma_compfile_methods, /* tp_methods */
|
|
0, /* tp_members */
|
|
0, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)pylzma_compfile_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
pylzma_compfile_new, /* tp_new */
|
|
};
|