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