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 */
19PyDoc_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
35static PyObject *
36bufferediobase_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
69static PyObject *
70bufferediobase_unsupported(const char *message)
71{
72    PyErr_SetString(_PyIO_unsupported_operation, message);
73    return NULL;
74}
75
76PyDoc_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
82static PyObject *
83bufferediobase_detach(PyObject *self)
84{
85    return bufferediobase_unsupported("detach");
86}
87
88PyDoc_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
106static PyObject *
107bufferediobase_read(PyObject *self, PyObject *args)
108{
109    return bufferediobase_unsupported("read");
110}
111
112PyDoc_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
119static PyObject *
120bufferediobase_read1(PyObject *self, PyObject *args)
121{
122    return bufferediobase_unsupported("read1");
123}
124
125PyDoc_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
134static PyObject *
135bufferediobase_write(PyObject *self, PyObject *args)
136{
137    return bufferediobase_unsupported("write");
138}
139
140
141static 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
150PyTypeObject 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
192typedef 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
264static 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
365static void
366buffered_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
389static int
390buffered_traverse(buffered *self, visitproc visit, void *arg)
391{
392    Py_VISIT(self->raw);
393    Py_VISIT(self->dict);
394    return 0;
395}
396
397static int
398buffered_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
416static PyObject *
417buffered_simple_flush(buffered *self, PyObject *args)
418{
419    CHECK_INITIALIZED(self)
420    return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
421}
422
423static int
424buffered_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
437static PyObject *
438buffered_closed_get(buffered *self, void *context)
439{
440    CHECK_INITIALIZED(self)
441    return PyObject_GetAttr(self->raw, _PyIO_str_closed);
442}
443
444static PyObject *
445buffered_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
474end:
475    LEAVE_BUFFERED(self)
476    return res;
477}
478
479/* detach */
480
481static PyObject *
482buffered_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
499static PyObject *
500buffered_seekable(buffered *self, PyObject *args)
501{
502    CHECK_INITIALIZED(self)
503    return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
504}
505
506static PyObject *
507buffered_readable(buffered *self, PyObject *args)
508{
509    CHECK_INITIALIZED(self)
510    return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
511}
512
513static PyObject *
514buffered_writable(buffered *self, PyObject *args)
515{
516    CHECK_INITIALIZED(self)
517    return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
518}
519
520static PyObject *
521buffered_name_get(buffered *self, void *context)
522{
523    CHECK_INITIALIZED(self)
524    return PyObject_GetAttrString(self->raw, "name");
525}
526
527static PyObject *
528buffered_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
536static PyObject *
537buffered_fileno(buffered *self, PyObject *args)
538{
539    CHECK_INITIALIZED(self)
540    return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
541}
542
543static PyObject *
544buffered_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 */
552static PyObject *
553_bufferedwriter_flush_unlocked(buffered *, int);
554static Py_ssize_t
555_bufferedreader_fill_buffer(buffered *self);
556static void
557_bufferedreader_reset_buf(buffered *self);
558static void
559_bufferedwriter_reset_buf(buffered *self);
560static PyObject *
561_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t);
562static PyObject *
563_bufferedreader_read_all(buffered *self);
564static PyObject *
565_bufferedreader_read_fast(buffered *self, Py_ssize_t);
566static 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. */
576static 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
593static 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
614static 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
647static 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*/
690static 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
723static PyObject *
724buffered_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
748static PyObject *
749buffered_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
770end:
771    LEAVE_BUFFERED(self)
772    return res;
773}
774
775static PyObject *
776buffered_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
814static PyObject *
815buffered_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
876end:
877    LEAVE_BUFFERED(self)
878    return res;
879}
880
881static PyObject *
882buffered_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
900end:
901    return res;
902}
903
904static 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    }
999found:
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
1007end:
1008    LEAVE_BUFFERED(self)
1009end_unlocked:
1010    Py_XDECREF(chunks);
1011    return res;
1012}
1013
1014static PyObject *
1015buffered_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
1026static PyObject *
1027buffered_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
1040static PyObject *
1041buffered_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
1109end:
1110    LEAVE_BUFFERED(self)
1111    return res;
1112}
1113
1114static PyObject *
1115buffered_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
1150end:
1151    LEAVE_BUFFERED(self)
1152    return res;
1153}
1154
1155static PyObject *
1156buffered_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
1193static PyObject *
1194buffered_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
1223PyDoc_STRVAR(bufferedreader_doc,
1224             "Create a new buffered reader using the given readable raw IO object.");
1225
1226static void _bufferedreader_reset_buf(buffered *self)
1227{
1228    self->read_end = -1;
1229}
1230
1231static int
1232bufferedreader_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
1267static 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
1308static 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
1325static 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. */
1397static 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 */
1416static 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
1502error:
1503    Py_XDECREF(res);
1504    return NULL;
1505}
1506
1507static 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
1534static 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
1555static PyMemberDef bufferedreader_members[] = {
1556    {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
1557    {NULL}
1558};
1559
1560static 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
1568PyTypeObject 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
1611
1612static int
1613complain_about_max_buffer_size(void)
1614{
1615    if (PyErr_WarnEx(PyExc_DeprecationWarning,
1616                     "max_buffer_size is deprecated", 1) < 0)
1617        return 0;
1618    return 1;
1619}
1620
1621/*
1622 * class BufferedWriter
1623 */
1624PyDoc_STRVAR(bufferedwriter_doc,
1625    "A buffer for a writeable sequential RawIO object.\n"
1626    "\n"
1627    "The constructor creates a BufferedWriter for the given writeable raw\n"
1628    "stream. If the buffer_size is not given, it defaults to\n"
1629    "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1630    );
1631
1632static void
1633_bufferedwriter_reset_buf(buffered *self)
1634{
1635    self->write_pos = 0;
1636    self->write_end = -1;
1637}
1638
1639static int
1640bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
1641{
1642    /* TODO: properly deprecate max_buffer_size */
1643    char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1644    Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1645    Py_ssize_t max_buffer_size = -234;
1646    PyObject *raw;
1647
1648    self->ok = 0;
1649    self->detached = 0;
1650
1651    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1652                                     &raw, &buffer_size, &max_buffer_size)) {
1653        return -1;
1654    }
1655
1656    if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1657        return -1;
1658
1659    if (_PyIOBase_check_writable(raw, Py_True) == NULL)
1660        return -1;
1661
1662    Py_CLEAR(self->raw);
1663    Py_INCREF(raw);
1664    self->raw = raw;
1665    self->readable = 0;
1666    self->writable = 1;
1667
1668    self->buffer_size = buffer_size;
1669    if (_buffered_init(self) < 0)
1670        return -1;
1671    _bufferedwriter_reset_buf(self);
1672    self->pos = 0;
1673
1674    self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1675                                Py_TYPE(raw) == &PyFileIO_Type);
1676
1677    self->ok = 1;
1678    return 0;
1679}
1680
1681static Py_ssize_t
1682_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
1683{
1684    Py_buffer buf;
1685    PyObject *memobj, *res;
1686    Py_ssize_t n;
1687    /* NOTE: the buffer needn't be released as its object is NULL. */
1688    if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1689        return -1;
1690    memobj = PyMemoryView_FromBuffer(&buf);
1691    if (memobj == NULL)
1692        return -1;
1693    /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1694       occurs so we needn't do it ourselves.
1695       We then retry writing, ignoring the signal if no handler has
1696       raised (see issue #10956).
1697    */
1698    do {
1699        res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1700    } while (res == NULL && _trap_eintr());
1701    Py_DECREF(memobj);
1702    if (res == NULL)
1703        return -1;
1704    n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1705    Py_DECREF(res);
1706    if (n < 0 || n > len) {
1707        PyErr_Format(PyExc_IOError,
1708                     "raw write() returned invalid length %zd "
1709                     "(should have been between 0 and %zd)", n, len);
1710        return -1;
1711    }
1712    if (n > 0 && self->abs_pos != -1)
1713        self->abs_pos += n;
1714    return n;
1715}
1716
1717/* `restore_pos` is 1 if we need to restore the raw stream position at
1718   the end, 0 otherwise. */
1719static PyObject *
1720_bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
1721{
1722    Py_ssize_t written = 0;
1723    Py_off_t n, rewind;
1724
1725    if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1726        goto end;
1727    /* First, rewind */
1728    rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1729    if (rewind != 0) {
1730        n = _buffered_raw_seek(self, -rewind, 1);
1731        if (n < 0) {
1732            goto error;
1733        }
1734        self->raw_pos -= rewind;
1735    }
1736    while (self->write_pos < self->write_end) {
1737        n = _bufferedwriter_raw_write(self,
1738            self->buffer + self->write_pos,
1739            Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1740                             Py_off_t, Py_ssize_t));
1741        if (n == -1) {
1742            Py_ssize_t *w = _buffered_check_blocking_error();
1743            if (w == NULL)
1744                goto error;
1745            self->write_pos += *w;
1746            self->raw_pos = self->write_pos;
1747            written += *w;
1748            *w = written;
1749            /* Already re-raised */
1750            goto error;
1751        }
1752        self->write_pos += n;
1753        self->raw_pos = self->write_pos;
1754        written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1755        /* Partial writes can return successfully when interrupted by a
1756           signal (see write(2)).  We must run signal handlers before
1757           blocking another time, possibly indefinitely. */
1758        if (PyErr_CheckSignals() < 0)
1759            goto error;
1760    }
1761
1762    if (restore_pos) {
1763        Py_off_t forward = rewind - written;
1764        if (forward != 0) {
1765            n = _buffered_raw_seek(self, forward, 1);
1766            if (n < 0) {
1767                goto error;
1768            }
1769            self->raw_pos += forward;
1770        }
1771    }
1772    _bufferedwriter_reset_buf(self);
1773
1774end:
1775    Py_RETURN_NONE;
1776
1777error:
1778    return NULL;
1779}
1780
1781static PyObject *
1782bufferedwriter_write(buffered *self, PyObject *args)
1783{
1784    PyObject *res = NULL;
1785    Py_buffer buf;
1786    Py_ssize_t written, avail, remaining;
1787    Py_off_t offset;
1788
1789    CHECK_INITIALIZED(self)
1790    if (!PyArg_ParseTuple(args, "s*:write", &buf)) {
1791        return NULL;
1792    }
1793
1794    if (IS_CLOSED(self)) {
1795        PyErr_SetString(PyExc_ValueError, "write to closed file");
1796        PyBuffer_Release(&buf);
1797        return NULL;
1798    }
1799
1800    if (!ENTER_BUFFERED(self)) {
1801        PyBuffer_Release(&buf);
1802        return NULL;
1803    }
1804
1805    /* Fast path: the data to write can be fully buffered. */
1806    if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1807        self->pos = 0;
1808        self->raw_pos = 0;
1809    }
1810    avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1811    if (buf.len <= avail) {
1812        memcpy(self->buffer + self->pos, buf.buf, buf.len);
1813        if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
1814            self->write_pos = self->pos;
1815        }
1816        ADJUST_POSITION(self, self->pos + buf.len);
1817        if (self->pos > self->write_end)
1818            self->write_end = self->pos;
1819        written = buf.len;
1820        goto end;
1821    }
1822
1823    /* First write the current buffer */
1824    res = _bufferedwriter_flush_unlocked(self, 0);
1825    if (res == NULL) {
1826        Py_ssize_t *w = _buffered_check_blocking_error();
1827        if (w == NULL)
1828            goto error;
1829        if (self->readable)
1830            _bufferedreader_reset_buf(self);
1831        /* Make some place by shifting the buffer. */
1832        assert(VALID_WRITE_BUFFER(self));
1833        memmove(self->buffer, self->buffer + self->write_pos,
1834                Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1835                                 Py_off_t, Py_ssize_t));
1836        self->write_end -= self->write_pos;
1837        self->raw_pos -= self->write_pos;
1838        self->pos -= self->write_pos;
1839        self->write_pos = 0;
1840        avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1841                                 Py_off_t, Py_ssize_t);
1842        if (buf.len <= avail) {
1843            /* Everything can be buffered */
1844            PyErr_Clear();
1845            memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1846            self->write_end += buf.len;
1847            written = buf.len;
1848            goto end;
1849        }
1850        /* Buffer as much as possible. */
1851        memcpy(self->buffer + self->write_end, buf.buf, avail);
1852        self->write_end += avail;
1853        /* Already re-raised */
1854        *w = avail;
1855        goto error;
1856    }
1857    Py_CLEAR(res);
1858
1859    /* Adjust the raw stream position if it is away from the logical stream
1860       position. This happens if the read buffer has been filled but not
1861       modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1862       the raw stream by itself).
1863       Fixes issue #6629.
1864    */
1865    offset = RAW_OFFSET(self);
1866    if (offset != 0) {
1867        if (_buffered_raw_seek(self, -offset, 1) < 0)
1868            goto error;
1869        self->raw_pos -= offset;
1870    }
1871
1872    /* Then write buf itself. At this point the buffer has been emptied. */
1873    remaining = buf.len;
1874    written = 0;
1875    while (remaining > self->buffer_size) {
1876        Py_ssize_t n = _bufferedwriter_raw_write(
1877            self, (char *) buf.buf + written, buf.len - written);
1878        if (n == -1) {
1879            Py_ssize_t *w = _buffered_check_blocking_error();
1880            if (w == NULL)
1881                goto error;
1882            written += *w;
1883            remaining -= *w;
1884            if (remaining > self->buffer_size) {
1885                /* Can't buffer everything, still buffer as much as possible */
1886                memcpy(self->buffer,
1887                       (char *) buf.buf + written, self->buffer_size);
1888                self->raw_pos = 0;
1889                ADJUST_POSITION(self, self->buffer_size);
1890                self->write_end = self->buffer_size;
1891                *w = written + self->buffer_size;
1892                /* Already re-raised */
1893                goto error;
1894            }
1895            PyErr_Clear();
1896            break;
1897        }
1898        written += n;
1899        remaining -= n;
1900        /* Partial writes can return successfully when interrupted by a
1901           signal (see write(2)).  We must run signal handlers before
1902           blocking another time, possibly indefinitely. */
1903        if (PyErr_CheckSignals() < 0)
1904            goto error;
1905    }
1906    if (self->readable)
1907        _bufferedreader_reset_buf(self);
1908    if (remaining > 0) {
1909        memcpy(self->buffer, (char *) buf.buf + written, remaining);
1910        written += remaining;
1911    }
1912    self->write_pos = 0;
1913    /* TODO: sanity check (remaining >= 0) */
1914    self->write_end = remaining;
1915    ADJUST_POSITION(self, remaining);
1916    self->raw_pos = 0;
1917
1918end:
1919    res = PyLong_FromSsize_t(written);
1920
1921error:
1922    LEAVE_BUFFERED(self)
1923    PyBuffer_Release(&buf);
1924    return res;
1925}
1926
1927static PyMethodDef bufferedwriter_methods[] = {
1928    /* BufferedIOMixin methods */
1929    {"close", (PyCFunction)buffered_close, METH_NOARGS},
1930    {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1931    {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1932    {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1933    {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1934    {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1935    {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
1936
1937    {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1938    {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1939    {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1940    {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1941    {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1942    {NULL, NULL}
1943};
1944
1945static PyMemberDef bufferedwriter_members[] = {
1946    {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
1947    {NULL}
1948};
1949
1950static PyGetSetDef bufferedwriter_getset[] = {
1951    {"closed", (getter)buffered_closed_get, NULL, NULL},
1952    {"name", (getter)buffered_name_get, NULL, NULL},
1953    {"mode", (getter)buffered_mode_get, NULL, NULL},
1954    {NULL}
1955};
1956
1957
1958PyTypeObject PyBufferedWriter_Type = {
1959    PyVarObject_HEAD_INIT(NULL, 0)
1960    "_io.BufferedWriter",       /*tp_name*/
1961    sizeof(buffered),           /*tp_basicsize*/
1962    0,                          /*tp_itemsize*/
1963    (destructor)buffered_dealloc,     /*tp_dealloc*/
1964    0,                          /*tp_print*/
1965    0,                          /*tp_getattr*/
1966    0,                          /*tp_setattr*/
1967    0,                          /*tp_compare */
1968    (reprfunc)buffered_repr,    /*tp_repr*/
1969    0,                          /*tp_as_number*/
1970    0,                          /*tp_as_sequence*/
1971    0,                          /*tp_as_mapping*/
1972    0,                          /*tp_hash */
1973    0,                          /*tp_call*/
1974    0,                          /*tp_str*/
1975    0,                          /*tp_getattro*/
1976    0,                          /*tp_setattro*/
1977    0,                          /*tp_as_buffer*/
1978    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1979        | Py_TPFLAGS_HAVE_GC,   /*tp_flags*/
1980    bufferedwriter_doc,         /* tp_doc */
1981    (traverseproc)buffered_traverse, /* tp_traverse */
1982    (inquiry)buffered_clear,    /* tp_clear */
1983    0,                          /* tp_richcompare */
1984    offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
1985    0,                          /* tp_iter */
1986    0,                          /* tp_iternext */
1987    bufferedwriter_methods,     /* tp_methods */
1988    bufferedwriter_members,     /* tp_members */
1989    bufferedwriter_getset,      /* tp_getset */
1990    0,                          /* tp_base */
1991    0,                          /* tp_dict */
1992    0,                          /* tp_descr_get */
1993    0,                          /* tp_descr_set */
1994    offsetof(buffered, dict),   /* tp_dictoffset */
1995    (initproc)bufferedwriter_init, /* tp_init */
1996    0,                          /* tp_alloc */
1997    PyType_GenericNew,          /* tp_new */
1998};
1999
2000
2001
2002/*
2003 * BufferedRWPair
2004 */
2005
2006PyDoc_STRVAR(bufferedrwpair_doc,
2007    "A buffered reader and writer object together.\n"
2008    "\n"
2009    "A buffered reader object and buffered writer object put together to\n"
2010    "form a sequential IO object that can read and write. This is typically\n"
2011    "used with a socket or two-way pipe.\n"
2012    "\n"
2013    "reader and writer are RawIOBase objects that are readable and\n"
2014    "writeable respectively. If the buffer_size is omitted it defaults to\n"
2015    "DEFAULT_BUFFER_SIZE.\n"
2016    );
2017
2018/* XXX The usefulness of this (compared to having two separate IO objects) is
2019 * questionable.
2020 */
2021
2022typedef struct {
2023    PyObject_HEAD
2024    buffered *reader;
2025    buffered *writer;
2026    PyObject *dict;
2027    PyObject *weakreflist;
2028} rwpair;
2029
2030static int
2031bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
2032{
2033    PyObject *reader, *writer;
2034    Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
2035    Py_ssize_t max_buffer_size = -234;
2036
2037    if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
2038                          &buffer_size, &max_buffer_size)) {
2039        return -1;
2040    }
2041
2042    if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2043        return -1;
2044
2045    if (_PyIOBase_check_readable(reader, Py_True) == NULL)
2046        return -1;
2047    if (_PyIOBase_check_writable(writer, Py_True) == NULL)
2048        return -1;
2049
2050    self->reader = (buffered *) PyObject_CallFunction(
2051            (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
2052    if (self->reader == NULL)
2053        return -1;
2054
2055    self->writer = (buffered *) PyObject_CallFunction(
2056            (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
2057    if (self->writer == NULL) {
2058        Py_CLEAR(self->reader);
2059        return -1;
2060    }
2061
2062    return 0;
2063}
2064
2065static int
2066bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
2067{
2068    Py_VISIT(self->dict);
2069    return 0;
2070}
2071
2072static int
2073bufferedrwpair_clear(rwpair *self)
2074{
2075    Py_CLEAR(self->reader);
2076    Py_CLEAR(self->writer);
2077    Py_CLEAR(self->dict);
2078    return 0;
2079}
2080
2081static void
2082bufferedrwpair_dealloc(rwpair *self)
2083{
2084    _PyObject_GC_UNTRACK(self);
2085    Py_CLEAR(self->reader);
2086    Py_CLEAR(self->writer);
2087    Py_CLEAR(self->dict);
2088    Py_TYPE(self)->tp_free((PyObject *) self);
2089}
2090
2091static PyObject *
2092_forward_call(buffered *self, const char *name, PyObject *args)
2093{
2094    PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
2095    PyObject *ret;
2096
2097    if (func == NULL) {
2098        PyErr_SetString(PyExc_AttributeError, name);
2099        return NULL;
2100    }
2101
2102    ret = PyObject_CallObject(func, args);
2103    Py_DECREF(func);
2104    return ret;
2105}
2106
2107static PyObject *
2108bufferedrwpair_read(rwpair *self, PyObject *args)
2109{
2110    return _forward_call(self->reader, "read", args);
2111}
2112
2113static PyObject *
2114bufferedrwpair_peek(rwpair *self, PyObject *args)
2115{
2116    return _forward_call(self->reader, "peek", args);
2117}
2118
2119static PyObject *
2120bufferedrwpair_read1(rwpair *self, PyObject *args)
2121{
2122    return _forward_call(self->reader, "read1", args);
2123}
2124
2125static PyObject *
2126bufferedrwpair_readinto(rwpair *self, PyObject *args)
2127{
2128    return _forward_call(self->reader, "readinto", args);
2129}
2130
2131static PyObject *
2132bufferedrwpair_write(rwpair *self, PyObject *args)
2133{
2134    return _forward_call(self->writer, "write", args);
2135}
2136
2137static PyObject *
2138bufferedrwpair_flush(rwpair *self, PyObject *args)
2139{
2140    return _forward_call(self->writer, "flush", args);
2141}
2142
2143static PyObject *
2144bufferedrwpair_readable(rwpair *self, PyObject *args)
2145{
2146    return _forward_call(self->reader, "readable", args);
2147}
2148
2149static PyObject *
2150bufferedrwpair_writable(rwpair *self, PyObject *args)
2151{
2152    return _forward_call(self->writer, "writable", args);
2153}
2154
2155static PyObject *
2156bufferedrwpair_close(rwpair *self, PyObject *args)
2157{
2158    PyObject *ret = _forward_call(self->writer, "close", args);
2159    if (ret == NULL)
2160        return NULL;
2161    Py_DECREF(ret);
2162
2163    return _forward_call(self->reader, "close", args);
2164}
2165
2166static PyObject *
2167bufferedrwpair_isatty(rwpair *self, PyObject *args)
2168{
2169    PyObject *ret = _forward_call(self->writer, "isatty", args);
2170
2171    if (ret != Py_False) {
2172        /* either True or exception */
2173        return ret;
2174    }
2175    Py_DECREF(ret);
2176
2177    return _forward_call(self->reader, "isatty", args);
2178}
2179
2180static PyObject *
2181bufferedrwpair_closed_get(rwpair *self, void *context)
2182{
2183    return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2184}
2185
2186static PyMethodDef bufferedrwpair_methods[] = {
2187    {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2188    {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2189    {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2190    {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
2191
2192    {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2193    {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
2194
2195    {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2196    {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
2197
2198    {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2199    {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
2200
2201    {NULL, NULL}
2202};
2203
2204static PyGetSetDef bufferedrwpair_getset[] = {
2205    {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
2206    {NULL}
2207};
2208
2209PyTypeObject PyBufferedRWPair_Type = {
2210    PyVarObject_HEAD_INIT(NULL, 0)
2211    "_io.BufferedRWPair",       /*tp_name*/
2212    sizeof(rwpair),            /*tp_basicsize*/
2213    0,                          /*tp_itemsize*/
2214    (destructor)bufferedrwpair_dealloc,     /*tp_dealloc*/
2215    0,                          /*tp_print*/
2216    0,                          /*tp_getattr*/
2217    0,                          /*tp_setattr*/
2218    0,                          /*tp_compare */
2219    0,                          /*tp_repr*/
2220    0,                          /*tp_as_number*/
2221    0,                          /*tp_as_sequence*/
2222    0,                          /*tp_as_mapping*/
2223    0,                          /*tp_hash */
2224    0,                          /*tp_call*/
2225    0,                          /*tp_str*/
2226    0,                          /*tp_getattro*/
2227    0,                          /*tp_setattro*/
2228    0,                          /*tp_as_buffer*/
2229    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2230        | Py_TPFLAGS_HAVE_GC,   /* tp_flags */
2231    bufferedrwpair_doc,         /* tp_doc */
2232    (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2233    (inquiry)bufferedrwpair_clear, /* tp_clear */
2234    0,                          /* tp_richcompare */
2235    offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
2236    0,                          /* tp_iter */
2237    0,                          /* tp_iternext */
2238    bufferedrwpair_methods,     /* tp_methods */
2239    0,                          /* tp_members */
2240    bufferedrwpair_getset,      /* tp_getset */
2241    0,                          /* tp_base */
2242    0,                          /* tp_dict */
2243    0,                          /* tp_descr_get */
2244    0,                          /* tp_descr_set */
2245    offsetof(rwpair, dict),     /* tp_dictoffset */
2246    (initproc)bufferedrwpair_init, /* tp_init */
2247    0,                          /* tp_alloc */
2248    PyType_GenericNew,          /* tp_new */
2249};
2250
2251
2252
2253/*
2254 * BufferedRandom
2255 */
2256
2257PyDoc_STRVAR(bufferedrandom_doc,
2258    "A buffered interface to random access streams.\n"
2259    "\n"
2260    "The constructor creates a reader and writer for a seekable stream,\n"
2261    "raw, given in the first argument. If the buffer_size is omitted it\n"
2262    "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2263    );
2264
2265static int
2266bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
2267{
2268    char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2269    Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
2270    Py_ssize_t max_buffer_size = -234;
2271    PyObject *raw;
2272
2273    self->ok = 0;
2274    self->detached = 0;
2275
2276    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2277                                     &raw, &buffer_size, &max_buffer_size)) {
2278        return -1;
2279    }
2280
2281    if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2282        return -1;
2283
2284    if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
2285        return -1;
2286    if (_PyIOBase_check_readable(raw, Py_True) == NULL)
2287        return -1;
2288    if (_PyIOBase_check_writable(raw, Py_True) == NULL)
2289        return -1;
2290
2291    Py_CLEAR(self->raw);
2292    Py_INCREF(raw);
2293    self->raw = raw;
2294    self->buffer_size = buffer_size;
2295    self->readable = 1;
2296    self->writable = 1;
2297
2298    if (_buffered_init(self) < 0)
2299        return -1;
2300    _bufferedreader_reset_buf(self);
2301    _bufferedwriter_reset_buf(self);
2302    self->pos = 0;
2303
2304    self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2305                                Py_TYPE(raw) == &PyFileIO_Type);
2306
2307    self->ok = 1;
2308    return 0;
2309}
2310
2311static PyMethodDef bufferedrandom_methods[] = {
2312    /* BufferedIOMixin methods */
2313    {"close", (PyCFunction)buffered_close, METH_NOARGS},
2314    {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2315    {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2316    {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2317    {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2318    {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2319    {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2320
2321    {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2322
2323    {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2324    {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2325    {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2326    {"read", (PyCFunction)buffered_read, METH_VARARGS},
2327    {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2328    {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2329    {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2330    {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2331    {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
2332    {NULL, NULL}
2333};
2334
2335static PyMemberDef bufferedrandom_members[] = {
2336    {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
2337    {NULL}
2338};
2339
2340static PyGetSetDef bufferedrandom_getset[] = {
2341    {"closed", (getter)buffered_closed_get, NULL, NULL},
2342    {"name", (getter)buffered_name_get, NULL, NULL},
2343    {"mode", (getter)buffered_mode_get, NULL, NULL},
2344    {NULL}
2345};
2346
2347
2348PyTypeObject PyBufferedRandom_Type = {
2349    PyVarObject_HEAD_INIT(NULL, 0)
2350    "_io.BufferedRandom",       /*tp_name*/
2351    sizeof(buffered),           /*tp_basicsize*/
2352    0,                          /*tp_itemsize*/
2353    (destructor)buffered_dealloc,     /*tp_dealloc*/
2354    0,                          /*tp_print*/
2355    0,                          /*tp_getattr*/
2356    0,                          /*tp_setattr*/
2357    0,                          /*tp_compare */
2358    (reprfunc)buffered_repr,    /*tp_repr*/
2359    0,                          /*tp_as_number*/
2360    0,                          /*tp_as_sequence*/
2361    0,                          /*tp_as_mapping*/
2362    0,                          /*tp_hash */
2363    0,                          /*tp_call*/
2364    0,                          /*tp_str*/
2365    0,                          /*tp_getattro*/
2366    0,                          /*tp_setattro*/
2367    0,                          /*tp_as_buffer*/
2368    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2369        | Py_TPFLAGS_HAVE_GC,   /*tp_flags*/
2370    bufferedrandom_doc,         /* tp_doc */
2371    (traverseproc)buffered_traverse, /* tp_traverse */
2372    (inquiry)buffered_clear,    /* tp_clear */
2373    0,                          /* tp_richcompare */
2374    offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2375    0,                          /* tp_iter */
2376    (iternextfunc)buffered_iternext, /* tp_iternext */
2377    bufferedrandom_methods,     /* tp_methods */
2378    bufferedrandom_members,     /* tp_members */
2379    bufferedrandom_getset,      /* tp_getset */
2380    0,                          /* tp_base */
2381    0,                          /*tp_dict*/
2382    0,                          /* tp_descr_get */
2383    0,                          /* tp_descr_set */
2384    offsetof(buffered, dict), /*tp_dictoffset*/
2385    (initproc)bufferedrandom_init, /* tp_init */
2386    0,                          /* tp_alloc */
2387    PyType_GenericNew,          /* tp_new */
2388};
2389
2390