blob: 15b6e44af98e0f7d84fd6dc4db9c9c6055696ec1 [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
Guido van Rossum522a6c62007-05-22 23:13:45 +000037#define BUF(v) PyBytes_AS_STRING(v)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000038
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öwis9f2e3462007-07-21 17:22:18 +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
Guido van Rossumf09ca142007-06-13 00:03:05 +000099 FILE *rawfp;
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000100
101 char* f_buf; /* Allocated readahead buffer */
102 char* f_bufend; /* Points after last occupied position */
103 char* f_bufptr; /* Current buffer position */
104
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000105 BZFILE *fp;
106 int mode;
Georg Brandla8bcecc2005-09-03 07:49:53 +0000107 Py_off_t pos;
108 Py_off_t size;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000109#ifdef WITH_THREAD
110 PyThread_type_lock lock;
111#endif
112} BZ2FileObject;
113
114typedef struct {
115 PyObject_HEAD
116 bz_stream bzs;
117 int running;
118#ifdef WITH_THREAD
119 PyThread_type_lock lock;
120#endif
121} BZ2CompObject;
122
123typedef struct {
124 PyObject_HEAD
125 bz_stream bzs;
126 int running;
127 PyObject *unused_data;
128#ifdef WITH_THREAD
129 PyThread_type_lock lock;
130#endif
131} BZ2DecompObject;
132
133/* ===================================================================== */
134/* Utility functions. */
135
136static int
137Util_CatchBZ2Error(int bzerror)
138{
139 int ret = 0;
140 switch(bzerror) {
141 case BZ_OK:
142 case BZ_STREAM_END:
143 break;
144
Gustavo Niemeyer7628f1f2003-04-27 06:25:24 +0000145#ifdef BZ_CONFIG_ERROR
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000146 case BZ_CONFIG_ERROR:
147 PyErr_SetString(PyExc_SystemError,
148 "the bz2 library was not compiled "
149 "correctly");
150 ret = 1;
151 break;
Gustavo Niemeyer7628f1f2003-04-27 06:25:24 +0000152#endif
Tim Peterse3228092002-11-09 04:21:44 +0000153
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000154 case BZ_PARAM_ERROR:
155 PyErr_SetString(PyExc_ValueError,
156 "the bz2 library has received wrong "
157 "parameters");
158 ret = 1;
159 break;
Tim Peterse3228092002-11-09 04:21:44 +0000160
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000161 case BZ_MEM_ERROR:
162 PyErr_NoMemory();
163 ret = 1;
164 break;
165
166 case BZ_DATA_ERROR:
167 case BZ_DATA_ERROR_MAGIC:
168 PyErr_SetString(PyExc_IOError, "invalid data stream");
169 ret = 1;
170 break;
171
172 case BZ_IO_ERROR:
173 PyErr_SetString(PyExc_IOError, "unknown IO error");
174 ret = 1;
175 break;
176
177 case BZ_UNEXPECTED_EOF:
178 PyErr_SetString(PyExc_EOFError,
179 "compressed file ended before the "
180 "logical end-of-stream was detected");
181 ret = 1;
182 break;
183
184 case BZ_SEQUENCE_ERROR:
185 PyErr_SetString(PyExc_RuntimeError,
186 "wrong sequence of bz2 library "
187 "commands used");
188 ret = 1;
189 break;
190 }
191 return ret;
192}
193
194#if BUFSIZ < 8192
195#define SMALLCHUNK 8192
196#else
197#define SMALLCHUNK BUFSIZ
198#endif
199
200#if SIZEOF_INT < 4
201#define BIGCHUNK (512 * 32)
202#else
203#define BIGCHUNK (512 * 1024)
204#endif
205
206/* This is a hacked version of Python's fileobject.c:new_buffersize(). */
207static size_t
208Util_NewBufferSize(size_t currentsize)
209{
210 if (currentsize > SMALLCHUNK) {
211 /* Keep doubling until we reach BIGCHUNK;
212 then keep adding BIGCHUNK. */
213 if (currentsize <= BIGCHUNK)
214 return currentsize + currentsize;
215 else
216 return currentsize + BIGCHUNK;
217 }
218 return currentsize + SMALLCHUNK;
219}
220
221/* This is a hacked version of Python's fileobject.c:get_line(). */
222static PyObject *
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000223Util_GetLine(BZ2FileObject *f, int n)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000224{
225 char c;
226 char *buf, *end;
227 size_t total_v_size; /* total # of slots in buffer */
228 size_t used_v_size; /* # used slots in buffer */
229 size_t increment; /* amount to increment the buffer */
230 PyObject *v;
231 int bzerror;
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000232 int bytes_read;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000233
234 total_v_size = n > 0 ? n : 100;
Guido van Rossum522a6c62007-05-22 23:13:45 +0000235 v = PyBytes_FromStringAndSize((char *)NULL, total_v_size);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000236 if (v == NULL)
237 return NULL;
238
239 buf = BUF(v);
240 end = buf + total_v_size;
241
242 for (;;) {
243 Py_BEGIN_ALLOW_THREADS
Guido van Rossumf09ca142007-06-13 00:03:05 +0000244 do {
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000245 bytes_read = BZ2_bzRead(&bzerror, f->fp, &c, 1);
Guido van Rossumf09ca142007-06-13 00:03:05 +0000246 f->pos++;
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000247 if (bytes_read == 0)
248 break;
Guido van Rossumf09ca142007-06-13 00:03:05 +0000249 *buf++ = c;
250 } while (bzerror == BZ_OK && c != '\n' && buf != end);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000251 Py_END_ALLOW_THREADS
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000252 if (bzerror == BZ_STREAM_END) {
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000253 f->size = f->pos;
254 f->mode = MODE_READ_EOF;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000255 break;
256 } else if (bzerror != BZ_OK) {
257 Util_CatchBZ2Error(bzerror);
258 Py_DECREF(v);
259 return NULL;
260 }
261 if (c == '\n')
262 break;
263 /* Must be because buf == end */
264 if (n > 0)
265 break;
266 used_v_size = total_v_size;
267 increment = total_v_size >> 2; /* mild exponential growth */
268 total_v_size += increment;
269 if (total_v_size > INT_MAX) {
270 PyErr_SetString(PyExc_OverflowError,
271 "line is longer than a Python string can hold");
272 Py_DECREF(v);
273 return NULL;
274 }
Guido van Rossum522a6c62007-05-22 23:13:45 +0000275 if (PyBytes_Resize(v, total_v_size) < 0) {
276 Py_DECREF(v);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000277 return NULL;
Guido van Rossum522a6c62007-05-22 23:13:45 +0000278 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000279 buf = BUF(v) + used_v_size;
280 end = BUF(v) + total_v_size;
281 }
282
283 used_v_size = buf - BUF(v);
Guido van Rossum522a6c62007-05-22 23:13:45 +0000284 if (used_v_size != total_v_size) {
285 if (PyBytes_Resize(v, used_v_size) < 0) {
286 Py_DECREF(v);
287 v = NULL;
288 }
289 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000290 return v;
291}
292
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000293/* This is a hacked version of Python's fileobject.c:drop_readahead(). */
294static void
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000295Util_DropReadAhead(BZ2FileObject *f)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000296{
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000297 if (f->f_buf != NULL) {
298 PyMem_Free(f->f_buf);
299 f->f_buf = NULL;
300 }
301}
302
303/* This is a hacked version of Python's fileobject.c:readahead(). */
304static int
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000305Util_ReadAhead(BZ2FileObject *f, int bufsize)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000306{
307 int chunksize;
308 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000309
310 if (f->f_buf != NULL) {
Tim Peterse3228092002-11-09 04:21:44 +0000311 if((f->f_bufend - f->f_bufptr) >= 1)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000312 return 0;
313 else
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000314 Util_DropReadAhead(f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000315 }
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000316 if (f->mode == MODE_READ_EOF) {
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000317 f->f_bufptr = f->f_buf;
318 f->f_bufend = f->f_buf;
319 return 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000320 }
321 if ((f->f_buf = PyMem_Malloc(bufsize)) == NULL) {
322 return -1;
323 }
324 Py_BEGIN_ALLOW_THREADS
Guido van Rossumf09ca142007-06-13 00:03:05 +0000325 chunksize = BZ2_bzRead(&bzerror, f->fp, f->f_buf, bufsize);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000326 Py_END_ALLOW_THREADS
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000327 f->pos += chunksize;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000328 if (bzerror == BZ_STREAM_END) {
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000329 f->size = f->pos;
330 f->mode = MODE_READ_EOF;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000331 } else if (bzerror != BZ_OK) {
332 Util_CatchBZ2Error(bzerror);
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000333 Util_DropReadAhead(f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000334 return -1;
335 }
336 f->f_bufptr = f->f_buf;
337 f->f_bufend = f->f_buf + chunksize;
338 return 0;
339}
340
341/* This is a hacked version of Python's
342 * fileobject.c:readahead_get_line_skip(). */
Guido van Rossum522a6c62007-05-22 23:13:45 +0000343static PyBytesObject *
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000344Util_ReadAheadGetLineSkip(BZ2FileObject *f, int skip, int bufsize)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000345{
Guido van Rossum522a6c62007-05-22 23:13:45 +0000346 PyBytesObject* s;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000347 char *bufptr;
348 char *buf;
349 int len;
350
351 if (f->f_buf == NULL)
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000352 if (Util_ReadAhead(f, bufsize) < 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000353 return NULL;
354
355 len = f->f_bufend - f->f_bufptr;
Tim Peterse3228092002-11-09 04:21:44 +0000356 if (len == 0)
Guido van Rossum522a6c62007-05-22 23:13:45 +0000357 return (PyBytesObject *)
358 PyBytes_FromStringAndSize(NULL, skip);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000359 bufptr = memchr(f->f_bufptr, '\n', len);
360 if (bufptr != NULL) {
361 bufptr++; /* Count the '\n' */
362 len = bufptr - f->f_bufptr;
Guido van Rossum522a6c62007-05-22 23:13:45 +0000363 s = (PyBytesObject *)
364 PyBytes_FromStringAndSize(NULL, skip+len);
Tim Peterse3228092002-11-09 04:21:44 +0000365 if (s == NULL)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000366 return NULL;
Guido van Rossum522a6c62007-05-22 23:13:45 +0000367 memcpy(PyBytes_AS_STRING(s)+skip, f->f_bufptr, len);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000368 f->f_bufptr = bufptr;
369 if (bufptr == f->f_bufend)
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000370 Util_DropReadAhead(f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000371 } else {
372 bufptr = f->f_bufptr;
373 buf = f->f_buf;
374 f->f_buf = NULL; /* Force new readahead buffer */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000375 s = Util_ReadAheadGetLineSkip(f, skip+len,
376 bufsize + (bufsize>>2));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000377 if (s == NULL) {
378 PyMem_Free(buf);
379 return NULL;
380 }
Guido van Rossum522a6c62007-05-22 23:13:45 +0000381 memcpy(PyBytes_AS_STRING(s)+skip, bufptr, len);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000382 PyMem_Free(buf);
383 }
384 return s;
385}
386
387/* ===================================================================== */
388/* Methods of BZ2File. */
389
390PyDoc_STRVAR(BZ2File_read__doc__,
391"read([size]) -> string\n\
392\n\
393Read at most size uncompressed bytes, returned as a string. If the size\n\
394argument is negative or omitted, read until EOF is reached.\n\
395");
396
397/* This is a hacked version of Python's fileobject.c:file_read(). */
398static PyObject *
399BZ2File_read(BZ2FileObject *self, PyObject *args)
400{
401 long bytesrequested = -1;
402 size_t bytesread, buffersize, chunksize;
403 int bzerror;
404 PyObject *ret = NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000405
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000406 if (!PyArg_ParseTuple(args, "|l:read", &bytesrequested))
407 return NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000408
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000409 ACQUIRE_LOCK(self);
410 switch (self->mode) {
411 case MODE_READ:
412 break;
413 case MODE_READ_EOF:
Guido van Rossum522a6c62007-05-22 23:13:45 +0000414 ret = PyBytes_FromStringAndSize("", 0);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000415 goto cleanup;
416 case MODE_CLOSED:
417 PyErr_SetString(PyExc_ValueError,
418 "I/O operation on closed file");
419 goto cleanup;
420 default:
421 PyErr_SetString(PyExc_IOError,
422 "file is not ready for reading");
423 goto cleanup;
424 }
425
426 if (bytesrequested < 0)
427 buffersize = Util_NewBufferSize((size_t)0);
428 else
429 buffersize = bytesrequested;
430 if (buffersize > INT_MAX) {
431 PyErr_SetString(PyExc_OverflowError,
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +0000432 "requested number of bytes is "
433 "more than a Python string can hold");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000434 goto cleanup;
435 }
Guido van Rossum522a6c62007-05-22 23:13:45 +0000436 ret = PyBytes_FromStringAndSize((char *)NULL, buffersize);
Guido van Rossum75c26bc2007-08-07 23:29:20 +0000437 if (ret == NULL || buffersize == 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000438 goto cleanup;
439 bytesread = 0;
440
441 for (;;) {
442 Py_BEGIN_ALLOW_THREADS
Guido van Rossumf09ca142007-06-13 00:03:05 +0000443 chunksize = BZ2_bzRead(&bzerror, self->fp,
444 BUF(ret)+bytesread,
445 buffersize-bytesread);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000446 self->pos += chunksize;
447 Py_END_ALLOW_THREADS
448 bytesread += chunksize;
449 if (bzerror == BZ_STREAM_END) {
450 self->size = self->pos;
451 self->mode = MODE_READ_EOF;
452 break;
453 } else if (bzerror != BZ_OK) {
454 Util_CatchBZ2Error(bzerror);
455 Py_DECREF(ret);
456 ret = NULL;
457 goto cleanup;
458 }
459 if (bytesrequested < 0) {
460 buffersize = Util_NewBufferSize(buffersize);
Guido van Rossum522a6c62007-05-22 23:13:45 +0000461 if (PyBytes_Resize(ret, buffersize) < 0) {
462 Py_DECREF(ret);
463 ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000464 goto cleanup;
Guido van Rossum522a6c62007-05-22 23:13:45 +0000465 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000466 } else {
467 break;
468 }
469 }
Guido van Rossum522a6c62007-05-22 23:13:45 +0000470 if (bytesread != buffersize) {
471 if (PyBytes_Resize(ret, bytesread) < 0) {
472 Py_DECREF(ret);
473 ret = NULL;
474 }
475 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000476
477cleanup:
478 RELEASE_LOCK(self);
479 return ret;
480}
481
482PyDoc_STRVAR(BZ2File_readline__doc__,
483"readline([size]) -> string\n\
484\n\
485Return the next line from the file, as a string, retaining newline.\n\
486A non-negative size argument will limit the maximum number of bytes to\n\
487return (an incomplete line may be returned then). Return an empty\n\
488string at EOF.\n\
489");
490
491static PyObject *
492BZ2File_readline(BZ2FileObject *self, PyObject *args)
493{
494 PyObject *ret = NULL;
495 int sizehint = -1;
496
497 if (!PyArg_ParseTuple(args, "|i:readline", &sizehint))
498 return NULL;
499
500 ACQUIRE_LOCK(self);
501 switch (self->mode) {
502 case MODE_READ:
503 break;
504 case MODE_READ_EOF:
Guido van Rossum522a6c62007-05-22 23:13:45 +0000505 ret = PyBytes_FromStringAndSize("", 0);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000506 goto cleanup;
507 case MODE_CLOSED:
508 PyErr_SetString(PyExc_ValueError,
509 "I/O operation on closed file");
510 goto cleanup;
511 default:
512 PyErr_SetString(PyExc_IOError,
513 "file is not ready for reading");
514 goto cleanup;
515 }
516
517 if (sizehint == 0)
Guido van Rossum522a6c62007-05-22 23:13:45 +0000518 ret = PyBytes_FromStringAndSize("", 0);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000519 else
520 ret = Util_GetLine(self, (sizehint < 0) ? 0 : sizehint);
521
522cleanup:
523 RELEASE_LOCK(self);
524 return ret;
525}
526
527PyDoc_STRVAR(BZ2File_readlines__doc__,
528"readlines([size]) -> list\n\
529\n\
530Call readline() repeatedly and return a list of lines read.\n\
531The optional size argument, if given, is an approximate bound on the\n\
532total number of bytes in the lines returned.\n\
533");
534
535/* This is a hacked version of Python's fileobject.c:file_readlines(). */
536static PyObject *
537BZ2File_readlines(BZ2FileObject *self, PyObject *args)
538{
539 long sizehint = 0;
540 PyObject *list = NULL;
541 PyObject *line;
542 char small_buffer[SMALLCHUNK];
543 char *buffer = small_buffer;
544 size_t buffersize = SMALLCHUNK;
545 PyObject *big_buffer = NULL;
546 size_t nfilled = 0;
547 size_t nread;
548 size_t totalread = 0;
549 char *p, *q, *end;
550 int err;
551 int shortread = 0;
552 int bzerror;
553
554 if (!PyArg_ParseTuple(args, "|l:readlines", &sizehint))
555 return NULL;
556
557 ACQUIRE_LOCK(self);
558 switch (self->mode) {
559 case MODE_READ:
560 break;
561 case MODE_READ_EOF:
562 list = PyList_New(0);
563 goto cleanup;
564 case MODE_CLOSED:
565 PyErr_SetString(PyExc_ValueError,
566 "I/O operation on closed file");
567 goto cleanup;
568 default:
569 PyErr_SetString(PyExc_IOError,
570 "file is not ready for reading");
571 goto cleanup;
572 }
573
574 if ((list = PyList_New(0)) == NULL)
575 goto cleanup;
576
577 for (;;) {
578 Py_BEGIN_ALLOW_THREADS
Guido van Rossumf09ca142007-06-13 00:03:05 +0000579 nread = BZ2_bzRead(&bzerror, self->fp,
580 buffer+nfilled, buffersize-nfilled);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000581 self->pos += nread;
582 Py_END_ALLOW_THREADS
583 if (bzerror == BZ_STREAM_END) {
584 self->size = self->pos;
585 self->mode = MODE_READ_EOF;
586 if (nread == 0) {
587 sizehint = 0;
588 break;
589 }
590 shortread = 1;
591 } else if (bzerror != BZ_OK) {
592 Util_CatchBZ2Error(bzerror);
593 error:
594 Py_DECREF(list);
595 list = NULL;
596 goto cleanup;
597 }
598 totalread += nread;
599 p = memchr(buffer+nfilled, '\n', nread);
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000600 if (!shortread && p == NULL) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000601 /* Need a larger buffer to fit this line */
602 nfilled += nread;
603 buffersize *= 2;
604 if (buffersize > INT_MAX) {
605 PyErr_SetString(PyExc_OverflowError,
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000606 "line is longer than a Python string can hold");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000607 goto error;
608 }
609 if (big_buffer == NULL) {
610 /* Create the big buffer */
Guido van Rossum522a6c62007-05-22 23:13:45 +0000611 big_buffer = PyBytes_FromStringAndSize(
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000612 NULL, buffersize);
613 if (big_buffer == NULL)
614 goto error;
Guido van Rossum522a6c62007-05-22 23:13:45 +0000615 buffer = PyBytes_AS_STRING(big_buffer);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000616 memcpy(buffer, small_buffer, nfilled);
617 }
618 else {
619 /* Grow the big buffer */
Guido van Rossum522a6c62007-05-22 23:13:45 +0000620 if (PyBytes_Resize(big_buffer, buffersize) < 0){
621 Py_DECREF(big_buffer);
622 big_buffer = NULL;
623 goto error;
624 }
625 buffer = PyBytes_AS_STRING(big_buffer);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000626 }
Guido van Rossum522a6c62007-05-22 23:13:45 +0000627 continue;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000628 }
629 end = buffer+nfilled+nread;
630 q = buffer;
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000631 while (p != NULL) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000632 /* Process complete lines */
633 p++;
Guido van Rossum522a6c62007-05-22 23:13:45 +0000634 line = PyBytes_FromStringAndSize(q, p-q);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000635 if (line == NULL)
636 goto error;
637 err = PyList_Append(list, line);
638 Py_DECREF(line);
639 if (err != 0)
640 goto error;
641 q = p;
642 p = memchr(q, '\n', end-q);
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000643 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000644 /* Move the remaining incomplete line to the start */
645 nfilled = end-q;
646 memmove(buffer, q, nfilled);
647 if (sizehint > 0)
648 if (totalread >= (size_t)sizehint)
649 break;
650 if (shortread) {
651 sizehint = 0;
652 break;
653 }
654 }
655 if (nfilled != 0) {
656 /* Partial last line */
Guido van Rossum522a6c62007-05-22 23:13:45 +0000657 line = PyBytes_FromStringAndSize(buffer, nfilled);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000658 if (line == NULL)
659 goto error;
660 if (sizehint > 0) {
661 /* Need to complete the last line */
662 PyObject *rest = Util_GetLine(self, 0);
Guido van Rossum522a6c62007-05-22 23:13:45 +0000663 PyObject *new;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000664 if (rest == NULL) {
665 Py_DECREF(line);
666 goto error;
667 }
Guido van Rossum522a6c62007-05-22 23:13:45 +0000668 new = PyBytes_Concat(line, rest);
669 Py_DECREF(line);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000670 Py_DECREF(rest);
Guido van Rossum522a6c62007-05-22 23:13:45 +0000671 line = new;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000672 if (line == NULL)
673 goto error;
674 }
675 err = PyList_Append(list, line);
676 Py_DECREF(line);
677 if (err != 0)
678 goto error;
679 }
680
681 cleanup:
682 RELEASE_LOCK(self);
683 if (big_buffer) {
684 Py_DECREF(big_buffer);
685 }
686 return list;
687}
688
689PyDoc_STRVAR(BZ2File_write__doc__,
690"write(data) -> None\n\
691\n\
692Write the 'data' string to file. Note that due to buffering, close() may\n\
693be needed before the file on disk reflects the data written.\n\
694");
695
696/* This is a hacked version of Python's fileobject.c:file_write(). */
697static PyObject *
698BZ2File_write(BZ2FileObject *self, PyObject *args)
699{
700 PyObject *ret = NULL;
701 char *buf;
702 int len;
703 int bzerror;
704
Walter Dörwaldbb9c7392004-11-01 17:10:19 +0000705 if (!PyArg_ParseTuple(args, "s#:write", &buf, &len))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000706 return NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000707
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000708 ACQUIRE_LOCK(self);
709 switch (self->mode) {
710 case MODE_WRITE:
711 break;
Tim Peterse3228092002-11-09 04:21:44 +0000712
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000713 case MODE_CLOSED:
714 PyErr_SetString(PyExc_ValueError,
715 "I/O operation on closed file");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000716 goto cleanup;
Tim Peterse3228092002-11-09 04:21:44 +0000717
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000718 default:
719 PyErr_SetString(PyExc_IOError,
720 "file is not ready for writing");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000721 goto cleanup;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000722 }
723
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000724 Py_BEGIN_ALLOW_THREADS
725 BZ2_bzWrite (&bzerror, self->fp, buf, len);
726 self->pos += len;
727 Py_END_ALLOW_THREADS
Tim Peterse3228092002-11-09 04:21:44 +0000728
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000729 if (bzerror != BZ_OK) {
730 Util_CatchBZ2Error(bzerror);
731 goto cleanup;
732 }
Tim Peterse3228092002-11-09 04:21:44 +0000733
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000734 Py_INCREF(Py_None);
735 ret = Py_None;
736
737cleanup:
738 RELEASE_LOCK(self);
739 return ret;
740}
741
742PyDoc_STRVAR(BZ2File_writelines__doc__,
743"writelines(sequence_of_strings) -> None\n\
744\n\
745Write the sequence of strings to the file. Note that newlines are not\n\
746added. The sequence can be any iterable object producing strings. This is\n\
747equivalent to calling write() for each string.\n\
748");
749
750/* This is a hacked version of Python's fileobject.c:file_writelines(). */
751static PyObject *
752BZ2File_writelines(BZ2FileObject *self, PyObject *seq)
753{
754#define CHUNKSIZE 1000
755 PyObject *list = NULL;
756 PyObject *iter = NULL;
757 PyObject *ret = NULL;
758 PyObject *line;
759 int i, j, index, len, islist;
760 int bzerror;
761
762 ACQUIRE_LOCK(self);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000763 switch (self->mode) {
764 case MODE_WRITE:
765 break;
766
767 case MODE_CLOSED:
768 PyErr_SetString(PyExc_ValueError,
769 "I/O operation on closed file");
770 goto error;
771
772 default:
773 PyErr_SetString(PyExc_IOError,
774 "file is not ready for writing");
775 goto error;
776 }
777
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000778 islist = PyList_Check(seq);
779 if (!islist) {
780 iter = PyObject_GetIter(seq);
781 if (iter == NULL) {
782 PyErr_SetString(PyExc_TypeError,
783 "writelines() requires an iterable argument");
784 goto error;
785 }
786 list = PyList_New(CHUNKSIZE);
787 if (list == NULL)
788 goto error;
789 }
790
791 /* Strategy: slurp CHUNKSIZE lines into a private list,
792 checking that they are all strings, then write that list
793 without holding the interpreter lock, then come back for more. */
794 for (index = 0; ; index += CHUNKSIZE) {
795 if (islist) {
796 Py_XDECREF(list);
797 list = PyList_GetSlice(seq, index, index+CHUNKSIZE);
798 if (list == NULL)
799 goto error;
800 j = PyList_GET_SIZE(list);
801 }
802 else {
803 for (j = 0; j < CHUNKSIZE; j++) {
804 line = PyIter_Next(iter);
805 if (line == NULL) {
806 if (PyErr_Occurred())
807 goto error;
808 break;
809 }
810 PyList_SetItem(list, j, line);
811 }
812 }
813 if (j == 0)
814 break;
815
Guido van Rossum522a6c62007-05-22 23:13:45 +0000816 /* Check that all entries are indeed byte strings. If not,
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000817 apply the same rules as for file.write() and
818 convert the rets to strings. This is slow, but
819 seems to be the only way since all conversion APIs
820 could potentially execute Python code. */
821 for (i = 0; i < j; i++) {
822 PyObject *v = PyList_GET_ITEM(list, i);
Guido van Rossum522a6c62007-05-22 23:13:45 +0000823 if (!PyBytes_Check(v)) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000824 const char *buffer;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000825 Py_ssize_t len;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000826 if (PyObject_AsCharBuffer(v, &buffer, &len)) {
827 PyErr_SetString(PyExc_TypeError,
828 "writelines() "
829 "argument must be "
830 "a sequence of "
Guido van Rossum522a6c62007-05-22 23:13:45 +0000831 "bytes objects");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000832 goto error;
833 }
Guido van Rossum522a6c62007-05-22 23:13:45 +0000834 line = PyBytes_FromStringAndSize(buffer,
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000835 len);
836 if (line == NULL)
837 goto error;
838 Py_DECREF(v);
839 PyList_SET_ITEM(list, i, line);
840 }
841 }
842
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000843 /* Since we are releasing the global lock, the
844 following code may *not* execute Python code. */
845 Py_BEGIN_ALLOW_THREADS
846 for (i = 0; i < j; i++) {
847 line = PyList_GET_ITEM(list, i);
Guido van Rossum522a6c62007-05-22 23:13:45 +0000848 len = PyBytes_GET_SIZE(line);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000849 BZ2_bzWrite (&bzerror, self->fp,
Guido van Rossum522a6c62007-05-22 23:13:45 +0000850 PyBytes_AS_STRING(line), len);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000851 if (bzerror != BZ_OK) {
852 Py_BLOCK_THREADS
853 Util_CatchBZ2Error(bzerror);
854 goto error;
855 }
856 }
857 Py_END_ALLOW_THREADS
858
859 if (j < CHUNKSIZE)
860 break;
861 }
862
863 Py_INCREF(Py_None);
864 ret = Py_None;
865
866 error:
867 RELEASE_LOCK(self);
868 Py_XDECREF(list);
869 Py_XDECREF(iter);
870 return ret;
871#undef CHUNKSIZE
872}
873
874PyDoc_STRVAR(BZ2File_seek__doc__,
875"seek(offset [, whence]) -> None\n\
876\n\
877Move to new file position. Argument offset is a byte count. Optional\n\
878argument whence defaults to 0 (offset from start of file, offset\n\
879should be >= 0); other values are 1 (move relative to current position,\n\
880positive or negative), and 2 (move relative to end of file, usually\n\
881negative, although many platforms allow seeking beyond the end of a file).\n\
882\n\
883Note that seeking of bz2 files is emulated, and depending on the parameters\n\
884the operation may be extremely slow.\n\
885");
886
887static PyObject *
888BZ2File_seek(BZ2FileObject *self, PyObject *args)
889{
890 int where = 0;
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000891 PyObject *offobj;
892 Py_off_t offset;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000893 char small_buffer[SMALLCHUNK];
894 char *buffer = small_buffer;
895 size_t buffersize = SMALLCHUNK;
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000896 Py_off_t bytesread = 0;
Georg Brandla8bcecc2005-09-03 07:49:53 +0000897 size_t readsize;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000898 int chunksize;
899 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000900 PyObject *ret = NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000901
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000902 if (!PyArg_ParseTuple(args, "O|i:seek", &offobj, &where))
903 return NULL;
904#if !defined(HAVE_LARGEFILE_SUPPORT)
905 offset = PyInt_AsLong(offobj);
906#else
907 offset = PyLong_Check(offobj) ?
908 PyLong_AsLongLong(offobj) : PyInt_AsLong(offobj);
909#endif
910 if (PyErr_Occurred())
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000911 return NULL;
912
913 ACQUIRE_LOCK(self);
914 Util_DropReadAhead(self);
915 switch (self->mode) {
916 case MODE_READ:
917 case MODE_READ_EOF:
918 break;
Tim Peterse3228092002-11-09 04:21:44 +0000919
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000920 case MODE_CLOSED:
921 PyErr_SetString(PyExc_ValueError,
922 "I/O operation on closed file");
Thomas Wouters89f507f2006-12-13 04:49:30 +0000923 goto cleanup;
Tim Peterse3228092002-11-09 04:21:44 +0000924
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000925 default:
926 PyErr_SetString(PyExc_IOError,
927 "seek works only while reading");
Thomas Wouters89f507f2006-12-13 04:49:30 +0000928 goto cleanup;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000929 }
930
Georg Brandl47fab922006-02-18 21:57:25 +0000931 if (where == 2) {
932 if (self->size == -1) {
933 assert(self->mode != MODE_READ_EOF);
934 for (;;) {
935 Py_BEGIN_ALLOW_THREADS
Guido van Rossumf09ca142007-06-13 00:03:05 +0000936 chunksize = BZ2_bzRead(&bzerror, self->fp,
937 buffer, buffersize);
Georg Brandl47fab922006-02-18 21:57:25 +0000938 self->pos += chunksize;
939 Py_END_ALLOW_THREADS
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000940
Georg Brandl47fab922006-02-18 21:57:25 +0000941 bytesread += chunksize;
942 if (bzerror == BZ_STREAM_END) {
943 break;
944 } else if (bzerror != BZ_OK) {
945 Util_CatchBZ2Error(bzerror);
946 goto cleanup;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000947 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000948 }
Georg Brandl47fab922006-02-18 21:57:25 +0000949 self->mode = MODE_READ_EOF;
950 self->size = self->pos;
951 bytesread = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000952 }
Georg Brandl47fab922006-02-18 21:57:25 +0000953 offset = self->size + offset;
954 } else if (where == 1) {
955 offset = self->pos + offset;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000956 }
957
Guido van Rossum522a6c62007-05-22 23:13:45 +0000958 /* Before getting here, offset must be the absolute position the file
Georg Brandl47fab922006-02-18 21:57:25 +0000959 * pointer should be set to. */
960
961 if (offset >= self->pos) {
962 /* we can move forward */
963 offset -= self->pos;
964 } else {
965 /* we cannot move back, so rewind the stream */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000966 BZ2_bzReadClose(&bzerror, self->fp);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000967 if (bzerror != BZ_OK) {
968 Util_CatchBZ2Error(bzerror);
969 goto cleanup;
970 }
Guido van Rossumf09ca142007-06-13 00:03:05 +0000971 rewind(self->rawfp);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000972 self->pos = 0;
Guido van Rossumf09ca142007-06-13 00:03:05 +0000973 self->fp = BZ2_bzReadOpen(&bzerror, self->rawfp,
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000974 0, 0, NULL, 0);
975 if (bzerror != BZ_OK) {
976 Util_CatchBZ2Error(bzerror);
977 goto cleanup;
978 }
979 self->mode = MODE_READ;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000980 }
981
Georg Brandl47fab922006-02-18 21:57:25 +0000982 if (offset <= 0 || self->mode == MODE_READ_EOF)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000983 goto exit;
984
985 /* Before getting here, offset must be set to the number of bytes
986 * to walk forward. */
987 for (;;) {
Georg Brandla8bcecc2005-09-03 07:49:53 +0000988 if (offset-bytesread > buffersize)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000989 readsize = buffersize;
990 else
Georg Brandla8bcecc2005-09-03 07:49:53 +0000991 /* offset might be wider that readsize, but the result
992 * of the subtraction is bound by buffersize (see the
993 * condition above). buffersize is 8192. */
994 readsize = (size_t)(offset-bytesread);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000995 Py_BEGIN_ALLOW_THREADS
Guido van Rossumf09ca142007-06-13 00:03:05 +0000996 chunksize = BZ2_bzRead(&bzerror, self->fp, buffer, readsize);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000997 self->pos += chunksize;
998 Py_END_ALLOW_THREADS
999 bytesread += chunksize;
1000 if (bzerror == BZ_STREAM_END) {
1001 self->size = self->pos;
1002 self->mode = MODE_READ_EOF;
1003 break;
1004 } else if (bzerror != BZ_OK) {
1005 Util_CatchBZ2Error(bzerror);
1006 goto cleanup;
1007 }
1008 if (bytesread == offset)
1009 break;
1010 }
1011
1012exit:
1013 Py_INCREF(Py_None);
1014 ret = Py_None;
1015
1016cleanup:
1017 RELEASE_LOCK(self);
1018 return ret;
1019}
1020
1021PyDoc_STRVAR(BZ2File_tell__doc__,
1022"tell() -> int\n\
1023\n\
1024Return the current file position, an integer (may be a long integer).\n\
1025");
1026
1027static PyObject *
1028BZ2File_tell(BZ2FileObject *self, PyObject *args)
1029{
1030 PyObject *ret = NULL;
1031
1032 if (self->mode == MODE_CLOSED) {
1033 PyErr_SetString(PyExc_ValueError,
1034 "I/O operation on closed file");
1035 goto cleanup;
1036 }
1037
Georg Brandla8bcecc2005-09-03 07:49:53 +00001038#if !defined(HAVE_LARGEFILE_SUPPORT)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001039 ret = PyInt_FromLong(self->pos);
Georg Brandla8bcecc2005-09-03 07:49:53 +00001040#else
1041 ret = PyLong_FromLongLong(self->pos);
1042#endif
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001043
1044cleanup:
1045 return ret;
1046}
1047
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001048PyDoc_STRVAR(BZ2File_close__doc__,
1049"close() -> None or (perhaps) an integer\n\
1050\n\
1051Close the file. Sets data attribute .closed to true. A closed file\n\
1052cannot be used for further I/O operations. close() may be called more\n\
1053than once without error.\n\
1054");
1055
1056static PyObject *
1057BZ2File_close(BZ2FileObject *self)
1058{
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001059 PyObject *ret = NULL;
1060 int bzerror = BZ_OK;
1061
Guido van Rossumf09ca142007-06-13 00:03:05 +00001062 if (self->mode == MODE_CLOSED) {
1063 Py_RETURN_NONE;
1064 }
1065
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001066 ACQUIRE_LOCK(self);
1067 switch (self->mode) {
1068 case MODE_READ:
1069 case MODE_READ_EOF:
1070 BZ2_bzReadClose(&bzerror, self->fp);
1071 break;
1072 case MODE_WRITE:
1073 BZ2_bzWriteClose(&bzerror, self->fp,
1074 0, NULL, NULL);
1075 break;
1076 }
1077 self->mode = MODE_CLOSED;
Guido van Rossumf09ca142007-06-13 00:03:05 +00001078 fclose(self->rawfp);
1079 self->rawfp = NULL;
1080 if (bzerror == BZ_OK) {
1081 Py_INCREF(Py_None);
1082 ret = Py_None;
1083 }
1084 else {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001085 Util_CatchBZ2Error(bzerror);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001086 }
1087
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001088 RELEASE_LOCK(self);
1089 return ret;
1090}
1091
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001092static PyObject *BZ2File_getiter(BZ2FileObject *self);
1093
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001094static PyMethodDef BZ2File_methods[] = {
1095 {"read", (PyCFunction)BZ2File_read, METH_VARARGS, BZ2File_read__doc__},
1096 {"readline", (PyCFunction)BZ2File_readline, METH_VARARGS, BZ2File_readline__doc__},
1097 {"readlines", (PyCFunction)BZ2File_readlines, METH_VARARGS, BZ2File_readlines__doc__},
1098 {"write", (PyCFunction)BZ2File_write, METH_VARARGS, BZ2File_write__doc__},
1099 {"writelines", (PyCFunction)BZ2File_writelines, METH_O, BZ2File_writelines__doc__},
1100 {"seek", (PyCFunction)BZ2File_seek, METH_VARARGS, BZ2File_seek__doc__},
1101 {"tell", (PyCFunction)BZ2File_tell, METH_NOARGS, BZ2File_tell__doc__},
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001102 {"close", (PyCFunction)BZ2File_close, METH_NOARGS, BZ2File_close__doc__},
1103 {NULL, NULL} /* sentinel */
1104};
1105
1106
1107/* ===================================================================== */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001108/* Getters and setters of BZ2File. */
1109
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001110static PyObject *
1111BZ2File_get_closed(BZ2FileObject *self, void *closure)
1112{
1113 return PyInt_FromLong(self->mode == MODE_CLOSED);
1114}
1115
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001116static PyGetSetDef BZ2File_getset[] = {
1117 {"closed", (getter)BZ2File_get_closed, NULL,
1118 "True if the file is closed"},
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001119 {NULL} /* Sentinel */
1120};
1121
1122
1123/* ===================================================================== */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001124/* Slot definitions for BZ2File_Type. */
1125
1126static int
1127BZ2File_init(BZ2FileObject *self, PyObject *args, PyObject *kwargs)
1128{
Martin v. Löwis15e62742006-02-27 16:46:16 +00001129 static char *kwlist[] = {"filename", "mode", "buffering",
Guido van Rossumf09ca142007-06-13 00:03:05 +00001130 "compresslevel", 0};
1131 char *name;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001132 char *mode = "r";
1133 int buffering = -1;
1134 int compresslevel = 9;
1135 int bzerror;
1136 int mode_char = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001137
1138 self->size = -1;
Tim Peterse3228092002-11-09 04:21:44 +00001139
Guido van Rossumf09ca142007-06-13 00:03:05 +00001140 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|sii:BZ2File",
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001141 kwlist, &name, &mode, &buffering,
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001142 &compresslevel))
1143 return -1;
1144
1145 if (compresslevel < 1 || compresslevel > 9) {
1146 PyErr_SetString(PyExc_ValueError,
1147 "compresslevel must be between 1 and 9");
1148 return -1;
1149 }
1150
1151 for (;;) {
1152 int error = 0;
1153 switch (*mode) {
1154 case 'r':
1155 case 'w':
1156 if (mode_char)
1157 error = 1;
1158 mode_char = *mode;
1159 break;
1160
1161 case 'b':
1162 break;
1163
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001164 default:
1165 error = 1;
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001166 break;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001167 }
1168 if (error) {
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001169 PyErr_Format(PyExc_ValueError,
1170 "invalid mode char %c", *mode);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001171 return -1;
1172 }
1173 mode++;
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001174 if (*mode == '\0')
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001175 break;
1176 }
1177
Georg Brandl6b95f1d2005-06-03 19:47:00 +00001178 if (mode_char == 0) {
1179 mode_char = 'r';
1180 }
1181
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001182 mode = (mode_char == 'r') ? "rb" : "wb";
Tim Peterse3228092002-11-09 04:21:44 +00001183
Guido van Rossumf09ca142007-06-13 00:03:05 +00001184 self->rawfp = fopen(name, mode);
1185 if (self->rawfp == NULL) {
1186 PyErr_SetFromErrno(PyExc_IOError);
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001187 return -1;
Guido van Rossumf09ca142007-06-13 00:03:05 +00001188 }
1189 /* XXX Ignore buffering */
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001190
1191 /* From now on, we have stuff to dealloc, so jump to error label
1192 * instead of returning */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001193
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001194#ifdef WITH_THREAD
1195 self->lock = PyThread_allocate_lock();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001196 if (!self->lock) {
1197 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001198 goto error;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001199 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001200#endif
1201
1202 if (mode_char == 'r')
Guido van Rossumf09ca142007-06-13 00:03:05 +00001203 self->fp = BZ2_bzReadOpen(&bzerror, self->rawfp,
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001204 0, 0, NULL, 0);
1205 else
Guido van Rossumf09ca142007-06-13 00:03:05 +00001206 self->fp = BZ2_bzWriteOpen(&bzerror, self->rawfp,
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001207 compresslevel, 0, 0);
1208
1209 if (bzerror != BZ_OK) {
1210 Util_CatchBZ2Error(bzerror);
1211 goto error;
1212 }
1213
1214 self->mode = (mode_char == 'r') ? MODE_READ : MODE_WRITE;
1215
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001216 return 0;
1217
1218error:
Guido van Rossumf09ca142007-06-13 00:03:05 +00001219 fclose(self->rawfp);
1220 self->rawfp = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001221#ifdef WITH_THREAD
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001222 if (self->lock) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001223 PyThread_free_lock(self->lock);
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001224 self->lock = NULL;
1225 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001226#endif
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001227 return -1;
1228}
1229
1230static void
1231BZ2File_dealloc(BZ2FileObject *self)
1232{
1233 int bzerror;
1234#ifdef WITH_THREAD
1235 if (self->lock)
1236 PyThread_free_lock(self->lock);
1237#endif
1238 switch (self->mode) {
1239 case MODE_READ:
1240 case MODE_READ_EOF:
1241 BZ2_bzReadClose(&bzerror, self->fp);
1242 break;
1243 case MODE_WRITE:
1244 BZ2_bzWriteClose(&bzerror, self->fp,
1245 0, NULL, NULL);
1246 break;
1247 }
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001248 Util_DropReadAhead(self);
Guido van Rossumf09ca142007-06-13 00:03:05 +00001249 if (self->rawfp != NULL)
1250 fclose(self->rawfp);
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00001251 Py_Type(self)->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001252}
1253
1254/* This is a hacked version of Python's fileobject.c:file_getiter(). */
1255static PyObject *
1256BZ2File_getiter(BZ2FileObject *self)
1257{
1258 if (self->mode == MODE_CLOSED) {
1259 PyErr_SetString(PyExc_ValueError,
1260 "I/O operation on closed file");
1261 return NULL;
1262 }
1263 Py_INCREF((PyObject*)self);
1264 return (PyObject *)self;
1265}
1266
1267/* This is a hacked version of Python's fileobject.c:file_iternext(). */
1268#define READAHEAD_BUFSIZE 8192
1269static PyObject *
1270BZ2File_iternext(BZ2FileObject *self)
1271{
Guido van Rossum522a6c62007-05-22 23:13:45 +00001272 PyBytesObject* ret;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001273 ACQUIRE_LOCK(self);
1274 if (self->mode == MODE_CLOSED) {
1275 PyErr_SetString(PyExc_ValueError,
1276 "I/O operation on closed file");
1277 return NULL;
1278 }
1279 ret = Util_ReadAheadGetLineSkip(self, 0, READAHEAD_BUFSIZE);
1280 RELEASE_LOCK(self);
Guido van Rossum522a6c62007-05-22 23:13:45 +00001281 if (ret == NULL || PyBytes_GET_SIZE(ret) == 0) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001282 Py_XDECREF(ret);
1283 return NULL;
1284 }
1285 return (PyObject *)ret;
1286}
1287
1288/* ===================================================================== */
1289/* BZ2File_Type definition. */
1290
1291PyDoc_VAR(BZ2File__doc__) =
1292PyDoc_STR(
1293"BZ2File(name [, mode='r', buffering=0, compresslevel=9]) -> file object\n\
1294\n\
1295Open a bz2 file. The mode can be 'r' or 'w', for reading (default) or\n\
1296writing. When opened for writing, the file will be created if it doesn't\n\
1297exist, and truncated otherwise. If the buffering argument is given, 0 means\n\
1298unbuffered, and larger numbers specify the buffer size. If compresslevel\n\
1299is given, must be a number between 1 and 9.\n\
Guido van Rossum88e860c2007-06-13 01:46:31 +00001300Data read is always returned in bytes; data written ought to be bytes.\n\
1301");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001302
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001303static PyTypeObject BZ2File_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00001304 PyVarObject_HEAD_INIT(NULL, 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001305 "bz2.BZ2File", /*tp_name*/
1306 sizeof(BZ2FileObject), /*tp_basicsize*/
1307 0, /*tp_itemsize*/
1308 (destructor)BZ2File_dealloc, /*tp_dealloc*/
1309 0, /*tp_print*/
1310 0, /*tp_getattr*/
1311 0, /*tp_setattr*/
1312 0, /*tp_compare*/
1313 0, /*tp_repr*/
1314 0, /*tp_as_number*/
1315 0, /*tp_as_sequence*/
1316 0, /*tp_as_mapping*/
1317 0, /*tp_hash*/
1318 0, /*tp_call*/
1319 0, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001320 PyObject_GenericGetAttr,/*tp_getattro*/
1321 PyObject_GenericSetAttr,/*tp_setattro*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001322 0, /*tp_as_buffer*/
1323 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1324 BZ2File__doc__, /*tp_doc*/
1325 0, /*tp_traverse*/
1326 0, /*tp_clear*/
1327 0, /*tp_richcompare*/
1328 0, /*tp_weaklistoffset*/
1329 (getiterfunc)BZ2File_getiter, /*tp_iter*/
1330 (iternextfunc)BZ2File_iternext, /*tp_iternext*/
1331 BZ2File_methods, /*tp_methods*/
Guido van Rossum79139b22007-02-09 23:20:19 +00001332 0, /*tp_members*/
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001333 BZ2File_getset, /*tp_getset*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001334 0, /*tp_base*/
1335 0, /*tp_dict*/
1336 0, /*tp_descr_get*/
1337 0, /*tp_descr_set*/
1338 0, /*tp_dictoffset*/
1339 (initproc)BZ2File_init, /*tp_init*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001340 PyType_GenericAlloc, /*tp_alloc*/
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001341 PyType_GenericNew, /*tp_new*/
Neal Norwitz30d1c512007-08-19 22:48:23 +00001342 PyObject_Free, /*tp_free*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001343 0, /*tp_is_gc*/
1344};
1345
1346
1347/* ===================================================================== */
1348/* Methods of BZ2Comp. */
1349
1350PyDoc_STRVAR(BZ2Comp_compress__doc__,
1351"compress(data) -> string\n\
1352\n\
1353Provide more data to the compressor object. It will return chunks of\n\
1354compressed data whenever possible. When you've finished providing data\n\
1355to compress, call the flush() method to finish the compression process,\n\
1356and return what is left in the internal buffers.\n\
1357");
1358
1359static PyObject *
1360BZ2Comp_compress(BZ2CompObject *self, PyObject *args)
1361{
1362 char *data;
1363 int datasize;
1364 int bufsize = SMALLCHUNK;
Martin v. Löwisb9a0f912003-03-29 10:06:18 +00001365 PY_LONG_LONG totalout;
Gustavo Niemeyer7d7930b2002-11-05 18:41:53 +00001366 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001367 bz_stream *bzs = &self->bzs;
1368 int bzerror;
1369
Walter Dörwaldbb9c7392004-11-01 17:10:19 +00001370 if (!PyArg_ParseTuple(args, "s#:compress", &data, &datasize))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001371 return NULL;
1372
Gustavo Niemeyera6e436e2004-02-14 00:02:45 +00001373 if (datasize == 0)
Guido van Rossum522a6c62007-05-22 23:13:45 +00001374 return PyBytes_FromStringAndSize("", 0);
Gustavo Niemeyera6e436e2004-02-14 00:02:45 +00001375
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001376 ACQUIRE_LOCK(self);
1377 if (!self->running) {
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001378 PyErr_SetString(PyExc_ValueError,
1379 "this object was already flushed");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001380 goto error;
1381 }
1382
Guido van Rossum522a6c62007-05-22 23:13:45 +00001383 ret = PyBytes_FromStringAndSize(NULL, bufsize);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001384 if (!ret)
1385 goto error;
1386
1387 bzs->next_in = data;
1388 bzs->avail_in = datasize;
1389 bzs->next_out = BUF(ret);
1390 bzs->avail_out = bufsize;
1391
1392 totalout = BZS_TOTAL_OUT(bzs);
1393
1394 for (;;) {
1395 Py_BEGIN_ALLOW_THREADS
1396 bzerror = BZ2_bzCompress(bzs, BZ_RUN);
1397 Py_END_ALLOW_THREADS
1398 if (bzerror != BZ_RUN_OK) {
1399 Util_CatchBZ2Error(bzerror);
1400 goto error;
1401 }
Guido van Rossumd8faa362007-04-27 19:54:29 +00001402 if (bzs->avail_in == 0)
1403 break; /* no more input data */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001404 if (bzs->avail_out == 0) {
1405 bufsize = Util_NewBufferSize(bufsize);
Guido van Rossum522a6c62007-05-22 23:13:45 +00001406 if (PyBytes_Resize(ret, bufsize) < 0) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001407 BZ2_bzCompressEnd(bzs);
1408 goto error;
1409 }
1410 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs)
1411 - totalout);
1412 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001413 }
1414 }
1415
Guido van Rossum522a6c62007-05-22 23:13:45 +00001416 if (PyBytes_Resize(ret,
1417 (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout)) < 0)
1418 goto error;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001419
1420 RELEASE_LOCK(self);
1421 return ret;
1422
1423error:
1424 RELEASE_LOCK(self);
1425 Py_XDECREF(ret);
1426 return NULL;
1427}
1428
1429PyDoc_STRVAR(BZ2Comp_flush__doc__,
1430"flush() -> string\n\
1431\n\
1432Finish the compression process and return what is left in internal buffers.\n\
1433You must not use the compressor object after calling this method.\n\
1434");
1435
1436static PyObject *
1437BZ2Comp_flush(BZ2CompObject *self)
1438{
1439 int bufsize = SMALLCHUNK;
Gustavo Niemeyer7d7930b2002-11-05 18:41:53 +00001440 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001441 bz_stream *bzs = &self->bzs;
Martin v. Löwisb9a0f912003-03-29 10:06:18 +00001442 PY_LONG_LONG totalout;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001443 int bzerror;
1444
1445 ACQUIRE_LOCK(self);
1446 if (!self->running) {
1447 PyErr_SetString(PyExc_ValueError, "object was already "
1448 "flushed");
1449 goto error;
1450 }
1451 self->running = 0;
1452
Guido van Rossum522a6c62007-05-22 23:13:45 +00001453 ret = PyBytes_FromStringAndSize(NULL, bufsize);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001454 if (!ret)
1455 goto error;
1456
1457 bzs->next_out = BUF(ret);
1458 bzs->avail_out = bufsize;
1459
1460 totalout = BZS_TOTAL_OUT(bzs);
1461
1462 for (;;) {
1463 Py_BEGIN_ALLOW_THREADS
1464 bzerror = BZ2_bzCompress(bzs, BZ_FINISH);
1465 Py_END_ALLOW_THREADS
1466 if (bzerror == BZ_STREAM_END) {
1467 break;
1468 } else if (bzerror != BZ_FINISH_OK) {
1469 Util_CatchBZ2Error(bzerror);
1470 goto error;
1471 }
1472 if (bzs->avail_out == 0) {
1473 bufsize = Util_NewBufferSize(bufsize);
Guido van Rossum522a6c62007-05-22 23:13:45 +00001474 if (PyBytes_Resize(ret, bufsize) < 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001475 goto error;
1476 bzs->next_out = BUF(ret);
1477 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs)
1478 - totalout);
1479 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
1480 }
1481 }
1482
Guido van Rossum522a6c62007-05-22 23:13:45 +00001483 if (bzs->avail_out != 0) {
1484 if (PyBytes_Resize(ret,
1485 (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout)) < 0)
1486 goto error;
1487 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001488
1489 RELEASE_LOCK(self);
1490 return ret;
1491
1492error:
1493 RELEASE_LOCK(self);
1494 Py_XDECREF(ret);
1495 return NULL;
1496}
1497
1498static PyMethodDef BZ2Comp_methods[] = {
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001499 {"compress", (PyCFunction)BZ2Comp_compress, METH_VARARGS,
1500 BZ2Comp_compress__doc__},
1501 {"flush", (PyCFunction)BZ2Comp_flush, METH_NOARGS,
1502 BZ2Comp_flush__doc__},
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001503 {NULL, NULL} /* sentinel */
1504};
1505
1506
1507/* ===================================================================== */
1508/* Slot definitions for BZ2Comp_Type. */
1509
1510static int
1511BZ2Comp_init(BZ2CompObject *self, PyObject *args, PyObject *kwargs)
1512{
1513 int compresslevel = 9;
1514 int bzerror;
Martin v. Löwis15e62742006-02-27 16:46:16 +00001515 static char *kwlist[] = {"compresslevel", 0};
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001516
1517 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:BZ2Compressor",
1518 kwlist, &compresslevel))
1519 return -1;
1520
1521 if (compresslevel < 1 || compresslevel > 9) {
1522 PyErr_SetString(PyExc_ValueError,
1523 "compresslevel must be between 1 and 9");
1524 goto error;
1525 }
1526
1527#ifdef WITH_THREAD
1528 self->lock = PyThread_allocate_lock();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001529 if (!self->lock) {
1530 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001531 goto error;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001532 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001533#endif
1534
1535 memset(&self->bzs, 0, sizeof(bz_stream));
1536 bzerror = BZ2_bzCompressInit(&self->bzs, compresslevel, 0, 0);
1537 if (bzerror != BZ_OK) {
1538 Util_CatchBZ2Error(bzerror);
1539 goto error;
1540 }
1541
1542 self->running = 1;
1543
1544 return 0;
1545error:
1546#ifdef WITH_THREAD
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001547 if (self->lock) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001548 PyThread_free_lock(self->lock);
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001549 self->lock = NULL;
1550 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001551#endif
1552 return -1;
1553}
1554
1555static void
1556BZ2Comp_dealloc(BZ2CompObject *self)
1557{
1558#ifdef WITH_THREAD
1559 if (self->lock)
1560 PyThread_free_lock(self->lock);
1561#endif
1562 BZ2_bzCompressEnd(&self->bzs);
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00001563 Py_Type(self)->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001564}
1565
1566
1567/* ===================================================================== */
1568/* BZ2Comp_Type definition. */
1569
1570PyDoc_STRVAR(BZ2Comp__doc__,
1571"BZ2Compressor([compresslevel=9]) -> compressor object\n\
1572\n\
1573Create a new compressor object. This object may be used to compress\n\
1574data sequentially. If you want to compress data in one shot, use the\n\
1575compress() function instead. The compresslevel parameter, if given,\n\
1576must be a number between 1 and 9.\n\
1577");
1578
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001579static PyTypeObject BZ2Comp_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00001580 PyVarObject_HEAD_INIT(NULL, 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001581 "bz2.BZ2Compressor", /*tp_name*/
1582 sizeof(BZ2CompObject), /*tp_basicsize*/
1583 0, /*tp_itemsize*/
1584 (destructor)BZ2Comp_dealloc, /*tp_dealloc*/
1585 0, /*tp_print*/
1586 0, /*tp_getattr*/
1587 0, /*tp_setattr*/
1588 0, /*tp_compare*/
1589 0, /*tp_repr*/
1590 0, /*tp_as_number*/
1591 0, /*tp_as_sequence*/
1592 0, /*tp_as_mapping*/
1593 0, /*tp_hash*/
1594 0, /*tp_call*/
1595 0, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001596 PyObject_GenericGetAttr,/*tp_getattro*/
1597 PyObject_GenericSetAttr,/*tp_setattro*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001598 0, /*tp_as_buffer*/
1599 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1600 BZ2Comp__doc__, /*tp_doc*/
1601 0, /*tp_traverse*/
1602 0, /*tp_clear*/
1603 0, /*tp_richcompare*/
1604 0, /*tp_weaklistoffset*/
1605 0, /*tp_iter*/
1606 0, /*tp_iternext*/
1607 BZ2Comp_methods, /*tp_methods*/
1608 0, /*tp_members*/
1609 0, /*tp_getset*/
1610 0, /*tp_base*/
1611 0, /*tp_dict*/
1612 0, /*tp_descr_get*/
1613 0, /*tp_descr_set*/
1614 0, /*tp_dictoffset*/
1615 (initproc)BZ2Comp_init, /*tp_init*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001616 PyType_GenericAlloc, /*tp_alloc*/
1617 PyType_GenericNew, /*tp_new*/
Neal Norwitz30d1c512007-08-19 22:48:23 +00001618 PyObject_Free, /*tp_free*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001619 0, /*tp_is_gc*/
1620};
1621
1622
1623/* ===================================================================== */
1624/* Members of BZ2Decomp. */
1625
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001626#undef OFF
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001627#define OFF(x) offsetof(BZ2DecompObject, x)
1628
1629static PyMemberDef BZ2Decomp_members[] = {
Guido van Rossum33d26892007-08-05 15:29:28 +00001630 {"unused_data", T_OBJECT, OFF(unused_data), READONLY},
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001631 {NULL} /* Sentinel */
1632};
1633
1634
1635/* ===================================================================== */
1636/* Methods of BZ2Decomp. */
1637
1638PyDoc_STRVAR(BZ2Decomp_decompress__doc__,
1639"decompress(data) -> string\n\
1640\n\
1641Provide more data to the decompressor object. It will return chunks\n\
1642of decompressed data whenever possible. If you try to decompress data\n\
1643after the end of stream is found, EOFError will be raised. If any data\n\
1644was found after the end of stream, it'll be ignored and saved in\n\
1645unused_data attribute.\n\
1646");
1647
1648static PyObject *
1649BZ2Decomp_decompress(BZ2DecompObject *self, PyObject *args)
1650{
1651 char *data;
1652 int datasize;
1653 int bufsize = SMALLCHUNK;
Martin v. Löwisb9a0f912003-03-29 10:06:18 +00001654 PY_LONG_LONG totalout;
Neal Norwitz18142c02002-11-05 18:17:32 +00001655 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001656 bz_stream *bzs = &self->bzs;
1657 int bzerror;
1658
Walter Dörwaldbb9c7392004-11-01 17:10:19 +00001659 if (!PyArg_ParseTuple(args, "s#:decompress", &data, &datasize))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001660 return NULL;
1661
1662 ACQUIRE_LOCK(self);
1663 if (!self->running) {
1664 PyErr_SetString(PyExc_EOFError, "end of stream was "
1665 "already found");
1666 goto error;
1667 }
1668
Guido van Rossum522a6c62007-05-22 23:13:45 +00001669 ret = PyBytes_FromStringAndSize(NULL, bufsize);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001670 if (!ret)
1671 goto error;
1672
1673 bzs->next_in = data;
1674 bzs->avail_in = datasize;
1675 bzs->next_out = BUF(ret);
1676 bzs->avail_out = bufsize;
1677
1678 totalout = BZS_TOTAL_OUT(bzs);
1679
1680 for (;;) {
1681 Py_BEGIN_ALLOW_THREADS
1682 bzerror = BZ2_bzDecompress(bzs);
1683 Py_END_ALLOW_THREADS
1684 if (bzerror == BZ_STREAM_END) {
1685 if (bzs->avail_in != 0) {
1686 Py_DECREF(self->unused_data);
1687 self->unused_data =
Guido van Rossum522a6c62007-05-22 23:13:45 +00001688 PyBytes_FromStringAndSize(bzs->next_in,
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001689 bzs->avail_in);
1690 }
1691 self->running = 0;
1692 break;
1693 }
1694 if (bzerror != BZ_OK) {
1695 Util_CatchBZ2Error(bzerror);
1696 goto error;
1697 }
Guido van Rossumd8faa362007-04-27 19:54:29 +00001698 if (bzs->avail_in == 0)
1699 break; /* no more input data */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001700 if (bzs->avail_out == 0) {
1701 bufsize = Util_NewBufferSize(bufsize);
Guido van Rossum522a6c62007-05-22 23:13:45 +00001702 if (PyBytes_Resize(ret, bufsize) < 0) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001703 BZ2_bzDecompressEnd(bzs);
1704 goto error;
1705 }
1706 bzs->next_out = BUF(ret);
1707 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs)
1708 - totalout);
1709 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001710 }
1711 }
1712
Guido van Rossum522a6c62007-05-22 23:13:45 +00001713 if (bzs->avail_out != 0) {
1714 if (PyBytes_Resize(ret,
1715 (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout)) < 0)
1716 goto error;
1717 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001718
1719 RELEASE_LOCK(self);
1720 return ret;
1721
1722error:
1723 RELEASE_LOCK(self);
1724 Py_XDECREF(ret);
1725 return NULL;
1726}
1727
1728static PyMethodDef BZ2Decomp_methods[] = {
1729 {"decompress", (PyCFunction)BZ2Decomp_decompress, METH_VARARGS, BZ2Decomp_decompress__doc__},
1730 {NULL, NULL} /* sentinel */
1731};
1732
1733
1734/* ===================================================================== */
1735/* Slot definitions for BZ2Decomp_Type. */
1736
1737static int
1738BZ2Decomp_init(BZ2DecompObject *self, PyObject *args, PyObject *kwargs)
1739{
1740 int bzerror;
1741
1742 if (!PyArg_ParseTuple(args, ":BZ2Decompressor"))
1743 return -1;
1744
1745#ifdef WITH_THREAD
1746 self->lock = PyThread_allocate_lock();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001747 if (!self->lock) {
1748 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001749 goto error;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001750 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001751#endif
1752
Guido van Rossum522a6c62007-05-22 23:13:45 +00001753 self->unused_data = PyBytes_FromStringAndSize("", 0);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001754 if (!self->unused_data)
1755 goto error;
1756
1757 memset(&self->bzs, 0, sizeof(bz_stream));
1758 bzerror = BZ2_bzDecompressInit(&self->bzs, 0, 0);
1759 if (bzerror != BZ_OK) {
1760 Util_CatchBZ2Error(bzerror);
1761 goto error;
1762 }
1763
1764 self->running = 1;
1765
1766 return 0;
1767
1768error:
1769#ifdef WITH_THREAD
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001770 if (self->lock) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001771 PyThread_free_lock(self->lock);
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001772 self->lock = NULL;
1773 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001774#endif
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001775 Py_CLEAR(self->unused_data);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001776 return -1;
1777}
1778
1779static void
1780BZ2Decomp_dealloc(BZ2DecompObject *self)
1781{
1782#ifdef WITH_THREAD
1783 if (self->lock)
1784 PyThread_free_lock(self->lock);
1785#endif
1786 Py_XDECREF(self->unused_data);
1787 BZ2_bzDecompressEnd(&self->bzs);
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00001788 Py_Type(self)->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001789}
1790
1791
1792/* ===================================================================== */
1793/* BZ2Decomp_Type definition. */
1794
1795PyDoc_STRVAR(BZ2Decomp__doc__,
1796"BZ2Decompressor() -> decompressor object\n\
1797\n\
1798Create a new decompressor object. This object may be used to decompress\n\
1799data sequentially. If you want to decompress data in one shot, use the\n\
1800decompress() function instead.\n\
1801");
1802
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001803static PyTypeObject BZ2Decomp_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00001804 PyVarObject_HEAD_INIT(NULL, 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001805 "bz2.BZ2Decompressor", /*tp_name*/
1806 sizeof(BZ2DecompObject), /*tp_basicsize*/
1807 0, /*tp_itemsize*/
1808 (destructor)BZ2Decomp_dealloc, /*tp_dealloc*/
1809 0, /*tp_print*/
1810 0, /*tp_getattr*/
1811 0, /*tp_setattr*/
1812 0, /*tp_compare*/
1813 0, /*tp_repr*/
1814 0, /*tp_as_number*/
1815 0, /*tp_as_sequence*/
1816 0, /*tp_as_mapping*/
1817 0, /*tp_hash*/
1818 0, /*tp_call*/
1819 0, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001820 PyObject_GenericGetAttr,/*tp_getattro*/
1821 PyObject_GenericSetAttr,/*tp_setattro*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001822 0, /*tp_as_buffer*/
1823 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1824 BZ2Decomp__doc__, /*tp_doc*/
1825 0, /*tp_traverse*/
1826 0, /*tp_clear*/
1827 0, /*tp_richcompare*/
1828 0, /*tp_weaklistoffset*/
1829 0, /*tp_iter*/
1830 0, /*tp_iternext*/
1831 BZ2Decomp_methods, /*tp_methods*/
1832 BZ2Decomp_members, /*tp_members*/
1833 0, /*tp_getset*/
1834 0, /*tp_base*/
1835 0, /*tp_dict*/
1836 0, /*tp_descr_get*/
1837 0, /*tp_descr_set*/
1838 0, /*tp_dictoffset*/
1839 (initproc)BZ2Decomp_init, /*tp_init*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001840 PyType_GenericAlloc, /*tp_alloc*/
1841 PyType_GenericNew, /*tp_new*/
Neal Norwitz30d1c512007-08-19 22:48:23 +00001842 PyObject_Free, /*tp_free*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001843 0, /*tp_is_gc*/
1844};
1845
1846
1847/* ===================================================================== */
1848/* Module functions. */
1849
1850PyDoc_STRVAR(bz2_compress__doc__,
1851"compress(data [, compresslevel=9]) -> string\n\
1852\n\
1853Compress data in one shot. If you want to compress data sequentially,\n\
1854use an instance of BZ2Compressor instead. The compresslevel parameter, if\n\
1855given, must be a number between 1 and 9.\n\
1856");
1857
1858static PyObject *
1859bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
1860{
1861 int compresslevel=9;
1862 char *data;
1863 int datasize;
1864 int bufsize;
Gustavo Niemeyer7d7930b2002-11-05 18:41:53 +00001865 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001866 bz_stream _bzs;
1867 bz_stream *bzs = &_bzs;
1868 int bzerror;
Martin v. Löwis15e62742006-02-27 16:46:16 +00001869 static char *kwlist[] = {"data", "compresslevel", 0};
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001870
1871 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|i",
1872 kwlist, &data, &datasize,
1873 &compresslevel))
1874 return NULL;
1875
1876 if (compresslevel < 1 || compresslevel > 9) {
1877 PyErr_SetString(PyExc_ValueError,
1878 "compresslevel must be between 1 and 9");
1879 return NULL;
1880 }
1881
1882 /* Conforming to bz2 manual, this is large enough to fit compressed
1883 * data in one shot. We will check it later anyway. */
1884 bufsize = datasize + (datasize/100+1) + 600;
1885
Guido van Rossum522a6c62007-05-22 23:13:45 +00001886 ret = PyBytes_FromStringAndSize(NULL, bufsize);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001887 if (!ret)
1888 return NULL;
1889
1890 memset(bzs, 0, sizeof(bz_stream));
1891
1892 bzs->next_in = data;
1893 bzs->avail_in = datasize;
1894 bzs->next_out = BUF(ret);
1895 bzs->avail_out = bufsize;
1896
1897 bzerror = BZ2_bzCompressInit(bzs, compresslevel, 0, 0);
1898 if (bzerror != BZ_OK) {
1899 Util_CatchBZ2Error(bzerror);
1900 Py_DECREF(ret);
1901 return NULL;
1902 }
Tim Peterse3228092002-11-09 04:21:44 +00001903
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001904 for (;;) {
1905 Py_BEGIN_ALLOW_THREADS
1906 bzerror = BZ2_bzCompress(bzs, BZ_FINISH);
1907 Py_END_ALLOW_THREADS
1908 if (bzerror == BZ_STREAM_END) {
1909 break;
1910 } else if (bzerror != BZ_FINISH_OK) {
1911 BZ2_bzCompressEnd(bzs);
1912 Util_CatchBZ2Error(bzerror);
1913 Py_DECREF(ret);
1914 return NULL;
1915 }
1916 if (bzs->avail_out == 0) {
1917 bufsize = Util_NewBufferSize(bufsize);
Guido van Rossum522a6c62007-05-22 23:13:45 +00001918 if (PyBytes_Resize(ret, bufsize) < 0) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001919 BZ2_bzCompressEnd(bzs);
1920 Py_DECREF(ret);
1921 return NULL;
1922 }
1923 bzs->next_out = BUF(ret) + BZS_TOTAL_OUT(bzs);
1924 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
1925 }
1926 }
1927
Guido van Rossum522a6c62007-05-22 23:13:45 +00001928 if (bzs->avail_out != 0) {
1929 if (PyBytes_Resize(ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs)) < 0) {
1930 Py_DECREF(ret);
1931 ret = NULL;
1932 }
1933 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001934 BZ2_bzCompressEnd(bzs);
1935
1936 return ret;
1937}
1938
1939PyDoc_STRVAR(bz2_decompress__doc__,
1940"decompress(data) -> decompressed data\n\
1941\n\
1942Decompress data in one shot. If you want to decompress data sequentially,\n\
1943use an instance of BZ2Decompressor instead.\n\
1944");
1945
1946static PyObject *
1947bz2_decompress(PyObject *self, PyObject *args)
1948{
1949 char *data;
1950 int datasize;
1951 int bufsize = SMALLCHUNK;
1952 PyObject *ret;
1953 bz_stream _bzs;
1954 bz_stream *bzs = &_bzs;
1955 int bzerror;
1956
Walter Dörwaldbb9c7392004-11-01 17:10:19 +00001957 if (!PyArg_ParseTuple(args, "s#:decompress", &data, &datasize))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001958 return NULL;
1959
1960 if (datasize == 0)
Guido van Rossum522a6c62007-05-22 23:13:45 +00001961 return PyBytes_FromStringAndSize("", 0);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001962
Guido van Rossum522a6c62007-05-22 23:13:45 +00001963 ret = PyBytes_FromStringAndSize(NULL, bufsize);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001964 if (!ret)
1965 return NULL;
1966
1967 memset(bzs, 0, sizeof(bz_stream));
1968
1969 bzs->next_in = data;
1970 bzs->avail_in = datasize;
1971 bzs->next_out = BUF(ret);
1972 bzs->avail_out = bufsize;
1973
1974 bzerror = BZ2_bzDecompressInit(bzs, 0, 0);
1975 if (bzerror != BZ_OK) {
1976 Util_CatchBZ2Error(bzerror);
1977 Py_DECREF(ret);
1978 return NULL;
1979 }
Tim Peterse3228092002-11-09 04:21:44 +00001980
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001981 for (;;) {
1982 Py_BEGIN_ALLOW_THREADS
1983 bzerror = BZ2_bzDecompress(bzs);
1984 Py_END_ALLOW_THREADS
1985 if (bzerror == BZ_STREAM_END) {
1986 break;
1987 } else if (bzerror != BZ_OK) {
1988 BZ2_bzDecompressEnd(bzs);
1989 Util_CatchBZ2Error(bzerror);
1990 Py_DECREF(ret);
1991 return NULL;
1992 }
Guido van Rossumd8faa362007-04-27 19:54:29 +00001993 if (bzs->avail_in == 0) {
1994 BZ2_bzDecompressEnd(bzs);
1995 PyErr_SetString(PyExc_ValueError,
1996 "couldn't find end of stream");
1997 Py_DECREF(ret);
1998 return NULL;
1999 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002000 if (bzs->avail_out == 0) {
2001 bufsize = Util_NewBufferSize(bufsize);
Guido van Rossum522a6c62007-05-22 23:13:45 +00002002 if (PyBytes_Resize(ret, bufsize) < 0) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002003 BZ2_bzDecompressEnd(bzs);
2004 Py_DECREF(ret);
2005 return NULL;
2006 }
2007 bzs->next_out = BUF(ret) + BZS_TOTAL_OUT(bzs);
2008 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002009 }
2010 }
2011
Guido van Rossum522a6c62007-05-22 23:13:45 +00002012 if (bzs->avail_out != 0) {
2013 if (PyBytes_Resize(ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs)) < 0) {
2014 Py_DECREF(ret);
2015 ret = NULL;
2016 }
2017 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002018 BZ2_bzDecompressEnd(bzs);
2019
2020 return ret;
2021}
2022
2023static PyMethodDef bz2_methods[] = {
2024 {"compress", (PyCFunction) bz2_compress, METH_VARARGS|METH_KEYWORDS,
2025 bz2_compress__doc__},
2026 {"decompress", (PyCFunction) bz2_decompress, METH_VARARGS,
2027 bz2_decompress__doc__},
2028 {NULL, NULL} /* sentinel */
2029};
2030
2031/* ===================================================================== */
2032/* Initialization function. */
2033
2034PyDoc_STRVAR(bz2__doc__,
2035"The python bz2 module provides a comprehensive interface for\n\
2036the bz2 compression library. It implements a complete file\n\
2037interface, one shot (de)compression functions, and types for\n\
2038sequential (de)compression.\n\
2039");
2040
Neal Norwitz21d896c2003-07-01 20:15:21 +00002041PyMODINIT_FUNC
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002042initbz2(void)
2043{
2044 PyObject *m;
2045
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00002046 Py_Type(&BZ2File_Type) = &PyType_Type;
2047 Py_Type(&BZ2Comp_Type) = &PyType_Type;
2048 Py_Type(&BZ2Decomp_Type) = &PyType_Type;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002049
2050 m = Py_InitModule3("bz2", bz2_methods, bz2__doc__);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00002051 if (m == NULL)
2052 return;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002053
Neal Norwitz53cbdaa2007-08-23 21:42:55 +00002054 PyModule_AddObject(m, "__author__", PyUnicode_FromString(__author__));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002055
2056 Py_INCREF(&BZ2File_Type);
2057 PyModule_AddObject(m, "BZ2File", (PyObject *)&BZ2File_Type);
2058
2059 Py_INCREF(&BZ2Comp_Type);
2060 PyModule_AddObject(m, "BZ2Compressor", (PyObject *)&BZ2Comp_Type);
2061
2062 Py_INCREF(&BZ2Decomp_Type);
2063 PyModule_AddObject(m, "BZ2Decompressor", (PyObject *)&BZ2Decomp_Type);
2064}