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 Py_BEGIN_ALLOW_THREADS \
264 PyThread_acquire_lock(self->lock, 1); \
267 #define LEAVE_BUFFERED(self) \
268 PyThread_release_lock(self->lock);
270 #define ENTER_BUFFERED(self)
271 #define LEAVE_BUFFERED(self)
274 #define CHECK_INITIALIZED(self) \
275 if (self->ok <= 0) { \
276 if (self->detached) { \
277 PyErr_SetString(PyExc_ValueError, \
278 "raw stream has been detached"); \
280 PyErr_SetString(PyExc_ValueError, \
281 "I/O operation on uninitialized object"); \
286 #define CHECK_INITIALIZED_INT(self) \
287 if (self->ok <= 0) { \
288 if (self->detached) { \
289 PyErr_SetString(PyExc_ValueError, \
290 "raw stream has been detached"); \
292 PyErr_SetString(PyExc_ValueError, \
293 "I/O operation on uninitialized object"); \
298 #define IS_CLOSED(self) \
299 (self->fast_closed_checks \
300 ? _PyFileIO_closed(self->raw) \
301 : buffered_closed(self))
303 #define CHECK_CLOSED(self, error_msg) \
304 if (IS_CLOSED(self)) { \
305 PyErr_SetString(PyExc_ValueError, error_msg); \
310 #define VALID_READ_BUFFER(self) \
311 (self->readable && self->read_end != -1)
313 #define VALID_WRITE_BUFFER(self) \
314 (self->writable && self->write_end != -1)
316 #define ADJUST_POSITION(self, _new_pos) \
318 self->pos = _new_pos; \
319 if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
320 self->read_end = self->pos; \
323 #define READAHEAD(self) \
324 ((self->readable && VALID_READ_BUFFER(self)) \
325 ? (self->read_end - self->pos) : 0)
327 #define RAW_OFFSET(self) \
328 (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
329 && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
331 #define RAW_TELL(self) \
332 (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
334 #define MINUS_LAST_BLOCK(self, size) \
335 (self->buffer_mask ? \
336 (size & ~self->buffer_mask) : \
337 (self->buffer_size * (size / self->buffer_size)))
341 buffered_dealloc(buffered
*self
)
343 if (self
->ok
&& _PyIOBase_finalize((PyObject
*) self
) < 0)
345 _PyObject_GC_UNTRACK(self
);
347 if (self
->weakreflist
!= NULL
)
348 PyObject_ClearWeakRefs((PyObject
*)self
);
351 PyMem_Free(self
->buffer
);
356 PyThread_free_lock(self
->lock
);
360 Py_CLEAR(self
->dict
);
361 Py_TYPE(self
)->tp_free((PyObject
*)self
);
365 buffered_traverse(buffered
*self
, visitproc visit
, void *arg
)
368 Py_VISIT(self
->dict
);
373 buffered_clear(buffered
*self
)
375 if (self
->ok
&& _PyIOBase_finalize((PyObject
*) self
) < 0)
379 Py_CLEAR(self
->dict
);
384 * _BufferedIOMixin methods
385 * This is not a class, just a collection of methods that will be reused
386 * by BufferedReader and BufferedWriter
389 /* Flush and close */
392 buffered_simple_flush(buffered
*self
, PyObject
*args
)
394 CHECK_INITIALIZED(self
)
395 return PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_flush
, NULL
);
399 buffered_closed(buffered
*self
)
403 CHECK_INITIALIZED_INT(self
)
404 res
= PyObject_GetAttr(self
->raw
, _PyIO_str_closed
);
407 closed
= PyObject_IsTrue(res
);
413 buffered_closed_get(buffered
*self
, void *context
)
415 CHECK_INITIALIZED(self
)
416 return PyObject_GetAttr(self
->raw
, _PyIO_str_closed
);
420 buffered_close(buffered
*self
, PyObject
*args
)
422 PyObject
*res
= NULL
;
425 CHECK_INITIALIZED(self
)
428 r
= buffered_closed(self
);
436 /* flush() will most probably re-take the lock, so drop it first */
438 res
= PyObject_CallMethodObjArgs((PyObject
*)self
, _PyIO_str_flush
, NULL
);
441 /* If flush() fails, just give up */
442 if (PyErr_ExceptionMatches(PyExc_IOError
))
449 res
= PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_close
, NULL
);
459 buffered_detach(buffered
*self
, PyObject
*args
)
462 CHECK_INITIALIZED(self
)
463 res
= PyObject_CallMethodObjArgs((PyObject
*)self
, _PyIO_str_flush
, NULL
);
477 buffered_seekable(buffered
*self
, PyObject
*args
)
479 CHECK_INITIALIZED(self
)
480 return PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_seekable
, NULL
);
484 buffered_readable(buffered
*self
, PyObject
*args
)
486 CHECK_INITIALIZED(self
)
487 return PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_readable
, NULL
);
491 buffered_writable(buffered
*self
, PyObject
*args
)
493 CHECK_INITIALIZED(self
)
494 return PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_writable
, NULL
);
498 buffered_name_get(buffered
*self
, void *context
)
500 CHECK_INITIALIZED(self
)
501 return PyObject_GetAttrString(self
->raw
, "name");
505 buffered_mode_get(buffered
*self
, void *context
)
507 CHECK_INITIALIZED(self
)
508 return PyObject_GetAttrString(self
->raw
, "mode");
511 /* Lower-level APIs */
514 buffered_fileno(buffered
*self
, PyObject
*args
)
516 CHECK_INITIALIZED(self
)
517 return PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_fileno
, NULL
);
521 buffered_isatty(buffered
*self
, PyObject
*args
)
523 CHECK_INITIALIZED(self
)
524 return PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_isatty
, NULL
);
530 _bufferedwriter_flush_unlocked(buffered
*, int);
532 _bufferedreader_fill_buffer(buffered
*self
);
534 _bufferedreader_reset_buf(buffered
*self
);
536 _bufferedwriter_reset_buf(buffered
*self
);
538 _bufferedreader_peek_unlocked(buffered
*self
, Py_ssize_t
);
540 _bufferedreader_read_all(buffered
*self
);
542 _bufferedreader_read_fast(buffered
*self
, Py_ssize_t
);
544 _bufferedreader_read_generic(buffered
*self
, Py_ssize_t
);
551 /* Returns the address of the `written` member if a BlockingIOError was
552 raised, NULL otherwise. The error is always re-raised. */
554 _buffered_check_blocking_error(void)
556 PyObject
*t
, *v
, *tb
;
557 PyBlockingIOErrorObject
*err
;
559 PyErr_Fetch(&t
, &v
, &tb
);
560 if (v
== NULL
|| !PyErr_GivenExceptionMatches(v
, PyExc_BlockingIOError
)) {
561 PyErr_Restore(t
, v
, tb
);
564 err
= (PyBlockingIOErrorObject
*) v
;
565 /* TODO: sanity check (err->written >= 0) */
566 PyErr_Restore(t
, v
, tb
);
567 return &err
->written
;
571 _buffered_raw_tell(buffered
*self
)
575 res
= PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_tell
, NULL
);
578 n
= PyNumber_AsOff_t(res
, PyExc_ValueError
);
581 if (!PyErr_Occurred())
582 PyErr_Format(PyExc_IOError
,
583 "Raw stream returned invalid position %zd", n
);
591 _buffered_raw_seek(buffered
*self
, Py_off_t target
, int whence
)
593 PyObject
*res
, *posobj
, *whenceobj
;
596 posobj
= PyLong_FromOff_t(target
);
599 whenceobj
= PyLong_FromLong(whence
);
600 if (whenceobj
== NULL
) {
604 res
= PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_seek
,
605 posobj
, whenceobj
, NULL
);
607 Py_DECREF(whenceobj
);
610 n
= PyNumber_AsOff_t(res
, PyExc_ValueError
);
613 if (!PyErr_Occurred())
614 PyErr_Format(PyExc_IOError
,
615 "Raw stream returned invalid position %zd", n
);
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
) {
639 self
->lock
= PyThread_allocate_lock();
640 if (self
->lock
== NULL
) {
641 PyErr_SetString(PyExc_RuntimeError
, "can't allocate read lock");
645 /* Find out whether buffer_size is a power of 2 */
646 /* XXX is this optimization useful? */
647 for (n
= self
->buffer_size
- 1; n
& 1; n
>>= 1)
650 self
->buffer_mask
= self
->buffer_size
- 1;
652 self
->buffer_mask
= 0;
653 if (_buffered_raw_tell(self
) == -1)
659 * Shared methods and wrappers
663 buffered_flush(buffered
*self
, PyObject
*args
)
667 CHECK_INITIALIZED(self
)
668 CHECK_CLOSED(self
, "flush of closed file")
671 res
= _bufferedwriter_flush_unlocked(self
, 0);
672 if (res
!= NULL
&& self
->readable
) {
673 /* Rewind the raw stream so that its position corresponds to
674 the current logical position. */
676 n
= _buffered_raw_seek(self
, -RAW_OFFSET(self
), 1);
679 _bufferedreader_reset_buf(self
);
687 buffered_peek(buffered
*self
, PyObject
*args
)
690 PyObject
*res
= NULL
;
692 CHECK_INITIALIZED(self
)
693 if (!PyArg_ParseTuple(args
, "|n:peek", &n
)) {
699 if (self
->writable
) {
700 res
= _bufferedwriter_flush_unlocked(self
, 1);
705 res
= _bufferedreader_peek_unlocked(self
, n
);
713 buffered_read(buffered
*self
, PyObject
*args
)
718 CHECK_INITIALIZED(self
)
719 if (!PyArg_ParseTuple(args
, "|n:read", &n
)) {
723 PyErr_SetString(PyExc_ValueError
,
724 "read length must be positive or -1");
728 CHECK_CLOSED(self
, "read of closed file")
731 /* The number of bytes is unspecified, read until the end of stream */
733 res
= _bufferedreader_read_all(self
);
737 res
= _bufferedreader_read_fast(self
, n
);
738 if (res
== Py_None
) {
741 res
= _bufferedreader_read_generic(self
, n
);
750 buffered_read1(buffered
*self
, PyObject
*args
)
752 Py_ssize_t n
, have
, r
;
753 PyObject
*res
= NULL
;
755 CHECK_INITIALIZED(self
)
756 if (!PyArg_ParseTuple(args
, "n:read1", &n
)) {
761 PyErr_SetString(PyExc_ValueError
,
762 "read length must be positive");
766 return PyBytes_FromStringAndSize(NULL
, 0);
770 if (self
->writable
) {
771 res
= _bufferedwriter_flush_unlocked(self
, 1);
777 /* Return up to n bytes. If at least one byte is buffered, we
778 only return buffered bytes. Otherwise, we do one raw read. */
780 /* XXX: this mimicks the io.py implementation but is probably wrong.
781 If we need to read from the raw stream, then we could actually read
782 all `n` bytes asked by the caller (and possibly more, so as to fill
783 our buffer for the next reads). */
785 have
= Py_SAFE_DOWNCAST(READAHEAD(self
), Py_off_t
, Py_ssize_t
);
789 res
= PyBytes_FromStringAndSize(self
->buffer
+ self
->pos
, n
);
796 /* Fill the buffer from the raw stream, and copy it to the result. */
797 _bufferedreader_reset_buf(self
);
798 r
= _bufferedreader_fill_buffer(self
);
805 res
= PyBytes_FromStringAndSize(self
->buffer
, n
);
816 buffered_readinto(buffered
*self
, PyObject
*args
)
818 PyObject
*res
= NULL
;
820 CHECK_INITIALIZED(self
)
822 /* TODO: use raw.readinto() instead! */
823 if (self
->writable
) {
825 res
= _bufferedwriter_flush_unlocked(self
, 0);
831 res
= bufferediobase_readinto((PyObject
*)self
, args
);
838 _buffered_readline(buffered
*self
, Py_ssize_t limit
)
840 PyObject
*res
= NULL
;
841 PyObject
*chunks
= NULL
;
842 Py_ssize_t n
, written
= 0;
843 const char *start
, *s
, *end
;
845 CHECK_CLOSED(self
, "readline of closed file")
847 /* First, try to find a line in the buffer. This can run unlocked because
848 the calls to the C API are simple enough that they can't trigger
849 any thread switch. */
850 n
= Py_SAFE_DOWNCAST(READAHEAD(self
), Py_off_t
, Py_ssize_t
);
851 if (limit
>= 0 && n
> limit
)
853 start
= self
->buffer
+ self
->pos
;
854 s
= memchr(start
, '\n', n
);
856 res
= PyBytes_FromStringAndSize(start
, s
- start
+ 1);
858 self
->pos
+= s
- start
+ 1;
862 res
= PyBytes_FromStringAndSize(start
, n
);
870 /* Now we try to get some more from the raw stream */
871 if (self
->writable
) {
872 res
= _bufferedwriter_flush_unlocked(self
, 1);
877 chunks
= PyList_New(0);
881 res
= PyBytes_FromStringAndSize(start
, n
);
884 if (PyList_Append(chunks
, res
) < 0) {
895 _bufferedreader_reset_buf(self
);
896 n
= _bufferedreader_fill_buffer(self
);
901 if (limit
>= 0 && n
> limit
)
903 start
= self
->buffer
;
908 res
= PyBytes_FromStringAndSize(start
, s
- start
);
911 self
->pos
= s
- start
;
915 res
= PyBytes_FromStringAndSize(start
, n
);
922 if (PyList_Append(chunks
, res
) < 0) {
932 if (res
!= NULL
&& PyList_Append(chunks
, res
) < 0) {
937 res
= _PyBytes_Join(_PyIO_empty_bytes
, chunks
);
947 buffered_readline(buffered
*self
, PyObject
*args
)
949 PyObject
*limitobj
= NULL
;
950 Py_ssize_t limit
= -1;
952 CHECK_INITIALIZED(self
)
954 if (!PyArg_ParseTuple(args
, "|O:readline", &limitobj
)) {
958 if (!PyNumber_Check(limitobj
)) {
959 PyErr_Format(PyExc_TypeError
,
960 "integer argument expected, got '%.200s'",
961 Py_TYPE(limitobj
)->tp_name
);
964 limit
= PyNumber_AsSsize_t(limitobj
, PyExc_OverflowError
);
965 if (limit
== -1 && PyErr_Occurred())
968 return _buffered_readline(self
, limit
);
973 buffered_tell(buffered
*self
, PyObject
*args
)
977 CHECK_INITIALIZED(self
)
978 pos
= _buffered_raw_tell(self
);
981 pos
-= RAW_OFFSET(self
);
982 /* TODO: sanity check (pos >= 0) */
983 return PyLong_FromOff_t(pos
);
987 buffered_seek(buffered
*self
, PyObject
*args
)
991 PyObject
*targetobj
, *res
= NULL
;
993 CHECK_INITIALIZED(self
)
994 if (!PyArg_ParseTuple(args
, "O|i:seek", &targetobj
, &whence
)) {
997 if (whence
< 0 || whence
> 2) {
998 PyErr_Format(PyExc_ValueError
,
999 "whence must be between 0 and 2, not %d", whence
);
1003 CHECK_CLOSED(self
, "seek of closed file")
1005 target
= PyNumber_AsOff_t(targetobj
, PyExc_ValueError
);
1006 if (target
== -1 && PyErr_Occurred())
1009 if (whence
!= 2 && self
->readable
) {
1010 Py_off_t current
, avail
;
1011 /* Check if seeking leaves us inside the current buffer,
1012 so as to return quickly if possible. Also, we needn't take the
1013 lock in this fast path.
1014 Don't know how to do that when whence == 2, though. */
1015 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1016 state at this point. */
1017 current
= RAW_TELL(self
);
1018 avail
= READAHEAD(self
);
1022 offset
= target
- (current
- RAW_OFFSET(self
));
1025 if (offset
>= -self
->pos
&& offset
<= avail
) {
1026 self
->pos
+= offset
;
1027 return PyLong_FromOff_t(current
- avail
+ offset
);
1032 ENTER_BUFFERED(self
)
1034 /* Fallback: invoke raw seek() method and clear buffer */
1035 if (self
->writable
) {
1036 res
= _bufferedwriter_flush_unlocked(self
, 0);
1040 _bufferedwriter_reset_buf(self
);
1043 /* TODO: align on block boundary and read buffer if needed? */
1045 target
-= RAW_OFFSET(self
);
1046 n
= _buffered_raw_seek(self
, target
, whence
);
1050 res
= PyLong_FromOff_t(n
);
1051 if (res
!= NULL
&& self
->readable
)
1052 _bufferedreader_reset_buf(self
);
1055 LEAVE_BUFFERED(self
)
1060 buffered_truncate(buffered
*self
, PyObject
*args
)
1062 PyObject
*pos
= Py_None
;
1063 PyObject
*res
= NULL
;
1065 CHECK_INITIALIZED(self
)
1066 if (!PyArg_ParseTuple(args
, "|O:truncate", &pos
)) {
1070 ENTER_BUFFERED(self
)
1072 if (self
->writable
) {
1073 res
= _bufferedwriter_flush_unlocked(self
, 0);
1078 if (self
->readable
) {
1079 if (pos
== Py_None
) {
1080 /* Rewind the raw stream so that its position corresponds to
1081 the current logical position. */
1082 if (_buffered_raw_seek(self
, -RAW_OFFSET(self
), 1) == -1)
1085 _bufferedreader_reset_buf(self
);
1087 res
= PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_truncate
, pos
, NULL
);
1090 /* Reset cached position */
1091 if (_buffered_raw_tell(self
) == -1)
1095 LEAVE_BUFFERED(self
)
1100 buffered_iternext(buffered
*self
)
1105 CHECK_INITIALIZED(self
);
1108 if (tp
== &PyBufferedReader_Type
||
1109 tp
== &PyBufferedRandom_Type
) {
1110 /* Skip method call overhead for speed */
1111 line
= _buffered_readline(self
, -1);
1114 line
= PyObject_CallMethodObjArgs((PyObject
*)self
,
1115 _PyIO_str_readline
, NULL
);
1116 if (line
&& !PyBytes_Check(line
)) {
1117 PyErr_Format(PyExc_IOError
,
1118 "readline() should have returned a bytes object, "
1119 "not '%.200s'", Py_TYPE(line
)->tp_name
);
1128 if (PyBytes_GET_SIZE(line
) == 0) {
1129 /* Reached EOF or would have blocked */
1138 buffered_repr(buffered
*self
)
1140 PyObject
*nameobj
, *res
;
1142 nameobj
= PyObject_GetAttrString((PyObject
*) self
, "name");
1143 if (nameobj
== NULL
) {
1144 if (PyErr_ExceptionMatches(PyExc_AttributeError
))
1148 res
= PyString_FromFormat("<%s>", Py_TYPE(self
)->tp_name
);
1151 PyObject
*repr
= PyObject_Repr(nameobj
);
1155 res
= PyString_FromFormat("<%s name=%s>",
1156 Py_TYPE(self
)->tp_name
,
1157 PyString_AS_STRING(repr
));
1164 * class BufferedReader
1167 PyDoc_STRVAR(bufferedreader_doc
,
1168 "Create a new buffered reader using the given readable raw IO object.");
1170 static void _bufferedreader_reset_buf(buffered
*self
)
1172 self
->read_end
= -1;
1176 bufferedreader_init(buffered
*self
, PyObject
*args
, PyObject
*kwds
)
1178 char *kwlist
[] = {"raw", "buffer_size", NULL
};
1179 Py_ssize_t buffer_size
= DEFAULT_BUFFER_SIZE
;
1185 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "O|n:BufferedReader", kwlist
,
1186 &raw
, &buffer_size
)) {
1190 if (_PyIOBase_check_readable(raw
, Py_True
) == NULL
)
1193 Py_CLEAR(self
->raw
);
1196 self
->buffer_size
= buffer_size
;
1200 if (_buffered_init(self
) < 0)
1202 _bufferedreader_reset_buf(self
);
1204 self
->fast_closed_checks
= (Py_TYPE(self
) == &PyBufferedReader_Type
&&
1205 Py_TYPE(raw
) == &PyFileIO_Type
);
1212 _bufferedreader_raw_read(buffered
*self
, char *start
, Py_ssize_t len
)
1215 PyObject
*memobj
, *res
;
1217 /* NOTE: the buffer needn't be released as its object is NULL. */
1218 if (PyBuffer_FillInfo(&buf
, NULL
, start
, len
, 0, PyBUF_CONTIG
) == -1)
1220 memobj
= PyMemoryView_FromBuffer(&buf
);
1223 res
= PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_readinto
, memobj
, NULL
);
1227 if (res
== Py_None
) {
1228 /* Non-blocking stream would have blocked. Special return code! */
1232 n
= PyNumber_AsSsize_t(res
, PyExc_ValueError
);
1234 if (n
< 0 || n
> len
) {
1235 PyErr_Format(PyExc_IOError
,
1236 "raw readinto() returned invalid length %zd "
1237 "(should have been between 0 and %zd)", n
, len
);
1240 if (n
> 0 && self
->abs_pos
!= -1)
1246 _bufferedreader_fill_buffer(buffered
*self
)
1248 Py_ssize_t start
, len
, n
;
1249 if (VALID_READ_BUFFER(self
))
1250 start
= Py_SAFE_DOWNCAST(self
->read_end
, Py_off_t
, Py_ssize_t
);
1253 len
= self
->buffer_size
- start
;
1254 n
= _bufferedreader_raw_read(self
, self
->buffer
+ start
, len
);
1257 self
->read_end
= start
+ n
;
1258 self
->raw_pos
= start
+ n
;
1263 _bufferedreader_read_all(buffered
*self
)
1265 Py_ssize_t current_size
;
1266 PyObject
*res
, *data
= NULL
;
1267 PyObject
*chunks
= PyList_New(0);
1272 /* First copy what we have in the current buffer. */
1273 current_size
= Py_SAFE_DOWNCAST(READAHEAD(self
), Py_off_t
, Py_ssize_t
);
1275 data
= PyBytes_FromStringAndSize(
1276 self
->buffer
+ self
->pos
, current_size
);
1282 _bufferedreader_reset_buf(self
);
1283 /* We're going past the buffer's bounds, flush it */
1284 if (self
->writable
) {
1285 res
= _bufferedwriter_flush_unlocked(self
, 1);
1294 if (PyList_Append(chunks
, data
) < 0) {
1302 /* Read until EOF or until read() would block. */
1303 data
= PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_read
, NULL
);
1308 if (data
!= Py_None
&& !PyBytes_Check(data
)) {
1311 PyErr_SetString(PyExc_TypeError
, "read() should return bytes");
1314 if (data
== Py_None
|| PyBytes_GET_SIZE(data
) == 0) {
1315 if (current_size
== 0) {
1320 res
= _PyBytes_Join(_PyIO_empty_bytes
, chunks
);
1326 current_size
+= PyBytes_GET_SIZE(data
);
1327 if (self
->abs_pos
!= -1)
1328 self
->abs_pos
+= PyBytes_GET_SIZE(data
);
1332 /* Read n bytes from the buffer if it can, otherwise return None.
1333 This function is simple enough that it can run unlocked. */
1335 _bufferedreader_read_fast(buffered
*self
, Py_ssize_t n
)
1337 Py_ssize_t current_size
;
1339 current_size
= Py_SAFE_DOWNCAST(READAHEAD(self
), Py_off_t
, Py_ssize_t
);
1340 if (n
<= current_size
) {
1341 /* Fast path: the data to read is fully buffered. */
1342 PyObject
*res
= PyBytes_FromStringAndSize(self
->buffer
+ self
->pos
, n
);
1350 /* Generic read function: read from the stream until enough bytes are read,
1351 * or until an EOF occurs or until read() would block.
1354 _bufferedreader_read_generic(buffered
*self
, Py_ssize_t n
)
1356 PyObject
*res
= NULL
;
1357 Py_ssize_t current_size
, remaining
, written
;
1360 current_size
= Py_SAFE_DOWNCAST(READAHEAD(self
), Py_off_t
, Py_ssize_t
);
1361 if (n
<= current_size
)
1362 return _bufferedreader_read_fast(self
, n
);
1364 res
= PyBytes_FromStringAndSize(NULL
, n
);
1367 out
= PyBytes_AS_STRING(res
);
1370 if (current_size
> 0) {
1371 memcpy(out
, self
->buffer
+ self
->pos
, current_size
);
1372 remaining
-= current_size
;
1373 written
+= current_size
;
1375 _bufferedreader_reset_buf(self
);
1376 while (remaining
> 0) {
1377 /* We want to read a whole block at the end into buffer.
1378 If we had readv() we could do this in one pass. */
1379 Py_ssize_t r
= MINUS_LAST_BLOCK(self
, remaining
);
1382 r
= _bufferedreader_raw_read(self
, out
+ written
, r
);
1385 if (r
== 0 || r
== -2) {
1386 /* EOF occurred or read() would block. */
1387 if (r
== 0 || written
> 0) {
1388 if (_PyBytes_Resize(&res
, written
))
1399 assert(remaining
<= self
->buffer_size
);
1403 while (self
->read_end
< self
->buffer_size
) {
1404 Py_ssize_t r
= _bufferedreader_fill_buffer(self
);
1407 if (r
== 0 || r
== -2) {
1408 /* EOF occurred or read() would block. */
1409 if (r
== 0 || written
> 0) {
1410 if (_PyBytes_Resize(&res
, written
))
1418 if (remaining
> r
) {
1419 memcpy(out
+ written
, self
->buffer
+ self
->pos
, r
);
1424 else if (remaining
> 0) {
1425 memcpy(out
+ written
, self
->buffer
+ self
->pos
, remaining
);
1426 written
+= remaining
;
1427 self
->pos
+= remaining
;
1442 _bufferedreader_peek_unlocked(buffered
*self
, Py_ssize_t n
)
1446 have
= Py_SAFE_DOWNCAST(READAHEAD(self
), Py_off_t
, Py_ssize_t
);
1448 1. we don't want to advance the file position.
1449 2. we don't want to lose block alignment, so we can't shift the buffer
1451 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1454 return PyBytes_FromStringAndSize(self
->buffer
+ self
->pos
, have
);
1457 /* Fill the buffer from the raw stream, and copy it to the result. */
1458 _bufferedreader_reset_buf(self
);
1459 r
= _bufferedreader_fill_buffer(self
);
1465 return PyBytes_FromStringAndSize(self
->buffer
, r
);
1468 static PyMethodDef bufferedreader_methods
[] = {
1469 /* BufferedIOMixin methods */
1470 {"detach", (PyCFunction
)buffered_detach
, METH_NOARGS
},
1471 {"flush", (PyCFunction
)buffered_simple_flush
, METH_NOARGS
},
1472 {"close", (PyCFunction
)buffered_close
, METH_NOARGS
},
1473 {"seekable", (PyCFunction
)buffered_seekable
, METH_NOARGS
},
1474 {"readable", (PyCFunction
)buffered_readable
, METH_NOARGS
},
1475 {"writable", (PyCFunction
)buffered_writable
, METH_NOARGS
},
1476 {"fileno", (PyCFunction
)buffered_fileno
, METH_NOARGS
},
1477 {"isatty", (PyCFunction
)buffered_isatty
, METH_NOARGS
},
1479 {"read", (PyCFunction
)buffered_read
, METH_VARARGS
},
1480 {"peek", (PyCFunction
)buffered_peek
, METH_VARARGS
},
1481 {"read1", (PyCFunction
)buffered_read1
, METH_VARARGS
},
1482 {"readline", (PyCFunction
)buffered_readline
, METH_VARARGS
},
1483 {"seek", (PyCFunction
)buffered_seek
, METH_VARARGS
},
1484 {"tell", (PyCFunction
)buffered_tell
, METH_NOARGS
},
1485 {"truncate", (PyCFunction
)buffered_truncate
, METH_VARARGS
},
1489 static PyMemberDef bufferedreader_members
[] = {
1490 {"raw", T_OBJECT
, offsetof(buffered
, raw
), 0},
1494 static PyGetSetDef bufferedreader_getset
[] = {
1495 {"closed", (getter
)buffered_closed_get
, NULL
, NULL
},
1496 {"name", (getter
)buffered_name_get
, NULL
, NULL
},
1497 {"mode", (getter
)buffered_mode_get
, NULL
, NULL
},
1502 PyTypeObject PyBufferedReader_Type
= {
1503 PyVarObject_HEAD_INIT(NULL
, 0)
1504 "_io.BufferedReader", /*tp_name*/
1505 sizeof(buffered
), /*tp_basicsize*/
1507 (destructor
)buffered_dealloc
, /*tp_dealloc*/
1512 (reprfunc
)buffered_repr
, /*tp_repr*/
1514 0, /*tp_as_sequence*/
1515 0, /*tp_as_mapping*/
1522 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
1523 | Py_TPFLAGS_HAVE_GC
, /*tp_flags*/
1524 bufferedreader_doc
, /* tp_doc */
1525 (traverseproc
)buffered_traverse
, /* tp_traverse */
1526 (inquiry
)buffered_clear
, /* tp_clear */
1527 0, /* tp_richcompare */
1528 offsetof(buffered
, weakreflist
), /*tp_weaklistoffset*/
1530 (iternextfunc
)buffered_iternext
, /* tp_iternext */
1531 bufferedreader_methods
, /* tp_methods */
1532 bufferedreader_members
, /* tp_members */
1533 bufferedreader_getset
, /* tp_getset */
1536 0, /* tp_descr_get */
1537 0, /* tp_descr_set */
1538 offsetof(buffered
, dict
), /* tp_dictoffset */
1539 (initproc
)bufferedreader_init
, /* tp_init */
1541 PyType_GenericNew
, /* tp_new */
1547 complain_about_max_buffer_size(void)
1549 if (PyErr_WarnEx(PyExc_DeprecationWarning
,
1550 "max_buffer_size is deprecated", 1) < 0)
1556 * class BufferedWriter
1558 PyDoc_STRVAR(bufferedwriter_doc
,
1559 "A buffer for a writeable sequential RawIO object.\n"
1561 "The constructor creates a BufferedWriter for the given writeable raw\n"
1562 "stream. If the buffer_size is not given, it defaults to\n"
1563 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1567 _bufferedwriter_reset_buf(buffered
*self
)
1569 self
->write_pos
= 0;
1570 self
->write_end
= -1;
1574 bufferedwriter_init(buffered
*self
, PyObject
*args
, PyObject
*kwds
)
1576 /* TODO: properly deprecate max_buffer_size */
1577 char *kwlist
[] = {"raw", "buffer_size", "max_buffer_size", NULL
};
1578 Py_ssize_t buffer_size
= DEFAULT_BUFFER_SIZE
;
1579 Py_ssize_t max_buffer_size
= -234;
1585 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "O|nn:BufferedReader", kwlist
,
1586 &raw
, &buffer_size
, &max_buffer_size
)) {
1590 if (max_buffer_size
!= -234 && !complain_about_max_buffer_size())
1593 if (_PyIOBase_check_writable(raw
, Py_True
) == NULL
)
1596 Py_CLEAR(self
->raw
);
1602 self
->buffer_size
= buffer_size
;
1603 if (_buffered_init(self
) < 0)
1605 _bufferedwriter_reset_buf(self
);
1608 self
->fast_closed_checks
= (Py_TYPE(self
) == &PyBufferedWriter_Type
&&
1609 Py_TYPE(raw
) == &PyFileIO_Type
);
1616 _bufferedwriter_raw_write(buffered
*self
, char *start
, Py_ssize_t len
)
1619 PyObject
*memobj
, *res
;
1621 /* NOTE: the buffer needn't be released as its object is NULL. */
1622 if (PyBuffer_FillInfo(&buf
, NULL
, start
, len
, 1, PyBUF_CONTIG_RO
) == -1)
1624 memobj
= PyMemoryView_FromBuffer(&buf
);
1627 res
= PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_write
, memobj
, NULL
);
1631 n
= PyNumber_AsSsize_t(res
, PyExc_ValueError
);
1633 if (n
< 0 || n
> len
) {
1634 PyErr_Format(PyExc_IOError
,
1635 "raw write() returned invalid length %zd "
1636 "(should have been between 0 and %zd)", n
, len
);
1639 if (n
> 0 && self
->abs_pos
!= -1)
1644 /* `restore_pos` is 1 if we need to restore the raw stream position at
1645 the end, 0 otherwise. */
1647 _bufferedwriter_flush_unlocked(buffered
*self
, int restore_pos
)
1649 Py_ssize_t written
= 0;
1652 if (!VALID_WRITE_BUFFER(self
) || self
->write_pos
== self
->write_end
)
1655 rewind
= RAW_OFFSET(self
) + (self
->pos
- self
->write_pos
);
1657 n
= _buffered_raw_seek(self
, -rewind
, 1);
1661 self
->raw_pos
-= rewind
;
1663 while (self
->write_pos
< self
->write_end
) {
1664 n
= _bufferedwriter_raw_write(self
,
1665 self
->buffer
+ self
->write_pos
,
1666 Py_SAFE_DOWNCAST(self
->write_end
- self
->write_pos
,
1667 Py_off_t
, Py_ssize_t
));
1669 Py_ssize_t
*w
= _buffered_check_blocking_error();
1672 self
->write_pos
+= *w
;
1673 self
->raw_pos
= self
->write_pos
;
1676 /* Already re-raised */
1679 self
->write_pos
+= n
;
1680 self
->raw_pos
= self
->write_pos
;
1681 written
+= Py_SAFE_DOWNCAST(n
, Py_off_t
, Py_ssize_t
);
1685 Py_off_t forward
= rewind
- written
;
1687 n
= _buffered_raw_seek(self
, forward
, 1);
1691 self
->raw_pos
+= forward
;
1694 _bufferedwriter_reset_buf(self
);
1704 bufferedwriter_write(buffered
*self
, PyObject
*args
)
1706 PyObject
*res
= NULL
;
1708 Py_ssize_t written
, avail
, remaining
, n
;
1710 CHECK_INITIALIZED(self
)
1711 if (!PyArg_ParseTuple(args
, "s*:write", &buf
)) {
1715 if (IS_CLOSED(self
)) {
1716 PyErr_SetString(PyExc_ValueError
, "write to closed file");
1717 PyBuffer_Release(&buf
);
1721 ENTER_BUFFERED(self
)
1723 /* Fast path: the data to write can be fully buffered. */
1724 if (!VALID_READ_BUFFER(self
) && !VALID_WRITE_BUFFER(self
)) {
1728 avail
= Py_SAFE_DOWNCAST(self
->buffer_size
- self
->pos
, Py_off_t
, Py_ssize_t
);
1729 if (buf
.len
<= avail
) {
1730 memcpy(self
->buffer
+ self
->pos
, buf
.buf
, buf
.len
);
1731 if (!VALID_WRITE_BUFFER(self
)) {
1732 self
->write_pos
= self
->pos
;
1734 ADJUST_POSITION(self
, self
->pos
+ buf
.len
);
1735 if (self
->pos
> self
->write_end
)
1736 self
->write_end
= self
->pos
;
1741 /* First write the current buffer */
1742 res
= _bufferedwriter_flush_unlocked(self
, 0);
1744 Py_ssize_t
*w
= _buffered_check_blocking_error();
1748 _bufferedreader_reset_buf(self
);
1749 /* Make some place by shifting the buffer. */
1750 assert(VALID_WRITE_BUFFER(self
));
1751 memmove(self
->buffer
, self
->buffer
+ self
->write_pos
,
1752 Py_SAFE_DOWNCAST(self
->write_end
- self
->write_pos
,
1753 Py_off_t
, Py_ssize_t
));
1754 self
->write_end
-= self
->write_pos
;
1755 self
->raw_pos
-= self
->write_pos
;
1756 self
->pos
-= self
->write_pos
;
1757 self
->write_pos
= 0;
1758 avail
= Py_SAFE_DOWNCAST(self
->buffer_size
- self
->write_end
,
1759 Py_off_t
, Py_ssize_t
);
1760 if (buf
.len
<= avail
) {
1761 /* Everything can be buffered */
1763 memcpy(self
->buffer
+ self
->write_end
, buf
.buf
, buf
.len
);
1764 self
->write_end
+= buf
.len
;
1768 /* Buffer as much as possible. */
1769 memcpy(self
->buffer
+ self
->write_end
, buf
.buf
, avail
);
1770 self
->write_end
+= avail
;
1771 /* Already re-raised */
1777 /* Adjust the raw stream position if it is away from the logical stream
1778 position. This happens if the read buffer has been filled but not
1779 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1780 the raw stream by itself).
1783 n
= RAW_OFFSET(self
);
1785 if (_buffered_raw_seek(self
, -n
, 1) < 0)
1790 /* Then write buf itself. At this point the buffer has been emptied. */
1791 remaining
= buf
.len
;
1793 while (remaining
> self
->buffer_size
) {
1794 n
= _bufferedwriter_raw_write(
1795 self
, (char *) buf
.buf
+ written
, buf
.len
- written
);
1797 Py_ssize_t
*w
= _buffered_check_blocking_error();
1802 if (remaining
> self
->buffer_size
) {
1803 /* Can't buffer everything, still buffer as much as possible */
1804 memcpy(self
->buffer
,
1805 (char *) buf
.buf
+ written
, self
->buffer_size
);
1807 ADJUST_POSITION(self
, self
->buffer_size
);
1808 self
->write_end
= self
->buffer_size
;
1809 *w
= written
+ self
->buffer_size
;
1810 /* Already re-raised */
1820 _bufferedreader_reset_buf(self
);
1821 if (remaining
> 0) {
1822 memcpy(self
->buffer
, (char *) buf
.buf
+ written
, remaining
);
1823 written
+= remaining
;
1825 self
->write_pos
= 0;
1826 /* TODO: sanity check (remaining >= 0) */
1827 self
->write_end
= remaining
;
1828 ADJUST_POSITION(self
, remaining
);
1832 res
= PyLong_FromSsize_t(written
);
1835 LEAVE_BUFFERED(self
)
1836 PyBuffer_Release(&buf
);
1840 static PyMethodDef bufferedwriter_methods
[] = {
1841 /* BufferedIOMixin methods */
1842 {"close", (PyCFunction
)buffered_close
, METH_NOARGS
},
1843 {"detach", (PyCFunction
)buffered_detach
, METH_NOARGS
},
1844 {"seekable", (PyCFunction
)buffered_seekable
, METH_NOARGS
},
1845 {"readable", (PyCFunction
)buffered_readable
, METH_NOARGS
},
1846 {"writable", (PyCFunction
)buffered_writable
, METH_NOARGS
},
1847 {"fileno", (PyCFunction
)buffered_fileno
, METH_NOARGS
},
1848 {"isatty", (PyCFunction
)buffered_isatty
, METH_NOARGS
},
1850 {"write", (PyCFunction
)bufferedwriter_write
, METH_VARARGS
},
1851 {"truncate", (PyCFunction
)buffered_truncate
, METH_VARARGS
},
1852 {"flush", (PyCFunction
)buffered_flush
, METH_NOARGS
},
1853 {"seek", (PyCFunction
)buffered_seek
, METH_VARARGS
},
1854 {"tell", (PyCFunction
)buffered_tell
, METH_NOARGS
},
1858 static PyMemberDef bufferedwriter_members
[] = {
1859 {"raw", T_OBJECT
, offsetof(buffered
, raw
), 0},
1863 static PyGetSetDef bufferedwriter_getset
[] = {
1864 {"closed", (getter
)buffered_closed_get
, NULL
, NULL
},
1865 {"name", (getter
)buffered_name_get
, NULL
, NULL
},
1866 {"mode", (getter
)buffered_mode_get
, NULL
, NULL
},
1871 PyTypeObject PyBufferedWriter_Type
= {
1872 PyVarObject_HEAD_INIT(NULL
, 0)
1873 "_io.BufferedWriter", /*tp_name*/
1874 sizeof(buffered
), /*tp_basicsize*/
1876 (destructor
)buffered_dealloc
, /*tp_dealloc*/
1881 (reprfunc
)buffered_repr
, /*tp_repr*/
1883 0, /*tp_as_sequence*/
1884 0, /*tp_as_mapping*/
1891 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
1892 | Py_TPFLAGS_HAVE_GC
, /*tp_flags*/
1893 bufferedwriter_doc
, /* tp_doc */
1894 (traverseproc
)buffered_traverse
, /* tp_traverse */
1895 (inquiry
)buffered_clear
, /* tp_clear */
1896 0, /* tp_richcompare */
1897 offsetof(buffered
, weakreflist
), /*tp_weaklistoffset*/
1899 0, /* tp_iternext */
1900 bufferedwriter_methods
, /* tp_methods */
1901 bufferedwriter_members
, /* tp_members */
1902 bufferedwriter_getset
, /* tp_getset */
1905 0, /* tp_descr_get */
1906 0, /* tp_descr_set */
1907 offsetof(buffered
, dict
), /* tp_dictoffset */
1908 (initproc
)bufferedwriter_init
, /* tp_init */
1910 PyType_GenericNew
, /* tp_new */
1919 PyDoc_STRVAR(bufferedrwpair_doc
,
1920 "A buffered reader and writer object together.\n"
1922 "A buffered reader object and buffered writer object put together to\n"
1923 "form a sequential IO object that can read and write. This is typically\n"
1924 "used with a socket or two-way pipe.\n"
1926 "reader and writer are RawIOBase objects that are readable and\n"
1927 "writeable respectively. If the buffer_size is omitted it defaults to\n"
1928 "DEFAULT_BUFFER_SIZE.\n"
1931 /* XXX The usefulness of this (compared to having two separate IO objects) is
1940 PyObject
*weakreflist
;
1944 bufferedrwpair_init(rwpair
*self
, PyObject
*args
, PyObject
*kwds
)
1946 PyObject
*reader
, *writer
;
1947 Py_ssize_t buffer_size
= DEFAULT_BUFFER_SIZE
;
1948 Py_ssize_t max_buffer_size
= -234;
1950 if (!PyArg_ParseTuple(args
, "OO|nn:BufferedRWPair", &reader
, &writer
,
1951 &buffer_size
, &max_buffer_size
)) {
1955 if (max_buffer_size
!= -234 && !complain_about_max_buffer_size())
1958 if (_PyIOBase_check_readable(reader
, Py_True
) == NULL
)
1960 if (_PyIOBase_check_writable(writer
, Py_True
) == NULL
)
1963 self
->reader
= (buffered
*) PyObject_CallFunction(
1964 (PyObject
*) &PyBufferedReader_Type
, "On", reader
, buffer_size
);
1965 if (self
->reader
== NULL
)
1968 self
->writer
= (buffered
*) PyObject_CallFunction(
1969 (PyObject
*) &PyBufferedWriter_Type
, "On", writer
, buffer_size
);
1970 if (self
->writer
== NULL
) {
1971 Py_CLEAR(self
->reader
);
1979 bufferedrwpair_traverse(rwpair
*self
, visitproc visit
, void *arg
)
1981 Py_VISIT(self
->dict
);
1986 bufferedrwpair_clear(rwpair
*self
)
1988 Py_CLEAR(self
->reader
);
1989 Py_CLEAR(self
->writer
);
1990 Py_CLEAR(self
->dict
);
1995 bufferedrwpair_dealloc(rwpair
*self
)
1997 _PyObject_GC_UNTRACK(self
);
1998 Py_CLEAR(self
->reader
);
1999 Py_CLEAR(self
->writer
);
2000 Py_CLEAR(self
->dict
);
2001 Py_TYPE(self
)->tp_free((PyObject
*) self
);
2005 _forward_call(buffered
*self
, const char *name
, PyObject
*args
)
2007 PyObject
*func
= PyObject_GetAttrString((PyObject
*)self
, name
);
2011 PyErr_SetString(PyExc_AttributeError
, name
);
2015 ret
= PyObject_CallObject(func
, args
);
2021 bufferedrwpair_read(rwpair
*self
, PyObject
*args
)
2023 return _forward_call(self
->reader
, "read", args
);
2027 bufferedrwpair_peek(rwpair
*self
, PyObject
*args
)
2029 return _forward_call(self
->reader
, "peek", args
);
2033 bufferedrwpair_read1(rwpair
*self
, PyObject
*args
)
2035 return _forward_call(self
->reader
, "read1", args
);
2039 bufferedrwpair_readinto(rwpair
*self
, PyObject
*args
)
2041 return _forward_call(self
->reader
, "readinto", args
);
2045 bufferedrwpair_write(rwpair
*self
, PyObject
*args
)
2047 return _forward_call(self
->writer
, "write", args
);
2051 bufferedrwpair_flush(rwpair
*self
, PyObject
*args
)
2053 return _forward_call(self
->writer
, "flush", args
);
2057 bufferedrwpair_readable(rwpair
*self
, PyObject
*args
)
2059 return _forward_call(self
->reader
, "readable", args
);
2063 bufferedrwpair_writable(rwpair
*self
, PyObject
*args
)
2065 return _forward_call(self
->writer
, "writable", args
);
2069 bufferedrwpair_close(rwpair
*self
, PyObject
*args
)
2071 PyObject
*ret
= _forward_call(self
->writer
, "close", args
);
2076 return _forward_call(self
->reader
, "close", args
);
2080 bufferedrwpair_isatty(rwpair
*self
, PyObject
*args
)
2082 PyObject
*ret
= _forward_call(self
->writer
, "isatty", args
);
2084 if (ret
!= Py_False
) {
2085 /* either True or exception */
2090 return _forward_call(self
->reader
, "isatty", args
);
2094 bufferedrwpair_closed_get(rwpair
*self
, void *context
)
2096 return PyObject_GetAttr((PyObject
*) self
->writer
, _PyIO_str_closed
);
2099 static PyMethodDef bufferedrwpair_methods
[] = {
2100 {"read", (PyCFunction
)bufferedrwpair_read
, METH_VARARGS
},
2101 {"peek", (PyCFunction
)bufferedrwpair_peek
, METH_VARARGS
},
2102 {"read1", (PyCFunction
)bufferedrwpair_read1
, METH_VARARGS
},
2103 {"readinto", (PyCFunction
)bufferedrwpair_readinto
, METH_VARARGS
},
2105 {"write", (PyCFunction
)bufferedrwpair_write
, METH_VARARGS
},
2106 {"flush", (PyCFunction
)bufferedrwpair_flush
, METH_NOARGS
},
2108 {"readable", (PyCFunction
)bufferedrwpair_readable
, METH_NOARGS
},
2109 {"writable", (PyCFunction
)bufferedrwpair_writable
, METH_NOARGS
},
2111 {"close", (PyCFunction
)bufferedrwpair_close
, METH_NOARGS
},
2112 {"isatty", (PyCFunction
)bufferedrwpair_isatty
, METH_NOARGS
},
2117 static PyGetSetDef bufferedrwpair_getset
[] = {
2118 {"closed", (getter
)bufferedrwpair_closed_get
, NULL
, NULL
},
2122 PyTypeObject PyBufferedRWPair_Type
= {
2123 PyVarObject_HEAD_INIT(NULL
, 0)
2124 "_io.BufferedRWPair", /*tp_name*/
2125 sizeof(rwpair
), /*tp_basicsize*/
2127 (destructor
)bufferedrwpair_dealloc
, /*tp_dealloc*/
2134 0, /*tp_as_sequence*/
2135 0, /*tp_as_mapping*/
2142 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
2143 | Py_TPFLAGS_HAVE_GC
, /* tp_flags */
2144 bufferedrwpair_doc
, /* tp_doc */
2145 (traverseproc
)bufferedrwpair_traverse
, /* tp_traverse */
2146 (inquiry
)bufferedrwpair_clear
, /* tp_clear */
2147 0, /* tp_richcompare */
2148 offsetof(rwpair
, weakreflist
), /*tp_weaklistoffset*/
2150 0, /* tp_iternext */
2151 bufferedrwpair_methods
, /* tp_methods */
2153 bufferedrwpair_getset
, /* tp_getset */
2156 0, /* tp_descr_get */
2157 0, /* tp_descr_set */
2158 offsetof(rwpair
, dict
), /* tp_dictoffset */
2159 (initproc
)bufferedrwpair_init
, /* tp_init */
2161 PyType_GenericNew
, /* tp_new */
2170 PyDoc_STRVAR(bufferedrandom_doc
,
2171 "A buffered interface to random access streams.\n"
2173 "The constructor creates a reader and writer for a seekable stream,\n"
2174 "raw, given in the first argument. If the buffer_size is omitted it\n"
2175 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2179 bufferedrandom_init(buffered
*self
, PyObject
*args
, PyObject
*kwds
)
2181 char *kwlist
[] = {"raw", "buffer_size", "max_buffer_size", NULL
};
2182 Py_ssize_t buffer_size
= DEFAULT_BUFFER_SIZE
;
2183 Py_ssize_t max_buffer_size
= -234;
2189 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "O|nn:BufferedReader", kwlist
,
2190 &raw
, &buffer_size
, &max_buffer_size
)) {
2194 if (max_buffer_size
!= -234 && !complain_about_max_buffer_size())
2197 if (_PyIOBase_check_seekable(raw
, Py_True
) == NULL
)
2199 if (_PyIOBase_check_readable(raw
, Py_True
) == NULL
)
2201 if (_PyIOBase_check_writable(raw
, Py_True
) == NULL
)
2204 Py_CLEAR(self
->raw
);
2207 self
->buffer_size
= buffer_size
;
2211 if (_buffered_init(self
) < 0)
2213 _bufferedreader_reset_buf(self
);
2214 _bufferedwriter_reset_buf(self
);
2217 self
->fast_closed_checks
= (Py_TYPE(self
) == &PyBufferedRandom_Type
&&
2218 Py_TYPE(raw
) == &PyFileIO_Type
);
2224 static PyMethodDef bufferedrandom_methods
[] = {
2225 /* BufferedIOMixin methods */
2226 {"close", (PyCFunction
)buffered_close
, METH_NOARGS
},
2227 {"detach", (PyCFunction
)buffered_detach
, METH_NOARGS
},
2228 {"seekable", (PyCFunction
)buffered_seekable
, METH_NOARGS
},
2229 {"readable", (PyCFunction
)buffered_readable
, METH_NOARGS
},
2230 {"writable", (PyCFunction
)buffered_writable
, METH_NOARGS
},
2231 {"fileno", (PyCFunction
)buffered_fileno
, METH_NOARGS
},
2232 {"isatty", (PyCFunction
)buffered_isatty
, METH_NOARGS
},
2234 {"flush", (PyCFunction
)buffered_flush
, METH_NOARGS
},
2236 {"seek", (PyCFunction
)buffered_seek
, METH_VARARGS
},
2237 {"tell", (PyCFunction
)buffered_tell
, METH_NOARGS
},
2238 {"truncate", (PyCFunction
)buffered_truncate
, METH_VARARGS
},
2239 {"read", (PyCFunction
)buffered_read
, METH_VARARGS
},
2240 {"read1", (PyCFunction
)buffered_read1
, METH_VARARGS
},
2241 {"readinto", (PyCFunction
)buffered_readinto
, METH_VARARGS
},
2242 {"readline", (PyCFunction
)buffered_readline
, METH_VARARGS
},
2243 {"peek", (PyCFunction
)buffered_peek
, METH_VARARGS
},
2244 {"write", (PyCFunction
)bufferedwriter_write
, METH_VARARGS
},
2248 static PyMemberDef bufferedrandom_members
[] = {
2249 {"raw", T_OBJECT
, offsetof(buffered
, raw
), 0},
2253 static PyGetSetDef bufferedrandom_getset
[] = {
2254 {"closed", (getter
)buffered_closed_get
, NULL
, NULL
},
2255 {"name", (getter
)buffered_name_get
, NULL
, NULL
},
2256 {"mode", (getter
)buffered_mode_get
, NULL
, NULL
},
2261 PyTypeObject PyBufferedRandom_Type
= {
2262 PyVarObject_HEAD_INIT(NULL
, 0)
2263 "_io.BufferedRandom", /*tp_name*/
2264 sizeof(buffered
), /*tp_basicsize*/
2266 (destructor
)buffered_dealloc
, /*tp_dealloc*/
2271 (reprfunc
)buffered_repr
, /*tp_repr*/
2273 0, /*tp_as_sequence*/
2274 0, /*tp_as_mapping*/
2281 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
2282 | Py_TPFLAGS_HAVE_GC
, /*tp_flags*/
2283 bufferedrandom_doc
, /* tp_doc */
2284 (traverseproc
)buffered_traverse
, /* tp_traverse */
2285 (inquiry
)buffered_clear
, /* tp_clear */
2286 0, /* tp_richcompare */
2287 offsetof(buffered
, weakreflist
), /*tp_weaklistoffset*/
2289 (iternextfunc
)buffered_iternext
, /* tp_iternext */
2290 bufferedrandom_methods
, /* tp_methods */
2291 bufferedrandom_members
, /* tp_members */
2292 bufferedrandom_getset
, /* tp_getset */
2295 0, /* tp_descr_get */
2296 0, /* tp_descr_set */
2297 offsetof(buffered
, dict
), /*tp_dictoffset*/
2298 (initproc
)bufferedrandom_init
, /* tp_init */
2300 PyType_GenericNew
, /* tp_new */