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