1#include "Python.h"
2#include "structmember.h"       /* for offsetof() */
3#include "_iomodule.h"
4
5typedef struct {
6    PyObject_HEAD
7    char *buf;
8    Py_ssize_t pos;
9    Py_ssize_t string_size;
10    size_t buf_size;
11    PyObject *dict;
12    PyObject *weakreflist;
13} bytesio;
14
15#define CHECK_CLOSED(self)                                  \
16    if ((self)->buf == NULL) {                              \
17        PyErr_SetString(PyExc_ValueError,                   \
18                        "I/O operation on closed file.");   \
19        return NULL;                                        \
20    }
21
22/* Internal routine to get a line from the buffer of a BytesIO
23   object. Returns the length between the current position to the
24   next newline character. */
25static Py_ssize_t
26get_line(bytesio *self, char **output)
27{
28    char *n;
29    const char *str_end;
30    Py_ssize_t len;
31
32    assert(self->buf != NULL);
33
34    /* Move to the end of the line, up to the end of the string, s. */
35    str_end = self->buf + self->string_size;
36    for (n = self->buf + self->pos;
37         n < str_end && *n != '\n';
38         n++);
39
40    /* Skip the newline character */
41    if (n < str_end)
42        n++;
43
44    /* Get the length from the current position to the end of the line. */
45    len = n - (self->buf + self->pos);
46    *output = self->buf + self->pos;
47
48    assert(len >= 0);
49    assert(self->pos < PY_SSIZE_T_MAX - len);
50    self->pos += len;
51
52    return len;
53}
54
55/* Internal routine for changing the size of the buffer of BytesIO objects.
56   The caller should ensure that the 'size' argument is non-negative.  Returns
57   0 on success, -1 otherwise. */
58static int
59resize_buffer(bytesio *self, size_t size)
60{
61    /* Here, unsigned types are used to avoid dealing with signed integer
62       overflow, which is undefined in C. */
63    size_t alloc = self->buf_size;
64    char *new_buf = NULL;
65
66    assert(self->buf != NULL);
67
68    /* For simplicity, stay in the range of the signed type. Anyway, Python
69       doesn't allow strings to be longer than this. */
70    if (size > PY_SSIZE_T_MAX)
71        goto overflow;
72
73    if (size < alloc / 2) {
74        /* Major downsize; resize down to exact size. */
75        alloc = size + 1;
76    }
77    else if (size < alloc) {
78        /* Within allocated size; quick exit */
79        return 0;
80    }
81    else if (size <= alloc * 1.125) {
82        /* Moderate upsize; overallocate similar to list_resize() */
83        alloc = size + (size >> 3) + (size < 9 ? 3 : 6);
84    }
85    else {
86        /* Major upsize; resize up to exact size */
87        alloc = size + 1;
88    }
89
90    if (alloc > ((size_t)-1) / sizeof(char))
91        goto overflow;
92    new_buf = (char *)PyMem_Realloc(self->buf, alloc * sizeof(char));
93    if (new_buf == NULL) {
94        PyErr_NoMemory();
95        return -1;
96    }
97    self->buf_size = alloc;
98    self->buf = new_buf;
99
100    return 0;
101
102  overflow:
103    PyErr_SetString(PyExc_OverflowError,
104                    "new buffer size too large");
105    return -1;
106}
107
108/* Internal routine for writing a string of bytes to the buffer of a BytesIO
109   object. Returns the number of bytes written, or -1 on error. */
110static Py_ssize_t
111write_bytes(bytesio *self, const char *bytes, Py_ssize_t len)
112{
113    assert(self->buf != NULL);
114    assert(self->pos >= 0);
115    assert(len >= 0);
116
117    if ((size_t)self->pos + len > self->buf_size) {
118        if (resize_buffer(self, (size_t)self->pos + len) < 0)
119            return -1;
120    }
121
122    if (self->pos > self->string_size) {
123        /* In case of overseek, pad with null bytes the buffer region between
124           the end of stream and the current position.
125
126          0   lo      string_size                           hi
127          |   |<---used--->|<----------available----------->|
128          |   |            <--to pad-->|<---to write--->    |
129          0   buf                   position
130        */
131        memset(self->buf + self->string_size, '\0',
132               (self->pos - self->string_size) * sizeof(char));
133    }
134
135    /* Copy the data to the internal buffer, overwriting some of the existing
136       data if self->pos < self->string_size. */
137    memcpy(self->buf + self->pos, bytes, len);
138    self->pos += len;
139
140    /* Set the new length of the internal string if it has changed. */
141    if (self->string_size < self->pos) {
142        self->string_size = self->pos;
143    }
144
145    return len;
146}
147
148static PyObject *
149bytesio_get_closed(bytesio *self)
150{
151    if (self->buf == NULL) {
152        Py_RETURN_TRUE;
153    }
154    else {
155        Py_RETURN_FALSE;
156    }
157}
158
159PyDoc_STRVAR(readable_doc,
160"readable() -> bool. Returns True if the IO object can be read.");
161
162PyDoc_STRVAR(writable_doc,
163"writable() -> bool. Returns True if the IO object can be written.");
164
165PyDoc_STRVAR(seekable_doc,
166"seekable() -> bool. Returns True if the IO object can be seeked.");
167
168/* Generic getter for the writable, readable and seekable properties */
169static PyObject *
170return_not_closed(bytesio *self)
171{
172    CHECK_CLOSED(self);
173    Py_RETURN_TRUE;
174}
175
176PyDoc_STRVAR(flush_doc,
177"flush() -> None.  Does nothing.");
178
179static PyObject *
180bytesio_flush(bytesio *self)
181{
182    CHECK_CLOSED(self);
183    Py_RETURN_NONE;
184}
185
186PyDoc_STRVAR(getval_doc,
187"getvalue() -> bytes.\n"
188"\n"
189"Retrieve the entire contents of the BytesIO object.");
190
191static PyObject *
192bytesio_getvalue(bytesio *self)
193{
194    CHECK_CLOSED(self);
195    return PyBytes_FromStringAndSize(self->buf, self->string_size);
196}
197
198PyDoc_STRVAR(isatty_doc,
199"isatty() -> False.\n"
200"\n"
201"Always returns False since BytesIO objects are not connected\n"
202"to a tty-like device.");
203
204static PyObject *
205bytesio_isatty(bytesio *self)
206{
207    CHECK_CLOSED(self);
208    Py_RETURN_FALSE;
209}
210
211PyDoc_STRVAR(tell_doc,
212"tell() -> current file position, an integer\n");
213
214static PyObject *
215bytesio_tell(bytesio *self)
216{
217    CHECK_CLOSED(self);
218    return PyLong_FromSsize_t(self->pos);
219}
220
221PyDoc_STRVAR(read_doc,
222"read([size]) -> read at most size bytes, returned as a string.\n"
223"\n"
224"If the size argument is negative, read until EOF is reached.\n"
225"Return an empty string at EOF.");
226
227static PyObject *
228bytesio_read(bytesio *self, PyObject *args)
229{
230    Py_ssize_t size, n;
231    char *output;
232    PyObject *arg = Py_None;
233
234    CHECK_CLOSED(self);
235
236    if (!PyArg_ParseTuple(args, "|O:read", &arg))
237        return NULL;
238
239    if (PyNumber_Check(arg)) {
240        size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
241        if (size == -1 && PyErr_Occurred())
242            return NULL;
243    }
244    else if (arg == Py_None) {
245        /* Read until EOF is reached, by default. */
246        size = -1;
247    }
248    else {
249        PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
250                     Py_TYPE(arg)->tp_name);
251        return NULL;
252    }
253
254    /* adjust invalid sizes */
255    n = self->string_size - self->pos;
256    if (size < 0 || size > n) {
257        size = n;
258        if (size < 0)
259            size = 0;
260    }
261
262    assert(self->buf != NULL);
263    output = self->buf + self->pos;
264    self->pos += size;
265
266    return PyBytes_FromStringAndSize(output, size);
267}
268
269
270PyDoc_STRVAR(read1_doc,
271"read1(size) -> read at most size bytes, returned as a string.\n"
272"\n"
273"If the size argument is negative or omitted, read until EOF is reached.\n"
274"Return an empty string at EOF.");
275
276static PyObject *
277bytesio_read1(bytesio *self, PyObject *n)
278{
279    PyObject *arg, *res;
280
281    arg = PyTuple_Pack(1, n);
282    if (arg == NULL)
283        return NULL;
284    res  = bytesio_read(self, arg);
285    Py_DECREF(arg);
286    return res;
287}
288
289PyDoc_STRVAR(readline_doc,
290"readline([size]) -> next line from the file, as a string.\n"
291"\n"
292"Retain newline.  A non-negative size argument limits the maximum\n"
293"number of bytes to return (an incomplete line may be returned then).\n"
294"Return an empty string at EOF.\n");
295
296static PyObject *
297bytesio_readline(bytesio *self, PyObject *args)
298{
299    Py_ssize_t size, n;
300    char *output;
301    PyObject *arg = Py_None;
302
303    CHECK_CLOSED(self);
304
305    if (!PyArg_ParseTuple(args, "|O:readline", &arg))
306        return NULL;
307
308    if (PyNumber_Check(arg)) {
309        size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
310        if (size == -1 && PyErr_Occurred())
311            return NULL;
312    }
313    else if (arg == Py_None) {
314        /* No size limit, by default. */
315        size = -1;
316    }
317    else {
318        PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
319                     Py_TYPE(arg)->tp_name);
320        return NULL;
321    }
322
323    n = get_line(self, &output);
324
325    if (size >= 0 && size < n) {
326        size = n - size;
327        n -= size;
328        self->pos -= size;
329    }
330
331    return PyBytes_FromStringAndSize(output, n);
332}
333
334PyDoc_STRVAR(readlines_doc,
335"readlines([size]) -> list of strings, each a line from the file.\n"
336"\n"
337"Call readline() repeatedly and return a list of the lines so read.\n"
338"The optional size argument, if given, is an approximate bound on the\n"
339"total number of bytes in the lines returned.\n");
340
341static PyObject *
342bytesio_readlines(bytesio *self, PyObject *args)
343{
344    Py_ssize_t maxsize, size, n;
345    PyObject *result, *line;
346    char *output;
347    PyObject *arg = Py_None;
348
349    CHECK_CLOSED(self);
350
351    if (!PyArg_ParseTuple(args, "|O:readlines", &arg))
352        return NULL;
353
354    if (PyNumber_Check(arg)) {
355        maxsize = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
356        if (maxsize == -1 && PyErr_Occurred())
357            return NULL;
358    }
359    else if (arg == Py_None) {
360        /* No size limit, by default. */
361        maxsize = -1;
362    }
363    else {
364        PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
365                     Py_TYPE(arg)->tp_name);
366        return NULL;
367    }
368
369    size = 0;
370    result = PyList_New(0);
371    if (!result)
372        return NULL;
373
374    while ((n = get_line(self, &output)) != 0) {
375        line = PyBytes_FromStringAndSize(output, n);
376        if (!line)
377            goto on_error;
378        if (PyList_Append(result, line) == -1) {
379            Py_DECREF(line);
380            goto on_error;
381        }
382        Py_DECREF(line);
383        size += n;
384        if (maxsize > 0 && size >= maxsize)
385            break;
386    }
387    return result;
388
389  on_error:
390    Py_DECREF(result);
391    return NULL;
392}
393
394PyDoc_STRVAR(readinto_doc,
395"readinto(b) -> int.  Read up to len(b) bytes into b.\n"
396"\n"
397"Returns number of bytes read (0 for EOF), or None if the object\n"
398"is set not to block and has no data to read.");
399
400static PyObject *
401bytesio_readinto(bytesio *self, PyObject *args)
402{
403    Py_buffer buf;
404    Py_ssize_t len, n;
405
406    CHECK_CLOSED(self);
407
408    if (!PyArg_ParseTuple(args, "w*", &buf))
409        return NULL;
410
411    len = buf.len;
412    /* adjust invalid sizes */
413    n = self->string_size - self->pos;
414    if (len > n) {
415        len = n;
416        if (len < 0)
417            len = 0;
418    }
419
420    memcpy(buf.buf, self->buf + self->pos, len);
421    assert(self->pos + len < PY_SSIZE_T_MAX);
422    assert(len >= 0);
423    self->pos += len;
424
425    PyBuffer_Release(&buf);
426    return PyLong_FromSsize_t(len);
427}
428
429PyDoc_STRVAR(truncate_doc,
430"truncate([size]) -> int.  Truncate the file to at most size bytes.\n"
431"\n"
432"Size defaults to the current file position, as returned by tell().\n"
433"The current file position is unchanged.  Returns the new size.\n");
434
435static PyObject *
436bytesio_truncate(bytesio *self, PyObject *args)
437{
438    Py_ssize_t size;
439    PyObject *arg = Py_None;
440
441    CHECK_CLOSED(self);
442
443    if (!PyArg_ParseTuple(args, "|O:truncate", &arg))
444        return NULL;
445
446    if (PyNumber_Check(arg)) {
447        size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
448        if (size == -1 && PyErr_Occurred())
449            return NULL;
450    }
451    else if (arg == Py_None) {
452        /* Truncate to current position if no argument is passed. */
453        size = self->pos;
454    }
455    else {
456        PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
457                     Py_TYPE(arg)->tp_name);
458        return NULL;
459    }
460
461    if (size < 0) {
462        PyErr_Format(PyExc_ValueError,
463                     "negative size value %zd", size);
464        return NULL;
465    }
466
467    if (size < self->string_size) {
468        self->string_size = size;
469        if (resize_buffer(self, size) < 0)
470            return NULL;
471    }
472
473    return PyLong_FromSsize_t(size);
474}
475
476static PyObject *
477bytesio_iternext(bytesio *self)
478{
479    char *next;
480    Py_ssize_t n;
481
482    CHECK_CLOSED(self);
483
484    n = get_line(self, &next);
485
486    if (!next || n == 0)
487        return NULL;
488
489    return PyBytes_FromStringAndSize(next, n);
490}
491
492PyDoc_STRVAR(seek_doc,
493"seek(pos[, whence]) -> int.  Change stream position.\n"
494"\n"
495"Seek to byte offset pos relative to position indicated by whence:\n"
496"     0  Start of stream (the default).  pos should be >= 0;\n"
497"     1  Current position - pos may be negative;\n"
498"     2  End of stream - pos usually negative.\n"
499"Returns the new absolute position.");
500
501static PyObject *
502bytesio_seek(bytesio *self, PyObject *args)
503{
504    PyObject *posobj;
505    Py_ssize_t pos;
506    int mode = 0;
507
508    CHECK_CLOSED(self);
509
510    if (!PyArg_ParseTuple(args, "O|i:seek", &posobj, &mode))
511        return NULL;
512
513    pos = PyNumber_AsSsize_t(posobj, PyExc_OverflowError);
514    if (pos == -1 && PyErr_Occurred())
515        return NULL;
516
517    if (pos < 0 && mode == 0) {
518        PyErr_Format(PyExc_ValueError,
519                     "negative seek value %zd", pos);
520        return NULL;
521    }
522
523    /* mode 0: offset relative to beginning of the string.
524       mode 1: offset relative to current position.
525       mode 2: offset relative the end of the string. */
526    if (mode == 1) {
527        if (pos > PY_SSIZE_T_MAX - self->pos) {
528            PyErr_SetString(PyExc_OverflowError,
529                            "new position too large");
530            return NULL;
531        }
532        pos += self->pos;
533    }
534    else if (mode == 2) {
535        if (pos > PY_SSIZE_T_MAX - self->string_size) {
536            PyErr_SetString(PyExc_OverflowError,
537                            "new position too large");
538            return NULL;
539        }
540        pos += self->string_size;
541    }
542    else if (mode != 0) {
543        PyErr_Format(PyExc_ValueError,
544                     "invalid whence (%i, should be 0, 1 or 2)", mode);
545        return NULL;
546    }
547
548    if (pos < 0)
549        pos = 0;
550    self->pos = pos;
551
552    return PyLong_FromSsize_t(self->pos);
553}
554
555PyDoc_STRVAR(write_doc,
556"write(bytes) -> int.  Write bytes to file.\n"
557"\n"
558"Return the number of bytes written.");
559
560static PyObject *
561bytesio_write(bytesio *self, PyObject *obj)
562{
563    Py_ssize_t n = 0;
564    Py_buffer buf;
565    PyObject *result = NULL;
566
567    CHECK_CLOSED(self);
568
569    if (PyObject_GetBuffer(obj, &buf, PyBUF_CONTIG_RO) < 0)
570        return NULL;
571
572    if (buf.len != 0)
573        n = write_bytes(self, buf.buf, buf.len);
574    if (n >= 0)
575        result = PyLong_FromSsize_t(n);
576
577    PyBuffer_Release(&buf);
578    return result;
579}
580
581PyDoc_STRVAR(writelines_doc,
582"writelines(sequence_of_strings) -> None.  Write strings to the file.\n"
583"\n"
584"Note that newlines are not added.  The sequence can be any iterable\n"
585"object producing strings. This is equivalent to calling write() for\n"
586"each string.");
587
588static PyObject *
589bytesio_writelines(bytesio *self, PyObject *v)
590{
591    PyObject *it, *item;
592    PyObject *ret;
593
594    CHECK_CLOSED(self);
595
596    it = PyObject_GetIter(v);
597    if (it == NULL)
598        return NULL;
599
600    while ((item = PyIter_Next(it)) != NULL) {
601        ret = bytesio_write(self, item);
602        Py_DECREF(item);
603        if (ret == NULL) {
604            Py_DECREF(it);
605            return NULL;
606        }
607        Py_DECREF(ret);
608    }
609    Py_DECREF(it);
610
611    /* See if PyIter_Next failed */
612    if (PyErr_Occurred())
613        return NULL;
614
615    Py_RETURN_NONE;
616}
617
618PyDoc_STRVAR(close_doc,
619"close() -> None.  Disable all I/O operations.");
620
621static PyObject *
622bytesio_close(bytesio *self)
623{
624    if (self->buf != NULL) {
625        PyMem_Free(self->buf);
626        self->buf = NULL;
627    }
628    Py_RETURN_NONE;
629}
630
631/* Pickling support.
632
633   Note that only pickle protocol 2 and onward are supported since we use
634   extended __reduce__ API of PEP 307 to make BytesIO instances picklable.
635
636   Providing support for protocol < 2 would require the __reduce_ex__ method
637   which is notably long-winded when defined properly.
638
639   For BytesIO, the implementation would similar to one coded for
640   object.__reduce_ex__, but slightly less general. To be more specific, we
641   could call bytesio_getstate directly and avoid checking for the presence of
642   a fallback __reduce__ method. However, we would still need a __newobj__
643   function to use the efficient instance representation of PEP 307.
644 */
645
646static PyObject *
647bytesio_getstate(bytesio *self)
648{
649    PyObject *initvalue = bytesio_getvalue(self);
650    PyObject *dict;
651    PyObject *state;
652
653    if (initvalue == NULL)
654        return NULL;
655    if (self->dict == NULL) {
656        Py_INCREF(Py_None);
657        dict = Py_None;
658    }
659    else {
660        dict = PyDict_Copy(self->dict);
661        if (dict == NULL)
662            return NULL;
663    }
664
665    state = Py_BuildValue("(OnN)", initvalue, self->pos, dict);
666    Py_DECREF(initvalue);
667    return state;
668}
669
670static PyObject *
671bytesio_setstate(bytesio *self, PyObject *state)
672{
673    PyObject *result;
674    PyObject *position_obj;
675    PyObject *dict;
676    Py_ssize_t pos;
677
678    assert(state != NULL);
679
680    /* We allow the state tuple to be longer than 3, because we may need
681       someday to extend the object's state without breaking
682       backward-compatibility. */
683    if (!PyTuple_Check(state) || Py_SIZE(state) < 3) {
684        PyErr_Format(PyExc_TypeError,
685                     "%.200s.__setstate__ argument should be 3-tuple, got %.200s",
686                     Py_TYPE(self)->tp_name, Py_TYPE(state)->tp_name);
687        return NULL;
688    }
689    /* Reset the object to its default state. This is only needed to handle
690       the case of repeated calls to __setstate__. */
691    self->string_size = 0;
692    self->pos = 0;
693
694    /* Set the value of the internal buffer. If state[0] does not support the
695       buffer protocol, bytesio_write will raise the appropriate TypeError. */
696    result = bytesio_write(self, PyTuple_GET_ITEM(state, 0));
697    if (result == NULL)
698        return NULL;
699    Py_DECREF(result);
700
701    /* Set carefully the position value. Alternatively, we could use the seek
702       method instead of modifying self->pos directly to better protect the
703       object internal state against errneous (or malicious) inputs. */
704    position_obj = PyTuple_GET_ITEM(state, 1);
705    if (!PyIndex_Check(position_obj)) {
706        PyErr_Format(PyExc_TypeError,
707                     "second item of state must be an integer, not %.200s",
708                     Py_TYPE(position_obj)->tp_name);
709        return NULL;
710    }
711    pos = PyNumber_AsSsize_t(position_obj, PyExc_OverflowError);
712    if (pos == -1 && PyErr_Occurred())
713        return NULL;
714    if (pos < 0) {
715        PyErr_SetString(PyExc_ValueError,
716                        "position value cannot be negative");
717        return NULL;
718    }
719    self->pos = pos;
720
721    /* Set the dictionary of the instance variables. */
722    dict = PyTuple_GET_ITEM(state, 2);
723    if (dict != Py_None) {
724        if (!PyDict_Check(dict)) {
725            PyErr_Format(PyExc_TypeError,
726                         "third item of state should be a dict, got a %.200s",
727                         Py_TYPE(dict)->tp_name);
728            return NULL;
729        }
730        if (self->dict) {
731            /* Alternatively, we could replace the internal dictionary
732               completely. However, it seems more practical to just update it. */
733            if (PyDict_Update(self->dict, dict) < 0)
734                return NULL;
735        }
736        else {
737            Py_INCREF(dict);
738            self->dict = dict;
739        }
740    }
741
742    Py_RETURN_NONE;
743}
744
745static void
746bytesio_dealloc(bytesio *self)
747{
748    _PyObject_GC_UNTRACK(self);
749    if (self->buf != NULL) {
750        PyMem_Free(self->buf);
751        self->buf = NULL;
752    }
753    Py_CLEAR(self->dict);
754    if (self->weakreflist != NULL)
755        PyObject_ClearWeakRefs((PyObject *) self);
756    Py_TYPE(self)->tp_free(self);
757}
758
759static PyObject *
760bytesio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
761{
762    bytesio *self;
763
764    assert(type != NULL && type->tp_alloc != NULL);
765    self = (bytesio *)type->tp_alloc(type, 0);
766    if (self == NULL)
767        return NULL;
768
769    /* tp_alloc initializes all the fields to zero. So we don't have to
770       initialize them here. */
771
772    self->buf = (char *)PyMem_Malloc(0);
773    if (self->buf == NULL) {
774        Py_DECREF(self);
775        return PyErr_NoMemory();
776    }
777
778    return (PyObject *)self;
779}
780
781static int
782bytesio_init(bytesio *self, PyObject *args, PyObject *kwds)
783{
784    char *kwlist[] = {"initial_bytes", NULL};
785    PyObject *initvalue = NULL;
786
787    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:BytesIO", kwlist,
788                                     &initvalue))
789        return -1;
790
791    /* In case, __init__ is called multiple times. */
792    self->string_size = 0;
793    self->pos = 0;
794
795    if (initvalue && initvalue != Py_None) {
796        PyObject *res;
797        res = bytesio_write(self, initvalue);
798        if (res == NULL)
799            return -1;
800        Py_DECREF(res);
801        self->pos = 0;
802    }
803
804    return 0;
805}
806
807static PyObject *
808bytesio_sizeof(bytesio *self, void *unused)
809{
810    Py_ssize_t res;
811
812    res = _PyObject_SIZE(Py_TYPE(self));
813    if (self->buf)
814        res += self->buf_size;
815    return PyLong_FromSsize_t(res);
816}
817
818static int
819bytesio_traverse(bytesio *self, visitproc visit, void *arg)
820{
821    Py_VISIT(self->dict);
822    return 0;
823}
824
825static int
826bytesio_clear(bytesio *self)
827{
828    Py_CLEAR(self->dict);
829    return 0;
830}
831
832
833static PyGetSetDef bytesio_getsetlist[] = {
834    {"closed",  (getter)bytesio_get_closed, NULL,
835     "True if the file is closed."},
836    {NULL},            /* sentinel */
837};
838
839static struct PyMethodDef bytesio_methods[] = {
840    {"readable",   (PyCFunction)return_not_closed,  METH_NOARGS, readable_doc},
841    {"seekable",   (PyCFunction)return_not_closed,  METH_NOARGS, seekable_doc},
842    {"writable",   (PyCFunction)return_not_closed,  METH_NOARGS, writable_doc},
843    {"close",      (PyCFunction)bytesio_close,      METH_NOARGS, close_doc},
844    {"flush",      (PyCFunction)bytesio_flush,      METH_NOARGS, flush_doc},
845    {"isatty",     (PyCFunction)bytesio_isatty,     METH_NOARGS, isatty_doc},
846    {"tell",       (PyCFunction)bytesio_tell,       METH_NOARGS, tell_doc},
847    {"write",      (PyCFunction)bytesio_write,      METH_O, write_doc},
848    {"writelines", (PyCFunction)bytesio_writelines, METH_O, writelines_doc},
849    {"read1",      (PyCFunction)bytesio_read1,      METH_O, read1_doc},
850    {"readinto",   (PyCFunction)bytesio_readinto,   METH_VARARGS, readinto_doc},
851    {"readline",   (PyCFunction)bytesio_readline,   METH_VARARGS, readline_doc},
852    {"readlines",  (PyCFunction)bytesio_readlines,  METH_VARARGS, readlines_doc},
853    {"read",       (PyCFunction)bytesio_read,       METH_VARARGS, read_doc},
854    {"getvalue",   (PyCFunction)bytesio_getvalue,   METH_NOARGS,  getval_doc},
855    {"seek",       (PyCFunction)bytesio_seek,       METH_VARARGS, seek_doc},
856    {"truncate",   (PyCFunction)bytesio_truncate,   METH_VARARGS, truncate_doc},
857    {"__getstate__",  (PyCFunction)bytesio_getstate,  METH_NOARGS, NULL},
858    {"__setstate__",  (PyCFunction)bytesio_setstate,  METH_O, NULL},
859    {"__sizeof__", (PyCFunction)bytesio_sizeof,     METH_NOARGS, NULL},
860    {NULL, NULL}        /* sentinel */
861};
862
863PyDoc_STRVAR(bytesio_doc,
864"BytesIO([buffer]) -> object\n"
865"\n"
866"Create a buffered I/O implementation using an in-memory bytes\n"
867"buffer, ready for reading and writing.");
868
869PyTypeObject PyBytesIO_Type = {
870    PyVarObject_HEAD_INIT(NULL, 0)
871    "_io.BytesIO",                             /*tp_name*/
872    sizeof(bytesio),                     /*tp_basicsize*/
873    0,                                         /*tp_itemsize*/
874    (destructor)bytesio_dealloc,               /*tp_dealloc*/
875    0,                                         /*tp_print*/
876    0,                                         /*tp_getattr*/
877    0,                                         /*tp_setattr*/
878    0,                                         /*tp_reserved*/
879    0,                                         /*tp_repr*/
880    0,                                         /*tp_as_number*/
881    0,                                         /*tp_as_sequence*/
882    0,                                         /*tp_as_mapping*/
883    0,                                         /*tp_hash*/
884    0,                                         /*tp_call*/
885    0,                                         /*tp_str*/
886    0,                                         /*tp_getattro*/
887    0,                                         /*tp_setattro*/
888    0,                                         /*tp_as_buffer*/
889    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
890    Py_TPFLAGS_HAVE_GC,                        /*tp_flags*/
891    bytesio_doc,                               /*tp_doc*/
892    (traverseproc)bytesio_traverse,            /*tp_traverse*/
893    (inquiry)bytesio_clear,                    /*tp_clear*/
894    0,                                         /*tp_richcompare*/
895    offsetof(bytesio, weakreflist),      /*tp_weaklistoffset*/
896    PyObject_SelfIter,                         /*tp_iter*/
897    (iternextfunc)bytesio_iternext,            /*tp_iternext*/
898    bytesio_methods,                           /*tp_methods*/
899    0,                                         /*tp_members*/
900    bytesio_getsetlist,                        /*tp_getset*/
901    0,                                         /*tp_base*/
902    0,                                         /*tp_dict*/
903    0,                                         /*tp_descr_get*/
904    0,                                         /*tp_descr_set*/
905    offsetof(bytesio, dict),             /*tp_dictoffset*/
906    (initproc)bytesio_init,                    /*tp_init*/
907    0,                                         /*tp_alloc*/
908    bytesio_new,                               /*tp_new*/
909};
910