1 /*
2 An implementation of Buffered I/O as defined by PEP 3116 - "New I/O"
3
4 Classes defined here: BufferedIOBase, BufferedReader, BufferedWriter,
5 BufferedRandom.
6
7 Written by Amaury Forgeot d'Arc and Antoine Pitrou
8 */
9
10 #define PY_SSIZE_T_CLEAN
11 #include "Python.h"
12 #include "pycore_object.h"
13 #include "structmember.h" // PyMemberDef
14 #include "_iomodule.h"
15
16 /*[clinic input]
17 module _io
18 class _io._BufferedIOBase "PyObject *" "&PyBufferedIOBase_Type"
19 class _io._Buffered "buffered *" "&PyBufferedIOBase_Type"
20 class _io.BufferedReader "buffered *" "&PyBufferedReader_Type"
21 class _io.BufferedWriter "buffered *" "&PyBufferedWriter_Type"
22 class _io.BufferedRWPair "rwpair *" "&PyBufferedRWPair_Type"
23 class _io.BufferedRandom "buffered *" "&PyBufferedRandom_Type"
24 [clinic start generated code]*/
25 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=59460b9c5639984d]*/
26
27 _Py_IDENTIFIER(close);
28 _Py_IDENTIFIER(_dealloc_warn);
29 _Py_IDENTIFIER(flush);
30 _Py_IDENTIFIER(isatty);
31 _Py_IDENTIFIER(mode);
32 _Py_IDENTIFIER(name);
33 _Py_IDENTIFIER(peek);
34 _Py_IDENTIFIER(read);
35 _Py_IDENTIFIER(read1);
36 _Py_IDENTIFIER(readable);
37 _Py_IDENTIFIER(readinto);
38 _Py_IDENTIFIER(readinto1);
39 _Py_IDENTIFIER(writable);
40 _Py_IDENTIFIER(write);
41
42 /*
43 * BufferedIOBase class, inherits from IOBase.
44 */
45 PyDoc_STRVAR(bufferediobase_doc,
46 "Base class for buffered IO objects.\n"
47 "\n"
48 "The main difference with RawIOBase is that the read() method\n"
49 "supports omitting the size argument, and does not have a default\n"
50 "implementation that defers to readinto().\n"
51 "\n"
52 "In addition, read(), readinto() and write() may raise\n"
53 "BlockingIOError if the underlying raw stream is in non-blocking\n"
54 "mode and not ready; unlike their raw counterparts, they will never\n"
55 "return None.\n"
56 "\n"
57 "A typical implementation should not inherit from a RawIOBase\n"
58 "implementation, but wrap one.\n"
59 );
60
61 static PyObject *
_bufferediobase_readinto_generic(PyObject * self,Py_buffer * buffer,char readinto1)62 _bufferediobase_readinto_generic(PyObject *self, Py_buffer *buffer, char readinto1)
63 {
64 Py_ssize_t len;
65 PyObject *data;
66
67 data = _PyObject_CallMethodId(self,
68 readinto1 ? &PyId_read1 : &PyId_read,
69 "n", buffer->len);
70 if (data == NULL)
71 return NULL;
72
73 if (!PyBytes_Check(data)) {
74 Py_DECREF(data);
75 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
76 return NULL;
77 }
78
79 len = PyBytes_GET_SIZE(data);
80 if (len > buffer->len) {
81 PyErr_Format(PyExc_ValueError,
82 "read() returned too much data: "
83 "%zd bytes requested, %zd returned",
84 buffer->len, len);
85 Py_DECREF(data);
86 return NULL;
87 }
88 memcpy(buffer->buf, PyBytes_AS_STRING(data), len);
89
90 Py_DECREF(data);
91
92 return PyLong_FromSsize_t(len);
93 }
94
95 /*[clinic input]
96 _io._BufferedIOBase.readinto
97 buffer: Py_buffer(accept={rwbuffer})
98 /
99 [clinic start generated code]*/
100
101 static PyObject *
_io__BufferedIOBase_readinto_impl(PyObject * self,Py_buffer * buffer)102 _io__BufferedIOBase_readinto_impl(PyObject *self, Py_buffer *buffer)
103 /*[clinic end generated code: output=8c8cda6684af8038 input=00a6b9a38f29830a]*/
104 {
105 return _bufferediobase_readinto_generic(self, buffer, 0);
106 }
107
108 /*[clinic input]
109 _io._BufferedIOBase.readinto1
110 buffer: Py_buffer(accept={rwbuffer})
111 /
112 [clinic start generated code]*/
113
114 static PyObject *
_io__BufferedIOBase_readinto1_impl(PyObject * self,Py_buffer * buffer)115 _io__BufferedIOBase_readinto1_impl(PyObject *self, Py_buffer *buffer)
116 /*[clinic end generated code: output=358623e4fd2b69d3 input=ebad75b4aadfb9be]*/
117 {
118 return _bufferediobase_readinto_generic(self, buffer, 1);
119 }
120
121 static PyObject *
bufferediobase_unsupported(const char * message)122 bufferediobase_unsupported(const char *message)
123 {
124 _PyIO_State *state = IO_STATE();
125 if (state != NULL)
126 PyErr_SetString(state->unsupported_operation, message);
127 return NULL;
128 }
129
130 /*[clinic input]
131 _io._BufferedIOBase.detach
132
133 Disconnect this buffer from its underlying raw stream and return it.
134
135 After the raw stream has been detached, the buffer is in an unusable
136 state.
137 [clinic start generated code]*/
138
139 static PyObject *
_io__BufferedIOBase_detach_impl(PyObject * self)140 _io__BufferedIOBase_detach_impl(PyObject *self)
141 /*[clinic end generated code: output=754977c8d10ed88c input=822427fb58fe4169]*/
142 {
143 return bufferediobase_unsupported("detach");
144 }
145
146 PyDoc_STRVAR(bufferediobase_read_doc,
147 "Read and return up to n bytes.\n"
148 "\n"
149 "If the argument is omitted, None, or negative, reads and\n"
150 "returns all data until EOF.\n"
151 "\n"
152 "If the argument is positive, and the underlying raw stream is\n"
153 "not 'interactive', multiple raw reads may be issued to satisfy\n"
154 "the byte count (unless EOF is reached first). But for\n"
155 "interactive raw streams (as well as sockets and pipes), at most\n"
156 "one raw read will be issued, and a short result does not imply\n"
157 "that EOF is imminent.\n"
158 "\n"
159 "Returns an empty bytes object on EOF.\n"
160 "\n"
161 "Returns None if the underlying raw stream was open in non-blocking\n"
162 "mode and no data is available at the moment.\n");
163
164 static PyObject *
bufferediobase_read(PyObject * self,PyObject * args)165 bufferediobase_read(PyObject *self, PyObject *args)
166 {
167 return bufferediobase_unsupported("read");
168 }
169
170 PyDoc_STRVAR(bufferediobase_read1_doc,
171 "Read and return up to n bytes, with at most one read() call\n"
172 "to the underlying raw stream. A short result does not imply\n"
173 "that EOF is imminent.\n"
174 "\n"
175 "Returns an empty bytes object on EOF.\n");
176
177 static PyObject *
bufferediobase_read1(PyObject * self,PyObject * args)178 bufferediobase_read1(PyObject *self, PyObject *args)
179 {
180 return bufferediobase_unsupported("read1");
181 }
182
183 PyDoc_STRVAR(bufferediobase_write_doc,
184 "Write the given buffer to the IO stream.\n"
185 "\n"
186 "Returns the number of bytes written, which is always the length of b\n"
187 "in bytes.\n"
188 "\n"
189 "Raises BlockingIOError if the buffer is full and the\n"
190 "underlying raw stream cannot accept more data at the moment.\n");
191
192 static PyObject *
bufferediobase_write(PyObject * self,PyObject * args)193 bufferediobase_write(PyObject *self, PyObject *args)
194 {
195 return bufferediobase_unsupported("write");
196 }
197
198
199 typedef struct {
200 PyObject_HEAD
201
202 PyObject *raw;
203 int ok; /* Initialized? */
204 int detached;
205 int readable;
206 int writable;
207 char finalizing;
208
209 /* True if this is a vanilla Buffered object (rather than a user derived
210 class) *and* the raw stream is a vanilla FileIO object. */
211 int fast_closed_checks;
212
213 /* Absolute position inside the raw stream (-1 if unknown). */
214 Py_off_t abs_pos;
215
216 /* A static buffer of size `buffer_size` */
217 char *buffer;
218 /* Current logical position in the buffer. */
219 Py_off_t pos;
220 /* Position of the raw stream in the buffer. */
221 Py_off_t raw_pos;
222
223 /* Just after the last buffered byte in the buffer, or -1 if the buffer
224 isn't ready for reading. */
225 Py_off_t read_end;
226
227 /* Just after the last byte actually written */
228 Py_off_t write_pos;
229 /* Just after the last byte waiting to be written, or -1 if the buffer
230 isn't ready for writing. */
231 Py_off_t write_end;
232
233 PyThread_type_lock lock;
234 volatile unsigned long owner;
235
236 Py_ssize_t buffer_size;
237 Py_ssize_t buffer_mask;
238
239 PyObject *dict;
240 PyObject *weakreflist;
241 } buffered;
242
243 /*
244 Implementation notes:
245
246 * BufferedReader, BufferedWriter and BufferedRandom try to share most
247 methods (this is helped by the members `readable` and `writable`, which
248 are initialized in the respective constructors)
249 * They also share a single buffer for reading and writing. This enables
250 interleaved reads and writes without flushing. It also makes the logic
251 a bit trickier to get right.
252 * The absolute position of the raw stream is cached, if possible, in the
253 `abs_pos` member. It must be updated every time an operation is done
254 on the raw stream. If not sure, it can be reinitialized by calling
255 _buffered_raw_tell(), which queries the raw stream (_buffered_raw_seek()
256 also does it). To read it, use RAW_TELL().
257 * Three helpers, _bufferedreader_raw_read, _bufferedwriter_raw_write and
258 _bufferedwriter_flush_unlocked do a lot of useful housekeeping.
259
260 NOTE: we should try to maintain block alignment of reads and writes to the
261 raw stream (according to the buffer size), but for now it is only done
262 in read() and friends.
263
264 */
265
266 /* These macros protect the buffered object against concurrent operations. */
267
268 static int
_enter_buffered_busy(buffered * self)269 _enter_buffered_busy(buffered *self)
270 {
271 int relax_locking;
272 PyLockStatus st;
273 if (self->owner == PyThread_get_thread_ident()) {
274 PyErr_Format(PyExc_RuntimeError,
275 "reentrant call inside %R", self);
276 return 0;
277 }
278 relax_locking = _Py_IsFinalizing();
279 Py_BEGIN_ALLOW_THREADS
280 if (!relax_locking)
281 st = PyThread_acquire_lock(self->lock, 1);
282 else {
283 /* When finalizing, we don't want a deadlock to happen with daemon
284 * threads abruptly shut down while they owned the lock.
285 * Therefore, only wait for a grace period (1 s.).
286 * Note that non-daemon threads have already exited here, so this
287 * shouldn't affect carefully written threaded I/O code.
288 */
289 st = PyThread_acquire_lock_timed(self->lock, (PY_TIMEOUT_T)1e6, 0);
290 }
291 Py_END_ALLOW_THREADS
292 if (relax_locking && st != PY_LOCK_ACQUIRED) {
293 PyObject *ascii = PyObject_ASCII((PyObject*)self);
294 _Py_FatalErrorFormat(__func__,
295 "could not acquire lock for %s at interpreter "
296 "shutdown, possibly due to daemon threads",
297 ascii ? PyUnicode_AsUTF8(ascii) : "<ascii(self) failed>");
298 }
299 return 1;
300 }
301
302 #define ENTER_BUFFERED(self) \
303 ( (PyThread_acquire_lock(self->lock, 0) ? \
304 1 : _enter_buffered_busy(self)) \
305 && (self->owner = PyThread_get_thread_ident(), 1) )
306
307 #define LEAVE_BUFFERED(self) \
308 do { \
309 self->owner = 0; \
310 PyThread_release_lock(self->lock); \
311 } while(0);
312
313 #define CHECK_INITIALIZED(self) \
314 if (self->ok <= 0) { \
315 if (self->detached) { \
316 PyErr_SetString(PyExc_ValueError, \
317 "raw stream has been detached"); \
318 } else { \
319 PyErr_SetString(PyExc_ValueError, \
320 "I/O operation on uninitialized object"); \
321 } \
322 return NULL; \
323 }
324
325 #define CHECK_INITIALIZED_INT(self) \
326 if (self->ok <= 0) { \
327 if (self->detached) { \
328 PyErr_SetString(PyExc_ValueError, \
329 "raw stream has been detached"); \
330 } else { \
331 PyErr_SetString(PyExc_ValueError, \
332 "I/O operation on uninitialized object"); \
333 } \
334 return -1; \
335 }
336
337 #define IS_CLOSED(self) \
338 (!self->buffer || \
339 (self->fast_closed_checks \
340 ? _PyFileIO_closed(self->raw) \
341 : buffered_closed(self)))
342
343 #define CHECK_CLOSED(self, error_msg) \
344 if (IS_CLOSED(self) & (Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t) == 0)) { \
345 PyErr_SetString(PyExc_ValueError, error_msg); \
346 return NULL; \
347 } \
348
349 #define VALID_READ_BUFFER(self) \
350 (self->readable && self->read_end != -1)
351
352 #define VALID_WRITE_BUFFER(self) \
353 (self->writable && self->write_end != -1)
354
355 #define ADJUST_POSITION(self, _new_pos) \
356 do { \
357 self->pos = _new_pos; \
358 if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
359 self->read_end = self->pos; \
360 } while(0)
361
362 #define READAHEAD(self) \
363 ((self->readable && VALID_READ_BUFFER(self)) \
364 ? (self->read_end - self->pos) : 0)
365
366 #define RAW_OFFSET(self) \
367 (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
368 && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
369
370 #define RAW_TELL(self) \
371 (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
372
373 #define MINUS_LAST_BLOCK(self, size) \
374 (self->buffer_mask ? \
375 (size & ~self->buffer_mask) : \
376 (self->buffer_size * (size / self->buffer_size)))
377
378
379 static void
buffered_dealloc(buffered * self)380 buffered_dealloc(buffered *self)
381 {
382 self->finalizing = 1;
383 if (_PyIOBase_finalize((PyObject *) self) < 0)
384 return;
385 _PyObject_GC_UNTRACK(self);
386 self->ok = 0;
387 if (self->weakreflist != NULL)
388 PyObject_ClearWeakRefs((PyObject *)self);
389 Py_CLEAR(self->raw);
390 if (self->buffer) {
391 PyMem_Free(self->buffer);
392 self->buffer = NULL;
393 }
394 if (self->lock) {
395 PyThread_free_lock(self->lock);
396 self->lock = NULL;
397 }
398 Py_CLEAR(self->dict);
399 Py_TYPE(self)->tp_free((PyObject *)self);
400 }
401
402 static PyObject *
buffered_sizeof(buffered * self,PyObject * Py_UNUSED (ignored))403 buffered_sizeof(buffered *self, PyObject *Py_UNUSED(ignored))
404 {
405 Py_ssize_t res;
406
407 res = _PyObject_SIZE(Py_TYPE(self));
408 if (self->buffer)
409 res += self->buffer_size;
410 return PyLong_FromSsize_t(res);
411 }
412
413 static int
buffered_traverse(buffered * self,visitproc visit,void * arg)414 buffered_traverse(buffered *self, visitproc visit, void *arg)
415 {
416 Py_VISIT(self->raw);
417 Py_VISIT(self->dict);
418 return 0;
419 }
420
421 static int
buffered_clear(buffered * self)422 buffered_clear(buffered *self)
423 {
424 self->ok = 0;
425 Py_CLEAR(self->raw);
426 Py_CLEAR(self->dict);
427 return 0;
428 }
429
430 /* Because this can call arbitrary code, it shouldn't be called when
431 the refcount is 0 (that is, not directly from tp_dealloc unless
432 the refcount has been temporarily re-incremented). */
433 static PyObject *
buffered_dealloc_warn(buffered * self,PyObject * source)434 buffered_dealloc_warn(buffered *self, PyObject *source)
435 {
436 if (self->ok && self->raw) {
437 PyObject *r;
438 r = _PyObject_CallMethodIdOneArg(self->raw, &PyId__dealloc_warn,
439 source);
440 if (r)
441 Py_DECREF(r);
442 else
443 PyErr_Clear();
444 }
445 Py_RETURN_NONE;
446 }
447
448 /*
449 * _BufferedIOMixin methods
450 * This is not a class, just a collection of methods that will be reused
451 * by BufferedReader and BufferedWriter
452 */
453
454 /* Flush and close */
455
456 static PyObject *
buffered_simple_flush(buffered * self,PyObject * args)457 buffered_simple_flush(buffered *self, PyObject *args)
458 {
459 CHECK_INITIALIZED(self)
460 return PyObject_CallMethodNoArgs(self->raw, _PyIO_str_flush);
461 }
462
463 static int
buffered_closed(buffered * self)464 buffered_closed(buffered *self)
465 {
466 int closed;
467 PyObject *res;
468 CHECK_INITIALIZED_INT(self)
469 res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
470 if (res == NULL)
471 return -1;
472 closed = PyObject_IsTrue(res);
473 Py_DECREF(res);
474 return closed;
475 }
476
477 static PyObject *
buffered_closed_get(buffered * self,void * context)478 buffered_closed_get(buffered *self, void *context)
479 {
480 CHECK_INITIALIZED(self)
481 return PyObject_GetAttr(self->raw, _PyIO_str_closed);
482 }
483
484 static PyObject *
buffered_close(buffered * self,PyObject * args)485 buffered_close(buffered *self, PyObject *args)
486 {
487 PyObject *res = NULL, *exc = NULL, *val, *tb;
488 int r;
489
490 CHECK_INITIALIZED(self)
491 if (!ENTER_BUFFERED(self))
492 return NULL;
493
494 r = buffered_closed(self);
495 if (r < 0)
496 goto end;
497 if (r > 0) {
498 res = Py_None;
499 Py_INCREF(res);
500 goto end;
501 }
502
503 if (self->finalizing) {
504 PyObject *r = buffered_dealloc_warn(self, (PyObject *) self);
505 if (r)
506 Py_DECREF(r);
507 else
508 PyErr_Clear();
509 }
510 /* flush() will most probably re-take the lock, so drop it first */
511 LEAVE_BUFFERED(self)
512 res = PyObject_CallMethodNoArgs((PyObject *)self, _PyIO_str_flush);
513 if (!ENTER_BUFFERED(self))
514 return NULL;
515 if (res == NULL)
516 PyErr_Fetch(&exc, &val, &tb);
517 else
518 Py_DECREF(res);
519
520 res = PyObject_CallMethodNoArgs(self->raw, _PyIO_str_close);
521
522 if (self->buffer) {
523 PyMem_Free(self->buffer);
524 self->buffer = NULL;
525 }
526
527 if (exc != NULL) {
528 _PyErr_ChainExceptions(exc, val, tb);
529 Py_CLEAR(res);
530 }
531
532 self->read_end = 0;
533 self->pos = 0;
534
535 end:
536 LEAVE_BUFFERED(self)
537 return res;
538 }
539
540 /* detach */
541
542 static PyObject *
buffered_detach(buffered * self,PyObject * Py_UNUSED (ignored))543 buffered_detach(buffered *self, PyObject *Py_UNUSED(ignored))
544 {
545 PyObject *raw, *res;
546 CHECK_INITIALIZED(self)
547 res = PyObject_CallMethodNoArgs((PyObject *)self, _PyIO_str_flush);
548 if (res == NULL)
549 return NULL;
550 Py_DECREF(res);
551 raw = self->raw;
552 self->raw = NULL;
553 self->detached = 1;
554 self->ok = 0;
555 return raw;
556 }
557
558 /* Inquiries */
559
560 static PyObject *
buffered_seekable(buffered * self,PyObject * Py_UNUSED (ignored))561 buffered_seekable(buffered *self, PyObject *Py_UNUSED(ignored))
562 {
563 CHECK_INITIALIZED(self)
564 return PyObject_CallMethodNoArgs(self->raw, _PyIO_str_seekable);
565 }
566
567 static PyObject *
buffered_readable(buffered * self,PyObject * Py_UNUSED (ignored))568 buffered_readable(buffered *self, PyObject *Py_UNUSED(ignored))
569 {
570 CHECK_INITIALIZED(self)
571 return PyObject_CallMethodNoArgs(self->raw, _PyIO_str_readable);
572 }
573
574 static PyObject *
buffered_writable(buffered * self,PyObject * Py_UNUSED (ignored))575 buffered_writable(buffered *self, PyObject *Py_UNUSED(ignored))
576 {
577 CHECK_INITIALIZED(self)
578 return PyObject_CallMethodNoArgs(self->raw, _PyIO_str_writable);
579 }
580
581 static PyObject *
buffered_name_get(buffered * self,void * context)582 buffered_name_get(buffered *self, void *context)
583 {
584 CHECK_INITIALIZED(self)
585 return _PyObject_GetAttrId(self->raw, &PyId_name);
586 }
587
588 static PyObject *
buffered_mode_get(buffered * self,void * context)589 buffered_mode_get(buffered *self, void *context)
590 {
591 CHECK_INITIALIZED(self)
592 return _PyObject_GetAttrId(self->raw, &PyId_mode);
593 }
594
595 /* Lower-level APIs */
596
597 static PyObject *
buffered_fileno(buffered * self,PyObject * Py_UNUSED (ignored))598 buffered_fileno(buffered *self, PyObject *Py_UNUSED(ignored))
599 {
600 CHECK_INITIALIZED(self)
601 return PyObject_CallMethodNoArgs(self->raw, _PyIO_str_fileno);
602 }
603
604 static PyObject *
buffered_isatty(buffered * self,PyObject * Py_UNUSED (ignored))605 buffered_isatty(buffered *self, PyObject *Py_UNUSED(ignored))
606 {
607 CHECK_INITIALIZED(self)
608 return PyObject_CallMethodNoArgs(self->raw, _PyIO_str_isatty);
609 }
610
611 /* Forward decls */
612 static PyObject *
613 _bufferedwriter_flush_unlocked(buffered *);
614 static Py_ssize_t
615 _bufferedreader_fill_buffer(buffered *self);
616 static void
617 _bufferedreader_reset_buf(buffered *self);
618 static void
619 _bufferedwriter_reset_buf(buffered *self);
620 static PyObject *
621 _bufferedreader_peek_unlocked(buffered *self);
622 static PyObject *
623 _bufferedreader_read_all(buffered *self);
624 static PyObject *
625 _bufferedreader_read_fast(buffered *self, Py_ssize_t);
626 static PyObject *
627 _bufferedreader_read_generic(buffered *self, Py_ssize_t);
628 static Py_ssize_t
629 _bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len);
630
631 /*
632 * Helpers
633 */
634
635 /* Sets the current error to BlockingIOError */
636 static void
_set_BlockingIOError(const char * msg,Py_ssize_t written)637 _set_BlockingIOError(const char *msg, Py_ssize_t written)
638 {
639 PyObject *err;
640 PyErr_Clear();
641 err = PyObject_CallFunction(PyExc_BlockingIOError, "isn",
642 errno, msg, written);
643 if (err)
644 PyErr_SetObject(PyExc_BlockingIOError, err);
645 Py_XDECREF(err);
646 }
647
648 /* Returns the address of the `written` member if a BlockingIOError was
649 raised, NULL otherwise. The error is always re-raised. */
650 static Py_ssize_t *
_buffered_check_blocking_error(void)651 _buffered_check_blocking_error(void)
652 {
653 PyObject *t, *v, *tb;
654 PyOSErrorObject *err;
655
656 PyErr_Fetch(&t, &v, &tb);
657 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
658 PyErr_Restore(t, v, tb);
659 return NULL;
660 }
661 err = (PyOSErrorObject *) v;
662 /* TODO: sanity check (err->written >= 0) */
663 PyErr_Restore(t, v, tb);
664 return &err->written;
665 }
666
667 static Py_off_t
_buffered_raw_tell(buffered * self)668 _buffered_raw_tell(buffered *self)
669 {
670 Py_off_t n;
671 PyObject *res;
672 res = PyObject_CallMethodNoArgs(self->raw, _PyIO_str_tell);
673 if (res == NULL)
674 return -1;
675 n = PyNumber_AsOff_t(res, PyExc_ValueError);
676 Py_DECREF(res);
677 if (n < 0) {
678 if (!PyErr_Occurred())
679 PyErr_Format(PyExc_OSError,
680 "Raw stream returned invalid position %" PY_PRIdOFF,
681 (PY_OFF_T_COMPAT)n);
682 return -1;
683 }
684 self->abs_pos = n;
685 return n;
686 }
687
688 static Py_off_t
_buffered_raw_seek(buffered * self,Py_off_t target,int whence)689 _buffered_raw_seek(buffered *self, Py_off_t target, int whence)
690 {
691 PyObject *res, *posobj, *whenceobj;
692 Py_off_t n;
693
694 posobj = PyLong_FromOff_t(target);
695 if (posobj == NULL)
696 return -1;
697 whenceobj = PyLong_FromLong(whence);
698 if (whenceobj == NULL) {
699 Py_DECREF(posobj);
700 return -1;
701 }
702 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
703 posobj, whenceobj, NULL);
704 Py_DECREF(posobj);
705 Py_DECREF(whenceobj);
706 if (res == NULL)
707 return -1;
708 n = PyNumber_AsOff_t(res, PyExc_ValueError);
709 Py_DECREF(res);
710 if (n < 0) {
711 if (!PyErr_Occurred())
712 PyErr_Format(PyExc_OSError,
713 "Raw stream returned invalid position %" PY_PRIdOFF,
714 (PY_OFF_T_COMPAT)n);
715 return -1;
716 }
717 self->abs_pos = n;
718 return n;
719 }
720
721 static int
_buffered_init(buffered * self)722 _buffered_init(buffered *self)
723 {
724 Py_ssize_t n;
725 if (self->buffer_size <= 0) {
726 PyErr_SetString(PyExc_ValueError,
727 "buffer size must be strictly positive");
728 return -1;
729 }
730 if (self->buffer)
731 PyMem_Free(self->buffer);
732 self->buffer = PyMem_Malloc(self->buffer_size);
733 if (self->buffer == NULL) {
734 PyErr_NoMemory();
735 return -1;
736 }
737 if (self->lock)
738 PyThread_free_lock(self->lock);
739 self->lock = PyThread_allocate_lock();
740 if (self->lock == NULL) {
741 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
742 return -1;
743 }
744 self->owner = 0;
745 /* Find out whether buffer_size is a power of 2 */
746 /* XXX is this optimization useful? */
747 for (n = self->buffer_size - 1; n & 1; n >>= 1)
748 ;
749 if (n == 0)
750 self->buffer_mask = self->buffer_size - 1;
751 else
752 self->buffer_mask = 0;
753 if (_buffered_raw_tell(self) == -1)
754 PyErr_Clear();
755 return 0;
756 }
757
758 /* Return 1 if an OSError with errno == EINTR is set (and then
759 clears the error indicator), 0 otherwise.
760 Should only be called when PyErr_Occurred() is true.
761 */
762 int
_PyIO_trap_eintr(void)763 _PyIO_trap_eintr(void)
764 {
765 static PyObject *eintr_int = NULL;
766 PyObject *typ, *val, *tb;
767 PyOSErrorObject *env_err;
768
769 if (eintr_int == NULL) {
770 eintr_int = PyLong_FromLong(EINTR);
771 assert(eintr_int != NULL);
772 }
773 if (!PyErr_ExceptionMatches(PyExc_OSError))
774 return 0;
775 PyErr_Fetch(&typ, &val, &tb);
776 PyErr_NormalizeException(&typ, &val, &tb);
777 env_err = (PyOSErrorObject *) val;
778 assert(env_err != NULL);
779 if (env_err->myerrno != NULL &&
780 PyObject_RichCompareBool(env_err->myerrno, eintr_int, Py_EQ) > 0) {
781 Py_DECREF(typ);
782 Py_DECREF(val);
783 Py_XDECREF(tb);
784 return 1;
785 }
786 /* This silences any error set by PyObject_RichCompareBool() */
787 PyErr_Restore(typ, val, tb);
788 return 0;
789 }
790
791 /*
792 * Shared methods and wrappers
793 */
794
795 static PyObject *
buffered_flush_and_rewind_unlocked(buffered * self)796 buffered_flush_and_rewind_unlocked(buffered *self)
797 {
798 PyObject *res;
799
800 res = _bufferedwriter_flush_unlocked(self);
801 if (res == NULL)
802 return NULL;
803 Py_DECREF(res);
804
805 if (self->readable) {
806 /* Rewind the raw stream so that its position corresponds to
807 the current logical position. */
808 Py_off_t n;
809 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
810 _bufferedreader_reset_buf(self);
811 if (n == -1)
812 return NULL;
813 }
814 Py_RETURN_NONE;
815 }
816
817 static PyObject *
buffered_flush(buffered * self,PyObject * args)818 buffered_flush(buffered *self, PyObject *args)
819 {
820 PyObject *res;
821
822 CHECK_INITIALIZED(self)
823 CHECK_CLOSED(self, "flush of closed file")
824
825 if (!ENTER_BUFFERED(self))
826 return NULL;
827 res = buffered_flush_and_rewind_unlocked(self);
828 LEAVE_BUFFERED(self)
829
830 return res;
831 }
832
833 /*[clinic input]
834 _io._Buffered.peek
835 size: Py_ssize_t = 0
836 /
837
838 [clinic start generated code]*/
839
840 static PyObject *
_io__Buffered_peek_impl(buffered * self,Py_ssize_t size)841 _io__Buffered_peek_impl(buffered *self, Py_ssize_t size)
842 /*[clinic end generated code: output=ba7a097ca230102b input=37ffb97d06ff4adb]*/
843 {
844 PyObject *res = NULL;
845
846 CHECK_INITIALIZED(self)
847 CHECK_CLOSED(self, "peek of closed file")
848
849 if (!ENTER_BUFFERED(self))
850 return NULL;
851
852 if (self->writable) {
853 res = buffered_flush_and_rewind_unlocked(self);
854 if (res == NULL)
855 goto end;
856 Py_CLEAR(res);
857 }
858 res = _bufferedreader_peek_unlocked(self);
859
860 end:
861 LEAVE_BUFFERED(self)
862 return res;
863 }
864
865 /*[clinic input]
866 _io._Buffered.read
867 size as n: Py_ssize_t(accept={int, NoneType}) = -1
868 /
869 [clinic start generated code]*/
870
871 static PyObject *
_io__Buffered_read_impl(buffered * self,Py_ssize_t n)872 _io__Buffered_read_impl(buffered *self, Py_ssize_t n)
873 /*[clinic end generated code: output=f41c78bb15b9bbe9 input=7df81e82e08a68a2]*/
874 {
875 PyObject *res;
876
877 CHECK_INITIALIZED(self)
878 if (n < -1) {
879 PyErr_SetString(PyExc_ValueError,
880 "read length must be non-negative or -1");
881 return NULL;
882 }
883
884 CHECK_CLOSED(self, "read of closed file")
885
886 if (n == -1) {
887 /* The number of bytes is unspecified, read until the end of stream */
888 if (!ENTER_BUFFERED(self))
889 return NULL;
890 res = _bufferedreader_read_all(self);
891 }
892 else {
893 res = _bufferedreader_read_fast(self, n);
894 if (res != Py_None)
895 return res;
896 Py_DECREF(res);
897 if (!ENTER_BUFFERED(self))
898 return NULL;
899 res = _bufferedreader_read_generic(self, n);
900 }
901
902 LEAVE_BUFFERED(self)
903 return res;
904 }
905
906 /*[clinic input]
907 _io._Buffered.read1
908 size as n: Py_ssize_t = -1
909 /
910 [clinic start generated code]*/
911
912 static PyObject *
_io__Buffered_read1_impl(buffered * self,Py_ssize_t n)913 _io__Buffered_read1_impl(buffered *self, Py_ssize_t n)
914 /*[clinic end generated code: output=bcc4fb4e54d103a3 input=7d22de9630b61774]*/
915 {
916 Py_ssize_t have, r;
917 PyObject *res = NULL;
918
919 CHECK_INITIALIZED(self)
920 if (n < 0) {
921 n = self->buffer_size;
922 }
923
924 CHECK_CLOSED(self, "read of closed file")
925
926 if (n == 0)
927 return PyBytes_FromStringAndSize(NULL, 0);
928
929 /* Return up to n bytes. If at least one byte is buffered, we
930 only return buffered bytes. Otherwise, we do one raw read. */
931
932 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
933 if (have > 0) {
934 n = Py_MIN(have, n);
935 res = _bufferedreader_read_fast(self, n);
936 assert(res != Py_None);
937 return res;
938 }
939 res = PyBytes_FromStringAndSize(NULL, n);
940 if (res == NULL)
941 return NULL;
942 if (!ENTER_BUFFERED(self)) {
943 Py_DECREF(res);
944 return NULL;
945 }
946 _bufferedreader_reset_buf(self);
947 r = _bufferedreader_raw_read(self, PyBytes_AS_STRING(res), n);
948 LEAVE_BUFFERED(self)
949 if (r == -1) {
950 Py_DECREF(res);
951 return NULL;
952 }
953 if (r == -2)
954 r = 0;
955 if (n > r)
956 _PyBytes_Resize(&res, r);
957 return res;
958 }
959
960 static PyObject *
_buffered_readinto_generic(buffered * self,Py_buffer * buffer,char readinto1)961 _buffered_readinto_generic(buffered *self, Py_buffer *buffer, char readinto1)
962 {
963 Py_ssize_t n, written = 0, remaining;
964 PyObject *res = NULL;
965
966 CHECK_INITIALIZED(self)
967 CHECK_CLOSED(self, "readinto of closed file")
968
969 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
970 if (n > 0) {
971 if (n >= buffer->len) {
972 memcpy(buffer->buf, self->buffer + self->pos, buffer->len);
973 self->pos += buffer->len;
974 return PyLong_FromSsize_t(buffer->len);
975 }
976 memcpy(buffer->buf, self->buffer + self->pos, n);
977 self->pos += n;
978 written = n;
979 }
980
981 if (!ENTER_BUFFERED(self))
982 return NULL;
983
984 if (self->writable) {
985 res = buffered_flush_and_rewind_unlocked(self);
986 if (res == NULL)
987 goto end;
988 Py_CLEAR(res);
989 }
990
991 _bufferedreader_reset_buf(self);
992 self->pos = 0;
993
994 for (remaining = buffer->len - written;
995 remaining > 0;
996 written += n, remaining -= n) {
997 /* If remaining bytes is larger than internal buffer size, copy
998 * directly into caller's buffer. */
999 if (remaining > self->buffer_size) {
1000 n = _bufferedreader_raw_read(self, (char *) buffer->buf + written,
1001 remaining);
1002 }
1003
1004 /* In readinto1 mode, we do not want to fill the internal
1005 buffer if we already have some data to return */
1006 else if (!(readinto1 && written)) {
1007 n = _bufferedreader_fill_buffer(self);
1008 if (n > 0) {
1009 if (n > remaining)
1010 n = remaining;
1011 memcpy((char *) buffer->buf + written,
1012 self->buffer + self->pos, n);
1013 self->pos += n;
1014 continue; /* short circuit */
1015 }
1016 }
1017 else
1018 n = 0;
1019
1020 if (n == 0 || (n == -2 && written > 0))
1021 break;
1022 if (n < 0) {
1023 if (n == -2) {
1024 Py_INCREF(Py_None);
1025 res = Py_None;
1026 }
1027 goto end;
1028 }
1029
1030 /* At most one read in readinto1 mode */
1031 if (readinto1) {
1032 written += n;
1033 break;
1034 }
1035 }
1036 res = PyLong_FromSsize_t(written);
1037
1038 end:
1039 LEAVE_BUFFERED(self);
1040 return res;
1041 }
1042
1043 /*[clinic input]
1044 _io._Buffered.readinto
1045 buffer: Py_buffer(accept={rwbuffer})
1046 /
1047 [clinic start generated code]*/
1048
1049 static PyObject *
_io__Buffered_readinto_impl(buffered * self,Py_buffer * buffer)1050 _io__Buffered_readinto_impl(buffered *self, Py_buffer *buffer)
1051 /*[clinic end generated code: output=bcb376580b1d8170 input=ed6b98b7a20a3008]*/
1052 {
1053 return _buffered_readinto_generic(self, buffer, 0);
1054 }
1055
1056 /*[clinic input]
1057 _io._Buffered.readinto1
1058 buffer: Py_buffer(accept={rwbuffer})
1059 /
1060 [clinic start generated code]*/
1061
1062 static PyObject *
_io__Buffered_readinto1_impl(buffered * self,Py_buffer * buffer)1063 _io__Buffered_readinto1_impl(buffered *self, Py_buffer *buffer)
1064 /*[clinic end generated code: output=6e5c6ac5868205d6 input=4455c5d55fdf1687]*/
1065 {
1066 return _buffered_readinto_generic(self, buffer, 1);
1067 }
1068
1069
1070 static PyObject *
_buffered_readline(buffered * self,Py_ssize_t limit)1071 _buffered_readline(buffered *self, Py_ssize_t limit)
1072 {
1073 PyObject *res = NULL;
1074 PyObject *chunks = NULL;
1075 Py_ssize_t n, written = 0;
1076 const char *start, *s, *end;
1077
1078 CHECK_CLOSED(self, "readline of closed file")
1079
1080 /* First, try to find a line in the buffer. This can run unlocked because
1081 the calls to the C API are simple enough that they can't trigger
1082 any thread switch. */
1083 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1084 if (limit >= 0 && n > limit)
1085 n = limit;
1086 start = self->buffer + self->pos;
1087 s = memchr(start, '\n', n);
1088 if (s != NULL) {
1089 res = PyBytes_FromStringAndSize(start, s - start + 1);
1090 if (res != NULL)
1091 self->pos += s - start + 1;
1092 goto end_unlocked;
1093 }
1094 if (n == limit) {
1095 res = PyBytes_FromStringAndSize(start, n);
1096 if (res != NULL)
1097 self->pos += n;
1098 goto end_unlocked;
1099 }
1100
1101 if (!ENTER_BUFFERED(self))
1102 goto end_unlocked;
1103
1104 /* Now we try to get some more from the raw stream */
1105 chunks = PyList_New(0);
1106 if (chunks == NULL)
1107 goto end;
1108 if (n > 0) {
1109 res = PyBytes_FromStringAndSize(start, n);
1110 if (res == NULL)
1111 goto end;
1112 if (PyList_Append(chunks, res) < 0) {
1113 Py_CLEAR(res);
1114 goto end;
1115 }
1116 Py_CLEAR(res);
1117 written += n;
1118 self->pos += n;
1119 if (limit >= 0)
1120 limit -= n;
1121 }
1122 if (self->writable) {
1123 PyObject *r = buffered_flush_and_rewind_unlocked(self);
1124 if (r == NULL)
1125 goto end;
1126 Py_DECREF(r);
1127 }
1128
1129 for (;;) {
1130 _bufferedreader_reset_buf(self);
1131 n = _bufferedreader_fill_buffer(self);
1132 if (n == -1)
1133 goto end;
1134 if (n <= 0)
1135 break;
1136 if (limit >= 0 && n > limit)
1137 n = limit;
1138 start = self->buffer;
1139 end = start + n;
1140 s = start;
1141 while (s < end) {
1142 if (*s++ == '\n') {
1143 res = PyBytes_FromStringAndSize(start, s - start);
1144 if (res == NULL)
1145 goto end;
1146 self->pos = s - start;
1147 goto found;
1148 }
1149 }
1150 res = PyBytes_FromStringAndSize(start, n);
1151 if (res == NULL)
1152 goto end;
1153 if (n == limit) {
1154 self->pos = n;
1155 break;
1156 }
1157 if (PyList_Append(chunks, res) < 0) {
1158 Py_CLEAR(res);
1159 goto end;
1160 }
1161 Py_CLEAR(res);
1162 written += n;
1163 if (limit >= 0)
1164 limit -= n;
1165 }
1166 found:
1167 if (res != NULL && PyList_Append(chunks, res) < 0) {
1168 Py_CLEAR(res);
1169 goto end;
1170 }
1171 Py_XSETREF(res, _PyBytes_Join(_PyIO_empty_bytes, chunks));
1172
1173 end:
1174 LEAVE_BUFFERED(self)
1175 end_unlocked:
1176 Py_XDECREF(chunks);
1177 return res;
1178 }
1179
1180 /*[clinic input]
1181 _io._Buffered.readline
1182 size: Py_ssize_t(accept={int, NoneType}) = -1
1183 /
1184 [clinic start generated code]*/
1185
1186 static PyObject *
_io__Buffered_readline_impl(buffered * self,Py_ssize_t size)1187 _io__Buffered_readline_impl(buffered *self, Py_ssize_t size)
1188 /*[clinic end generated code: output=24dd2aa6e33be83c input=673b6240e315ef8a]*/
1189 {
1190 CHECK_INITIALIZED(self)
1191 return _buffered_readline(self, size);
1192 }
1193
1194
1195 static PyObject *
buffered_tell(buffered * self,PyObject * Py_UNUSED (ignored))1196 buffered_tell(buffered *self, PyObject *Py_UNUSED(ignored))
1197 {
1198 Py_off_t pos;
1199
1200 CHECK_INITIALIZED(self)
1201 pos = _buffered_raw_tell(self);
1202 if (pos == -1)
1203 return NULL;
1204 pos -= RAW_OFFSET(self);
1205 /* TODO: sanity check (pos >= 0) */
1206 return PyLong_FromOff_t(pos);
1207 }
1208
1209 /*[clinic input]
1210 _io._Buffered.seek
1211 target as targetobj: object
1212 whence: int = 0
1213 /
1214 [clinic start generated code]*/
1215
1216 static PyObject *
_io__Buffered_seek_impl(buffered * self,PyObject * targetobj,int whence)1217 _io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence)
1218 /*[clinic end generated code: output=7ae0e8dc46efdefb input=a9c4920bfcba6163]*/
1219 {
1220 Py_off_t target, n;
1221 PyObject *res = NULL;
1222
1223 CHECK_INITIALIZED(self)
1224
1225 /* Do some error checking instead of trusting OS 'seek()'
1226 ** error detection, just in case.
1227 */
1228 if ((whence < 0 || whence >2)
1229 #ifdef SEEK_HOLE
1230 && (whence != SEEK_HOLE)
1231 #endif
1232 #ifdef SEEK_DATA
1233 && (whence != SEEK_DATA)
1234 #endif
1235 ) {
1236 PyErr_Format(PyExc_ValueError,
1237 "whence value %d unsupported", whence);
1238 return NULL;
1239 }
1240
1241 CHECK_CLOSED(self, "seek of closed file")
1242
1243 if (_PyIOBase_check_seekable(self->raw, Py_True) == NULL)
1244 return NULL;
1245
1246 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1247 if (target == -1 && PyErr_Occurred())
1248 return NULL;
1249
1250 /* SEEK_SET and SEEK_CUR are special because we could seek inside the
1251 buffer. Other whence values must be managed without this optimization.
1252 Some Operating Systems can provide additional values, like
1253 SEEK_HOLE/SEEK_DATA. */
1254 if (((whence == 0) || (whence == 1)) && self->readable) {
1255 Py_off_t current, avail;
1256 /* Check if seeking leaves us inside the current buffer,
1257 so as to return quickly if possible. Also, we needn't take the
1258 lock in this fast path.
1259 Don't know how to do that when whence == 2, though. */
1260 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1261 state at this point. */
1262 current = RAW_TELL(self);
1263 avail = READAHEAD(self);
1264 if (avail > 0) {
1265 Py_off_t offset;
1266 if (whence == 0)
1267 offset = target - (current - RAW_OFFSET(self));
1268 else
1269 offset = target;
1270 if (offset >= -self->pos && offset <= avail) {
1271 self->pos += offset;
1272 return PyLong_FromOff_t(current - avail + offset);
1273 }
1274 }
1275 }
1276
1277 if (!ENTER_BUFFERED(self))
1278 return NULL;
1279
1280 /* Fallback: invoke raw seek() method and clear buffer */
1281 if (self->writable) {
1282 res = _bufferedwriter_flush_unlocked(self);
1283 if (res == NULL)
1284 goto end;
1285 Py_CLEAR(res);
1286 }
1287
1288 /* TODO: align on block boundary and read buffer if needed? */
1289 if (whence == 1)
1290 target -= RAW_OFFSET(self);
1291 n = _buffered_raw_seek(self, target, whence);
1292 if (n == -1)
1293 goto end;
1294 self->raw_pos = -1;
1295 res = PyLong_FromOff_t(n);
1296 if (res != NULL && self->readable)
1297 _bufferedreader_reset_buf(self);
1298
1299 end:
1300 LEAVE_BUFFERED(self)
1301 return res;
1302 }
1303
1304 /*[clinic input]
1305 _io._Buffered.truncate
1306 pos: object = None
1307 /
1308 [clinic start generated code]*/
1309
1310 static PyObject *
_io__Buffered_truncate_impl(buffered * self,PyObject * pos)1311 _io__Buffered_truncate_impl(buffered *self, PyObject *pos)
1312 /*[clinic end generated code: output=667ca03c60c270de input=8a1be34d57cca2d3]*/
1313 {
1314 PyObject *res = NULL;
1315
1316 CHECK_INITIALIZED(self)
1317 CHECK_CLOSED(self, "truncate of closed file")
1318 if (!self->writable) {
1319 return bufferediobase_unsupported("truncate");
1320 }
1321 if (!ENTER_BUFFERED(self))
1322 return NULL;
1323
1324 res = buffered_flush_and_rewind_unlocked(self);
1325 if (res == NULL) {
1326 goto end;
1327 }
1328 Py_CLEAR(res);
1329
1330 res = PyObject_CallMethodOneArg(self->raw, _PyIO_str_truncate, pos);
1331 if (res == NULL)
1332 goto end;
1333 /* Reset cached position */
1334 if (_buffered_raw_tell(self) == -1)
1335 PyErr_Clear();
1336
1337 end:
1338 LEAVE_BUFFERED(self)
1339 return res;
1340 }
1341
1342 static PyObject *
buffered_iternext(buffered * self)1343 buffered_iternext(buffered *self)
1344 {
1345 PyObject *line;
1346 PyTypeObject *tp;
1347
1348 CHECK_INITIALIZED(self);
1349
1350 tp = Py_TYPE(self);
1351 if (tp == &PyBufferedReader_Type ||
1352 tp == &PyBufferedRandom_Type) {
1353 /* Skip method call overhead for speed */
1354 line = _buffered_readline(self, -1);
1355 }
1356 else {
1357 line = PyObject_CallMethodNoArgs((PyObject *)self,
1358 _PyIO_str_readline);
1359 if (line && !PyBytes_Check(line)) {
1360 PyErr_Format(PyExc_OSError,
1361 "readline() should have returned a bytes object, "
1362 "not '%.200s'", Py_TYPE(line)->tp_name);
1363 Py_DECREF(line);
1364 return NULL;
1365 }
1366 }
1367
1368 if (line == NULL)
1369 return NULL;
1370
1371 if (PyBytes_GET_SIZE(line) == 0) {
1372 /* Reached EOF or would have blocked */
1373 Py_DECREF(line);
1374 return NULL;
1375 }
1376
1377 return line;
1378 }
1379
1380 static PyObject *
buffered_repr(buffered * self)1381 buffered_repr(buffered *self)
1382 {
1383 PyObject *nameobj, *res;
1384
1385 if (_PyObject_LookupAttrId((PyObject *) self, &PyId_name, &nameobj) < 0) {
1386 if (!PyErr_ExceptionMatches(PyExc_ValueError)) {
1387 return NULL;
1388 }
1389 /* Ignore ValueError raised if the underlying stream was detached */
1390 PyErr_Clear();
1391 }
1392 if (nameobj == NULL) {
1393 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1394 }
1395 else {
1396 int status = Py_ReprEnter((PyObject *)self);
1397 res = NULL;
1398 if (status == 0) {
1399 res = PyUnicode_FromFormat("<%s name=%R>",
1400 Py_TYPE(self)->tp_name, nameobj);
1401 Py_ReprLeave((PyObject *)self);
1402 }
1403 else if (status > 0) {
1404 PyErr_Format(PyExc_RuntimeError,
1405 "reentrant call inside %s.__repr__",
1406 Py_TYPE(self)->tp_name);
1407 }
1408 Py_DECREF(nameobj);
1409 }
1410 return res;
1411 }
1412
1413 /*
1414 * class BufferedReader
1415 */
1416
_bufferedreader_reset_buf(buffered * self)1417 static void _bufferedreader_reset_buf(buffered *self)
1418 {
1419 self->read_end = -1;
1420 }
1421
1422 /*[clinic input]
1423 _io.BufferedReader.__init__
1424 raw: object
1425 buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
1426
1427 Create a new buffered reader using the given readable raw IO object.
1428 [clinic start generated code]*/
1429
1430 static int
_io_BufferedReader___init___impl(buffered * self,PyObject * raw,Py_ssize_t buffer_size)1431 _io_BufferedReader___init___impl(buffered *self, PyObject *raw,
1432 Py_ssize_t buffer_size)
1433 /*[clinic end generated code: output=cddcfefa0ed294c4 input=fb887e06f11b4e48]*/
1434 {
1435 self->ok = 0;
1436 self->detached = 0;
1437
1438 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
1439 return -1;
1440
1441 Py_INCREF(raw);
1442 Py_XSETREF(self->raw, raw);
1443 self->buffer_size = buffer_size;
1444 self->readable = 1;
1445 self->writable = 0;
1446
1447 if (_buffered_init(self) < 0)
1448 return -1;
1449 _bufferedreader_reset_buf(self);
1450
1451 self->fast_closed_checks = (Py_IS_TYPE(self, &PyBufferedReader_Type) &&
1452 Py_IS_TYPE(raw, &PyFileIO_Type));
1453
1454 self->ok = 1;
1455 return 0;
1456 }
1457
1458 static Py_ssize_t
_bufferedreader_raw_read(buffered * self,char * start,Py_ssize_t len)1459 _bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
1460 {
1461 Py_buffer buf;
1462 PyObject *memobj, *res;
1463 Py_ssize_t n;
1464 /* NOTE: the buffer needn't be released as its object is NULL. */
1465 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1466 return -1;
1467 memobj = PyMemoryView_FromBuffer(&buf);
1468 if (memobj == NULL)
1469 return -1;
1470 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1471 occurs so we needn't do it ourselves.
1472 We then retry reading, ignoring the signal if no handler has
1473 raised (see issue #10956).
1474 */
1475 do {
1476 res = PyObject_CallMethodOneArg(self->raw, _PyIO_str_readinto, memobj);
1477 } while (res == NULL && _PyIO_trap_eintr());
1478 Py_DECREF(memobj);
1479 if (res == NULL)
1480 return -1;
1481 if (res == Py_None) {
1482 /* Non-blocking stream would have blocked. Special return code! */
1483 Py_DECREF(res);
1484 return -2;
1485 }
1486 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1487 Py_DECREF(res);
1488
1489 if (n == -1 && PyErr_Occurred()) {
1490 _PyErr_FormatFromCause(
1491 PyExc_OSError,
1492 "raw readinto() failed"
1493 );
1494 return -1;
1495 }
1496
1497 if (n < 0 || n > len) {
1498 PyErr_Format(PyExc_OSError,
1499 "raw readinto() returned invalid length %zd "
1500 "(should have been between 0 and %zd)", n, len);
1501 return -1;
1502 }
1503 if (n > 0 && self->abs_pos != -1)
1504 self->abs_pos += n;
1505 return n;
1506 }
1507
1508 static Py_ssize_t
_bufferedreader_fill_buffer(buffered * self)1509 _bufferedreader_fill_buffer(buffered *self)
1510 {
1511 Py_ssize_t start, len, n;
1512 if (VALID_READ_BUFFER(self))
1513 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1514 else
1515 start = 0;
1516 len = self->buffer_size - start;
1517 n = _bufferedreader_raw_read(self, self->buffer + start, len);
1518 if (n <= 0)
1519 return n;
1520 self->read_end = start + n;
1521 self->raw_pos = start + n;
1522 return n;
1523 }
1524
1525 static PyObject *
_bufferedreader_read_all(buffered * self)1526 _bufferedreader_read_all(buffered *self)
1527 {
1528 Py_ssize_t current_size;
1529 PyObject *res = NULL, *data = NULL, *tmp = NULL, *chunks = NULL, *readall;
1530
1531 /* First copy what we have in the current buffer. */
1532 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1533 if (current_size) {
1534 data = PyBytes_FromStringAndSize(
1535 self->buffer + self->pos, current_size);
1536 if (data == NULL)
1537 return NULL;
1538 self->pos += current_size;
1539 }
1540 /* We're going past the buffer's bounds, flush it */
1541 if (self->writable) {
1542 tmp = buffered_flush_and_rewind_unlocked(self);
1543 if (tmp == NULL)
1544 goto cleanup;
1545 Py_CLEAR(tmp);
1546 }
1547 _bufferedreader_reset_buf(self);
1548
1549 if (_PyObject_LookupAttr(self->raw, _PyIO_str_readall, &readall) < 0) {
1550 goto cleanup;
1551 }
1552 if (readall) {
1553 tmp = _PyObject_CallNoArg(readall);
1554 Py_DECREF(readall);
1555 if (tmp == NULL)
1556 goto cleanup;
1557 if (tmp != Py_None && !PyBytes_Check(tmp)) {
1558 PyErr_SetString(PyExc_TypeError, "readall() should return bytes");
1559 goto cleanup;
1560 }
1561 if (current_size == 0) {
1562 res = tmp;
1563 } else {
1564 if (tmp != Py_None) {
1565 PyBytes_Concat(&data, tmp);
1566 }
1567 res = data;
1568 }
1569 goto cleanup;
1570 }
1571
1572 chunks = PyList_New(0);
1573 if (chunks == NULL)
1574 goto cleanup;
1575
1576 while (1) {
1577 if (data) {
1578 if (PyList_Append(chunks, data) < 0)
1579 goto cleanup;
1580 Py_CLEAR(data);
1581 }
1582
1583 /* Read until EOF or until read() would block. */
1584 data = PyObject_CallMethodNoArgs(self->raw, _PyIO_str_read);
1585 if (data == NULL)
1586 goto cleanup;
1587 if (data != Py_None && !PyBytes_Check(data)) {
1588 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1589 goto cleanup;
1590 }
1591 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1592 if (current_size == 0) {
1593 res = data;
1594 goto cleanup;
1595 }
1596 else {
1597 tmp = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1598 res = tmp;
1599 goto cleanup;
1600 }
1601 }
1602 current_size += PyBytes_GET_SIZE(data);
1603 if (self->abs_pos != -1)
1604 self->abs_pos += PyBytes_GET_SIZE(data);
1605 }
1606 cleanup:
1607 /* res is either NULL or a borrowed ref */
1608 Py_XINCREF(res);
1609 Py_XDECREF(data);
1610 Py_XDECREF(tmp);
1611 Py_XDECREF(chunks);
1612 return res;
1613 }
1614
1615 /* Read n bytes from the buffer if it can, otherwise return None.
1616 This function is simple enough that it can run unlocked. */
1617 static PyObject *
_bufferedreader_read_fast(buffered * self,Py_ssize_t n)1618 _bufferedreader_read_fast(buffered *self, Py_ssize_t n)
1619 {
1620 Py_ssize_t current_size;
1621
1622 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1623 if (n <= current_size) {
1624 /* Fast path: the data to read is fully buffered. */
1625 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1626 if (res != NULL)
1627 self->pos += n;
1628 return res;
1629 }
1630 Py_RETURN_NONE;
1631 }
1632
1633 /* Generic read function: read from the stream until enough bytes are read,
1634 * or until an EOF occurs or until read() would block.
1635 */
1636 static PyObject *
_bufferedreader_read_generic(buffered * self,Py_ssize_t n)1637 _bufferedreader_read_generic(buffered *self, Py_ssize_t n)
1638 {
1639 PyObject *res = NULL;
1640 Py_ssize_t current_size, remaining, written;
1641 char *out;
1642
1643 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1644 if (n <= current_size)
1645 return _bufferedreader_read_fast(self, n);
1646
1647 res = PyBytes_FromStringAndSize(NULL, n);
1648 if (res == NULL)
1649 goto error;
1650 out = PyBytes_AS_STRING(res);
1651 remaining = n;
1652 written = 0;
1653 if (current_size > 0) {
1654 memcpy(out, self->buffer + self->pos, current_size);
1655 remaining -= current_size;
1656 written += current_size;
1657 self->pos += current_size;
1658 }
1659 /* Flush the write buffer if necessary */
1660 if (self->writable) {
1661 PyObject *r = buffered_flush_and_rewind_unlocked(self);
1662 if (r == NULL)
1663 goto error;
1664 Py_DECREF(r);
1665 }
1666 _bufferedreader_reset_buf(self);
1667 while (remaining > 0) {
1668 /* We want to read a whole block at the end into buffer.
1669 If we had readv() we could do this in one pass. */
1670 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1671 if (r == 0)
1672 break;
1673 r = _bufferedreader_raw_read(self, out + written, r);
1674 if (r == -1)
1675 goto error;
1676 if (r == 0 || r == -2) {
1677 /* EOF occurred or read() would block. */
1678 if (r == 0 || written > 0) {
1679 if (_PyBytes_Resize(&res, written))
1680 goto error;
1681 return res;
1682 }
1683 Py_DECREF(res);
1684 Py_RETURN_NONE;
1685 }
1686 remaining -= r;
1687 written += r;
1688 }
1689 assert(remaining <= self->buffer_size);
1690 self->pos = 0;
1691 self->raw_pos = 0;
1692 self->read_end = 0;
1693 /* NOTE: when the read is satisfied, we avoid issuing any additional
1694 reads, which could block indefinitely (e.g. on a socket).
1695 See issue #9550. */
1696 while (remaining > 0 && self->read_end < self->buffer_size) {
1697 Py_ssize_t r = _bufferedreader_fill_buffer(self);
1698 if (r == -1)
1699 goto error;
1700 if (r == 0 || r == -2) {
1701 /* EOF occurred or read() would block. */
1702 if (r == 0 || written > 0) {
1703 if (_PyBytes_Resize(&res, written))
1704 goto error;
1705 return res;
1706 }
1707 Py_DECREF(res);
1708 Py_RETURN_NONE;
1709 }
1710 if (remaining > r) {
1711 memcpy(out + written, self->buffer + self->pos, r);
1712 written += r;
1713 self->pos += r;
1714 remaining -= r;
1715 }
1716 else if (remaining > 0) {
1717 memcpy(out + written, self->buffer + self->pos, remaining);
1718 written += remaining;
1719 self->pos += remaining;
1720 remaining = 0;
1721 }
1722 if (remaining == 0)
1723 break;
1724 }
1725
1726 return res;
1727
1728 error:
1729 Py_XDECREF(res);
1730 return NULL;
1731 }
1732
1733 static PyObject *
_bufferedreader_peek_unlocked(buffered * self)1734 _bufferedreader_peek_unlocked(buffered *self)
1735 {
1736 Py_ssize_t have, r;
1737
1738 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1739 /* Constraints:
1740 1. we don't want to advance the file position.
1741 2. we don't want to lose block alignment, so we can't shift the buffer
1742 to make some place.
1743 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1744 */
1745 if (have > 0) {
1746 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1747 }
1748
1749 /* Fill the buffer from the raw stream, and copy it to the result. */
1750 _bufferedreader_reset_buf(self);
1751 r = _bufferedreader_fill_buffer(self);
1752 if (r == -1)
1753 return NULL;
1754 if (r == -2)
1755 r = 0;
1756 self->pos = 0;
1757 return PyBytes_FromStringAndSize(self->buffer, r);
1758 }
1759
1760
1761
1762 /*
1763 * class BufferedWriter
1764 */
1765 static void
_bufferedwriter_reset_buf(buffered * self)1766 _bufferedwriter_reset_buf(buffered *self)
1767 {
1768 self->write_pos = 0;
1769 self->write_end = -1;
1770 }
1771
1772 /*[clinic input]
1773 _io.BufferedWriter.__init__
1774 raw: object
1775 buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
1776
1777 A buffer for a writeable sequential RawIO object.
1778
1779 The constructor creates a BufferedWriter for the given writeable raw
1780 stream. If the buffer_size is not given, it defaults to
1781 DEFAULT_BUFFER_SIZE.
1782 [clinic start generated code]*/
1783
1784 static int
_io_BufferedWriter___init___impl(buffered * self,PyObject * raw,Py_ssize_t buffer_size)1785 _io_BufferedWriter___init___impl(buffered *self, PyObject *raw,
1786 Py_ssize_t buffer_size)
1787 /*[clinic end generated code: output=c8942a020c0dee64 input=914be9b95e16007b]*/
1788 {
1789 self->ok = 0;
1790 self->detached = 0;
1791
1792 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
1793 return -1;
1794
1795 Py_INCREF(raw);
1796 Py_XSETREF(self->raw, raw);
1797 self->readable = 0;
1798 self->writable = 1;
1799
1800 self->buffer_size = buffer_size;
1801 if (_buffered_init(self) < 0)
1802 return -1;
1803 _bufferedwriter_reset_buf(self);
1804 self->pos = 0;
1805
1806 self->fast_closed_checks = (Py_IS_TYPE(self, &PyBufferedWriter_Type) &&
1807 Py_IS_TYPE(raw, &PyFileIO_Type));
1808
1809 self->ok = 1;
1810 return 0;
1811 }
1812
1813 static Py_ssize_t
_bufferedwriter_raw_write(buffered * self,char * start,Py_ssize_t len)1814 _bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
1815 {
1816 Py_buffer buf;
1817 PyObject *memobj, *res;
1818 Py_ssize_t n;
1819 int errnum;
1820 /* NOTE: the buffer needn't be released as its object is NULL. */
1821 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1822 return -1;
1823 memobj = PyMemoryView_FromBuffer(&buf);
1824 if (memobj == NULL)
1825 return -1;
1826 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1827 occurs so we needn't do it ourselves.
1828 We then retry writing, ignoring the signal if no handler has
1829 raised (see issue #10956).
1830 */
1831 do {
1832 errno = 0;
1833 res = PyObject_CallMethodOneArg(self->raw, _PyIO_str_write, memobj);
1834 errnum = errno;
1835 } while (res == NULL && _PyIO_trap_eintr());
1836 Py_DECREF(memobj);
1837 if (res == NULL)
1838 return -1;
1839 if (res == Py_None) {
1840 /* Non-blocking stream would have blocked. Special return code!
1841 Being paranoid we reset errno in case it is changed by code
1842 triggered by a decref. errno is used by _set_BlockingIOError(). */
1843 Py_DECREF(res);
1844 errno = errnum;
1845 return -2;
1846 }
1847 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1848 Py_DECREF(res);
1849 if (n < 0 || n > len) {
1850 PyErr_Format(PyExc_OSError,
1851 "raw write() returned invalid length %zd "
1852 "(should have been between 0 and %zd)", n, len);
1853 return -1;
1854 }
1855 if (n > 0 && self->abs_pos != -1)
1856 self->abs_pos += n;
1857 return n;
1858 }
1859
1860 static PyObject *
_bufferedwriter_flush_unlocked(buffered * self)1861 _bufferedwriter_flush_unlocked(buffered *self)
1862 {
1863 Py_ssize_t written = 0;
1864 Py_off_t n, rewind;
1865
1866 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1867 goto end;
1868 /* First, rewind */
1869 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1870 if (rewind != 0) {
1871 n = _buffered_raw_seek(self, -rewind, 1);
1872 if (n < 0) {
1873 goto error;
1874 }
1875 self->raw_pos -= rewind;
1876 }
1877 while (self->write_pos < self->write_end) {
1878 n = _bufferedwriter_raw_write(self,
1879 self->buffer + self->write_pos,
1880 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1881 Py_off_t, Py_ssize_t));
1882 if (n == -1) {
1883 goto error;
1884 }
1885 else if (n == -2) {
1886 _set_BlockingIOError("write could not complete without blocking",
1887 0);
1888 goto error;
1889 }
1890 self->write_pos += n;
1891 self->raw_pos = self->write_pos;
1892 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1893 /* Partial writes can return successfully when interrupted by a
1894 signal (see write(2)). We must run signal handlers before
1895 blocking another time, possibly indefinitely. */
1896 if (PyErr_CheckSignals() < 0)
1897 goto error;
1898 }
1899
1900
1901 end:
1902 /* This ensures that after return from this function,
1903 VALID_WRITE_BUFFER(self) returns false.
1904
1905 This is a required condition because when a tell() is called
1906 after flushing and if VALID_READ_BUFFER(self) is false, we need
1907 VALID_WRITE_BUFFER(self) to be false to have
1908 RAW_OFFSET(self) == 0.
1909
1910 Issue: https://bugs.python.org/issue32228 */
1911 _bufferedwriter_reset_buf(self);
1912 Py_RETURN_NONE;
1913
1914 error:
1915 return NULL;
1916 }
1917
1918 /*[clinic input]
1919 _io.BufferedWriter.write
1920 buffer: Py_buffer
1921 /
1922 [clinic start generated code]*/
1923
1924 static PyObject *
_io_BufferedWriter_write_impl(buffered * self,Py_buffer * buffer)1925 _io_BufferedWriter_write_impl(buffered *self, Py_buffer *buffer)
1926 /*[clinic end generated code: output=7f8d1365759bfc6b input=dd87dd85fc7f8850]*/
1927 {
1928 PyObject *res = NULL;
1929 Py_ssize_t written, avail, remaining;
1930 Py_off_t offset;
1931
1932 CHECK_INITIALIZED(self)
1933
1934 if (!ENTER_BUFFERED(self))
1935 return NULL;
1936
1937 /* Issue #31976: Check for closed file after acquiring the lock. Another
1938 thread could be holding the lock while closing the file. */
1939 if (IS_CLOSED(self)) {
1940 PyErr_SetString(PyExc_ValueError, "write to closed file");
1941 goto error;
1942 }
1943
1944 /* Fast path: the data to write can be fully buffered. */
1945 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1946 self->pos = 0;
1947 self->raw_pos = 0;
1948 }
1949 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1950 if (buffer->len <= avail) {
1951 memcpy(self->buffer + self->pos, buffer->buf, buffer->len);
1952 if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
1953 self->write_pos = self->pos;
1954 }
1955 ADJUST_POSITION(self, self->pos + buffer->len);
1956 if (self->pos > self->write_end)
1957 self->write_end = self->pos;
1958 written = buffer->len;
1959 goto end;
1960 }
1961
1962 /* First write the current buffer */
1963 res = _bufferedwriter_flush_unlocked(self);
1964 if (res == NULL) {
1965 Py_ssize_t *w = _buffered_check_blocking_error();
1966 if (w == NULL)
1967 goto error;
1968 if (self->readable)
1969 _bufferedreader_reset_buf(self);
1970 /* Make some place by shifting the buffer. */
1971 assert(VALID_WRITE_BUFFER(self));
1972 memmove(self->buffer, self->buffer + self->write_pos,
1973 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1974 Py_off_t, Py_ssize_t));
1975 self->write_end -= self->write_pos;
1976 self->raw_pos -= self->write_pos;
1977 self->pos -= self->write_pos;
1978 self->write_pos = 0;
1979 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1980 Py_off_t, Py_ssize_t);
1981 if (buffer->len <= avail) {
1982 /* Everything can be buffered */
1983 PyErr_Clear();
1984 memcpy(self->buffer + self->write_end, buffer->buf, buffer->len);
1985 self->write_end += buffer->len;
1986 self->pos += buffer->len;
1987 written = buffer->len;
1988 goto end;
1989 }
1990 /* Buffer as much as possible. */
1991 memcpy(self->buffer + self->write_end, buffer->buf, avail);
1992 self->write_end += avail;
1993 self->pos += avail;
1994 /* XXX Modifying the existing exception e using the pointer w
1995 will change e.characters_written but not e.args[2].
1996 Therefore we just replace with a new error. */
1997 _set_BlockingIOError("write could not complete without blocking",
1998 avail);
1999 goto error;
2000 }
2001 Py_CLEAR(res);
2002
2003 /* Adjust the raw stream position if it is away from the logical stream
2004 position. This happens if the read buffer has been filled but not
2005 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
2006 the raw stream by itself).
2007 Fixes issue #6629.
2008 */
2009 offset = RAW_OFFSET(self);
2010 if (offset != 0) {
2011 if (_buffered_raw_seek(self, -offset, 1) < 0)
2012 goto error;
2013 self->raw_pos -= offset;
2014 }
2015
2016 /* Then write buf itself. At this point the buffer has been emptied. */
2017 remaining = buffer->len;
2018 written = 0;
2019 while (remaining > self->buffer_size) {
2020 Py_ssize_t n = _bufferedwriter_raw_write(
2021 self, (char *) buffer->buf + written, buffer->len - written);
2022 if (n == -1) {
2023 goto error;
2024 } else if (n == -2) {
2025 /* Write failed because raw file is non-blocking */
2026 if (remaining > self->buffer_size) {
2027 /* Can't buffer everything, still buffer as much as possible */
2028 memcpy(self->buffer,
2029 (char *) buffer->buf + written, self->buffer_size);
2030 self->raw_pos = 0;
2031 ADJUST_POSITION(self, self->buffer_size);
2032 self->write_end = self->buffer_size;
2033 written += self->buffer_size;
2034 _set_BlockingIOError("write could not complete without "
2035 "blocking", written);
2036 goto error;
2037 }
2038 PyErr_Clear();
2039 break;
2040 }
2041 written += n;
2042 remaining -= n;
2043 /* Partial writes can return successfully when interrupted by a
2044 signal (see write(2)). We must run signal handlers before
2045 blocking another time, possibly indefinitely. */
2046 if (PyErr_CheckSignals() < 0)
2047 goto error;
2048 }
2049 if (self->readable)
2050 _bufferedreader_reset_buf(self);
2051 if (remaining > 0) {
2052 memcpy(self->buffer, (char *) buffer->buf + written, remaining);
2053 written += remaining;
2054 }
2055 self->write_pos = 0;
2056 /* TODO: sanity check (remaining >= 0) */
2057 self->write_end = remaining;
2058 ADJUST_POSITION(self, remaining);
2059 self->raw_pos = 0;
2060
2061 end:
2062 res = PyLong_FromSsize_t(written);
2063
2064 error:
2065 LEAVE_BUFFERED(self)
2066 return res;
2067 }
2068
2069
2070
2071 /*
2072 * BufferedRWPair
2073 */
2074
2075 /* XXX The usefulness of this (compared to having two separate IO objects) is
2076 * questionable.
2077 */
2078
2079 typedef struct {
2080 PyObject_HEAD
2081 buffered *reader;
2082 buffered *writer;
2083 PyObject *dict;
2084 PyObject *weakreflist;
2085 } rwpair;
2086
2087 /*[clinic input]
2088 _io.BufferedRWPair.__init__
2089 reader: object
2090 writer: object
2091 buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
2092 /
2093
2094 A buffered reader and writer object together.
2095
2096 A buffered reader object and buffered writer object put together to
2097 form a sequential IO object that can read and write. This is typically
2098 used with a socket or two-way pipe.
2099
2100 reader and writer are RawIOBase objects that are readable and
2101 writeable respectively. If the buffer_size is omitted it defaults to
2102 DEFAULT_BUFFER_SIZE.
2103 [clinic start generated code]*/
2104
2105 static int
_io_BufferedRWPair___init___impl(rwpair * self,PyObject * reader,PyObject * writer,Py_ssize_t buffer_size)2106 _io_BufferedRWPair___init___impl(rwpair *self, PyObject *reader,
2107 PyObject *writer, Py_ssize_t buffer_size)
2108 /*[clinic end generated code: output=327e73d1aee8f984 input=620d42d71f33a031]*/
2109 {
2110 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
2111 return -1;
2112 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
2113 return -1;
2114
2115 self->reader = (buffered *) PyObject_CallFunction(
2116 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
2117 if (self->reader == NULL)
2118 return -1;
2119
2120 self->writer = (buffered *) PyObject_CallFunction(
2121 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
2122 if (self->writer == NULL) {
2123 Py_CLEAR(self->reader);
2124 return -1;
2125 }
2126
2127 return 0;
2128 }
2129
2130 static int
bufferedrwpair_traverse(rwpair * self,visitproc visit,void * arg)2131 bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
2132 {
2133 Py_VISIT(self->dict);
2134 return 0;
2135 }
2136
2137 static int
bufferedrwpair_clear(rwpair * self)2138 bufferedrwpair_clear(rwpair *self)
2139 {
2140 Py_CLEAR(self->reader);
2141 Py_CLEAR(self->writer);
2142 Py_CLEAR(self->dict);
2143 return 0;
2144 }
2145
2146 static void
bufferedrwpair_dealloc(rwpair * self)2147 bufferedrwpair_dealloc(rwpair *self)
2148 {
2149 _PyObject_GC_UNTRACK(self);
2150 if (self->weakreflist != NULL)
2151 PyObject_ClearWeakRefs((PyObject *)self);
2152 Py_CLEAR(self->reader);
2153 Py_CLEAR(self->writer);
2154 Py_CLEAR(self->dict);
2155 Py_TYPE(self)->tp_free((PyObject *) self);
2156 }
2157
2158 static PyObject *
_forward_call(buffered * self,_Py_Identifier * name,PyObject * args)2159 _forward_call(buffered *self, _Py_Identifier *name, PyObject *args)
2160 {
2161 PyObject *func, *ret;
2162 if (self == NULL) {
2163 PyErr_SetString(PyExc_ValueError,
2164 "I/O operation on uninitialized object");
2165 return NULL;
2166 }
2167
2168 func = _PyObject_GetAttrId((PyObject *)self, name);
2169 if (func == NULL) {
2170 PyErr_SetString(PyExc_AttributeError, name->string);
2171 return NULL;
2172 }
2173
2174 ret = PyObject_CallObject(func, args);
2175 Py_DECREF(func);
2176 return ret;
2177 }
2178
2179 static PyObject *
bufferedrwpair_read(rwpair * self,PyObject * args)2180 bufferedrwpair_read(rwpair *self, PyObject *args)
2181 {
2182 return _forward_call(self->reader, &PyId_read, args);
2183 }
2184
2185 static PyObject *
bufferedrwpair_peek(rwpair * self,PyObject * args)2186 bufferedrwpair_peek(rwpair *self, PyObject *args)
2187 {
2188 return _forward_call(self->reader, &PyId_peek, args);
2189 }
2190
2191 static PyObject *
bufferedrwpair_read1(rwpair * self,PyObject * args)2192 bufferedrwpair_read1(rwpair *self, PyObject *args)
2193 {
2194 return _forward_call(self->reader, &PyId_read1, args);
2195 }
2196
2197 static PyObject *
bufferedrwpair_readinto(rwpair * self,PyObject * args)2198 bufferedrwpair_readinto(rwpair *self, PyObject *args)
2199 {
2200 return _forward_call(self->reader, &PyId_readinto, args);
2201 }
2202
2203 static PyObject *
bufferedrwpair_readinto1(rwpair * self,PyObject * args)2204 bufferedrwpair_readinto1(rwpair *self, PyObject *args)
2205 {
2206 return _forward_call(self->reader, &PyId_readinto1, args);
2207 }
2208
2209 static PyObject *
bufferedrwpair_write(rwpair * self,PyObject * args)2210 bufferedrwpair_write(rwpair *self, PyObject *args)
2211 {
2212 return _forward_call(self->writer, &PyId_write, args);
2213 }
2214
2215 static PyObject *
bufferedrwpair_flush(rwpair * self,PyObject * Py_UNUSED (ignored))2216 bufferedrwpair_flush(rwpair *self, PyObject *Py_UNUSED(ignored))
2217 {
2218 return _forward_call(self->writer, &PyId_flush, NULL);
2219 }
2220
2221 static PyObject *
bufferedrwpair_readable(rwpair * self,PyObject * Py_UNUSED (ignored))2222 bufferedrwpair_readable(rwpair *self, PyObject *Py_UNUSED(ignored))
2223 {
2224 return _forward_call(self->reader, &PyId_readable, NULL);
2225 }
2226
2227 static PyObject *
bufferedrwpair_writable(rwpair * self,PyObject * Py_UNUSED (ignored))2228 bufferedrwpair_writable(rwpair *self, PyObject *Py_UNUSED(ignored))
2229 {
2230 return _forward_call(self->writer, &PyId_writable, NULL);
2231 }
2232
2233 static PyObject *
bufferedrwpair_close(rwpair * self,PyObject * Py_UNUSED (ignored))2234 bufferedrwpair_close(rwpair *self, PyObject *Py_UNUSED(ignored))
2235 {
2236 PyObject *exc = NULL, *val, *tb;
2237 PyObject *ret = _forward_call(self->writer, &PyId_close, NULL);
2238 if (ret == NULL)
2239 PyErr_Fetch(&exc, &val, &tb);
2240 else
2241 Py_DECREF(ret);
2242 ret = _forward_call(self->reader, &PyId_close, NULL);
2243 if (exc != NULL) {
2244 _PyErr_ChainExceptions(exc, val, tb);
2245 Py_CLEAR(ret);
2246 }
2247 return ret;
2248 }
2249
2250 static PyObject *
bufferedrwpair_isatty(rwpair * self,PyObject * Py_UNUSED (ignored))2251 bufferedrwpair_isatty(rwpair *self, PyObject *Py_UNUSED(ignored))
2252 {
2253 PyObject *ret = _forward_call(self->writer, &PyId_isatty, NULL);
2254
2255 if (ret != Py_False) {
2256 /* either True or exception */
2257 return ret;
2258 }
2259 Py_DECREF(ret);
2260
2261 return _forward_call(self->reader, &PyId_isatty, NULL);
2262 }
2263
2264 static PyObject *
bufferedrwpair_closed_get(rwpair * self,void * context)2265 bufferedrwpair_closed_get(rwpair *self, void *context)
2266 {
2267 if (self->writer == NULL) {
2268 PyErr_SetString(PyExc_RuntimeError,
2269 "the BufferedRWPair object is being garbage-collected");
2270 return NULL;
2271 }
2272 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2273 }
2274
2275
2276
2277 /*
2278 * BufferedRandom
2279 */
2280
2281 /*[clinic input]
2282 _io.BufferedRandom.__init__
2283 raw: object
2284 buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
2285
2286 A buffered interface to random access streams.
2287
2288 The constructor creates a reader and writer for a seekable stream,
2289 raw, given in the first argument. If the buffer_size is omitted it
2290 defaults to DEFAULT_BUFFER_SIZE.
2291 [clinic start generated code]*/
2292
2293 static int
_io_BufferedRandom___init___impl(buffered * self,PyObject * raw,Py_ssize_t buffer_size)2294 _io_BufferedRandom___init___impl(buffered *self, PyObject *raw,
2295 Py_ssize_t buffer_size)
2296 /*[clinic end generated code: output=d3d64eb0f64e64a3 input=a4e818fb86d0e50c]*/
2297 {
2298 self->ok = 0;
2299 self->detached = 0;
2300
2301 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
2302 return -1;
2303 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
2304 return -1;
2305 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
2306 return -1;
2307
2308 Py_INCREF(raw);
2309 Py_XSETREF(self->raw, raw);
2310 self->buffer_size = buffer_size;
2311 self->readable = 1;
2312 self->writable = 1;
2313
2314 if (_buffered_init(self) < 0)
2315 return -1;
2316 _bufferedreader_reset_buf(self);
2317 _bufferedwriter_reset_buf(self);
2318 self->pos = 0;
2319
2320 self->fast_closed_checks = (Py_IS_TYPE(self, &PyBufferedRandom_Type) &&
2321 Py_IS_TYPE(raw, &PyFileIO_Type));
2322
2323 self->ok = 1;
2324 return 0;
2325 }
2326
2327 #include "clinic/bufferedio.c.h"
2328
2329
2330 static PyMethodDef bufferediobase_methods[] = {
2331 _IO__BUFFEREDIOBASE_DETACH_METHODDEF
2332 {"read", bufferediobase_read, METH_VARARGS, bufferediobase_read_doc},
2333 {"read1", bufferediobase_read1, METH_VARARGS, bufferediobase_read1_doc},
2334 _IO__BUFFEREDIOBASE_READINTO_METHODDEF
2335 _IO__BUFFEREDIOBASE_READINTO1_METHODDEF
2336 {"write", bufferediobase_write, METH_VARARGS, bufferediobase_write_doc},
2337 {NULL, NULL}
2338 };
2339
2340 PyTypeObject PyBufferedIOBase_Type = {
2341 PyVarObject_HEAD_INIT(NULL, 0)
2342 "_io._BufferedIOBase", /*tp_name*/
2343 0, /*tp_basicsize*/
2344 0, /*tp_itemsize*/
2345 0, /*tp_dealloc*/
2346 0, /*tp_vectorcall_offset*/
2347 0, /*tp_getattr*/
2348 0, /*tp_setattr*/
2349 0, /*tp_as_async*/
2350 0, /*tp_repr*/
2351 0, /*tp_as_number*/
2352 0, /*tp_as_sequence*/
2353 0, /*tp_as_mapping*/
2354 0, /*tp_hash */
2355 0, /*tp_call*/
2356 0, /*tp_str*/
2357 0, /*tp_getattro*/
2358 0, /*tp_setattro*/
2359 0, /*tp_as_buffer*/
2360 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
2361 bufferediobase_doc, /* tp_doc */
2362 0, /* tp_traverse */
2363 0, /* tp_clear */
2364 0, /* tp_richcompare */
2365 0, /* tp_weaklistoffset */
2366 0, /* tp_iter */
2367 0, /* tp_iternext */
2368 bufferediobase_methods, /* tp_methods */
2369 0, /* tp_members */
2370 0, /* tp_getset */
2371 &PyIOBase_Type, /* tp_base */
2372 0, /* tp_dict */
2373 0, /* tp_descr_get */
2374 0, /* tp_descr_set */
2375 0, /* tp_dictoffset */
2376 0, /* tp_init */
2377 0, /* tp_alloc */
2378 0, /* tp_new */
2379 0, /* tp_free */
2380 0, /* tp_is_gc */
2381 0, /* tp_bases */
2382 0, /* tp_mro */
2383 0, /* tp_cache */
2384 0, /* tp_subclasses */
2385 0, /* tp_weaklist */
2386 0, /* tp_del */
2387 0, /* tp_version_tag */
2388 0, /* tp_finalize */
2389 };
2390
2391
2392 static PyMethodDef bufferedreader_methods[] = {
2393 /* BufferedIOMixin methods */
2394 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2395 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
2396 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2397 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2398 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2399 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2400 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2401 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
2402
2403 _IO__BUFFERED_READ_METHODDEF
2404 _IO__BUFFERED_PEEK_METHODDEF
2405 _IO__BUFFERED_READ1_METHODDEF
2406 _IO__BUFFERED_READINTO_METHODDEF
2407 _IO__BUFFERED_READINTO1_METHODDEF
2408 _IO__BUFFERED_READLINE_METHODDEF
2409 _IO__BUFFERED_SEEK_METHODDEF
2410 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2411 _IO__BUFFERED_TRUNCATE_METHODDEF
2412 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
2413 {NULL, NULL}
2414 };
2415
2416 static PyMemberDef bufferedreader_members[] = {
2417 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
2418 {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
2419 {NULL}
2420 };
2421
2422 static PyGetSetDef bufferedreader_getset[] = {
2423 {"closed", (getter)buffered_closed_get, NULL, NULL},
2424 {"name", (getter)buffered_name_get, NULL, NULL},
2425 {"mode", (getter)buffered_mode_get, NULL, NULL},
2426 {NULL}
2427 };
2428
2429
2430 PyTypeObject PyBufferedReader_Type = {
2431 PyVarObject_HEAD_INIT(NULL, 0)
2432 "_io.BufferedReader", /*tp_name*/
2433 sizeof(buffered), /*tp_basicsize*/
2434 0, /*tp_itemsize*/
2435 (destructor)buffered_dealloc, /*tp_dealloc*/
2436 0, /*tp_vectorcall_offset*/
2437 0, /*tp_getattr*/
2438 0, /*tp_setattr*/
2439 0, /*tp_as_async*/
2440 (reprfunc)buffered_repr, /*tp_repr*/
2441 0, /*tp_as_number*/
2442 0, /*tp_as_sequence*/
2443 0, /*tp_as_mapping*/
2444 0, /*tp_hash */
2445 0, /*tp_call*/
2446 0, /*tp_str*/
2447 0, /*tp_getattro*/
2448 0, /*tp_setattro*/
2449 0, /*tp_as_buffer*/
2450 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2451 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2452 _io_BufferedReader___init____doc__, /* tp_doc */
2453 (traverseproc)buffered_traverse, /* tp_traverse */
2454 (inquiry)buffered_clear, /* tp_clear */
2455 0, /* tp_richcompare */
2456 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2457 0, /* tp_iter */
2458 (iternextfunc)buffered_iternext, /* tp_iternext */
2459 bufferedreader_methods, /* tp_methods */
2460 bufferedreader_members, /* tp_members */
2461 bufferedreader_getset, /* tp_getset */
2462 0, /* tp_base */
2463 0, /* tp_dict */
2464 0, /* tp_descr_get */
2465 0, /* tp_descr_set */
2466 offsetof(buffered, dict), /* tp_dictoffset */
2467 _io_BufferedReader___init__, /* tp_init */
2468 0, /* tp_alloc */
2469 PyType_GenericNew, /* tp_new */
2470 0, /* tp_free */
2471 0, /* tp_is_gc */
2472 0, /* tp_bases */
2473 0, /* tp_mro */
2474 0, /* tp_cache */
2475 0, /* tp_subclasses */
2476 0, /* tp_weaklist */
2477 0, /* tp_del */
2478 0, /* tp_version_tag */
2479 0, /* tp_finalize */
2480 };
2481
2482
2483 static PyMethodDef bufferedwriter_methods[] = {
2484 /* BufferedIOMixin methods */
2485 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2486 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2487 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2488 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2489 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2490 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2491 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
2492
2493 _IO_BUFFEREDWRITER_WRITE_METHODDEF
2494 _IO__BUFFERED_TRUNCATE_METHODDEF
2495 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2496 _IO__BUFFERED_SEEK_METHODDEF
2497 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2498 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
2499 {NULL, NULL}
2500 };
2501
2502 static PyMemberDef bufferedwriter_members[] = {
2503 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
2504 {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
2505 {NULL}
2506 };
2507
2508 static PyGetSetDef bufferedwriter_getset[] = {
2509 {"closed", (getter)buffered_closed_get, NULL, NULL},
2510 {"name", (getter)buffered_name_get, NULL, NULL},
2511 {"mode", (getter)buffered_mode_get, NULL, NULL},
2512 {NULL}
2513 };
2514
2515
2516 PyTypeObject PyBufferedWriter_Type = {
2517 PyVarObject_HEAD_INIT(NULL, 0)
2518 "_io.BufferedWriter", /*tp_name*/
2519 sizeof(buffered), /*tp_basicsize*/
2520 0, /*tp_itemsize*/
2521 (destructor)buffered_dealloc, /*tp_dealloc*/
2522 0, /*tp_vectorcall_offset*/
2523 0, /*tp_getattr*/
2524 0, /*tp_setattr*/
2525 0, /*tp_as_async*/
2526 (reprfunc)buffered_repr, /*tp_repr*/
2527 0, /*tp_as_number*/
2528 0, /*tp_as_sequence*/
2529 0, /*tp_as_mapping*/
2530 0, /*tp_hash */
2531 0, /*tp_call*/
2532 0, /*tp_str*/
2533 0, /*tp_getattro*/
2534 0, /*tp_setattro*/
2535 0, /*tp_as_buffer*/
2536 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2537 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2538 _io_BufferedWriter___init____doc__, /* tp_doc */
2539 (traverseproc)buffered_traverse, /* tp_traverse */
2540 (inquiry)buffered_clear, /* tp_clear */
2541 0, /* tp_richcompare */
2542 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2543 0, /* tp_iter */
2544 0, /* tp_iternext */
2545 bufferedwriter_methods, /* tp_methods */
2546 bufferedwriter_members, /* tp_members */
2547 bufferedwriter_getset, /* tp_getset */
2548 0, /* tp_base */
2549 0, /* tp_dict */
2550 0, /* tp_descr_get */
2551 0, /* tp_descr_set */
2552 offsetof(buffered, dict), /* tp_dictoffset */
2553 _io_BufferedWriter___init__, /* tp_init */
2554 0, /* tp_alloc */
2555 PyType_GenericNew, /* tp_new */
2556 0, /* tp_free */
2557 0, /* tp_is_gc */
2558 0, /* tp_bases */
2559 0, /* tp_mro */
2560 0, /* tp_cache */
2561 0, /* tp_subclasses */
2562 0, /* tp_weaklist */
2563 0, /* tp_del */
2564 0, /* tp_version_tag */
2565 0, /* tp_finalize */
2566 };
2567
2568
2569 static PyMethodDef bufferedrwpair_methods[] = {
2570 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2571 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2572 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2573 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
2574 {"readinto1", (PyCFunction)bufferedrwpair_readinto1, METH_VARARGS},
2575
2576 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2577 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
2578
2579 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2580 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
2581
2582 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2583 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
2584
2585 {NULL, NULL}
2586 };
2587
2588 static PyGetSetDef bufferedrwpair_getset[] = {
2589 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
2590 {NULL}
2591 };
2592
2593 PyTypeObject PyBufferedRWPair_Type = {
2594 PyVarObject_HEAD_INIT(NULL, 0)
2595 "_io.BufferedRWPair", /*tp_name*/
2596 sizeof(rwpair), /*tp_basicsize*/
2597 0, /*tp_itemsize*/
2598 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
2599 0, /*tp_vectorcall_offset*/
2600 0, /*tp_getattr*/
2601 0, /*tp_setattr*/
2602 0, /*tp_as_async*/
2603 0, /*tp_repr*/
2604 0, /*tp_as_number*/
2605 0, /*tp_as_sequence*/
2606 0, /*tp_as_mapping*/
2607 0, /*tp_hash */
2608 0, /*tp_call*/
2609 0, /*tp_str*/
2610 0, /*tp_getattro*/
2611 0, /*tp_setattro*/
2612 0, /*tp_as_buffer*/
2613 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2614 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
2615 _io_BufferedRWPair___init____doc__, /* tp_doc */
2616 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2617 (inquiry)bufferedrwpair_clear, /* tp_clear */
2618 0, /* tp_richcompare */
2619 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
2620 0, /* tp_iter */
2621 0, /* tp_iternext */
2622 bufferedrwpair_methods, /* tp_methods */
2623 0, /* tp_members */
2624 bufferedrwpair_getset, /* tp_getset */
2625 0, /* tp_base */
2626 0, /* tp_dict */
2627 0, /* tp_descr_get */
2628 0, /* tp_descr_set */
2629 offsetof(rwpair, dict), /* tp_dictoffset */
2630 _io_BufferedRWPair___init__, /* tp_init */
2631 0, /* tp_alloc */
2632 PyType_GenericNew, /* tp_new */
2633 0, /* tp_free */
2634 0, /* tp_is_gc */
2635 0, /* tp_bases */
2636 0, /* tp_mro */
2637 0, /* tp_cache */
2638 0, /* tp_subclasses */
2639 0, /* tp_weaklist */
2640 0, /* tp_del */
2641 0, /* tp_version_tag */
2642 0, /* tp_finalize */
2643 };
2644
2645
2646 static PyMethodDef bufferedrandom_methods[] = {
2647 /* BufferedIOMixin methods */
2648 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2649 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2650 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2651 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2652 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2653 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2654 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2655 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
2656
2657 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2658
2659 _IO__BUFFERED_SEEK_METHODDEF
2660 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2661 _IO__BUFFERED_TRUNCATE_METHODDEF
2662 _IO__BUFFERED_READ_METHODDEF
2663 _IO__BUFFERED_READ1_METHODDEF
2664 _IO__BUFFERED_READINTO_METHODDEF
2665 _IO__BUFFERED_READINTO1_METHODDEF
2666 _IO__BUFFERED_READLINE_METHODDEF
2667 _IO__BUFFERED_PEEK_METHODDEF
2668 _IO_BUFFEREDWRITER_WRITE_METHODDEF
2669 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
2670 {NULL, NULL}
2671 };
2672
2673 static PyMemberDef bufferedrandom_members[] = {
2674 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
2675 {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
2676 {NULL}
2677 };
2678
2679 static PyGetSetDef bufferedrandom_getset[] = {
2680 {"closed", (getter)buffered_closed_get, NULL, NULL},
2681 {"name", (getter)buffered_name_get, NULL, NULL},
2682 {"mode", (getter)buffered_mode_get, NULL, NULL},
2683 {NULL}
2684 };
2685
2686
2687 PyTypeObject PyBufferedRandom_Type = {
2688 PyVarObject_HEAD_INIT(NULL, 0)
2689 "_io.BufferedRandom", /*tp_name*/
2690 sizeof(buffered), /*tp_basicsize*/
2691 0, /*tp_itemsize*/
2692 (destructor)buffered_dealloc, /*tp_dealloc*/
2693 0, /*tp_vectorcall_offset*/
2694 0, /*tp_getattr*/
2695 0, /*tp_setattr*/
2696 0, /*tp_as_async*/
2697 (reprfunc)buffered_repr, /*tp_repr*/
2698 0, /*tp_as_number*/
2699 0, /*tp_as_sequence*/
2700 0, /*tp_as_mapping*/
2701 0, /*tp_hash */
2702 0, /*tp_call*/
2703 0, /*tp_str*/
2704 0, /*tp_getattro*/
2705 0, /*tp_setattro*/
2706 0, /*tp_as_buffer*/
2707 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2708 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2709 _io_BufferedRandom___init____doc__, /* tp_doc */
2710 (traverseproc)buffered_traverse, /* tp_traverse */
2711 (inquiry)buffered_clear, /* tp_clear */
2712 0, /* tp_richcompare */
2713 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2714 0, /* tp_iter */
2715 (iternextfunc)buffered_iternext, /* tp_iternext */
2716 bufferedrandom_methods, /* tp_methods */
2717 bufferedrandom_members, /* tp_members */
2718 bufferedrandom_getset, /* tp_getset */
2719 0, /* tp_base */
2720 0, /*tp_dict*/
2721 0, /* tp_descr_get */
2722 0, /* tp_descr_set */
2723 offsetof(buffered, dict), /*tp_dictoffset*/
2724 _io_BufferedRandom___init__, /* tp_init */
2725 0, /* tp_alloc */
2726 PyType_GenericNew, /* tp_new */
2727 0, /* tp_free */
2728 0, /* tp_is_gc */
2729 0, /* tp_bases */
2730 0, /* tp_mro */
2731 0, /* tp_cache */
2732 0, /* tp_subclasses */
2733 0, /* tp_weaklist */
2734 0, /* tp_del */
2735 0, /* tp_version_tag */
2736 0, /* tp_finalize */
2737 };
2738