blob: e369f8136410b9d5821ead8238c8f06fe509a4dc [file] [log] [blame]
Alexandre Vassalotti1aed6242008-05-09 21:49:43 +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
113 if ((size_t)self->pos + len > self->buf_size) {
114 if (resize_buffer(self, (size_t)self->pos + len) < 0)
115 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{
Antoine Pitrou01a255a2010-05-03 16:48:13 +0000166 CHECK_CLOSED(self);
Alexandre Vassalotti1aed6242008-05-09 21:49:43 +0000167 Py_RETURN_NONE;
168}
169
170PyDoc_STRVAR(getval_doc,
171"getvalue() -> bytes.\n"
172"\n"
173"Retrieve the entire contents of the BytesIO object.");
174
175static PyObject *
176bytesio_getvalue(BytesIOObject *self)
177{
178 CHECK_CLOSED(self);
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000179 return PyString_FromStringAndSize(self->buf, self->string_size);
Alexandre Vassalotti1aed6242008-05-09 21:49:43 +0000180}
181
182PyDoc_STRVAR(isatty_doc,
183"isatty() -> False.\n"
184"\n"
185"Always returns False since BytesIO objects are not connected\n"
186"to a tty-like device.");
187
188static PyObject *
189bytesio_isatty(BytesIOObject *self)
190{
191 CHECK_CLOSED(self);
192 Py_RETURN_FALSE;
193}
194
195PyDoc_STRVAR(tell_doc,
196"tell() -> current file position, an integer\n");
197
198static PyObject *
199bytesio_tell(BytesIOObject *self)
200{
201 CHECK_CLOSED(self);
202 return PyInt_FromSsize_t(self->pos);
203}
204
205PyDoc_STRVAR(read_doc,
206"read([size]) -> read at most size bytes, returned as a string.\n"
207"\n"
208"If the size argument is negative, read until EOF is reached.\n"
209"Return an empty string at EOF.");
210
211static PyObject *
212bytesio_read(BytesIOObject *self, PyObject *args)
213{
214 Py_ssize_t size, n;
215 char *output;
216 PyObject *arg = Py_None;
217
218 CHECK_CLOSED(self);
219
220 if (!PyArg_ParseTuple(args, "|O:read", &arg))
221 return NULL;
222
Antoine Pitrouf226ac82009-11-02 21:03:53 +0000223 if (PyIndex_Check(arg)) {
224 size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
Benjamin Peterson02252482008-09-30 02:11:07 +0000225 if (size == -1 && PyErr_Occurred())
226 return NULL;
Alexandre Vassalotti1aed6242008-05-09 21:49:43 +0000227 }
228 else if (arg == Py_None) {
229 /* Read until EOF is reached, by default. */
230 size = -1;
231 }
232 else {
233 PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
234 Py_TYPE(arg)->tp_name);
235 return NULL;
236 }
237
238 /* adjust invalid sizes */
239 n = self->string_size - self->pos;
240 if (size < 0 || size > n) {
241 size = n;
242 if (size < 0)
243 size = 0;
244 }
245
246 assert(self->buf != NULL);
247 output = self->buf + self->pos;
248 self->pos += size;
249
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000250 return PyString_FromStringAndSize(output, size);
Alexandre Vassalotti1aed6242008-05-09 21:49:43 +0000251}
252
253
254PyDoc_STRVAR(read1_doc,
255"read1(size) -> read at most size bytes, returned as a string.\n"
256"\n"
257"If the size argument is negative or omitted, read until EOF is reached.\n"
258"Return an empty string at EOF.");
259
260static PyObject *
261bytesio_read1(BytesIOObject *self, PyObject *n)
262{
263 PyObject *arg, *res;
264
265 arg = PyTuple_Pack(1, n);
266 if (arg == NULL)
267 return NULL;
268 res = bytesio_read(self, arg);
269 Py_DECREF(arg);
270 return res;
271}
272
273PyDoc_STRVAR(readline_doc,
274"readline([size]) -> next line from the file, as a string.\n"
275"\n"
276"Retain newline. A non-negative size argument limits the maximum\n"
277"number of bytes to return (an incomplete line may be returned then).\n"
278"Return an empty string at EOF.\n");
279
280static PyObject *
281bytesio_readline(BytesIOObject *self, PyObject *args)
282{
283 Py_ssize_t size, n;
284 char *output;
285 PyObject *arg = Py_None;
286
287 CHECK_CLOSED(self);
288
289 if (!PyArg_ParseTuple(args, "|O:readline", &arg))
290 return NULL;
291
Antoine Pitrouf226ac82009-11-02 21:03:53 +0000292 if (PyIndex_Check(arg)) {
293 size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
Benjamin Peterson02252482008-09-30 02:11:07 +0000294 if (size == -1 && PyErr_Occurred())
295 return NULL;
Alexandre Vassalotti1aed6242008-05-09 21:49:43 +0000296 }
297 else if (arg == Py_None) {
298 /* No size limit, by default. */
299 size = -1;
300 }
301 else {
302 PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
303 Py_TYPE(arg)->tp_name);
304 return NULL;
305 }
306
307 n = get_line(self, &output);
308
309 if (size >= 0 && size < n) {
310 size = n - size;
311 n -= size;
312 self->pos -= size;
313 }
314
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000315 return PyString_FromStringAndSize(output, n);
Alexandre Vassalotti1aed6242008-05-09 21:49:43 +0000316}
317
318PyDoc_STRVAR(readlines_doc,
319"readlines([size]) -> list of strings, each a line from the file.\n"
320"\n"
321"Call readline() repeatedly and return a list of the lines so read.\n"
322"The optional size argument, if given, is an approximate bound on the\n"
323"total number of bytes in the lines returned.\n");
324
325static PyObject *
326bytesio_readlines(BytesIOObject *self, PyObject *args)
327{
328 Py_ssize_t maxsize, size, n;
329 PyObject *result, *line;
330 char *output;
331 PyObject *arg = Py_None;
332
333 CHECK_CLOSED(self);
334
335 if (!PyArg_ParseTuple(args, "|O:readlines", &arg))
336 return NULL;
337
Antoine Pitrouf226ac82009-11-02 21:03:53 +0000338 if (PyIndex_Check(arg)) {
339 maxsize = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
Benjamin Peterson02252482008-09-30 02:11:07 +0000340 if (maxsize == -1 && PyErr_Occurred())
341 return NULL;
Alexandre Vassalotti1aed6242008-05-09 21:49:43 +0000342 }
343 else if (arg == Py_None) {
344 /* No size limit, by default. */
345 maxsize = -1;
346 }
347 else {
348 PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
349 Py_TYPE(arg)->tp_name);
350 return NULL;
351 }
352
353 size = 0;
354 result = PyList_New(0);
355 if (!result)
356 return NULL;
357
358 while ((n = get_line(self, &output)) != 0) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000359 line = PyString_FromStringAndSize(output, n);
Alexandre Vassalotti1aed6242008-05-09 21:49:43 +0000360 if (!line)
361 goto on_error;
362 if (PyList_Append(result, line) == -1) {
363 Py_DECREF(line);
364 goto on_error;
365 }
366 Py_DECREF(line);
367 size += n;
368 if (maxsize > 0 && size >= maxsize)
369 break;
370 }
371 return result;
372
373 on_error:
374 Py_DECREF(result);
375 return NULL;
376}
377
378PyDoc_STRVAR(readinto_doc,
379"readinto(bytearray) -> int. Read up to len(b) bytes into b.\n"
380"\n"
381"Returns number of bytes read (0 for EOF), or None if the object\n"
382"is set not to block as has no data to read.");
383
384static PyObject *
385bytesio_readinto(BytesIOObject *self, PyObject *buffer)
386{
387 void *raw_buffer;
388 Py_ssize_t len;
389
390 CHECK_CLOSED(self);
391
392 if (PyObject_AsWriteBuffer(buffer, &raw_buffer, &len) == -1)
393 return NULL;
394
395 if (self->pos + len > self->string_size)
396 len = self->string_size - self->pos;
397
398 memcpy(raw_buffer, self->buf + self->pos, len);
399 assert(self->pos + len < PY_SSIZE_T_MAX);
400 assert(len >= 0);
401 self->pos += len;
402
403 return PyInt_FromSsize_t(len);
404}
405
406PyDoc_STRVAR(truncate_doc,
407"truncate([size]) -> int. Truncate the file to at most size bytes.\n"
408"\n"
409"Size defaults to the current file position, as returned by tell().\n"
410"Returns the new size. Imply an absolute seek to the position size.");
411
412static PyObject *
413bytesio_truncate(BytesIOObject *self, PyObject *args)
414{
415 Py_ssize_t size;
416 PyObject *arg = Py_None;
417
418 CHECK_CLOSED(self);
419
420 if (!PyArg_ParseTuple(args, "|O:truncate", &arg))
421 return NULL;
422
Antoine Pitrouf226ac82009-11-02 21:03:53 +0000423 if (PyIndex_Check(arg)) {
424 size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
Benjamin Peterson02252482008-09-30 02:11:07 +0000425 if (size == -1 && PyErr_Occurred())
426 return NULL;
Alexandre Vassalotti1aed6242008-05-09 21:49:43 +0000427 }
428 else if (arg == Py_None) {
429 /* Truncate to current position if no argument is passed. */
430 size = self->pos;
431 }
432 else {
433 PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
434 Py_TYPE(arg)->tp_name);
435 return NULL;
436 }
437
438 if (size < 0) {
439 PyErr_Format(PyExc_ValueError,
440 "negative size value %zd", size);
441 return NULL;
442 }
443
444 if (size < self->string_size) {
445 self->string_size = size;
446 if (resize_buffer(self, size) < 0)
447 return NULL;
448 }
Alexandre Vassalotti1aed6242008-05-09 21:49:43 +0000449
450 return PyInt_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
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000466 return PyString_FromStringAndSize(next, n);
Alexandre Vassalotti1aed6242008-05-09 21:49:43 +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 PyObject *pos_obj, *mode_obj;
482 Py_ssize_t pos;
483 int mode = 0;
484
485 CHECK_CLOSED(self);
486
487 /* Special-case for 2.x to prevent floats from passing through.
488 This only needed to make a test in test_io succeed. */
489 if (!PyArg_UnpackTuple(args, "seek", 1, 2, &pos_obj, &mode_obj))
490 return NULL;
491 if (PyFloat_Check(pos_obj)) {
492 PyErr_SetString(PyExc_TypeError,
493 "position argument must be an integer");
494 return NULL;
495 }
496
497 if (!PyArg_ParseTuple(args, "n|i:seek", &pos, &mode))
498 return NULL;
499
500 if (pos < 0 && mode == 0) {
501 PyErr_Format(PyExc_ValueError,
502 "negative seek value %zd", pos);
503 return NULL;
504 }
505
506 /* mode 0: offset relative to beginning of the string.
507 mode 1: offset relative to current position.
508 mode 2: offset relative the end of the string. */
509 if (mode == 1) {
510 if (pos > PY_SSIZE_T_MAX - self->pos) {
511 PyErr_SetString(PyExc_OverflowError,
512 "new position too large");
513 return NULL;
514 }
515 pos += self->pos;
516 }
517 else if (mode == 2) {
518 if (pos > PY_SSIZE_T_MAX - self->string_size) {
519 PyErr_SetString(PyExc_OverflowError,
520 "new position too large");
521 return NULL;
522 }
523 pos += self->string_size;
524 }
525 else if (mode != 0) {
526 PyErr_Format(PyExc_ValueError,
527 "invalid whence (%i, should be 0, 1 or 2)", mode);
528 return NULL;
529 }
530
531 if (pos < 0)
532 pos = 0;
533 self->pos = pos;
534
535 return PyInt_FromSsize_t(self->pos);
536}
537
538PyDoc_STRVAR(write_doc,
539"write(bytes) -> int. Write bytes to file.\n"
540"\n"
541"Return the number of bytes written.");
542
543static PyObject *
544bytesio_write(BytesIOObject *self, PyObject *obj)
545{
546 const char *bytes;
547 Py_ssize_t size;
548 Py_ssize_t n = 0;
549
550 CHECK_CLOSED(self);
551
552 /* Special-case in 2.x to prevent unicode objects to pass through. */
553 if (PyUnicode_Check(obj)) {
554 PyErr_SetString(PyExc_TypeError,
555 "expecting a bytes object, got unicode");
556 return NULL;
557 }
558
559 if (PyObject_AsReadBuffer(obj, (void *)&bytes, &size) < 0)
560 return NULL;
561
562 if (size != 0) {
563 n = write_bytes(self, bytes, size);
564 if (n < 0)
565 return NULL;
566 }
567
568 return PyInt_FromSsize_t(n);
569}
570
571PyDoc_STRVAR(writelines_doc,
572"writelines(sequence_of_strings) -> None. Write strings to the file.\n"
573"\n"
574"Note that newlines are not added. The sequence can be any iterable\n"
575"object producing strings. This is equivalent to calling write() for\n"
576"each string.");
577
578static PyObject *
579bytesio_writelines(BytesIOObject *self, PyObject *v)
580{
581 PyObject *it, *item;
582 PyObject *ret;
583
584 CHECK_CLOSED(self);
585
586 it = PyObject_GetIter(v);
587 if (it == NULL)
588 return NULL;
589
590 while ((item = PyIter_Next(it)) != NULL) {
591 ret = bytesio_write(self, item);
592 Py_DECREF(item);
593 if (ret == NULL) {
594 Py_DECREF(it);
595 return NULL;
596 }
597 Py_DECREF(ret);
598 }
599 Py_DECREF(it);
600
601 /* See if PyIter_Next failed */
602 if (PyErr_Occurred())
603 return NULL;
604
605 Py_RETURN_NONE;
606}
607
608PyDoc_STRVAR(close_doc,
609"close() -> None. Disable all I/O operations.");
610
611static PyObject *
612bytesio_close(BytesIOObject *self)
613{
614 if (self->buf != NULL) {
615 PyMem_Free(self->buf);
616 self->buf = NULL;
617 }
618 Py_RETURN_NONE;
619}
620
621static void
622bytesio_dealloc(BytesIOObject *self)
623{
624 if (self->buf != NULL) {
625 PyMem_Free(self->buf);
626 self->buf = NULL;
627 }
628 Py_TYPE(self)->tp_free(self);
629}
630
631static PyObject *
632bytesio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
633{
634 BytesIOObject *self;
635
636 assert(type != NULL && type->tp_alloc != NULL);
637 self = (BytesIOObject *)type->tp_alloc(type, 0);
638 if (self == NULL)
639 return NULL;
640
641 self->string_size = 0;
642 self->pos = 0;
643 self->buf_size = 0;
644 self->buf = (char *)PyMem_Malloc(0);
645 if (self->buf == NULL) {
646 Py_DECREF(self);
647 return PyErr_NoMemory();
648 }
649
650 return (PyObject *)self;
651}
652
653static int
654bytesio_init(BytesIOObject *self, PyObject *args, PyObject *kwds)
655{
656 PyObject *initvalue = NULL;
657
658 if (!PyArg_ParseTuple(args, "|O:BytesIO", &initvalue))
659 return -1;
660
661 /* In case, __init__ is called multiple times. */
662 self->string_size = 0;
663 self->pos = 0;
664
665 if (initvalue && initvalue != Py_None) {
666 PyObject *res;
667 res = bytesio_write(self, initvalue);
668 if (res == NULL)
669 return -1;
670 Py_DECREF(res);
671 self->pos = 0;
672 }
673
674 return 0;
675}
676
677static PyGetSetDef bytesio_getsetlist[] = {
678 {"closed", (getter)bytesio_get_closed, NULL,
679 "True if the file is closed."},
680 {0}, /* sentinel */
681};
682
683static struct PyMethodDef bytesio_methods[] = {
684 {"readable", (PyCFunction)return_true, METH_NOARGS, NULL},
685 {"seekable", (PyCFunction)return_true, METH_NOARGS, NULL},
686 {"writable", (PyCFunction)return_true, METH_NOARGS, NULL},
687 {"close", (PyCFunction)bytesio_close, METH_NOARGS, close_doc},
688 {"flush", (PyCFunction)bytesio_flush, METH_NOARGS, flush_doc},
689 {"isatty", (PyCFunction)bytesio_isatty, METH_NOARGS, isatty_doc},
690 {"tell", (PyCFunction)bytesio_tell, METH_NOARGS, tell_doc},
691 {"write", (PyCFunction)bytesio_write, METH_O, write_doc},
692 {"writelines", (PyCFunction)bytesio_writelines, METH_O, writelines_doc},
693 {"read1", (PyCFunction)bytesio_read1, METH_O, read1_doc},
694 {"readinto", (PyCFunction)bytesio_readinto, METH_O, readinto_doc},
695 {"readline", (PyCFunction)bytesio_readline, METH_VARARGS, readline_doc},
696 {"readlines", (PyCFunction)bytesio_readlines, METH_VARARGS, readlines_doc},
697 {"read", (PyCFunction)bytesio_read, METH_VARARGS, read_doc},
698 {"getvalue", (PyCFunction)bytesio_getvalue, METH_VARARGS, getval_doc},
699 {"seek", (PyCFunction)bytesio_seek, METH_VARARGS, seek_doc},
700 {"truncate", (PyCFunction)bytesio_truncate, METH_VARARGS, truncate_doc},
701 {NULL, NULL} /* sentinel */
702};
703
704PyDoc_STRVAR(bytesio_doc,
705"BytesIO([buffer]) -> object\n"
706"\n"
707"Create a buffered I/O implementation using an in-memory bytes\n"
708"buffer, ready for reading and writing.");
709
710static PyTypeObject BytesIO_Type = {
711 PyVarObject_HEAD_INIT(NULL, 0)
712 "_bytesio._BytesIO", /*tp_name*/
713 sizeof(BytesIOObject), /*tp_basicsize*/
714 0, /*tp_itemsize*/
715 (destructor)bytesio_dealloc, /*tp_dealloc*/
716 0, /*tp_print*/
717 0, /*tp_getattr*/
718 0, /*tp_setattr*/
719 0, /*tp_compare*/
720 0, /*tp_repr*/
721 0, /*tp_as_number*/
722 0, /*tp_as_sequence*/
723 0, /*tp_as_mapping*/
724 0, /*tp_hash*/
725 0, /*tp_call*/
726 0, /*tp_str*/
727 0, /*tp_getattro*/
728 0, /*tp_setattro*/
729 0, /*tp_as_buffer*/
730 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
731 bytesio_doc, /*tp_doc*/
732 0, /*tp_traverse*/
733 0, /*tp_clear*/
734 0, /*tp_richcompare*/
735 0, /*tp_weaklistoffset*/
736 PyObject_SelfIter, /*tp_iter*/
737 (iternextfunc)bytesio_iternext, /*tp_iternext*/
738 bytesio_methods, /*tp_methods*/
739 0, /*tp_members*/
740 bytesio_getsetlist, /*tp_getset*/
741 0, /*tp_base*/
742 0, /*tp_dict*/
743 0, /*tp_descr_get*/
744 0, /*tp_descr_set*/
745 0, /*tp_dictoffset*/
746 (initproc)bytesio_init, /*tp_init*/
747 0, /*tp_alloc*/
748 bytesio_new, /*tp_new*/
749};
750
751PyMODINIT_FUNC
752init_bytesio(void)
753{
754 PyObject *m;
755
756 if (PyType_Ready(&BytesIO_Type) < 0)
757 return;
758 m = Py_InitModule("_bytesio", NULL);
759 if (m == NULL)
760 return;
761 Py_INCREF(&BytesIO_Type);
762 PyModule_AddObject(m, "_BytesIO", (PyObject *)&BytesIO_Type);
763}