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