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