2 An implementation of Buffered I/O as defined by PEP 3116 - "New I/O"
4 Classes defined here: BufferedIOBase, BufferedReader, BufferedWriter,
7 Written by Amaury Forgeot d'Arc and Antoine Pitrou
10 #define PY_SSIZE_T_CLEAN
12 #include "structmember.h"
14 #include "_iomodule.h"
17 * BufferedIOBase class, inherits from IOBase.
19 PyDoc_STRVAR(bufferediobase_doc,
20 "Base class for buffered IO objects.\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"
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"
31 "A typical implementation should not inherit from a RawIOBase\n"
32 "implementation, but wrap one.\n"
36 bufferediobase_readinto(PyObject *self, PyObject *args)
42 if (!PyArg_ParseTuple(args, "w*:readinto", &buf)) {
46 data = PyObject_CallMethod(self, "read", "n", buf.len);
50 if (!PyBytes_Check(data)) {
52 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
57 memcpy(buf.buf, PyBytes_AS_STRING(data), len);
59 PyBuffer_Release(&buf);
62 return PyLong_FromSsize_t(len);
65 PyBuffer_Release(&buf);
70 bufferediobase_unsupported(const char *message)
72 PyErr_SetString(_PyIO_unsupported_operation, message);
76 PyDoc_STRVAR(bufferediobase_detach_doc,
77 "Disconnect this buffer from its underlying raw stream and return it.\n"
79 "After the raw stream has been detached, the buffer is in an unusable\n"
83 bufferediobase_detach(PyObject *self)
85 return bufferediobase_unsupported("detach");
88 PyDoc_STRVAR(bufferediobase_read_doc,
89 "Read and return up to n bytes.\n"
91 "If the argument is omitted, None, or negative, reads and\n"
92 "returns all data until EOF.\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"
101 "Returns an empty bytes object on EOF.\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");
107 bufferediobase_read(PyObject *self, PyObject *args)
109 return bufferediobase_unsupported("read");
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"
117 "Returns an empty bytes object on EOF.\n");
120 bufferediobase_read1(PyObject *self, PyObject *args)
122 return bufferediobase_unsupported("read1");
125 PyDoc_STRVAR(bufferediobase_write_doc,
126 "Write the given buffer to the IO stream.\n"
128 "Returns the number of bytes written, which is never less than\n"
131 "Raises BlockingIOError if the buffer is full and the\n"
132 "underlying raw stream cannot accept more data at the moment.\n");
135 bufferediobase_write(PyObject *self, PyObject *args)
137 return bufferediobase_unsupported("write");
141 static PyMethodDef bufferediobase_methods[] = {
142 {"detach", (PyCFunction)bufferediobase_detach, METH_NOARGS, bufferediobase_detach_doc},
143 {"read", bufferediobase_read, METH_VARARGS, bufferediobase_read_doc},
144 {"read1", bufferediobase_read1, METH_VARARGS, bufferediobase_read1_doc},
145 {"readinto", bufferediobase_readinto, METH_VARARGS, NULL},
146 {"write", bufferediobase_write, METH_VARARGS, bufferediobase_write_doc},
150 PyTypeObject PyBufferedIOBase_Type = {
151 PyVarObject_HEAD_INIT(NULL, 0)
152 "_io._BufferedIOBase", /*tp_name*/
162 0, /*tp_as_sequence*/
170 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
171 bufferediobase_doc, /* tp_doc */
174 0, /* tp_richcompare */
175 0, /* tp_weaklistoffset */
178 bufferediobase_methods, /* tp_methods */
181 &PyIOBase_Type, /* tp_base */
183 0, /* tp_descr_get */
184 0, /* tp_descr_set */
185 0, /* tp_dictoffset */
196 int ok; /* Initialized? */
201 /* True if this is a vanilla Buffered object (rather than a user derived
202 class) *and* the raw stream is a vanilla FileIO object. */
203 int fast_closed_checks;
205 /* Absolute position inside the raw stream (-1 if unknown). */
208 /* A static buffer of size `buffer_size` */
210 /* Current logical position in the buffer. */
212 /* Position of the raw stream in the buffer. */
215 /* Just after the last buffered byte in the buffer, or -1 if the buffer
216 isn't ready for reading. */
219 /* Just after the last byte actually written */
221 /* Just after the last byte waiting to be written, or -1 if the buffer
222 isn't ready for writing. */
226 PyThread_type_lock lock;
229 Py_ssize_t buffer_size;
230 Py_ssize_t buffer_mask;
233 PyObject *weakreflist;
237 Implementation notes:
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.
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.
259 /* These macros protect the buffered object against concurrent operations. */
262 #define ENTER_BUFFERED(self) \
263 if (!PyThread_acquire_lock(self->lock, 0)) { \
264 Py_BEGIN_ALLOW_THREADS \
265 PyThread_acquire_lock(self->lock, 1); \
266 Py_END_ALLOW_THREADS \
269 #define LEAVE_BUFFERED(self) \
270 PyThread_release_lock(self->lock);
272 #define ENTER_BUFFERED(self)
273 #define LEAVE_BUFFERED(self)
276 #define CHECK_INITIALIZED(self) \
277 if (self->ok <= 0) { \
278 if (self->detached) { \
279 PyErr_SetString(PyExc_ValueError, \
280 "raw stream has been detached"); \
282 PyErr_SetString(PyExc_ValueError, \
283 "I/O operation on uninitialized object"); \
288 #define CHECK_INITIALIZED_INT(self) \
289 if (self->ok <= 0) { \
290 if (self->detached) { \
291 PyErr_SetString(PyExc_ValueError, \
292 "raw stream has been detached"); \
294 PyErr_SetString(PyExc_ValueError, \
295 "I/O operation on uninitialized object"); \
300 #define IS_CLOSED(self) \
301 (self->fast_closed_checks \
302 ? _PyFileIO_closed(self->raw) \
303 : buffered_closed(self))
305 #define CHECK_CLOSED(self, error_msg) \
306 if (IS_CLOSED(self)) { \
307 PyErr_SetString(PyExc_ValueError, error_msg); \
312 #define VALID_READ_BUFFER(self) \
313 (self->readable && self->read_end != -1)
315 #define VALID_WRITE_BUFFER(self) \
316 (self->writable && self->write_end != -1)
318 #define ADJUST_POSITION(self, _new_pos) \
320 self->pos = _new_pos; \
321 if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
322 self->read_end = self->pos; \
325 #define READAHEAD(self) \
326 ((self->readable && VALID_READ_BUFFER(self)) \
327 ? (self->read_end - self->pos) : 0)
329 #define RAW_OFFSET(self) \
330 (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
331 && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
333 #define RAW_TELL(self) \
334 (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
336 #define MINUS_LAST_BLOCK(self, size) \
337 (self->buffer_mask ? \
338 (size & ~self->buffer_mask) : \
339 (self->buffer_size * (size / self->buffer_size)))
343 buffered_dealloc(buffered *self)
345 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
347 _PyObject_GC_UNTRACK(self);
349 if (self->weakreflist != NULL)
350 PyObject_ClearWeakRefs((PyObject *)self);
353 PyMem_Free(self->buffer);
358 PyThread_free_lock(self->lock);
362 Py_CLEAR(self->dict);
363 Py_TYPE(self)->tp_free((PyObject *)self);
367 buffered_traverse(buffered *self, visitproc visit, void *arg)
370 Py_VISIT(self->dict);
375 buffered_clear(buffered *self)
377 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
381 Py_CLEAR(self->dict);
386 * _BufferedIOMixin methods
387 * This is not a class, just a collection of methods that will be reused
388 * by BufferedReader and BufferedWriter
391 /* Flush and close */
394 buffered_simple_flush(buffered *self, PyObject *args)
396 CHECK_INITIALIZED(self)
397 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
401 buffered_closed(buffered *self)
405 CHECK_INITIALIZED_INT(self)
406 res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
409 closed = PyObject_IsTrue(res);
415 buffered_closed_get(buffered *self, void *context)
417 CHECK_INITIALIZED(self)
418 return PyObject_GetAttr(self->raw, _PyIO_str_closed);
422 buffered_close(buffered *self, PyObject *args)
424 PyObject *res = NULL;
427 CHECK_INITIALIZED(self)
430 r = buffered_closed(self);
438 /* flush() will most probably re-take the lock, so drop it first */
440 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
447 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
457 buffered_detach(buffered *self, PyObject *args)
460 CHECK_INITIALIZED(self)
461 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
475 buffered_seekable(buffered *self, PyObject *args)
477 CHECK_INITIALIZED(self)
478 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
482 buffered_readable(buffered *self, PyObject *args)
484 CHECK_INITIALIZED(self)
485 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
489 buffered_writable(buffered *self, PyObject *args)
491 CHECK_INITIALIZED(self)
492 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
496 buffered_name_get(buffered *self, void *context)
498 CHECK_INITIALIZED(self)
499 return PyObject_GetAttrString(self->raw, "name");
503 buffered_mode_get(buffered *self, void *context)
505 CHECK_INITIALIZED(self)
506 return PyObject_GetAttrString(self->raw, "mode");
509 /* Lower-level APIs */
512 buffered_fileno(buffered *self, PyObject *args)
514 CHECK_INITIALIZED(self)
515 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
519 buffered_isatty(buffered *self, PyObject *args)
521 CHECK_INITIALIZED(self)
522 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
528 _bufferedwriter_flush_unlocked(buffered *, int);
530 _bufferedreader_fill_buffer(buffered *self);
532 _bufferedreader_reset_buf(buffered *self);
534 _bufferedwriter_reset_buf(buffered *self);
536 _bufferedreader_peek_unlocked(buffered *self, Py_ssize_t);
538 _bufferedreader_read_all(buffered *self);
540 _bufferedreader_read_fast(buffered *self, Py_ssize_t);
542 _bufferedreader_read_generic(buffered *self, Py_ssize_t);
549 /* Returns the address of the `written` member if a BlockingIOError was
550 raised, NULL otherwise. The error is always re-raised. */
552 _buffered_check_blocking_error(void)
554 PyObject *t, *v, *tb;
555 PyBlockingIOErrorObject *err;
557 PyErr_Fetch(&t, &v, &tb);
558 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
559 PyErr_Restore(t, v, tb);
562 err = (PyBlockingIOErrorObject *) v;
563 /* TODO: sanity check (err->written >= 0) */
564 PyErr_Restore(t, v, tb);
565 return &err->written;
569 _buffered_raw_tell(buffered *self)
573 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
576 n = PyNumber_AsOff_t(res, PyExc_ValueError);
579 if (!PyErr_Occurred())
580 PyErr_Format(PyExc_IOError,
581 "Raw stream returned invalid position %" PY_PRIdOFF,
590 _buffered_raw_seek(buffered *self, Py_off_t target, int whence)
592 PyObject *res, *posobj, *whenceobj;
595 posobj = PyLong_FromOff_t(target);
598 whenceobj = PyLong_FromLong(whence);
599 if (whenceobj == NULL) {
603 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
604 posobj, whenceobj, NULL);
606 Py_DECREF(whenceobj);
609 n = PyNumber_AsOff_t(res, PyExc_ValueError);
612 if (!PyErr_Occurred())
613 PyErr_Format(PyExc_IOError,
614 "Raw stream returned invalid position %" PY_PRIdOFF,
623 _buffered_init(buffered *self)
626 if (self->buffer_size <= 0) {
627 PyErr_SetString(PyExc_ValueError,
628 "buffer size must be strictly positive");
632 PyMem_Free(self->buffer);
633 self->buffer = PyMem_Malloc(self->buffer_size);
634 if (self->buffer == NULL) {
640 PyThread_free_lock(self->lock);
641 self->lock = PyThread_allocate_lock();
642 if (self->lock == NULL) {
643 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
647 /* Find out whether buffer_size is a power of 2 */
648 /* XXX is this optimization useful? */
649 for (n = self->buffer_size - 1; n & 1; n >>= 1)
652 self->buffer_mask = self->buffer_size - 1;
654 self->buffer_mask = 0;
655 if (_buffered_raw_tell(self) == -1)
661 * Shared methods and wrappers
665 buffered_flush(buffered *self, PyObject *args)
669 CHECK_INITIALIZED(self)
670 CHECK_CLOSED(self, "flush of closed file")
673 res = _bufferedwriter_flush_unlocked(self, 0);
674 if (res != NULL && self->readable) {
675 /* Rewind the raw stream so that its position corresponds to
676 the current logical position. */
678 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
681 _bufferedreader_reset_buf(self);
689 buffered_peek(buffered *self, PyObject *args)
692 PyObject *res = NULL;
694 CHECK_INITIALIZED(self)
695 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
701 if (self->writable) {
702 res = _bufferedwriter_flush_unlocked(self, 1);
707 res = _bufferedreader_peek_unlocked(self, n);
715 buffered_read(buffered *self, PyObject *args)
720 CHECK_INITIALIZED(self)
721 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
725 PyErr_SetString(PyExc_ValueError,
726 "read length must be positive or -1");
730 CHECK_CLOSED(self, "read of closed file")
733 /* The number of bytes is unspecified, read until the end of stream */
735 res = _bufferedreader_read_all(self);
739 res = _bufferedreader_read_fast(self, n);
740 if (res == Py_None) {
743 res = _bufferedreader_read_generic(self, n);
752 buffered_read1(buffered *self, PyObject *args)
754 Py_ssize_t n, have, r;
755 PyObject *res = NULL;
757 CHECK_INITIALIZED(self)
758 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
763 PyErr_SetString(PyExc_ValueError,
764 "read length must be positive");
768 return PyBytes_FromStringAndSize(NULL, 0);
772 if (self->writable) {
773 res = _bufferedwriter_flush_unlocked(self, 1);
779 /* Return up to n bytes. If at least one byte is buffered, we
780 only return buffered bytes. Otherwise, we do one raw read. */
782 /* XXX: this mimicks the io.py implementation but is probably wrong.
783 If we need to read from the raw stream, then we could actually read
784 all `n` bytes asked by the caller (and possibly more, so as to fill
785 our buffer for the next reads). */
787 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
791 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
798 /* Fill the buffer from the raw stream, and copy it to the result. */
799 _bufferedreader_reset_buf(self);
800 r = _bufferedreader_fill_buffer(self);
807 res = PyBytes_FromStringAndSize(self->buffer, n);
818 buffered_readinto(buffered *self, PyObject *args)
820 PyObject *res = NULL;
822 CHECK_INITIALIZED(self)
824 /* TODO: use raw.readinto() instead! */
825 if (self->writable) {
827 res = _bufferedwriter_flush_unlocked(self, 0);
833 res = bufferediobase_readinto((PyObject *)self, args);
840 _buffered_readline(buffered *self, Py_ssize_t limit)
842 PyObject *res = NULL;
843 PyObject *chunks = NULL;
844 Py_ssize_t n, written = 0;
845 const char *start, *s, *end;
847 CHECK_CLOSED(self, "readline of closed file")
849 /* First, try to find a line in the buffer. This can run unlocked because
850 the calls to the C API are simple enough that they can't trigger
851 any thread switch. */
852 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
853 if (limit >= 0 && n > limit)
855 start = self->buffer + self->pos;
856 s = memchr(start, '\n', n);
858 res = PyBytes_FromStringAndSize(start, s - start + 1);
860 self->pos += s - start + 1;
864 res = PyBytes_FromStringAndSize(start, n);
872 /* Now we try to get some more from the raw stream */
873 if (self->writable) {
874 res = _bufferedwriter_flush_unlocked(self, 1);
879 chunks = PyList_New(0);
883 res = PyBytes_FromStringAndSize(start, n);
886 if (PyList_Append(chunks, res) < 0) {
897 _bufferedreader_reset_buf(self);
898 n = _bufferedreader_fill_buffer(self);
903 if (limit >= 0 && n > limit)
905 start = self->buffer;
910 res = PyBytes_FromStringAndSize(start, s - start);
913 self->pos = s - start;
917 res = PyBytes_FromStringAndSize(start, n);
924 if (PyList_Append(chunks, res) < 0) {
934 if (res != NULL && PyList_Append(chunks, res) < 0) {
939 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
949 buffered_readline(buffered *self, PyObject *args)
951 Py_ssize_t limit = -1;
953 CHECK_INITIALIZED(self)
954 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
956 return _buffered_readline(self, limit);
961 buffered_tell(buffered *self, PyObject *args)
965 CHECK_INITIALIZED(self)
966 pos = _buffered_raw_tell(self);
969 pos -= RAW_OFFSET(self);
970 /* TODO: sanity check (pos >= 0) */
971 return PyLong_FromOff_t(pos);
975 buffered_seek(buffered *self, PyObject *args)
979 PyObject *targetobj, *res = NULL;
981 CHECK_INITIALIZED(self)
982 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
985 if (whence < 0 || whence > 2) {
986 PyErr_Format(PyExc_ValueError,
987 "whence must be between 0 and 2, not %d", whence);
991 CHECK_CLOSED(self, "seek of closed file")
993 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
994 if (target == -1 && PyErr_Occurred())
997 if (whence != 2 && self->readable) {
998 Py_off_t current, avail;
999 /* Check if seeking leaves us inside the current buffer,
1000 so as to return quickly if possible. Also, we needn't take the
1001 lock in this fast path.
1002 Don't know how to do that when whence == 2, though. */
1003 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1004 state at this point. */
1005 current = RAW_TELL(self);
1006 avail = READAHEAD(self);
1010 offset = target - (current - RAW_OFFSET(self));
1013 if (offset >= -self->pos && offset <= avail) {
1014 self->pos += offset;
1015 return PyLong_FromOff_t(current - avail + offset);
1020 ENTER_BUFFERED(self)
1022 /* Fallback: invoke raw seek() method and clear buffer */
1023 if (self->writable) {
1024 res = _bufferedwriter_flush_unlocked(self, 0);
1028 _bufferedwriter_reset_buf(self);
1031 /* TODO: align on block boundary and read buffer if needed? */
1033 target -= RAW_OFFSET(self);
1034 n = _buffered_raw_seek(self, target, whence);
1038 res = PyLong_FromOff_t(n);
1039 if (res != NULL && self->readable)
1040 _bufferedreader_reset_buf(self);
1043 LEAVE_BUFFERED(self)
1048 buffered_truncate(buffered *self, PyObject *args)
1050 PyObject *pos = Py_None;
1051 PyObject *res = NULL;
1053 CHECK_INITIALIZED(self)
1054 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1058 ENTER_BUFFERED(self)
1060 if (self->writable) {
1061 res = _bufferedwriter_flush_unlocked(self, 0);
1066 if (self->readable) {
1067 if (pos == Py_None) {
1068 /* Rewind the raw stream so that its position corresponds to
1069 the current logical position. */
1070 if (_buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)
1073 _bufferedreader_reset_buf(self);
1075 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1078 /* Reset cached position */
1079 if (_buffered_raw_tell(self) == -1)
1083 LEAVE_BUFFERED(self)
1088 buffered_iternext(buffered *self)
1093 CHECK_INITIALIZED(self);
1096 if (tp == &PyBufferedReader_Type ||
1097 tp == &PyBufferedRandom_Type) {
1098 /* Skip method call overhead for speed */
1099 line = _buffered_readline(self, -1);
1102 line = PyObject_CallMethodObjArgs((PyObject *)self,
1103 _PyIO_str_readline, NULL);
1104 if (line && !PyBytes_Check(line)) {
1105 PyErr_Format(PyExc_IOError,
1106 "readline() should have returned a bytes object, "
1107 "not '%.200s'", Py_TYPE(line)->tp_name);
1116 if (PyBytes_GET_SIZE(line) == 0) {
1117 /* Reached EOF or would have blocked */
1126 buffered_repr(buffered *self)
1128 PyObject *nameobj, *res;
1130 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1131 if (nameobj == NULL) {
1132 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1136 res = PyString_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1139 PyObject *repr = PyObject_Repr(nameobj);
1143 res = PyString_FromFormat("<%s name=%s>",
1144 Py_TYPE(self)->tp_name,
1145 PyString_AS_STRING(repr));
1152 * class BufferedReader
1155 PyDoc_STRVAR(bufferedreader_doc,
1156 "Create a new buffered reader using the given readable raw IO object.");
1158 static void _bufferedreader_reset_buf(buffered *self)
1160 self->read_end = -1;
1164 bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
1166 char *kwlist[] = {"raw", "buffer_size", NULL};
1167 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1173 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1174 &raw, &buffer_size)) {
1178 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
1181 Py_CLEAR(self->raw);
1184 self->buffer_size = buffer_size;
1188 if (_buffered_init(self) < 0)
1190 _bufferedreader_reset_buf(self);
1192 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1193 Py_TYPE(raw) == &PyFileIO_Type);
1200 _bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
1203 PyObject *memobj, *res;
1205 /* NOTE: the buffer needn't be released as its object is NULL. */
1206 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1208 memobj = PyMemoryView_FromBuffer(&buf);
1211 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1215 if (res == Py_None) {
1216 /* Non-blocking stream would have blocked. Special return code! */
1220 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1222 if (n < 0 || n > len) {
1223 PyErr_Format(PyExc_IOError,
1224 "raw readinto() returned invalid length %zd "
1225 "(should have been between 0 and %zd)", n, len);
1228 if (n > 0 && self->abs_pos != -1)
1234 _bufferedreader_fill_buffer(buffered *self)
1236 Py_ssize_t start, len, n;
1237 if (VALID_READ_BUFFER(self))
1238 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1241 len = self->buffer_size - start;
1242 n = _bufferedreader_raw_read(self, self->buffer + start, len);
1245 self->read_end = start + n;
1246 self->raw_pos = start + n;
1251 _bufferedreader_read_all(buffered *self)
1253 Py_ssize_t current_size;
1254 PyObject *res, *data = NULL;
1255 PyObject *chunks = PyList_New(0);
1260 /* First copy what we have in the current buffer. */
1261 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1263 data = PyBytes_FromStringAndSize(
1264 self->buffer + self->pos, current_size);
1270 _bufferedreader_reset_buf(self);
1271 /* We're going past the buffer's bounds, flush it */
1272 if (self->writable) {
1273 res = _bufferedwriter_flush_unlocked(self, 1);
1282 if (PyList_Append(chunks, data) < 0) {
1290 /* Read until EOF or until read() would block. */
1291 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1296 if (data != Py_None && !PyBytes_Check(data)) {
1299 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1302 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1303 if (current_size == 0) {
1308 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1314 current_size += PyBytes_GET_SIZE(data);
1315 if (self->abs_pos != -1)
1316 self->abs_pos += PyBytes_GET_SIZE(data);
1320 /* Read n bytes from the buffer if it can, otherwise return None.
1321 This function is simple enough that it can run unlocked. */
1323 _bufferedreader_read_fast(buffered *self, Py_ssize_t n)
1325 Py_ssize_t current_size;
1327 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1328 if (n <= current_size) {
1329 /* Fast path: the data to read is fully buffered. */
1330 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1338 /* Generic read function: read from the stream until enough bytes are read,
1339 * or until an EOF occurs or until read() would block.
1342 _bufferedreader_read_generic(buffered *self, Py_ssize_t n)
1344 PyObject *res = NULL;
1345 Py_ssize_t current_size, remaining, written;
1348 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1349 if (n <= current_size)
1350 return _bufferedreader_read_fast(self, n);
1352 res = PyBytes_FromStringAndSize(NULL, n);
1355 out = PyBytes_AS_STRING(res);
1358 if (current_size > 0) {
1359 memcpy(out, self->buffer + self->pos, current_size);
1360 remaining -= current_size;
1361 written += current_size;
1363 _bufferedreader_reset_buf(self);
1364 while (remaining > 0) {
1365 /* We want to read a whole block at the end into buffer.
1366 If we had readv() we could do this in one pass. */
1367 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1370 r = _bufferedreader_raw_read(self, out + written, r);
1373 if (r == 0 || r == -2) {
1374 /* EOF occurred or read() would block. */
1375 if (r == 0 || written > 0) {
1376 if (_PyBytes_Resize(&res, written))
1387 assert(remaining <= self->buffer_size);
1391 /* NOTE: when the read is satisfied, we avoid issuing any additional
1392 reads, which could block indefinitely (e.g. on a socket).
1394 while (remaining > 0 && self->read_end < self->buffer_size) {
1395 Py_ssize_t r = _bufferedreader_fill_buffer(self);
1398 if (r == 0 || r == -2) {
1399 /* EOF occurred or read() would block. */
1400 if (r == 0 || written > 0) {
1401 if (_PyBytes_Resize(&res, written))
1409 if (remaining > r) {
1410 memcpy(out + written, self->buffer + self->pos, r);
1415 else if (remaining > 0) {
1416 memcpy(out + written, self->buffer + self->pos, remaining);
1417 written += remaining;
1418 self->pos += remaining;
1433 _bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
1437 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1439 1. we don't want to advance the file position.
1440 2. we don't want to lose block alignment, so we can't shift the buffer
1442 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1445 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1448 /* Fill the buffer from the raw stream, and copy it to the result. */
1449 _bufferedreader_reset_buf(self);
1450 r = _bufferedreader_fill_buffer(self);
1456 return PyBytes_FromStringAndSize(self->buffer, r);
1459 static PyMethodDef bufferedreader_methods[] = {
1460 /* BufferedIOMixin methods */
1461 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1462 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1463 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1464 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1465 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1466 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1467 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1468 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
1470 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1471 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1472 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
1473 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1474 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1475 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1476 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1480 static PyMemberDef bufferedreader_members[] = {
1481 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
1485 static PyGetSetDef bufferedreader_getset[] = {
1486 {"closed", (getter)buffered_closed_get, NULL, NULL},
1487 {"name", (getter)buffered_name_get, NULL, NULL},
1488 {"mode", (getter)buffered_mode_get, NULL, NULL},
1493 PyTypeObject PyBufferedReader_Type = {
1494 PyVarObject_HEAD_INIT(NULL, 0)
1495 "_io.BufferedReader", /*tp_name*/
1496 sizeof(buffered), /*tp_basicsize*/
1498 (destructor)buffered_dealloc, /*tp_dealloc*/
1503 (reprfunc)buffered_repr, /*tp_repr*/
1505 0, /*tp_as_sequence*/
1506 0, /*tp_as_mapping*/
1513 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1514 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1515 bufferedreader_doc, /* tp_doc */
1516 (traverseproc)buffered_traverse, /* tp_traverse */
1517 (inquiry)buffered_clear, /* tp_clear */
1518 0, /* tp_richcompare */
1519 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
1521 (iternextfunc)buffered_iternext, /* tp_iternext */
1522 bufferedreader_methods, /* tp_methods */
1523 bufferedreader_members, /* tp_members */
1524 bufferedreader_getset, /* tp_getset */
1527 0, /* tp_descr_get */
1528 0, /* tp_descr_set */
1529 offsetof(buffered, dict), /* tp_dictoffset */
1530 (initproc)bufferedreader_init, /* tp_init */
1532 PyType_GenericNew, /* tp_new */
1538 complain_about_max_buffer_size(void)
1540 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1541 "max_buffer_size is deprecated", 1) < 0)
1547 * class BufferedWriter
1549 PyDoc_STRVAR(bufferedwriter_doc,
1550 "A buffer for a writeable sequential RawIO object.\n"
1552 "The constructor creates a BufferedWriter for the given writeable raw\n"
1553 "stream. If the buffer_size is not given, it defaults to\n"
1554 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1558 _bufferedwriter_reset_buf(buffered *self)
1560 self->write_pos = 0;
1561 self->write_end = -1;
1565 bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
1567 /* TODO: properly deprecate max_buffer_size */
1568 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1569 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1570 Py_ssize_t max_buffer_size = -234;
1576 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1577 &raw, &buffer_size, &max_buffer_size)) {
1581 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1584 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
1587 Py_CLEAR(self->raw);
1593 self->buffer_size = buffer_size;
1594 if (_buffered_init(self) < 0)
1596 _bufferedwriter_reset_buf(self);
1599 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1600 Py_TYPE(raw) == &PyFileIO_Type);
1607 _bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
1610 PyObject *memobj, *res;
1612 /* NOTE: the buffer needn't be released as its object is NULL. */
1613 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1615 memobj = PyMemoryView_FromBuffer(&buf);
1618 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1622 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1624 if (n < 0 || n > len) {
1625 PyErr_Format(PyExc_IOError,
1626 "raw write() returned invalid length %zd "
1627 "(should have been between 0 and %zd)", n, len);
1630 if (n > 0 && self->abs_pos != -1)
1635 /* `restore_pos` is 1 if we need to restore the raw stream position at
1636 the end, 0 otherwise. */
1638 _bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
1640 Py_ssize_t written = 0;
1643 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1646 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1648 n = _buffered_raw_seek(self, -rewind, 1);
1652 self->raw_pos -= rewind;
1654 while (self->write_pos < self->write_end) {
1655 n = _bufferedwriter_raw_write(self,
1656 self->buffer + self->write_pos,
1657 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1658 Py_off_t, Py_ssize_t));
1660 Py_ssize_t *w = _buffered_check_blocking_error();
1663 self->write_pos += *w;
1664 self->raw_pos = self->write_pos;
1667 /* Already re-raised */
1670 self->write_pos += n;
1671 self->raw_pos = self->write_pos;
1672 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1673 /* Partial writes can return successfully when interrupted by a
1674 signal (see write(2)). We must run signal handlers before
1675 blocking another time, possibly indefinitely. */
1676 if (PyErr_CheckSignals() < 0)
1681 Py_off_t forward = rewind - written;
1683 n = _buffered_raw_seek(self, forward, 1);
1687 self->raw_pos += forward;
1690 _bufferedwriter_reset_buf(self);
1700 bufferedwriter_write(buffered *self, PyObject *args)
1702 PyObject *res = NULL;
1704 Py_ssize_t written, avail, remaining;
1707 CHECK_INITIALIZED(self)
1708 if (!PyArg_ParseTuple(args, "s*:write", &buf)) {
1712 if (IS_CLOSED(self)) {
1713 PyErr_SetString(PyExc_ValueError, "write to closed file");
1714 PyBuffer_Release(&buf);
1718 ENTER_BUFFERED(self)
1720 /* Fast path: the data to write can be fully buffered. */
1721 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1725 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1726 if (buf.len <= avail) {
1727 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1728 if (!VALID_WRITE_BUFFER(self)) {
1729 self->write_pos = self->pos;
1731 ADJUST_POSITION(self, self->pos + buf.len);
1732 if (self->pos > self->write_end)
1733 self->write_end = self->pos;
1738 /* First write the current buffer */
1739 res = _bufferedwriter_flush_unlocked(self, 0);
1741 Py_ssize_t *w = _buffered_check_blocking_error();
1745 _bufferedreader_reset_buf(self);
1746 /* Make some place by shifting the buffer. */
1747 assert(VALID_WRITE_BUFFER(self));
1748 memmove(self->buffer, self->buffer + self->write_pos,
1749 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1750 Py_off_t, Py_ssize_t));
1751 self->write_end -= self->write_pos;
1752 self->raw_pos -= self->write_pos;
1753 self->pos -= self->write_pos;
1754 self->write_pos = 0;
1755 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1756 Py_off_t, Py_ssize_t);
1757 if (buf.len <= avail) {
1758 /* Everything can be buffered */
1760 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1761 self->write_end += buf.len;
1765 /* Buffer as much as possible. */
1766 memcpy(self->buffer + self->write_end, buf.buf, avail);
1767 self->write_end += avail;
1768 /* Already re-raised */
1774 /* Adjust the raw stream position if it is away from the logical stream
1775 position. This happens if the read buffer has been filled but not
1776 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1777 the raw stream by itself).
1780 offset = RAW_OFFSET(self);
1782 if (_buffered_raw_seek(self, -offset, 1) < 0)
1784 self->raw_pos -= offset;
1787 /* Then write buf itself. At this point the buffer has been emptied. */
1788 remaining = buf.len;
1790 while (remaining > self->buffer_size) {
1791 Py_ssize_t n = _bufferedwriter_raw_write(
1792 self, (char *) buf.buf + written, buf.len - written);
1794 Py_ssize_t *w = _buffered_check_blocking_error();
1799 if (remaining > self->buffer_size) {
1800 /* Can't buffer everything, still buffer as much as possible */
1801 memcpy(self->buffer,
1802 (char *) buf.buf + written, self->buffer_size);
1804 ADJUST_POSITION(self, self->buffer_size);
1805 self->write_end = self->buffer_size;
1806 *w = written + self->buffer_size;
1807 /* Already re-raised */
1815 /* Partial writes can return successfully when interrupted by a
1816 signal (see write(2)). We must run signal handlers before
1817 blocking another time, possibly indefinitely. */
1818 if (PyErr_CheckSignals() < 0)
1822 _bufferedreader_reset_buf(self);
1823 if (remaining > 0) {
1824 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1825 written += remaining;
1827 self->write_pos = 0;
1828 /* TODO: sanity check (remaining >= 0) */
1829 self->write_end = remaining;
1830 ADJUST_POSITION(self, remaining);
1834 res = PyLong_FromSsize_t(written);
1837 LEAVE_BUFFERED(self)
1838 PyBuffer_Release(&buf);
1842 static PyMethodDef bufferedwriter_methods[] = {
1843 /* BufferedIOMixin methods */
1844 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1845 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1846 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1847 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1848 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1849 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1850 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
1852 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1853 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1854 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1855 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1856 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1860 static PyMemberDef bufferedwriter_members[] = {
1861 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
1865 static PyGetSetDef bufferedwriter_getset[] = {
1866 {"closed", (getter)buffered_closed_get, NULL, NULL},
1867 {"name", (getter)buffered_name_get, NULL, NULL},
1868 {"mode", (getter)buffered_mode_get, NULL, NULL},
1873 PyTypeObject PyBufferedWriter_Type = {
1874 PyVarObject_HEAD_INIT(NULL, 0)
1875 "_io.BufferedWriter", /*tp_name*/
1876 sizeof(buffered), /*tp_basicsize*/
1878 (destructor)buffered_dealloc, /*tp_dealloc*/
1883 (reprfunc)buffered_repr, /*tp_repr*/
1885 0, /*tp_as_sequence*/
1886 0, /*tp_as_mapping*/
1893 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1894 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1895 bufferedwriter_doc, /* tp_doc */
1896 (traverseproc)buffered_traverse, /* tp_traverse */
1897 (inquiry)buffered_clear, /* tp_clear */
1898 0, /* tp_richcompare */
1899 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
1901 0, /* tp_iternext */
1902 bufferedwriter_methods, /* tp_methods */
1903 bufferedwriter_members, /* tp_members */
1904 bufferedwriter_getset, /* tp_getset */
1907 0, /* tp_descr_get */
1908 0, /* tp_descr_set */
1909 offsetof(buffered, dict), /* tp_dictoffset */
1910 (initproc)bufferedwriter_init, /* tp_init */
1912 PyType_GenericNew, /* tp_new */
1921 PyDoc_STRVAR(bufferedrwpair_doc,
1922 "A buffered reader and writer object together.\n"
1924 "A buffered reader object and buffered writer object put together to\n"
1925 "form a sequential IO object that can read and write. This is typically\n"
1926 "used with a socket or two-way pipe.\n"
1928 "reader and writer are RawIOBase objects that are readable and\n"
1929 "writeable respectively. If the buffer_size is omitted it defaults to\n"
1930 "DEFAULT_BUFFER_SIZE.\n"
1933 /* XXX The usefulness of this (compared to having two separate IO objects) is
1942 PyObject *weakreflist;
1946 bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
1948 PyObject *reader, *writer;
1949 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1950 Py_ssize_t max_buffer_size = -234;
1952 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1953 &buffer_size, &max_buffer_size)) {
1957 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1960 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
1962 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
1965 self->reader = (buffered *) PyObject_CallFunction(
1966 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
1967 if (self->reader == NULL)
1970 self->writer = (buffered *) PyObject_CallFunction(
1971 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
1972 if (self->writer == NULL) {
1973 Py_CLEAR(self->reader);
1981 bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
1983 Py_VISIT(self->dict);
1988 bufferedrwpair_clear(rwpair *self)
1990 Py_CLEAR(self->reader);
1991 Py_CLEAR(self->writer);
1992 Py_CLEAR(self->dict);
1997 bufferedrwpair_dealloc(rwpair *self)
1999 _PyObject_GC_UNTRACK(self);
2000 Py_CLEAR(self->reader);
2001 Py_CLEAR(self->writer);
2002 Py_CLEAR(self->dict);
2003 Py_TYPE(self)->tp_free((PyObject *) self);
2007 _forward_call(buffered *self, const char *name, PyObject *args)
2009 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
2013 PyErr_SetString(PyExc_AttributeError, name);
2017 ret = PyObject_CallObject(func, args);
2023 bufferedrwpair_read(rwpair *self, PyObject *args)
2025 return _forward_call(self->reader, "read", args);
2029 bufferedrwpair_peek(rwpair *self, PyObject *args)
2031 return _forward_call(self->reader, "peek", args);
2035 bufferedrwpair_read1(rwpair *self, PyObject *args)
2037 return _forward_call(self->reader, "read1", args);
2041 bufferedrwpair_readinto(rwpair *self, PyObject *args)
2043 return _forward_call(self->reader, "readinto", args);
2047 bufferedrwpair_write(rwpair *self, PyObject *args)
2049 return _forward_call(self->writer, "write", args);
2053 bufferedrwpair_flush(rwpair *self, PyObject *args)
2055 return _forward_call(self->writer, "flush", args);
2059 bufferedrwpair_readable(rwpair *self, PyObject *args)
2061 return _forward_call(self->reader, "readable", args);
2065 bufferedrwpair_writable(rwpair *self, PyObject *args)
2067 return _forward_call(self->writer, "writable", args);
2071 bufferedrwpair_close(rwpair *self, PyObject *args)
2073 PyObject *ret = _forward_call(self->writer, "close", args);
2078 return _forward_call(self->reader, "close", args);
2082 bufferedrwpair_isatty(rwpair *self, PyObject *args)
2084 PyObject *ret = _forward_call(self->writer, "isatty", args);
2086 if (ret != Py_False) {
2087 /* either True or exception */
2092 return _forward_call(self->reader, "isatty", args);
2096 bufferedrwpair_closed_get(rwpair *self, void *context)
2098 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2101 static PyMethodDef bufferedrwpair_methods[] = {
2102 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2103 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2104 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2105 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
2107 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2108 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
2110 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2111 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
2113 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2114 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
2119 static PyGetSetDef bufferedrwpair_getset[] = {
2120 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
2124 PyTypeObject PyBufferedRWPair_Type = {
2125 PyVarObject_HEAD_INIT(NULL, 0)
2126 "_io.BufferedRWPair", /*tp_name*/
2127 sizeof(rwpair), /*tp_basicsize*/
2129 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
2136 0, /*tp_as_sequence*/
2137 0, /*tp_as_mapping*/
2144 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2145 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
2146 bufferedrwpair_doc, /* tp_doc */
2147 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2148 (inquiry)bufferedrwpair_clear, /* tp_clear */
2149 0, /* tp_richcompare */
2150 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
2152 0, /* tp_iternext */
2153 bufferedrwpair_methods, /* tp_methods */
2155 bufferedrwpair_getset, /* tp_getset */
2158 0, /* tp_descr_get */
2159 0, /* tp_descr_set */
2160 offsetof(rwpair, dict), /* tp_dictoffset */
2161 (initproc)bufferedrwpair_init, /* tp_init */
2163 PyType_GenericNew, /* tp_new */
2172 PyDoc_STRVAR(bufferedrandom_doc,
2173 "A buffered interface to random access streams.\n"
2175 "The constructor creates a reader and writer for a seekable stream,\n"
2176 "raw, given in the first argument. If the buffer_size is omitted it\n"
2177 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2181 bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
2183 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2184 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
2185 Py_ssize_t max_buffer_size = -234;
2191 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2192 &raw, &buffer_size, &max_buffer_size)) {
2196 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2199 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
2201 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
2203 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
2206 Py_CLEAR(self->raw);
2209 self->buffer_size = buffer_size;
2213 if (_buffered_init(self) < 0)
2215 _bufferedreader_reset_buf(self);
2216 _bufferedwriter_reset_buf(self);
2219 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2220 Py_TYPE(raw) == &PyFileIO_Type);
2226 static PyMethodDef bufferedrandom_methods[] = {
2227 /* BufferedIOMixin methods */
2228 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2229 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2230 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2231 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2232 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2233 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2234 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2236 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2238 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2239 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2240 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2241 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2242 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2243 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2244 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2245 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2246 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
2250 static PyMemberDef bufferedrandom_members[] = {
2251 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
2255 static PyGetSetDef bufferedrandom_getset[] = {
2256 {"closed", (getter)buffered_closed_get, NULL, NULL},
2257 {"name", (getter)buffered_name_get, NULL, NULL},
2258 {"mode", (getter)buffered_mode_get, NULL, NULL},
2263 PyTypeObject PyBufferedRandom_Type = {
2264 PyVarObject_HEAD_INIT(NULL, 0)
2265 "_io.BufferedRandom", /*tp_name*/
2266 sizeof(buffered), /*tp_basicsize*/
2268 (destructor)buffered_dealloc, /*tp_dealloc*/
2273 (reprfunc)buffered_repr, /*tp_repr*/
2275 0, /*tp_as_sequence*/
2276 0, /*tp_as_mapping*/
2283 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2284 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2285 bufferedrandom_doc, /* tp_doc */
2286 (traverseproc)buffered_traverse, /* tp_traverse */
2287 (inquiry)buffered_clear, /* tp_clear */
2288 0, /* tp_richcompare */
2289 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2291 (iternextfunc)buffered_iternext, /* tp_iternext */
2292 bufferedrandom_methods, /* tp_methods */
2293 bufferedrandom_members, /* tp_members */
2294 bufferedrandom_getset, /* tp_getset */
2297 0, /* tp_descr_get */
2298 0, /* tp_descr_set */
2299 offsetof(buffered, dict), /*tp_dictoffset*/
2300 (initproc)bufferedrandom_init, /* tp_init */
2302 PyType_GenericNew, /* tp_new */