blob: 73de628e860009128210c562e0a950c52784507a [file] [log] [blame]
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001/*
2
3python-bz2 - python bz2 library interface
4
5Copyright (c) 2002 Gustavo Niemeyer <niemeyer@conectiva.com>
6Copyright (c) 2002 Python Software Foundation; All Rights Reserved
7
8*/
9
Martin v. Löwise17af7b2002-11-23 09:16:19 +000010#include "Python.h"
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000011#include <stdio.h>
12#include <bzlib.h>
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000013#include "structmember.h"
14
15#ifdef WITH_THREAD
16#include "pythread.h"
17#endif
18
19static char __author__[] =
20"The bz2 python module was written by:\n\
21\n\
22 Gustavo Niemeyer <niemeyer@conectiva.com>\n\
23";
24
Georg Brandl33a5f2a2005-08-21 14:16:04 +000025/* Our very own off_t-like type, 64-bit if possible */
26/* copied from Objects/fileobject.c */
27#if !defined(HAVE_LARGEFILE_SUPPORT)
28typedef off_t Py_off_t;
29#elif SIZEOF_OFF_T >= 8
30typedef off_t Py_off_t;
31#elif SIZEOF_FPOS_T >= 8
32typedef fpos_t Py_off_t;
33#else
34#error "Large file support, but neither off_t nor fpos_t is large enough."
35#endif
36
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000037#define BUF(v) PyString_AS_STRING((PyStringObject *)v)
38
39#define MODE_CLOSED 0
40#define MODE_READ 1
41#define MODE_READ_EOF 2
42#define MODE_WRITE 3
43
44#define BZ2FileObject_Check(v) ((v)->ob_type == &BZ2File_Type)
45
Gustavo Niemeyer7628f1f2003-04-27 06:25:24 +000046
47#ifdef BZ_CONFIG_ERROR
48
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000049#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) \
Martin v. Löwisb9a0f912003-03-29 10:06:18 +000054 (((PY_LONG_LONG)bzs->total_out_hi32 << 32) + bzs->total_out_lo32)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000055#else
56#define BZS_TOTAL_OUT(bzs) \
Neal Norwitz20bad742006-01-17 05:27:39 +000057 bzs->total_out_lo32
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000058#endif
59
Gustavo Niemeyer7628f1f2003-04-27 06:25:24 +000060#else /* ! BZ_CONFIG_ERROR */
61
62#define BZ2_bzRead bzRead
63#define BZ2_bzReadOpen bzReadOpen
64#define BZ2_bzReadClose bzReadClose
65#define BZ2_bzWrite bzWrite
66#define BZ2_bzWriteOpen bzWriteOpen
67#define BZ2_bzWriteClose bzWriteClose
68#define BZ2_bzCompress bzCompress
69#define BZ2_bzCompressInit bzCompressInit
70#define BZ2_bzCompressEnd bzCompressEnd
71#define BZ2_bzDecompress bzDecompress
72#define BZ2_bzDecompressInit bzDecompressInit
73#define BZ2_bzDecompressEnd bzDecompressEnd
74
75#define BZS_TOTAL_OUT(bzs) bzs->total_out
76
77#endif /* ! BZ_CONFIG_ERROR */
78
79
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000080#ifdef WITH_THREAD
81#define ACQUIRE_LOCK(obj) PyThread_acquire_lock(obj->lock, 1)
82#define RELEASE_LOCK(obj) PyThread_release_lock(obj->lock)
83#else
84#define ACQUIRE_LOCK(obj)
85#define RELEASE_LOCK(obj)
86#endif
87
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000088/* 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 */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000093
94/* ===================================================================== */
95/* Structure definitions. */
96
97typedef struct {
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +000098 PyObject_HEAD
99 PyObject *file;
100
101 char* f_buf; /* Allocated readahead buffer */
102 char* f_bufend; /* Points after last occupied position */
103 char* f_bufptr; /* Current buffer position */
104
105 int f_softspace; /* Flag used by 'print' command */
106
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000107 int f_univ_newline; /* Handle any newline convention */
108 int f_newlinetypes; /* Types of newlines seen */
109 int f_skipnextlf; /* Skip next \n */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000110
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000111 BZFILE *fp;
112 int mode;
Georg Brandla8bcecc2005-09-03 07:49:53 +0000113 Py_off_t pos;
114 Py_off_t size;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000115#ifdef WITH_THREAD
116 PyThread_type_lock lock;
117#endif
118} BZ2FileObject;
119
120typedef struct {
121 PyObject_HEAD
122 bz_stream bzs;
123 int running;
124#ifdef WITH_THREAD
125 PyThread_type_lock lock;
126#endif
127} BZ2CompObject;
128
129typedef struct {
130 PyObject_HEAD
131 bz_stream bzs;
132 int running;
133 PyObject *unused_data;
134#ifdef WITH_THREAD
135 PyThread_type_lock lock;
136#endif
137} BZ2DecompObject;
138
139/* ===================================================================== */
140/* Utility functions. */
141
142static int
143Util_CatchBZ2Error(int bzerror)
144{
145 int ret = 0;
146 switch(bzerror) {
147 case BZ_OK:
148 case BZ_STREAM_END:
149 break;
150
Gustavo Niemeyer7628f1f2003-04-27 06:25:24 +0000151#ifdef BZ_CONFIG_ERROR
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000152 case BZ_CONFIG_ERROR:
153 PyErr_SetString(PyExc_SystemError,
154 "the bz2 library was not compiled "
155 "correctly");
156 ret = 1;
157 break;
Gustavo Niemeyer7628f1f2003-04-27 06:25:24 +0000158#endif
Tim Peterse3228092002-11-09 04:21:44 +0000159
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000160 case BZ_PARAM_ERROR:
161 PyErr_SetString(PyExc_ValueError,
162 "the bz2 library has received wrong "
163 "parameters");
164 ret = 1;
165 break;
Tim Peterse3228092002-11-09 04:21:44 +0000166
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000167 case BZ_MEM_ERROR:
168 PyErr_NoMemory();
169 ret = 1;
170 break;
171
172 case BZ_DATA_ERROR:
173 case BZ_DATA_ERROR_MAGIC:
174 PyErr_SetString(PyExc_IOError, "invalid data stream");
175 ret = 1;
176 break;
177
178 case BZ_IO_ERROR:
179 PyErr_SetString(PyExc_IOError, "unknown IO error");
180 ret = 1;
181 break;
182
183 case BZ_UNEXPECTED_EOF:
184 PyErr_SetString(PyExc_EOFError,
185 "compressed file ended before the "
186 "logical end-of-stream was detected");
187 ret = 1;
188 break;
189
190 case BZ_SEQUENCE_ERROR:
191 PyErr_SetString(PyExc_RuntimeError,
192 "wrong sequence of bz2 library "
193 "commands used");
194 ret = 1;
195 break;
196 }
197 return ret;
198}
199
200#if BUFSIZ < 8192
201#define SMALLCHUNK 8192
202#else
203#define SMALLCHUNK BUFSIZ
204#endif
205
206#if SIZEOF_INT < 4
207#define BIGCHUNK (512 * 32)
208#else
209#define BIGCHUNK (512 * 1024)
210#endif
211
212/* This is a hacked version of Python's fileobject.c:new_buffersize(). */
213static size_t
214Util_NewBufferSize(size_t currentsize)
215{
216 if (currentsize > SMALLCHUNK) {
217 /* Keep doubling until we reach BIGCHUNK;
218 then keep adding BIGCHUNK. */
219 if (currentsize <= BIGCHUNK)
220 return currentsize + currentsize;
221 else
222 return currentsize + BIGCHUNK;
223 }
224 return currentsize + SMALLCHUNK;
225}
226
227/* This is a hacked version of Python's fileobject.c:get_line(). */
228static PyObject *
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000229Util_GetLine(BZ2FileObject *f, int n)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000230{
231 char c;
232 char *buf, *end;
233 size_t total_v_size; /* total # of slots in buffer */
234 size_t used_v_size; /* # used slots in buffer */
235 size_t increment; /* amount to increment the buffer */
236 PyObject *v;
237 int bzerror;
Sean Reifscheiderb5ec5872007-09-17 05:45:20 +0000238 int bytes_read;
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000239 int newlinetypes = f->f_newlinetypes;
240 int skipnextlf = f->f_skipnextlf;
241 int univ_newline = f->f_univ_newline;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000242
243 total_v_size = n > 0 ? n : 100;
244 v = PyString_FromStringAndSize((char *)NULL, total_v_size);
245 if (v == NULL)
246 return NULL;
247
248 buf = BUF(v);
249 end = buf + total_v_size;
250
251 for (;;) {
252 Py_BEGIN_ALLOW_THREADS
Sean Reifscheiderb5ec5872007-09-17 05:45:20 +0000253 while (buf != end) {
254 bytes_read = BZ2_bzRead(&bzerror, f->fp, &c, 1);
255 f->pos++;
256 if (bytes_read == 0) break;
257 if (univ_newline) {
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +0000258 if (skipnextlf) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000259 skipnextlf = 0;
260 if (c == '\n') {
Sean Reifscheiderb5ec5872007-09-17 05:45:20 +0000261 /* Seeing a \n here with skipnextlf true means we
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000262 * saw a \r before.
263 */
264 newlinetypes |= NEWLINE_CRLF;
Sean Reifscheiderb5ec5872007-09-17 05:45:20 +0000265 if (bzerror != BZ_OK) break;
266 bytes_read = BZ2_bzRead(&bzerror, f->fp, &c, 1);
267 f->pos++;
268 if (bytes_read == 0) break;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000269 } else {
270 newlinetypes |= NEWLINE_CR;
271 }
272 }
273 if (c == '\r') {
274 skipnextlf = 1;
275 c = '\n';
Sean Reifscheiderb5ec5872007-09-17 05:45:20 +0000276 } else if (c == '\n')
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000277 newlinetypes |= NEWLINE_LF;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000278 }
Sean Reifscheiderb5ec5872007-09-17 05:45:20 +0000279 *buf++ = c;
280 if (bzerror != BZ_OK || c == '\n') break;
281 }
282 if (univ_newline && bzerror == BZ_STREAM_END && skipnextlf)
283 newlinetypes |= NEWLINE_CR;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000284 Py_END_ALLOW_THREADS
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000285 f->f_newlinetypes = newlinetypes;
286 f->f_skipnextlf = skipnextlf;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000287 if (bzerror == BZ_STREAM_END) {
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000288 f->size = f->pos;
289 f->mode = MODE_READ_EOF;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000290 break;
291 } else if (bzerror != BZ_OK) {
292 Util_CatchBZ2Error(bzerror);
293 Py_DECREF(v);
294 return NULL;
295 }
296 if (c == '\n')
297 break;
298 /* Must be because buf == end */
299 if (n > 0)
300 break;
301 used_v_size = total_v_size;
302 increment = total_v_size >> 2; /* mild exponential growth */
303 total_v_size += increment;
304 if (total_v_size > INT_MAX) {
305 PyErr_SetString(PyExc_OverflowError,
306 "line is longer than a Python string can hold");
307 Py_DECREF(v);
308 return NULL;
309 }
310 if (_PyString_Resize(&v, total_v_size) < 0)
311 return NULL;
312 buf = BUF(v) + used_v_size;
313 end = BUF(v) + total_v_size;
314 }
315
316 used_v_size = buf - BUF(v);
317 if (used_v_size != total_v_size)
318 _PyString_Resize(&v, used_v_size);
319 return v;
320}
321
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000322/* This is a hacked version of Python's
323 * fileobject.c:Py_UniversalNewlineFread(). */
324size_t
325Util_UnivNewlineRead(int *bzerror, BZFILE *stream,
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000326 char* buf, size_t n, BZ2FileObject *f)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000327{
328 char *dst = buf;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000329 int newlinetypes, skipnextlf;
330
331 assert(buf != NULL);
332 assert(stream != NULL);
333
334 if (!f->f_univ_newline)
335 return BZ2_bzRead(bzerror, stream, buf, n);
336
337 newlinetypes = f->f_newlinetypes;
338 skipnextlf = f->f_skipnextlf;
339
340 /* Invariant: n is the number of bytes remaining to be filled
341 * in the buffer.
342 */
343 while (n) {
344 size_t nread;
345 int shortread;
346 char *src = dst;
347
348 nread = BZ2_bzRead(bzerror, stream, dst, n);
349 assert(nread <= n);
350 n -= nread; /* assuming 1 byte out for each in; will adjust */
351 shortread = n != 0; /* true iff EOF or error */
352 while (nread--) {
353 char c = *src++;
354 if (c == '\r') {
355 /* Save as LF and set flag to skip next LF. */
356 *dst++ = '\n';
357 skipnextlf = 1;
358 }
359 else if (skipnextlf && c == '\n') {
360 /* Skip LF, and remember we saw CR LF. */
361 skipnextlf = 0;
362 newlinetypes |= NEWLINE_CRLF;
363 ++n;
364 }
365 else {
366 /* Normal char to be stored in buffer. Also
367 * update the newlinetypes flag if either this
368 * is an LF or the previous char was a CR.
369 */
370 if (c == '\n')
371 newlinetypes |= NEWLINE_LF;
372 else if (skipnextlf)
373 newlinetypes |= NEWLINE_CR;
374 *dst++ = c;
375 skipnextlf = 0;
376 }
377 }
378 if (shortread) {
379 /* If this is EOF, update type flags. */
380 if (skipnextlf && *bzerror == BZ_STREAM_END)
381 newlinetypes |= NEWLINE_CR;
382 break;
383 }
384 }
385 f->f_newlinetypes = newlinetypes;
386 f->f_skipnextlf = skipnextlf;
387 return dst - buf;
388}
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000389
390/* This is a hacked version of Python's fileobject.c:drop_readahead(). */
391static void
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000392Util_DropReadAhead(BZ2FileObject *f)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000393{
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000394 if (f->f_buf != NULL) {
395 PyMem_Free(f->f_buf);
396 f->f_buf = NULL;
397 }
398}
399
400/* This is a hacked version of Python's fileobject.c:readahead(). */
401static int
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000402Util_ReadAhead(BZ2FileObject *f, int bufsize)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000403{
404 int chunksize;
405 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000406
407 if (f->f_buf != NULL) {
Tim Peterse3228092002-11-09 04:21:44 +0000408 if((f->f_bufend - f->f_bufptr) >= 1)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000409 return 0;
410 else
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000411 Util_DropReadAhead(f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000412 }
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000413 if (f->mode == MODE_READ_EOF) {
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000414 f->f_bufptr = f->f_buf;
415 f->f_bufend = f->f_buf;
416 return 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000417 }
418 if ((f->f_buf = PyMem_Malloc(bufsize)) == NULL) {
Georg Brandle71268f2008-08-12 08:47:02 +0000419 PyErr_NoMemory();
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000420 return -1;
421 }
422 Py_BEGIN_ALLOW_THREADS
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000423 chunksize = Util_UnivNewlineRead(&bzerror, f->fp, f->f_buf,
424 bufsize, f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000425 Py_END_ALLOW_THREADS
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000426 f->pos += chunksize;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000427 if (bzerror == BZ_STREAM_END) {
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000428 f->size = f->pos;
429 f->mode = MODE_READ_EOF;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000430 } else if (bzerror != BZ_OK) {
431 Util_CatchBZ2Error(bzerror);
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000432 Util_DropReadAhead(f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000433 return -1;
434 }
435 f->f_bufptr = f->f_buf;
436 f->f_bufend = f->f_buf + chunksize;
437 return 0;
438}
439
440/* This is a hacked version of Python's
441 * fileobject.c:readahead_get_line_skip(). */
442static PyStringObject *
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000443Util_ReadAheadGetLineSkip(BZ2FileObject *f, int skip, int bufsize)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000444{
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000445 PyStringObject* s;
446 char *bufptr;
447 char *buf;
448 int len;
449
450 if (f->f_buf == NULL)
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000451 if (Util_ReadAhead(f, bufsize) < 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000452 return NULL;
453
454 len = f->f_bufend - f->f_bufptr;
Tim Peterse3228092002-11-09 04:21:44 +0000455 if (len == 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000456 return (PyStringObject *)
457 PyString_FromStringAndSize(NULL, skip);
458 bufptr = memchr(f->f_bufptr, '\n', len);
459 if (bufptr != NULL) {
460 bufptr++; /* Count the '\n' */
461 len = bufptr - f->f_bufptr;
462 s = (PyStringObject *)
463 PyString_FromStringAndSize(NULL, skip+len);
Tim Peterse3228092002-11-09 04:21:44 +0000464 if (s == NULL)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000465 return NULL;
466 memcpy(PyString_AS_STRING(s)+skip, f->f_bufptr, len);
467 f->f_bufptr = bufptr;
468 if (bufptr == f->f_bufend)
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000469 Util_DropReadAhead(f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000470 } else {
471 bufptr = f->f_bufptr;
472 buf = f->f_buf;
473 f->f_buf = NULL; /* Force new readahead buffer */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000474 s = Util_ReadAheadGetLineSkip(f, skip+len,
475 bufsize + (bufsize>>2));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000476 if (s == NULL) {
477 PyMem_Free(buf);
478 return NULL;
479 }
480 memcpy(PyString_AS_STRING(s)+skip, bufptr, len);
481 PyMem_Free(buf);
482 }
483 return s;
484}
485
486/* ===================================================================== */
487/* Methods of BZ2File. */
488
489PyDoc_STRVAR(BZ2File_read__doc__,
490"read([size]) -> string\n\
491\n\
492Read at most size uncompressed bytes, returned as a string. If the size\n\
493argument is negative or omitted, read until EOF is reached.\n\
494");
495
496/* This is a hacked version of Python's fileobject.c:file_read(). */
497static PyObject *
498BZ2File_read(BZ2FileObject *self, PyObject *args)
499{
500 long bytesrequested = -1;
501 size_t bytesread, buffersize, chunksize;
502 int bzerror;
503 PyObject *ret = NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000504
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000505 if (!PyArg_ParseTuple(args, "|l:read", &bytesrequested))
506 return NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000507
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000508 ACQUIRE_LOCK(self);
509 switch (self->mode) {
510 case MODE_READ:
511 break;
512 case MODE_READ_EOF:
513 ret = PyString_FromString("");
514 goto cleanup;
515 case MODE_CLOSED:
516 PyErr_SetString(PyExc_ValueError,
517 "I/O operation on closed file");
518 goto cleanup;
519 default:
520 PyErr_SetString(PyExc_IOError,
521 "file is not ready for reading");
522 goto cleanup;
523 }
524
525 if (bytesrequested < 0)
526 buffersize = Util_NewBufferSize((size_t)0);
527 else
528 buffersize = bytesrequested;
529 if (buffersize > INT_MAX) {
530 PyErr_SetString(PyExc_OverflowError,
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +0000531 "requested number of bytes is "
532 "more than a Python string can hold");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000533 goto cleanup;
534 }
535 ret = PyString_FromStringAndSize((char *)NULL, buffersize);
536 if (ret == NULL)
537 goto cleanup;
538 bytesread = 0;
539
540 for (;;) {
541 Py_BEGIN_ALLOW_THREADS
542 chunksize = Util_UnivNewlineRead(&bzerror, self->fp,
543 BUF(ret)+bytesread,
544 buffersize-bytesread,
545 self);
546 self->pos += chunksize;
547 Py_END_ALLOW_THREADS
548 bytesread += chunksize;
549 if (bzerror == BZ_STREAM_END) {
550 self->size = self->pos;
551 self->mode = MODE_READ_EOF;
552 break;
553 } else if (bzerror != BZ_OK) {
554 Util_CatchBZ2Error(bzerror);
555 Py_DECREF(ret);
556 ret = NULL;
557 goto cleanup;
558 }
559 if (bytesrequested < 0) {
560 buffersize = Util_NewBufferSize(buffersize);
561 if (_PyString_Resize(&ret, buffersize) < 0)
562 goto cleanup;
563 } else {
564 break;
565 }
566 }
567 if (bytesread != buffersize)
568 _PyString_Resize(&ret, bytesread);
569
570cleanup:
571 RELEASE_LOCK(self);
572 return ret;
573}
574
575PyDoc_STRVAR(BZ2File_readline__doc__,
576"readline([size]) -> string\n\
577\n\
578Return the next line from the file, as a string, retaining newline.\n\
579A non-negative size argument will limit the maximum number of bytes to\n\
580return (an incomplete line may be returned then). Return an empty\n\
581string at EOF.\n\
582");
583
584static PyObject *
585BZ2File_readline(BZ2FileObject *self, PyObject *args)
586{
587 PyObject *ret = NULL;
588 int sizehint = -1;
589
590 if (!PyArg_ParseTuple(args, "|i:readline", &sizehint))
591 return NULL;
592
593 ACQUIRE_LOCK(self);
594 switch (self->mode) {
595 case MODE_READ:
596 break;
597 case MODE_READ_EOF:
598 ret = PyString_FromString("");
599 goto cleanup;
600 case MODE_CLOSED:
601 PyErr_SetString(PyExc_ValueError,
602 "I/O operation on closed file");
603 goto cleanup;
604 default:
605 PyErr_SetString(PyExc_IOError,
606 "file is not ready for reading");
607 goto cleanup;
608 }
609
610 if (sizehint == 0)
611 ret = PyString_FromString("");
612 else
613 ret = Util_GetLine(self, (sizehint < 0) ? 0 : sizehint);
614
615cleanup:
616 RELEASE_LOCK(self);
617 return ret;
618}
619
620PyDoc_STRVAR(BZ2File_readlines__doc__,
621"readlines([size]) -> list\n\
622\n\
623Call readline() repeatedly and return a list of lines read.\n\
624The optional size argument, if given, is an approximate bound on the\n\
625total number of bytes in the lines returned.\n\
626");
627
628/* This is a hacked version of Python's fileobject.c:file_readlines(). */
629static PyObject *
630BZ2File_readlines(BZ2FileObject *self, PyObject *args)
631{
632 long sizehint = 0;
633 PyObject *list = NULL;
634 PyObject *line;
635 char small_buffer[SMALLCHUNK];
636 char *buffer = small_buffer;
637 size_t buffersize = SMALLCHUNK;
638 PyObject *big_buffer = NULL;
639 size_t nfilled = 0;
640 size_t nread;
641 size_t totalread = 0;
642 char *p, *q, *end;
643 int err;
644 int shortread = 0;
645 int bzerror;
646
647 if (!PyArg_ParseTuple(args, "|l:readlines", &sizehint))
648 return NULL;
649
650 ACQUIRE_LOCK(self);
651 switch (self->mode) {
652 case MODE_READ:
653 break;
654 case MODE_READ_EOF:
655 list = PyList_New(0);
656 goto cleanup;
657 case MODE_CLOSED:
658 PyErr_SetString(PyExc_ValueError,
659 "I/O operation on closed file");
660 goto cleanup;
661 default:
662 PyErr_SetString(PyExc_IOError,
663 "file is not ready for reading");
664 goto cleanup;
665 }
666
667 if ((list = PyList_New(0)) == NULL)
668 goto cleanup;
669
670 for (;;) {
671 Py_BEGIN_ALLOW_THREADS
672 nread = Util_UnivNewlineRead(&bzerror, self->fp,
673 buffer+nfilled,
674 buffersize-nfilled, self);
675 self->pos += nread;
676 Py_END_ALLOW_THREADS
677 if (bzerror == BZ_STREAM_END) {
678 self->size = self->pos;
679 self->mode = MODE_READ_EOF;
680 if (nread == 0) {
681 sizehint = 0;
682 break;
683 }
684 shortread = 1;
685 } else if (bzerror != BZ_OK) {
686 Util_CatchBZ2Error(bzerror);
687 error:
688 Py_DECREF(list);
689 list = NULL;
690 goto cleanup;
691 }
692 totalread += nread;
693 p = memchr(buffer+nfilled, '\n', nread);
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000694 if (!shortread && p == NULL) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000695 /* Need a larger buffer to fit this line */
696 nfilled += nread;
697 buffersize *= 2;
698 if (buffersize > INT_MAX) {
699 PyErr_SetString(PyExc_OverflowError,
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000700 "line is longer than a Python string can hold");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000701 goto error;
702 }
703 if (big_buffer == NULL) {
704 /* Create the big buffer */
705 big_buffer = PyString_FromStringAndSize(
706 NULL, buffersize);
707 if (big_buffer == NULL)
708 goto error;
709 buffer = PyString_AS_STRING(big_buffer);
710 memcpy(buffer, small_buffer, nfilled);
711 }
712 else {
713 /* Grow the big buffer */
714 _PyString_Resize(&big_buffer, buffersize);
715 buffer = PyString_AS_STRING(big_buffer);
716 }
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000717 continue;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000718 }
719 end = buffer+nfilled+nread;
720 q = buffer;
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000721 while (p != NULL) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000722 /* Process complete lines */
723 p++;
724 line = PyString_FromStringAndSize(q, p-q);
725 if (line == NULL)
726 goto error;
727 err = PyList_Append(list, line);
728 Py_DECREF(line);
729 if (err != 0)
730 goto error;
731 q = p;
732 p = memchr(q, '\n', end-q);
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000733 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000734 /* Move the remaining incomplete line to the start */
735 nfilled = end-q;
736 memmove(buffer, q, nfilled);
737 if (sizehint > 0)
738 if (totalread >= (size_t)sizehint)
739 break;
740 if (shortread) {
741 sizehint = 0;
742 break;
743 }
744 }
745 if (nfilled != 0) {
746 /* Partial last line */
747 line = PyString_FromStringAndSize(buffer, nfilled);
748 if (line == NULL)
749 goto error;
750 if (sizehint > 0) {
751 /* Need to complete the last line */
752 PyObject *rest = Util_GetLine(self, 0);
753 if (rest == NULL) {
754 Py_DECREF(line);
755 goto error;
756 }
757 PyString_Concat(&line, rest);
758 Py_DECREF(rest);
759 if (line == NULL)
760 goto error;
761 }
762 err = PyList_Append(list, line);
763 Py_DECREF(line);
764 if (err != 0)
765 goto error;
766 }
767
768 cleanup:
769 RELEASE_LOCK(self);
770 if (big_buffer) {
771 Py_DECREF(big_buffer);
772 }
773 return list;
774}
775
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000776PyDoc_STRVAR(BZ2File_xreadlines__doc__,
777"xreadlines() -> self\n\
778\n\
779For backward compatibility. BZ2File objects now include the performance\n\
780optimizations previously implemented in the xreadlines module.\n\
781");
782
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000783PyDoc_STRVAR(BZ2File_write__doc__,
784"write(data) -> None\n\
785\n\
786Write the 'data' string to file. Note that due to buffering, close() may\n\
787be needed before the file on disk reflects the data written.\n\
788");
789
790/* This is a hacked version of Python's fileobject.c:file_write(). */
791static PyObject *
792BZ2File_write(BZ2FileObject *self, PyObject *args)
793{
794 PyObject *ret = NULL;
795 char *buf;
796 int len;
797 int bzerror;
798
Walter Dörwaldbb9c7392004-11-01 17:10:19 +0000799 if (!PyArg_ParseTuple(args, "s#:write", &buf, &len))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000800 return NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000801
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000802 ACQUIRE_LOCK(self);
803 switch (self->mode) {
804 case MODE_WRITE:
805 break;
Tim Peterse3228092002-11-09 04:21:44 +0000806
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000807 case MODE_CLOSED:
808 PyErr_SetString(PyExc_ValueError,
809 "I/O operation on closed file");
Georg Brandl3335a7a2006-08-14 21:42:55 +0000810 goto cleanup;
Tim Peterse3228092002-11-09 04:21:44 +0000811
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000812 default:
813 PyErr_SetString(PyExc_IOError,
814 "file is not ready for writing");
Georg Brandl3335a7a2006-08-14 21:42:55 +0000815 goto cleanup;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000816 }
817
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000818 self->f_softspace = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000819
820 Py_BEGIN_ALLOW_THREADS
821 BZ2_bzWrite (&bzerror, self->fp, buf, len);
822 self->pos += len;
823 Py_END_ALLOW_THREADS
Tim Peterse3228092002-11-09 04:21:44 +0000824
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000825 if (bzerror != BZ_OK) {
826 Util_CatchBZ2Error(bzerror);
827 goto cleanup;
828 }
Tim Peterse3228092002-11-09 04:21:44 +0000829
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000830 Py_INCREF(Py_None);
831 ret = Py_None;
832
833cleanup:
834 RELEASE_LOCK(self);
835 return ret;
836}
837
838PyDoc_STRVAR(BZ2File_writelines__doc__,
839"writelines(sequence_of_strings) -> None\n\
840\n\
841Write the sequence of strings to the file. Note that newlines are not\n\
842added. The sequence can be any iterable object producing strings. This is\n\
843equivalent to calling write() for each string.\n\
844");
845
846/* This is a hacked version of Python's fileobject.c:file_writelines(). */
847static PyObject *
848BZ2File_writelines(BZ2FileObject *self, PyObject *seq)
849{
850#define CHUNKSIZE 1000
851 PyObject *list = NULL;
852 PyObject *iter = NULL;
853 PyObject *ret = NULL;
854 PyObject *line;
855 int i, j, index, len, islist;
856 int bzerror;
857
858 ACQUIRE_LOCK(self);
Georg Brandl3335a7a2006-08-14 21:42:55 +0000859 switch (self->mode) {
860 case MODE_WRITE:
861 break;
862
863 case MODE_CLOSED:
864 PyErr_SetString(PyExc_ValueError,
865 "I/O operation on closed file");
866 goto error;
867
868 default:
869 PyErr_SetString(PyExc_IOError,
870 "file is not ready for writing");
871 goto error;
872 }
873
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000874 islist = PyList_Check(seq);
875 if (!islist) {
876 iter = PyObject_GetIter(seq);
877 if (iter == NULL) {
878 PyErr_SetString(PyExc_TypeError,
879 "writelines() requires an iterable argument");
880 goto error;
881 }
882 list = PyList_New(CHUNKSIZE);
883 if (list == NULL)
884 goto error;
885 }
886
887 /* Strategy: slurp CHUNKSIZE lines into a private list,
888 checking that they are all strings, then write that list
889 without holding the interpreter lock, then come back for more. */
890 for (index = 0; ; index += CHUNKSIZE) {
891 if (islist) {
892 Py_XDECREF(list);
893 list = PyList_GetSlice(seq, index, index+CHUNKSIZE);
894 if (list == NULL)
895 goto error;
896 j = PyList_GET_SIZE(list);
897 }
898 else {
899 for (j = 0; j < CHUNKSIZE; j++) {
900 line = PyIter_Next(iter);
901 if (line == NULL) {
902 if (PyErr_Occurred())
903 goto error;
904 break;
905 }
906 PyList_SetItem(list, j, line);
907 }
908 }
909 if (j == 0)
910 break;
911
912 /* Check that all entries are indeed strings. If not,
913 apply the same rules as for file.write() and
914 convert the rets to strings. This is slow, but
915 seems to be the only way since all conversion APIs
916 could potentially execute Python code. */
917 for (i = 0; i < j; i++) {
918 PyObject *v = PyList_GET_ITEM(list, i);
919 if (!PyString_Check(v)) {
920 const char *buffer;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000921 Py_ssize_t len;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000922 if (PyObject_AsCharBuffer(v, &buffer, &len)) {
923 PyErr_SetString(PyExc_TypeError,
924 "writelines() "
925 "argument must be "
926 "a sequence of "
927 "strings");
928 goto error;
929 }
930 line = PyString_FromStringAndSize(buffer,
931 len);
932 if (line == NULL)
933 goto error;
934 Py_DECREF(v);
935 PyList_SET_ITEM(list, i, line);
936 }
937 }
938
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000939 self->f_softspace = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000940
941 /* Since we are releasing the global lock, the
942 following code may *not* execute Python code. */
943 Py_BEGIN_ALLOW_THREADS
944 for (i = 0; i < j; i++) {
945 line = PyList_GET_ITEM(list, i);
946 len = PyString_GET_SIZE(line);
947 BZ2_bzWrite (&bzerror, self->fp,
948 PyString_AS_STRING(line), len);
949 if (bzerror != BZ_OK) {
950 Py_BLOCK_THREADS
951 Util_CatchBZ2Error(bzerror);
952 goto error;
953 }
954 }
955 Py_END_ALLOW_THREADS
956
957 if (j < CHUNKSIZE)
958 break;
959 }
960
961 Py_INCREF(Py_None);
962 ret = Py_None;
963
964 error:
965 RELEASE_LOCK(self);
966 Py_XDECREF(list);
967 Py_XDECREF(iter);
968 return ret;
969#undef CHUNKSIZE
970}
971
972PyDoc_STRVAR(BZ2File_seek__doc__,
973"seek(offset [, whence]) -> None\n\
974\n\
975Move to new file position. Argument offset is a byte count. Optional\n\
976argument whence defaults to 0 (offset from start of file, offset\n\
977should be >= 0); other values are 1 (move relative to current position,\n\
978positive or negative), and 2 (move relative to end of file, usually\n\
979negative, although many platforms allow seeking beyond the end of a file).\n\
980\n\
981Note that seeking of bz2 files is emulated, and depending on the parameters\n\
982the operation may be extremely slow.\n\
983");
984
985static PyObject *
986BZ2File_seek(BZ2FileObject *self, PyObject *args)
987{
988 int where = 0;
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000989 PyObject *offobj;
990 Py_off_t offset;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000991 char small_buffer[SMALLCHUNK];
992 char *buffer = small_buffer;
993 size_t buffersize = SMALLCHUNK;
Andrew M. Kuchling9333ce12006-12-18 19:26:13 +0000994 Py_off_t bytesread = 0;
Georg Brandla8bcecc2005-09-03 07:49:53 +0000995 size_t readsize;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000996 int chunksize;
997 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000998 PyObject *ret = NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000999
Georg Brandl33a5f2a2005-08-21 14:16:04 +00001000 if (!PyArg_ParseTuple(args, "O|i:seek", &offobj, &where))
1001 return NULL;
1002#if !defined(HAVE_LARGEFILE_SUPPORT)
1003 offset = PyInt_AsLong(offobj);
1004#else
1005 offset = PyLong_Check(offobj) ?
1006 PyLong_AsLongLong(offobj) : PyInt_AsLong(offobj);
1007#endif
1008 if (PyErr_Occurred())
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001009 return NULL;
1010
1011 ACQUIRE_LOCK(self);
1012 Util_DropReadAhead(self);
1013 switch (self->mode) {
1014 case MODE_READ:
1015 case MODE_READ_EOF:
1016 break;
Tim Peterse3228092002-11-09 04:21:44 +00001017
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001018 case MODE_CLOSED:
1019 PyErr_SetString(PyExc_ValueError,
1020 "I/O operation on closed file");
Georg Brandlb14b59f2006-09-25 06:53:42 +00001021 goto cleanup;
Tim Peterse3228092002-11-09 04:21:44 +00001022
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001023 default:
1024 PyErr_SetString(PyExc_IOError,
1025 "seek works only while reading");
Georg Brandlb14b59f2006-09-25 06:53:42 +00001026 goto cleanup;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001027 }
1028
Georg Brandl47fab922006-02-18 21:57:25 +00001029 if (where == 2) {
1030 if (self->size == -1) {
1031 assert(self->mode != MODE_READ_EOF);
1032 for (;;) {
1033 Py_BEGIN_ALLOW_THREADS
1034 chunksize = Util_UnivNewlineRead(
1035 &bzerror, self->fp,
1036 buffer, buffersize,
1037 self);
1038 self->pos += chunksize;
1039 Py_END_ALLOW_THREADS
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001040
Georg Brandl47fab922006-02-18 21:57:25 +00001041 bytesread += chunksize;
1042 if (bzerror == BZ_STREAM_END) {
1043 break;
1044 } else if (bzerror != BZ_OK) {
1045 Util_CatchBZ2Error(bzerror);
1046 goto cleanup;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001047 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001048 }
Georg Brandl47fab922006-02-18 21:57:25 +00001049 self->mode = MODE_READ_EOF;
1050 self->size = self->pos;
1051 bytesread = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001052 }
Georg Brandl47fab922006-02-18 21:57:25 +00001053 offset = self->size + offset;
1054 } else if (where == 1) {
1055 offset = self->pos + offset;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001056 }
1057
Georg Brandl47fab922006-02-18 21:57:25 +00001058 /* Before getting here, offset must be the absolute position the file
1059 * pointer should be set to. */
1060
1061 if (offset >= self->pos) {
1062 /* we can move forward */
1063 offset -= self->pos;
1064 } else {
1065 /* we cannot move back, so rewind the stream */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001066 BZ2_bzReadClose(&bzerror, self->fp);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001067 if (bzerror != BZ_OK) {
1068 Util_CatchBZ2Error(bzerror);
1069 goto cleanup;
1070 }
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001071 ret = PyObject_CallMethod(self->file, "seek", "(i)", 0);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001072 if (!ret)
1073 goto cleanup;
1074 Py_DECREF(ret);
1075 ret = NULL;
1076 self->pos = 0;
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001077 self->fp = BZ2_bzReadOpen(&bzerror, PyFile_AsFile(self->file),
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001078 0, 0, NULL, 0);
1079 if (bzerror != BZ_OK) {
1080 Util_CatchBZ2Error(bzerror);
1081 goto cleanup;
1082 }
1083 self->mode = MODE_READ;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001084 }
1085
Georg Brandl47fab922006-02-18 21:57:25 +00001086 if (offset <= 0 || self->mode == MODE_READ_EOF)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001087 goto exit;
1088
1089 /* Before getting here, offset must be set to the number of bytes
1090 * to walk forward. */
1091 for (;;) {
Georg Brandla8bcecc2005-09-03 07:49:53 +00001092 if (offset-bytesread > buffersize)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001093 readsize = buffersize;
1094 else
Georg Brandla8bcecc2005-09-03 07:49:53 +00001095 /* offset might be wider that readsize, but the result
1096 * of the subtraction is bound by buffersize (see the
1097 * condition above). buffersize is 8192. */
1098 readsize = (size_t)(offset-bytesread);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001099 Py_BEGIN_ALLOW_THREADS
1100 chunksize = Util_UnivNewlineRead(&bzerror, self->fp,
1101 buffer, readsize, self);
1102 self->pos += chunksize;
1103 Py_END_ALLOW_THREADS
1104 bytesread += chunksize;
1105 if (bzerror == BZ_STREAM_END) {
1106 self->size = self->pos;
1107 self->mode = MODE_READ_EOF;
1108 break;
1109 } else if (bzerror != BZ_OK) {
1110 Util_CatchBZ2Error(bzerror);
1111 goto cleanup;
1112 }
1113 if (bytesread == offset)
1114 break;
1115 }
1116
1117exit:
1118 Py_INCREF(Py_None);
1119 ret = Py_None;
1120
1121cleanup:
1122 RELEASE_LOCK(self);
1123 return ret;
1124}
1125
1126PyDoc_STRVAR(BZ2File_tell__doc__,
1127"tell() -> int\n\
1128\n\
1129Return the current file position, an integer (may be a long integer).\n\
1130");
1131
1132static PyObject *
1133BZ2File_tell(BZ2FileObject *self, PyObject *args)
1134{
1135 PyObject *ret = NULL;
1136
1137 if (self->mode == MODE_CLOSED) {
1138 PyErr_SetString(PyExc_ValueError,
1139 "I/O operation on closed file");
1140 goto cleanup;
1141 }
1142
Georg Brandla8bcecc2005-09-03 07:49:53 +00001143#if !defined(HAVE_LARGEFILE_SUPPORT)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001144 ret = PyInt_FromLong(self->pos);
Georg Brandla8bcecc2005-09-03 07:49:53 +00001145#else
1146 ret = PyLong_FromLongLong(self->pos);
1147#endif
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001148
1149cleanup:
1150 return ret;
1151}
1152
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001153PyDoc_STRVAR(BZ2File_close__doc__,
1154"close() -> None or (perhaps) an integer\n\
1155\n\
1156Close the file. Sets data attribute .closed to true. A closed file\n\
1157cannot be used for further I/O operations. close() may be called more\n\
1158than once without error.\n\
1159");
1160
1161static PyObject *
1162BZ2File_close(BZ2FileObject *self)
1163{
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001164 PyObject *ret = NULL;
1165 int bzerror = BZ_OK;
1166
1167 ACQUIRE_LOCK(self);
1168 switch (self->mode) {
1169 case MODE_READ:
1170 case MODE_READ_EOF:
1171 BZ2_bzReadClose(&bzerror, self->fp);
1172 break;
1173 case MODE_WRITE:
1174 BZ2_bzWriteClose(&bzerror, self->fp,
1175 0, NULL, NULL);
1176 break;
1177 }
1178 self->mode = MODE_CLOSED;
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001179 ret = PyObject_CallMethod(self->file, "close", NULL);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001180 if (bzerror != BZ_OK) {
1181 Util_CatchBZ2Error(bzerror);
1182 Py_XDECREF(ret);
1183 ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001184 }
1185
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001186 RELEASE_LOCK(self);
1187 return ret;
1188}
1189
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001190static PyObject *BZ2File_getiter(BZ2FileObject *self);
1191
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001192static PyMethodDef BZ2File_methods[] = {
1193 {"read", (PyCFunction)BZ2File_read, METH_VARARGS, BZ2File_read__doc__},
1194 {"readline", (PyCFunction)BZ2File_readline, METH_VARARGS, BZ2File_readline__doc__},
1195 {"readlines", (PyCFunction)BZ2File_readlines, METH_VARARGS, BZ2File_readlines__doc__},
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001196 {"xreadlines", (PyCFunction)BZ2File_getiter, METH_VARARGS, BZ2File_xreadlines__doc__},
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001197 {"write", (PyCFunction)BZ2File_write, METH_VARARGS, BZ2File_write__doc__},
1198 {"writelines", (PyCFunction)BZ2File_writelines, METH_O, BZ2File_writelines__doc__},
1199 {"seek", (PyCFunction)BZ2File_seek, METH_VARARGS, BZ2File_seek__doc__},
1200 {"tell", (PyCFunction)BZ2File_tell, METH_NOARGS, BZ2File_tell__doc__},
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001201 {"close", (PyCFunction)BZ2File_close, METH_NOARGS, BZ2File_close__doc__},
1202 {NULL, NULL} /* sentinel */
1203};
1204
1205
1206/* ===================================================================== */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001207/* Getters and setters of BZ2File. */
1208
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001209/* This is a hacked version of Python's fileobject.c:get_newlines(). */
1210static PyObject *
1211BZ2File_get_newlines(BZ2FileObject *self, void *closure)
1212{
1213 switch (self->f_newlinetypes) {
1214 case NEWLINE_UNKNOWN:
1215 Py_INCREF(Py_None);
1216 return Py_None;
1217 case NEWLINE_CR:
1218 return PyString_FromString("\r");
1219 case NEWLINE_LF:
1220 return PyString_FromString("\n");
1221 case NEWLINE_CR|NEWLINE_LF:
1222 return Py_BuildValue("(ss)", "\r", "\n");
1223 case NEWLINE_CRLF:
1224 return PyString_FromString("\r\n");
1225 case NEWLINE_CR|NEWLINE_CRLF:
1226 return Py_BuildValue("(ss)", "\r", "\r\n");
1227 case NEWLINE_LF|NEWLINE_CRLF:
1228 return Py_BuildValue("(ss)", "\n", "\r\n");
1229 case NEWLINE_CR|NEWLINE_LF|NEWLINE_CRLF:
1230 return Py_BuildValue("(sss)", "\r", "\n", "\r\n");
1231 default:
1232 PyErr_Format(PyExc_SystemError,
1233 "Unknown newlines value 0x%x\n",
1234 self->f_newlinetypes);
1235 return NULL;
1236 }
1237}
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001238
1239static PyObject *
1240BZ2File_get_closed(BZ2FileObject *self, void *closure)
1241{
1242 return PyInt_FromLong(self->mode == MODE_CLOSED);
1243}
1244
1245static PyObject *
1246BZ2File_get_mode(BZ2FileObject *self, void *closure)
1247{
1248 return PyObject_GetAttrString(self->file, "mode");
1249}
1250
1251static PyObject *
1252BZ2File_get_name(BZ2FileObject *self, void *closure)
1253{
1254 return PyObject_GetAttrString(self->file, "name");
1255}
1256
1257static PyGetSetDef BZ2File_getset[] = {
1258 {"closed", (getter)BZ2File_get_closed, NULL,
1259 "True if the file is closed"},
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001260 {"newlines", (getter)BZ2File_get_newlines, NULL,
1261 "end-of-line convention used in this file"},
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001262 {"mode", (getter)BZ2File_get_mode, NULL,
1263 "file mode ('r', 'w', or 'U')"},
1264 {"name", (getter)BZ2File_get_name, NULL,
1265 "file name"},
1266 {NULL} /* Sentinel */
1267};
1268
1269
1270/* ===================================================================== */
1271/* Members of BZ2File_Type. */
1272
1273#undef OFF
1274#define OFF(x) offsetof(BZ2FileObject, x)
1275
1276static PyMemberDef BZ2File_members[] = {
1277 {"softspace", T_INT, OFF(f_softspace), 0,
1278 "flag indicating that a space needs to be printed; used by print"},
1279 {NULL} /* Sentinel */
1280};
1281
1282/* ===================================================================== */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001283/* Slot definitions for BZ2File_Type. */
1284
1285static int
1286BZ2File_init(BZ2FileObject *self, PyObject *args, PyObject *kwargs)
1287{
Martin v. Löwis15e62742006-02-27 16:46:16 +00001288 static char *kwlist[] = {"filename", "mode", "buffering",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001289 "compresslevel", 0};
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001290 PyObject *name;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001291 char *mode = "r";
1292 int buffering = -1;
1293 int compresslevel = 9;
1294 int bzerror;
1295 int mode_char = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001296
1297 self->size = -1;
Tim Peterse3228092002-11-09 04:21:44 +00001298
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001299 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|sii:BZ2File",
1300 kwlist, &name, &mode, &buffering,
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001301 &compresslevel))
1302 return -1;
1303
1304 if (compresslevel < 1 || compresslevel > 9) {
1305 PyErr_SetString(PyExc_ValueError,
1306 "compresslevel must be between 1 and 9");
1307 return -1;
1308 }
1309
1310 for (;;) {
1311 int error = 0;
1312 switch (*mode) {
1313 case 'r':
1314 case 'w':
1315 if (mode_char)
1316 error = 1;
1317 mode_char = *mode;
1318 break;
1319
1320 case 'b':
1321 break;
1322
1323 case 'U':
Neal Norwitz2a30cd02006-07-10 01:18:57 +00001324#ifdef __VMS
1325 self->f_univ_newline = 0;
1326#else
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001327 self->f_univ_newline = 1;
Neal Norwitz2a30cd02006-07-10 01:18:57 +00001328#endif
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001329 break;
1330
1331 default:
1332 error = 1;
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001333 break;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001334 }
1335 if (error) {
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001336 PyErr_Format(PyExc_ValueError,
1337 "invalid mode char %c", *mode);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001338 return -1;
1339 }
1340 mode++;
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001341 if (*mode == '\0')
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001342 break;
1343 }
1344
Georg Brandl6b95f1d2005-06-03 19:47:00 +00001345 if (mode_char == 0) {
1346 mode_char = 'r';
1347 }
1348
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001349 mode = (mode_char == 'r') ? "rb" : "wb";
Tim Peterse3228092002-11-09 04:21:44 +00001350
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001351 self->file = PyObject_CallFunction((PyObject*)&PyFile_Type, "(Osi)",
1352 name, mode, buffering);
1353 if (self->file == NULL)
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001354 return -1;
1355
1356 /* From now on, we have stuff to dealloc, so jump to error label
1357 * instead of returning */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001358
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001359#ifdef WITH_THREAD
1360 self->lock = PyThread_allocate_lock();
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001361 if (!self->lock) {
1362 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001363 goto error;
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001364 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001365#endif
1366
1367 if (mode_char == 'r')
1368 self->fp = BZ2_bzReadOpen(&bzerror,
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001369 PyFile_AsFile(self->file),
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001370 0, 0, NULL, 0);
1371 else
1372 self->fp = BZ2_bzWriteOpen(&bzerror,
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001373 PyFile_AsFile(self->file),
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001374 compresslevel, 0, 0);
1375
1376 if (bzerror != BZ_OK) {
1377 Util_CatchBZ2Error(bzerror);
1378 goto error;
1379 }
1380
1381 self->mode = (mode_char == 'r') ? MODE_READ : MODE_WRITE;
1382
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001383 return 0;
1384
1385error:
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001386 Py_CLEAR(self->file);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001387#ifdef WITH_THREAD
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001388 if (self->lock) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001389 PyThread_free_lock(self->lock);
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001390 self->lock = NULL;
1391 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001392#endif
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001393 return -1;
1394}
1395
1396static void
1397BZ2File_dealloc(BZ2FileObject *self)
1398{
1399 int bzerror;
1400#ifdef WITH_THREAD
1401 if (self->lock)
1402 PyThread_free_lock(self->lock);
1403#endif
1404 switch (self->mode) {
1405 case MODE_READ:
1406 case MODE_READ_EOF:
1407 BZ2_bzReadClose(&bzerror, self->fp);
1408 break;
1409 case MODE_WRITE:
1410 BZ2_bzWriteClose(&bzerror, self->fp,
1411 0, NULL, NULL);
1412 break;
1413 }
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001414 Util_DropReadAhead(self);
Gustavo Niemeyer572f5232003-04-29 14:53:08 +00001415 Py_XDECREF(self->file);
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001416 self->ob_type->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001417}
1418
1419/* This is a hacked version of Python's fileobject.c:file_getiter(). */
1420static PyObject *
1421BZ2File_getiter(BZ2FileObject *self)
1422{
1423 if (self->mode == MODE_CLOSED) {
1424 PyErr_SetString(PyExc_ValueError,
1425 "I/O operation on closed file");
1426 return NULL;
1427 }
1428 Py_INCREF((PyObject*)self);
1429 return (PyObject *)self;
1430}
1431
1432/* This is a hacked version of Python's fileobject.c:file_iternext(). */
1433#define READAHEAD_BUFSIZE 8192
1434static PyObject *
1435BZ2File_iternext(BZ2FileObject *self)
1436{
1437 PyStringObject* ret;
1438 ACQUIRE_LOCK(self);
1439 if (self->mode == MODE_CLOSED) {
Gregory P. Smith7a076be2008-08-17 23:06:19 +00001440 RELEASE_LOCK(self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001441 PyErr_SetString(PyExc_ValueError,
1442 "I/O operation on closed file");
1443 return NULL;
1444 }
1445 ret = Util_ReadAheadGetLineSkip(self, 0, READAHEAD_BUFSIZE);
1446 RELEASE_LOCK(self);
1447 if (ret == NULL || PyString_GET_SIZE(ret) == 0) {
1448 Py_XDECREF(ret);
1449 return NULL;
1450 }
1451 return (PyObject *)ret;
1452}
1453
1454/* ===================================================================== */
1455/* BZ2File_Type definition. */
1456
1457PyDoc_VAR(BZ2File__doc__) =
1458PyDoc_STR(
1459"BZ2File(name [, mode='r', buffering=0, compresslevel=9]) -> file object\n\
1460\n\
1461Open a bz2 file. The mode can be 'r' or 'w', for reading (default) or\n\
1462writing. When opened for writing, the file will be created if it doesn't\n\
1463exist, and truncated otherwise. If the buffering argument is given, 0 means\n\
1464unbuffered, and larger numbers specify the buffer size. If compresslevel\n\
1465is given, must be a number between 1 and 9.\n\
1466")
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001467PyDoc_STR(
1468"\n\
1469Add a 'U' to mode to open the file for input with universal newline\n\
1470support. Any line ending in the input file will be seen as a '\\n' in\n\
1471Python. Also, a file so opened gains the attribute 'newlines'; the value\n\
1472for this attribute is one of None (no newline read yet), '\\r', '\\n',\n\
1473'\\r\\n' or a tuple containing all the newline types seen. Universal\n\
1474newlines are available only when reading.\n\
1475")
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001476;
1477
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001478static PyTypeObject BZ2File_Type = {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001479 PyObject_HEAD_INIT(NULL)
1480 0, /*ob_size*/
1481 "bz2.BZ2File", /*tp_name*/
1482 sizeof(BZ2FileObject), /*tp_basicsize*/
1483 0, /*tp_itemsize*/
1484 (destructor)BZ2File_dealloc, /*tp_dealloc*/
1485 0, /*tp_print*/
1486 0, /*tp_getattr*/
1487 0, /*tp_setattr*/
1488 0, /*tp_compare*/
1489 0, /*tp_repr*/
1490 0, /*tp_as_number*/
1491 0, /*tp_as_sequence*/
1492 0, /*tp_as_mapping*/
1493 0, /*tp_hash*/
1494 0, /*tp_call*/
1495 0, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001496 PyObject_GenericGetAttr,/*tp_getattro*/
1497 PyObject_GenericSetAttr,/*tp_setattro*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001498 0, /*tp_as_buffer*/
1499 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1500 BZ2File__doc__, /*tp_doc*/
1501 0, /*tp_traverse*/
1502 0, /*tp_clear*/
1503 0, /*tp_richcompare*/
1504 0, /*tp_weaklistoffset*/
1505 (getiterfunc)BZ2File_getiter, /*tp_iter*/
1506 (iternextfunc)BZ2File_iternext, /*tp_iternext*/
1507 BZ2File_methods, /*tp_methods*/
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001508 BZ2File_members, /*tp_members*/
1509 BZ2File_getset, /*tp_getset*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001510 0, /*tp_base*/
1511 0, /*tp_dict*/
1512 0, /*tp_descr_get*/
1513 0, /*tp_descr_set*/
1514 0, /*tp_dictoffset*/
1515 (initproc)BZ2File_init, /*tp_init*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001516 PyType_GenericAlloc, /*tp_alloc*/
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001517 PyType_GenericNew, /*tp_new*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001518 _PyObject_Del, /*tp_free*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001519 0, /*tp_is_gc*/
1520};
1521
1522
1523/* ===================================================================== */
1524/* Methods of BZ2Comp. */
1525
1526PyDoc_STRVAR(BZ2Comp_compress__doc__,
1527"compress(data) -> string\n\
1528\n\
1529Provide more data to the compressor object. It will return chunks of\n\
1530compressed data whenever possible. When you've finished providing data\n\
1531to compress, call the flush() method to finish the compression process,\n\
1532and return what is left in the internal buffers.\n\
1533");
1534
1535static PyObject *
1536BZ2Comp_compress(BZ2CompObject *self, PyObject *args)
1537{
1538 char *data;
1539 int datasize;
1540 int bufsize = SMALLCHUNK;
Martin v. Löwisb9a0f912003-03-29 10:06:18 +00001541 PY_LONG_LONG totalout;
Gustavo Niemeyer7d7930b2002-11-05 18:41:53 +00001542 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001543 bz_stream *bzs = &self->bzs;
1544 int bzerror;
1545
Walter Dörwaldbb9c7392004-11-01 17:10:19 +00001546 if (!PyArg_ParseTuple(args, "s#:compress", &data, &datasize))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001547 return NULL;
1548
Gustavo Niemeyera6e436e2004-02-14 00:02:45 +00001549 if (datasize == 0)
1550 return PyString_FromString("");
1551
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001552 ACQUIRE_LOCK(self);
1553 if (!self->running) {
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001554 PyErr_SetString(PyExc_ValueError,
1555 "this object was already flushed");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001556 goto error;
1557 }
1558
1559 ret = PyString_FromStringAndSize(NULL, bufsize);
1560 if (!ret)
1561 goto error;
1562
1563 bzs->next_in = data;
1564 bzs->avail_in = datasize;
1565 bzs->next_out = BUF(ret);
1566 bzs->avail_out = bufsize;
1567
1568 totalout = BZS_TOTAL_OUT(bzs);
1569
1570 for (;;) {
1571 Py_BEGIN_ALLOW_THREADS
1572 bzerror = BZ2_bzCompress(bzs, BZ_RUN);
1573 Py_END_ALLOW_THREADS
1574 if (bzerror != BZ_RUN_OK) {
1575 Util_CatchBZ2Error(bzerror);
1576 goto error;
1577 }
Georg Brandld6e73c12007-03-13 12:34:35 +00001578 if (bzs->avail_in == 0)
1579 break; /* no more input data */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001580 if (bzs->avail_out == 0) {
1581 bufsize = Util_NewBufferSize(bufsize);
1582 if (_PyString_Resize(&ret, bufsize) < 0) {
1583 BZ2_bzCompressEnd(bzs);
1584 goto error;
1585 }
1586 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs)
1587 - totalout);
1588 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001589 }
1590 }
1591
Neal Norwitz047f3c72006-06-12 02:06:42 +00001592 _PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001593
1594 RELEASE_LOCK(self);
1595 return ret;
1596
1597error:
1598 RELEASE_LOCK(self);
1599 Py_XDECREF(ret);
1600 return NULL;
1601}
1602
1603PyDoc_STRVAR(BZ2Comp_flush__doc__,
1604"flush() -> string\n\
1605\n\
1606Finish the compression process and return what is left in internal buffers.\n\
1607You must not use the compressor object after calling this method.\n\
1608");
1609
1610static PyObject *
1611BZ2Comp_flush(BZ2CompObject *self)
1612{
1613 int bufsize = SMALLCHUNK;
Gustavo Niemeyer7d7930b2002-11-05 18:41:53 +00001614 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001615 bz_stream *bzs = &self->bzs;
Martin v. Löwisb9a0f912003-03-29 10:06:18 +00001616 PY_LONG_LONG totalout;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001617 int bzerror;
1618
1619 ACQUIRE_LOCK(self);
1620 if (!self->running) {
1621 PyErr_SetString(PyExc_ValueError, "object was already "
1622 "flushed");
1623 goto error;
1624 }
1625 self->running = 0;
1626
1627 ret = PyString_FromStringAndSize(NULL, bufsize);
1628 if (!ret)
1629 goto error;
1630
1631 bzs->next_out = BUF(ret);
1632 bzs->avail_out = bufsize;
1633
1634 totalout = BZS_TOTAL_OUT(bzs);
1635
1636 for (;;) {
1637 Py_BEGIN_ALLOW_THREADS
1638 bzerror = BZ2_bzCompress(bzs, BZ_FINISH);
1639 Py_END_ALLOW_THREADS
1640 if (bzerror == BZ_STREAM_END) {
1641 break;
1642 } else if (bzerror != BZ_FINISH_OK) {
1643 Util_CatchBZ2Error(bzerror);
1644 goto error;
1645 }
1646 if (bzs->avail_out == 0) {
1647 bufsize = Util_NewBufferSize(bufsize);
1648 if (_PyString_Resize(&ret, bufsize) < 0)
1649 goto error;
1650 bzs->next_out = BUF(ret);
1651 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs)
1652 - totalout);
1653 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
1654 }
1655 }
1656
1657 if (bzs->avail_out != 0)
Neal Norwitz047f3c72006-06-12 02:06:42 +00001658 _PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001659
1660 RELEASE_LOCK(self);
1661 return ret;
1662
1663error:
1664 RELEASE_LOCK(self);
1665 Py_XDECREF(ret);
1666 return NULL;
1667}
1668
1669static PyMethodDef BZ2Comp_methods[] = {
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001670 {"compress", (PyCFunction)BZ2Comp_compress, METH_VARARGS,
1671 BZ2Comp_compress__doc__},
1672 {"flush", (PyCFunction)BZ2Comp_flush, METH_NOARGS,
1673 BZ2Comp_flush__doc__},
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001674 {NULL, NULL} /* sentinel */
1675};
1676
1677
1678/* ===================================================================== */
1679/* Slot definitions for BZ2Comp_Type. */
1680
1681static int
1682BZ2Comp_init(BZ2CompObject *self, PyObject *args, PyObject *kwargs)
1683{
1684 int compresslevel = 9;
1685 int bzerror;
Martin v. Löwis15e62742006-02-27 16:46:16 +00001686 static char *kwlist[] = {"compresslevel", 0};
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001687
1688 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:BZ2Compressor",
1689 kwlist, &compresslevel))
1690 return -1;
1691
1692 if (compresslevel < 1 || compresslevel > 9) {
1693 PyErr_SetString(PyExc_ValueError,
1694 "compresslevel must be between 1 and 9");
1695 goto error;
1696 }
1697
1698#ifdef WITH_THREAD
1699 self->lock = PyThread_allocate_lock();
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001700 if (!self->lock) {
1701 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001702 goto error;
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001703 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001704#endif
1705
1706 memset(&self->bzs, 0, sizeof(bz_stream));
1707 bzerror = BZ2_bzCompressInit(&self->bzs, compresslevel, 0, 0);
1708 if (bzerror != BZ_OK) {
1709 Util_CatchBZ2Error(bzerror);
1710 goto error;
1711 }
1712
1713 self->running = 1;
1714
1715 return 0;
1716error:
1717#ifdef WITH_THREAD
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001718 if (self->lock) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001719 PyThread_free_lock(self->lock);
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001720 self->lock = NULL;
1721 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001722#endif
1723 return -1;
1724}
1725
1726static void
1727BZ2Comp_dealloc(BZ2CompObject *self)
1728{
1729#ifdef WITH_THREAD
1730 if (self->lock)
1731 PyThread_free_lock(self->lock);
1732#endif
1733 BZ2_bzCompressEnd(&self->bzs);
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001734 self->ob_type->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001735}
1736
1737
1738/* ===================================================================== */
1739/* BZ2Comp_Type definition. */
1740
1741PyDoc_STRVAR(BZ2Comp__doc__,
1742"BZ2Compressor([compresslevel=9]) -> compressor object\n\
1743\n\
1744Create a new compressor object. This object may be used to compress\n\
1745data sequentially. If you want to compress data in one shot, use the\n\
1746compress() function instead. The compresslevel parameter, if given,\n\
1747must be a number between 1 and 9.\n\
1748");
1749
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001750static PyTypeObject BZ2Comp_Type = {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001751 PyObject_HEAD_INIT(NULL)
1752 0, /*ob_size*/
1753 "bz2.BZ2Compressor", /*tp_name*/
1754 sizeof(BZ2CompObject), /*tp_basicsize*/
1755 0, /*tp_itemsize*/
1756 (destructor)BZ2Comp_dealloc, /*tp_dealloc*/
1757 0, /*tp_print*/
1758 0, /*tp_getattr*/
1759 0, /*tp_setattr*/
1760 0, /*tp_compare*/
1761 0, /*tp_repr*/
1762 0, /*tp_as_number*/
1763 0, /*tp_as_sequence*/
1764 0, /*tp_as_mapping*/
1765 0, /*tp_hash*/
1766 0, /*tp_call*/
1767 0, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001768 PyObject_GenericGetAttr,/*tp_getattro*/
1769 PyObject_GenericSetAttr,/*tp_setattro*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001770 0, /*tp_as_buffer*/
1771 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1772 BZ2Comp__doc__, /*tp_doc*/
1773 0, /*tp_traverse*/
1774 0, /*tp_clear*/
1775 0, /*tp_richcompare*/
1776 0, /*tp_weaklistoffset*/
1777 0, /*tp_iter*/
1778 0, /*tp_iternext*/
1779 BZ2Comp_methods, /*tp_methods*/
1780 0, /*tp_members*/
1781 0, /*tp_getset*/
1782 0, /*tp_base*/
1783 0, /*tp_dict*/
1784 0, /*tp_descr_get*/
1785 0, /*tp_descr_set*/
1786 0, /*tp_dictoffset*/
1787 (initproc)BZ2Comp_init, /*tp_init*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001788 PyType_GenericAlloc, /*tp_alloc*/
1789 PyType_GenericNew, /*tp_new*/
1790 _PyObject_Del, /*tp_free*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001791 0, /*tp_is_gc*/
1792};
1793
1794
1795/* ===================================================================== */
1796/* Members of BZ2Decomp. */
1797
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001798#undef OFF
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001799#define OFF(x) offsetof(BZ2DecompObject, x)
1800
1801static PyMemberDef BZ2Decomp_members[] = {
1802 {"unused_data", T_OBJECT, OFF(unused_data), RO},
1803 {NULL} /* Sentinel */
1804};
1805
1806
1807/* ===================================================================== */
1808/* Methods of BZ2Decomp. */
1809
1810PyDoc_STRVAR(BZ2Decomp_decompress__doc__,
1811"decompress(data) -> string\n\
1812\n\
1813Provide more data to the decompressor object. It will return chunks\n\
1814of decompressed data whenever possible. If you try to decompress data\n\
1815after the end of stream is found, EOFError will be raised. If any data\n\
1816was found after the end of stream, it'll be ignored and saved in\n\
1817unused_data attribute.\n\
1818");
1819
1820static PyObject *
1821BZ2Decomp_decompress(BZ2DecompObject *self, PyObject *args)
1822{
1823 char *data;
1824 int datasize;
1825 int bufsize = SMALLCHUNK;
Martin v. Löwisb9a0f912003-03-29 10:06:18 +00001826 PY_LONG_LONG totalout;
Neal Norwitz18142c02002-11-05 18:17:32 +00001827 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001828 bz_stream *bzs = &self->bzs;
1829 int bzerror;
1830
Walter Dörwaldbb9c7392004-11-01 17:10:19 +00001831 if (!PyArg_ParseTuple(args, "s#:decompress", &data, &datasize))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001832 return NULL;
1833
1834 ACQUIRE_LOCK(self);
1835 if (!self->running) {
1836 PyErr_SetString(PyExc_EOFError, "end of stream was "
1837 "already found");
1838 goto error;
1839 }
1840
1841 ret = PyString_FromStringAndSize(NULL, bufsize);
1842 if (!ret)
1843 goto error;
1844
1845 bzs->next_in = data;
1846 bzs->avail_in = datasize;
1847 bzs->next_out = BUF(ret);
1848 bzs->avail_out = bufsize;
1849
1850 totalout = BZS_TOTAL_OUT(bzs);
1851
1852 for (;;) {
1853 Py_BEGIN_ALLOW_THREADS
1854 bzerror = BZ2_bzDecompress(bzs);
1855 Py_END_ALLOW_THREADS
1856 if (bzerror == BZ_STREAM_END) {
1857 if (bzs->avail_in != 0) {
1858 Py_DECREF(self->unused_data);
1859 self->unused_data =
1860 PyString_FromStringAndSize(bzs->next_in,
1861 bzs->avail_in);
1862 }
1863 self->running = 0;
1864 break;
1865 }
1866 if (bzerror != BZ_OK) {
1867 Util_CatchBZ2Error(bzerror);
1868 goto error;
1869 }
Georg Brandld6e73c12007-03-13 12:34:35 +00001870 if (bzs->avail_in == 0)
1871 break; /* no more input data */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001872 if (bzs->avail_out == 0) {
1873 bufsize = Util_NewBufferSize(bufsize);
1874 if (_PyString_Resize(&ret, bufsize) < 0) {
1875 BZ2_bzDecompressEnd(bzs);
1876 goto error;
1877 }
1878 bzs->next_out = BUF(ret);
1879 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs)
1880 - totalout);
1881 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001882 }
1883 }
1884
1885 if (bzs->avail_out != 0)
Neal Norwitz047f3c72006-06-12 02:06:42 +00001886 _PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001887
1888 RELEASE_LOCK(self);
1889 return ret;
1890
1891error:
1892 RELEASE_LOCK(self);
1893 Py_XDECREF(ret);
1894 return NULL;
1895}
1896
1897static PyMethodDef BZ2Decomp_methods[] = {
1898 {"decompress", (PyCFunction)BZ2Decomp_decompress, METH_VARARGS, BZ2Decomp_decompress__doc__},
1899 {NULL, NULL} /* sentinel */
1900};
1901
1902
1903/* ===================================================================== */
1904/* Slot definitions for BZ2Decomp_Type. */
1905
1906static int
1907BZ2Decomp_init(BZ2DecompObject *self, PyObject *args, PyObject *kwargs)
1908{
1909 int bzerror;
1910
1911 if (!PyArg_ParseTuple(args, ":BZ2Decompressor"))
1912 return -1;
1913
1914#ifdef WITH_THREAD
1915 self->lock = PyThread_allocate_lock();
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001916 if (!self->lock) {
1917 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001918 goto error;
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001919 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001920#endif
1921
1922 self->unused_data = PyString_FromString("");
1923 if (!self->unused_data)
1924 goto error;
1925
1926 memset(&self->bzs, 0, sizeof(bz_stream));
1927 bzerror = BZ2_bzDecompressInit(&self->bzs, 0, 0);
1928 if (bzerror != BZ_OK) {
1929 Util_CatchBZ2Error(bzerror);
1930 goto error;
1931 }
1932
1933 self->running = 1;
1934
1935 return 0;
1936
1937error:
1938#ifdef WITH_THREAD
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001939 if (self->lock) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001940 PyThread_free_lock(self->lock);
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001941 self->lock = NULL;
1942 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001943#endif
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001944 Py_CLEAR(self->unused_data);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001945 return -1;
1946}
1947
1948static void
1949BZ2Decomp_dealloc(BZ2DecompObject *self)
1950{
1951#ifdef WITH_THREAD
1952 if (self->lock)
1953 PyThread_free_lock(self->lock);
1954#endif
1955 Py_XDECREF(self->unused_data);
1956 BZ2_bzDecompressEnd(&self->bzs);
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001957 self->ob_type->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001958}
1959
1960
1961/* ===================================================================== */
1962/* BZ2Decomp_Type definition. */
1963
1964PyDoc_STRVAR(BZ2Decomp__doc__,
1965"BZ2Decompressor() -> decompressor object\n\
1966\n\
1967Create a new decompressor object. This object may be used to decompress\n\
1968data sequentially. If you want to decompress data in one shot, use the\n\
1969decompress() function instead.\n\
1970");
1971
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001972static PyTypeObject BZ2Decomp_Type = {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001973 PyObject_HEAD_INIT(NULL)
1974 0, /*ob_size*/
1975 "bz2.BZ2Decompressor", /*tp_name*/
1976 sizeof(BZ2DecompObject), /*tp_basicsize*/
1977 0, /*tp_itemsize*/
1978 (destructor)BZ2Decomp_dealloc, /*tp_dealloc*/
1979 0, /*tp_print*/
1980 0, /*tp_getattr*/
1981 0, /*tp_setattr*/
1982 0, /*tp_compare*/
1983 0, /*tp_repr*/
1984 0, /*tp_as_number*/
1985 0, /*tp_as_sequence*/
1986 0, /*tp_as_mapping*/
1987 0, /*tp_hash*/
1988 0, /*tp_call*/
1989 0, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001990 PyObject_GenericGetAttr,/*tp_getattro*/
1991 PyObject_GenericSetAttr,/*tp_setattro*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001992 0, /*tp_as_buffer*/
1993 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1994 BZ2Decomp__doc__, /*tp_doc*/
1995 0, /*tp_traverse*/
1996 0, /*tp_clear*/
1997 0, /*tp_richcompare*/
1998 0, /*tp_weaklistoffset*/
1999 0, /*tp_iter*/
2000 0, /*tp_iternext*/
2001 BZ2Decomp_methods, /*tp_methods*/
2002 BZ2Decomp_members, /*tp_members*/
2003 0, /*tp_getset*/
2004 0, /*tp_base*/
2005 0, /*tp_dict*/
2006 0, /*tp_descr_get*/
2007 0, /*tp_descr_set*/
2008 0, /*tp_dictoffset*/
2009 (initproc)BZ2Decomp_init, /*tp_init*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00002010 PyType_GenericAlloc, /*tp_alloc*/
2011 PyType_GenericNew, /*tp_new*/
2012 _PyObject_Del, /*tp_free*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002013 0, /*tp_is_gc*/
2014};
2015
2016
2017/* ===================================================================== */
2018/* Module functions. */
2019
2020PyDoc_STRVAR(bz2_compress__doc__,
2021"compress(data [, compresslevel=9]) -> string\n\
2022\n\
2023Compress data in one shot. If you want to compress data sequentially,\n\
2024use an instance of BZ2Compressor instead. The compresslevel parameter, if\n\
2025given, must be a number between 1 and 9.\n\
2026");
2027
2028static PyObject *
2029bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
2030{
2031 int compresslevel=9;
2032 char *data;
2033 int datasize;
2034 int bufsize;
Gustavo Niemeyer7d7930b2002-11-05 18:41:53 +00002035 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002036 bz_stream _bzs;
2037 bz_stream *bzs = &_bzs;
2038 int bzerror;
Martin v. Löwis15e62742006-02-27 16:46:16 +00002039 static char *kwlist[] = {"data", "compresslevel", 0};
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002040
2041 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|i",
2042 kwlist, &data, &datasize,
2043 &compresslevel))
2044 return NULL;
2045
2046 if (compresslevel < 1 || compresslevel > 9) {
2047 PyErr_SetString(PyExc_ValueError,
2048 "compresslevel must be between 1 and 9");
2049 return NULL;
2050 }
2051
2052 /* Conforming to bz2 manual, this is large enough to fit compressed
2053 * data in one shot. We will check it later anyway. */
2054 bufsize = datasize + (datasize/100+1) + 600;
2055
2056 ret = PyString_FromStringAndSize(NULL, bufsize);
2057 if (!ret)
2058 return NULL;
2059
2060 memset(bzs, 0, sizeof(bz_stream));
2061
2062 bzs->next_in = data;
2063 bzs->avail_in = datasize;
2064 bzs->next_out = BUF(ret);
2065 bzs->avail_out = bufsize;
2066
2067 bzerror = BZ2_bzCompressInit(bzs, compresslevel, 0, 0);
2068 if (bzerror != BZ_OK) {
2069 Util_CatchBZ2Error(bzerror);
2070 Py_DECREF(ret);
2071 return NULL;
2072 }
Tim Peterse3228092002-11-09 04:21:44 +00002073
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002074 for (;;) {
2075 Py_BEGIN_ALLOW_THREADS
2076 bzerror = BZ2_bzCompress(bzs, BZ_FINISH);
2077 Py_END_ALLOW_THREADS
2078 if (bzerror == BZ_STREAM_END) {
2079 break;
2080 } else if (bzerror != BZ_FINISH_OK) {
2081 BZ2_bzCompressEnd(bzs);
2082 Util_CatchBZ2Error(bzerror);
2083 Py_DECREF(ret);
2084 return NULL;
2085 }
2086 if (bzs->avail_out == 0) {
2087 bufsize = Util_NewBufferSize(bufsize);
2088 if (_PyString_Resize(&ret, bufsize) < 0) {
2089 BZ2_bzCompressEnd(bzs);
2090 Py_DECREF(ret);
2091 return NULL;
2092 }
2093 bzs->next_out = BUF(ret) + BZS_TOTAL_OUT(bzs);
2094 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
2095 }
2096 }
2097
2098 if (bzs->avail_out != 0)
Neal Norwitz047f3c72006-06-12 02:06:42 +00002099 _PyString_Resize(&ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002100 BZ2_bzCompressEnd(bzs);
2101
2102 return ret;
2103}
2104
2105PyDoc_STRVAR(bz2_decompress__doc__,
2106"decompress(data) -> decompressed data\n\
2107\n\
2108Decompress data in one shot. If you want to decompress data sequentially,\n\
2109use an instance of BZ2Decompressor instead.\n\
2110");
2111
2112static PyObject *
2113bz2_decompress(PyObject *self, PyObject *args)
2114{
2115 char *data;
2116 int datasize;
2117 int bufsize = SMALLCHUNK;
2118 PyObject *ret;
2119 bz_stream _bzs;
2120 bz_stream *bzs = &_bzs;
2121 int bzerror;
2122
Walter Dörwaldbb9c7392004-11-01 17:10:19 +00002123 if (!PyArg_ParseTuple(args, "s#:decompress", &data, &datasize))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002124 return NULL;
2125
2126 if (datasize == 0)
2127 return PyString_FromString("");
2128
2129 ret = PyString_FromStringAndSize(NULL, bufsize);
2130 if (!ret)
2131 return NULL;
2132
2133 memset(bzs, 0, sizeof(bz_stream));
2134
2135 bzs->next_in = data;
2136 bzs->avail_in = datasize;
2137 bzs->next_out = BUF(ret);
2138 bzs->avail_out = bufsize;
2139
2140 bzerror = BZ2_bzDecompressInit(bzs, 0, 0);
2141 if (bzerror != BZ_OK) {
2142 Util_CatchBZ2Error(bzerror);
2143 Py_DECREF(ret);
2144 return NULL;
2145 }
Tim Peterse3228092002-11-09 04:21:44 +00002146
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002147 for (;;) {
2148 Py_BEGIN_ALLOW_THREADS
2149 bzerror = BZ2_bzDecompress(bzs);
2150 Py_END_ALLOW_THREADS
2151 if (bzerror == BZ_STREAM_END) {
2152 break;
2153 } else if (bzerror != BZ_OK) {
2154 BZ2_bzDecompressEnd(bzs);
2155 Util_CatchBZ2Error(bzerror);
2156 Py_DECREF(ret);
2157 return NULL;
2158 }
Georg Brandld6e73c12007-03-13 12:34:35 +00002159 if (bzs->avail_in == 0) {
2160 BZ2_bzDecompressEnd(bzs);
2161 PyErr_SetString(PyExc_ValueError,
2162 "couldn't find end of stream");
2163 Py_DECREF(ret);
2164 return NULL;
2165 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002166 if (bzs->avail_out == 0) {
2167 bufsize = Util_NewBufferSize(bufsize);
2168 if (_PyString_Resize(&ret, bufsize) < 0) {
2169 BZ2_bzDecompressEnd(bzs);
2170 Py_DECREF(ret);
2171 return NULL;
2172 }
2173 bzs->next_out = BUF(ret) + BZS_TOTAL_OUT(bzs);
2174 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002175 }
2176 }
2177
2178 if (bzs->avail_out != 0)
Neal Norwitz047f3c72006-06-12 02:06:42 +00002179 _PyString_Resize(&ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002180 BZ2_bzDecompressEnd(bzs);
2181
2182 return ret;
2183}
2184
2185static PyMethodDef bz2_methods[] = {
2186 {"compress", (PyCFunction) bz2_compress, METH_VARARGS|METH_KEYWORDS,
2187 bz2_compress__doc__},
2188 {"decompress", (PyCFunction) bz2_decompress, METH_VARARGS,
2189 bz2_decompress__doc__},
2190 {NULL, NULL} /* sentinel */
2191};
2192
2193/* ===================================================================== */
2194/* Initialization function. */
2195
2196PyDoc_STRVAR(bz2__doc__,
2197"The python bz2 module provides a comprehensive interface for\n\
2198the bz2 compression library. It implements a complete file\n\
2199interface, one shot (de)compression functions, and types for\n\
2200sequential (de)compression.\n\
2201");
2202
Neal Norwitz21d896c2003-07-01 20:15:21 +00002203PyMODINIT_FUNC
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002204initbz2(void)
2205{
2206 PyObject *m;
2207
2208 BZ2File_Type.ob_type = &PyType_Type;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002209 BZ2Comp_Type.ob_type = &PyType_Type;
2210 BZ2Decomp_Type.ob_type = &PyType_Type;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002211
2212 m = Py_InitModule3("bz2", bz2_methods, bz2__doc__);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00002213 if (m == NULL)
2214 return;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002215
2216 PyModule_AddObject(m, "__author__", PyString_FromString(__author__));
2217
2218 Py_INCREF(&BZ2File_Type);
2219 PyModule_AddObject(m, "BZ2File", (PyObject *)&BZ2File_Type);
2220
2221 Py_INCREF(&BZ2Comp_Type);
2222 PyModule_AddObject(m, "BZ2Compressor", (PyObject *)&BZ2Comp_Type);
2223
2224 Py_INCREF(&BZ2Decomp_Type);
2225 PyModule_AddObject(m, "BZ2Decompressor", (PyObject *)&BZ2Decomp_Type);
2226}