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