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