blob: e479777a1b34838988c46de408a66f0be058561d [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
Gregory P. Smithdd96db62008-06-09 04:58:54 +000037#define BUF(v) PyString_AS_STRING((PyStringObject *)v)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000038
39#define MODE_CLOSED 0
40#define MODE_READ 1
41#define MODE_READ_EOF 2
42#define MODE_WRITE 3
43
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000044
Nadeem Vawda45dba1d2012-10-21 23:09:08 +020045#ifndef BZ_CONFIG_ERROR
Gustavo Niemeyer7628f1f2003-04-27 06:25:24 +000046
47#define BZ2_bzRead bzRead
48#define BZ2_bzReadOpen bzReadOpen
49#define BZ2_bzReadClose bzReadClose
50#define BZ2_bzWrite bzWrite
51#define BZ2_bzWriteOpen bzWriteOpen
52#define BZ2_bzWriteClose bzWriteClose
53#define BZ2_bzCompress bzCompress
54#define BZ2_bzCompressInit bzCompressInit
55#define BZ2_bzCompressEnd bzCompressEnd
56#define BZ2_bzDecompress bzDecompress
57#define BZ2_bzDecompressInit bzDecompressInit
58#define BZ2_bzDecompressEnd bzDecompressEnd
59
Gustavo Niemeyer7628f1f2003-04-27 06:25:24 +000060#endif /* ! BZ_CONFIG_ERROR */
61
62
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000063#ifdef WITH_THREAD
Antoine Pitroudd629662009-10-27 17:41:58 +000064#define ACQUIRE_LOCK(obj) do { \
Antoine Pitrouc83ea132010-05-09 14:46:46 +000065 if (!PyThread_acquire_lock(obj->lock, 0)) { \
66 Py_BEGIN_ALLOW_THREADS \
67 PyThread_acquire_lock(obj->lock, 1); \
68 Py_END_ALLOW_THREADS \
69 } } while(0)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000070#define RELEASE_LOCK(obj) PyThread_release_lock(obj->lock)
71#else
72#define ACQUIRE_LOCK(obj)
73#define RELEASE_LOCK(obj)
74#endif
75
Nadeem Vawda45dba1d2012-10-21 23:09:08 +020076#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
77
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000078/* Bits in f_newlinetypes */
Antoine Pitrouc83ea132010-05-09 14:46:46 +000079#define NEWLINE_UNKNOWN 0 /* No newline seen, yet */
80#define NEWLINE_CR 1 /* \r newline seen */
81#define NEWLINE_LF 2 /* \n newline seen */
82#define NEWLINE_CRLF 4 /* \r\n newline seen */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +000083
84/* ===================================================================== */
85/* Structure definitions. */
86
87typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +000088 PyObject_HEAD
89 PyObject *file;
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +000090
Antoine Pitrouc83ea132010-05-09 14:46:46 +000091 char* f_buf; /* Allocated readahead buffer */
92 char* f_bufend; /* Points after last occupied position */
93 char* f_bufptr; /* Current buffer position */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +000094
Antoine Pitrouc83ea132010-05-09 14:46:46 +000095 int f_softspace; /* Flag used by 'print' command */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +000096
Antoine Pitrouc83ea132010-05-09 14:46:46 +000097 int f_univ_newline; /* Handle any newline convention */
98 int f_newlinetypes; /* Types of newlines seen */
99 int f_skipnextlf; /* Skip next \n */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000100
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000101 BZFILE *fp;
102 int mode;
103 Py_off_t pos;
104 Py_off_t size;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000105#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000106 PyThread_type_lock lock;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000107#endif
108} BZ2FileObject;
109
110typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000111 PyObject_HEAD
112 bz_stream bzs;
113 int running;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000114#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000115 PyThread_type_lock lock;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000116#endif
117} BZ2CompObject;
118
119typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000120 PyObject_HEAD
121 bz_stream bzs;
122 int running;
123 PyObject *unused_data;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000124#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000125 PyThread_type_lock lock;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000126#endif
127} BZ2DecompObject;
128
129/* ===================================================================== */
130/* Utility functions. */
131
Antoine Pitrou39703012010-08-01 20:13:11 +0000132/* Refuse regular I/O if there's data in the iteration-buffer.
133 * Mixing them would cause data to arrive out of order, as the read*
134 * methods don't use the iteration buffer. */
135static int
136check_iterbuffered(BZ2FileObject *f)
137{
138 if (f->f_buf != NULL &&
139 (f->f_bufend - f->f_bufptr) > 0 &&
140 f->f_buf[0] != '\0') {
141 PyErr_SetString(PyExc_ValueError,
142 "Mixing iteration and read methods would lose data");
143 return -1;
144 }
145 return 0;
146}
147
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000148static int
149Util_CatchBZ2Error(int bzerror)
150{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000151 int ret = 0;
152 switch(bzerror) {
153 case BZ_OK:
154 case BZ_STREAM_END:
155 break;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000156
Gustavo Niemeyer7628f1f2003-04-27 06:25:24 +0000157#ifdef BZ_CONFIG_ERROR
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000158 case BZ_CONFIG_ERROR:
159 PyErr_SetString(PyExc_SystemError,
160 "the bz2 library was not compiled "
161 "correctly");
162 ret = 1;
163 break;
Gustavo Niemeyer7628f1f2003-04-27 06:25:24 +0000164#endif
Tim Peterse3228092002-11-09 04:21:44 +0000165
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000166 case BZ_PARAM_ERROR:
167 PyErr_SetString(PyExc_ValueError,
168 "the bz2 library has received wrong "
169 "parameters");
170 ret = 1;
171 break;
Tim Peterse3228092002-11-09 04:21:44 +0000172
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000173 case BZ_MEM_ERROR:
174 PyErr_NoMemory();
175 ret = 1;
176 break;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000177
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000178 case BZ_DATA_ERROR:
179 case BZ_DATA_ERROR_MAGIC:
180 PyErr_SetString(PyExc_IOError, "invalid data stream");
181 ret = 1;
182 break;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000183
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000184 case BZ_IO_ERROR:
185 PyErr_SetString(PyExc_IOError, "unknown IO error");
186 ret = 1;
187 break;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000188
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000189 case BZ_UNEXPECTED_EOF:
190 PyErr_SetString(PyExc_EOFError,
191 "compressed file ended before the "
192 "logical end-of-stream was detected");
193 ret = 1;
194 break;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000195
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000196 case BZ_SEQUENCE_ERROR:
197 PyErr_SetString(PyExc_RuntimeError,
198 "wrong sequence of bz2 library "
199 "commands used");
200 ret = 1;
201 break;
202 }
203 return ret;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000204}
205
206#if BUFSIZ < 8192
207#define SMALLCHUNK 8192
208#else
209#define SMALLCHUNK BUFSIZ
210#endif
211
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000212/* This is a hacked version of Python's fileobject.c:new_buffersize(). */
213static size_t
214Util_NewBufferSize(size_t currentsize)
215{
Nadeem Vawda36248152011-10-13 13:52:46 +0200216 /* Expand the buffer by an amount proportional to the current size,
217 giving us amortized linear-time behavior. Use a less-than-double
218 growth factor to avoid excessive allocation. */
219 return currentsize + (currentsize >> 3) + 6;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000220}
221
Nadeem Vawda45dba1d2012-10-21 23:09:08 +0200222static int
223Util_GrowBuffer(PyObject **buf)
224{
225 size_t size = PyString_GET_SIZE(*buf);
226 size_t new_size = Util_NewBufferSize(size);
227 if (new_size > size) {
228 return _PyString_Resize(buf, new_size);
229 } else { /* overflow */
230 PyErr_SetString(PyExc_OverflowError,
231 "Unable to allocate buffer - output too large");
232 return -1;
233 }
234}
235
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000236/* This is a hacked version of Python's fileobject.c:get_line(). */
237static PyObject *
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000238Util_GetLine(BZ2FileObject *f, int n)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000239{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000240 char c;
241 char *buf, *end;
242 size_t total_v_size; /* total # of slots in buffer */
243 size_t used_v_size; /* # used slots in buffer */
244 size_t increment; /* amount to increment the buffer */
245 PyObject *v;
246 int bzerror;
247 int bytes_read;
248 int newlinetypes = f->f_newlinetypes;
249 int skipnextlf = f->f_skipnextlf;
250 int univ_newline = f->f_univ_newline;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000251
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000252 total_v_size = n > 0 ? n : 100;
253 v = PyString_FromStringAndSize((char *)NULL, total_v_size);
254 if (v == NULL)
255 return NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000256
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000257 buf = BUF(v);
258 end = buf + total_v_size;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000259
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000260 for (;;) {
261 Py_BEGIN_ALLOW_THREADS
262 while (buf != end) {
263 bytes_read = BZ2_bzRead(&bzerror, f->fp, &c, 1);
264 f->pos++;
265 if (bytes_read == 0) break;
266 if (univ_newline) {
267 if (skipnextlf) {
268 skipnextlf = 0;
269 if (c == '\n') {
270 /* Seeing a \n here with skipnextlf true means we
271 * saw a \r before.
272 */
273 newlinetypes |= NEWLINE_CRLF;
274 if (bzerror != BZ_OK) break;
275 bytes_read = BZ2_bzRead(&bzerror, f->fp, &c, 1);
276 f->pos++;
277 if (bytes_read == 0) break;
278 } else {
279 newlinetypes |= NEWLINE_CR;
280 }
281 }
282 if (c == '\r') {
283 skipnextlf = 1;
284 c = '\n';
285 } else if (c == '\n')
286 newlinetypes |= NEWLINE_LF;
287 }
288 *buf++ = c;
289 if (bzerror != BZ_OK || c == '\n') break;
290 }
291 if (univ_newline && bzerror == BZ_STREAM_END && skipnextlf)
292 newlinetypes |= NEWLINE_CR;
293 Py_END_ALLOW_THREADS
294 f->f_newlinetypes = newlinetypes;
295 f->f_skipnextlf = skipnextlf;
296 if (bzerror == BZ_STREAM_END) {
297 f->size = f->pos;
298 f->mode = MODE_READ_EOF;
299 break;
300 } else if (bzerror != BZ_OK) {
301 Util_CatchBZ2Error(bzerror);
302 Py_DECREF(v);
303 return NULL;
304 }
305 if (c == '\n')
306 break;
307 /* Must be because buf == end */
308 if (n > 0)
309 break;
310 used_v_size = total_v_size;
311 increment = total_v_size >> 2; /* mild exponential growth */
312 total_v_size += increment;
313 if (total_v_size > INT_MAX) {
314 PyErr_SetString(PyExc_OverflowError,
315 "line is longer than a Python string can hold");
316 Py_DECREF(v);
317 return NULL;
318 }
319 if (_PyString_Resize(&v, total_v_size) < 0)
320 return NULL;
321 buf = BUF(v) + used_v_size;
322 end = BUF(v) + total_v_size;
323 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000324
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000325 used_v_size = buf - BUF(v);
326 if (used_v_size != total_v_size)
327 _PyString_Resize(&v, used_v_size);
328 return v;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000329}
330
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000331/* This is a hacked version of Python's
332 * fileobject.c:Py_UniversalNewlineFread(). */
333size_t
334Util_UnivNewlineRead(int *bzerror, BZFILE *stream,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000335 char* buf, size_t n, BZ2FileObject *f)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000336{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000337 char *dst = buf;
338 int newlinetypes, skipnextlf;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000339
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000340 assert(buf != NULL);
341 assert(stream != NULL);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000342
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000343 if (!f->f_univ_newline)
344 return BZ2_bzRead(bzerror, stream, buf, n);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000345
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000346 newlinetypes = f->f_newlinetypes;
347 skipnextlf = f->f_skipnextlf;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000348
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000349 /* Invariant: n is the number of bytes remaining to be filled
350 * in the buffer.
351 */
352 while (n) {
353 size_t nread;
354 int shortread;
355 char *src = dst;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000356
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000357 nread = BZ2_bzRead(bzerror, stream, dst, n);
358 assert(nread <= n);
359 n -= nread; /* assuming 1 byte out for each in; will adjust */
360 shortread = n != 0; /* true iff EOF or error */
361 while (nread--) {
362 char c = *src++;
363 if (c == '\r') {
364 /* Save as LF and set flag to skip next LF. */
365 *dst++ = '\n';
366 skipnextlf = 1;
367 }
368 else if (skipnextlf && c == '\n') {
369 /* Skip LF, and remember we saw CR LF. */
370 skipnextlf = 0;
371 newlinetypes |= NEWLINE_CRLF;
372 ++n;
373 }
374 else {
375 /* Normal char to be stored in buffer. Also
376 * update the newlinetypes flag if either this
377 * is an LF or the previous char was a CR.
378 */
379 if (c == '\n')
380 newlinetypes |= NEWLINE_LF;
381 else if (skipnextlf)
382 newlinetypes |= NEWLINE_CR;
383 *dst++ = c;
384 skipnextlf = 0;
385 }
386 }
387 if (shortread) {
388 /* If this is EOF, update type flags. */
389 if (skipnextlf && *bzerror == BZ_STREAM_END)
390 newlinetypes |= NEWLINE_CR;
391 break;
392 }
393 }
394 f->f_newlinetypes = newlinetypes;
395 f->f_skipnextlf = skipnextlf;
396 return dst - buf;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000397}
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000398
399/* This is a hacked version of Python's fileobject.c:drop_readahead(). */
400static void
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000401Util_DropReadAhead(BZ2FileObject *f)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000402{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000403 if (f->f_buf != NULL) {
404 PyMem_Free(f->f_buf);
405 f->f_buf = NULL;
406 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000407}
408
409/* This is a hacked version of Python's fileobject.c:readahead(). */
410static int
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000411Util_ReadAhead(BZ2FileObject *f, int bufsize)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000412{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000413 int chunksize;
414 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000415
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000416 if (f->f_buf != NULL) {
417 if((f->f_bufend - f->f_bufptr) >= 1)
418 return 0;
419 else
420 Util_DropReadAhead(f);
421 }
422 if (f->mode == MODE_READ_EOF) {
423 f->f_bufptr = f->f_buf;
424 f->f_bufend = f->f_buf;
425 return 0;
426 }
427 if ((f->f_buf = PyMem_Malloc(bufsize)) == NULL) {
428 PyErr_NoMemory();
429 return -1;
430 }
431 Py_BEGIN_ALLOW_THREADS
432 chunksize = Util_UnivNewlineRead(&bzerror, f->fp, f->f_buf,
433 bufsize, f);
434 Py_END_ALLOW_THREADS
435 f->pos += chunksize;
436 if (bzerror == BZ_STREAM_END) {
437 f->size = f->pos;
438 f->mode = MODE_READ_EOF;
439 } else if (bzerror != BZ_OK) {
440 Util_CatchBZ2Error(bzerror);
441 Util_DropReadAhead(f);
442 return -1;
443 }
444 f->f_bufptr = f->f_buf;
445 f->f_bufend = f->f_buf + chunksize;
446 return 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000447}
448
449/* This is a hacked version of Python's
450 * fileobject.c:readahead_get_line_skip(). */
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000451static PyStringObject *
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000452Util_ReadAheadGetLineSkip(BZ2FileObject *f, int skip, int bufsize)
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000453{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000454 PyStringObject* s;
455 char *bufptr;
456 char *buf;
457 int len;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000458
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000459 if (f->f_buf == NULL)
460 if (Util_ReadAhead(f, bufsize) < 0)
461 return NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000462
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000463 len = f->f_bufend - f->f_bufptr;
464 if (len == 0)
465 return (PyStringObject *)
466 PyString_FromStringAndSize(NULL, skip);
467 bufptr = memchr(f->f_bufptr, '\n', len);
468 if (bufptr != NULL) {
469 bufptr++; /* Count the '\n' */
470 len = bufptr - f->f_bufptr;
471 s = (PyStringObject *)
472 PyString_FromStringAndSize(NULL, skip+len);
473 if (s == NULL)
474 return NULL;
475 memcpy(PyString_AS_STRING(s)+skip, f->f_bufptr, len);
476 f->f_bufptr = bufptr;
477 if (bufptr == f->f_bufend)
478 Util_DropReadAhead(f);
479 } else {
480 bufptr = f->f_bufptr;
481 buf = f->f_buf;
482 f->f_buf = NULL; /* Force new readahead buffer */
483 s = Util_ReadAheadGetLineSkip(f, skip+len,
484 bufsize + (bufsize>>2));
485 if (s == NULL) {
486 PyMem_Free(buf);
487 return NULL;
488 }
489 memcpy(PyString_AS_STRING(s)+skip, bufptr, len);
490 PyMem_Free(buf);
491 }
492 return s;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000493}
494
495/* ===================================================================== */
496/* Methods of BZ2File. */
497
498PyDoc_STRVAR(BZ2File_read__doc__,
499"read([size]) -> string\n\
500\n\
501Read at most size uncompressed bytes, returned as a string. If the size\n\
502argument is negative or omitted, read until EOF is reached.\n\
503");
504
505/* This is a hacked version of Python's fileobject.c:file_read(). */
506static PyObject *
507BZ2File_read(BZ2FileObject *self, PyObject *args)
508{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000509 long bytesrequested = -1;
510 size_t bytesread, buffersize, chunksize;
511 int bzerror;
512 PyObject *ret = NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000513
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000514 if (!PyArg_ParseTuple(args, "|l:read", &bytesrequested))
515 return NULL;
Tim Peterse3228092002-11-09 04:21:44 +0000516
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000517 ACQUIRE_LOCK(self);
518 switch (self->mode) {
519 case MODE_READ:
520 break;
521 case MODE_READ_EOF:
522 ret = PyString_FromString("");
523 goto cleanup;
524 case MODE_CLOSED:
525 PyErr_SetString(PyExc_ValueError,
526 "I/O operation on closed file");
527 goto cleanup;
528 default:
529 PyErr_SetString(PyExc_IOError,
530 "file is not ready for reading");
531 goto cleanup;
532 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000533
Antoine Pitrou39703012010-08-01 20:13:11 +0000534 /* refuse to mix with f.next() */
535 if (check_iterbuffered(self))
536 goto cleanup;
537
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000538 if (bytesrequested < 0)
539 buffersize = Util_NewBufferSize((size_t)0);
540 else
541 buffersize = bytesrequested;
542 if (buffersize > INT_MAX) {
543 PyErr_SetString(PyExc_OverflowError,
544 "requested number of bytes is "
545 "more than a Python string can hold");
546 goto cleanup;
547 }
548 ret = PyString_FromStringAndSize((char *)NULL, buffersize);
549 if (ret == NULL)
550 goto cleanup;
551 bytesread = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000552
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000553 for (;;) {
554 Py_BEGIN_ALLOW_THREADS
555 chunksize = Util_UnivNewlineRead(&bzerror, self->fp,
556 BUF(ret)+bytesread,
557 buffersize-bytesread,
558 self);
559 self->pos += chunksize;
560 Py_END_ALLOW_THREADS
561 bytesread += chunksize;
562 if (bzerror == BZ_STREAM_END) {
563 self->size = self->pos;
564 self->mode = MODE_READ_EOF;
565 break;
566 } else if (bzerror != BZ_OK) {
567 Util_CatchBZ2Error(bzerror);
568 Py_DECREF(ret);
569 ret = NULL;
570 goto cleanup;
571 }
572 if (bytesrequested < 0) {
573 buffersize = Util_NewBufferSize(buffersize);
574 if (_PyString_Resize(&ret, buffersize) < 0)
575 goto cleanup;
576 } else {
577 break;
578 }
579 }
580 if (bytesread != buffersize)
581 _PyString_Resize(&ret, bytesread);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000582
583cleanup:
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000584 RELEASE_LOCK(self);
585 return ret;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000586}
587
588PyDoc_STRVAR(BZ2File_readline__doc__,
589"readline([size]) -> string\n\
590\n\
591Return the next line from the file, as a string, retaining newline.\n\
592A non-negative size argument will limit the maximum number of bytes to\n\
593return (an incomplete line may be returned then). Return an empty\n\
594string at EOF.\n\
595");
596
597static PyObject *
598BZ2File_readline(BZ2FileObject *self, PyObject *args)
599{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000600 PyObject *ret = NULL;
601 int sizehint = -1;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000602
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000603 if (!PyArg_ParseTuple(args, "|i:readline", &sizehint))
604 return NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000605
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000606 ACQUIRE_LOCK(self);
607 switch (self->mode) {
608 case MODE_READ:
609 break;
610 case MODE_READ_EOF:
611 ret = PyString_FromString("");
612 goto cleanup;
613 case MODE_CLOSED:
614 PyErr_SetString(PyExc_ValueError,
615 "I/O operation on closed file");
616 goto cleanup;
617 default:
618 PyErr_SetString(PyExc_IOError,
619 "file is not ready for reading");
620 goto cleanup;
621 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000622
Antoine Pitrou39703012010-08-01 20:13:11 +0000623 /* refuse to mix with f.next() */
624 if (check_iterbuffered(self))
625 goto cleanup;
626
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000627 if (sizehint == 0)
628 ret = PyString_FromString("");
629 else
630 ret = Util_GetLine(self, (sizehint < 0) ? 0 : sizehint);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000631
632cleanup:
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000633 RELEASE_LOCK(self);
634 return ret;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000635}
636
637PyDoc_STRVAR(BZ2File_readlines__doc__,
638"readlines([size]) -> list\n\
639\n\
640Call readline() repeatedly and return a list of lines read.\n\
641The optional size argument, if given, is an approximate bound on the\n\
642total number of bytes in the lines returned.\n\
643");
644
645/* This is a hacked version of Python's fileobject.c:file_readlines(). */
646static PyObject *
647BZ2File_readlines(BZ2FileObject *self, PyObject *args)
648{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000649 long sizehint = 0;
650 PyObject *list = NULL;
651 PyObject *line;
652 char small_buffer[SMALLCHUNK];
653 char *buffer = small_buffer;
654 size_t buffersize = SMALLCHUNK;
655 PyObject *big_buffer = NULL;
656 size_t nfilled = 0;
657 size_t nread;
658 size_t totalread = 0;
659 char *p, *q, *end;
660 int err;
661 int shortread = 0;
662 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000663
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000664 if (!PyArg_ParseTuple(args, "|l:readlines", &sizehint))
665 return NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000666
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000667 ACQUIRE_LOCK(self);
668 switch (self->mode) {
669 case MODE_READ:
670 break;
671 case MODE_READ_EOF:
672 list = PyList_New(0);
673 goto cleanup;
674 case MODE_CLOSED:
675 PyErr_SetString(PyExc_ValueError,
676 "I/O operation on closed file");
677 goto cleanup;
678 default:
679 PyErr_SetString(PyExc_IOError,
680 "file is not ready for reading");
681 goto cleanup;
682 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000683
Antoine Pitrou39703012010-08-01 20:13:11 +0000684 /* refuse to mix with f.next() */
685 if (check_iterbuffered(self))
686 goto cleanup;
687
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000688 if ((list = PyList_New(0)) == NULL)
689 goto cleanup;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000690
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000691 for (;;) {
692 Py_BEGIN_ALLOW_THREADS
693 nread = Util_UnivNewlineRead(&bzerror, self->fp,
694 buffer+nfilled,
695 buffersize-nfilled, self);
696 self->pos += nread;
697 Py_END_ALLOW_THREADS
698 if (bzerror == BZ_STREAM_END) {
699 self->size = self->pos;
700 self->mode = MODE_READ_EOF;
701 if (nread == 0) {
702 sizehint = 0;
703 break;
704 }
705 shortread = 1;
706 } else if (bzerror != BZ_OK) {
707 Util_CatchBZ2Error(bzerror);
708 error:
709 Py_DECREF(list);
710 list = NULL;
711 goto cleanup;
712 }
713 totalread += nread;
714 p = memchr(buffer+nfilled, '\n', nread);
715 if (!shortread && p == NULL) {
716 /* Need a larger buffer to fit this line */
717 nfilled += nread;
718 buffersize *= 2;
719 if (buffersize > INT_MAX) {
720 PyErr_SetString(PyExc_OverflowError,
721 "line is longer than a Python string can hold");
722 goto error;
723 }
724 if (big_buffer == NULL) {
725 /* Create the big buffer */
726 big_buffer = PyString_FromStringAndSize(
727 NULL, buffersize);
728 if (big_buffer == NULL)
729 goto error;
730 buffer = PyString_AS_STRING(big_buffer);
731 memcpy(buffer, small_buffer, nfilled);
732 }
733 else {
734 /* Grow the big buffer */
735 _PyString_Resize(&big_buffer, buffersize);
736 buffer = PyString_AS_STRING(big_buffer);
737 }
738 continue;
739 }
740 end = buffer+nfilled+nread;
741 q = buffer;
742 while (p != NULL) {
743 /* Process complete lines */
744 p++;
745 line = PyString_FromStringAndSize(q, p-q);
746 if (line == NULL)
747 goto error;
748 err = PyList_Append(list, line);
749 Py_DECREF(line);
750 if (err != 0)
751 goto error;
752 q = p;
753 p = memchr(q, '\n', end-q);
754 }
755 /* Move the remaining incomplete line to the start */
756 nfilled = end-q;
757 memmove(buffer, q, nfilled);
758 if (sizehint > 0)
759 if (totalread >= (size_t)sizehint)
760 break;
761 if (shortread) {
762 sizehint = 0;
763 break;
764 }
765 }
766 if (nfilled != 0) {
767 /* Partial last line */
768 line = PyString_FromStringAndSize(buffer, nfilled);
769 if (line == NULL)
770 goto error;
771 if (sizehint > 0) {
772 /* Need to complete the last line */
773 PyObject *rest = Util_GetLine(self, 0);
774 if (rest == NULL) {
775 Py_DECREF(line);
776 goto error;
777 }
778 PyString_Concat(&line, rest);
779 Py_DECREF(rest);
780 if (line == NULL)
781 goto error;
782 }
783 err = PyList_Append(list, line);
784 Py_DECREF(line);
785 if (err != 0)
786 goto error;
787 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000788
789 cleanup:
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000790 RELEASE_LOCK(self);
791 if (big_buffer) {
792 Py_DECREF(big_buffer);
793 }
794 return list;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000795}
796
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +0000797PyDoc_STRVAR(BZ2File_xreadlines__doc__,
798"xreadlines() -> self\n\
799\n\
800For backward compatibility. BZ2File objects now include the performance\n\
801optimizations previously implemented in the xreadlines module.\n\
802");
803
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000804PyDoc_STRVAR(BZ2File_write__doc__,
805"write(data) -> None\n\
806\n\
807Write the 'data' string to file. Note that due to buffering, close() may\n\
808be needed before the file on disk reflects the data written.\n\
809");
810
811/* This is a hacked version of Python's fileobject.c:file_write(). */
812static PyObject *
813BZ2File_write(BZ2FileObject *self, PyObject *args)
814{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000815 PyObject *ret = NULL;
816 Py_buffer pbuf;
817 char *buf;
818 int len;
819 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000820
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000821 if (!PyArg_ParseTuple(args, "s*:write", &pbuf))
822 return NULL;
823 buf = pbuf.buf;
824 len = pbuf.len;
Tim Peterse3228092002-11-09 04:21:44 +0000825
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000826 ACQUIRE_LOCK(self);
827 switch (self->mode) {
828 case MODE_WRITE:
829 break;
Tim Peterse3228092002-11-09 04:21:44 +0000830
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000831 case MODE_CLOSED:
832 PyErr_SetString(PyExc_ValueError,
833 "I/O operation on closed file");
834 goto cleanup;
Tim Peterse3228092002-11-09 04:21:44 +0000835
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000836 default:
837 PyErr_SetString(PyExc_IOError,
838 "file is not ready for writing");
839 goto cleanup;
840 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000841
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000842 self->f_softspace = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000843
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000844 Py_BEGIN_ALLOW_THREADS
845 BZ2_bzWrite (&bzerror, self->fp, buf, len);
846 self->pos += len;
847 Py_END_ALLOW_THREADS
Tim Peterse3228092002-11-09 04:21:44 +0000848
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000849 if (bzerror != BZ_OK) {
850 Util_CatchBZ2Error(bzerror);
851 goto cleanup;
852 }
Tim Peterse3228092002-11-09 04:21:44 +0000853
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000854 Py_INCREF(Py_None);
855 ret = Py_None;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000856
857cleanup:
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000858 PyBuffer_Release(&pbuf);
859 RELEASE_LOCK(self);
860 return ret;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000861}
862
863PyDoc_STRVAR(BZ2File_writelines__doc__,
864"writelines(sequence_of_strings) -> None\n\
865\n\
866Write the sequence of strings to the file. Note that newlines are not\n\
867added. The sequence can be any iterable object producing strings. This is\n\
868equivalent to calling write() for each string.\n\
869");
870
871/* This is a hacked version of Python's fileobject.c:file_writelines(). */
872static PyObject *
873BZ2File_writelines(BZ2FileObject *self, PyObject *seq)
874{
875#define CHUNKSIZE 1000
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000876 PyObject *list = NULL;
877 PyObject *iter = NULL;
878 PyObject *ret = NULL;
879 PyObject *line;
880 int i, j, index, len, islist;
881 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000882
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000883 ACQUIRE_LOCK(self);
884 switch (self->mode) {
885 case MODE_WRITE:
886 break;
Georg Brandl3335a7a2006-08-14 21:42:55 +0000887
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000888 case MODE_CLOSED:
889 PyErr_SetString(PyExc_ValueError,
890 "I/O operation on closed file");
891 goto error;
Georg Brandl3335a7a2006-08-14 21:42:55 +0000892
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000893 default:
894 PyErr_SetString(PyExc_IOError,
895 "file is not ready for writing");
896 goto error;
897 }
Georg Brandl3335a7a2006-08-14 21:42:55 +0000898
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000899 islist = PyList_Check(seq);
900 if (!islist) {
901 iter = PyObject_GetIter(seq);
902 if (iter == NULL) {
903 PyErr_SetString(PyExc_TypeError,
904 "writelines() requires an iterable argument");
905 goto error;
906 }
907 list = PyList_New(CHUNKSIZE);
908 if (list == NULL)
909 goto error;
910 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000911
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000912 /* Strategy: slurp CHUNKSIZE lines into a private list,
913 checking that they are all strings, then write that list
914 without holding the interpreter lock, then come back for more. */
915 for (index = 0; ; index += CHUNKSIZE) {
916 if (islist) {
917 Py_XDECREF(list);
918 list = PyList_GetSlice(seq, index, index+CHUNKSIZE);
919 if (list == NULL)
920 goto error;
921 j = PyList_GET_SIZE(list);
922 }
923 else {
924 for (j = 0; j < CHUNKSIZE; j++) {
925 line = PyIter_Next(iter);
926 if (line == NULL) {
927 if (PyErr_Occurred())
928 goto error;
929 break;
930 }
931 PyList_SetItem(list, j, line);
932 }
933 }
934 if (j == 0)
935 break;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000936
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000937 /* Check that all entries are indeed strings. If not,
938 apply the same rules as for file.write() and
939 convert the rets to strings. This is slow, but
940 seems to be the only way since all conversion APIs
941 could potentially execute Python code. */
942 for (i = 0; i < j; i++) {
943 PyObject *v = PyList_GET_ITEM(list, i);
944 if (!PyString_Check(v)) {
945 const char *buffer;
946 Py_ssize_t len;
947 if (PyObject_AsCharBuffer(v, &buffer, &len)) {
948 PyErr_SetString(PyExc_TypeError,
949 "writelines() "
950 "argument must be "
951 "a sequence of "
952 "strings");
953 goto error;
954 }
955 line = PyString_FromStringAndSize(buffer,
956 len);
957 if (line == NULL)
958 goto error;
959 Py_DECREF(v);
960 PyList_SET_ITEM(list, i, line);
961 }
962 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000963
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000964 self->f_softspace = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000965
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000966 /* Since we are releasing the global lock, the
967 following code may *not* execute Python code. */
968 Py_BEGIN_ALLOW_THREADS
969 for (i = 0; i < j; i++) {
970 line = PyList_GET_ITEM(list, i);
971 len = PyString_GET_SIZE(line);
972 BZ2_bzWrite (&bzerror, self->fp,
973 PyString_AS_STRING(line), len);
974 if (bzerror != BZ_OK) {
975 Py_BLOCK_THREADS
976 Util_CatchBZ2Error(bzerror);
977 goto error;
978 }
979 }
980 Py_END_ALLOW_THREADS
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000981
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000982 if (j < CHUNKSIZE)
983 break;
984 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000985
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000986 Py_INCREF(Py_None);
987 ret = Py_None;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000988
989 error:
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000990 RELEASE_LOCK(self);
991 Py_XDECREF(list);
992 Py_XDECREF(iter);
993 return ret;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +0000994#undef CHUNKSIZE
995}
996
997PyDoc_STRVAR(BZ2File_seek__doc__,
998"seek(offset [, whence]) -> None\n\
999\n\
1000Move to new file position. Argument offset is a byte count. Optional\n\
1001argument whence defaults to 0 (offset from start of file, offset\n\
1002should be >= 0); other values are 1 (move relative to current position,\n\
1003positive or negative), and 2 (move relative to end of file, usually\n\
1004negative, although many platforms allow seeking beyond the end of a file).\n\
1005\n\
1006Note that seeking of bz2 files is emulated, and depending on the parameters\n\
1007the operation may be extremely slow.\n\
1008");
1009
1010static PyObject *
1011BZ2File_seek(BZ2FileObject *self, PyObject *args)
1012{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001013 int where = 0;
1014 PyObject *offobj;
1015 Py_off_t offset;
1016 char small_buffer[SMALLCHUNK];
1017 char *buffer = small_buffer;
1018 size_t buffersize = SMALLCHUNK;
1019 Py_off_t bytesread = 0;
1020 size_t readsize;
1021 int chunksize;
1022 int bzerror;
1023 PyObject *ret = NULL;
Tim Peterse3228092002-11-09 04:21:44 +00001024
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001025 if (!PyArg_ParseTuple(args, "O|i:seek", &offobj, &where))
1026 return NULL;
Georg Brandl33a5f2a2005-08-21 14:16:04 +00001027#if !defined(HAVE_LARGEFILE_SUPPORT)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001028 offset = PyInt_AsLong(offobj);
Georg Brandl33a5f2a2005-08-21 14:16:04 +00001029#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001030 offset = PyLong_Check(offobj) ?
1031 PyLong_AsLongLong(offobj) : PyInt_AsLong(offobj);
Georg Brandl33a5f2a2005-08-21 14:16:04 +00001032#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001033 if (PyErr_Occurred())
1034 return NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001035
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001036 ACQUIRE_LOCK(self);
1037 Util_DropReadAhead(self);
1038 switch (self->mode) {
1039 case MODE_READ:
1040 case MODE_READ_EOF:
1041 break;
Tim Peterse3228092002-11-09 04:21:44 +00001042
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001043 case MODE_CLOSED:
1044 PyErr_SetString(PyExc_ValueError,
1045 "I/O operation on closed file");
1046 goto cleanup;
Tim Peterse3228092002-11-09 04:21:44 +00001047
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001048 default:
1049 PyErr_SetString(PyExc_IOError,
1050 "seek works only while reading");
1051 goto cleanup;
1052 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001053
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001054 if (where == 2) {
1055 if (self->size == -1) {
1056 assert(self->mode != MODE_READ_EOF);
1057 for (;;) {
1058 Py_BEGIN_ALLOW_THREADS
1059 chunksize = Util_UnivNewlineRead(
1060 &bzerror, self->fp,
1061 buffer, buffersize,
1062 self);
1063 self->pos += chunksize;
1064 Py_END_ALLOW_THREADS
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001065
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001066 bytesread += chunksize;
1067 if (bzerror == BZ_STREAM_END) {
1068 break;
1069 } else if (bzerror != BZ_OK) {
1070 Util_CatchBZ2Error(bzerror);
1071 goto cleanup;
1072 }
1073 }
1074 self->mode = MODE_READ_EOF;
1075 self->size = self->pos;
1076 bytesread = 0;
1077 }
1078 offset = self->size + offset;
1079 } else if (where == 1) {
1080 offset = self->pos + offset;
1081 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001082
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001083 /* Before getting here, offset must be the absolute position the file
1084 * pointer should be set to. */
Georg Brandl47fab922006-02-18 21:57:25 +00001085
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001086 if (offset >= self->pos) {
1087 /* we can move forward */
1088 offset -= self->pos;
1089 } else {
1090 /* we cannot move back, so rewind the stream */
1091 BZ2_bzReadClose(&bzerror, self->fp);
1092 if (self->fp) {
1093 PyFile_DecUseCount((PyFileObject *)self->file);
1094 self->fp = NULL;
1095 }
1096 if (bzerror != BZ_OK) {
1097 Util_CatchBZ2Error(bzerror);
1098 goto cleanup;
1099 }
1100 ret = PyObject_CallMethod(self->file, "seek", "(i)", 0);
1101 if (!ret)
1102 goto cleanup;
1103 Py_DECREF(ret);
1104 ret = NULL;
1105 self->pos = 0;
1106 self->fp = BZ2_bzReadOpen(&bzerror, PyFile_AsFile(self->file),
1107 0, 0, NULL, 0);
1108 if (self->fp)
1109 PyFile_IncUseCount((PyFileObject *)self->file);
1110 if (bzerror != BZ_OK) {
1111 Util_CatchBZ2Error(bzerror);
1112 goto cleanup;
1113 }
1114 self->mode = MODE_READ;
1115 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001116
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001117 if (offset <= 0 || self->mode == MODE_READ_EOF)
1118 goto exit;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001119
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001120 /* Before getting here, offset must be set to the number of bytes
1121 * to walk forward. */
1122 for (;;) {
1123 if (offset-bytesread > buffersize)
1124 readsize = buffersize;
1125 else
1126 /* offset might be wider that readsize, but the result
1127 * of the subtraction is bound by buffersize (see the
1128 * condition above). buffersize is 8192. */
1129 readsize = (size_t)(offset-bytesread);
1130 Py_BEGIN_ALLOW_THREADS
1131 chunksize = Util_UnivNewlineRead(&bzerror, self->fp,
1132 buffer, readsize, self);
1133 self->pos += chunksize;
1134 Py_END_ALLOW_THREADS
1135 bytesread += chunksize;
1136 if (bzerror == BZ_STREAM_END) {
1137 self->size = self->pos;
1138 self->mode = MODE_READ_EOF;
1139 break;
1140 } else if (bzerror != BZ_OK) {
1141 Util_CatchBZ2Error(bzerror);
1142 goto cleanup;
1143 }
1144 if (bytesread == offset)
1145 break;
1146 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001147
1148exit:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001149 Py_INCREF(Py_None);
1150 ret = Py_None;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001151
1152cleanup:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001153 RELEASE_LOCK(self);
1154 return ret;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001155}
1156
1157PyDoc_STRVAR(BZ2File_tell__doc__,
1158"tell() -> int\n\
1159\n\
1160Return the current file position, an integer (may be a long integer).\n\
1161");
1162
1163static PyObject *
1164BZ2File_tell(BZ2FileObject *self, PyObject *args)
1165{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001166 PyObject *ret = NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001167
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001168 if (self->mode == MODE_CLOSED) {
1169 PyErr_SetString(PyExc_ValueError,
1170 "I/O operation on closed file");
1171 goto cleanup;
1172 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001173
Georg Brandla8bcecc2005-09-03 07:49:53 +00001174#if !defined(HAVE_LARGEFILE_SUPPORT)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001175 ret = PyInt_FromLong(self->pos);
Georg Brandla8bcecc2005-09-03 07:49:53 +00001176#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001177 ret = PyLong_FromLongLong(self->pos);
Georg Brandla8bcecc2005-09-03 07:49:53 +00001178#endif
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001179
1180cleanup:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001181 return ret;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001182}
1183
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001184PyDoc_STRVAR(BZ2File_close__doc__,
1185"close() -> None or (perhaps) an integer\n\
1186\n\
1187Close the file. Sets data attribute .closed to true. A closed file\n\
1188cannot be used for further I/O operations. close() may be called more\n\
1189than once without error.\n\
1190");
1191
1192static PyObject *
1193BZ2File_close(BZ2FileObject *self)
1194{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001195 PyObject *ret = NULL;
1196 int bzerror = BZ_OK;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001197
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001198 ACQUIRE_LOCK(self);
1199 switch (self->mode) {
1200 case MODE_READ:
1201 case MODE_READ_EOF:
1202 BZ2_bzReadClose(&bzerror, self->fp);
1203 break;
1204 case MODE_WRITE:
1205 BZ2_bzWriteClose(&bzerror, self->fp,
1206 0, NULL, NULL);
1207 break;
1208 }
Nadeem Vawda337c50b2013-12-08 15:31:50 +01001209 if (self->file) {
1210 if (self->fp)
1211 PyFile_DecUseCount((PyFileObject *)self->file);
1212 ret = PyObject_CallMethod(self->file, "close", NULL);
1213 } else {
1214 Py_INCREF(Py_None);
1215 ret = Py_None;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001216 }
Nadeem Vawda337c50b2013-12-08 15:31:50 +01001217 self->fp = NULL;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001218 self->mode = MODE_CLOSED;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001219 if (bzerror != BZ_OK) {
1220 Util_CatchBZ2Error(bzerror);
1221 Py_XDECREF(ret);
1222 ret = NULL;
1223 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001224
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001225 RELEASE_LOCK(self);
1226 return ret;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001227}
1228
Antoine Pitroub74fc2b2009-01-10 16:13:45 +00001229PyDoc_STRVAR(BZ2File_enter_doc,
1230"__enter__() -> self.");
1231
1232static PyObject *
1233BZ2File_enter(BZ2FileObject *self)
1234{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001235 if (self->mode == MODE_CLOSED) {
1236 PyErr_SetString(PyExc_ValueError,
1237 "I/O operation on closed file");
1238 return NULL;
1239 }
1240 Py_INCREF(self);
1241 return (PyObject *) self;
Antoine Pitroub74fc2b2009-01-10 16:13:45 +00001242}
1243
1244PyDoc_STRVAR(BZ2File_exit_doc,
1245"__exit__(*excinfo) -> None. Closes the file.");
1246
1247static PyObject *
1248BZ2File_exit(BZ2FileObject *self, PyObject *args)
1249{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001250 PyObject *ret = PyObject_CallMethod((PyObject *) self, "close", NULL);
1251 if (!ret)
1252 /* If error occurred, pass through */
1253 return NULL;
1254 Py_DECREF(ret);
1255 Py_RETURN_NONE;
Antoine Pitroub74fc2b2009-01-10 16:13:45 +00001256}
1257
1258
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001259static PyObject *BZ2File_getiter(BZ2FileObject *self);
1260
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001261static PyMethodDef BZ2File_methods[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001262 {"read", (PyCFunction)BZ2File_read, METH_VARARGS, BZ2File_read__doc__},
1263 {"readline", (PyCFunction)BZ2File_readline, METH_VARARGS, BZ2File_readline__doc__},
1264 {"readlines", (PyCFunction)BZ2File_readlines, METH_VARARGS, BZ2File_readlines__doc__},
1265 {"xreadlines", (PyCFunction)BZ2File_getiter, METH_VARARGS, BZ2File_xreadlines__doc__},
1266 {"write", (PyCFunction)BZ2File_write, METH_VARARGS, BZ2File_write__doc__},
1267 {"writelines", (PyCFunction)BZ2File_writelines, METH_O, BZ2File_writelines__doc__},
1268 {"seek", (PyCFunction)BZ2File_seek, METH_VARARGS, BZ2File_seek__doc__},
1269 {"tell", (PyCFunction)BZ2File_tell, METH_NOARGS, BZ2File_tell__doc__},
1270 {"close", (PyCFunction)BZ2File_close, METH_NOARGS, BZ2File_close__doc__},
1271 {"__enter__", (PyCFunction)BZ2File_enter, METH_NOARGS, BZ2File_enter_doc},
1272 {"__exit__", (PyCFunction)BZ2File_exit, METH_VARARGS, BZ2File_exit_doc},
1273 {NULL, NULL} /* sentinel */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001274};
1275
1276
1277/* ===================================================================== */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001278/* Getters and setters of BZ2File. */
1279
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001280/* This is a hacked version of Python's fileobject.c:get_newlines(). */
1281static PyObject *
1282BZ2File_get_newlines(BZ2FileObject *self, void *closure)
1283{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001284 switch (self->f_newlinetypes) {
1285 case NEWLINE_UNKNOWN:
1286 Py_INCREF(Py_None);
1287 return Py_None;
1288 case NEWLINE_CR:
1289 return PyString_FromString("\r");
1290 case NEWLINE_LF:
1291 return PyString_FromString("\n");
1292 case NEWLINE_CR|NEWLINE_LF:
1293 return Py_BuildValue("(ss)", "\r", "\n");
1294 case NEWLINE_CRLF:
1295 return PyString_FromString("\r\n");
1296 case NEWLINE_CR|NEWLINE_CRLF:
1297 return Py_BuildValue("(ss)", "\r", "\r\n");
1298 case NEWLINE_LF|NEWLINE_CRLF:
1299 return Py_BuildValue("(ss)", "\n", "\r\n");
1300 case NEWLINE_CR|NEWLINE_LF|NEWLINE_CRLF:
1301 return Py_BuildValue("(sss)", "\r", "\n", "\r\n");
1302 default:
1303 PyErr_Format(PyExc_SystemError,
1304 "Unknown newlines value 0x%x\n",
1305 self->f_newlinetypes);
1306 return NULL;
1307 }
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001308}
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001309
1310static PyObject *
1311BZ2File_get_closed(BZ2FileObject *self, void *closure)
1312{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001313 return PyInt_FromLong(self->mode == MODE_CLOSED);
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001314}
1315
1316static PyObject *
1317BZ2File_get_mode(BZ2FileObject *self, void *closure)
1318{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001319 return PyObject_GetAttrString(self->file, "mode");
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001320}
1321
1322static PyObject *
1323BZ2File_get_name(BZ2FileObject *self, void *closure)
1324{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001325 return PyObject_GetAttrString(self->file, "name");
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001326}
1327
1328static PyGetSetDef BZ2File_getset[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001329 {"closed", (getter)BZ2File_get_closed, NULL,
1330 "True if the file is closed"},
1331 {"newlines", (getter)BZ2File_get_newlines, NULL,
1332 "end-of-line convention used in this file"},
1333 {"mode", (getter)BZ2File_get_mode, NULL,
1334 "file mode ('r', 'w', or 'U')"},
1335 {"name", (getter)BZ2File_get_name, NULL,
1336 "file name"},
1337 {NULL} /* Sentinel */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001338};
1339
1340
1341/* ===================================================================== */
1342/* Members of BZ2File_Type. */
1343
1344#undef OFF
1345#define OFF(x) offsetof(BZ2FileObject, x)
1346
1347static PyMemberDef BZ2File_members[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001348 {"softspace", T_INT, OFF(f_softspace), 0,
1349 "flag indicating that a space needs to be printed; used by print"},
1350 {NULL} /* Sentinel */
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001351};
1352
1353/* ===================================================================== */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001354/* Slot definitions for BZ2File_Type. */
1355
1356static int
1357BZ2File_init(BZ2FileObject *self, PyObject *args, PyObject *kwargs)
1358{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001359 static char *kwlist[] = {"filename", "mode", "buffering",
1360 "compresslevel", 0};
1361 PyObject *name;
1362 char *mode = "r";
1363 int buffering = -1;
1364 int compresslevel = 9;
1365 int bzerror;
1366 int mode_char = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001367
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001368 self->size = -1;
Tim Peterse3228092002-11-09 04:21:44 +00001369
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001370 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|sii:BZ2File",
1371 kwlist, &name, &mode, &buffering,
1372 &compresslevel))
1373 return -1;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001374
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001375 if (compresslevel < 1 || compresslevel > 9) {
1376 PyErr_SetString(PyExc_ValueError,
1377 "compresslevel must be between 1 and 9");
1378 return -1;
1379 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001380
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001381 for (;;) {
1382 int error = 0;
1383 switch (*mode) {
1384 case 'r':
1385 case 'w':
1386 if (mode_char)
1387 error = 1;
1388 mode_char = *mode;
1389 break;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001390
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001391 case 'b':
1392 break;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001393
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001394 case 'U':
Neal Norwitz2a30cd02006-07-10 01:18:57 +00001395#ifdef __VMS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001396 self->f_univ_newline = 0;
Neal Norwitz2a30cd02006-07-10 01:18:57 +00001397#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001398 self->f_univ_newline = 1;
Neal Norwitz2a30cd02006-07-10 01:18:57 +00001399#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001400 break;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001401
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001402 default:
1403 error = 1;
1404 break;
1405 }
1406 if (error) {
1407 PyErr_Format(PyExc_ValueError,
1408 "invalid mode char %c", *mode);
1409 return -1;
1410 }
1411 mode++;
1412 if (*mode == '\0')
1413 break;
1414 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001415
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001416 if (mode_char == 0) {
1417 mode_char = 'r';
1418 }
Georg Brandl6b95f1d2005-06-03 19:47:00 +00001419
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001420 mode = (mode_char == 'r') ? "rb" : "wb";
Tim Peterse3228092002-11-09 04:21:44 +00001421
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001422 self->file = PyObject_CallFunction((PyObject*)&PyFile_Type, "(Osi)",
1423 name, mode, buffering);
1424 if (self->file == NULL)
1425 return -1;
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001426
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001427 /* From now on, we have stuff to dealloc, so jump to error label
1428 * instead of returning */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001429
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001430#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001431 self->lock = PyThread_allocate_lock();
1432 if (!self->lock) {
1433 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
1434 goto error;
1435 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001436#endif
1437
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001438 if (mode_char == 'r')
1439 self->fp = BZ2_bzReadOpen(&bzerror,
1440 PyFile_AsFile(self->file),
1441 0, 0, NULL, 0);
1442 else
1443 self->fp = BZ2_bzWriteOpen(&bzerror,
1444 PyFile_AsFile(self->file),
1445 compresslevel, 0, 0);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001446
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001447 if (bzerror != BZ_OK) {
1448 Util_CatchBZ2Error(bzerror);
1449 goto error;
1450 }
1451 PyFile_IncUseCount((PyFileObject *)self->file);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001452
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001453 self->mode = (mode_char == 'r') ? MODE_READ : MODE_WRITE;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001454
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001455 return 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001456
1457error:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001458 Py_CLEAR(self->file);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001459#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001460 if (self->lock) {
1461 PyThread_free_lock(self->lock);
1462 self->lock = NULL;
1463 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001464#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001465 return -1;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001466}
1467
1468static void
1469BZ2File_dealloc(BZ2FileObject *self)
1470{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001471 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001472#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001473 if (self->lock)
1474 PyThread_free_lock(self->lock);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001475#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001476 switch (self->mode) {
1477 case MODE_READ:
1478 case MODE_READ_EOF:
1479 BZ2_bzReadClose(&bzerror, self->fp);
1480 break;
1481 case MODE_WRITE:
1482 BZ2_bzWriteClose(&bzerror, self->fp,
1483 0, NULL, NULL);
1484 break;
1485 }
Nadeem Vawda337c50b2013-12-08 15:31:50 +01001486 if (self->fp != NULL && self->file != NULL)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001487 PyFile_DecUseCount((PyFileObject *)self->file);
Nadeem Vawda337c50b2013-12-08 15:31:50 +01001488 self->fp = NULL;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001489 Util_DropReadAhead(self);
1490 Py_XDECREF(self->file);
1491 Py_TYPE(self)->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001492}
1493
1494/* This is a hacked version of Python's fileobject.c:file_getiter(). */
1495static PyObject *
1496BZ2File_getiter(BZ2FileObject *self)
1497{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001498 if (self->mode == MODE_CLOSED) {
1499 PyErr_SetString(PyExc_ValueError,
1500 "I/O operation on closed file");
1501 return NULL;
1502 }
1503 Py_INCREF((PyObject*)self);
1504 return (PyObject *)self;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001505}
1506
1507/* This is a hacked version of Python's fileobject.c:file_iternext(). */
1508#define READAHEAD_BUFSIZE 8192
1509static PyObject *
1510BZ2File_iternext(BZ2FileObject *self)
1511{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001512 PyStringObject* ret;
1513 ACQUIRE_LOCK(self);
1514 if (self->mode == MODE_CLOSED) {
1515 RELEASE_LOCK(self);
1516 PyErr_SetString(PyExc_ValueError,
1517 "I/O operation on closed file");
1518 return NULL;
1519 }
1520 ret = Util_ReadAheadGetLineSkip(self, 0, READAHEAD_BUFSIZE);
1521 RELEASE_LOCK(self);
1522 if (ret == NULL || PyString_GET_SIZE(ret) == 0) {
1523 Py_XDECREF(ret);
1524 return NULL;
1525 }
1526 return (PyObject *)ret;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001527}
1528
1529/* ===================================================================== */
1530/* BZ2File_Type definition. */
1531
1532PyDoc_VAR(BZ2File__doc__) =
1533PyDoc_STR(
1534"BZ2File(name [, mode='r', buffering=0, compresslevel=9]) -> file object\n\
1535\n\
1536Open a bz2 file. The mode can be 'r' or 'w', for reading (default) or\n\
1537writing. When opened for writing, the file will be created if it doesn't\n\
1538exist, and truncated otherwise. If the buffering argument is given, 0 means\n\
1539unbuffered, and larger numbers specify the buffer size. If compresslevel\n\
1540is given, must be a number between 1 and 9.\n\
1541")
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001542PyDoc_STR(
1543"\n\
1544Add a 'U' to mode to open the file for input with universal newline\n\
1545support. Any line ending in the input file will be seen as a '\\n' in\n\
1546Python. Also, a file so opened gains the attribute 'newlines'; the value\n\
1547for this attribute is one of None (no newline read yet), '\\r', '\\n',\n\
1548'\\r\\n' or a tuple containing all the newline types seen. Universal\n\
1549newlines are available only when reading.\n\
1550")
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001551;
1552
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001553static PyTypeObject BZ2File_Type = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001554 PyVarObject_HEAD_INIT(NULL, 0)
1555 "bz2.BZ2File", /*tp_name*/
1556 sizeof(BZ2FileObject), /*tp_basicsize*/
1557 0, /*tp_itemsize*/
1558 (destructor)BZ2File_dealloc, /*tp_dealloc*/
1559 0, /*tp_print*/
1560 0, /*tp_getattr*/
1561 0, /*tp_setattr*/
1562 0, /*tp_compare*/
1563 0, /*tp_repr*/
1564 0, /*tp_as_number*/
1565 0, /*tp_as_sequence*/
1566 0, /*tp_as_mapping*/
1567 0, /*tp_hash*/
1568 0, /*tp_call*/
1569 0, /*tp_str*/
1570 PyObject_GenericGetAttr,/*tp_getattro*/
1571 PyObject_GenericSetAttr,/*tp_setattro*/
1572 0, /*tp_as_buffer*/
1573 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1574 BZ2File__doc__, /*tp_doc*/
1575 0, /*tp_traverse*/
1576 0, /*tp_clear*/
1577 0, /*tp_richcompare*/
1578 0, /*tp_weaklistoffset*/
1579 (getiterfunc)BZ2File_getiter, /*tp_iter*/
1580 (iternextfunc)BZ2File_iternext, /*tp_iternext*/
1581 BZ2File_methods, /*tp_methods*/
1582 BZ2File_members, /*tp_members*/
1583 BZ2File_getset, /*tp_getset*/
1584 0, /*tp_base*/
1585 0, /*tp_dict*/
1586 0, /*tp_descr_get*/
1587 0, /*tp_descr_set*/
1588 0, /*tp_dictoffset*/
1589 (initproc)BZ2File_init, /*tp_init*/
1590 PyType_GenericAlloc, /*tp_alloc*/
1591 PyType_GenericNew, /*tp_new*/
1592 _PyObject_Del, /*tp_free*/
1593 0, /*tp_is_gc*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001594};
1595
1596
1597/* ===================================================================== */
1598/* Methods of BZ2Comp. */
1599
1600PyDoc_STRVAR(BZ2Comp_compress__doc__,
1601"compress(data) -> string\n\
1602\n\
1603Provide more data to the compressor object. It will return chunks of\n\
1604compressed data whenever possible. When you've finished providing data\n\
1605to compress, call the flush() method to finish the compression process,\n\
1606and return what is left in the internal buffers.\n\
1607");
1608
1609static PyObject *
1610BZ2Comp_compress(BZ2CompObject *self, PyObject *args)
1611{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001612 Py_buffer pdata;
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001613 size_t input_left;
1614 size_t output_size = 0;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001615 PyObject *ret = NULL;
1616 bz_stream *bzs = &self->bzs;
1617 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001618
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001619 if (!PyArg_ParseTuple(args, "s*:compress", &pdata))
1620 return NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001621
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001622 if (pdata.len == 0) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001623 PyBuffer_Release(&pdata);
1624 return PyString_FromString("");
1625 }
Gustavo Niemeyera6e436e2004-02-14 00:02:45 +00001626
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001627 ACQUIRE_LOCK(self);
1628 if (!self->running) {
1629 PyErr_SetString(PyExc_ValueError,
1630 "this object was already flushed");
1631 goto error;
1632 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001633
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001634 ret = PyString_FromStringAndSize(NULL, SMALLCHUNK);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001635 if (!ret)
1636 goto error;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001637
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001638 bzs->next_in = pdata.buf;
1639 bzs->avail_in = MIN(pdata.len, UINT_MAX);
1640 input_left = pdata.len - bzs->avail_in;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001641
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001642 bzs->next_out = BUF(ret);
1643 bzs->avail_out = PyString_GET_SIZE(ret);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001644
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001645 for (;;) {
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001646 char *saved_next_out;
1647
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001648 Py_BEGIN_ALLOW_THREADS
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001649 saved_next_out = bzs->next_out;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001650 bzerror = BZ2_bzCompress(bzs, BZ_RUN);
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001651 output_size += bzs->next_out - saved_next_out;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001652 Py_END_ALLOW_THREADS
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001653
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001654 if (bzerror != BZ_RUN_OK) {
1655 Util_CatchBZ2Error(bzerror);
1656 goto error;
1657 }
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001658 if (bzs->avail_in == 0) {
1659 if (input_left == 0)
1660 break; /* no more input data */
1661 bzs->avail_in = MIN(input_left, UINT_MAX);
1662 input_left -= bzs->avail_in;
1663 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001664 if (bzs->avail_out == 0) {
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001665 size_t buffer_left = PyString_GET_SIZE(ret) - output_size;
1666 if (buffer_left == 0) {
1667 if (Util_GrowBuffer(&ret) < 0) {
1668 BZ2_bzCompressEnd(bzs);
1669 goto error;
1670 }
1671 bzs->next_out = BUF(ret) + output_size;
1672 buffer_left = PyString_GET_SIZE(ret) - output_size;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001673 }
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001674 bzs->avail_out = MIN(buffer_left, UINT_MAX);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001675 }
1676 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001677
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001678 if (_PyString_Resize(&ret, output_size) < 0)
1679 goto error;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001680
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001681 RELEASE_LOCK(self);
1682 PyBuffer_Release(&pdata);
1683 return ret;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001684
1685error:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001686 RELEASE_LOCK(self);
1687 PyBuffer_Release(&pdata);
1688 Py_XDECREF(ret);
1689 return NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001690}
1691
1692PyDoc_STRVAR(BZ2Comp_flush__doc__,
1693"flush() -> string\n\
1694\n\
1695Finish the compression process and return what is left in internal buffers.\n\
1696You must not use the compressor object after calling this method.\n\
1697");
1698
1699static PyObject *
1700BZ2Comp_flush(BZ2CompObject *self)
1701{
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001702 size_t output_size = 0;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001703 PyObject *ret = NULL;
1704 bz_stream *bzs = &self->bzs;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001705 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001706
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001707 ACQUIRE_LOCK(self);
1708 if (!self->running) {
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001709 PyErr_SetString(PyExc_ValueError, "object was already flushed");
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001710 goto error;
1711 }
1712 self->running = 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001713
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001714 ret = PyString_FromStringAndSize(NULL, SMALLCHUNK);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001715 if (!ret)
1716 goto error;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001717
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001718 bzs->next_out = BUF(ret);
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001719 bzs->avail_out = PyString_GET_SIZE(ret);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001720
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001721 for (;;) {
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001722 char *saved_next_out;
1723
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001724 Py_BEGIN_ALLOW_THREADS
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001725 saved_next_out = bzs->next_out;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001726 bzerror = BZ2_bzCompress(bzs, BZ_FINISH);
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001727 output_size += bzs->next_out - saved_next_out;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001728 Py_END_ALLOW_THREADS
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001729
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001730 if (bzerror == BZ_STREAM_END) {
1731 break;
1732 } else if (bzerror != BZ_FINISH_OK) {
1733 Util_CatchBZ2Error(bzerror);
1734 goto error;
1735 }
1736 if (bzs->avail_out == 0) {
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001737 size_t buffer_left = PyString_GET_SIZE(ret) - output_size;
1738 if (buffer_left == 0) {
1739 if (Util_GrowBuffer(&ret) < 0)
1740 goto error;
1741 bzs->next_out = BUF(ret) + output_size;
1742 buffer_left = PyString_GET_SIZE(ret) - output_size;
1743 }
1744 bzs->avail_out = MIN(buffer_left, UINT_MAX);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001745 }
1746 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001747
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001748 if (output_size != PyString_GET_SIZE(ret))
1749 if (_PyString_Resize(&ret, output_size) < 0)
1750 goto error;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001751
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001752 RELEASE_LOCK(self);
1753 return ret;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001754
1755error:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001756 RELEASE_LOCK(self);
1757 Py_XDECREF(ret);
1758 return NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001759}
1760
1761static PyMethodDef BZ2Comp_methods[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001762 {"compress", (PyCFunction)BZ2Comp_compress, METH_VARARGS,
1763 BZ2Comp_compress__doc__},
1764 {"flush", (PyCFunction)BZ2Comp_flush, METH_NOARGS,
1765 BZ2Comp_flush__doc__},
1766 {NULL, NULL} /* sentinel */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001767};
1768
1769
1770/* ===================================================================== */
1771/* Slot definitions for BZ2Comp_Type. */
1772
1773static int
1774BZ2Comp_init(BZ2CompObject *self, PyObject *args, PyObject *kwargs)
1775{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001776 int compresslevel = 9;
1777 int bzerror;
1778 static char *kwlist[] = {"compresslevel", 0};
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001779
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001780 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:BZ2Compressor",
1781 kwlist, &compresslevel))
1782 return -1;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001783
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001784 if (compresslevel < 1 || compresslevel > 9) {
1785 PyErr_SetString(PyExc_ValueError,
1786 "compresslevel must be between 1 and 9");
1787 goto error;
1788 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001789
1790#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001791 self->lock = PyThread_allocate_lock();
1792 if (!self->lock) {
1793 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
1794 goto error;
1795 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001796#endif
1797
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001798 memset(&self->bzs, 0, sizeof(bz_stream));
1799 bzerror = BZ2_bzCompressInit(&self->bzs, compresslevel, 0, 0);
1800 if (bzerror != BZ_OK) {
1801 Util_CatchBZ2Error(bzerror);
1802 goto error;
1803 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001804
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001805 self->running = 1;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001806
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001807 return 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001808error:
1809#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001810 if (self->lock) {
1811 PyThread_free_lock(self->lock);
1812 self->lock = NULL;
1813 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001814#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001815 return -1;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001816}
1817
1818static void
1819BZ2Comp_dealloc(BZ2CompObject *self)
1820{
1821#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001822 if (self->lock)
1823 PyThread_free_lock(self->lock);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001824#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001825 BZ2_bzCompressEnd(&self->bzs);
1826 Py_TYPE(self)->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001827}
1828
1829
1830/* ===================================================================== */
1831/* BZ2Comp_Type definition. */
1832
1833PyDoc_STRVAR(BZ2Comp__doc__,
1834"BZ2Compressor([compresslevel=9]) -> compressor object\n\
1835\n\
1836Create a new compressor object. This object may be used to compress\n\
1837data sequentially. If you want to compress data in one shot, use the\n\
1838compress() function instead. The compresslevel parameter, if given,\n\
1839must be a number between 1 and 9.\n\
1840");
1841
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00001842static PyTypeObject BZ2Comp_Type = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001843 PyVarObject_HEAD_INIT(NULL, 0)
1844 "bz2.BZ2Compressor", /*tp_name*/
1845 sizeof(BZ2CompObject), /*tp_basicsize*/
1846 0, /*tp_itemsize*/
1847 (destructor)BZ2Comp_dealloc, /*tp_dealloc*/
1848 0, /*tp_print*/
1849 0, /*tp_getattr*/
1850 0, /*tp_setattr*/
1851 0, /*tp_compare*/
1852 0, /*tp_repr*/
1853 0, /*tp_as_number*/
1854 0, /*tp_as_sequence*/
1855 0, /*tp_as_mapping*/
1856 0, /*tp_hash*/
1857 0, /*tp_call*/
1858 0, /*tp_str*/
1859 PyObject_GenericGetAttr,/*tp_getattro*/
1860 PyObject_GenericSetAttr,/*tp_setattro*/
1861 0, /*tp_as_buffer*/
1862 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
1863 BZ2Comp__doc__, /*tp_doc*/
1864 0, /*tp_traverse*/
1865 0, /*tp_clear*/
1866 0, /*tp_richcompare*/
1867 0, /*tp_weaklistoffset*/
1868 0, /*tp_iter*/
1869 0, /*tp_iternext*/
1870 BZ2Comp_methods, /*tp_methods*/
1871 0, /*tp_members*/
1872 0, /*tp_getset*/
1873 0, /*tp_base*/
1874 0, /*tp_dict*/
1875 0, /*tp_descr_get*/
1876 0, /*tp_descr_set*/
1877 0, /*tp_dictoffset*/
1878 (initproc)BZ2Comp_init, /*tp_init*/
1879 PyType_GenericAlloc, /*tp_alloc*/
1880 PyType_GenericNew, /*tp_new*/
1881 _PyObject_Del, /*tp_free*/
1882 0, /*tp_is_gc*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001883};
1884
1885
1886/* ===================================================================== */
1887/* Members of BZ2Decomp. */
1888
Gustavo Niemeyera33d0aa2003-02-11 18:46:20 +00001889#undef OFF
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001890#define OFF(x) offsetof(BZ2DecompObject, x)
1891
1892static PyMemberDef BZ2Decomp_members[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001893 {"unused_data", T_OBJECT, OFF(unused_data), RO},
1894 {NULL} /* Sentinel */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001895};
1896
1897
1898/* ===================================================================== */
1899/* Methods of BZ2Decomp. */
1900
1901PyDoc_STRVAR(BZ2Decomp_decompress__doc__,
1902"decompress(data) -> string\n\
1903\n\
1904Provide more data to the decompressor object. It will return chunks\n\
1905of decompressed data whenever possible. If you try to decompress data\n\
1906after the end of stream is found, EOFError will be raised. If any data\n\
1907was found after the end of stream, it'll be ignored and saved in\n\
1908unused_data attribute.\n\
1909");
1910
1911static PyObject *
1912BZ2Decomp_decompress(BZ2DecompObject *self, PyObject *args)
1913{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001914 Py_buffer pdata;
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001915 size_t input_left;
1916 size_t output_size = 0;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001917 PyObject *ret = NULL;
1918 bz_stream *bzs = &self->bzs;
1919 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001920
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001921 if (!PyArg_ParseTuple(args, "s*:decompress", &pdata))
1922 return NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001923
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001924 ACQUIRE_LOCK(self);
1925 if (!self->running) {
1926 PyErr_SetString(PyExc_EOFError, "end of stream was "
1927 "already found");
1928 goto error;
1929 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001930
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001931 ret = PyString_FromStringAndSize(NULL, SMALLCHUNK);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001932 if (!ret)
1933 goto error;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001934
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001935 bzs->next_in = pdata.buf;
1936 bzs->avail_in = MIN(pdata.len, UINT_MAX);
1937 input_left = pdata.len - bzs->avail_in;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001938
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001939 bzs->next_out = BUF(ret);
1940 bzs->avail_out = PyString_GET_SIZE(ret);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001941
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001942 for (;;) {
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001943 char *saved_next_out;
1944
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001945 Py_BEGIN_ALLOW_THREADS
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001946 saved_next_out = bzs->next_out;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001947 bzerror = BZ2_bzDecompress(bzs);
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001948 output_size += bzs->next_out - saved_next_out;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001949 Py_END_ALLOW_THREADS
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001950
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001951 if (bzerror == BZ_STREAM_END) {
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001952 self->running = 0;
1953 input_left += bzs->avail_in;
1954 if (input_left != 0) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001955 Py_DECREF(self->unused_data);
1956 self->unused_data =
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001957 PyString_FromStringAndSize(bzs->next_in, input_left);
1958 if (self->unused_data == NULL)
1959 goto error;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001960 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001961 break;
1962 }
1963 if (bzerror != BZ_OK) {
1964 Util_CatchBZ2Error(bzerror);
1965 goto error;
1966 }
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001967 if (bzs->avail_in == 0) {
1968 if (input_left == 0)
1969 break; /* no more input data */
1970 bzs->avail_in = MIN(input_left, UINT_MAX);
1971 input_left -= bzs->avail_in;
1972 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001973 if (bzs->avail_out == 0) {
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001974 size_t buffer_left = PyString_GET_SIZE(ret) - output_size;
1975 if (buffer_left == 0) {
1976 if (Util_GrowBuffer(&ret) < 0) {
1977 BZ2_bzDecompressEnd(bzs);
1978 goto error;
1979 }
1980 bzs->next_out = BUF(ret) + output_size;
1981 buffer_left = PyString_GET_SIZE(ret) - output_size;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001982 }
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001983 bzs->avail_out = MIN(buffer_left, UINT_MAX);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001984 }
1985 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001986
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02001987 if (output_size != PyString_GET_SIZE(ret))
1988 if (_PyString_Resize(&ret, output_size) < 0)
1989 goto error;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001990
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001991 RELEASE_LOCK(self);
1992 PyBuffer_Release(&pdata);
1993 return ret;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00001994
1995error:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001996 RELEASE_LOCK(self);
1997 PyBuffer_Release(&pdata);
1998 Py_XDECREF(ret);
1999 return NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002000}
2001
2002static PyMethodDef BZ2Decomp_methods[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002003 {"decompress", (PyCFunction)BZ2Decomp_decompress, METH_VARARGS, BZ2Decomp_decompress__doc__},
2004 {NULL, NULL} /* sentinel */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002005};
2006
2007
2008/* ===================================================================== */
2009/* Slot definitions for BZ2Decomp_Type. */
2010
2011static int
2012BZ2Decomp_init(BZ2DecompObject *self, PyObject *args, PyObject *kwargs)
2013{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002014 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002015
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002016 if (!PyArg_ParseTuple(args, ":BZ2Decompressor"))
2017 return -1;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002018
2019#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002020 self->lock = PyThread_allocate_lock();
2021 if (!self->lock) {
2022 PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
2023 goto error;
2024 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002025#endif
2026
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002027 self->unused_data = PyString_FromString("");
2028 if (!self->unused_data)
2029 goto error;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002030
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002031 memset(&self->bzs, 0, sizeof(bz_stream));
2032 bzerror = BZ2_bzDecompressInit(&self->bzs, 0, 0);
2033 if (bzerror != BZ_OK) {
2034 Util_CatchBZ2Error(bzerror);
2035 goto error;
2036 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002037
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002038 self->running = 1;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002039
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002040 return 0;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002041
2042error:
2043#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002044 if (self->lock) {
2045 PyThread_free_lock(self->lock);
2046 self->lock = NULL;
2047 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002048#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002049 Py_CLEAR(self->unused_data);
2050 return -1;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002051}
2052
2053static void
2054BZ2Decomp_dealloc(BZ2DecompObject *self)
2055{
2056#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002057 if (self->lock)
2058 PyThread_free_lock(self->lock);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002059#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002060 Py_XDECREF(self->unused_data);
2061 BZ2_bzDecompressEnd(&self->bzs);
2062 Py_TYPE(self)->tp_free((PyObject *)self);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002063}
2064
2065
2066/* ===================================================================== */
2067/* BZ2Decomp_Type definition. */
2068
2069PyDoc_STRVAR(BZ2Decomp__doc__,
2070"BZ2Decompressor() -> decompressor object\n\
2071\n\
2072Create a new decompressor object. This object may be used to decompress\n\
2073data sequentially. If you want to decompress data in one shot, use the\n\
2074decompress() function instead.\n\
2075");
2076
Gustavo Niemeyer49ea7be2002-11-08 14:31:49 +00002077static PyTypeObject BZ2Decomp_Type = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002078 PyVarObject_HEAD_INIT(NULL, 0)
2079 "bz2.BZ2Decompressor", /*tp_name*/
2080 sizeof(BZ2DecompObject), /*tp_basicsize*/
2081 0, /*tp_itemsize*/
2082 (destructor)BZ2Decomp_dealloc, /*tp_dealloc*/
2083 0, /*tp_print*/
2084 0, /*tp_getattr*/
2085 0, /*tp_setattr*/
2086 0, /*tp_compare*/
2087 0, /*tp_repr*/
2088 0, /*tp_as_number*/
2089 0, /*tp_as_sequence*/
2090 0, /*tp_as_mapping*/
2091 0, /*tp_hash*/
2092 0, /*tp_call*/
2093 0, /*tp_str*/
2094 PyObject_GenericGetAttr,/*tp_getattro*/
2095 PyObject_GenericSetAttr,/*tp_setattro*/
2096 0, /*tp_as_buffer*/
2097 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
2098 BZ2Decomp__doc__, /*tp_doc*/
2099 0, /*tp_traverse*/
2100 0, /*tp_clear*/
2101 0, /*tp_richcompare*/
2102 0, /*tp_weaklistoffset*/
2103 0, /*tp_iter*/
2104 0, /*tp_iternext*/
2105 BZ2Decomp_methods, /*tp_methods*/
2106 BZ2Decomp_members, /*tp_members*/
2107 0, /*tp_getset*/
2108 0, /*tp_base*/
2109 0, /*tp_dict*/
2110 0, /*tp_descr_get*/
2111 0, /*tp_descr_set*/
2112 0, /*tp_dictoffset*/
2113 (initproc)BZ2Decomp_init, /*tp_init*/
2114 PyType_GenericAlloc, /*tp_alloc*/
2115 PyType_GenericNew, /*tp_new*/
2116 _PyObject_Del, /*tp_free*/
2117 0, /*tp_is_gc*/
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002118};
2119
2120
2121/* ===================================================================== */
2122/* Module functions. */
2123
2124PyDoc_STRVAR(bz2_compress__doc__,
2125"compress(data [, compresslevel=9]) -> string\n\
2126\n\
2127Compress data in one shot. If you want to compress data sequentially,\n\
2128use an instance of BZ2Compressor instead. The compresslevel parameter, if\n\
2129given, must be a number between 1 and 9.\n\
2130");
2131
2132static PyObject *
2133bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs)
2134{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002135 int compresslevel=9;
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002136 int action;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002137 Py_buffer pdata;
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002138 size_t input_left;
2139 size_t output_size = 0;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002140 PyObject *ret = NULL;
2141 bz_stream _bzs;
2142 bz_stream *bzs = &_bzs;
2143 int bzerror;
2144 static char *kwlist[] = {"data", "compresslevel", 0};
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002145
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002146 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|i",
2147 kwlist, &pdata,
2148 &compresslevel))
2149 return NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002150
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002151 if (compresslevel < 1 || compresslevel > 9) {
2152 PyErr_SetString(PyExc_ValueError,
2153 "compresslevel must be between 1 and 9");
2154 PyBuffer_Release(&pdata);
2155 return NULL;
2156 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002157
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002158 ret = PyString_FromStringAndSize(NULL, SMALLCHUNK);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002159 if (!ret) {
2160 PyBuffer_Release(&pdata);
2161 return NULL;
2162 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002163
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002164 memset(bzs, 0, sizeof(bz_stream));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002165
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002166 bzs->next_in = pdata.buf;
2167 bzs->avail_in = MIN(pdata.len, UINT_MAX);
2168 input_left = pdata.len - bzs->avail_in;
2169
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002170 bzs->next_out = BUF(ret);
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002171 bzs->avail_out = PyString_GET_SIZE(ret);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002172
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002173 bzerror = BZ2_bzCompressInit(bzs, compresslevel, 0, 0);
2174 if (bzerror != BZ_OK) {
2175 Util_CatchBZ2Error(bzerror);
2176 PyBuffer_Release(&pdata);
2177 Py_DECREF(ret);
2178 return NULL;
2179 }
Tim Peterse3228092002-11-09 04:21:44 +00002180
Nadeem Vawda895cc222013-01-02 22:59:51 +01002181 action = input_left > 0 ? BZ_RUN : BZ_FINISH;
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002182
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002183 for (;;) {
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002184 char *saved_next_out;
2185
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002186 Py_BEGIN_ALLOW_THREADS
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002187 saved_next_out = bzs->next_out;
2188 bzerror = BZ2_bzCompress(bzs, action);
2189 output_size += bzs->next_out - saved_next_out;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002190 Py_END_ALLOW_THREADS
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002191
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002192 if (bzerror == BZ_STREAM_END) {
2193 break;
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002194 } else if (bzerror != BZ_RUN_OK && bzerror != BZ_FINISH_OK) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002195 BZ2_bzCompressEnd(bzs);
2196 Util_CatchBZ2Error(bzerror);
2197 PyBuffer_Release(&pdata);
2198 Py_DECREF(ret);
2199 return NULL;
2200 }
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002201 if (action == BZ_RUN && bzs->avail_in == 0) {
2202 if (input_left == 0) {
2203 action = BZ_FINISH;
2204 } else {
2205 bzs->avail_in = MIN(input_left, UINT_MAX);
2206 input_left -= bzs->avail_in;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002207 }
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002208 }
2209 if (bzs->avail_out == 0) {
2210 size_t buffer_left = PyString_GET_SIZE(ret) - output_size;
2211 if (buffer_left == 0) {
2212 if (Util_GrowBuffer(&ret) < 0) {
2213 BZ2_bzCompressEnd(bzs);
2214 PyBuffer_Release(&pdata);
2215 return NULL;
2216 }
2217 bzs->next_out = BUF(ret) + output_size;
2218 buffer_left = PyString_GET_SIZE(ret) - output_size;
2219 }
2220 bzs->avail_out = MIN(buffer_left, UINT_MAX);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002221 }
2222 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002223
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002224 if (output_size != PyString_GET_SIZE(ret))
2225 _PyString_Resize(&ret, output_size); /* Sets ret to NULL on failure. */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002226
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002227 BZ2_bzCompressEnd(bzs);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002228 PyBuffer_Release(&pdata);
2229 return ret;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002230}
2231
2232PyDoc_STRVAR(bz2_decompress__doc__,
2233"decompress(data) -> decompressed data\n\
2234\n\
2235Decompress data in one shot. If you want to decompress data sequentially,\n\
2236use an instance of BZ2Decompressor instead.\n\
2237");
2238
2239static PyObject *
2240bz2_decompress(PyObject *self, PyObject *args)
2241{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002242 Py_buffer pdata;
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002243 size_t input_left;
2244 size_t output_size = 0;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002245 PyObject *ret;
2246 bz_stream _bzs;
2247 bz_stream *bzs = &_bzs;
2248 int bzerror;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002249
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002250 if (!PyArg_ParseTuple(args, "s*:decompress", &pdata))
2251 return NULL;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002252
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002253 if (pdata.len == 0) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002254 PyBuffer_Release(&pdata);
2255 return PyString_FromString("");
2256 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002257
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002258 ret = PyString_FromStringAndSize(NULL, SMALLCHUNK);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002259 if (!ret) {
2260 PyBuffer_Release(&pdata);
2261 return NULL;
2262 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002263
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002264 memset(bzs, 0, sizeof(bz_stream));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002265
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002266 bzs->next_in = pdata.buf;
2267 bzs->avail_in = MIN(pdata.len, UINT_MAX);
2268 input_left = pdata.len - bzs->avail_in;
2269
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002270 bzs->next_out = BUF(ret);
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002271 bzs->avail_out = PyString_GET_SIZE(ret);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002272
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002273 bzerror = BZ2_bzDecompressInit(bzs, 0, 0);
2274 if (bzerror != BZ_OK) {
2275 Util_CatchBZ2Error(bzerror);
2276 Py_DECREF(ret);
2277 PyBuffer_Release(&pdata);
2278 return NULL;
2279 }
Tim Peterse3228092002-11-09 04:21:44 +00002280
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002281 for (;;) {
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002282 char *saved_next_out;
2283
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002284 Py_BEGIN_ALLOW_THREADS
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002285 saved_next_out = bzs->next_out;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002286 bzerror = BZ2_bzDecompress(bzs);
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002287 output_size += bzs->next_out - saved_next_out;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002288 Py_END_ALLOW_THREADS
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002289
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002290 if (bzerror == BZ_STREAM_END) {
2291 break;
2292 } else if (bzerror != BZ_OK) {
2293 BZ2_bzDecompressEnd(bzs);
2294 Util_CatchBZ2Error(bzerror);
2295 PyBuffer_Release(&pdata);
2296 Py_DECREF(ret);
2297 return NULL;
2298 }
2299 if (bzs->avail_in == 0) {
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002300 if (input_left == 0) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002301 BZ2_bzDecompressEnd(bzs);
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002302 PyErr_SetString(PyExc_ValueError,
2303 "couldn't find end of stream");
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002304 PyBuffer_Release(&pdata);
2305 Py_DECREF(ret);
2306 return NULL;
2307 }
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002308 bzs->avail_in = MIN(input_left, UINT_MAX);
2309 input_left -= bzs->avail_in;
2310 }
2311 if (bzs->avail_out == 0) {
2312 size_t buffer_left = PyString_GET_SIZE(ret) - output_size;
2313 if (buffer_left == 0) {
2314 if (Util_GrowBuffer(&ret) < 0) {
2315 BZ2_bzDecompressEnd(bzs);
2316 PyBuffer_Release(&pdata);
2317 return NULL;
2318 }
2319 bzs->next_out = BUF(ret) + output_size;
2320 buffer_left = PyString_GET_SIZE(ret) - output_size;
2321 }
2322 bzs->avail_out = MIN(buffer_left, UINT_MAX);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002323 }
2324 }
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002325
Nadeem Vawda45dba1d2012-10-21 23:09:08 +02002326 if (output_size != PyString_GET_SIZE(ret))
2327 _PyString_Resize(&ret, output_size); /* Sets ret to NULL on failure. */
2328
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002329 BZ2_bzDecompressEnd(bzs);
2330 PyBuffer_Release(&pdata);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002331 return ret;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002332}
2333
2334static PyMethodDef bz2_methods[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002335 {"compress", (PyCFunction) bz2_compress, METH_VARARGS|METH_KEYWORDS,
2336 bz2_compress__doc__},
2337 {"decompress", (PyCFunction) bz2_decompress, METH_VARARGS,
2338 bz2_decompress__doc__},
2339 {NULL, NULL} /* sentinel */
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002340};
2341
2342/* ===================================================================== */
2343/* Initialization function. */
2344
2345PyDoc_STRVAR(bz2__doc__,
2346"The python bz2 module provides a comprehensive interface for\n\
2347the bz2 compression library. It implements a complete file\n\
2348interface, one shot (de)compression functions, and types for\n\
2349sequential (de)compression.\n\
2350");
2351
Neal Norwitz21d896c2003-07-01 20:15:21 +00002352PyMODINIT_FUNC
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002353initbz2(void)
2354{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002355 PyObject *m;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002356
Antoine Pitrou2c7d6852010-09-23 19:55:24 +00002357 if (PyType_Ready(&BZ2File_Type) < 0)
2358 return;
2359 if (PyType_Ready(&BZ2Comp_Type) < 0)
2360 return;
2361 if (PyType_Ready(&BZ2Decomp_Type) < 0)
2362 return;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002363
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002364 m = Py_InitModule3("bz2", bz2_methods, bz2__doc__);
2365 if (m == NULL)
2366 return;
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002367
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002368 PyModule_AddObject(m, "__author__", PyString_FromString(__author__));
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002369
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002370 Py_INCREF(&BZ2File_Type);
2371 PyModule_AddObject(m, "BZ2File", (PyObject *)&BZ2File_Type);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002372
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002373 Py_INCREF(&BZ2Comp_Type);
2374 PyModule_AddObject(m, "BZ2Compressor", (PyObject *)&BZ2Comp_Type);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002375
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002376 Py_INCREF(&BZ2Decomp_Type);
2377 PyModule_AddObject(m, "BZ2Decompressor", (PyObject *)&BZ2Decomp_Type);
Gustavo Niemeyerf8ca8362002-11-05 16:50:05 +00002378}