3 python-bz2 - python bz2 library interface
5 Copyright (c) 2002 Gustavo Niemeyer <niemeyer@conectiva.com>
6 Copyright (c) 2002 Python Software Foundation; All Rights Reserved
13 #include "structmember.h"
19 static char __author__
[] =
20 "The bz2 python module was written by:\n\
22 Gustavo Niemeyer <niemeyer@conectiva.com>\n\
25 /* Our very own off_t-like type, 64-bit if possible */
26 /* copied from Objects/fileobject.c */
27 #if !defined(HAVE_LARGEFILE_SUPPORT)
28 typedef off_t Py_off_t
;
29 #elif SIZEOF_OFF_T >= 8
30 typedef off_t Py_off_t
;
31 #elif SIZEOF_FPOS_T >= 8
32 typedef fpos_t Py_off_t
;
34 #error "Large file support, but neither off_t nor fpos_t is large enough."
37 #define BUF(v) PyBytes_AS_STRING(v)
41 #define MODE_READ_EOF 2
44 #define BZ2FileObject_Check(v) (Py_TYPE(v) == &BZ2File_Type)
47 #ifdef BZ_CONFIG_ERROR
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)
56 #define BZS_TOTAL_OUT(bzs) \
60 #else /* ! BZ_CONFIG_ERROR */
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
75 #define BZS_TOTAL_OUT(bzs) bzs->total_out
77 #endif /* ! BZ_CONFIG_ERROR */
81 #define ACQUIRE_LOCK(obj) PyThread_acquire_lock(obj->lock, 1)
82 #define RELEASE_LOCK(obj) PyThread_release_lock(obj->lock)
84 #define ACQUIRE_LOCK(obj)
85 #define RELEASE_LOCK(obj)
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 */
94 /* ===================================================================== */
95 /* Structure definitions. */
101 char* f_buf
; /* Allocated readahead buffer */
102 char* f_bufend
; /* Points after last occupied position */
103 char* f_bufptr
; /* Current buffer position */
110 PyThread_type_lock lock
;
119 PyThread_type_lock lock
;
127 PyObject
*unused_data
;
129 PyThread_type_lock lock
;
133 /* ===================================================================== */
134 /* Utility functions. */
137 Util_CatchBZ2Error(int bzerror
)
145 #ifdef BZ_CONFIG_ERROR
146 case BZ_CONFIG_ERROR
:
147 PyErr_SetString(PyExc_SystemError
,
148 "the bz2 library was not compiled "
155 PyErr_SetString(PyExc_ValueError
,
156 "the bz2 library has received wrong "
167 case BZ_DATA_ERROR_MAGIC
:
168 PyErr_SetString(PyExc_IOError
, "invalid data stream");
173 PyErr_SetString(PyExc_IOError
, "unknown IO error");
177 case BZ_UNEXPECTED_EOF
:
178 PyErr_SetString(PyExc_EOFError
,
179 "compressed file ended before the "
180 "logical end-of-stream was detected");
184 case BZ_SEQUENCE_ERROR
:
185 PyErr_SetString(PyExc_RuntimeError
,
186 "wrong sequence of bz2 library "
195 #define SMALLCHUNK 8192
197 #define SMALLCHUNK BUFSIZ
201 #define BIGCHUNK (512 * 32)
203 #define BIGCHUNK (512 * 1024)
206 /* This is a hacked version of Python's fileobject.c:new_buffersize(). */
208 Util_NewBufferSize(size_t currentsize
)
210 if (currentsize
> SMALLCHUNK
) {
211 /* Keep doubling until we reach BIGCHUNK;
212 then keep adding BIGCHUNK. */
213 if (currentsize
<= BIGCHUNK
)
214 return currentsize
+ currentsize
;
216 return currentsize
+ BIGCHUNK
;
218 return currentsize
+ SMALLCHUNK
;
221 /* This is a hacked version of Python's fileobject.c:get_line(). */
223 Util_GetLine(BZ2FileObject
*f
, int n
)
227 size_t total_v_size
; /* total # of slots in buffer */
228 size_t used_v_size
; /* # used slots in buffer */
229 size_t increment
; /* amount to increment the buffer */
234 total_v_size
= n
> 0 ? n
: 100;
235 v
= PyBytes_FromStringAndSize((char *)NULL
, total_v_size
);
240 end
= buf
+ total_v_size
;
243 Py_BEGIN_ALLOW_THREADS
245 bytes_read
= BZ2_bzRead(&bzerror
, f
->fp
, &c
, 1);
250 } while (bzerror
== BZ_OK
&& c
!= '\n' && buf
!= end
);
252 if (bzerror
== BZ_STREAM_END
) {
254 f
->mode
= MODE_READ_EOF
;
256 } else if (bzerror
!= BZ_OK
) {
257 Util_CatchBZ2Error(bzerror
);
263 /* Must be because buf == end */
266 used_v_size
= total_v_size
;
267 increment
= total_v_size
>> 2; /* mild exponential growth */
268 total_v_size
+= increment
;
269 if (total_v_size
> INT_MAX
) {
270 PyErr_SetString(PyExc_OverflowError
,
271 "line is longer than a Python string can hold");
275 if (_PyBytes_Resize(&v
, total_v_size
) < 0) {
278 buf
= BUF(v
) + used_v_size
;
279 end
= BUF(v
) + total_v_size
;
282 used_v_size
= buf
- BUF(v
);
283 if (used_v_size
!= total_v_size
) {
284 if (_PyBytes_Resize(&v
, used_v_size
) < 0) {
291 /* This is a hacked version of Python's fileobject.c:drop_readahead(). */
293 Util_DropReadAhead(BZ2FileObject
*f
)
295 if (f
->f_buf
!= NULL
) {
296 PyMem_Free(f
->f_buf
);
301 /* This is a hacked version of Python's fileobject.c:readahead(). */
303 Util_ReadAhead(BZ2FileObject
*f
, int bufsize
)
308 if (f
->f_buf
!= NULL
) {
309 if((f
->f_bufend
- f
->f_bufptr
) >= 1)
312 Util_DropReadAhead(f
);
314 if (f
->mode
== MODE_READ_EOF
) {
315 f
->f_bufptr
= f
->f_buf
;
316 f
->f_bufend
= f
->f_buf
;
319 if ((f
->f_buf
= PyMem_Malloc(bufsize
)) == NULL
) {
323 Py_BEGIN_ALLOW_THREADS
324 chunksize
= BZ2_bzRead(&bzerror
, f
->fp
, f
->f_buf
, bufsize
);
327 if (bzerror
== BZ_STREAM_END
) {
329 f
->mode
= MODE_READ_EOF
;
330 } else if (bzerror
!= BZ_OK
) {
331 Util_CatchBZ2Error(bzerror
);
332 Util_DropReadAhead(f
);
335 f
->f_bufptr
= f
->f_buf
;
336 f
->f_bufend
= f
->f_buf
+ chunksize
;
340 /* This is a hacked version of Python's
341 * fileobject.c:readahead_get_line_skip(). */
342 static PyBytesObject
*
343 Util_ReadAheadGetLineSkip(BZ2FileObject
*f
, int skip
, int bufsize
)
350 if (f
->f_buf
== NULL
)
351 if (Util_ReadAhead(f
, bufsize
) < 0)
354 len
= f
->f_bufend
- f
->f_bufptr
;
356 return (PyBytesObject
*)
357 PyBytes_FromStringAndSize(NULL
, skip
);
358 bufptr
= memchr(f
->f_bufptr
, '\n', len
);
359 if (bufptr
!= NULL
) {
360 bufptr
++; /* Count the '\n' */
361 len
= bufptr
- f
->f_bufptr
;
362 s
= (PyBytesObject
*)
363 PyBytes_FromStringAndSize(NULL
, skip
+len
);
366 memcpy(PyBytes_AS_STRING(s
)+skip
, f
->f_bufptr
, len
);
367 f
->f_bufptr
= bufptr
;
368 if (bufptr
== f
->f_bufend
)
369 Util_DropReadAhead(f
);
371 bufptr
= f
->f_bufptr
;
373 f
->f_buf
= NULL
; /* Force new readahead buffer */
374 s
= Util_ReadAheadGetLineSkip(f
, skip
+len
,
375 bufsize
+ (bufsize
>>2));
380 memcpy(PyBytes_AS_STRING(s
)+skip
, bufptr
, len
);
386 /* ===================================================================== */
387 /* Methods of BZ2File. */
389 PyDoc_STRVAR(BZ2File_read__doc__
,
390 "read([size]) -> string\n\
392 Read at most size uncompressed bytes, returned as a string. If the size\n\
393 argument is negative or omitted, read until EOF is reached.\n\
396 /* This is a hacked version of Python's fileobject.c:file_read(). */
398 BZ2File_read(BZ2FileObject
*self
, PyObject
*args
)
400 long bytesrequested
= -1;
401 size_t bytesread
, buffersize
, chunksize
;
403 PyObject
*ret
= NULL
;
405 if (!PyArg_ParseTuple(args
, "|l:read", &bytesrequested
))
409 switch (self
->mode
) {
413 ret
= PyBytes_FromStringAndSize("", 0);
416 PyErr_SetString(PyExc_ValueError
,
417 "I/O operation on closed file");
420 PyErr_SetString(PyExc_IOError
,
421 "file is not ready for reading");
425 if (bytesrequested
< 0)
426 buffersize
= Util_NewBufferSize((size_t)0);
428 buffersize
= bytesrequested
;
429 if (buffersize
> INT_MAX
) {
430 PyErr_SetString(PyExc_OverflowError
,
431 "requested number of bytes is "
432 "more than a Python string can hold");
435 ret
= PyBytes_FromStringAndSize((char *)NULL
, buffersize
);
436 if (ret
== NULL
|| buffersize
== 0)
441 Py_BEGIN_ALLOW_THREADS
442 chunksize
= BZ2_bzRead(&bzerror
, self
->fp
,
444 buffersize
-bytesread
);
445 self
->pos
+= chunksize
;
447 bytesread
+= chunksize
;
448 if (bzerror
== BZ_STREAM_END
) {
449 self
->size
= self
->pos
;
450 self
->mode
= MODE_READ_EOF
;
452 } else if (bzerror
!= BZ_OK
) {
453 Util_CatchBZ2Error(bzerror
);
458 if (bytesrequested
< 0) {
459 buffersize
= Util_NewBufferSize(buffersize
);
460 if (_PyBytes_Resize(&ret
, buffersize
) < 0) {
468 if (bytesread
!= buffersize
) {
469 if (_PyBytes_Resize(&ret
, bytesread
) < 0) {
479 PyDoc_STRVAR(BZ2File_readline__doc__
,
480 "readline([size]) -> string\n\
482 Return the next line from the file, as a string, retaining newline.\n\
483 A non-negative size argument will limit the maximum number of bytes to\n\
484 return (an incomplete line may be returned then). Return an empty\n\
489 BZ2File_readline(BZ2FileObject
*self
, PyObject
*args
)
491 PyObject
*ret
= NULL
;
494 if (!PyArg_ParseTuple(args
, "|i:readline", &sizehint
))
498 switch (self
->mode
) {
502 ret
= PyBytes_FromStringAndSize("", 0);
505 PyErr_SetString(PyExc_ValueError
,
506 "I/O operation on closed file");
509 PyErr_SetString(PyExc_IOError
,
510 "file is not ready for reading");
515 ret
= PyBytes_FromStringAndSize("", 0);
517 ret
= Util_GetLine(self
, (sizehint
< 0) ? 0 : sizehint
);
524 PyDoc_STRVAR(BZ2File_readlines__doc__
,
525 "readlines([size]) -> list\n\
527 Call readline() repeatedly and return a list of lines read.\n\
528 The optional size argument, if given, is an approximate bound on the\n\
529 total number of bytes in the lines returned.\n\
532 /* This is a hacked version of Python's fileobject.c:file_readlines(). */
534 BZ2File_readlines(BZ2FileObject
*self
, PyObject
*args
)
537 PyObject
*list
= NULL
;
539 char small_buffer
[SMALLCHUNK
];
540 char *buffer
= small_buffer
;
541 size_t buffersize
= SMALLCHUNK
;
542 PyObject
*big_buffer
= NULL
;
545 size_t totalread
= 0;
551 if (!PyArg_ParseTuple(args
, "|l:readlines", &sizehint
))
555 switch (self
->mode
) {
559 list
= PyList_New(0);
562 PyErr_SetString(PyExc_ValueError
,
563 "I/O operation on closed file");
566 PyErr_SetString(PyExc_IOError
,
567 "file is not ready for reading");
571 if ((list
= PyList_New(0)) == NULL
)
575 Py_BEGIN_ALLOW_THREADS
576 nread
= BZ2_bzRead(&bzerror
, self
->fp
,
577 buffer
+nfilled
, buffersize
-nfilled
);
580 if (bzerror
== BZ_STREAM_END
) {
581 self
->size
= self
->pos
;
582 self
->mode
= MODE_READ_EOF
;
588 } else if (bzerror
!= BZ_OK
) {
589 Util_CatchBZ2Error(bzerror
);
596 p
= memchr(buffer
+nfilled
, '\n', nread
);
597 if (!shortread
&& p
== NULL
) {
598 /* Need a larger buffer to fit this line */
601 if (buffersize
> INT_MAX
) {
602 PyErr_SetString(PyExc_OverflowError
,
603 "line is longer than a Python string can hold");
606 if (big_buffer
== NULL
) {
607 /* Create the big buffer */
608 big_buffer
= PyBytes_FromStringAndSize(
610 if (big_buffer
== NULL
)
612 buffer
= PyBytes_AS_STRING(big_buffer
);
613 memcpy(buffer
, small_buffer
, nfilled
);
616 /* Grow the big buffer */
617 if (_PyBytes_Resize(&big_buffer
, buffersize
) < 0){
621 buffer
= PyBytes_AS_STRING(big_buffer
);
625 end
= buffer
+nfilled
+nread
;
628 /* Process complete lines */
630 line
= PyBytes_FromStringAndSize(q
, p
-q
);
633 err
= PyList_Append(list
, line
);
638 p
= memchr(q
, '\n', end
-q
);
640 /* Move the remaining incomplete line to the start */
642 memmove(buffer
, q
, nfilled
);
644 if (totalread
>= (size_t)sizehint
)
652 /* Partial last line */
653 line
= PyBytes_FromStringAndSize(buffer
, nfilled
);
657 /* Need to complete the last line */
658 PyObject
*rest
= Util_GetLine(self
, 0);
663 PyBytes_Concat(&line
, rest
);
668 err
= PyList_Append(list
, line
);
677 Py_DECREF(big_buffer
);
682 PyDoc_STRVAR(BZ2File_write__doc__
,
683 "write(data) -> None\n\
685 Write the 'data' string to file. Note that due to buffering, close() may\n\
686 be needed before the file on disk reflects the data written.\n\
689 /* This is a hacked version of Python's fileobject.c:file_write(). */
691 BZ2File_write(BZ2FileObject
*self
, PyObject
*args
)
693 PyObject
*ret
= NULL
;
699 if (!PyArg_ParseTuple(args
, "y*:write", &pbuf
))
705 switch (self
->mode
) {
710 PyErr_SetString(PyExc_ValueError
,
711 "I/O operation on closed file");
715 PyErr_SetString(PyExc_IOError
,
716 "file is not ready for writing");
720 Py_BEGIN_ALLOW_THREADS
721 BZ2_bzWrite (&bzerror
, self
->fp
, buf
, len
);
725 if (bzerror
!= BZ_OK
) {
726 Util_CatchBZ2Error(bzerror
);
734 PyBuffer_Release(&pbuf
);
739 PyDoc_STRVAR(BZ2File_writelines__doc__
,
740 "writelines(sequence_of_strings) -> None\n\
742 Write the sequence of strings to the file. Note that newlines are not\n\
743 added. The sequence can be any iterable object producing strings. This is\n\
744 equivalent to calling write() for each string.\n\
747 /* This is a hacked version of Python's fileobject.c:file_writelines(). */
749 BZ2File_writelines(BZ2FileObject
*self
, PyObject
*seq
)
751 #define CHUNKSIZE 1000
752 PyObject
*list
= NULL
;
753 PyObject
*iter
= NULL
;
754 PyObject
*ret
= NULL
;
756 int i
, j
, index
, len
, islist
;
760 switch (self
->mode
) {
765 PyErr_SetString(PyExc_ValueError
,
766 "I/O operation on closed file");
770 PyErr_SetString(PyExc_IOError
,
771 "file is not ready for writing");
775 islist
= PyList_Check(seq
);
777 iter
= PyObject_GetIter(seq
);
779 PyErr_SetString(PyExc_TypeError
,
780 "writelines() requires an iterable argument");
783 list
= PyList_New(CHUNKSIZE
);
788 /* Strategy: slurp CHUNKSIZE lines into a private list,
789 checking that they are all strings, then write that list
790 without holding the interpreter lock, then come back for more. */
791 for (index
= 0; ; index
+= CHUNKSIZE
) {
794 list
= PyList_GetSlice(seq
, index
, index
+CHUNKSIZE
);
797 j
= PyList_GET_SIZE(list
);
800 for (j
= 0; j
< CHUNKSIZE
; j
++) {
801 line
= PyIter_Next(iter
);
803 if (PyErr_Occurred())
807 PyList_SetItem(list
, j
, line
);
813 /* Check that all entries are indeed byte strings. If not,
814 apply the same rules as for file.write() and
815 convert the rets to strings. This is slow, but
816 seems to be the only way since all conversion APIs
817 could potentially execute Python code. */
818 for (i
= 0; i
< j
; i
++) {
819 PyObject
*v
= PyList_GET_ITEM(list
, i
);
820 if (!PyBytes_Check(v
)) {
823 if (PyObject_AsCharBuffer(v
, &buffer
, &len
)) {
824 PyErr_SetString(PyExc_TypeError
,
831 line
= PyBytes_FromStringAndSize(buffer
,
836 PyList_SET_ITEM(list
, i
, line
);
840 /* Since we are releasing the global lock, the
841 following code may *not* execute Python code. */
842 Py_BEGIN_ALLOW_THREADS
843 for (i
= 0; i
< j
; i
++) {
844 line
= PyList_GET_ITEM(list
, i
);
845 len
= PyBytes_GET_SIZE(line
);
846 BZ2_bzWrite (&bzerror
, self
->fp
,
847 PyBytes_AS_STRING(line
), len
);
848 if (bzerror
!= BZ_OK
) {
850 Util_CatchBZ2Error(bzerror
);
871 PyDoc_STRVAR(BZ2File_seek__doc__
,
872 "seek(offset [, whence]) -> None\n\
874 Move to new file position. Argument offset is a byte count. Optional\n\
875 argument whence defaults to 0 (offset from start of file, offset\n\
876 should be >= 0); other values are 1 (move relative to current position,\n\
877 positive or negative), and 2 (move relative to end of file, usually\n\
878 negative, although many platforms allow seeking beyond the end of a file).\n\
880 Note that seeking of bz2 files is emulated, and depending on the parameters\n\
881 the operation may be extremely slow.\n\
885 BZ2File_seek(BZ2FileObject
*self
, PyObject
*args
)
890 char small_buffer
[SMALLCHUNK
];
891 char *buffer
= small_buffer
;
892 size_t buffersize
= SMALLCHUNK
;
893 Py_off_t bytesread
= 0;
897 PyObject
*ret
= NULL
;
899 if (!PyArg_ParseTuple(args
, "O|i:seek", &offobj
, &where
))
901 #if !defined(HAVE_LARGEFILE_SUPPORT)
902 offset
= PyLong_AsLong(offobj
);
904 offset
= PyLong_Check(offobj
) ?
905 PyLong_AsLongLong(offobj
) : PyLong_AsLong(offobj
);
907 if (PyErr_Occurred())
911 Util_DropReadAhead(self
);
912 switch (self
->mode
) {
918 PyErr_SetString(PyExc_ValueError
,
919 "I/O operation on closed file");
923 PyErr_SetString(PyExc_IOError
,
924 "seek works only while reading");
929 if (self
->size
== -1) {
930 assert(self
->mode
!= MODE_READ_EOF
);
932 Py_BEGIN_ALLOW_THREADS
933 chunksize
= BZ2_bzRead(&bzerror
, self
->fp
,
935 self
->pos
+= chunksize
;
938 bytesread
+= chunksize
;
939 if (bzerror
== BZ_STREAM_END
) {
941 } else if (bzerror
!= BZ_OK
) {
942 Util_CatchBZ2Error(bzerror
);
946 self
->mode
= MODE_READ_EOF
;
947 self
->size
= self
->pos
;
950 offset
= self
->size
+ offset
;
951 } else if (where
== 1) {
952 offset
= self
->pos
+ offset
;
955 /* Before getting here, offset must be the absolute position the file
956 * pointer should be set to. */
958 if (offset
>= self
->pos
) {
959 /* we can move forward */
962 /* we cannot move back, so rewind the stream */
963 BZ2_bzReadClose(&bzerror
, self
->fp
);
964 if (bzerror
!= BZ_OK
) {
965 Util_CatchBZ2Error(bzerror
);
970 self
->fp
= BZ2_bzReadOpen(&bzerror
, self
->rawfp
,
972 if (bzerror
!= BZ_OK
) {
973 Util_CatchBZ2Error(bzerror
);
976 self
->mode
= MODE_READ
;
979 if (offset
<= 0 || self
->mode
== MODE_READ_EOF
)
982 /* Before getting here, offset must be set to the number of bytes
983 * to walk forward. */
985 if (offset
-bytesread
> buffersize
)
986 readsize
= buffersize
;
988 /* offset might be wider that readsize, but the result
989 * of the subtraction is bound by buffersize (see the
990 * condition above). buffersize is 8192. */
991 readsize
= (size_t)(offset
-bytesread
);
992 Py_BEGIN_ALLOW_THREADS
993 chunksize
= BZ2_bzRead(&bzerror
, self
->fp
, buffer
, readsize
);
994 self
->pos
+= chunksize
;
996 bytesread
+= chunksize
;
997 if (bzerror
== BZ_STREAM_END
) {
998 self
->size
= self
->pos
;
999 self
->mode
= MODE_READ_EOF
;
1001 } else if (bzerror
!= BZ_OK
) {
1002 Util_CatchBZ2Error(bzerror
);
1005 if (bytesread
== offset
)
1018 PyDoc_STRVAR(BZ2File_tell__doc__
,
1021 Return the current file position, an integer (may be a long integer).\n\
1025 BZ2File_tell(BZ2FileObject
*self
, PyObject
*args
)
1027 PyObject
*ret
= NULL
;
1029 if (self
->mode
== MODE_CLOSED
) {
1030 PyErr_SetString(PyExc_ValueError
,
1031 "I/O operation on closed file");
1035 #if !defined(HAVE_LARGEFILE_SUPPORT)
1036 ret
= PyLong_FromLong(self
->pos
);
1038 ret
= PyLong_FromLongLong(self
->pos
);
1045 PyDoc_STRVAR(BZ2File_close__doc__
,
1046 "close() -> None or (perhaps) an integer\n\
1048 Close the file. Sets data attribute .closed to true. A closed file\n\
1049 cannot be used for further I/O operations. close() may be called more\n\
1050 than once without error.\n\
1054 BZ2File_close(BZ2FileObject
*self
)
1056 PyObject
*ret
= NULL
;
1057 int bzerror
= BZ_OK
;
1059 if (self
->mode
== MODE_CLOSED
) {
1064 switch (self
->mode
) {
1067 BZ2_bzReadClose(&bzerror
, self
->fp
);
1070 BZ2_bzWriteClose(&bzerror
, self
->fp
,
1074 self
->mode
= MODE_CLOSED
;
1075 fclose(self
->rawfp
);
1077 if (bzerror
== BZ_OK
) {
1082 Util_CatchBZ2Error(bzerror
);
1089 PyDoc_STRVAR(BZ2File_enter_doc
,
1090 "__enter__() -> self.");
1093 BZ2File_enter(BZ2FileObject
*self
)
1095 if (self
->mode
== MODE_CLOSED
) {
1096 PyErr_SetString(PyExc_ValueError
,
1097 "I/O operation on closed file");
1101 return (PyObject
*) self
;
1104 PyDoc_STRVAR(BZ2File_exit_doc
,
1105 "__exit__(*excinfo) -> None. Closes the file.");
1108 BZ2File_exit(BZ2FileObject
*self
, PyObject
*args
)
1110 PyObject
*ret
= PyObject_CallMethod((PyObject
*) self
, "close", NULL
);
1112 /* If error occurred, pass through */
1119 static PyObject
*BZ2File_getiter(BZ2FileObject
*self
);
1121 static PyMethodDef BZ2File_methods
[] = {
1122 {"read", (PyCFunction
)BZ2File_read
, METH_VARARGS
, BZ2File_read__doc__
},
1123 {"readline", (PyCFunction
)BZ2File_readline
, METH_VARARGS
, BZ2File_readline__doc__
},
1124 {"readlines", (PyCFunction
)BZ2File_readlines
, METH_VARARGS
, BZ2File_readlines__doc__
},
1125 {"write", (PyCFunction
)BZ2File_write
, METH_VARARGS
, BZ2File_write__doc__
},
1126 {"writelines", (PyCFunction
)BZ2File_writelines
, METH_O
, BZ2File_writelines__doc__
},
1127 {"seek", (PyCFunction
)BZ2File_seek
, METH_VARARGS
, BZ2File_seek__doc__
},
1128 {"tell", (PyCFunction
)BZ2File_tell
, METH_NOARGS
, BZ2File_tell__doc__
},
1129 {"close", (PyCFunction
)BZ2File_close
, METH_NOARGS
, BZ2File_close__doc__
},
1130 {"__enter__", (PyCFunction
)BZ2File_enter
, METH_NOARGS
, BZ2File_enter_doc
},
1131 {"__exit__", (PyCFunction
)BZ2File_exit
, METH_VARARGS
, BZ2File_exit_doc
},
1132 {NULL
, NULL
} /* sentinel */
1136 /* ===================================================================== */
1137 /* Getters and setters of BZ2File. */
1140 BZ2File_get_closed(BZ2FileObject
*self
, void *closure
)
1142 return PyLong_FromLong(self
->mode
== MODE_CLOSED
);
1145 static PyGetSetDef BZ2File_getset
[] = {
1146 {"closed", (getter
)BZ2File_get_closed
, NULL
,
1147 "True if the file is closed"},
1148 {NULL
} /* Sentinel */
1152 /* ===================================================================== */
1153 /* Slot definitions for BZ2File_Type. */
1156 BZ2File_init(BZ2FileObject
*self
, PyObject
*args
, PyObject
*kwargs
)
1158 static char *kwlist
[] = {"filename", "mode", "buffering",
1159 "compresslevel", 0};
1163 int compresslevel
= 9;
1169 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "s|sii:BZ2File",
1170 kwlist
, &name
, &mode
, &buffering
,
1174 if (compresslevel
< 1 || compresslevel
> 9) {
1175 PyErr_SetString(PyExc_ValueError
,
1176 "compresslevel must be between 1 and 9");
1198 PyErr_Format(PyExc_ValueError
,
1199 "invalid mode char %c", *mode
);
1207 if (mode_char
== 0) {
1211 mode
= (mode_char
== 'r') ? "rb" : "wb";
1213 self
->rawfp
= fopen(name
, mode
);
1214 if (self
->rawfp
== NULL
) {
1215 PyErr_SetFromErrno(PyExc_IOError
);
1218 /* XXX Ignore buffering */
1220 /* From now on, we have stuff to dealloc, so jump to error label
1221 * instead of returning */
1224 self
->lock
= PyThread_allocate_lock();
1226 PyErr_SetString(PyExc_MemoryError
, "unable to allocate lock");
1231 if (mode_char
== 'r')
1232 self
->fp
= BZ2_bzReadOpen(&bzerror
, self
->rawfp
,
1235 self
->fp
= BZ2_bzWriteOpen(&bzerror
, self
->rawfp
,
1236 compresslevel
, 0, 0);
1238 if (bzerror
!= BZ_OK
) {
1239 Util_CatchBZ2Error(bzerror
);
1243 self
->mode
= (mode_char
== 'r') ? MODE_READ
: MODE_WRITE
;
1248 fclose(self
->rawfp
);
1252 PyThread_free_lock(self
->lock
);
1260 BZ2File_dealloc(BZ2FileObject
*self
)
1265 PyThread_free_lock(self
->lock
);
1267 switch (self
->mode
) {
1270 BZ2_bzReadClose(&bzerror
, self
->fp
);
1273 BZ2_bzWriteClose(&bzerror
, self
->fp
,
1277 Util_DropReadAhead(self
);
1278 if (self
->rawfp
!= NULL
)
1279 fclose(self
->rawfp
);
1280 Py_TYPE(self
)->tp_free((PyObject
*)self
);
1283 /* This is a hacked version of Python's fileobject.c:file_getiter(). */
1285 BZ2File_getiter(BZ2FileObject
*self
)
1287 if (self
->mode
== MODE_CLOSED
) {
1288 PyErr_SetString(PyExc_ValueError
,
1289 "I/O operation on closed file");
1292 Py_INCREF((PyObject
*)self
);
1293 return (PyObject
*)self
;
1296 /* This is a hacked version of Python's fileobject.c:file_iternext(). */
1297 #define READAHEAD_BUFSIZE 8192
1299 BZ2File_iternext(BZ2FileObject
*self
)
1303 if (self
->mode
== MODE_CLOSED
) {
1305 PyErr_SetString(PyExc_ValueError
,
1306 "I/O operation on closed file");
1309 ret
= Util_ReadAheadGetLineSkip(self
, 0, READAHEAD_BUFSIZE
);
1311 if (ret
== NULL
|| PyBytes_GET_SIZE(ret
) == 0) {
1315 return (PyObject
*)ret
;
1318 /* ===================================================================== */
1319 /* BZ2File_Type definition. */
1321 PyDoc_VAR(BZ2File__doc__
) =
1323 "BZ2File(name [, mode='r', buffering=0, compresslevel=9]) -> file object\n\
1325 Open a bz2 file. The mode can be 'r' or 'w', for reading (default) or\n\
1326 writing. When opened for writing, the file will be created if it doesn't\n\
1327 exist, and truncated otherwise. If the buffering argument is given, 0 means\n\
1328 unbuffered, and larger numbers specify the buffer size. If compresslevel\n\
1329 is given, must be a number between 1 and 9.\n\
1330 Data read is always returned in bytes; data written ought to be bytes.\n\
1333 static PyTypeObject BZ2File_Type
= {
1334 PyVarObject_HEAD_INIT(NULL
, 0)
1335 "bz2.BZ2File", /*tp_name*/
1336 sizeof(BZ2FileObject
), /*tp_basicsize*/
1338 (destructor
)BZ2File_dealloc
, /*tp_dealloc*/
1345 0, /*tp_as_sequence*/
1346 0, /*tp_as_mapping*/
1350 PyObject_GenericGetAttr
,/*tp_getattro*/
1351 PyObject_GenericSetAttr
,/*tp_setattro*/
1353 Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
, /*tp_flags*/
1354 BZ2File__doc__
, /*tp_doc*/
1357 0, /*tp_richcompare*/
1358 0, /*tp_weaklistoffset*/
1359 (getiterfunc
)BZ2File_getiter
, /*tp_iter*/
1360 (iternextfunc
)BZ2File_iternext
, /*tp_iternext*/
1361 BZ2File_methods
, /*tp_methods*/
1363 BZ2File_getset
, /*tp_getset*/
1368 0, /*tp_dictoffset*/
1369 (initproc
)BZ2File_init
, /*tp_init*/
1370 PyType_GenericAlloc
, /*tp_alloc*/
1371 PyType_GenericNew
, /*tp_new*/
1372 PyObject_Free
, /*tp_free*/
1377 /* ===================================================================== */
1378 /* Methods of BZ2Comp. */
1380 PyDoc_STRVAR(BZ2Comp_compress__doc__
,
1381 "compress(data) -> string\n\
1383 Provide more data to the compressor object. It will return chunks of\n\
1384 compressed data whenever possible. When you've finished providing data\n\
1385 to compress, call the flush() method to finish the compression process,\n\
1386 and return what is left in the internal buffers.\n\
1390 BZ2Comp_compress(BZ2CompObject
*self
, PyObject
*args
)
1395 int bufsize
= SMALLCHUNK
;
1396 PY_LONG_LONG totalout
;
1397 PyObject
*ret
= NULL
;
1398 bz_stream
*bzs
= &self
->bzs
;
1401 if (!PyArg_ParseTuple(args
, "y*:compress", &pdata
))
1404 datasize
= pdata
.len
;
1406 if (datasize
== 0) {
1407 PyBuffer_Release(&pdata
);
1408 return PyBytes_FromStringAndSize("", 0);
1412 if (!self
->running
) {
1413 PyErr_SetString(PyExc_ValueError
,
1414 "this object was already flushed");
1418 ret
= PyBytes_FromStringAndSize(NULL
, bufsize
);
1422 bzs
->next_in
= data
;
1423 bzs
->avail_in
= datasize
;
1424 bzs
->next_out
= BUF(ret
);
1425 bzs
->avail_out
= bufsize
;
1427 totalout
= BZS_TOTAL_OUT(bzs
);
1430 Py_BEGIN_ALLOW_THREADS
1431 bzerror
= BZ2_bzCompress(bzs
, BZ_RUN
);
1432 Py_END_ALLOW_THREADS
1433 if (bzerror
!= BZ_RUN_OK
) {
1434 Util_CatchBZ2Error(bzerror
);
1437 if (bzs
->avail_in
== 0)
1438 break; /* no more input data */
1439 if (bzs
->avail_out
== 0) {
1440 bufsize
= Util_NewBufferSize(bufsize
);
1441 if (_PyBytes_Resize(&ret
, bufsize
) < 0) {
1442 BZ2_bzCompressEnd(bzs
);
1445 bzs
->next_out
= BUF(ret
) + (BZS_TOTAL_OUT(bzs
)
1447 bzs
->avail_out
= bufsize
- (bzs
->next_out
- BUF(ret
));
1451 if (_PyBytes_Resize(&ret
,
1452 (Py_ssize_t
)(BZS_TOTAL_OUT(bzs
) - totalout
)) < 0)
1456 PyBuffer_Release(&pdata
);
1461 PyBuffer_Release(&pdata
);
1466 PyDoc_STRVAR(BZ2Comp_flush__doc__
,
1467 "flush() -> string\n\
1469 Finish the compression process and return what is left in internal buffers.\n\
1470 You must not use the compressor object after calling this method.\n\
1474 BZ2Comp_flush(BZ2CompObject
*self
)
1476 int bufsize
= SMALLCHUNK
;
1477 PyObject
*ret
= NULL
;
1478 bz_stream
*bzs
= &self
->bzs
;
1479 PY_LONG_LONG totalout
;
1483 if (!self
->running
) {
1484 PyErr_SetString(PyExc_ValueError
, "object was already "
1490 ret
= PyBytes_FromStringAndSize(NULL
, bufsize
);
1494 bzs
->next_out
= BUF(ret
);
1495 bzs
->avail_out
= bufsize
;
1497 totalout
= BZS_TOTAL_OUT(bzs
);
1500 Py_BEGIN_ALLOW_THREADS
1501 bzerror
= BZ2_bzCompress(bzs
, BZ_FINISH
);
1502 Py_END_ALLOW_THREADS
1503 if (bzerror
== BZ_STREAM_END
) {
1505 } else if (bzerror
!= BZ_FINISH_OK
) {
1506 Util_CatchBZ2Error(bzerror
);
1509 if (bzs
->avail_out
== 0) {
1510 bufsize
= Util_NewBufferSize(bufsize
);
1511 if (_PyBytes_Resize(&ret
, bufsize
) < 0)
1513 bzs
->next_out
= BUF(ret
);
1514 bzs
->next_out
= BUF(ret
) + (BZS_TOTAL_OUT(bzs
)
1516 bzs
->avail_out
= bufsize
- (bzs
->next_out
- BUF(ret
));
1520 if (bzs
->avail_out
!= 0) {
1521 if (_PyBytes_Resize(&ret
,
1522 (Py_ssize_t
)(BZS_TOTAL_OUT(bzs
) - totalout
)) < 0)
1535 static PyMethodDef BZ2Comp_methods
[] = {
1536 {"compress", (PyCFunction
)BZ2Comp_compress
, METH_VARARGS
,
1537 BZ2Comp_compress__doc__
},
1538 {"flush", (PyCFunction
)BZ2Comp_flush
, METH_NOARGS
,
1539 BZ2Comp_flush__doc__
},
1540 {NULL
, NULL
} /* sentinel */
1544 /* ===================================================================== */
1545 /* Slot definitions for BZ2Comp_Type. */
1548 BZ2Comp_init(BZ2CompObject
*self
, PyObject
*args
, PyObject
*kwargs
)
1550 int compresslevel
= 9;
1552 static char *kwlist
[] = {"compresslevel", 0};
1554 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|i:BZ2Compressor",
1555 kwlist
, &compresslevel
))
1558 if (compresslevel
< 1 || compresslevel
> 9) {
1559 PyErr_SetString(PyExc_ValueError
,
1560 "compresslevel must be between 1 and 9");
1565 self
->lock
= PyThread_allocate_lock();
1567 PyErr_SetString(PyExc_MemoryError
, "unable to allocate lock");
1572 memset(&self
->bzs
, 0, sizeof(bz_stream
));
1573 bzerror
= BZ2_bzCompressInit(&self
->bzs
, compresslevel
, 0, 0);
1574 if (bzerror
!= BZ_OK
) {
1575 Util_CatchBZ2Error(bzerror
);
1585 PyThread_free_lock(self
->lock
);
1593 BZ2Comp_dealloc(BZ2CompObject
*self
)
1597 PyThread_free_lock(self
->lock
);
1599 BZ2_bzCompressEnd(&self
->bzs
);
1600 Py_TYPE(self
)->tp_free((PyObject
*)self
);
1604 /* ===================================================================== */
1605 /* BZ2Comp_Type definition. */
1607 PyDoc_STRVAR(BZ2Comp__doc__
,
1608 "BZ2Compressor([compresslevel=9]) -> compressor object\n\
1610 Create a new compressor object. This object may be used to compress\n\
1611 data sequentially. If you want to compress data in one shot, use the\n\
1612 compress() function instead. The compresslevel parameter, if given,\n\
1613 must be a number between 1 and 9.\n\
1616 static PyTypeObject BZ2Comp_Type
= {
1617 PyVarObject_HEAD_INIT(NULL
, 0)
1618 "bz2.BZ2Compressor", /*tp_name*/
1619 sizeof(BZ2CompObject
), /*tp_basicsize*/
1621 (destructor
)BZ2Comp_dealloc
, /*tp_dealloc*/
1628 0, /*tp_as_sequence*/
1629 0, /*tp_as_mapping*/
1633 PyObject_GenericGetAttr
,/*tp_getattro*/
1634 PyObject_GenericSetAttr
,/*tp_setattro*/
1636 Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
, /*tp_flags*/
1637 BZ2Comp__doc__
, /*tp_doc*/
1640 0, /*tp_richcompare*/
1641 0, /*tp_weaklistoffset*/
1644 BZ2Comp_methods
, /*tp_methods*/
1651 0, /*tp_dictoffset*/
1652 (initproc
)BZ2Comp_init
, /*tp_init*/
1653 PyType_GenericAlloc
, /*tp_alloc*/
1654 PyType_GenericNew
, /*tp_new*/
1655 PyObject_Free
, /*tp_free*/
1660 /* ===================================================================== */
1661 /* Members of BZ2Decomp. */
1664 #define OFF(x) offsetof(BZ2DecompObject, x)
1666 static PyMemberDef BZ2Decomp_members
[] = {
1667 {"unused_data", T_OBJECT
, OFF(unused_data
), READONLY
},
1668 {NULL
} /* Sentinel */
1672 /* ===================================================================== */
1673 /* Methods of BZ2Decomp. */
1675 PyDoc_STRVAR(BZ2Decomp_decompress__doc__
,
1676 "decompress(data) -> string\n\
1678 Provide more data to the decompressor object. It will return chunks\n\
1679 of decompressed data whenever possible. If you try to decompress data\n\
1680 after the end of stream is found, EOFError will be raised. If any data\n\
1681 was found after the end of stream, it'll be ignored and saved in\n\
1682 unused_data attribute.\n\
1686 BZ2Decomp_decompress(BZ2DecompObject
*self
, PyObject
*args
)
1691 int bufsize
= SMALLCHUNK
;
1692 PY_LONG_LONG totalout
;
1693 PyObject
*ret
= NULL
;
1694 bz_stream
*bzs
= &self
->bzs
;
1697 if (!PyArg_ParseTuple(args
, "y*:decompress", &pdata
))
1700 datasize
= pdata
.len
;
1703 if (!self
->running
) {
1704 PyErr_SetString(PyExc_EOFError
, "end of stream was "
1709 ret
= PyBytes_FromStringAndSize(NULL
, bufsize
);
1713 bzs
->next_in
= data
;
1714 bzs
->avail_in
= datasize
;
1715 bzs
->next_out
= BUF(ret
);
1716 bzs
->avail_out
= bufsize
;
1718 totalout
= BZS_TOTAL_OUT(bzs
);
1721 Py_BEGIN_ALLOW_THREADS
1722 bzerror
= BZ2_bzDecompress(bzs
);
1723 Py_END_ALLOW_THREADS
1724 if (bzerror
== BZ_STREAM_END
) {
1725 if (bzs
->avail_in
!= 0) {
1726 Py_DECREF(self
->unused_data
);
1728 PyBytes_FromStringAndSize(bzs
->next_in
,
1734 if (bzerror
!= BZ_OK
) {
1735 Util_CatchBZ2Error(bzerror
);
1738 if (bzs
->avail_in
== 0)
1739 break; /* no more input data */
1740 if (bzs
->avail_out
== 0) {
1741 bufsize
= Util_NewBufferSize(bufsize
);
1742 if (_PyBytes_Resize(&ret
, bufsize
) < 0) {
1743 BZ2_bzDecompressEnd(bzs
);
1746 bzs
->next_out
= BUF(ret
);
1747 bzs
->next_out
= BUF(ret
) + (BZS_TOTAL_OUT(bzs
)
1749 bzs
->avail_out
= bufsize
- (bzs
->next_out
- BUF(ret
));
1753 if (bzs
->avail_out
!= 0) {
1754 if (_PyBytes_Resize(&ret
,
1755 (Py_ssize_t
)(BZS_TOTAL_OUT(bzs
) - totalout
)) < 0)
1760 PyBuffer_Release(&pdata
);
1765 PyBuffer_Release(&pdata
);
1770 static PyMethodDef BZ2Decomp_methods
[] = {
1771 {"decompress", (PyCFunction
)BZ2Decomp_decompress
, METH_VARARGS
, BZ2Decomp_decompress__doc__
},
1772 {NULL
, NULL
} /* sentinel */
1776 /* ===================================================================== */
1777 /* Slot definitions for BZ2Decomp_Type. */
1780 BZ2Decomp_init(BZ2DecompObject
*self
, PyObject
*args
, PyObject
*kwargs
)
1784 if (!PyArg_ParseTuple(args
, ":BZ2Decompressor"))
1788 self
->lock
= PyThread_allocate_lock();
1790 PyErr_SetString(PyExc_MemoryError
, "unable to allocate lock");
1795 self
->unused_data
= PyBytes_FromStringAndSize("", 0);
1796 if (!self
->unused_data
)
1799 memset(&self
->bzs
, 0, sizeof(bz_stream
));
1800 bzerror
= BZ2_bzDecompressInit(&self
->bzs
, 0, 0);
1801 if (bzerror
!= BZ_OK
) {
1802 Util_CatchBZ2Error(bzerror
);
1813 PyThread_free_lock(self
->lock
);
1817 Py_CLEAR(self
->unused_data
);
1822 BZ2Decomp_dealloc(BZ2DecompObject
*self
)
1826 PyThread_free_lock(self
->lock
);
1828 Py_XDECREF(self
->unused_data
);
1829 BZ2_bzDecompressEnd(&self
->bzs
);
1830 Py_TYPE(self
)->tp_free((PyObject
*)self
);
1834 /* ===================================================================== */
1835 /* BZ2Decomp_Type definition. */
1837 PyDoc_STRVAR(BZ2Decomp__doc__
,
1838 "BZ2Decompressor() -> decompressor object\n\
1840 Create a new decompressor object. This object may be used to decompress\n\
1841 data sequentially. If you want to decompress data in one shot, use the\n\
1842 decompress() function instead.\n\
1845 static PyTypeObject BZ2Decomp_Type
= {
1846 PyVarObject_HEAD_INIT(NULL
, 0)
1847 "bz2.BZ2Decompressor", /*tp_name*/
1848 sizeof(BZ2DecompObject
), /*tp_basicsize*/
1850 (destructor
)BZ2Decomp_dealloc
, /*tp_dealloc*/
1857 0, /*tp_as_sequence*/
1858 0, /*tp_as_mapping*/
1862 PyObject_GenericGetAttr
,/*tp_getattro*/
1863 PyObject_GenericSetAttr
,/*tp_setattro*/
1865 Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
, /*tp_flags*/
1866 BZ2Decomp__doc__
, /*tp_doc*/
1869 0, /*tp_richcompare*/
1870 0, /*tp_weaklistoffset*/
1873 BZ2Decomp_methods
, /*tp_methods*/
1874 BZ2Decomp_members
, /*tp_members*/
1880 0, /*tp_dictoffset*/
1881 (initproc
)BZ2Decomp_init
, /*tp_init*/
1882 PyType_GenericAlloc
, /*tp_alloc*/
1883 PyType_GenericNew
, /*tp_new*/
1884 PyObject_Free
, /*tp_free*/
1889 /* ===================================================================== */
1890 /* Module functions. */
1892 PyDoc_STRVAR(bz2_compress__doc__
,
1893 "compress(data [, compresslevel=9]) -> string\n\
1895 Compress data in one shot. If you want to compress data sequentially,\n\
1896 use an instance of BZ2Compressor instead. The compresslevel parameter, if\n\
1897 given, must be a number between 1 and 9.\n\
1901 bz2_compress(PyObject
*self
, PyObject
*args
, PyObject
*kwargs
)
1903 int compresslevel
=9;
1908 PyObject
*ret
= NULL
;
1910 bz_stream
*bzs
= &_bzs
;
1912 static char *kwlist
[] = {"data", "compresslevel", 0};
1914 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "y*|i",
1919 datasize
= pdata
.len
;
1921 if (compresslevel
< 1 || compresslevel
> 9) {
1922 PyErr_SetString(PyExc_ValueError
,
1923 "compresslevel must be between 1 and 9");
1924 PyBuffer_Release(&pdata
);
1928 /* Conforming to bz2 manual, this is large enough to fit compressed
1929 * data in one shot. We will check it later anyway. */
1930 bufsize
= datasize
+ (datasize
/100+1) + 600;
1932 ret
= PyBytes_FromStringAndSize(NULL
, bufsize
);
1934 PyBuffer_Release(&pdata
);
1938 memset(bzs
, 0, sizeof(bz_stream
));
1940 bzs
->next_in
= data
;
1941 bzs
->avail_in
= datasize
;
1942 bzs
->next_out
= BUF(ret
);
1943 bzs
->avail_out
= bufsize
;
1945 bzerror
= BZ2_bzCompressInit(bzs
, compresslevel
, 0, 0);
1946 if (bzerror
!= BZ_OK
) {
1947 Util_CatchBZ2Error(bzerror
);
1948 PyBuffer_Release(&pdata
);
1954 Py_BEGIN_ALLOW_THREADS
1955 bzerror
= BZ2_bzCompress(bzs
, BZ_FINISH
);
1956 Py_END_ALLOW_THREADS
1957 if (bzerror
== BZ_STREAM_END
) {
1959 } else if (bzerror
!= BZ_FINISH_OK
) {
1960 BZ2_bzCompressEnd(bzs
);
1961 Util_CatchBZ2Error(bzerror
);
1962 PyBuffer_Release(&pdata
);
1966 if (bzs
->avail_out
== 0) {
1967 bufsize
= Util_NewBufferSize(bufsize
);
1968 if (_PyBytes_Resize(&ret
, bufsize
) < 0) {
1969 BZ2_bzCompressEnd(bzs
);
1970 PyBuffer_Release(&pdata
);
1973 bzs
->next_out
= BUF(ret
) + BZS_TOTAL_OUT(bzs
);
1974 bzs
->avail_out
= bufsize
- (bzs
->next_out
- BUF(ret
));
1978 if (bzs
->avail_out
!= 0) {
1979 if (_PyBytes_Resize(&ret
, (Py_ssize_t
)BZS_TOTAL_OUT(bzs
)) < 0) {
1983 BZ2_bzCompressEnd(bzs
);
1985 PyBuffer_Release(&pdata
);
1989 PyDoc_STRVAR(bz2_decompress__doc__
,
1990 "decompress(data) -> decompressed data\n\
1992 Decompress data in one shot. If you want to decompress data sequentially,\n\
1993 use an instance of BZ2Decompressor instead.\n\
1997 bz2_decompress(PyObject
*self
, PyObject
*args
)
2002 int bufsize
= SMALLCHUNK
;
2005 bz_stream
*bzs
= &_bzs
;
2008 if (!PyArg_ParseTuple(args
, "y*:decompress", &pdata
))
2011 datasize
= pdata
.len
;
2013 if (datasize
== 0) {
2014 PyBuffer_Release(&pdata
);
2015 return PyBytes_FromStringAndSize("", 0);
2018 ret
= PyBytes_FromStringAndSize(NULL
, bufsize
);
2020 PyBuffer_Release(&pdata
);
2024 memset(bzs
, 0, sizeof(bz_stream
));
2026 bzs
->next_in
= data
;
2027 bzs
->avail_in
= datasize
;
2028 bzs
->next_out
= BUF(ret
);
2029 bzs
->avail_out
= bufsize
;
2031 bzerror
= BZ2_bzDecompressInit(bzs
, 0, 0);
2032 if (bzerror
!= BZ_OK
) {
2033 Util_CatchBZ2Error(bzerror
);
2035 PyBuffer_Release(&pdata
);
2040 Py_BEGIN_ALLOW_THREADS
2041 bzerror
= BZ2_bzDecompress(bzs
);
2042 Py_END_ALLOW_THREADS
2043 if (bzerror
== BZ_STREAM_END
) {
2045 } else if (bzerror
!= BZ_OK
) {
2046 BZ2_bzDecompressEnd(bzs
);
2047 Util_CatchBZ2Error(bzerror
);
2048 PyBuffer_Release(&pdata
);
2052 if (bzs
->avail_in
== 0) {
2053 BZ2_bzDecompressEnd(bzs
);
2054 PyErr_SetString(PyExc_ValueError
,
2055 "couldn't find end of stream");
2056 PyBuffer_Release(&pdata
);
2060 if (bzs
->avail_out
== 0) {
2061 bufsize
= Util_NewBufferSize(bufsize
);
2062 if (_PyBytes_Resize(&ret
, bufsize
) < 0) {
2063 BZ2_bzDecompressEnd(bzs
);
2064 PyBuffer_Release(&pdata
);
2067 bzs
->next_out
= BUF(ret
) + BZS_TOTAL_OUT(bzs
);
2068 bzs
->avail_out
= bufsize
- (bzs
->next_out
- BUF(ret
));
2072 if (bzs
->avail_out
!= 0) {
2073 if (_PyBytes_Resize(&ret
, (Py_ssize_t
)BZS_TOTAL_OUT(bzs
)) < 0) {
2077 BZ2_bzDecompressEnd(bzs
);
2078 PyBuffer_Release(&pdata
);
2083 static PyMethodDef bz2_methods
[] = {
2084 {"compress", (PyCFunction
) bz2_compress
, METH_VARARGS
|METH_KEYWORDS
,
2085 bz2_compress__doc__
},
2086 {"decompress", (PyCFunction
) bz2_decompress
, METH_VARARGS
,
2087 bz2_decompress__doc__
},
2088 {NULL
, NULL
} /* sentinel */
2091 /* ===================================================================== */
2092 /* Initialization function. */
2094 PyDoc_STRVAR(bz2__doc__
,
2095 "The python bz2 module provides a comprehensive interface for\n\
2096 the bz2 compression library. It implements a complete file\n\
2097 interface, one shot (de)compression functions, and types for\n\
2098 sequential (de)compression.\n\
2102 static struct PyModuleDef bz2module
= {
2103 PyModuleDef_HEAD_INIT
,
2119 Py_TYPE(&BZ2File_Type
) = &PyType_Type
;
2120 Py_TYPE(&BZ2Comp_Type
) = &PyType_Type
;
2121 Py_TYPE(&BZ2Decomp_Type
) = &PyType_Type
;
2123 m
= PyModule_Create(&bz2module
);
2127 PyModule_AddObject(m
, "__author__", PyUnicode_FromString(__author__
));
2129 Py_INCREF(&BZ2File_Type
);
2130 PyModule_AddObject(m
, "BZ2File", (PyObject
*)&BZ2File_Type
);
2132 Py_INCREF(&BZ2Comp_Type
);
2133 PyModule_AddObject(m
, "BZ2Compressor", (PyObject
*)&BZ2Comp_Type
);
2135 Py_INCREF(&BZ2Decomp_Type
);
2136 PyModule_AddObject(m
, "BZ2Decompressor", (PyObject
*)&BZ2Decomp_Type
);