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
);
443 /* If flush() fails, just give up */
444 if (PyErr_ExceptionMatches(PyExc_IOError
))
451 res
= PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_close
, NULL
);
461 buffered_detach(buffered
*self
, PyObject
*args
)
464 CHECK_INITIALIZED(self
)
465 res
= PyObject_CallMethodObjArgs((PyObject
*)self
, _PyIO_str_flush
, NULL
);
479 buffered_seekable(buffered
*self
, PyObject
*args
)
481 CHECK_INITIALIZED(self
)
482 return PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_seekable
, NULL
);
486 buffered_readable(buffered
*self
, PyObject
*args
)
488 CHECK_INITIALIZED(self
)
489 return PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_readable
, NULL
);
493 buffered_writable(buffered
*self
, PyObject
*args
)
495 CHECK_INITIALIZED(self
)
496 return PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_writable
, NULL
);
500 buffered_name_get(buffered
*self
, void *context
)
502 CHECK_INITIALIZED(self
)
503 return PyObject_GetAttrString(self
->raw
, "name");
507 buffered_mode_get(buffered
*self
, void *context
)
509 CHECK_INITIALIZED(self
)
510 return PyObject_GetAttrString(self
->raw
, "mode");
513 /* Lower-level APIs */
516 buffered_fileno(buffered
*self
, PyObject
*args
)
518 CHECK_INITIALIZED(self
)
519 return PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_fileno
, NULL
);
523 buffered_isatty(buffered
*self
, PyObject
*args
)
525 CHECK_INITIALIZED(self
)
526 return PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_isatty
, NULL
);
532 _bufferedwriter_flush_unlocked(buffered
*, int);
534 _bufferedreader_fill_buffer(buffered
*self
);
536 _bufferedreader_reset_buf(buffered
*self
);
538 _bufferedwriter_reset_buf(buffered
*self
);
540 _bufferedreader_peek_unlocked(buffered
*self
, Py_ssize_t
);
542 _bufferedreader_read_all(buffered
*self
);
544 _bufferedreader_read_fast(buffered
*self
, Py_ssize_t
);
546 _bufferedreader_read_generic(buffered
*self
, Py_ssize_t
);
553 /* Returns the address of the `written` member if a BlockingIOError was
554 raised, NULL otherwise. The error is always re-raised. */
556 _buffered_check_blocking_error(void)
558 PyObject
*t
, *v
, *tb
;
559 PyBlockingIOErrorObject
*err
;
561 PyErr_Fetch(&t
, &v
, &tb
);
562 if (v
== NULL
|| !PyErr_GivenExceptionMatches(v
, PyExc_BlockingIOError
)) {
563 PyErr_Restore(t
, v
, tb
);
566 err
= (PyBlockingIOErrorObject
*) v
;
567 /* TODO: sanity check (err->written >= 0) */
568 PyErr_Restore(t
, v
, tb
);
569 return &err
->written
;
573 _buffered_raw_tell(buffered
*self
)
577 res
= PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_tell
, NULL
);
580 n
= PyNumber_AsOff_t(res
, PyExc_ValueError
);
583 if (!PyErr_Occurred())
584 PyErr_Format(PyExc_IOError
,
585 "Raw stream returned invalid position %zd", n
);
593 _buffered_raw_seek(buffered
*self
, Py_off_t target
, int whence
)
595 PyObject
*res
, *posobj
, *whenceobj
;
598 posobj
= PyLong_FromOff_t(target
);
601 whenceobj
= PyLong_FromLong(whence
);
602 if (whenceobj
== NULL
) {
606 res
= PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_seek
,
607 posobj
, whenceobj
, NULL
);
609 Py_DECREF(whenceobj
);
612 n
= PyNumber_AsOff_t(res
, PyExc_ValueError
);
615 if (!PyErr_Occurred())
616 PyErr_Format(PyExc_IOError
,
617 "Raw stream returned invalid position %zd", n
);
625 _buffered_init(buffered
*self
)
628 if (self
->buffer_size
<= 0) {
629 PyErr_SetString(PyExc_ValueError
,
630 "buffer size must be strictly positive");
634 PyMem_Free(self
->buffer
);
635 self
->buffer
= PyMem_Malloc(self
->buffer_size
);
636 if (self
->buffer
== NULL
) {
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
, "|n:read", &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 PyObject
*limitobj
= NULL
;
952 Py_ssize_t limit
= -1;
954 CHECK_INITIALIZED(self
)
956 if (!PyArg_ParseTuple(args
, "|O:readline", &limitobj
)) {
960 if (!PyNumber_Check(limitobj
)) {
961 PyErr_Format(PyExc_TypeError
,
962 "integer argument expected, got '%.200s'",
963 Py_TYPE(limitobj
)->tp_name
);
966 limit
= PyNumber_AsSsize_t(limitobj
, PyExc_OverflowError
);
967 if (limit
== -1 && PyErr_Occurred())
970 return _buffered_readline(self
, limit
);
975 buffered_tell(buffered
*self
, PyObject
*args
)
979 CHECK_INITIALIZED(self
)
980 pos
= _buffered_raw_tell(self
);
983 pos
-= RAW_OFFSET(self
);
984 /* TODO: sanity check (pos >= 0) */
985 return PyLong_FromOff_t(pos
);
989 buffered_seek(buffered
*self
, PyObject
*args
)
993 PyObject
*targetobj
, *res
= NULL
;
995 CHECK_INITIALIZED(self
)
996 if (!PyArg_ParseTuple(args
, "O|i:seek", &targetobj
, &whence
)) {
999 if (whence
< 0 || whence
> 2) {
1000 PyErr_Format(PyExc_ValueError
,
1001 "whence must be between 0 and 2, not %d", whence
);
1005 CHECK_CLOSED(self
, "seek of closed file")
1007 target
= PyNumber_AsOff_t(targetobj
, PyExc_ValueError
);
1008 if (target
== -1 && PyErr_Occurred())
1011 if (whence
!= 2 && self
->readable
) {
1012 Py_off_t current
, avail
;
1013 /* Check if seeking leaves us inside the current buffer,
1014 so as to return quickly if possible. Also, we needn't take the
1015 lock in this fast path.
1016 Don't know how to do that when whence == 2, though. */
1017 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1018 state at this point. */
1019 current
= RAW_TELL(self
);
1020 avail
= READAHEAD(self
);
1024 offset
= target
- (current
- RAW_OFFSET(self
));
1027 if (offset
>= -self
->pos
&& offset
<= avail
) {
1028 self
->pos
+= offset
;
1029 return PyLong_FromOff_t(current
- avail
+ offset
);
1034 ENTER_BUFFERED(self
)
1036 /* Fallback: invoke raw seek() method and clear buffer */
1037 if (self
->writable
) {
1038 res
= _bufferedwriter_flush_unlocked(self
, 0);
1042 _bufferedwriter_reset_buf(self
);
1045 /* TODO: align on block boundary and read buffer if needed? */
1047 target
-= RAW_OFFSET(self
);
1048 n
= _buffered_raw_seek(self
, target
, whence
);
1052 res
= PyLong_FromOff_t(n
);
1053 if (res
!= NULL
&& self
->readable
)
1054 _bufferedreader_reset_buf(self
);
1057 LEAVE_BUFFERED(self
)
1062 buffered_truncate(buffered
*self
, PyObject
*args
)
1064 PyObject
*pos
= Py_None
;
1065 PyObject
*res
= NULL
;
1067 CHECK_INITIALIZED(self
)
1068 if (!PyArg_ParseTuple(args
, "|O:truncate", &pos
)) {
1072 ENTER_BUFFERED(self
)
1074 if (self
->writable
) {
1075 res
= _bufferedwriter_flush_unlocked(self
, 0);
1080 if (self
->readable
) {
1081 if (pos
== Py_None
) {
1082 /* Rewind the raw stream so that its position corresponds to
1083 the current logical position. */
1084 if (_buffered_raw_seek(self
, -RAW_OFFSET(self
), 1) == -1)
1087 _bufferedreader_reset_buf(self
);
1089 res
= PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_truncate
, pos
, NULL
);
1092 /* Reset cached position */
1093 if (_buffered_raw_tell(self
) == -1)
1097 LEAVE_BUFFERED(self
)
1102 buffered_iternext(buffered
*self
)
1107 CHECK_INITIALIZED(self
);
1110 if (tp
== &PyBufferedReader_Type
||
1111 tp
== &PyBufferedRandom_Type
) {
1112 /* Skip method call overhead for speed */
1113 line
= _buffered_readline(self
, -1);
1116 line
= PyObject_CallMethodObjArgs((PyObject
*)self
,
1117 _PyIO_str_readline
, NULL
);
1118 if (line
&& !PyBytes_Check(line
)) {
1119 PyErr_Format(PyExc_IOError
,
1120 "readline() should have returned a bytes object, "
1121 "not '%.200s'", Py_TYPE(line
)->tp_name
);
1130 if (PyBytes_GET_SIZE(line
) == 0) {
1131 /* Reached EOF or would have blocked */
1140 buffered_repr(buffered
*self
)
1142 PyObject
*nameobj
, *res
;
1144 nameobj
= PyObject_GetAttrString((PyObject
*) self
, "name");
1145 if (nameobj
== NULL
) {
1146 if (PyErr_ExceptionMatches(PyExc_AttributeError
))
1150 res
= PyString_FromFormat("<%s>", Py_TYPE(self
)->tp_name
);
1153 PyObject
*repr
= PyObject_Repr(nameobj
);
1157 res
= PyString_FromFormat("<%s name=%s>",
1158 Py_TYPE(self
)->tp_name
,
1159 PyString_AS_STRING(repr
));
1166 * class BufferedReader
1169 PyDoc_STRVAR(bufferedreader_doc
,
1170 "Create a new buffered reader using the given readable raw IO object.");
1172 static void _bufferedreader_reset_buf(buffered
*self
)
1174 self
->read_end
= -1;
1178 bufferedreader_init(buffered
*self
, PyObject
*args
, PyObject
*kwds
)
1180 char *kwlist
[] = {"raw", "buffer_size", NULL
};
1181 Py_ssize_t buffer_size
= DEFAULT_BUFFER_SIZE
;
1187 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "O|n:BufferedReader", kwlist
,
1188 &raw
, &buffer_size
)) {
1192 if (_PyIOBase_check_readable(raw
, Py_True
) == NULL
)
1195 Py_CLEAR(self
->raw
);
1198 self
->buffer_size
= buffer_size
;
1202 if (_buffered_init(self
) < 0)
1204 _bufferedreader_reset_buf(self
);
1206 self
->fast_closed_checks
= (Py_TYPE(self
) == &PyBufferedReader_Type
&&
1207 Py_TYPE(raw
) == &PyFileIO_Type
);
1214 _bufferedreader_raw_read(buffered
*self
, char *start
, Py_ssize_t len
)
1217 PyObject
*memobj
, *res
;
1219 /* NOTE: the buffer needn't be released as its object is NULL. */
1220 if (PyBuffer_FillInfo(&buf
, NULL
, start
, len
, 0, PyBUF_CONTIG
) == -1)
1222 memobj
= PyMemoryView_FromBuffer(&buf
);
1225 res
= PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_readinto
, memobj
, NULL
);
1229 if (res
== Py_None
) {
1230 /* Non-blocking stream would have blocked. Special return code! */
1234 n
= PyNumber_AsSsize_t(res
, PyExc_ValueError
);
1236 if (n
< 0 || n
> len
) {
1237 PyErr_Format(PyExc_IOError
,
1238 "raw readinto() returned invalid length %zd "
1239 "(should have been between 0 and %zd)", n
, len
);
1242 if (n
> 0 && self
->abs_pos
!= -1)
1248 _bufferedreader_fill_buffer(buffered
*self
)
1250 Py_ssize_t start
, len
, n
;
1251 if (VALID_READ_BUFFER(self
))
1252 start
= Py_SAFE_DOWNCAST(self
->read_end
, Py_off_t
, Py_ssize_t
);
1255 len
= self
->buffer_size
- start
;
1256 n
= _bufferedreader_raw_read(self
, self
->buffer
+ start
, len
);
1259 self
->read_end
= start
+ n
;
1260 self
->raw_pos
= start
+ n
;
1265 _bufferedreader_read_all(buffered
*self
)
1267 Py_ssize_t current_size
;
1268 PyObject
*res
, *data
= NULL
;
1269 PyObject
*chunks
= PyList_New(0);
1274 /* First copy what we have in the current buffer. */
1275 current_size
= Py_SAFE_DOWNCAST(READAHEAD(self
), Py_off_t
, Py_ssize_t
);
1277 data
= PyBytes_FromStringAndSize(
1278 self
->buffer
+ self
->pos
, current_size
);
1284 _bufferedreader_reset_buf(self
);
1285 /* We're going past the buffer's bounds, flush it */
1286 if (self
->writable
) {
1287 res
= _bufferedwriter_flush_unlocked(self
, 1);
1296 if (PyList_Append(chunks
, data
) < 0) {
1304 /* Read until EOF or until read() would block. */
1305 data
= PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_read
, NULL
);
1310 if (data
!= Py_None
&& !PyBytes_Check(data
)) {
1313 PyErr_SetString(PyExc_TypeError
, "read() should return bytes");
1316 if (data
== Py_None
|| PyBytes_GET_SIZE(data
) == 0) {
1317 if (current_size
== 0) {
1322 res
= _PyBytes_Join(_PyIO_empty_bytes
, chunks
);
1328 current_size
+= PyBytes_GET_SIZE(data
);
1329 if (self
->abs_pos
!= -1)
1330 self
->abs_pos
+= PyBytes_GET_SIZE(data
);
1334 /* Read n bytes from the buffer if it can, otherwise return None.
1335 This function is simple enough that it can run unlocked. */
1337 _bufferedreader_read_fast(buffered
*self
, Py_ssize_t n
)
1339 Py_ssize_t current_size
;
1341 current_size
= Py_SAFE_DOWNCAST(READAHEAD(self
), Py_off_t
, Py_ssize_t
);
1342 if (n
<= current_size
) {
1343 /* Fast path: the data to read is fully buffered. */
1344 PyObject
*res
= PyBytes_FromStringAndSize(self
->buffer
+ self
->pos
, n
);
1352 /* Generic read function: read from the stream until enough bytes are read,
1353 * or until an EOF occurs or until read() would block.
1356 _bufferedreader_read_generic(buffered
*self
, Py_ssize_t n
)
1358 PyObject
*res
= NULL
;
1359 Py_ssize_t current_size
, remaining
, written
;
1362 current_size
= Py_SAFE_DOWNCAST(READAHEAD(self
), Py_off_t
, Py_ssize_t
);
1363 if (n
<= current_size
)
1364 return _bufferedreader_read_fast(self
, n
);
1366 res
= PyBytes_FromStringAndSize(NULL
, n
);
1369 out
= PyBytes_AS_STRING(res
);
1372 if (current_size
> 0) {
1373 memcpy(out
, self
->buffer
+ self
->pos
, current_size
);
1374 remaining
-= current_size
;
1375 written
+= current_size
;
1377 _bufferedreader_reset_buf(self
);
1378 while (remaining
> 0) {
1379 /* We want to read a whole block at the end into buffer.
1380 If we had readv() we could do this in one pass. */
1381 Py_ssize_t r
= MINUS_LAST_BLOCK(self
, remaining
);
1384 r
= _bufferedreader_raw_read(self
, out
+ written
, r
);
1387 if (r
== 0 || r
== -2) {
1388 /* EOF occurred or read() would block. */
1389 if (r
== 0 || written
> 0) {
1390 if (_PyBytes_Resize(&res
, written
))
1401 assert(remaining
<= self
->buffer_size
);
1405 while (self
->read_end
< self
->buffer_size
) {
1406 Py_ssize_t r
= _bufferedreader_fill_buffer(self
);
1409 if (r
== 0 || r
== -2) {
1410 /* EOF occurred or read() would block. */
1411 if (r
== 0 || written
> 0) {
1412 if (_PyBytes_Resize(&res
, written
))
1420 if (remaining
> r
) {
1421 memcpy(out
+ written
, self
->buffer
+ self
->pos
, r
);
1426 else if (remaining
> 0) {
1427 memcpy(out
+ written
, self
->buffer
+ self
->pos
, remaining
);
1428 written
+= remaining
;
1429 self
->pos
+= remaining
;
1444 _bufferedreader_peek_unlocked(buffered
*self
, Py_ssize_t n
)
1448 have
= Py_SAFE_DOWNCAST(READAHEAD(self
), Py_off_t
, Py_ssize_t
);
1450 1. we don't want to advance the file position.
1451 2. we don't want to lose block alignment, so we can't shift the buffer
1453 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1456 return PyBytes_FromStringAndSize(self
->buffer
+ self
->pos
, have
);
1459 /* Fill the buffer from the raw stream, and copy it to the result. */
1460 _bufferedreader_reset_buf(self
);
1461 r
= _bufferedreader_fill_buffer(self
);
1467 return PyBytes_FromStringAndSize(self
->buffer
, r
);
1470 static PyMethodDef bufferedreader_methods
[] = {
1471 /* BufferedIOMixin methods */
1472 {"detach", (PyCFunction
)buffered_detach
, METH_NOARGS
},
1473 {"flush", (PyCFunction
)buffered_simple_flush
, METH_NOARGS
},
1474 {"close", (PyCFunction
)buffered_close
, METH_NOARGS
},
1475 {"seekable", (PyCFunction
)buffered_seekable
, METH_NOARGS
},
1476 {"readable", (PyCFunction
)buffered_readable
, METH_NOARGS
},
1477 {"writable", (PyCFunction
)buffered_writable
, METH_NOARGS
},
1478 {"fileno", (PyCFunction
)buffered_fileno
, METH_NOARGS
},
1479 {"isatty", (PyCFunction
)buffered_isatty
, METH_NOARGS
},
1481 {"read", (PyCFunction
)buffered_read
, METH_VARARGS
},
1482 {"peek", (PyCFunction
)buffered_peek
, METH_VARARGS
},
1483 {"read1", (PyCFunction
)buffered_read1
, METH_VARARGS
},
1484 {"readline", (PyCFunction
)buffered_readline
, METH_VARARGS
},
1485 {"seek", (PyCFunction
)buffered_seek
, METH_VARARGS
},
1486 {"tell", (PyCFunction
)buffered_tell
, METH_NOARGS
},
1487 {"truncate", (PyCFunction
)buffered_truncate
, METH_VARARGS
},
1491 static PyMemberDef bufferedreader_members
[] = {
1492 {"raw", T_OBJECT
, offsetof(buffered
, raw
), 0},
1496 static PyGetSetDef bufferedreader_getset
[] = {
1497 {"closed", (getter
)buffered_closed_get
, NULL
, NULL
},
1498 {"name", (getter
)buffered_name_get
, NULL
, NULL
},
1499 {"mode", (getter
)buffered_mode_get
, NULL
, NULL
},
1504 PyTypeObject PyBufferedReader_Type
= {
1505 PyVarObject_HEAD_INIT(NULL
, 0)
1506 "_io.BufferedReader", /*tp_name*/
1507 sizeof(buffered
), /*tp_basicsize*/
1509 (destructor
)buffered_dealloc
, /*tp_dealloc*/
1514 (reprfunc
)buffered_repr
, /*tp_repr*/
1516 0, /*tp_as_sequence*/
1517 0, /*tp_as_mapping*/
1524 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
1525 | Py_TPFLAGS_HAVE_GC
, /*tp_flags*/
1526 bufferedreader_doc
, /* tp_doc */
1527 (traverseproc
)buffered_traverse
, /* tp_traverse */
1528 (inquiry
)buffered_clear
, /* tp_clear */
1529 0, /* tp_richcompare */
1530 offsetof(buffered
, weakreflist
), /*tp_weaklistoffset*/
1532 (iternextfunc
)buffered_iternext
, /* tp_iternext */
1533 bufferedreader_methods
, /* tp_methods */
1534 bufferedreader_members
, /* tp_members */
1535 bufferedreader_getset
, /* tp_getset */
1538 0, /* tp_descr_get */
1539 0, /* tp_descr_set */
1540 offsetof(buffered
, dict
), /* tp_dictoffset */
1541 (initproc
)bufferedreader_init
, /* tp_init */
1543 PyType_GenericNew
, /* tp_new */
1549 complain_about_max_buffer_size(void)
1551 if (PyErr_WarnEx(PyExc_DeprecationWarning
,
1552 "max_buffer_size is deprecated", 1) < 0)
1558 * class BufferedWriter
1560 PyDoc_STRVAR(bufferedwriter_doc
,
1561 "A buffer for a writeable sequential RawIO object.\n"
1563 "The constructor creates a BufferedWriter for the given writeable raw\n"
1564 "stream. If the buffer_size is not given, it defaults to\n"
1565 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1569 _bufferedwriter_reset_buf(buffered
*self
)
1571 self
->write_pos
= 0;
1572 self
->write_end
= -1;
1576 bufferedwriter_init(buffered
*self
, PyObject
*args
, PyObject
*kwds
)
1578 /* TODO: properly deprecate max_buffer_size */
1579 char *kwlist
[] = {"raw", "buffer_size", "max_buffer_size", NULL
};
1580 Py_ssize_t buffer_size
= DEFAULT_BUFFER_SIZE
;
1581 Py_ssize_t max_buffer_size
= -234;
1587 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "O|nn:BufferedReader", kwlist
,
1588 &raw
, &buffer_size
, &max_buffer_size
)) {
1592 if (max_buffer_size
!= -234 && !complain_about_max_buffer_size())
1595 if (_PyIOBase_check_writable(raw
, Py_True
) == NULL
)
1598 Py_CLEAR(self
->raw
);
1604 self
->buffer_size
= buffer_size
;
1605 if (_buffered_init(self
) < 0)
1607 _bufferedwriter_reset_buf(self
);
1610 self
->fast_closed_checks
= (Py_TYPE(self
) == &PyBufferedWriter_Type
&&
1611 Py_TYPE(raw
) == &PyFileIO_Type
);
1618 _bufferedwriter_raw_write(buffered
*self
, char *start
, Py_ssize_t len
)
1621 PyObject
*memobj
, *res
;
1623 /* NOTE: the buffer needn't be released as its object is NULL. */
1624 if (PyBuffer_FillInfo(&buf
, NULL
, start
, len
, 1, PyBUF_CONTIG_RO
) == -1)
1626 memobj
= PyMemoryView_FromBuffer(&buf
);
1629 res
= PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_write
, memobj
, NULL
);
1633 n
= PyNumber_AsSsize_t(res
, PyExc_ValueError
);
1635 if (n
< 0 || n
> len
) {
1636 PyErr_Format(PyExc_IOError
,
1637 "raw write() returned invalid length %zd "
1638 "(should have been between 0 and %zd)", n
, len
);
1641 if (n
> 0 && self
->abs_pos
!= -1)
1646 /* `restore_pos` is 1 if we need to restore the raw stream position at
1647 the end, 0 otherwise. */
1649 _bufferedwriter_flush_unlocked(buffered
*self
, int restore_pos
)
1651 Py_ssize_t written
= 0;
1654 if (!VALID_WRITE_BUFFER(self
) || self
->write_pos
== self
->write_end
)
1657 rewind
= RAW_OFFSET(self
) + (self
->pos
- self
->write_pos
);
1659 n
= _buffered_raw_seek(self
, -rewind
, 1);
1663 self
->raw_pos
-= rewind
;
1665 while (self
->write_pos
< self
->write_end
) {
1666 n
= _bufferedwriter_raw_write(self
,
1667 self
->buffer
+ self
->write_pos
,
1668 Py_SAFE_DOWNCAST(self
->write_end
- self
->write_pos
,
1669 Py_off_t
, Py_ssize_t
));
1671 Py_ssize_t
*w
= _buffered_check_blocking_error();
1674 self
->write_pos
+= *w
;
1675 self
->raw_pos
= self
->write_pos
;
1678 /* Already re-raised */
1681 self
->write_pos
+= n
;
1682 self
->raw_pos
= self
->write_pos
;
1683 written
+= Py_SAFE_DOWNCAST(n
, Py_off_t
, Py_ssize_t
);
1687 Py_off_t forward
= rewind
- written
;
1689 n
= _buffered_raw_seek(self
, forward
, 1);
1693 self
->raw_pos
+= forward
;
1696 _bufferedwriter_reset_buf(self
);
1706 bufferedwriter_write(buffered
*self
, PyObject
*args
)
1708 PyObject
*res
= NULL
;
1710 Py_ssize_t written
, avail
, remaining
;
1713 CHECK_INITIALIZED(self
)
1714 if (!PyArg_ParseTuple(args
, "s*:write", &buf
)) {
1718 if (IS_CLOSED(self
)) {
1719 PyErr_SetString(PyExc_ValueError
, "write to closed file");
1720 PyBuffer_Release(&buf
);
1724 ENTER_BUFFERED(self
)
1726 /* Fast path: the data to write can be fully buffered. */
1727 if (!VALID_READ_BUFFER(self
) && !VALID_WRITE_BUFFER(self
)) {
1731 avail
= Py_SAFE_DOWNCAST(self
->buffer_size
- self
->pos
, Py_off_t
, Py_ssize_t
);
1732 if (buf
.len
<= avail
) {
1733 memcpy(self
->buffer
+ self
->pos
, buf
.buf
, buf
.len
);
1734 if (!VALID_WRITE_BUFFER(self
)) {
1735 self
->write_pos
= self
->pos
;
1737 ADJUST_POSITION(self
, self
->pos
+ buf
.len
);
1738 if (self
->pos
> self
->write_end
)
1739 self
->write_end
= self
->pos
;
1744 /* First write the current buffer */
1745 res
= _bufferedwriter_flush_unlocked(self
, 0);
1747 Py_ssize_t
*w
= _buffered_check_blocking_error();
1751 _bufferedreader_reset_buf(self
);
1752 /* Make some place by shifting the buffer. */
1753 assert(VALID_WRITE_BUFFER(self
));
1754 memmove(self
->buffer
, self
->buffer
+ self
->write_pos
,
1755 Py_SAFE_DOWNCAST(self
->write_end
- self
->write_pos
,
1756 Py_off_t
, Py_ssize_t
));
1757 self
->write_end
-= self
->write_pos
;
1758 self
->raw_pos
-= self
->write_pos
;
1759 self
->pos
-= self
->write_pos
;
1760 self
->write_pos
= 0;
1761 avail
= Py_SAFE_DOWNCAST(self
->buffer_size
- self
->write_end
,
1762 Py_off_t
, Py_ssize_t
);
1763 if (buf
.len
<= avail
) {
1764 /* Everything can be buffered */
1766 memcpy(self
->buffer
+ self
->write_end
, buf
.buf
, buf
.len
);
1767 self
->write_end
+= buf
.len
;
1771 /* Buffer as much as possible. */
1772 memcpy(self
->buffer
+ self
->write_end
, buf
.buf
, avail
);
1773 self
->write_end
+= avail
;
1774 /* Already re-raised */
1780 /* Adjust the raw stream position if it is away from the logical stream
1781 position. This happens if the read buffer has been filled but not
1782 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1783 the raw stream by itself).
1786 offset
= RAW_OFFSET(self
);
1788 if (_buffered_raw_seek(self
, -offset
, 1) < 0)
1790 self
->raw_pos
-= offset
;
1793 /* Then write buf itself. At this point the buffer has been emptied. */
1794 remaining
= buf
.len
;
1796 while (remaining
> self
->buffer_size
) {
1797 Py_ssize_t n
= _bufferedwriter_raw_write(
1798 self
, (char *) buf
.buf
+ written
, buf
.len
- written
);
1800 Py_ssize_t
*w
= _buffered_check_blocking_error();
1805 if (remaining
> self
->buffer_size
) {
1806 /* Can't buffer everything, still buffer as much as possible */
1807 memcpy(self
->buffer
,
1808 (char *) buf
.buf
+ written
, self
->buffer_size
);
1810 ADJUST_POSITION(self
, self
->buffer_size
);
1811 self
->write_end
= self
->buffer_size
;
1812 *w
= written
+ self
->buffer_size
;
1813 /* Already re-raised */
1823 _bufferedreader_reset_buf(self
);
1824 if (remaining
> 0) {
1825 memcpy(self
->buffer
, (char *) buf
.buf
+ written
, remaining
);
1826 written
+= remaining
;
1828 self
->write_pos
= 0;
1829 /* TODO: sanity check (remaining >= 0) */
1830 self
->write_end
= remaining
;
1831 ADJUST_POSITION(self
, remaining
);
1835 res
= PyLong_FromSsize_t(written
);
1838 LEAVE_BUFFERED(self
)
1839 PyBuffer_Release(&buf
);
1843 static PyMethodDef bufferedwriter_methods
[] = {
1844 /* BufferedIOMixin methods */
1845 {"close", (PyCFunction
)buffered_close
, METH_NOARGS
},
1846 {"detach", (PyCFunction
)buffered_detach
, METH_NOARGS
},
1847 {"seekable", (PyCFunction
)buffered_seekable
, METH_NOARGS
},
1848 {"readable", (PyCFunction
)buffered_readable
, METH_NOARGS
},
1849 {"writable", (PyCFunction
)buffered_writable
, METH_NOARGS
},
1850 {"fileno", (PyCFunction
)buffered_fileno
, METH_NOARGS
},
1851 {"isatty", (PyCFunction
)buffered_isatty
, METH_NOARGS
},
1853 {"write", (PyCFunction
)bufferedwriter_write
, METH_VARARGS
},
1854 {"truncate", (PyCFunction
)buffered_truncate
, METH_VARARGS
},
1855 {"flush", (PyCFunction
)buffered_flush
, METH_NOARGS
},
1856 {"seek", (PyCFunction
)buffered_seek
, METH_VARARGS
},
1857 {"tell", (PyCFunction
)buffered_tell
, METH_NOARGS
},
1861 static PyMemberDef bufferedwriter_members
[] = {
1862 {"raw", T_OBJECT
, offsetof(buffered
, raw
), 0},
1866 static PyGetSetDef bufferedwriter_getset
[] = {
1867 {"closed", (getter
)buffered_closed_get
, NULL
, NULL
},
1868 {"name", (getter
)buffered_name_get
, NULL
, NULL
},
1869 {"mode", (getter
)buffered_mode_get
, NULL
, NULL
},
1874 PyTypeObject PyBufferedWriter_Type
= {
1875 PyVarObject_HEAD_INIT(NULL
, 0)
1876 "_io.BufferedWriter", /*tp_name*/
1877 sizeof(buffered
), /*tp_basicsize*/
1879 (destructor
)buffered_dealloc
, /*tp_dealloc*/
1884 (reprfunc
)buffered_repr
, /*tp_repr*/
1886 0, /*tp_as_sequence*/
1887 0, /*tp_as_mapping*/
1894 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
1895 | Py_TPFLAGS_HAVE_GC
, /*tp_flags*/
1896 bufferedwriter_doc
, /* tp_doc */
1897 (traverseproc
)buffered_traverse
, /* tp_traverse */
1898 (inquiry
)buffered_clear
, /* tp_clear */
1899 0, /* tp_richcompare */
1900 offsetof(buffered
, weakreflist
), /*tp_weaklistoffset*/
1902 0, /* tp_iternext */
1903 bufferedwriter_methods
, /* tp_methods */
1904 bufferedwriter_members
, /* tp_members */
1905 bufferedwriter_getset
, /* tp_getset */
1908 0, /* tp_descr_get */
1909 0, /* tp_descr_set */
1910 offsetof(buffered
, dict
), /* tp_dictoffset */
1911 (initproc
)bufferedwriter_init
, /* tp_init */
1913 PyType_GenericNew
, /* tp_new */
1922 PyDoc_STRVAR(bufferedrwpair_doc
,
1923 "A buffered reader and writer object together.\n"
1925 "A buffered reader object and buffered writer object put together to\n"
1926 "form a sequential IO object that can read and write. This is typically\n"
1927 "used with a socket or two-way pipe.\n"
1929 "reader and writer are RawIOBase objects that are readable and\n"
1930 "writeable respectively. If the buffer_size is omitted it defaults to\n"
1931 "DEFAULT_BUFFER_SIZE.\n"
1934 /* XXX The usefulness of this (compared to having two separate IO objects) is
1943 PyObject
*weakreflist
;
1947 bufferedrwpair_init(rwpair
*self
, PyObject
*args
, PyObject
*kwds
)
1949 PyObject
*reader
, *writer
;
1950 Py_ssize_t buffer_size
= DEFAULT_BUFFER_SIZE
;
1951 Py_ssize_t max_buffer_size
= -234;
1953 if (!PyArg_ParseTuple(args
, "OO|nn:BufferedRWPair", &reader
, &writer
,
1954 &buffer_size
, &max_buffer_size
)) {
1958 if (max_buffer_size
!= -234 && !complain_about_max_buffer_size())
1961 if (_PyIOBase_check_readable(reader
, Py_True
) == NULL
)
1963 if (_PyIOBase_check_writable(writer
, Py_True
) == NULL
)
1966 self
->reader
= (buffered
*) PyObject_CallFunction(
1967 (PyObject
*) &PyBufferedReader_Type
, "On", reader
, buffer_size
);
1968 if (self
->reader
== NULL
)
1971 self
->writer
= (buffered
*) PyObject_CallFunction(
1972 (PyObject
*) &PyBufferedWriter_Type
, "On", writer
, buffer_size
);
1973 if (self
->writer
== NULL
) {
1974 Py_CLEAR(self
->reader
);
1982 bufferedrwpair_traverse(rwpair
*self
, visitproc visit
, void *arg
)
1984 Py_VISIT(self
->dict
);
1989 bufferedrwpair_clear(rwpair
*self
)
1991 Py_CLEAR(self
->reader
);
1992 Py_CLEAR(self
->writer
);
1993 Py_CLEAR(self
->dict
);
1998 bufferedrwpair_dealloc(rwpair
*self
)
2000 _PyObject_GC_UNTRACK(self
);
2001 Py_CLEAR(self
->reader
);
2002 Py_CLEAR(self
->writer
);
2003 Py_CLEAR(self
->dict
);
2004 Py_TYPE(self
)->tp_free((PyObject
*) self
);
2008 _forward_call(buffered
*self
, const char *name
, PyObject
*args
)
2010 PyObject
*func
= PyObject_GetAttrString((PyObject
*)self
, name
);
2014 PyErr_SetString(PyExc_AttributeError
, name
);
2018 ret
= PyObject_CallObject(func
, args
);
2024 bufferedrwpair_read(rwpair
*self
, PyObject
*args
)
2026 return _forward_call(self
->reader
, "read", args
);
2030 bufferedrwpair_peek(rwpair
*self
, PyObject
*args
)
2032 return _forward_call(self
->reader
, "peek", args
);
2036 bufferedrwpair_read1(rwpair
*self
, PyObject
*args
)
2038 return _forward_call(self
->reader
, "read1", args
);
2042 bufferedrwpair_readinto(rwpair
*self
, PyObject
*args
)
2044 return _forward_call(self
->reader
, "readinto", args
);
2048 bufferedrwpair_write(rwpair
*self
, PyObject
*args
)
2050 return _forward_call(self
->writer
, "write", args
);
2054 bufferedrwpair_flush(rwpair
*self
, PyObject
*args
)
2056 return _forward_call(self
->writer
, "flush", args
);
2060 bufferedrwpair_readable(rwpair
*self
, PyObject
*args
)
2062 return _forward_call(self
->reader
, "readable", args
);
2066 bufferedrwpair_writable(rwpair
*self
, PyObject
*args
)
2068 return _forward_call(self
->writer
, "writable", args
);
2072 bufferedrwpair_close(rwpair
*self
, PyObject
*args
)
2074 PyObject
*ret
= _forward_call(self
->writer
, "close", args
);
2079 return _forward_call(self
->reader
, "close", args
);
2083 bufferedrwpair_isatty(rwpair
*self
, PyObject
*args
)
2085 PyObject
*ret
= _forward_call(self
->writer
, "isatty", args
);
2087 if (ret
!= Py_False
) {
2088 /* either True or exception */
2093 return _forward_call(self
->reader
, "isatty", args
);
2097 bufferedrwpair_closed_get(rwpair
*self
, void *context
)
2099 return PyObject_GetAttr((PyObject
*) self
->writer
, _PyIO_str_closed
);
2102 static PyMethodDef bufferedrwpair_methods
[] = {
2103 {"read", (PyCFunction
)bufferedrwpair_read
, METH_VARARGS
},
2104 {"peek", (PyCFunction
)bufferedrwpair_peek
, METH_VARARGS
},
2105 {"read1", (PyCFunction
)bufferedrwpair_read1
, METH_VARARGS
},
2106 {"readinto", (PyCFunction
)bufferedrwpair_readinto
, METH_VARARGS
},
2108 {"write", (PyCFunction
)bufferedrwpair_write
, METH_VARARGS
},
2109 {"flush", (PyCFunction
)bufferedrwpair_flush
, METH_NOARGS
},
2111 {"readable", (PyCFunction
)bufferedrwpair_readable
, METH_NOARGS
},
2112 {"writable", (PyCFunction
)bufferedrwpair_writable
, METH_NOARGS
},
2114 {"close", (PyCFunction
)bufferedrwpair_close
, METH_NOARGS
},
2115 {"isatty", (PyCFunction
)bufferedrwpair_isatty
, METH_NOARGS
},
2120 static PyGetSetDef bufferedrwpair_getset
[] = {
2121 {"closed", (getter
)bufferedrwpair_closed_get
, NULL
, NULL
},
2125 PyTypeObject PyBufferedRWPair_Type
= {
2126 PyVarObject_HEAD_INIT(NULL
, 0)
2127 "_io.BufferedRWPair", /*tp_name*/
2128 sizeof(rwpair
), /*tp_basicsize*/
2130 (destructor
)bufferedrwpair_dealloc
, /*tp_dealloc*/
2137 0, /*tp_as_sequence*/
2138 0, /*tp_as_mapping*/
2145 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
2146 | Py_TPFLAGS_HAVE_GC
, /* tp_flags */
2147 bufferedrwpair_doc
, /* tp_doc */
2148 (traverseproc
)bufferedrwpair_traverse
, /* tp_traverse */
2149 (inquiry
)bufferedrwpair_clear
, /* tp_clear */
2150 0, /* tp_richcompare */
2151 offsetof(rwpair
, weakreflist
), /*tp_weaklistoffset*/
2153 0, /* tp_iternext */
2154 bufferedrwpair_methods
, /* tp_methods */
2156 bufferedrwpair_getset
, /* tp_getset */
2159 0, /* tp_descr_get */
2160 0, /* tp_descr_set */
2161 offsetof(rwpair
, dict
), /* tp_dictoffset */
2162 (initproc
)bufferedrwpair_init
, /* tp_init */
2164 PyType_GenericNew
, /* tp_new */
2173 PyDoc_STRVAR(bufferedrandom_doc
,
2174 "A buffered interface to random access streams.\n"
2176 "The constructor creates a reader and writer for a seekable stream,\n"
2177 "raw, given in the first argument. If the buffer_size is omitted it\n"
2178 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2182 bufferedrandom_init(buffered
*self
, PyObject
*args
, PyObject
*kwds
)
2184 char *kwlist
[] = {"raw", "buffer_size", "max_buffer_size", NULL
};
2185 Py_ssize_t buffer_size
= DEFAULT_BUFFER_SIZE
;
2186 Py_ssize_t max_buffer_size
= -234;
2192 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "O|nn:BufferedReader", kwlist
,
2193 &raw
, &buffer_size
, &max_buffer_size
)) {
2197 if (max_buffer_size
!= -234 && !complain_about_max_buffer_size())
2200 if (_PyIOBase_check_seekable(raw
, Py_True
) == NULL
)
2202 if (_PyIOBase_check_readable(raw
, Py_True
) == NULL
)
2204 if (_PyIOBase_check_writable(raw
, Py_True
) == NULL
)
2207 Py_CLEAR(self
->raw
);
2210 self
->buffer_size
= buffer_size
;
2214 if (_buffered_init(self
) < 0)
2216 _bufferedreader_reset_buf(self
);
2217 _bufferedwriter_reset_buf(self
);
2220 self
->fast_closed_checks
= (Py_TYPE(self
) == &PyBufferedRandom_Type
&&
2221 Py_TYPE(raw
) == &PyFileIO_Type
);
2227 static PyMethodDef bufferedrandom_methods
[] = {
2228 /* BufferedIOMixin methods */
2229 {"close", (PyCFunction
)buffered_close
, METH_NOARGS
},
2230 {"detach", (PyCFunction
)buffered_detach
, METH_NOARGS
},
2231 {"seekable", (PyCFunction
)buffered_seekable
, METH_NOARGS
},
2232 {"readable", (PyCFunction
)buffered_readable
, METH_NOARGS
},
2233 {"writable", (PyCFunction
)buffered_writable
, METH_NOARGS
},
2234 {"fileno", (PyCFunction
)buffered_fileno
, METH_NOARGS
},
2235 {"isatty", (PyCFunction
)buffered_isatty
, METH_NOARGS
},
2237 {"flush", (PyCFunction
)buffered_flush
, METH_NOARGS
},
2239 {"seek", (PyCFunction
)buffered_seek
, METH_VARARGS
},
2240 {"tell", (PyCFunction
)buffered_tell
, METH_NOARGS
},
2241 {"truncate", (PyCFunction
)buffered_truncate
, METH_VARARGS
},
2242 {"read", (PyCFunction
)buffered_read
, METH_VARARGS
},
2243 {"read1", (PyCFunction
)buffered_read1
, METH_VARARGS
},
2244 {"readinto", (PyCFunction
)buffered_readinto
, METH_VARARGS
},
2245 {"readline", (PyCFunction
)buffered_readline
, METH_VARARGS
},
2246 {"peek", (PyCFunction
)buffered_peek
, METH_VARARGS
},
2247 {"write", (PyCFunction
)bufferedwriter_write
, METH_VARARGS
},
2251 static PyMemberDef bufferedrandom_members
[] = {
2252 {"raw", T_OBJECT
, offsetof(buffered
, raw
), 0},
2256 static PyGetSetDef bufferedrandom_getset
[] = {
2257 {"closed", (getter
)buffered_closed_get
, NULL
, NULL
},
2258 {"name", (getter
)buffered_name_get
, NULL
, NULL
},
2259 {"mode", (getter
)buffered_mode_get
, NULL
, NULL
},
2264 PyTypeObject PyBufferedRandom_Type
= {
2265 PyVarObject_HEAD_INIT(NULL
, 0)
2266 "_io.BufferedRandom", /*tp_name*/
2267 sizeof(buffered
), /*tp_basicsize*/
2269 (destructor
)buffered_dealloc
, /*tp_dealloc*/
2274 (reprfunc
)buffered_repr
, /*tp_repr*/
2276 0, /*tp_as_sequence*/
2277 0, /*tp_as_mapping*/
2284 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
2285 | Py_TPFLAGS_HAVE_GC
, /*tp_flags*/
2286 bufferedrandom_doc
, /* tp_doc */
2287 (traverseproc
)buffered_traverse
, /* tp_traverse */
2288 (inquiry
)buffered_clear
, /* tp_clear */
2289 0, /* tp_richcompare */
2290 offsetof(buffered
, weakreflist
), /*tp_weaklistoffset*/
2292 (iternextfunc
)buffered_iternext
, /* tp_iternext */
2293 bufferedrandom_methods
, /* tp_methods */
2294 bufferedrandom_members
, /* tp_members */
2295 bufferedrandom_getset
, /* tp_getset */
2298 0, /* tp_descr_get */
2299 0, /* tp_descr_set */
2300 offsetof(buffered
, dict
), /*tp_dictoffset*/
2301 (initproc
)bufferedrandom_init
, /* tp_init */
2303 PyType_GenericNew
, /* tp_new */