• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *" "&PyBytesIO_Type"
9 [clinic start generated code]*/
10 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=7f50ec034f5c0b26]*/
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
check_closed(bytesio * self)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
check_exports(bytesio * self)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
scan_eol(bytesio * self,Py_ssize_t len)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
unshare_buffer(bytesio * self,size_t size)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
resize_buffer(bytesio * self,size_t size)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
write_bytes(bytesio * self,PyObject * b)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 *
bytesio_get_closed(bytesio * self,void * Py_UNUSED (ignored))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 *
_io_BytesIO_readable_impl(bytesio * self)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 *
_io_BytesIO_writable_impl(bytesio * self)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 *
_io_BytesIO_seekable_impl(bytesio * self)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 *
_io_BytesIO_flush_impl(bytesio * self)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 Get a read-write view over the contents of the BytesIO object.
312 [clinic start generated code]*/
313 
314 static PyObject *
_io_BytesIO_getbuffer_impl(bytesio * self)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 
337 Retrieve the entire contents of the BytesIO object.
338 [clinic start generated code]*/
339 
340 static PyObject *
_io_BytesIO_getvalue_impl(bytesio * self)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 
366 Always returns False.
367 
368 BytesIO objects are not connected to a TTY-like device.
369 [clinic start generated code]*/
370 
371 static PyObject *
_io_BytesIO_isatty_impl(bytesio * self)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 
382 Current file position, an integer.
383 [clinic start generated code]*/
384 
385 static PyObject *
_io_BytesIO_tell_impl(bytesio * self)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 
393 static PyObject *
read_bytes(bytesio * self,Py_ssize_t size)394 read_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 
418 Read at most size bytes, returned as a bytes object.
419 
420 If the size argument is negative, read until EOF is reached.
421 Return an empty bytes object at EOF.
422 [clinic start generated code]*/
423 
424 static PyObject *
_io_BytesIO_read_impl(bytesio * self,Py_ssize_t size)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 
449 Read at most size bytes, returned as a bytes object.
450 
451 If the size argument is negative or omitted, read until EOF is reached.
452 Return an empty bytes object at EOF.
453 [clinic start generated code]*/
454 
455 static PyObject *
_io_BytesIO_read1_impl(bytesio * self,Py_ssize_t size)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 
467 Next line from the file, as a bytes object.
468 
469 Retain newline.  A non-negative size argument limits the maximum
470 number of bytes to return (an incomplete line may be returned then).
471 Return an empty bytes object at EOF.
472 [clinic start generated code]*/
473 
474 static PyObject *
_io_BytesIO_readline_impl(bytesio * self,Py_ssize_t size)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 
492 List of bytes objects, each a line from the file.
493 
494 Call readline() repeatedly and return a list of the lines so read.
495 The optional size argument, if given, is an approximate bound on the
496 total number of bytes in the lines returned.
497 [clinic start generated code]*/
498 
499 static PyObject *
_io_BytesIO_readlines_impl(bytesio * self,PyObject * arg)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 
557 Read bytes into buffer.
558 
559 Returns number of bytes read (0 for EOF), or None if the object
560 is set not to block and has no data to read.
561 [clinic start generated code]*/
562 
563 static PyObject *
_io_BytesIO_readinto_impl(bytesio * self,Py_buffer * buffer)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 
593 Truncate the file to at most size bytes.
594 
595 Size defaults to the current file position, as returned by tell().
596 The current file position is unchanged.  Returns the new size.
597 [clinic start generated code]*/
598 
599 static PyObject *
_io_BytesIO_truncate_impl(bytesio * self,Py_ssize_t size)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 
621 static PyObject *
bytesio_iternext(bytesio * self)622 bytesio_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 
642 Change stream position.
643 
644 Seek 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.
648 Returns the new absolute position.
649 [clinic start generated code]*/
650 
651 static PyObject *
_io_BytesIO_seek_impl(bytesio * self,Py_ssize_t pos,int whence)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 
700 Write bytes to file.
701 
702 Return the number of bytes written.
703 [clinic start generated code]*/
704 
705 static PyObject *
_io_BytesIO_write(bytesio * self,PyObject * b)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 
718 Write lines to the file.
719 
720 Note that newlines are not added.  lines can be any iterable object
721 producing bytes-like objects. This is equivalent to calling write() for
722 each element.
723 [clinic start generated code]*/
724 
725 static PyObject *
_io_BytesIO_writelines(bytesio * self,PyObject * lines)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 
757 Disable all I/O operations.
758 [clinic start generated code]*/
759 
760 static PyObject *
_io_BytesIO_close_impl(bytesio * self)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 
784 static PyObject *
bytesio_getstate(bytesio * self,PyObject * Py_UNUSED (ignored))785 bytesio_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 
810 static PyObject *
bytesio_setstate(bytesio * self,PyObject * state)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             Py_INCREF(dict);
879             self->dict = dict;
880         }
881     }
882 
883     Py_RETURN_NONE;
884 }
885 
886 static void
bytesio_dealloc(bytesio * self)887 bytesio_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 
902 static PyObject *
bytesio_new(PyTypeObject * type,PyObject * args,PyObject * kwds)903 bytesio_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 
928 Buffered I/O implementation using an in-memory bytes buffer.
929 [clinic start generated code]*/
930 
931 static int
_io_BytesIO___init___impl(bytesio * self,PyObject * initvalue)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 
963 static PyObject *
bytesio_sizeof(bytesio * self,void * unused)964 bytesio_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 
979 static int
bytesio_traverse(bytesio * self,visitproc visit,void * arg)980 bytesio_traverse(bytesio *self, visitproc visit, void *arg)
981 {
982     Py_VISIT(self->dict);
983     return 0;
984 }
985 
986 static int
bytesio_clear(bytesio * self)987 bytesio_clear(bytesio *self)
988 {
989     Py_CLEAR(self->dict);
990     return 0;
991 }
992 
993 
994 #include "clinic/bytesio.c.h"
995 
996 static PyGetSetDef bytesio_getsetlist[] = {
997     {"closed",  (getter)bytesio_get_closed, NULL,
998      "True if the file is closed."},
999     {NULL},            /* sentinel */
1000 };
1001 
1002 static 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 
1027 PyTypeObject 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 
1076 static int
bytesiobuf_getbuffer(bytesiobuf * obj,Py_buffer * view,int flags)1077 bytesiobuf_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 
1099 static void
bytesiobuf_releasebuffer(bytesiobuf * obj,Py_buffer * view)1100 bytesiobuf_releasebuffer(bytesiobuf *obj, Py_buffer *view)
1101 {
1102     bytesio *b = (bytesio *) obj->source;
1103     b->exports--;
1104 }
1105 
1106 static int
bytesiobuf_traverse(bytesiobuf * self,visitproc visit,void * arg)1107 bytesiobuf_traverse(bytesiobuf *self, visitproc visit, void *arg)
1108 {
1109     Py_VISIT(self->source);
1110     return 0;
1111 }
1112 
1113 static void
bytesiobuf_dealloc(bytesiobuf * self)1114 bytesiobuf_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 
1122 static PyBufferProcs bytesiobuf_as_buffer = {
1123     (getbufferproc) bytesiobuf_getbuffer,
1124     (releasebufferproc) bytesiobuf_releasebuffer,
1125 };
1126 
1127 Py_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