blob: 2468f45f941e2ec6b6e553d019501024cb6492c3 [file] [log] [blame]
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00001#include "Python.h"
Victor Stinnerbcda8f12018-11-21 22:27:47 +01002#include "pycore_object.h"
Victor Stinner4a21e572020-04-15 02:35:41 +02003#include <stddef.h> // offsetof()
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00004#include "_iomodule.h"
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00005
Serhiy Storchakaf24131f2015-04-16 11:19:43 +03006/*[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
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000012typedef struct {
13 PyObject_HEAD
Serhiy Storchaka87d0b452015-02-03 11:30:10 +020014 PyObject *buf;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000015 Py_ssize_t pos;
16 Py_ssize_t string_size;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000017 PyObject *dict;
18 PyObject *weakreflist;
Antoine Pitrou972ee132010-09-06 18:48:21 +000019 Py_ssize_t exports;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000020} bytesio;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000021
Antoine Pitrou972ee132010-09-06 18:48:21 +000022typedef struct {
23 PyObject_HEAD
24 bytesio *source;
25} bytesiobuf;
26
Serhiy Storchaka87d0b452015-02-03 11:30:10 +020027/* The bytesio object can be in three states:
28 * Py_REFCNT(buf) == 1, exports == 0.
Serhiy Storchaka38c30e62015-02-03 18:51:58 +020029 * Py_REFCNT(buf) > 1. exports == 0,
Serhiy Storchaka87d0b452015-02-03 11:30:10 +020030 first modification or export causes the internal buffer copying.
31 * exports > 0. Py_REFCNT(buf) == 1, any modifications are forbidden.
32*/
Antoine Pitrou972ee132010-09-06 18:48:21 +000033
Sergey Fedoseev3e41f3c2019-08-07 05:38:31 +050034static 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
Serhiy Storchaka87d0b452015-02-03 11:30:10 +020055#define CHECK_CLOSED(self) \
Sergey Fedoseev3e41f3c2019-08-07 05:38:31 +050056 if (check_closed(self)) { \
Serhiy Storchaka87d0b452015-02-03 11:30:10 +020057 return NULL; \
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000058 }
59
Antoine Pitrou972ee132010-09-06 18:48:21 +000060#define CHECK_EXPORTS(self) \
Sergey Fedoseev3e41f3c2019-08-07 05:38:31 +050061 if (check_exports(self)) { \
Antoine Pitrou972ee132010-09-06 18:48:21 +000062 return NULL; \
63 }
64
Serhiy Storchaka38c30e62015-02-03 18:51:58 +020065#define SHARED_BUF(self) (Py_REFCNT((self)->buf) > 1)
Antoine Pitroucc66a732014-07-29 19:41:11 -040066
Antoine Pitrou972ee132010-09-06 18:48:21 +000067
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000068/* 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
Serhiy Storchakad7728ca2014-08-14 22:26:38 +030072scan_eol(bytesio *self, Py_ssize_t len)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000073{
Serhiy Storchakad7728ca2014-08-14 22:26:38 +030074 const char *start, *n;
75 Py_ssize_t maxlen;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000076
77 assert(self->buf != NULL);
Serhiy Storchaka4e63f7a2015-09-04 07:48:19 +030078 assert(self->pos >= 0);
79
80 if (self->pos >= self->string_size)
81 return 0;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000082
83 /* Move to the end of the line, up to the end of the string, s. */
Serhiy Storchakad7728ca2014-08-14 22:26:38 +030084 maxlen = self->string_size - self->pos;
85 if (len < 0 || len > maxlen)
86 len = maxlen;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000087
Serhiy Storchakad7728ca2014-08-14 22:26:38 +030088 if (len) {
Serhiy Storchaka4e63f7a2015-09-04 07:48:19 +030089 start = PyBytes_AS_STRING(self->buf) + self->pos;
Serhiy Storchakad7728ca2014-08-14 22:26:38 +030090 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 }
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000096 assert(len >= 0);
97 assert(self->pos < PY_SSIZE_T_MAX - len);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +000098
99 return len;
100}
101
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200102/* 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{
Serhiy Storchaka1ed017a2015-12-27 15:51:32 +0200108 PyObject *new_buf;
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200109 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);
Serhiy Storchakaf01e4082016-04-10 18:12:01 +0300117 Py_SETREF(self->buf, new_buf);
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200118 return 0;
119}
120
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000121/* 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
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000125resize_buffer(bytesio *self, size_t size)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000126{
127 /* Here, unsigned types are used to avoid dealing with signed integer
128 overflow, which is undefined in C. */
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200129 size_t alloc = PyBytes_GET_SIZE(self->buf);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000130
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;
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200157
158 if (SHARED_BUF(self)) {
159 if (unshare_buffer(self, alloc) < 0)
160 return -1;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000161 }
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200162 else {
163 if (_PyBytes_Resize(&self->buf, alloc) < 0)
164 return -1;
165 }
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000166
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
Sergey Fedoseev3e41f3c2019-08-07 05:38:31 +0500176 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)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000181{
Sergey Fedoseev3e41f3c2019-08-07 05:38:31 +0500182 if (check_closed(self)) {
183 return -1;
184 }
185 if (check_exports(self)) {
186 return -1;
187 }
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000188
Sergey Fedoseev3e41f3c2019-08-07 05:38:31 +0500189 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;
Serhiy Storchaka38c30e62015-02-03 18:51:58 +0200200 if (endpos > (size_t)PyBytes_GET_SIZE(self->buf)) {
Sergey Fedoseev3e41f3c2019-08-07 05:38:31 +0500201 if (resize_buffer(self, endpos) < 0) {
202 len = -1;
203 goto done;
204 }
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000205 }
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200206 else if (SHARED_BUF(self)) {
Sergey Fedoseev3e41f3c2019-08-07 05:38:31 +0500207 if (unshare_buffer(self, Py_MAX(endpos, (size_t)self->string_size)) < 0) {
208 len = -1;
209 goto done;
210 }
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200211 }
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000212
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 */
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200222 memset(PyBytes_AS_STRING(self->buf) + self->string_size, '\0',
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000223 (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. */
Sergey Fedoseev3e41f3c2019-08-07 05:38:31 +0500228 memcpy(PyBytes_AS_STRING(self->buf) + self->pos, buf.buf, len);
Serhiy Storchaka38c30e62015-02-03 18:51:58 +0200229 self->pos = endpos;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000230
231 /* Set the new length of the internal string if it has changed. */
Serhiy Storchaka38c30e62015-02-03 18:51:58 +0200232 if ((size_t)self->string_size < endpos) {
233 self->string_size = endpos;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000234 }
235
Sergey Fedoseev3e41f3c2019-08-07 05:38:31 +0500236 done:
237 PyBuffer_Release(&buf);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000238 return len;
239}
240
241static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +0200242bytesio_get_closed(bytesio *self, void *Py_UNUSED(ignored))
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000243{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000244 if (self->buf == NULL) {
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000245 Py_RETURN_TRUE;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000246 }
247 else {
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000248 Py_RETURN_FALSE;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000249 }
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000250}
251
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300252/*[clinic input]
253_io.BytesIO.readable
Antoine Pitrou1d857452012-09-05 20:11:49 +0200254
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300255Returns True if the IO object can be read.
256[clinic start generated code]*/
Antoine Pitrou1d857452012-09-05 20:11:49 +0200257
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000258static PyObject *
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300259_io_BytesIO_readable_impl(bytesio *self)
260/*[clinic end generated code: output=4e93822ad5b62263 input=96c5d0cccfb29f5c]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000261{
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200262 CHECK_CLOSED(self);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000263 Py_RETURN_TRUE;
264}
265
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300266/*[clinic input]
267_io.BytesIO.writable
268
269Returns True if the IO object can be written.
270[clinic start generated code]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000271
272static PyObject *
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300273_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]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000303{
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200304 CHECK_CLOSED(self);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000305 Py_RETURN_NONE;
306}
307
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300308/*[clinic input]
309_io.BytesIO.getbuffer
310
311Get a read-write view over the contents of the BytesIO object.
312[clinic start generated code]*/
Antoine Pitrou972ee132010-09-06 18:48:21 +0000313
314static PyObject *
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300315_io_BytesIO_getbuffer_impl(bytesio *self)
316/*[clinic end generated code: output=72cd7c6e13aa09ed input=8f738ef615865176]*/
Antoine Pitrou972ee132010-09-06 18:48:21 +0000317{
318 PyTypeObject *type = &_PyBytesIOBuffer_Type;
319 bytesiobuf *buf;
320 PyObject *view;
321
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200322 CHECK_CLOSED(self);
Antoine Pitrou972ee132010-09-06 18:48:21 +0000323
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
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300334/*[clinic input]
335_io.BytesIO.getvalue
336
337Retrieve the entire contents of the BytesIO object.
338[clinic start generated code]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000339
340static PyObject *
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300341_io_BytesIO_getvalue_impl(bytesio *self)
342/*[clinic end generated code: output=b3f6a3233c8fd628 input=4b403ac0af3973ed]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000343{
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200344 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;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000361}
362
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300363/*[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]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000370
371static PyObject *
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300372_io_BytesIO_isatty_impl(bytesio *self)
373/*[clinic end generated code: output=df67712e669f6c8f input=6f97f0985d13f827]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000374{
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200375 CHECK_CLOSED(self);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000376 Py_RETURN_FALSE;
377}
378
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300379/*[clinic input]
380_io.BytesIO.tell
381
382Current file position, an integer.
383[clinic start generated code]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000384
385static PyObject *
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300386_io_BytesIO_tell_impl(bytesio *self)
387/*[clinic end generated code: output=b54b0f93cd0e5e1d input=b106adf099cb3657]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000388{
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200389 CHECK_CLOSED(self);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000390 return PyLong_FromSsize_t(self->pos);
391}
392
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200393static PyObject *
394read_bytes(bytesio *self, Py_ssize_t size)
395{
Serhiy Storchaka8f87eef2020-04-12 14:58:27 +0300396 const char *output;
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200397
398 assert(self->buf != NULL);
Serhiy Storchakab9765ee2015-02-03 14:57:49 +0200399 assert(size <= self->string_size);
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200400 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
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300413/*[clinic input]
414_io.BytesIO.read
Serhiy Storchaka762bf402017-03-30 09:15:31 +0300415 size: Py_ssize_t(accept={int, NoneType}) = -1
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300416 /
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]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000423
424static PyObject *
orenmn74002542017-03-11 00:52:01 +0200425_io_BytesIO_read_impl(bytesio *self, Py_ssize_t size)
Serhiy Storchaka762bf402017-03-30 09:15:31 +0300426/*[clinic end generated code: output=9cc025f21c75bdd2 input=74344a39f431c3d7]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000427{
orenmn74002542017-03-11 00:52:01 +0200428 Py_ssize_t n;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000429
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200430 CHECK_CLOSED(self);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000431
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000432 /* 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
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200440 return read_bytes(self, size);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000441}
442
443
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300444/*[clinic input]
445_io.BytesIO.read1
Serhiy Storchaka762bf402017-03-30 09:15:31 +0300446 size: Py_ssize_t(accept={int, NoneType}) = -1
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300447 /
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]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000454
455static PyObject *
orenmn74002542017-03-11 00:52:01 +0200456_io_BytesIO_read1_impl(bytesio *self, Py_ssize_t size)
Serhiy Storchaka762bf402017-03-30 09:15:31 +0300457/*[clinic end generated code: output=d0f843285aa95f1c input=440a395bf9129ef5]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000458{
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300459 return _io_BytesIO_read_impl(self, size);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000460}
461
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300462/*[clinic input]
463_io.BytesIO.readline
Serhiy Storchaka762bf402017-03-30 09:15:31 +0300464 size: Py_ssize_t(accept={int, NoneType}) = -1
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300465 /
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]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000473
474static PyObject *
orenmn74002542017-03-11 00:52:01 +0200475_io_BytesIO_readline_impl(bytesio *self, Py_ssize_t size)
Serhiy Storchaka762bf402017-03-30 09:15:31 +0300476/*[clinic end generated code: output=4bff3c251df8ffcd input=e7c3fbd1744e2783]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000477{
orenmn74002542017-03-11 00:52:01 +0200478 Py_ssize_t n;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000479
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200480 CHECK_CLOSED(self);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000481
Serhiy Storchakad7728ca2014-08-14 22:26:38 +0300482 n = scan_eol(self, size);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000483
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200484 return read_bytes(self, n);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000485}
486
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300487/*[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]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000498
499static PyObject *
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300500_io_BytesIO_readlines_impl(bytesio *self, PyObject *arg)
501/*[clinic end generated code: output=09b8e34c880808ff input=691aa1314f2c2a87]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000502{
503 Py_ssize_t maxsize, size, n;
504 PyObject *result, *line;
Serhiy Storchaka8f87eef2020-04-12 14:58:27 +0300505 const char *output;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000506
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200507 CHECK_CLOSED(self);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000508
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000509 if (PyLong_Check(arg)) {
510 maxsize = PyLong_AsSsize_t(arg);
Benjamin Petersona8a93042008-09-30 02:18:09 +0000511 if (maxsize == -1 && PyErr_Occurred())
512 return NULL;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000513 }
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
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200529 output = PyBytes_AS_STRING(self->buf) + self->pos;
Serhiy Storchakad7728ca2014-08-14 22:26:38 +0300530 while ((n = scan_eol(self, -1)) != 0) {
531 self->pos += n;
Christian Heimes72b710a2008-05-26 13:28:38 +0000532 line = PyBytes_FromStringAndSize(output, n);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000533 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;
Serhiy Storchakad7728ca2014-08-14 22:26:38 +0300543 output += n;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000544 }
545 return result;
546
547 on_error:
548 Py_DECREF(result);
549 return NULL;
550}
551
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300552/*[clinic input]
553_io.BytesIO.readinto
Larry Hastingsdbfdc382015-05-04 06:59:46 -0700554 buffer: Py_buffer(accept={rwbuffer})
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300555 /
556
Martin Panter6bb91f32016-05-28 00:41:57 +0000557Read bytes into buffer.
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300558
559Returns number of bytes read (0 for EOF), or None if the object
Martin Panter119e5022016-04-16 09:28:57 +0000560is set not to block and has no data to read.
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300561[clinic start generated code]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000562
563static PyObject *
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300564_io_BytesIO_readinto_impl(bytesio *self, Py_buffer *buffer)
Martin Panter6bb91f32016-05-28 00:41:57 +0000565/*[clinic end generated code: output=a5d407217dcf0639 input=1424d0fdce857919]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000566{
Benjamin Petersonfa735552010-11-20 17:24:04 +0000567 Py_ssize_t len, n;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000568
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200569 CHECK_CLOSED(self);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000570
Benjamin Petersonfa735552010-11-20 17:24:04 +0000571 /* adjust invalid sizes */
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300572 len = buffer->len;
Benjamin Petersonfa735552010-11-20 17:24:04 +0000573 n = self->string_size - self->pos;
574 if (len > n) {
575 len = n;
576 if (len < 0)
577 len = 0;
578 }
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000579
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300580 memcpy(buffer->buf, PyBytes_AS_STRING(self->buf) + self->pos, len);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000581 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
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300588/*[clinic input]
589_io.BytesIO.truncate
Serhiy Storchaka762bf402017-03-30 09:15:31 +0300590 size: Py_ssize_t(accept={int, NoneType}, c_default="self->pos") = None
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300591 /
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]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000598
599static PyObject *
Serhiy Storchaka762bf402017-03-30 09:15:31 +0300600_io_BytesIO_truncate_impl(bytesio *self, Py_ssize_t size)
601/*[clinic end generated code: output=9ad17650c15fa09b input=423759dd42d2f7c1]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000602{
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200603 CHECK_CLOSED(self);
Antoine Pitrou972ee132010-09-06 18:48:21 +0000604 CHECK_EXPORTS(self);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000605
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000606 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 }
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000617
618 return PyLong_FromSsize_t(size);
619}
620
621static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000622bytesio_iternext(bytesio *self)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000623{
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000624 Py_ssize_t n;
625
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200626 CHECK_CLOSED(self);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000627
Serhiy Storchakad7728ca2014-08-14 22:26:38 +0300628 n = scan_eol(self, -1);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000629
Serhiy Storchakad7728ca2014-08-14 22:26:38 +0300630 if (n == 0)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000631 return NULL;
632
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200633 return read_bytes(self, n);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000634}
635
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300636/*[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]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000650
651static PyObject *
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300652_io_BytesIO_seek_impl(bytesio *self, Py_ssize_t pos, int whence)
653/*[clinic end generated code: output=c26204a68e9190e4 input=1e875e6ebc652948]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000654{
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200655 CHECK_CLOSED(self);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000656
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300657 if (pos < 0 && whence == 0) {
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000658 PyErr_Format(PyExc_ValueError,
659 "negative seek value %zd", pos);
660 return NULL;
661 }
662
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300663 /* 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) {
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000667 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 }
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300674 else if (whence == 2) {
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000675 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 }
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300682 else if (whence != 0) {
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000683 PyErr_Format(PyExc_ValueError,
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300684 "invalid whence (%i, should be 0, 1 or 2)", whence);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000685 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
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300695/*[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]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000704
705static PyObject *
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300706_io_BytesIO_write(bytesio *self, PyObject *b)
707/*[clinic end generated code: output=53316d99800a0b95 input=f5ec7c8c64ed720a]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000708{
Sergey Fedoseev3e41f3c2019-08-07 05:38:31 +0500709 Py_ssize_t n = write_bytes(self, b);
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300710 return n >= 0 ? PyLong_FromSsize_t(n) : NULL;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000711}
712
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300713/*[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]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000724
725static PyObject *
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300726_io_BytesIO_writelines(bytesio *self, PyObject *lines)
727/*[clinic end generated code: output=7f33aa3271c91752 input=e972539176fc8fc1]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000728{
729 PyObject *it, *item;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000730
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200731 CHECK_CLOSED(self);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000732
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300733 it = PyObject_GetIter(lines);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000734 if (it == NULL)
735 return NULL;
736
737 while ((item = PyIter_Next(it)) != NULL) {
Sergey Fedoseev3e41f3c2019-08-07 05:38:31 +0500738 Py_ssize_t ret = write_bytes(self, item);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000739 Py_DECREF(item);
Sergey Fedoseev3e41f3c2019-08-07 05:38:31 +0500740 if (ret < 0) {
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000741 Py_DECREF(it);
742 return NULL;
743 }
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000744 }
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
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300754/*[clinic input]
755_io.BytesIO.close
756
757Disable all I/O operations.
758[clinic start generated code]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000759
760static PyObject *
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300761_io_BytesIO_close_impl(bytesio *self)
762/*[clinic end generated code: output=1471bb9411af84a0 input=37e1f55556e61f60]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000763{
Serhiy Storchakac057c382015-02-03 02:00:18 +0200764 CHECK_EXPORTS(self);
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200765 Py_CLEAR(self->buf);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000766 Py_RETURN_NONE;
767}
768
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000769/* 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 *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530785bytesio_getstate(bytesio *self, PyObject *Py_UNUSED(ignored))
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000786{
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300787 PyObject *initvalue = _io_BytesIO_getvalue_impl(self);
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000788 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);
Stefan Krah96efdd42012-09-08 11:12:33 +0200799 if (dict == NULL) {
800 Py_DECREF(initvalue);
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000801 return NULL;
Stefan Krah96efdd42012-09-08 11:12:33 +0200802 }
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000803 }
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{
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200813 PyObject *result;
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000814 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. */
Serhiy Storchakafff9a312017-03-21 08:53:25 +0200823 if (!PyTuple_Check(state) || PyTuple_GET_SIZE(state) < 3) {
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000824 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 }
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200829 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;
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000834
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200835 /* Set the value of the internal buffer. If state[0] does not support the
836 buffer protocol, bytesio_write will raise the appropriate TypeError. */
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300837 result = _io_BytesIO_write(self, PyTuple_GET_ITEM(state, 0));
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200838 if (result == NULL)
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000839 return NULL;
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200840 Py_DECREF(result);
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000841
842 /* Set carefully the position value. Alternatively, we could use the seek
843 method instead of modifying self->pos directly to better protect the
Min ho Kim39d87b52019-08-31 06:21:19 +1000844 object internal state against erroneous (or malicious) inputs. */
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000845 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
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000886static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000887bytesio_dealloc(bytesio *self)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000888{
Alexandre Vassalottifc477042009-07-22 02:24:49 +0000889 _PyObject_GC_UNTRACK(self);
Antoine Pitrou972ee132010-09-06 18:48:21 +0000890 if (self->exports > 0) {
891 PyErr_SetString(PyExc_SystemError,
892 "deallocated BytesIO object has exported buffers");
893 PyErr_Print();
894 }
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200895 Py_CLEAR(self->buf);
Alexandre Vassalottifc477042009-07-22 02:24:49 +0000896 Py_CLEAR(self->dict);
897 if (self->weakreflist != NULL)
898 PyObject_ClearWeakRefs((PyObject *) self);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000899 Py_TYPE(self)->tp_free(self);
900}
901
902static PyObject *
903bytesio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
904{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000905 bytesio *self;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000906
907 assert(type != NULL && type->tp_alloc != NULL);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000908 self = (bytesio *)type->tp_alloc(type, 0);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000909 if (self == NULL)
910 return NULL;
911
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +0000912 /* tp_alloc initializes all the fields to zero. So we don't have to
913 initialize them here. */
914
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200915 self->buf = PyBytes_FromStringAndSize(NULL, 0);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000916 if (self->buf == NULL) {
917 Py_DECREF(self);
918 return PyErr_NoMemory();
919 }
920
921 return (PyObject *)self;
922}
923
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300924/*[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
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000931static int
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300932_io_BytesIO___init___impl(bytesio *self, PyObject *initvalue)
933/*[clinic end generated code: output=65c0c51e24c5b621 input=aac7f31b67bf0fb6]*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000934{
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200935 /* 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);
Serhiy Storchaka48842712016-04-06 09:45:48 +0300947 Py_XSETREF(self->buf, initvalue);
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200948 self->string_size = PyBytes_GET_SIZE(initvalue);
949 }
950 else {
951 PyObject *res;
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300952 res = _io_BytesIO_write(self, initvalue);
Serhiy Storchaka87d0b452015-02-03 11:30:10 +0200953 if (res == NULL)
954 return -1;
955 Py_DECREF(res);
956 self->pos = 0;
957 }
958 }
959
960 return 0;
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000961}
962
Antoine Pitrou8f328d02012-07-30 00:01:06 +0200963static PyObject *
964bytesio_sizeof(bytesio *self, void *unused)
965{
966 Py_ssize_t res;
967
Serhiy Storchaka5c4064e2015-12-19 20:05:25 +0200968 res = _PyObject_SIZE(Py_TYPE(self));
Zackery Spytz36dcaab2019-06-01 15:07:46 -0600969 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 }
Antoine Pitrou8f328d02012-07-30 00:01:06 +0200976 return PyLong_FromSsize_t(res);
977}
978
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000979static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000980bytesio_traverse(bytesio *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000981{
982 Py_VISIT(self->dict);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000983 return 0;
984}
985
986static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000987bytesio_clear(bytesio *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000988{
989 Py_CLEAR(self->dict);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000990 return 0;
991}
992
993
Serhiy Storchakaf24131f2015-04-16 11:19:43 +0300994#include "clinic/bytesio.c.h"
995
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000996static PyGetSetDef bytesio_getsetlist[] = {
997 {"closed", (getter)bytesio_get_closed, NULL,
998 "True if the file is closed."},
Benjamin Peterson1fea3212009-04-19 03:15:20 +0000999 {NULL}, /* sentinel */
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00001000};
1001
1002static struct PyMethodDef bytesio_methods[] = {
Serhiy Storchakaf24131f2015-04-16 11:19:43 +03001003 _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
Alexandre Vassalotticf76e1a2009-07-22 03:24:36 +00001021 {"__getstate__", (PyCFunction)bytesio_getstate, METH_NOARGS, NULL},
1022 {"__setstate__", (PyCFunction)bytesio_setstate, METH_O, NULL},
Antoine Pitrou8f328d02012-07-30 00:01:06 +02001023 {"__sizeof__", (PyCFunction)bytesio_sizeof, METH_NOARGS, NULL},
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00001024 {NULL, NULL} /* sentinel */
1025};
1026
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001027PyTypeObject PyBytesIO_Type = {
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00001028 PyVarObject_HEAD_INIT(NULL, 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001029 "_io.BytesIO", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001030 sizeof(bytesio), /*tp_basicsize*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00001031 0, /*tp_itemsize*/
1032 (destructor)bytesio_dealloc, /*tp_dealloc*/
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001033 0, /*tp_vectorcall_offset*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00001034 0, /*tp_getattr*/
1035 0, /*tp_setattr*/
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001036 0, /*tp_as_async*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00001037 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*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001047 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
1048 Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Serhiy Storchakaf24131f2015-04-16 11:19:43 +03001049 _io_BytesIO___init____doc__, /*tp_doc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001050 (traverseproc)bytesio_traverse, /*tp_traverse*/
1051 (inquiry)bytesio_clear, /*tp_clear*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00001052 0, /*tp_richcompare*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001053 offsetof(bytesio, weakreflist), /*tp_weaklistoffset*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00001054 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*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001063 offsetof(bytesio, dict), /*tp_dictoffset*/
Serhiy Storchakaf24131f2015-04-16 11:19:43 +03001064 _io_BytesIO___init__, /*tp_init*/
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00001065 0, /*tp_alloc*/
1066 bytesio_new, /*tp_new*/
1067};
Antoine Pitrou972ee132010-09-06 18:48:21 +00001068
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{
Antoine Pitrou972ee132010-09-06 18:48:21 +00001079 bytesio *b = (bytesio *) obj->source;
Stefan Krah650c1e82015-02-03 21:43:23 +01001080
1081 if (view == NULL) {
1082 PyErr_SetString(PyExc_BufferError,
1083 "bytesiobuf_getbuffer: view==NULL argument is obsolete");
1084 return -1;
1085 }
Serhiy Storchaka87d0b452015-02-03 11:30:10 +02001086 if (SHARED_BUF(b)) {
1087 if (unshare_buffer(b, b->string_size) < 0)
1088 return -1;
1089 }
Stefan Krah650c1e82015-02-03 21:43:23 +01001090
1091 /* cannot fail if view != NULL and readonly == 0 */
1092 (void)PyBuffer_FillInfo(view, (PyObject*)obj,
Serhiy Storchaka87d0b452015-02-03 11:30:10 +02001093 PyBytes_AS_STRING(b->buf), b->string_size,
Antoine Pitrou972ee132010-09-06 18:48:21 +00001094 0, flags);
Stefan Krah650c1e82015-02-03 21:43:23 +01001095 b->exports++;
1096 return 0;
Antoine Pitrou972ee132010-09-06 18:48:21 +00001097}
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{
INADA Naokia6296d32017-08-24 14:55:17 +09001116 /* bpo-31095: UnTrack is needed before calling any callbacks */
1117 PyObject_GC_UnTrack(self);
Antoine Pitrou972ee132010-09-06 18:48:21 +00001118 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
Vinay Sajip0b60f642019-10-15 08:26:12 +01001127Py_EXPORTED_SYMBOL PyTypeObject _PyBytesIOBuffer_Type = {
Antoine Pitrou972ee132010-09-06 18:48:21 +00001128 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*/
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001133 0, /*tp_vectorcall_offset*/
Antoine Pitrou972ee132010-09-06 18:48:21 +00001134 0, /*tp_getattr*/
1135 0, /*tp_setattr*/
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001136 0, /*tp_as_async*/
Antoine Pitrou972ee132010-09-06 18:48:21 +00001137 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};