blob: 053461f3bd806eaed8dfbecaa54d1c96cf8d2c19 [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
Martin v. Löwis68192102007-07-21 06:55:02 +000044#define BZ2FileObject_Check(v) (Py_Type(v) == &BZ2File_Type)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000045
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;
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000238 int newlinetypes = f->f_newlinetypes;
239 int skipnextlf = f->f_skipnextlf;
240 int univ_newline = f->f_univ_newline;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000241
242 total_v_size = n > 0 ? n : 100;
243 v = PyString_FromStringAndSize((char *)NULL, total_v_size);
244 if (v == NULL)
245 return NULL;
246
247 buf = BUF(v);
248 end = buf + total_v_size;
249
250 for (;;) {
251 Py_BEGIN_ALLOW_THREADS
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000252 if (univ_newline) {
253 while (1) {
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000254 BZ2_bzRead(&bzerror, f->fp, &c, 1);
255 f->pos++;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000256 if (bzerror != BZ_OK || buf == end)
257 break;
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +0000258 if (skipnextlf) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000259 skipnextlf = 0;
260 if (c == '\n') {
Tim Peterse3228092002-11-09 04:21:44 +0000261 /* Seeing a \n here with
262 * skipnextlf true means we
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000263 * saw a \r before.
264 */
265 newlinetypes |= NEWLINE_CRLF;
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000266 BZ2_bzRead(&bzerror, f->fp,
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000267 &c, 1);
268 if (bzerror != BZ_OK)
269 break;
270 } else {
271 newlinetypes |= NEWLINE_CR;
272 }
273 }
274 if (c == '\r') {
275 skipnextlf = 1;
276 c = '\n';
277 } else if ( c == '\n')
278 newlinetypes |= NEWLINE_LF;
279 *buf++ = c;
280 if (c == '\n') break;
281 }
282 if (bzerror == BZ_STREAM_END && skipnextlf)
283 newlinetypes |= NEWLINE_CR;
284 } else /* If not universal newlines use the normal loop */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000285 do {
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000286 BZ2_bzRead(&bzerror, f->fp, &c, 1);
287 f->pos++;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000288 *buf++ = c;
289 } while (bzerror == BZ_OK && c != '\n' && buf != end);
290 Py_END_ALLOW_THREADS
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000291 f->f_newlinetypes = newlinetypes;
292 f->f_skipnextlf = skipnextlf;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000293 if (bzerror == BZ_STREAM_END) {
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000294 f->size = f->pos;
295 f->mode = MODE_READ_EOF;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000296 break;
297 } else if (bzerror != BZ_OK) {
298 Util_CatchBZ2Error(bzerror);
299 Py_DECREF(v);
300 return NULL;
301 }
302 if (c == '\n')
303 break;
304 /* Must be because buf == end */
305 if (n > 0)
306 break;
307 used_v_size = total_v_size;
308 increment = total_v_size >> 2; /* mild exponential growth */
309 total_v_size += increment;
310 if (total_v_size > INT_MAX) {
311 PyErr_SetString(PyExc_OverflowError,
312 "line is longer than a Python string can hold");
313 Py_DECREF(v);
314 return NULL;
315 }
316 if (_PyString_Resize(&v, total_v_size) < 0)
317 return NULL;
318 buf = BUF(v) + used_v_size;
319 end = BUF(v) + total_v_size;
320 }
321
322 used_v_size = buf - BUF(v);
323 if (used_v_size != total_v_size)
324 _PyString_Resize(&v, used_v_size);
325 return v;
326}
327
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000328/* This is a hacked version of Python's
329 * fileobject.c:Py_UniversalNewlineFread(). */
330size_t
331Util_UnivNewlineRead(int *bzerror, BZFILE *stream,
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000332 char* buf, size_t n, BZ2FileObject *f)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000333{
334 char *dst = buf;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000335 int newlinetypes, skipnextlf;
336
337 assert(buf != NULL);
338 assert(stream != NULL);
339
340 if (!f->f_univ_newline)
341 return BZ2_bzRead(bzerror, stream, buf, n);
342
343 newlinetypes = f->f_newlinetypes;
344 skipnextlf = f->f_skipnextlf;
345
346 /* Invariant: n is the number of bytes remaining to be filled
347 * in the buffer.
348 */
349 while (n) {
350 size_t nread;
351 int shortread;
352 char *src = dst;
353
354 nread = BZ2_bzRead(bzerror, stream, dst, n);
355 assert(nread <= n);
356 n -= nread; /* assuming 1 byte out for each in; will adjust */
357 shortread = n != 0; /* true iff EOF or error */
358 while (nread--) {
359 char c = *src++;
360 if (c == '\r') {
361 /* Save as LF and set flag to skip next LF. */
362 *dst++ = '\n';
363 skipnextlf = 1;
364 }
365 else if (skipnextlf && c == '\n') {
366 /* Skip LF, and remember we saw CR LF. */
367 skipnextlf = 0;
368 newlinetypes |= NEWLINE_CRLF;
369 ++n;
370 }
371 else {
372 /* Normal char to be stored in buffer. Also
373 * update the newlinetypes flag if either this
374 * is an LF or the previous char was a CR.
375 */
376 if (c == '\n')
377 newlinetypes |= NEWLINE_LF;
378 else if (skipnextlf)
379 newlinetypes |= NEWLINE_CR;
380 *dst++ = c;
381 skipnextlf = 0;
382 }
383 }
384 if (shortread) {
385 /* If this is EOF, update type flags. */
386 if (skipnextlf && *bzerror == BZ_STREAM_END)
387 newlinetypes |= NEWLINE_CR;
388 break;
389 }
390 }
391 f->f_newlinetypes = newlinetypes;
392 f->f_skipnextlf = skipnextlf;
393 return dst - buf;
394}
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000395
396/* This is a hacked version of Python's fileobject.c:drop_readahead(). */
397static void
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000398Util_DropReadAhead(BZ2FileObject *f)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000399{
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000400 if (f->f_buf != NULL) {
401 PyMem_Free(f->f_buf);
402 f->f_buf = NULL;
403 }
404}
405
406/* This is a hacked version of Python's fileobject.c:readahead(). */
407static int
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000408Util_ReadAhead(BZ2FileObject *f, int bufsize)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000409{
410 int chunksize;
411 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000412
413 if (f->f_buf != NULL) {
Tim Peterse3228092002-11-09 04:21:44 +0000414 if((f->f_bufend - f->f_bufptr) >= 1)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000415 return 0;
416 else
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000417 Util_DropReadAhead(f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000418 }
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000419 if (f->mode == MODE_READ_EOF) {
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000420 f->f_bufptr = f->f_buf;
421 f->f_bufend = f->f_buf;
422 return 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000423 }
424 if ((f->f_buf = PyMem_Malloc(bufsize)) == NULL) {
425 return -1;
426 }
427 Py_BEGIN_ALLOW_THREADS
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000428 chunksize = Util_UnivNewlineRead(&bzerror, f->fp, f->f_buf,
429 bufsize, f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000430 Py_END_ALLOW_THREADS
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000431 f->pos += chunksize;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000432 if (bzerror == BZ_STREAM_END) {
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000433 f->size = f->pos;
434 f->mode = MODE_READ_EOF;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000435 } else if (bzerror != BZ_OK) {
436 Util_CatchBZ2Error(bzerror);
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000437 Util_DropReadAhead(f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000438 return -1;
439 }
440 f->f_bufptr = f->f_buf;
441 f->f_bufend = f->f_buf + chunksize;
442 return 0;
443}
444
445/* This is a hacked version of Python's
446 * fileobject.c:readahead_get_line_skip(). */
447static PyStringObject *
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000448Util_ReadAheadGetLineSkip(BZ2FileObject *f, int skip, int bufsize)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000449{
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000450 PyStringObject* s;
451 char *bufptr;
452 char *buf;
453 int len;
454
455 if (f->f_buf == NULL)
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000456 if (Util_ReadAhead(f, bufsize) < 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000457 return NULL;
458
459 len = f->f_bufend - f->f_bufptr;
Tim Peterse3228092002-11-09 04:21:44 +0000460 if (len == 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000461 return (PyStringObject *)
462 PyString_FromStringAndSize(NULL, skip);
463 bufptr = memchr(f->f_bufptr, '\n', len);
464 if (bufptr != NULL) {
465 bufptr++; /* Count the '\n' */
466 len = bufptr - f->f_bufptr;
467 s = (PyStringObject *)
468 PyString_FromStringAndSize(NULL, skip+len);
Tim Peterse3228092002-11-09 04:21:44 +0000469 if (s == NULL)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000470 return NULL;
471 memcpy(PyString_AS_STRING(s)+skip, f->f_bufptr, len);
472 f->f_bufptr = bufptr;
473 if (bufptr == f->f_bufend)
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000474 Util_DropReadAhead(f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000475 } else {
476 bufptr = f->f_bufptr;
477 buf = f->f_buf;
478 f->f_buf = NULL; /* Force new readahead buffer */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000479 s = Util_ReadAheadGetLineSkip(f, skip+len,
480 bufsize + (bufsize>>2));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000481 if (s == NULL) {
482 PyMem_Free(buf);
483 return NULL;
484 }
485 memcpy(PyString_AS_STRING(s)+skip, bufptr, len);
486 PyMem_Free(buf);
487 }
488 return s;
489}
490
491/* ===================================================================== */
492/* Methods of BZ2File. */
493
494PyDoc_STRVAR(BZ2File_read__doc__,
495"read([size]) -> string\n\
496\n\
497Read at most size uncompressed bytes, returned as a string. If the size\n\
498argument is negative or omitted, read until EOF is reached.\n\
499");
500
501/* This is a hacked version of Python's fileobject.c:file_read(). */
502static PyObject *
503BZ2File_read(BZ2FileObject *self, PyObject *args)
504{
505 long bytesrequested = -1;
506 size_t bytesread, buffersize, chunksize;
507 int bzerror;
508 PyObject *ret = NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000509
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000510 if (!PyArg_ParseTuple(args, "|l:read", &bytesrequested))
511 return NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000512
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000513 ACQUIRE_LOCK(self);
514 switch (self->mode) {
515 case MODE_READ:
516 break;
517 case MODE_READ_EOF:
518 ret = PyString_FromString("");
519 goto cleanup;
520 case MODE_CLOSED:
521 PyErr_SetString(PyExc_ValueError,
522 "I/O operation on closed file");
523 goto cleanup;
524 default:
525 PyErr_SetString(PyExc_IOError,
526 "file is not ready for reading");
527 goto cleanup;
528 }
529
530 if (bytesrequested < 0)
531 buffersize = Util_NewBufferSize((size_t)0);
532 else
533 buffersize = bytesrequested;
534 if (buffersize > INT_MAX) {
535 PyErr_SetString(PyExc_OverflowError,
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +0000536 "requested number of bytes is "
537 "more than a Python string can hold");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000538 goto cleanup;
539 }
540 ret = PyString_FromStringAndSize((char *)NULL, buffersize);
541 if (ret == NULL)
542 goto cleanup;
543 bytesread = 0;
544
545 for (;;) {
546 Py_BEGIN_ALLOW_THREADS
547 chunksize = Util_UnivNewlineRead(&bzerror, self->fp,
548 BUF(ret)+bytesread,
549 buffersize-bytesread,
550 self);
551 self->pos += chunksize;
552 Py_END_ALLOW_THREADS
553 bytesread += chunksize;
554 if (bzerror == BZ_STREAM_END) {
555 self->size = self->pos;
556 self->mode = MODE_READ_EOF;
557 break;
558 } else if (bzerror != BZ_OK) {
559 Util_CatchBZ2Error(bzerror);
560 Py_DECREF(ret);
561 ret = NULL;
562 goto cleanup;
563 }
564 if (bytesrequested < 0) {
565 buffersize = Util_NewBufferSize(buffersize);
566 if (_PyString_Resize(&ret, buffersize) < 0)
567 goto cleanup;
568 } else {
569 break;
570 }
571 }
572 if (bytesread != buffersize)
573 _PyString_Resize(&ret, bytesread);
574
575cleanup:
576 RELEASE_LOCK(self);
577 return ret;
578}
579
580PyDoc_STRVAR(BZ2File_readline__doc__,
581"readline([size]) -> string\n\
582\n\
583Return the next line from the file, as a string, retaining newline.\n\
584A non-negative size argument will limit the maximum number of bytes to\n\
585return (an incomplete line may be returned then). Return an empty\n\
586string at EOF.\n\
587");
588
589static PyObject *
590BZ2File_readline(BZ2FileObject *self, PyObject *args)
591{
592 PyObject *ret = NULL;
593 int sizehint = -1;
594
595 if (!PyArg_ParseTuple(args, "|i:readline", &sizehint))
596 return NULL;
597
598 ACQUIRE_LOCK(self);
599 switch (self->mode) {
600 case MODE_READ:
601 break;
602 case MODE_READ_EOF:
603 ret = PyString_FromString("");
604 goto cleanup;
605 case MODE_CLOSED:
606 PyErr_SetString(PyExc_ValueError,
607 "I/O operation on closed file");
608 goto cleanup;
609 default:
610 PyErr_SetString(PyExc_IOError,
611 "file is not ready for reading");
612 goto cleanup;
613 }
614
615 if (sizehint == 0)
616 ret = PyString_FromString("");
617 else
618 ret = Util_GetLine(self, (sizehint < 0) ? 0 : sizehint);
619
620cleanup:
621 RELEASE_LOCK(self);
622 return ret;
623}
624
625PyDoc_STRVAR(BZ2File_readlines__doc__,
626"readlines([size]) -> list\n\
627\n\
628Call readline() repeatedly and return a list of lines read.\n\
629The optional size argument, if given, is an approximate bound on the\n\
630total number of bytes in the lines returned.\n\
631");
632
633/* This is a hacked version of Python's fileobject.c:file_readlines(). */
634static PyObject *
635BZ2File_readlines(BZ2FileObject *self, PyObject *args)
636{
637 long sizehint = 0;
638 PyObject *list = NULL;
639 PyObject *line;
640 char small_buffer[SMALLCHUNK];
641 char *buffer = small_buffer;
642 size_t buffersize = SMALLCHUNK;
643 PyObject *big_buffer = NULL;
644 size_t nfilled = 0;
645 size_t nread;
646 size_t totalread = 0;
647 char *p, *q, *end;
648 int err;
649 int shortread = 0;
650 int bzerror;
651
652 if (!PyArg_ParseTuple(args, "|l:readlines", &sizehint))
653 return NULL;
654
655 ACQUIRE_LOCK(self);
656 switch (self->mode) {
657 case MODE_READ:
658 break;
659 case MODE_READ_EOF:
660 list = PyList_New(0);
661 goto cleanup;
662 case MODE_CLOSED:
663 PyErr_SetString(PyExc_ValueError,
664 "I/O operation on closed file");
665 goto cleanup;
666 default:
667 PyErr_SetString(PyExc_IOError,
668 "file is not ready for reading");
669 goto cleanup;
670 }
671
672 if ((list = PyList_New(0)) == NULL)
673 goto cleanup;
674
675 for (;;) {
676 Py_BEGIN_ALLOW_THREADS
677 nread = Util_UnivNewlineRead(&bzerror, self->fp,
678 buffer+nfilled,
679 buffersize-nfilled, self);
680 self->pos += nread;
681 Py_END_ALLOW_THREADS
682 if (bzerror == BZ_STREAM_END) {
683 self->size = self->pos;
684 self->mode = MODE_READ_EOF;
685 if (nread == 0) {
686 sizehint = 0;
687 break;
688 }
689 shortread = 1;
690 } else if (bzerror != BZ_OK) {
691 Util_CatchBZ2Error(bzerror);
692 error:
693 Py_DECREF(list);
694 list = NULL;
695 goto cleanup;
696 }
697 totalread += nread;
698 p = memchr(buffer+nfilled, '\n', nread);
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000699 if (!shortread && p == NULL) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000700 /* Need a larger buffer to fit this line */
701 nfilled += nread;
702 buffersize *= 2;
703 if (buffersize > INT_MAX) {
704 PyErr_SetString(PyExc_OverflowError,
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000705 "line is longer than a Python string can hold");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000706 goto error;
707 }
708 if (big_buffer == NULL) {
709 /* Create the big buffer */
710 big_buffer = PyString_FromStringAndSize(
711 NULL, buffersize);
712 if (big_buffer == NULL)
713 goto error;
714 buffer = PyString_AS_STRING(big_buffer);
715 memcpy(buffer, small_buffer, nfilled);
716 }
717 else {
718 /* Grow the big buffer */
719 _PyString_Resize(&big_buffer, buffersize);
720 buffer = PyString_AS_STRING(big_buffer);
721 }
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000722 continue;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000723 }
724 end = buffer+nfilled+nread;
725 q = buffer;
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000726 while (p != NULL) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000727 /* Process complete lines */
728 p++;
729 line = PyString_FromStringAndSize(q, p-q);
730 if (line == NULL)
731 goto error;
732 err = PyList_Append(list, line);
733 Py_DECREF(line);
734 if (err != 0)
735 goto error;
736 q = p;
737 p = memchr(q, '\n', end-q);
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000738 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000739 /* Move the remaining incomplete line to the start */
740 nfilled = end-q;
741 memmove(buffer, q, nfilled);
742 if (sizehint > 0)
743 if (totalread >= (size_t)sizehint)
744 break;
745 if (shortread) {
746 sizehint = 0;
747 break;
748 }
749 }
750 if (nfilled != 0) {
751 /* Partial last line */
752 line = PyString_FromStringAndSize(buffer, nfilled);
753 if (line == NULL)
754 goto error;
755 if (sizehint > 0) {
756 /* Need to complete the last line */
757 PyObject *rest = Util_GetLine(self, 0);
758 if (rest == NULL) {
759 Py_DECREF(line);
760 goto error;
761 }
762 PyString_Concat(&line, rest);
763 Py_DECREF(rest);
764 if (line == NULL)
765 goto error;
766 }
767 err = PyList_Append(list, line);
768 Py_DECREF(line);
769 if (err != 0)
770 goto error;
771 }
772
773 cleanup:
774 RELEASE_LOCK(self);
775 if (big_buffer) {
776 Py_DECREF(big_buffer);
777 }
778 return list;
779}
780
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000781PyDoc_STRVAR(BZ2File_xreadlines__doc__,
782"xreadlines() -> self\n\
783\n\
784For backward compatibility. BZ2File objects now include the performance\n\
785optimizations previously implemented in the xreadlines module.\n\
786");
787
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000788PyDoc_STRVAR(BZ2File_write__doc__,
789"write(data) -> None\n\
790\n\
791Write the 'data' string to file. Note that due to buffering, close() may\n\
792be needed before the file on disk reflects the data written.\n\
793");
794
795/* This is a hacked version of Python's fileobject.c:file_write(). */
796static PyObject *
797BZ2File_write(BZ2FileObject *self, PyObject *args)
798{
799 PyObject *ret = NULL;
800 char *buf;
801 int len;
802 int bzerror;
803
Walter Dörwaldbb9c7392004-11-01 17:10:19 +0000804 if (!PyArg_ParseTuple(args, "s#:write", &buf, &len))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000805 return NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000806
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000807 ACQUIRE_LOCK(self);
808 switch (self->mode) {
809 case MODE_WRITE:
810 break;
Tim Peterse3228092002-11-09 04:21:44 +0000811
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000812 case MODE_CLOSED:
813 PyErr_SetString(PyExc_ValueError,
814 "I/O operation on closed file");
Georg Brandl3335a7a2006-08-14 21:42:55 +0000815 goto cleanup;
Tim Peterse3228092002-11-09 04:21:44 +0000816
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000817 default:
818 PyErr_SetString(PyExc_IOError,
819 "file is not ready for writing");
Georg Brandl3335a7a2006-08-14 21:42:55 +0000820 goto cleanup;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000821 }
822
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000823 self->f_softspace = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000824
825 Py_BEGIN_ALLOW_THREADS
826 BZ2_bzWrite (&bzerror, self->fp, buf, len);
827 self->pos += len;
828 Py_END_ALLOW_THREADS
Tim Peterse3228092002-11-09 04:21:44 +0000829
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000830 if (bzerror != BZ_OK) {
831 Util_CatchBZ2Error(bzerror);
832 goto cleanup;
833 }
Tim Peterse3228092002-11-09 04:21:44 +0000834
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000835 Py_INCREF(Py_None);
836 ret = Py_None;
837
838cleanup:
839 RELEASE_LOCK(self);
840 return ret;
841}
842
843PyDoc_STRVAR(BZ2File_writelines__doc__,
844"writelines(sequence_of_strings) -> None\n\
845\n\
846Write the sequence of strings to the file. Note that newlines are not\n\
847added. The sequence can be any iterable object producing strings. This is\n\
848equivalent to calling write() for each string.\n\
849");
850
851/* This is a hacked version of Python's fileobject.c:file_writelines(). */
852static PyObject *
853BZ2File_writelines(BZ2FileObject *self, PyObject *seq)
854{
855#define CHUNKSIZE 1000
856 PyObject *list = NULL;
857 PyObject *iter = NULL;
858 PyObject *ret = NULL;
859 PyObject *line;
860 int i, j, index, len, islist;
861 int bzerror;
862
863 ACQUIRE_LOCK(self);
Georg Brandl3335a7a2006-08-14 21:42:55 +0000864 switch (self->mode) {
865 case MODE_WRITE:
866 break;
867
868 case MODE_CLOSED:
869 PyErr_SetString(PyExc_ValueError,
870 "I/O operation on closed file");
871 goto error;
872
873 default:
874 PyErr_SetString(PyExc_IOError,
875 "file is not ready for writing");
876 goto error;
877 }
878
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000879 islist = PyList_Check(seq);
880 if (!islist) {
881 iter = PyObject_GetIter(seq);
882 if (iter == NULL) {
883 PyErr_SetString(PyExc_TypeError,
884 "writelines() requires an iterable argument");
885 goto error;
886 }
887 list = PyList_New(CHUNKSIZE);
888 if (list == NULL)
889 goto error;
890 }
891
892 /* Strategy: slurp CHUNKSIZE lines into a private list,
893 checking that they are all strings, then write that list
894 without holding the interpreter lock, then come back for more. */
895 for (index = 0; ; index += CHUNKSIZE) {
896 if (islist) {
897 Py_XDECREF(list);
898 list = PyList_GetSlice(seq, index, index+CHUNKSIZE);
899 if (list == NULL)
900 goto error;
901 j = PyList_GET_SIZE(list);
902 }
903 else {
904 for (j = 0; j < CHUNKSIZE; j++) {
905 line = PyIter_Next(iter);
906 if (line == NULL) {
907 if (PyErr_Occurred())
908 goto error;
909 break;
910 }
911 PyList_SetItem(list, j, line);
912 }
913 }
914 if (j == 0)
915 break;
916
917 /* Check that all entries are indeed strings. If not,
918 apply the same rules as for file.write() and
919 convert the rets to strings. This is slow, but
920 seems to be the only way since all conversion APIs
921 could potentially execute Python code. */
922 for (i = 0; i < j; i++) {
923 PyObject *v = PyList_GET_ITEM(list, i);
924 if (!PyString_Check(v)) {
925 const char *buffer;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000926 Py_ssize_t len;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000927 if (PyObject_AsCharBuffer(v, &buffer, &len)) {
928 PyErr_SetString(PyExc_TypeError,
929 "writelines() "
930 "argument must be "
931 "a sequence of "
932 "strings");
933 goto error;
934 }
935 line = PyString_FromStringAndSize(buffer,
936 len);
937 if (line == NULL)
938 goto error;
939 Py_DECREF(v);
940 PyList_SET_ITEM(list, i, line);
941 }
942 }
943
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000944 self->f_softspace = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000945
946 /* Since we are releasing the global lock, the
947 following code may *not* execute Python code. */
948 Py_BEGIN_ALLOW_THREADS
949 for (i = 0; i < j; i++) {
950 line = PyList_GET_ITEM(list, i);
951 len = PyString_GET_SIZE(line);
952 BZ2_bzWrite (&bzerror, self->fp,
953 PyString_AS_STRING(line), len);
954 if (bzerror != BZ_OK) {
955 Py_BLOCK_THREADS
956 Util_CatchBZ2Error(bzerror);
957 goto error;
958 }
959 }
960 Py_END_ALLOW_THREADS
961
962 if (j < CHUNKSIZE)
963 break;
964 }
965
966 Py_INCREF(Py_None);
967 ret = Py_None;
968
969 error:
970 RELEASE_LOCK(self);
971 Py_XDECREF(list);
972 Py_XDECREF(iter);
973 return ret;
974#undef CHUNKSIZE
975}
976
977PyDoc_STRVAR(BZ2File_seek__doc__,
978"seek(offset [, whence]) -> None\n\
979\n\
980Move to new file position. Argument offset is a byte count. Optional\n\
981argument whence defaults to 0 (offset from start of file, offset\n\
982should be >= 0); other values are 1 (move relative to current position,\n\
983positive or negative), and 2 (move relative to end of file, usually\n\
984negative, although many platforms allow seeking beyond the end of a file).\n\
985\n\
986Note that seeking of bz2 files is emulated, and depending on the parameters\n\
987the operation may be extremely slow.\n\
988");
989
990static PyObject *
991BZ2File_seek(BZ2FileObject *self, PyObject *args)
992{
993 int where = 0;
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000994 PyObject *offobj;
995 Py_off_t offset;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000996 char small_buffer[SMALLCHUNK];
997 char *buffer = small_buffer;
998 size_t buffersize = SMALLCHUNK;
Andrew M. Kuchling44b054b2006-12-18 19:22:24 +0000999 Py_off_t bytesread = 0;
Georg Brandla8bcecc2005-09-03 07:49:53 +00001000 size_t readsize;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001001 int chunksize;
1002 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001003 PyObject *ret = NULL;
Tim Peterse3228092002-11-09 04:21:44 +00001004
Georg Brandl33a5f2a2005-08-21 14:16:04 +00001005 if (!PyArg_ParseTuple(args, "O|i:seek", &offobj, &where))
1006 return NULL;
1007#if !defined(HAVE_LARGEFILE_SUPPORT)
1008 offset = PyInt_AsLong(offobj);
1009#else
1010 offset = PyLong_Check(offobj) ?
1011 PyLong_AsLongLong(offobj) : PyInt_AsLong(offobj);
1012#endif
1013 if (PyErr_Occurred())
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001014 return NULL;
1015
1016 ACQUIRE_LOCK(self);
1017 Util_DropReadAhead(self);
1018 switch (self->mode) {
1019 case MODE_READ:
1020 case MODE_READ_EOF:
1021 break;
Tim Peterse3228092002-11-09 04:21:44 +00001022
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001023 case MODE_CLOSED:
1024 PyErr_SetString(PyExc_ValueError,
1025 "I/O operation on closed file");
Neal Norwitzd3f91902006-09-23 04:11:38 +00001026 goto cleanup;
Tim Peterse3228092002-11-09 04:21:44 +00001027
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001028 default:
1029 PyErr_SetString(PyExc_IOError,
1030 "seek works only while reading");
Neal Norwitzd3f91902006-09-23 04:11:38 +00001031 goto cleanup;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001032 }
1033
Georg Brandl47fab922006-02-18 21:57:25 +00001034 if (where == 2) {
1035 if (self->size == -1) {
1036 assert(self->mode != MODE_READ_EOF);
1037 for (;;) {
1038 Py_BEGIN_ALLOW_THREADS
1039 chunksize = Util_UnivNewlineRead(
1040 &bzerror, self->fp,
1041 buffer, buffersize,
1042 self);
1043 self->pos += chunksize;
1044 Py_END_ALLOW_THREADS
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001045
Georg Brandl47fab922006-02-18 21:57:25 +00001046 bytesread += chunksize;
1047 if (bzerror == BZ_STREAM_END) {
1048 break;
1049 } else if (bzerror != BZ_OK) {
1050 Util_CatchBZ2Error(bzerror);
1051 goto cleanup;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001052 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001053 }
Georg Brandl47fab922006-02-18 21:57:25 +00001054 self->mode = MODE_READ_EOF;
1055 self->size = self->pos;
1056 bytesread = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001057 }
Georg Brandl47fab922006-02-18 21:57:25 +00001058 offset = self->size + offset;
1059 } else if (where == 1) {
1060 offset = self->pos + offset;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001061 }
1062
Georg Brandl47fab922006-02-18 21:57:25 +00001063 /* Before getting here, offset must be the absolute position the file
1064 * pointer should be set to. */
1065
1066 if (offset >= self->pos) {
1067 /* we can move forward */
1068 offset -= self->pos;
1069 } else {
1070 /* we cannot move back, so rewind the stream */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001071 BZ2_bzReadClose(&bzerror, self->fp);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001072 if (bzerror != BZ_OK) {
1073 Util_CatchBZ2Error(bzerror);
1074 goto cleanup;
1075 }
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001076 ret = PyObject_CallMethod(self->file, "seek", "(i)", 0);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001077 if (!ret)
1078 goto cleanup;
1079 Py_DECREF(ret);
1080 ret = NULL;
1081 self->pos = 0;
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001082 self->fp = BZ2_bzReadOpen(&bzerror, PyFile_AsFile(self->file),
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001083 0, 0, NULL, 0);
1084 if (bzerror != BZ_OK) {
1085 Util_CatchBZ2Error(bzerror);
1086 goto cleanup;
1087 }
1088 self->mode = MODE_READ;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001089 }
1090
Georg Brandl47fab922006-02-18 21:57:25 +00001091 if (offset <= 0 || self->mode == MODE_READ_EOF)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001092 goto exit;
1093
1094 /* Before getting here, offset must be set to the number of bytes
1095 * to walk forward. */
1096 for (;;) {
Georg Brandla8bcecc2005-09-03 07:49:53 +00001097 if (offset-bytesread > buffersize)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001098 readsize = buffersize;
1099 else
Georg Brandla8bcecc2005-09-03 07:49:53 +00001100 /* offset might be wider that readsize, but the result
1101 * of the subtraction is bound by buffersize (see the
1102 * condition above). buffersize is 8192. */
1103 readsize = (size_t)(offset-bytesread);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001104 Py_BEGIN_ALLOW_THREADS
1105 chunksize = Util_UnivNewlineRead(&bzerror, self->fp,
1106 buffer, readsize, self);
1107 self->pos += chunksize;
1108 Py_END_ALLOW_THREADS
1109 bytesread += chunksize;
1110 if (bzerror == BZ_STREAM_END) {
1111 self->size = self->pos;
1112 self->mode = MODE_READ_EOF;
1113 break;
1114 } else if (bzerror != BZ_OK) {
1115 Util_CatchBZ2Error(bzerror);
1116 goto cleanup;
1117 }
1118 if (bytesread == offset)
1119 break;
1120 }
1121
1122exit:
1123 Py_INCREF(Py_None);
1124 ret = Py_None;
1125
1126cleanup:
1127 RELEASE_LOCK(self);
1128 return ret;
1129}
1130
1131PyDoc_STRVAR(BZ2File_tell__doc__,
1132"tell() -> int\n\
1133\n\
1134Return the current file position, an integer (may be a long integer).\n\
1135");
1136
1137static PyObject *
1138BZ2File_tell(BZ2FileObject *self, PyObject *args)
1139{
1140 PyObject *ret = NULL;
1141
1142 if (self->mode == MODE_CLOSED) {
1143 PyErr_SetString(PyExc_ValueError,
1144 "I/O operation on closed file");
1145 goto cleanup;
1146 }
1147
Georg Brandla8bcecc2005-09-03 07:49:53 +00001148#if !defined(HAVE_LARGEFILE_SUPPORT)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001149 ret = PyInt_FromLong(self->pos);
Georg Brandla8bcecc2005-09-03 07:49:53 +00001150#else
1151 ret = PyLong_FromLongLong(self->pos);
1152#endif
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001153
1154cleanup:
1155 return ret;
1156}
1157
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001158PyDoc_STRVAR(BZ2File_close__doc__,
1159"close() -> None or (perhaps) an integer\n\
1160\n\
1161Close the file. Sets data attribute .closed to true. A closed file\n\
1162cannot be used for further I/O operations. close() may be called more\n\
1163than once without error.\n\
1164");
1165
1166static PyObject *
1167BZ2File_close(BZ2FileObject *self)
1168{
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001169 PyObject *ret = NULL;
1170 int bzerror = BZ_OK;
1171
1172 ACQUIRE_LOCK(self);
1173 switch (self->mode) {
1174 case MODE_READ:
1175 case MODE_READ_EOF:
1176 BZ2_bzReadClose(&bzerror, self->fp);
1177 break;
1178 case MODE_WRITE:
1179 BZ2_bzWriteClose(&bzerror, self->fp,
1180 0, NULL, NULL);
1181 break;
1182 }
1183 self->mode = MODE_CLOSED;
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001184 ret = PyObject_CallMethod(self->file, "close", NULL);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001185 if (bzerror != BZ_OK) {
1186 Util_CatchBZ2Error(bzerror);
1187 Py_XDECREF(ret);
1188 ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001189 }
1190
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001191 RELEASE_LOCK(self);
1192 return ret;
1193}
1194
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001195static PyObject *BZ2File_getiter(BZ2FileObject *self);
1196
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001197static PyMethodDef BZ2File_methods[] = {
1198 {"read", (PyCFunction)BZ2File_read, METH_VARARGS, BZ2File_read__doc__},
1199 {"readline", (PyCFunction)BZ2File_readline, METH_VARARGS, BZ2File_readline__doc__},
1200 {"readlines", (PyCFunction)BZ2File_readlines, METH_VARARGS, BZ2File_readlines__doc__},
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001201 {"xreadlines", (PyCFunction)BZ2File_getiter, METH_VARARGS, BZ2File_xreadlines__doc__},
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001202 {"write", (PyCFunction)BZ2File_write, METH_VARARGS, BZ2File_write__doc__},
1203 {"writelines", (PyCFunction)BZ2File_writelines, METH_O, BZ2File_writelines__doc__},
1204 {"seek", (PyCFunction)BZ2File_seek, METH_VARARGS, BZ2File_seek__doc__},
1205 {"tell", (PyCFunction)BZ2File_tell, METH_NOARGS, BZ2File_tell__doc__},
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001206 {"close", (PyCFunction)BZ2File_close, METH_NOARGS, BZ2File_close__doc__},
1207 {NULL, NULL} /* sentinel */
1208};
1209
1210
1211/* ===================================================================== */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001212/* Getters and setters of BZ2File. */
1213
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001214/* This is a hacked version of Python's fileobject.c:get_newlines(). */
1215static PyObject *
1216BZ2File_get_newlines(BZ2FileObject *self, void *closure)
1217{
1218 switch (self->f_newlinetypes) {
1219 case NEWLINE_UNKNOWN:
1220 Py_INCREF(Py_None);
1221 return Py_None;
1222 case NEWLINE_CR:
1223 return PyString_FromString("\r");
1224 case NEWLINE_LF:
1225 return PyString_FromString("\n");
1226 case NEWLINE_CR|NEWLINE_LF:
1227 return Py_BuildValue("(ss)", "\r", "\n");
1228 case NEWLINE_CRLF:
1229 return PyString_FromString("\r\n");
1230 case NEWLINE_CR|NEWLINE_CRLF:
1231 return Py_BuildValue("(ss)", "\r", "\r\n");
1232 case NEWLINE_LF|NEWLINE_CRLF:
1233 return Py_BuildValue("(ss)", "\n", "\r\n");
1234 case NEWLINE_CR|NEWLINE_LF|NEWLINE_CRLF:
1235 return Py_BuildValue("(sss)", "\r", "\n", "\r\n");
1236 default:
1237 PyErr_Format(PyExc_SystemError,
1238 "Unknown newlines value 0x%x\n",
1239 self->f_newlinetypes);
1240 return NULL;
1241 }
1242}
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001243
1244static PyObject *
1245BZ2File_get_closed(BZ2FileObject *self, void *closure)
1246{
1247 return PyInt_FromLong(self->mode == MODE_CLOSED);
1248}
1249
1250static PyObject *
1251BZ2File_get_mode(BZ2FileObject *self, void *closure)
1252{
1253 return PyObject_GetAttrString(self->file, "mode");
1254}
1255
1256static PyObject *
1257BZ2File_get_name(BZ2FileObject *self, void *closure)
1258{
1259 return PyObject_GetAttrString(self->file, "name");
1260}
1261
1262static PyGetSetDef BZ2File_getset[] = {
1263 {"closed", (getter)BZ2File_get_closed, NULL,
1264 "True if the file is closed"},
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001265 {"newlines", (getter)BZ2File_get_newlines, NULL,
1266 "end-of-line convention used in this file"},
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001267 {"mode", (getter)BZ2File_get_mode, NULL,
1268 "file mode ('r', 'w', or 'U')"},
1269 {"name", (getter)BZ2File_get_name, NULL,
1270 "file name"},
1271 {NULL} /* Sentinel */
1272};
1273
1274
1275/* ===================================================================== */
1276/* Members of BZ2File_Type. */
1277
1278#undef OFF
1279#define OFF(x) offsetof(BZ2FileObject, x)
1280
1281static PyMemberDef BZ2File_members[] = {
1282 {"softspace", T_INT, OFF(f_softspace), 0,
1283 "flag indicating that a space needs to be printed; used by print"},
1284 {NULL} /* Sentinel */
1285};
1286
1287/* ===================================================================== */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001288/* Slot definitions for BZ2File_Type. */
1289
1290static int
1291BZ2File_init(BZ2FileObject *self, PyObject *args, PyObject *kwargs)
1292{
Martin v. Löwis15e62742006-02-27 16:46:16 +00001293 static char *kwlist[] = {"filename", "mode", "buffering",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001294 "compresslevel", 0};
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001295 PyObject *name;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001296 char *mode = "r";
1297 int buffering = -1;
1298 int compresslevel = 9;
1299 int bzerror;
1300 int mode_char = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001301
1302 self->size = -1;
Tim Peterse3228092002-11-09 04:21:44 +00001303
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001304 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|sii:BZ2File",
1305 kwlist, &name, &mode, &buffering,
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001306 &compresslevel))
1307 return -1;
1308
1309 if (compresslevel < 1 || compresslevel > 9) {
1310 PyErr_SetString(PyExc_ValueError,
1311 "compresslevel must be between 1 and 9");
1312 return -1;
1313 }
1314
1315 for (;;) {
1316 int error = 0;
1317 switch (*mode) {
1318 case 'r':
1319 case 'w':
1320 if (mode_char)
1321 error = 1;
1322 mode_char = *mode;
1323 break;
1324
1325 case 'b':
1326 break;
1327
1328 case 'U':
Neal Norwitz2a30cd02006-07-10 01:18:57 +00001329#ifdef __VMS
1330 self->f_univ_newline = 0;
1331#else
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001332 self->f_univ_newline = 1;
Neal Norwitz2a30cd02006-07-10 01:18:57 +00001333#endif
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001334 break;
1335
1336 default:
1337 error = 1;
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001338 break;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001339 }
1340 if (error) {
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001341 PyErr_Format(PyExc_ValueError,
1342 "invalid mode char %c", *mode);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001343 return -1;
1344 }
1345 mode++;
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001346 if (*mode == '\0')
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001347 break;
1348 }
1349
Georg Brandl6b95f1d2005-06-03 19:47:00 +00001350 if (mode_char == 0) {
1351 mode_char = 'r';
1352 }
1353
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001354 mode = (mode_char == 'r') ? "rb" : "wb";
Tim Peterse3228092002-11-09 04:21:44 +00001355
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001356 self->file = PyObject_CallFunction((PyObject*)&PyFile_Type, "(Osi)",
1357 name, mode, buffering);
1358 if (self->file == NULL)
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001359 return -1;
1360
1361 /* From now on, we have stuff to dealloc, so jump to error label
1362 * instead of returning */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001363
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001364#ifdef WITH_THREAD
1365 self->lock = PyThread_allocate_lock();
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001366 if (!self->lock) {
1367 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001368 goto error;
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001369 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001370#endif
1371
1372 if (mode_char == 'r')
1373 self->fp = BZ2_bzReadOpen(&bzerror,
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001374 PyFile_AsFile(self->file),
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001375 0, 0, NULL, 0);
1376 else
1377 self->fp = BZ2_bzWriteOpen(&bzerror,
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001378 PyFile_AsFile(self->file),
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001379 compresslevel, 0, 0);
1380
1381 if (bzerror != BZ_OK) {
1382 Util_CatchBZ2Error(bzerror);
1383 goto error;
1384 }
1385
1386 self->mode = (mode_char == 'r') ? MODE_READ : MODE_WRITE;
1387
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001388 return 0;
1389
1390error:
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001391 Py_CLEAR(self->file);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001392#ifdef WITH_THREAD
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001393 if (self->lock) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001394 PyThread_free_lock(self->lock);
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001395 self->lock = NULL;
1396 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001397#endif
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001398 return -1;
1399}
1400
1401static void
1402BZ2File_dealloc(BZ2FileObject *self)
1403{
1404 int bzerror;
1405#ifdef WITH_THREAD
1406 if (self->lock)
1407 PyThread_free_lock(self->lock);
1408#endif
1409 switch (self->mode) {
1410 case MODE_READ:
1411 case MODE_READ_EOF:
1412 BZ2_bzReadClose(&bzerror, self->fp);
1413 break;
1414 case MODE_WRITE:
1415 BZ2_bzWriteClose(&bzerror, self->fp,
1416 0, NULL, NULL);
1417 break;
1418 }
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001419 Util_DropReadAhead(self);
Gustavo Niemeyer572f5232003-04-29 14:53:08 +00001420 Py_XDECREF(self->file);
Martin v. Löwis68192102007-07-21 06:55:02 +00001421 Py_Type(self)->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001422}
1423
1424/* This is a hacked version of Python's fileobject.c:file_getiter(). */
1425static PyObject *
1426BZ2File_getiter(BZ2FileObject *self)
1427{
1428 if (self->mode == MODE_CLOSED) {
1429 PyErr_SetString(PyExc_ValueError,
1430 "I/O operation on closed file");
1431 return NULL;
1432 }
1433 Py_INCREF((PyObject*)self);
1434 return (PyObject *)self;
1435}
1436
1437/* This is a hacked version of Python's fileobject.c:file_iternext(). */
1438#define READAHEAD_BUFSIZE 8192
1439static PyObject *
1440BZ2File_iternext(BZ2FileObject *self)
1441{
1442 PyStringObject* ret;
1443 ACQUIRE_LOCK(self);
1444 if (self->mode == MODE_CLOSED) {
1445 PyErr_SetString(PyExc_ValueError,
1446 "I/O operation on closed file");
1447 return NULL;
1448 }
1449 ret = Util_ReadAheadGetLineSkip(self, 0, READAHEAD_BUFSIZE);
1450 RELEASE_LOCK(self);
1451 if (ret == NULL || PyString_GET_SIZE(ret) == 0) {
1452 Py_XDECREF(ret);
1453 return NULL;
1454 }
1455 return (PyObject *)ret;
1456}
1457
1458/* ===================================================================== */
1459/* BZ2File_Type definition. */
1460
1461PyDoc_VAR(BZ2File__doc__) =
1462PyDoc_STR(
1463"BZ2File(name [, mode='r', buffering=0, compresslevel=9]) -> file object\n\
1464\n\
1465Open a bz2 file. The mode can be 'r' or 'w', for reading (default) or\n\
1466writing. When opened for writing, the file will be created if it doesn't\n\
1467exist, and truncated otherwise. If the buffering argument is given, 0 means\n\
1468unbuffered, and larger numbers specify the buffer size. If compresslevel\n\
1469is given, must be a number between 1 and 9.\n\
1470")
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001471PyDoc_STR(
1472"\n\
1473Add a 'U' to mode to open the file for input with universal newline\n\
1474support. Any line ending in the input file will be seen as a '\\n' in\n\
1475Python. Also, a file so opened gains the attribute 'newlines'; the value\n\
1476for this attribute is one of None (no newline read yet), '\\r', '\\n',\n\
1477'\\r\\n' or a tuple containing all the newline types seen. Universal\n\
1478newlines are available only when reading.\n\
1479")
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001480;
1481
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001482static PyTypeObject BZ2File_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +00001483 PyVarObject_HEAD_INIT(NULL, 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001484 "bz2.BZ2File", /*tp_name*/
1485 sizeof(BZ2FileObject), /*tp_basicsize*/
1486 0, /*tp_itemsize*/
1487 (destructor)BZ2File_dealloc, /*tp_dealloc*/
1488 0, /*tp_print*/
1489 0, /*tp_getattr*/
1490 0, /*tp_setattr*/
1491 0, /*tp_compare*/
1492 0, /*tp_repr*/
1493 0, /*tp_as_number*/
1494 0, /*tp_as_sequence*/
1495 0, /*tp_as_mapping*/
1496 0, /*tp_hash*/
1497 0, /*tp_call*/
1498 0, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001499 PyObject_GenericGetAttr,/*tp_getattro*/
1500 PyObject_GenericSetAttr,/*tp_setattro*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001501 0, /*tp_as_buffer*/
1502 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1503 BZ2File__doc__, /*tp_doc*/
1504 0, /*tp_traverse*/
1505 0, /*tp_clear*/
1506 0, /*tp_richcompare*/
1507 0, /*tp_weaklistoffset*/
1508 (getiterfunc)BZ2File_getiter, /*tp_iter*/
1509 (iternextfunc)BZ2File_iternext, /*tp_iternext*/
1510 BZ2File_methods, /*tp_methods*/
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001511 BZ2File_members, /*tp_members*/
1512 BZ2File_getset, /*tp_getset*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001513 0, /*tp_base*/
1514 0, /*tp_dict*/
1515 0, /*tp_descr_get*/
1516 0, /*tp_descr_set*/
1517 0, /*tp_dictoffset*/
1518 (initproc)BZ2File_init, /*tp_init*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001519 PyType_GenericAlloc, /*tp_alloc*/
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001520 PyType_GenericNew, /*tp_new*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001521 _PyObject_Del, /*tp_free*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001522 0, /*tp_is_gc*/
1523};
1524
1525
1526/* ===================================================================== */
1527/* Methods of BZ2Comp. */
1528
1529PyDoc_STRVAR(BZ2Comp_compress__doc__,
1530"compress(data) -> string\n\
1531\n\
1532Provide more data to the compressor object. It will return chunks of\n\
1533compressed data whenever possible. When you've finished providing data\n\
1534to compress, call the flush() method to finish the compression process,\n\
1535and return what is left in the internal buffers.\n\
1536");
1537
1538static PyObject *
1539BZ2Comp_compress(BZ2CompObject *self, PyObject *args)
1540{
1541 char *data;
1542 int datasize;
1543 int bufsize = SMALLCHUNK;
Martin v. Löwisb9a0f912003-03-29 10:06:18 +00001544 PY_LONG_LONG totalout;
Gustavo Niemeyer7d7930b2002-11-05 18:41:53 +00001545 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001546 bz_stream *bzs = &self->bzs;
1547 int bzerror;
1548
Walter Dörwaldbb9c7392004-11-01 17:10:19 +00001549 if (!PyArg_ParseTuple(args, "s#:compress", &data, &datasize))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001550 return NULL;
1551
Gustavo Niemeyera6e436e2004-02-14 00:02:45 +00001552 if (datasize == 0)
1553 return PyString_FromString("");
1554
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001555 ACQUIRE_LOCK(self);
1556 if (!self->running) {
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001557 PyErr_SetString(PyExc_ValueError,
1558 "this object was already flushed");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001559 goto error;
1560 }
1561
1562 ret = PyString_FromStringAndSize(NULL, bufsize);
1563 if (!ret)
1564 goto error;
1565
1566 bzs->next_in = data;
1567 bzs->avail_in = datasize;
1568 bzs->next_out = BUF(ret);
1569 bzs->avail_out = bufsize;
1570
1571 totalout = BZS_TOTAL_OUT(bzs);
1572
1573 for (;;) {
1574 Py_BEGIN_ALLOW_THREADS
1575 bzerror = BZ2_bzCompress(bzs, BZ_RUN);
1576 Py_END_ALLOW_THREADS
1577 if (bzerror != BZ_RUN_OK) {
1578 Util_CatchBZ2Error(bzerror);
1579 goto error;
1580 }
Georg Brandla47337f2007-03-13 12:34:25 +00001581 if (bzs->avail_in == 0)
1582 break; /* no more input data */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001583 if (bzs->avail_out == 0) {
1584 bufsize = Util_NewBufferSize(bufsize);
1585 if (_PyString_Resize(&ret, bufsize) < 0) {
1586 BZ2_bzCompressEnd(bzs);
1587 goto error;
1588 }
1589 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs)
1590 - totalout);
1591 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001592 }
1593 }
1594
Neal Norwitz047f3c72006-06-12 02:06:42 +00001595 _PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001596
1597 RELEASE_LOCK(self);
1598 return ret;
1599
1600error:
1601 RELEASE_LOCK(self);
1602 Py_XDECREF(ret);
1603 return NULL;
1604}
1605
1606PyDoc_STRVAR(BZ2Comp_flush__doc__,
1607"flush() -> string\n\
1608\n\
1609Finish the compression process and return what is left in internal buffers.\n\
1610You must not use the compressor object after calling this method.\n\
1611");
1612
1613static PyObject *
1614BZ2Comp_flush(BZ2CompObject *self)
1615{
1616 int bufsize = SMALLCHUNK;
Gustavo Niemeyer7d7930b2002-11-05 18:41:53 +00001617 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001618 bz_stream *bzs = &self->bzs;
Martin v. Löwisb9a0f912003-03-29 10:06:18 +00001619 PY_LONG_LONG totalout;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001620 int bzerror;
1621
1622 ACQUIRE_LOCK(self);
1623 if (!self->running) {
1624 PyErr_SetString(PyExc_ValueError, "object was already "
1625 "flushed");
1626 goto error;
1627 }
1628 self->running = 0;
1629
1630 ret = PyString_FromStringAndSize(NULL, bufsize);
1631 if (!ret)
1632 goto error;
1633
1634 bzs->next_out = BUF(ret);
1635 bzs->avail_out = bufsize;
1636
1637 totalout = BZS_TOTAL_OUT(bzs);
1638
1639 for (;;) {
1640 Py_BEGIN_ALLOW_THREADS
1641 bzerror = BZ2_bzCompress(bzs, BZ_FINISH);
1642 Py_END_ALLOW_THREADS
1643 if (bzerror == BZ_STREAM_END) {
1644 break;
1645 } else if (bzerror != BZ_FINISH_OK) {
1646 Util_CatchBZ2Error(bzerror);
1647 goto error;
1648 }
1649 if (bzs->avail_out == 0) {
1650 bufsize = Util_NewBufferSize(bufsize);
1651 if (_PyString_Resize(&ret, bufsize) < 0)
1652 goto error;
1653 bzs->next_out = BUF(ret);
1654 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs)
1655 - totalout);
1656 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
1657 }
1658 }
1659
1660 if (bzs->avail_out != 0)
Neal Norwitz047f3c72006-06-12 02:06:42 +00001661 _PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001662
1663 RELEASE_LOCK(self);
1664 return ret;
1665
1666error:
1667 RELEASE_LOCK(self);
1668 Py_XDECREF(ret);
1669 return NULL;
1670}
1671
1672static PyMethodDef BZ2Comp_methods[] = {
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001673 {"compress", (PyCFunction)BZ2Comp_compress, METH_VARARGS,
1674 BZ2Comp_compress__doc__},
1675 {"flush", (PyCFunction)BZ2Comp_flush, METH_NOARGS,
1676 BZ2Comp_flush__doc__},
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001677 {NULL, NULL} /* sentinel */
1678};
1679
1680
1681/* ===================================================================== */
1682/* Slot definitions for BZ2Comp_Type. */
1683
1684static int
1685BZ2Comp_init(BZ2CompObject *self, PyObject *args, PyObject *kwargs)
1686{
1687 int compresslevel = 9;
1688 int bzerror;
Martin v. Löwis15e62742006-02-27 16:46:16 +00001689 static char *kwlist[] = {"compresslevel", 0};
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001690
1691 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:BZ2Compressor",
1692 kwlist, &compresslevel))
1693 return -1;
1694
1695 if (compresslevel < 1 || compresslevel > 9) {
1696 PyErr_SetString(PyExc_ValueError,
1697 "compresslevel must be between 1 and 9");
1698 goto error;
1699 }
1700
1701#ifdef WITH_THREAD
1702 self->lock = PyThread_allocate_lock();
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001703 if (!self->lock) {
1704 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001705 goto error;
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001706 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001707#endif
1708
1709 memset(&self->bzs, 0, sizeof(bz_stream));
1710 bzerror = BZ2_bzCompressInit(&self->bzs, compresslevel, 0, 0);
1711 if (bzerror != BZ_OK) {
1712 Util_CatchBZ2Error(bzerror);
1713 goto error;
1714 }
1715
1716 self->running = 1;
1717
1718 return 0;
1719error:
1720#ifdef WITH_THREAD
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001721 if (self->lock) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001722 PyThread_free_lock(self->lock);
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001723 self->lock = NULL;
1724 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001725#endif
1726 return -1;
1727}
1728
1729static void
1730BZ2Comp_dealloc(BZ2CompObject *self)
1731{
1732#ifdef WITH_THREAD
1733 if (self->lock)
1734 PyThread_free_lock(self->lock);
1735#endif
1736 BZ2_bzCompressEnd(&self->bzs);
Martin v. Löwis68192102007-07-21 06:55:02 +00001737 Py_Type(self)->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001738}
1739
1740
1741/* ===================================================================== */
1742/* BZ2Comp_Type definition. */
1743
1744PyDoc_STRVAR(BZ2Comp__doc__,
1745"BZ2Compressor([compresslevel=9]) -> compressor object\n\
1746\n\
1747Create a new compressor object. This object may be used to compress\n\
1748data sequentially. If you want to compress data in one shot, use the\n\
1749compress() function instead. The compresslevel parameter, if given,\n\
1750must be a number between 1 and 9.\n\
1751");
1752
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001753static PyTypeObject BZ2Comp_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +00001754 PyVarObject_HEAD_INIT(NULL, 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001755 "bz2.BZ2Compressor", /*tp_name*/
1756 sizeof(BZ2CompObject), /*tp_basicsize*/
1757 0, /*tp_itemsize*/
1758 (destructor)BZ2Comp_dealloc, /*tp_dealloc*/
1759 0, /*tp_print*/
1760 0, /*tp_getattr*/
1761 0, /*tp_setattr*/
1762 0, /*tp_compare*/
1763 0, /*tp_repr*/
1764 0, /*tp_as_number*/
1765 0, /*tp_as_sequence*/
1766 0, /*tp_as_mapping*/
1767 0, /*tp_hash*/
1768 0, /*tp_call*/
1769 0, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001770 PyObject_GenericGetAttr,/*tp_getattro*/
1771 PyObject_GenericSetAttr,/*tp_setattro*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001772 0, /*tp_as_buffer*/
1773 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1774 BZ2Comp__doc__, /*tp_doc*/
1775 0, /*tp_traverse*/
1776 0, /*tp_clear*/
1777 0, /*tp_richcompare*/
1778 0, /*tp_weaklistoffset*/
1779 0, /*tp_iter*/
1780 0, /*tp_iternext*/
1781 BZ2Comp_methods, /*tp_methods*/
1782 0, /*tp_members*/
1783 0, /*tp_getset*/
1784 0, /*tp_base*/
1785 0, /*tp_dict*/
1786 0, /*tp_descr_get*/
1787 0, /*tp_descr_set*/
1788 0, /*tp_dictoffset*/
1789 (initproc)BZ2Comp_init, /*tp_init*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001790 PyType_GenericAlloc, /*tp_alloc*/
1791 PyType_GenericNew, /*tp_new*/
1792 _PyObject_Del, /*tp_free*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001793 0, /*tp_is_gc*/
1794};
1795
1796
1797/* ===================================================================== */
1798/* Members of BZ2Decomp. */
1799
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001800#undef OFF
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001801#define OFF(x) offsetof(BZ2DecompObject, x)
1802
1803static PyMemberDef BZ2Decomp_members[] = {
1804 {"unused_data", T_OBJECT, OFF(unused_data), RO},
1805 {NULL} /* Sentinel */
1806};
1807
1808
1809/* ===================================================================== */
1810/* Methods of BZ2Decomp. */
1811
1812PyDoc_STRVAR(BZ2Decomp_decompress__doc__,
1813"decompress(data) -> string\n\
1814\n\
1815Provide more data to the decompressor object. It will return chunks\n\
1816of decompressed data whenever possible. If you try to decompress data\n\
1817after the end of stream is found, EOFError will be raised. If any data\n\
1818was found after the end of stream, it'll be ignored and saved in\n\
1819unused_data attribute.\n\
1820");
1821
1822static PyObject *
1823BZ2Decomp_decompress(BZ2DecompObject *self, PyObject *args)
1824{
1825 char *data;
1826 int datasize;
1827 int bufsize = SMALLCHUNK;
Martin v. Löwisb9a0f912003-03-29 10:06:18 +00001828 PY_LONG_LONG totalout;
Neal Norwitz18142c02002-11-05 18:17:32 +00001829 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001830 bz_stream *bzs = &self->bzs;
1831 int bzerror;
1832
Walter Dörwaldbb9c7392004-11-01 17:10:19 +00001833 if (!PyArg_ParseTuple(args, "s#:decompress", &data, &datasize))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001834 return NULL;
1835
1836 ACQUIRE_LOCK(self);
1837 if (!self->running) {
1838 PyErr_SetString(PyExc_EOFError, "end of stream was "
1839 "already found");
1840 goto error;
1841 }
1842
1843 ret = PyString_FromStringAndSize(NULL, bufsize);
1844 if (!ret)
1845 goto error;
1846
1847 bzs->next_in = data;
1848 bzs->avail_in = datasize;
1849 bzs->next_out = BUF(ret);
1850 bzs->avail_out = bufsize;
1851
1852 totalout = BZS_TOTAL_OUT(bzs);
1853
1854 for (;;) {
1855 Py_BEGIN_ALLOW_THREADS
1856 bzerror = BZ2_bzDecompress(bzs);
1857 Py_END_ALLOW_THREADS
1858 if (bzerror == BZ_STREAM_END) {
1859 if (bzs->avail_in != 0) {
1860 Py_DECREF(self->unused_data);
1861 self->unused_data =
1862 PyString_FromStringAndSize(bzs->next_in,
1863 bzs->avail_in);
1864 }
1865 self->running = 0;
1866 break;
1867 }
1868 if (bzerror != BZ_OK) {
1869 Util_CatchBZ2Error(bzerror);
1870 goto error;
1871 }
Georg Brandla47337f2007-03-13 12:34:25 +00001872 if (bzs->avail_in == 0)
1873 break; /* no more input data */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001874 if (bzs->avail_out == 0) {
1875 bufsize = Util_NewBufferSize(bufsize);
1876 if (_PyString_Resize(&ret, bufsize) < 0) {
1877 BZ2_bzDecompressEnd(bzs);
1878 goto error;
1879 }
1880 bzs->next_out = BUF(ret);
1881 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs)
1882 - totalout);
1883 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001884 }
1885 }
1886
1887 if (bzs->avail_out != 0)
Neal Norwitz047f3c72006-06-12 02:06:42 +00001888 _PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001889
1890 RELEASE_LOCK(self);
1891 return ret;
1892
1893error:
1894 RELEASE_LOCK(self);
1895 Py_XDECREF(ret);
1896 return NULL;
1897}
1898
1899static PyMethodDef BZ2Decomp_methods[] = {
1900 {"decompress", (PyCFunction)BZ2Decomp_decompress, METH_VARARGS, BZ2Decomp_decompress__doc__},
1901 {NULL, NULL} /* sentinel */
1902};
1903
1904
1905/* ===================================================================== */
1906/* Slot definitions for BZ2Decomp_Type. */
1907
1908static int
1909BZ2Decomp_init(BZ2DecompObject *self, PyObject *args, PyObject *kwargs)
1910{
1911 int bzerror;
1912
1913 if (!PyArg_ParseTuple(args, ":BZ2Decompressor"))
1914 return -1;
1915
1916#ifdef WITH_THREAD
1917 self->lock = PyThread_allocate_lock();
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001918 if (!self->lock) {
1919 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001920 goto error;
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001921 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001922#endif
1923
1924 self->unused_data = PyString_FromString("");
1925 if (!self->unused_data)
1926 goto error;
1927
1928 memset(&self->bzs, 0, sizeof(bz_stream));
1929 bzerror = BZ2_bzDecompressInit(&self->bzs, 0, 0);
1930 if (bzerror != BZ_OK) {
1931 Util_CatchBZ2Error(bzerror);
1932 goto error;
1933 }
1934
1935 self->running = 1;
1936
1937 return 0;
1938
1939error:
1940#ifdef WITH_THREAD
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001941 if (self->lock) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001942 PyThread_free_lock(self->lock);
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001943 self->lock = NULL;
1944 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001945#endif
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001946 Py_CLEAR(self->unused_data);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001947 return -1;
1948}
1949
1950static void
1951BZ2Decomp_dealloc(BZ2DecompObject *self)
1952{
1953#ifdef WITH_THREAD
1954 if (self->lock)
1955 PyThread_free_lock(self->lock);
1956#endif
1957 Py_XDECREF(self->unused_data);
1958 BZ2_bzDecompressEnd(&self->bzs);
Martin v. Löwis68192102007-07-21 06:55:02 +00001959 Py_Type(self)->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001960}
1961
1962
1963/* ===================================================================== */
1964/* BZ2Decomp_Type definition. */
1965
1966PyDoc_STRVAR(BZ2Decomp__doc__,
1967"BZ2Decompressor() -> decompressor object\n\
1968\n\
1969Create a new decompressor object. This object may be used to decompress\n\
1970data sequentially. If you want to decompress data in one shot, use the\n\
1971decompress() function instead.\n\
1972");
1973
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001974static PyTypeObject BZ2Decomp_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +00001975 PyVarObject_HEAD_INIT(NULL, 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001976 "bz2.BZ2Decompressor", /*tp_name*/
1977 sizeof(BZ2DecompObject), /*tp_basicsize*/
1978 0, /*tp_itemsize*/
1979 (destructor)BZ2Decomp_dealloc, /*tp_dealloc*/
1980 0, /*tp_print*/
1981 0, /*tp_getattr*/
1982 0, /*tp_setattr*/
1983 0, /*tp_compare*/
1984 0, /*tp_repr*/
1985 0, /*tp_as_number*/
1986 0, /*tp_as_sequence*/
1987 0, /*tp_as_mapping*/
1988 0, /*tp_hash*/
1989 0, /*tp_call*/
1990 0, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001991 PyObject_GenericGetAttr,/*tp_getattro*/
1992 PyObject_GenericSetAttr,/*tp_setattro*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001993 0, /*tp_as_buffer*/
1994 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1995 BZ2Decomp__doc__, /*tp_doc*/
1996 0, /*tp_traverse*/
1997 0, /*tp_clear*/
1998 0, /*tp_richcompare*/
1999 0, /*tp_weaklistoffset*/
2000 0, /*tp_iter*/
2001 0, /*tp_iternext*/
2002 BZ2Decomp_methods, /*tp_methods*/
2003 BZ2Decomp_members, /*tp_members*/
2004 0, /*tp_getset*/
2005 0, /*tp_base*/
2006 0, /*tp_dict*/
2007 0, /*tp_descr_get*/
2008 0, /*tp_descr_set*/
2009 0, /*tp_dictoffset*/
2010 (initproc)BZ2Decomp_init, /*tp_init*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00002011 PyType_GenericAlloc, /*tp_alloc*/
2012 PyType_GenericNew, /*tp_new*/
2013 _PyObject_Del, /*tp_free*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002014 0, /*tp_is_gc*/
2015};
2016
2017
2018/* ===================================================================== */
2019/* Module functions. */
2020
2021PyDoc_STRVAR(bz2_compress__doc__,
2022"compress(data [, compresslevel=9]) -> string\n\
2023\n\
2024Compress data in one shot. If you want to compress data sequentially,\n\
2025use an instance of BZ2Compressor instead. The compresslevel parameter, if\n\
2026given, must be a number between 1 and 9.\n\
2027");
2028
2029static PyObject *
2030bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
2031{
2032 int compresslevel=9;
2033 char *data;
2034 int datasize;
2035 int bufsize;
Gustavo Niemeyer7d7930b2002-11-05 18:41:53 +00002036 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002037 bz_stream _bzs;
2038 bz_stream *bzs = &_bzs;
2039 int bzerror;
Martin v. Löwis15e62742006-02-27 16:46:16 +00002040 static char *kwlist[] = {"data", "compresslevel", 0};
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002041
2042 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|i",
2043 kwlist, &data, &datasize,
2044 &compresslevel))
2045 return NULL;
2046
2047 if (compresslevel < 1 || compresslevel > 9) {
2048 PyErr_SetString(PyExc_ValueError,
2049 "compresslevel must be between 1 and 9");
2050 return NULL;
2051 }
2052
2053 /* Conforming to bz2 manual, this is large enough to fit compressed
2054 * data in one shot. We will check it later anyway. */
2055 bufsize = datasize + (datasize/100+1) + 600;
2056
2057 ret = PyString_FromStringAndSize(NULL, bufsize);
2058 if (!ret)
2059 return NULL;
2060
2061 memset(bzs, 0, sizeof(bz_stream));
2062
2063 bzs->next_in = data;
2064 bzs->avail_in = datasize;
2065 bzs->next_out = BUF(ret);
2066 bzs->avail_out = bufsize;
2067
2068 bzerror = BZ2_bzCompressInit(bzs, compresslevel, 0, 0);
2069 if (bzerror != BZ_OK) {
2070 Util_CatchBZ2Error(bzerror);
2071 Py_DECREF(ret);
2072 return NULL;
2073 }
Tim Peterse3228092002-11-09 04:21:44 +00002074
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002075 for (;;) {
2076 Py_BEGIN_ALLOW_THREADS
2077 bzerror = BZ2_bzCompress(bzs, BZ_FINISH);
2078 Py_END_ALLOW_THREADS
2079 if (bzerror == BZ_STREAM_END) {
2080 break;
2081 } else if (bzerror != BZ_FINISH_OK) {
2082 BZ2_bzCompressEnd(bzs);
2083 Util_CatchBZ2Error(bzerror);
2084 Py_DECREF(ret);
2085 return NULL;
2086 }
2087 if (bzs->avail_out == 0) {
2088 bufsize = Util_NewBufferSize(bufsize);
2089 if (_PyString_Resize(&ret, bufsize) < 0) {
2090 BZ2_bzCompressEnd(bzs);
2091 Py_DECREF(ret);
2092 return NULL;
2093 }
2094 bzs->next_out = BUF(ret) + BZS_TOTAL_OUT(bzs);
2095 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
2096 }
2097 }
2098
2099 if (bzs->avail_out != 0)
Neal Norwitz047f3c72006-06-12 02:06:42 +00002100 _PyString_Resize(&ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002101 BZ2_bzCompressEnd(bzs);
2102
2103 return ret;
2104}
2105
2106PyDoc_STRVAR(bz2_decompress__doc__,
2107"decompress(data) -> decompressed data\n\
2108\n\
2109Decompress data in one shot. If you want to decompress data sequentially,\n\
2110use an instance of BZ2Decompressor instead.\n\
2111");
2112
2113static PyObject *
2114bz2_decompress(PyObject *self, PyObject *args)
2115{
2116 char *data;
2117 int datasize;
2118 int bufsize = SMALLCHUNK;
2119 PyObject *ret;
2120 bz_stream _bzs;
2121 bz_stream *bzs = &_bzs;
2122 int bzerror;
2123
Walter Dörwaldbb9c7392004-11-01 17:10:19 +00002124 if (!PyArg_ParseTuple(args, "s#:decompress", &data, &datasize))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002125 return NULL;
2126
2127 if (datasize == 0)
2128 return PyString_FromString("");
2129
2130 ret = PyString_FromStringAndSize(NULL, bufsize);
2131 if (!ret)
2132 return NULL;
2133
2134 memset(bzs, 0, sizeof(bz_stream));
2135
2136 bzs->next_in = data;
2137 bzs->avail_in = datasize;
2138 bzs->next_out = BUF(ret);
2139 bzs->avail_out = bufsize;
2140
2141 bzerror = BZ2_bzDecompressInit(bzs, 0, 0);
2142 if (bzerror != BZ_OK) {
2143 Util_CatchBZ2Error(bzerror);
2144 Py_DECREF(ret);
2145 return NULL;
2146 }
Tim Peterse3228092002-11-09 04:21:44 +00002147
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002148 for (;;) {
2149 Py_BEGIN_ALLOW_THREADS
2150 bzerror = BZ2_bzDecompress(bzs);
2151 Py_END_ALLOW_THREADS
2152 if (bzerror == BZ_STREAM_END) {
2153 break;
2154 } else if (bzerror != BZ_OK) {
2155 BZ2_bzDecompressEnd(bzs);
2156 Util_CatchBZ2Error(bzerror);
2157 Py_DECREF(ret);
2158 return NULL;
2159 }
Georg Brandla47337f2007-03-13 12:34:25 +00002160 if (bzs->avail_in == 0) {
2161 BZ2_bzDecompressEnd(bzs);
2162 PyErr_SetString(PyExc_ValueError,
2163 "couldn't find end of stream");
2164 Py_DECREF(ret);
2165 return NULL;
2166 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002167 if (bzs->avail_out == 0) {
2168 bufsize = Util_NewBufferSize(bufsize);
2169 if (_PyString_Resize(&ret, bufsize) < 0) {
2170 BZ2_bzDecompressEnd(bzs);
2171 Py_DECREF(ret);
2172 return NULL;
2173 }
2174 bzs->next_out = BUF(ret) + BZS_TOTAL_OUT(bzs);
2175 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002176 }
2177 }
2178
2179 if (bzs->avail_out != 0)
Neal Norwitz047f3c72006-06-12 02:06:42 +00002180 _PyString_Resize(&ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002181 BZ2_bzDecompressEnd(bzs);
2182
2183 return ret;
2184}
2185
2186static PyMethodDef bz2_methods[] = {
2187 {"compress", (PyCFunction) bz2_compress, METH_VARARGS|METH_KEYWORDS,
2188 bz2_compress__doc__},
2189 {"decompress", (PyCFunction) bz2_decompress, METH_VARARGS,
2190 bz2_decompress__doc__},
2191 {NULL, NULL} /* sentinel */
2192};
2193
2194/* ===================================================================== */
2195/* Initialization function. */
2196
2197PyDoc_STRVAR(bz2__doc__,
2198"The python bz2 module provides a comprehensive interface for\n\
2199the bz2 compression library. It implements a complete file\n\
2200interface, one shot (de)compression functions, and types for\n\
2201sequential (de)compression.\n\
2202");
2203
Neal Norwitz21d896c2003-07-01 20:15:21 +00002204PyMODINIT_FUNC
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002205initbz2(void)
2206{
2207 PyObject *m;
2208
Martin v. Löwis68192102007-07-21 06:55:02 +00002209 Py_Type(&BZ2File_Type) = &PyType_Type;
2210 Py_Type(&BZ2Comp_Type) = &PyType_Type;
2211 Py_Type(&BZ2Decomp_Type) = &PyType_Type;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002212
2213 m = Py_InitModule3("bz2", bz2_methods, bz2__doc__);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00002214 if (m == NULL)
2215 return;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002216
2217 PyModule_AddObject(m, "__author__", PyString_FromString(__author__));
2218
2219 Py_INCREF(&BZ2File_Type);
2220 PyModule_AddObject(m, "BZ2File", (PyObject *)&BZ2File_Type);
2221
2222 Py_INCREF(&BZ2Comp_Type);
2223 PyModule_AddObject(m, "BZ2Compressor", (PyObject *)&BZ2Comp_Type);
2224
2225 Py_INCREF(&BZ2Decomp_Type);
2226 PyModule_AddObject(m, "BZ2Decompressor", (PyObject *)&BZ2Decomp_Type);
2227}