blob: 48fe50a09411ca5ec7205177e1a53a9a1ec1f506 [file] [log] [blame]
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00001#include "Python.h"
2
3typedef struct {
4 PyObject_HEAD
5 char *buf;
6 Py_ssize_t pos;
7 Py_ssize_t string_size;
8 size_t buf_size;
9} BytesIOObject;
10
11#define CHECK_CLOSED(self) \
12 if ((self)->buf == NULL) { \
13 PyErr_SetString(PyExc_ValueError, \
14 "I/O operation on closed file."); \
15 return NULL; \
16 }
17
18/* Internal routine to get a line from the buffer of a BytesIO
19 object. Returns the length between the current position to the
20 next newline character. */
21static Py_ssize_t
22get_line(BytesIOObject *self, char **output)
23{
24 char *n;
25 const char *str_end;
26 Py_ssize_t len;
27
28 assert(self->buf != NULL);
29
30 /* Move to the end of the line, up to the end of the string, s. */
31 str_end = self->buf + self->string_size;
32 for (n = self->buf + self->pos;
33 n < str_end && *n != '\n';
34 n++);
35
36 /* Skip the newline character */
37 if (n < str_end)
38 n++;
39
40 /* Get the length from the current position to the end of the line. */
41 len = n - (self->buf + self->pos);
42 *output = self->buf + self->pos;
43
44 assert(len >= 0);
45 assert(self->pos < PY_SSIZE_T_MAX - len);
46 self->pos += len;
47
48 return len;
49}
50
51/* Internal routine for changing the size of the buffer of BytesIO objects.
52 The caller should ensure that the 'size' argument is non-negative. Returns
53 0 on success, -1 otherwise. */
54static int
55resize_buffer(BytesIOObject *self, size_t size)
56{
57 /* Here, unsigned types are used to avoid dealing with signed integer
58 overflow, which is undefined in C. */
59 size_t alloc = self->buf_size;
60 char *new_buf = NULL;
61
62 assert(self->buf != NULL);
63
64 /* For simplicity, stay in the range of the signed type. Anyway, Python
65 doesn't allow strings to be longer than this. */
66 if (size > PY_SSIZE_T_MAX)
67 goto overflow;
68
69 if (size < alloc / 2) {
70 /* Major downsize; resize down to exact size. */
71 alloc = size + 1;
72 }
73 else if (size < alloc) {
74 /* Within allocated size; quick exit */
75 return 0;
76 }
77 else if (size <= alloc * 1.125) {
78 /* Moderate upsize; overallocate similar to list_resize() */
79 alloc = size + (size >> 3) + (size < 9 ? 3 : 6);
80 }
81 else {
82 /* Major upsize; resize up to exact size */
83 alloc = size + 1;
84 }
85
86 if (alloc > ((size_t)-1) / sizeof(char))
87 goto overflow;
88 new_buf = (char *)PyMem_Realloc(self->buf, alloc * sizeof(char));
89 if (new_buf == NULL) {
90 PyErr_NoMemory();
91 return -1;
92 }
93 self->buf_size = alloc;
94 self->buf = new_buf;
95
96 return 0;
97
98 overflow:
99 PyErr_SetString(PyExc_OverflowError,
100 "new buffer size too large");
101 return -1;
102}
103
104/* Internal routine for writing a string of bytes to the buffer of a BytesIO
105 object. Returns the number of bytes wrote, or -1 on error. */
106static Py_ssize_t
107write_bytes(BytesIOObject *self, const char *bytes, Py_ssize_t len)
108{
109 assert(self->buf != NULL);
110 assert(self->pos >= 0);
111 assert(len >= 0);
112
Alexandre Vassalotti1bfe9dc82008-05-07 01:44:31 +0000113 if ((size_t)self->pos + len > self->buf_size) {
114 if (resize_buffer(self, (size_t)self->pos + len) < 0)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000115 return -1;
116 }
117
118 if (self->pos > self->string_size) {
119 /* In case of overseek, pad with null bytes the buffer region between
120 the end of stream and the current position.
121
122 0 lo string_size hi
123 | |<---used--->|<----------available----------->|
124 | | <--to pad-->|<---to write---> |
125 0 buf position
126 */
127 memset(self->buf + self->string_size, '\0',
128 (self->pos - self->string_size) * sizeof(char));
129 }
130
131 /* Copy the data to the internal buffer, overwriting some of the existing
132 data if self->pos < self->string_size. */
133 memcpy(self->buf + self->pos, bytes, len);
134 self->pos += len;
135
136 /* Set the new length of the internal string if it has changed. */
137 if (self->string_size < self->pos) {
138 self->string_size = self->pos;
139 }
140
141 return len;
142}
143
144static PyObject *
145bytesio_get_closed(BytesIOObject *self)
146{
147 if (self->buf == NULL)
148 Py_RETURN_TRUE;
149 else
150 Py_RETURN_FALSE;
151}
152
153/* Generic getter for the writable, readable and seekable properties */
154static PyObject *
155return_true(BytesIOObject *self)
156{
157 Py_RETURN_TRUE;
158}
159
160PyDoc_STRVAR(flush_doc,
161"flush() -> None. Does nothing.");
162
163static PyObject *
164bytesio_flush(BytesIOObject *self)
165{
166 Py_RETURN_NONE;
167}
168
169PyDoc_STRVAR(getval_doc,
Alexandre Vassalotti10dfc1e2008-05-08 01:34:41 +0000170"getvalue() -> bytes.\n"
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000171"\n"
172"Retrieve the entire contents of the BytesIO object.");
173
174static PyObject *
175bytesio_getvalue(BytesIOObject *self)
176{
177 CHECK_CLOSED(self);
Christian Heimes72b710a2008-05-26 13:28:38 +0000178 return PyBytes_FromStringAndSize(self->buf, self->string_size);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000179}
180
181PyDoc_STRVAR(isatty_doc,
182"isatty() -> False.\n"
183"\n"
184"Always returns False since BytesIO objects are not connected\n"
185"to a tty-like device.");
186
187static PyObject *
188bytesio_isatty(BytesIOObject *self)
189{
190 CHECK_CLOSED(self);
191 Py_RETURN_FALSE;
192}
193
194PyDoc_STRVAR(tell_doc,
195"tell() -> current file position, an integer\n");
196
197static PyObject *
198bytesio_tell(BytesIOObject *self)
199{
200 CHECK_CLOSED(self);
201 return PyLong_FromSsize_t(self->pos);
202}
203
204PyDoc_STRVAR(read_doc,
205"read([size]) -> read at most size bytes, returned as a string.\n"
206"\n"
207"If the size argument is negative, read until EOF is reached.\n"
208"Return an empty string at EOF.");
209
210static PyObject *
211bytesio_read(BytesIOObject *self, PyObject *args)
212{
213 Py_ssize_t size, n;
214 char *output;
215 PyObject *arg = Py_None;
216
217 CHECK_CLOSED(self);
218
219 if (!PyArg_ParseTuple(args, "|O:read", &arg))
220 return NULL;
221
222 if (PyLong_Check(arg)) {
223 size = PyLong_AsSsize_t(arg);
Benjamin Petersona8a93042008-09-30 02:18:09 +0000224 if (size == -1 && PyErr_Occurred())
225 return NULL;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000226 }
227 else if (arg == Py_None) {
228 /* Read until EOF is reached, by default. */
229 size = -1;
230 }
231 else {
232 PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
233 Py_TYPE(arg)->tp_name);
234 return NULL;
235 }
236
237 /* adjust invalid sizes */
238 n = self->string_size - self->pos;
239 if (size < 0 || size > n) {
240 size = n;
241 if (size < 0)
242 size = 0;
243 }
244
245 assert(self->buf != NULL);
246 output = self->buf + self->pos;
247 self->pos += size;
248
Christian Heimes72b710a2008-05-26 13:28:38 +0000249 return PyBytes_FromStringAndSize(output, size);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000250}
251
252
253PyDoc_STRVAR(read1_doc,
254"read1(size) -> read at most size bytes, returned as a string.\n"
255"\n"
256"If the size argument is negative or omitted, read until EOF is reached.\n"
257"Return an empty string at EOF.");
258
259static PyObject *
260bytesio_read1(BytesIOObject *self, PyObject *n)
261{
262 PyObject *arg, *res;
263
264 arg = PyTuple_Pack(1, n);
265 if (arg == NULL)
266 return NULL;
267 res = bytesio_read(self, arg);
268 Py_DECREF(arg);
269 return res;
270}
271
272PyDoc_STRVAR(readline_doc,
273"readline([size]) -> next line from the file, as a string.\n"
274"\n"
275"Retain newline. A non-negative size argument limits the maximum\n"
276"number of bytes to return (an incomplete line may be returned then).\n"
277"Return an empty string at EOF.\n");
278
279static PyObject *
280bytesio_readline(BytesIOObject *self, PyObject *args)
281{
282 Py_ssize_t size, n;
283 char *output;
284 PyObject *arg = Py_None;
285
286 CHECK_CLOSED(self);
287
288 if (!PyArg_ParseTuple(args, "|O:readline", &arg))
289 return NULL;
290
291 if (PyLong_Check(arg)) {
292 size = PyLong_AsSsize_t(arg);
Benjamin Petersona8a93042008-09-30 02:18:09 +0000293 if (size == -1 && PyErr_Occurred())
294 return NULL;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000295 }
296 else if (arg == Py_None) {
297 /* No size limit, by default. */
298 size = -1;
299 }
300 else {
301 PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
302 Py_TYPE(arg)->tp_name);
303 return NULL;
304 }
305
306 n = get_line(self, &output);
307
308 if (size >= 0 && size < n) {
309 size = n - size;
310 n -= size;
311 self->pos -= size;
312 }
313
Christian Heimes72b710a2008-05-26 13:28:38 +0000314 return PyBytes_FromStringAndSize(output, n);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000315}
316
317PyDoc_STRVAR(readlines_doc,
318"readlines([size]) -> list of strings, each a line from the file.\n"
319"\n"
320"Call readline() repeatedly and return a list of the lines so read.\n"
321"The optional size argument, if given, is an approximate bound on the\n"
322"total number of bytes in the lines returned.\n");
323
324static PyObject *
325bytesio_readlines(BytesIOObject *self, PyObject *args)
326{
327 Py_ssize_t maxsize, size, n;
328 PyObject *result, *line;
329 char *output;
330 PyObject *arg = Py_None;
331
332 CHECK_CLOSED(self);
333
334 if (!PyArg_ParseTuple(args, "|O:readlines", &arg))
335 return NULL;
336
337 if (PyLong_Check(arg)) {
338 maxsize = PyLong_AsSsize_t(arg);
Benjamin Petersona8a93042008-09-30 02:18:09 +0000339 if (maxsize == -1 && PyErr_Occurred())
340 return NULL;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000341 }
342 else if (arg == Py_None) {
343 /* No size limit, by default. */
344 maxsize = -1;
345 }
346 else {
347 PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
348 Py_TYPE(arg)->tp_name);
349 return NULL;
350 }
351
352 size = 0;
353 result = PyList_New(0);
354 if (!result)
355 return NULL;
356
357 while ((n = get_line(self, &output)) != 0) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000358 line = PyBytes_FromStringAndSize(output, n);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000359 if (!line)
360 goto on_error;
361 if (PyList_Append(result, line) == -1) {
362 Py_DECREF(line);
363 goto on_error;
364 }
365 Py_DECREF(line);
366 size += n;
367 if (maxsize > 0 && size >= maxsize)
368 break;
369 }
370 return result;
371
372 on_error:
373 Py_DECREF(result);
374 return NULL;
375}
376
377PyDoc_STRVAR(readinto_doc,
Alexandre Vassalotti10dfc1e2008-05-08 01:34:41 +0000378"readinto(bytearray) -> int. Read up to len(b) bytes into b.\n"
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000379"\n"
380"Returns number of bytes read (0 for EOF), or None if the object\n"
381"is set not to block as has no data to read.");
382
383static PyObject *
384bytesio_readinto(BytesIOObject *self, PyObject *buffer)
385{
386 void *raw_buffer;
387 Py_ssize_t len;
388
389 CHECK_CLOSED(self);
390
391 if (PyObject_AsWriteBuffer(buffer, &raw_buffer, &len) == -1)
392 return NULL;
393
394 if (self->pos + len > self->string_size)
395 len = self->string_size - self->pos;
396
397 memcpy(raw_buffer, self->buf + self->pos, len);
398 assert(self->pos + len < PY_SSIZE_T_MAX);
399 assert(len >= 0);
400 self->pos += len;
401
402 return PyLong_FromSsize_t(len);
403}
404
405PyDoc_STRVAR(truncate_doc,
406"truncate([size]) -> int. Truncate the file to at most size bytes.\n"
407"\n"
408"Size defaults to the current file position, as returned by tell().\n"
409"Returns the new size. Imply an absolute seek to the position size.");
410
411static PyObject *
412bytesio_truncate(BytesIOObject *self, PyObject *args)
413{
414 Py_ssize_t size;
415 PyObject *arg = Py_None;
416
417 CHECK_CLOSED(self);
418
419 if (!PyArg_ParseTuple(args, "|O:truncate", &arg))
420 return NULL;
421
422 if (PyLong_Check(arg)) {
423 size = PyLong_AsSsize_t(arg);
Benjamin Petersona8a93042008-09-30 02:18:09 +0000424 if (size == -1 && PyErr_Occurred())
425 return NULL;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000426 }
427 else if (arg == Py_None) {
428 /* Truncate to current position if no argument is passed. */
429 size = self->pos;
430 }
431 else {
432 PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
433 Py_TYPE(arg)->tp_name);
434 return NULL;
435 }
436
437 if (size < 0) {
438 PyErr_Format(PyExc_ValueError,
439 "negative size value %zd", size);
440 return NULL;
441 }
442
443 if (size < self->string_size) {
444 self->string_size = size;
445 if (resize_buffer(self, size) < 0)
446 return NULL;
447 }
448 self->pos = size;
449
450 return PyLong_FromSsize_t(size);
451}
452
453static PyObject *
454bytesio_iternext(BytesIOObject *self)
455{
456 char *next;
457 Py_ssize_t n;
458
459 CHECK_CLOSED(self);
460
461 n = get_line(self, &next);
462
463 if (!next || n == 0)
464 return NULL;
465
Christian Heimes72b710a2008-05-26 13:28:38 +0000466 return PyBytes_FromStringAndSize(next, n);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000467}
468
469PyDoc_STRVAR(seek_doc,
470"seek(pos, whence=0) -> int. Change stream position.\n"
471"\n"
472"Seek to byte offset pos relative to position indicated by whence:\n"
473" 0 Start of stream (the default). pos should be >= 0;\n"
474" 1 Current position - pos may be negative;\n"
475" 2 End of stream - pos usually negative.\n"
476"Returns the new absolute position.");
477
478static PyObject *
479bytesio_seek(BytesIOObject *self, PyObject *args)
480{
481 Py_ssize_t pos;
482 int mode = 0;
483
484 CHECK_CLOSED(self);
485
486 if (!PyArg_ParseTuple(args, "n|i:seek", &pos, &mode))
487 return NULL;
488
489 if (pos < 0 && mode == 0) {
490 PyErr_Format(PyExc_ValueError,
491 "negative seek value %zd", pos);
492 return NULL;
493 }
494
495 /* mode 0: offset relative to beginning of the string.
496 mode 1: offset relative to current position.
497 mode 2: offset relative the end of the string. */
498 if (mode == 1) {
499 if (pos > PY_SSIZE_T_MAX - self->pos) {
500 PyErr_SetString(PyExc_OverflowError,
501 "new position too large");
502 return NULL;
503 }
504 pos += self->pos;
505 }
506 else if (mode == 2) {
507 if (pos > PY_SSIZE_T_MAX - self->string_size) {
508 PyErr_SetString(PyExc_OverflowError,
509 "new position too large");
510 return NULL;
511 }
512 pos += self->string_size;
513 }
514 else if (mode != 0) {
515 PyErr_Format(PyExc_ValueError,
516 "invalid whence (%i, should be 0, 1 or 2)", mode);
517 return NULL;
518 }
519
520 if (pos < 0)
521 pos = 0;
522 self->pos = pos;
523
524 return PyLong_FromSsize_t(self->pos);
525}
526
527PyDoc_STRVAR(write_doc,
Alexandre Vassalotti10dfc1e2008-05-08 01:34:41 +0000528"write(bytes) -> int. Write bytes to file.\n"
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000529"\n"
530"Return the number of bytes written.");
531
532static PyObject *
533bytesio_write(BytesIOObject *self, PyObject *obj)
534{
535 const char *bytes;
536 Py_ssize_t size;
537 Py_ssize_t n = 0;
538
539 CHECK_CLOSED(self);
540
541 if (PyObject_AsReadBuffer(obj, (void *)&bytes, &size) < 0)
542 return NULL;
543
544 if (size != 0) {
545 n = write_bytes(self, bytes, size);
546 if (n < 0)
547 return NULL;
548 }
549
550 return PyLong_FromSsize_t(n);
551}
552
553PyDoc_STRVAR(writelines_doc,
Alexandre Vassalotti7d060892008-05-07 01:47:37 +0000554"writelines(sequence_of_strings) -> None. Write strings to the file.\n"
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000555"\n"
Alexandre Vassalotti7d060892008-05-07 01:47:37 +0000556"Note that newlines are not added. The sequence can be any iterable\n"
557"object producing strings. This is equivalent to calling write() for\n"
558"each string.");
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000559
560static PyObject *
561bytesio_writelines(BytesIOObject *self, PyObject *v)
562{
563 PyObject *it, *item;
564 PyObject *ret;
565
566 CHECK_CLOSED(self);
567
568 it = PyObject_GetIter(v);
569 if (it == NULL)
570 return NULL;
571
572 while ((item = PyIter_Next(it)) != NULL) {
573 ret = bytesio_write(self, item);
574 Py_DECREF(item);
575 if (ret == NULL) {
576 Py_DECREF(it);
577 return NULL;
578 }
579 Py_DECREF(ret);
580 }
581 Py_DECREF(it);
582
583 /* See if PyIter_Next failed */
584 if (PyErr_Occurred())
585 return NULL;
586
587 Py_RETURN_NONE;
588}
589
590PyDoc_STRVAR(close_doc,
591"close() -> None. Disable all I/O operations.");
592
593static PyObject *
594bytesio_close(BytesIOObject *self)
595{
596 if (self->buf != NULL) {
597 PyMem_Free(self->buf);
598 self->buf = NULL;
599 }
600 Py_RETURN_NONE;
601}
602
603static void
604bytesio_dealloc(BytesIOObject *self)
605{
606 if (self->buf != NULL) {
607 PyMem_Free(self->buf);
608 self->buf = NULL;
609 }
610 Py_TYPE(self)->tp_free(self);
611}
612
613static PyObject *
614bytesio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
615{
616 BytesIOObject *self;
617
618 assert(type != NULL && type->tp_alloc != NULL);
619 self = (BytesIOObject *)type->tp_alloc(type, 0);
620 if (self == NULL)
621 return NULL;
622
623 self->string_size = 0;
624 self->pos = 0;
625 self->buf_size = 0;
626 self->buf = (char *)PyMem_Malloc(0);
627 if (self->buf == NULL) {
628 Py_DECREF(self);
629 return PyErr_NoMemory();
630 }
631
632 return (PyObject *)self;
633}
634
635static int
636bytesio_init(BytesIOObject *self, PyObject *args, PyObject *kwds)
637{
638 PyObject *initvalue = NULL;
639
640 if (!PyArg_ParseTuple(args, "|O:BytesIO", &initvalue))
641 return -1;
642
643 /* In case, __init__ is called multiple times. */
644 self->string_size = 0;
645 self->pos = 0;
646
647 if (initvalue && initvalue != Py_None) {
648 PyObject *res;
649 res = bytesio_write(self, initvalue);
650 if (res == NULL)
651 return -1;
652 Py_DECREF(res);
653 self->pos = 0;
654 }
655
656 return 0;
657}
658
659static PyGetSetDef bytesio_getsetlist[] = {
660 {"closed", (getter)bytesio_get_closed, NULL,
661 "True if the file is closed."},
662 {0}, /* sentinel */
663};
664
665static struct PyMethodDef bytesio_methods[] = {
666 {"readable", (PyCFunction)return_true, METH_NOARGS, NULL},
667 {"seekable", (PyCFunction)return_true, METH_NOARGS, NULL},
668 {"writable", (PyCFunction)return_true, METH_NOARGS, NULL},
669 {"close", (PyCFunction)bytesio_close, METH_NOARGS, close_doc},
670 {"flush", (PyCFunction)bytesio_flush, METH_NOARGS, flush_doc},
671 {"isatty", (PyCFunction)bytesio_isatty, METH_NOARGS, isatty_doc},
672 {"tell", (PyCFunction)bytesio_tell, METH_NOARGS, tell_doc},
673 {"write", (PyCFunction)bytesio_write, METH_O, write_doc},
674 {"writelines", (PyCFunction)bytesio_writelines, METH_O, writelines_doc},
675 {"read1", (PyCFunction)bytesio_read1, METH_O, read1_doc},
676 {"readinto", (PyCFunction)bytesio_readinto, METH_O, readinto_doc},
677 {"readline", (PyCFunction)bytesio_readline, METH_VARARGS, readline_doc},
678 {"readlines", (PyCFunction)bytesio_readlines, METH_VARARGS, readlines_doc},
679 {"read", (PyCFunction)bytesio_read, METH_VARARGS, read_doc},
680 {"getvalue", (PyCFunction)bytesio_getvalue, METH_VARARGS, getval_doc},
681 {"seek", (PyCFunction)bytesio_seek, METH_VARARGS, seek_doc},
682 {"truncate", (PyCFunction)bytesio_truncate, METH_VARARGS, truncate_doc},
683 {NULL, NULL} /* sentinel */
684};
685
686PyDoc_STRVAR(bytesio_doc,
687"BytesIO([buffer]) -> object\n"
688"\n"
689"Create a buffered I/O implementation using an in-memory bytes\n"
690"buffer, ready for reading and writing.");
691
692static PyTypeObject BytesIO_Type = {
693 PyVarObject_HEAD_INIT(NULL, 0)
694 "_bytesio._BytesIO", /*tp_name*/
695 sizeof(BytesIOObject), /*tp_basicsize*/
696 0, /*tp_itemsize*/
697 (destructor)bytesio_dealloc, /*tp_dealloc*/
698 0, /*tp_print*/
699 0, /*tp_getattr*/
700 0, /*tp_setattr*/
701 0, /*tp_compare*/
702 0, /*tp_repr*/
703 0, /*tp_as_number*/
704 0, /*tp_as_sequence*/
705 0, /*tp_as_mapping*/
706 0, /*tp_hash*/
707 0, /*tp_call*/
708 0, /*tp_str*/
709 0, /*tp_getattro*/
710 0, /*tp_setattro*/
711 0, /*tp_as_buffer*/
712 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
713 bytesio_doc, /*tp_doc*/
714 0, /*tp_traverse*/
715 0, /*tp_clear*/
716 0, /*tp_richcompare*/
717 0, /*tp_weaklistoffset*/
718 PyObject_SelfIter, /*tp_iter*/
719 (iternextfunc)bytesio_iternext, /*tp_iternext*/
720 bytesio_methods, /*tp_methods*/
721 0, /*tp_members*/
722 bytesio_getsetlist, /*tp_getset*/
723 0, /*tp_base*/
724 0, /*tp_dict*/
725 0, /*tp_descr_get*/
726 0, /*tp_descr_set*/
727 0, /*tp_dictoffset*/
728 (initproc)bytesio_init, /*tp_init*/
729 0, /*tp_alloc*/
730 bytesio_new, /*tp_new*/
731};
732
Martin v. Löwis1a214512008-06-11 05:26:20 +0000733
734static struct PyModuleDef _bytesiomodule = {
735 PyModuleDef_HEAD_INIT,
736 "_bytesio",
737 NULL,
738 -1,
739 NULL,
740 NULL,
741 NULL,
742 NULL,
743 NULL
744};
745
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000746PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000747PyInit__bytesio(void)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000748{
749 PyObject *m;
750
751 if (PyType_Ready(&BytesIO_Type) < 0)
Martin v. Löwis1a214512008-06-11 05:26:20 +0000752 return NULL;
753 m = PyModule_Create(&_bytesiomodule);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000754 if (m == NULL)
Martin v. Löwis1a214512008-06-11 05:26:20 +0000755 return NULL;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000756 Py_INCREF(&BytesIO_Type);
757 PyModule_AddObject(m, "_BytesIO", (PyObject *)&BytesIO_Type);
Martin v. Löwis1a214512008-06-11 05:26:20 +0000758 return m;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000759}