1 #include "Python.h"
2 #include "pycore_object.h"
3 #include <stddef.h> // offsetof()
4 #include "_iomodule.h"
5
6 /*[clinic input]
7 module _io
8 class _io.BytesIO "bytesio *" "clinic_state()->PyBytesIO_Type"
9 [clinic start generated code]*/
10 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=48ede2f330f847c3]*/
11
12 typedef 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
22 typedef 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
34 static int
35 check_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
44 static int
45 check_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. */
71 static Py_ssize_t
72 scan_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. */
105 static int
106 unshare_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. */
124 static int
125 resize_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
180 write_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
241 static PyObject *
242 bytesio_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
255 Returns True if the IO object can be read.
256 [clinic start generated code]*/
257
258 static 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
269 Returns True if the IO object can be written.
270 [clinic start generated code]*/
271
272 static 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
283 Returns True if the IO object can be seeked.
284 [clinic start generated code]*/
285
286 static 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
297 Does nothing.
298 [clinic start generated code]*/
299
300 static 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
311 cls: defining_class
312 /
313
314 Get a read-write view over the contents of the BytesIO object.
315 [clinic start generated code]*/
316
317 static PyObject *
318 _io_BytesIO_getbuffer_impl(bytesio *self, PyTypeObject *cls)
319 /*[clinic end generated code: output=045091d7ce87fe4e input=0668fbb48f95dffa]*/
320 {
321 _PyIO_State *state = get_io_state_by_cls(cls);
322 PyTypeObject *type = state->PyBytesIOBuffer_Type;
323 bytesiobuf *buf;
324 PyObject *view;
325
326 CHECK_CLOSED(self);
327
328 buf = (bytesiobuf *) type->tp_alloc(type, 0);
329 if (buf == NULL)
330 return NULL;
331 buf->source = (bytesio*)Py_NewRef(self);
332 view = PyMemoryView_FromObject((PyObject *) buf);
333 Py_DECREF(buf);
334 return view;
335 }
336
337 /*[clinic input]
338 _io.BytesIO.getvalue
339
340 Retrieve the entire contents of the BytesIO object.
341 [clinic start generated code]*/
342
343 static PyObject *
344 _io_BytesIO_getvalue_impl(bytesio *self)
345 /*[clinic end generated code: output=b3f6a3233c8fd628 input=4b403ac0af3973ed]*/
346 {
347 CHECK_CLOSED(self);
348 if (self->string_size <= 1 || self->exports > 0)
349 return PyBytes_FromStringAndSize(PyBytes_AS_STRING(self->buf),
350 self->string_size);
351
352 if (self->string_size != PyBytes_GET_SIZE(self->buf)) {
353 if (SHARED_BUF(self)) {
354 if (unshare_buffer(self, self->string_size) < 0)
355 return NULL;
356 }
357 else {
358 if (_PyBytes_Resize(&self->buf, self->string_size) < 0)
359 return NULL;
360 }
361 }
362 return Py_NewRef(self->buf);
363 }
364
365 /*[clinic input]
366 _io.BytesIO.isatty
367
368 Always returns False.
369
370 BytesIO objects are not connected to a TTY-like device.
371 [clinic start generated code]*/
372
373 static PyObject *
374 _io_BytesIO_isatty_impl(bytesio *self)
375 /*[clinic end generated code: output=df67712e669f6c8f input=6f97f0985d13f827]*/
376 {
377 CHECK_CLOSED(self);
378 Py_RETURN_FALSE;
379 }
380
381 /*[clinic input]
382 _io.BytesIO.tell
383
384 Current file position, an integer.
385 [clinic start generated code]*/
386
387 static PyObject *
388 _io_BytesIO_tell_impl(bytesio *self)
389 /*[clinic end generated code: output=b54b0f93cd0e5e1d input=b106adf099cb3657]*/
390 {
391 CHECK_CLOSED(self);
392 return PyLong_FromSsize_t(self->pos);
393 }
394
395 static PyObject *
396 read_bytes(bytesio *self, Py_ssize_t size)
397 {
398 const char *output;
399
400 assert(self->buf != NULL);
401 assert(size <= self->string_size);
402 if (size > 1 &&
403 self->pos == 0 && size == PyBytes_GET_SIZE(self->buf) &&
404 self->exports == 0) {
405 self->pos += size;
406 return Py_NewRef(self->buf);
407 }
408
409 output = PyBytes_AS_STRING(self->buf) + self->pos;
410 self->pos += size;
411 return PyBytes_FromStringAndSize(output, size);
412 }
413
414 /*[clinic input]
415 _io.BytesIO.read
416 size: Py_ssize_t(accept={int, NoneType}) = -1
417 /
418
419 Read at most size bytes, returned as a bytes object.
420
421 If the size argument is negative, read until EOF is reached.
422 Return an empty bytes object at EOF.
423 [clinic start generated code]*/
424
425 static PyObject *
426 _io_BytesIO_read_impl(bytesio *self, Py_ssize_t size)
427 /*[clinic end generated code: output=9cc025f21c75bdd2 input=74344a39f431c3d7]*/
428 {
429 Py_ssize_t n;
430
431 CHECK_CLOSED(self);
432
433 /* adjust invalid sizes */
434 n = self->string_size - self->pos;
435 if (size < 0 || size > n) {
436 size = n;
437 if (size < 0)
438 size = 0;
439 }
440
441 return read_bytes(self, size);
442 }
443
444
445 /*[clinic input]
446 _io.BytesIO.read1
447 size: Py_ssize_t(accept={int, NoneType}) = -1
448 /
449
450 Read at most size bytes, returned as a bytes object.
451
452 If the size argument is negative or omitted, read until EOF is reached.
453 Return an empty bytes object at EOF.
454 [clinic start generated code]*/
455
456 static PyObject *
457 _io_BytesIO_read1_impl(bytesio *self, Py_ssize_t size)
458 /*[clinic end generated code: output=d0f843285aa95f1c input=440a395bf9129ef5]*/
459 {
460 return _io_BytesIO_read_impl(self, size);
461 }
462
463 /*[clinic input]
464 _io.BytesIO.readline
465 size: Py_ssize_t(accept={int, NoneType}) = -1
466 /
467
468 Next line from the file, as a bytes object.
469
470 Retain newline. A non-negative size argument limits the maximum
471 number of bytes to return (an incomplete line may be returned then).
472 Return an empty bytes object at EOF.
473 [clinic start generated code]*/
474
475 static PyObject *
476 _io_BytesIO_readline_impl(bytesio *self, Py_ssize_t size)
477 /*[clinic end generated code: output=4bff3c251df8ffcd input=e7c3fbd1744e2783]*/
478 {
479 Py_ssize_t n;
480
481 CHECK_CLOSED(self);
482
483 n = scan_eol(self, size);
484
485 return read_bytes(self, n);
486 }
487
488 /*[clinic input]
489 _io.BytesIO.readlines
490 size as arg: object = None
491 /
492
493 List of bytes objects, each a line from the file.
494
495 Call readline() repeatedly and return a list of the lines so read.
496 The optional size argument, if given, is an approximate bound on the
497 total number of bytes in the lines returned.
498 [clinic start generated code]*/
499
500 static PyObject *
501 _io_BytesIO_readlines_impl(bytesio *self, PyObject *arg)
502 /*[clinic end generated code: output=09b8e34c880808ff input=691aa1314f2c2a87]*/
503 {
504 Py_ssize_t maxsize, size, n;
505 PyObject *result, *line;
506 const char *output;
507
508 CHECK_CLOSED(self);
509
510 if (PyLong_Check(arg)) {
511 maxsize = PyLong_AsSsize_t(arg);
512 if (maxsize == -1 && PyErr_Occurred())
513 return NULL;
514 }
515 else if (arg == Py_None) {
516 /* No size limit, by default. */
517 maxsize = -1;
518 }
519 else {
520 PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
521 Py_TYPE(arg)->tp_name);
522 return NULL;
523 }
524
525 size = 0;
526 result = PyList_New(0);
527 if (!result)
528 return NULL;
529
530 output = PyBytes_AS_STRING(self->buf) + self->pos;
531 while ((n = scan_eol(self, -1)) != 0) {
532 self->pos += n;
533 line = PyBytes_FromStringAndSize(output, n);
534 if (!line)
535 goto on_error;
536 if (PyList_Append(result, line) == -1) {
537 Py_DECREF(line);
538 goto on_error;
539 }
540 Py_DECREF(line);
541 size += n;
542 if (maxsize > 0 && size >= maxsize)
543 break;
544 output += n;
545 }
546 return result;
547
548 on_error:
549 Py_DECREF(result);
550 return NULL;
551 }
552
553 /*[clinic input]
554 _io.BytesIO.readinto
555 buffer: Py_buffer(accept={rwbuffer})
556 /
557
558 Read bytes into buffer.
559
560 Returns number of bytes read (0 for EOF), or None if the object
561 is set not to block and has no data to read.
562 [clinic start generated code]*/
563
564 static PyObject *
565 _io_BytesIO_readinto_impl(bytesio *self, Py_buffer *buffer)
566 /*[clinic end generated code: output=a5d407217dcf0639 input=1424d0fdce857919]*/
567 {
568 Py_ssize_t len, n;
569
570 CHECK_CLOSED(self);
571
572 /* adjust invalid sizes */
573 len = buffer->len;
574 n = self->string_size - self->pos;
575 if (len > n) {
576 len = n;
577 if (len < 0)
578 len = 0;
579 }
580
581 memcpy(buffer->buf, PyBytes_AS_STRING(self->buf) + self->pos, len);
582 assert(self->pos + len < PY_SSIZE_T_MAX);
583 assert(len >= 0);
584 self->pos += len;
585
586 return PyLong_FromSsize_t(len);
587 }
588
589 /*[clinic input]
590 _io.BytesIO.truncate
591 size: Py_ssize_t(accept={int, NoneType}, c_default="self->pos") = None
592 /
593
594 Truncate the file to at most size bytes.
595
596 Size defaults to the current file position, as returned by tell().
597 The current file position is unchanged. Returns the new size.
598 [clinic start generated code]*/
599
600 static PyObject *
601 _io_BytesIO_truncate_impl(bytesio *self, Py_ssize_t size)
602 /*[clinic end generated code: output=9ad17650c15fa09b input=423759dd42d2f7c1]*/
603 {
604 CHECK_CLOSED(self);
605 CHECK_EXPORTS(self);
606
607 if (size < 0) {
608 PyErr_Format(PyExc_ValueError,
609 "negative size value %zd", size);
610 return NULL;
611 }
612
613 if (size < self->string_size) {
614 self->string_size = size;
615 if (resize_buffer(self, size) < 0)
616 return NULL;
617 }
618
619 return PyLong_FromSsize_t(size);
620 }
621
622 static PyObject *
623 bytesio_iternext(bytesio *self)
624 {
625 Py_ssize_t n;
626
627 CHECK_CLOSED(self);
628
629 n = scan_eol(self, -1);
630
631 if (n == 0)
632 return NULL;
633
634 return read_bytes(self, n);
635 }
636
637 /*[clinic input]
638 _io.BytesIO.seek
639 pos: Py_ssize_t
640 whence: int = 0
641 /
642
643 Change stream position.
644
645 Seek to byte offset pos relative to position indicated by whence:
646 0 Start of stream (the default). pos should be >= 0;
647 1 Current position - pos may be negative;
648 2 End of stream - pos usually negative.
649 Returns the new absolute position.
650 [clinic start generated code]*/
651
652 static PyObject *
653 _io_BytesIO_seek_impl(bytesio *self, Py_ssize_t pos, int whence)
654 /*[clinic end generated code: output=c26204a68e9190e4 input=1e875e6ebc652948]*/
655 {
656 CHECK_CLOSED(self);
657
658 if (pos < 0 && whence == 0) {
659 PyErr_Format(PyExc_ValueError,
660 "negative seek value %zd", pos);
661 return NULL;
662 }
663
664 /* whence = 0: offset relative to beginning of the string.
665 whence = 1: offset relative to current position.
666 whence = 2: offset relative the end of the string. */
667 if (whence == 1) {
668 if (pos > PY_SSIZE_T_MAX - self->pos) {
669 PyErr_SetString(PyExc_OverflowError,
670 "new position too large");
671 return NULL;
672 }
673 pos += self->pos;
674 }
675 else if (whence == 2) {
676 if (pos > PY_SSIZE_T_MAX - self->string_size) {
677 PyErr_SetString(PyExc_OverflowError,
678 "new position too large");
679 return NULL;
680 }
681 pos += self->string_size;
682 }
683 else if (whence != 0) {
684 PyErr_Format(PyExc_ValueError,
685 "invalid whence (%i, should be 0, 1 or 2)", whence);
686 return NULL;
687 }
688
689 if (pos < 0)
690 pos = 0;
691 self->pos = pos;
692
693 return PyLong_FromSsize_t(self->pos);
694 }
695
696 /*[clinic input]
697 _io.BytesIO.write
698 b: object
699 /
700
701 Write bytes to file.
702
703 Return the number of bytes written.
704 [clinic start generated code]*/
705
706 static PyObject *
707 _io_BytesIO_write(bytesio *self, PyObject *b)
708 /*[clinic end generated code: output=53316d99800a0b95 input=f5ec7c8c64ed720a]*/
709 {
710 Py_ssize_t n = write_bytes(self, b);
711 return n >= 0 ? PyLong_FromSsize_t(n) : NULL;
712 }
713
714 /*[clinic input]
715 _io.BytesIO.writelines
716 lines: object
717 /
718
719 Write lines to the file.
720
721 Note that newlines are not added. lines can be any iterable object
722 producing bytes-like objects. This is equivalent to calling write() for
723 each element.
724 [clinic start generated code]*/
725
726 static PyObject *
727 _io_BytesIO_writelines(bytesio *self, PyObject *lines)
728 /*[clinic end generated code: output=7f33aa3271c91752 input=e972539176fc8fc1]*/
729 {
730 PyObject *it, *item;
731
732 CHECK_CLOSED(self);
733
734 it = PyObject_GetIter(lines);
735 if (it == NULL)
736 return NULL;
737
738 while ((item = PyIter_Next(it)) != NULL) {
739 Py_ssize_t ret = write_bytes(self, item);
740 Py_DECREF(item);
741 if (ret < 0) {
742 Py_DECREF(it);
743 return NULL;
744 }
745 }
746 Py_DECREF(it);
747
748 /* See if PyIter_Next failed */
749 if (PyErr_Occurred())
750 return NULL;
751
752 Py_RETURN_NONE;
753 }
754
755 /*[clinic input]
756 _io.BytesIO.close
757
758 Disable all I/O operations.
759 [clinic start generated code]*/
760
761 static PyObject *
762 _io_BytesIO_close_impl(bytesio *self)
763 /*[clinic end generated code: output=1471bb9411af84a0 input=37e1f55556e61f60]*/
764 {
765 CHECK_EXPORTS(self);
766 Py_CLEAR(self->buf);
767 Py_RETURN_NONE;
768 }
769
770 /* Pickling support.
771
772 Note that only pickle protocol 2 and onward are supported since we use
773 extended __reduce__ API of PEP 307 to make BytesIO instances picklable.
774
775 Providing support for protocol < 2 would require the __reduce_ex__ method
776 which is notably long-winded when defined properly.
777
778 For BytesIO, the implementation would similar to one coded for
779 object.__reduce_ex__, but slightly less general. To be more specific, we
780 could call bytesio_getstate directly and avoid checking for the presence of
781 a fallback __reduce__ method. However, we would still need a __newobj__
782 function to use the efficient instance representation of PEP 307.
783 */
784
785 static PyObject *
786 bytesio_getstate(bytesio *self, PyObject *Py_UNUSED(ignored))
787 {
788 PyObject *initvalue = _io_BytesIO_getvalue_impl(self);
789 PyObject *dict;
790 PyObject *state;
791
792 if (initvalue == NULL)
793 return NULL;
794 if (self->dict == NULL) {
795 dict = Py_NewRef(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
810 static PyObject *
811 bytesio_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 self->dict = Py_NewRef(dict);
879 }
880 }
881
882 Py_RETURN_NONE;
883 }
884
885 static void
886 bytesio_dealloc(bytesio *self)
887 {
888 PyTypeObject *tp = Py_TYPE(self);
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 tp->tp_free(self);
900 Py_DECREF(tp);
901 }
902
903 static PyObject *
904 bytesio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
905 {
906 bytesio *self;
907
908 assert(type != NULL && type->tp_alloc != NULL);
909 self = (bytesio *)type->tp_alloc(type, 0);
910 if (self == NULL)
911 return NULL;
912
913 /* tp_alloc initializes all the fields to zero. So we don't have to
914 initialize them here. */
915
916 self->buf = PyBytes_FromStringAndSize(NULL, 0);
917 if (self->buf == NULL) {
918 Py_DECREF(self);
919 return PyErr_NoMemory();
920 }
921
922 return (PyObject *)self;
923 }
924
925 /*[clinic input]
926 _io.BytesIO.__init__
927 initial_bytes as initvalue: object(c_default="NULL") = b''
928
929 Buffered I/O implementation using an in-memory bytes buffer.
930 [clinic start generated code]*/
931
932 static int
933 _io_BytesIO___init___impl(bytesio *self, PyObject *initvalue)
934 /*[clinic end generated code: output=65c0c51e24c5b621 input=aac7f31b67bf0fb6]*/
935 {
936 /* In case, __init__ is called multiple times. */
937 self->string_size = 0;
938 self->pos = 0;
939
940 if (self->exports > 0) {
941 PyErr_SetString(PyExc_BufferError,
942 "Existing exports of data: object cannot be re-sized");
943 return -1;
944 }
945 if (initvalue && initvalue != Py_None) {
946 if (PyBytes_CheckExact(initvalue)) {
947 Py_XSETREF(self->buf, Py_NewRef(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
963 static PyObject *
964 bytesio_sizeof(bytesio *self, void *unused)
965 {
966 size_t res = _PyObject_SIZE(Py_TYPE(self));
967 if (self->buf && !SHARED_BUF(self)) {
968 size_t s = _PySys_GetSizeOf(self->buf);
969 if (s == (size_t)-1) {
970 return NULL;
971 }
972 res += s;
973 }
974 return PyLong_FromSize_t(res);
975 }
976
977 static int
978 bytesio_traverse(bytesio *self, visitproc visit, void *arg)
979 {
980 Py_VISIT(Py_TYPE(self));
981 Py_VISIT(self->dict);
982 Py_VISIT(self->buf);
983 return 0;
984 }
985
986 static int
987 bytesio_clear(bytesio *self)
988 {
989 Py_CLEAR(self->dict);
990 Py_CLEAR(self->buf);
991 return 0;
992 }
993
994
995 #define clinic_state() (find_io_state_by_def(Py_TYPE(self)))
996 #include "clinic/bytesio.c.h"
997 #undef clinic_state
998
999 static PyGetSetDef bytesio_getsetlist[] = {
1000 {"closed", (getter)bytesio_get_closed, NULL,
1001 "True if the file is closed."},
1002 {NULL}, /* sentinel */
1003 };
1004
1005 static struct PyMethodDef bytesio_methods[] = {
1006 _IO_BYTESIO_READABLE_METHODDEF
1007 _IO_BYTESIO_SEEKABLE_METHODDEF
1008 _IO_BYTESIO_WRITABLE_METHODDEF
1009 _IO_BYTESIO_CLOSE_METHODDEF
1010 _IO_BYTESIO_FLUSH_METHODDEF
1011 _IO_BYTESIO_ISATTY_METHODDEF
1012 _IO_BYTESIO_TELL_METHODDEF
1013 _IO_BYTESIO_WRITE_METHODDEF
1014 _IO_BYTESIO_WRITELINES_METHODDEF
1015 _IO_BYTESIO_READ1_METHODDEF
1016 _IO_BYTESIO_READINTO_METHODDEF
1017 _IO_BYTESIO_READLINE_METHODDEF
1018 _IO_BYTESIO_READLINES_METHODDEF
1019 _IO_BYTESIO_READ_METHODDEF
1020 _IO_BYTESIO_GETBUFFER_METHODDEF
1021 _IO_BYTESIO_GETVALUE_METHODDEF
1022 _IO_BYTESIO_SEEK_METHODDEF
1023 _IO_BYTESIO_TRUNCATE_METHODDEF
1024 {"__getstate__", (PyCFunction)bytesio_getstate, METH_NOARGS, NULL},
1025 {"__setstate__", (PyCFunction)bytesio_setstate, METH_O, NULL},
1026 {"__sizeof__", (PyCFunction)bytesio_sizeof, METH_NOARGS, NULL},
1027 {NULL, NULL} /* sentinel */
1028 };
1029
1030 static PyMemberDef bytesio_members[] = {
1031 {"__weaklistoffset__", T_PYSSIZET, offsetof(bytesio, weakreflist), READONLY},
1032 {"__dictoffset__", T_PYSSIZET, offsetof(bytesio, dict), READONLY},
1033 {NULL}
1034 };
1035
1036 static PyType_Slot bytesio_slots[] = {
1037 {Py_tp_dealloc, bytesio_dealloc},
1038 {Py_tp_doc, (void *)_io_BytesIO___init____doc__},
1039 {Py_tp_traverse, bytesio_traverse},
1040 {Py_tp_clear, bytesio_clear},
1041 {Py_tp_iter, PyObject_SelfIter},
1042 {Py_tp_iternext, bytesio_iternext},
1043 {Py_tp_methods, bytesio_methods},
1044 {Py_tp_members, bytesio_members},
1045 {Py_tp_getset, bytesio_getsetlist},
1046 {Py_tp_init, _io_BytesIO___init__},
1047 {Py_tp_new, bytesio_new},
1048 {0, NULL},
1049 };
1050
1051 PyType_Spec bytesio_spec = {
1052 .name = "_io.BytesIO",
1053 .basicsize = sizeof(bytesio),
1054 .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
1055 Py_TPFLAGS_IMMUTABLETYPE),
1056 .slots = bytesio_slots,
1057 };
1058
1059 /*
1060 * Implementation of the small intermediate object used by getbuffer().
1061 * getbuffer() returns a memoryview over this object, which should make it
1062 * invisible from Python code.
1063 */
1064
1065 static int
1066 bytesiobuf_getbuffer(bytesiobuf *obj, Py_buffer *view, int flags)
1067 {
1068 bytesio *b = (bytesio *) obj->source;
1069
1070 if (view == NULL) {
1071 PyErr_SetString(PyExc_BufferError,
1072 "bytesiobuf_getbuffer: view==NULL argument is obsolete");
1073 return -1;
1074 }
1075 if (SHARED_BUF(b)) {
1076 if (unshare_buffer(b, b->string_size) < 0)
1077 return -1;
1078 }
1079
1080 /* cannot fail if view != NULL and readonly == 0 */
1081 (void)PyBuffer_FillInfo(view, (PyObject*)obj,
1082 PyBytes_AS_STRING(b->buf), b->string_size,
1083 0, flags);
1084 b->exports++;
1085 return 0;
1086 }
1087
1088 static void
1089 bytesiobuf_releasebuffer(bytesiobuf *obj, Py_buffer *view)
1090 {
1091 bytesio *b = (bytesio *) obj->source;
1092 b->exports--;
1093 }
1094
1095 static int
1096 bytesiobuf_clear(bytesiobuf *self)
1097 {
1098 Py_CLEAR(self->source);
1099 return 0;
1100 }
1101
1102 static int
1103 bytesiobuf_traverse(bytesiobuf *self, visitproc visit, void *arg)
1104 {
1105 Py_VISIT(Py_TYPE(self));
1106 Py_VISIT(self->source);
1107 return 0;
1108 }
1109
1110 static void
1111 bytesiobuf_dealloc(bytesiobuf *self)
1112 {
1113 PyTypeObject *tp = Py_TYPE(self);
1114 /* bpo-31095: UnTrack is needed before calling any callbacks */
1115 PyObject_GC_UnTrack(self);
1116 (void)bytesiobuf_clear(self);
1117 tp->tp_free(self);
1118 Py_DECREF(tp);
1119 }
1120
1121 static PyType_Slot bytesiobuf_slots[] = {
1122 {Py_tp_dealloc, bytesiobuf_dealloc},
1123 {Py_tp_traverse, bytesiobuf_traverse},
1124 {Py_tp_clear, bytesiobuf_clear},
1125
1126 // Buffer protocol
1127 {Py_bf_getbuffer, bytesiobuf_getbuffer},
1128 {Py_bf_releasebuffer, bytesiobuf_releasebuffer},
1129 {0, NULL},
1130 };
1131
1132 PyType_Spec bytesiobuf_spec = {
1133 .name = "_io._BytesIOBuffer",
1134 .basicsize = sizeof(bytesiobuf),
1135 .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1136 Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION),
1137 .slots = bytesiobuf_slots,
1138 };