ยปCore Development>Code coverage>Modules/_bz2module.c

Python code coverage for Modules/_bz2module.c

#countcontent
1n/a/* _bz2 - Low-level Python interface to libbzip2. */
2n/a
3n/a#define PY_SSIZE_T_CLEAN
4n/a
5n/a#include "Python.h"
6n/a#include "structmember.h"
7n/a
8n/a#ifdef WITH_THREAD
9n/a#include "pythread.h"
10n/a#endif
11n/a
12n/a#include <bzlib.h>
13n/a#include <stdio.h>
14n/a
15n/a
16n/a#ifndef BZ_CONFIG_ERROR
17n/a#define BZ2_bzCompress bzCompress
18n/a#define BZ2_bzCompressInit bzCompressInit
19n/a#define BZ2_bzCompressEnd bzCompressEnd
20n/a#define BZ2_bzDecompress bzDecompress
21n/a#define BZ2_bzDecompressInit bzDecompressInit
22n/a#define BZ2_bzDecompressEnd bzDecompressEnd
23n/a#endif /* ! BZ_CONFIG_ERROR */
24n/a
25n/a
26n/a#ifdef WITH_THREAD
27n/a#define ACQUIRE_LOCK(obj) do { \
28n/a if (!PyThread_acquire_lock((obj)->lock, 0)) { \
29n/a Py_BEGIN_ALLOW_THREADS \
30n/a PyThread_acquire_lock((obj)->lock, 1); \
31n/a Py_END_ALLOW_THREADS \
32n/a } } while (0)
33n/a#define RELEASE_LOCK(obj) PyThread_release_lock((obj)->lock)
34n/a#else
35n/a#define ACQUIRE_LOCK(obj)
36n/a#define RELEASE_LOCK(obj)
37n/a#endif
38n/a
39n/a
40n/atypedef struct {
41n/a PyObject_HEAD
42n/a bz_stream bzs;
43n/a int flushed;
44n/a#ifdef WITH_THREAD
45n/a PyThread_type_lock lock;
46n/a#endif
47n/a} BZ2Compressor;
48n/a
49n/atypedef struct {
50n/a PyObject_HEAD
51n/a bz_stream bzs;
52n/a char eof; /* T_BOOL expects a char */
53n/a PyObject *unused_data;
54n/a char needs_input;
55n/a char *input_buffer;
56n/a size_t input_buffer_size;
57n/a
58n/a /* bzs->avail_in is only 32 bit, so we store the true length
59n/a separately. Conversion and looping is encapsulated in
60n/a decompress_buf() */
61n/a size_t bzs_avail_in_real;
62n/a#ifdef WITH_THREAD
63n/a PyThread_type_lock lock;
64n/a#endif
65n/a} BZ2Decompressor;
66n/a
67n/astatic PyTypeObject BZ2Compressor_Type;
68n/astatic PyTypeObject BZ2Decompressor_Type;
69n/a
70n/a/* Helper functions. */
71n/a
72n/astatic int
73n/acatch_bz2_error(int bzerror)
74n/a{
75n/a switch(bzerror) {
76n/a case BZ_OK:
77n/a case BZ_RUN_OK:
78n/a case BZ_FLUSH_OK:
79n/a case BZ_FINISH_OK:
80n/a case BZ_STREAM_END:
81n/a return 0;
82n/a
83n/a#ifdef BZ_CONFIG_ERROR
84n/a case BZ_CONFIG_ERROR:
85n/a PyErr_SetString(PyExc_SystemError,
86n/a "libbzip2 was not compiled correctly");
87n/a return 1;
88n/a#endif
89n/a case BZ_PARAM_ERROR:
90n/a PyErr_SetString(PyExc_ValueError,
91n/a "Internal error - "
92n/a "invalid parameters passed to libbzip2");
93n/a return 1;
94n/a case BZ_MEM_ERROR:
95n/a PyErr_NoMemory();
96n/a return 1;
97n/a case BZ_DATA_ERROR:
98n/a case BZ_DATA_ERROR_MAGIC:
99n/a PyErr_SetString(PyExc_IOError, "Invalid data stream");
100n/a return 1;
101n/a case BZ_IO_ERROR:
102n/a PyErr_SetString(PyExc_IOError, "Unknown I/O error");
103n/a return 1;
104n/a case BZ_UNEXPECTED_EOF:
105n/a PyErr_SetString(PyExc_EOFError,
106n/a "Compressed file ended before the logical "
107n/a "end-of-stream was detected");
108n/a return 1;
109n/a case BZ_SEQUENCE_ERROR:
110n/a PyErr_SetString(PyExc_RuntimeError,
111n/a "Internal error - "
112n/a "Invalid sequence of commands sent to libbzip2");
113n/a return 1;
114n/a default:
115n/a PyErr_Format(PyExc_IOError,
116n/a "Unrecognized error from libbzip2: %d", bzerror);
117n/a return 1;
118n/a }
119n/a}
120n/a
121n/a#if BUFSIZ < 8192
122n/a#define INITIAL_BUFFER_SIZE 8192
123n/a#else
124n/a#define INITIAL_BUFFER_SIZE BUFSIZ
125n/a#endif
126n/a
127n/astatic int
128n/agrow_buffer(PyObject **buf, Py_ssize_t max_length)
129n/a{
130n/a /* Expand the buffer by an amount proportional to the current size,
131n/a giving us amortized linear-time behavior. Use a less-than-double
132n/a growth factor to avoid excessive allocation. */
133n/a size_t size = PyBytes_GET_SIZE(*buf);
134n/a size_t new_size = size + (size >> 3) + 6;
135n/a
136n/a if (max_length > 0 && new_size > (size_t) max_length)
137n/a new_size = (size_t) max_length;
138n/a
139n/a if (new_size > size) {
140n/a return _PyBytes_Resize(buf, new_size);
141n/a } else { /* overflow */
142n/a PyErr_SetString(PyExc_OverflowError,
143n/a "Unable to allocate buffer - output too large");
144n/a return -1;
145n/a }
146n/a}
147n/a
148n/a
149n/a/* BZ2Compressor class. */
150n/a
151n/astatic PyObject *
152n/acompress(BZ2Compressor *c, char *data, size_t len, int action)
153n/a{
154n/a size_t data_size = 0;
155n/a PyObject *result;
156n/a
157n/a result = PyBytes_FromStringAndSize(NULL, INITIAL_BUFFER_SIZE);
158n/a if (result == NULL)
159n/a return NULL;
160n/a
161n/a c->bzs.next_in = data;
162n/a c->bzs.avail_in = 0;
163n/a c->bzs.next_out = PyBytes_AS_STRING(result);
164n/a c->bzs.avail_out = INITIAL_BUFFER_SIZE;
165n/a for (;;) {
166n/a char *this_out;
167n/a int bzerror;
168n/a
169n/a /* On a 64-bit system, len might not fit in avail_in (an unsigned int).
170n/a Do compression in chunks of no more than UINT_MAX bytes each. */
171n/a if (c->bzs.avail_in == 0 && len > 0) {
172n/a c->bzs.avail_in = (unsigned int)Py_MIN(len, UINT_MAX);
173n/a len -= c->bzs.avail_in;
174n/a }
175n/a
176n/a /* In regular compression mode, stop when input data is exhausted. */
177n/a if (action == BZ_RUN && c->bzs.avail_in == 0)
178n/a break;
179n/a
180n/a if (c->bzs.avail_out == 0) {
181n/a size_t buffer_left = PyBytes_GET_SIZE(result) - data_size;
182n/a if (buffer_left == 0) {
183n/a if (grow_buffer(&result, -1) < 0)
184n/a goto error;
185n/a c->bzs.next_out = PyBytes_AS_STRING(result) + data_size;
186n/a buffer_left = PyBytes_GET_SIZE(result) - data_size;
187n/a }
188n/a c->bzs.avail_out = (unsigned int)Py_MIN(buffer_left, UINT_MAX);
189n/a }
190n/a
191n/a Py_BEGIN_ALLOW_THREADS
192n/a this_out = c->bzs.next_out;
193n/a bzerror = BZ2_bzCompress(&c->bzs, action);
194n/a data_size += c->bzs.next_out - this_out;
195n/a Py_END_ALLOW_THREADS
196n/a if (catch_bz2_error(bzerror))
197n/a goto error;
198n/a
199n/a /* In flushing mode, stop when all buffered data has been flushed. */
200n/a if (action == BZ_FINISH && bzerror == BZ_STREAM_END)
201n/a break;
202n/a }
203n/a if (data_size != (size_t)PyBytes_GET_SIZE(result))
204n/a if (_PyBytes_Resize(&result, data_size) < 0)
205n/a goto error;
206n/a return result;
207n/a
208n/aerror:
209n/a Py_XDECREF(result);
210n/a return NULL;
211n/a}
212n/a
213n/a/*[clinic input]
214n/amodule _bz2
215n/aclass _bz2.BZ2Compressor "BZ2Compressor *" "&BZ2Compressor_Type"
216n/aclass _bz2.BZ2Decompressor "BZ2Decompressor *" "&BZ2Decompressor_Type"
217n/a[clinic start generated code]*/
218n/a/*[clinic end generated code: output=da39a3ee5e6b4b0d input=dc7d7992a79f9cb7]*/
219n/a
220n/a#include "clinic/_bz2module.c.h"
221n/a
222n/a/*[clinic input]
223n/a_bz2.BZ2Compressor.compress
224n/a
225n/a data: Py_buffer
226n/a /
227n/a
228n/aProvide data to the compressor object.
229n/a
230n/aReturns a chunk of compressed data if possible, or b'' otherwise.
231n/a
232n/aWhen you have finished providing data to the compressor, call the
233n/aflush() method to finish the compression process.
234n/a[clinic start generated code]*/
235n/a
236n/astatic PyObject *
237n/a_bz2_BZ2Compressor_compress_impl(BZ2Compressor *self, Py_buffer *data)
238n/a/*[clinic end generated code: output=59365426e941fbcc input=85c963218070fc4c]*/
239n/a{
240n/a PyObject *result = NULL;
241n/a
242n/a ACQUIRE_LOCK(self);
243n/a if (self->flushed)
244n/a PyErr_SetString(PyExc_ValueError, "Compressor has been flushed");
245n/a else
246n/a result = compress(self, data->buf, data->len, BZ_RUN);
247n/a RELEASE_LOCK(self);
248n/a return result;
249n/a}
250n/a
251n/a/*[clinic input]
252n/a_bz2.BZ2Compressor.flush
253n/a
254n/aFinish the compression process.
255n/a
256n/aReturns the compressed data left in internal buffers.
257n/a
258n/aThe compressor object may not be used after this method is called.
259n/a[clinic start generated code]*/
260n/a
261n/astatic PyObject *
262n/a_bz2_BZ2Compressor_flush_impl(BZ2Compressor *self)
263n/a/*[clinic end generated code: output=3ef03fc1b092a701 input=d64405d3c6f76691]*/
264n/a{
265n/a PyObject *result = NULL;
266n/a
267n/a ACQUIRE_LOCK(self);
268n/a if (self->flushed)
269n/a PyErr_SetString(PyExc_ValueError, "Repeated call to flush()");
270n/a else {
271n/a self->flushed = 1;
272n/a result = compress(self, NULL, 0, BZ_FINISH);
273n/a }
274n/a RELEASE_LOCK(self);
275n/a return result;
276n/a}
277n/a
278n/astatic PyObject *
279n/aBZ2Compressor_getstate(BZ2Compressor *self, PyObject *noargs)
280n/a{
281n/a PyErr_Format(PyExc_TypeError, "cannot serialize '%s' object",
282n/a Py_TYPE(self)->tp_name);
283n/a return NULL;
284n/a}
285n/a
286n/astatic void*
287n/aBZ2_Malloc(void* ctx, int items, int size)
288n/a{
289n/a if (items < 0 || size < 0)
290n/a return NULL;
291n/a if ((size_t)items > (size_t)PY_SSIZE_T_MAX / (size_t)size)
292n/a return NULL;
293n/a /* PyMem_Malloc() cannot be used: compress() and decompress()
294n/a release the GIL */
295n/a return PyMem_RawMalloc(items * size);
296n/a}
297n/a
298n/astatic void
299n/aBZ2_Free(void* ctx, void *ptr)
300n/a{
301n/a PyMem_RawFree(ptr);
302n/a}
303n/a
304n/a/*[clinic input]
305n/a_bz2.BZ2Compressor.__init__
306n/a
307n/a compresslevel: int = 9
308n/a Compression level, as a number between 1 and 9.
309n/a /
310n/a
311n/aCreate a compressor object for compressing data incrementally.
312n/a
313n/aFor one-shot compression, use the compress() function instead.
314n/a[clinic start generated code]*/
315n/a
316n/astatic int
317n/a_bz2_BZ2Compressor___init___impl(BZ2Compressor *self, int compresslevel)
318n/a/*[clinic end generated code: output=c4e6adfd02963827 input=4e1ff7b8394b6e9a]*/
319n/a{
320n/a int bzerror;
321n/a
322n/a if (!(1 <= compresslevel && compresslevel <= 9)) {
323n/a PyErr_SetString(PyExc_ValueError,
324n/a "compresslevel must be between 1 and 9");
325n/a return -1;
326n/a }
327n/a
328n/a#ifdef WITH_THREAD
329n/a self->lock = PyThread_allocate_lock();
330n/a if (self->lock == NULL) {
331n/a PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock");
332n/a return -1;
333n/a }
334n/a#endif
335n/a
336n/a self->bzs.opaque = NULL;
337n/a self->bzs.bzalloc = BZ2_Malloc;
338n/a self->bzs.bzfree = BZ2_Free;
339n/a bzerror = BZ2_bzCompressInit(&self->bzs, compresslevel, 0, 0);
340n/a if (catch_bz2_error(bzerror))
341n/a goto error;
342n/a
343n/a return 0;
344n/a
345n/aerror:
346n/a#ifdef WITH_THREAD
347n/a PyThread_free_lock(self->lock);
348n/a self->lock = NULL;
349n/a#endif
350n/a return -1;
351n/a}
352n/a
353n/astatic void
354n/aBZ2Compressor_dealloc(BZ2Compressor *self)
355n/a{
356n/a BZ2_bzCompressEnd(&self->bzs);
357n/a#ifdef WITH_THREAD
358n/a if (self->lock != NULL)
359n/a PyThread_free_lock(self->lock);
360n/a#endif
361n/a Py_TYPE(self)->tp_free((PyObject *)self);
362n/a}
363n/a
364n/astatic PyMethodDef BZ2Compressor_methods[] = {
365n/a _BZ2_BZ2COMPRESSOR_COMPRESS_METHODDEF
366n/a _BZ2_BZ2COMPRESSOR_FLUSH_METHODDEF
367n/a {"__getstate__", (PyCFunction)BZ2Compressor_getstate, METH_NOARGS},
368n/a {NULL}
369n/a};
370n/a
371n/a
372n/astatic PyTypeObject BZ2Compressor_Type = {
373n/a PyVarObject_HEAD_INIT(NULL, 0)
374n/a "_bz2.BZ2Compressor", /* tp_name */
375n/a sizeof(BZ2Compressor), /* tp_basicsize */
376n/a 0, /* tp_itemsize */
377n/a (destructor)BZ2Compressor_dealloc, /* tp_dealloc */
378n/a 0, /* tp_print */
379n/a 0, /* tp_getattr */
380n/a 0, /* tp_setattr */
381n/a 0, /* tp_reserved */
382n/a 0, /* tp_repr */
383n/a 0, /* tp_as_number */
384n/a 0, /* tp_as_sequence */
385n/a 0, /* tp_as_mapping */
386n/a 0, /* tp_hash */
387n/a 0, /* tp_call */
388n/a 0, /* tp_str */
389n/a 0, /* tp_getattro */
390n/a 0, /* tp_setattro */
391n/a 0, /* tp_as_buffer */
392n/a Py_TPFLAGS_DEFAULT, /* tp_flags */
393n/a _bz2_BZ2Compressor___init____doc__, /* tp_doc */
394n/a 0, /* tp_traverse */
395n/a 0, /* tp_clear */
396n/a 0, /* tp_richcompare */
397n/a 0, /* tp_weaklistoffset */
398n/a 0, /* tp_iter */
399n/a 0, /* tp_iternext */
400n/a BZ2Compressor_methods, /* tp_methods */
401n/a 0, /* tp_members */
402n/a 0, /* tp_getset */
403n/a 0, /* tp_base */
404n/a 0, /* tp_dict */
405n/a 0, /* tp_descr_get */
406n/a 0, /* tp_descr_set */
407n/a 0, /* tp_dictoffset */
408n/a _bz2_BZ2Compressor___init__, /* tp_init */
409n/a 0, /* tp_alloc */
410n/a PyType_GenericNew, /* tp_new */
411n/a};
412n/a
413n/a
414n/a/* BZ2Decompressor class. */
415n/a
416n/a/* Decompress data of length d->bzs_avail_in_real in d->bzs.next_in. The output
417n/a buffer is allocated dynamically and returned. At most max_length bytes are
418n/a returned, so some of the input may not be consumed. d->bzs.next_in and
419n/a d->bzs_avail_in_real are updated to reflect the consumed input. */
420n/astatic PyObject*
421n/adecompress_buf(BZ2Decompressor *d, Py_ssize_t max_length)
422n/a{
423n/a /* data_size is strictly positive, but because we repeatedly have to
424n/a compare against max_length and PyBytes_GET_SIZE we declare it as
425n/a signed */
426n/a Py_ssize_t data_size = 0;
427n/a PyObject *result;
428n/a bz_stream *bzs = &d->bzs;
429n/a
430n/a if (max_length < 0 || max_length >= INITIAL_BUFFER_SIZE)
431n/a result = PyBytes_FromStringAndSize(NULL, INITIAL_BUFFER_SIZE);
432n/a else
433n/a result = PyBytes_FromStringAndSize(NULL, max_length);
434n/a if (result == NULL)
435n/a return NULL;
436n/a
437n/a bzs->next_out = PyBytes_AS_STRING(result);
438n/a for (;;) {
439n/a int bzret;
440n/a size_t avail;
441n/a
442n/a /* On a 64-bit system, buffer length might not fit in avail_out, so we
443n/a do decompression in chunks of no more than UINT_MAX bytes
444n/a each. Note that the expression for `avail` is guaranteed to be
445n/a positive, so the cast is safe. */
446n/a avail = (size_t) (PyBytes_GET_SIZE(result) - data_size);
447n/a bzs->avail_out = (unsigned int)Py_MIN(avail, UINT_MAX);
448n/a bzs->avail_in = (unsigned int)Py_MIN(d->bzs_avail_in_real, UINT_MAX);
449n/a d->bzs_avail_in_real -= bzs->avail_in;
450n/a
451n/a Py_BEGIN_ALLOW_THREADS
452n/a bzret = BZ2_bzDecompress(bzs);
453n/a data_size = bzs->next_out - PyBytes_AS_STRING(result);
454n/a d->bzs_avail_in_real += bzs->avail_in;
455n/a Py_END_ALLOW_THREADS
456n/a if (catch_bz2_error(bzret))
457n/a goto error;
458n/a if (bzret == BZ_STREAM_END) {
459n/a d->eof = 1;
460n/a break;
461n/a } else if (d->bzs_avail_in_real == 0) {
462n/a break;
463n/a } else if (bzs->avail_out == 0) {
464n/a if (data_size == max_length)
465n/a break;
466n/a if (data_size == PyBytes_GET_SIZE(result) &&
467n/a grow_buffer(&result, max_length) == -1)
468n/a goto error;
469n/a bzs->next_out = PyBytes_AS_STRING(result) + data_size;
470n/a }
471n/a }
472n/a if (data_size != PyBytes_GET_SIZE(result))
473n/a if (_PyBytes_Resize(&result, data_size) == -1)
474n/a goto error;
475n/a
476n/a return result;
477n/a
478n/aerror:
479n/a Py_XDECREF(result);
480n/a return NULL;
481n/a}
482n/a
483n/a
484n/astatic PyObject *
485n/adecompress(BZ2Decompressor *d, char *data, size_t len, Py_ssize_t max_length)
486n/a{
487n/a char input_buffer_in_use;
488n/a PyObject *result;
489n/a bz_stream *bzs = &d->bzs;
490n/a
491n/a /* Prepend unconsumed input if necessary */
492n/a if (bzs->next_in != NULL) {
493n/a size_t avail_now, avail_total;
494n/a
495n/a /* Number of bytes we can append to input buffer */
496n/a avail_now = (d->input_buffer + d->input_buffer_size)
497n/a - (bzs->next_in + d->bzs_avail_in_real);
498n/a
499n/a /* Number of bytes we can append if we move existing
500n/a contents to beginning of buffer (overwriting
501n/a consumed input) */
502n/a avail_total = d->input_buffer_size - d->bzs_avail_in_real;
503n/a
504n/a if (avail_total < len) {
505n/a size_t offset = bzs->next_in - d->input_buffer;
506n/a char *tmp;
507n/a size_t new_size = d->input_buffer_size + len - avail_now;
508n/a
509n/a /* Assign to temporary variable first, so we don't
510n/a lose address of allocated buffer if realloc fails */
511n/a tmp = PyMem_Realloc(d->input_buffer, new_size);
512n/a if (tmp == NULL) {
513n/a PyErr_SetNone(PyExc_MemoryError);
514n/a return NULL;
515n/a }
516n/a d->input_buffer = tmp;
517n/a d->input_buffer_size = new_size;
518n/a
519n/a bzs->next_in = d->input_buffer + offset;
520n/a }
521n/a else if (avail_now < len) {
522n/a memmove(d->input_buffer, bzs->next_in,
523n/a d->bzs_avail_in_real);
524n/a bzs->next_in = d->input_buffer;
525n/a }
526n/a memcpy((void*)(bzs->next_in + d->bzs_avail_in_real), data, len);
527n/a d->bzs_avail_in_real += len;
528n/a input_buffer_in_use = 1;
529n/a }
530n/a else {
531n/a bzs->next_in = data;
532n/a d->bzs_avail_in_real = len;
533n/a input_buffer_in_use = 0;
534n/a }
535n/a
536n/a result = decompress_buf(d, max_length);
537n/a if(result == NULL) {
538n/a bzs->next_in = NULL;
539n/a return NULL;
540n/a }
541n/a
542n/a if (d->eof) {
543n/a d->needs_input = 0;
544n/a if (d->bzs_avail_in_real > 0) {
545n/a Py_XSETREF(d->unused_data,
546n/a PyBytes_FromStringAndSize(bzs->next_in, d->bzs_avail_in_real));
547n/a if (d->unused_data == NULL)
548n/a goto error;
549n/a }
550n/a }
551n/a else if (d->bzs_avail_in_real == 0) {
552n/a bzs->next_in = NULL;
553n/a d->needs_input = 1;
554n/a }
555n/a else {
556n/a d->needs_input = 0;
557n/a
558n/a /* If we did not use the input buffer, we now have
559n/a to copy the tail from the caller's buffer into the
560n/a input buffer */
561n/a if (!input_buffer_in_use) {
562n/a
563n/a /* Discard buffer if it's too small
564n/a (resizing it may needlessly copy the current contents) */
565n/a if (d->input_buffer != NULL &&
566n/a d->input_buffer_size < d->bzs_avail_in_real) {
567n/a PyMem_Free(d->input_buffer);
568n/a d->input_buffer = NULL;
569n/a }
570n/a
571n/a /* Allocate if necessary */
572n/a if (d->input_buffer == NULL) {
573n/a d->input_buffer = PyMem_Malloc(d->bzs_avail_in_real);
574n/a if (d->input_buffer == NULL) {
575n/a PyErr_SetNone(PyExc_MemoryError);
576n/a goto error;
577n/a }
578n/a d->input_buffer_size = d->bzs_avail_in_real;
579n/a }
580n/a
581n/a /* Copy tail */
582n/a memcpy(d->input_buffer, bzs->next_in, d->bzs_avail_in_real);
583n/a bzs->next_in = d->input_buffer;
584n/a }
585n/a }
586n/a
587n/a return result;
588n/a
589n/aerror:
590n/a Py_XDECREF(result);
591n/a return NULL;
592n/a}
593n/a
594n/a/*[clinic input]
595n/a_bz2.BZ2Decompressor.decompress
596n/a
597n/a data: Py_buffer
598n/a max_length: Py_ssize_t=-1
599n/a
600n/aDecompress *data*, returning uncompressed data as bytes.
601n/a
602n/aIf *max_length* is nonnegative, returns at most *max_length* bytes of
603n/adecompressed data. If this limit is reached and further output can be
604n/aproduced, *self.needs_input* will be set to ``False``. In this case, the next
605n/acall to *decompress()* may provide *data* as b'' to obtain more of the output.
606n/a
607n/aIf all of the input data was decompressed and returned (either because this
608n/awas less than *max_length* bytes, or because *max_length* was negative),
609n/a*self.needs_input* will be set to True.
610n/a
611n/aAttempting to decompress data after the end of stream is reached raises an
612n/aEOFError. Any data found after the end of the stream is ignored and saved in
613n/athe unused_data attribute.
614n/a[clinic start generated code]*/
615n/a
616n/astatic PyObject *
617n/a_bz2_BZ2Decompressor_decompress_impl(BZ2Decompressor *self, Py_buffer *data,
618n/a Py_ssize_t max_length)
619n/a/*[clinic end generated code: output=23e41045deb240a3 input=52e1ffc66a8ea624]*/
620n/a{
621n/a PyObject *result = NULL;
622n/a
623n/a ACQUIRE_LOCK(self);
624n/a if (self->eof)
625n/a PyErr_SetString(PyExc_EOFError, "End of stream already reached");
626n/a else
627n/a result = decompress(self, data->buf, data->len, max_length);
628n/a RELEASE_LOCK(self);
629n/a return result;
630n/a}
631n/a
632n/astatic PyObject *
633n/aBZ2Decompressor_getstate(BZ2Decompressor *self, PyObject *noargs)
634n/a{
635n/a PyErr_Format(PyExc_TypeError, "cannot serialize '%s' object",
636n/a Py_TYPE(self)->tp_name);
637n/a return NULL;
638n/a}
639n/a
640n/a/*[clinic input]
641n/a_bz2.BZ2Decompressor.__init__
642n/a
643n/aCreate a decompressor object for decompressing data incrementally.
644n/a
645n/aFor one-shot decompression, use the decompress() function instead.
646n/a[clinic start generated code]*/
647n/a
648n/astatic int
649n/a_bz2_BZ2Decompressor___init___impl(BZ2Decompressor *self)
650n/a/*[clinic end generated code: output=e4d2b9bb866ab8f1 input=95f6500dcda60088]*/
651n/a{
652n/a int bzerror;
653n/a
654n/a#ifdef WITH_THREAD
655n/a self->lock = PyThread_allocate_lock();
656n/a if (self->lock == NULL) {
657n/a PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock");
658n/a return -1;
659n/a }
660n/a#endif
661n/a
662n/a self->needs_input = 1;
663n/a self->bzs_avail_in_real = 0;
664n/a self->input_buffer = NULL;
665n/a self->input_buffer_size = 0;
666n/a self->unused_data = PyBytes_FromStringAndSize(NULL, 0);
667n/a if (self->unused_data == NULL)
668n/a goto error;
669n/a
670n/a bzerror = BZ2_bzDecompressInit(&self->bzs, 0, 0);
671n/a if (catch_bz2_error(bzerror))
672n/a goto error;
673n/a
674n/a return 0;
675n/a
676n/aerror:
677n/a Py_CLEAR(self->unused_data);
678n/a#ifdef WITH_THREAD
679n/a PyThread_free_lock(self->lock);
680n/a self->lock = NULL;
681n/a#endif
682n/a return -1;
683n/a}
684n/a
685n/astatic void
686n/aBZ2Decompressor_dealloc(BZ2Decompressor *self)
687n/a{
688n/a if(self->input_buffer != NULL)
689n/a PyMem_Free(self->input_buffer);
690n/a BZ2_bzDecompressEnd(&self->bzs);
691n/a Py_CLEAR(self->unused_data);
692n/a#ifdef WITH_THREAD
693n/a if (self->lock != NULL)
694n/a PyThread_free_lock(self->lock);
695n/a#endif
696n/a Py_TYPE(self)->tp_free((PyObject *)self);
697n/a}
698n/a
699n/astatic PyMethodDef BZ2Decompressor_methods[] = {
700n/a _BZ2_BZ2DECOMPRESSOR_DECOMPRESS_METHODDEF
701n/a {"__getstate__", (PyCFunction)BZ2Decompressor_getstate, METH_NOARGS},
702n/a {NULL}
703n/a};
704n/a
705n/aPyDoc_STRVAR(BZ2Decompressor_eof__doc__,
706n/a"True if the end-of-stream marker has been reached.");
707n/a
708n/aPyDoc_STRVAR(BZ2Decompressor_unused_data__doc__,
709n/a"Data found after the end of the compressed stream.");
710n/a
711n/aPyDoc_STRVAR(BZ2Decompressor_needs_input_doc,
712n/a"True if more input is needed before more decompressed data can be produced.");
713n/a
714n/astatic PyMemberDef BZ2Decompressor_members[] = {
715n/a {"eof", T_BOOL, offsetof(BZ2Decompressor, eof),
716n/a READONLY, BZ2Decompressor_eof__doc__},
717n/a {"unused_data", T_OBJECT_EX, offsetof(BZ2Decompressor, unused_data),
718n/a READONLY, BZ2Decompressor_unused_data__doc__},
719n/a {"needs_input", T_BOOL, offsetof(BZ2Decompressor, needs_input), READONLY,
720n/a BZ2Decompressor_needs_input_doc},
721n/a {NULL}
722n/a};
723n/a
724n/astatic PyTypeObject BZ2Decompressor_Type = {
725n/a PyVarObject_HEAD_INIT(NULL, 0)
726n/a "_bz2.BZ2Decompressor", /* tp_name */
727n/a sizeof(BZ2Decompressor), /* tp_basicsize */
728n/a 0, /* tp_itemsize */
729n/a (destructor)BZ2Decompressor_dealloc,/* tp_dealloc */
730n/a 0, /* tp_print */
731n/a 0, /* tp_getattr */
732n/a 0, /* tp_setattr */
733n/a 0, /* tp_reserved */
734n/a 0, /* tp_repr */
735n/a 0, /* tp_as_number */
736n/a 0, /* tp_as_sequence */
737n/a 0, /* tp_as_mapping */
738n/a 0, /* tp_hash */
739n/a 0, /* tp_call */
740n/a 0, /* tp_str */
741n/a 0, /* tp_getattro */
742n/a 0, /* tp_setattro */
743n/a 0, /* tp_as_buffer */
744n/a Py_TPFLAGS_DEFAULT, /* tp_flags */
745n/a _bz2_BZ2Decompressor___init____doc__, /* tp_doc */
746n/a 0, /* tp_traverse */
747n/a 0, /* tp_clear */
748n/a 0, /* tp_richcompare */
749n/a 0, /* tp_weaklistoffset */
750n/a 0, /* tp_iter */
751n/a 0, /* tp_iternext */
752n/a BZ2Decompressor_methods, /* tp_methods */
753n/a BZ2Decompressor_members, /* tp_members */
754n/a 0, /* tp_getset */
755n/a 0, /* tp_base */
756n/a 0, /* tp_dict */
757n/a 0, /* tp_descr_get */
758n/a 0, /* tp_descr_set */
759n/a 0, /* tp_dictoffset */
760n/a _bz2_BZ2Decompressor___init__, /* tp_init */
761n/a 0, /* tp_alloc */
762n/a PyType_GenericNew, /* tp_new */
763n/a};
764n/a
765n/a
766n/a/* Module initialization. */
767n/a
768n/astatic struct PyModuleDef _bz2module = {
769n/a PyModuleDef_HEAD_INIT,
770n/a "_bz2",
771n/a NULL,
772n/a -1,
773n/a NULL,
774n/a NULL,
775n/a NULL,
776n/a NULL,
777n/a NULL
778n/a};
779n/a
780n/aPyMODINIT_FUNC
781n/aPyInit__bz2(void)
782n/a{
783n/a PyObject *m;
784n/a
785n/a if (PyType_Ready(&BZ2Compressor_Type) < 0)
786n/a return NULL;
787n/a if (PyType_Ready(&BZ2Decompressor_Type) < 0)
788n/a return NULL;
789n/a
790n/a m = PyModule_Create(&_bz2module);
791n/a if (m == NULL)
792n/a return NULL;
793n/a
794n/a Py_INCREF(&BZ2Compressor_Type);
795n/a PyModule_AddObject(m, "BZ2Compressor", (PyObject *)&BZ2Compressor_Type);
796n/a
797n/a Py_INCREF(&BZ2Decompressor_Type);
798n/a PyModule_AddObject(m, "BZ2Decompressor",
799n/a (PyObject *)&BZ2Decompressor_Type);
800n/a
801n/a return m;
802n/a}