1#include "Python.h"
2#include "structmember.h"       /* for offsetof() */
3#include "_iomodule.h"
4
5/*[clinic input]
6module _io
7class _io.BytesIO "bytesio *" "&PyBytesIO_Type"
8[clinic start generated code]*/
9/*[clinic end generated code: output=da39a3ee5e6b4b0d input=7f50ec034f5c0b26]*/
10
11typedef struct {
12    PyObject_HEAD
13    PyObject *buf;
14    Py_ssize_t pos;
15    Py_ssize_t string_size;
16    PyObject *dict;
17    PyObject *weakreflist;
18    Py_ssize_t exports;
19} bytesio;
20
21typedef struct {
22    PyObject_HEAD
23    bytesio *source;
24} bytesiobuf;
25
26/* The bytesio object can be in three states:
27  * Py_REFCNT(buf) == 1, exports == 0.
28  * Py_REFCNT(buf) > 1.  exports == 0,
29    first modification or export causes the internal buffer copying.
30  * exports > 0.  Py_REFCNT(buf) == 1, any modifications are forbidden.
31*/
32
33#define CHECK_CLOSED(self)                                  \
34    if ((self)->buf == NULL) {                              \
35        PyErr_SetString(PyExc_ValueError,                   \
36                        "I/O operation on closed file.");   \
37        return NULL;                                        \
38    }
39
40#define CHECK_EXPORTS(self) \
41    if ((self)->exports > 0) { \
42        PyErr_SetString(PyExc_BufferError, \
43                        "Existing exports of data: object cannot be re-sized"); \
44        return NULL; \
45    }
46
47#define SHARED_BUF(self) (Py_REFCNT((self)->buf) > 1)
48
49
50/* Internal routine to get a line from the buffer of a BytesIO
51   object. Returns the length between the current position to the
52   next newline character. */
53static Py_ssize_t
54scan_eol(bytesio *self, Py_ssize_t len)
55{
56    const char *start, *n;
57    Py_ssize_t maxlen;
58
59    assert(self->buf != NULL);
60    assert(self->pos >= 0);
61
62    if (self->pos >= self->string_size)
63        return 0;
64
65    /* Move to the end of the line, up to the end of the string, s. */
66    maxlen = self->string_size - self->pos;
67    if (len < 0 || len > maxlen)
68        len = maxlen;
69
70    if (len) {
71        start = PyBytes_AS_STRING(self->buf) + self->pos;
72        n = memchr(start, '\n', len);
73        if (n)
74            /* Get the length from the current position to the end of
75               the line. */
76            len = n - start + 1;
77    }
78    assert(len >= 0);
79    assert(self->pos < PY_SSIZE_T_MAX - len);
80
81    return len;
82}
83
84/* Internal routine for detaching the shared buffer of BytesIO objects.
85   The caller should ensure that the 'size' argument is non-negative and
86   not lesser than self->string_size.  Returns 0 on success, -1 otherwise. */
87static int
88unshare_buffer(bytesio *self, size_t size)
89{
90    PyObject *new_buf;
91    assert(SHARED_BUF(self));
92    assert(self->exports == 0);
93    assert(size >= (size_t)self->string_size);
94    new_buf = PyBytes_FromStringAndSize(NULL, size);
95    if (new_buf == NULL)
96        return -1;
97    memcpy(PyBytes_AS_STRING(new_buf), PyBytes_AS_STRING(self->buf),
98           self->string_size);
99    Py_SETREF(self->buf, new_buf);
100    return 0;
101}
102
103/* Internal routine for changing the size of the buffer of BytesIO objects.
104   The caller should ensure that the 'size' argument is non-negative.  Returns
105   0 on success, -1 otherwise. */
106static int
107resize_buffer(bytesio *self, size_t size)
108{
109    /* Here, unsigned types are used to avoid dealing with signed integer
110       overflow, which is undefined in C. */
111    size_t alloc = PyBytes_GET_SIZE(self->buf);
112
113    assert(self->buf != NULL);
114
115    /* For simplicity, stay in the range of the signed type. Anyway, Python
116       doesn't allow strings to be longer than this. */
117    if (size > PY_SSIZE_T_MAX)
118        goto overflow;
119
120    if (size < alloc / 2) {
121        /* Major downsize; resize down to exact size. */
122        alloc = size + 1;
123    }
124    else if (size < alloc) {
125        /* Within allocated size; quick exit */
126        return 0;
127    }
128    else if (size <= alloc * 1.125) {
129        /* Moderate upsize; overallocate similar to list_resize() */
130        alloc = size + (size >> 3) + (size < 9 ? 3 : 6);
131    }
132    else {
133        /* Major upsize; resize up to exact size */
134        alloc = size + 1;
135    }
136
137    if (alloc > ((size_t)-1) / sizeof(char))
138        goto overflow;
139
140    if (SHARED_BUF(self)) {
141        if (unshare_buffer(self, alloc) < 0)
142            return -1;
143    }
144    else {
145        if (_PyBytes_Resize(&self->buf, alloc) < 0)
146            return -1;
147    }
148
149    return 0;
150
151  overflow:
152    PyErr_SetString(PyExc_OverflowError,
153                    "new buffer size too large");
154    return -1;
155}
156
157/* Internal routine for writing a string of bytes to the buffer of a BytesIO
158   object. Returns the number of bytes written, or -1 on error. */
159static Py_ssize_t
160write_bytes(bytesio *self, const char *bytes, Py_ssize_t len)
161{
162    size_t endpos;
163    assert(self->buf != NULL);
164    assert(self->pos >= 0);
165    assert(len >= 0);
166
167    endpos = (size_t)self->pos + len;
168    if (endpos > (size_t)PyBytes_GET_SIZE(self->buf)) {
169        if (resize_buffer(self, endpos) < 0)
170            return -1;
171    }
172    else if (SHARED_BUF(self)) {
173        if (unshare_buffer(self, Py_MAX(endpos, (size_t)self->string_size)) < 0)
174            return -1;
175    }
176
177    if (self->pos > self->string_size) {
178        /* In case of overseek, pad with null bytes the buffer region between
179           the end of stream and the current position.
180
181          0   lo      string_size                           hi
182          |   |<---used--->|<----------available----------->|
183          |   |            <--to pad-->|<---to write--->    |
184          0   buf                   position
185        */
186        memset(PyBytes_AS_STRING(self->buf) + self->string_size, '\0',
187               (self->pos - self->string_size) * sizeof(char));
188    }
189
190    /* Copy the data to the internal buffer, overwriting some of the existing
191       data if self->pos < self->string_size. */
192    memcpy(PyBytes_AS_STRING(self->buf) + self->pos, bytes, len);
193    self->pos = endpos;
194
195    /* Set the new length of the internal string if it has changed. */
196    if ((size_t)self->string_size < endpos) {
197        self->string_size = endpos;
198    }
199
200    return len;
201}
202
203static PyObject *
204bytesio_get_closed(bytesio *self)
205{
206    if (self->buf == NULL) {
207        Py_RETURN_TRUE;
208    }
209    else {
210        Py_RETURN_FALSE;
211    }
212}
213
214/*[clinic input]
215_io.BytesIO.readable
216
217Returns True if the IO object can be read.
218[clinic start generated code]*/
219
220static PyObject *
221_io_BytesIO_readable_impl(bytesio *self)
222/*[clinic end generated code: output=4e93822ad5b62263 input=96c5d0cccfb29f5c]*/
223{
224    CHECK_CLOSED(self);
225    Py_RETURN_TRUE;
226}
227
228/*[clinic input]
229_io.BytesIO.writable
230
231Returns True if the IO object can be written.
232[clinic start generated code]*/
233
234static PyObject *
235_io_BytesIO_writable_impl(bytesio *self)
236/*[clinic end generated code: output=64ff6a254b1150b8 input=700eed808277560a]*/
237{
238    CHECK_CLOSED(self);
239    Py_RETURN_TRUE;
240}
241
242/*[clinic input]
243_io.BytesIO.seekable
244
245Returns True if the IO object can be seeked.
246[clinic start generated code]*/
247
248static PyObject *
249_io_BytesIO_seekable_impl(bytesio *self)
250/*[clinic end generated code: output=6b417f46dcc09b56 input=9421f65627a344dd]*/
251{
252    CHECK_CLOSED(self);
253    Py_RETURN_TRUE;
254}
255
256/*[clinic input]
257_io.BytesIO.flush
258
259Does nothing.
260[clinic start generated code]*/
261
262static PyObject *
263_io_BytesIO_flush_impl(bytesio *self)
264/*[clinic end generated code: output=187e3d781ca134a0 input=561ea490be4581a7]*/
265{
266    CHECK_CLOSED(self);
267    Py_RETURN_NONE;
268}
269
270/*[clinic input]
271_io.BytesIO.getbuffer
272
273Get a read-write view over the contents of the BytesIO object.
274[clinic start generated code]*/
275
276static PyObject *
277_io_BytesIO_getbuffer_impl(bytesio *self)
278/*[clinic end generated code: output=72cd7c6e13aa09ed input=8f738ef615865176]*/
279{
280    PyTypeObject *type = &_PyBytesIOBuffer_Type;
281    bytesiobuf *buf;
282    PyObject *view;
283
284    CHECK_CLOSED(self);
285
286    buf = (bytesiobuf *) type->tp_alloc(type, 0);
287    if (buf == NULL)
288        return NULL;
289    Py_INCREF(self);
290    buf->source = self;
291    view = PyMemoryView_FromObject((PyObject *) buf);
292    Py_DECREF(buf);
293    return view;
294}
295
296/*[clinic input]
297_io.BytesIO.getvalue
298
299Retrieve the entire contents of the BytesIO object.
300[clinic start generated code]*/
301
302static PyObject *
303_io_BytesIO_getvalue_impl(bytesio *self)
304/*[clinic end generated code: output=b3f6a3233c8fd628 input=4b403ac0af3973ed]*/
305{
306    CHECK_CLOSED(self);
307    if (self->string_size <= 1 || self->exports > 0)
308        return PyBytes_FromStringAndSize(PyBytes_AS_STRING(self->buf),
309                                         self->string_size);
310
311    if (self->string_size != PyBytes_GET_SIZE(self->buf)) {
312        if (SHARED_BUF(self)) {
313            if (unshare_buffer(self, self->string_size) < 0)
314                return NULL;
315        }
316        else {
317            if (_PyBytes_Resize(&self->buf, self->string_size) < 0)
318                return NULL;
319        }
320    }
321    Py_INCREF(self->buf);
322    return self->buf;
323}
324
325/*[clinic input]
326_io.BytesIO.isatty
327
328Always returns False.
329
330BytesIO objects are not connected to a TTY-like device.
331[clinic start generated code]*/
332
333static PyObject *
334_io_BytesIO_isatty_impl(bytesio *self)
335/*[clinic end generated code: output=df67712e669f6c8f input=6f97f0985d13f827]*/
336{
337    CHECK_CLOSED(self);
338    Py_RETURN_FALSE;
339}
340
341/*[clinic input]
342_io.BytesIO.tell
343
344Current file position, an integer.
345[clinic start generated code]*/
346
347static PyObject *
348_io_BytesIO_tell_impl(bytesio *self)
349/*[clinic end generated code: output=b54b0f93cd0e5e1d input=b106adf099cb3657]*/
350{
351    CHECK_CLOSED(self);
352    return PyLong_FromSsize_t(self->pos);
353}
354
355static PyObject *
356read_bytes(bytesio *self, Py_ssize_t size)
357{
358    char *output;
359
360    assert(self->buf != NULL);
361    assert(size <= self->string_size);
362    if (size > 1 &&
363        self->pos == 0 && size == PyBytes_GET_SIZE(self->buf) &&
364        self->exports == 0) {
365        self->pos += size;
366        Py_INCREF(self->buf);
367        return self->buf;
368    }
369
370    output = PyBytes_AS_STRING(self->buf) + self->pos;
371    self->pos += size;
372    return PyBytes_FromStringAndSize(output, size);
373}
374
375/*[clinic input]
376_io.BytesIO.read
377    size as arg: object = None
378    /
379
380Read at most size bytes, returned as a bytes object.
381
382If the size argument is negative, read until EOF is reached.
383Return an empty bytes object at EOF.
384[clinic start generated code]*/
385
386static PyObject *
387_io_BytesIO_read_impl(bytesio *self, PyObject *arg)
388/*[clinic end generated code: output=85dacb535c1e1781 input=cc7ba4a797bb1555]*/
389{
390    Py_ssize_t size, n;
391
392    CHECK_CLOSED(self);
393
394    if (PyLong_Check(arg)) {
395        size = PyLong_AsSsize_t(arg);
396        if (size == -1 && PyErr_Occurred())
397            return NULL;
398    }
399    else if (arg == Py_None) {
400        /* Read until EOF is reached, by default. */
401        size = -1;
402    }
403    else {
404        PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
405                     Py_TYPE(arg)->tp_name);
406        return NULL;
407    }
408
409    /* adjust invalid sizes */
410    n = self->string_size - self->pos;
411    if (size < 0 || size > n) {
412        size = n;
413        if (size < 0)
414            size = 0;
415    }
416
417    return read_bytes(self, size);
418}
419
420
421/*[clinic input]
422_io.BytesIO.read1
423    size: object
424    /
425
426Read at most size bytes, returned as a bytes object.
427
428If the size argument is negative or omitted, read until EOF is reached.
429Return an empty bytes object at EOF.
430[clinic start generated code]*/
431
432static PyObject *
433_io_BytesIO_read1(bytesio *self, PyObject *size)
434/*[clinic end generated code: output=16021f5d0ac3d4e2 input=d4f40bb8f2f99418]*/
435{
436    return _io_BytesIO_read_impl(self, size);
437}
438
439/*[clinic input]
440_io.BytesIO.readline
441    size as arg: object = None
442    /
443
444Next line from the file, as a bytes object.
445
446Retain newline.  A non-negative size argument limits the maximum
447number of bytes to return (an incomplete line may be returned then).
448Return an empty bytes object at EOF.
449[clinic start generated code]*/
450
451static PyObject *
452_io_BytesIO_readline_impl(bytesio *self, PyObject *arg)
453/*[clinic end generated code: output=1c2115534a4f9276 input=ca31f06de6eab257]*/
454{
455    Py_ssize_t size, n;
456
457    CHECK_CLOSED(self);
458
459    if (PyLong_Check(arg)) {
460        size = PyLong_AsSsize_t(arg);
461        if (size == -1 && PyErr_Occurred())
462            return NULL;
463    }
464    else if (arg == Py_None) {
465        /* No size limit, by default. */
466        size = -1;
467    }
468    else {
469        PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
470                     Py_TYPE(arg)->tp_name);
471        return NULL;
472    }
473
474    n = scan_eol(self, size);
475
476    return read_bytes(self, n);
477}
478
479/*[clinic input]
480_io.BytesIO.readlines
481    size as arg: object = None
482    /
483
484List of bytes objects, each a line from the file.
485
486Call readline() repeatedly and return a list of the lines so read.
487The optional size argument, if given, is an approximate bound on the
488total number of bytes in the lines returned.
489[clinic start generated code]*/
490
491static PyObject *
492_io_BytesIO_readlines_impl(bytesio *self, PyObject *arg)
493/*[clinic end generated code: output=09b8e34c880808ff input=691aa1314f2c2a87]*/
494{
495    Py_ssize_t maxsize, size, n;
496    PyObject *result, *line;
497    char *output;
498
499    CHECK_CLOSED(self);
500
501    if (PyLong_Check(arg)) {
502        maxsize = PyLong_AsSsize_t(arg);
503        if (maxsize == -1 && PyErr_Occurred())
504            return NULL;
505    }
506    else if (arg == Py_None) {
507        /* No size limit, by default. */
508        maxsize = -1;
509    }
510    else {
511        PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
512                     Py_TYPE(arg)->tp_name);
513        return NULL;
514    }
515
516    size = 0;
517    result = PyList_New(0);
518    if (!result)
519        return NULL;
520
521    output = PyBytes_AS_STRING(self->buf) + self->pos;
522    while ((n = scan_eol(self, -1)) != 0) {
523        self->pos += n;
524        line = PyBytes_FromStringAndSize(output, n);
525        if (!line)
526            goto on_error;
527        if (PyList_Append(result, line) == -1) {
528            Py_DECREF(line);
529            goto on_error;
530        }
531        Py_DECREF(line);
532        size += n;
533        if (maxsize > 0 && size >= maxsize)
534            break;
535        output += n;
536    }
537    return result;
538
539  on_error:
540    Py_DECREF(result);
541    return NULL;
542}
543
544/*[clinic input]
545_io.BytesIO.readinto
546    buffer: Py_buffer(accept={rwbuffer})
547    /
548
549Read bytes into buffer.
550
551Returns number of bytes read (0 for EOF), or None if the object
552is set not to block and has no data to read.
553[clinic start generated code]*/
554
555static PyObject *
556_io_BytesIO_readinto_impl(bytesio *self, Py_buffer *buffer)
557/*[clinic end generated code: output=a5d407217dcf0639 input=1424d0fdce857919]*/
558{
559    Py_ssize_t len, n;
560
561    CHECK_CLOSED(self);
562
563    /* adjust invalid sizes */
564    len = buffer->len;
565    n = self->string_size - self->pos;
566    if (len > n) {
567        len = n;
568        if (len < 0)
569            len = 0;
570    }
571
572    memcpy(buffer->buf, PyBytes_AS_STRING(self->buf) + self->pos, len);
573    assert(self->pos + len < PY_SSIZE_T_MAX);
574    assert(len >= 0);
575    self->pos += len;
576
577    return PyLong_FromSsize_t(len);
578}
579
580/*[clinic input]
581_io.BytesIO.truncate
582    size as arg: object = None
583    /
584
585Truncate the file to at most size bytes.
586
587Size defaults to the current file position, as returned by tell().
588The current file position is unchanged.  Returns the new size.
589[clinic start generated code]*/
590
591static PyObject *
592_io_BytesIO_truncate_impl(bytesio *self, PyObject *arg)
593/*[clinic end generated code: output=81e6be60e67ddd66 input=11ed1966835462ba]*/
594{
595    Py_ssize_t size;
596
597    CHECK_CLOSED(self);
598    CHECK_EXPORTS(self);
599
600    if (PyLong_Check(arg)) {
601        size = PyLong_AsSsize_t(arg);
602        if (size == -1 && PyErr_Occurred())
603            return NULL;
604    }
605    else if (arg == Py_None) {
606        /* Truncate to current position if no argument is passed. */
607        size = self->pos;
608    }
609    else {
610        PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
611                     Py_TYPE(arg)->tp_name);
612        return NULL;
613    }
614
615    if (size < 0) {
616        PyErr_Format(PyExc_ValueError,
617                     "negative size value %zd", size);
618        return NULL;
619    }
620
621    if (size < self->string_size) {
622        self->string_size = size;
623        if (resize_buffer(self, size) < 0)
624            return NULL;
625    }
626
627    return PyLong_FromSsize_t(size);
628}
629
630static PyObject *
631bytesio_iternext(bytesio *self)
632{
633    Py_ssize_t n;
634
635    CHECK_CLOSED(self);
636
637    n = scan_eol(self, -1);
638
639    if (n == 0)
640        return NULL;
641
642    return read_bytes(self, n);
643}
644
645/*[clinic input]
646_io.BytesIO.seek
647    pos: Py_ssize_t
648    whence: int = 0
649    /
650
651Change stream position.
652
653Seek to byte offset pos relative to position indicated by whence:
654     0  Start of stream (the default).  pos should be >= 0;
655     1  Current position - pos may be negative;
656     2  End of stream - pos usually negative.
657Returns the new absolute position.
658[clinic start generated code]*/
659
660static PyObject *
661_io_BytesIO_seek_impl(bytesio *self, Py_ssize_t pos, int whence)
662/*[clinic end generated code: output=c26204a68e9190e4 input=1e875e6ebc652948]*/
663{
664    CHECK_CLOSED(self);
665
666    if (pos < 0 && whence == 0) {
667        PyErr_Format(PyExc_ValueError,
668                     "negative seek value %zd", pos);
669        return NULL;
670    }
671
672    /* whence = 0: offset relative to beginning of the string.
673       whence = 1: offset relative to current position.
674       whence = 2: offset relative the end of the string. */
675    if (whence == 1) {
676        if (pos > PY_SSIZE_T_MAX - self->pos) {
677            PyErr_SetString(PyExc_OverflowError,
678                            "new position too large");
679            return NULL;
680        }
681        pos += self->pos;
682    }
683    else if (whence == 2) {
684        if (pos > PY_SSIZE_T_MAX - self->string_size) {
685            PyErr_SetString(PyExc_OverflowError,
686                            "new position too large");
687            return NULL;
688        }
689        pos += self->string_size;
690    }
691    else if (whence != 0) {
692        PyErr_Format(PyExc_ValueError,
693                     "invalid whence (%i, should be 0, 1 or 2)", whence);
694        return NULL;
695    }
696
697    if (pos < 0)
698        pos = 0;
699    self->pos = pos;
700
701    return PyLong_FromSsize_t(self->pos);
702}
703
704/*[clinic input]
705_io.BytesIO.write
706    b: object
707    /
708
709Write bytes to file.
710
711Return the number of bytes written.
712[clinic start generated code]*/
713
714static PyObject *
715_io_BytesIO_write(bytesio *self, PyObject *b)
716/*[clinic end generated code: output=53316d99800a0b95 input=f5ec7c8c64ed720a]*/
717{
718    Py_ssize_t n = 0;
719    Py_buffer buf;
720
721    CHECK_CLOSED(self);
722    CHECK_EXPORTS(self);
723
724    if (PyObject_GetBuffer(b, &buf, PyBUF_CONTIG_RO) < 0)
725        return NULL;
726
727    if (buf.len != 0)
728        n = write_bytes(self, buf.buf, buf.len);
729
730    PyBuffer_Release(&buf);
731    return n >= 0 ? PyLong_FromSsize_t(n) : NULL;
732}
733
734/*[clinic input]
735_io.BytesIO.writelines
736    lines: object
737    /
738
739Write lines to the file.
740
741Note that newlines are not added.  lines can be any iterable object
742producing bytes-like objects. This is equivalent to calling write() for
743each element.
744[clinic start generated code]*/
745
746static PyObject *
747_io_BytesIO_writelines(bytesio *self, PyObject *lines)
748/*[clinic end generated code: output=7f33aa3271c91752 input=e972539176fc8fc1]*/
749{
750    PyObject *it, *item;
751    PyObject *ret;
752
753    CHECK_CLOSED(self);
754
755    it = PyObject_GetIter(lines);
756    if (it == NULL)
757        return NULL;
758
759    while ((item = PyIter_Next(it)) != NULL) {
760        ret = _io_BytesIO_write(self, item);
761        Py_DECREF(item);
762        if (ret == NULL) {
763            Py_DECREF(it);
764            return NULL;
765        }
766        Py_DECREF(ret);
767    }
768    Py_DECREF(it);
769
770    /* See if PyIter_Next failed */
771    if (PyErr_Occurred())
772        return NULL;
773
774    Py_RETURN_NONE;
775}
776
777/*[clinic input]
778_io.BytesIO.close
779
780Disable all I/O operations.
781[clinic start generated code]*/
782
783static PyObject *
784_io_BytesIO_close_impl(bytesio *self)
785/*[clinic end generated code: output=1471bb9411af84a0 input=37e1f55556e61f60]*/
786{
787    CHECK_EXPORTS(self);
788    Py_CLEAR(self->buf);
789    Py_RETURN_NONE;
790}
791
792/* Pickling support.
793
794   Note that only pickle protocol 2 and onward are supported since we use
795   extended __reduce__ API of PEP 307 to make BytesIO instances picklable.
796
797   Providing support for protocol < 2 would require the __reduce_ex__ method
798   which is notably long-winded when defined properly.
799
800   For BytesIO, the implementation would similar to one coded for
801   object.__reduce_ex__, but slightly less general. To be more specific, we
802   could call bytesio_getstate directly and avoid checking for the presence of
803   a fallback __reduce__ method. However, we would still need a __newobj__
804   function to use the efficient instance representation of PEP 307.
805 */
806
807static PyObject *
808bytesio_getstate(bytesio *self)
809{
810    PyObject *initvalue = _io_BytesIO_getvalue_impl(self);
811    PyObject *dict;
812    PyObject *state;
813
814    if (initvalue == NULL)
815        return NULL;
816    if (self->dict == NULL) {
817        Py_INCREF(Py_None);
818        dict = Py_None;
819    }
820    else {
821        dict = PyDict_Copy(self->dict);
822        if (dict == NULL) {
823            Py_DECREF(initvalue);
824            return NULL;
825        }
826    }
827
828    state = Py_BuildValue("(OnN)", initvalue, self->pos, dict);
829    Py_DECREF(initvalue);
830    return state;
831}
832
833static PyObject *
834bytesio_setstate(bytesio *self, PyObject *state)
835{
836    PyObject *result;
837    PyObject *position_obj;
838    PyObject *dict;
839    Py_ssize_t pos;
840
841    assert(state != NULL);
842
843    /* We allow the state tuple to be longer than 3, because we may need
844       someday to extend the object's state without breaking
845       backward-compatibility. */
846    if (!PyTuple_Check(state) || Py_SIZE(state) < 3) {
847        PyErr_Format(PyExc_TypeError,
848                     "%.200s.__setstate__ argument should be 3-tuple, got %.200s",
849                     Py_TYPE(self)->tp_name, Py_TYPE(state)->tp_name);
850        return NULL;
851    }
852    CHECK_EXPORTS(self);
853    /* Reset the object to its default state. This is only needed to handle
854       the case of repeated calls to __setstate__. */
855    self->string_size = 0;
856    self->pos = 0;
857
858    /* Set the value of the internal buffer. If state[0] does not support the
859       buffer protocol, bytesio_write will raise the appropriate TypeError. */
860    result = _io_BytesIO_write(self, PyTuple_GET_ITEM(state, 0));
861    if (result == NULL)
862        return NULL;
863    Py_DECREF(result);
864
865    /* Set carefully the position value. Alternatively, we could use the seek
866       method instead of modifying self->pos directly to better protect the
867       object internal state against errneous (or malicious) inputs. */
868    position_obj = PyTuple_GET_ITEM(state, 1);
869    if (!PyLong_Check(position_obj)) {
870        PyErr_Format(PyExc_TypeError,
871                     "second item of state must be an integer, not %.200s",
872                     Py_TYPE(position_obj)->tp_name);
873        return NULL;
874    }
875    pos = PyLong_AsSsize_t(position_obj);
876    if (pos == -1 && PyErr_Occurred())
877        return NULL;
878    if (pos < 0) {
879        PyErr_SetString(PyExc_ValueError,
880                        "position value cannot be negative");
881        return NULL;
882    }
883    self->pos = pos;
884
885    /* Set the dictionary of the instance variables. */
886    dict = PyTuple_GET_ITEM(state, 2);
887    if (dict != Py_None) {
888        if (!PyDict_Check(dict)) {
889            PyErr_Format(PyExc_TypeError,
890                         "third item of state should be a dict, got a %.200s",
891                         Py_TYPE(dict)->tp_name);
892            return NULL;
893        }
894        if (self->dict) {
895            /* Alternatively, we could replace the internal dictionary
896               completely. However, it seems more practical to just update it. */
897            if (PyDict_Update(self->dict, dict) < 0)
898                return NULL;
899        }
900        else {
901            Py_INCREF(dict);
902            self->dict = dict;
903        }
904    }
905
906    Py_RETURN_NONE;
907}
908
909static void
910bytesio_dealloc(bytesio *self)
911{
912    _PyObject_GC_UNTRACK(self);
913    if (self->exports > 0) {
914        PyErr_SetString(PyExc_SystemError,
915                        "deallocated BytesIO object has exported buffers");
916        PyErr_Print();
917    }
918    Py_CLEAR(self->buf);
919    Py_CLEAR(self->dict);
920    if (self->weakreflist != NULL)
921        PyObject_ClearWeakRefs((PyObject *) self);
922    Py_TYPE(self)->tp_free(self);
923}
924
925static PyObject *
926bytesio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
927{
928    bytesio *self;
929
930    assert(type != NULL && type->tp_alloc != NULL);
931    self = (bytesio *)type->tp_alloc(type, 0);
932    if (self == NULL)
933        return NULL;
934
935    /* tp_alloc initializes all the fields to zero. So we don't have to
936       initialize them here. */
937
938    self->buf = PyBytes_FromStringAndSize(NULL, 0);
939    if (self->buf == NULL) {
940        Py_DECREF(self);
941        return PyErr_NoMemory();
942    }
943
944    return (PyObject *)self;
945}
946
947/*[clinic input]
948_io.BytesIO.__init__
949    initial_bytes as initvalue: object(c_default="NULL") = b''
950
951Buffered I/O implementation using an in-memory bytes buffer.
952[clinic start generated code]*/
953
954static int
955_io_BytesIO___init___impl(bytesio *self, PyObject *initvalue)
956/*[clinic end generated code: output=65c0c51e24c5b621 input=aac7f31b67bf0fb6]*/
957{
958    /* In case, __init__ is called multiple times. */
959    self->string_size = 0;
960    self->pos = 0;
961
962    if (self->exports > 0) {
963        PyErr_SetString(PyExc_BufferError,
964                        "Existing exports of data: object cannot be re-sized");
965        return -1;
966    }
967    if (initvalue && initvalue != Py_None) {
968        if (PyBytes_CheckExact(initvalue)) {
969            Py_INCREF(initvalue);
970            Py_XSETREF(self->buf, initvalue);
971            self->string_size = PyBytes_GET_SIZE(initvalue);
972        }
973        else {
974            PyObject *res;
975            res = _io_BytesIO_write(self, initvalue);
976            if (res == NULL)
977                return -1;
978            Py_DECREF(res);
979            self->pos = 0;
980        }
981    }
982
983    return 0;
984}
985
986static PyObject *
987bytesio_sizeof(bytesio *self, void *unused)
988{
989    Py_ssize_t res;
990
991    res = _PyObject_SIZE(Py_TYPE(self));
992    if (self->buf && !SHARED_BUF(self))
993        res += _PySys_GetSizeOf(self->buf);
994    return PyLong_FromSsize_t(res);
995}
996
997static int
998bytesio_traverse(bytesio *self, visitproc visit, void *arg)
999{
1000    Py_VISIT(self->dict);
1001    return 0;
1002}
1003
1004static int
1005bytesio_clear(bytesio *self)
1006{
1007    Py_CLEAR(self->dict);
1008    return 0;
1009}
1010
1011
1012#include "clinic/bytesio.c.h"
1013
1014static PyGetSetDef bytesio_getsetlist[] = {
1015    {"closed",  (getter)bytesio_get_closed, NULL,
1016     "True if the file is closed."},
1017    {NULL},            /* sentinel */
1018};
1019
1020static struct PyMethodDef bytesio_methods[] = {
1021    _IO_BYTESIO_READABLE_METHODDEF
1022    _IO_BYTESIO_SEEKABLE_METHODDEF
1023    _IO_BYTESIO_WRITABLE_METHODDEF
1024    _IO_BYTESIO_CLOSE_METHODDEF
1025    _IO_BYTESIO_FLUSH_METHODDEF
1026    _IO_BYTESIO_ISATTY_METHODDEF
1027    _IO_BYTESIO_TELL_METHODDEF
1028    _IO_BYTESIO_WRITE_METHODDEF
1029    _IO_BYTESIO_WRITELINES_METHODDEF
1030    _IO_BYTESIO_READ1_METHODDEF
1031    _IO_BYTESIO_READINTO_METHODDEF
1032    _IO_BYTESIO_READLINE_METHODDEF
1033    _IO_BYTESIO_READLINES_METHODDEF
1034    _IO_BYTESIO_READ_METHODDEF
1035    _IO_BYTESIO_GETBUFFER_METHODDEF
1036    _IO_BYTESIO_GETVALUE_METHODDEF
1037    _IO_BYTESIO_SEEK_METHODDEF
1038    _IO_BYTESIO_TRUNCATE_METHODDEF
1039    {"__getstate__",  (PyCFunction)bytesio_getstate,  METH_NOARGS, NULL},
1040    {"__setstate__",  (PyCFunction)bytesio_setstate,  METH_O, NULL},
1041    {"__sizeof__", (PyCFunction)bytesio_sizeof,     METH_NOARGS, NULL},
1042    {NULL, NULL}        /* sentinel */
1043};
1044
1045PyTypeObject PyBytesIO_Type = {
1046    PyVarObject_HEAD_INIT(NULL, 0)
1047    "_io.BytesIO",                             /*tp_name*/
1048    sizeof(bytesio),                     /*tp_basicsize*/
1049    0,                                         /*tp_itemsize*/
1050    (destructor)bytesio_dealloc,               /*tp_dealloc*/
1051    0,                                         /*tp_print*/
1052    0,                                         /*tp_getattr*/
1053    0,                                         /*tp_setattr*/
1054    0,                                         /*tp_reserved*/
1055    0,                                         /*tp_repr*/
1056    0,                                         /*tp_as_number*/
1057    0,                                         /*tp_as_sequence*/
1058    0,                                         /*tp_as_mapping*/
1059    0,                                         /*tp_hash*/
1060    0,                                         /*tp_call*/
1061    0,                                         /*tp_str*/
1062    0,                                         /*tp_getattro*/
1063    0,                                         /*tp_setattro*/
1064    0,                                         /*tp_as_buffer*/
1065    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
1066    Py_TPFLAGS_HAVE_GC,                        /*tp_flags*/
1067    _io_BytesIO___init____doc__,               /*tp_doc*/
1068    (traverseproc)bytesio_traverse,            /*tp_traverse*/
1069    (inquiry)bytesio_clear,                    /*tp_clear*/
1070    0,                                         /*tp_richcompare*/
1071    offsetof(bytesio, weakreflist),      /*tp_weaklistoffset*/
1072    PyObject_SelfIter,                         /*tp_iter*/
1073    (iternextfunc)bytesio_iternext,            /*tp_iternext*/
1074    bytesio_methods,                           /*tp_methods*/
1075    0,                                         /*tp_members*/
1076    bytesio_getsetlist,                        /*tp_getset*/
1077    0,                                         /*tp_base*/
1078    0,                                         /*tp_dict*/
1079    0,                                         /*tp_descr_get*/
1080    0,                                         /*tp_descr_set*/
1081    offsetof(bytesio, dict),             /*tp_dictoffset*/
1082    _io_BytesIO___init__,                      /*tp_init*/
1083    0,                                         /*tp_alloc*/
1084    bytesio_new,                               /*tp_new*/
1085};
1086
1087
1088/*
1089 * Implementation of the small intermediate object used by getbuffer().
1090 * getbuffer() returns a memoryview over this object, which should make it
1091 * invisible from Python code.
1092 */
1093
1094static int
1095bytesiobuf_getbuffer(bytesiobuf *obj, Py_buffer *view, int flags)
1096{
1097    bytesio *b = (bytesio *) obj->source;
1098
1099    if (view == NULL) {
1100        PyErr_SetString(PyExc_BufferError,
1101            "bytesiobuf_getbuffer: view==NULL argument is obsolete");
1102        return -1;
1103    }
1104    if (SHARED_BUF(b)) {
1105        if (unshare_buffer(b, b->string_size) < 0)
1106            return -1;
1107    }
1108
1109    /* cannot fail if view != NULL and readonly == 0 */
1110    (void)PyBuffer_FillInfo(view, (PyObject*)obj,
1111                            PyBytes_AS_STRING(b->buf), b->string_size,
1112                            0, flags);
1113    b->exports++;
1114    return 0;
1115}
1116
1117static void
1118bytesiobuf_releasebuffer(bytesiobuf *obj, Py_buffer *view)
1119{
1120    bytesio *b = (bytesio *) obj->source;
1121    b->exports--;
1122}
1123
1124static int
1125bytesiobuf_traverse(bytesiobuf *self, visitproc visit, void *arg)
1126{
1127    Py_VISIT(self->source);
1128    return 0;
1129}
1130
1131static void
1132bytesiobuf_dealloc(bytesiobuf *self)
1133{
1134    Py_CLEAR(self->source);
1135    Py_TYPE(self)->tp_free(self);
1136}
1137
1138static PyBufferProcs bytesiobuf_as_buffer = {
1139    (getbufferproc) bytesiobuf_getbuffer,
1140    (releasebufferproc) bytesiobuf_releasebuffer,
1141};
1142
1143PyTypeObject _PyBytesIOBuffer_Type = {
1144    PyVarObject_HEAD_INIT(NULL, 0)
1145    "_io._BytesIOBuffer",                      /*tp_name*/
1146    sizeof(bytesiobuf),                        /*tp_basicsize*/
1147    0,                                         /*tp_itemsize*/
1148    (destructor)bytesiobuf_dealloc,            /*tp_dealloc*/
1149    0,                                         /*tp_print*/
1150    0,                                         /*tp_getattr*/
1151    0,                                         /*tp_setattr*/
1152    0,                                         /*tp_reserved*/
1153    0,                                         /*tp_repr*/
1154    0,                                         /*tp_as_number*/
1155    0,                                         /*tp_as_sequence*/
1156    0,                                         /*tp_as_mapping*/
1157    0,                                         /*tp_hash*/
1158    0,                                         /*tp_call*/
1159    0,                                         /*tp_str*/
1160    0,                                         /*tp_getattro*/
1161    0,                                         /*tp_setattro*/
1162    &bytesiobuf_as_buffer,                     /*tp_as_buffer*/
1163    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,   /*tp_flags*/
1164    0,                                         /*tp_doc*/
1165    (traverseproc)bytesiobuf_traverse,         /*tp_traverse*/
1166    0,                                         /*tp_clear*/
1167    0,                                         /*tp_richcompare*/
1168    0,                                         /*tp_weaklistoffset*/
1169    0,                                         /*tp_iter*/
1170    0,                                         /*tp_iternext*/
1171    0,                                         /*tp_methods*/
1172    0,                                         /*tp_members*/
1173    0,                                         /*tp_getset*/
1174    0,                                         /*tp_base*/
1175    0,                                         /*tp_dict*/
1176    0,                                         /*tp_descr_get*/
1177    0,                                         /*tp_descr_set*/
1178    0,                                         /*tp_dictoffset*/
1179    0,                                         /*tp_init*/
1180    0,                                         /*tp_alloc*/
1181    0,                                         /*tp_new*/
1182};
1183