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 |
35 | check_closed(bytesio *self) |
36 | { |
37 | if (self->buf == NULL) { |
38 | PyErr_SetString(PyExc_ValueError, "I/O operation on closed file." ); |
39 | return 1; |
40 | } |
41 | return 0; |
42 | } |
43 | |
44 | static int |
45 | check_exports(bytesio *self) |
46 | { |
47 | if (self->exports > 0) { |
48 | PyErr_SetString(PyExc_BufferError, |
49 | "Existing exports of data: object cannot be re-sized" ); |
50 | return 1; |
51 | } |
52 | return 0; |
53 | } |
54 | |
55 | #define CHECK_CLOSED(self) \ |
56 | if (check_closed(self)) { \ |
57 | return NULL; \ |
58 | } |
59 | |
60 | #define CHECK_EXPORTS(self) \ |
61 | if (check_exports(self)) { \ |
62 | return NULL; \ |
63 | } |
64 | |
65 | #define SHARED_BUF(self) (Py_REFCNT((self)->buf) > 1) |
66 | |
67 | |
68 | /* Internal routine to get a line from the buffer of a BytesIO |
69 | object. Returns the length between the current position to the |
70 | next newline character. */ |
71 | static Py_ssize_t |
72 | scan_eol(bytesio *self, Py_ssize_t len) |
73 | { |
74 | const char *start, *n; |
75 | Py_ssize_t maxlen; |
76 | |
77 | assert(self->buf != NULL); |
78 | assert(self->pos >= 0); |
79 | |
80 | if (self->pos >= self->string_size) |
81 | return 0; |
82 | |
83 | /* Move to the end of the line, up to the end of the string, s. */ |
84 | maxlen = self->string_size - self->pos; |
85 | if (len < 0 || len > maxlen) |
86 | len = maxlen; |
87 | |
88 | if (len) { |
89 | start = PyBytes_AS_STRING(self->buf) + self->pos; |
90 | n = memchr(start, '\n', len); |
91 | if (n) |
92 | /* Get the length from the current position to the end of |
93 | the line. */ |
94 | len = n - start + 1; |
95 | } |
96 | assert(len >= 0); |
97 | assert(self->pos < PY_SSIZE_T_MAX - len); |
98 | |
99 | return len; |
100 | } |
101 | |
102 | /* Internal routine for detaching the shared buffer of BytesIO objects. |
103 | The caller should ensure that the 'size' argument is non-negative and |
104 | not lesser than self->string_size. Returns 0 on success, -1 otherwise. */ |
105 | static int |
106 | unshare_buffer(bytesio *self, size_t size) |
107 | { |
108 | PyObject *new_buf; |
109 | assert(SHARED_BUF(self)); |
110 | assert(self->exports == 0); |
111 | assert(size >= (size_t)self->string_size); |
112 | new_buf = PyBytes_FromStringAndSize(NULL, size); |
113 | if (new_buf == NULL) |
114 | return -1; |
115 | memcpy(PyBytes_AS_STRING(new_buf), PyBytes_AS_STRING(self->buf), |
116 | self->string_size); |
117 | Py_SETREF(self->buf, new_buf); |
118 | return 0; |
119 | } |
120 | |
121 | /* Internal routine for changing the size of the buffer of BytesIO objects. |
122 | The caller should ensure that the 'size' argument is non-negative. Returns |
123 | 0 on success, -1 otherwise. */ |
124 | static int |
125 | resize_buffer(bytesio *self, size_t size) |
126 | { |
127 | /* Here, unsigned types are used to avoid dealing with signed integer |
128 | overflow, which is undefined in C. */ |
129 | size_t alloc = PyBytes_GET_SIZE(self->buf); |
130 | |
131 | assert(self->buf != NULL); |
132 | |
133 | /* For simplicity, stay in the range of the signed type. Anyway, Python |
134 | doesn't allow strings to be longer than this. */ |
135 | if (size > PY_SSIZE_T_MAX) |
136 | goto overflow; |
137 | |
138 | if (size < alloc / 2) { |
139 | /* Major downsize; resize down to exact size. */ |
140 | alloc = size + 1; |
141 | } |
142 | else if (size < alloc) { |
143 | /* Within allocated size; quick exit */ |
144 | return 0; |
145 | } |
146 | else if (size <= alloc * 1.125) { |
147 | /* Moderate upsize; overallocate similar to list_resize() */ |
148 | alloc = size + (size >> 3) + (size < 9 ? 3 : 6); |
149 | } |
150 | else { |
151 | /* Major upsize; resize up to exact size */ |
152 | alloc = size + 1; |
153 | } |
154 | |
155 | if (alloc > ((size_t)-1) / sizeof(char)) |
156 | goto overflow; |
157 | |
158 | if (SHARED_BUF(self)) { |
159 | if (unshare_buffer(self, alloc) < 0) |
160 | return -1; |
161 | } |
162 | else { |
163 | if (_PyBytes_Resize(&self->buf, alloc) < 0) |
164 | return -1; |
165 | } |
166 | |
167 | return 0; |
168 | |
169 | overflow: |
170 | PyErr_SetString(PyExc_OverflowError, |
171 | "new buffer size too large" ); |
172 | return -1; |
173 | } |
174 | |
175 | /* Internal routine for writing a string of bytes to the buffer of a BytesIO |
176 | object. Returns the number of bytes written, or -1 on error. |
177 | Inlining is disabled because it's significantly decreases performance |
178 | of writelines() in PGO build. */ |
179 | _Py_NO_INLINE static Py_ssize_t |
180 | write_bytes(bytesio *self, PyObject *b) |
181 | { |
182 | if (check_closed(self)) { |
183 | return -1; |
184 | } |
185 | if (check_exports(self)) { |
186 | return -1; |
187 | } |
188 | |
189 | Py_buffer buf; |
190 | if (PyObject_GetBuffer(b, &buf, PyBUF_CONTIG_RO) < 0) { |
191 | return -1; |
192 | } |
193 | Py_ssize_t len = buf.len; |
194 | if (len == 0) { |
195 | goto done; |
196 | } |
197 | |
198 | assert(self->pos >= 0); |
199 | size_t endpos = (size_t)self->pos + len; |
200 | if (endpos > (size_t)PyBytes_GET_SIZE(self->buf)) { |
201 | if (resize_buffer(self, endpos) < 0) { |
202 | len = -1; |
203 | goto done; |
204 | } |
205 | } |
206 | else if (SHARED_BUF(self)) { |
207 | if (unshare_buffer(self, Py_MAX(endpos, (size_t)self->string_size)) < 0) { |
208 | len = -1; |
209 | goto done; |
210 | } |
211 | } |
212 | |
213 | if (self->pos > self->string_size) { |
214 | /* In case of overseek, pad with null bytes the buffer region between |
215 | the end of stream and the current position. |
216 | |
217 | 0 lo string_size hi |
218 | | |<---used--->|<----------available----------->| |
219 | | | <--to pad-->|<---to write---> | |
220 | 0 buf position |
221 | */ |
222 | memset(PyBytes_AS_STRING(self->buf) + self->string_size, '\0', |
223 | (self->pos - self->string_size) * sizeof(char)); |
224 | } |
225 | |
226 | /* Copy the data to the internal buffer, overwriting some of the existing |
227 | data if self->pos < self->string_size. */ |
228 | memcpy(PyBytes_AS_STRING(self->buf) + self->pos, buf.buf, len); |
229 | self->pos = endpos; |
230 | |
231 | /* Set the new length of the internal string if it has changed. */ |
232 | if ((size_t)self->string_size < endpos) { |
233 | self->string_size = endpos; |
234 | } |
235 | |
236 | done: |
237 | PyBuffer_Release(&buf); |
238 | return len; |
239 | } |
240 | |
241 | static PyObject * |
242 | bytesio_get_closed(bytesio *self, void *Py_UNUSED(ignored)) |
243 | { |
244 | if (self->buf == NULL) { |
245 | Py_RETURN_TRUE; |
246 | } |
247 | else { |
248 | Py_RETURN_FALSE; |
249 | } |
250 | } |
251 | |
252 | /*[clinic input] |
253 | _io.BytesIO.readable |
254 | |
255 | Returns True if the IO object can be read. |
256 | [clinic start generated code]*/ |
257 | |
258 | static PyObject * |
259 | _io_BytesIO_readable_impl(bytesio *self) |
260 | /*[clinic end generated code: output=4e93822ad5b62263 input=96c5d0cccfb29f5c]*/ |
261 | { |
262 | CHECK_CLOSED(self); |
263 | Py_RETURN_TRUE; |
264 | } |
265 | |
266 | /*[clinic input] |
267 | _io.BytesIO.writable |
268 | |
269 | Returns True if the IO object can be written. |
270 | [clinic start generated code]*/ |
271 | |
272 | static PyObject * |
273 | _io_BytesIO_writable_impl(bytesio *self) |
274 | /*[clinic end generated code: output=64ff6a254b1150b8 input=700eed808277560a]*/ |
275 | { |
276 | CHECK_CLOSED(self); |
277 | Py_RETURN_TRUE; |
278 | } |
279 | |
280 | /*[clinic input] |
281 | _io.BytesIO.seekable |
282 | |
283 | Returns True if the IO object can be seeked. |
284 | [clinic start generated code]*/ |
285 | |
286 | static PyObject * |
287 | _io_BytesIO_seekable_impl(bytesio *self) |
288 | /*[clinic end generated code: output=6b417f46dcc09b56 input=9421f65627a344dd]*/ |
289 | { |
290 | CHECK_CLOSED(self); |
291 | Py_RETURN_TRUE; |
292 | } |
293 | |
294 | /*[clinic input] |
295 | _io.BytesIO.flush |
296 | |
297 | Does nothing. |
298 | [clinic start generated code]*/ |
299 | |
300 | static PyObject * |
301 | _io_BytesIO_flush_impl(bytesio *self) |
302 | /*[clinic end generated code: output=187e3d781ca134a0 input=561ea490be4581a7]*/ |
303 | { |
304 | CHECK_CLOSED(self); |
305 | Py_RETURN_NONE; |
306 | } |
307 | |
308 | /*[clinic input] |
309 | _io.BytesIO.getbuffer |
310 | |
311 | Get a read-write view over the contents of the BytesIO object. |
312 | [clinic start generated code]*/ |
313 | |
314 | static PyObject * |
315 | _io_BytesIO_getbuffer_impl(bytesio *self) |
316 | /*[clinic end generated code: output=72cd7c6e13aa09ed input=8f738ef615865176]*/ |
317 | { |
318 | PyTypeObject *type = &_PyBytesIOBuffer_Type; |
319 | bytesiobuf *buf; |
320 | PyObject *view; |
321 | |
322 | CHECK_CLOSED(self); |
323 | |
324 | buf = (bytesiobuf *) type->tp_alloc(type, 0); |
325 | if (buf == NULL) |
326 | return NULL; |
327 | Py_INCREF(self); |
328 | buf->source = self; |
329 | view = PyMemoryView_FromObject((PyObject *) buf); |
330 | Py_DECREF(buf); |
331 | return view; |
332 | } |
333 | |
334 | /*[clinic input] |
335 | _io.BytesIO.getvalue |
336 | |
337 | Retrieve the entire contents of the BytesIO object. |
338 | [clinic start generated code]*/ |
339 | |
340 | static PyObject * |
341 | _io_BytesIO_getvalue_impl(bytesio *self) |
342 | /*[clinic end generated code: output=b3f6a3233c8fd628 input=4b403ac0af3973ed]*/ |
343 | { |
344 | CHECK_CLOSED(self); |
345 | if (self->string_size <= 1 || self->exports > 0) |
346 | return PyBytes_FromStringAndSize(PyBytes_AS_STRING(self->buf), |
347 | self->string_size); |
348 | |
349 | if (self->string_size != PyBytes_GET_SIZE(self->buf)) { |
350 | if (SHARED_BUF(self)) { |
351 | if (unshare_buffer(self, self->string_size) < 0) |
352 | return NULL; |
353 | } |
354 | else { |
355 | if (_PyBytes_Resize(&self->buf, self->string_size) < 0) |
356 | return NULL; |
357 | } |
358 | } |
359 | Py_INCREF(self->buf); |
360 | return self->buf; |
361 | } |
362 | |
363 | /*[clinic input] |
364 | _io.BytesIO.isatty |
365 | |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 |
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 * |
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 |
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 * |
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 |
980 | bytesio_traverse(bytesio *self, visitproc visit, void *arg) |
981 | { |
982 | Py_VISIT(self->dict); |
983 | return 0; |
984 | } |
985 | |
986 | static int |
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 |
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 |
1100 | bytesiobuf_releasebuffer(bytesiobuf *obj, Py_buffer *view) |
1101 | { |
1102 | bytesio *b = (bytesio *) obj->source; |
1103 | b->exports--; |
1104 | } |
1105 | |
1106 | static int |
1107 | bytesiobuf_traverse(bytesiobuf *self, visitproc visit, void *arg) |
1108 | { |
1109 | Py_VISIT(self->source); |
1110 | return 0; |
1111 | } |
1112 | |
1113 | static void |
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 | |