diff options
Diffstat (limited to 'Modules/_bz2module.c')
| -rw-r--r-- | Modules/_bz2module.c | 196 |
1 files changed, 115 insertions, 81 deletions
diff --git a/Modules/_bz2module.c b/Modules/_bz2module.c index 3f7a6cf..e652f4d 100644 --- a/Modules/_bz2module.c +++ b/Modules/_bz2module.c @@ -36,8 +36,6 @@ #define RELEASE_LOCK(obj) #endif -#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) - typedef struct { PyObject_HEAD @@ -58,6 +56,8 @@ typedef struct { #endif } BZ2Decompressor; +static PyTypeObject BZ2Compressor_Type; +static PyTypeObject BZ2Decompressor_Type; /* Helper functions. */ @@ -149,7 +149,7 @@ compress(BZ2Compressor *c, char *data, size_t len, int action) c->bzs.next_in = data; c->bzs.avail_in = 0; c->bzs.next_out = PyBytes_AS_STRING(result); - c->bzs.avail_out = PyBytes_GET_SIZE(result); + c->bzs.avail_out = SMALLCHUNK; for (;;) { char *this_out; int bzerror; @@ -157,7 +157,7 @@ compress(BZ2Compressor *c, char *data, size_t len, int action) /* On a 64-bit system, len might not fit in avail_in (an unsigned int). Do compression in chunks of no more than UINT_MAX bytes each. */ if (c->bzs.avail_in == 0 && len > 0) { - c->bzs.avail_in = MIN(len, UINT_MAX); + c->bzs.avail_in = (unsigned int)Py_MIN(len, UINT_MAX); len -= c->bzs.avail_in; } @@ -173,7 +173,7 @@ compress(BZ2Compressor *c, char *data, size_t len, int action) c->bzs.next_out = PyBytes_AS_STRING(result) + data_size; buffer_left = PyBytes_GET_SIZE(result) - data_size; } - c->bzs.avail_out = MIN(buffer_left, UINT_MAX); + c->bzs.avail_out = (unsigned int)Py_MIN(buffer_left, UINT_MAX); } Py_BEGIN_ALLOW_THREADS @@ -198,44 +198,58 @@ error: return NULL; } -PyDoc_STRVAR(BZ2Compressor_compress__doc__, -"compress(data) -> bytes\n" -"\n" -"Provide data to the compressor object. Returns a chunk of\n" -"compressed data if possible, or b'' otherwise.\n" -"\n" -"When you have finished providing data to the compressor, call the\n" -"flush() method to finish the compression process.\n"); +/*[clinic input] +output preset file +module _bz2 +class _bz2.BZ2Compressor "BZ2Compressor *" "&BZ2Compressor_Type" +class _bz2.BZ2Decompressor "BZ2Decompressor *" "&BZ2Decompressor_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e3b139924f5e18cc]*/ + +#include "clinic/_bz2module.c.h" + +/*[clinic input] +_bz2.BZ2Compressor.compress + + data: Py_buffer + / + +Provide data to the compressor object. + +Returns a chunk of compressed data if possible, or b'' otherwise. + +When you have finished providing data to the compressor, call the +flush() method to finish the compression process. +[clinic start generated code]*/ static PyObject * -BZ2Compressor_compress(BZ2Compressor *self, PyObject *args) +_bz2_BZ2Compressor_compress_impl(BZ2Compressor *self, Py_buffer *data) +/*[clinic end generated code: output=59365426e941fbcc input=85c963218070fc4c]*/ { - Py_buffer buffer; PyObject *result = NULL; - if (!PyArg_ParseTuple(args, "y*:compress", &buffer)) - return NULL; - ACQUIRE_LOCK(self); if (self->flushed) PyErr_SetString(PyExc_ValueError, "Compressor has been flushed"); else - result = compress(self, buffer.buf, buffer.len, BZ_RUN); + result = compress(self, data->buf, data->len, BZ_RUN); RELEASE_LOCK(self); - PyBuffer_Release(&buffer); return result; } -PyDoc_STRVAR(BZ2Compressor_flush__doc__, -"flush() -> bytes\n" -"\n" -"Finish the compression process. Returns the compressed data left\n" -"in internal buffers.\n" -"\n" -"The compressor object may not be used after this method is called.\n"); +/*[clinic input] +_bz2.BZ2Compressor.flush + +Finish the compression process. + +Returns the compressed data left in internal buffers. + +The compressor object may not be used after this method is called. +[clinic start generated code]*/ static PyObject * -BZ2Compressor_flush(BZ2Compressor *self, PyObject *noargs) +_bz2_BZ2Compressor_flush_impl(BZ2Compressor *self) +/*[clinic end generated code: output=3ef03fc1b092a701 input=d64405d3c6f76691]*/ { PyObject *result = NULL; @@ -258,14 +272,42 @@ BZ2Compressor_getstate(BZ2Compressor *self, PyObject *noargs) return NULL; } +static void* +BZ2_Malloc(void* ctx, int items, int size) +{ + if (items < 0 || size < 0) + return NULL; + if ((size_t)items > (size_t)PY_SSIZE_T_MAX / (size_t)size) + return NULL; + /* PyMem_Malloc() cannot be used: compress() and decompress() + release the GIL */ + return PyMem_RawMalloc(items * size); +} + +static void +BZ2_Free(void* ctx, void *ptr) +{ + PyMem_RawFree(ptr); +} + +/*[clinic input] +_bz2.BZ2Compressor.__init__ + + compresslevel: int = 9 + Compression level, as a number between 1 and 9. + / + +Create a compressor object for compressing data incrementally. + +For one-shot compression, use the compress() function instead. +[clinic start generated code]*/ + static int -BZ2Compressor_init(BZ2Compressor *self, PyObject *args, PyObject *kwargs) +_bz2_BZ2Compressor___init___impl(BZ2Compressor *self, int compresslevel) +/*[clinic end generated code: output=c4e6adfd02963827 input=4e1ff7b8394b6e9a]*/ { - int compresslevel = 9; int bzerror; - if (!PyArg_ParseTuple(args, "|i:BZ2Compressor", &compresslevel)) - return -1; if (!(1 <= compresslevel && compresslevel <= 9)) { PyErr_SetString(PyExc_ValueError, "compresslevel must be between 1 and 9"); @@ -280,6 +322,9 @@ BZ2Compressor_init(BZ2Compressor *self, PyObject *args, PyObject *kwargs) } #endif + self->bzs.opaque = NULL; + self->bzs.bzalloc = BZ2_Malloc; + self->bzs.bzfree = BZ2_Free; bzerror = BZ2_bzCompressInit(&self->bzs, compresslevel, 0, 0); if (catch_bz2_error(bzerror)) goto error; @@ -306,22 +351,12 @@ BZ2Compressor_dealloc(BZ2Compressor *self) } static PyMethodDef BZ2Compressor_methods[] = { - {"compress", (PyCFunction)BZ2Compressor_compress, METH_VARARGS, - BZ2Compressor_compress__doc__}, - {"flush", (PyCFunction)BZ2Compressor_flush, METH_NOARGS, - BZ2Compressor_flush__doc__}, + _BZ2_BZ2COMPRESSOR_COMPRESS_METHODDEF + _BZ2_BZ2COMPRESSOR_FLUSH_METHODDEF {"__getstate__", (PyCFunction)BZ2Compressor_getstate, METH_NOARGS}, {NULL} }; -PyDoc_STRVAR(BZ2Compressor__doc__, -"BZ2Compressor(compresslevel=9)\n" -"\n" -"Create a compressor object for compressing data incrementally.\n" -"\n" -"compresslevel, if given, must be a number between 1 and 9.\n" -"\n" -"For one-shot compression, use the compress() function instead.\n"); static PyTypeObject BZ2Compressor_Type = { PyVarObject_HEAD_INIT(NULL, 0) @@ -344,7 +379,7 @@ static PyTypeObject BZ2Compressor_Type = { 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ - BZ2Compressor__doc__, /* tp_doc */ + _bz2_BZ2Compressor___init____doc__, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ @@ -359,7 +394,7 @@ static PyTypeObject BZ2Compressor_Type = { 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ - (initproc)BZ2Compressor_init, /* tp_init */ + _bz2_BZ2Compressor___init__, /* tp_init */ 0, /* tp_alloc */ PyType_GenericNew, /* tp_new */ }; @@ -379,10 +414,10 @@ decompress(BZ2Decompressor *d, char *data, size_t len) d->bzs.next_in = data; /* On a 64-bit system, len might not fit in avail_in (an unsigned int). Do decompression in chunks of no more than UINT_MAX bytes each. */ - d->bzs.avail_in = MIN(len, UINT_MAX); + d->bzs.avail_in = (unsigned int)Py_MIN(len, UINT_MAX); len -= d->bzs.avail_in; d->bzs.next_out = PyBytes_AS_STRING(result); - d->bzs.avail_out = PyBytes_GET_SIZE(result); + d->bzs.avail_out = SMALLCHUNK; for (;;) { char *this_out; int bzerror; @@ -408,7 +443,7 @@ decompress(BZ2Decompressor *d, char *data, size_t len) if (d->bzs.avail_in == 0) { if (len == 0) break; - d->bzs.avail_in = MIN(len, UINT_MAX); + d->bzs.avail_in = (unsigned int)Py_MIN(len, UINT_MAX); len -= d->bzs.avail_in; } if (d->bzs.avail_out == 0) { @@ -419,7 +454,7 @@ decompress(BZ2Decompressor *d, char *data, size_t len) d->bzs.next_out = PyBytes_AS_STRING(result) + data_size; buffer_left = PyBytes_GET_SIZE(result) - data_size; } - d->bzs.avail_out = MIN(buffer_left, UINT_MAX); + d->bzs.avail_out = (unsigned int)Py_MIN(buffer_left, UINT_MAX); } } if (data_size != PyBytes_GET_SIZE(result)) @@ -432,32 +467,33 @@ error: return NULL; } -PyDoc_STRVAR(BZ2Decompressor_decompress__doc__, -"decompress(data) -> bytes\n" -"\n" -"Provide data to the decompressor object. Returns a chunk of\n" -"decompressed data if possible, or b'' otherwise.\n" -"\n" -"Attempting to decompress data after the end of stream is reached\n" -"raises an EOFError. Any data found after the end of the stream\n" -"is ignored and saved in the unused_data attribute.\n"); +/*[clinic input] +_bz2.BZ2Decompressor.decompress + + data: Py_buffer + / + +Provide data to the decompressor object. + +Returns a chunk of decompressed data if possible, or b'' otherwise. + +Attempting to decompress data after the end of stream is reached +raises an EOFError. Any data found after the end of the stream +is ignored and saved in the unused_data attribute. +[clinic start generated code]*/ static PyObject * -BZ2Decompressor_decompress(BZ2Decompressor *self, PyObject *args) +_bz2_BZ2Decompressor_decompress_impl(BZ2Decompressor *self, Py_buffer *data) +/*[clinic end generated code: output=086e4b99e60cb3f6 input=616c2a6db5269961]*/ { - Py_buffer buffer; PyObject *result = NULL; - if (!PyArg_ParseTuple(args, "y*:decompress", &buffer)) - return NULL; - ACQUIRE_LOCK(self); if (self->eof) PyErr_SetString(PyExc_EOFError, "End of stream already reached"); else - result = decompress(self, buffer.buf, buffer.len); + result = decompress(self, data->buf, data->len); RELEASE_LOCK(self); - PyBuffer_Release(&buffer); return result; } @@ -469,14 +505,20 @@ BZ2Decompressor_getstate(BZ2Decompressor *self, PyObject *noargs) return NULL; } +/*[clinic input] +_bz2.BZ2Decompressor.__init__ + +Create a decompressor object for decompressing data incrementally. + +For one-shot decompression, use the decompress() function instead. +[clinic start generated code]*/ + static int -BZ2Decompressor_init(BZ2Decompressor *self, PyObject *args, PyObject *kwargs) +_bz2_BZ2Decompressor___init___impl(BZ2Decompressor *self) +/*[clinic end generated code: output=e4d2b9bb866ab8f1 input=95f6500dcda60088]*/ { int bzerror; - if (!PyArg_ParseTuple(args, ":BZ2Decompressor")) - return -1; - #ifdef WITH_THREAD self->lock = PyThread_allocate_lock(); if (self->lock == NULL) { @@ -517,8 +559,7 @@ BZ2Decompressor_dealloc(BZ2Decompressor *self) } static PyMethodDef BZ2Decompressor_methods[] = { - {"decompress", (PyCFunction)BZ2Decompressor_decompress, METH_VARARGS, - BZ2Decompressor_decompress__doc__}, + _BZ2_BZ2DECOMPRESSOR_DECOMPRESS_METHODDEF {"__getstate__", (PyCFunction)BZ2Decompressor_getstate, METH_NOARGS}, {NULL} }; @@ -537,13 +578,6 @@ static PyMemberDef BZ2Decompressor_members[] = { {NULL} }; -PyDoc_STRVAR(BZ2Decompressor__doc__, -"BZ2Decompressor()\n" -"\n" -"Create a decompressor object for decompressing data incrementally.\n" -"\n" -"For one-shot decompression, use the decompress() function instead.\n"); - static PyTypeObject BZ2Decompressor_Type = { PyVarObject_HEAD_INIT(NULL, 0) "_bz2.BZ2Decompressor", /* tp_name */ @@ -565,7 +599,7 @@ static PyTypeObject BZ2Decompressor_Type = { 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ - BZ2Decompressor__doc__, /* tp_doc */ + _bz2_BZ2Decompressor___init____doc__, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ @@ -580,7 +614,7 @@ static PyTypeObject BZ2Decompressor_Type = { 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ - (initproc)BZ2Decompressor_init, /* tp_init */ + _bz2_BZ2Decompressor___init__, /* tp_init */ 0, /* tp_alloc */ PyType_GenericNew, /* tp_new */ }; |
