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