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