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