blob: 43c287bcbb3209753fe54d9aa5911461df622b11 [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;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000232
233 total_v_size = n > 0 ? n : 100;
Guido van Rossum522a6c62007-05-22 23:13:45 +0000234 v = PyBytes_FromStringAndSize((char *)NULL, total_v_size);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000235 if (v == NULL)
236 return NULL;
237
238 buf = BUF(v);
239 end = buf + total_v_size;
240
241 for (;;) {
242 Py_BEGIN_ALLOW_THREADS
Guido van Rossumf09ca142007-06-13 00:03:05 +0000243 do {
244 BZ2_bzRead(&bzerror, f->fp, &c, 1);
245 f->pos++;
246 *buf++ = c;
247 } while (bzerror == BZ_OK && c != '\n' && buf != end);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000248 Py_END_ALLOW_THREADS
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000249 if (bzerror == BZ_STREAM_END) {
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000250 f->size = f->pos;
251 f->mode = MODE_READ_EOF;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000252 break;
253 } else if (bzerror != BZ_OK) {
254 Util_CatchBZ2Error(bzerror);
255 Py_DECREF(v);
256 return NULL;
257 }
258 if (c == '\n')
259 break;
260 /* Must be because buf == end */
261 if (n > 0)
262 break;
263 used_v_size = total_v_size;
264 increment = total_v_size >> 2; /* mild exponential growth */
265 total_v_size += increment;
266 if (total_v_size > INT_MAX) {
267 PyErr_SetString(PyExc_OverflowError,
268 "line is longer than a Python string can hold");
269 Py_DECREF(v);
270 return NULL;
271 }
Guido van Rossum522a6c62007-05-22 23:13:45 +0000272 if (PyBytes_Resize(v, total_v_size) < 0) {
273 Py_DECREF(v);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000274 return NULL;
Guido van Rossum522a6c62007-05-22 23:13:45 +0000275 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000276 buf = BUF(v) + used_v_size;
277 end = BUF(v) + total_v_size;
278 }
279
280 used_v_size = buf - BUF(v);
Guido van Rossum522a6c62007-05-22 23:13:45 +0000281 if (used_v_size != total_v_size) {
282 if (PyBytes_Resize(v, used_v_size) < 0) {
283 Py_DECREF(v);
284 v = NULL;
285 }
286 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000287 return v;
288}
289
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000290/* This is a hacked version of Python's fileobject.c:drop_readahead(). */
291static void
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000292Util_DropReadAhead(BZ2FileObject *f)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000293{
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000294 if (f->f_buf != NULL) {
295 PyMem_Free(f->f_buf);
296 f->f_buf = NULL;
297 }
298}
299
300/* This is a hacked version of Python's fileobject.c:readahead(). */
301static int
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000302Util_ReadAhead(BZ2FileObject *f, int bufsize)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000303{
304 int chunksize;
305 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000306
307 if (f->f_buf != NULL) {
Tim Peterse3228092002-11-09 04:21:44 +0000308 if((f->f_bufend - f->f_bufptr) >= 1)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000309 return 0;
310 else
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000311 Util_DropReadAhead(f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000312 }
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000313 if (f->mode == MODE_READ_EOF) {
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000314 f->f_bufptr = f->f_buf;
315 f->f_bufend = f->f_buf;
316 return 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000317 }
318 if ((f->f_buf = PyMem_Malloc(bufsize)) == NULL) {
319 return -1;
320 }
321 Py_BEGIN_ALLOW_THREADS
Guido van Rossumf09ca142007-06-13 00:03:05 +0000322 chunksize = BZ2_bzRead(&bzerror, f->fp, f->f_buf, bufsize);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000323 Py_END_ALLOW_THREADS
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000324 f->pos += chunksize;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000325 if (bzerror == BZ_STREAM_END) {
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000326 f->size = f->pos;
327 f->mode = MODE_READ_EOF;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000328 } else if (bzerror != BZ_OK) {
329 Util_CatchBZ2Error(bzerror);
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000330 Util_DropReadAhead(f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000331 return -1;
332 }
333 f->f_bufptr = f->f_buf;
334 f->f_bufend = f->f_buf + chunksize;
335 return 0;
336}
337
338/* This is a hacked version of Python's
339 * fileobject.c:readahead_get_line_skip(). */
Guido van Rossum522a6c62007-05-22 23:13:45 +0000340static PyBytesObject *
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000341Util_ReadAheadGetLineSkip(BZ2FileObject *f, int skip, int bufsize)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000342{
Guido van Rossum522a6c62007-05-22 23:13:45 +0000343 PyBytesObject* s;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000344 char *bufptr;
345 char *buf;
346 int len;
347
348 if (f->f_buf == NULL)
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000349 if (Util_ReadAhead(f, bufsize) < 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000350 return NULL;
351
352 len = f->f_bufend - f->f_bufptr;
Tim Peterse3228092002-11-09 04:21:44 +0000353 if (len == 0)
Guido van Rossum522a6c62007-05-22 23:13:45 +0000354 return (PyBytesObject *)
355 PyBytes_FromStringAndSize(NULL, skip);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000356 bufptr = memchr(f->f_bufptr, '\n', len);
357 if (bufptr != NULL) {
358 bufptr++; /* Count the '\n' */
359 len = bufptr - f->f_bufptr;
Guido van Rossum522a6c62007-05-22 23:13:45 +0000360 s = (PyBytesObject *)
361 PyBytes_FromStringAndSize(NULL, skip+len);
Tim Peterse3228092002-11-09 04:21:44 +0000362 if (s == NULL)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000363 return NULL;
Guido van Rossum522a6c62007-05-22 23:13:45 +0000364 memcpy(PyBytes_AS_STRING(s)+skip, f->f_bufptr, len);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000365 f->f_bufptr = bufptr;
366 if (bufptr == f->f_bufend)
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000367 Util_DropReadAhead(f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000368 } else {
369 bufptr = f->f_bufptr;
370 buf = f->f_buf;
371 f->f_buf = NULL; /* Force new readahead buffer */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000372 s = Util_ReadAheadGetLineSkip(f, skip+len,
373 bufsize + (bufsize>>2));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000374 if (s == NULL) {
375 PyMem_Free(buf);
376 return NULL;
377 }
Guido van Rossum522a6c62007-05-22 23:13:45 +0000378 memcpy(PyBytes_AS_STRING(s)+skip, bufptr, len);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000379 PyMem_Free(buf);
380 }
381 return s;
382}
383
384/* ===================================================================== */
385/* Methods of BZ2File. */
386
387PyDoc_STRVAR(BZ2File_read__doc__,
388"read([size]) -> string\n\
389\n\
390Read at most size uncompressed bytes, returned as a string. If the size\n\
391argument is negative or omitted, read until EOF is reached.\n\
392");
393
394/* This is a hacked version of Python's fileobject.c:file_read(). */
395static PyObject *
396BZ2File_read(BZ2FileObject *self, PyObject *args)
397{
398 long bytesrequested = -1;
399 size_t bytesread, buffersize, chunksize;
400 int bzerror;
401 PyObject *ret = NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000402
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000403 if (!PyArg_ParseTuple(args, "|l:read", &bytesrequested))
404 return NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000405
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000406 ACQUIRE_LOCK(self);
407 switch (self->mode) {
408 case MODE_READ:
409 break;
410 case MODE_READ_EOF:
Guido van Rossum522a6c62007-05-22 23:13:45 +0000411 ret = PyBytes_FromStringAndSize("", 0);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000412 goto cleanup;
413 case MODE_CLOSED:
414 PyErr_SetString(PyExc_ValueError,
415 "I/O operation on closed file");
416 goto cleanup;
417 default:
418 PyErr_SetString(PyExc_IOError,
419 "file is not ready for reading");
420 goto cleanup;
421 }
422
423 if (bytesrequested < 0)
424 buffersize = Util_NewBufferSize((size_t)0);
425 else
426 buffersize = bytesrequested;
427 if (buffersize > INT_MAX) {
428 PyErr_SetString(PyExc_OverflowError,
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +0000429 "requested number of bytes is "
430 "more than a Python string can hold");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000431 goto cleanup;
432 }
Guido van Rossum522a6c62007-05-22 23:13:45 +0000433 ret = PyBytes_FromStringAndSize((char *)NULL, buffersize);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000434 if (ret == NULL)
435 goto cleanup;
436 bytesread = 0;
437
438 for (;;) {
439 Py_BEGIN_ALLOW_THREADS
Guido van Rossumf09ca142007-06-13 00:03:05 +0000440 chunksize = BZ2_bzRead(&bzerror, self->fp,
441 BUF(ret)+bytesread,
442 buffersize-bytesread);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000443 self->pos += chunksize;
444 Py_END_ALLOW_THREADS
445 bytesread += chunksize;
446 if (bzerror == BZ_STREAM_END) {
447 self->size = self->pos;
448 self->mode = MODE_READ_EOF;
449 break;
450 } else if (bzerror != BZ_OK) {
451 Util_CatchBZ2Error(bzerror);
452 Py_DECREF(ret);
453 ret = NULL;
454 goto cleanup;
455 }
456 if (bytesrequested < 0) {
457 buffersize = Util_NewBufferSize(buffersize);
Guido van Rossum522a6c62007-05-22 23:13:45 +0000458 if (PyBytes_Resize(ret, buffersize) < 0) {
459 Py_DECREF(ret);
460 ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000461 goto cleanup;
Guido van Rossum522a6c62007-05-22 23:13:45 +0000462 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000463 } else {
464 break;
465 }
466 }
Guido van Rossum522a6c62007-05-22 23:13:45 +0000467 if (bytesread != buffersize) {
468 if (PyBytes_Resize(ret, bytesread) < 0) {
469 Py_DECREF(ret);
470 ret = NULL;
471 }
472 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000473
474cleanup:
475 RELEASE_LOCK(self);
476 return ret;
477}
478
479PyDoc_STRVAR(BZ2File_readline__doc__,
480"readline([size]) -> string\n\
481\n\
482Return the next line from the file, as a string, retaining newline.\n\
483A non-negative size argument will limit the maximum number of bytes to\n\
484return (an incomplete line may be returned then). Return an empty\n\
485string at EOF.\n\
486");
487
488static PyObject *
489BZ2File_readline(BZ2FileObject *self, PyObject *args)
490{
491 PyObject *ret = NULL;
492 int sizehint = -1;
493
494 if (!PyArg_ParseTuple(args, "|i:readline", &sizehint))
495 return NULL;
496
497 ACQUIRE_LOCK(self);
498 switch (self->mode) {
499 case MODE_READ:
500 break;
501 case MODE_READ_EOF:
Guido van Rossum522a6c62007-05-22 23:13:45 +0000502 ret = PyBytes_FromStringAndSize("", 0);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000503 goto cleanup;
504 case MODE_CLOSED:
505 PyErr_SetString(PyExc_ValueError,
506 "I/O operation on closed file");
507 goto cleanup;
508 default:
509 PyErr_SetString(PyExc_IOError,
510 "file is not ready for reading");
511 goto cleanup;
512 }
513
514 if (sizehint == 0)
Guido van Rossum522a6c62007-05-22 23:13:45 +0000515 ret = PyBytes_FromStringAndSize("", 0);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000516 else
517 ret = Util_GetLine(self, (sizehint < 0) ? 0 : sizehint);
518
519cleanup:
520 RELEASE_LOCK(self);
521 return ret;
522}
523
524PyDoc_STRVAR(BZ2File_readlines__doc__,
525"readlines([size]) -> list\n\
526\n\
527Call readline() repeatedly and return a list of lines read.\n\
528The optional size argument, if given, is an approximate bound on the\n\
529total number of bytes in the lines returned.\n\
530");
531
532/* This is a hacked version of Python's fileobject.c:file_readlines(). */
533static PyObject *
534BZ2File_readlines(BZ2FileObject *self, PyObject *args)
535{
536 long sizehint = 0;
537 PyObject *list = NULL;
538 PyObject *line;
539 char small_buffer[SMALLCHUNK];
540 char *buffer = small_buffer;
541 size_t buffersize = SMALLCHUNK;
542 PyObject *big_buffer = NULL;
543 size_t nfilled = 0;
544 size_t nread;
545 size_t totalread = 0;
546 char *p, *q, *end;
547 int err;
548 int shortread = 0;
549 int bzerror;
550
551 if (!PyArg_ParseTuple(args, "|l:readlines", &sizehint))
552 return NULL;
553
554 ACQUIRE_LOCK(self);
555 switch (self->mode) {
556 case MODE_READ:
557 break;
558 case MODE_READ_EOF:
559 list = PyList_New(0);
560 goto cleanup;
561 case MODE_CLOSED:
562 PyErr_SetString(PyExc_ValueError,
563 "I/O operation on closed file");
564 goto cleanup;
565 default:
566 PyErr_SetString(PyExc_IOError,
567 "file is not ready for reading");
568 goto cleanup;
569 }
570
571 if ((list = PyList_New(0)) == NULL)
572 goto cleanup;
573
574 for (;;) {
575 Py_BEGIN_ALLOW_THREADS
Guido van Rossumf09ca142007-06-13 00:03:05 +0000576 nread = BZ2_bzRead(&bzerror, self->fp,
577 buffer+nfilled, buffersize-nfilled);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000578 self->pos += nread;
579 Py_END_ALLOW_THREADS
580 if (bzerror == BZ_STREAM_END) {
581 self->size = self->pos;
582 self->mode = MODE_READ_EOF;
583 if (nread == 0) {
584 sizehint = 0;
585 break;
586 }
587 shortread = 1;
588 } else if (bzerror != BZ_OK) {
589 Util_CatchBZ2Error(bzerror);
590 error:
591 Py_DECREF(list);
592 list = NULL;
593 goto cleanup;
594 }
595 totalread += nread;
596 p = memchr(buffer+nfilled, '\n', nread);
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000597 if (!shortread && p == NULL) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000598 /* Need a larger buffer to fit this line */
599 nfilled += nread;
600 buffersize *= 2;
601 if (buffersize > INT_MAX) {
602 PyErr_SetString(PyExc_OverflowError,
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000603 "line is longer than a Python string can hold");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000604 goto error;
605 }
606 if (big_buffer == NULL) {
607 /* Create the big buffer */
Guido van Rossum522a6c62007-05-22 23:13:45 +0000608 big_buffer = PyBytes_FromStringAndSize(
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000609 NULL, buffersize);
610 if (big_buffer == NULL)
611 goto error;
Guido van Rossum522a6c62007-05-22 23:13:45 +0000612 buffer = PyBytes_AS_STRING(big_buffer);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000613 memcpy(buffer, small_buffer, nfilled);
614 }
615 else {
616 /* Grow the big buffer */
Guido van Rossum522a6c62007-05-22 23:13:45 +0000617 if (PyBytes_Resize(big_buffer, buffersize) < 0){
618 Py_DECREF(big_buffer);
619 big_buffer = NULL;
620 goto error;
621 }
622 buffer = PyBytes_AS_STRING(big_buffer);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000623 }
Guido van Rossum522a6c62007-05-22 23:13:45 +0000624 continue;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000625 }
626 end = buffer+nfilled+nread;
627 q = buffer;
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000628 while (p != NULL) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000629 /* Process complete lines */
630 p++;
Guido van Rossum522a6c62007-05-22 23:13:45 +0000631 line = PyBytes_FromStringAndSize(q, p-q);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000632 if (line == NULL)
633 goto error;
634 err = PyList_Append(list, line);
635 Py_DECREF(line);
636 if (err != 0)
637 goto error;
638 q = p;
639 p = memchr(q, '\n', end-q);
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000640 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000641 /* Move the remaining incomplete line to the start */
642 nfilled = end-q;
643 memmove(buffer, q, nfilled);
644 if (sizehint > 0)
645 if (totalread >= (size_t)sizehint)
646 break;
647 if (shortread) {
648 sizehint = 0;
649 break;
650 }
651 }
652 if (nfilled != 0) {
653 /* Partial last line */
Guido van Rossum522a6c62007-05-22 23:13:45 +0000654 line = PyBytes_FromStringAndSize(buffer, nfilled);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000655 if (line == NULL)
656 goto error;
657 if (sizehint > 0) {
658 /* Need to complete the last line */
659 PyObject *rest = Util_GetLine(self, 0);
Guido van Rossum522a6c62007-05-22 23:13:45 +0000660 PyObject *new;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000661 if (rest == NULL) {
662 Py_DECREF(line);
663 goto error;
664 }
Guido van Rossum522a6c62007-05-22 23:13:45 +0000665 new = PyBytes_Concat(line, rest);
666 Py_DECREF(line);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000667 Py_DECREF(rest);
Guido van Rossum522a6c62007-05-22 23:13:45 +0000668 line = new;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000669 if (line == NULL)
670 goto error;
671 }
672 err = PyList_Append(list, line);
673 Py_DECREF(line);
674 if (err != 0)
675 goto error;
676 }
677
678 cleanup:
679 RELEASE_LOCK(self);
680 if (big_buffer) {
681 Py_DECREF(big_buffer);
682 }
683 return list;
684}
685
686PyDoc_STRVAR(BZ2File_write__doc__,
687"write(data) -> None\n\
688\n\
689Write the 'data' string to file. Note that due to buffering, close() may\n\
690be needed before the file on disk reflects the data written.\n\
691");
692
693/* This is a hacked version of Python's fileobject.c:file_write(). */
694static PyObject *
695BZ2File_write(BZ2FileObject *self, PyObject *args)
696{
697 PyObject *ret = NULL;
698 char *buf;
699 int len;
700 int bzerror;
701
Walter Dörwaldbb9c7392004-11-01 17:10:19 +0000702 if (!PyArg_ParseTuple(args, "s#:write", &buf, &len))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000703 return NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000704
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000705 ACQUIRE_LOCK(self);
706 switch (self->mode) {
707 case MODE_WRITE:
708 break;
Tim Peterse3228092002-11-09 04:21:44 +0000709
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000710 case MODE_CLOSED:
711 PyErr_SetString(PyExc_ValueError,
712 "I/O operation on closed file");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000713 goto cleanup;
Tim Peterse3228092002-11-09 04:21:44 +0000714
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000715 default:
716 PyErr_SetString(PyExc_IOError,
717 "file is not ready for writing");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000718 goto cleanup;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000719 }
720
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000721 Py_BEGIN_ALLOW_THREADS
722 BZ2_bzWrite (&bzerror, self->fp, buf, len);
723 self->pos += len;
724 Py_END_ALLOW_THREADS
Tim Peterse3228092002-11-09 04:21:44 +0000725
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000726 if (bzerror != BZ_OK) {
727 Util_CatchBZ2Error(bzerror);
728 goto cleanup;
729 }
Tim Peterse3228092002-11-09 04:21:44 +0000730
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000731 Py_INCREF(Py_None);
732 ret = Py_None;
733
734cleanup:
735 RELEASE_LOCK(self);
736 return ret;
737}
738
739PyDoc_STRVAR(BZ2File_writelines__doc__,
740"writelines(sequence_of_strings) -> None\n\
741\n\
742Write the sequence of strings to the file. Note that newlines are not\n\
743added. The sequence can be any iterable object producing strings. This is\n\
744equivalent to calling write() for each string.\n\
745");
746
747/* This is a hacked version of Python's fileobject.c:file_writelines(). */
748static PyObject *
749BZ2File_writelines(BZ2FileObject *self, PyObject *seq)
750{
751#define CHUNKSIZE 1000
752 PyObject *list = NULL;
753 PyObject *iter = NULL;
754 PyObject *ret = NULL;
755 PyObject *line;
756 int i, j, index, len, islist;
757 int bzerror;
758
759 ACQUIRE_LOCK(self);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000760 switch (self->mode) {
761 case MODE_WRITE:
762 break;
763
764 case MODE_CLOSED:
765 PyErr_SetString(PyExc_ValueError,
766 "I/O operation on closed file");
767 goto error;
768
769 default:
770 PyErr_SetString(PyExc_IOError,
771 "file is not ready for writing");
772 goto error;
773 }
774
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000775 islist = PyList_Check(seq);
776 if (!islist) {
777 iter = PyObject_GetIter(seq);
778 if (iter == NULL) {
779 PyErr_SetString(PyExc_TypeError,
780 "writelines() requires an iterable argument");
781 goto error;
782 }
783 list = PyList_New(CHUNKSIZE);
784 if (list == NULL)
785 goto error;
786 }
787
788 /* Strategy: slurp CHUNKSIZE lines into a private list,
789 checking that they are all strings, then write that list
790 without holding the interpreter lock, then come back for more. */
791 for (index = 0; ; index += CHUNKSIZE) {
792 if (islist) {
793 Py_XDECREF(list);
794 list = PyList_GetSlice(seq, index, index+CHUNKSIZE);
795 if (list == NULL)
796 goto error;
797 j = PyList_GET_SIZE(list);
798 }
799 else {
800 for (j = 0; j < CHUNKSIZE; j++) {
801 line = PyIter_Next(iter);
802 if (line == NULL) {
803 if (PyErr_Occurred())
804 goto error;
805 break;
806 }
807 PyList_SetItem(list, j, line);
808 }
809 }
810 if (j == 0)
811 break;
812
Guido van Rossum522a6c62007-05-22 23:13:45 +0000813 /* Check that all entries are indeed byte strings. If not,
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000814 apply the same rules as for file.write() and
815 convert the rets to strings. This is slow, but
816 seems to be the only way since all conversion APIs
817 could potentially execute Python code. */
818 for (i = 0; i < j; i++) {
819 PyObject *v = PyList_GET_ITEM(list, i);
Guido van Rossum522a6c62007-05-22 23:13:45 +0000820 if (!PyBytes_Check(v)) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000821 const char *buffer;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000822 Py_ssize_t len;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000823 if (PyObject_AsCharBuffer(v, &buffer, &len)) {
824 PyErr_SetString(PyExc_TypeError,
825 "writelines() "
826 "argument must be "
827 "a sequence of "
Guido van Rossum522a6c62007-05-22 23:13:45 +0000828 "bytes objects");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000829 goto error;
830 }
Guido van Rossum522a6c62007-05-22 23:13:45 +0000831 line = PyBytes_FromStringAndSize(buffer,
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000832 len);
833 if (line == NULL)
834 goto error;
835 Py_DECREF(v);
836 PyList_SET_ITEM(list, i, line);
837 }
838 }
839
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000840 /* Since we are releasing the global lock, the
841 following code may *not* execute Python code. */
842 Py_BEGIN_ALLOW_THREADS
843 for (i = 0; i < j; i++) {
844 line = PyList_GET_ITEM(list, i);
Guido van Rossum522a6c62007-05-22 23:13:45 +0000845 len = PyBytes_GET_SIZE(line);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000846 BZ2_bzWrite (&bzerror, self->fp,
Guido van Rossum522a6c62007-05-22 23:13:45 +0000847 PyBytes_AS_STRING(line), len);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000848 if (bzerror != BZ_OK) {
849 Py_BLOCK_THREADS
850 Util_CatchBZ2Error(bzerror);
851 goto error;
852 }
853 }
854 Py_END_ALLOW_THREADS
855
856 if (j < CHUNKSIZE)
857 break;
858 }
859
860 Py_INCREF(Py_None);
861 ret = Py_None;
862
863 error:
864 RELEASE_LOCK(self);
865 Py_XDECREF(list);
866 Py_XDECREF(iter);
867 return ret;
868#undef CHUNKSIZE
869}
870
871PyDoc_STRVAR(BZ2File_seek__doc__,
872"seek(offset [, whence]) -> None\n\
873\n\
874Move to new file position. Argument offset is a byte count. Optional\n\
875argument whence defaults to 0 (offset from start of file, offset\n\
876should be >= 0); other values are 1 (move relative to current position,\n\
877positive or negative), and 2 (move relative to end of file, usually\n\
878negative, although many platforms allow seeking beyond the end of a file).\n\
879\n\
880Note that seeking of bz2 files is emulated, and depending on the parameters\n\
881the operation may be extremely slow.\n\
882");
883
884static PyObject *
885BZ2File_seek(BZ2FileObject *self, PyObject *args)
886{
887 int where = 0;
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000888 PyObject *offobj;
889 Py_off_t offset;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000890 char small_buffer[SMALLCHUNK];
891 char *buffer = small_buffer;
892 size_t buffersize = SMALLCHUNK;
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000893 Py_off_t bytesread = 0;
Georg Brandla8bcecc2005-09-03 07:49:53 +0000894 size_t readsize;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000895 int chunksize;
896 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000897 PyObject *ret = NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000898
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000899 if (!PyArg_ParseTuple(args, "O|i:seek", &offobj, &where))
900 return NULL;
901#if !defined(HAVE_LARGEFILE_SUPPORT)
902 offset = PyInt_AsLong(offobj);
903#else
904 offset = PyLong_Check(offobj) ?
905 PyLong_AsLongLong(offobj) : PyInt_AsLong(offobj);
906#endif
907 if (PyErr_Occurred())
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000908 return NULL;
909
910 ACQUIRE_LOCK(self);
911 Util_DropReadAhead(self);
912 switch (self->mode) {
913 case MODE_READ:
914 case MODE_READ_EOF:
915 break;
Tim Peterse3228092002-11-09 04:21:44 +0000916
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000917 case MODE_CLOSED:
918 PyErr_SetString(PyExc_ValueError,
919 "I/O operation on closed file");
Thomas Wouters89f507f2006-12-13 04:49:30 +0000920 goto cleanup;
Tim Peterse3228092002-11-09 04:21:44 +0000921
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000922 default:
923 PyErr_SetString(PyExc_IOError,
924 "seek works only while reading");
Thomas Wouters89f507f2006-12-13 04:49:30 +0000925 goto cleanup;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000926 }
927
Georg Brandl47fab922006-02-18 21:57:25 +0000928 if (where == 2) {
929 if (self->size == -1) {
930 assert(self->mode != MODE_READ_EOF);
931 for (;;) {
932 Py_BEGIN_ALLOW_THREADS
Guido van Rossumf09ca142007-06-13 00:03:05 +0000933 chunksize = BZ2_bzRead(&bzerror, self->fp,
934 buffer, buffersize);
Georg Brandl47fab922006-02-18 21:57:25 +0000935 self->pos += chunksize;
936 Py_END_ALLOW_THREADS
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000937
Georg Brandl47fab922006-02-18 21:57:25 +0000938 bytesread += chunksize;
939 if (bzerror == BZ_STREAM_END) {
940 break;
941 } else if (bzerror != BZ_OK) {
942 Util_CatchBZ2Error(bzerror);
943 goto cleanup;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000944 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000945 }
Georg Brandl47fab922006-02-18 21:57:25 +0000946 self->mode = MODE_READ_EOF;
947 self->size = self->pos;
948 bytesread = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000949 }
Georg Brandl47fab922006-02-18 21:57:25 +0000950 offset = self->size + offset;
951 } else if (where == 1) {
952 offset = self->pos + offset;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000953 }
954
Guido van Rossum522a6c62007-05-22 23:13:45 +0000955 /* Before getting here, offset must be the absolute position the file
Georg Brandl47fab922006-02-18 21:57:25 +0000956 * pointer should be set to. */
957
958 if (offset >= self->pos) {
959 /* we can move forward */
960 offset -= self->pos;
961 } else {
962 /* we cannot move back, so rewind the stream */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000963 BZ2_bzReadClose(&bzerror, self->fp);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000964 if (bzerror != BZ_OK) {
965 Util_CatchBZ2Error(bzerror);
966 goto cleanup;
967 }
Guido van Rossumf09ca142007-06-13 00:03:05 +0000968 rewind(self->rawfp);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000969 self->pos = 0;
Guido van Rossumf09ca142007-06-13 00:03:05 +0000970 self->fp = BZ2_bzReadOpen(&bzerror, self->rawfp,
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000971 0, 0, NULL, 0);
972 if (bzerror != BZ_OK) {
973 Util_CatchBZ2Error(bzerror);
974 goto cleanup;
975 }
976 self->mode = MODE_READ;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000977 }
978
Georg Brandl47fab922006-02-18 21:57:25 +0000979 if (offset <= 0 || self->mode == MODE_READ_EOF)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000980 goto exit;
981
982 /* Before getting here, offset must be set to the number of bytes
983 * to walk forward. */
984 for (;;) {
Georg Brandla8bcecc2005-09-03 07:49:53 +0000985 if (offset-bytesread > buffersize)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000986 readsize = buffersize;
987 else
Georg Brandla8bcecc2005-09-03 07:49:53 +0000988 /* offset might be wider that readsize, but the result
989 * of the subtraction is bound by buffersize (see the
990 * condition above). buffersize is 8192. */
991 readsize = (size_t)(offset-bytesread);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000992 Py_BEGIN_ALLOW_THREADS
Guido van Rossumf09ca142007-06-13 00:03:05 +0000993 chunksize = BZ2_bzRead(&bzerror, self->fp, buffer, readsize);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000994 self->pos += chunksize;
995 Py_END_ALLOW_THREADS
996 bytesread += chunksize;
997 if (bzerror == BZ_STREAM_END) {
998 self->size = self->pos;
999 self->mode = MODE_READ_EOF;
1000 break;
1001 } else if (bzerror != BZ_OK) {
1002 Util_CatchBZ2Error(bzerror);
1003 goto cleanup;
1004 }
1005 if (bytesread == offset)
1006 break;
1007 }
1008
1009exit:
1010 Py_INCREF(Py_None);
1011 ret = Py_None;
1012
1013cleanup:
1014 RELEASE_LOCK(self);
1015 return ret;
1016}
1017
1018PyDoc_STRVAR(BZ2File_tell__doc__,
1019"tell() -> int\n\
1020\n\
1021Return the current file position, an integer (may be a long integer).\n\
1022");
1023
1024static PyObject *
1025BZ2File_tell(BZ2FileObject *self, PyObject *args)
1026{
1027 PyObject *ret = NULL;
1028
1029 if (self->mode == MODE_CLOSED) {
1030 PyErr_SetString(PyExc_ValueError,
1031 "I/O operation on closed file");
1032 goto cleanup;
1033 }
1034
Georg Brandla8bcecc2005-09-03 07:49:53 +00001035#if !defined(HAVE_LARGEFILE_SUPPORT)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001036 ret = PyInt_FromLong(self->pos);
Georg Brandla8bcecc2005-09-03 07:49:53 +00001037#else
1038 ret = PyLong_FromLongLong(self->pos);
1039#endif
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001040
1041cleanup:
1042 return ret;
1043}
1044
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001045PyDoc_STRVAR(BZ2File_close__doc__,
1046"close() -> None or (perhaps) an integer\n\
1047\n\
1048Close the file. Sets data attribute .closed to true. A closed file\n\
1049cannot be used for further I/O operations. close() may be called more\n\
1050than once without error.\n\
1051");
1052
1053static PyObject *
1054BZ2File_close(BZ2FileObject *self)
1055{
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001056 PyObject *ret = NULL;
1057 int bzerror = BZ_OK;
1058
Guido van Rossumf09ca142007-06-13 00:03:05 +00001059 if (self->mode == MODE_CLOSED) {
1060 Py_RETURN_NONE;
1061 }
1062
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001063 ACQUIRE_LOCK(self);
1064 switch (self->mode) {
1065 case MODE_READ:
1066 case MODE_READ_EOF:
1067 BZ2_bzReadClose(&bzerror, self->fp);
1068 break;
1069 case MODE_WRITE:
1070 BZ2_bzWriteClose(&bzerror, self->fp,
1071 0, NULL, NULL);
1072 break;
1073 }
1074 self->mode = MODE_CLOSED;
Guido van Rossumf09ca142007-06-13 00:03:05 +00001075 fclose(self->rawfp);
1076 self->rawfp = NULL;
1077 if (bzerror == BZ_OK) {
1078 Py_INCREF(Py_None);
1079 ret = Py_None;
1080 }
1081 else {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001082 Util_CatchBZ2Error(bzerror);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001083 }
1084
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001085 RELEASE_LOCK(self);
1086 return ret;
1087}
1088
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001089static PyObject *BZ2File_getiter(BZ2FileObject *self);
1090
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001091static PyMethodDef BZ2File_methods[] = {
1092 {"read", (PyCFunction)BZ2File_read, METH_VARARGS, BZ2File_read__doc__},
1093 {"readline", (PyCFunction)BZ2File_readline, METH_VARARGS, BZ2File_readline__doc__},
1094 {"readlines", (PyCFunction)BZ2File_readlines, METH_VARARGS, BZ2File_readlines__doc__},
1095 {"write", (PyCFunction)BZ2File_write, METH_VARARGS, BZ2File_write__doc__},
1096 {"writelines", (PyCFunction)BZ2File_writelines, METH_O, BZ2File_writelines__doc__},
1097 {"seek", (PyCFunction)BZ2File_seek, METH_VARARGS, BZ2File_seek__doc__},
1098 {"tell", (PyCFunction)BZ2File_tell, METH_NOARGS, BZ2File_tell__doc__},
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001099 {"close", (PyCFunction)BZ2File_close, METH_NOARGS, BZ2File_close__doc__},
1100 {NULL, NULL} /* sentinel */
1101};
1102
1103
1104/* ===================================================================== */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001105/* Getters and setters of BZ2File. */
1106
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001107static PyObject *
1108BZ2File_get_closed(BZ2FileObject *self, void *closure)
1109{
1110 return PyInt_FromLong(self->mode == MODE_CLOSED);
1111}
1112
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001113static PyGetSetDef BZ2File_getset[] = {
1114 {"closed", (getter)BZ2File_get_closed, NULL,
1115 "True if the file is closed"},
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001116 {NULL} /* Sentinel */
1117};
1118
1119
1120/* ===================================================================== */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001121/* Slot definitions for BZ2File_Type. */
1122
1123static int
1124BZ2File_init(BZ2FileObject *self, PyObject *args, PyObject *kwargs)
1125{
Martin v. Löwis15e62742006-02-27 16:46:16 +00001126 static char *kwlist[] = {"filename", "mode", "buffering",
Guido van Rossumf09ca142007-06-13 00:03:05 +00001127 "compresslevel", 0};
1128 char *name;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001129 char *mode = "r";
1130 int buffering = -1;
1131 int compresslevel = 9;
1132 int bzerror;
1133 int mode_char = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001134
1135 self->size = -1;
Tim Peterse3228092002-11-09 04:21:44 +00001136
Guido van Rossumf09ca142007-06-13 00:03:05 +00001137 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|sii:BZ2File",
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001138 kwlist, &name, &mode, &buffering,
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001139 &compresslevel))
1140 return -1;
1141
1142 if (compresslevel < 1 || compresslevel > 9) {
1143 PyErr_SetString(PyExc_ValueError,
1144 "compresslevel must be between 1 and 9");
1145 return -1;
1146 }
1147
1148 for (;;) {
1149 int error = 0;
1150 switch (*mode) {
1151 case 'r':
1152 case 'w':
1153 if (mode_char)
1154 error = 1;
1155 mode_char = *mode;
1156 break;
1157
1158 case 'b':
1159 break;
1160
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001161 default:
1162 error = 1;
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001163 break;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001164 }
1165 if (error) {
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001166 PyErr_Format(PyExc_ValueError,
1167 "invalid mode char %c", *mode);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001168 return -1;
1169 }
1170 mode++;
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001171 if (*mode == '\0')
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001172 break;
1173 }
1174
Georg Brandl6b95f1d2005-06-03 19:47:00 +00001175 if (mode_char == 0) {
1176 mode_char = 'r';
1177 }
1178
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001179 mode = (mode_char == 'r') ? "rb" : "wb";
Tim Peterse3228092002-11-09 04:21:44 +00001180
Guido van Rossumf09ca142007-06-13 00:03:05 +00001181 self->rawfp = fopen(name, mode);
1182 if (self->rawfp == NULL) {
1183 PyErr_SetFromErrno(PyExc_IOError);
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001184 return -1;
Guido van Rossumf09ca142007-06-13 00:03:05 +00001185 }
1186 /* XXX Ignore buffering */
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001187
1188 /* From now on, we have stuff to dealloc, so jump to error label
1189 * instead of returning */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001190
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001191#ifdef WITH_THREAD
1192 self->lock = PyThread_allocate_lock();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001193 if (!self->lock) {
1194 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001195 goto error;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001196 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001197#endif
1198
1199 if (mode_char == 'r')
Guido van Rossumf09ca142007-06-13 00:03:05 +00001200 self->fp = BZ2_bzReadOpen(&bzerror, self->rawfp,
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001201 0, 0, NULL, 0);
1202 else
Guido van Rossumf09ca142007-06-13 00:03:05 +00001203 self->fp = BZ2_bzWriteOpen(&bzerror, self->rawfp,
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001204 compresslevel, 0, 0);
1205
1206 if (bzerror != BZ_OK) {
1207 Util_CatchBZ2Error(bzerror);
1208 goto error;
1209 }
1210
1211 self->mode = (mode_char == 'r') ? MODE_READ : MODE_WRITE;
1212
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001213 return 0;
1214
1215error:
Guido van Rossumf09ca142007-06-13 00:03:05 +00001216 fclose(self->rawfp);
1217 self->rawfp = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001218#ifdef WITH_THREAD
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001219 if (self->lock) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001220 PyThread_free_lock(self->lock);
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001221 self->lock = NULL;
1222 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001223#endif
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001224 return -1;
1225}
1226
1227static void
1228BZ2File_dealloc(BZ2FileObject *self)
1229{
1230 int bzerror;
1231#ifdef WITH_THREAD
1232 if (self->lock)
1233 PyThread_free_lock(self->lock);
1234#endif
1235 switch (self->mode) {
1236 case MODE_READ:
1237 case MODE_READ_EOF:
1238 BZ2_bzReadClose(&bzerror, self->fp);
1239 break;
1240 case MODE_WRITE:
1241 BZ2_bzWriteClose(&bzerror, self->fp,
1242 0, NULL, NULL);
1243 break;
1244 }
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001245 Util_DropReadAhead(self);
Guido van Rossumf09ca142007-06-13 00:03:05 +00001246 if (self->rawfp != NULL)
1247 fclose(self->rawfp);
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00001248 Py_Type(self)->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001249}
1250
1251/* This is a hacked version of Python's fileobject.c:file_getiter(). */
1252static PyObject *
1253BZ2File_getiter(BZ2FileObject *self)
1254{
1255 if (self->mode == MODE_CLOSED) {
1256 PyErr_SetString(PyExc_ValueError,
1257 "I/O operation on closed file");
1258 return NULL;
1259 }
1260 Py_INCREF((PyObject*)self);
1261 return (PyObject *)self;
1262}
1263
1264/* This is a hacked version of Python's fileobject.c:file_iternext(). */
1265#define READAHEAD_BUFSIZE 8192
1266static PyObject *
1267BZ2File_iternext(BZ2FileObject *self)
1268{
Guido van Rossum522a6c62007-05-22 23:13:45 +00001269 PyBytesObject* ret;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001270 ACQUIRE_LOCK(self);
1271 if (self->mode == MODE_CLOSED) {
1272 PyErr_SetString(PyExc_ValueError,
1273 "I/O operation on closed file");
1274 return NULL;
1275 }
1276 ret = Util_ReadAheadGetLineSkip(self, 0, READAHEAD_BUFSIZE);
1277 RELEASE_LOCK(self);
Guido van Rossum522a6c62007-05-22 23:13:45 +00001278 if (ret == NULL || PyBytes_GET_SIZE(ret) == 0) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001279 Py_XDECREF(ret);
1280 return NULL;
1281 }
1282 return (PyObject *)ret;
1283}
1284
1285/* ===================================================================== */
1286/* BZ2File_Type definition. */
1287
1288PyDoc_VAR(BZ2File__doc__) =
1289PyDoc_STR(
1290"BZ2File(name [, mode='r', buffering=0, compresslevel=9]) -> file object\n\
1291\n\
1292Open a bz2 file. The mode can be 'r' or 'w', for reading (default) or\n\
1293writing. When opened for writing, the file will be created if it doesn't\n\
1294exist, and truncated otherwise. If the buffering argument is given, 0 means\n\
1295unbuffered, and larger numbers specify the buffer size. If compresslevel\n\
1296is given, must be a number between 1 and 9.\n\
Guido van Rossum88e860c2007-06-13 01:46:31 +00001297Data read is always returned in bytes; data written ought to be bytes.\n\
1298");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001299
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001300static PyTypeObject BZ2File_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00001301 PyVarObject_HEAD_INIT(NULL, 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001302 "bz2.BZ2File", /*tp_name*/
1303 sizeof(BZ2FileObject), /*tp_basicsize*/
1304 0, /*tp_itemsize*/
1305 (destructor)BZ2File_dealloc, /*tp_dealloc*/
1306 0, /*tp_print*/
1307 0, /*tp_getattr*/
1308 0, /*tp_setattr*/
1309 0, /*tp_compare*/
1310 0, /*tp_repr*/
1311 0, /*tp_as_number*/
1312 0, /*tp_as_sequence*/
1313 0, /*tp_as_mapping*/
1314 0, /*tp_hash*/
1315 0, /*tp_call*/
1316 0, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001317 PyObject_GenericGetAttr,/*tp_getattro*/
1318 PyObject_GenericSetAttr,/*tp_setattro*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001319 0, /*tp_as_buffer*/
1320 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1321 BZ2File__doc__, /*tp_doc*/
1322 0, /*tp_traverse*/
1323 0, /*tp_clear*/
1324 0, /*tp_richcompare*/
1325 0, /*tp_weaklistoffset*/
1326 (getiterfunc)BZ2File_getiter, /*tp_iter*/
1327 (iternextfunc)BZ2File_iternext, /*tp_iternext*/
1328 BZ2File_methods, /*tp_methods*/
Guido van Rossum79139b22007-02-09 23:20:19 +00001329 0, /*tp_members*/
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001330 BZ2File_getset, /*tp_getset*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001331 0, /*tp_base*/
1332 0, /*tp_dict*/
1333 0, /*tp_descr_get*/
1334 0, /*tp_descr_set*/
1335 0, /*tp_dictoffset*/
1336 (initproc)BZ2File_init, /*tp_init*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001337 PyType_GenericAlloc, /*tp_alloc*/
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001338 PyType_GenericNew, /*tp_new*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001339 _PyObject_Del, /*tp_free*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001340 0, /*tp_is_gc*/
1341};
1342
1343
1344/* ===================================================================== */
1345/* Methods of BZ2Comp. */
1346
1347PyDoc_STRVAR(BZ2Comp_compress__doc__,
1348"compress(data) -> string\n\
1349\n\
1350Provide more data to the compressor object. It will return chunks of\n\
1351compressed data whenever possible. When you've finished providing data\n\
1352to compress, call the flush() method to finish the compression process,\n\
1353and return what is left in the internal buffers.\n\
1354");
1355
1356static PyObject *
1357BZ2Comp_compress(BZ2CompObject *self, PyObject *args)
1358{
1359 char *data;
1360 int datasize;
1361 int bufsize = SMALLCHUNK;
Martin v. Löwisb9a0f912003-03-29 10:06:18 +00001362 PY_LONG_LONG totalout;
Gustavo Niemeyer7d7930b2002-11-05 18:41:53 +00001363 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001364 bz_stream *bzs = &self->bzs;
1365 int bzerror;
1366
Walter Dörwaldbb9c7392004-11-01 17:10:19 +00001367 if (!PyArg_ParseTuple(args, "s#:compress", &data, &datasize))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001368 return NULL;
1369
Gustavo Niemeyera6e436e2004-02-14 00:02:45 +00001370 if (datasize == 0)
Guido van Rossum522a6c62007-05-22 23:13:45 +00001371 return PyBytes_FromStringAndSize("", 0);
Gustavo Niemeyera6e436e2004-02-14 00:02:45 +00001372
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001373 ACQUIRE_LOCK(self);
1374 if (!self->running) {
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001375 PyErr_SetString(PyExc_ValueError,
1376 "this object was already flushed");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001377 goto error;
1378 }
1379
Guido van Rossum522a6c62007-05-22 23:13:45 +00001380 ret = PyBytes_FromStringAndSize(NULL, bufsize);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001381 if (!ret)
1382 goto error;
1383
1384 bzs->next_in = data;
1385 bzs->avail_in = datasize;
1386 bzs->next_out = BUF(ret);
1387 bzs->avail_out = bufsize;
1388
1389 totalout = BZS_TOTAL_OUT(bzs);
1390
1391 for (;;) {
1392 Py_BEGIN_ALLOW_THREADS
1393 bzerror = BZ2_bzCompress(bzs, BZ_RUN);
1394 Py_END_ALLOW_THREADS
1395 if (bzerror != BZ_RUN_OK) {
1396 Util_CatchBZ2Error(bzerror);
1397 goto error;
1398 }
Guido van Rossumd8faa362007-04-27 19:54:29 +00001399 if (bzs->avail_in == 0)
1400 break; /* no more input data */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001401 if (bzs->avail_out == 0) {
1402 bufsize = Util_NewBufferSize(bufsize);
Guido van Rossum522a6c62007-05-22 23:13:45 +00001403 if (PyBytes_Resize(ret, bufsize) < 0) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001404 BZ2_bzCompressEnd(bzs);
1405 goto error;
1406 }
1407 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs)
1408 - totalout);
1409 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001410 }
1411 }
1412
Guido van Rossum522a6c62007-05-22 23:13:45 +00001413 if (PyBytes_Resize(ret,
1414 (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout)) < 0)
1415 goto error;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001416
1417 RELEASE_LOCK(self);
1418 return ret;
1419
1420error:
1421 RELEASE_LOCK(self);
1422 Py_XDECREF(ret);
1423 return NULL;
1424}
1425
1426PyDoc_STRVAR(BZ2Comp_flush__doc__,
1427"flush() -> string\n\
1428\n\
1429Finish the compression process and return what is left in internal buffers.\n\
1430You must not use the compressor object after calling this method.\n\
1431");
1432
1433static PyObject *
1434BZ2Comp_flush(BZ2CompObject *self)
1435{
1436 int bufsize = SMALLCHUNK;
Gustavo Niemeyer7d7930b2002-11-05 18:41:53 +00001437 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001438 bz_stream *bzs = &self->bzs;
Martin v. Löwisb9a0f912003-03-29 10:06:18 +00001439 PY_LONG_LONG totalout;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001440 int bzerror;
1441
1442 ACQUIRE_LOCK(self);
1443 if (!self->running) {
1444 PyErr_SetString(PyExc_ValueError, "object was already "
1445 "flushed");
1446 goto error;
1447 }
1448 self->running = 0;
1449
Guido van Rossum522a6c62007-05-22 23:13:45 +00001450 ret = PyBytes_FromStringAndSize(NULL, bufsize);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001451 if (!ret)
1452 goto error;
1453
1454 bzs->next_out = BUF(ret);
1455 bzs->avail_out = bufsize;
1456
1457 totalout = BZS_TOTAL_OUT(bzs);
1458
1459 for (;;) {
1460 Py_BEGIN_ALLOW_THREADS
1461 bzerror = BZ2_bzCompress(bzs, BZ_FINISH);
1462 Py_END_ALLOW_THREADS
1463 if (bzerror == BZ_STREAM_END) {
1464 break;
1465 } else if (bzerror != BZ_FINISH_OK) {
1466 Util_CatchBZ2Error(bzerror);
1467 goto error;
1468 }
1469 if (bzs->avail_out == 0) {
1470 bufsize = Util_NewBufferSize(bufsize);
Guido van Rossum522a6c62007-05-22 23:13:45 +00001471 if (PyBytes_Resize(ret, bufsize) < 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001472 goto error;
1473 bzs->next_out = BUF(ret);
1474 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs)
1475 - totalout);
1476 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
1477 }
1478 }
1479
Guido van Rossum522a6c62007-05-22 23:13:45 +00001480 if (bzs->avail_out != 0) {
1481 if (PyBytes_Resize(ret,
1482 (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout)) < 0)
1483 goto error;
1484 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001485
1486 RELEASE_LOCK(self);
1487 return ret;
1488
1489error:
1490 RELEASE_LOCK(self);
1491 Py_XDECREF(ret);
1492 return NULL;
1493}
1494
1495static PyMethodDef BZ2Comp_methods[] = {
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001496 {"compress", (PyCFunction)BZ2Comp_compress, METH_VARARGS,
1497 BZ2Comp_compress__doc__},
1498 {"flush", (PyCFunction)BZ2Comp_flush, METH_NOARGS,
1499 BZ2Comp_flush__doc__},
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001500 {NULL, NULL} /* sentinel */
1501};
1502
1503
1504/* ===================================================================== */
1505/* Slot definitions for BZ2Comp_Type. */
1506
1507static int
1508BZ2Comp_init(BZ2CompObject *self, PyObject *args, PyObject *kwargs)
1509{
1510 int compresslevel = 9;
1511 int bzerror;
Martin v. Löwis15e62742006-02-27 16:46:16 +00001512 static char *kwlist[] = {"compresslevel", 0};
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001513
1514 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:BZ2Compressor",
1515 kwlist, &compresslevel))
1516 return -1;
1517
1518 if (compresslevel < 1 || compresslevel > 9) {
1519 PyErr_SetString(PyExc_ValueError,
1520 "compresslevel must be between 1 and 9");
1521 goto error;
1522 }
1523
1524#ifdef WITH_THREAD
1525 self->lock = PyThread_allocate_lock();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001526 if (!self->lock) {
1527 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001528 goto error;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001529 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001530#endif
1531
1532 memset(&self->bzs, 0, sizeof(bz_stream));
1533 bzerror = BZ2_bzCompressInit(&self->bzs, compresslevel, 0, 0);
1534 if (bzerror != BZ_OK) {
1535 Util_CatchBZ2Error(bzerror);
1536 goto error;
1537 }
1538
1539 self->running = 1;
1540
1541 return 0;
1542error:
1543#ifdef WITH_THREAD
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001544 if (self->lock) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001545 PyThread_free_lock(self->lock);
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001546 self->lock = NULL;
1547 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001548#endif
1549 return -1;
1550}
1551
1552static void
1553BZ2Comp_dealloc(BZ2CompObject *self)
1554{
1555#ifdef WITH_THREAD
1556 if (self->lock)
1557 PyThread_free_lock(self->lock);
1558#endif
1559 BZ2_bzCompressEnd(&self->bzs);
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00001560 Py_Type(self)->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001561}
1562
1563
1564/* ===================================================================== */
1565/* BZ2Comp_Type definition. */
1566
1567PyDoc_STRVAR(BZ2Comp__doc__,
1568"BZ2Compressor([compresslevel=9]) -> compressor object\n\
1569\n\
1570Create a new compressor object. This object may be used to compress\n\
1571data sequentially. If you want to compress data in one shot, use the\n\
1572compress() function instead. The compresslevel parameter, if given,\n\
1573must be a number between 1 and 9.\n\
1574");
1575
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001576static PyTypeObject BZ2Comp_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00001577 PyVarObject_HEAD_INIT(NULL, 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001578 "bz2.BZ2Compressor", /*tp_name*/
1579 sizeof(BZ2CompObject), /*tp_basicsize*/
1580 0, /*tp_itemsize*/
1581 (destructor)BZ2Comp_dealloc, /*tp_dealloc*/
1582 0, /*tp_print*/
1583 0, /*tp_getattr*/
1584 0, /*tp_setattr*/
1585 0, /*tp_compare*/
1586 0, /*tp_repr*/
1587 0, /*tp_as_number*/
1588 0, /*tp_as_sequence*/
1589 0, /*tp_as_mapping*/
1590 0, /*tp_hash*/
1591 0, /*tp_call*/
1592 0, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001593 PyObject_GenericGetAttr,/*tp_getattro*/
1594 PyObject_GenericSetAttr,/*tp_setattro*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001595 0, /*tp_as_buffer*/
1596 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1597 BZ2Comp__doc__, /*tp_doc*/
1598 0, /*tp_traverse*/
1599 0, /*tp_clear*/
1600 0, /*tp_richcompare*/
1601 0, /*tp_weaklistoffset*/
1602 0, /*tp_iter*/
1603 0, /*tp_iternext*/
1604 BZ2Comp_methods, /*tp_methods*/
1605 0, /*tp_members*/
1606 0, /*tp_getset*/
1607 0, /*tp_base*/
1608 0, /*tp_dict*/
1609 0, /*tp_descr_get*/
1610 0, /*tp_descr_set*/
1611 0, /*tp_dictoffset*/
1612 (initproc)BZ2Comp_init, /*tp_init*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001613 PyType_GenericAlloc, /*tp_alloc*/
1614 PyType_GenericNew, /*tp_new*/
1615 _PyObject_Del, /*tp_free*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001616 0, /*tp_is_gc*/
1617};
1618
1619
1620/* ===================================================================== */
1621/* Members of BZ2Decomp. */
1622
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001623#undef OFF
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001624#define OFF(x) offsetof(BZ2DecompObject, x)
1625
1626static PyMemberDef BZ2Decomp_members[] = {
1627 {"unused_data", T_OBJECT, OFF(unused_data), RO},
1628 {NULL} /* Sentinel */
1629};
1630
1631
1632/* ===================================================================== */
1633/* Methods of BZ2Decomp. */
1634
1635PyDoc_STRVAR(BZ2Decomp_decompress__doc__,
1636"decompress(data) -> string\n\
1637\n\
1638Provide more data to the decompressor object. It will return chunks\n\
1639of decompressed data whenever possible. If you try to decompress data\n\
1640after the end of stream is found, EOFError will be raised. If any data\n\
1641was found after the end of stream, it'll be ignored and saved in\n\
1642unused_data attribute.\n\
1643");
1644
1645static PyObject *
1646BZ2Decomp_decompress(BZ2DecompObject *self, PyObject *args)
1647{
1648 char *data;
1649 int datasize;
1650 int bufsize = SMALLCHUNK;
Martin v. Löwisb9a0f912003-03-29 10:06:18 +00001651 PY_LONG_LONG totalout;
Neal Norwitz18142c02002-11-05 18:17:32 +00001652 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001653 bz_stream *bzs = &self->bzs;
1654 int bzerror;
1655
Walter Dörwaldbb9c7392004-11-01 17:10:19 +00001656 if (!PyArg_ParseTuple(args, "s#:decompress", &data, &datasize))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001657 return NULL;
1658
1659 ACQUIRE_LOCK(self);
1660 if (!self->running) {
1661 PyErr_SetString(PyExc_EOFError, "end of stream was "
1662 "already found");
1663 goto error;
1664 }
1665
Guido van Rossum522a6c62007-05-22 23:13:45 +00001666 ret = PyBytes_FromStringAndSize(NULL, bufsize);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001667 if (!ret)
1668 goto error;
1669
1670 bzs->next_in = data;
1671 bzs->avail_in = datasize;
1672 bzs->next_out = BUF(ret);
1673 bzs->avail_out = bufsize;
1674
1675 totalout = BZS_TOTAL_OUT(bzs);
1676
1677 for (;;) {
1678 Py_BEGIN_ALLOW_THREADS
1679 bzerror = BZ2_bzDecompress(bzs);
1680 Py_END_ALLOW_THREADS
1681 if (bzerror == BZ_STREAM_END) {
1682 if (bzs->avail_in != 0) {
1683 Py_DECREF(self->unused_data);
1684 self->unused_data =
Guido van Rossum522a6c62007-05-22 23:13:45 +00001685 PyBytes_FromStringAndSize(bzs->next_in,
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001686 bzs->avail_in);
1687 }
1688 self->running = 0;
1689 break;
1690 }
1691 if (bzerror != BZ_OK) {
1692 Util_CatchBZ2Error(bzerror);
1693 goto error;
1694 }
Guido van Rossumd8faa362007-04-27 19:54:29 +00001695 if (bzs->avail_in == 0)
1696 break; /* no more input data */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001697 if (bzs->avail_out == 0) {
1698 bufsize = Util_NewBufferSize(bufsize);
Guido van Rossum522a6c62007-05-22 23:13:45 +00001699 if (PyBytes_Resize(ret, bufsize) < 0) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001700 BZ2_bzDecompressEnd(bzs);
1701 goto error;
1702 }
1703 bzs->next_out = BUF(ret);
1704 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs)
1705 - totalout);
1706 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001707 }
1708 }
1709
Guido van Rossum522a6c62007-05-22 23:13:45 +00001710 if (bzs->avail_out != 0) {
1711 if (PyBytes_Resize(ret,
1712 (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout)) < 0)
1713 goto error;
1714 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001715
1716 RELEASE_LOCK(self);
1717 return ret;
1718
1719error:
1720 RELEASE_LOCK(self);
1721 Py_XDECREF(ret);
1722 return NULL;
1723}
1724
1725static PyMethodDef BZ2Decomp_methods[] = {
1726 {"decompress", (PyCFunction)BZ2Decomp_decompress, METH_VARARGS, BZ2Decomp_decompress__doc__},
1727 {NULL, NULL} /* sentinel */
1728};
1729
1730
1731/* ===================================================================== */
1732/* Slot definitions for BZ2Decomp_Type. */
1733
1734static int
1735BZ2Decomp_init(BZ2DecompObject *self, PyObject *args, PyObject *kwargs)
1736{
1737 int bzerror;
1738
1739 if (!PyArg_ParseTuple(args, ":BZ2Decompressor"))
1740 return -1;
1741
1742#ifdef WITH_THREAD
1743 self->lock = PyThread_allocate_lock();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001744 if (!self->lock) {
1745 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001746 goto error;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001747 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001748#endif
1749
Guido van Rossum522a6c62007-05-22 23:13:45 +00001750 self->unused_data = PyBytes_FromStringAndSize("", 0);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001751 if (!self->unused_data)
1752 goto error;
1753
1754 memset(&self->bzs, 0, sizeof(bz_stream));
1755 bzerror = BZ2_bzDecompressInit(&self->bzs, 0, 0);
1756 if (bzerror != BZ_OK) {
1757 Util_CatchBZ2Error(bzerror);
1758 goto error;
1759 }
1760
1761 self->running = 1;
1762
1763 return 0;
1764
1765error:
1766#ifdef WITH_THREAD
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001767 if (self->lock) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001768 PyThread_free_lock(self->lock);
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001769 self->lock = NULL;
1770 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001771#endif
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001772 Py_CLEAR(self->unused_data);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001773 return -1;
1774}
1775
1776static void
1777BZ2Decomp_dealloc(BZ2DecompObject *self)
1778{
1779#ifdef WITH_THREAD
1780 if (self->lock)
1781 PyThread_free_lock(self->lock);
1782#endif
1783 Py_XDECREF(self->unused_data);
1784 BZ2_bzDecompressEnd(&self->bzs);
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00001785 Py_Type(self)->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001786}
1787
1788
1789/* ===================================================================== */
1790/* BZ2Decomp_Type definition. */
1791
1792PyDoc_STRVAR(BZ2Decomp__doc__,
1793"BZ2Decompressor() -> decompressor object\n\
1794\n\
1795Create a new decompressor object. This object may be used to decompress\n\
1796data sequentially. If you want to decompress data in one shot, use the\n\
1797decompress() function instead.\n\
1798");
1799
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001800static PyTypeObject BZ2Decomp_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00001801 PyVarObject_HEAD_INIT(NULL, 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001802 "bz2.BZ2Decompressor", /*tp_name*/
1803 sizeof(BZ2DecompObject), /*tp_basicsize*/
1804 0, /*tp_itemsize*/
1805 (destructor)BZ2Decomp_dealloc, /*tp_dealloc*/
1806 0, /*tp_print*/
1807 0, /*tp_getattr*/
1808 0, /*tp_setattr*/
1809 0, /*tp_compare*/
1810 0, /*tp_repr*/
1811 0, /*tp_as_number*/
1812 0, /*tp_as_sequence*/
1813 0, /*tp_as_mapping*/
1814 0, /*tp_hash*/
1815 0, /*tp_call*/
1816 0, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001817 PyObject_GenericGetAttr,/*tp_getattro*/
1818 PyObject_GenericSetAttr,/*tp_setattro*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001819 0, /*tp_as_buffer*/
1820 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1821 BZ2Decomp__doc__, /*tp_doc*/
1822 0, /*tp_traverse*/
1823 0, /*tp_clear*/
1824 0, /*tp_richcompare*/
1825 0, /*tp_weaklistoffset*/
1826 0, /*tp_iter*/
1827 0, /*tp_iternext*/
1828 BZ2Decomp_methods, /*tp_methods*/
1829 BZ2Decomp_members, /*tp_members*/
1830 0, /*tp_getset*/
1831 0, /*tp_base*/
1832 0, /*tp_dict*/
1833 0, /*tp_descr_get*/
1834 0, /*tp_descr_set*/
1835 0, /*tp_dictoffset*/
1836 (initproc)BZ2Decomp_init, /*tp_init*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001837 PyType_GenericAlloc, /*tp_alloc*/
1838 PyType_GenericNew, /*tp_new*/
1839 _PyObject_Del, /*tp_free*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001840 0, /*tp_is_gc*/
1841};
1842
1843
1844/* ===================================================================== */
1845/* Module functions. */
1846
1847PyDoc_STRVAR(bz2_compress__doc__,
1848"compress(data [, compresslevel=9]) -> string\n\
1849\n\
1850Compress data in one shot. If you want to compress data sequentially,\n\
1851use an instance of BZ2Compressor instead. The compresslevel parameter, if\n\
1852given, must be a number between 1 and 9.\n\
1853");
1854
1855static PyObject *
1856bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
1857{
1858 int compresslevel=9;
1859 char *data;
1860 int datasize;
1861 int bufsize;
Gustavo Niemeyer7d7930b2002-11-05 18:41:53 +00001862 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001863 bz_stream _bzs;
1864 bz_stream *bzs = &_bzs;
1865 int bzerror;
Martin v. Löwis15e62742006-02-27 16:46:16 +00001866 static char *kwlist[] = {"data", "compresslevel", 0};
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001867
1868 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|i",
1869 kwlist, &data, &datasize,
1870 &compresslevel))
1871 return NULL;
1872
1873 if (compresslevel < 1 || compresslevel > 9) {
1874 PyErr_SetString(PyExc_ValueError,
1875 "compresslevel must be between 1 and 9");
1876 return NULL;
1877 }
1878
1879 /* Conforming to bz2 manual, this is large enough to fit compressed
1880 * data in one shot. We will check it later anyway. */
1881 bufsize = datasize + (datasize/100+1) + 600;
1882
Guido van Rossum522a6c62007-05-22 23:13:45 +00001883 ret = PyBytes_FromStringAndSize(NULL, bufsize);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001884 if (!ret)
1885 return NULL;
1886
1887 memset(bzs, 0, sizeof(bz_stream));
1888
1889 bzs->next_in = data;
1890 bzs->avail_in = datasize;
1891 bzs->next_out = BUF(ret);
1892 bzs->avail_out = bufsize;
1893
1894 bzerror = BZ2_bzCompressInit(bzs, compresslevel, 0, 0);
1895 if (bzerror != BZ_OK) {
1896 Util_CatchBZ2Error(bzerror);
1897 Py_DECREF(ret);
1898 return NULL;
1899 }
Tim Peterse3228092002-11-09 04:21:44 +00001900
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001901 for (;;) {
1902 Py_BEGIN_ALLOW_THREADS
1903 bzerror = BZ2_bzCompress(bzs, BZ_FINISH);
1904 Py_END_ALLOW_THREADS
1905 if (bzerror == BZ_STREAM_END) {
1906 break;
1907 } else if (bzerror != BZ_FINISH_OK) {
1908 BZ2_bzCompressEnd(bzs);
1909 Util_CatchBZ2Error(bzerror);
1910 Py_DECREF(ret);
1911 return NULL;
1912 }
1913 if (bzs->avail_out == 0) {
1914 bufsize = Util_NewBufferSize(bufsize);
Guido van Rossum522a6c62007-05-22 23:13:45 +00001915 if (PyBytes_Resize(ret, bufsize) < 0) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001916 BZ2_bzCompressEnd(bzs);
1917 Py_DECREF(ret);
1918 return NULL;
1919 }
1920 bzs->next_out = BUF(ret) + BZS_TOTAL_OUT(bzs);
1921 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
1922 }
1923 }
1924
Guido van Rossum522a6c62007-05-22 23:13:45 +00001925 if (bzs->avail_out != 0) {
1926 if (PyBytes_Resize(ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs)) < 0) {
1927 Py_DECREF(ret);
1928 ret = NULL;
1929 }
1930 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001931 BZ2_bzCompressEnd(bzs);
1932
1933 return ret;
1934}
1935
1936PyDoc_STRVAR(bz2_decompress__doc__,
1937"decompress(data) -> decompressed data\n\
1938\n\
1939Decompress data in one shot. If you want to decompress data sequentially,\n\
1940use an instance of BZ2Decompressor instead.\n\
1941");
1942
1943static PyObject *
1944bz2_decompress(PyObject *self, PyObject *args)
1945{
1946 char *data;
1947 int datasize;
1948 int bufsize = SMALLCHUNK;
1949 PyObject *ret;
1950 bz_stream _bzs;
1951 bz_stream *bzs = &_bzs;
1952 int bzerror;
1953
Walter Dörwaldbb9c7392004-11-01 17:10:19 +00001954 if (!PyArg_ParseTuple(args, "s#:decompress", &data, &datasize))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001955 return NULL;
1956
1957 if (datasize == 0)
Guido van Rossum522a6c62007-05-22 23:13:45 +00001958 return PyBytes_FromStringAndSize("", 0);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001959
Guido van Rossum522a6c62007-05-22 23:13:45 +00001960 ret = PyBytes_FromStringAndSize(NULL, bufsize);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001961 if (!ret)
1962 return NULL;
1963
1964 memset(bzs, 0, sizeof(bz_stream));
1965
1966 bzs->next_in = data;
1967 bzs->avail_in = datasize;
1968 bzs->next_out = BUF(ret);
1969 bzs->avail_out = bufsize;
1970
1971 bzerror = BZ2_bzDecompressInit(bzs, 0, 0);
1972 if (bzerror != BZ_OK) {
1973 Util_CatchBZ2Error(bzerror);
1974 Py_DECREF(ret);
1975 return NULL;
1976 }
Tim Peterse3228092002-11-09 04:21:44 +00001977
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001978 for (;;) {
1979 Py_BEGIN_ALLOW_THREADS
1980 bzerror = BZ2_bzDecompress(bzs);
1981 Py_END_ALLOW_THREADS
1982 if (bzerror == BZ_STREAM_END) {
1983 break;
1984 } else if (bzerror != BZ_OK) {
1985 BZ2_bzDecompressEnd(bzs);
1986 Util_CatchBZ2Error(bzerror);
1987 Py_DECREF(ret);
1988 return NULL;
1989 }
Guido van Rossumd8faa362007-04-27 19:54:29 +00001990 if (bzs->avail_in == 0) {
1991 BZ2_bzDecompressEnd(bzs);
1992 PyErr_SetString(PyExc_ValueError,
1993 "couldn't find end of stream");
1994 Py_DECREF(ret);
1995 return NULL;
1996 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001997 if (bzs->avail_out == 0) {
1998 bufsize = Util_NewBufferSize(bufsize);
Guido van Rossum522a6c62007-05-22 23:13:45 +00001999 if (PyBytes_Resize(ret, bufsize) < 0) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002000 BZ2_bzDecompressEnd(bzs);
2001 Py_DECREF(ret);
2002 return NULL;
2003 }
2004 bzs->next_out = BUF(ret) + BZS_TOTAL_OUT(bzs);
2005 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002006 }
2007 }
2008
Guido van Rossum522a6c62007-05-22 23:13:45 +00002009 if (bzs->avail_out != 0) {
2010 if (PyBytes_Resize(ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs)) < 0) {
2011 Py_DECREF(ret);
2012 ret = NULL;
2013 }
2014 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002015 BZ2_bzDecompressEnd(bzs);
2016
2017 return ret;
2018}
2019
2020static PyMethodDef bz2_methods[] = {
2021 {"compress", (PyCFunction) bz2_compress, METH_VARARGS|METH_KEYWORDS,
2022 bz2_compress__doc__},
2023 {"decompress", (PyCFunction) bz2_decompress, METH_VARARGS,
2024 bz2_decompress__doc__},
2025 {NULL, NULL} /* sentinel */
2026};
2027
2028/* ===================================================================== */
2029/* Initialization function. */
2030
2031PyDoc_STRVAR(bz2__doc__,
2032"The python bz2 module provides a comprehensive interface for\n\
2033the bz2 compression library. It implements a complete file\n\
2034interface, one shot (de)compression functions, and types for\n\
2035sequential (de)compression.\n\
2036");
2037
Neal Norwitz21d896c2003-07-01 20:15:21 +00002038PyMODINIT_FUNC
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002039initbz2(void)
2040{
2041 PyObject *m;
2042
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00002043 Py_Type(&BZ2File_Type) = &PyType_Type;
2044 Py_Type(&BZ2Comp_Type) = &PyType_Type;
2045 Py_Type(&BZ2Decomp_Type) = &PyType_Type;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002046
2047 m = Py_InitModule3("bz2", bz2_methods, bz2__doc__);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00002048 if (m == NULL)
2049 return;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002050
2051 PyModule_AddObject(m, "__author__", PyString_FromString(__author__));
2052
2053 Py_INCREF(&BZ2File_Type);
2054 PyModule_AddObject(m, "BZ2File", (PyObject *)&BZ2File_Type);
2055
2056 Py_INCREF(&BZ2Comp_Type);
2057 PyModule_AddObject(m, "BZ2Compressor", (PyObject *)&BZ2Comp_Type);
2058
2059 Py_INCREF(&BZ2Decomp_Type);
2060 PyModule_AddObject(m, "BZ2Decompressor", (PyObject *)&BZ2Decomp_Type);
2061}