summaryrefslogtreecommitdiffstats
path: root/Modules/_bz2module.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_bz2module.c')
-rw-r--r--Modules/_bz2module.c196
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 */
};