blob: 5a4e5d99581eac82d0044c495d809ec125710d25 [file] [log] [blame]
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001/*
2
3python-bz2 - python bz2 library interface
4
5Copyright (c) 2002 Gustavo Niemeyer <niemeyer@conectiva.com>
6Copyright (c) 2002 Python Software Foundation; All Rights Reserved
7
8*/
9
Martin v. Löwise17af7b2002-11-23 09:16:19 +000010#include "Python.h"
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000011#include <stdio.h>
12#include <bzlib.h>
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000013#include "structmember.h"
14
15#ifdef WITH_THREAD
16#include "pythread.h"
17#endif
18
19static char __author__[] =
20"The bz2 python module was written by:\n\
21\n\
22 Gustavo Niemeyer <niemeyer@conectiva.com>\n\
23";
24
Georg Brandl33a5f2a2005-08-21 14:16:04 +000025/* Our very own off_t-like type, 64-bit if possible */
26/* copied from Objects/fileobject.c */
27#if !defined(HAVE_LARGEFILE_SUPPORT)
28typedef off_t Py_off_t;
29#elif SIZEOF_OFF_T >= 8
30typedef off_t Py_off_t;
31#elif SIZEOF_FPOS_T >= 8
32typedef fpos_t Py_off_t;
33#else
34#error "Large file support, but neither off_t nor fpos_t is large enough."
35#endif
36
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000037#define BUF(v) PyString_AS_STRING((PyStringObject *)v)
38
39#define MODE_CLOSED 0
40#define MODE_READ 1
41#define MODE_READ_EOF 2
42#define MODE_WRITE 3
43
44#define BZ2FileObject_Check(v) ((v)->ob_type == &BZ2File_Type)
45
Gustavo Niemeyer7628f1f2003-04-27 06:25:24 +000046
47#ifdef BZ_CONFIG_ERROR
48
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000049#if SIZEOF_LONG >= 8
50#define BZS_TOTAL_OUT(bzs) \
51 (((long)bzs->total_out_hi32 << 32) + bzs->total_out_lo32)
52#elif SIZEOF_LONG_LONG >= 8
53#define BZS_TOTAL_OUT(bzs) \
Martin v. Löwisb9a0f912003-03-29 10:06:18 +000054 (((PY_LONG_LONG)bzs->total_out_hi32 << 32) + bzs->total_out_lo32)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000055#else
56#define BZS_TOTAL_OUT(bzs) \
Neal Norwitz20bad742006-01-17 05:27:39 +000057 bzs->total_out_lo32
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000058#endif
59
Gustavo Niemeyer7628f1f2003-04-27 06:25:24 +000060#else /* ! BZ_CONFIG_ERROR */
61
62#define BZ2_bzRead bzRead
63#define BZ2_bzReadOpen bzReadOpen
64#define BZ2_bzReadClose bzReadClose
65#define BZ2_bzWrite bzWrite
66#define BZ2_bzWriteOpen bzWriteOpen
67#define BZ2_bzWriteClose bzWriteClose
68#define BZ2_bzCompress bzCompress
69#define BZ2_bzCompressInit bzCompressInit
70#define BZ2_bzCompressEnd bzCompressEnd
71#define BZ2_bzDecompress bzDecompress
72#define BZ2_bzDecompressInit bzDecompressInit
73#define BZ2_bzDecompressEnd bzDecompressEnd
74
75#define BZS_TOTAL_OUT(bzs) bzs->total_out
76
77#endif /* ! BZ_CONFIG_ERROR */
78
79
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000080#ifdef WITH_THREAD
81#define ACQUIRE_LOCK(obj) PyThread_acquire_lock(obj->lock, 1)
82#define RELEASE_LOCK(obj) PyThread_release_lock(obj->lock)
83#else
84#define ACQUIRE_LOCK(obj)
85#define RELEASE_LOCK(obj)
86#endif
87
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000088/* Bits in f_newlinetypes */
89#define NEWLINE_UNKNOWN 0 /* No newline seen, yet */
90#define NEWLINE_CR 1 /* \r newline seen */
91#define NEWLINE_LF 2 /* \n newline seen */
92#define NEWLINE_CRLF 4 /* \r\n newline seen */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000093
94/* ===================================================================== */
95/* Structure definitions. */
96
97typedef struct {
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +000098 PyObject_HEAD
99 PyObject *file;
100
101 char* f_buf; /* Allocated readahead buffer */
102 char* f_bufend; /* Points after last occupied position */
103 char* f_bufptr; /* Current buffer position */
104
105 int f_softspace; /* Flag used by 'print' command */
106
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000107 int f_univ_newline; /* Handle any newline convention */
108 int f_newlinetypes; /* Types of newlines seen */
109 int f_skipnextlf; /* Skip next \n */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000110
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000111 BZFILE *fp;
112 int mode;
Georg Brandla8bcecc2005-09-03 07:49:53 +0000113 Py_off_t pos;
114 Py_off_t size;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000115#ifdef WITH_THREAD
116 PyThread_type_lock lock;
117#endif
118} BZ2FileObject;
119
120typedef struct {
121 PyObject_HEAD
122 bz_stream bzs;
123 int running;
124#ifdef WITH_THREAD
125 PyThread_type_lock lock;
126#endif
127} BZ2CompObject;
128
129typedef struct {
130 PyObject_HEAD
131 bz_stream bzs;
132 int running;
133 PyObject *unused_data;
134#ifdef WITH_THREAD
135 PyThread_type_lock lock;
136#endif
137} BZ2DecompObject;
138
139/* ===================================================================== */
140/* Utility functions. */
141
142static int
143Util_CatchBZ2Error(int bzerror)
144{
145 int ret = 0;
146 switch(bzerror) {
147 case BZ_OK:
148 case BZ_STREAM_END:
149 break;
150
Gustavo Niemeyer7628f1f2003-04-27 06:25:24 +0000151#ifdef BZ_CONFIG_ERROR
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000152 case BZ_CONFIG_ERROR:
153 PyErr_SetString(PyExc_SystemError,
154 "the bz2 library was not compiled "
155 "correctly");
156 ret = 1;
157 break;
Gustavo Niemeyer7628f1f2003-04-27 06:25:24 +0000158#endif
Tim Peterse3228092002-11-09 04:21:44 +0000159
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000160 case BZ_PARAM_ERROR:
161 PyErr_SetString(PyExc_ValueError,
162 "the bz2 library has received wrong "
163 "parameters");
164 ret = 1;
165 break;
Tim Peterse3228092002-11-09 04:21:44 +0000166
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000167 case BZ_MEM_ERROR:
168 PyErr_NoMemory();
169 ret = 1;
170 break;
171
172 case BZ_DATA_ERROR:
173 case BZ_DATA_ERROR_MAGIC:
174 PyErr_SetString(PyExc_IOError, "invalid data stream");
175 ret = 1;
176 break;
177
178 case BZ_IO_ERROR:
179 PyErr_SetString(PyExc_IOError, "unknown IO error");
180 ret = 1;
181 break;
182
183 case BZ_UNEXPECTED_EOF:
184 PyErr_SetString(PyExc_EOFError,
185 "compressed file ended before the "
186 "logical end-of-stream was detected");
187 ret = 1;
188 break;
189
190 case BZ_SEQUENCE_ERROR:
191 PyErr_SetString(PyExc_RuntimeError,
192 "wrong sequence of bz2 library "
193 "commands used");
194 ret = 1;
195 break;
196 }
197 return ret;
198}
199
200#if BUFSIZ < 8192
201#define SMALLCHUNK 8192
202#else
203#define SMALLCHUNK BUFSIZ
204#endif
205
206#if SIZEOF_INT < 4
207#define BIGCHUNK (512 * 32)
208#else
209#define BIGCHUNK (512 * 1024)
210#endif
211
212/* This is a hacked version of Python's fileobject.c:new_buffersize(). */
213static size_t
214Util_NewBufferSize(size_t currentsize)
215{
216 if (currentsize > SMALLCHUNK) {
217 /* Keep doubling until we reach BIGCHUNK;
218 then keep adding BIGCHUNK. */
219 if (currentsize <= BIGCHUNK)
220 return currentsize + currentsize;
221 else
222 return currentsize + BIGCHUNK;
223 }
224 return currentsize + SMALLCHUNK;
225}
226
227/* This is a hacked version of Python's fileobject.c:get_line(). */
228static PyObject *
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000229Util_GetLine(BZ2FileObject *f, int n)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000230{
231 char c;
232 char *buf, *end;
233 size_t total_v_size; /* total # of slots in buffer */
234 size_t used_v_size; /* # used slots in buffer */
235 size_t increment; /* amount to increment the buffer */
236 PyObject *v;
237 int bzerror;
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000238 int newlinetypes = f->f_newlinetypes;
239 int skipnextlf = f->f_skipnextlf;
240 int univ_newline = f->f_univ_newline;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000241
242 total_v_size = n > 0 ? n : 100;
243 v = PyString_FromStringAndSize((char *)NULL, total_v_size);
244 if (v == NULL)
245 return NULL;
246
247 buf = BUF(v);
248 end = buf + total_v_size;
249
250 for (;;) {
251 Py_BEGIN_ALLOW_THREADS
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000252 if (univ_newline) {
253 while (1) {
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000254 BZ2_bzRead(&bzerror, f->fp, &c, 1);
255 f->pos++;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000256 if (bzerror != BZ_OK || buf == end)
257 break;
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +0000258 if (skipnextlf) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000259 skipnextlf = 0;
260 if (c == '\n') {
Tim Peterse3228092002-11-09 04:21:44 +0000261 /* Seeing a \n here with
262 * skipnextlf true means we
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000263 * saw a \r before.
264 */
265 newlinetypes |= NEWLINE_CRLF;
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000266 BZ2_bzRead(&bzerror, f->fp,
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000267 &c, 1);
268 if (bzerror != BZ_OK)
269 break;
270 } else {
271 newlinetypes |= NEWLINE_CR;
272 }
273 }
274 if (c == '\r') {
275 skipnextlf = 1;
276 c = '\n';
277 } else if ( c == '\n')
278 newlinetypes |= NEWLINE_LF;
279 *buf++ = c;
280 if (c == '\n') break;
281 }
282 if (bzerror == BZ_STREAM_END && skipnextlf)
283 newlinetypes |= NEWLINE_CR;
284 } else /* If not universal newlines use the normal loop */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000285 do {
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000286 BZ2_bzRead(&bzerror, f->fp, &c, 1);
287 f->pos++;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000288 *buf++ = c;
289 } while (bzerror == BZ_OK && c != '\n' && buf != end);
290 Py_END_ALLOW_THREADS
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000291 f->f_newlinetypes = newlinetypes;
292 f->f_skipnextlf = skipnextlf;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000293 if (bzerror == BZ_STREAM_END) {
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000294 f->size = f->pos;
295 f->mode = MODE_READ_EOF;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000296 break;
297 } else if (bzerror != BZ_OK) {
298 Util_CatchBZ2Error(bzerror);
299 Py_DECREF(v);
300 return NULL;
301 }
302 if (c == '\n')
303 break;
304 /* Must be because buf == end */
305 if (n > 0)
306 break;
307 used_v_size = total_v_size;
308 increment = total_v_size >> 2; /* mild exponential growth */
309 total_v_size += increment;
310 if (total_v_size > INT_MAX) {
311 PyErr_SetString(PyExc_OverflowError,
312 "line is longer than a Python string can hold");
313 Py_DECREF(v);
314 return NULL;
315 }
316 if (_PyString_Resize(&v, total_v_size) < 0)
317 return NULL;
318 buf = BUF(v) + used_v_size;
319 end = BUF(v) + total_v_size;
320 }
321
322 used_v_size = buf - BUF(v);
323 if (used_v_size != total_v_size)
324 _PyString_Resize(&v, used_v_size);
325 return v;
326}
327
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000328/* This is a hacked version of Python's
329 * fileobject.c:Py_UniversalNewlineFread(). */
330size_t
331Util_UnivNewlineRead(int *bzerror, BZFILE *stream,
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000332 char* buf, size_t n, BZ2FileObject *f)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000333{
334 char *dst = buf;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000335 int newlinetypes, skipnextlf;
336
337 assert(buf != NULL);
338 assert(stream != NULL);
339
340 if (!f->f_univ_newline)
341 return BZ2_bzRead(bzerror, stream, buf, n);
342
343 newlinetypes = f->f_newlinetypes;
344 skipnextlf = f->f_skipnextlf;
345
346 /* Invariant: n is the number of bytes remaining to be filled
347 * in the buffer.
348 */
349 while (n) {
350 size_t nread;
351 int shortread;
352 char *src = dst;
353
354 nread = BZ2_bzRead(bzerror, stream, dst, n);
355 assert(nread <= n);
356 n -= nread; /* assuming 1 byte out for each in; will adjust */
357 shortread = n != 0; /* true iff EOF or error */
358 while (nread--) {
359 char c = *src++;
360 if (c == '\r') {
361 /* Save as LF and set flag to skip next LF. */
362 *dst++ = '\n';
363 skipnextlf = 1;
364 }
365 else if (skipnextlf && c == '\n') {
366 /* Skip LF, and remember we saw CR LF. */
367 skipnextlf = 0;
368 newlinetypes |= NEWLINE_CRLF;
369 ++n;
370 }
371 else {
372 /* Normal char to be stored in buffer. Also
373 * update the newlinetypes flag if either this
374 * is an LF or the previous char was a CR.
375 */
376 if (c == '\n')
377 newlinetypes |= NEWLINE_LF;
378 else if (skipnextlf)
379 newlinetypes |= NEWLINE_CR;
380 *dst++ = c;
381 skipnextlf = 0;
382 }
383 }
384 if (shortread) {
385 /* If this is EOF, update type flags. */
386 if (skipnextlf && *bzerror == BZ_STREAM_END)
387 newlinetypes |= NEWLINE_CR;
388 break;
389 }
390 }
391 f->f_newlinetypes = newlinetypes;
392 f->f_skipnextlf = skipnextlf;
393 return dst - buf;
394}
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000395
396/* This is a hacked version of Python's fileobject.c:drop_readahead(). */
397static void
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000398Util_DropReadAhead(BZ2FileObject *f)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000399{
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000400 if (f->f_buf != NULL) {
401 PyMem_Free(f->f_buf);
402 f->f_buf = NULL;
403 }
404}
405
406/* This is a hacked version of Python's fileobject.c:readahead(). */
407static int
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000408Util_ReadAhead(BZ2FileObject *f, int bufsize)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000409{
410 int chunksize;
411 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000412
413 if (f->f_buf != NULL) {
Tim Peterse3228092002-11-09 04:21:44 +0000414 if((f->f_bufend - f->f_bufptr) >= 1)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000415 return 0;
416 else
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000417 Util_DropReadAhead(f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000418 }
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000419 if (f->mode == MODE_READ_EOF) {
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000420 f->f_bufptr = f->f_buf;
421 f->f_bufend = f->f_buf;
422 return 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000423 }
424 if ((f->f_buf = PyMem_Malloc(bufsize)) == NULL) {
425 return -1;
426 }
427 Py_BEGIN_ALLOW_THREADS
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000428 chunksize = Util_UnivNewlineRead(&bzerror, f->fp, f->f_buf,
429 bufsize, f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000430 Py_END_ALLOW_THREADS
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000431 f->pos += chunksize;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000432 if (bzerror == BZ_STREAM_END) {
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000433 f->size = f->pos;
434 f->mode = MODE_READ_EOF;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000435 } else if (bzerror != BZ_OK) {
436 Util_CatchBZ2Error(bzerror);
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000437 Util_DropReadAhead(f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000438 return -1;
439 }
440 f->f_bufptr = f->f_buf;
441 f->f_bufend = f->f_buf + chunksize;
442 return 0;
443}
444
445/* This is a hacked version of Python's
446 * fileobject.c:readahead_get_line_skip(). */
447static PyStringObject *
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000448Util_ReadAheadGetLineSkip(BZ2FileObject *f, int skip, int bufsize)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000449{
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000450 PyStringObject* s;
451 char *bufptr;
452 char *buf;
453 int len;
454
455 if (f->f_buf == NULL)
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000456 if (Util_ReadAhead(f, bufsize) < 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000457 return NULL;
458
459 len = f->f_bufend - f->f_bufptr;
Tim Peterse3228092002-11-09 04:21:44 +0000460 if (len == 0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000461 return (PyStringObject *)
462 PyString_FromStringAndSize(NULL, skip);
463 bufptr = memchr(f->f_bufptr, '\n', len);
464 if (bufptr != NULL) {
465 bufptr++; /* Count the '\n' */
466 len = bufptr - f->f_bufptr;
467 s = (PyStringObject *)
468 PyString_FromStringAndSize(NULL, skip+len);
Tim Peterse3228092002-11-09 04:21:44 +0000469 if (s == NULL)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000470 return NULL;
471 memcpy(PyString_AS_STRING(s)+skip, f->f_bufptr, len);
472 f->f_bufptr = bufptr;
473 if (bufptr == f->f_bufend)
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000474 Util_DropReadAhead(f);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000475 } else {
476 bufptr = f->f_bufptr;
477 buf = f->f_buf;
478 f->f_buf = NULL; /* Force new readahead buffer */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000479 s = Util_ReadAheadGetLineSkip(f, skip+len,
480 bufsize + (bufsize>>2));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000481 if (s == NULL) {
482 PyMem_Free(buf);
483 return NULL;
484 }
485 memcpy(PyString_AS_STRING(s)+skip, bufptr, len);
486 PyMem_Free(buf);
487 }
488 return s;
489}
490
491/* ===================================================================== */
492/* Methods of BZ2File. */
493
494PyDoc_STRVAR(BZ2File_read__doc__,
495"read([size]) -> string\n\
496\n\
497Read at most size uncompressed bytes, returned as a string. If the size\n\
498argument is negative or omitted, read until EOF is reached.\n\
499");
500
501/* This is a hacked version of Python's fileobject.c:file_read(). */
502static PyObject *
503BZ2File_read(BZ2FileObject *self, PyObject *args)
504{
505 long bytesrequested = -1;
506 size_t bytesread, buffersize, chunksize;
507 int bzerror;
508 PyObject *ret = NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000509
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000510 if (!PyArg_ParseTuple(args, "|l:read", &bytesrequested))
511 return NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000512
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000513 ACQUIRE_LOCK(self);
514 switch (self->mode) {
515 case MODE_READ:
516 break;
517 case MODE_READ_EOF:
518 ret = PyString_FromString("");
519 goto cleanup;
520 case MODE_CLOSED:
521 PyErr_SetString(PyExc_ValueError,
522 "I/O operation on closed file");
523 goto cleanup;
524 default:
525 PyErr_SetString(PyExc_IOError,
526 "file is not ready for reading");
527 goto cleanup;
528 }
529
530 if (bytesrequested < 0)
531 buffersize = Util_NewBufferSize((size_t)0);
532 else
533 buffersize = bytesrequested;
534 if (buffersize > INT_MAX) {
535 PyErr_SetString(PyExc_OverflowError,
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +0000536 "requested number of bytes is "
537 "more than a Python string can hold");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000538 goto cleanup;
539 }
540 ret = PyString_FromStringAndSize((char *)NULL, buffersize);
541 if (ret == NULL)
542 goto cleanup;
543 bytesread = 0;
544
545 for (;;) {
546 Py_BEGIN_ALLOW_THREADS
547 chunksize = Util_UnivNewlineRead(&bzerror, self->fp,
548 BUF(ret)+bytesread,
549 buffersize-bytesread,
550 self);
551 self->pos += chunksize;
552 Py_END_ALLOW_THREADS
553 bytesread += chunksize;
554 if (bzerror == BZ_STREAM_END) {
555 self->size = self->pos;
556 self->mode = MODE_READ_EOF;
557 break;
558 } else if (bzerror != BZ_OK) {
559 Util_CatchBZ2Error(bzerror);
560 Py_DECREF(ret);
561 ret = NULL;
562 goto cleanup;
563 }
564 if (bytesrequested < 0) {
565 buffersize = Util_NewBufferSize(buffersize);
566 if (_PyString_Resize(&ret, buffersize) < 0)
567 goto cleanup;
568 } else {
569 break;
570 }
571 }
572 if (bytesread != buffersize)
573 _PyString_Resize(&ret, bytesread);
574
575cleanup:
576 RELEASE_LOCK(self);
577 return ret;
578}
579
580PyDoc_STRVAR(BZ2File_readline__doc__,
581"readline([size]) -> string\n\
582\n\
583Return the next line from the file, as a string, retaining newline.\n\
584A non-negative size argument will limit the maximum number of bytes to\n\
585return (an incomplete line may be returned then). Return an empty\n\
586string at EOF.\n\
587");
588
589static PyObject *
590BZ2File_readline(BZ2FileObject *self, PyObject *args)
591{
592 PyObject *ret = NULL;
593 int sizehint = -1;
594
595 if (!PyArg_ParseTuple(args, "|i:readline", &sizehint))
596 return NULL;
597
598 ACQUIRE_LOCK(self);
599 switch (self->mode) {
600 case MODE_READ:
601 break;
602 case MODE_READ_EOF:
603 ret = PyString_FromString("");
604 goto cleanup;
605 case MODE_CLOSED:
606 PyErr_SetString(PyExc_ValueError,
607 "I/O operation on closed file");
608 goto cleanup;
609 default:
610 PyErr_SetString(PyExc_IOError,
611 "file is not ready for reading");
612 goto cleanup;
613 }
614
615 if (sizehint == 0)
616 ret = PyString_FromString("");
617 else
618 ret = Util_GetLine(self, (sizehint < 0) ? 0 : sizehint);
619
620cleanup:
621 RELEASE_LOCK(self);
622 return ret;
623}
624
625PyDoc_STRVAR(BZ2File_readlines__doc__,
626"readlines([size]) -> list\n\
627\n\
628Call readline() repeatedly and return a list of lines read.\n\
629The optional size argument, if given, is an approximate bound on the\n\
630total number of bytes in the lines returned.\n\
631");
632
633/* This is a hacked version of Python's fileobject.c:file_readlines(). */
634static PyObject *
635BZ2File_readlines(BZ2FileObject *self, PyObject *args)
636{
637 long sizehint = 0;
638 PyObject *list = NULL;
639 PyObject *line;
640 char small_buffer[SMALLCHUNK];
641 char *buffer = small_buffer;
642 size_t buffersize = SMALLCHUNK;
643 PyObject *big_buffer = NULL;
644 size_t nfilled = 0;
645 size_t nread;
646 size_t totalread = 0;
647 char *p, *q, *end;
648 int err;
649 int shortread = 0;
650 int bzerror;
651
652 if (!PyArg_ParseTuple(args, "|l:readlines", &sizehint))
653 return NULL;
654
655 ACQUIRE_LOCK(self);
656 switch (self->mode) {
657 case MODE_READ:
658 break;
659 case MODE_READ_EOF:
660 list = PyList_New(0);
661 goto cleanup;
662 case MODE_CLOSED:
663 PyErr_SetString(PyExc_ValueError,
664 "I/O operation on closed file");
665 goto cleanup;
666 default:
667 PyErr_SetString(PyExc_IOError,
668 "file is not ready for reading");
669 goto cleanup;
670 }
671
672 if ((list = PyList_New(0)) == NULL)
673 goto cleanup;
674
675 for (;;) {
676 Py_BEGIN_ALLOW_THREADS
677 nread = Util_UnivNewlineRead(&bzerror, self->fp,
678 buffer+nfilled,
679 buffersize-nfilled, self);
680 self->pos += nread;
681 Py_END_ALLOW_THREADS
682 if (bzerror == BZ_STREAM_END) {
683 self->size = self->pos;
684 self->mode = MODE_READ_EOF;
685 if (nread == 0) {
686 sizehint = 0;
687 break;
688 }
689 shortread = 1;
690 } else if (bzerror != BZ_OK) {
691 Util_CatchBZ2Error(bzerror);
692 error:
693 Py_DECREF(list);
694 list = NULL;
695 goto cleanup;
696 }
697 totalread += nread;
698 p = memchr(buffer+nfilled, '\n', nread);
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000699 if (!shortread && p == NULL) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000700 /* Need a larger buffer to fit this line */
701 nfilled += nread;
702 buffersize *= 2;
703 if (buffersize > INT_MAX) {
704 PyErr_SetString(PyExc_OverflowError,
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000705 "line is longer than a Python string can hold");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000706 goto error;
707 }
708 if (big_buffer == NULL) {
709 /* Create the big buffer */
710 big_buffer = PyString_FromStringAndSize(
711 NULL, buffersize);
712 if (big_buffer == NULL)
713 goto error;
714 buffer = PyString_AS_STRING(big_buffer);
715 memcpy(buffer, small_buffer, nfilled);
716 }
717 else {
718 /* Grow the big buffer */
719 _PyString_Resize(&big_buffer, buffersize);
720 buffer = PyString_AS_STRING(big_buffer);
721 }
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000722 continue;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000723 }
724 end = buffer+nfilled+nread;
725 q = buffer;
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000726 while (p != NULL) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000727 /* Process complete lines */
728 p++;
729 line = PyString_FromStringAndSize(q, p-q);
730 if (line == NULL)
731 goto error;
732 err = PyList_Append(list, line);
733 Py_DECREF(line);
734 if (err != 0)
735 goto error;
736 q = p;
737 p = memchr(q, '\n', end-q);
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000738 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000739 /* Move the remaining incomplete line to the start */
740 nfilled = end-q;
741 memmove(buffer, q, nfilled);
742 if (sizehint > 0)
743 if (totalread >= (size_t)sizehint)
744 break;
745 if (shortread) {
746 sizehint = 0;
747 break;
748 }
749 }
750 if (nfilled != 0) {
751 /* Partial last line */
752 line = PyString_FromStringAndSize(buffer, nfilled);
753 if (line == NULL)
754 goto error;
755 if (sizehint > 0) {
756 /* Need to complete the last line */
757 PyObject *rest = Util_GetLine(self, 0);
758 if (rest == NULL) {
759 Py_DECREF(line);
760 goto error;
761 }
762 PyString_Concat(&line, rest);
763 Py_DECREF(rest);
764 if (line == NULL)
765 goto error;
766 }
767 err = PyList_Append(list, line);
768 Py_DECREF(line);
769 if (err != 0)
770 goto error;
771 }
772
773 cleanup:
774 RELEASE_LOCK(self);
775 if (big_buffer) {
776 Py_DECREF(big_buffer);
777 }
778 return list;
779}
780
781PyDoc_STRVAR(BZ2File_write__doc__,
782"write(data) -> None\n\
783\n\
784Write the 'data' string to file. Note that due to buffering, close() may\n\
785be needed before the file on disk reflects the data written.\n\
786");
787
788/* This is a hacked version of Python's fileobject.c:file_write(). */
789static PyObject *
790BZ2File_write(BZ2FileObject *self, PyObject *args)
791{
792 PyObject *ret = NULL;
793 char *buf;
794 int len;
795 int bzerror;
796
Walter Dörwaldbb9c7392004-11-01 17:10:19 +0000797 if (!PyArg_ParseTuple(args, "s#:write", &buf, &len))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000798 return NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000799
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000800 ACQUIRE_LOCK(self);
801 switch (self->mode) {
802 case MODE_WRITE:
803 break;
Tim Peterse3228092002-11-09 04:21:44 +0000804
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000805 case MODE_CLOSED:
806 PyErr_SetString(PyExc_ValueError,
807 "I/O operation on closed file");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000808 goto cleanup;
Tim Peterse3228092002-11-09 04:21:44 +0000809
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000810 default:
811 PyErr_SetString(PyExc_IOError,
812 "file is not ready for writing");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000813 goto cleanup;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000814 }
815
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000816 self->f_softspace = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000817
818 Py_BEGIN_ALLOW_THREADS
819 BZ2_bzWrite (&bzerror, self->fp, buf, len);
820 self->pos += len;
821 Py_END_ALLOW_THREADS
Tim Peterse3228092002-11-09 04:21:44 +0000822
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000823 if (bzerror != BZ_OK) {
824 Util_CatchBZ2Error(bzerror);
825 goto cleanup;
826 }
Tim Peterse3228092002-11-09 04:21:44 +0000827
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000828 Py_INCREF(Py_None);
829 ret = Py_None;
830
831cleanup:
832 RELEASE_LOCK(self);
833 return ret;
834}
835
836PyDoc_STRVAR(BZ2File_writelines__doc__,
837"writelines(sequence_of_strings) -> None\n\
838\n\
839Write the sequence of strings to the file. Note that newlines are not\n\
840added. The sequence can be any iterable object producing strings. This is\n\
841equivalent to calling write() for each string.\n\
842");
843
844/* This is a hacked version of Python's fileobject.c:file_writelines(). */
845static PyObject *
846BZ2File_writelines(BZ2FileObject *self, PyObject *seq)
847{
848#define CHUNKSIZE 1000
849 PyObject *list = NULL;
850 PyObject *iter = NULL;
851 PyObject *ret = NULL;
852 PyObject *line;
853 int i, j, index, len, islist;
854 int bzerror;
855
856 ACQUIRE_LOCK(self);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000857 switch (self->mode) {
858 case MODE_WRITE:
859 break;
860
861 case MODE_CLOSED:
862 PyErr_SetString(PyExc_ValueError,
863 "I/O operation on closed file");
864 goto error;
865
866 default:
867 PyErr_SetString(PyExc_IOError,
868 "file is not ready for writing");
869 goto error;
870 }
871
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000872 islist = PyList_Check(seq);
873 if (!islist) {
874 iter = PyObject_GetIter(seq);
875 if (iter == NULL) {
876 PyErr_SetString(PyExc_TypeError,
877 "writelines() requires an iterable argument");
878 goto error;
879 }
880 list = PyList_New(CHUNKSIZE);
881 if (list == NULL)
882 goto error;
883 }
884
885 /* Strategy: slurp CHUNKSIZE lines into a private list,
886 checking that they are all strings, then write that list
887 without holding the interpreter lock, then come back for more. */
888 for (index = 0; ; index += CHUNKSIZE) {
889 if (islist) {
890 Py_XDECREF(list);
891 list = PyList_GetSlice(seq, index, index+CHUNKSIZE);
892 if (list == NULL)
893 goto error;
894 j = PyList_GET_SIZE(list);
895 }
896 else {
897 for (j = 0; j < CHUNKSIZE; j++) {
898 line = PyIter_Next(iter);
899 if (line == NULL) {
900 if (PyErr_Occurred())
901 goto error;
902 break;
903 }
904 PyList_SetItem(list, j, line);
905 }
906 }
907 if (j == 0)
908 break;
909
910 /* Check that all entries are indeed strings. If not,
911 apply the same rules as for file.write() and
912 convert the rets to strings. This is slow, but
913 seems to be the only way since all conversion APIs
914 could potentially execute Python code. */
915 for (i = 0; i < j; i++) {
916 PyObject *v = PyList_GET_ITEM(list, i);
917 if (!PyString_Check(v)) {
918 const char *buffer;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000919 Py_ssize_t len;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000920 if (PyObject_AsCharBuffer(v, &buffer, &len)) {
921 PyErr_SetString(PyExc_TypeError,
922 "writelines() "
923 "argument must be "
924 "a sequence of "
925 "strings");
926 goto error;
927 }
928 line = PyString_FromStringAndSize(buffer,
929 len);
930 if (line == NULL)
931 goto error;
932 Py_DECREF(v);
933 PyList_SET_ITEM(list, i, line);
934 }
935 }
936
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000937 self->f_softspace = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000938
939 /* Since we are releasing the global lock, the
940 following code may *not* execute Python code. */
941 Py_BEGIN_ALLOW_THREADS
942 for (i = 0; i < j; i++) {
943 line = PyList_GET_ITEM(list, i);
944 len = PyString_GET_SIZE(line);
945 BZ2_bzWrite (&bzerror, self->fp,
946 PyString_AS_STRING(line), len);
947 if (bzerror != BZ_OK) {
948 Py_BLOCK_THREADS
949 Util_CatchBZ2Error(bzerror);
950 goto error;
951 }
952 }
953 Py_END_ALLOW_THREADS
954
955 if (j < CHUNKSIZE)
956 break;
957 }
958
959 Py_INCREF(Py_None);
960 ret = Py_None;
961
962 error:
963 RELEASE_LOCK(self);
964 Py_XDECREF(list);
965 Py_XDECREF(iter);
966 return ret;
967#undef CHUNKSIZE
968}
969
970PyDoc_STRVAR(BZ2File_seek__doc__,
971"seek(offset [, whence]) -> None\n\
972\n\
973Move to new file position. Argument offset is a byte count. Optional\n\
974argument whence defaults to 0 (offset from start of file, offset\n\
975should be >= 0); other values are 1 (move relative to current position,\n\
976positive or negative), and 2 (move relative to end of file, usually\n\
977negative, although many platforms allow seeking beyond the end of a file).\n\
978\n\
979Note that seeking of bz2 files is emulated, and depending on the parameters\n\
980the operation may be extremely slow.\n\
981");
982
983static PyObject *
984BZ2File_seek(BZ2FileObject *self, PyObject *args)
985{
986 int where = 0;
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000987 PyObject *offobj;
988 Py_off_t offset;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000989 char small_buffer[SMALLCHUNK];
990 char *buffer = small_buffer;
991 size_t buffersize = SMALLCHUNK;
992 int bytesread = 0;
Georg Brandla8bcecc2005-09-03 07:49:53 +0000993 size_t readsize;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000994 int chunksize;
995 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000996 PyObject *ret = NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000997
Georg Brandl33a5f2a2005-08-21 14:16:04 +0000998 if (!PyArg_ParseTuple(args, "O|i:seek", &offobj, &where))
999 return NULL;
1000#if !defined(HAVE_LARGEFILE_SUPPORT)
1001 offset = PyInt_AsLong(offobj);
1002#else
1003 offset = PyLong_Check(offobj) ?
1004 PyLong_AsLongLong(offobj) : PyInt_AsLong(offobj);
1005#endif
1006 if (PyErr_Occurred())
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001007 return NULL;
1008
1009 ACQUIRE_LOCK(self);
1010 Util_DropReadAhead(self);
1011 switch (self->mode) {
1012 case MODE_READ:
1013 case MODE_READ_EOF:
1014 break;
Tim Peterse3228092002-11-09 04:21:44 +00001015
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001016 case MODE_CLOSED:
1017 PyErr_SetString(PyExc_ValueError,
1018 "I/O operation on closed file");
Thomas Wouters89f507f2006-12-13 04:49:30 +00001019 goto cleanup;
Tim Peterse3228092002-11-09 04:21:44 +00001020
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001021 default:
1022 PyErr_SetString(PyExc_IOError,
1023 "seek works only while reading");
Thomas Wouters89f507f2006-12-13 04:49:30 +00001024 goto cleanup;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001025 }
1026
Georg Brandl47fab922006-02-18 21:57:25 +00001027 if (where == 2) {
1028 if (self->size == -1) {
1029 assert(self->mode != MODE_READ_EOF);
1030 for (;;) {
1031 Py_BEGIN_ALLOW_THREADS
1032 chunksize = Util_UnivNewlineRead(
1033 &bzerror, self->fp,
1034 buffer, buffersize,
1035 self);
1036 self->pos += chunksize;
1037 Py_END_ALLOW_THREADS
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001038
Georg Brandl47fab922006-02-18 21:57:25 +00001039 bytesread += chunksize;
1040 if (bzerror == BZ_STREAM_END) {
1041 break;
1042 } else if (bzerror != BZ_OK) {
1043 Util_CatchBZ2Error(bzerror);
1044 goto cleanup;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001045 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001046 }
Georg Brandl47fab922006-02-18 21:57:25 +00001047 self->mode = MODE_READ_EOF;
1048 self->size = self->pos;
1049 bytesread = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001050 }
Georg Brandl47fab922006-02-18 21:57:25 +00001051 offset = self->size + offset;
1052 } else if (where == 1) {
1053 offset = self->pos + offset;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001054 }
1055
Georg Brandl47fab922006-02-18 21:57:25 +00001056 /* Before getting here, offset must be the absolute position the file
1057 * pointer should be set to. */
1058
1059 if (offset >= self->pos) {
1060 /* we can move forward */
1061 offset -= self->pos;
1062 } else {
1063 /* we cannot move back, so rewind the stream */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001064 BZ2_bzReadClose(&bzerror, self->fp);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001065 if (bzerror != BZ_OK) {
1066 Util_CatchBZ2Error(bzerror);
1067 goto cleanup;
1068 }
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001069 ret = PyObject_CallMethod(self->file, "seek", "(i)", 0);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001070 if (!ret)
1071 goto cleanup;
1072 Py_DECREF(ret);
1073 ret = NULL;
1074 self->pos = 0;
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001075 self->fp = BZ2_bzReadOpen(&bzerror, PyFile_AsFile(self->file),
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001076 0, 0, NULL, 0);
1077 if (bzerror != BZ_OK) {
1078 Util_CatchBZ2Error(bzerror);
1079 goto cleanup;
1080 }
1081 self->mode = MODE_READ;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001082 }
1083
Georg Brandl47fab922006-02-18 21:57:25 +00001084 if (offset <= 0 || self->mode == MODE_READ_EOF)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001085 goto exit;
1086
1087 /* Before getting here, offset must be set to the number of bytes
1088 * to walk forward. */
1089 for (;;) {
Georg Brandla8bcecc2005-09-03 07:49:53 +00001090 if (offset-bytesread > buffersize)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001091 readsize = buffersize;
1092 else
Georg Brandla8bcecc2005-09-03 07:49:53 +00001093 /* offset might be wider that readsize, but the result
1094 * of the subtraction is bound by buffersize (see the
1095 * condition above). buffersize is 8192. */
1096 readsize = (size_t)(offset-bytesread);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001097 Py_BEGIN_ALLOW_THREADS
1098 chunksize = Util_UnivNewlineRead(&bzerror, self->fp,
1099 buffer, readsize, self);
1100 self->pos += chunksize;
1101 Py_END_ALLOW_THREADS
1102 bytesread += chunksize;
1103 if (bzerror == BZ_STREAM_END) {
1104 self->size = self->pos;
1105 self->mode = MODE_READ_EOF;
1106 break;
1107 } else if (bzerror != BZ_OK) {
1108 Util_CatchBZ2Error(bzerror);
1109 goto cleanup;
1110 }
1111 if (bytesread == offset)
1112 break;
1113 }
1114
1115exit:
1116 Py_INCREF(Py_None);
1117 ret = Py_None;
1118
1119cleanup:
1120 RELEASE_LOCK(self);
1121 return ret;
1122}
1123
1124PyDoc_STRVAR(BZ2File_tell__doc__,
1125"tell() -> int\n\
1126\n\
1127Return the current file position, an integer (may be a long integer).\n\
1128");
1129
1130static PyObject *
1131BZ2File_tell(BZ2FileObject *self, PyObject *args)
1132{
1133 PyObject *ret = NULL;
1134
1135 if (self->mode == MODE_CLOSED) {
1136 PyErr_SetString(PyExc_ValueError,
1137 "I/O operation on closed file");
1138 goto cleanup;
1139 }
1140
Georg Brandla8bcecc2005-09-03 07:49:53 +00001141#if !defined(HAVE_LARGEFILE_SUPPORT)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001142 ret = PyInt_FromLong(self->pos);
Georg Brandla8bcecc2005-09-03 07:49:53 +00001143#else
1144 ret = PyLong_FromLongLong(self->pos);
1145#endif
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001146
1147cleanup:
1148 return ret;
1149}
1150
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001151PyDoc_STRVAR(BZ2File_close__doc__,
1152"close() -> None or (perhaps) an integer\n\
1153\n\
1154Close the file. Sets data attribute .closed to true. A closed file\n\
1155cannot be used for further I/O operations. close() may be called more\n\
1156than once without error.\n\
1157");
1158
1159static PyObject *
1160BZ2File_close(BZ2FileObject *self)
1161{
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001162 PyObject *ret = NULL;
1163 int bzerror = BZ_OK;
1164
1165 ACQUIRE_LOCK(self);
1166 switch (self->mode) {
1167 case MODE_READ:
1168 case MODE_READ_EOF:
1169 BZ2_bzReadClose(&bzerror, self->fp);
1170 break;
1171 case MODE_WRITE:
1172 BZ2_bzWriteClose(&bzerror, self->fp,
1173 0, NULL, NULL);
1174 break;
1175 }
1176 self->mode = MODE_CLOSED;
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001177 ret = PyObject_CallMethod(self->file, "close", NULL);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001178 if (bzerror != BZ_OK) {
1179 Util_CatchBZ2Error(bzerror);
1180 Py_XDECREF(ret);
1181 ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001182 }
1183
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001184 RELEASE_LOCK(self);
1185 return ret;
1186}
1187
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001188static PyObject *BZ2File_getiter(BZ2FileObject *self);
1189
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001190static PyMethodDef BZ2File_methods[] = {
1191 {"read", (PyCFunction)BZ2File_read, METH_VARARGS, BZ2File_read__doc__},
1192 {"readline", (PyCFunction)BZ2File_readline, METH_VARARGS, BZ2File_readline__doc__},
1193 {"readlines", (PyCFunction)BZ2File_readlines, METH_VARARGS, BZ2File_readlines__doc__},
1194 {"write", (PyCFunction)BZ2File_write, METH_VARARGS, BZ2File_write__doc__},
1195 {"writelines", (PyCFunction)BZ2File_writelines, METH_O, BZ2File_writelines__doc__},
1196 {"seek", (PyCFunction)BZ2File_seek, METH_VARARGS, BZ2File_seek__doc__},
1197 {"tell", (PyCFunction)BZ2File_tell, METH_NOARGS, BZ2File_tell__doc__},
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001198 {"close", (PyCFunction)BZ2File_close, METH_NOARGS, BZ2File_close__doc__},
1199 {NULL, NULL} /* sentinel */
1200};
1201
1202
1203/* ===================================================================== */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001204/* Getters and setters of BZ2File. */
1205
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001206/* This is a hacked version of Python's fileobject.c:get_newlines(). */
1207static PyObject *
1208BZ2File_get_newlines(BZ2FileObject *self, void *closure)
1209{
1210 switch (self->f_newlinetypes) {
1211 case NEWLINE_UNKNOWN:
1212 Py_INCREF(Py_None);
1213 return Py_None;
1214 case NEWLINE_CR:
1215 return PyString_FromString("\r");
1216 case NEWLINE_LF:
1217 return PyString_FromString("\n");
1218 case NEWLINE_CR|NEWLINE_LF:
1219 return Py_BuildValue("(ss)", "\r", "\n");
1220 case NEWLINE_CRLF:
1221 return PyString_FromString("\r\n");
1222 case NEWLINE_CR|NEWLINE_CRLF:
1223 return Py_BuildValue("(ss)", "\r", "\r\n");
1224 case NEWLINE_LF|NEWLINE_CRLF:
1225 return Py_BuildValue("(ss)", "\n", "\r\n");
1226 case NEWLINE_CR|NEWLINE_LF|NEWLINE_CRLF:
1227 return Py_BuildValue("(sss)", "\r", "\n", "\r\n");
1228 default:
1229 PyErr_Format(PyExc_SystemError,
1230 "Unknown newlines value 0x%x\n",
1231 self->f_newlinetypes);
1232 return NULL;
1233 }
1234}
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001235
1236static PyObject *
1237BZ2File_get_closed(BZ2FileObject *self, void *closure)
1238{
1239 return PyInt_FromLong(self->mode == MODE_CLOSED);
1240}
1241
1242static PyObject *
1243BZ2File_get_mode(BZ2FileObject *self, void *closure)
1244{
1245 return PyObject_GetAttrString(self->file, "mode");
1246}
1247
1248static PyObject *
1249BZ2File_get_name(BZ2FileObject *self, void *closure)
1250{
1251 return PyObject_GetAttrString(self->file, "name");
1252}
1253
1254static PyGetSetDef BZ2File_getset[] = {
1255 {"closed", (getter)BZ2File_get_closed, NULL,
1256 "True if the file is closed"},
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001257 {"newlines", (getter)BZ2File_get_newlines, NULL,
1258 "end-of-line convention used in this file"},
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001259 {"mode", (getter)BZ2File_get_mode, NULL,
1260 "file mode ('r', 'w', or 'U')"},
1261 {"name", (getter)BZ2File_get_name, NULL,
1262 "file name"},
1263 {NULL} /* Sentinel */
1264};
1265
1266
1267/* ===================================================================== */
1268/* Members of BZ2File_Type. */
1269
1270#undef OFF
1271#define OFF(x) offsetof(BZ2FileObject, x)
1272
1273static PyMemberDef BZ2File_members[] = {
1274 {"softspace", T_INT, OFF(f_softspace), 0,
1275 "flag indicating that a space needs to be printed; used by print"},
1276 {NULL} /* Sentinel */
1277};
1278
1279/* ===================================================================== */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001280/* Slot definitions for BZ2File_Type. */
1281
1282static int
1283BZ2File_init(BZ2FileObject *self, PyObject *args, PyObject *kwargs)
1284{
Martin v. Löwis15e62742006-02-27 16:46:16 +00001285 static char *kwlist[] = {"filename", "mode", "buffering",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001286 "compresslevel", 0};
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001287 PyObject *name;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001288 char *mode = "r";
1289 int buffering = -1;
1290 int compresslevel = 9;
1291 int bzerror;
1292 int mode_char = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001293
1294 self->size = -1;
Tim Peterse3228092002-11-09 04:21:44 +00001295
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001296 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|sii:BZ2File",
1297 kwlist, &name, &mode, &buffering,
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001298 &compresslevel))
1299 return -1;
1300
1301 if (compresslevel < 1 || compresslevel > 9) {
1302 PyErr_SetString(PyExc_ValueError,
1303 "compresslevel must be between 1 and 9");
1304 return -1;
1305 }
1306
1307 for (;;) {
1308 int error = 0;
1309 switch (*mode) {
1310 case 'r':
1311 case 'w':
1312 if (mode_char)
1313 error = 1;
1314 mode_char = *mode;
1315 break;
1316
1317 case 'b':
1318 break;
1319
1320 case 'U':
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001321#ifdef __VMS
1322 self->f_univ_newline = 0;
1323#else
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001324 self->f_univ_newline = 1;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001325#endif
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001326 break;
1327
1328 default:
1329 error = 1;
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001330 break;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001331 }
1332 if (error) {
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001333 PyErr_Format(PyExc_ValueError,
1334 "invalid mode char %c", *mode);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001335 return -1;
1336 }
1337 mode++;
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001338 if (*mode == '\0')
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001339 break;
1340 }
1341
Georg Brandl6b95f1d2005-06-03 19:47:00 +00001342 if (mode_char == 0) {
1343 mode_char = 'r';
1344 }
1345
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001346 mode = (mode_char == 'r') ? "rb" : "wb";
Tim Peterse3228092002-11-09 04:21:44 +00001347
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001348 self->file = PyObject_CallFunction((PyObject*)&PyFile_Type, "(Osi)",
1349 name, mode, buffering);
1350 if (self->file == NULL)
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001351 return -1;
1352
1353 /* From now on, we have stuff to dealloc, so jump to error label
1354 * instead of returning */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001355
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001356#ifdef WITH_THREAD
1357 self->lock = PyThread_allocate_lock();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001358 if (!self->lock) {
1359 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001360 goto error;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001361 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001362#endif
1363
1364 if (mode_char == 'r')
1365 self->fp = BZ2_bzReadOpen(&bzerror,
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001366 PyFile_AsFile(self->file),
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001367 0, 0, NULL, 0);
1368 else
1369 self->fp = BZ2_bzWriteOpen(&bzerror,
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001370 PyFile_AsFile(self->file),
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001371 compresslevel, 0, 0);
1372
1373 if (bzerror != BZ_OK) {
1374 Util_CatchBZ2Error(bzerror);
1375 goto error;
1376 }
1377
1378 self->mode = (mode_char == 'r') ? MODE_READ : MODE_WRITE;
1379
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001380 return 0;
1381
1382error:
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001383 Py_CLEAR(self->file);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001384#ifdef WITH_THREAD
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001385 if (self->lock) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001386 PyThread_free_lock(self->lock);
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001387 self->lock = NULL;
1388 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001389#endif
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001390 return -1;
1391}
1392
1393static void
1394BZ2File_dealloc(BZ2FileObject *self)
1395{
1396 int bzerror;
1397#ifdef WITH_THREAD
1398 if (self->lock)
1399 PyThread_free_lock(self->lock);
1400#endif
1401 switch (self->mode) {
1402 case MODE_READ:
1403 case MODE_READ_EOF:
1404 BZ2_bzReadClose(&bzerror, self->fp);
1405 break;
1406 case MODE_WRITE:
1407 BZ2_bzWriteClose(&bzerror, self->fp,
1408 0, NULL, NULL);
1409 break;
1410 }
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001411 Util_DropReadAhead(self);
Gustavo Niemeyer572f5232003-04-29 14:53:08 +00001412 Py_XDECREF(self->file);
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001413 self->ob_type->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001414}
1415
1416/* This is a hacked version of Python's fileobject.c:file_getiter(). */
1417static PyObject *
1418BZ2File_getiter(BZ2FileObject *self)
1419{
1420 if (self->mode == MODE_CLOSED) {
1421 PyErr_SetString(PyExc_ValueError,
1422 "I/O operation on closed file");
1423 return NULL;
1424 }
1425 Py_INCREF((PyObject*)self);
1426 return (PyObject *)self;
1427}
1428
1429/* This is a hacked version of Python's fileobject.c:file_iternext(). */
1430#define READAHEAD_BUFSIZE 8192
1431static PyObject *
1432BZ2File_iternext(BZ2FileObject *self)
1433{
1434 PyStringObject* ret;
1435 ACQUIRE_LOCK(self);
1436 if (self->mode == MODE_CLOSED) {
1437 PyErr_SetString(PyExc_ValueError,
1438 "I/O operation on closed file");
1439 return NULL;
1440 }
1441 ret = Util_ReadAheadGetLineSkip(self, 0, READAHEAD_BUFSIZE);
1442 RELEASE_LOCK(self);
1443 if (ret == NULL || PyString_GET_SIZE(ret) == 0) {
1444 Py_XDECREF(ret);
1445 return NULL;
1446 }
1447 return (PyObject *)ret;
1448}
1449
1450/* ===================================================================== */
1451/* BZ2File_Type definition. */
1452
1453PyDoc_VAR(BZ2File__doc__) =
1454PyDoc_STR(
1455"BZ2File(name [, mode='r', buffering=0, compresslevel=9]) -> file object\n\
1456\n\
1457Open a bz2 file. The mode can be 'r' or 'w', for reading (default) or\n\
1458writing. When opened for writing, the file will be created if it doesn't\n\
1459exist, and truncated otherwise. If the buffering argument is given, 0 means\n\
1460unbuffered, and larger numbers specify the buffer size. If compresslevel\n\
1461is given, must be a number between 1 and 9.\n\
1462")
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001463PyDoc_STR(
1464"\n\
1465Add a 'U' to mode to open the file for input with universal newline\n\
1466support. Any line ending in the input file will be seen as a '\\n' in\n\
1467Python. Also, a file so opened gains the attribute 'newlines'; the value\n\
1468for this attribute is one of None (no newline read yet), '\\r', '\\n',\n\
1469'\\r\\n' or a tuple containing all the newline types seen. Universal\n\
1470newlines are available only when reading.\n\
1471")
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001472;
1473
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001474static PyTypeObject BZ2File_Type = {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001475 PyObject_HEAD_INIT(NULL)
1476 0, /*ob_size*/
1477 "bz2.BZ2File", /*tp_name*/
1478 sizeof(BZ2FileObject), /*tp_basicsize*/
1479 0, /*tp_itemsize*/
1480 (destructor)BZ2File_dealloc, /*tp_dealloc*/
1481 0, /*tp_print*/
1482 0, /*tp_getattr*/
1483 0, /*tp_setattr*/
1484 0, /*tp_compare*/
1485 0, /*tp_repr*/
1486 0, /*tp_as_number*/
1487 0, /*tp_as_sequence*/
1488 0, /*tp_as_mapping*/
1489 0, /*tp_hash*/
1490 0, /*tp_call*/
1491 0, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001492 PyObject_GenericGetAttr,/*tp_getattro*/
1493 PyObject_GenericSetAttr,/*tp_setattro*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001494 0, /*tp_as_buffer*/
1495 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1496 BZ2File__doc__, /*tp_doc*/
1497 0, /*tp_traverse*/
1498 0, /*tp_clear*/
1499 0, /*tp_richcompare*/
1500 0, /*tp_weaklistoffset*/
1501 (getiterfunc)BZ2File_getiter, /*tp_iter*/
1502 (iternextfunc)BZ2File_iternext, /*tp_iternext*/
1503 BZ2File_methods, /*tp_methods*/
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001504 BZ2File_members, /*tp_members*/
1505 BZ2File_getset, /*tp_getset*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001506 0, /*tp_base*/
1507 0, /*tp_dict*/
1508 0, /*tp_descr_get*/
1509 0, /*tp_descr_set*/
1510 0, /*tp_dictoffset*/
1511 (initproc)BZ2File_init, /*tp_init*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001512 PyType_GenericAlloc, /*tp_alloc*/
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001513 PyType_GenericNew, /*tp_new*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001514 _PyObject_Del, /*tp_free*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001515 0, /*tp_is_gc*/
1516};
1517
1518
1519/* ===================================================================== */
1520/* Methods of BZ2Comp. */
1521
1522PyDoc_STRVAR(BZ2Comp_compress__doc__,
1523"compress(data) -> string\n\
1524\n\
1525Provide more data to the compressor object. It will return chunks of\n\
1526compressed data whenever possible. When you've finished providing data\n\
1527to compress, call the flush() method to finish the compression process,\n\
1528and return what is left in the internal buffers.\n\
1529");
1530
1531static PyObject *
1532BZ2Comp_compress(BZ2CompObject *self, PyObject *args)
1533{
1534 char *data;
1535 int datasize;
1536 int bufsize = SMALLCHUNK;
Martin v. Löwisb9a0f912003-03-29 10:06:18 +00001537 PY_LONG_LONG totalout;
Gustavo Niemeyer7d7930b2002-11-05 18:41:53 +00001538 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001539 bz_stream *bzs = &self->bzs;
1540 int bzerror;
1541
Walter Dörwaldbb9c7392004-11-01 17:10:19 +00001542 if (!PyArg_ParseTuple(args, "s#:compress", &data, &datasize))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001543 return NULL;
1544
Gustavo Niemeyera6e436e2004-02-14 00:02:45 +00001545 if (datasize == 0)
1546 return PyString_FromString("");
1547
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001548 ACQUIRE_LOCK(self);
1549 if (!self->running) {
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001550 PyErr_SetString(PyExc_ValueError,
1551 "this object was already flushed");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001552 goto error;
1553 }
1554
1555 ret = PyString_FromStringAndSize(NULL, bufsize);
1556 if (!ret)
1557 goto error;
1558
1559 bzs->next_in = data;
1560 bzs->avail_in = datasize;
1561 bzs->next_out = BUF(ret);
1562 bzs->avail_out = bufsize;
1563
1564 totalout = BZS_TOTAL_OUT(bzs);
1565
1566 for (;;) {
1567 Py_BEGIN_ALLOW_THREADS
1568 bzerror = BZ2_bzCompress(bzs, BZ_RUN);
1569 Py_END_ALLOW_THREADS
1570 if (bzerror != BZ_RUN_OK) {
1571 Util_CatchBZ2Error(bzerror);
1572 goto error;
1573 }
1574 if (bzs->avail_out == 0) {
1575 bufsize = Util_NewBufferSize(bufsize);
1576 if (_PyString_Resize(&ret, bufsize) < 0) {
1577 BZ2_bzCompressEnd(bzs);
1578 goto error;
1579 }
1580 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs)
1581 - totalout);
1582 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
1583 } else if (bzs->avail_in == 0) {
1584 break;
1585 }
1586 }
1587
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001588 _PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001589
1590 RELEASE_LOCK(self);
1591 return ret;
1592
1593error:
1594 RELEASE_LOCK(self);
1595 Py_XDECREF(ret);
1596 return NULL;
1597}
1598
1599PyDoc_STRVAR(BZ2Comp_flush__doc__,
1600"flush() -> string\n\
1601\n\
1602Finish the compression process and return what is left in internal buffers.\n\
1603You must not use the compressor object after calling this method.\n\
1604");
1605
1606static PyObject *
1607BZ2Comp_flush(BZ2CompObject *self)
1608{
1609 int bufsize = SMALLCHUNK;
Gustavo Niemeyer7d7930b2002-11-05 18:41:53 +00001610 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001611 bz_stream *bzs = &self->bzs;
Martin v. Löwisb9a0f912003-03-29 10:06:18 +00001612 PY_LONG_LONG totalout;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001613 int bzerror;
1614
1615 ACQUIRE_LOCK(self);
1616 if (!self->running) {
1617 PyErr_SetString(PyExc_ValueError, "object was already "
1618 "flushed");
1619 goto error;
1620 }
1621 self->running = 0;
1622
1623 ret = PyString_FromStringAndSize(NULL, bufsize);
1624 if (!ret)
1625 goto error;
1626
1627 bzs->next_out = BUF(ret);
1628 bzs->avail_out = bufsize;
1629
1630 totalout = BZS_TOTAL_OUT(bzs);
1631
1632 for (;;) {
1633 Py_BEGIN_ALLOW_THREADS
1634 bzerror = BZ2_bzCompress(bzs, BZ_FINISH);
1635 Py_END_ALLOW_THREADS
1636 if (bzerror == BZ_STREAM_END) {
1637 break;
1638 } else if (bzerror != BZ_FINISH_OK) {
1639 Util_CatchBZ2Error(bzerror);
1640 goto error;
1641 }
1642 if (bzs->avail_out == 0) {
1643 bufsize = Util_NewBufferSize(bufsize);
1644 if (_PyString_Resize(&ret, bufsize) < 0)
1645 goto error;
1646 bzs->next_out = BUF(ret);
1647 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs)
1648 - totalout);
1649 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
1650 }
1651 }
1652
1653 if (bzs->avail_out != 0)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001654 _PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001655
1656 RELEASE_LOCK(self);
1657 return ret;
1658
1659error:
1660 RELEASE_LOCK(self);
1661 Py_XDECREF(ret);
1662 return NULL;
1663}
1664
1665static PyMethodDef BZ2Comp_methods[] = {
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001666 {"compress", (PyCFunction)BZ2Comp_compress, METH_VARARGS,
1667 BZ2Comp_compress__doc__},
1668 {"flush", (PyCFunction)BZ2Comp_flush, METH_NOARGS,
1669 BZ2Comp_flush__doc__},
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001670 {NULL, NULL} /* sentinel */
1671};
1672
1673
1674/* ===================================================================== */
1675/* Slot definitions for BZ2Comp_Type. */
1676
1677static int
1678BZ2Comp_init(BZ2CompObject *self, PyObject *args, PyObject *kwargs)
1679{
1680 int compresslevel = 9;
1681 int bzerror;
Martin v. Löwis15e62742006-02-27 16:46:16 +00001682 static char *kwlist[] = {"compresslevel", 0};
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001683
1684 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:BZ2Compressor",
1685 kwlist, &compresslevel))
1686 return -1;
1687
1688 if (compresslevel < 1 || compresslevel > 9) {
1689 PyErr_SetString(PyExc_ValueError,
1690 "compresslevel must be between 1 and 9");
1691 goto error;
1692 }
1693
1694#ifdef WITH_THREAD
1695 self->lock = PyThread_allocate_lock();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001696 if (!self->lock) {
1697 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001698 goto error;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001699 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001700#endif
1701
1702 memset(&self->bzs, 0, sizeof(bz_stream));
1703 bzerror = BZ2_bzCompressInit(&self->bzs, compresslevel, 0, 0);
1704 if (bzerror != BZ_OK) {
1705 Util_CatchBZ2Error(bzerror);
1706 goto error;
1707 }
1708
1709 self->running = 1;
1710
1711 return 0;
1712error:
1713#ifdef WITH_THREAD
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001714 if (self->lock) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001715 PyThread_free_lock(self->lock);
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001716 self->lock = NULL;
1717 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001718#endif
1719 return -1;
1720}
1721
1722static void
1723BZ2Comp_dealloc(BZ2CompObject *self)
1724{
1725#ifdef WITH_THREAD
1726 if (self->lock)
1727 PyThread_free_lock(self->lock);
1728#endif
1729 BZ2_bzCompressEnd(&self->bzs);
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001730 self->ob_type->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001731}
1732
1733
1734/* ===================================================================== */
1735/* BZ2Comp_Type definition. */
1736
1737PyDoc_STRVAR(BZ2Comp__doc__,
1738"BZ2Compressor([compresslevel=9]) -> compressor object\n\
1739\n\
1740Create a new compressor object. This object may be used to compress\n\
1741data sequentially. If you want to compress data in one shot, use the\n\
1742compress() function instead. The compresslevel parameter, if given,\n\
1743must be a number between 1 and 9.\n\
1744");
1745
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001746static PyTypeObject BZ2Comp_Type = {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001747 PyObject_HEAD_INIT(NULL)
1748 0, /*ob_size*/
1749 "bz2.BZ2Compressor", /*tp_name*/
1750 sizeof(BZ2CompObject), /*tp_basicsize*/
1751 0, /*tp_itemsize*/
1752 (destructor)BZ2Comp_dealloc, /*tp_dealloc*/
1753 0, /*tp_print*/
1754 0, /*tp_getattr*/
1755 0, /*tp_setattr*/
1756 0, /*tp_compare*/
1757 0, /*tp_repr*/
1758 0, /*tp_as_number*/
1759 0, /*tp_as_sequence*/
1760 0, /*tp_as_mapping*/
1761 0, /*tp_hash*/
1762 0, /*tp_call*/
1763 0, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001764 PyObject_GenericGetAttr,/*tp_getattro*/
1765 PyObject_GenericSetAttr,/*tp_setattro*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001766 0, /*tp_as_buffer*/
1767 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1768 BZ2Comp__doc__, /*tp_doc*/
1769 0, /*tp_traverse*/
1770 0, /*tp_clear*/
1771 0, /*tp_richcompare*/
1772 0, /*tp_weaklistoffset*/
1773 0, /*tp_iter*/
1774 0, /*tp_iternext*/
1775 BZ2Comp_methods, /*tp_methods*/
1776 0, /*tp_members*/
1777 0, /*tp_getset*/
1778 0, /*tp_base*/
1779 0, /*tp_dict*/
1780 0, /*tp_descr_get*/
1781 0, /*tp_descr_set*/
1782 0, /*tp_dictoffset*/
1783 (initproc)BZ2Comp_init, /*tp_init*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001784 PyType_GenericAlloc, /*tp_alloc*/
1785 PyType_GenericNew, /*tp_new*/
1786 _PyObject_Del, /*tp_free*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001787 0, /*tp_is_gc*/
1788};
1789
1790
1791/* ===================================================================== */
1792/* Members of BZ2Decomp. */
1793
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001794#undef OFF
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001795#define OFF(x) offsetof(BZ2DecompObject, x)
1796
1797static PyMemberDef BZ2Decomp_members[] = {
1798 {"unused_data", T_OBJECT, OFF(unused_data), RO},
1799 {NULL} /* Sentinel */
1800};
1801
1802
1803/* ===================================================================== */
1804/* Methods of BZ2Decomp. */
1805
1806PyDoc_STRVAR(BZ2Decomp_decompress__doc__,
1807"decompress(data) -> string\n\
1808\n\
1809Provide more data to the decompressor object. It will return chunks\n\
1810of decompressed data whenever possible. If you try to decompress data\n\
1811after the end of stream is found, EOFError will be raised. If any data\n\
1812was found after the end of stream, it'll be ignored and saved in\n\
1813unused_data attribute.\n\
1814");
1815
1816static PyObject *
1817BZ2Decomp_decompress(BZ2DecompObject *self, PyObject *args)
1818{
1819 char *data;
1820 int datasize;
1821 int bufsize = SMALLCHUNK;
Martin v. Löwisb9a0f912003-03-29 10:06:18 +00001822 PY_LONG_LONG totalout;
Neal Norwitz18142c02002-11-05 18:17:32 +00001823 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001824 bz_stream *bzs = &self->bzs;
1825 int bzerror;
1826
Walter Dörwaldbb9c7392004-11-01 17:10:19 +00001827 if (!PyArg_ParseTuple(args, "s#:decompress", &data, &datasize))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001828 return NULL;
1829
1830 ACQUIRE_LOCK(self);
1831 if (!self->running) {
1832 PyErr_SetString(PyExc_EOFError, "end of stream was "
1833 "already found");
1834 goto error;
1835 }
1836
1837 ret = PyString_FromStringAndSize(NULL, bufsize);
1838 if (!ret)
1839 goto error;
1840
1841 bzs->next_in = data;
1842 bzs->avail_in = datasize;
1843 bzs->next_out = BUF(ret);
1844 bzs->avail_out = bufsize;
1845
1846 totalout = BZS_TOTAL_OUT(bzs);
1847
1848 for (;;) {
1849 Py_BEGIN_ALLOW_THREADS
1850 bzerror = BZ2_bzDecompress(bzs);
1851 Py_END_ALLOW_THREADS
1852 if (bzerror == BZ_STREAM_END) {
1853 if (bzs->avail_in != 0) {
1854 Py_DECREF(self->unused_data);
1855 self->unused_data =
1856 PyString_FromStringAndSize(bzs->next_in,
1857 bzs->avail_in);
1858 }
1859 self->running = 0;
1860 break;
1861 }
1862 if (bzerror != BZ_OK) {
1863 Util_CatchBZ2Error(bzerror);
1864 goto error;
1865 }
1866 if (bzs->avail_out == 0) {
1867 bufsize = Util_NewBufferSize(bufsize);
1868 if (_PyString_Resize(&ret, bufsize) < 0) {
1869 BZ2_bzDecompressEnd(bzs);
1870 goto error;
1871 }
1872 bzs->next_out = BUF(ret);
1873 bzs->next_out = BUF(ret) + (BZS_TOTAL_OUT(bzs)
1874 - totalout);
1875 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
1876 } else if (bzs->avail_in == 0) {
1877 break;
1878 }
1879 }
1880
1881 if (bzs->avail_out != 0)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001882 _PyString_Resize(&ret, (Py_ssize_t)(BZS_TOTAL_OUT(bzs) - totalout));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001883
1884 RELEASE_LOCK(self);
1885 return ret;
1886
1887error:
1888 RELEASE_LOCK(self);
1889 Py_XDECREF(ret);
1890 return NULL;
1891}
1892
1893static PyMethodDef BZ2Decomp_methods[] = {
1894 {"decompress", (PyCFunction)BZ2Decomp_decompress, METH_VARARGS, BZ2Decomp_decompress__doc__},
1895 {NULL, NULL} /* sentinel */
1896};
1897
1898
1899/* ===================================================================== */
1900/* Slot definitions for BZ2Decomp_Type. */
1901
1902static int
1903BZ2Decomp_init(BZ2DecompObject *self, PyObject *args, PyObject *kwargs)
1904{
1905 int bzerror;
1906
1907 if (!PyArg_ParseTuple(args, ":BZ2Decompressor"))
1908 return -1;
1909
1910#ifdef WITH_THREAD
1911 self->lock = PyThread_allocate_lock();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001912 if (!self->lock) {
1913 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001914 goto error;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001915 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001916#endif
1917
1918 self->unused_data = PyString_FromString("");
1919 if (!self->unused_data)
1920 goto error;
1921
1922 memset(&self->bzs, 0, sizeof(bz_stream));
1923 bzerror = BZ2_bzDecompressInit(&self->bzs, 0, 0);
1924 if (bzerror != BZ_OK) {
1925 Util_CatchBZ2Error(bzerror);
1926 goto error;
1927 }
1928
1929 self->running = 1;
1930
1931 return 0;
1932
1933error:
1934#ifdef WITH_THREAD
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001935 if (self->lock) {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001936 PyThread_free_lock(self->lock);
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001937 self->lock = NULL;
1938 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001939#endif
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001940 Py_CLEAR(self->unused_data);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001941 return -1;
1942}
1943
1944static void
1945BZ2Decomp_dealloc(BZ2DecompObject *self)
1946{
1947#ifdef WITH_THREAD
1948 if (self->lock)
1949 PyThread_free_lock(self->lock);
1950#endif
1951 Py_XDECREF(self->unused_data);
1952 BZ2_bzDecompressEnd(&self->bzs);
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001953 self->ob_type->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001954}
1955
1956
1957/* ===================================================================== */
1958/* BZ2Decomp_Type definition. */
1959
1960PyDoc_STRVAR(BZ2Decomp__doc__,
1961"BZ2Decompressor() -> decompressor object\n\
1962\n\
1963Create a new decompressor object. This object may be used to decompress\n\
1964data sequentially. If you want to decompress data in one shot, use the\n\
1965decompress() function instead.\n\
1966");
1967
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001968static PyTypeObject BZ2Decomp_Type = {
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001969 PyObject_HEAD_INIT(NULL)
1970 0, /*ob_size*/
1971 "bz2.BZ2Decompressor", /*tp_name*/
1972 sizeof(BZ2DecompObject), /*tp_basicsize*/
1973 0, /*tp_itemsize*/
1974 (destructor)BZ2Decomp_dealloc, /*tp_dealloc*/
1975 0, /*tp_print*/
1976 0, /*tp_getattr*/
1977 0, /*tp_setattr*/
1978 0, /*tp_compare*/
1979 0, /*tp_repr*/
1980 0, /*tp_as_number*/
1981 0, /*tp_as_sequence*/
1982 0, /*tp_as_mapping*/
1983 0, /*tp_hash*/
1984 0, /*tp_call*/
1985 0, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00001986 PyObject_GenericGetAttr,/*tp_getattro*/
1987 PyObject_GenericSetAttr,/*tp_setattro*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001988 0, /*tp_as_buffer*/
1989 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1990 BZ2Decomp__doc__, /*tp_doc*/
1991 0, /*tp_traverse*/
1992 0, /*tp_clear*/
1993 0, /*tp_richcompare*/
1994 0, /*tp_weaklistoffset*/
1995 0, /*tp_iter*/
1996 0, /*tp_iternext*/
1997 BZ2Decomp_methods, /*tp_methods*/
1998 BZ2Decomp_members, /*tp_members*/
1999 0, /*tp_getset*/
2000 0, /*tp_base*/
2001 0, /*tp_dict*/
2002 0, /*tp_descr_get*/
2003 0, /*tp_descr_set*/
2004 0, /*tp_dictoffset*/
2005 (initproc)BZ2Decomp_init, /*tp_init*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +00002006 PyType_GenericAlloc, /*tp_alloc*/
2007 PyType_GenericNew, /*tp_new*/
2008 _PyObject_Del, /*tp_free*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002009 0, /*tp_is_gc*/
2010};
2011
2012
2013/* ===================================================================== */
2014/* Module functions. */
2015
2016PyDoc_STRVAR(bz2_compress__doc__,
2017"compress(data [, compresslevel=9]) -> string\n\
2018\n\
2019Compress data in one shot. If you want to compress data sequentially,\n\
2020use an instance of BZ2Compressor instead. The compresslevel parameter, if\n\
2021given, must be a number between 1 and 9.\n\
2022");
2023
2024static PyObject *
2025bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
2026{
2027 int compresslevel=9;
2028 char *data;
2029 int datasize;
2030 int bufsize;
Gustavo Niemeyer7d7930b2002-11-05 18:41:53 +00002031 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002032 bz_stream _bzs;
2033 bz_stream *bzs = &_bzs;
2034 int bzerror;
Martin v. Löwis15e62742006-02-27 16:46:16 +00002035 static char *kwlist[] = {"data", "compresslevel", 0};
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002036
2037 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|i",
2038 kwlist, &data, &datasize,
2039 &compresslevel))
2040 return NULL;
2041
2042 if (compresslevel < 1 || compresslevel > 9) {
2043 PyErr_SetString(PyExc_ValueError,
2044 "compresslevel must be between 1 and 9");
2045 return NULL;
2046 }
2047
2048 /* Conforming to bz2 manual, this is large enough to fit compressed
2049 * data in one shot. We will check it later anyway. */
2050 bufsize = datasize + (datasize/100+1) + 600;
2051
2052 ret = PyString_FromStringAndSize(NULL, bufsize);
2053 if (!ret)
2054 return NULL;
2055
2056 memset(bzs, 0, sizeof(bz_stream));
2057
2058 bzs->next_in = data;
2059 bzs->avail_in = datasize;
2060 bzs->next_out = BUF(ret);
2061 bzs->avail_out = bufsize;
2062
2063 bzerror = BZ2_bzCompressInit(bzs, compresslevel, 0, 0);
2064 if (bzerror != BZ_OK) {
2065 Util_CatchBZ2Error(bzerror);
2066 Py_DECREF(ret);
2067 return NULL;
2068 }
Tim Peterse3228092002-11-09 04:21:44 +00002069
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002070 for (;;) {
2071 Py_BEGIN_ALLOW_THREADS
2072 bzerror = BZ2_bzCompress(bzs, BZ_FINISH);
2073 Py_END_ALLOW_THREADS
2074 if (bzerror == BZ_STREAM_END) {
2075 break;
2076 } else if (bzerror != BZ_FINISH_OK) {
2077 BZ2_bzCompressEnd(bzs);
2078 Util_CatchBZ2Error(bzerror);
2079 Py_DECREF(ret);
2080 return NULL;
2081 }
2082 if (bzs->avail_out == 0) {
2083 bufsize = Util_NewBufferSize(bufsize);
2084 if (_PyString_Resize(&ret, bufsize) < 0) {
2085 BZ2_bzCompressEnd(bzs);
2086 Py_DECREF(ret);
2087 return NULL;
2088 }
2089 bzs->next_out = BUF(ret) + BZS_TOTAL_OUT(bzs);
2090 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
2091 }
2092 }
2093
2094 if (bzs->avail_out != 0)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002095 _PyString_Resize(&ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002096 BZ2_bzCompressEnd(bzs);
2097
2098 return ret;
2099}
2100
2101PyDoc_STRVAR(bz2_decompress__doc__,
2102"decompress(data) -> decompressed data\n\
2103\n\
2104Decompress data in one shot. If you want to decompress data sequentially,\n\
2105use an instance of BZ2Decompressor instead.\n\
2106");
2107
2108static PyObject *
2109bz2_decompress(PyObject *self, PyObject *args)
2110{
2111 char *data;
2112 int datasize;
2113 int bufsize = SMALLCHUNK;
2114 PyObject *ret;
2115 bz_stream _bzs;
2116 bz_stream *bzs = &_bzs;
2117 int bzerror;
2118
Walter Dörwaldbb9c7392004-11-01 17:10:19 +00002119 if (!PyArg_ParseTuple(args, "s#:decompress", &data, &datasize))
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002120 return NULL;
2121
2122 if (datasize == 0)
2123 return PyString_FromString("");
2124
2125 ret = PyString_FromStringAndSize(NULL, bufsize);
2126 if (!ret)
2127 return NULL;
2128
2129 memset(bzs, 0, sizeof(bz_stream));
2130
2131 bzs->next_in = data;
2132 bzs->avail_in = datasize;
2133 bzs->next_out = BUF(ret);
2134 bzs->avail_out = bufsize;
2135
2136 bzerror = BZ2_bzDecompressInit(bzs, 0, 0);
2137 if (bzerror != BZ_OK) {
2138 Util_CatchBZ2Error(bzerror);
2139 Py_DECREF(ret);
2140 return NULL;
2141 }
Tim Peterse3228092002-11-09 04:21:44 +00002142
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002143 for (;;) {
2144 Py_BEGIN_ALLOW_THREADS
2145 bzerror = BZ2_bzDecompress(bzs);
2146 Py_END_ALLOW_THREADS
2147 if (bzerror == BZ_STREAM_END) {
2148 break;
2149 } else if (bzerror != BZ_OK) {
2150 BZ2_bzDecompressEnd(bzs);
2151 Util_CatchBZ2Error(bzerror);
2152 Py_DECREF(ret);
2153 return NULL;
2154 }
2155 if (bzs->avail_out == 0) {
2156 bufsize = Util_NewBufferSize(bufsize);
2157 if (_PyString_Resize(&ret, bufsize) < 0) {
2158 BZ2_bzDecompressEnd(bzs);
2159 Py_DECREF(ret);
2160 return NULL;
2161 }
2162 bzs->next_out = BUF(ret) + BZS_TOTAL_OUT(bzs);
2163 bzs->avail_out = bufsize - (bzs->next_out - BUF(ret));
2164 } else if (bzs->avail_in == 0) {
2165 BZ2_bzDecompressEnd(bzs);
2166 PyErr_SetString(PyExc_ValueError,
2167 "couldn't find end of stream");
2168 Py_DECREF(ret);
2169 return NULL;
2170 }
2171 }
2172
2173 if (bzs->avail_out != 0)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002174 _PyString_Resize(&ret, (Py_ssize_t)BZS_TOTAL_OUT(bzs));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002175 BZ2_bzDecompressEnd(bzs);
2176
2177 return ret;
2178}
2179
2180static PyMethodDef bz2_methods[] = {
2181 {"compress", (PyCFunction) bz2_compress, METH_VARARGS|METH_KEYWORDS,
2182 bz2_compress__doc__},
2183 {"decompress", (PyCFunction) bz2_decompress, METH_VARARGS,
2184 bz2_decompress__doc__},
2185 {NULL, NULL} /* sentinel */
2186};
2187
2188/* ===================================================================== */
2189/* Initialization function. */
2190
2191PyDoc_STRVAR(bz2__doc__,
2192"The python bz2 module provides a comprehensive interface for\n\
2193the bz2 compression library. It implements a complete file\n\
2194interface, one shot (de)compression functions, and types for\n\
2195sequential (de)compression.\n\
2196");
2197
Neal Norwitz21d896c2003-07-01 20:15:21 +00002198PyMODINIT_FUNC
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002199initbz2(void)
2200{
2201 PyObject *m;
2202
2203 BZ2File_Type.ob_type = &PyType_Type;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002204 BZ2Comp_Type.ob_type = &PyType_Type;
2205 BZ2Decomp_Type.ob_type = &PyType_Type;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002206
2207 m = Py_InitModule3("bz2", bz2_methods, bz2__doc__);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00002208 if (m == NULL)
2209 return;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002210
2211 PyModule_AddObject(m, "__author__", PyString_FromString(__author__));
2212
2213 Py_INCREF(&BZ2File_Type);
2214 PyModule_AddObject(m, "BZ2File", (PyObject *)&BZ2File_Type);
2215
2216 Py_INCREF(&BZ2Comp_Type);
2217 PyModule_AddObject(m, "BZ2Compressor", (PyObject *)&BZ2Comp_Type);
2218
2219 Py_INCREF(&BZ2Decomp_Type);
2220 PyModule_AddObject(m, "BZ2Decompressor", (PyObject *)&BZ2Decomp_Type);
2221}