blob: a40334d77d434f8b3f41a1c6c21e39ab9b74c8a6 [file] [log] [blame]
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001/*
2
3python-bz2 - python bz2 library interface
4
5Copyright (c) 2002 Gustavo Niemeyer <niemeyer@conectiva.com>
6Copyright (c) 2002 Python Software Foundation; All Rights Reserved
7
8*/
9
Martin v. Löwise17af7b2002-11-23 09:16:19 +000010#include "Python.h"
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000011#include <stdio.h>
12#include <bzlib.h>
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000013#include "structmember.h"
14
15#ifdef WITH_THREAD
16#include "pythread.h"
17#endif
18
19static char __author__[] =
20"The bz2 python module was written by:\n\
21\n\
22 Gustavo Niemeyer <niemeyer@conectiva.com>\n\
23";
24
Georg Brandl33a5f2a2005-08-21 14:16:04 +000025/* Our very own off_t-like type, 64-bit if possible */
26/* copied from Objects/fileobject.c */
27#if !defined(HAVE_LARGEFILE_SUPPORT)
28typedef off_t Py_off_t;
29#elif SIZEOF_OFF_T >= 8
30typedef off_t Py_off_t;
31#elif SIZEOF_FPOS_T >= 8
32typedef fpos_t Py_off_t;
33#else
34#error "Large file support, but neither off_t nor fpos_t is large enough."
35#endif
36
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000037#define BUF(v) PyString_AS_STRING((PyStringObject *)v)
38
39#define MODE_CLOSED 0
40#define MODE_READ 1
41#define MODE_READ_EOF 2
42#define MODE_WRITE 3
43
44#define BZ2FileObject_Check(v) ((v)->ob_type == &BZ2File_Type)
45
Gustavo Niemeyer7628f1f2003-04-27 06:25:24 +000046
47#ifdef BZ_CONFIG_ERROR
48
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000049#if SIZEOF_LONG >= 8
50#define BZS_TOTAL_OUT(bzs) \
51 (((long)bzs->total_out_hi32 << 32) + bzs->total_out_lo32)
52#elif SIZEOF_LONG_LONG >= 8
53#define BZS_TOTAL_OUT(bzs) \
Martin v. Löwisb9a0f912003-03-29 10:06:18 +000054 (((PY_LONG_LONG)bzs->total_out_hi32 << 32) + bzs->total_out_lo32)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000055#else
56#define BZS_TOTAL_OUT(bzs) \
Neal Norwitz20bad742006-01-17 05:27:39 +000057 bzs->total_out_lo32
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000058#endif
59
Gustavo Niemeyer7628f1f2003-04-27 06:25:24 +000060#else /* ! BZ_CONFIG_ERROR */
61
62#define BZ2_bzRead bzRead
63#define BZ2_bzReadOpen bzReadOpen
64#define BZ2_bzReadClose bzReadClose
65#define BZ2_bzWrite bzWrite
66#define BZ2_bzWriteOpen bzWriteOpen
67#define BZ2_bzWriteClose bzWriteClose
68#define BZ2_bzCompress bzCompress
69#define BZ2_bzCompressInit bzCompressInit
70#define BZ2_bzCompressEnd bzCompressEnd
71#define BZ2_bzDecompress bzDecompress
72#define BZ2_bzDecompressInit bzDecompressInit
73#define BZ2_bzDecompressEnd bzDecompressEnd
74
75#define BZS_TOTAL_OUT(bzs) bzs->total_out
76
77#endif /* ! BZ_CONFIG_ERROR */
78
79
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000080#ifdef WITH_THREAD
81#define ACQUIRE_LOCK(obj) PyThread_acquire_lock(obj->lock, 1)
82#define RELEASE_LOCK(obj) PyThread_release_lock(obj->lock)
83#else
84#define ACQUIRE_LOCK(obj)
85#define RELEASE_LOCK(obj)
86#endif
87
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000088/* Bits in f_newlinetypes */
89#define NEWLINE_UNKNOWN 0 /* No newline seen, yet */
90#define NEWLINE_CR 1 /* \r newline seen */
91#define NEWLINE_LF 2 /* \n newline seen */
92#define NEWLINE_CRLF 4 /* \r\n newline seen */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000093
94/* ===================================================================== */
95/* Structure definitions. */
96
97typedef struct {
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +000098 PyObject_HEAD
99 PyObject *file;
100
101 char* f_buf; /* Allocated readahead buffer */
102 char* f_bufend; /* Points after last occupied position */
103 char* f_bufptr; /* Current buffer position */
104
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000105 int f_univ_newline; /* Handle any newline convention */
106 int f_newlinetypes; /* Types of newlines seen */
107 int f_skipnextlf; /* Skip next \n */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000108
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000109 BZFILE *fp;
110 int mode;
Georg Brandla8bcecc2005-09-03 07:49:53 +0000111 Py_off_t pos;
112 Py_off_t size;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000113#ifdef WITH_THREAD
114 PyThread_type_lock lock;
115#endif
116} BZ2FileObject;
117
118typedef struct {
119 PyObject_HEAD
120 bz_stream bzs;
121 int running;
122#ifdef WITH_THREAD
123 PyThread_type_lock lock;
124#endif
125} BZ2CompObject;
126
127typedef struct {
128 PyObject_HEAD
129 bz_stream bzs;
130 int running;
131 PyObject *unused_data;
132#ifdef WITH_THREAD
133 PyThread_type_lock lock;
134#endif
135} BZ2DecompObject;
136
137/* ===================================================================== */
138/* Utility functions. */
139
140static int
141Util_CatchBZ2Error(int bzerror)
142{
143 int ret = 0;
144 switch(bzerror) {
145 case BZ_OK:
146 case BZ_STREAM_END:
147 break;
148
Gustavo Niemeyer7628f1f2003-04-27 06:25:24 +0000149#ifdef BZ_CONFIG_ERROR
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000150 case BZ_CONFIG_ERROR:
151 PyErr_SetString(PyExc_SystemError,
152 "the bz2 library was not compiled "
153 "correctly");
154 ret = 1;
155 break;
Gustavo Niemeyer7628f1f2003-04-27 06:25:24 +0000156#endif
Tim Peterse3228092002-11-09 04:21:44 +0000157
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000158 case BZ_PARAM_ERROR:
159 PyErr_SetString(PyExc_ValueError,
160 "the bz2 library has received wrong "
161 "parameters");
162 ret = 1;
163 break;
Tim Peterse3228092002-11-09 04:21:44 +0000164
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000165 case BZ_MEM_ERROR:
166 PyErr_NoMemory();
167 ret = 1;
168 break;
169
170 case BZ_DATA_ERROR:
171 case BZ_DATA_ERROR_MAGIC:
172 PyErr_SetString(PyExc_IOError, "invalid data stream");
173 ret = 1;
174 break;
175
176 case BZ_IO_ERROR:
177 PyErr_SetString(PyExc_IOError, "unknown IO error");
178 ret = 1;
179 break;
180
181 case BZ_UNEXPECTED_EOF:
182 PyErr_SetString(PyExc_EOFError,
183 "compressed file ended before the "
184 "logical end-of-stream was detected");
185 ret = 1;
186 break;
187
188 case BZ_SEQUENCE_ERROR:
189 PyErr_SetString(PyExc_RuntimeError,
190 "wrong sequence of bz2 library "
191 "commands used");
192 ret = 1;
193 break;
194 }
195 return ret;
196}
197
198#if BUFSIZ < 8192
199#define SMALLCHUNK 8192
200#else
201#define SMALLCHUNK BUFSIZ
202#endif
203
204#if SIZEOF_INT < 4
205#define BIGCHUNK (512 * 32)
206#else
207#define BIGCHUNK (512 * 1024)
208#endif
209
210/* This is a hacked version of Python's fileobject.c:new_buffersize(). */
211static size_t
212Util_NewBufferSize(size_t currentsize)
213{
214 if (currentsize > SMALLCHUNK) {
215 /* Keep doubling until we reach BIGCHUNK;
216 then keep adding BIGCHUNK. */
217 if (currentsize <= BIGCHUNK)
218 return currentsize + currentsize;
219 else
220 return currentsize + BIGCHUNK;
221 }
222 return currentsize + SMALLCHUNK;
223}
224
225/* This is a hacked version of Python's fileobject.c:get_line(). */
226static PyObject *
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000227Util_GetLine(BZ2FileObject *f, int n)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000228{
229 char c;
230 char *buf, *end;
231 size_t total_v_size; /* total # of slots in buffer */
232 size_t used_v_size; /* # used slots in buffer */
233 size_t increment; /* amount to increment the buffer */
234 PyObject *v;
235 int bzerror;
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000236 int newlinetypes = f->f_newlinetypes;
237 int skipnextlf = f->f_skipnextlf;
238 int univ_newline = f->f_univ_newline;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000239
240 total_v_size = n > 0 ? n : 100;
241 v = PyString_FromStringAndSize((char *)NULL, total_v_size);
242 if (v == NULL)
243 return NULL;
244
245 buf = BUF(v);
246 end = buf + total_v_size;
247
248 for (;;) {
249 Py_BEGIN_ALLOW_THREADS
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000250 if (univ_newline) {
251 while (1) {
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000252 BZ2_bzRead(&bzerror, f->fp, &c, 1);
253 f->pos++;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000254 if (bzerror != BZ_OK || buf == end)
255 break;
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +0000256 if (skipnextlf) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000257 skipnextlf = 0;
258 if (c == '\n') {
Tim Peterse3228092002-11-09 04:21:44 +0000259 /* Seeing a \n here with
260 * skipnextlf true means we
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000261 * saw a \r before.
262 */
263 newlinetypes |= NEWLINE_CRLF;
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000264 BZ2_bzRead(&bzerror, f->fp,
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000265 &c, 1);
266 if (bzerror != BZ_OK)
267 break;
268 } else {
269 newlinetypes |= NEWLINE_CR;
270 }
271 }
272 if (c == '\r') {
273 skipnextlf = 1;
274 c = '\n';
275 } else if ( c == '\n')
276 newlinetypes |= NEWLINE_LF;
277 *buf++ = c;
278 if (c == '\n') break;
279 }
280 if (bzerror == BZ_STREAM_END && skipnextlf)
281 newlinetypes |= NEWLINE_CR;
282 } else /* If not universal newlines use the normal loop */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000283 do {
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000284 BZ2_bzRead(&bzerror, f->fp, &c, 1);
285 f->pos++;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000286 *buf++ = c;
287 } while (bzerror == BZ_OK && c != '\n' && buf != end);
288 Py_END_ALLOW_THREADS
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000289 f->f_newlinetypes = newlinetypes;
290 f->f_skipnextlf = skipnextlf;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000291 if (bzerror == BZ_STREAM_END) {
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000292 f->size = f->pos;
293 f->mode = MODE_READ_EOF;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000294 break;
295 } else if (bzerror != BZ_OK) {
296 Util_CatchBZ2Error(bzerror);
297 Py_DECREF(v);
298 return NULL;
299 }
300 if (c == '\n')
301 break;
302 /* Must be because buf == end */
303 if (n > 0)
304 break;
305 used_v_size = total_v_size;
306 increment = total_v_size >> 2; /* mild exponential growth */
307 total_v_size += increment;
308 if (total_v_size > INT_MAX) {
309 PyErr_SetString(PyExc_OverflowError,
310 "line is longer than a Python string can hold");
311 Py_DECREF(v);
312 return NULL;
313 }
314 if (_PyString_Resize(&v, total_v_size) < 0)
315 return NULL;
316 buf = BUF(v) + used_v_size;
317 end = BUF(v) + total_v_size;
318 }
319
320 used_v_size = buf - BUF(v);
321 if (used_v_size != total_v_size)
322 _PyString_Resize(&v, used_v_size);
323 return v;
324}
325
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000326/* This is a hacked version of Python's
327 * fileobject.c:Py_UniversalNewlineFread(). */
328size_t
329Util_UnivNewlineRead(int *bzerror, BZFILE *stream,
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000330 char* buf, size_t n, BZ2FileObject *f)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000331{
332 char *dst = buf;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000333 int newlinetypes, skipnextlf;
334
335 assert(buf != NULL);
336 assert(stream != NULL);
337
338 if (!f->f_univ_newline)
339 return BZ2_bzRead(bzerror, stream, buf, n);
340
341 newlinetypes = f->f_newlinetypes;
342 skipnextlf = f->f_skipnextlf;
343
344 /* Invariant: n is the number of bytes remaining to be filled
345 * in the buffer.
346 */
347 while (n) {
348 size_t nread;
349 int shortread;
350 char *src = dst;
351
352 nread = BZ2_bzRead(bzerror, stream, dst, n);
353 assert(nread <= n);
354 n -= nread; /* assuming 1 byte out for each in; will adjust */
355 shortread = n != 0; /* true iff EOF or error */
356 while (nread--) {
357 char c = *src++;
358 if (c == '\r') {
359 /* Save as LF and set flag to skip next LF. */
360 *dst++ = '\n';
361 skipnextlf = 1;
362 }
363 else if (skipnextlf && c == '\n') {
364 /* Skip LF, and remember we saw CR LF. */
365 skipnextlf = 0;
366 newlinetypes |= NEWLINE_CRLF;
367 ++n;
368 }
369 else {
370 /* Normal char to be stored in buffer. Also
371 * update the newlinetypes flag if either this
372 * is an LF or the previous char was a CR.
373 */
374 if (c == '\n')
375 newlinetypes |= NEWLINE_LF;
376 else if (skipnextlf)
377 newlinetypes |= NEWLINE_CR;
378 *dst++ = c;
379 skipnextlf = 0;
380 }
381 }
382 if (shortread) {
383 /* If this is EOF, update type flags. */
384 if (skipnextlf && *bzerror == BZ_STREAM_END)
385 newlinetypes |= NEWLINE_CR;
386 break;
387 }
388 }
389 f->f_newlinetypes = newlinetypes;
390 f->f_skipnextlf = skipnextlf;
391 return dst - buf;
392}
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000393
394/* This is a hacked version of Python's fileobject.c:drop_readahead(). */
395static void
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000396Util_DropReadAhead(BZ2FileObject *f)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000397{
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000398 if (f->f_buf != NULL) {
399 PyMem_Free(f->f_buf);
400 f->f_buf = NULL;
401 }
402}
403
404/* This is a hacked version of Python's fileobject.c:readahead(). */
405static int
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000406Util_ReadAhead(BZ2FileObject *f, int bufsize)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000407{
408 int chunksize;
409 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000410
411 if (f->f_buf != NULL) {
Tim Peterse3228092002-11-09 04:21:44 +0000412 if((f->f_bufend - f->f_bufptr) >= 1)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000413 return 0;
414 else
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000415 Util_DropReadAhead(f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000416 }
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000417 if (f->mode == MODE_READ_EOF) {
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000418 f->f_bufptr = f->f_buf;
419 f->f_bufend = f->f_buf;
420 return 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000421 }
422 if ((f->f_buf = PyMem_Malloc(bufsize)) == NULL) {
423 return -1;
424 }
425 Py_BEGIN_ALLOW_THREADS
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000426 chunksize = Util_UnivNewlineRead(&bzerror, f->fp, f->f_buf,
427 bufsize, f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000428 Py_END_ALLOW_THREADS
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000429 f->pos += chunksize;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000430 if (bzerror == BZ_STREAM_END) {
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000431 f->size = f->pos;
432 f->mode = MODE_READ_EOF;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000433 } else if (bzerror != BZ_OK) {
434 Util_CatchBZ2Error(bzerror);
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000435 Util_DropReadAhead(f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000436 return -1;
437 }
438 f->f_bufptr = f->f_buf;
439 f->f_bufend = f->f_buf + chunksize;
440 return 0;
441}
442
443/* This is a hacked version of Python's
444 * fileobject.c:readahead_get_line_skip(). */
445static PyStringObject *
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000446Util_ReadAheadGetLineSkip(BZ2FileObject *f, int skip, int bufsize)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000447{
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000448 PyStringObject* s;
449 char *bufptr;
450 char *buf;
451 int len;
452
453 if (f->f_buf == NULL)
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000454 if (Util_ReadAhead(f, bufsize) < 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000455 return NULL;
456
457 len = f->f_bufend - f->f_bufptr;
Tim Peterse3228092002-11-09 04:21:44 +0000458 if (len == 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000459 return (PyStringObject *)
460 PyString_FromStringAndSize(NULL, skip);
461 bufptr = memchr(f->f_bufptr, '\n', len);
462 if (bufptr != NULL) {
463 bufptr++; /* Count the '\n' */
464 len = bufptr - f->f_bufptr;
465 s = (PyStringObject *)
466 PyString_FromStringAndSize(NULL, skip+len);
Tim Peterse3228092002-11-09 04:21:44 +0000467 if (s == NULL)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000468 return NULL;
469 memcpy(PyString_AS_STRING(s)+skip, f->f_bufptr, len);
470 f->f_bufptr = bufptr;
471 if (bufptr == f->f_bufend)
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000472 Util_DropReadAhead(f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000473 } else {
474 bufptr = f->f_bufptr;
475 buf = f->f_buf;
476 f->f_buf = NULL; /* Force new readahead buffer */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000477 s = Util_ReadAheadGetLineSkip(f, skip+len,
478 bufsize + (bufsize>>2));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000479 if (s == NULL) {
480 PyMem_Free(buf);
481 return NULL;
482 }
483 memcpy(PyString_AS_STRING(s)+skip, bufptr, len);
484 PyMem_Free(buf);
485 }
486 return s;
487}
488
489/* ===================================================================== */
490/* Methods of BZ2File. */
491
492PyDoc_STRVAR(BZ2File_read__doc__,
493"read([size]) -> string\n\
494\n\
495Read at most size uncompressed bytes, returned as a string. If the size\n\
496argument is negative or omitted, read until EOF is reached.\n\
497");
498
499/* This is a hacked version of Python's fileobject.c:file_read(). */
500static PyObject *
501BZ2File_read(BZ2FileObject *self, PyObject *args)
502{
503 long bytesrequested = -1;
504 size_t bytesread, buffersize, chunksize;
505 int bzerror;
506 PyObject *ret = NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000507
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000508 if (!PyArg_ParseTuple(args, "|l:read", &bytesrequested))
509 return NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000510
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000511 ACQUIRE_LOCK(self);
512 switch (self->mode) {
513 case MODE_READ:
514 break;
515 case MODE_READ_EOF:
516 ret = PyString_FromString("");
517 goto cleanup;
518 case MODE_CLOSED:
519 PyErr_SetString(PyExc_ValueError,
520 "I/O operation on closed file");
521 goto cleanup;
522 default:
523 PyErr_SetString(PyExc_IOError,
524 "file is not ready for reading");
525 goto cleanup;
526 }
527
528 if (bytesrequested < 0)
529 buffersize = Util_NewBufferSize((size_t)0);
530 else
531 buffersize = bytesrequested;
532 if (buffersize > INT_MAX) {
533 PyErr_SetString(PyExc_OverflowError,
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +0000534 "requested number of bytes is "
535 "more than a Python string can hold");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000536 goto cleanup;
537 }
538 ret = PyString_FromStringAndSize((char *)NULL, buffersize);
539 if (ret == NULL)
540 goto cleanup;
541 bytesread = 0;
542
543 for (;;) {
544 Py_BEGIN_ALLOW_THREADS
545 chunksize = Util_UnivNewlineRead(&bzerror, self->fp,
546 BUF(ret)+bytesread,
547 buffersize-bytesread,
548 self);
549 self->pos += chunksize;
550 Py_END_ALLOW_THREADS
551 bytesread += chunksize;
552 if (bzerror == BZ_STREAM_END) {
553 self->size = self->pos;
554 self->mode = MODE_READ_EOF;
555 break;
556 } else if (bzerror != BZ_OK) {
557 Util_CatchBZ2Error(bzerror);
558 Py_DECREF(ret);
559 ret = NULL;
560 goto cleanup;
561 }
562 if (bytesrequested < 0) {
563 buffersize = Util_NewBufferSize(buffersize);
564 if (_PyString_Resize(&ret, buffersize) < 0)
565 goto cleanup;
566 } else {
567 break;
568 }
569 }
570 if (bytesread != buffersize)
571 _PyString_Resize(&ret, bytesread);
572
573cleanup:
574 RELEASE_LOCK(self);
575 return ret;
576}
577
578PyDoc_STRVAR(BZ2File_readline__doc__,
579"readline([size]) -> string\n\
580\n\
581Return the next line from the file, as a string, retaining newline.\n\
582A non-negative size argument will limit the maximum number of bytes to\n\
583return (an incomplete line may be returned then). Return an empty\n\
584string at EOF.\n\
585");
586
587static PyObject *
588BZ2File_readline(BZ2FileObject *self, PyObject *args)
589{
590 PyObject *ret = NULL;
591 int sizehint = -1;
592
593 if (!PyArg_ParseTuple(args, "|i:readline", &sizehint))
594 return NULL;
595
596 ACQUIRE_LOCK(self);
597 switch (self->mode) {
598 case MODE_READ:
599 break;
600 case MODE_READ_EOF:
601 ret = PyString_FromString("");
602 goto cleanup;
603 case MODE_CLOSED:
604 PyErr_SetString(PyExc_ValueError,
605 "I/O operation on closed file");
606 goto cleanup;
607 default:
608 PyErr_SetString(PyExc_IOError,
609 "file is not ready for reading");
610 goto cleanup;
611 }
612
613 if (sizehint == 0)
614 ret = PyString_FromString("");
615 else
616 ret = Util_GetLine(self, (sizehint < 0) ? 0 : sizehint);
617
618cleanup:
619 RELEASE_LOCK(self);
620 return ret;
621}
622
623PyDoc_STRVAR(BZ2File_readlines__doc__,
624"readlines([size]) -> list\n\
625\n\
626Call readline() repeatedly and return a list of lines read.\n\
627The optional size argument, if given, is an approximate bound on the\n\
628total number of bytes in the lines returned.\n\
629");
630
631/* This is a hacked version of Python's fileobject.c:file_readlines(). */
632static PyObject *
633BZ2File_readlines(BZ2FileObject *self, PyObject *args)
634{
635 long sizehint = 0;
636 PyObject *list = NULL;
637 PyObject *line;
638 char small_buffer[SMALLCHUNK];
639 char *buffer = small_buffer;
640 size_t buffersize = SMALLCHUNK;
641 PyObject *big_buffer = NULL;
642 size_t nfilled = 0;
643 size_t nread;
644 size_t totalread = 0;
645 char *p, *q, *end;
646 int err;
647 int shortread = 0;
648 int bzerror;
649
650 if (!PyArg_ParseTuple(args, "|l:readlines", &sizehint))
651 return NULL;
652
653 ACQUIRE_LOCK(self);
654 switch (self->mode) {
655 case MODE_READ:
656 break;
657 case MODE_READ_EOF:
658 list = PyList_New(0);
659 goto cleanup;
660 case MODE_CLOSED:
661 PyErr_SetString(PyExc_ValueError,
662 "I/O operation on closed file");
663 goto cleanup;
664 default:
665 PyErr_SetString(PyExc_IOError,
666 "file is not ready for reading");
667 goto cleanup;
668 }
669
670 if ((list = PyList_New(0)) == NULL)
671 goto cleanup;
672
673 for (;;) {
674 Py_BEGIN_ALLOW_THREADS
675 nread = Util_UnivNewlineRead(&bzerror, self->fp,
676 buffer+nfilled,
677 buffersize-nfilled, self);
678 self->pos += nread;
679 Py_END_ALLOW_THREADS
680 if (bzerror == BZ_STREAM_END) {
681 self->size = self->pos;
682 self->mode = MODE_READ_EOF;
683 if (nread == 0) {
684 sizehint = 0;
685 break;
686 }
687 shortread = 1;
688 } else if (bzerror != BZ_OK) {
689 Util_CatchBZ2Error(bzerror);
690 error:
691 Py_DECREF(list);
692 list = NULL;
693 goto cleanup;
694 }
695 totalread += nread;
696 p = memchr(buffer+nfilled, '\n', nread);
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000697 if (!shortread && p == NULL) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000698 /* Need a larger buffer to fit this line */
699 nfilled += nread;
700 buffersize *= 2;
701 if (buffersize > INT_MAX) {
702 PyErr_SetString(PyExc_OverflowError,
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000703 "line is longer than a Python string can hold");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000704 goto error;
705 }
706 if (big_buffer == NULL) {
707 /* Create the big buffer */
708 big_buffer = PyString_FromStringAndSize(
709 NULL, buffersize);
710 if (big_buffer == NULL)
711 goto error;
712 buffer = PyString_AS_STRING(big_buffer);
713 memcpy(buffer, small_buffer, nfilled);
714 }
715 else {
716 /* Grow the big buffer */
717 _PyString_Resize(&big_buffer, buffersize);
718 buffer = PyString_AS_STRING(big_buffer);
719 }
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000720 continue;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000721 }
722 end = buffer+nfilled+nread;
723 q = buffer;
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000724 while (p != NULL) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000725 /* Process complete lines */
726 p++;
727 line = PyString_FromStringAndSize(q, p-q);
728 if (line == NULL)
729 goto error;
730 err = PyList_Append(list, line);
731 Py_DECREF(line);
732 if (err != 0)
733 goto error;
734 q = p;
735 p = memchr(q, '\n', end-q);
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000736 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000737 /* Move the remaining incomplete line to the start */
738 nfilled = end-q;
739 memmove(buffer, q, nfilled);
740 if (sizehint > 0)
741 if (totalread >= (size_t)sizehint)
742 break;
743 if (shortread) {
744 sizehint = 0;
745 break;
746 }
747 }
748 if (nfilled != 0) {
749 /* Partial last line */
750 line = PyString_FromStringAndSize(buffer, nfilled);
751 if (line == NULL)
752 goto error;
753 if (sizehint > 0) {
754 /* Need to complete the last line */
755 PyObject *rest = Util_GetLine(self, 0);
756 if (rest == NULL) {
757 Py_DECREF(line);
758 goto error;
759 }
760 PyString_Concat(&line, rest);
761 Py_DECREF(rest);
762 if (line == NULL)
763 goto error;
764 }
765 err = PyList_Append(list, line);
766 Py_DECREF(line);
767 if (err != 0)
768 goto error;
769 }
770
771 cleanup:
772 RELEASE_LOCK(self);
773 if (big_buffer) {
774 Py_DECREF(big_buffer);
775 }
776 return list;
777}
778
779PyDoc_STRVAR(BZ2File_write__doc__,
780"write(data) -> None\n\
781\n\
782Write the 'data' string to file. Note that due to buffering, close() may\n\
783be needed before the file on disk reflects the data written.\n\
784");
785
786/* This is a hacked version of Python's fileobject.c:file_write(). */
787static PyObject *
788BZ2File_write(BZ2FileObject *self, PyObject *args)
789{
790 PyObject *ret = NULL;
791 char *buf;
792 int len;
793 int bzerror;
794
Walter Dörwaldbb9c7392004-11-01 17:10:19 +0000795 if (!PyArg_ParseTuple(args, "s#:write", &buf, &len))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000796 return NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000797
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000798 ACQUIRE_LOCK(self);
799 switch (self->mode) {
800 case MODE_WRITE:
801 break;
Tim Peterse3228092002-11-09 04:21:44 +0000802
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000803 case MODE_CLOSED:
804 PyErr_SetString(PyExc_ValueError,
805 "I/O operation on closed file");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000806 goto cleanup;
Tim Peterse3228092002-11-09 04:21:44 +0000807
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000808 default:
809 PyErr_SetString(PyExc_IOError,
810 "file is not ready for writing");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000811 goto cleanup;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000812 }
813
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000814 Py_BEGIN_ALLOW_THREADS
815 BZ2_bzWrite (&bzerror, self->fp, buf, len);
816 self->pos += len;
817 Py_END_ALLOW_THREADS
Tim Peterse3228092002-11-09 04:21:44 +0000818
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000819 if (bzerror != BZ_OK) {
820 Util_CatchBZ2Error(bzerror);
821 goto cleanup;
822 }
Tim Peterse3228092002-11-09 04:21:44 +0000823
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000824 Py_INCREF(Py_None);
825 ret = Py_None;
826
827cleanup:
828 RELEASE_LOCK(self);
829 return ret;
830}
831
832PyDoc_STRVAR(BZ2File_writelines__doc__,
833"writelines(sequence_of_strings) -> None\n\
834\n\
835Write the sequence of strings to the file. Note that newlines are not\n\
836added. The sequence can be any iterable object producing strings. This is\n\
837equivalent to calling write() for each string.\n\
838");
839
840/* This is a hacked version of Python's fileobject.c:file_writelines(). */
841static PyObject *
842BZ2File_writelines(BZ2FileObject *self, PyObject *seq)
843{
844#define CHUNKSIZE 1000
845 PyObject *list = NULL;
846 PyObject *iter = NULL;
847 PyObject *ret = NULL;
848 PyObject *line;
849 int i, j, index, len, islist;
850 int bzerror;
851
852 ACQUIRE_LOCK(self);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000853 switch (self->mode) {
854 case MODE_WRITE:
855 break;
856
857 case MODE_CLOSED:
858 PyErr_SetString(PyExc_ValueError,
859 "I/O operation on closed file");
860 goto error;
861
862 default:
863 PyErr_SetString(PyExc_IOError,
864 "file is not ready for writing");
865 goto error;
866 }
867
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000868 islist = PyList_Check(seq);
869 if (!islist) {
870 iter = PyObject_GetIter(seq);
871 if (iter == NULL) {
872 PyErr_SetString(PyExc_TypeError,
873 "writelines() requires an iterable argument");
874 goto error;
875 }
876 list = PyList_New(CHUNKSIZE);
877 if (list == NULL)
878 goto error;
879 }
880
881 /* Strategy: slurp CHUNKSIZE lines into a private list,
882 checking that they are all strings, then write that list
883 without holding the interpreter lock, then come back for more. */
884 for (index = 0; ; index += CHUNKSIZE) {
885 if (islist) {
886 Py_XDECREF(list);
887 list = PyList_GetSlice(seq, index, index+CHUNKSIZE);
888 if (list == NULL)
889 goto error;
890 j = PyList_GET_SIZE(list);
891 }
892 else {
893 for (j = 0; j < CHUNKSIZE; j++) {
894 line = PyIter_Next(iter);
895 if (line == NULL) {
896 if (PyErr_Occurred())
897 goto error;
898 break;
899 }
900 PyList_SetItem(list, j, line);
901 }
902 }
903 if (j == 0)
904 break;
905
906 /* Check that all entries are indeed strings. If not,
907 apply the same rules as for file.write() and
908 convert the rets to strings. This is slow, but
909 seems to be the only way since all conversion APIs
910 could potentially execute Python code. */
911 for (i = 0; i < j; i++) {
912 PyObject *v = PyList_GET_ITEM(list, i);
913 if (!PyString_Check(v)) {
914 const char *buffer;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000915 Py_ssize_t len;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000916 if (PyObject_AsCharBuffer(v, &buffer, &len)) {
917 PyErr_SetString(PyExc_TypeError,
918 "writelines() "
919 "argument must be "
920 "a sequence of "
921 "strings");
922 goto error;
923 }
924 line = PyString_FromStringAndSize(buffer,
925 len);
926 if (line == NULL)
927 goto error;
928 Py_DECREF(v);
929 PyList_SET_ITEM(list, i, line);
930 }
931 }
932
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000933 /* Since we are releasing the global lock, the
934 following code may *not* execute Python code. */
935 Py_BEGIN_ALLOW_THREADS
936 for (i = 0; i < j; i++) {
937 line = PyList_GET_ITEM(list, i);
938 len = PyString_GET_SIZE(line);
939 BZ2_bzWrite (&bzerror, self->fp,
940 PyString_AS_STRING(line), len);
941 if (bzerror != BZ_OK) {
942 Py_BLOCK_THREADS
943 Util_CatchBZ2Error(bzerror);
944 goto error;
945 }
946 }
947 Py_END_ALLOW_THREADS
948
949 if (j < CHUNKSIZE)
950 break;
951 }
952
953 Py_INCREF(Py_None);
954 ret = Py_None;
955
956 error:
957 RELEASE_LOCK(self);
958 Py_XDECREF(list);
959 Py_XDECREF(iter);
960 return ret;
961#undef CHUNKSIZE
962}
963
964PyDoc_STRVAR(BZ2File_seek__doc__,
965"seek(offset [, whence]) -> None\n\
966\n\
967Move to new file position. Argument offset is a byte count. Optional\n\
968argument whence defaults to 0 (offset from start of file, offset\n\
969should be >= 0); other values are 1 (move relative to current position,\n\
970positive or negative), and 2 (move relative to end of file, usually\n\
971negative, although many platforms allow seeking beyond the end of a file).\n\
972\n\
973Note that seeking of bz2 files is emulated, and depending on the parameters\n\
974the operation may be extremely slow.\n\
975");
976
977static PyObject *
978BZ2File_seek(BZ2FileObject *self, PyObject *args)
979{
980 int where = 0;
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000981 PyObject *offobj;
982 Py_off_t offset;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000983 char small_buffer[SMALLCHUNK];
984 char *buffer = small_buffer;
985 size_t buffersize = SMALLCHUNK;
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000986 Py_off_t bytesread = 0;
Georg Brandla8bcecc2005-09-03 07:49:53 +0000987 size_t readsize;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000988 int chunksize;
989 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000990 PyObject *ret = NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000991
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000992 if (!PyArg_ParseTuple(args, "O|i:seek", &offobj, &where))
993 return NULL;
994#if !defined(HAVE_LARGEFILE_SUPPORT)
995 offset = PyInt_AsLong(offobj);
996#else
997 offset = PyLong_Check(offobj) ?
998 PyLong_AsLongLong(offobj) : PyInt_AsLong(offobj);
999#endif
1000 if (PyErr_Occurred())
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001001 return NULL;
1002
1003 ACQUIRE_LOCK(self);
1004 Util_DropReadAhead(self);
1005 switch (self->mode) {
1006 case MODE_READ:
1007 case MODE_READ_EOF:
1008 break;
Tim Peterse3228092002-11-09 04:21:44 +00001009
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001010 case MODE_CLOSED:
1011 PyErr_SetString(PyExc_ValueError,
1012 "I/O operation on closed file");
Thomas Wouters89f507f2006-12-13 04:49:30 +00001013 goto cleanup;
Tim Peterse3228092002-11-09 04:21:44 +00001014
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001015 default:
1016 PyErr_SetString(PyExc_IOError,
1017 "seek works only while reading");
Thomas Wouters89f507f2006-12-13 04:49:30 +00001018 goto cleanup;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001019 }
1020
Georg Brandl47fab922006-02-18 21:57:25 +00001021 if (where == 2) {
1022 if (self->size == -1) {
1023 assert(self->mode != MODE_READ_EOF);
1024 for (;;) {
1025 Py_BEGIN_ALLOW_THREADS
1026 chunksize = Util_UnivNewlineRead(
1027 &bzerror, self->fp,
1028 buffer, buffersize,
1029 self);
1030 self->pos += chunksize;
1031 Py_END_ALLOW_THREADS
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001032
Georg Brandl47fab922006-02-18 21:57:25 +00001033 bytesread += chunksize;
1034 if (bzerror == BZ_STREAM_END) {
1035 break;
1036 } else if (bzerror != BZ_OK) {
1037 Util_CatchBZ2Error(bzerror);
1038 goto cleanup;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001039 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001040 }
Georg Brandl47fab922006-02-18 21:57:25 +00001041 self->mode = MODE_READ_EOF;
1042 self->size = self->pos;
1043 bytesread = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001044 }
Georg Brandl47fab922006-02-18 21:57:25 +00001045 offset = self->size + offset;
1046 } else if (where == 1) {
1047 offset = self->pos + offset;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001048 }
1049
Georg Brandl47fab922006-02-18 21:57:25 +00001050 /* Before getting here, offset must be the absolute position the file
1051 * pointer should be set to. */
1052
1053 if (offset >= self->pos) {
1054 /* we can move forward */
1055 offset -= self->pos;
1056 } else {
1057 /* we cannot move back, so rewind the stream */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001058 BZ2_bzReadClose(&bzerror, self->fp);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001059 if (bzerror != BZ_OK) {
1060 Util_CatchBZ2Error(bzerror);
1061 goto cleanup;
1062 }
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001063 ret = PyObject_CallMethod(self->file, "seek", "(i)", 0);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001064 if (!ret)
1065 goto cleanup;
1066 Py_DECREF(ret);
1067 ret = NULL;
1068 self->pos = 0;
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001069 self->fp = BZ2_bzReadOpen(&bzerror, PyFile_AsFile(self->file),
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001070 0, 0, NULL, 0);
1071 if (bzerror != BZ_OK) {
1072 Util_CatchBZ2Error(bzerror);
1073 goto cleanup;
1074 }
1075 self->mode = MODE_READ;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001076 }
1077
Georg Brandl47fab922006-02-18 21:57:25 +00001078 if (offset <= 0 || self->mode == MODE_READ_EOF)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001079 goto exit;
1080
1081 /* Before getting here, offset must be set to the number of bytes
1082 * to walk forward. */
1083 for (;;) {
Georg Brandla8bcecc2005-09-03 07:49:53 +00001084 if (offset-bytesread > buffersize)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001085 readsize = buffersize;
1086 else
Georg Brandla8bcecc2005-09-03 07:49:53 +00001087 /* offset might be wider that readsize, but the result
1088 * of the subtraction is bound by buffersize (see the
1089 * condition above). buffersize is 8192. */
1090 readsize = (size_t)(offset-bytesread);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001091 Py_BEGIN_ALLOW_THREADS
1092 chunksize = Util_UnivNewlineRead(&bzerror, self->fp,
1093 buffer, readsize, self);
1094 self->pos += chunksize;
1095 Py_END_ALLOW_THREADS
1096 bytesread += chunksize;
1097 if (bzerror == BZ_STREAM_END) {
1098 self->size = self->pos;
1099 self->mode = MODE_READ_EOF;
1100 break;
1101 } else if (bzerror != BZ_OK) {
1102 Util_CatchBZ2Error(bzerror);
1103 goto cleanup;
1104 }
1105 if (bytesread == offset)
1106 break;
1107 }
1108
1109exit:
1110 Py_INCREF(Py_None);
1111 ret = Py_None;
1112
1113cleanup:
1114 RELEASE_LOCK(self);
1115 return ret;
1116}
1117
1118PyDoc_STRVAR(BZ2File_tell__doc__,
1119"tell() -> int\n\
1120\n\
1121Return the current file position, an integer (may be a long integer).\n\
1122");
1123
1124static PyObject *
1125BZ2File_tell(BZ2FileObject *self, PyObject *args)
1126{
1127 PyObject *ret = NULL;
1128
1129 if (self->mode == MODE_CLOSED) {
1130 PyErr_SetString(PyExc_ValueError,
1131 "I/O operation on closed file");
1132 goto cleanup;
1133 }
1134
Georg Brandla8bcecc2005-09-03 07:49:53 +00001135#if !defined(HAVE_LARGEFILE_SUPPORT)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001136 ret = PyInt_FromLong(self->pos);
Georg Brandla8bcecc2005-09-03 07:49:53 +00001137#else
1138 ret = PyLong_FromLongLong(self->pos);
1139#endif
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001140
1141cleanup:
1142 return ret;
1143}
1144
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001145PyDoc_STRVAR(BZ2File_close__doc__,
1146"close() -> None or (perhaps) an integer\n\
1147\n\
1148Close the file. Sets data attribute .closed to true. A closed file\n\
1149cannot be used for further I/O operations. close() may be called more\n\
1150than once without error.\n\
1151");
1152
1153static PyObject *
1154BZ2File_close(BZ2FileObject *self)
1155{
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001156 PyObject *ret = NULL;
1157 int bzerror = BZ_OK;
1158
1159 ACQUIRE_LOCK(self);
1160 switch (self->mode) {
1161 case MODE_READ:
1162 case MODE_READ_EOF:
1163 BZ2_bzReadClose(&bzerror, self->fp);
1164 break;
1165 case MODE_WRITE:
1166 BZ2_bzWriteClose(&bzerror, self->fp,
1167 0, NULL, NULL);
1168 break;
1169 }
1170 self->mode = MODE_CLOSED;
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001171 ret = PyObject_CallMethod(self->file, "close", NULL);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001172 if (bzerror != BZ_OK) {
1173 Util_CatchBZ2Error(bzerror);
1174 Py_XDECREF(ret);
1175 ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001176 }
1177
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001178 RELEASE_LOCK(self);
1179 return ret;
1180}
1181
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001182static PyObject *BZ2File_getiter(BZ2FileObject *self);
1183
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001184static PyMethodDef BZ2File_methods[] = {
1185 {"read", (PyCFunction)BZ2File_read, METH_VARARGS, BZ2File_read__doc__},
1186 {"readline", (PyCFunction)BZ2File_readline, METH_VARARGS, BZ2File_readline__doc__},
1187 {"readlines", (PyCFunction)BZ2File_readlines, METH_VARARGS, BZ2File_readlines__doc__},
1188 {"write", (PyCFunction)BZ2File_write, METH_VARARGS, BZ2File_write__doc__},
1189 {"writelines", (PyCFunction)BZ2File_writelines, METH_O, BZ2File_writelines__doc__},
1190 {"seek", (PyCFunction)BZ2File_seek, METH_VARARGS, BZ2File_seek__doc__},
1191 {"tell", (PyCFunction)BZ2File_tell, METH_NOARGS, BZ2File_tell__doc__},
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001192 {"close", (PyCFunction)BZ2File_close, METH_NOARGS, BZ2File_close__doc__},
1193 {NULL, NULL} /* sentinel */
1194};
1195
1196
1197/* ===================================================================== */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001198/* Getters and setters of BZ2File. */
1199
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001200/* This is a hacked version of Python's fileobject.c:get_newlines(). */
1201static PyObject *
1202BZ2File_get_newlines(BZ2FileObject *self, void *closure)
1203{
1204 switch (self->f_newlinetypes) {
1205 case NEWLINE_UNKNOWN:
1206 Py_INCREF(Py_None);
1207 return Py_None;
1208 case NEWLINE_CR:
1209 return PyString_FromString("\r");
1210 case NEWLINE_LF:
1211 return PyString_FromString("\n");
1212 case NEWLINE_CR|NEWLINE_LF:
1213 return Py_BuildValue("(ss)", "\r", "\n");
1214 case NEWLINE_CRLF:
1215 return PyString_FromString("\r\n");
1216 case NEWLINE_CR|NEWLINE_CRLF:
1217 return Py_BuildValue("(ss)", "\r", "\r\n");
1218 case NEWLINE_LF|NEWLINE_CRLF:
1219 return Py_BuildValue("(ss)", "\n", "\r\n");
1220 case NEWLINE_CR|NEWLINE_LF|NEWLINE_CRLF:
1221 return Py_BuildValue("(sss)", "\r", "\n", "\r\n");
1222 default:
1223 PyErr_Format(PyExc_SystemError,
1224 "Unknown newlines value 0x%x\n",
1225 self->f_newlinetypes);
1226 return NULL;
1227 }
1228}
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001229
1230static PyObject *
1231BZ2File_get_closed(BZ2FileObject *self, void *closure)
1232{
1233 return PyInt_FromLong(self->mode == MODE_CLOSED);
1234}
1235
1236static PyObject *
1237BZ2File_get_mode(BZ2FileObject *self, void *closure)
1238{
1239 return PyObject_GetAttrString(self->file, "mode");
1240}
1241
1242static PyObject *
1243BZ2File_get_name(BZ2FileObject *self, void *closure)
1244{
1245 return PyObject_GetAttrString(self->file, "name");
1246}
1247
1248static PyGetSetDef BZ2File_getset[] = {
1249 {"closed", (getter)BZ2File_get_closed, NULL,
1250 "True if the file is closed"},
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001251 {"newlines", (getter)BZ2File_get_newlines, NULL,
1252 "end-of-line convention used in this file"},
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001253 {"mode", (getter)BZ2File_get_mode, NULL,
1254 "file mode ('r', 'w', or 'U')"},
1255 {"name", (getter)BZ2File_get_name, NULL,
1256 "file name"},
1257 {NULL} /* Sentinel */
1258};
1259
1260
1261/* ===================================================================== */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001262/* Slot definitions for BZ2File_Type. */
1263
1264static int
1265BZ2File_init(BZ2FileObject *self, PyObject *args, PyObject *kwargs)
1266{
Martin v. Löwis15e62742006-02-27 16:46:16 +00001267 static char *kwlist[] = {"filename", "mode", "buffering",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001268 "compresslevel", 0};
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001269 PyObject *name;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001270 char *mode = "r";
1271 int buffering = -1;
1272 int compresslevel = 9;
1273 int bzerror;
1274 int mode_char = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001275
1276 self->size = -1;
Tim Peterse3228092002-11-09 04:21:44 +00001277
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001278 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|sii:BZ2File",
1279 kwlist, &name, &mode, &buffering,
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001280 &compresslevel))
1281 return -1;
1282
1283 if (compresslevel < 1 || compresslevel > 9) {
1284 PyErr_SetString(PyExc_ValueError,
1285 "compresslevel must be between 1 and 9");
1286 return -1;
1287 }
1288
1289 for (;;) {
1290 int error = 0;
1291 switch (*mode) {
1292 case 'r':
1293 case 'w':
1294 if (mode_char)
1295 error = 1;
1296 mode_char = *mode;
1297 break;
1298
1299 case 'b':
1300 break;
1301
1302 case 'U':
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001303#ifdef __VMS
1304 self->f_univ_newline = 0;
1305#else
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001306 self->f_univ_newline = 1;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001307#endif
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001308 break;
1309
1310 default:
1311 error = 1;
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001312 break;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001313 }
1314 if (error) {
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001315 PyErr_Format(PyExc_ValueError,
1316 "invalid mode char %c", *mode);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001317 return -1;
1318 }
1319 mode++;
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001320 if (*mode == '\0')
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001321 break;
1322 }
1323
Georg Brandl6b95f1d2005-06-03 19:47:00 +00001324 if (mode_char == 0) {
1325 mode_char = 'r';
1326 }
1327
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001328 mode = (mode_char == 'r') ? "rb" : "wb";
Tim Peterse3228092002-11-09 04:21:44 +00001329
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001330 self->file = PyObject_CallFunction((PyObject*)&PyFile_Type, "(Osi)",
1331 name, mode, buffering);
1332 if (self->file == NULL)
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001333 return -1;
1334
1335 /* From now on, we have stuff to dealloc, so jump to error label
1336 * instead of returning */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001337
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001338#ifdef WITH_THREAD
1339 self->lock = PyThread_allocate_lock();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001340 if (!self->lock) {
1341 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001342 goto error;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001343 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001344#endif
1345
1346 if (mode_char == 'r')
1347 self->fp = BZ2_bzReadOpen(&bzerror,
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001348 PyFile_AsFile(self->file),
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001349 0, 0, NULL, 0);
1350 else
1351 self->fp = BZ2_bzWriteOpen(&bzerror,
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001352 PyFile_AsFile(self->file),
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001353 compresslevel, 0, 0);
1354
1355 if (bzerror != BZ_OK) {
1356 Util_CatchBZ2Error(bzerror);
1357 goto error;
1358 }
1359
1360 self->mode = (mode_char == 'r') ? MODE_READ : MODE_WRITE;
1361
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001362 return 0;
1363
1364error:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001365 Py_CLEAR(self->file);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001366#ifdef WITH_THREAD
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001367 if (self->lock) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001368 PyThread_free_lock(self->lock);
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001369 self->lock = NULL;
1370 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001371#endif
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001372 return -1;
1373}
1374
1375static void
1376BZ2File_dealloc(BZ2FileObject *self)
1377{
1378 int bzerror;
1379#ifdef WITH_THREAD
1380 if (self->lock)
1381 PyThread_free_lock(self->lock);
1382#endif
1383 switch (self->mode) {
1384 case MODE_READ:
1385 case MODE_READ_EOF:
1386 BZ2_bzReadClose(&bzerror, self->fp);
1387 break;
1388 case MODE_WRITE:
1389 BZ2_bzWriteClose(&bzerror, self->fp,
1390 0, NULL, NULL);
1391 break;
1392 }
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001393 Util_DropReadAhead(self);
Gustavo Niemeyer572f5232003-04-29 14:53:08 +00001394 Py_XDECREF(self->file);
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001395 self->ob_type->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001396}
1397
1398/* This is a hacked version of Python's fileobject.c:file_getiter(). */
1399static PyObject *
1400BZ2File_getiter(BZ2FileObject *self)
1401{
1402 if (self->mode == MODE_CLOSED) {
1403 PyErr_SetString(PyExc_ValueError,
1404 "I/O operation on closed file");
1405 return NULL;
1406 }
1407 Py_INCREF((PyObject*)self);
1408 return (PyObject *)self;
1409}
1410
1411/* This is a hacked version of Python's fileobject.c:file_iternext(). */
1412#define READAHEAD_BUFSIZE 8192
1413static PyObject *
1414BZ2File_iternext(BZ2FileObject *self)
1415{
1416 PyStringObject* ret;
1417 ACQUIRE_LOCK(self);
1418 if (self->mode == MODE_CLOSED) {
1419 PyErr_SetString(PyExc_ValueError,
1420 "I/O operation on closed file");
1421 return NULL;
1422 }
1423 ret = Util_ReadAheadGetLineSkip(self, 0, READAHEAD_BUFSIZE);
1424 RELEASE_LOCK(self);
1425 if (ret == NULL || PyString_GET_SIZE(ret) == 0) {
1426 Py_XDECREF(ret);
1427 return NULL;
1428 }
1429 return (PyObject *)ret;
1430}
1431
1432/* ===================================================================== */
1433/* BZ2File_Type definition. */
1434
1435PyDoc_VAR(BZ2File__doc__) =
1436PyDoc_STR(
1437"BZ2File(name [, mode='r', buffering=0, compresslevel=9]) -> file object\n\
1438\n\
1439Open a bz2 file. The mode can be 'r' or 'w', for reading (default) or\n\
1440writing. When opened for writing, the file will be created if it doesn't\n\
1441exist, and truncated otherwise. If the buffering argument is given, 0 means\n\
1442unbuffered, and larger numbers specify the buffer size. If compresslevel\n\
1443is given, must be a number between 1 and 9.\n\
1444")
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001445PyDoc_STR(
1446"\n\
1447Add a 'U' to mode to open the file for input with universal newline\n\
1448support. Any line ending in the input file will be seen as a '\\n' in\n\
1449Python. Also, a file so opened gains the attribute 'newlines'; the value\n\
1450for this attribute is one of None (no newline read yet), '\\r', '\\n',\n\
1451'\\r\\n' or a tuple containing all the newline types seen. Universal\n\
1452newlines are available only when reading.\n\
1453")
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001454;
1455
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001456static PyTypeObject BZ2File_Type = {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001457 PyObject_HEAD_INIT(NULL)
1458 0, /*ob_size*/
1459 "bz2.BZ2File", /*tp_name*/
1460 sizeof(BZ2FileObject), /*tp_basicsize*/
1461 0, /*tp_itemsize*/
1462 (destructor)BZ2File_dealloc, /*tp_dealloc*/
1463 0, /*tp_print*/
1464 0, /*tp_getattr*/
1465 0, /*tp_setattr*/
1466 0, /*tp_compare*/
1467 0, /*tp_repr*/
1468 0, /*tp_as_number*/
1469 0, /*tp_as_sequence*/
1470 0, /*tp_as_mapping*/
1471 0, /*tp_hash*/
1472 0, /*tp_call*/
1473 0, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001474 PyObject_GenericGetAttr,/*tp_getattro*/
1475 PyObject_GenericSetAttr,/*tp_setattro*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001476 0, /*tp_as_buffer*/
1477 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1478 BZ2File__doc__, /*tp_doc*/
1479 0, /*tp_traverse*/
1480 0, /*tp_clear*/
1481 0, /*tp_richcompare*/
1482 0, /*tp_weaklistoffset*/
1483 (getiterfunc)BZ2File_getiter, /*tp_iter*/
1484 (iternextfunc)BZ2File_iternext, /*tp_iternext*/
1485 BZ2File_methods, /*tp_methods*/
Guido van Rossum79139b22007-02-09 23:20:19 +00001486 0, /*tp_members*/
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001487 BZ2File_getset, /*tp_getset*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001488 0, /*tp_base*/
1489 0, /*tp_dict*/
1490 0, /*tp_descr_get*/
1491 0, /*tp_descr_set*/
1492 0, /*tp_dictoffset*/
1493 (initproc)BZ2File_init, /*tp_init*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001494 PyType_GenericAlloc, /*tp_alloc*/
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001495 PyType_GenericNew, /*tp_new*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001496 _PyObject_Del, /*tp_free*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001497 0, /*tp_is_gc*/
1498};
1499
1500
1501/* ===================================================================== */
1502/* Methods of BZ2Comp. */
1503
1504PyDoc_STRVAR(BZ2Comp_compress__doc__,
1505"compress(data) -> string\n\
1506\n\
1507Provide more data to the compressor object. It will return chunks of\n\
1508compressed data whenever possible. When you've finished providing data\n\
1509to compress, call the flush() method to finish the compression process,\n\
1510and return what is left in the internal buffers.\n\
1511");
1512
1513static PyObject *
1514BZ2Comp_compress(BZ2CompObject *self, PyObject *args)
1515{
1516 char *data;
1517 int datasize;
1518 int bufsize = SMALLCHUNK;
Martin v. Löwisb9a0f912003-03-29 10:06:18 +00001519 PY_LONG_LONG totalout;
Gustavo Niemeyer7d7930b2002-11-05 18:41:53 +00001520 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001521 bz_stream *bzs = &self->bzs;
1522 int bzerror;
1523
Walter Dörwaldbb9c7392004-11-01 17:10:19 +00001524 if (!PyArg_ParseTuple(args, "s#:compress", &data, &datasize))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001525 return NULL;
1526
Gustavo Niemeyera6e436e2004-02-14 00:02:45 +00001527 if (datasize == 0)
1528 return PyString_FromString("");
1529
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001530 ACQUIRE_LOCK(self);
1531 if (!self->running) {
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001532 PyErr_SetString(PyExc_ValueError,
1533 "this object was already flushed");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001534 goto error;
1535 }
1536
1537 ret = PyString_FromStringAndSize(NULL, bufsize);
1538 if (!ret)
1539 goto error;
1540
1541 bzs->next_in = data;
1542 bzs->avail_in = datasize;
1543 bzs->next_out = BUF(ret);
1544 bzs->avail_out = bufsize;
1545
1546 totalout = BZS_TOTAL_OUT(bzs);
1547
1548 for (;;) {
1549 Py_BEGIN_ALLOW_THREADS
1550 bzerror = BZ2_bzCompress(bzs, BZ_RUN);
1551 Py_END_ALLOW_THREADS
1552 if (bzerror != BZ_RUN_OK) {
1553 Util_CatchBZ2Error(bzerror);
1554 goto error;
1555 }
Guido van Rossumd8faa362007-04-27 19:54:29 +00001556 if (bzs->avail_in == 0)
1557 break; /* no more input data */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001558 if (bzs->avail_out == 0) {
1559 bufsize = Util_NewBufferSize(bufsize);
1560 if (_PyString_Resize(&ret, bufsize) < 0) {
1561 BZ2_bzCompressEnd(bzs);
1562 goto error;
1563 }
1564 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs)
1565 - totalout);
1566 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001567 }
1568 }
1569
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001570 _PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001571
1572 RELEASE_LOCK(self);
1573 return ret;
1574
1575error:
1576 RELEASE_LOCK(self);
1577 Py_XDECREF(ret);
1578 return NULL;
1579}
1580
1581PyDoc_STRVAR(BZ2Comp_flush__doc__,
1582"flush() -> string\n\
1583\n\
1584Finish the compression process and return what is left in internal buffers.\n\
1585You must not use the compressor object after calling this method.\n\
1586");
1587
1588static PyObject *
1589BZ2Comp_flush(BZ2CompObject *self)
1590{
1591 int bufsize = SMALLCHUNK;
Gustavo Niemeyer7d7930b2002-11-05 18:41:53 +00001592 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001593 bz_stream *bzs = &self->bzs;
Martin v. Löwisb9a0f912003-03-29 10:06:18 +00001594 PY_LONG_LONG totalout;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001595 int bzerror;
1596
1597 ACQUIRE_LOCK(self);
1598 if (!self->running) {
1599 PyErr_SetString(PyExc_ValueError, "object was already "
1600 "flushed");
1601 goto error;
1602 }
1603 self->running = 0;
1604
1605 ret = PyString_FromStringAndSize(NULL, bufsize);
1606 if (!ret)
1607 goto error;
1608
1609 bzs->next_out = BUF(ret);
1610 bzs->avail_out = bufsize;
1611
1612 totalout = BZS_TOTAL_OUT(bzs);
1613
1614 for (;;) {
1615 Py_BEGIN_ALLOW_THREADS
1616 bzerror = BZ2_bzCompress(bzs, BZ_FINISH);
1617 Py_END_ALLOW_THREADS
1618 if (bzerror == BZ_STREAM_END) {
1619 break;
1620 } else if (bzerror != BZ_FINISH_OK) {
1621 Util_CatchBZ2Error(bzerror);
1622 goto error;
1623 }
1624 if (bzs->avail_out == 0) {
1625 bufsize = Util_NewBufferSize(bufsize);
1626 if (_PyString_Resize(&ret, bufsize) < 0)
1627 goto error;
1628 bzs->next_out = BUF(ret);
1629 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs)
1630 - totalout);
1631 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
1632 }
1633 }
1634
1635 if (bzs->avail_out != 0)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001636 _PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001637
1638 RELEASE_LOCK(self);
1639 return ret;
1640
1641error:
1642 RELEASE_LOCK(self);
1643 Py_XDECREF(ret);
1644 return NULL;
1645}
1646
1647static PyMethodDef BZ2Comp_methods[] = {
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001648 {"compress", (PyCFunction)BZ2Comp_compress, METH_VARARGS,
1649 BZ2Comp_compress__doc__},
1650 {"flush", (PyCFunction)BZ2Comp_flush, METH_NOARGS,
1651 BZ2Comp_flush__doc__},
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001652 {NULL, NULL} /* sentinel */
1653};
1654
1655
1656/* ===================================================================== */
1657/* Slot definitions for BZ2Comp_Type. */
1658
1659static int
1660BZ2Comp_init(BZ2CompObject *self, PyObject *args, PyObject *kwargs)
1661{
1662 int compresslevel = 9;
1663 int bzerror;
Martin v. Löwis15e62742006-02-27 16:46:16 +00001664 static char *kwlist[] = {"compresslevel", 0};
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001665
1666 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:BZ2Compressor",
1667 kwlist, &compresslevel))
1668 return -1;
1669
1670 if (compresslevel < 1 || compresslevel > 9) {
1671 PyErr_SetString(PyExc_ValueError,
1672 "compresslevel must be between 1 and 9");
1673 goto error;
1674 }
1675
1676#ifdef WITH_THREAD
1677 self->lock = PyThread_allocate_lock();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001678 if (!self->lock) {
1679 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001680 goto error;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001681 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001682#endif
1683
1684 memset(&self->bzs, 0, sizeof(bz_stream));
1685 bzerror = BZ2_bzCompressInit(&self->bzs, compresslevel, 0, 0);
1686 if (bzerror != BZ_OK) {
1687 Util_CatchBZ2Error(bzerror);
1688 goto error;
1689 }
1690
1691 self->running = 1;
1692
1693 return 0;
1694error:
1695#ifdef WITH_THREAD
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001696 if (self->lock) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001697 PyThread_free_lock(self->lock);
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001698 self->lock = NULL;
1699 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001700#endif
1701 return -1;
1702}
1703
1704static void
1705BZ2Comp_dealloc(BZ2CompObject *self)
1706{
1707#ifdef WITH_THREAD
1708 if (self->lock)
1709 PyThread_free_lock(self->lock);
1710#endif
1711 BZ2_bzCompressEnd(&self->bzs);
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001712 self->ob_type->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001713}
1714
1715
1716/* ===================================================================== */
1717/* BZ2Comp_Type definition. */
1718
1719PyDoc_STRVAR(BZ2Comp__doc__,
1720"BZ2Compressor([compresslevel=9]) -> compressor object\n\
1721\n\
1722Create a new compressor object. This object may be used to compress\n\
1723data sequentially. If you want to compress data in one shot, use the\n\
1724compress() function instead. The compresslevel parameter, if given,\n\
1725must be a number between 1 and 9.\n\
1726");
1727
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001728static PyTypeObject BZ2Comp_Type = {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001729 PyObject_HEAD_INIT(NULL)
1730 0, /*ob_size*/
1731 "bz2.BZ2Compressor", /*tp_name*/
1732 sizeof(BZ2CompObject), /*tp_basicsize*/
1733 0, /*tp_itemsize*/
1734 (destructor)BZ2Comp_dealloc, /*tp_dealloc*/
1735 0, /*tp_print*/
1736 0, /*tp_getattr*/
1737 0, /*tp_setattr*/
1738 0, /*tp_compare*/
1739 0, /*tp_repr*/
1740 0, /*tp_as_number*/
1741 0, /*tp_as_sequence*/
1742 0, /*tp_as_mapping*/
1743 0, /*tp_hash*/
1744 0, /*tp_call*/
1745 0, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001746 PyObject_GenericGetAttr,/*tp_getattro*/
1747 PyObject_GenericSetAttr,/*tp_setattro*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001748 0, /*tp_as_buffer*/
1749 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1750 BZ2Comp__doc__, /*tp_doc*/
1751 0, /*tp_traverse*/
1752 0, /*tp_clear*/
1753 0, /*tp_richcompare*/
1754 0, /*tp_weaklistoffset*/
1755 0, /*tp_iter*/
1756 0, /*tp_iternext*/
1757 BZ2Comp_methods, /*tp_methods*/
1758 0, /*tp_members*/
1759 0, /*tp_getset*/
1760 0, /*tp_base*/
1761 0, /*tp_dict*/
1762 0, /*tp_descr_get*/
1763 0, /*tp_descr_set*/
1764 0, /*tp_dictoffset*/
1765 (initproc)BZ2Comp_init, /*tp_init*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001766 PyType_GenericAlloc, /*tp_alloc*/
1767 PyType_GenericNew, /*tp_new*/
1768 _PyObject_Del, /*tp_free*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001769 0, /*tp_is_gc*/
1770};
1771
1772
1773/* ===================================================================== */
1774/* Members of BZ2Decomp. */
1775
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001776#undef OFF
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001777#define OFF(x) offsetof(BZ2DecompObject, x)
1778
1779static PyMemberDef BZ2Decomp_members[] = {
1780 {"unused_data", T_OBJECT, OFF(unused_data), RO},
1781 {NULL} /* Sentinel */
1782};
1783
1784
1785/* ===================================================================== */
1786/* Methods of BZ2Decomp. */
1787
1788PyDoc_STRVAR(BZ2Decomp_decompress__doc__,
1789"decompress(data) -> string\n\
1790\n\
1791Provide more data to the decompressor object. It will return chunks\n\
1792of decompressed data whenever possible. If you try to decompress data\n\
1793after the end of stream is found, EOFError will be raised. If any data\n\
1794was found after the end of stream, it'll be ignored and saved in\n\
1795unused_data attribute.\n\
1796");
1797
1798static PyObject *
1799BZ2Decomp_decompress(BZ2DecompObject *self, PyObject *args)
1800{
1801 char *data;
1802 int datasize;
1803 int bufsize = SMALLCHUNK;
Martin v. Löwisb9a0f912003-03-29 10:06:18 +00001804 PY_LONG_LONG totalout;
Neal Norwitz18142c02002-11-05 18:17:32 +00001805 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001806 bz_stream *bzs = &self->bzs;
1807 int bzerror;
1808
Walter Dörwaldbb9c7392004-11-01 17:10:19 +00001809 if (!PyArg_ParseTuple(args, "s#:decompress", &data, &datasize))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001810 return NULL;
1811
1812 ACQUIRE_LOCK(self);
1813 if (!self->running) {
1814 PyErr_SetString(PyExc_EOFError, "end of stream was "
1815 "already found");
1816 goto error;
1817 }
1818
1819 ret = PyString_FromStringAndSize(NULL, bufsize);
1820 if (!ret)
1821 goto error;
1822
1823 bzs->next_in = data;
1824 bzs->avail_in = datasize;
1825 bzs->next_out = BUF(ret);
1826 bzs->avail_out = bufsize;
1827
1828 totalout = BZS_TOTAL_OUT(bzs);
1829
1830 for (;;) {
1831 Py_BEGIN_ALLOW_THREADS
1832 bzerror = BZ2_bzDecompress(bzs);
1833 Py_END_ALLOW_THREADS
1834 if (bzerror == BZ_STREAM_END) {
1835 if (bzs->avail_in != 0) {
1836 Py_DECREF(self->unused_data);
1837 self->unused_data =
1838 PyString_FromStringAndSize(bzs->next_in,
1839 bzs->avail_in);
1840 }
1841 self->running = 0;
1842 break;
1843 }
1844 if (bzerror != BZ_OK) {
1845 Util_CatchBZ2Error(bzerror);
1846 goto error;
1847 }
Guido van Rossumd8faa362007-04-27 19:54:29 +00001848 if (bzs->avail_in == 0)
1849 break; /* no more input data */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001850 if (bzs->avail_out == 0) {
1851 bufsize = Util_NewBufferSize(bufsize);
1852 if (_PyString_Resize(&ret, bufsize) < 0) {
1853 BZ2_bzDecompressEnd(bzs);
1854 goto error;
1855 }
1856 bzs->next_out = BUF(ret);
1857 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs)
1858 - totalout);
1859 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001860 }
1861 }
1862
1863 if (bzs->avail_out != 0)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001864 _PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001865
1866 RELEASE_LOCK(self);
1867 return ret;
1868
1869error:
1870 RELEASE_LOCK(self);
1871 Py_XDECREF(ret);
1872 return NULL;
1873}
1874
1875static PyMethodDef BZ2Decomp_methods[] = {
1876 {"decompress", (PyCFunction)BZ2Decomp_decompress, METH_VARARGS, BZ2Decomp_decompress__doc__},
1877 {NULL, NULL} /* sentinel */
1878};
1879
1880
1881/* ===================================================================== */
1882/* Slot definitions for BZ2Decomp_Type. */
1883
1884static int
1885BZ2Decomp_init(BZ2DecompObject *self, PyObject *args, PyObject *kwargs)
1886{
1887 int bzerror;
1888
1889 if (!PyArg_ParseTuple(args, ":BZ2Decompressor"))
1890 return -1;
1891
1892#ifdef WITH_THREAD
1893 self->lock = PyThread_allocate_lock();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001894 if (!self->lock) {
1895 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001896 goto error;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001897 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001898#endif
1899
1900 self->unused_data = PyString_FromString("");
1901 if (!self->unused_data)
1902 goto error;
1903
1904 memset(&self->bzs, 0, sizeof(bz_stream));
1905 bzerror = BZ2_bzDecompressInit(&self->bzs, 0, 0);
1906 if (bzerror != BZ_OK) {
1907 Util_CatchBZ2Error(bzerror);
1908 goto error;
1909 }
1910
1911 self->running = 1;
1912
1913 return 0;
1914
1915error:
1916#ifdef WITH_THREAD
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001917 if (self->lock) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001918 PyThread_free_lock(self->lock);
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001919 self->lock = NULL;
1920 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001921#endif
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001922 Py_CLEAR(self->unused_data);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001923 return -1;
1924}
1925
1926static void
1927BZ2Decomp_dealloc(BZ2DecompObject *self)
1928{
1929#ifdef WITH_THREAD
1930 if (self->lock)
1931 PyThread_free_lock(self->lock);
1932#endif
1933 Py_XDECREF(self->unused_data);
1934 BZ2_bzDecompressEnd(&self->bzs);
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001935 self->ob_type->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001936}
1937
1938
1939/* ===================================================================== */
1940/* BZ2Decomp_Type definition. */
1941
1942PyDoc_STRVAR(BZ2Decomp__doc__,
1943"BZ2Decompressor() -> decompressor object\n\
1944\n\
1945Create a new decompressor object. This object may be used to decompress\n\
1946data sequentially. If you want to decompress data in one shot, use the\n\
1947decompress() function instead.\n\
1948");
1949
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001950static PyTypeObject BZ2Decomp_Type = {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001951 PyObject_HEAD_INIT(NULL)
1952 0, /*ob_size*/
1953 "bz2.BZ2Decompressor", /*tp_name*/
1954 sizeof(BZ2DecompObject), /*tp_basicsize*/
1955 0, /*tp_itemsize*/
1956 (destructor)BZ2Decomp_dealloc, /*tp_dealloc*/
1957 0, /*tp_print*/
1958 0, /*tp_getattr*/
1959 0, /*tp_setattr*/
1960 0, /*tp_compare*/
1961 0, /*tp_repr*/
1962 0, /*tp_as_number*/
1963 0, /*tp_as_sequence*/
1964 0, /*tp_as_mapping*/
1965 0, /*tp_hash*/
1966 0, /*tp_call*/
1967 0, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001968 PyObject_GenericGetAttr,/*tp_getattro*/
1969 PyObject_GenericSetAttr,/*tp_setattro*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001970 0, /*tp_as_buffer*/
1971 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1972 BZ2Decomp__doc__, /*tp_doc*/
1973 0, /*tp_traverse*/
1974 0, /*tp_clear*/
1975 0, /*tp_richcompare*/
1976 0, /*tp_weaklistoffset*/
1977 0, /*tp_iter*/
1978 0, /*tp_iternext*/
1979 BZ2Decomp_methods, /*tp_methods*/
1980 BZ2Decomp_members, /*tp_members*/
1981 0, /*tp_getset*/
1982 0, /*tp_base*/
1983 0, /*tp_dict*/
1984 0, /*tp_descr_get*/
1985 0, /*tp_descr_set*/
1986 0, /*tp_dictoffset*/
1987 (initproc)BZ2Decomp_init, /*tp_init*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001988 PyType_GenericAlloc, /*tp_alloc*/
1989 PyType_GenericNew, /*tp_new*/
1990 _PyObject_Del, /*tp_free*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001991 0, /*tp_is_gc*/
1992};
1993
1994
1995/* ===================================================================== */
1996/* Module functions. */
1997
1998PyDoc_STRVAR(bz2_compress__doc__,
1999"compress(data [, compresslevel=9]) -> string\n\
2000\n\
2001Compress data in one shot. If you want to compress data sequentially,\n\
2002use an instance of BZ2Compressor instead. The compresslevel parameter, if\n\
2003given, must be a number between 1 and 9.\n\
2004");
2005
2006static PyObject *
2007bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
2008{
2009 int compresslevel=9;
2010 char *data;
2011 int datasize;
2012 int bufsize;
Gustavo Niemeyer7d7930b2002-11-05 18:41:53 +00002013 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002014 bz_stream _bzs;
2015 bz_stream *bzs = &_bzs;
2016 int bzerror;
Martin v. Löwis15e62742006-02-27 16:46:16 +00002017 static char *kwlist[] = {"data", "compresslevel", 0};
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002018
2019 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|i",
2020 kwlist, &data, &datasize,
2021 &compresslevel))
2022 return NULL;
2023
2024 if (compresslevel < 1 || compresslevel > 9) {
2025 PyErr_SetString(PyExc_ValueError,
2026 "compresslevel must be between 1 and 9");
2027 return NULL;
2028 }
2029
2030 /* Conforming to bz2 manual, this is large enough to fit compressed
2031 * data in one shot. We will check it later anyway. */
2032 bufsize = datasize + (datasize/100+1) + 600;
2033
2034 ret = PyString_FromStringAndSize(NULL, bufsize);
2035 if (!ret)
2036 return NULL;
2037
2038 memset(bzs, 0, sizeof(bz_stream));
2039
2040 bzs->next_in = data;
2041 bzs->avail_in = datasize;
2042 bzs->next_out = BUF(ret);
2043 bzs->avail_out = bufsize;
2044
2045 bzerror = BZ2_bzCompressInit(bzs, compresslevel, 0, 0);
2046 if (bzerror != BZ_OK) {
2047 Util_CatchBZ2Error(bzerror);
2048 Py_DECREF(ret);
2049 return NULL;
2050 }
Tim Peterse3228092002-11-09 04:21:44 +00002051
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002052 for (;;) {
2053 Py_BEGIN_ALLOW_THREADS
2054 bzerror = BZ2_bzCompress(bzs, BZ_FINISH);
2055 Py_END_ALLOW_THREADS
2056 if (bzerror == BZ_STREAM_END) {
2057 break;
2058 } else if (bzerror != BZ_FINISH_OK) {
2059 BZ2_bzCompressEnd(bzs);
2060 Util_CatchBZ2Error(bzerror);
2061 Py_DECREF(ret);
2062 return NULL;
2063 }
2064 if (bzs->avail_out == 0) {
2065 bufsize = Util_NewBufferSize(bufsize);
2066 if (_PyString_Resize(&ret, bufsize) < 0) {
2067 BZ2_bzCompressEnd(bzs);
2068 Py_DECREF(ret);
2069 return NULL;
2070 }
2071 bzs->next_out = BUF(ret) + BZS_TOTAL_OUT(bzs);
2072 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
2073 }
2074 }
2075
2076 if (bzs->avail_out != 0)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002077 _PyString_Resize(&ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002078 BZ2_bzCompressEnd(bzs);
2079
2080 return ret;
2081}
2082
2083PyDoc_STRVAR(bz2_decompress__doc__,
2084"decompress(data) -> decompressed data\n\
2085\n\
2086Decompress data in one shot. If you want to decompress data sequentially,\n\
2087use an instance of BZ2Decompressor instead.\n\
2088");
2089
2090static PyObject *
2091bz2_decompress(PyObject *self, PyObject *args)
2092{
2093 char *data;
2094 int datasize;
2095 int bufsize = SMALLCHUNK;
2096 PyObject *ret;
2097 bz_stream _bzs;
2098 bz_stream *bzs = &_bzs;
2099 int bzerror;
2100
Walter Dörwaldbb9c7392004-11-01 17:10:19 +00002101 if (!PyArg_ParseTuple(args, "s#:decompress", &data, &datasize))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002102 return NULL;
2103
2104 if (datasize == 0)
2105 return PyString_FromString("");
2106
2107 ret = PyString_FromStringAndSize(NULL, bufsize);
2108 if (!ret)
2109 return NULL;
2110
2111 memset(bzs, 0, sizeof(bz_stream));
2112
2113 bzs->next_in = data;
2114 bzs->avail_in = datasize;
2115 bzs->next_out = BUF(ret);
2116 bzs->avail_out = bufsize;
2117
2118 bzerror = BZ2_bzDecompressInit(bzs, 0, 0);
2119 if (bzerror != BZ_OK) {
2120 Util_CatchBZ2Error(bzerror);
2121 Py_DECREF(ret);
2122 return NULL;
2123 }
Tim Peterse3228092002-11-09 04:21:44 +00002124
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002125 for (;;) {
2126 Py_BEGIN_ALLOW_THREADS
2127 bzerror = BZ2_bzDecompress(bzs);
2128 Py_END_ALLOW_THREADS
2129 if (bzerror == BZ_STREAM_END) {
2130 break;
2131 } else if (bzerror != BZ_OK) {
2132 BZ2_bzDecompressEnd(bzs);
2133 Util_CatchBZ2Error(bzerror);
2134 Py_DECREF(ret);
2135 return NULL;
2136 }
Guido van Rossumd8faa362007-04-27 19:54:29 +00002137 if (bzs->avail_in == 0) {
2138 BZ2_bzDecompressEnd(bzs);
2139 PyErr_SetString(PyExc_ValueError,
2140 "couldn't find end of stream");
2141 Py_DECREF(ret);
2142 return NULL;
2143 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002144 if (bzs->avail_out == 0) {
2145 bufsize = Util_NewBufferSize(bufsize);
2146 if (_PyString_Resize(&ret, bufsize) < 0) {
2147 BZ2_bzDecompressEnd(bzs);
2148 Py_DECREF(ret);
2149 return NULL;
2150 }
2151 bzs->next_out = BUF(ret) + BZS_TOTAL_OUT(bzs);
2152 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002153 }
2154 }
2155
2156 if (bzs->avail_out != 0)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002157 _PyString_Resize(&ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002158 BZ2_bzDecompressEnd(bzs);
2159
2160 return ret;
2161}
2162
2163static PyMethodDef bz2_methods[] = {
2164 {"compress", (PyCFunction) bz2_compress, METH_VARARGS|METH_KEYWORDS,
2165 bz2_compress__doc__},
2166 {"decompress", (PyCFunction) bz2_decompress, METH_VARARGS,
2167 bz2_decompress__doc__},
2168 {NULL, NULL} /* sentinel */
2169};
2170
2171/* ===================================================================== */
2172/* Initialization function. */
2173
2174PyDoc_STRVAR(bz2__doc__,
2175"The python bz2 module provides a comprehensive interface for\n\
2176the bz2 compression library. It implements a complete file\n\
2177interface, one shot (de)compression functions, and types for\n\
2178sequential (de)compression.\n\
2179");
2180
Neal Norwitz21d896c2003-07-01 20:15:21 +00002181PyMODINIT_FUNC
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002182initbz2(void)
2183{
2184 PyObject *m;
2185
2186 BZ2File_Type.ob_type = &PyType_Type;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002187 BZ2Comp_Type.ob_type = &PyType_Type;
2188 BZ2Decomp_Type.ob_type = &PyType_Type;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002189
2190 m = Py_InitModule3("bz2", bz2_methods, bz2__doc__);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00002191 if (m == NULL)
2192 return;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002193
2194 PyModule_AddObject(m, "__author__", PyString_FromString(__author__));
2195
2196 Py_INCREF(&BZ2File_Type);
2197 PyModule_AddObject(m, "BZ2File", (PyObject *)&BZ2File_Type);
2198
2199 Py_INCREF(&BZ2Comp_Type);
2200 PyModule_AddObject(m, "BZ2Compressor", (PyObject *)&BZ2Comp_Type);
2201
2202 Py_INCREF(&BZ2Decomp_Type);
2203 PyModule_AddObject(m, "BZ2Decompressor", (PyObject *)&BZ2Decomp_Type);
2204}