blob: 7d33a77f128d5738621bc37421962bd1222a89e4 [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) {
419 return -1;
420 }
421 Py_BEGIN_ALLOW_THREADS
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000422 chunksize = Util_UnivNewlineRead(&bzerror, f->fp, f->f_buf,
423 bufsize, f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000424 Py_END_ALLOW_THREADS
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000425 f->pos += chunksize;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000426 if (bzerror == BZ_STREAM_END) {
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000427 f->size = f->pos;
428 f->mode = MODE_READ_EOF;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000429 } else if (bzerror != BZ_OK) {
430 Util_CatchBZ2Error(bzerror);
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000431 Util_DropReadAhead(f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000432 return -1;
433 }
434 f->f_bufptr = f->f_buf;
435 f->f_bufend = f->f_buf + chunksize;
436 return 0;
437}
438
439/* This is a hacked version of Python's
440 * fileobject.c:readahead_get_line_skip(). */
441static PyStringObject *
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000442Util_ReadAheadGetLineSkip(BZ2FileObject *f, int skip, int bufsize)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000443{
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000444 PyStringObject* s;
445 char *bufptr;
446 char *buf;
447 int len;
448
449 if (f->f_buf == NULL)
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000450 if (Util_ReadAhead(f, bufsize) < 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000451 return NULL;
452
453 len = f->f_bufend - f->f_bufptr;
Tim Peterse3228092002-11-09 04:21:44 +0000454 if (len == 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000455 return (PyStringObject *)
456 PyString_FromStringAndSize(NULL, skip);
457 bufptr = memchr(f->f_bufptr, '\n', len);
458 if (bufptr != NULL) {
459 bufptr++; /* Count the '\n' */
460 len = bufptr - f->f_bufptr;
461 s = (PyStringObject *)
462 PyString_FromStringAndSize(NULL, skip+len);
Tim Peterse3228092002-11-09 04:21:44 +0000463 if (s == NULL)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000464 return NULL;
465 memcpy(PyString_AS_STRING(s)+skip, f->f_bufptr, len);
466 f->f_bufptr = bufptr;
467 if (bufptr == f->f_bufend)
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000468 Util_DropReadAhead(f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000469 } else {
470 bufptr = f->f_bufptr;
471 buf = f->f_buf;
472 f->f_buf = NULL; /* Force new readahead buffer */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000473 s = Util_ReadAheadGetLineSkip(f, skip+len,
474 bufsize + (bufsize>>2));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000475 if (s == NULL) {
476 PyMem_Free(buf);
477 return NULL;
478 }
479 memcpy(PyString_AS_STRING(s)+skip, bufptr, len);
480 PyMem_Free(buf);
481 }
482 return s;
483}
484
485/* ===================================================================== */
486/* Methods of BZ2File. */
487
488PyDoc_STRVAR(BZ2File_read__doc__,
489"read([size]) -> string\n\
490\n\
491Read at most size uncompressed bytes, returned as a string. If the size\n\
492argument is negative or omitted, read until EOF is reached.\n\
493");
494
495/* This is a hacked version of Python's fileobject.c:file_read(). */
496static PyObject *
497BZ2File_read(BZ2FileObject *self, PyObject *args)
498{
499 long bytesrequested = -1;
500 size_t bytesread, buffersize, chunksize;
501 int bzerror;
502 PyObject *ret = NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000503
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000504 if (!PyArg_ParseTuple(args, "|l:read", &bytesrequested))
505 return NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000506
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000507 ACQUIRE_LOCK(self);
508 switch (self->mode) {
509 case MODE_READ:
510 break;
511 case MODE_READ_EOF:
512 ret = PyString_FromString("");
513 goto cleanup;
514 case MODE_CLOSED:
515 PyErr_SetString(PyExc_ValueError,
516 "I/O operation on closed file");
517 goto cleanup;
518 default:
519 PyErr_SetString(PyExc_IOError,
520 "file is not ready for reading");
521 goto cleanup;
522 }
523
524 if (bytesrequested < 0)
525 buffersize = Util_NewBufferSize((size_t)0);
526 else
527 buffersize = bytesrequested;
528 if (buffersize > INT_MAX) {
529 PyErr_SetString(PyExc_OverflowError,
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +0000530 "requested number of bytes is "
531 "more than a Python string can hold");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000532 goto cleanup;
533 }
534 ret = PyString_FromStringAndSize((char *)NULL, buffersize);
535 if (ret == NULL)
536 goto cleanup;
537 bytesread = 0;
538
539 for (;;) {
540 Py_BEGIN_ALLOW_THREADS
541 chunksize = Util_UnivNewlineRead(&bzerror, self->fp,
542 BUF(ret)+bytesread,
543 buffersize-bytesread,
544 self);
545 self->pos += chunksize;
546 Py_END_ALLOW_THREADS
547 bytesread += chunksize;
548 if (bzerror == BZ_STREAM_END) {
549 self->size = self->pos;
550 self->mode = MODE_READ_EOF;
551 break;
552 } else if (bzerror != BZ_OK) {
553 Util_CatchBZ2Error(bzerror);
554 Py_DECREF(ret);
555 ret = NULL;
556 goto cleanup;
557 }
558 if (bytesrequested < 0) {
559 buffersize = Util_NewBufferSize(buffersize);
560 if (_PyString_Resize(&ret, buffersize) < 0)
561 goto cleanup;
562 } else {
563 break;
564 }
565 }
566 if (bytesread != buffersize)
567 _PyString_Resize(&ret, bytesread);
568
569cleanup:
570 RELEASE_LOCK(self);
571 return ret;
572}
573
574PyDoc_STRVAR(BZ2File_readline__doc__,
575"readline([size]) -> string\n\
576\n\
577Return the next line from the file, as a string, retaining newline.\n\
578A non-negative size argument will limit the maximum number of bytes to\n\
579return (an incomplete line may be returned then). Return an empty\n\
580string at EOF.\n\
581");
582
583static PyObject *
584BZ2File_readline(BZ2FileObject *self, PyObject *args)
585{
586 PyObject *ret = NULL;
587 int sizehint = -1;
588
589 if (!PyArg_ParseTuple(args, "|i:readline", &sizehint))
590 return NULL;
591
592 ACQUIRE_LOCK(self);
593 switch (self->mode) {
594 case MODE_READ:
595 break;
596 case MODE_READ_EOF:
597 ret = PyString_FromString("");
598 goto cleanup;
599 case MODE_CLOSED:
600 PyErr_SetString(PyExc_ValueError,
601 "I/O operation on closed file");
602 goto cleanup;
603 default:
604 PyErr_SetString(PyExc_IOError,
605 "file is not ready for reading");
606 goto cleanup;
607 }
608
609 if (sizehint == 0)
610 ret = PyString_FromString("");
611 else
612 ret = Util_GetLine(self, (sizehint < 0) ? 0 : sizehint);
613
614cleanup:
615 RELEASE_LOCK(self);
616 return ret;
617}
618
619PyDoc_STRVAR(BZ2File_readlines__doc__,
620"readlines([size]) -> list\n\
621\n\
622Call readline() repeatedly and return a list of lines read.\n\
623The optional size argument, if given, is an approximate bound on the\n\
624total number of bytes in the lines returned.\n\
625");
626
627/* This is a hacked version of Python's fileobject.c:file_readlines(). */
628static PyObject *
629BZ2File_readlines(BZ2FileObject *self, PyObject *args)
630{
631 long sizehint = 0;
632 PyObject *list = NULL;
633 PyObject *line;
634 char small_buffer[SMALLCHUNK];
635 char *buffer = small_buffer;
636 size_t buffersize = SMALLCHUNK;
637 PyObject *big_buffer = NULL;
638 size_t nfilled = 0;
639 size_t nread;
640 size_t totalread = 0;
641 char *p, *q, *end;
642 int err;
643 int shortread = 0;
644 int bzerror;
645
646 if (!PyArg_ParseTuple(args, "|l:readlines", &sizehint))
647 return NULL;
648
649 ACQUIRE_LOCK(self);
650 switch (self->mode) {
651 case MODE_READ:
652 break;
653 case MODE_READ_EOF:
654 list = PyList_New(0);
655 goto cleanup;
656 case MODE_CLOSED:
657 PyErr_SetString(PyExc_ValueError,
658 "I/O operation on closed file");
659 goto cleanup;
660 default:
661 PyErr_SetString(PyExc_IOError,
662 "file is not ready for reading");
663 goto cleanup;
664 }
665
666 if ((list = PyList_New(0)) == NULL)
667 goto cleanup;
668
669 for (;;) {
670 Py_BEGIN_ALLOW_THREADS
671 nread = Util_UnivNewlineRead(&bzerror, self->fp,
672 buffer+nfilled,
673 buffersize-nfilled, self);
674 self->pos += nread;
675 Py_END_ALLOW_THREADS
676 if (bzerror == BZ_STREAM_END) {
677 self->size = self->pos;
678 self->mode = MODE_READ_EOF;
679 if (nread == 0) {
680 sizehint = 0;
681 break;
682 }
683 shortread = 1;
684 } else if (bzerror != BZ_OK) {
685 Util_CatchBZ2Error(bzerror);
686 error:
687 Py_DECREF(list);
688 list = NULL;
689 goto cleanup;
690 }
691 totalread += nread;
692 p = memchr(buffer+nfilled, '\n', nread);
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000693 if (!shortread && p == NULL) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000694 /* Need a larger buffer to fit this line */
695 nfilled += nread;
696 buffersize *= 2;
697 if (buffersize > INT_MAX) {
698 PyErr_SetString(PyExc_OverflowError,
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000699 "line is longer than a Python string can hold");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000700 goto error;
701 }
702 if (big_buffer == NULL) {
703 /* Create the big buffer */
704 big_buffer = PyString_FromStringAndSize(
705 NULL, buffersize);
706 if (big_buffer == NULL)
707 goto error;
708 buffer = PyString_AS_STRING(big_buffer);
709 memcpy(buffer, small_buffer, nfilled);
710 }
711 else {
712 /* Grow the big buffer */
713 _PyString_Resize(&big_buffer, buffersize);
714 buffer = PyString_AS_STRING(big_buffer);
715 }
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000716 continue;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000717 }
718 end = buffer+nfilled+nread;
719 q = buffer;
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000720 while (p != NULL) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000721 /* Process complete lines */
722 p++;
723 line = PyString_FromStringAndSize(q, p-q);
724 if (line == NULL)
725 goto error;
726 err = PyList_Append(list, line);
727 Py_DECREF(line);
728 if (err != 0)
729 goto error;
730 q = p;
731 p = memchr(q, '\n', end-q);
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000732 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000733 /* Move the remaining incomplete line to the start */
734 nfilled = end-q;
735 memmove(buffer, q, nfilled);
736 if (sizehint > 0)
737 if (totalread >= (size_t)sizehint)
738 break;
739 if (shortread) {
740 sizehint = 0;
741 break;
742 }
743 }
744 if (nfilled != 0) {
745 /* Partial last line */
746 line = PyString_FromStringAndSize(buffer, nfilled);
747 if (line == NULL)
748 goto error;
749 if (sizehint > 0) {
750 /* Need to complete the last line */
751 PyObject *rest = Util_GetLine(self, 0);
752 if (rest == NULL) {
753 Py_DECREF(line);
754 goto error;
755 }
756 PyString_Concat(&line, rest);
757 Py_DECREF(rest);
758 if (line == NULL)
759 goto error;
760 }
761 err = PyList_Append(list, line);
762 Py_DECREF(line);
763 if (err != 0)
764 goto error;
765 }
766
767 cleanup:
768 RELEASE_LOCK(self);
769 if (big_buffer) {
770 Py_DECREF(big_buffer);
771 }
772 return list;
773}
774
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000775PyDoc_STRVAR(BZ2File_xreadlines__doc__,
776"xreadlines() -> self\n\
777\n\
778For backward compatibility. BZ2File objects now include the performance\n\
779optimizations previously implemented in the xreadlines module.\n\
780");
781
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000782PyDoc_STRVAR(BZ2File_write__doc__,
783"write(data) -> None\n\
784\n\
785Write the 'data' string to file. Note that due to buffering, close() may\n\
786be needed before the file on disk reflects the data written.\n\
787");
788
789/* This is a hacked version of Python's fileobject.c:file_write(). */
790static PyObject *
791BZ2File_write(BZ2FileObject *self, PyObject *args)
792{
793 PyObject *ret = NULL;
794 char *buf;
795 int len;
796 int bzerror;
797
Walter Dörwaldbb9c7392004-11-01 17:10:19 +0000798 if (!PyArg_ParseTuple(args, "s#:write", &buf, &len))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000799 return NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000800
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000801 ACQUIRE_LOCK(self);
802 switch (self->mode) {
803 case MODE_WRITE:
804 break;
Tim Peterse3228092002-11-09 04:21:44 +0000805
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000806 case MODE_CLOSED:
807 PyErr_SetString(PyExc_ValueError,
808 "I/O operation on closed file");
Georg Brandl3335a7a2006-08-14 21:42:55 +0000809 goto cleanup;
Tim Peterse3228092002-11-09 04:21:44 +0000810
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000811 default:
812 PyErr_SetString(PyExc_IOError,
813 "file is not ready for writing");
Georg Brandl3335a7a2006-08-14 21:42:55 +0000814 goto cleanup;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000815 }
816
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000817 self->f_softspace = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000818
819 Py_BEGIN_ALLOW_THREADS
820 BZ2_bzWrite (&bzerror, self->fp, buf, len);
821 self->pos += len;
822 Py_END_ALLOW_THREADS
Tim Peterse3228092002-11-09 04:21:44 +0000823
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000824 if (bzerror != BZ_OK) {
825 Util_CatchBZ2Error(bzerror);
826 goto cleanup;
827 }
Tim Peterse3228092002-11-09 04:21:44 +0000828
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000829 Py_INCREF(Py_None);
830 ret = Py_None;
831
832cleanup:
833 RELEASE_LOCK(self);
834 return ret;
835}
836
837PyDoc_STRVAR(BZ2File_writelines__doc__,
838"writelines(sequence_of_strings) -> None\n\
839\n\
840Write the sequence of strings to the file. Note that newlines are not\n\
841added. The sequence can be any iterable object producing strings. This is\n\
842equivalent to calling write() for each string.\n\
843");
844
845/* This is a hacked version of Python's fileobject.c:file_writelines(). */
846static PyObject *
847BZ2File_writelines(BZ2FileObject *self, PyObject *seq)
848{
849#define CHUNKSIZE 1000
850 PyObject *list = NULL;
851 PyObject *iter = NULL;
852 PyObject *ret = NULL;
853 PyObject *line;
854 int i, j, index, len, islist;
855 int bzerror;
856
857 ACQUIRE_LOCK(self);
Georg Brandl3335a7a2006-08-14 21:42:55 +0000858 switch (self->mode) {
859 case MODE_WRITE:
860 break;
861
862 case MODE_CLOSED:
863 PyErr_SetString(PyExc_ValueError,
864 "I/O operation on closed file");
865 goto error;
866
867 default:
868 PyErr_SetString(PyExc_IOError,
869 "file is not ready for writing");
870 goto error;
871 }
872
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000873 islist = PyList_Check(seq);
874 if (!islist) {
875 iter = PyObject_GetIter(seq);
876 if (iter == NULL) {
877 PyErr_SetString(PyExc_TypeError,
878 "writelines() requires an iterable argument");
879 goto error;
880 }
881 list = PyList_New(CHUNKSIZE);
882 if (list == NULL)
883 goto error;
884 }
885
886 /* Strategy: slurp CHUNKSIZE lines into a private list,
887 checking that they are all strings, then write that list
888 without holding the interpreter lock, then come back for more. */
889 for (index = 0; ; index += CHUNKSIZE) {
890 if (islist) {
891 Py_XDECREF(list);
892 list = PyList_GetSlice(seq, index, index+CHUNKSIZE);
893 if (list == NULL)
894 goto error;
895 j = PyList_GET_SIZE(list);
896 }
897 else {
898 for (j = 0; j < CHUNKSIZE; j++) {
899 line = PyIter_Next(iter);
900 if (line == NULL) {
901 if (PyErr_Occurred())
902 goto error;
903 break;
904 }
905 PyList_SetItem(list, j, line);
906 }
907 }
908 if (j == 0)
909 break;
910
911 /* Check that all entries are indeed strings. If not,
912 apply the same rules as for file.write() and
913 convert the rets to strings. This is slow, but
914 seems to be the only way since all conversion APIs
915 could potentially execute Python code. */
916 for (i = 0; i < j; i++) {
917 PyObject *v = PyList_GET_ITEM(list, i);
918 if (!PyString_Check(v)) {
919 const char *buffer;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000920 Py_ssize_t len;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000921 if (PyObject_AsCharBuffer(v, &buffer, &len)) {
922 PyErr_SetString(PyExc_TypeError,
923 "writelines() "
924 "argument must be "
925 "a sequence of "
926 "strings");
927 goto error;
928 }
929 line = PyString_FromStringAndSize(buffer,
930 len);
931 if (line == NULL)
932 goto error;
933 Py_DECREF(v);
934 PyList_SET_ITEM(list, i, line);
935 }
936 }
937
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000938 self->f_softspace = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000939
940 /* Since we are releasing the global lock, the
941 following code may *not* execute Python code. */
942 Py_BEGIN_ALLOW_THREADS
943 for (i = 0; i < j; i++) {
944 line = PyList_GET_ITEM(list, i);
945 len = PyString_GET_SIZE(line);
946 BZ2_bzWrite (&bzerror, self->fp,
947 PyString_AS_STRING(line), len);
948 if (bzerror != BZ_OK) {
949 Py_BLOCK_THREADS
950 Util_CatchBZ2Error(bzerror);
951 goto error;
952 }
953 }
954 Py_END_ALLOW_THREADS
955
956 if (j < CHUNKSIZE)
957 break;
958 }
959
960 Py_INCREF(Py_None);
961 ret = Py_None;
962
963 error:
964 RELEASE_LOCK(self);
965 Py_XDECREF(list);
966 Py_XDECREF(iter);
967 return ret;
968#undef CHUNKSIZE
969}
970
971PyDoc_STRVAR(BZ2File_seek__doc__,
972"seek(offset [, whence]) -> None\n\
973\n\
974Move to new file position. Argument offset is a byte count. Optional\n\
975argument whence defaults to 0 (offset from start of file, offset\n\
976should be >= 0); other values are 1 (move relative to current position,\n\
977positive or negative), and 2 (move relative to end of file, usually\n\
978negative, although many platforms allow seeking beyond the end of a file).\n\
979\n\
980Note that seeking of bz2 files is emulated, and depending on the parameters\n\
981the operation may be extremely slow.\n\
982");
983
984static PyObject *
985BZ2File_seek(BZ2FileObject *self, PyObject *args)
986{
987 int where = 0;
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000988 PyObject *offobj;
989 Py_off_t offset;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000990 char small_buffer[SMALLCHUNK];
991 char *buffer = small_buffer;
992 size_t buffersize = SMALLCHUNK;
Andrew M. Kuchling9333ce12006-12-18 19:26:13 +0000993 Py_off_t bytesread = 0;
Georg Brandla8bcecc2005-09-03 07:49:53 +0000994 size_t readsize;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000995 int chunksize;
996 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000997 PyObject *ret = NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000998
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000999 if (!PyArg_ParseTuple(args, "O|i:seek", &offobj, &where))
1000 return NULL;
1001#if !defined(HAVE_LARGEFILE_SUPPORT)
1002 offset = PyInt_AsLong(offobj);
1003#else
1004 offset = PyLong_Check(offobj) ?
1005 PyLong_AsLongLong(offobj) : PyInt_AsLong(offobj);
1006#endif
1007 if (PyErr_Occurred())
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001008 return NULL;
1009
1010 ACQUIRE_LOCK(self);
1011 Util_DropReadAhead(self);
1012 switch (self->mode) {
1013 case MODE_READ:
1014 case MODE_READ_EOF:
1015 break;
Tim Peterse3228092002-11-09 04:21:44 +00001016
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001017 case MODE_CLOSED:
1018 PyErr_SetString(PyExc_ValueError,
1019 "I/O operation on closed file");
Georg Brandlb14b59f2006-09-25 06:53:42 +00001020 goto cleanup;
Tim Peterse3228092002-11-09 04:21:44 +00001021
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001022 default:
1023 PyErr_SetString(PyExc_IOError,
1024 "seek works only while reading");
Georg Brandlb14b59f2006-09-25 06:53:42 +00001025 goto cleanup;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001026 }
1027
Georg Brandl47fab922006-02-18 21:57:25 +00001028 if (where == 2) {
1029 if (self->size == -1) {
1030 assert(self->mode != MODE_READ_EOF);
1031 for (;;) {
1032 Py_BEGIN_ALLOW_THREADS
1033 chunksize = Util_UnivNewlineRead(
1034 &bzerror, self->fp,
1035 buffer, buffersize,
1036 self);
1037 self->pos += chunksize;
1038 Py_END_ALLOW_THREADS
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001039
Georg Brandl47fab922006-02-18 21:57:25 +00001040 bytesread += chunksize;
1041 if (bzerror == BZ_STREAM_END) {
1042 break;
1043 } else if (bzerror != BZ_OK) {
1044 Util_CatchBZ2Error(bzerror);
1045 goto cleanup;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001046 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001047 }
Georg Brandl47fab922006-02-18 21:57:25 +00001048 self->mode = MODE_READ_EOF;
1049 self->size = self->pos;
1050 bytesread = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001051 }
Georg Brandl47fab922006-02-18 21:57:25 +00001052 offset = self->size + offset;
1053 } else if (where == 1) {
1054 offset = self->pos + offset;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001055 }
1056
Georg Brandl47fab922006-02-18 21:57:25 +00001057 /* Before getting here, offset must be the absolute position the file
1058 * pointer should be set to. */
1059
1060 if (offset >= self->pos) {
1061 /* we can move forward */
1062 offset -= self->pos;
1063 } else {
1064 /* we cannot move back, so rewind the stream */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001065 BZ2_bzReadClose(&bzerror, self->fp);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001066 if (bzerror != BZ_OK) {
1067 Util_CatchBZ2Error(bzerror);
1068 goto cleanup;
1069 }
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001070 ret = PyObject_CallMethod(self->file, "seek", "(i)", 0);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001071 if (!ret)
1072 goto cleanup;
1073 Py_DECREF(ret);
1074 ret = NULL;
1075 self->pos = 0;
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001076 self->fp = BZ2_bzReadOpen(&bzerror, PyFile_AsFile(self->file),
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001077 0, 0, NULL, 0);
1078 if (bzerror != BZ_OK) {
1079 Util_CatchBZ2Error(bzerror);
1080 goto cleanup;
1081 }
1082 self->mode = MODE_READ;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001083 }
1084
Georg Brandl47fab922006-02-18 21:57:25 +00001085 if (offset <= 0 || self->mode == MODE_READ_EOF)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001086 goto exit;
1087
1088 /* Before getting here, offset must be set to the number of bytes
1089 * to walk forward. */
1090 for (;;) {
Georg Brandla8bcecc2005-09-03 07:49:53 +00001091 if (offset-bytesread > buffersize)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001092 readsize = buffersize;
1093 else
Georg Brandla8bcecc2005-09-03 07:49:53 +00001094 /* offset might be wider that readsize, but the result
1095 * of the subtraction is bound by buffersize (see the
1096 * condition above). buffersize is 8192. */
1097 readsize = (size_t)(offset-bytesread);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001098 Py_BEGIN_ALLOW_THREADS
1099 chunksize = Util_UnivNewlineRead(&bzerror, self->fp,
1100 buffer, readsize, self);
1101 self->pos += chunksize;
1102 Py_END_ALLOW_THREADS
1103 bytesread += chunksize;
1104 if (bzerror == BZ_STREAM_END) {
1105 self->size = self->pos;
1106 self->mode = MODE_READ_EOF;
1107 break;
1108 } else if (bzerror != BZ_OK) {
1109 Util_CatchBZ2Error(bzerror);
1110 goto cleanup;
1111 }
1112 if (bytesread == offset)
1113 break;
1114 }
1115
1116exit:
1117 Py_INCREF(Py_None);
1118 ret = Py_None;
1119
1120cleanup:
1121 RELEASE_LOCK(self);
1122 return ret;
1123}
1124
1125PyDoc_STRVAR(BZ2File_tell__doc__,
1126"tell() -> int\n\
1127\n\
1128Return the current file position, an integer (may be a long integer).\n\
1129");
1130
1131static PyObject *
1132BZ2File_tell(BZ2FileObject *self, PyObject *args)
1133{
1134 PyObject *ret = NULL;
1135
1136 if (self->mode == MODE_CLOSED) {
1137 PyErr_SetString(PyExc_ValueError,
1138 "I/O operation on closed file");
1139 goto cleanup;
1140 }
1141
Georg Brandla8bcecc2005-09-03 07:49:53 +00001142#if !defined(HAVE_LARGEFILE_SUPPORT)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001143 ret = PyInt_FromLong(self->pos);
Georg Brandla8bcecc2005-09-03 07:49:53 +00001144#else
1145 ret = PyLong_FromLongLong(self->pos);
1146#endif
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001147
1148cleanup:
1149 return ret;
1150}
1151
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001152PyDoc_STRVAR(BZ2File_close__doc__,
1153"close() -> None or (perhaps) an integer\n\
1154\n\
1155Close the file. Sets data attribute .closed to true. A closed file\n\
1156cannot be used for further I/O operations. close() may be called more\n\
1157than once without error.\n\
1158");
1159
1160static PyObject *
1161BZ2File_close(BZ2FileObject *self)
1162{
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001163 PyObject *ret = NULL;
1164 int bzerror = BZ_OK;
1165
1166 ACQUIRE_LOCK(self);
1167 switch (self->mode) {
1168 case MODE_READ:
1169 case MODE_READ_EOF:
1170 BZ2_bzReadClose(&bzerror, self->fp);
1171 break;
1172 case MODE_WRITE:
1173 BZ2_bzWriteClose(&bzerror, self->fp,
1174 0, NULL, NULL);
1175 break;
1176 }
1177 self->mode = MODE_CLOSED;
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001178 ret = PyObject_CallMethod(self->file, "close", NULL);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001179 if (bzerror != BZ_OK) {
1180 Util_CatchBZ2Error(bzerror);
1181 Py_XDECREF(ret);
1182 ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001183 }
1184
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001185 RELEASE_LOCK(self);
1186 return ret;
1187}
1188
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001189static PyObject *BZ2File_getiter(BZ2FileObject *self);
1190
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001191static PyMethodDef BZ2File_methods[] = {
1192 {"read", (PyCFunction)BZ2File_read, METH_VARARGS, BZ2File_read__doc__},
1193 {"readline", (PyCFunction)BZ2File_readline, METH_VARARGS, BZ2File_readline__doc__},
1194 {"readlines", (PyCFunction)BZ2File_readlines, METH_VARARGS, BZ2File_readlines__doc__},
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001195 {"xreadlines", (PyCFunction)BZ2File_getiter, METH_VARARGS, BZ2File_xreadlines__doc__},
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001196 {"write", (PyCFunction)BZ2File_write, METH_VARARGS, BZ2File_write__doc__},
1197 {"writelines", (PyCFunction)BZ2File_writelines, METH_O, BZ2File_writelines__doc__},
1198 {"seek", (PyCFunction)BZ2File_seek, METH_VARARGS, BZ2File_seek__doc__},
1199 {"tell", (PyCFunction)BZ2File_tell, METH_NOARGS, BZ2File_tell__doc__},
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001200 {"close", (PyCFunction)BZ2File_close, METH_NOARGS, BZ2File_close__doc__},
1201 {NULL, NULL} /* sentinel */
1202};
1203
1204
1205/* ===================================================================== */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001206/* Getters and setters of BZ2File. */
1207
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001208/* This is a hacked version of Python's fileobject.c:get_newlines(). */
1209static PyObject *
1210BZ2File_get_newlines(BZ2FileObject *self, void *closure)
1211{
1212 switch (self->f_newlinetypes) {
1213 case NEWLINE_UNKNOWN:
1214 Py_INCREF(Py_None);
1215 return Py_None;
1216 case NEWLINE_CR:
1217 return PyString_FromString("\r");
1218 case NEWLINE_LF:
1219 return PyString_FromString("\n");
1220 case NEWLINE_CR|NEWLINE_LF:
1221 return Py_BuildValue("(ss)", "\r", "\n");
1222 case NEWLINE_CRLF:
1223 return PyString_FromString("\r\n");
1224 case NEWLINE_CR|NEWLINE_CRLF:
1225 return Py_BuildValue("(ss)", "\r", "\r\n");
1226 case NEWLINE_LF|NEWLINE_CRLF:
1227 return Py_BuildValue("(ss)", "\n", "\r\n");
1228 case NEWLINE_CR|NEWLINE_LF|NEWLINE_CRLF:
1229 return Py_BuildValue("(sss)", "\r", "\n", "\r\n");
1230 default:
1231 PyErr_Format(PyExc_SystemError,
1232 "Unknown newlines value 0x%x\n",
1233 self->f_newlinetypes);
1234 return NULL;
1235 }
1236}
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001237
1238static PyObject *
1239BZ2File_get_closed(BZ2FileObject *self, void *closure)
1240{
1241 return PyInt_FromLong(self->mode == MODE_CLOSED);
1242}
1243
1244static PyObject *
1245BZ2File_get_mode(BZ2FileObject *self, void *closure)
1246{
1247 return PyObject_GetAttrString(self->file, "mode");
1248}
1249
1250static PyObject *
1251BZ2File_get_name(BZ2FileObject *self, void *closure)
1252{
1253 return PyObject_GetAttrString(self->file, "name");
1254}
1255
1256static PyGetSetDef BZ2File_getset[] = {
1257 {"closed", (getter)BZ2File_get_closed, NULL,
1258 "True if the file is closed"},
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001259 {"newlines", (getter)BZ2File_get_newlines, NULL,
1260 "end-of-line convention used in this file"},
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001261 {"mode", (getter)BZ2File_get_mode, NULL,
1262 "file mode ('r', 'w', or 'U')"},
1263 {"name", (getter)BZ2File_get_name, NULL,
1264 "file name"},
1265 {NULL} /* Sentinel */
1266};
1267
1268
1269/* ===================================================================== */
1270/* Members of BZ2File_Type. */
1271
1272#undef OFF
1273#define OFF(x) offsetof(BZ2FileObject, x)
1274
1275static PyMemberDef BZ2File_members[] = {
1276 {"softspace", T_INT, OFF(f_softspace), 0,
1277 "flag indicating that a space needs to be printed; used by print"},
1278 {NULL} /* Sentinel */
1279};
1280
1281/* ===================================================================== */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001282/* Slot definitions for BZ2File_Type. */
1283
1284static int
1285BZ2File_init(BZ2FileObject *self, PyObject *args, PyObject *kwargs)
1286{
Martin v. Löwis15e62742006-02-27 16:46:16 +00001287 static char *kwlist[] = {"filename", "mode", "buffering",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001288 "compresslevel", 0};
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001289 PyObject *name;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001290 char *mode = "r";
1291 int buffering = -1;
1292 int compresslevel = 9;
1293 int bzerror;
1294 int mode_char = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001295
1296 self->size = -1;
Tim Peterse3228092002-11-09 04:21:44 +00001297
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001298 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|sii:BZ2File",
1299 kwlist, &name, &mode, &buffering,
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001300 &compresslevel))
1301 return -1;
1302
1303 if (compresslevel < 1 || compresslevel > 9) {
1304 PyErr_SetString(PyExc_ValueError,
1305 "compresslevel must be between 1 and 9");
1306 return -1;
1307 }
1308
1309 for (;;) {
1310 int error = 0;
1311 switch (*mode) {
1312 case 'r':
1313 case 'w':
1314 if (mode_char)
1315 error = 1;
1316 mode_char = *mode;
1317 break;
1318
1319 case 'b':
1320 break;
1321
1322 case 'U':
Neal Norwitz2a30cd02006-07-10 01:18:57 +00001323#ifdef __VMS
1324 self->f_univ_newline = 0;
1325#else
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001326 self->f_univ_newline = 1;
Neal Norwitz2a30cd02006-07-10 01:18:57 +00001327#endif
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001328 break;
1329
1330 default:
1331 error = 1;
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001332 break;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001333 }
1334 if (error) {
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001335 PyErr_Format(PyExc_ValueError,
1336 "invalid mode char %c", *mode);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001337 return -1;
1338 }
1339 mode++;
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001340 if (*mode == '\0')
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001341 break;
1342 }
1343
Georg Brandl6b95f1d2005-06-03 19:47:00 +00001344 if (mode_char == 0) {
1345 mode_char = 'r';
1346 }
1347
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001348 mode = (mode_char == 'r') ? "rb" : "wb";
Tim Peterse3228092002-11-09 04:21:44 +00001349
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001350 self->file = PyObject_CallFunction((PyObject*)&PyFile_Type, "(Osi)",
1351 name, mode, buffering);
1352 if (self->file == NULL)
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001353 return -1;
1354
1355 /* From now on, we have stuff to dealloc, so jump to error label
1356 * instead of returning */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001357
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001358#ifdef WITH_THREAD
1359 self->lock = PyThread_allocate_lock();
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001360 if (!self->lock) {
1361 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001362 goto error;
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001363 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001364#endif
1365
1366 if (mode_char == 'r')
1367 self->fp = BZ2_bzReadOpen(&bzerror,
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001368 PyFile_AsFile(self->file),
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001369 0, 0, NULL, 0);
1370 else
1371 self->fp = BZ2_bzWriteOpen(&bzerror,
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001372 PyFile_AsFile(self->file),
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001373 compresslevel, 0, 0);
1374
1375 if (bzerror != BZ_OK) {
1376 Util_CatchBZ2Error(bzerror);
1377 goto error;
1378 }
1379
1380 self->mode = (mode_char == 'r') ? MODE_READ : MODE_WRITE;
1381
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001382 return 0;
1383
1384error:
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001385 Py_CLEAR(self->file);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001386#ifdef WITH_THREAD
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001387 if (self->lock) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001388 PyThread_free_lock(self->lock);
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001389 self->lock = NULL;
1390 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001391#endif
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001392 return -1;
1393}
1394
1395static void
1396BZ2File_dealloc(BZ2FileObject *self)
1397{
1398 int bzerror;
1399#ifdef WITH_THREAD
1400 if (self->lock)
1401 PyThread_free_lock(self->lock);
1402#endif
1403 switch (self->mode) {
1404 case MODE_READ:
1405 case MODE_READ_EOF:
1406 BZ2_bzReadClose(&bzerror, self->fp);
1407 break;
1408 case MODE_WRITE:
1409 BZ2_bzWriteClose(&bzerror, self->fp,
1410 0, NULL, NULL);
1411 break;
1412 }
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001413 Util_DropReadAhead(self);
Gustavo Niemeyer572f5232003-04-29 14:53:08 +00001414 Py_XDECREF(self->file);
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001415 self->ob_type->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001416}
1417
1418/* This is a hacked version of Python's fileobject.c:file_getiter(). */
1419static PyObject *
1420BZ2File_getiter(BZ2FileObject *self)
1421{
1422 if (self->mode == MODE_CLOSED) {
1423 PyErr_SetString(PyExc_ValueError,
1424 "I/O operation on closed file");
1425 return NULL;
1426 }
1427 Py_INCREF((PyObject*)self);
1428 return (PyObject *)self;
1429}
1430
1431/* This is a hacked version of Python's fileobject.c:file_iternext(). */
1432#define READAHEAD_BUFSIZE 8192
1433static PyObject *
1434BZ2File_iternext(BZ2FileObject *self)
1435{
1436 PyStringObject* ret;
1437 ACQUIRE_LOCK(self);
1438 if (self->mode == MODE_CLOSED) {
1439 PyErr_SetString(PyExc_ValueError,
1440 "I/O operation on closed file");
1441 return NULL;
1442 }
1443 ret = Util_ReadAheadGetLineSkip(self, 0, READAHEAD_BUFSIZE);
1444 RELEASE_LOCK(self);
1445 if (ret == NULL || PyString_GET_SIZE(ret) == 0) {
1446 Py_XDECREF(ret);
1447 return NULL;
1448 }
1449 return (PyObject *)ret;
1450}
1451
1452/* ===================================================================== */
1453/* BZ2File_Type definition. */
1454
1455PyDoc_VAR(BZ2File__doc__) =
1456PyDoc_STR(
1457"BZ2File(name [, mode='r', buffering=0, compresslevel=9]) -> file object\n\
1458\n\
1459Open a bz2 file. The mode can be 'r' or 'w', for reading (default) or\n\
1460writing. When opened for writing, the file will be created if it doesn't\n\
1461exist, and truncated otherwise. If the buffering argument is given, 0 means\n\
1462unbuffered, and larger numbers specify the buffer size. If compresslevel\n\
1463is given, must be a number between 1 and 9.\n\
1464")
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001465PyDoc_STR(
1466"\n\
1467Add a 'U' to mode to open the file for input with universal newline\n\
1468support. Any line ending in the input file will be seen as a '\\n' in\n\
1469Python. Also, a file so opened gains the attribute 'newlines'; the value\n\
1470for this attribute is one of None (no newline read yet), '\\r', '\\n',\n\
1471'\\r\\n' or a tuple containing all the newline types seen. Universal\n\
1472newlines are available only when reading.\n\
1473")
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001474;
1475
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001476static PyTypeObject BZ2File_Type = {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001477 PyObject_HEAD_INIT(NULL)
1478 0, /*ob_size*/
1479 "bz2.BZ2File", /*tp_name*/
1480 sizeof(BZ2FileObject), /*tp_basicsize*/
1481 0, /*tp_itemsize*/
1482 (destructor)BZ2File_dealloc, /*tp_dealloc*/
1483 0, /*tp_print*/
1484 0, /*tp_getattr*/
1485 0, /*tp_setattr*/
1486 0, /*tp_compare*/
1487 0, /*tp_repr*/
1488 0, /*tp_as_number*/
1489 0, /*tp_as_sequence*/
1490 0, /*tp_as_mapping*/
1491 0, /*tp_hash*/
1492 0, /*tp_call*/
1493 0, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001494 PyObject_GenericGetAttr,/*tp_getattro*/
1495 PyObject_GenericSetAttr,/*tp_setattro*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001496 0, /*tp_as_buffer*/
1497 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1498 BZ2File__doc__, /*tp_doc*/
1499 0, /*tp_traverse*/
1500 0, /*tp_clear*/
1501 0, /*tp_richcompare*/
1502 0, /*tp_weaklistoffset*/
1503 (getiterfunc)BZ2File_getiter, /*tp_iter*/
1504 (iternextfunc)BZ2File_iternext, /*tp_iternext*/
1505 BZ2File_methods, /*tp_methods*/
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001506 BZ2File_members, /*tp_members*/
1507 BZ2File_getset, /*tp_getset*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001508 0, /*tp_base*/
1509 0, /*tp_dict*/
1510 0, /*tp_descr_get*/
1511 0, /*tp_descr_set*/
1512 0, /*tp_dictoffset*/
1513 (initproc)BZ2File_init, /*tp_init*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001514 PyType_GenericAlloc, /*tp_alloc*/
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001515 PyType_GenericNew, /*tp_new*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001516 _PyObject_Del, /*tp_free*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001517 0, /*tp_is_gc*/
1518};
1519
1520
1521/* ===================================================================== */
1522/* Methods of BZ2Comp. */
1523
1524PyDoc_STRVAR(BZ2Comp_compress__doc__,
1525"compress(data) -> string\n\
1526\n\
1527Provide more data to the compressor object. It will return chunks of\n\
1528compressed data whenever possible. When you've finished providing data\n\
1529to compress, call the flush() method to finish the compression process,\n\
1530and return what is left in the internal buffers.\n\
1531");
1532
1533static PyObject *
1534BZ2Comp_compress(BZ2CompObject *self, PyObject *args)
1535{
1536 char *data;
1537 int datasize;
1538 int bufsize = SMALLCHUNK;
Martin v. Löwisb9a0f912003-03-29 10:06:18 +00001539 PY_LONG_LONG totalout;
Gustavo Niemeyer7d7930b2002-11-05 18:41:53 +00001540 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001541 bz_stream *bzs = &self->bzs;
1542 int bzerror;
1543
Walter Dörwaldbb9c7392004-11-01 17:10:19 +00001544 if (!PyArg_ParseTuple(args, "s#:compress", &data, &datasize))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001545 return NULL;
1546
Gustavo Niemeyera6e436e2004-02-14 00:02:45 +00001547 if (datasize == 0)
1548 return PyString_FromString("");
1549
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001550 ACQUIRE_LOCK(self);
1551 if (!self->running) {
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001552 PyErr_SetString(PyExc_ValueError,
1553 "this object was already flushed");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001554 goto error;
1555 }
1556
1557 ret = PyString_FromStringAndSize(NULL, bufsize);
1558 if (!ret)
1559 goto error;
1560
1561 bzs->next_in = data;
1562 bzs->avail_in = datasize;
1563 bzs->next_out = BUF(ret);
1564 bzs->avail_out = bufsize;
1565
1566 totalout = BZS_TOTAL_OUT(bzs);
1567
1568 for (;;) {
1569 Py_BEGIN_ALLOW_THREADS
1570 bzerror = BZ2_bzCompress(bzs, BZ_RUN);
1571 Py_END_ALLOW_THREADS
1572 if (bzerror != BZ_RUN_OK) {
1573 Util_CatchBZ2Error(bzerror);
1574 goto error;
1575 }
Georg Brandld6e73c12007-03-13 12:34:35 +00001576 if (bzs->avail_in == 0)
1577 break; /* no more input data */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001578 if (bzs->avail_out == 0) {
1579 bufsize = Util_NewBufferSize(bufsize);
1580 if (_PyString_Resize(&ret, bufsize) < 0) {
1581 BZ2_bzCompressEnd(bzs);
1582 goto error;
1583 }
1584 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs)
1585 - totalout);
1586 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001587 }
1588 }
1589
Neal Norwitz047f3c72006-06-12 02:06:42 +00001590 _PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001591
1592 RELEASE_LOCK(self);
1593 return ret;
1594
1595error:
1596 RELEASE_LOCK(self);
1597 Py_XDECREF(ret);
1598 return NULL;
1599}
1600
1601PyDoc_STRVAR(BZ2Comp_flush__doc__,
1602"flush() -> string\n\
1603\n\
1604Finish the compression process and return what is left in internal buffers.\n\
1605You must not use the compressor object after calling this method.\n\
1606");
1607
1608static PyObject *
1609BZ2Comp_flush(BZ2CompObject *self)
1610{
1611 int bufsize = SMALLCHUNK;
Gustavo Niemeyer7d7930b2002-11-05 18:41:53 +00001612 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001613 bz_stream *bzs = &self->bzs;
Martin v. Löwisb9a0f912003-03-29 10:06:18 +00001614 PY_LONG_LONG totalout;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001615 int bzerror;
1616
1617 ACQUIRE_LOCK(self);
1618 if (!self->running) {
1619 PyErr_SetString(PyExc_ValueError, "object was already "
1620 "flushed");
1621 goto error;
1622 }
1623 self->running = 0;
1624
1625 ret = PyString_FromStringAndSize(NULL, bufsize);
1626 if (!ret)
1627 goto error;
1628
1629 bzs->next_out = BUF(ret);
1630 bzs->avail_out = bufsize;
1631
1632 totalout = BZS_TOTAL_OUT(bzs);
1633
1634 for (;;) {
1635 Py_BEGIN_ALLOW_THREADS
1636 bzerror = BZ2_bzCompress(bzs, BZ_FINISH);
1637 Py_END_ALLOW_THREADS
1638 if (bzerror == BZ_STREAM_END) {
1639 break;
1640 } else if (bzerror != BZ_FINISH_OK) {
1641 Util_CatchBZ2Error(bzerror);
1642 goto error;
1643 }
1644 if (bzs->avail_out == 0) {
1645 bufsize = Util_NewBufferSize(bufsize);
1646 if (_PyString_Resize(&ret, bufsize) < 0)
1647 goto error;
1648 bzs->next_out = BUF(ret);
1649 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs)
1650 - totalout);
1651 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
1652 }
1653 }
1654
1655 if (bzs->avail_out != 0)
Neal Norwitz047f3c72006-06-12 02:06:42 +00001656 _PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001657
1658 RELEASE_LOCK(self);
1659 return ret;
1660
1661error:
1662 RELEASE_LOCK(self);
1663 Py_XDECREF(ret);
1664 return NULL;
1665}
1666
1667static PyMethodDef BZ2Comp_methods[] = {
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001668 {"compress", (PyCFunction)BZ2Comp_compress, METH_VARARGS,
1669 BZ2Comp_compress__doc__},
1670 {"flush", (PyCFunction)BZ2Comp_flush, METH_NOARGS,
1671 BZ2Comp_flush__doc__},
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001672 {NULL, NULL} /* sentinel */
1673};
1674
1675
1676/* ===================================================================== */
1677/* Slot definitions for BZ2Comp_Type. */
1678
1679static int
1680BZ2Comp_init(BZ2CompObject *self, PyObject *args, PyObject *kwargs)
1681{
1682 int compresslevel = 9;
1683 int bzerror;
Martin v. Löwis15e62742006-02-27 16:46:16 +00001684 static char *kwlist[] = {"compresslevel", 0};
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001685
1686 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:BZ2Compressor",
1687 kwlist, &compresslevel))
1688 return -1;
1689
1690 if (compresslevel < 1 || compresslevel > 9) {
1691 PyErr_SetString(PyExc_ValueError,
1692 "compresslevel must be between 1 and 9");
1693 goto error;
1694 }
1695
1696#ifdef WITH_THREAD
1697 self->lock = PyThread_allocate_lock();
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001698 if (!self->lock) {
1699 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001700 goto error;
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001701 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001702#endif
1703
1704 memset(&self->bzs, 0, sizeof(bz_stream));
1705 bzerror = BZ2_bzCompressInit(&self->bzs, compresslevel, 0, 0);
1706 if (bzerror != BZ_OK) {
1707 Util_CatchBZ2Error(bzerror);
1708 goto error;
1709 }
1710
1711 self->running = 1;
1712
1713 return 0;
1714error:
1715#ifdef WITH_THREAD
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001716 if (self->lock) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001717 PyThread_free_lock(self->lock);
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001718 self->lock = NULL;
1719 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001720#endif
1721 return -1;
1722}
1723
1724static void
1725BZ2Comp_dealloc(BZ2CompObject *self)
1726{
1727#ifdef WITH_THREAD
1728 if (self->lock)
1729 PyThread_free_lock(self->lock);
1730#endif
1731 BZ2_bzCompressEnd(&self->bzs);
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001732 self->ob_type->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001733}
1734
1735
1736/* ===================================================================== */
1737/* BZ2Comp_Type definition. */
1738
1739PyDoc_STRVAR(BZ2Comp__doc__,
1740"BZ2Compressor([compresslevel=9]) -> compressor object\n\
1741\n\
1742Create a new compressor object. This object may be used to compress\n\
1743data sequentially. If you want to compress data in one shot, use the\n\
1744compress() function instead. The compresslevel parameter, if given,\n\
1745must be a number between 1 and 9.\n\
1746");
1747
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001748static PyTypeObject BZ2Comp_Type = {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001749 PyObject_HEAD_INIT(NULL)
1750 0, /*ob_size*/
1751 "bz2.BZ2Compressor", /*tp_name*/
1752 sizeof(BZ2CompObject), /*tp_basicsize*/
1753 0, /*tp_itemsize*/
1754 (destructor)BZ2Comp_dealloc, /*tp_dealloc*/
1755 0, /*tp_print*/
1756 0, /*tp_getattr*/
1757 0, /*tp_setattr*/
1758 0, /*tp_compare*/
1759 0, /*tp_repr*/
1760 0, /*tp_as_number*/
1761 0, /*tp_as_sequence*/
1762 0, /*tp_as_mapping*/
1763 0, /*tp_hash*/
1764 0, /*tp_call*/
1765 0, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001766 PyObject_GenericGetAttr,/*tp_getattro*/
1767 PyObject_GenericSetAttr,/*tp_setattro*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001768 0, /*tp_as_buffer*/
1769 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1770 BZ2Comp__doc__, /*tp_doc*/
1771 0, /*tp_traverse*/
1772 0, /*tp_clear*/
1773 0, /*tp_richcompare*/
1774 0, /*tp_weaklistoffset*/
1775 0, /*tp_iter*/
1776 0, /*tp_iternext*/
1777 BZ2Comp_methods, /*tp_methods*/
1778 0, /*tp_members*/
1779 0, /*tp_getset*/
1780 0, /*tp_base*/
1781 0, /*tp_dict*/
1782 0, /*tp_descr_get*/
1783 0, /*tp_descr_set*/
1784 0, /*tp_dictoffset*/
1785 (initproc)BZ2Comp_init, /*tp_init*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001786 PyType_GenericAlloc, /*tp_alloc*/
1787 PyType_GenericNew, /*tp_new*/
1788 _PyObject_Del, /*tp_free*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001789 0, /*tp_is_gc*/
1790};
1791
1792
1793/* ===================================================================== */
1794/* Members of BZ2Decomp. */
1795
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001796#undef OFF
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001797#define OFF(x) offsetof(BZ2DecompObject, x)
1798
1799static PyMemberDef BZ2Decomp_members[] = {
1800 {"unused_data", T_OBJECT, OFF(unused_data), RO},
1801 {NULL} /* Sentinel */
1802};
1803
1804
1805/* ===================================================================== */
1806/* Methods of BZ2Decomp. */
1807
1808PyDoc_STRVAR(BZ2Decomp_decompress__doc__,
1809"decompress(data) -> string\n\
1810\n\
1811Provide more data to the decompressor object. It will return chunks\n\
1812of decompressed data whenever possible. If you try to decompress data\n\
1813after the end of stream is found, EOFError will be raised. If any data\n\
1814was found after the end of stream, it'll be ignored and saved in\n\
1815unused_data attribute.\n\
1816");
1817
1818static PyObject *
1819BZ2Decomp_decompress(BZ2DecompObject *self, PyObject *args)
1820{
1821 char *data;
1822 int datasize;
1823 int bufsize = SMALLCHUNK;
Martin v. Löwisb9a0f912003-03-29 10:06:18 +00001824 PY_LONG_LONG totalout;
Neal Norwitz18142c02002-11-05 18:17:32 +00001825 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001826 bz_stream *bzs = &self->bzs;
1827 int bzerror;
1828
Walter Dörwaldbb9c7392004-11-01 17:10:19 +00001829 if (!PyArg_ParseTuple(args, "s#:decompress", &data, &datasize))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001830 return NULL;
1831
1832 ACQUIRE_LOCK(self);
1833 if (!self->running) {
1834 PyErr_SetString(PyExc_EOFError, "end of stream was "
1835 "already found");
1836 goto error;
1837 }
1838
1839 ret = PyString_FromStringAndSize(NULL, bufsize);
1840 if (!ret)
1841 goto error;
1842
1843 bzs->next_in = data;
1844 bzs->avail_in = datasize;
1845 bzs->next_out = BUF(ret);
1846 bzs->avail_out = bufsize;
1847
1848 totalout = BZS_TOTAL_OUT(bzs);
1849
1850 for (;;) {
1851 Py_BEGIN_ALLOW_THREADS
1852 bzerror = BZ2_bzDecompress(bzs);
1853 Py_END_ALLOW_THREADS
1854 if (bzerror == BZ_STREAM_END) {
1855 if (bzs->avail_in != 0) {
1856 Py_DECREF(self->unused_data);
1857 self->unused_data =
1858 PyString_FromStringAndSize(bzs->next_in,
1859 bzs->avail_in);
1860 }
1861 self->running = 0;
1862 break;
1863 }
1864 if (bzerror != BZ_OK) {
1865 Util_CatchBZ2Error(bzerror);
1866 goto error;
1867 }
Georg Brandld6e73c12007-03-13 12:34:35 +00001868 if (bzs->avail_in == 0)
1869 break; /* no more input data */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001870 if (bzs->avail_out == 0) {
1871 bufsize = Util_NewBufferSize(bufsize);
1872 if (_PyString_Resize(&ret, bufsize) < 0) {
1873 BZ2_bzDecompressEnd(bzs);
1874 goto error;
1875 }
1876 bzs->next_out = BUF(ret);
1877 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs)
1878 - totalout);
1879 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001880 }
1881 }
1882
1883 if (bzs->avail_out != 0)
Neal Norwitz047f3c72006-06-12 02:06:42 +00001884 _PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001885
1886 RELEASE_LOCK(self);
1887 return ret;
1888
1889error:
1890 RELEASE_LOCK(self);
1891 Py_XDECREF(ret);
1892 return NULL;
1893}
1894
1895static PyMethodDef BZ2Decomp_methods[] = {
1896 {"decompress", (PyCFunction)BZ2Decomp_decompress, METH_VARARGS, BZ2Decomp_decompress__doc__},
1897 {NULL, NULL} /* sentinel */
1898};
1899
1900
1901/* ===================================================================== */
1902/* Slot definitions for BZ2Decomp_Type. */
1903
1904static int
1905BZ2Decomp_init(BZ2DecompObject *self, PyObject *args, PyObject *kwargs)
1906{
1907 int bzerror;
1908
1909 if (!PyArg_ParseTuple(args, ":BZ2Decompressor"))
1910 return -1;
1911
1912#ifdef WITH_THREAD
1913 self->lock = PyThread_allocate_lock();
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001914 if (!self->lock) {
1915 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001916 goto error;
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001917 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001918#endif
1919
1920 self->unused_data = PyString_FromString("");
1921 if (!self->unused_data)
1922 goto error;
1923
1924 memset(&self->bzs, 0, sizeof(bz_stream));
1925 bzerror = BZ2_bzDecompressInit(&self->bzs, 0, 0);
1926 if (bzerror != BZ_OK) {
1927 Util_CatchBZ2Error(bzerror);
1928 goto error;
1929 }
1930
1931 self->running = 1;
1932
1933 return 0;
1934
1935error:
1936#ifdef WITH_THREAD
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001937 if (self->lock) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001938 PyThread_free_lock(self->lock);
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001939 self->lock = NULL;
1940 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001941#endif
Neal Norwitzb59d08c2006-07-22 16:20:49 +00001942 Py_CLEAR(self->unused_data);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001943 return -1;
1944}
1945
1946static void
1947BZ2Decomp_dealloc(BZ2DecompObject *self)
1948{
1949#ifdef WITH_THREAD
1950 if (self->lock)
1951 PyThread_free_lock(self->lock);
1952#endif
1953 Py_XDECREF(self->unused_data);
1954 BZ2_bzDecompressEnd(&self->bzs);
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001955 self->ob_type->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001956}
1957
1958
1959/* ===================================================================== */
1960/* BZ2Decomp_Type definition. */
1961
1962PyDoc_STRVAR(BZ2Decomp__doc__,
1963"BZ2Decompressor() -> decompressor object\n\
1964\n\
1965Create a new decompressor object. This object may be used to decompress\n\
1966data sequentially. If you want to decompress data in one shot, use the\n\
1967decompress() function instead.\n\
1968");
1969
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001970static PyTypeObject BZ2Decomp_Type = {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001971 PyObject_HEAD_INIT(NULL)
1972 0, /*ob_size*/
1973 "bz2.BZ2Decompressor", /*tp_name*/
1974 sizeof(BZ2DecompObject), /*tp_basicsize*/
1975 0, /*tp_itemsize*/
1976 (destructor)BZ2Decomp_dealloc, /*tp_dealloc*/
1977 0, /*tp_print*/
1978 0, /*tp_getattr*/
1979 0, /*tp_setattr*/
1980 0, /*tp_compare*/
1981 0, /*tp_repr*/
1982 0, /*tp_as_number*/
1983 0, /*tp_as_sequence*/
1984 0, /*tp_as_mapping*/
1985 0, /*tp_hash*/
1986 0, /*tp_call*/
1987 0, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001988 PyObject_GenericGetAttr,/*tp_getattro*/
1989 PyObject_GenericSetAttr,/*tp_setattro*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001990 0, /*tp_as_buffer*/
1991 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1992 BZ2Decomp__doc__, /*tp_doc*/
1993 0, /*tp_traverse*/
1994 0, /*tp_clear*/
1995 0, /*tp_richcompare*/
1996 0, /*tp_weaklistoffset*/
1997 0, /*tp_iter*/
1998 0, /*tp_iternext*/
1999 BZ2Decomp_methods, /*tp_methods*/
2000 BZ2Decomp_members, /*tp_members*/
2001 0, /*tp_getset*/
2002 0, /*tp_base*/
2003 0, /*tp_dict*/
2004 0, /*tp_descr_get*/
2005 0, /*tp_descr_set*/
2006 0, /*tp_dictoffset*/
2007 (initproc)BZ2Decomp_init, /*tp_init*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00002008 PyType_GenericAlloc, /*tp_alloc*/
2009 PyType_GenericNew, /*tp_new*/
2010 _PyObject_Del, /*tp_free*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002011 0, /*tp_is_gc*/
2012};
2013
2014
2015/* ===================================================================== */
2016/* Module functions. */
2017
2018PyDoc_STRVAR(bz2_compress__doc__,
2019"compress(data [, compresslevel=9]) -> string\n\
2020\n\
2021Compress data in one shot. If you want to compress data sequentially,\n\
2022use an instance of BZ2Compressor instead. The compresslevel parameter, if\n\
2023given, must be a number between 1 and 9.\n\
2024");
2025
2026static PyObject *
2027bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
2028{
2029 int compresslevel=9;
2030 char *data;
2031 int datasize;
2032 int bufsize;
Gustavo Niemeyer7d7930b2002-11-05 18:41:53 +00002033 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002034 bz_stream _bzs;
2035 bz_stream *bzs = &_bzs;
2036 int bzerror;
Martin v. Löwis15e62742006-02-27 16:46:16 +00002037 static char *kwlist[] = {"data", "compresslevel", 0};
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002038
2039 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|i",
2040 kwlist, &data, &datasize,
2041 &compresslevel))
2042 return NULL;
2043
2044 if (compresslevel < 1 || compresslevel > 9) {
2045 PyErr_SetString(PyExc_ValueError,
2046 "compresslevel must be between 1 and 9");
2047 return NULL;
2048 }
2049
2050 /* Conforming to bz2 manual, this is large enough to fit compressed
2051 * data in one shot. We will check it later anyway. */
2052 bufsize = datasize + (datasize/100+1) + 600;
2053
2054 ret = PyString_FromStringAndSize(NULL, bufsize);
2055 if (!ret)
2056 return NULL;
2057
2058 memset(bzs, 0, sizeof(bz_stream));
2059
2060 bzs->next_in = data;
2061 bzs->avail_in = datasize;
2062 bzs->next_out = BUF(ret);
2063 bzs->avail_out = bufsize;
2064
2065 bzerror = BZ2_bzCompressInit(bzs, compresslevel, 0, 0);
2066 if (bzerror != BZ_OK) {
2067 Util_CatchBZ2Error(bzerror);
2068 Py_DECREF(ret);
2069 return NULL;
2070 }
Tim Peterse3228092002-11-09 04:21:44 +00002071
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002072 for (;;) {
2073 Py_BEGIN_ALLOW_THREADS
2074 bzerror = BZ2_bzCompress(bzs, BZ_FINISH);
2075 Py_END_ALLOW_THREADS
2076 if (bzerror == BZ_STREAM_END) {
2077 break;
2078 } else if (bzerror != BZ_FINISH_OK) {
2079 BZ2_bzCompressEnd(bzs);
2080 Util_CatchBZ2Error(bzerror);
2081 Py_DECREF(ret);
2082 return NULL;
2083 }
2084 if (bzs->avail_out == 0) {
2085 bufsize = Util_NewBufferSize(bufsize);
2086 if (_PyString_Resize(&ret, bufsize) < 0) {
2087 BZ2_bzCompressEnd(bzs);
2088 Py_DECREF(ret);
2089 return NULL;
2090 }
2091 bzs->next_out = BUF(ret) + BZS_TOTAL_OUT(bzs);
2092 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
2093 }
2094 }
2095
2096 if (bzs->avail_out != 0)
Neal Norwitz047f3c72006-06-12 02:06:42 +00002097 _PyString_Resize(&ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002098 BZ2_bzCompressEnd(bzs);
2099
2100 return ret;
2101}
2102
2103PyDoc_STRVAR(bz2_decompress__doc__,
2104"decompress(data) -> decompressed data\n\
2105\n\
2106Decompress data in one shot. If you want to decompress data sequentially,\n\
2107use an instance of BZ2Decompressor instead.\n\
2108");
2109
2110static PyObject *
2111bz2_decompress(PyObject *self, PyObject *args)
2112{
2113 char *data;
2114 int datasize;
2115 int bufsize = SMALLCHUNK;
2116 PyObject *ret;
2117 bz_stream _bzs;
2118 bz_stream *bzs = &_bzs;
2119 int bzerror;
2120
Walter Dörwaldbb9c7392004-11-01 17:10:19 +00002121 if (!PyArg_ParseTuple(args, "s#:decompress", &data, &datasize))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002122 return NULL;
2123
2124 if (datasize == 0)
2125 return PyString_FromString("");
2126
2127 ret = PyString_FromStringAndSize(NULL, bufsize);
2128 if (!ret)
2129 return NULL;
2130
2131 memset(bzs, 0, sizeof(bz_stream));
2132
2133 bzs->next_in = data;
2134 bzs->avail_in = datasize;
2135 bzs->next_out = BUF(ret);
2136 bzs->avail_out = bufsize;
2137
2138 bzerror = BZ2_bzDecompressInit(bzs, 0, 0);
2139 if (bzerror != BZ_OK) {
2140 Util_CatchBZ2Error(bzerror);
2141 Py_DECREF(ret);
2142 return NULL;
2143 }
Tim Peterse3228092002-11-09 04:21:44 +00002144
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002145 for (;;) {
2146 Py_BEGIN_ALLOW_THREADS
2147 bzerror = BZ2_bzDecompress(bzs);
2148 Py_END_ALLOW_THREADS
2149 if (bzerror == BZ_STREAM_END) {
2150 break;
2151 } else if (bzerror != BZ_OK) {
2152 BZ2_bzDecompressEnd(bzs);
2153 Util_CatchBZ2Error(bzerror);
2154 Py_DECREF(ret);
2155 return NULL;
2156 }
Georg Brandld6e73c12007-03-13 12:34:35 +00002157 if (bzs->avail_in == 0) {
2158 BZ2_bzDecompressEnd(bzs);
2159 PyErr_SetString(PyExc_ValueError,
2160 "couldn't find end of stream");
2161 Py_DECREF(ret);
2162 return NULL;
2163 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002164 if (bzs->avail_out == 0) {
2165 bufsize = Util_NewBufferSize(bufsize);
2166 if (_PyString_Resize(&ret, bufsize) < 0) {
2167 BZ2_bzDecompressEnd(bzs);
2168 Py_DECREF(ret);
2169 return NULL;
2170 }
2171 bzs->next_out = BUF(ret) + BZS_TOTAL_OUT(bzs);
2172 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002173 }
2174 }
2175
2176 if (bzs->avail_out != 0)
Neal Norwitz047f3c72006-06-12 02:06:42 +00002177 _PyString_Resize(&ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002178 BZ2_bzDecompressEnd(bzs);
2179
2180 return ret;
2181}
2182
2183static PyMethodDef bz2_methods[] = {
2184 {"compress", (PyCFunction) bz2_compress, METH_VARARGS|METH_KEYWORDS,
2185 bz2_compress__doc__},
2186 {"decompress", (PyCFunction) bz2_decompress, METH_VARARGS,
2187 bz2_decompress__doc__},
2188 {NULL, NULL} /* sentinel */
2189};
2190
2191/* ===================================================================== */
2192/* Initialization function. */
2193
2194PyDoc_STRVAR(bz2__doc__,
2195"The python bz2 module provides a comprehensive interface for\n\
2196the bz2 compression library. It implements a complete file\n\
2197interface, one shot (de)compression functions, and types for\n\
2198sequential (de)compression.\n\
2199");
2200
Neal Norwitz21d896c2003-07-01 20:15:21 +00002201PyMODINIT_FUNC
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002202initbz2(void)
2203{
2204 PyObject *m;
2205
2206 BZ2File_Type.ob_type = &PyType_Type;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002207 BZ2Comp_Type.ob_type = &PyType_Type;
2208 BZ2Decomp_Type.ob_type = &PyType_Type;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002209
2210 m = Py_InitModule3("bz2", bz2_methods, bz2__doc__);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00002211 if (m == NULL)
2212 return;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002213
2214 PyModule_AddObject(m, "__author__", PyString_FromString(__author__));
2215
2216 Py_INCREF(&BZ2File_Type);
2217 PyModule_AddObject(m, "BZ2File", (PyObject *)&BZ2File_Type);
2218
2219 Py_INCREF(&BZ2Comp_Type);
2220 PyModule_AddObject(m, "BZ2Compressor", (PyObject *)&BZ2Comp_Type);
2221
2222 Py_INCREF(&BZ2Decomp_Type);
2223 PyModule_AddObject(m, "BZ2Decompressor", (PyObject *)&BZ2Decomp_Type);
2224}