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