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 #define BUF(v) PyString_AS_STRING((PyStringObject *)v)
29 #define MODE_READ_EOF 2
32 #define BZ2FileObject_Check(v) ((v)->ob_type == &BZ2File_Type)
35 #define BZS_TOTAL_OUT(bzs) \
36 (((long)bzs->total_out_hi32 << 32) + bzs->total_out_lo32)
37 #elif SIZEOF_LONG_LONG >= 8
38 #define BZS_TOTAL_OUT(bzs) \
39 (((LONG_LONG)bzs->total_out_hi32 << 32) + bzs->total_out_lo32)
41 #define BZS_TOTAL_OUT(bzs) \
46 #define ACQUIRE_LOCK(obj) PyThread_acquire_lock(obj->lock, 1)
47 #define RELEASE_LOCK(obj) PyThread_release_lock(obj->lock)
49 #define ACQUIRE_LOCK(obj)
50 #define RELEASE_LOCK(obj)
53 #ifdef WITH_UNIVERSAL_NEWLINES
54 /* Bits in f_newlinetypes */
55 #define NEWLINE_UNKNOWN 0 /* No newline seen, yet */
56 #define NEWLINE_CR 1 /* \r newline seen */
57 #define NEWLINE_LF 2 /* \n newline seen */
58 #define NEWLINE_CRLF 4 /* \r\n newline seen */
61 /* ===================================================================== */
62 /* Structure definitions. */
71 PyThread_type_lock lock
;
80 PyThread_type_lock lock
;
88 PyObject
*unused_data
;
90 PyThread_type_lock lock
;
94 /* ===================================================================== */
95 /* Utility functions. */
98 Util_CatchBZ2Error(int bzerror
)
106 case BZ_CONFIG_ERROR
:
107 PyErr_SetString(PyExc_SystemError
,
108 "the bz2 library was not compiled "
114 PyErr_SetString(PyExc_ValueError
,
115 "the bz2 library has received wrong "
126 case BZ_DATA_ERROR_MAGIC
:
127 PyErr_SetString(PyExc_IOError
, "invalid data stream");
132 PyErr_SetString(PyExc_IOError
, "unknown IO error");
136 case BZ_UNEXPECTED_EOF
:
137 PyErr_SetString(PyExc_EOFError
,
138 "compressed file ended before the "
139 "logical end-of-stream was detected");
143 case BZ_SEQUENCE_ERROR
:
144 PyErr_SetString(PyExc_RuntimeError
,
145 "wrong sequence of bz2 library "
154 #define SMALLCHUNK 8192
156 #define SMALLCHUNK BUFSIZ
160 #define BIGCHUNK (512 * 32)
162 #define BIGCHUNK (512 * 1024)
165 /* This is a hacked version of Python's fileobject.c:new_buffersize(). */
167 Util_NewBufferSize(size_t currentsize
)
169 if (currentsize
> SMALLCHUNK
) {
170 /* Keep doubling until we reach BIGCHUNK;
171 then keep adding BIGCHUNK. */
172 if (currentsize
<= BIGCHUNK
)
173 return currentsize
+ currentsize
;
175 return currentsize
+ BIGCHUNK
;
177 return currentsize
+ SMALLCHUNK
;
180 /* This is a hacked version of Python's fileobject.c:get_line(). */
182 Util_GetLine(BZ2FileObject
*self
, int n
)
186 size_t total_v_size
; /* total # of slots in buffer */
187 size_t used_v_size
; /* # used slots in buffer */
188 size_t increment
; /* amount to increment the buffer */
191 #ifdef WITH_UNIVERSAL_NEWLINES
192 int newlinetypes
= ((PyFileObject
*)self
)->f_newlinetypes
;
193 int skipnextlf
= ((PyFileObject
*)self
)->f_skipnextlf
;
194 int univ_newline
= ((PyFileObject
*)self
)->f_univ_newline
;
197 total_v_size
= n
> 0 ? n
: 100;
198 v
= PyString_FromStringAndSize((char *)NULL
, total_v_size
);
203 end
= buf
+ total_v_size
;
206 Py_BEGIN_ALLOW_THREADS
207 #ifdef WITH_UNIVERSAL_NEWLINES
210 BZ2_bzRead(&bzerror
, self
->fp
, &c
, 1);
212 if (bzerror
!= BZ_OK
|| buf
== end
)
217 /* Seeing a \n here with
218 * skipnextlf true means we
221 newlinetypes
|= NEWLINE_CRLF
;
222 BZ2_bzRead(&bzerror
, self
->fp
,
224 if (bzerror
!= BZ_OK
)
227 newlinetypes
|= NEWLINE_CR
;
233 } else if ( c
== '\n')
234 newlinetypes
|= NEWLINE_LF
;
236 if (c
== '\n') break;
238 if (bzerror
== BZ_STREAM_END
&& skipnextlf
)
239 newlinetypes
|= NEWLINE_CR
;
240 } else /* If not universal newlines use the normal loop */
243 BZ2_bzRead(&bzerror
, self
->fp
, &c
, 1);
246 } while (bzerror
== BZ_OK
&& c
!= '\n' && buf
!= end
);
248 #ifdef WITH_UNIVERSAL_NEWLINES
249 ((PyFileObject
*)self
)->f_newlinetypes
= newlinetypes
;
250 ((PyFileObject
*)self
)->f_skipnextlf
= skipnextlf
;
252 if (bzerror
== BZ_STREAM_END
) {
253 self
->size
= self
->pos
;
254 self
->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 (_PyString_Resize(&v
, total_v_size
) < 0)
277 buf
= BUF(v
) + used_v_size
;
278 end
= BUF(v
) + total_v_size
;
281 used_v_size
= buf
- BUF(v
);
282 if (used_v_size
!= total_v_size
)
283 _PyString_Resize(&v
, used_v_size
);
287 #ifndef WITH_UNIVERSAL_NEWLINES
288 #define Util_UnivNewlineRead(a,b,c,d,e) BZ2_bzRead(a,b,c,d)
290 /* This is a hacked version of Python's
291 * fileobject.c:Py_UniversalNewlineFread(). */
293 Util_UnivNewlineRead(int *bzerror
, BZFILE
*stream
,
294 char* buf
, size_t n
, BZ2FileObject
*fobj
)
297 PyFileObject
*f
= (PyFileObject
*)fobj
;
298 int newlinetypes
, skipnextlf
;
301 assert(stream
!= NULL
);
303 if (!f
->f_univ_newline
)
304 return BZ2_bzRead(bzerror
, stream
, buf
, n
);
306 newlinetypes
= f
->f_newlinetypes
;
307 skipnextlf
= f
->f_skipnextlf
;
309 /* Invariant: n is the number of bytes remaining to be filled
317 nread
= BZ2_bzRead(bzerror
, stream
, dst
, n
);
319 n
-= nread
; /* assuming 1 byte out for each in; will adjust */
320 shortread
= n
!= 0; /* true iff EOF or error */
324 /* Save as LF and set flag to skip next LF. */
328 else if (skipnextlf
&& c
== '\n') {
329 /* Skip LF, and remember we saw CR LF. */
331 newlinetypes
|= NEWLINE_CRLF
;
335 /* Normal char to be stored in buffer. Also
336 * update the newlinetypes flag if either this
337 * is an LF or the previous char was a CR.
340 newlinetypes
|= NEWLINE_LF
;
342 newlinetypes
|= NEWLINE_CR
;
348 /* If this is EOF, update type flags. */
349 if (skipnextlf
&& *bzerror
== BZ_STREAM_END
)
350 newlinetypes
|= NEWLINE_CR
;
354 f
->f_newlinetypes
= newlinetypes
;
355 f
->f_skipnextlf
= skipnextlf
;
360 /* This is a hacked version of Python's fileobject.c:drop_readahead(). */
362 Util_DropReadAhead(BZ2FileObject
*self
)
364 PyFileObject
*f
= (PyFileObject
*)self
;
365 if (f
->f_buf
!= NULL
) {
366 PyMem_Free(f
->f_buf
);
371 /* This is a hacked version of Python's fileobject.c:readahead(). */
373 Util_ReadAhead(BZ2FileObject
*self
, int bufsize
)
377 PyFileObject
*f
= (PyFileObject
*)self
;
379 if (f
->f_buf
!= NULL
) {
380 if((f
->f_bufend
- f
->f_bufptr
) >= 1)
383 Util_DropReadAhead(self
);
385 if (self
->mode
== MODE_READ_EOF
) {
388 if ((f
->f_buf
= PyMem_Malloc(bufsize
)) == NULL
) {
391 Py_BEGIN_ALLOW_THREADS
392 chunksize
= Util_UnivNewlineRead(&bzerror
, self
->fp
, f
->f_buf
,
395 self
->pos
+= chunksize
;
396 if (bzerror
== BZ_STREAM_END
) {
397 self
->size
= self
->pos
;
398 self
->mode
= MODE_READ_EOF
;
399 } else if (bzerror
!= BZ_OK
) {
400 Util_CatchBZ2Error(bzerror
);
401 Util_DropReadAhead(self
);
404 f
->f_bufptr
= f
->f_buf
;
405 f
->f_bufend
= f
->f_buf
+ chunksize
;
409 /* This is a hacked version of Python's
410 * fileobject.c:readahead_get_line_skip(). */
411 static PyStringObject
*
412 Util_ReadAheadGetLineSkip(BZ2FileObject
*bf
, int skip
, int bufsize
)
414 PyFileObject
*f
= (PyFileObject
*)bf
;
420 if (f
->f_buf
== NULL
)
421 if (Util_ReadAhead(bf
, bufsize
) < 0)
424 len
= f
->f_bufend
- f
->f_bufptr
;
426 return (PyStringObject
*)
427 PyString_FromStringAndSize(NULL
, skip
);
428 bufptr
= memchr(f
->f_bufptr
, '\n', len
);
429 if (bufptr
!= NULL
) {
430 bufptr
++; /* Count the '\n' */
431 len
= bufptr
- f
->f_bufptr
;
432 s
= (PyStringObject
*)
433 PyString_FromStringAndSize(NULL
, skip
+len
);
436 memcpy(PyString_AS_STRING(s
)+skip
, f
->f_bufptr
, len
);
437 f
->f_bufptr
= bufptr
;
438 if (bufptr
== f
->f_bufend
)
439 Util_DropReadAhead(bf
);
441 bufptr
= f
->f_bufptr
;
443 f
->f_buf
= NULL
; /* Force new readahead buffer */
444 s
= Util_ReadAheadGetLineSkip(
445 bf
, skip
+len
, bufsize
+ (bufsize
>>2) );
450 memcpy(PyString_AS_STRING(s
)+skip
, bufptr
, len
);
456 /* ===================================================================== */
457 /* Methods of BZ2File. */
459 PyDoc_STRVAR(BZ2File_read__doc__
,
460 "read([size]) -> string\n\
462 Read at most size uncompressed bytes, returned as a string. If the size\n\
463 argument is negative or omitted, read until EOF is reached.\n\
466 /* This is a hacked version of Python's fileobject.c:file_read(). */
468 BZ2File_read(BZ2FileObject
*self
, PyObject
*args
)
470 long bytesrequested
= -1;
471 size_t bytesread
, buffersize
, chunksize
;
473 PyObject
*ret
= NULL
;
475 if (!PyArg_ParseTuple(args
, "|l:read", &bytesrequested
))
479 switch (self
->mode
) {
483 ret
= PyString_FromString("");
486 PyErr_SetString(PyExc_ValueError
,
487 "I/O operation on closed file");
490 PyErr_SetString(PyExc_IOError
,
491 "file is not ready for reading");
495 if (bytesrequested
< 0)
496 buffersize
= Util_NewBufferSize((size_t)0);
498 buffersize
= bytesrequested
;
499 if (buffersize
> INT_MAX
) {
500 PyErr_SetString(PyExc_OverflowError
,
501 "requested number of bytes is "
502 "more than a Python string can hold");
505 ret
= PyString_FromStringAndSize((char *)NULL
, buffersize
);
511 Py_BEGIN_ALLOW_THREADS
512 chunksize
= Util_UnivNewlineRead(&bzerror
, self
->fp
,
514 buffersize
-bytesread
,
516 self
->pos
+= chunksize
;
518 bytesread
+= chunksize
;
519 if (bzerror
== BZ_STREAM_END
) {
520 self
->size
= self
->pos
;
521 self
->mode
= MODE_READ_EOF
;
523 } else if (bzerror
!= BZ_OK
) {
524 Util_CatchBZ2Error(bzerror
);
529 if (bytesrequested
< 0) {
530 buffersize
= Util_NewBufferSize(buffersize
);
531 if (_PyString_Resize(&ret
, buffersize
) < 0)
537 if (bytesread
!= buffersize
)
538 _PyString_Resize(&ret
, bytesread
);
545 PyDoc_STRVAR(BZ2File_readline__doc__
,
546 "readline([size]) -> string\n\
548 Return the next line from the file, as a string, retaining newline.\n\
549 A non-negative size argument will limit the maximum number of bytes to\n\
550 return (an incomplete line may be returned then). Return an empty\n\
555 BZ2File_readline(BZ2FileObject
*self
, PyObject
*args
)
557 PyObject
*ret
= NULL
;
560 if (!PyArg_ParseTuple(args
, "|i:readline", &sizehint
))
564 switch (self
->mode
) {
568 ret
= PyString_FromString("");
571 PyErr_SetString(PyExc_ValueError
,
572 "I/O operation on closed file");
575 PyErr_SetString(PyExc_IOError
,
576 "file is not ready for reading");
581 ret
= PyString_FromString("");
583 ret
= Util_GetLine(self
, (sizehint
< 0) ? 0 : sizehint
);
590 PyDoc_STRVAR(BZ2File_readlines__doc__
,
591 "readlines([size]) -> list\n\
593 Call readline() repeatedly and return a list of lines read.\n\
594 The optional size argument, if given, is an approximate bound on the\n\
595 total number of bytes in the lines returned.\n\
598 /* This is a hacked version of Python's fileobject.c:file_readlines(). */
600 BZ2File_readlines(BZ2FileObject
*self
, PyObject
*args
)
603 PyObject
*list
= NULL
;
605 char small_buffer
[SMALLCHUNK
];
606 char *buffer
= small_buffer
;
607 size_t buffersize
= SMALLCHUNK
;
608 PyObject
*big_buffer
= NULL
;
611 size_t totalread
= 0;
617 if (!PyArg_ParseTuple(args
, "|l:readlines", &sizehint
))
621 switch (self
->mode
) {
625 list
= PyList_New(0);
628 PyErr_SetString(PyExc_ValueError
,
629 "I/O operation on closed file");
632 PyErr_SetString(PyExc_IOError
,
633 "file is not ready for reading");
637 if ((list
= PyList_New(0)) == NULL
)
641 Py_BEGIN_ALLOW_THREADS
642 nread
= Util_UnivNewlineRead(&bzerror
, self
->fp
,
644 buffersize
-nfilled
, self
);
647 if (bzerror
== BZ_STREAM_END
) {
648 self
->size
= self
->pos
;
649 self
->mode
= MODE_READ_EOF
;
655 } else if (bzerror
!= BZ_OK
) {
656 Util_CatchBZ2Error(bzerror
);
663 p
= memchr(buffer
+nfilled
, '\n', nread
);
665 /* Need a larger buffer to fit this line */
668 if (buffersize
> INT_MAX
) {
669 PyErr_SetString(PyExc_OverflowError
,
670 "line is longer than a Python string can hold");
673 if (big_buffer
== NULL
) {
674 /* Create the big buffer */
675 big_buffer
= PyString_FromStringAndSize(
677 if (big_buffer
== NULL
)
679 buffer
= PyString_AS_STRING(big_buffer
);
680 memcpy(buffer
, small_buffer
, nfilled
);
683 /* Grow the big buffer */
684 _PyString_Resize(&big_buffer
, buffersize
);
685 buffer
= PyString_AS_STRING(big_buffer
);
689 end
= buffer
+nfilled
+nread
;
692 /* Process complete lines */
694 line
= PyString_FromStringAndSize(q
, p
-q
);
697 err
= PyList_Append(list
, line
);
702 p
= memchr(q
, '\n', end
-q
);
704 /* Move the remaining incomplete line to the start */
706 memmove(buffer
, q
, nfilled
);
708 if (totalread
>= (size_t)sizehint
)
716 /* Partial last line */
717 line
= PyString_FromStringAndSize(buffer
, nfilled
);
721 /* Need to complete the last line */
722 PyObject
*rest
= Util_GetLine(self
, 0);
727 PyString_Concat(&line
, rest
);
732 err
= PyList_Append(list
, line
);
741 Py_DECREF(big_buffer
);
746 PyDoc_STRVAR(BZ2File_write__doc__
,
747 "write(data) -> None\n\
749 Write the 'data' string to file. Note that due to buffering, close() may\n\
750 be needed before the file on disk reflects the data written.\n\
753 /* This is a hacked version of Python's fileobject.c:file_write(). */
755 BZ2File_write(BZ2FileObject
*self
, PyObject
*args
)
757 PyObject
*ret
= NULL
;
762 if (!PyArg_ParseTuple(args
, "s#", &buf
, &len
))
766 switch (self
->mode
) {
771 PyErr_SetString(PyExc_ValueError
,
772 "I/O operation on closed file");
776 PyErr_SetString(PyExc_IOError
,
777 "file is not ready for writing");
781 PyFile_SoftSpace((PyObject
*)self
, 0);
783 Py_BEGIN_ALLOW_THREADS
784 BZ2_bzWrite (&bzerror
, self
->fp
, buf
, len
);
788 if (bzerror
!= BZ_OK
) {
789 Util_CatchBZ2Error(bzerror
);
801 PyDoc_STRVAR(BZ2File_writelines__doc__
,
802 "writelines(sequence_of_strings) -> None\n\
804 Write the sequence of strings to the file. Note that newlines are not\n\
805 added. The sequence can be any iterable object producing strings. This is\n\
806 equivalent to calling write() for each string.\n\
809 /* This is a hacked version of Python's fileobject.c:file_writelines(). */
811 BZ2File_writelines(BZ2FileObject
*self
, PyObject
*seq
)
813 #define CHUNKSIZE 1000
814 PyObject
*list
= NULL
;
815 PyObject
*iter
= NULL
;
816 PyObject
*ret
= NULL
;
818 int i
, j
, index
, len
, islist
;
822 islist
= PyList_Check(seq
);
824 iter
= PyObject_GetIter(seq
);
826 PyErr_SetString(PyExc_TypeError
,
827 "writelines() requires an iterable argument");
830 list
= PyList_New(CHUNKSIZE
);
835 /* Strategy: slurp CHUNKSIZE lines into a private list,
836 checking that they are all strings, then write that list
837 without holding the interpreter lock, then come back for more. */
838 for (index
= 0; ; index
+= CHUNKSIZE
) {
841 list
= PyList_GetSlice(seq
, index
, index
+CHUNKSIZE
);
844 j
= PyList_GET_SIZE(list
);
847 for (j
= 0; j
< CHUNKSIZE
; j
++) {
848 line
= PyIter_Next(iter
);
850 if (PyErr_Occurred())
854 PyList_SetItem(list
, j
, line
);
860 /* Check that all entries are indeed strings. If not,
861 apply the same rules as for file.write() and
862 convert the rets to strings. This is slow, but
863 seems to be the only way since all conversion APIs
864 could potentially execute Python code. */
865 for (i
= 0; i
< j
; i
++) {
866 PyObject
*v
= PyList_GET_ITEM(list
, i
);
867 if (!PyString_Check(v
)) {
870 if (PyObject_AsCharBuffer(v
, &buffer
, &len
)) {
871 PyErr_SetString(PyExc_TypeError
,
878 line
= PyString_FromStringAndSize(buffer
,
883 PyList_SET_ITEM(list
, i
, line
);
887 PyFile_SoftSpace((PyObject
*)self
, 0);
889 /* Since we are releasing the global lock, the
890 following code may *not* execute Python code. */
891 Py_BEGIN_ALLOW_THREADS
892 for (i
= 0; i
< j
; i
++) {
893 line
= PyList_GET_ITEM(list
, i
);
894 len
= PyString_GET_SIZE(line
);
895 BZ2_bzWrite (&bzerror
, self
->fp
,
896 PyString_AS_STRING(line
), len
);
897 if (bzerror
!= BZ_OK
) {
899 Util_CatchBZ2Error(bzerror
);
920 PyDoc_STRVAR(BZ2File_seek__doc__
,
921 "seek(offset [, whence]) -> None\n\
923 Move to new file position. Argument offset is a byte count. Optional\n\
924 argument whence defaults to 0 (offset from start of file, offset\n\
925 should be >= 0); other values are 1 (move relative to current position,\n\
926 positive or negative), and 2 (move relative to end of file, usually\n\
927 negative, although many platforms allow seeking beyond the end of a file).\n\
929 Note that seeking of bz2 files is emulated, and depending on the parameters\n\
930 the operation may be extremely slow.\n\
934 BZ2File_seek(BZ2FileObject
*self
, PyObject
*args
)
938 char small_buffer
[SMALLCHUNK
];
939 char *buffer
= small_buffer
;
940 size_t buffersize
= SMALLCHUNK
;
947 PyObject
*ret
= NULL
;
949 if (!PyArg_ParseTuple(args
, "l|i:seek", &offset
, &where
))
953 Util_DropReadAhead(self
);
954 switch (self
->mode
) {
960 PyErr_SetString(PyExc_ValueError
,
961 "I/O operation on closed file");
965 PyErr_SetString(PyExc_IOError
,
966 "seek works only while reading");
972 offset
= self
->pos
+ offset
;
974 } else if (where
== 2) {
975 if (self
->size
== -1) {
976 assert(self
->mode
!= MODE_READ_EOF
);
978 Py_BEGIN_ALLOW_THREADS
979 chunksize
= Util_UnivNewlineRead(
983 self
->pos
+= chunksize
;
986 bytesread
+= chunksize
;
987 if (bzerror
== BZ_STREAM_END
) {
989 } else if (bzerror
!= BZ_OK
) {
990 Util_CatchBZ2Error(bzerror
);
994 self
->mode
= MODE_READ_EOF
;
995 self
->size
= self
->pos
;
998 offset
= self
->size
+ offset
;
999 if (offset
>= self
->pos
)
1000 offset
-= self
->pos
;
1006 } else if (where
== 0) {
1007 if (offset
>= self
->pos
)
1008 offset
-= self
->pos
;
1014 BZ2_bzReadClose(&bzerror
, self
->fp
);
1015 func
= Py_FindMethod(PyFile_Type
.tp_methods
, (PyObject
*)self
,
1017 if (bzerror
!= BZ_OK
) {
1018 Util_CatchBZ2Error(bzerror
);
1022 PyErr_SetString(PyExc_RuntimeError
,
1023 "can't find file.seek method");
1026 ret
= PyObject_CallFunction(func
, "(i)", 0);
1032 self
->fp
= BZ2_bzReadOpen(&bzerror
,
1033 PyFile_AsFile((PyObject
*)self
),
1035 if (bzerror
!= BZ_OK
) {
1036 Util_CatchBZ2Error(bzerror
);
1039 self
->mode
= MODE_READ
;
1040 } else if (self
->mode
== MODE_READ_EOF
) {
1047 /* Before getting here, offset must be set to the number of bytes
1048 * to walk forward. */
1050 if ((size_t)offset
-bytesread
> buffersize
)
1051 readsize
= buffersize
;
1053 readsize
= offset
-bytesread
;
1054 Py_BEGIN_ALLOW_THREADS
1055 chunksize
= Util_UnivNewlineRead(&bzerror
, self
->fp
,
1056 buffer
, readsize
, self
);
1057 self
->pos
+= chunksize
;
1058 Py_END_ALLOW_THREADS
1059 bytesread
+= chunksize
;
1060 if (bzerror
== BZ_STREAM_END
) {
1061 self
->size
= self
->pos
;
1062 self
->mode
= MODE_READ_EOF
;
1064 } else if (bzerror
!= BZ_OK
) {
1065 Util_CatchBZ2Error(bzerror
);
1068 if (bytesread
== offset
)
1081 PyDoc_STRVAR(BZ2File_tell__doc__
,
1084 Return the current file position, an integer (may be a long integer).\n\
1088 BZ2File_tell(BZ2FileObject
*self
, PyObject
*args
)
1090 PyObject
*ret
= NULL
;
1092 if (self
->mode
== MODE_CLOSED
) {
1093 PyErr_SetString(PyExc_ValueError
,
1094 "I/O operation on closed file");
1098 ret
= PyInt_FromLong(self
->pos
);
1104 PyDoc_STRVAR(BZ2File_notsup__doc__
,
1105 "Operation not supported.\n\
1109 BZ2File_notsup(BZ2FileObject
*self
, PyObject
*args
)
1111 PyErr_SetString(PyExc_IOError
, "operation not supported");
1115 PyDoc_STRVAR(BZ2File_close__doc__
,
1116 "close() -> None or (perhaps) an integer\n\
1118 Close the file. Sets data attribute .closed to true. A closed file\n\
1119 cannot be used for further I/O operations. close() may be called more\n\
1120 than once without error.\n\
1124 BZ2File_close(BZ2FileObject
*self
)
1126 PyObject
*file_close
;
1127 PyObject
*ret
= NULL
;
1128 int bzerror
= BZ_OK
;
1131 switch (self
->mode
) {
1134 BZ2_bzReadClose(&bzerror
, self
->fp
);
1137 BZ2_bzWriteClose(&bzerror
, self
->fp
,
1141 self
->mode
= MODE_CLOSED
;
1142 file_close
= Py_FindMethod(PyFile_Type
.tp_methods
, (PyObject
*)self
,
1145 PyErr_SetString(PyExc_RuntimeError
,
1146 "can't find file.close method");
1149 ret
= PyObject_CallObject(file_close
, NULL
);
1150 if (bzerror
!= BZ_OK
) {
1151 Util_CatchBZ2Error(bzerror
);
1162 static PyMethodDef BZ2File_methods
[] = {
1163 {"read", (PyCFunction
)BZ2File_read
, METH_VARARGS
, BZ2File_read__doc__
},
1164 {"readline", (PyCFunction
)BZ2File_readline
, METH_VARARGS
, BZ2File_readline__doc__
},
1165 {"readlines", (PyCFunction
)BZ2File_readlines
, METH_VARARGS
, BZ2File_readlines__doc__
},
1166 {"write", (PyCFunction
)BZ2File_write
, METH_VARARGS
, BZ2File_write__doc__
},
1167 {"writelines", (PyCFunction
)BZ2File_writelines
, METH_O
, BZ2File_writelines__doc__
},
1168 {"seek", (PyCFunction
)BZ2File_seek
, METH_VARARGS
, BZ2File_seek__doc__
},
1169 {"tell", (PyCFunction
)BZ2File_tell
, METH_NOARGS
, BZ2File_tell__doc__
},
1170 {"truncate", (PyCFunction
)BZ2File_notsup
, METH_VARARGS
, BZ2File_notsup__doc__
},
1171 {"readinto", (PyCFunction
)BZ2File_notsup
, METH_VARARGS
, BZ2File_notsup__doc__
},
1172 {"close", (PyCFunction
)BZ2File_close
, METH_NOARGS
, BZ2File_close__doc__
},
1173 {NULL
, NULL
} /* sentinel */
1177 /* ===================================================================== */
1178 /* Slot definitions for BZ2File_Type. */
1181 BZ2File_init(BZ2FileObject
*self
, PyObject
*args
, PyObject
*kwargs
)
1183 PyObject
*file_args
= NULL
;
1184 static char *kwlist
[] = {"filename", "mode", "buffering",
1185 "compresslevel", 0};
1189 int compresslevel
= 9;
1192 int univ_newline
= 0;
1196 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "et|sii:BZ2File",
1197 kwlist
, Py_FileSystemDefaultEncoding
,
1198 &name
, &mode
, &buffering
,
1202 if (compresslevel
< 1 || compresslevel
> 9) {
1203 PyErr_SetString(PyExc_ValueError
,
1204 "compresslevel must be between 1 and 9");
1230 PyErr_Format(PyExc_ValueError
,
1231 "invalid mode char %c", *mode
);
1239 if (mode_char
== 'r')
1240 mode
= univ_newline
? "rbU" : "rb";
1242 mode
= univ_newline
? "wbU" : "wb";
1244 file_args
= Py_BuildValue("(ssi)", name
, mode
, buffering
);
1248 /* From now on, we have stuff to dealloc, so jump to error label
1249 * instead of returning */
1251 if (PyFile_Type
.tp_init((PyObject
*)self
, file_args
, NULL
) < 0)
1255 self
->lock
= PyThread_allocate_lock();
1260 if (mode_char
== 'r')
1261 self
->fp
= BZ2_bzReadOpen(&bzerror
,
1262 PyFile_AsFile((PyObject
*)self
),
1265 self
->fp
= BZ2_bzWriteOpen(&bzerror
,
1266 PyFile_AsFile((PyObject
*)self
),
1267 compresslevel
, 0, 0);
1269 if (bzerror
!= BZ_OK
) {
1270 Util_CatchBZ2Error(bzerror
);
1274 self
->mode
= (mode_char
== 'r') ? MODE_READ
: MODE_WRITE
;
1276 Py_XDECREF(file_args
);
1283 PyThread_free_lock(self
->lock
);
1285 Py_XDECREF(file_args
);
1291 BZ2File_dealloc(BZ2FileObject
*self
)
1296 PyThread_free_lock(self
->lock
);
1298 switch (self
->mode
) {
1301 BZ2_bzReadClose(&bzerror
, self
->fp
);
1304 BZ2_bzWriteClose(&bzerror
, self
->fp
,
1308 Util_DropReadAhead(self
);
1309 ((PyObject
*)self
)->ob_type
->tp_free((PyObject
*)self
);
1312 /* This is a hacked version of Python's fileobject.c:file_getiter(). */
1314 BZ2File_getiter(BZ2FileObject
*self
)
1316 if (self
->mode
== MODE_CLOSED
) {
1317 PyErr_SetString(PyExc_ValueError
,
1318 "I/O operation on closed file");
1321 Py_INCREF((PyObject
*)self
);
1322 return (PyObject
*)self
;
1325 /* This is a hacked version of Python's fileobject.c:file_iternext(). */
1326 #define READAHEAD_BUFSIZE 8192
1328 BZ2File_iternext(BZ2FileObject
*self
)
1330 PyStringObject
* ret
;
1332 if (self
->mode
== MODE_CLOSED
) {
1333 PyErr_SetString(PyExc_ValueError
,
1334 "I/O operation on closed file");
1337 ret
= Util_ReadAheadGetLineSkip(self
, 0, READAHEAD_BUFSIZE
);
1339 if (ret
== NULL
|| PyString_GET_SIZE(ret
) == 0) {
1343 return (PyObject
*)ret
;
1346 /* ===================================================================== */
1347 /* BZ2File_Type definition. */
1349 PyDoc_VAR(BZ2File__doc__
) =
1351 "BZ2File(name [, mode='r', buffering=0, compresslevel=9]) -> file object\n\
1353 Open a bz2 file. The mode can be 'r' or 'w', for reading (default) or\n\
1354 writing. When opened for writing, the file will be created if it doesn't\n\
1355 exist, and truncated otherwise. If the buffering argument is given, 0 means\n\
1356 unbuffered, and larger numbers specify the buffer size. If compresslevel\n\
1357 is given, must be a number between 1 and 9.\n\
1359 #ifdef WITH_UNIVERSAL_NEWLINES
1362 Add a 'U' to mode to open the file for input with universal newline\n\
1363 support. Any line ending in the input file will be seen as a '\\n' in\n\
1364 Python. Also, a file so opened gains the attribute 'newlines'; the value\n\
1365 for this attribute is one of None (no newline read yet), '\\r', '\\n',\n\
1366 '\\r\\n' or a tuple containing all the newline types seen. Universal\n\
1367 newlines are available only when reading.\n\
1372 static PyTypeObject BZ2File_Type
= {
1373 PyObject_HEAD_INIT(NULL
)
1375 "bz2.BZ2File", /*tp_name*/
1376 sizeof(BZ2FileObject
), /*tp_basicsize*/
1378 (destructor
)BZ2File_dealloc
, /*tp_dealloc*/
1385 0, /*tp_as_sequence*/
1386 0, /*tp_as_mapping*/
1393 Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
, /*tp_flags*/
1394 BZ2File__doc__
, /*tp_doc*/
1397 0, /*tp_richcompare*/
1398 0, /*tp_weaklistoffset*/
1399 (getiterfunc
)BZ2File_getiter
, /*tp_iter*/
1400 (iternextfunc
)BZ2File_iternext
, /*tp_iternext*/
1401 BZ2File_methods
, /*tp_methods*/
1408 0, /*tp_dictoffset*/
1409 (initproc
)BZ2File_init
, /*tp_init*/
1417 /* ===================================================================== */
1418 /* Methods of BZ2Comp. */
1420 PyDoc_STRVAR(BZ2Comp_compress__doc__
,
1421 "compress(data) -> string\n\
1423 Provide more data to the compressor object. It will return chunks of\n\
1424 compressed data whenever possible. When you've finished providing data\n\
1425 to compress, call the flush() method to finish the compression process,\n\
1426 and return what is left in the internal buffers.\n\
1430 BZ2Comp_compress(BZ2CompObject
*self
, PyObject
*args
)
1434 int bufsize
= SMALLCHUNK
;
1436 PyObject
*ret
= NULL
;
1437 bz_stream
*bzs
= &self
->bzs
;
1440 if (!PyArg_ParseTuple(args
, "s#", &data
, &datasize
))
1444 if (!self
->running
) {
1445 PyErr_SetString(PyExc_ValueError
,
1446 "this object was already flushed");
1450 ret
= PyString_FromStringAndSize(NULL
, bufsize
);
1454 bzs
->next_in
= data
;
1455 bzs
->avail_in
= datasize
;
1456 bzs
->next_out
= BUF(ret
);
1457 bzs
->avail_out
= bufsize
;
1459 totalout
= BZS_TOTAL_OUT(bzs
);
1462 Py_BEGIN_ALLOW_THREADS
1463 bzerror
= BZ2_bzCompress(bzs
, BZ_RUN
);
1464 Py_END_ALLOW_THREADS
1465 if (bzerror
!= BZ_RUN_OK
) {
1466 Util_CatchBZ2Error(bzerror
);
1469 if (bzs
->avail_out
== 0) {
1470 bufsize
= Util_NewBufferSize(bufsize
);
1471 if (_PyString_Resize(&ret
, bufsize
) < 0) {
1472 BZ2_bzCompressEnd(bzs
);
1475 bzs
->next_out
= BUF(ret
) + (BZS_TOTAL_OUT(bzs
)
1477 bzs
->avail_out
= bufsize
- (bzs
->next_out
- BUF(ret
));
1478 } else if (bzs
->avail_in
== 0) {
1483 _PyString_Resize(&ret
, (int)(BZS_TOTAL_OUT(bzs
) - totalout
));
1494 PyDoc_STRVAR(BZ2Comp_flush__doc__
,
1495 "flush() -> string\n\
1497 Finish the compression process and return what is left in internal buffers.\n\
1498 You must not use the compressor object after calling this method.\n\
1502 BZ2Comp_flush(BZ2CompObject
*self
)
1504 int bufsize
= SMALLCHUNK
;
1505 PyObject
*ret
= NULL
;
1506 bz_stream
*bzs
= &self
->bzs
;
1511 if (!self
->running
) {
1512 PyErr_SetString(PyExc_ValueError
, "object was already "
1518 ret
= PyString_FromStringAndSize(NULL
, bufsize
);
1522 bzs
->next_out
= BUF(ret
);
1523 bzs
->avail_out
= bufsize
;
1525 totalout
= BZS_TOTAL_OUT(bzs
);
1528 Py_BEGIN_ALLOW_THREADS
1529 bzerror
= BZ2_bzCompress(bzs
, BZ_FINISH
);
1530 Py_END_ALLOW_THREADS
1531 if (bzerror
== BZ_STREAM_END
) {
1533 } else if (bzerror
!= BZ_FINISH_OK
) {
1534 Util_CatchBZ2Error(bzerror
);
1537 if (bzs
->avail_out
== 0) {
1538 bufsize
= Util_NewBufferSize(bufsize
);
1539 if (_PyString_Resize(&ret
, bufsize
) < 0)
1541 bzs
->next_out
= BUF(ret
);
1542 bzs
->next_out
= BUF(ret
) + (BZS_TOTAL_OUT(bzs
)
1544 bzs
->avail_out
= bufsize
- (bzs
->next_out
- BUF(ret
));
1548 if (bzs
->avail_out
!= 0)
1549 _PyString_Resize(&ret
, (int)(BZS_TOTAL_OUT(bzs
) - totalout
));
1560 static PyMethodDef BZ2Comp_methods
[] = {
1561 {"compress", (PyCFunction
)BZ2Comp_compress
, METH_VARARGS
,
1562 BZ2Comp_compress__doc__
},
1563 {"flush", (PyCFunction
)BZ2Comp_flush
, METH_NOARGS
,
1564 BZ2Comp_flush__doc__
},
1565 {NULL
, NULL
} /* sentinel */
1569 /* ===================================================================== */
1570 /* Slot definitions for BZ2Comp_Type. */
1573 BZ2Comp_init(BZ2CompObject
*self
, PyObject
*args
, PyObject
*kwargs
)
1575 int compresslevel
= 9;
1577 static char *kwlist
[] = {"compresslevel", 0};
1579 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|i:BZ2Compressor",
1580 kwlist
, &compresslevel
))
1583 if (compresslevel
< 1 || compresslevel
> 9) {
1584 PyErr_SetString(PyExc_ValueError
,
1585 "compresslevel must be between 1 and 9");
1590 self
->lock
= PyThread_allocate_lock();
1595 memset(&self
->bzs
, 0, sizeof(bz_stream
));
1596 bzerror
= BZ2_bzCompressInit(&self
->bzs
, compresslevel
, 0, 0);
1597 if (bzerror
!= BZ_OK
) {
1598 Util_CatchBZ2Error(bzerror
);
1608 PyThread_free_lock(self
->lock
);
1614 BZ2Comp_dealloc(BZ2CompObject
*self
)
1618 PyThread_free_lock(self
->lock
);
1620 BZ2_bzCompressEnd(&self
->bzs
);
1621 ((PyObject
*)self
)->ob_type
->tp_free((PyObject
*)self
);
1625 /* ===================================================================== */
1626 /* BZ2Comp_Type definition. */
1628 PyDoc_STRVAR(BZ2Comp__doc__
,
1629 "BZ2Compressor([compresslevel=9]) -> compressor object\n\
1631 Create a new compressor object. This object may be used to compress\n\
1632 data sequentially. If you want to compress data in one shot, use the\n\
1633 compress() function instead. The compresslevel parameter, if given,\n\
1634 must be a number between 1 and 9.\n\
1637 static PyTypeObject BZ2Comp_Type
= {
1638 PyObject_HEAD_INIT(NULL
)
1640 "bz2.BZ2Compressor", /*tp_name*/
1641 sizeof(BZ2CompObject
), /*tp_basicsize*/
1643 (destructor
)BZ2Comp_dealloc
, /*tp_dealloc*/
1650 0, /*tp_as_sequence*/
1651 0, /*tp_as_mapping*/
1658 Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
, /*tp_flags*/
1659 BZ2Comp__doc__
, /*tp_doc*/
1662 0, /*tp_richcompare*/
1663 0, /*tp_weaklistoffset*/
1666 BZ2Comp_methods
, /*tp_methods*/
1673 0, /*tp_dictoffset*/
1674 (initproc
)BZ2Comp_init
, /*tp_init*/
1682 /* ===================================================================== */
1683 /* Members of BZ2Decomp. */
1685 #define OFF(x) offsetof(BZ2DecompObject, x)
1687 static PyMemberDef BZ2Decomp_members
[] = {
1688 {"unused_data", T_OBJECT
, OFF(unused_data
), RO
},
1689 {NULL
} /* Sentinel */
1693 /* ===================================================================== */
1694 /* Methods of BZ2Decomp. */
1696 PyDoc_STRVAR(BZ2Decomp_decompress__doc__
,
1697 "decompress(data) -> string\n\
1699 Provide more data to the decompressor object. It will return chunks\n\
1700 of decompressed data whenever possible. If you try to decompress data\n\
1701 after the end of stream is found, EOFError will be raised. If any data\n\
1702 was found after the end of stream, it'll be ignored and saved in\n\
1703 unused_data attribute.\n\
1707 BZ2Decomp_decompress(BZ2DecompObject
*self
, PyObject
*args
)
1711 int bufsize
= SMALLCHUNK
;
1713 PyObject
*ret
= NULL
;
1714 bz_stream
*bzs
= &self
->bzs
;
1717 if (!PyArg_ParseTuple(args
, "s#", &data
, &datasize
))
1721 if (!self
->running
) {
1722 PyErr_SetString(PyExc_EOFError
, "end of stream was "
1727 ret
= PyString_FromStringAndSize(NULL
, bufsize
);
1731 bzs
->next_in
= data
;
1732 bzs
->avail_in
= datasize
;
1733 bzs
->next_out
= BUF(ret
);
1734 bzs
->avail_out
= bufsize
;
1736 totalout
= BZS_TOTAL_OUT(bzs
);
1739 Py_BEGIN_ALLOW_THREADS
1740 bzerror
= BZ2_bzDecompress(bzs
);
1741 Py_END_ALLOW_THREADS
1742 if (bzerror
== BZ_STREAM_END
) {
1743 if (bzs
->avail_in
!= 0) {
1744 Py_DECREF(self
->unused_data
);
1746 PyString_FromStringAndSize(bzs
->next_in
,
1752 if (bzerror
!= BZ_OK
) {
1753 Util_CatchBZ2Error(bzerror
);
1756 if (bzs
->avail_out
== 0) {
1757 bufsize
= Util_NewBufferSize(bufsize
);
1758 if (_PyString_Resize(&ret
, bufsize
) < 0) {
1759 BZ2_bzDecompressEnd(bzs
);
1762 bzs
->next_out
= BUF(ret
);
1763 bzs
->next_out
= BUF(ret
) + (BZS_TOTAL_OUT(bzs
)
1765 bzs
->avail_out
= bufsize
- (bzs
->next_out
- BUF(ret
));
1766 } else if (bzs
->avail_in
== 0) {
1771 if (bzs
->avail_out
!= 0)
1772 _PyString_Resize(&ret
, (int)(BZS_TOTAL_OUT(bzs
) - totalout
));
1783 static PyMethodDef BZ2Decomp_methods
[] = {
1784 {"decompress", (PyCFunction
)BZ2Decomp_decompress
, METH_VARARGS
, BZ2Decomp_decompress__doc__
},
1785 {NULL
, NULL
} /* sentinel */
1789 /* ===================================================================== */
1790 /* Slot definitions for BZ2Decomp_Type. */
1793 BZ2Decomp_init(BZ2DecompObject
*self
, PyObject
*args
, PyObject
*kwargs
)
1797 if (!PyArg_ParseTuple(args
, ":BZ2Decompressor"))
1801 self
->lock
= PyThread_allocate_lock();
1806 self
->unused_data
= PyString_FromString("");
1807 if (!self
->unused_data
)
1810 memset(&self
->bzs
, 0, sizeof(bz_stream
));
1811 bzerror
= BZ2_bzDecompressInit(&self
->bzs
, 0, 0);
1812 if (bzerror
!= BZ_OK
) {
1813 Util_CatchBZ2Error(bzerror
);
1824 PyThread_free_lock(self
->lock
);
1826 Py_XDECREF(self
->unused_data
);
1831 BZ2Decomp_dealloc(BZ2DecompObject
*self
)
1835 PyThread_free_lock(self
->lock
);
1837 Py_XDECREF(self
->unused_data
);
1838 BZ2_bzDecompressEnd(&self
->bzs
);
1839 ((PyObject
*)self
)->ob_type
->tp_free((PyObject
*)self
);
1843 /* ===================================================================== */
1844 /* BZ2Decomp_Type definition. */
1846 PyDoc_STRVAR(BZ2Decomp__doc__
,
1847 "BZ2Decompressor() -> decompressor object\n\
1849 Create a new decompressor object. This object may be used to decompress\n\
1850 data sequentially. If you want to decompress data in one shot, use the\n\
1851 decompress() function instead.\n\
1854 static PyTypeObject BZ2Decomp_Type
= {
1855 PyObject_HEAD_INIT(NULL
)
1857 "bz2.BZ2Decompressor", /*tp_name*/
1858 sizeof(BZ2DecompObject
), /*tp_basicsize*/
1860 (destructor
)BZ2Decomp_dealloc
, /*tp_dealloc*/
1867 0, /*tp_as_sequence*/
1868 0, /*tp_as_mapping*/
1875 Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
, /*tp_flags*/
1876 BZ2Decomp__doc__
, /*tp_doc*/
1879 0, /*tp_richcompare*/
1880 0, /*tp_weaklistoffset*/
1883 BZ2Decomp_methods
, /*tp_methods*/
1884 BZ2Decomp_members
, /*tp_members*/
1890 0, /*tp_dictoffset*/
1891 (initproc
)BZ2Decomp_init
, /*tp_init*/
1899 /* ===================================================================== */
1900 /* Module functions. */
1902 PyDoc_STRVAR(bz2_compress__doc__
,
1903 "compress(data [, compresslevel=9]) -> string\n\
1905 Compress data in one shot. If you want to compress data sequentially,\n\
1906 use an instance of BZ2Compressor instead. The compresslevel parameter, if\n\
1907 given, must be a number between 1 and 9.\n\
1911 bz2_compress(PyObject
*self
, PyObject
*args
, PyObject
*kwargs
)
1913 int compresslevel
=9;
1917 PyObject
*ret
= NULL
;
1919 bz_stream
*bzs
= &_bzs
;
1921 static char *kwlist
[] = {"data", "compresslevel", 0};
1923 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "s#|i",
1924 kwlist
, &data
, &datasize
,
1928 if (compresslevel
< 1 || compresslevel
> 9) {
1929 PyErr_SetString(PyExc_ValueError
,
1930 "compresslevel must be between 1 and 9");
1934 /* Conforming to bz2 manual, this is large enough to fit compressed
1935 * data in one shot. We will check it later anyway. */
1936 bufsize
= datasize
+ (datasize
/100+1) + 600;
1938 ret
= PyString_FromStringAndSize(NULL
, bufsize
);
1942 memset(bzs
, 0, sizeof(bz_stream
));
1944 bzs
->next_in
= data
;
1945 bzs
->avail_in
= datasize
;
1946 bzs
->next_out
= BUF(ret
);
1947 bzs
->avail_out
= bufsize
;
1949 bzerror
= BZ2_bzCompressInit(bzs
, compresslevel
, 0, 0);
1950 if (bzerror
!= BZ_OK
) {
1951 Util_CatchBZ2Error(bzerror
);
1957 Py_BEGIN_ALLOW_THREADS
1958 bzerror
= BZ2_bzCompress(bzs
, BZ_FINISH
);
1959 Py_END_ALLOW_THREADS
1960 if (bzerror
== BZ_STREAM_END
) {
1962 } else if (bzerror
!= BZ_FINISH_OK
) {
1963 BZ2_bzCompressEnd(bzs
);
1964 Util_CatchBZ2Error(bzerror
);
1968 if (bzs
->avail_out
== 0) {
1969 bufsize
= Util_NewBufferSize(bufsize
);
1970 if (_PyString_Resize(&ret
, bufsize
) < 0) {
1971 BZ2_bzCompressEnd(bzs
);
1975 bzs
->next_out
= BUF(ret
) + BZS_TOTAL_OUT(bzs
);
1976 bzs
->avail_out
= bufsize
- (bzs
->next_out
- BUF(ret
));
1980 if (bzs
->avail_out
!= 0)
1981 _PyString_Resize(&ret
, (int)BZS_TOTAL_OUT(bzs
));
1982 BZ2_bzCompressEnd(bzs
);
1987 PyDoc_STRVAR(bz2_decompress__doc__
,
1988 "decompress(data) -> decompressed data\n\
1990 Decompress data in one shot. If you want to decompress data sequentially,\n\
1991 use an instance of BZ2Decompressor instead.\n\
1995 bz2_decompress(PyObject
*self
, PyObject
*args
)
1999 int bufsize
= SMALLCHUNK
;
2002 bz_stream
*bzs
= &_bzs
;
2005 if (!PyArg_ParseTuple(args
, "s#", &data
, &datasize
))
2009 return PyString_FromString("");
2011 ret
= PyString_FromStringAndSize(NULL
, bufsize
);
2015 memset(bzs
, 0, sizeof(bz_stream
));
2017 bzs
->next_in
= data
;
2018 bzs
->avail_in
= datasize
;
2019 bzs
->next_out
= BUF(ret
);
2020 bzs
->avail_out
= bufsize
;
2022 bzerror
= BZ2_bzDecompressInit(bzs
, 0, 0);
2023 if (bzerror
!= BZ_OK
) {
2024 Util_CatchBZ2Error(bzerror
);
2030 Py_BEGIN_ALLOW_THREADS
2031 bzerror
= BZ2_bzDecompress(bzs
);
2032 Py_END_ALLOW_THREADS
2033 if (bzerror
== BZ_STREAM_END
) {
2035 } else if (bzerror
!= BZ_OK
) {
2036 BZ2_bzDecompressEnd(bzs
);
2037 Util_CatchBZ2Error(bzerror
);
2041 if (bzs
->avail_out
== 0) {
2042 bufsize
= Util_NewBufferSize(bufsize
);
2043 if (_PyString_Resize(&ret
, bufsize
) < 0) {
2044 BZ2_bzDecompressEnd(bzs
);
2048 bzs
->next_out
= BUF(ret
) + BZS_TOTAL_OUT(bzs
);
2049 bzs
->avail_out
= bufsize
- (bzs
->next_out
- BUF(ret
));
2050 } else if (bzs
->avail_in
== 0) {
2051 BZ2_bzDecompressEnd(bzs
);
2052 PyErr_SetString(PyExc_ValueError
,
2053 "couldn't find end of stream");
2059 if (bzs
->avail_out
!= 0)
2060 _PyString_Resize(&ret
, (int)BZS_TOTAL_OUT(bzs
));
2061 BZ2_bzDecompressEnd(bzs
);
2066 static PyMethodDef bz2_methods
[] = {
2067 {"compress", (PyCFunction
) bz2_compress
, METH_VARARGS
|METH_KEYWORDS
,
2068 bz2_compress__doc__
},
2069 {"decompress", (PyCFunction
) bz2_decompress
, METH_VARARGS
,
2070 bz2_decompress__doc__
},
2071 {NULL
, NULL
} /* sentinel */
2074 /* ===================================================================== */
2075 /* Initialization function. */
2077 PyDoc_STRVAR(bz2__doc__
,
2078 "The python bz2 module provides a comprehensive interface for\n\
2079 the bz2 compression library. It implements a complete file\n\
2080 interface, one shot (de)compression functions, and types for\n\
2081 sequential (de)compression.\n\
2089 BZ2File_Type
.ob_type
= &PyType_Type
;
2090 BZ2File_Type
.tp_base
= &PyFile_Type
;
2091 BZ2File_Type
.tp_new
= PyFile_Type
.tp_new
;
2092 BZ2File_Type
.tp_getattro
= PyObject_GenericGetAttr
;
2093 BZ2File_Type
.tp_setattro
= PyObject_GenericSetAttr
;
2094 BZ2File_Type
.tp_alloc
= PyType_GenericAlloc
;
2095 BZ2File_Type
.tp_free
= _PyObject_Del
;
2097 BZ2Comp_Type
.ob_type
= &PyType_Type
;
2098 BZ2Comp_Type
.tp_getattro
= PyObject_GenericGetAttr
;
2099 BZ2Comp_Type
.tp_setattro
= PyObject_GenericSetAttr
;
2100 BZ2Comp_Type
.tp_alloc
= PyType_GenericAlloc
;
2101 BZ2Comp_Type
.tp_new
= PyType_GenericNew
;
2102 BZ2Comp_Type
.tp_free
= _PyObject_Del
;
2104 BZ2Decomp_Type
.ob_type
= &PyType_Type
;
2105 BZ2Decomp_Type
.tp_getattro
= PyObject_GenericGetAttr
;
2106 BZ2Decomp_Type
.tp_setattro
= PyObject_GenericSetAttr
;
2107 BZ2Decomp_Type
.tp_alloc
= PyType_GenericAlloc
;
2108 BZ2Decomp_Type
.tp_new
= PyType_GenericNew
;
2109 BZ2Decomp_Type
.tp_free
= _PyObject_Del
;
2111 m
= Py_InitModule3("bz2", bz2_methods
, bz2__doc__
);
2113 PyModule_AddObject(m
, "__author__", PyString_FromString(__author__
));
2115 Py_INCREF(&BZ2File_Type
);
2116 PyModule_AddObject(m
, "BZ2File", (PyObject
*)&BZ2File_Type
);
2118 Py_INCREF(&BZ2Comp_Type
);
2119 PyModule_AddObject(m
, "BZ2Compressor", (PyObject
*)&BZ2Comp_Type
);
2121 Py_INCREF(&BZ2Decomp_Type
);
2122 PyModule_AddObject(m
, "BZ2Decompressor", (PyObject
*)&BZ2Decomp_Type
);