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