bz2module.c revision 8335acbf24abed1b21841e978c644a80ff83cbbd
1/* 2 3python-bz2 - python bz2 library interface 4 5Copyright (c) 2002 Gustavo Niemeyer <niemeyer@conectiva.com> 6Copyright (c) 2002 Python Software Foundation; All Rights Reserved 7 8*/ 9 10#include "Python.h" 11#include <stdio.h> 12#include <bzlib.h> 13#include "structmember.h" 14 15#ifdef WITH_THREAD 16#include "pythread.h" 17#endif 18 19static char __author__[] = 20"The bz2 python module was written by:\n\ 21\n\ 22 Gustavo Niemeyer <niemeyer@conectiva.com>\n\ 23"; 24 25/* Our very own off_t-like type, 64-bit if possible */ 26/* copied from Objects/fileobject.c */ 27#if !defined(HAVE_LARGEFILE_SUPPORT) 28typedef off_t Py_off_t; 29#elif SIZEOF_OFF_T >= 8 30typedef off_t Py_off_t; 31#elif SIZEOF_FPOS_T >= 8 32typedef fpos_t Py_off_t; 33#else 34#error "Large file support, but neither off_t nor fpos_t is large enough." 35#endif 36 37#define BUF(v) PyString_AS_STRING((PyStringObject *)v) 38 39#define MODE_CLOSED 0 40#define MODE_READ 1 41#define MODE_READ_EOF 2 42#define MODE_WRITE 3 43 44#define BZ2FileObject_Check(v) (Py_Type(v) == &BZ2File_Type) 45 46 47#ifdef BZ_CONFIG_ERROR 48 49#if SIZEOF_LONG >= 8 50#define BZS_TOTAL_OUT(bzs) \ 51 (((long)bzs->total_out_hi32 << 32) + bzs->total_out_lo32) 52#elif SIZEOF_LONG_LONG >= 8 53#define BZS_TOTAL_OUT(bzs) \ 54 (((PY_LONG_LONG)bzs->total_out_hi32 << 32) + bzs->total_out_lo32) 55#else 56#define BZS_TOTAL_OUT(bzs) \ 57 bzs->total_out_lo32 58#endif 59 60#else /* ! BZ_CONFIG_ERROR */ 61 62#define BZ2_bzRead bzRead 63#define BZ2_bzReadOpen bzReadOpen 64#define BZ2_bzReadClose bzReadClose 65#define BZ2_bzWrite bzWrite 66#define BZ2_bzWriteOpen bzWriteOpen 67#define BZ2_bzWriteClose bzWriteClose 68#define BZ2_bzCompress bzCompress 69#define BZ2_bzCompressInit bzCompressInit 70#define BZ2_bzCompressEnd bzCompressEnd 71#define BZ2_bzDecompress bzDecompress 72#define BZ2_bzDecompressInit bzDecompressInit 73#define BZ2_bzDecompressEnd bzDecompressEnd 74 75#define BZS_TOTAL_OUT(bzs) bzs->total_out 76 77#endif /* ! BZ_CONFIG_ERROR */ 78 79 80#ifdef WITH_THREAD 81#define ACQUIRE_LOCK(obj) PyThread_acquire_lock(obj->lock, 1) 82#define RELEASE_LOCK(obj) PyThread_release_lock(obj->lock) 83#else 84#define ACQUIRE_LOCK(obj) 85#define RELEASE_LOCK(obj) 86#endif 87 88/* Bits in f_newlinetypes */ 89#define NEWLINE_UNKNOWN 0 /* No newline seen, yet */ 90#define NEWLINE_CR 1 /* \r newline seen */ 91#define NEWLINE_LF 2 /* \n newline seen */ 92#define NEWLINE_CRLF 4 /* \r\n newline seen */ 93 94/* ===================================================================== */ 95/* Structure definitions. */ 96 97typedef struct { 98 PyObject_HEAD 99 PyObject *file; 100 101 char* f_buf; /* Allocated readahead buffer */ 102 char* f_bufend; /* Points after last occupied position */ 103 char* f_bufptr; /* Current buffer position */ 104 105 int f_softspace; /* Flag used by 'print' command */ 106 107 int f_univ_newline; /* Handle any newline convention */ 108 int f_newlinetypes; /* Types of newlines seen */ 109 int f_skipnextlf; /* Skip next \n */ 110 111 BZFILE *fp; 112 int mode; 113 Py_off_t pos; 114 Py_off_t size; 115#ifdef WITH_THREAD 116 PyThread_type_lock lock; 117#endif 118} BZ2FileObject; 119 120typedef struct { 121 PyObject_HEAD 122 bz_stream bzs; 123 int running; 124#ifdef WITH_THREAD 125 PyThread_type_lock lock; 126#endif 127} BZ2CompObject; 128 129typedef struct { 130 PyObject_HEAD 131 bz_stream bzs; 132 int running; 133 PyObject *unused_data; 134#ifdef WITH_THREAD 135 PyThread_type_lock lock; 136#endif 137} BZ2DecompObject; 138 139/* ===================================================================== */ 140/* Utility functions. */ 141 142static int 143Util_CatchBZ2Error(int bzerror) 144{ 145 int ret = 0; 146 switch(bzerror) { 147 case BZ_OK: 148 case BZ_STREAM_END: 149 break; 150 151#ifdef BZ_CONFIG_ERROR 152 case BZ_CONFIG_ERROR: 153 PyErr_SetString(PyExc_SystemError, 154 "the bz2 library was not compiled " 155 "correctly"); 156 ret = 1; 157 break; 158#endif 159 160 case BZ_PARAM_ERROR: 161 PyErr_SetString(PyExc_ValueError, 162 "the bz2 library has received wrong " 163 "parameters"); 164 ret = 1; 165 break; 166 167 case BZ_MEM_ERROR: 168 PyErr_NoMemory(); 169 ret = 1; 170 break; 171 172 case BZ_DATA_ERROR: 173 case BZ_DATA_ERROR_MAGIC: 174 PyErr_SetString(PyExc_IOError, "invalid data stream"); 175 ret = 1; 176 break; 177 178 case BZ_IO_ERROR: 179 PyErr_SetString(PyExc_IOError, "unknown IO error"); 180 ret = 1; 181 break; 182 183 case BZ_UNEXPECTED_EOF: 184 PyErr_SetString(PyExc_EOFError, 185 "compressed file ended before the " 186 "logical end-of-stream was detected"); 187 ret = 1; 188 break; 189 190 case BZ_SEQUENCE_ERROR: 191 PyErr_SetString(PyExc_RuntimeError, 192 "wrong sequence of bz2 library " 193 "commands used"); 194 ret = 1; 195 break; 196 } 197 return ret; 198} 199 200#if BUFSIZ < 8192 201#define SMALLCHUNK 8192 202#else 203#define SMALLCHUNK BUFSIZ 204#endif 205 206#if SIZEOF_INT < 4 207#define BIGCHUNK (512 * 32) 208#else 209#define BIGCHUNK (512 * 1024) 210#endif 211 212/* This is a hacked version of Python's fileobject.c:new_buffersize(). */ 213static size_t 214Util_NewBufferSize(size_t currentsize) 215{ 216 if (currentsize > SMALLCHUNK) { 217 /* Keep doubling until we reach BIGCHUNK; 218 then keep adding BIGCHUNK. */ 219 if (currentsize <= BIGCHUNK) 220 return currentsize + currentsize; 221 else 222 return currentsize + BIGCHUNK; 223 } 224 return currentsize + SMALLCHUNK; 225} 226 227/* This is a hacked version of Python's fileobject.c:get_line(). */ 228static PyObject * 229Util_GetLine(BZ2FileObject *f, int n) 230{ 231 char c; 232 char *buf, *end; 233 size_t total_v_size; /* total # of slots in buffer */ 234 size_t used_v_size; /* # used slots in buffer */ 235 size_t increment; /* amount to increment the buffer */ 236 PyObject *v; 237 int bzerror; 238 int bytes_read; 239 int newlinetypes = f->f_newlinetypes; 240 int skipnextlf = f->f_skipnextlf; 241 int univ_newline = f->f_univ_newline; 242 243 total_v_size = n > 0 ? n : 100; 244 v = PyString_FromStringAndSize((char *)NULL, total_v_size); 245 if (v == NULL) 246 return NULL; 247 248 buf = BUF(v); 249 end = buf + total_v_size; 250 251 for (;;) { 252 Py_BEGIN_ALLOW_THREADS 253 while (buf != end) { 254 bytes_read = BZ2_bzRead(&bzerror, f->fp, &c, 1); 255 f->pos++; 256 if (bytes_read == 0) break; 257 if (univ_newline) { 258 if (skipnextlf) { 259 skipnextlf = 0; 260 if (c == '\n') { 261 /* Seeing a \n here with skipnextlf true means we 262 * saw a \r before. 263 */ 264 newlinetypes |= NEWLINE_CRLF; 265 if (bzerror != BZ_OK) break; 266 bytes_read = BZ2_bzRead(&bzerror, f->fp, &c, 1); 267 f->pos++; 268 if (bytes_read == 0) break; 269 } else { 270 newlinetypes |= NEWLINE_CR; 271 } 272 } 273 if (c == '\r') { 274 skipnextlf = 1; 275 c = '\n'; 276 } else if (c == '\n') 277 newlinetypes |= NEWLINE_LF; 278 } 279 *buf++ = c; 280 if (bzerror != BZ_OK || c == '\n') break; 281 } 282 if (univ_newline && bzerror == BZ_STREAM_END && skipnextlf) 283 newlinetypes |= NEWLINE_CR; 284 Py_END_ALLOW_THREADS 285 f->f_newlinetypes = newlinetypes; 286 f->f_skipnextlf = skipnextlf; 287 if (bzerror == BZ_STREAM_END) { 288 f->size = f->pos; 289 f->mode = MODE_READ_EOF; 290 break; 291 } else if (bzerror != BZ_OK) { 292 Util_CatchBZ2Error(bzerror); 293 Py_DECREF(v); 294 return NULL; 295 } 296 if (c == '\n') 297 break; 298 /* Must be because buf == end */ 299 if (n > 0) 300 break; 301 used_v_size = total_v_size; 302 increment = total_v_size >> 2; /* mild exponential growth */ 303 total_v_size += increment; 304 if (total_v_size > INT_MAX) { 305 PyErr_SetString(PyExc_OverflowError, 306 "line is longer than a Python string can hold"); 307 Py_DECREF(v); 308 return NULL; 309 } 310 if (_PyString_Resize(&v, total_v_size) < 0) 311 return NULL; 312 buf = BUF(v) + used_v_size; 313 end = BUF(v) + total_v_size; 314 } 315 316 used_v_size = buf - BUF(v); 317 if (used_v_size != total_v_size) 318 _PyString_Resize(&v, used_v_size); 319 return v; 320} 321 322/* This is a hacked version of Python's 323 * fileobject.c:Py_UniversalNewlineFread(). */ 324size_t 325Util_UnivNewlineRead(int *bzerror, BZFILE *stream, 326 char* buf, size_t n, BZ2FileObject *f) 327{ 328 char *dst = buf; 329 int newlinetypes, skipnextlf; 330 331 assert(buf != NULL); 332 assert(stream != NULL); 333 334 if (!f->f_univ_newline) 335 return BZ2_bzRead(bzerror, stream, buf, n); 336 337 newlinetypes = f->f_newlinetypes; 338 skipnextlf = f->f_skipnextlf; 339 340 /* Invariant: n is the number of bytes remaining to be filled 341 * in the buffer. 342 */ 343 while (n) { 344 size_t nread; 345 int shortread; 346 char *src = dst; 347 348 nread = BZ2_bzRead(bzerror, stream, dst, n); 349 assert(nread <= n); 350 n -= nread; /* assuming 1 byte out for each in; will adjust */ 351 shortread = n != 0; /* true iff EOF or error */ 352 while (nread--) { 353 char c = *src++; 354 if (c == '\r') { 355 /* Save as LF and set flag to skip next LF. */ 356 *dst++ = '\n'; 357 skipnextlf = 1; 358 } 359 else if (skipnextlf && c == '\n') { 360 /* Skip LF, and remember we saw CR LF. */ 361 skipnextlf = 0; 362 newlinetypes |= NEWLINE_CRLF; 363 ++n; 364 } 365 else { 366 /* Normal char to be stored in buffer. Also 367 * update the newlinetypes flag if either this 368 * is an LF or the previous char was a CR. 369 */ 370 if (c == '\n') 371 newlinetypes |= NEWLINE_LF; 372 else if (skipnextlf) 373 newlinetypes |= NEWLINE_CR; 374 *dst++ = c; 375 skipnextlf = 0; 376 } 377 } 378 if (shortread) { 379 /* If this is EOF, update type flags. */ 380 if (skipnextlf && *bzerror == BZ_STREAM_END) 381 newlinetypes |= NEWLINE_CR; 382 break; 383 } 384 } 385 f->f_newlinetypes = newlinetypes; 386 f->f_skipnextlf = skipnextlf; 387 return dst - buf; 388} 389 390/* This is a hacked version of Python's fileobject.c:drop_readahead(). */ 391static void 392Util_DropReadAhead(BZ2FileObject *f) 393{ 394 if (f->f_buf != NULL) { 395 PyMem_Free(f->f_buf); 396 f->f_buf = NULL; 397 } 398} 399 400/* This is a hacked version of Python's fileobject.c:readahead(). */ 401static int 402Util_ReadAhead(BZ2FileObject *f, int bufsize) 403{ 404 int chunksize; 405 int bzerror; 406 407 if (f->f_buf != NULL) { 408 if((f->f_bufend - f->f_bufptr) >= 1) 409 return 0; 410 else 411 Util_DropReadAhead(f); 412 } 413 if (f->mode == MODE_READ_EOF) { 414 f->f_bufptr = f->f_buf; 415 f->f_bufend = f->f_buf; 416 return 0; 417 } 418 if ((f->f_buf = PyMem_Malloc(bufsize)) == NULL) { 419 return -1; 420 } 421 Py_BEGIN_ALLOW_THREADS 422 chunksize = Util_UnivNewlineRead(&bzerror, f->fp, f->f_buf, 423 bufsize, f); 424 Py_END_ALLOW_THREADS 425 f->pos += chunksize; 426 if (bzerror == BZ_STREAM_END) { 427 f->size = f->pos; 428 f->mode = MODE_READ_EOF; 429 } else if (bzerror != BZ_OK) { 430 Util_CatchBZ2Error(bzerror); 431 Util_DropReadAhead(f); 432 return -1; 433 } 434 f->f_bufptr = f->f_buf; 435 f->f_bufend = f->f_buf + chunksize; 436 return 0; 437} 438 439/* This is a hacked version of Python's 440 * fileobject.c:readahead_get_line_skip(). */ 441static PyStringObject * 442Util_ReadAheadGetLineSkip(BZ2FileObject *f, int skip, int bufsize) 443{ 444 PyStringObject* s; 445 char *bufptr; 446 char *buf; 447 int len; 448 449 if (f->f_buf == NULL) 450 if (Util_ReadAhead(f, bufsize) < 0) 451 return NULL; 452 453 len = f->f_bufend - f->f_bufptr; 454 if (len == 0) 455 return (PyStringObject *) 456 PyString_FromStringAndSize(NULL, skip); 457 bufptr = memchr(f->f_bufptr, '\n', len); 458 if (bufptr != NULL) { 459 bufptr++; /* Count the '\n' */ 460 len = bufptr - f->f_bufptr; 461 s = (PyStringObject *) 462 PyString_FromStringAndSize(NULL, skip+len); 463 if (s == NULL) 464 return NULL; 465 memcpy(PyString_AS_STRING(s)+skip, f->f_bufptr, len); 466 f->f_bufptr = bufptr; 467 if (bufptr == f->f_bufend) 468 Util_DropReadAhead(f); 469 } else { 470 bufptr = f->f_bufptr; 471 buf = f->f_buf; 472 f->f_buf = NULL; /* Force new readahead buffer */ 473 s = Util_ReadAheadGetLineSkip(f, skip+len, 474 bufsize + (bufsize>>2)); 475 if (s == NULL) { 476 PyMem_Free(buf); 477 return NULL; 478 } 479 memcpy(PyString_AS_STRING(s)+skip, bufptr, len); 480 PyMem_Free(buf); 481 } 482 return s; 483} 484 485/* ===================================================================== */ 486/* Methods of BZ2File. */ 487 488PyDoc_STRVAR(BZ2File_read__doc__, 489"read([size]) -> string\n\ 490\n\ 491Read at most size uncompressed bytes, returned as a string. If the size\n\ 492argument is negative or omitted, read until EOF is reached.\n\ 493"); 494 495/* This is a hacked version of Python's fileobject.c:file_read(). */ 496static PyObject * 497BZ2File_read(BZ2FileObject *self, PyObject *args) 498{ 499 long bytesrequested = -1; 500 size_t bytesread, buffersize, chunksize; 501 int bzerror; 502 PyObject *ret = NULL; 503 504 if (!PyArg_ParseTuple(args, "|l:read", &bytesrequested)) 505 return NULL; 506 507 ACQUIRE_LOCK(self); 508 switch (self->mode) { 509 case MODE_READ: 510 break; 511 case MODE_READ_EOF: 512 ret = PyString_FromString(""); 513 goto cleanup; 514 case MODE_CLOSED: 515 PyErr_SetString(PyExc_ValueError, 516 "I/O operation on closed file"); 517 goto cleanup; 518 default: 519 PyErr_SetString(PyExc_IOError, 520 "file is not ready for reading"); 521 goto cleanup; 522 } 523 524 if (bytesrequested < 0) 525 buffersize = Util_NewBufferSize((size_t)0); 526 else 527 buffersize = bytesrequested; 528 if (buffersize > INT_MAX) { 529 PyErr_SetString(PyExc_OverflowError, 530 "requested number of bytes is " 531 "more than a Python string can hold"); 532 goto cleanup; 533 } 534 ret = PyString_FromStringAndSize((char *)NULL, buffersize); 535 if (ret == NULL) 536 goto cleanup; 537 bytesread = 0; 538 539 for (;;) { 540 Py_BEGIN_ALLOW_THREADS 541 chunksize = Util_UnivNewlineRead(&bzerror, self->fp, 542 BUF(ret)+bytesread, 543 buffersize-bytesread, 544 self); 545 self->pos += chunksize; 546 Py_END_ALLOW_THREADS 547 bytesread += chunksize; 548 if (bzerror == BZ_STREAM_END) { 549 self->size = self->pos; 550 self->mode = MODE_READ_EOF; 551 break; 552 } else if (bzerror != BZ_OK) { 553 Util_CatchBZ2Error(bzerror); 554 Py_DECREF(ret); 555 ret = NULL; 556 goto cleanup; 557 } 558 if (bytesrequested < 0) { 559 buffersize = Util_NewBufferSize(buffersize); 560 if (_PyString_Resize(&ret, buffersize) < 0) 561 goto cleanup; 562 } else { 563 break; 564 } 565 } 566 if (bytesread != buffersize) 567 _PyString_Resize(&ret, bytesread); 568 569cleanup: 570 RELEASE_LOCK(self); 571 return ret; 572} 573 574PyDoc_STRVAR(BZ2File_readline__doc__, 575"readline([size]) -> string\n\ 576\n\ 577Return the next line from the file, as a string, retaining newline.\n\ 578A non-negative size argument will limit the maximum number of bytes to\n\ 579return (an incomplete line may be returned then). Return an empty\n\ 580string at EOF.\n\ 581"); 582 583static PyObject * 584BZ2File_readline(BZ2FileObject *self, PyObject *args) 585{ 586 PyObject *ret = NULL; 587 int sizehint = -1; 588 589 if (!PyArg_ParseTuple(args, "|i:readline", &sizehint)) 590 return NULL; 591 592 ACQUIRE_LOCK(self); 593 switch (self->mode) { 594 case MODE_READ: 595 break; 596 case MODE_READ_EOF: 597 ret = PyString_FromString(""); 598 goto cleanup; 599 case MODE_CLOSED: 600 PyErr_SetString(PyExc_ValueError, 601 "I/O operation on closed file"); 602 goto cleanup; 603 default: 604 PyErr_SetString(PyExc_IOError, 605 "file is not ready for reading"); 606 goto cleanup; 607 } 608 609 if (sizehint == 0) 610 ret = PyString_FromString(""); 611 else 612 ret = Util_GetLine(self, (sizehint < 0) ? 0 : sizehint); 613 614cleanup: 615 RELEASE_LOCK(self); 616 return ret; 617} 618 619PyDoc_STRVAR(BZ2File_readlines__doc__, 620"readlines([size]) -> list\n\ 621\n\ 622Call readline() repeatedly and return a list of lines read.\n\ 623The optional size argument, if given, is an approximate bound on the\n\ 624total number of bytes in the lines returned.\n\ 625"); 626 627/* This is a hacked version of Python's fileobject.c:file_readlines(). */ 628static PyObject * 629BZ2File_readlines(BZ2FileObject *self, PyObject *args) 630{ 631 long sizehint = 0; 632 PyObject *list = NULL; 633 PyObject *line; 634 char small_buffer[SMALLCHUNK]; 635 char *buffer = small_buffer; 636 size_t buffersize = SMALLCHUNK; 637 PyObject *big_buffer = NULL; 638 size_t nfilled = 0; 639 size_t nread; 640 size_t totalread = 0; 641 char *p, *q, *end; 642 int err; 643 int shortread = 0; 644 int bzerror; 645 646 if (!PyArg_ParseTuple(args, "|l:readlines", &sizehint)) 647 return NULL; 648 649 ACQUIRE_LOCK(self); 650 switch (self->mode) { 651 case MODE_READ: 652 break; 653 case MODE_READ_EOF: 654 list = PyList_New(0); 655 goto cleanup; 656 case MODE_CLOSED: 657 PyErr_SetString(PyExc_ValueError, 658 "I/O operation on closed file"); 659 goto cleanup; 660 default: 661 PyErr_SetString(PyExc_IOError, 662 "file is not ready for reading"); 663 goto cleanup; 664 } 665 666 if ((list = PyList_New(0)) == NULL) 667 goto cleanup; 668 669 for (;;) { 670 Py_BEGIN_ALLOW_THREADS 671 nread = Util_UnivNewlineRead(&bzerror, self->fp, 672 buffer+nfilled, 673 buffersize-nfilled, self); 674 self->pos += nread; 675 Py_END_ALLOW_THREADS 676 if (bzerror == BZ_STREAM_END) { 677 self->size = self->pos; 678 self->mode = MODE_READ_EOF; 679 if (nread == 0) { 680 sizehint = 0; 681 break; 682 } 683 shortread = 1; 684 } else if (bzerror != BZ_OK) { 685 Util_CatchBZ2Error(bzerror); 686 error: 687 Py_DECREF(list); 688 list = NULL; 689 goto cleanup; 690 } 691 totalread += nread; 692 p = memchr(buffer+nfilled, '\n', nread); 693 if (!shortread && p == NULL) { 694 /* Need a larger buffer to fit this line */ 695 nfilled += nread; 696 buffersize *= 2; 697 if (buffersize > INT_MAX) { 698 PyErr_SetString(PyExc_OverflowError, 699 "line is longer than a Python string can hold"); 700 goto error; 701 } 702 if (big_buffer == NULL) { 703 /* Create the big buffer */ 704 big_buffer = PyString_FromStringAndSize( 705 NULL, buffersize); 706 if (big_buffer == NULL) 707 goto error; 708 buffer = PyString_AS_STRING(big_buffer); 709 memcpy(buffer, small_buffer, nfilled); 710 } 711 else { 712 /* Grow the big buffer */ 713 _PyString_Resize(&big_buffer, buffersize); 714 buffer = PyString_AS_STRING(big_buffer); 715 } 716 continue; 717 } 718 end = buffer+nfilled+nread; 719 q = buffer; 720 while (p != NULL) { 721 /* Process complete lines */ 722 p++; 723 line = PyString_FromStringAndSize(q, p-q); 724 if (line == NULL) 725 goto error; 726 err = PyList_Append(list, line); 727 Py_DECREF(line); 728 if (err != 0) 729 goto error; 730 q = p; 731 p = memchr(q, '\n', end-q); 732 } 733 /* Move the remaining incomplete line to the start */ 734 nfilled = end-q; 735 memmove(buffer, q, nfilled); 736 if (sizehint > 0) 737 if (totalread >= (size_t)sizehint) 738 break; 739 if (shortread) { 740 sizehint = 0; 741 break; 742 } 743 } 744 if (nfilled != 0) { 745 /* Partial last line */ 746 line = PyString_FromStringAndSize(buffer, nfilled); 747 if (line == NULL) 748 goto error; 749 if (sizehint > 0) { 750 /* Need to complete the last line */ 751 PyObject *rest = Util_GetLine(self, 0); 752 if (rest == NULL) { 753 Py_DECREF(line); 754 goto error; 755 } 756 PyString_Concat(&line, rest); 757 Py_DECREF(rest); 758 if (line == NULL) 759 goto error; 760 } 761 err = PyList_Append(list, line); 762 Py_DECREF(line); 763 if (err != 0) 764 goto error; 765 } 766 767 cleanup: 768 RELEASE_LOCK(self); 769 if (big_buffer) { 770 Py_DECREF(big_buffer); 771 } 772 return list; 773} 774 775PyDoc_STRVAR(BZ2File_xreadlines__doc__, 776"xreadlines() -> self\n\ 777\n\ 778For backward compatibility. BZ2File objects now include the performance\n\ 779optimizations previously implemented in the xreadlines module.\n\ 780"); 781 782PyDoc_STRVAR(BZ2File_write__doc__, 783"write(data) -> None\n\ 784\n\ 785Write the 'data' string to file. Note that due to buffering, close() may\n\ 786be needed before the file on disk reflects the data written.\n\ 787"); 788 789/* This is a hacked version of Python's fileobject.c:file_write(). */ 790static PyObject * 791BZ2File_write(BZ2FileObject *self, PyObject *args) 792{ 793 PyObject *ret = NULL; 794 char *buf; 795 int len; 796 int bzerror; 797 798 if (!PyArg_ParseTuple(args, "s#:write", &buf, &len)) 799 return NULL; 800 801 ACQUIRE_LOCK(self); 802 switch (self->mode) { 803 case MODE_WRITE: 804 break; 805 806 case MODE_CLOSED: 807 PyErr_SetString(PyExc_ValueError, 808 "I/O operation on closed file"); 809 goto cleanup; 810 811 default: 812 PyErr_SetString(PyExc_IOError, 813 "file is not ready for writing"); 814 goto cleanup; 815 } 816 817 self->f_softspace = 0; 818 819 Py_BEGIN_ALLOW_THREADS 820 BZ2_bzWrite (&bzerror, self->fp, buf, len); 821 self->pos += len; 822 Py_END_ALLOW_THREADS 823 824 if (bzerror != BZ_OK) { 825 Util_CatchBZ2Error(bzerror); 826 goto cleanup; 827 } 828 829 Py_INCREF(Py_None); 830 ret = Py_None; 831 832cleanup: 833 RELEASE_LOCK(self); 834 return ret; 835} 836 837PyDoc_STRVAR(BZ2File_writelines__doc__, 838"writelines(sequence_of_strings) -> None\n\ 839\n\ 840Write the sequence of strings to the file. Note that newlines are not\n\ 841added. The sequence can be any iterable object producing strings. This is\n\ 842equivalent to calling write() for each string.\n\ 843"); 844 845/* This is a hacked version of Python's fileobject.c:file_writelines(). */ 846static PyObject * 847BZ2File_writelines(BZ2FileObject *self, PyObject *seq) 848{ 849#define CHUNKSIZE 1000 850 PyObject *list = NULL; 851 PyObject *iter = NULL; 852 PyObject *ret = NULL; 853 PyObject *line; 854 int i, j, index, len, islist; 855 int bzerror; 856 857 ACQUIRE_LOCK(self); 858 switch (self->mode) { 859 case MODE_WRITE: 860 break; 861 862 case MODE_CLOSED: 863 PyErr_SetString(PyExc_ValueError, 864 "I/O operation on closed file"); 865 goto error; 866 867 default: 868 PyErr_SetString(PyExc_IOError, 869 "file is not ready for writing"); 870 goto error; 871 } 872 873 islist = PyList_Check(seq); 874 if (!islist) { 875 iter = PyObject_GetIter(seq); 876 if (iter == NULL) { 877 PyErr_SetString(PyExc_TypeError, 878 "writelines() requires an iterable argument"); 879 goto error; 880 } 881 list = PyList_New(CHUNKSIZE); 882 if (list == NULL) 883 goto error; 884 } 885 886 /* Strategy: slurp CHUNKSIZE lines into a private list, 887 checking that they are all strings, then write that list 888 without holding the interpreter lock, then come back for more. */ 889 for (index = 0; ; index += CHUNKSIZE) { 890 if (islist) { 891 Py_XDECREF(list); 892 list = PyList_GetSlice(seq, index, index+CHUNKSIZE); 893 if (list == NULL) 894 goto error; 895 j = PyList_GET_SIZE(list); 896 } 897 else { 898 for (j = 0; j < CHUNKSIZE; j++) { 899 line = PyIter_Next(iter); 900 if (line == NULL) { 901 if (PyErr_Occurred()) 902 goto error; 903 break; 904 } 905 PyList_SetItem(list, j, line); 906 } 907 } 908 if (j == 0) 909 break; 910 911 /* Check that all entries are indeed strings. If not, 912 apply the same rules as for file.write() and 913 convert the rets to strings. This is slow, but 914 seems to be the only way since all conversion APIs 915 could potentially execute Python code. */ 916 for (i = 0; i < j; i++) { 917 PyObject *v = PyList_GET_ITEM(list, i); 918 if (!PyString_Check(v)) { 919 const char *buffer; 920 Py_ssize_t len; 921 if (PyObject_AsCharBuffer(v, &buffer, &len)) { 922 PyErr_SetString(PyExc_TypeError, 923 "writelines() " 924 "argument must be " 925 "a sequence of " 926 "strings"); 927 goto error; 928 } 929 line = PyString_FromStringAndSize(buffer, 930 len); 931 if (line == NULL) 932 goto error; 933 Py_DECREF(v); 934 PyList_SET_ITEM(list, i, line); 935 } 936 } 937 938 self->f_softspace = 0; 939 940 /* Since we are releasing the global lock, the 941 following code may *not* execute Python code. */ 942 Py_BEGIN_ALLOW_THREADS 943 for (i = 0; i < j; i++) { 944 line = PyList_GET_ITEM(list, i); 945 len = PyString_GET_SIZE(line); 946 BZ2_bzWrite (&bzerror, self->fp, 947 PyString_AS_STRING(line), len); 948 if (bzerror != BZ_OK) { 949 Py_BLOCK_THREADS 950 Util_CatchBZ2Error(bzerror); 951 goto error; 952 } 953 } 954 Py_END_ALLOW_THREADS 955 956 if (j < CHUNKSIZE) 957 break; 958 } 959 960 Py_INCREF(Py_None); 961 ret = Py_None; 962 963 error: 964 RELEASE_LOCK(self); 965 Py_XDECREF(list); 966 Py_XDECREF(iter); 967 return ret; 968#undef CHUNKSIZE 969} 970 971PyDoc_STRVAR(BZ2File_seek__doc__, 972"seek(offset [, whence]) -> None\n\ 973\n\ 974Move to new file position. Argument offset is a byte count. Optional\n\ 975argument whence defaults to 0 (offset from start of file, offset\n\ 976should be >= 0); other values are 1 (move relative to current position,\n\ 977positive or negative), and 2 (move relative to end of file, usually\n\ 978negative, although many platforms allow seeking beyond the end of a file).\n\ 979\n\ 980Note that seeking of bz2 files is emulated, and depending on the parameters\n\ 981the operation may be extremely slow.\n\ 982"); 983 984static PyObject * 985BZ2File_seek(BZ2FileObject *self, PyObject *args) 986{ 987 int where = 0; 988 PyObject *offobj; 989 Py_off_t offset; 990 char small_buffer[SMALLCHUNK]; 991 char *buffer = small_buffer; 992 size_t buffersize = SMALLCHUNK; 993 Py_off_t bytesread = 0; 994 size_t readsize; 995 int chunksize; 996 int bzerror; 997 PyObject *ret = NULL; 998 999 if (!PyArg_ParseTuple(args, "O|i:seek", &offobj, &where)) 1000 return NULL; 1001#if !defined(HAVE_LARGEFILE_SUPPORT) 1002 offset = PyInt_AsLong(offobj); 1003#else 1004 offset = PyLong_Check(offobj) ? 1005 PyLong_AsLongLong(offobj) : PyInt_AsLong(offobj); 1006#endif 1007 if (PyErr_Occurred()) 1008 return NULL; 1009 1010 ACQUIRE_LOCK(self); 1011 Util_DropReadAhead(self); 1012 switch (self->mode) { 1013 case MODE_READ: 1014 case MODE_READ_EOF: 1015 break; 1016 1017 case MODE_CLOSED: 1018 PyErr_SetString(PyExc_ValueError, 1019 "I/O operation on closed file"); 1020 goto cleanup; 1021 1022 default: 1023 PyErr_SetString(PyExc_IOError, 1024 "seek works only while reading"); 1025 goto cleanup; 1026 } 1027 1028 if (where == 2) { 1029 if (self->size == -1) { 1030 assert(self->mode != MODE_READ_EOF); 1031 for (;;) { 1032 Py_BEGIN_ALLOW_THREADS 1033 chunksize = Util_UnivNewlineRead( 1034 &bzerror, self->fp, 1035 buffer, buffersize, 1036 self); 1037 self->pos += chunksize; 1038 Py_END_ALLOW_THREADS 1039 1040 bytesread += chunksize; 1041 if (bzerror == BZ_STREAM_END) { 1042 break; 1043 } else if (bzerror != BZ_OK) { 1044 Util_CatchBZ2Error(bzerror); 1045 goto cleanup; 1046 } 1047 } 1048 self->mode = MODE_READ_EOF; 1049 self->size = self->pos; 1050 bytesread = 0; 1051 } 1052 offset = self->size + offset; 1053 } else if (where == 1) { 1054 offset = self->pos + offset; 1055 } 1056 1057 /* Before getting here, offset must be the absolute position the file 1058 * pointer should be set to. */ 1059 1060 if (offset >= self->pos) { 1061 /* we can move forward */ 1062 offset -= self->pos; 1063 } else { 1064 /* we cannot move back, so rewind the stream */ 1065 BZ2_bzReadClose(&bzerror, self->fp); 1066 if (bzerror != BZ_OK) { 1067 Util_CatchBZ2Error(bzerror); 1068 goto cleanup; 1069 } 1070 ret = PyObject_CallMethod(self->file, "seek", "(i)", 0); 1071 if (!ret) 1072 goto cleanup; 1073 Py_DECREF(ret); 1074 ret = NULL; 1075 self->pos = 0; 1076 self->fp = BZ2_bzReadOpen(&bzerror, PyFile_AsFile(self->file), 1077 0, 0, NULL, 0); 1078 if (bzerror != BZ_OK) { 1079 Util_CatchBZ2Error(bzerror); 1080 goto cleanup; 1081 } 1082 self->mode = MODE_READ; 1083 } 1084 1085 if (offset <= 0 || self->mode == MODE_READ_EOF) 1086 goto exit; 1087 1088 /* Before getting here, offset must be set to the number of bytes 1089 * to walk forward. */ 1090 for (;;) { 1091 if (offset-bytesread > buffersize) 1092 readsize = buffersize; 1093 else 1094 /* offset might be wider that readsize, but the result 1095 * of the subtraction is bound by buffersize (see the 1096 * condition above). buffersize is 8192. */ 1097 readsize = (size_t)(offset-bytesread); 1098 Py_BEGIN_ALLOW_THREADS 1099 chunksize = Util_UnivNewlineRead(&bzerror, self->fp, 1100 buffer, readsize, self); 1101 self->pos += chunksize; 1102 Py_END_ALLOW_THREADS 1103 bytesread += chunksize; 1104 if (bzerror == BZ_STREAM_END) { 1105 self->size = self->pos; 1106 self->mode = MODE_READ_EOF; 1107 break; 1108 } else if (bzerror != BZ_OK) { 1109 Util_CatchBZ2Error(bzerror); 1110 goto cleanup; 1111 } 1112 if (bytesread == offset) 1113 break; 1114 } 1115 1116exit: 1117 Py_INCREF(Py_None); 1118 ret = Py_None; 1119 1120cleanup: 1121 RELEASE_LOCK(self); 1122 return ret; 1123} 1124 1125PyDoc_STRVAR(BZ2File_tell__doc__, 1126"tell() -> int\n\ 1127\n\ 1128Return the current file position, an integer (may be a long integer).\n\ 1129"); 1130 1131static PyObject * 1132BZ2File_tell(BZ2FileObject *self, PyObject *args) 1133{ 1134 PyObject *ret = NULL; 1135 1136 if (self->mode == MODE_CLOSED) { 1137 PyErr_SetString(PyExc_ValueError, 1138 "I/O operation on closed file"); 1139 goto cleanup; 1140 } 1141 1142#if !defined(HAVE_LARGEFILE_SUPPORT) 1143 ret = PyInt_FromLong(self->pos); 1144#else 1145 ret = PyLong_FromLongLong(self->pos); 1146#endif 1147 1148cleanup: 1149 return ret; 1150} 1151 1152PyDoc_STRVAR(BZ2File_close__doc__, 1153"close() -> None or (perhaps) an integer\n\ 1154\n\ 1155Close the file. Sets data attribute .closed to true. A closed file\n\ 1156cannot be used for further I/O operations. close() may be called more\n\ 1157than once without error.\n\ 1158"); 1159 1160static PyObject * 1161BZ2File_close(BZ2FileObject *self) 1162{ 1163 PyObject *ret = NULL; 1164 int bzerror = BZ_OK; 1165 1166 ACQUIRE_LOCK(self); 1167 switch (self->mode) { 1168 case MODE_READ: 1169 case MODE_READ_EOF: 1170 BZ2_bzReadClose(&bzerror, self->fp); 1171 break; 1172 case MODE_WRITE: 1173 BZ2_bzWriteClose(&bzerror, self->fp, 1174 0, NULL, NULL); 1175 break; 1176 } 1177 self->mode = MODE_CLOSED; 1178 ret = PyObject_CallMethod(self->file, "close", NULL); 1179 if (bzerror != BZ_OK) { 1180 Util_CatchBZ2Error(bzerror); 1181 Py_XDECREF(ret); 1182 ret = NULL; 1183 } 1184 1185 RELEASE_LOCK(self); 1186 return ret; 1187} 1188 1189static PyObject *BZ2File_getiter(BZ2FileObject *self); 1190 1191static PyMethodDef BZ2File_methods[] = { 1192 {"read", (PyCFunction)BZ2File_read, METH_VARARGS, BZ2File_read__doc__}, 1193 {"readline", (PyCFunction)BZ2File_readline, METH_VARARGS, BZ2File_readline__doc__}, 1194 {"readlines", (PyCFunction)BZ2File_readlines, METH_VARARGS, BZ2File_readlines__doc__}, 1195 {"xreadlines", (PyCFunction)BZ2File_getiter, METH_VARARGS, BZ2File_xreadlines__doc__}, 1196 {"write", (PyCFunction)BZ2File_write, METH_VARARGS, BZ2File_write__doc__}, 1197 {"writelines", (PyCFunction)BZ2File_writelines, METH_O, BZ2File_writelines__doc__}, 1198 {"seek", (PyCFunction)BZ2File_seek, METH_VARARGS, BZ2File_seek__doc__}, 1199 {"tell", (PyCFunction)BZ2File_tell, METH_NOARGS, BZ2File_tell__doc__}, 1200 {"close", (PyCFunction)BZ2File_close, METH_NOARGS, BZ2File_close__doc__}, 1201 {NULL, NULL} /* sentinel */ 1202}; 1203 1204 1205/* ===================================================================== */ 1206/* Getters and setters of BZ2File. */ 1207 1208/* This is a hacked version of Python's fileobject.c:get_newlines(). */ 1209static PyObject * 1210BZ2File_get_newlines(BZ2FileObject *self, void *closure) 1211{ 1212 switch (self->f_newlinetypes) { 1213 case NEWLINE_UNKNOWN: 1214 Py_INCREF(Py_None); 1215 return Py_None; 1216 case NEWLINE_CR: 1217 return PyString_FromString("\r"); 1218 case NEWLINE_LF: 1219 return PyString_FromString("\n"); 1220 case NEWLINE_CR|NEWLINE_LF: 1221 return Py_BuildValue("(ss)", "\r", "\n"); 1222 case NEWLINE_CRLF: 1223 return PyString_FromString("\r\n"); 1224 case NEWLINE_CR|NEWLINE_CRLF: 1225 return Py_BuildValue("(ss)", "\r", "\r\n"); 1226 case NEWLINE_LF|NEWLINE_CRLF: 1227 return Py_BuildValue("(ss)", "\n", "\r\n"); 1228 case NEWLINE_CR|NEWLINE_LF|NEWLINE_CRLF: 1229 return Py_BuildValue("(sss)", "\r", "\n", "\r\n"); 1230 default: 1231 PyErr_Format(PyExc_SystemError, 1232 "Unknown newlines value 0x%x\n", 1233 self->f_newlinetypes); 1234 return NULL; 1235 } 1236} 1237 1238static PyObject * 1239BZ2File_get_closed(BZ2FileObject *self, void *closure) 1240{ 1241 return PyInt_FromLong(self->mode == MODE_CLOSED); 1242} 1243 1244static PyObject * 1245BZ2File_get_mode(BZ2FileObject *self, void *closure) 1246{ 1247 return PyObject_GetAttrString(self->file, "mode"); 1248} 1249 1250static PyObject * 1251BZ2File_get_name(BZ2FileObject *self, void *closure) 1252{ 1253 return PyObject_GetAttrString(self->file, "name"); 1254} 1255 1256static PyGetSetDef BZ2File_getset[] = { 1257 {"closed", (getter)BZ2File_get_closed, NULL, 1258 "True if the file is closed"}, 1259 {"newlines", (getter)BZ2File_get_newlines, NULL, 1260 "end-of-line convention used in this file"}, 1261 {"mode", (getter)BZ2File_get_mode, NULL, 1262 "file mode ('r', 'w', or 'U')"}, 1263 {"name", (getter)BZ2File_get_name, NULL, 1264 "file name"}, 1265 {NULL} /* Sentinel */ 1266}; 1267 1268 1269/* ===================================================================== */ 1270/* Members of BZ2File_Type. */ 1271 1272#undef OFF 1273#define OFF(x) offsetof(BZ2FileObject, x) 1274 1275static PyMemberDef BZ2File_members[] = { 1276 {"softspace", T_INT, OFF(f_softspace), 0, 1277 "flag indicating that a space needs to be printed; used by print"}, 1278 {NULL} /* Sentinel */ 1279}; 1280 1281/* ===================================================================== */ 1282/* Slot definitions for BZ2File_Type. */ 1283 1284static int 1285BZ2File_init(BZ2FileObject *self, PyObject *args, PyObject *kwargs) 1286{ 1287 static char *kwlist[] = {"filename", "mode", "buffering", 1288 "compresslevel", 0}; 1289 PyObject *name; 1290 char *mode = "r"; 1291 int buffering = -1; 1292 int compresslevel = 9; 1293 int bzerror; 1294 int mode_char = 0; 1295 1296 self->size = -1; 1297 1298 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|sii:BZ2File", 1299 kwlist, &name, &mode, &buffering, 1300 &compresslevel)) 1301 return -1; 1302 1303 if (compresslevel < 1 || compresslevel > 9) { 1304 PyErr_SetString(PyExc_ValueError, 1305 "compresslevel must be between 1 and 9"); 1306 return -1; 1307 } 1308 1309 for (;;) { 1310 int error = 0; 1311 switch (*mode) { 1312 case 'r': 1313 case 'w': 1314 if (mode_char) 1315 error = 1; 1316 mode_char = *mode; 1317 break; 1318 1319 case 'b': 1320 break; 1321 1322 case 'U': 1323#ifdef __VMS 1324 self->f_univ_newline = 0; 1325#else 1326 self->f_univ_newline = 1; 1327#endif 1328 break; 1329 1330 default: 1331 error = 1; 1332 break; 1333 } 1334 if (error) { 1335 PyErr_Format(PyExc_ValueError, 1336 "invalid mode char %c", *mode); 1337 return -1; 1338 } 1339 mode++; 1340 if (*mode == '\0') 1341 break; 1342 } 1343 1344 if (mode_char == 0) { 1345 mode_char = 'r'; 1346 } 1347 1348 mode = (mode_char == 'r') ? "rb" : "wb"; 1349 1350 self->file = PyObject_CallFunction((PyObject*)&PyFile_Type, "(Osi)", 1351 name, mode, buffering); 1352 if (self->file == NULL) 1353 return -1; 1354 1355 /* From now on, we have stuff to dealloc, so jump to error label 1356 * instead of returning */ 1357 1358#ifdef WITH_THREAD 1359 self->lock = PyThread_allocate_lock(); 1360 if (!self->lock) { 1361 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock"); 1362 goto error; 1363 } 1364#endif 1365 1366 if (mode_char == 'r') 1367 self->fp = BZ2_bzReadOpen(&bzerror, 1368 PyFile_AsFile(self->file), 1369 0, 0, NULL, 0); 1370 else 1371 self->fp = BZ2_bzWriteOpen(&bzerror, 1372 PyFile_AsFile(self->file), 1373 compresslevel, 0, 0); 1374 1375 if (bzerror != BZ_OK) { 1376 Util_CatchBZ2Error(bzerror); 1377 goto error; 1378 } 1379 1380 self->mode = (mode_char == 'r') ? MODE_READ : MODE_WRITE; 1381 1382 return 0; 1383 1384error: 1385 Py_CLEAR(self->file); 1386#ifdef WITH_THREAD 1387 if (self->lock) { 1388 PyThread_free_lock(self->lock); 1389 self->lock = NULL; 1390 } 1391#endif 1392 return -1; 1393} 1394 1395static void 1396BZ2File_dealloc(BZ2FileObject *self) 1397{ 1398 int bzerror; 1399#ifdef WITH_THREAD 1400 if (self->lock) 1401 PyThread_free_lock(self->lock); 1402#endif 1403 switch (self->mode) { 1404 case MODE_READ: 1405 case MODE_READ_EOF: 1406 BZ2_bzReadClose(&bzerror, self->fp); 1407 break; 1408 case MODE_WRITE: 1409 BZ2_bzWriteClose(&bzerror, self->fp, 1410 0, NULL, NULL); 1411 break; 1412 } 1413 Util_DropReadAhead(self); 1414 Py_XDECREF(self->file); 1415 Py_Type(self)->tp_free((PyObject *)self); 1416} 1417 1418/* This is a hacked version of Python's fileobject.c:file_getiter(). */ 1419static PyObject * 1420BZ2File_getiter(BZ2FileObject *self) 1421{ 1422 if (self->mode == MODE_CLOSED) { 1423 PyErr_SetString(PyExc_ValueError, 1424 "I/O operation on closed file"); 1425 return NULL; 1426 } 1427 Py_INCREF((PyObject*)self); 1428 return (PyObject *)self; 1429} 1430 1431/* This is a hacked version of Python's fileobject.c:file_iternext(). */ 1432#define READAHEAD_BUFSIZE 8192 1433static PyObject * 1434BZ2File_iternext(BZ2FileObject *self) 1435{ 1436 PyStringObject* ret; 1437 ACQUIRE_LOCK(self); 1438 if (self->mode == MODE_CLOSED) { 1439 PyErr_SetString(PyExc_ValueError, 1440 "I/O operation on closed file"); 1441 return NULL; 1442 } 1443 ret = Util_ReadAheadGetLineSkip(self, 0, READAHEAD_BUFSIZE); 1444 RELEASE_LOCK(self); 1445 if (ret == NULL || PyString_GET_SIZE(ret) == 0) { 1446 Py_XDECREF(ret); 1447 return NULL; 1448 } 1449 return (PyObject *)ret; 1450} 1451 1452/* ===================================================================== */ 1453/* BZ2File_Type definition. */ 1454 1455PyDoc_VAR(BZ2File__doc__) = 1456PyDoc_STR( 1457"BZ2File(name [, mode='r', buffering=0, compresslevel=9]) -> file object\n\ 1458\n\ 1459Open a bz2 file. The mode can be 'r' or 'w', for reading (default) or\n\ 1460writing. When opened for writing, the file will be created if it doesn't\n\ 1461exist, and truncated otherwise. If the buffering argument is given, 0 means\n\ 1462unbuffered, and larger numbers specify the buffer size. If compresslevel\n\ 1463is given, must be a number between 1 and 9.\n\ 1464") 1465PyDoc_STR( 1466"\n\ 1467Add a 'U' to mode to open the file for input with universal newline\n\ 1468support. Any line ending in the input file will be seen as a '\\n' in\n\ 1469Python. Also, a file so opened gains the attribute 'newlines'; the value\n\ 1470for this attribute is one of None (no newline read yet), '\\r', '\\n',\n\ 1471'\\r\\n' or a tuple containing all the newline types seen. Universal\n\ 1472newlines are available only when reading.\n\ 1473") 1474; 1475 1476static PyTypeObject BZ2File_Type = { 1477 PyVarObject_HEAD_INIT(NULL, 0) 1478 "bz2.BZ2File", /*tp_name*/ 1479 sizeof(BZ2FileObject), /*tp_basicsize*/ 1480 0, /*tp_itemsize*/ 1481 (destructor)BZ2File_dealloc, /*tp_dealloc*/ 1482 0, /*tp_print*/ 1483 0, /*tp_getattr*/ 1484 0, /*tp_setattr*/ 1485 0, /*tp_compare*/ 1486 0, /*tp_repr*/ 1487 0, /*tp_as_number*/ 1488 0, /*tp_as_sequence*/ 1489 0, /*tp_as_mapping*/ 1490 0, /*tp_hash*/ 1491 0, /*tp_call*/ 1492 0, /*tp_str*/ 1493 PyObject_GenericGetAttr,/*tp_getattro*/ 1494 PyObject_GenericSetAttr,/*tp_setattro*/ 1495 0, /*tp_as_buffer*/ 1496 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ 1497 BZ2File__doc__, /*tp_doc*/ 1498 0, /*tp_traverse*/ 1499 0, /*tp_clear*/ 1500 0, /*tp_richcompare*/ 1501 0, /*tp_weaklistoffset*/ 1502 (getiterfunc)BZ2File_getiter, /*tp_iter*/ 1503 (iternextfunc)BZ2File_iternext, /*tp_iternext*/ 1504 BZ2File_methods, /*tp_methods*/ 1505 BZ2File_members, /*tp_members*/ 1506 BZ2File_getset, /*tp_getset*/ 1507 0, /*tp_base*/ 1508 0, /*tp_dict*/ 1509 0, /*tp_descr_get*/ 1510 0, /*tp_descr_set*/ 1511 0, /*tp_dictoffset*/ 1512 (initproc)BZ2File_init, /*tp_init*/ 1513 PyType_GenericAlloc, /*tp_alloc*/ 1514 PyType_GenericNew, /*tp_new*/ 1515 _PyObject_Del, /*tp_free*/ 1516 0, /*tp_is_gc*/ 1517}; 1518 1519 1520/* ===================================================================== */ 1521/* Methods of BZ2Comp. */ 1522 1523PyDoc_STRVAR(BZ2Comp_compress__doc__, 1524"compress(data) -> string\n\ 1525\n\ 1526Provide more data to the compressor object. It will return chunks of\n\ 1527compressed data whenever possible. When you've finished providing data\n\ 1528to compress, call the flush() method to finish the compression process,\n\ 1529and return what is left in the internal buffers.\n\ 1530"); 1531 1532static PyObject * 1533BZ2Comp_compress(BZ2CompObject *self, PyObject *args) 1534{ 1535 char *data; 1536 int datasize; 1537 int bufsize = SMALLCHUNK; 1538 PY_LONG_LONG totalout; 1539 PyObject *ret = NULL; 1540 bz_stream *bzs = &self->bzs; 1541 int bzerror; 1542 1543 if (!PyArg_ParseTuple(args, "s#:compress", &data, &datasize)) 1544 return NULL; 1545 1546 if (datasize == 0) 1547 return PyString_FromString(""); 1548 1549 ACQUIRE_LOCK(self); 1550 if (!self->running) { 1551 PyErr_SetString(PyExc_ValueError, 1552 "this object was already flushed"); 1553 goto error; 1554 } 1555 1556 ret = PyString_FromStringAndSize(NULL, bufsize); 1557 if (!ret) 1558 goto error; 1559 1560 bzs->next_in = data; 1561 bzs->avail_in = datasize; 1562 bzs->next_out = BUF(ret); 1563 bzs->avail_out = bufsize; 1564 1565 totalout = BZS_TOTAL_OUT(bzs); 1566 1567 for (;;) { 1568 Py_BEGIN_ALLOW_THREADS 1569 bzerror = BZ2_bzCompress(bzs, BZ_RUN); 1570 Py_END_ALLOW_THREADS 1571 if (bzerror != BZ_RUN_OK) { 1572 Util_CatchBZ2Error(bzerror); 1573 goto error; 1574 } 1575 if (bzs->avail_in == 0) 1576 break; /* no more input data */ 1577 if (bzs->avail_out == 0) { 1578 bufsize = Util_NewBufferSize(bufsize); 1579 if (_PyString_Resize(&ret, bufsize) < 0) { 1580 BZ2_bzCompressEnd(bzs); 1581 goto error; 1582 } 1583 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs) 1584 - totalout); 1585 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret)); 1586 } 1587 } 1588 1589 _PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout)); 1590 1591 RELEASE_LOCK(self); 1592 return ret; 1593 1594error: 1595 RELEASE_LOCK(self); 1596 Py_XDECREF(ret); 1597 return NULL; 1598} 1599 1600PyDoc_STRVAR(BZ2Comp_flush__doc__, 1601"flush() -> string\n\ 1602\n\ 1603Finish the compression process and return what is left in internal buffers.\n\ 1604You must not use the compressor object after calling this method.\n\ 1605"); 1606 1607static PyObject * 1608BZ2Comp_flush(BZ2CompObject *self) 1609{ 1610 int bufsize = SMALLCHUNK; 1611 PyObject *ret = NULL; 1612 bz_stream *bzs = &self->bzs; 1613 PY_LONG_LONG totalout; 1614 int bzerror; 1615 1616 ACQUIRE_LOCK(self); 1617 if (!self->running) { 1618 PyErr_SetString(PyExc_ValueError, "object was already " 1619 "flushed"); 1620 goto error; 1621 } 1622 self->running = 0; 1623 1624 ret = PyString_FromStringAndSize(NULL, bufsize); 1625 if (!ret) 1626 goto error; 1627 1628 bzs->next_out = BUF(ret); 1629 bzs->avail_out = bufsize; 1630 1631 totalout = BZS_TOTAL_OUT(bzs); 1632 1633 for (;;) { 1634 Py_BEGIN_ALLOW_THREADS 1635 bzerror = BZ2_bzCompress(bzs, BZ_FINISH); 1636 Py_END_ALLOW_THREADS 1637 if (bzerror == BZ_STREAM_END) { 1638 break; 1639 } else if (bzerror != BZ_FINISH_OK) { 1640 Util_CatchBZ2Error(bzerror); 1641 goto error; 1642 } 1643 if (bzs->avail_out == 0) { 1644 bufsize = Util_NewBufferSize(bufsize); 1645 if (_PyString_Resize(&ret, bufsize) < 0) 1646 goto error; 1647 bzs->next_out = BUF(ret); 1648 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs) 1649 - totalout); 1650 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret)); 1651 } 1652 } 1653 1654 if (bzs->avail_out != 0) 1655 _PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout)); 1656 1657 RELEASE_LOCK(self); 1658 return ret; 1659 1660error: 1661 RELEASE_LOCK(self); 1662 Py_XDECREF(ret); 1663 return NULL; 1664} 1665 1666static PyMethodDef BZ2Comp_methods[] = { 1667 {"compress", (PyCFunction)BZ2Comp_compress, METH_VARARGS, 1668 BZ2Comp_compress__doc__}, 1669 {"flush", (PyCFunction)BZ2Comp_flush, METH_NOARGS, 1670 BZ2Comp_flush__doc__}, 1671 {NULL, NULL} /* sentinel */ 1672}; 1673 1674 1675/* ===================================================================== */ 1676/* Slot definitions for BZ2Comp_Type. */ 1677 1678static int 1679BZ2Comp_init(BZ2CompObject *self, PyObject *args, PyObject *kwargs) 1680{ 1681 int compresslevel = 9; 1682 int bzerror; 1683 static char *kwlist[] = {"compresslevel", 0}; 1684 1685 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:BZ2Compressor", 1686 kwlist, &compresslevel)) 1687 return -1; 1688 1689 if (compresslevel < 1 || compresslevel > 9) { 1690 PyErr_SetString(PyExc_ValueError, 1691 "compresslevel must be between 1 and 9"); 1692 goto error; 1693 } 1694 1695#ifdef WITH_THREAD 1696 self->lock = PyThread_allocate_lock(); 1697 if (!self->lock) { 1698 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock"); 1699 goto error; 1700 } 1701#endif 1702 1703 memset(&self->bzs, 0, sizeof(bz_stream)); 1704 bzerror = BZ2_bzCompressInit(&self->bzs, compresslevel, 0, 0); 1705 if (bzerror != BZ_OK) { 1706 Util_CatchBZ2Error(bzerror); 1707 goto error; 1708 } 1709 1710 self->running = 1; 1711 1712 return 0; 1713error: 1714#ifdef WITH_THREAD 1715 if (self->lock) { 1716 PyThread_free_lock(self->lock); 1717 self->lock = NULL; 1718 } 1719#endif 1720 return -1; 1721} 1722 1723static void 1724BZ2Comp_dealloc(BZ2CompObject *self) 1725{ 1726#ifdef WITH_THREAD 1727 if (self->lock) 1728 PyThread_free_lock(self->lock); 1729#endif 1730 BZ2_bzCompressEnd(&self->bzs); 1731 Py_Type(self)->tp_free((PyObject *)self); 1732} 1733 1734 1735/* ===================================================================== */ 1736/* BZ2Comp_Type definition. */ 1737 1738PyDoc_STRVAR(BZ2Comp__doc__, 1739"BZ2Compressor([compresslevel=9]) -> compressor object\n\ 1740\n\ 1741Create a new compressor object. This object may be used to compress\n\ 1742data sequentially. If you want to compress data in one shot, use the\n\ 1743compress() function instead. The compresslevel parameter, if given,\n\ 1744must be a number between 1 and 9.\n\ 1745"); 1746 1747static PyTypeObject BZ2Comp_Type = { 1748 PyVarObject_HEAD_INIT(NULL, 0) 1749 "bz2.BZ2Compressor", /*tp_name*/ 1750 sizeof(BZ2CompObject), /*tp_basicsize*/ 1751 0, /*tp_itemsize*/ 1752 (destructor)BZ2Comp_dealloc, /*tp_dealloc*/ 1753 0, /*tp_print*/ 1754 0, /*tp_getattr*/ 1755 0, /*tp_setattr*/ 1756 0, /*tp_compare*/ 1757 0, /*tp_repr*/ 1758 0, /*tp_as_number*/ 1759 0, /*tp_as_sequence*/ 1760 0, /*tp_as_mapping*/ 1761 0, /*tp_hash*/ 1762 0, /*tp_call*/ 1763 0, /*tp_str*/ 1764 PyObject_GenericGetAttr,/*tp_getattro*/ 1765 PyObject_GenericSetAttr,/*tp_setattro*/ 1766 0, /*tp_as_buffer*/ 1767 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ 1768 BZ2Comp__doc__, /*tp_doc*/ 1769 0, /*tp_traverse*/ 1770 0, /*tp_clear*/ 1771 0, /*tp_richcompare*/ 1772 0, /*tp_weaklistoffset*/ 1773 0, /*tp_iter*/ 1774 0, /*tp_iternext*/ 1775 BZ2Comp_methods, /*tp_methods*/ 1776 0, /*tp_members*/ 1777 0, /*tp_getset*/ 1778 0, /*tp_base*/ 1779 0, /*tp_dict*/ 1780 0, /*tp_descr_get*/ 1781 0, /*tp_descr_set*/ 1782 0, /*tp_dictoffset*/ 1783 (initproc)BZ2Comp_init, /*tp_init*/ 1784 PyType_GenericAlloc, /*tp_alloc*/ 1785 PyType_GenericNew, /*tp_new*/ 1786 _PyObject_Del, /*tp_free*/ 1787 0, /*tp_is_gc*/ 1788}; 1789 1790 1791/* ===================================================================== */ 1792/* Members of BZ2Decomp. */ 1793 1794#undef OFF 1795#define OFF(x) offsetof(BZ2DecompObject, x) 1796 1797static PyMemberDef BZ2Decomp_members[] = { 1798 {"unused_data", T_OBJECT, OFF(unused_data), RO}, 1799 {NULL} /* Sentinel */ 1800}; 1801 1802 1803/* ===================================================================== */ 1804/* Methods of BZ2Decomp. */ 1805 1806PyDoc_STRVAR(BZ2Decomp_decompress__doc__, 1807"decompress(data) -> string\n\ 1808\n\ 1809Provide more data to the decompressor object. It will return chunks\n\ 1810of decompressed data whenever possible. If you try to decompress data\n\ 1811after the end of stream is found, EOFError will be raised. If any data\n\ 1812was found after the end of stream, it'll be ignored and saved in\n\ 1813unused_data attribute.\n\ 1814"); 1815 1816static PyObject * 1817BZ2Decomp_decompress(BZ2DecompObject *self, PyObject *args) 1818{ 1819 char *data; 1820 int datasize; 1821 int bufsize = SMALLCHUNK; 1822 PY_LONG_LONG totalout; 1823 PyObject *ret = NULL; 1824 bz_stream *bzs = &self->bzs; 1825 int bzerror; 1826 1827 if (!PyArg_ParseTuple(args, "s#:decompress", &data, &datasize)) 1828 return NULL; 1829 1830 ACQUIRE_LOCK(self); 1831 if (!self->running) { 1832 PyErr_SetString(PyExc_EOFError, "end of stream was " 1833 "already found"); 1834 goto error; 1835 } 1836 1837 ret = PyString_FromStringAndSize(NULL, bufsize); 1838 if (!ret) 1839 goto error; 1840 1841 bzs->next_in = data; 1842 bzs->avail_in = datasize; 1843 bzs->next_out = BUF(ret); 1844 bzs->avail_out = bufsize; 1845 1846 totalout = BZS_TOTAL_OUT(bzs); 1847 1848 for (;;) { 1849 Py_BEGIN_ALLOW_THREADS 1850 bzerror = BZ2_bzDecompress(bzs); 1851 Py_END_ALLOW_THREADS 1852 if (bzerror == BZ_STREAM_END) { 1853 if (bzs->avail_in != 0) { 1854 Py_DECREF(self->unused_data); 1855 self->unused_data = 1856 PyString_FromStringAndSize(bzs->next_in, 1857 bzs->avail_in); 1858 } 1859 self->running = 0; 1860 break; 1861 } 1862 if (bzerror != BZ_OK) { 1863 Util_CatchBZ2Error(bzerror); 1864 goto error; 1865 } 1866 if (bzs->avail_in == 0) 1867 break; /* no more input data */ 1868 if (bzs->avail_out == 0) { 1869 bufsize = Util_NewBufferSize(bufsize); 1870 if (_PyString_Resize(&ret, bufsize) < 0) { 1871 BZ2_bzDecompressEnd(bzs); 1872 goto error; 1873 } 1874 bzs->next_out = BUF(ret); 1875 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs) 1876 - totalout); 1877 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret)); 1878 } 1879 } 1880 1881 if (bzs->avail_out != 0) 1882 _PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout)); 1883 1884 RELEASE_LOCK(self); 1885 return ret; 1886 1887error: 1888 RELEASE_LOCK(self); 1889 Py_XDECREF(ret); 1890 return NULL; 1891} 1892 1893static PyMethodDef BZ2Decomp_methods[] = { 1894 {"decompress", (PyCFunction)BZ2Decomp_decompress, METH_VARARGS, BZ2Decomp_decompress__doc__}, 1895 {NULL, NULL} /* sentinel */ 1896}; 1897 1898 1899/* ===================================================================== */ 1900/* Slot definitions for BZ2Decomp_Type. */ 1901 1902static int 1903BZ2Decomp_init(BZ2DecompObject *self, PyObject *args, PyObject *kwargs) 1904{ 1905 int bzerror; 1906 1907 if (!PyArg_ParseTuple(args, ":BZ2Decompressor")) 1908 return -1; 1909 1910#ifdef WITH_THREAD 1911 self->lock = PyThread_allocate_lock(); 1912 if (!self->lock) { 1913 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock"); 1914 goto error; 1915 } 1916#endif 1917 1918 self->unused_data = PyString_FromString(""); 1919 if (!self->unused_data) 1920 goto error; 1921 1922 memset(&self->bzs, 0, sizeof(bz_stream)); 1923 bzerror = BZ2_bzDecompressInit(&self->bzs, 0, 0); 1924 if (bzerror != BZ_OK) { 1925 Util_CatchBZ2Error(bzerror); 1926 goto error; 1927 } 1928 1929 self->running = 1; 1930 1931 return 0; 1932 1933error: 1934#ifdef WITH_THREAD 1935 if (self->lock) { 1936 PyThread_free_lock(self->lock); 1937 self->lock = NULL; 1938 } 1939#endif 1940 Py_CLEAR(self->unused_data); 1941 return -1; 1942} 1943 1944static void 1945BZ2Decomp_dealloc(BZ2DecompObject *self) 1946{ 1947#ifdef WITH_THREAD 1948 if (self->lock) 1949 PyThread_free_lock(self->lock); 1950#endif 1951 Py_XDECREF(self->unused_data); 1952 BZ2_bzDecompressEnd(&self->bzs); 1953 Py_Type(self)->tp_free((PyObject *)self); 1954} 1955 1956 1957/* ===================================================================== */ 1958/* BZ2Decomp_Type definition. */ 1959 1960PyDoc_STRVAR(BZ2Decomp__doc__, 1961"BZ2Decompressor() -> decompressor object\n\ 1962\n\ 1963Create a new decompressor object. This object may be used to decompress\n\ 1964data sequentially. If you want to decompress data in one shot, use the\n\ 1965decompress() function instead.\n\ 1966"); 1967 1968static PyTypeObject BZ2Decomp_Type = { 1969 PyVarObject_HEAD_INIT(NULL, 0) 1970 "bz2.BZ2Decompressor", /*tp_name*/ 1971 sizeof(BZ2DecompObject), /*tp_basicsize*/ 1972 0, /*tp_itemsize*/ 1973 (destructor)BZ2Decomp_dealloc, /*tp_dealloc*/ 1974 0, /*tp_print*/ 1975 0, /*tp_getattr*/ 1976 0, /*tp_setattr*/ 1977 0, /*tp_compare*/ 1978 0, /*tp_repr*/ 1979 0, /*tp_as_number*/ 1980 0, /*tp_as_sequence*/ 1981 0, /*tp_as_mapping*/ 1982 0, /*tp_hash*/ 1983 0, /*tp_call*/ 1984 0, /*tp_str*/ 1985 PyObject_GenericGetAttr,/*tp_getattro*/ 1986 PyObject_GenericSetAttr,/*tp_setattro*/ 1987 0, /*tp_as_buffer*/ 1988 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ 1989 BZ2Decomp__doc__, /*tp_doc*/ 1990 0, /*tp_traverse*/ 1991 0, /*tp_clear*/ 1992 0, /*tp_richcompare*/ 1993 0, /*tp_weaklistoffset*/ 1994 0, /*tp_iter*/ 1995 0, /*tp_iternext*/ 1996 BZ2Decomp_methods, /*tp_methods*/ 1997 BZ2Decomp_members, /*tp_members*/ 1998 0, /*tp_getset*/ 1999 0, /*tp_base*/ 2000 0, /*tp_dict*/ 2001 0, /*tp_descr_get*/ 2002 0, /*tp_descr_set*/ 2003 0, /*tp_dictoffset*/ 2004 (initproc)BZ2Decomp_init, /*tp_init*/ 2005 PyType_GenericAlloc, /*tp_alloc*/ 2006 PyType_GenericNew, /*tp_new*/ 2007 _PyObject_Del, /*tp_free*/ 2008 0, /*tp_is_gc*/ 2009}; 2010 2011 2012/* ===================================================================== */ 2013/* Module functions. */ 2014 2015PyDoc_STRVAR(bz2_compress__doc__, 2016"compress(data [, compresslevel=9]) -> string\n\ 2017\n\ 2018Compress data in one shot. If you want to compress data sequentially,\n\ 2019use an instance of BZ2Compressor instead. The compresslevel parameter, if\n\ 2020given, must be a number between 1 and 9.\n\ 2021"); 2022 2023static PyObject * 2024bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs) 2025{ 2026 int compresslevel=9; 2027 char *data; 2028 int datasize; 2029 int bufsize; 2030 PyObject *ret = NULL; 2031 bz_stream _bzs; 2032 bz_stream *bzs = &_bzs; 2033 int bzerror; 2034 static char *kwlist[] = {"data", "compresslevel", 0}; 2035 2036 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|i", 2037 kwlist, &data, &datasize, 2038 &compresslevel)) 2039 return NULL; 2040 2041 if (compresslevel < 1 || compresslevel > 9) { 2042 PyErr_SetString(PyExc_ValueError, 2043 "compresslevel must be between 1 and 9"); 2044 return NULL; 2045 } 2046 2047 /* Conforming to bz2 manual, this is large enough to fit compressed 2048 * data in one shot. We will check it later anyway. */ 2049 bufsize = datasize + (datasize/100+1) + 600; 2050 2051 ret = PyString_FromStringAndSize(NULL, bufsize); 2052 if (!ret) 2053 return NULL; 2054 2055 memset(bzs, 0, sizeof(bz_stream)); 2056 2057 bzs->next_in = data; 2058 bzs->avail_in = datasize; 2059 bzs->next_out = BUF(ret); 2060 bzs->avail_out = bufsize; 2061 2062 bzerror = BZ2_bzCompressInit(bzs, compresslevel, 0, 0); 2063 if (bzerror != BZ_OK) { 2064 Util_CatchBZ2Error(bzerror); 2065 Py_DECREF(ret); 2066 return NULL; 2067 } 2068 2069 for (;;) { 2070 Py_BEGIN_ALLOW_THREADS 2071 bzerror = BZ2_bzCompress(bzs, BZ_FINISH); 2072 Py_END_ALLOW_THREADS 2073 if (bzerror == BZ_STREAM_END) { 2074 break; 2075 } else if (bzerror != BZ_FINISH_OK) { 2076 BZ2_bzCompressEnd(bzs); 2077 Util_CatchBZ2Error(bzerror); 2078 Py_DECREF(ret); 2079 return NULL; 2080 } 2081 if (bzs->avail_out == 0) { 2082 bufsize = Util_NewBufferSize(bufsize); 2083 if (_PyString_Resize(&ret, bufsize) < 0) { 2084 BZ2_bzCompressEnd(bzs); 2085 Py_DECREF(ret); 2086 return NULL; 2087 } 2088 bzs->next_out = BUF(ret) + BZS_TOTAL_OUT(bzs); 2089 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret)); 2090 } 2091 } 2092 2093 if (bzs->avail_out != 0) 2094 _PyString_Resize(&ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs)); 2095 BZ2_bzCompressEnd(bzs); 2096 2097 return ret; 2098} 2099 2100PyDoc_STRVAR(bz2_decompress__doc__, 2101"decompress(data) -> decompressed data\n\ 2102\n\ 2103Decompress data in one shot. If you want to decompress data sequentially,\n\ 2104use an instance of BZ2Decompressor instead.\n\ 2105"); 2106 2107static PyObject * 2108bz2_decompress(PyObject *self, PyObject *args) 2109{ 2110 char *data; 2111 int datasize; 2112 int bufsize = SMALLCHUNK; 2113 PyObject *ret; 2114 bz_stream _bzs; 2115 bz_stream *bzs = &_bzs; 2116 int bzerror; 2117 2118 if (!PyArg_ParseTuple(args, "s#:decompress", &data, &datasize)) 2119 return NULL; 2120 2121 if (datasize == 0) 2122 return PyString_FromString(""); 2123 2124 ret = PyString_FromStringAndSize(NULL, bufsize); 2125 if (!ret) 2126 return NULL; 2127 2128 memset(bzs, 0, sizeof(bz_stream)); 2129 2130 bzs->next_in = data; 2131 bzs->avail_in = datasize; 2132 bzs->next_out = BUF(ret); 2133 bzs->avail_out = bufsize; 2134 2135 bzerror = BZ2_bzDecompressInit(bzs, 0, 0); 2136 if (bzerror != BZ_OK) { 2137 Util_CatchBZ2Error(bzerror); 2138 Py_DECREF(ret); 2139 return NULL; 2140 } 2141 2142 for (;;) { 2143 Py_BEGIN_ALLOW_THREADS 2144 bzerror = BZ2_bzDecompress(bzs); 2145 Py_END_ALLOW_THREADS 2146 if (bzerror == BZ_STREAM_END) { 2147 break; 2148 } else if (bzerror != BZ_OK) { 2149 BZ2_bzDecompressEnd(bzs); 2150 Util_CatchBZ2Error(bzerror); 2151 Py_DECREF(ret); 2152 return NULL; 2153 } 2154 if (bzs->avail_in == 0) { 2155 BZ2_bzDecompressEnd(bzs); 2156 PyErr_SetString(PyExc_ValueError, 2157 "couldn't find end of stream"); 2158 Py_DECREF(ret); 2159 return NULL; 2160 } 2161 if (bzs->avail_out == 0) { 2162 bufsize = Util_NewBufferSize(bufsize); 2163 if (_PyString_Resize(&ret, bufsize) < 0) { 2164 BZ2_bzDecompressEnd(bzs); 2165 Py_DECREF(ret); 2166 return NULL; 2167 } 2168 bzs->next_out = BUF(ret) + BZS_TOTAL_OUT(bzs); 2169 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret)); 2170 } 2171 } 2172 2173 if (bzs->avail_out != 0) 2174 _PyString_Resize(&ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs)); 2175 BZ2_bzDecompressEnd(bzs); 2176 2177 return ret; 2178} 2179 2180static PyMethodDef bz2_methods[] = { 2181 {"compress", (PyCFunction) bz2_compress, METH_VARARGS|METH_KEYWORDS, 2182 bz2_compress__doc__}, 2183 {"decompress", (PyCFunction) bz2_decompress, METH_VARARGS, 2184 bz2_decompress__doc__}, 2185 {NULL, NULL} /* sentinel */ 2186}; 2187 2188/* ===================================================================== */ 2189/* Initialization function. */ 2190 2191PyDoc_STRVAR(bz2__doc__, 2192"The python bz2 module provides a comprehensive interface for\n\ 2193the bz2 compression library. It implements a complete file\n\ 2194interface, one shot (de)compression functions, and types for\n\ 2195sequential (de)compression.\n\ 2196"); 2197 2198PyMODINIT_FUNC 2199initbz2(void) 2200{ 2201 PyObject *m; 2202 2203 Py_Type(&BZ2File_Type) = &PyType_Type; 2204 Py_Type(&BZ2Comp_Type) = &PyType_Type; 2205 Py_Type(&BZ2Decomp_Type) = &PyType_Type; 2206 2207 m = Py_InitModule3("bz2", bz2_methods, bz2__doc__); 2208 if (m == NULL) 2209 return; 2210 2211 PyModule_AddObject(m, "__author__", PyString_FromString(__author__)); 2212 2213 Py_INCREF(&BZ2File_Type); 2214 PyModule_AddObject(m, "BZ2File", (PyObject *)&BZ2File_Type); 2215 2216 Py_INCREF(&BZ2Comp_Type); 2217 PyModule_AddObject(m, "BZ2Compressor", (PyObject *)&BZ2Comp_Type); 2218 2219 Py_INCREF(&BZ2Decomp_Type); 2220 PyModule_AddObject(m, "BZ2Decompressor", (PyObject *)&BZ2Decomp_Type); 2221} 2222