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