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