Python-2.7.3/Modules/_io/bufferedio.c

No issues found

   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 *);
 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 /* Sets the current error to BlockingIOError */
 575 static void
 576 _set_BlockingIOError(char *msg, Py_ssize_t written)
 577 {
 578     PyObject *err;
 579     err = PyObject_CallFunction(PyExc_BlockingIOError, "isn",
 580                                 errno, msg, written);
 581     if (err)
 582         PyErr_SetObject(PyExc_BlockingIOError, err);
 583     Py_XDECREF(err);
 584 }
 585 
 586 /* Returns the address of the `written` member if a BlockingIOError was
 587    raised, NULL otherwise. The error is always re-raised. */
 588 static Py_ssize_t *
 589 _buffered_check_blocking_error(void)
 590 {
 591     PyObject *t, *v, *tb;
 592     PyBlockingIOErrorObject *err;
 593 
 594     PyErr_Fetch(&t, &v, &tb);
 595     if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
 596         PyErr_Restore(t, v, tb);
 597         return NULL;
 598     }
 599     err = (PyBlockingIOErrorObject *) v;
 600     /* TODO: sanity check (err->written >= 0) */
 601     PyErr_Restore(t, v, tb);
 602     return &err->written;
 603 }
 604 
 605 static Py_off_t
 606 _buffered_raw_tell(buffered *self)
 607 {
 608     Py_off_t n;
 609     PyObject *res;
 610     res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
 611     if (res == NULL)
 612         return -1;
 613     n = PyNumber_AsOff_t(res, PyExc_ValueError);
 614     Py_DECREF(res);
 615     if (n < 0) {
 616         if (!PyErr_Occurred())
 617             PyErr_Format(PyExc_IOError,
 618                          "Raw stream returned invalid position %" PY_PRIdOFF,
 619 			 (PY_OFF_T_COMPAT)n);
 620         return -1;
 621     }
 622     self->abs_pos = n;
 623     return n;
 624 }
 625 
 626 static Py_off_t
 627 _buffered_raw_seek(buffered *self, Py_off_t target, int whence)
 628 {
 629     PyObject *res, *posobj, *whenceobj;
 630     Py_off_t n;
 631 
 632     posobj = PyLong_FromOff_t(target);
 633     if (posobj == NULL)
 634         return -1;
 635     whenceobj = PyLong_FromLong(whence);
 636     if (whenceobj == NULL) {
 637         Py_DECREF(posobj);
 638         return -1;
 639     }
 640     res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
 641                                      posobj, whenceobj, NULL);
 642     Py_DECREF(posobj);
 643     Py_DECREF(whenceobj);
 644     if (res == NULL)
 645         return -1;
 646     n = PyNumber_AsOff_t(res, PyExc_ValueError);
 647     Py_DECREF(res);
 648     if (n < 0) {
 649         if (!PyErr_Occurred())
 650             PyErr_Format(PyExc_IOError,
 651                          "Raw stream returned invalid position %" PY_PRIdOFF,
 652 			 (PY_OFF_T_COMPAT)n);
 653         return -1;
 654     }
 655     self->abs_pos = n;
 656     return n;
 657 }
 658 
 659 static int
 660 _buffered_init(buffered *self)
 661 {
 662     Py_ssize_t n;
 663     if (self->buffer_size <= 0) {
 664         PyErr_SetString(PyExc_ValueError,
 665             "buffer size must be strictly positive");
 666         return -1;
 667     }
 668     if (self->buffer)
 669         PyMem_Free(self->buffer);
 670     self->buffer = PyMem_Malloc(self->buffer_size);
 671     if (self->buffer == NULL) {
 672         PyErr_NoMemory();
 673         return -1;
 674     }
 675 #ifdef WITH_THREAD
 676     if (self->lock)
 677         PyThread_free_lock(self->lock);
 678     self->lock = PyThread_allocate_lock();
 679     if (self->lock == NULL) {
 680         PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
 681         return -1;
 682     }
 683     self->owner = 0;
 684 #endif
 685     /* Find out whether buffer_size is a power of 2 */
 686     /* XXX is this optimization useful? */
 687     for (n = self->buffer_size - 1; n & 1; n >>= 1)
 688         ;
 689     if (n == 0)
 690         self->buffer_mask = self->buffer_size - 1;
 691     else
 692         self->buffer_mask = 0;
 693     if (_buffered_raw_tell(self) == -1)
 694         PyErr_Clear();
 695     return 0;
 696 }
 697 
 698 /* Return 1 if an EnvironmentError with errno == EINTR is set (and then
 699    clears the error indicator), 0 otherwise.
 700    Should only be called when PyErr_Occurred() is true.
 701 */
 702 static int
 703 _trap_eintr(void)
 704 {
 705     static PyObject *eintr_int = NULL;
 706     PyObject *typ, *val, *tb;
 707     PyEnvironmentErrorObject *env_err;
 708 
 709     if (eintr_int == NULL) {
 710         eintr_int = PyLong_FromLong(EINTR);
 711         assert(eintr_int != NULL);
 712     }
 713     if (!PyErr_ExceptionMatches(PyExc_EnvironmentError))
 714         return 0;
 715     PyErr_Fetch(&typ, &val, &tb);
 716     PyErr_NormalizeException(&typ, &val, &tb);
 717     env_err = (PyEnvironmentErrorObject *) val;
 718     assert(env_err != NULL);
 719     if (env_err->myerrno != NULL &&
 720         PyObject_RichCompareBool(env_err->myerrno, eintr_int, Py_EQ) > 0) {
 721         Py_DECREF(typ);
 722         Py_DECREF(val);
 723         Py_XDECREF(tb);
 724         return 1;
 725     }
 726     /* This silences any error set by PyObject_RichCompareBool() */
 727     PyErr_Restore(typ, val, tb);
 728     return 0;
 729 }
 730 
 731 /*
 732  * Shared methods and wrappers
 733  */
 734 
 735 static PyObject *
 736 buffered_flush_and_rewind_unlocked(buffered *self)
 737 {
 738     PyObject *res;
 739 
 740     res = _bufferedwriter_flush_unlocked(self);
 741     if (res == NULL)
 742         return NULL;
 743     Py_DECREF(res);
 744 
 745     if (self->readable) {
 746         /* Rewind the raw stream so that its position corresponds to
 747            the current logical position. */
 748         Py_off_t n;
 749         n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
 750         _bufferedreader_reset_buf(self);
 751         if (n == -1)
 752             return NULL;
 753     }
 754     Py_RETURN_NONE;
 755 }
 756 
 757 static PyObject *
 758 buffered_flush(buffered *self, PyObject *args)
 759 {
 760     PyObject *res;
 761 
 762     CHECK_INITIALIZED(self)
 763     CHECK_CLOSED(self, "flush of closed file")
 764 
 765     if (!ENTER_BUFFERED(self))
 766         return NULL;
 767     res = buffered_flush_and_rewind_unlocked(self);
 768     LEAVE_BUFFERED(self)
 769 
 770     return res;
 771 }
 772 
 773 static PyObject *
 774 buffered_peek(buffered *self, PyObject *args)
 775 {
 776     Py_ssize_t n = 0;
 777     PyObject *res = NULL;
 778 
 779     CHECK_INITIALIZED(self)
 780     if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
 781         return NULL;
 782     }
 783 
 784     if (!ENTER_BUFFERED(self))
 785         return NULL;
 786 
 787     if (self->writable) {
 788         res = buffered_flush_and_rewind_unlocked(self);
 789         if (res == NULL)
 790             goto end;
 791         Py_CLEAR(res);
 792     }
 793     res = _bufferedreader_peek_unlocked(self, n);
 794 
 795 end:
 796     LEAVE_BUFFERED(self)
 797     return res;
 798 }
 799 
 800 static PyObject *
 801 buffered_read(buffered *self, PyObject *args)
 802 {
 803     Py_ssize_t n = -1;
 804     PyObject *res;
 805 
 806     CHECK_INITIALIZED(self)
 807     if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
 808         return NULL;
 809     }
 810     if (n < -1) {
 811         PyErr_SetString(PyExc_ValueError,
 812                         "read length must be positive or -1");
 813         return NULL;
 814     }
 815 
 816     CHECK_CLOSED(self, "read of closed file")
 817 
 818     if (n == -1) {
 819         /* The number of bytes is unspecified, read until the end of stream */
 820         if (!ENTER_BUFFERED(self))
 821             return NULL;
 822         res = _bufferedreader_read_all(self);
 823     }
 824     else {
 825         res = _bufferedreader_read_fast(self, n);
 826         if (res != Py_None)
 827             return res;
 828         Py_DECREF(res);
 829         if (!ENTER_BUFFERED(self))
 830             return NULL;
 831         res = _bufferedreader_read_generic(self, n);
 832     }
 833 
 834     LEAVE_BUFFERED(self)
 835     return res;
 836 }
 837 
 838 static PyObject *
 839 buffered_read1(buffered *self, PyObject *args)
 840 {
 841     Py_ssize_t n, have, r;
 842     PyObject *res = NULL;
 843 
 844     CHECK_INITIALIZED(self)
 845     if (!PyArg_ParseTuple(args, "n:read1", &n)) {
 846         return NULL;
 847     }
 848 
 849     if (n < 0) {
 850         PyErr_SetString(PyExc_ValueError,
 851                         "read length must be positive");
 852         return NULL;
 853     }
 854     if (n == 0)
 855         return PyBytes_FromStringAndSize(NULL, 0);
 856 
 857     if (!ENTER_BUFFERED(self))
 858         return NULL;
 859     
 860     /* Return up to n bytes.  If at least one byte is buffered, we
 861        only return buffered bytes.  Otherwise, we do one raw read. */
 862 
 863     /* XXX: this mimicks the io.py implementation but is probably wrong.
 864        If we need to read from the raw stream, then we could actually read
 865        all `n` bytes asked by the caller (and possibly more, so as to fill
 866        our buffer for the next reads). */
 867 
 868     have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
 869     if (have > 0) {
 870         if (n > have)
 871             n = have;
 872         res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
 873         if (res == NULL)
 874             goto end;
 875         self->pos += n;
 876         goto end;
 877     }
 878 
 879     if (self->writable) {
 880         res = buffered_flush_and_rewind_unlocked(self);
 881         if (res == NULL)
 882             goto end;
 883         Py_DECREF(res);
 884     }
 885 
 886     /* Fill the buffer from the raw stream, and copy it to the result. */
 887     _bufferedreader_reset_buf(self);
 888     r = _bufferedreader_fill_buffer(self);
 889     if (r == -1)
 890         goto end;
 891     if (r == -2)
 892         r = 0;
 893     if (n > r)
 894         n = r;
 895     res = PyBytes_FromStringAndSize(self->buffer, n);
 896     if (res == NULL)
 897         goto end;
 898     self->pos = n;
 899 
 900 end:
 901     LEAVE_BUFFERED(self)
 902     return res;
 903 }
 904 
 905 static PyObject *
 906 buffered_readinto(buffered *self, PyObject *args)
 907 {
 908     CHECK_INITIALIZED(self)
 909     
 910     /* TODO: use raw.readinto() (or a direct copy from our buffer) instead! */
 911     return bufferediobase_readinto((PyObject *)self, args);
 912 }
 913 
 914 static PyObject *
 915 _buffered_readline(buffered *self, Py_ssize_t limit)
 916 {
 917     PyObject *res = NULL;
 918     PyObject *chunks = NULL;
 919     Py_ssize_t n, written = 0;
 920     const char *start, *s, *end;
 921 
 922     CHECK_CLOSED(self, "readline of closed file")
 923 
 924     /* First, try to find a line in the buffer. This can run unlocked because
 925        the calls to the C API are simple enough that they can't trigger
 926        any thread switch. */
 927     n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
 928     if (limit >= 0 && n > limit)
 929         n = limit;
 930     start = self->buffer + self->pos;
 931     s = memchr(start, '\n', n);
 932     if (s != NULL) {
 933         res = PyBytes_FromStringAndSize(start, s - start + 1);
 934         if (res != NULL)
 935             self->pos += s - start + 1;
 936         goto end_unlocked;
 937     }
 938     if (n == limit) {
 939         res = PyBytes_FromStringAndSize(start, n);
 940         if (res != NULL)
 941             self->pos += n;
 942         goto end_unlocked;
 943     }
 944 
 945     if (!ENTER_BUFFERED(self))
 946         goto end_unlocked;
 947 
 948     /* Now we try to get some more from the raw stream */
 949     chunks = PyList_New(0);
 950     if (chunks == NULL)
 951         goto end;
 952     if (n > 0) {
 953         res = PyBytes_FromStringAndSize(start, n);
 954         if (res == NULL)
 955             goto end;
 956         if (PyList_Append(chunks, res) < 0) {
 957             Py_CLEAR(res);
 958             goto end;
 959         }
 960         Py_CLEAR(res);
 961         written += n;
 962         self->pos += n;
 963         if (limit >= 0)
 964             limit -= n;
 965     }
 966     if (self->writable) {
 967         PyObject *r = buffered_flush_and_rewind_unlocked(self);
 968         if (r == NULL)
 969             goto end;
 970         Py_DECREF(r);
 971     }
 972 
 973     for (;;) {
 974         _bufferedreader_reset_buf(self);
 975         n = _bufferedreader_fill_buffer(self);
 976         if (n == -1)
 977             goto end;
 978         if (n <= 0)
 979             break;
 980         if (limit >= 0 && n > limit)
 981             n = limit;
 982         start = self->buffer;
 983         end = start + n;
 984         s = start;
 985         while (s < end) {
 986             if (*s++ == '\n') {
 987                 res = PyBytes_FromStringAndSize(start, s - start);
 988                 if (res == NULL)
 989                     goto end;
 990                 self->pos = s - start;
 991                 goto found;
 992             }
 993         }
 994         res = PyBytes_FromStringAndSize(start, n);
 995         if (res == NULL)
 996             goto end;
 997         if (n == limit) {
 998             self->pos = n;
 999             break;
1000         }
1001         if (PyList_Append(chunks, res) < 0) {
1002             Py_CLEAR(res);
1003             goto end;
1004         }
1005         Py_CLEAR(res);
1006         written += n;
1007         if (limit >= 0)
1008             limit -= n;
1009     }
1010 found:
1011     if (res != NULL && PyList_Append(chunks, res) < 0) {
1012         Py_CLEAR(res);
1013         goto end;
1014     }
1015     Py_CLEAR(res);
1016     res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1017 
1018 end:
1019     LEAVE_BUFFERED(self)
1020 end_unlocked:
1021     Py_XDECREF(chunks);
1022     return res;
1023 }
1024 
1025 static PyObject *
1026 buffered_readline(buffered *self, PyObject *args)
1027 {
1028     Py_ssize_t limit = -1;
1029 
1030     CHECK_INITIALIZED(self)
1031     if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
1032         return NULL;
1033     return _buffered_readline(self, limit);
1034 }
1035 
1036 
1037 static PyObject *
1038 buffered_tell(buffered *self, PyObject *args)
1039 {
1040     Py_off_t pos;
1041 
1042     CHECK_INITIALIZED(self)
1043     pos = _buffered_raw_tell(self);
1044     if (pos == -1)
1045         return NULL;
1046     pos -= RAW_OFFSET(self);
1047     /* TODO: sanity check (pos >= 0) */
1048     return PyLong_FromOff_t(pos);
1049 }
1050 
1051 static PyObject *
1052 buffered_seek(buffered *self, PyObject *args)
1053 {
1054     Py_off_t target, n;
1055     int whence = 0;
1056     PyObject *targetobj, *res = NULL;
1057 
1058     CHECK_INITIALIZED(self)
1059     if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
1060         return NULL;
1061     }
1062     if (whence < 0 || whence > 2) {
1063         PyErr_Format(PyExc_ValueError,
1064                      "whence must be between 0 and 2, not %d", whence);
1065         return NULL;
1066     }
1067 
1068     CHECK_CLOSED(self, "seek of closed file")
1069 
1070     target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1071     if (target == -1 && PyErr_Occurred())
1072         return NULL;
1073 
1074     if (whence != 2 && self->readable) {
1075         Py_off_t current, avail;
1076         /* Check if seeking leaves us inside the current buffer,
1077            so as to return quickly if possible. Also, we needn't take the
1078            lock in this fast path.
1079            Don't know how to do that when whence == 2, though. */
1080         /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1081            state at this point. */
1082         current = RAW_TELL(self);
1083         avail = READAHEAD(self);
1084         if (avail > 0) {
1085             Py_off_t offset;
1086             if (whence == 0)
1087                 offset = target - (current - RAW_OFFSET(self));
1088             else
1089                 offset = target;
1090             if (offset >= -self->pos && offset <= avail) {
1091                 self->pos += offset;
1092                 return PyLong_FromOff_t(current - avail + offset);
1093             }
1094         }
1095     }
1096 
1097     if (!ENTER_BUFFERED(self))
1098         return NULL;
1099 
1100     /* Fallback: invoke raw seek() method and clear buffer */
1101     if (self->writable) {
1102         res = _bufferedwriter_flush_unlocked(self);
1103         if (res == NULL)
1104             goto end;
1105         Py_CLEAR(res);
1106         _bufferedwriter_reset_buf(self);
1107     }
1108 
1109     /* TODO: align on block boundary and read buffer if needed? */
1110     if (whence == 1)
1111         target -= RAW_OFFSET(self);
1112     n = _buffered_raw_seek(self, target, whence);
1113     if (n == -1)
1114         goto end;
1115     self->raw_pos = -1;
1116     res = PyLong_FromOff_t(n);
1117     if (res != NULL && self->readable)
1118         _bufferedreader_reset_buf(self);
1119 
1120 end:
1121     LEAVE_BUFFERED(self)
1122     return res;
1123 }
1124 
1125 static PyObject *
1126 buffered_truncate(buffered *self, PyObject *args)
1127 {
1128     PyObject *pos = Py_None;
1129     PyObject *res = NULL;
1130 
1131     CHECK_INITIALIZED(self)
1132     if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1133         return NULL;
1134     }
1135 
1136     if (!ENTER_BUFFERED(self))
1137         return NULL;
1138 
1139     if (self->writable) {
1140         res = buffered_flush_and_rewind_unlocked(self);
1141         if (res == NULL)
1142             goto end;
1143         Py_CLEAR(res);
1144     }
1145     res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1146     if (res == NULL)
1147         goto end;
1148     /* Reset cached position */
1149     if (_buffered_raw_tell(self) == -1)
1150         PyErr_Clear();
1151 
1152 end:
1153     LEAVE_BUFFERED(self)
1154     return res;
1155 }
1156 
1157 static PyObject *
1158 buffered_iternext(buffered *self)
1159 {
1160     PyObject *line;
1161     PyTypeObject *tp;
1162 
1163     CHECK_INITIALIZED(self);
1164 
1165     tp = Py_TYPE(self);
1166     if (tp == &PyBufferedReader_Type ||
1167         tp == &PyBufferedRandom_Type) {
1168         /* Skip method call overhead for speed */
1169         line = _buffered_readline(self, -1);
1170     }
1171     else {
1172         line = PyObject_CallMethodObjArgs((PyObject *)self,
1173                                            _PyIO_str_readline, NULL);
1174         if (line && !PyBytes_Check(line)) {
1175             PyErr_Format(PyExc_IOError,
1176                          "readline() should have returned a bytes object, "
1177                          "not '%.200s'", Py_TYPE(line)->tp_name);
1178             Py_DECREF(line);
1179             return NULL;
1180         }
1181     }
1182 
1183     if (line == NULL)
1184         return NULL;
1185 
1186     if (PyBytes_GET_SIZE(line) == 0) {
1187         /* Reached EOF or would have blocked */
1188         Py_DECREF(line);
1189         return NULL;
1190     }
1191 
1192     return line;
1193 }
1194 
1195 static PyObject *
1196 buffered_repr(buffered *self)
1197 {
1198     PyObject *nameobj, *res;
1199 
1200     nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1201     if (nameobj == NULL) {
1202         if (PyErr_ExceptionMatches(PyExc_AttributeError))
1203             PyErr_Clear();
1204         else
1205             return NULL;
1206         res = PyString_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1207     }
1208     else {
1209         PyObject *repr = PyObject_Repr(nameobj);
1210         Py_DECREF(nameobj);
1211         if (repr == NULL)
1212             return NULL;
1213         res = PyString_FromFormat("<%s name=%s>",
1214                                    Py_TYPE(self)->tp_name,
1215                                    PyString_AS_STRING(repr));
1216         Py_DECREF(repr);
1217     }
1218     return res;
1219 }
1220 
1221 /*
1222  * class BufferedReader
1223  */
1224 
1225 PyDoc_STRVAR(bufferedreader_doc,
1226              "Create a new buffered reader using the given readable raw IO object.");
1227 
1228 static void _bufferedreader_reset_buf(buffered *self)
1229 {
1230     self->read_end = -1;
1231 }
1232 
1233 static int
1234 bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
1235 {
1236     char *kwlist[] = {"raw", "buffer_size", NULL};
1237     Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1238     PyObject *raw;
1239 
1240     self->ok = 0;
1241     self->detached = 0;
1242 
1243     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1244                                      &raw, &buffer_size)) {
1245         return -1;
1246     }
1247 
1248     if (_PyIOBase_check_readable(raw, Py_True) == NULL)
1249         return -1;
1250 
1251     Py_CLEAR(self->raw);
1252     Py_INCREF(raw);
1253     self->raw = raw;
1254     self->buffer_size = buffer_size;
1255     self->readable = 1;
1256     self->writable = 0;
1257 
1258     if (_buffered_init(self) < 0)
1259         return -1;
1260     _bufferedreader_reset_buf(self);
1261 
1262     self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1263                                 Py_TYPE(raw) == &PyFileIO_Type);
1264 
1265     self->ok = 1;
1266     return 0;
1267 }
1268 
1269 static Py_ssize_t
1270 _bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
1271 {
1272     Py_buffer buf;
1273     PyObject *memobj, *res;
1274     Py_ssize_t n;
1275     /* NOTE: the buffer needn't be released as its object is NULL. */
1276     if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1277         return -1;
1278     memobj = PyMemoryView_FromBuffer(&buf);
1279     if (memobj == NULL)
1280         return -1;
1281     /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1282        occurs so we needn't do it ourselves.
1283        We then retry reading, ignoring the signal if no handler has
1284        raised (see issue #10956).
1285     */
1286     do {
1287         res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1288     } while (res == NULL && _trap_eintr());
1289     Py_DECREF(memobj);
1290     if (res == NULL)
1291         return -1;
1292     if (res == Py_None) {
1293         /* Non-blocking stream would have blocked. Special return code! */
1294         Py_DECREF(res);
1295         return -2;
1296     }
1297     n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1298     Py_DECREF(res);
1299     if (n < 0 || n > len) {
1300         PyErr_Format(PyExc_IOError,
1301                      "raw readinto() returned invalid length %zd "
1302                      "(should have been between 0 and %zd)", n, len);
1303         return -1;
1304     }
1305     if (n > 0 && self->abs_pos != -1)
1306         self->abs_pos += n;
1307     return n;
1308 }
1309 
1310 static Py_ssize_t
1311 _bufferedreader_fill_buffer(buffered *self)
1312 {
1313     Py_ssize_t start, len, n;
1314     if (VALID_READ_BUFFER(self))
1315         start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1316     else
1317         start = 0;
1318     len = self->buffer_size - start;
1319     n = _bufferedreader_raw_read(self, self->buffer + start, len);
1320     if (n <= 0)
1321         return n;
1322     self->read_end = start + n;
1323     self->raw_pos = start + n;
1324     return n;
1325 }
1326 
1327 static PyObject *
1328 _bufferedreader_read_all(buffered *self)
1329 {
1330     Py_ssize_t current_size;
1331     PyObject *res, *data = NULL;
1332     PyObject *chunks = PyList_New(0);
1333 
1334     if (chunks == NULL)
1335         return NULL;
1336 
1337     /* First copy what we have in the current buffer. */
1338     current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1339     if (current_size) {
1340         data = PyBytes_FromStringAndSize(
1341             self->buffer + self->pos, current_size);
1342         if (data == NULL) {
1343             Py_DECREF(chunks);
1344             return NULL;
1345         }
1346         self->pos += current_size;
1347     }
1348     /* We're going past the buffer's bounds, flush it */
1349     if (self->writable) {
1350         res = buffered_flush_and_rewind_unlocked(self);
1351         if (res == NULL) {
1352             Py_DECREF(chunks);
1353             return NULL;
1354         }
1355         Py_CLEAR(res);
1356     }
1357     _bufferedreader_reset_buf(self);
1358     while (1) {
1359         if (data) {
1360             if (PyList_Append(chunks, data) < 0) {
1361                 Py_DECREF(data);
1362                 Py_DECREF(chunks);
1363                 return NULL;
1364             }
1365             Py_DECREF(data);
1366         }
1367 
1368         /* Read until EOF or until read() would block. */
1369         data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1370         if (data == NULL) {
1371             Py_DECREF(chunks);
1372             return NULL;
1373         }
1374         if (data != Py_None && !PyBytes_Check(data)) {
1375             Py_DECREF(data);
1376             Py_DECREF(chunks);
1377             PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1378             return NULL;
1379         }
1380         if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1381             if (current_size == 0) {
1382                 Py_DECREF(chunks);
1383                 return data;
1384             }
1385             else {
1386                 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1387                 Py_DECREF(data);
1388                 Py_DECREF(chunks);
1389                 return res;
1390             }
1391         }
1392         current_size += PyBytes_GET_SIZE(data);
1393         if (self->abs_pos != -1)
1394             self->abs_pos += PyBytes_GET_SIZE(data);
1395     }
1396 }
1397 
1398 /* Read n bytes from the buffer if it can, otherwise return None.
1399    This function is simple enough that it can run unlocked. */
1400 static PyObject *
1401 _bufferedreader_read_fast(buffered *self, Py_ssize_t n)
1402 {
1403     Py_ssize_t current_size;
1404 
1405     current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1406     if (n <= current_size) {
1407         /* Fast path: the data to read is fully buffered. */
1408         PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1409         if (res != NULL)
1410             self->pos += n;
1411         return res;
1412     }
1413     Py_RETURN_NONE;
1414 }
1415 
1416 /* Generic read function: read from the stream until enough bytes are read,
1417  * or until an EOF occurs or until read() would block.
1418  */
1419 static PyObject *
1420 _bufferedreader_read_generic(buffered *self, Py_ssize_t n)
1421 {
1422     PyObject *res = NULL;
1423     Py_ssize_t current_size, remaining, written;
1424     char *out;
1425 
1426     current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1427     if (n <= current_size)
1428         return _bufferedreader_read_fast(self, n);
1429 
1430     res = PyBytes_FromStringAndSize(NULL, n);
1431     if (res == NULL)
1432         goto error;
1433     out = PyBytes_AS_STRING(res);
1434     remaining = n;
1435     written = 0;
1436     if (current_size > 0) {
1437         memcpy(out, self->buffer + self->pos, current_size);
1438         remaining -= current_size;
1439         written += current_size;
1440         self->pos += current_size;
1441     }
1442     /* Flush the write buffer if necessary */
1443     if (self->writable) {
1444         PyObject *r = buffered_flush_and_rewind_unlocked(self);
1445         if (r == NULL)
1446             goto error;
1447         Py_DECREF(r);
1448     }
1449     _bufferedreader_reset_buf(self);
1450     while (remaining > 0) {
1451         /* We want to read a whole block at the end into buffer.
1452            If we had readv() we could do this in one pass. */
1453         Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1454         if (r == 0)
1455             break;
1456         r = _bufferedreader_raw_read(self, out + written, r);
1457         if (r == -1)
1458             goto error;
1459         if (r == 0 || r == -2) {
1460             /* EOF occurred or read() would block. */
1461             if (r == 0 || written > 0) {
1462                 if (_PyBytes_Resize(&res, written))
1463                     goto error;
1464                 return res;
1465             }
1466             Py_DECREF(res);
1467             Py_INCREF(Py_None);
1468             return Py_None;
1469         }
1470         remaining -= r;
1471         written += r;
1472     }
1473     assert(remaining <= self->buffer_size);
1474     self->pos = 0;
1475     self->raw_pos = 0;
1476     self->read_end = 0;
1477     /* NOTE: when the read is satisfied, we avoid issuing any additional
1478        reads, which could block indefinitely (e.g. on a socket).
1479        See issue #9550. */
1480     while (remaining > 0 && self->read_end < self->buffer_size) {
1481         Py_ssize_t r = _bufferedreader_fill_buffer(self);
1482         if (r == -1)
1483             goto error;
1484         if (r == 0 || r == -2) {
1485             /* EOF occurred or read() would block. */
1486             if (r == 0 || written > 0) {
1487                 if (_PyBytes_Resize(&res, written))
1488                     goto error;
1489                 return res;
1490             }
1491             Py_DECREF(res);
1492             Py_INCREF(Py_None);
1493             return Py_None;
1494         }
1495         if (remaining > r) {
1496             memcpy(out + written, self->buffer + self->pos, r);
1497             written += r;
1498             self->pos += r;
1499             remaining -= r;
1500         }
1501         else if (remaining > 0) {
1502             memcpy(out + written, self->buffer + self->pos, remaining);
1503             written += remaining;
1504             self->pos += remaining;
1505             remaining = 0;
1506         }
1507         if (remaining == 0)
1508             break;
1509     }
1510 
1511     return res;
1512 
1513 error:
1514     Py_XDECREF(res);
1515     return NULL;
1516 }
1517 
1518 static PyObject *
1519 _bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
1520 {
1521     Py_ssize_t have, r;
1522 
1523     have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1524     /* Constraints:
1525        1. we don't want to advance the file position.
1526        2. we don't want to lose block alignment, so we can't shift the buffer
1527           to make some place.
1528        Therefore, we either return `have` bytes (if > 0), or a full buffer.
1529     */
1530     if (have > 0) {
1531         return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1532     }
1533 
1534     /* Fill the buffer from the raw stream, and copy it to the result. */
1535     _bufferedreader_reset_buf(self);
1536     r = _bufferedreader_fill_buffer(self);
1537     if (r == -1)
1538         return NULL;
1539     if (r == -2)
1540         r = 0;
1541     self->pos = 0;
1542     return PyBytes_FromStringAndSize(self->buffer, r);
1543 }
1544 
1545 static PyMethodDef bufferedreader_methods[] = {
1546     /* BufferedIOMixin methods */
1547     {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1548     {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1549     {"close", (PyCFunction)buffered_close, METH_NOARGS},
1550     {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1551     {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1552     {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1553     {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1554     {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
1555 
1556     {"read", (PyCFunction)buffered_read, METH_VARARGS},
1557     {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1558     {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
1559     {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1560     {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1561     {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1562     {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1563     {NULL, NULL}
1564 };
1565 
1566 static PyMemberDef bufferedreader_members[] = {
1567     {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
1568     {NULL}
1569 };
1570 
1571 static PyGetSetDef bufferedreader_getset[] = {
1572     {"closed", (getter)buffered_closed_get, NULL, NULL},
1573     {"name", (getter)buffered_name_get, NULL, NULL},
1574     {"mode", (getter)buffered_mode_get, NULL, NULL},
1575     {NULL}
1576 };
1577 
1578 
1579 PyTypeObject PyBufferedReader_Type = {
1580     PyVarObject_HEAD_INIT(NULL, 0)
1581     "_io.BufferedReader",       /*tp_name*/
1582     sizeof(buffered),           /*tp_basicsize*/
1583     0,                          /*tp_itemsize*/
1584     (destructor)buffered_dealloc,     /*tp_dealloc*/
1585     0,                          /*tp_print*/
1586     0,                          /*tp_getattr*/
1587     0,                          /*tp_setattr*/
1588     0,                          /*tp_compare */
1589     (reprfunc)buffered_repr,    /*tp_repr*/
1590     0,                          /*tp_as_number*/
1591     0,                          /*tp_as_sequence*/
1592     0,                          /*tp_as_mapping*/
1593     0,                          /*tp_hash */
1594     0,                          /*tp_call*/
1595     0,                          /*tp_str*/
1596     0,                          /*tp_getattro*/
1597     0,                          /*tp_setattro*/
1598     0,                          /*tp_as_buffer*/
1599     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1600             | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1601     bufferedreader_doc,         /* tp_doc */
1602     (traverseproc)buffered_traverse, /* tp_traverse */
1603     (inquiry)buffered_clear,    /* tp_clear */
1604     0,                          /* tp_richcompare */
1605     offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
1606     0,                          /* tp_iter */
1607     (iternextfunc)buffered_iternext, /* tp_iternext */
1608     bufferedreader_methods,     /* tp_methods */
1609     bufferedreader_members,     /* tp_members */
1610     bufferedreader_getset,      /* tp_getset */
1611     0,                          /* tp_base */
1612     0,                          /* tp_dict */
1613     0,                          /* tp_descr_get */
1614     0,                          /* tp_descr_set */
1615     offsetof(buffered, dict), /* tp_dictoffset */
1616     (initproc)bufferedreader_init, /* tp_init */
1617     0,                          /* tp_alloc */
1618     PyType_GenericNew,          /* tp_new */
1619 };
1620 

1621 
1622 
1623 static int
1624 complain_about_max_buffer_size(void)
1625 {
1626     if (PyErr_WarnEx(PyExc_DeprecationWarning,
1627                      "max_buffer_size is deprecated", 1) < 0)
1628         return 0;
1629     return 1;
1630 }
1631 
1632 /*
1633  * class BufferedWriter
1634  */
1635 PyDoc_STRVAR(bufferedwriter_doc,
1636     "A buffer for a writeable sequential RawIO object.\n"
1637     "\n"
1638     "The constructor creates a BufferedWriter for the given writeable raw\n"
1639     "stream. If the buffer_size is not given, it defaults to\n"
1640     "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1641     );
1642 
1643 static void
1644 _bufferedwriter_reset_buf(buffered *self)
1645 {
1646     self->write_pos = 0;
1647     self->write_end = -1;
1648 }
1649 
1650 static int
1651 bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
1652 {
1653     /* TODO: properly deprecate max_buffer_size */
1654     char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1655     Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1656     Py_ssize_t max_buffer_size = -234;
1657     PyObject *raw;
1658 
1659     self->ok = 0;
1660     self->detached = 0;
1661 
1662     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1663                                      &raw, &buffer_size, &max_buffer_size)) {
1664         return -1;
1665     }
1666 
1667     if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1668         return -1;
1669 
1670     if (_PyIOBase_check_writable(raw, Py_True) == NULL)
1671         return -1;
1672 
1673     Py_CLEAR(self->raw);
1674     Py_INCREF(raw);
1675     self->raw = raw;
1676     self->readable = 0;
1677     self->writable = 1;
1678 
1679     self->buffer_size = buffer_size;
1680     if (_buffered_init(self) < 0)
1681         return -1;
1682     _bufferedwriter_reset_buf(self);
1683     self->pos = 0;
1684 
1685     self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1686                                 Py_TYPE(raw) == &PyFileIO_Type);
1687 
1688     self->ok = 1;
1689     return 0;
1690 }
1691 
1692 static Py_ssize_t
1693 _bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
1694 {
1695     Py_buffer buf;
1696     PyObject *memobj, *res;
1697     Py_ssize_t n;
1698     int errnum;
1699     /* NOTE: the buffer needn't be released as its object is NULL. */
1700     if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1701         return -1;
1702     memobj = PyMemoryView_FromBuffer(&buf);
1703     if (memobj == NULL)
1704         return -1;
1705     /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1706        occurs so we needn't do it ourselves.
1707        We then retry writing, ignoring the signal if no handler has
1708        raised (see issue #10956).
1709     */
1710     do {
1711         errno = 0;
1712         res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1713         errnum = errno;
1714     } while (res == NULL && _trap_eintr());
1715     Py_DECREF(memobj);
1716     if (res == NULL)
1717         return -1;
1718     if (res == Py_None) {
1719         /* Non-blocking stream would have blocked. Special return code!
1720            Being paranoid we reset errno in case it is changed by code
1721            triggered by a decref.  errno is used by _set_BlockingIOError(). */
1722         Py_DECREF(res);
1723         errno = errnum;
1724         return -2;
1725     }
1726     n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1727     Py_DECREF(res);
1728     if (n < 0 || n > len) {
1729         PyErr_Format(PyExc_IOError,
1730                      "raw write() returned invalid length %zd "
1731                      "(should have been between 0 and %zd)", n, len);
1732         return -1;
1733     }
1734     if (n > 0 && self->abs_pos != -1)
1735         self->abs_pos += n;
1736     return n;
1737 }
1738 
1739 /* `restore_pos` is 1 if we need to restore the raw stream position at
1740    the end, 0 otherwise. */
1741 static PyObject *
1742 _bufferedwriter_flush_unlocked(buffered *self)
1743 {
1744     Py_ssize_t written = 0;
1745     Py_off_t n, rewind;
1746 
1747     if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1748         goto end;
1749     /* First, rewind */
1750     rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1751     if (rewind != 0) {
1752         n = _buffered_raw_seek(self, -rewind, 1);
1753         if (n < 0) {
1754             goto error;
1755         }
1756         self->raw_pos -= rewind;
1757     }
1758     while (self->write_pos < self->write_end) {
1759         n = _bufferedwriter_raw_write(self,
1760             self->buffer + self->write_pos,
1761             Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1762                              Py_off_t, Py_ssize_t));
1763         if (n == -1) {
1764             goto error;
1765         }
1766         else if (n == -2) {
1767             _set_BlockingIOError("write could not complete without blocking",
1768                                  0);
1769             goto error;
1770         }
1771         self->write_pos += n;
1772         self->raw_pos = self->write_pos;
1773         written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1774         /* Partial writes can return successfully when interrupted by a
1775            signal (see write(2)).  We must run signal handlers before
1776            blocking another time, possibly indefinitely. */
1777         if (PyErr_CheckSignals() < 0)
1778             goto error;
1779     }
1780 
1781     _bufferedwriter_reset_buf(self);
1782 
1783 end:
1784     Py_RETURN_NONE;
1785 
1786 error:
1787     return NULL;
1788 }
1789 
1790 static PyObject *
1791 bufferedwriter_write(buffered *self, PyObject *args)
1792 {
1793     PyObject *res = NULL;
1794     Py_buffer buf;
1795     Py_ssize_t written, avail, remaining;
1796     Py_off_t offset;
1797 
1798     CHECK_INITIALIZED(self)
1799     if (!PyArg_ParseTuple(args, "s*:write", &buf)) {
1800         return NULL;
1801     }
1802 
1803     if (IS_CLOSED(self)) {
1804         PyErr_SetString(PyExc_ValueError, "write to closed file");
1805         PyBuffer_Release(&buf);
1806         return NULL;
1807     }
1808 
1809     if (!ENTER_BUFFERED(self)) {
1810         PyBuffer_Release(&buf);
1811         return NULL;
1812     }
1813 
1814     /* Fast path: the data to write can be fully buffered. */
1815     if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1816         self->pos = 0;
1817         self->raw_pos = 0;
1818     }
1819     avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1820     if (buf.len <= avail) {
1821         memcpy(self->buffer + self->pos, buf.buf, buf.len);
1822         if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
1823             self->write_pos = self->pos;
1824         }
1825         ADJUST_POSITION(self, self->pos + buf.len);
1826         if (self->pos > self->write_end)
1827             self->write_end = self->pos;
1828         written = buf.len;
1829         goto end;
1830     }
1831 
1832     /* First write the current buffer */
1833     res = _bufferedwriter_flush_unlocked(self);
1834     if (res == NULL) {
1835         Py_ssize_t *w = _buffered_check_blocking_error();
1836         if (w == NULL)
1837             goto error;
1838         if (self->readable)
1839             _bufferedreader_reset_buf(self);
1840         /* Make some place by shifting the buffer. */
1841         assert(VALID_WRITE_BUFFER(self));
1842         memmove(self->buffer, self->buffer + self->write_pos,
1843                 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1844                                  Py_off_t, Py_ssize_t));
1845         self->write_end -= self->write_pos;
1846         self->raw_pos -= self->write_pos;
1847         self->pos -= self->write_pos;
1848         self->write_pos = 0;
1849         avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1850                                  Py_off_t, Py_ssize_t);
1851         if (buf.len <= avail) {
1852             /* Everything can be buffered */
1853             PyErr_Clear();
1854             memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1855             self->write_end += buf.len;
1856             self->pos += buf.len;
1857             written = buf.len;
1858             goto end;
1859         }
1860         /* Buffer as much as possible. */
1861         memcpy(self->buffer + self->write_end, buf.buf, avail);
1862         self->write_end += avail;
1863         self->pos += avail;
1864         /* XXX Modifying the existing exception e using the pointer w
1865            will change e.characters_written but not e.args[2].
1866            Therefore we just replace with a new error. */
1867         _set_BlockingIOError("write could not complete without blocking",
1868                              avail);
1869         goto error;
1870     }
1871     Py_CLEAR(res);
1872 
1873     /* Adjust the raw stream position if it is away from the logical stream
1874        position. This happens if the read buffer has been filled but not
1875        modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1876        the raw stream by itself).
1877        Fixes issue #6629.
1878     */
1879     offset = RAW_OFFSET(self);
1880     if (offset != 0) {
1881         if (_buffered_raw_seek(self, -offset, 1) < 0)
1882             goto error;
1883         self->raw_pos -= offset;
1884     }
1885 
1886     /* Then write buf itself. At this point the buffer has been emptied. */
1887     remaining = buf.len;
1888     written = 0;
1889     while (remaining > self->buffer_size) {
1890         Py_ssize_t n = _bufferedwriter_raw_write(
1891             self, (char *) buf.buf + written, buf.len - written);
1892         if (n == -1) {
1893             goto error;
1894         } else if (n == -2) {
1895             /* Write failed because raw file is non-blocking */
1896             if (remaining > self->buffer_size) {
1897                 /* Can't buffer everything, still buffer as much as possible */
1898                 memcpy(self->buffer,
1899                        (char *) buf.buf + written, self->buffer_size);
1900                 self->raw_pos = 0;
1901                 ADJUST_POSITION(self, self->buffer_size);
1902                 self->write_end = self->buffer_size;
1903                 written += self->buffer_size;
1904                 _set_BlockingIOError("write could not complete without "
1905                                      "blocking", written);
1906                 goto error;
1907             }
1908             PyErr_Clear();
1909             break;
1910         }
1911         written += n;
1912         remaining -= n;
1913         /* Partial writes can return successfully when interrupted by a
1914            signal (see write(2)).  We must run signal handlers before
1915            blocking another time, possibly indefinitely. */
1916         if (PyErr_CheckSignals() < 0)
1917             goto error;
1918     }
1919     if (self->readable)
1920         _bufferedreader_reset_buf(self);
1921     if (remaining > 0) {
1922         memcpy(self->buffer, (char *) buf.buf + written, remaining);
1923         written += remaining;
1924     }
1925     self->write_pos = 0;
1926     /* TODO: sanity check (remaining >= 0) */
1927     self->write_end = remaining;
1928     ADJUST_POSITION(self, remaining);
1929     self->raw_pos = 0;
1930 
1931 end:
1932     res = PyLong_FromSsize_t(written);
1933 
1934 error:
1935     LEAVE_BUFFERED(self)
1936     PyBuffer_Release(&buf);
1937     return res;
1938 }
1939 
1940 static PyMethodDef bufferedwriter_methods[] = {
1941     /* BufferedIOMixin methods */
1942     {"close", (PyCFunction)buffered_close, METH_NOARGS},
1943     {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1944     {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1945     {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1946     {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1947     {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1948     {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
1949 
1950     {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1951     {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1952     {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1953     {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1954     {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1955     {NULL, NULL}
1956 };
1957 
1958 static PyMemberDef bufferedwriter_members[] = {
1959     {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
1960     {NULL}
1961 };
1962 
1963 static PyGetSetDef bufferedwriter_getset[] = {
1964     {"closed", (getter)buffered_closed_get, NULL, NULL},
1965     {"name", (getter)buffered_name_get, NULL, NULL},
1966     {"mode", (getter)buffered_mode_get, NULL, NULL},
1967     {NULL}
1968 };
1969 
1970 
1971 PyTypeObject PyBufferedWriter_Type = {
1972     PyVarObject_HEAD_INIT(NULL, 0)
1973     "_io.BufferedWriter",       /*tp_name*/
1974     sizeof(buffered),           /*tp_basicsize*/
1975     0,                          /*tp_itemsize*/
1976     (destructor)buffered_dealloc,     /*tp_dealloc*/
1977     0,                          /*tp_print*/
1978     0,                          /*tp_getattr*/
1979     0,                          /*tp_setattr*/
1980     0,                          /*tp_compare */
1981     (reprfunc)buffered_repr,    /*tp_repr*/
1982     0,                          /*tp_as_number*/
1983     0,                          /*tp_as_sequence*/
1984     0,                          /*tp_as_mapping*/
1985     0,                          /*tp_hash */
1986     0,                          /*tp_call*/
1987     0,                          /*tp_str*/
1988     0,                          /*tp_getattro*/
1989     0,                          /*tp_setattro*/
1990     0,                          /*tp_as_buffer*/
1991     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1992         | Py_TPFLAGS_HAVE_GC,   /*tp_flags*/
1993     bufferedwriter_doc,         /* tp_doc */
1994     (traverseproc)buffered_traverse, /* tp_traverse */
1995     (inquiry)buffered_clear,    /* tp_clear */
1996     0,                          /* tp_richcompare */
1997     offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
1998     0,                          /* tp_iter */
1999     0,                          /* tp_iternext */
2000     bufferedwriter_methods,     /* tp_methods */
2001     bufferedwriter_members,     /* tp_members */
2002     bufferedwriter_getset,      /* tp_getset */
2003     0,                          /* tp_base */
2004     0,                          /* tp_dict */
2005     0,                          /* tp_descr_get */
2006     0,                          /* tp_descr_set */
2007     offsetof(buffered, dict),   /* tp_dictoffset */
2008     (initproc)bufferedwriter_init, /* tp_init */
2009     0,                          /* tp_alloc */
2010     PyType_GenericNew,          /* tp_new */
2011 };
2012 

2013 
2014 
2015 /*
2016  * BufferedRWPair
2017  */
2018 
2019 PyDoc_STRVAR(bufferedrwpair_doc,
2020     "A buffered reader and writer object together.\n"
2021     "\n"
2022     "A buffered reader object and buffered writer object put together to\n"
2023     "form a sequential IO object that can read and write. This is typically\n"
2024     "used with a socket or two-way pipe.\n"
2025     "\n"
2026     "reader and writer are RawIOBase objects that are readable and\n"
2027     "writeable respectively. If the buffer_size is omitted it defaults to\n"
2028     "DEFAULT_BUFFER_SIZE.\n"
2029     );
2030 
2031 /* XXX The usefulness of this (compared to having two separate IO objects) is
2032  * questionable.
2033  */
2034 
2035 typedef struct {
2036     PyObject_HEAD
2037     buffered *reader;
2038     buffered *writer;
2039     PyObject *dict;
2040     PyObject *weakreflist;
2041 } rwpair;
2042 
2043 static int
2044 bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
2045 {
2046     PyObject *reader, *writer;
2047     Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
2048     Py_ssize_t max_buffer_size = -234;
2049 
2050     if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
2051                           &buffer_size, &max_buffer_size)) {
2052         return -1;
2053     }
2054 
2055     if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2056         return -1;
2057 
2058     if (_PyIOBase_check_readable(reader, Py_True) == NULL)
2059         return -1;
2060     if (_PyIOBase_check_writable(writer, Py_True) == NULL)
2061         return -1;
2062 
2063     self->reader = (buffered *) PyObject_CallFunction(
2064             (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
2065     if (self->reader == NULL)
2066         return -1;
2067 
2068     self->writer = (buffered *) PyObject_CallFunction(
2069             (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
2070     if (self->writer == NULL) {
2071         Py_CLEAR(self->reader);
2072         return -1;
2073     }
2074 
2075     return 0;
2076 }
2077 
2078 static int
2079 bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
2080 {
2081     Py_VISIT(self->dict);
2082     return 0;
2083 }
2084 
2085 static int
2086 bufferedrwpair_clear(rwpair *self)
2087 {
2088     Py_CLEAR(self->reader);
2089     Py_CLEAR(self->writer);
2090     Py_CLEAR(self->dict);
2091     return 0;
2092 }
2093 
2094 static void
2095 bufferedrwpair_dealloc(rwpair *self)
2096 {
2097     _PyObject_GC_UNTRACK(self);
2098     Py_CLEAR(self->reader);
2099     Py_CLEAR(self->writer);
2100     Py_CLEAR(self->dict);
2101     Py_TYPE(self)->tp_free((PyObject *) self);
2102 }
2103 
2104 static PyObject *
2105 _forward_call(buffered *self, const char *name, PyObject *args)
2106 {
2107     PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
2108     PyObject *ret;
2109 
2110     if (func == NULL) {
2111         PyErr_SetString(PyExc_AttributeError, name);
2112         return NULL;
2113     }
2114 
2115     ret = PyObject_CallObject(func, args);
2116     Py_DECREF(func);
2117     return ret;
2118 }
2119 
2120 static PyObject *
2121 bufferedrwpair_read(rwpair *self, PyObject *args)
2122 {
2123     return _forward_call(self->reader, "read", args);
2124 }
2125 
2126 static PyObject *
2127 bufferedrwpair_peek(rwpair *self, PyObject *args)
2128 {
2129     return _forward_call(self->reader, "peek", args);
2130 }
2131 
2132 static PyObject *
2133 bufferedrwpair_read1(rwpair *self, PyObject *args)
2134 {
2135     return _forward_call(self->reader, "read1", args);
2136 }
2137 
2138 static PyObject *
2139 bufferedrwpair_readinto(rwpair *self, PyObject *args)
2140 {
2141     return _forward_call(self->reader, "readinto", args);
2142 }
2143 
2144 static PyObject *
2145 bufferedrwpair_write(rwpair *self, PyObject *args)
2146 {
2147     return _forward_call(self->writer, "write", args);
2148 }
2149 
2150 static PyObject *
2151 bufferedrwpair_flush(rwpair *self, PyObject *args)
2152 {
2153     return _forward_call(self->writer, "flush", args);
2154 }
2155 
2156 static PyObject *
2157 bufferedrwpair_readable(rwpair *self, PyObject *args)
2158 {
2159     return _forward_call(self->reader, "readable", args);
2160 }
2161 
2162 static PyObject *
2163 bufferedrwpair_writable(rwpair *self, PyObject *args)
2164 {
2165     return _forward_call(self->writer, "writable", args);
2166 }
2167 
2168 static PyObject *
2169 bufferedrwpair_close(rwpair *self, PyObject *args)
2170 {
2171     PyObject *ret = _forward_call(self->writer, "close", args);
2172     if (ret == NULL)
2173         return NULL;
2174     Py_DECREF(ret);
2175 
2176     return _forward_call(self->reader, "close", args);
2177 }
2178 
2179 static PyObject *
2180 bufferedrwpair_isatty(rwpair *self, PyObject *args)
2181 {
2182     PyObject *ret = _forward_call(self->writer, "isatty", args);
2183 
2184     if (ret != Py_False) {
2185         /* either True or exception */
2186         return ret;
2187     }
2188     Py_DECREF(ret);
2189 
2190     return _forward_call(self->reader, "isatty", args);
2191 }
2192 
2193 static PyObject *
2194 bufferedrwpair_closed_get(rwpair *self, void *context)
2195 {
2196     if (self->writer == NULL) {
2197         PyErr_SetString(PyExc_RuntimeError,
2198                 "the BufferedRWPair object is being garbage-collected");
2199         return NULL;
2200     }
2201     return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2202 }
2203 
2204 static PyMethodDef bufferedrwpair_methods[] = {
2205     {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2206     {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2207     {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2208     {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
2209 
2210     {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2211     {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
2212 
2213     {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2214     {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
2215 
2216     {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2217     {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
2218 
2219     {NULL, NULL}
2220 };
2221 
2222 static PyGetSetDef bufferedrwpair_getset[] = {
2223     {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
2224     {NULL}
2225 };
2226 
2227 PyTypeObject PyBufferedRWPair_Type = {
2228     PyVarObject_HEAD_INIT(NULL, 0)
2229     "_io.BufferedRWPair",       /*tp_name*/
2230     sizeof(rwpair),            /*tp_basicsize*/
2231     0,                          /*tp_itemsize*/
2232     (destructor)bufferedrwpair_dealloc,     /*tp_dealloc*/
2233     0,                          /*tp_print*/
2234     0,                          /*tp_getattr*/
2235     0,                          /*tp_setattr*/
2236     0,                          /*tp_compare */
2237     0,                          /*tp_repr*/
2238     0,                          /*tp_as_number*/
2239     0,                          /*tp_as_sequence*/
2240     0,                          /*tp_as_mapping*/
2241     0,                          /*tp_hash */
2242     0,                          /*tp_call*/
2243     0,                          /*tp_str*/
2244     0,                          /*tp_getattro*/
2245     0,                          /*tp_setattro*/
2246     0,                          /*tp_as_buffer*/
2247     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2248         | Py_TPFLAGS_HAVE_GC,   /* tp_flags */
2249     bufferedrwpair_doc,         /* tp_doc */
2250     (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2251     (inquiry)bufferedrwpair_clear, /* tp_clear */
2252     0,                          /* tp_richcompare */
2253     offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
2254     0,                          /* tp_iter */
2255     0,                          /* tp_iternext */
2256     bufferedrwpair_methods,     /* tp_methods */
2257     0,                          /* tp_members */
2258     bufferedrwpair_getset,      /* tp_getset */
2259     0,                          /* tp_base */
2260     0,                          /* tp_dict */
2261     0,                          /* tp_descr_get */
2262     0,                          /* tp_descr_set */
2263     offsetof(rwpair, dict),     /* tp_dictoffset */
2264     (initproc)bufferedrwpair_init, /* tp_init */
2265     0,                          /* tp_alloc */
2266     PyType_GenericNew,          /* tp_new */
2267 };
2268 

2269 
2270 
2271 /*
2272  * BufferedRandom
2273  */
2274 
2275 PyDoc_STRVAR(bufferedrandom_doc,
2276     "A buffered interface to random access streams.\n"
2277     "\n"
2278     "The constructor creates a reader and writer for a seekable stream,\n"
2279     "raw, given in the first argument. If the buffer_size is omitted it\n"
2280     "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2281     );
2282 
2283 static int
2284 bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
2285 {
2286     char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2287     Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
2288     Py_ssize_t max_buffer_size = -234;
2289     PyObject *raw;
2290 
2291     self->ok = 0;
2292     self->detached = 0;
2293 
2294     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2295                                      &raw, &buffer_size, &max_buffer_size)) {
2296         return -1;
2297     }
2298 
2299     if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2300         return -1;
2301 
2302     if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
2303         return -1;
2304     if (_PyIOBase_check_readable(raw, Py_True) == NULL)
2305         return -1;
2306     if (_PyIOBase_check_writable(raw, Py_True) == NULL)
2307         return -1;
2308 
2309     Py_CLEAR(self->raw);
2310     Py_INCREF(raw);
2311     self->raw = raw;
2312     self->buffer_size = buffer_size;
2313     self->readable = 1;
2314     self->writable = 1;
2315 
2316     if (_buffered_init(self) < 0)
2317         return -1;
2318     _bufferedreader_reset_buf(self);
2319     _bufferedwriter_reset_buf(self);
2320     self->pos = 0;
2321 
2322     self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2323                                 Py_TYPE(raw) == &PyFileIO_Type);
2324 
2325     self->ok = 1;
2326     return 0;
2327 }
2328 
2329 static PyMethodDef bufferedrandom_methods[] = {
2330     /* BufferedIOMixin methods */
2331     {"close", (PyCFunction)buffered_close, METH_NOARGS},
2332     {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2333     {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2334     {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2335     {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2336     {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2337     {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2338 
2339     {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2340 
2341     {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2342     {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2343     {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2344     {"read", (PyCFunction)buffered_read, METH_VARARGS},
2345     {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2346     {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2347     {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2348     {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2349     {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
2350     {NULL, NULL}
2351 };
2352 
2353 static PyMemberDef bufferedrandom_members[] = {
2354     {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
2355     {NULL}
2356 };
2357 
2358 static PyGetSetDef bufferedrandom_getset[] = {
2359     {"closed", (getter)buffered_closed_get, NULL, NULL},
2360     {"name", (getter)buffered_name_get, NULL, NULL},
2361     {"mode", (getter)buffered_mode_get, NULL, NULL},
2362     {NULL}
2363 };
2364 
2365 
2366 PyTypeObject PyBufferedRandom_Type = {
2367     PyVarObject_HEAD_INIT(NULL, 0)
2368     "_io.BufferedRandom",       /*tp_name*/
2369     sizeof(buffered),           /*tp_basicsize*/
2370     0,                          /*tp_itemsize*/
2371     (destructor)buffered_dealloc,     /*tp_dealloc*/
2372     0,                          /*tp_print*/
2373     0,                          /*tp_getattr*/
2374     0,                          /*tp_setattr*/
2375     0,                          /*tp_compare */
2376     (reprfunc)buffered_repr,    /*tp_repr*/
2377     0,                          /*tp_as_number*/
2378     0,                          /*tp_as_sequence*/
2379     0,                          /*tp_as_mapping*/
2380     0,                          /*tp_hash */
2381     0,                          /*tp_call*/
2382     0,                          /*tp_str*/
2383     0,                          /*tp_getattro*/
2384     0,                          /*tp_setattro*/
2385     0,                          /*tp_as_buffer*/
2386     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2387         | Py_TPFLAGS_HAVE_GC,   /*tp_flags*/
2388     bufferedrandom_doc,         /* tp_doc */
2389     (traverseproc)buffered_traverse, /* tp_traverse */
2390     (inquiry)buffered_clear,    /* tp_clear */
2391     0,                          /* tp_richcompare */
2392     offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2393     0,                          /* tp_iter */
2394     (iternextfunc)buffered_iternext, /* tp_iternext */
2395     bufferedrandom_methods,     /* tp_methods */
2396     bufferedrandom_members,     /* tp_members */
2397     bufferedrandom_getset,      /* tp_getset */
2398     0,                          /* tp_base */
2399     0,                          /*tp_dict*/
2400     0,                          /* tp_descr_get */
2401     0,                          /* tp_descr_set */
2402     offsetof(buffered, dict), /*tp_dictoffset*/
2403     (initproc)bufferedrandom_init, /* tp_init */
2404     0,                          /* tp_alloc */
2405     PyType_GenericNew,          /* tp_new */
2406 };