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 %" PY_PRIdOFF
,
594 _buffered_raw_seek(buffered
*self
, Py_off_t target
, int whence
)
596 PyObject
*res
, *posobj
, *whenceobj
;
599 posobj
= PyLong_FromOff_t(target
);
602 whenceobj
= PyLong_FromLong(whence
);
603 if (whenceobj
== NULL
) {
607 res
= PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_seek
,
608 posobj
, whenceobj
, NULL
);
610 Py_DECREF(whenceobj
);
613 n
= PyNumber_AsOff_t(res
, PyExc_ValueError
);
616 if (!PyErr_Occurred())
617 PyErr_Format(PyExc_IOError
,
618 "Raw stream returned invalid position %" PY_PRIdOFF
,
627 _buffered_init(buffered
*self
)
630 if (self
->buffer_size
<= 0) {
631 PyErr_SetString(PyExc_ValueError
,
632 "buffer size must be strictly positive");
636 PyMem_Free(self
->buffer
);
637 self
->buffer
= PyMem_Malloc(self
->buffer_size
);
638 if (self
->buffer
== NULL
) {
643 self
->lock
= PyThread_allocate_lock();
644 if (self
->lock
== NULL
) {
645 PyErr_SetString(PyExc_RuntimeError
, "can't allocate read lock");
649 /* Find out whether buffer_size is a power of 2 */
650 /* XXX is this optimization useful? */
651 for (n
= self
->buffer_size
- 1; n
& 1; n
>>= 1)
654 self
->buffer_mask
= self
->buffer_size
- 1;
656 self
->buffer_mask
= 0;
657 if (_buffered_raw_tell(self
) == -1)
663 * Shared methods and wrappers
667 buffered_flush(buffered
*self
, PyObject
*args
)
671 CHECK_INITIALIZED(self
)
672 CHECK_CLOSED(self
, "flush of closed file")
675 res
= _bufferedwriter_flush_unlocked(self
, 0);
676 if (res
!= NULL
&& self
->readable
) {
677 /* Rewind the raw stream so that its position corresponds to
678 the current logical position. */
680 n
= _buffered_raw_seek(self
, -RAW_OFFSET(self
), 1);
683 _bufferedreader_reset_buf(self
);
691 buffered_peek(buffered
*self
, PyObject
*args
)
694 PyObject
*res
= NULL
;
696 CHECK_INITIALIZED(self
)
697 if (!PyArg_ParseTuple(args
, "|n:peek", &n
)) {
703 if (self
->writable
) {
704 res
= _bufferedwriter_flush_unlocked(self
, 1);
709 res
= _bufferedreader_peek_unlocked(self
, n
);
717 buffered_read(buffered
*self
, PyObject
*args
)
722 CHECK_INITIALIZED(self
)
723 if (!PyArg_ParseTuple(args
, "|n:read", &n
)) {
727 PyErr_SetString(PyExc_ValueError
,
728 "read length must be positive or -1");
732 CHECK_CLOSED(self
, "read of closed file")
735 /* The number of bytes is unspecified, read until the end of stream */
737 res
= _bufferedreader_read_all(self
);
741 res
= _bufferedreader_read_fast(self
, n
);
742 if (res
== Py_None
) {
745 res
= _bufferedreader_read_generic(self
, n
);
754 buffered_read1(buffered
*self
, PyObject
*args
)
756 Py_ssize_t n
, have
, r
;
757 PyObject
*res
= NULL
;
759 CHECK_INITIALIZED(self
)
760 if (!PyArg_ParseTuple(args
, "n:read1", &n
)) {
765 PyErr_SetString(PyExc_ValueError
,
766 "read length must be positive");
770 return PyBytes_FromStringAndSize(NULL
, 0);
774 if (self
->writable
) {
775 res
= _bufferedwriter_flush_unlocked(self
, 1);
781 /* Return up to n bytes. If at least one byte is buffered, we
782 only return buffered bytes. Otherwise, we do one raw read. */
784 /* XXX: this mimicks the io.py implementation but is probably wrong.
785 If we need to read from the raw stream, then we could actually read
786 all `n` bytes asked by the caller (and possibly more, so as to fill
787 our buffer for the next reads). */
789 have
= Py_SAFE_DOWNCAST(READAHEAD(self
), Py_off_t
, Py_ssize_t
);
793 res
= PyBytes_FromStringAndSize(self
->buffer
+ self
->pos
, n
);
800 /* Fill the buffer from the raw stream, and copy it to the result. */
801 _bufferedreader_reset_buf(self
);
802 r
= _bufferedreader_fill_buffer(self
);
809 res
= PyBytes_FromStringAndSize(self
->buffer
, n
);
820 buffered_readinto(buffered
*self
, PyObject
*args
)
822 PyObject
*res
= NULL
;
824 CHECK_INITIALIZED(self
)
826 /* TODO: use raw.readinto() instead! */
827 if (self
->writable
) {
829 res
= _bufferedwriter_flush_unlocked(self
, 0);
835 res
= bufferediobase_readinto((PyObject
*)self
, args
);
842 _buffered_readline(buffered
*self
, Py_ssize_t limit
)
844 PyObject
*res
= NULL
;
845 PyObject
*chunks
= NULL
;
846 Py_ssize_t n
, written
= 0;
847 const char *start
, *s
, *end
;
849 CHECK_CLOSED(self
, "readline of closed file")
851 /* First, try to find a line in the buffer. This can run unlocked because
852 the calls to the C API are simple enough that they can't trigger
853 any thread switch. */
854 n
= Py_SAFE_DOWNCAST(READAHEAD(self
), Py_off_t
, Py_ssize_t
);
855 if (limit
>= 0 && n
> limit
)
857 start
= self
->buffer
+ self
->pos
;
858 s
= memchr(start
, '\n', n
);
860 res
= PyBytes_FromStringAndSize(start
, s
- start
+ 1);
862 self
->pos
+= s
- start
+ 1;
866 res
= PyBytes_FromStringAndSize(start
, n
);
874 /* Now we try to get some more from the raw stream */
875 if (self
->writable
) {
876 res
= _bufferedwriter_flush_unlocked(self
, 1);
881 chunks
= PyList_New(0);
885 res
= PyBytes_FromStringAndSize(start
, n
);
888 if (PyList_Append(chunks
, res
) < 0) {
899 _bufferedreader_reset_buf(self
);
900 n
= _bufferedreader_fill_buffer(self
);
905 if (limit
>= 0 && n
> limit
)
907 start
= self
->buffer
;
912 res
= PyBytes_FromStringAndSize(start
, s
- start
);
915 self
->pos
= s
- start
;
919 res
= PyBytes_FromStringAndSize(start
, n
);
926 if (PyList_Append(chunks
, res
) < 0) {
936 if (res
!= NULL
&& PyList_Append(chunks
, res
) < 0) {
941 res
= _PyBytes_Join(_PyIO_empty_bytes
, chunks
);
951 buffered_readline(buffered
*self
, PyObject
*args
)
953 PyObject
*limitobj
= NULL
;
954 Py_ssize_t limit
= -1;
956 CHECK_INITIALIZED(self
)
958 if (!PyArg_ParseTuple(args
, "|O:readline", &limitobj
)) {
962 if (!PyNumber_Check(limitobj
)) {
963 PyErr_Format(PyExc_TypeError
,
964 "integer argument expected, got '%.200s'",
965 Py_TYPE(limitobj
)->tp_name
);
968 limit
= PyNumber_AsSsize_t(limitobj
, PyExc_OverflowError
);
969 if (limit
== -1 && PyErr_Occurred())
972 return _buffered_readline(self
, limit
);
977 buffered_tell(buffered
*self
, PyObject
*args
)
981 CHECK_INITIALIZED(self
)
982 pos
= _buffered_raw_tell(self
);
985 pos
-= RAW_OFFSET(self
);
986 /* TODO: sanity check (pos >= 0) */
987 return PyLong_FromOff_t(pos
);
991 buffered_seek(buffered
*self
, PyObject
*args
)
995 PyObject
*targetobj
, *res
= NULL
;
997 CHECK_INITIALIZED(self
)
998 if (!PyArg_ParseTuple(args
, "O|i:seek", &targetobj
, &whence
)) {
1001 if (whence
< 0 || whence
> 2) {
1002 PyErr_Format(PyExc_ValueError
,
1003 "whence must be between 0 and 2, not %d", whence
);
1007 CHECK_CLOSED(self
, "seek of closed file")
1009 target
= PyNumber_AsOff_t(targetobj
, PyExc_ValueError
);
1010 if (target
== -1 && PyErr_Occurred())
1013 if (whence
!= 2 && self
->readable
) {
1014 Py_off_t current
, avail
;
1015 /* Check if seeking leaves us inside the current buffer,
1016 so as to return quickly if possible. Also, we needn't take the
1017 lock in this fast path.
1018 Don't know how to do that when whence == 2, though. */
1019 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1020 state at this point. */
1021 current
= RAW_TELL(self
);
1022 avail
= READAHEAD(self
);
1026 offset
= target
- (current
- RAW_OFFSET(self
));
1029 if (offset
>= -self
->pos
&& offset
<= avail
) {
1030 self
->pos
+= offset
;
1031 return PyLong_FromOff_t(current
- avail
+ offset
);
1036 ENTER_BUFFERED(self
)
1038 /* Fallback: invoke raw seek() method and clear buffer */
1039 if (self
->writable
) {
1040 res
= _bufferedwriter_flush_unlocked(self
, 0);
1044 _bufferedwriter_reset_buf(self
);
1047 /* TODO: align on block boundary and read buffer if needed? */
1049 target
-= RAW_OFFSET(self
);
1050 n
= _buffered_raw_seek(self
, target
, whence
);
1054 res
= PyLong_FromOff_t(n
);
1055 if (res
!= NULL
&& self
->readable
)
1056 _bufferedreader_reset_buf(self
);
1059 LEAVE_BUFFERED(self
)
1064 buffered_truncate(buffered
*self
, PyObject
*args
)
1066 PyObject
*pos
= Py_None
;
1067 PyObject
*res
= NULL
;
1069 CHECK_INITIALIZED(self
)
1070 if (!PyArg_ParseTuple(args
, "|O:truncate", &pos
)) {
1074 ENTER_BUFFERED(self
)
1076 if (self
->writable
) {
1077 res
= _bufferedwriter_flush_unlocked(self
, 0);
1082 if (self
->readable
) {
1083 if (pos
== Py_None
) {
1084 /* Rewind the raw stream so that its position corresponds to
1085 the current logical position. */
1086 if (_buffered_raw_seek(self
, -RAW_OFFSET(self
), 1) == -1)
1089 _bufferedreader_reset_buf(self
);
1091 res
= PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_truncate
, pos
, NULL
);
1094 /* Reset cached position */
1095 if (_buffered_raw_tell(self
) == -1)
1099 LEAVE_BUFFERED(self
)
1104 buffered_iternext(buffered
*self
)
1109 CHECK_INITIALIZED(self
);
1112 if (tp
== &PyBufferedReader_Type
||
1113 tp
== &PyBufferedRandom_Type
) {
1114 /* Skip method call overhead for speed */
1115 line
= _buffered_readline(self
, -1);
1118 line
= PyObject_CallMethodObjArgs((PyObject
*)self
,
1119 _PyIO_str_readline
, NULL
);
1120 if (line
&& !PyBytes_Check(line
)) {
1121 PyErr_Format(PyExc_IOError
,
1122 "readline() should have returned a bytes object, "
1123 "not '%.200s'", Py_TYPE(line
)->tp_name
);
1132 if (PyBytes_GET_SIZE(line
) == 0) {
1133 /* Reached EOF or would have blocked */
1142 buffered_repr(buffered
*self
)
1144 PyObject
*nameobj
, *res
;
1146 nameobj
= PyObject_GetAttrString((PyObject
*) self
, "name");
1147 if (nameobj
== NULL
) {
1148 if (PyErr_ExceptionMatches(PyExc_AttributeError
))
1152 res
= PyString_FromFormat("<%s>", Py_TYPE(self
)->tp_name
);
1155 PyObject
*repr
= PyObject_Repr(nameobj
);
1159 res
= PyString_FromFormat("<%s name=%s>",
1160 Py_TYPE(self
)->tp_name
,
1161 PyString_AS_STRING(repr
));
1168 * class BufferedReader
1171 PyDoc_STRVAR(bufferedreader_doc
,
1172 "Create a new buffered reader using the given readable raw IO object.");
1174 static void _bufferedreader_reset_buf(buffered
*self
)
1176 self
->read_end
= -1;
1180 bufferedreader_init(buffered
*self
, PyObject
*args
, PyObject
*kwds
)
1182 char *kwlist
[] = {"raw", "buffer_size", NULL
};
1183 Py_ssize_t buffer_size
= DEFAULT_BUFFER_SIZE
;
1189 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "O|n:BufferedReader", kwlist
,
1190 &raw
, &buffer_size
)) {
1194 if (_PyIOBase_check_readable(raw
, Py_True
) == NULL
)
1197 Py_CLEAR(self
->raw
);
1200 self
->buffer_size
= buffer_size
;
1204 if (_buffered_init(self
) < 0)
1206 _bufferedreader_reset_buf(self
);
1208 self
->fast_closed_checks
= (Py_TYPE(self
) == &PyBufferedReader_Type
&&
1209 Py_TYPE(raw
) == &PyFileIO_Type
);
1216 _bufferedreader_raw_read(buffered
*self
, char *start
, Py_ssize_t len
)
1219 PyObject
*memobj
, *res
;
1221 /* NOTE: the buffer needn't be released as its object is NULL. */
1222 if (PyBuffer_FillInfo(&buf
, NULL
, start
, len
, 0, PyBUF_CONTIG
) == -1)
1224 memobj
= PyMemoryView_FromBuffer(&buf
);
1227 res
= PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_readinto
, memobj
, NULL
);
1231 if (res
== Py_None
) {
1232 /* Non-blocking stream would have blocked. Special return code! */
1236 n
= PyNumber_AsSsize_t(res
, PyExc_ValueError
);
1238 if (n
< 0 || n
> len
) {
1239 PyErr_Format(PyExc_IOError
,
1240 "raw readinto() returned invalid length %zd "
1241 "(should have been between 0 and %zd)", n
, len
);
1244 if (n
> 0 && self
->abs_pos
!= -1)
1250 _bufferedreader_fill_buffer(buffered
*self
)
1252 Py_ssize_t start
, len
, n
;
1253 if (VALID_READ_BUFFER(self
))
1254 start
= Py_SAFE_DOWNCAST(self
->read_end
, Py_off_t
, Py_ssize_t
);
1257 len
= self
->buffer_size
- start
;
1258 n
= _bufferedreader_raw_read(self
, self
->buffer
+ start
, len
);
1261 self
->read_end
= start
+ n
;
1262 self
->raw_pos
= start
+ n
;
1267 _bufferedreader_read_all(buffered
*self
)
1269 Py_ssize_t current_size
;
1270 PyObject
*res
, *data
= NULL
;
1271 PyObject
*chunks
= PyList_New(0);
1276 /* First copy what we have in the current buffer. */
1277 current_size
= Py_SAFE_DOWNCAST(READAHEAD(self
), Py_off_t
, Py_ssize_t
);
1279 data
= PyBytes_FromStringAndSize(
1280 self
->buffer
+ self
->pos
, current_size
);
1286 _bufferedreader_reset_buf(self
);
1287 /* We're going past the buffer's bounds, flush it */
1288 if (self
->writable
) {
1289 res
= _bufferedwriter_flush_unlocked(self
, 1);
1298 if (PyList_Append(chunks
, data
) < 0) {
1306 /* Read until EOF or until read() would block. */
1307 data
= PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_read
, NULL
);
1312 if (data
!= Py_None
&& !PyBytes_Check(data
)) {
1315 PyErr_SetString(PyExc_TypeError
, "read() should return bytes");
1318 if (data
== Py_None
|| PyBytes_GET_SIZE(data
) == 0) {
1319 if (current_size
== 0) {
1324 res
= _PyBytes_Join(_PyIO_empty_bytes
, chunks
);
1330 current_size
+= PyBytes_GET_SIZE(data
);
1331 if (self
->abs_pos
!= -1)
1332 self
->abs_pos
+= PyBytes_GET_SIZE(data
);
1336 /* Read n bytes from the buffer if it can, otherwise return None.
1337 This function is simple enough that it can run unlocked. */
1339 _bufferedreader_read_fast(buffered
*self
, Py_ssize_t n
)
1341 Py_ssize_t current_size
;
1343 current_size
= Py_SAFE_DOWNCAST(READAHEAD(self
), Py_off_t
, Py_ssize_t
);
1344 if (n
<= current_size
) {
1345 /* Fast path: the data to read is fully buffered. */
1346 PyObject
*res
= PyBytes_FromStringAndSize(self
->buffer
+ self
->pos
, n
);
1354 /* Generic read function: read from the stream until enough bytes are read,
1355 * or until an EOF occurs or until read() would block.
1358 _bufferedreader_read_generic(buffered
*self
, Py_ssize_t n
)
1360 PyObject
*res
= NULL
;
1361 Py_ssize_t current_size
, remaining
, written
;
1364 current_size
= Py_SAFE_DOWNCAST(READAHEAD(self
), Py_off_t
, Py_ssize_t
);
1365 if (n
<= current_size
)
1366 return _bufferedreader_read_fast(self
, n
);
1368 res
= PyBytes_FromStringAndSize(NULL
, n
);
1371 out
= PyBytes_AS_STRING(res
);
1374 if (current_size
> 0) {
1375 memcpy(out
, self
->buffer
+ self
->pos
, current_size
);
1376 remaining
-= current_size
;
1377 written
+= current_size
;
1379 _bufferedreader_reset_buf(self
);
1380 while (remaining
> 0) {
1381 /* We want to read a whole block at the end into buffer.
1382 If we had readv() we could do this in one pass. */
1383 Py_ssize_t r
= MINUS_LAST_BLOCK(self
, remaining
);
1386 r
= _bufferedreader_raw_read(self
, out
+ written
, r
);
1389 if (r
== 0 || r
== -2) {
1390 /* EOF occurred or read() would block. */
1391 if (r
== 0 || written
> 0) {
1392 if (_PyBytes_Resize(&res
, written
))
1403 assert(remaining
<= self
->buffer_size
);
1407 while (self
->read_end
< self
->buffer_size
) {
1408 Py_ssize_t r
= _bufferedreader_fill_buffer(self
);
1411 if (r
== 0 || r
== -2) {
1412 /* EOF occurred or read() would block. */
1413 if (r
== 0 || written
> 0) {
1414 if (_PyBytes_Resize(&res
, written
))
1422 if (remaining
> r
) {
1423 memcpy(out
+ written
, self
->buffer
+ self
->pos
, r
);
1428 else if (remaining
> 0) {
1429 memcpy(out
+ written
, self
->buffer
+ self
->pos
, remaining
);
1430 written
+= remaining
;
1431 self
->pos
+= remaining
;
1446 _bufferedreader_peek_unlocked(buffered
*self
, Py_ssize_t n
)
1450 have
= Py_SAFE_DOWNCAST(READAHEAD(self
), Py_off_t
, Py_ssize_t
);
1452 1. we don't want to advance the file position.
1453 2. we don't want to lose block alignment, so we can't shift the buffer
1455 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1458 return PyBytes_FromStringAndSize(self
->buffer
+ self
->pos
, have
);
1461 /* Fill the buffer from the raw stream, and copy it to the result. */
1462 _bufferedreader_reset_buf(self
);
1463 r
= _bufferedreader_fill_buffer(self
);
1469 return PyBytes_FromStringAndSize(self
->buffer
, r
);
1472 static PyMethodDef bufferedreader_methods
[] = {
1473 /* BufferedIOMixin methods */
1474 {"detach", (PyCFunction
)buffered_detach
, METH_NOARGS
},
1475 {"flush", (PyCFunction
)buffered_simple_flush
, METH_NOARGS
},
1476 {"close", (PyCFunction
)buffered_close
, METH_NOARGS
},
1477 {"seekable", (PyCFunction
)buffered_seekable
, METH_NOARGS
},
1478 {"readable", (PyCFunction
)buffered_readable
, METH_NOARGS
},
1479 {"writable", (PyCFunction
)buffered_writable
, METH_NOARGS
},
1480 {"fileno", (PyCFunction
)buffered_fileno
, METH_NOARGS
},
1481 {"isatty", (PyCFunction
)buffered_isatty
, METH_NOARGS
},
1483 {"read", (PyCFunction
)buffered_read
, METH_VARARGS
},
1484 {"peek", (PyCFunction
)buffered_peek
, METH_VARARGS
},
1485 {"read1", (PyCFunction
)buffered_read1
, METH_VARARGS
},
1486 {"readline", (PyCFunction
)buffered_readline
, METH_VARARGS
},
1487 {"seek", (PyCFunction
)buffered_seek
, METH_VARARGS
},
1488 {"tell", (PyCFunction
)buffered_tell
, METH_NOARGS
},
1489 {"truncate", (PyCFunction
)buffered_truncate
, METH_VARARGS
},
1493 static PyMemberDef bufferedreader_members
[] = {
1494 {"raw", T_OBJECT
, offsetof(buffered
, raw
), 0},
1498 static PyGetSetDef bufferedreader_getset
[] = {
1499 {"closed", (getter
)buffered_closed_get
, NULL
, NULL
},
1500 {"name", (getter
)buffered_name_get
, NULL
, NULL
},
1501 {"mode", (getter
)buffered_mode_get
, NULL
, NULL
},
1506 PyTypeObject PyBufferedReader_Type
= {
1507 PyVarObject_HEAD_INIT(NULL
, 0)
1508 "_io.BufferedReader", /*tp_name*/
1509 sizeof(buffered
), /*tp_basicsize*/
1511 (destructor
)buffered_dealloc
, /*tp_dealloc*/
1516 (reprfunc
)buffered_repr
, /*tp_repr*/
1518 0, /*tp_as_sequence*/
1519 0, /*tp_as_mapping*/
1526 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
1527 | Py_TPFLAGS_HAVE_GC
, /*tp_flags*/
1528 bufferedreader_doc
, /* tp_doc */
1529 (traverseproc
)buffered_traverse
, /* tp_traverse */
1530 (inquiry
)buffered_clear
, /* tp_clear */
1531 0, /* tp_richcompare */
1532 offsetof(buffered
, weakreflist
), /*tp_weaklistoffset*/
1534 (iternextfunc
)buffered_iternext
, /* tp_iternext */
1535 bufferedreader_methods
, /* tp_methods */
1536 bufferedreader_members
, /* tp_members */
1537 bufferedreader_getset
, /* tp_getset */
1540 0, /* tp_descr_get */
1541 0, /* tp_descr_set */
1542 offsetof(buffered
, dict
), /* tp_dictoffset */
1543 (initproc
)bufferedreader_init
, /* tp_init */
1545 PyType_GenericNew
, /* tp_new */
1551 complain_about_max_buffer_size(void)
1553 if (PyErr_WarnEx(PyExc_DeprecationWarning
,
1554 "max_buffer_size is deprecated", 1) < 0)
1560 * class BufferedWriter
1562 PyDoc_STRVAR(bufferedwriter_doc
,
1563 "A buffer for a writeable sequential RawIO object.\n"
1565 "The constructor creates a BufferedWriter for the given writeable raw\n"
1566 "stream. If the buffer_size is not given, it defaults to\n"
1567 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1571 _bufferedwriter_reset_buf(buffered
*self
)
1573 self
->write_pos
= 0;
1574 self
->write_end
= -1;
1578 bufferedwriter_init(buffered
*self
, PyObject
*args
, PyObject
*kwds
)
1580 /* TODO: properly deprecate max_buffer_size */
1581 char *kwlist
[] = {"raw", "buffer_size", "max_buffer_size", NULL
};
1582 Py_ssize_t buffer_size
= DEFAULT_BUFFER_SIZE
;
1583 Py_ssize_t max_buffer_size
= -234;
1589 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "O|nn:BufferedReader", kwlist
,
1590 &raw
, &buffer_size
, &max_buffer_size
)) {
1594 if (max_buffer_size
!= -234 && !complain_about_max_buffer_size())
1597 if (_PyIOBase_check_writable(raw
, Py_True
) == NULL
)
1600 Py_CLEAR(self
->raw
);
1606 self
->buffer_size
= buffer_size
;
1607 if (_buffered_init(self
) < 0)
1609 _bufferedwriter_reset_buf(self
);
1612 self
->fast_closed_checks
= (Py_TYPE(self
) == &PyBufferedWriter_Type
&&
1613 Py_TYPE(raw
) == &PyFileIO_Type
);
1620 _bufferedwriter_raw_write(buffered
*self
, char *start
, Py_ssize_t len
)
1623 PyObject
*memobj
, *res
;
1625 /* NOTE: the buffer needn't be released as its object is NULL. */
1626 if (PyBuffer_FillInfo(&buf
, NULL
, start
, len
, 1, PyBUF_CONTIG_RO
) == -1)
1628 memobj
= PyMemoryView_FromBuffer(&buf
);
1631 res
= PyObject_CallMethodObjArgs(self
->raw
, _PyIO_str_write
, memobj
, NULL
);
1635 n
= PyNumber_AsSsize_t(res
, PyExc_ValueError
);
1637 if (n
< 0 || n
> len
) {
1638 PyErr_Format(PyExc_IOError
,
1639 "raw write() returned invalid length %zd "
1640 "(should have been between 0 and %zd)", n
, len
);
1643 if (n
> 0 && self
->abs_pos
!= -1)
1648 /* `restore_pos` is 1 if we need to restore the raw stream position at
1649 the end, 0 otherwise. */
1651 _bufferedwriter_flush_unlocked(buffered
*self
, int restore_pos
)
1653 Py_ssize_t written
= 0;
1656 if (!VALID_WRITE_BUFFER(self
) || self
->write_pos
== self
->write_end
)
1659 rewind
= RAW_OFFSET(self
) + (self
->pos
- self
->write_pos
);
1661 n
= _buffered_raw_seek(self
, -rewind
, 1);
1665 self
->raw_pos
-= rewind
;
1667 while (self
->write_pos
< self
->write_end
) {
1668 n
= _bufferedwriter_raw_write(self
,
1669 self
->buffer
+ self
->write_pos
,
1670 Py_SAFE_DOWNCAST(self
->write_end
- self
->write_pos
,
1671 Py_off_t
, Py_ssize_t
));
1673 Py_ssize_t
*w
= _buffered_check_blocking_error();
1676 self
->write_pos
+= *w
;
1677 self
->raw_pos
= self
->write_pos
;
1680 /* Already re-raised */
1683 self
->write_pos
+= n
;
1684 self
->raw_pos
= self
->write_pos
;
1685 written
+= Py_SAFE_DOWNCAST(n
, Py_off_t
, Py_ssize_t
);
1689 Py_off_t forward
= rewind
- written
;
1691 n
= _buffered_raw_seek(self
, forward
, 1);
1695 self
->raw_pos
+= forward
;
1698 _bufferedwriter_reset_buf(self
);
1708 bufferedwriter_write(buffered
*self
, PyObject
*args
)
1710 PyObject
*res
= NULL
;
1712 Py_ssize_t written
, avail
, remaining
;
1715 CHECK_INITIALIZED(self
)
1716 if (!PyArg_ParseTuple(args
, "s*:write", &buf
)) {
1720 if (IS_CLOSED(self
)) {
1721 PyErr_SetString(PyExc_ValueError
, "write to closed file");
1722 PyBuffer_Release(&buf
);
1726 ENTER_BUFFERED(self
)
1728 /* Fast path: the data to write can be fully buffered. */
1729 if (!VALID_READ_BUFFER(self
) && !VALID_WRITE_BUFFER(self
)) {
1733 avail
= Py_SAFE_DOWNCAST(self
->buffer_size
- self
->pos
, Py_off_t
, Py_ssize_t
);
1734 if (buf
.len
<= avail
) {
1735 memcpy(self
->buffer
+ self
->pos
, buf
.buf
, buf
.len
);
1736 if (!VALID_WRITE_BUFFER(self
)) {
1737 self
->write_pos
= self
->pos
;
1739 ADJUST_POSITION(self
, self
->pos
+ buf
.len
);
1740 if (self
->pos
> self
->write_end
)
1741 self
->write_end
= self
->pos
;
1746 /* First write the current buffer */
1747 res
= _bufferedwriter_flush_unlocked(self
, 0);
1749 Py_ssize_t
*w
= _buffered_check_blocking_error();
1753 _bufferedreader_reset_buf(self
);
1754 /* Make some place by shifting the buffer. */
1755 assert(VALID_WRITE_BUFFER(self
));
1756 memmove(self
->buffer
, self
->buffer
+ self
->write_pos
,
1757 Py_SAFE_DOWNCAST(self
->write_end
- self
->write_pos
,
1758 Py_off_t
, Py_ssize_t
));
1759 self
->write_end
-= self
->write_pos
;
1760 self
->raw_pos
-= self
->write_pos
;
1761 self
->pos
-= self
->write_pos
;
1762 self
->write_pos
= 0;
1763 avail
= Py_SAFE_DOWNCAST(self
->buffer_size
- self
->write_end
,
1764 Py_off_t
, Py_ssize_t
);
1765 if (buf
.len
<= avail
) {
1766 /* Everything can be buffered */
1768 memcpy(self
->buffer
+ self
->write_end
, buf
.buf
, buf
.len
);
1769 self
->write_end
+= buf
.len
;
1773 /* Buffer as much as possible. */
1774 memcpy(self
->buffer
+ self
->write_end
, buf
.buf
, avail
);
1775 self
->write_end
+= avail
;
1776 /* Already re-raised */
1782 /* Adjust the raw stream position if it is away from the logical stream
1783 position. This happens if the read buffer has been filled but not
1784 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1785 the raw stream by itself).
1788 offset
= RAW_OFFSET(self
);
1790 if (_buffered_raw_seek(self
, -offset
, 1) < 0)
1792 self
->raw_pos
-= offset
;
1795 /* Then write buf itself. At this point the buffer has been emptied. */
1796 remaining
= buf
.len
;
1798 while (remaining
> self
->buffer_size
) {
1799 Py_ssize_t n
= _bufferedwriter_raw_write(
1800 self
, (char *) buf
.buf
+ written
, buf
.len
- written
);
1802 Py_ssize_t
*w
= _buffered_check_blocking_error();
1807 if (remaining
> self
->buffer_size
) {
1808 /* Can't buffer everything, still buffer as much as possible */
1809 memcpy(self
->buffer
,
1810 (char *) buf
.buf
+ written
, self
->buffer_size
);
1812 ADJUST_POSITION(self
, self
->buffer_size
);
1813 self
->write_end
= self
->buffer_size
;
1814 *w
= written
+ self
->buffer_size
;
1815 /* Already re-raised */
1825 _bufferedreader_reset_buf(self
);
1826 if (remaining
> 0) {
1827 memcpy(self
->buffer
, (char *) buf
.buf
+ written
, remaining
);
1828 written
+= remaining
;
1830 self
->write_pos
= 0;
1831 /* TODO: sanity check (remaining >= 0) */
1832 self
->write_end
= remaining
;
1833 ADJUST_POSITION(self
, remaining
);
1837 res
= PyLong_FromSsize_t(written
);
1840 LEAVE_BUFFERED(self
)
1841 PyBuffer_Release(&buf
);
1845 static PyMethodDef bufferedwriter_methods
[] = {
1846 /* BufferedIOMixin methods */
1847 {"close", (PyCFunction
)buffered_close
, METH_NOARGS
},
1848 {"detach", (PyCFunction
)buffered_detach
, METH_NOARGS
},
1849 {"seekable", (PyCFunction
)buffered_seekable
, METH_NOARGS
},
1850 {"readable", (PyCFunction
)buffered_readable
, METH_NOARGS
},
1851 {"writable", (PyCFunction
)buffered_writable
, METH_NOARGS
},
1852 {"fileno", (PyCFunction
)buffered_fileno
, METH_NOARGS
},
1853 {"isatty", (PyCFunction
)buffered_isatty
, METH_NOARGS
},
1855 {"write", (PyCFunction
)bufferedwriter_write
, METH_VARARGS
},
1856 {"truncate", (PyCFunction
)buffered_truncate
, METH_VARARGS
},
1857 {"flush", (PyCFunction
)buffered_flush
, METH_NOARGS
},
1858 {"seek", (PyCFunction
)buffered_seek
, METH_VARARGS
},
1859 {"tell", (PyCFunction
)buffered_tell
, METH_NOARGS
},
1863 static PyMemberDef bufferedwriter_members
[] = {
1864 {"raw", T_OBJECT
, offsetof(buffered
, raw
), 0},
1868 static PyGetSetDef bufferedwriter_getset
[] = {
1869 {"closed", (getter
)buffered_closed_get
, NULL
, NULL
},
1870 {"name", (getter
)buffered_name_get
, NULL
, NULL
},
1871 {"mode", (getter
)buffered_mode_get
, NULL
, NULL
},
1876 PyTypeObject PyBufferedWriter_Type
= {
1877 PyVarObject_HEAD_INIT(NULL
, 0)
1878 "_io.BufferedWriter", /*tp_name*/
1879 sizeof(buffered
), /*tp_basicsize*/
1881 (destructor
)buffered_dealloc
, /*tp_dealloc*/
1886 (reprfunc
)buffered_repr
, /*tp_repr*/
1888 0, /*tp_as_sequence*/
1889 0, /*tp_as_mapping*/
1896 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
1897 | Py_TPFLAGS_HAVE_GC
, /*tp_flags*/
1898 bufferedwriter_doc
, /* tp_doc */
1899 (traverseproc
)buffered_traverse
, /* tp_traverse */
1900 (inquiry
)buffered_clear
, /* tp_clear */
1901 0, /* tp_richcompare */
1902 offsetof(buffered
, weakreflist
), /*tp_weaklistoffset*/
1904 0, /* tp_iternext */
1905 bufferedwriter_methods
, /* tp_methods */
1906 bufferedwriter_members
, /* tp_members */
1907 bufferedwriter_getset
, /* tp_getset */
1910 0, /* tp_descr_get */
1911 0, /* tp_descr_set */
1912 offsetof(buffered
, dict
), /* tp_dictoffset */
1913 (initproc
)bufferedwriter_init
, /* tp_init */
1915 PyType_GenericNew
, /* tp_new */
1924 PyDoc_STRVAR(bufferedrwpair_doc
,
1925 "A buffered reader and writer object together.\n"
1927 "A buffered reader object and buffered writer object put together to\n"
1928 "form a sequential IO object that can read and write. This is typically\n"
1929 "used with a socket or two-way pipe.\n"
1931 "reader and writer are RawIOBase objects that are readable and\n"
1932 "writeable respectively. If the buffer_size is omitted it defaults to\n"
1933 "DEFAULT_BUFFER_SIZE.\n"
1936 /* XXX The usefulness of this (compared to having two separate IO objects) is
1945 PyObject
*weakreflist
;
1949 bufferedrwpair_init(rwpair
*self
, PyObject
*args
, PyObject
*kwds
)
1951 PyObject
*reader
, *writer
;
1952 Py_ssize_t buffer_size
= DEFAULT_BUFFER_SIZE
;
1953 Py_ssize_t max_buffer_size
= -234;
1955 if (!PyArg_ParseTuple(args
, "OO|nn:BufferedRWPair", &reader
, &writer
,
1956 &buffer_size
, &max_buffer_size
)) {
1960 if (max_buffer_size
!= -234 && !complain_about_max_buffer_size())
1963 if (_PyIOBase_check_readable(reader
, Py_True
) == NULL
)
1965 if (_PyIOBase_check_writable(writer
, Py_True
) == NULL
)
1968 self
->reader
= (buffered
*) PyObject_CallFunction(
1969 (PyObject
*) &PyBufferedReader_Type
, "On", reader
, buffer_size
);
1970 if (self
->reader
== NULL
)
1973 self
->writer
= (buffered
*) PyObject_CallFunction(
1974 (PyObject
*) &PyBufferedWriter_Type
, "On", writer
, buffer_size
);
1975 if (self
->writer
== NULL
) {
1976 Py_CLEAR(self
->reader
);
1984 bufferedrwpair_traverse(rwpair
*self
, visitproc visit
, void *arg
)
1986 Py_VISIT(self
->dict
);
1991 bufferedrwpair_clear(rwpair
*self
)
1993 Py_CLEAR(self
->reader
);
1994 Py_CLEAR(self
->writer
);
1995 Py_CLEAR(self
->dict
);
2000 bufferedrwpair_dealloc(rwpair
*self
)
2002 _PyObject_GC_UNTRACK(self
);
2003 Py_CLEAR(self
->reader
);
2004 Py_CLEAR(self
->writer
);
2005 Py_CLEAR(self
->dict
);
2006 Py_TYPE(self
)->tp_free((PyObject
*) self
);
2010 _forward_call(buffered
*self
, const char *name
, PyObject
*args
)
2012 PyObject
*func
= PyObject_GetAttrString((PyObject
*)self
, name
);
2016 PyErr_SetString(PyExc_AttributeError
, name
);
2020 ret
= PyObject_CallObject(func
, args
);
2026 bufferedrwpair_read(rwpair
*self
, PyObject
*args
)
2028 return _forward_call(self
->reader
, "read", args
);
2032 bufferedrwpair_peek(rwpair
*self
, PyObject
*args
)
2034 return _forward_call(self
->reader
, "peek", args
);
2038 bufferedrwpair_read1(rwpair
*self
, PyObject
*args
)
2040 return _forward_call(self
->reader
, "read1", args
);
2044 bufferedrwpair_readinto(rwpair
*self
, PyObject
*args
)
2046 return _forward_call(self
->reader
, "readinto", args
);
2050 bufferedrwpair_write(rwpair
*self
, PyObject
*args
)
2052 return _forward_call(self
->writer
, "write", args
);
2056 bufferedrwpair_flush(rwpair
*self
, PyObject
*args
)
2058 return _forward_call(self
->writer
, "flush", args
);
2062 bufferedrwpair_readable(rwpair
*self
, PyObject
*args
)
2064 return _forward_call(self
->reader
, "readable", args
);
2068 bufferedrwpair_writable(rwpair
*self
, PyObject
*args
)
2070 return _forward_call(self
->writer
, "writable", args
);
2074 bufferedrwpair_close(rwpair
*self
, PyObject
*args
)
2076 PyObject
*ret
= _forward_call(self
->writer
, "close", args
);
2081 return _forward_call(self
->reader
, "close", args
);
2085 bufferedrwpair_isatty(rwpair
*self
, PyObject
*args
)
2087 PyObject
*ret
= _forward_call(self
->writer
, "isatty", args
);
2089 if (ret
!= Py_False
) {
2090 /* either True or exception */
2095 return _forward_call(self
->reader
, "isatty", args
);
2099 bufferedrwpair_closed_get(rwpair
*self
, void *context
)
2101 return PyObject_GetAttr((PyObject
*) self
->writer
, _PyIO_str_closed
);
2104 static PyMethodDef bufferedrwpair_methods
[] = {
2105 {"read", (PyCFunction
)bufferedrwpair_read
, METH_VARARGS
},
2106 {"peek", (PyCFunction
)bufferedrwpair_peek
, METH_VARARGS
},
2107 {"read1", (PyCFunction
)bufferedrwpair_read1
, METH_VARARGS
},
2108 {"readinto", (PyCFunction
)bufferedrwpair_readinto
, METH_VARARGS
},
2110 {"write", (PyCFunction
)bufferedrwpair_write
, METH_VARARGS
},
2111 {"flush", (PyCFunction
)bufferedrwpair_flush
, METH_NOARGS
},
2113 {"readable", (PyCFunction
)bufferedrwpair_readable
, METH_NOARGS
},
2114 {"writable", (PyCFunction
)bufferedrwpair_writable
, METH_NOARGS
},
2116 {"close", (PyCFunction
)bufferedrwpair_close
, METH_NOARGS
},
2117 {"isatty", (PyCFunction
)bufferedrwpair_isatty
, METH_NOARGS
},
2122 static PyGetSetDef bufferedrwpair_getset
[] = {
2123 {"closed", (getter
)bufferedrwpair_closed_get
, NULL
, NULL
},
2127 PyTypeObject PyBufferedRWPair_Type
= {
2128 PyVarObject_HEAD_INIT(NULL
, 0)
2129 "_io.BufferedRWPair", /*tp_name*/
2130 sizeof(rwpair
), /*tp_basicsize*/
2132 (destructor
)bufferedrwpair_dealloc
, /*tp_dealloc*/
2139 0, /*tp_as_sequence*/
2140 0, /*tp_as_mapping*/
2147 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
2148 | Py_TPFLAGS_HAVE_GC
, /* tp_flags */
2149 bufferedrwpair_doc
, /* tp_doc */
2150 (traverseproc
)bufferedrwpair_traverse
, /* tp_traverse */
2151 (inquiry
)bufferedrwpair_clear
, /* tp_clear */
2152 0, /* tp_richcompare */
2153 offsetof(rwpair
, weakreflist
), /*tp_weaklistoffset*/
2155 0, /* tp_iternext */
2156 bufferedrwpair_methods
, /* tp_methods */
2158 bufferedrwpair_getset
, /* tp_getset */
2161 0, /* tp_descr_get */
2162 0, /* tp_descr_set */
2163 offsetof(rwpair
, dict
), /* tp_dictoffset */
2164 (initproc
)bufferedrwpair_init
, /* tp_init */
2166 PyType_GenericNew
, /* tp_new */
2175 PyDoc_STRVAR(bufferedrandom_doc
,
2176 "A buffered interface to random access streams.\n"
2178 "The constructor creates a reader and writer for a seekable stream,\n"
2179 "raw, given in the first argument. If the buffer_size is omitted it\n"
2180 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2184 bufferedrandom_init(buffered
*self
, PyObject
*args
, PyObject
*kwds
)
2186 char *kwlist
[] = {"raw", "buffer_size", "max_buffer_size", NULL
};
2187 Py_ssize_t buffer_size
= DEFAULT_BUFFER_SIZE
;
2188 Py_ssize_t max_buffer_size
= -234;
2194 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "O|nn:BufferedReader", kwlist
,
2195 &raw
, &buffer_size
, &max_buffer_size
)) {
2199 if (max_buffer_size
!= -234 && !complain_about_max_buffer_size())
2202 if (_PyIOBase_check_seekable(raw
, Py_True
) == NULL
)
2204 if (_PyIOBase_check_readable(raw
, Py_True
) == NULL
)
2206 if (_PyIOBase_check_writable(raw
, Py_True
) == NULL
)
2209 Py_CLEAR(self
->raw
);
2212 self
->buffer_size
= buffer_size
;
2216 if (_buffered_init(self
) < 0)
2218 _bufferedreader_reset_buf(self
);
2219 _bufferedwriter_reset_buf(self
);
2222 self
->fast_closed_checks
= (Py_TYPE(self
) == &PyBufferedRandom_Type
&&
2223 Py_TYPE(raw
) == &PyFileIO_Type
);
2229 static PyMethodDef bufferedrandom_methods
[] = {
2230 /* BufferedIOMixin methods */
2231 {"close", (PyCFunction
)buffered_close
, METH_NOARGS
},
2232 {"detach", (PyCFunction
)buffered_detach
, METH_NOARGS
},
2233 {"seekable", (PyCFunction
)buffered_seekable
, METH_NOARGS
},
2234 {"readable", (PyCFunction
)buffered_readable
, METH_NOARGS
},
2235 {"writable", (PyCFunction
)buffered_writable
, METH_NOARGS
},
2236 {"fileno", (PyCFunction
)buffered_fileno
, METH_NOARGS
},
2237 {"isatty", (PyCFunction
)buffered_isatty
, METH_NOARGS
},
2239 {"flush", (PyCFunction
)buffered_flush
, METH_NOARGS
},
2241 {"seek", (PyCFunction
)buffered_seek
, METH_VARARGS
},
2242 {"tell", (PyCFunction
)buffered_tell
, METH_NOARGS
},
2243 {"truncate", (PyCFunction
)buffered_truncate
, METH_VARARGS
},
2244 {"read", (PyCFunction
)buffered_read
, METH_VARARGS
},
2245 {"read1", (PyCFunction
)buffered_read1
, METH_VARARGS
},
2246 {"readinto", (PyCFunction
)buffered_readinto
, METH_VARARGS
},
2247 {"readline", (PyCFunction
)buffered_readline
, METH_VARARGS
},
2248 {"peek", (PyCFunction
)buffered_peek
, METH_VARARGS
},
2249 {"write", (PyCFunction
)bufferedwriter_write
, METH_VARARGS
},
2253 static PyMemberDef bufferedrandom_members
[] = {
2254 {"raw", T_OBJECT
, offsetof(buffered
, raw
), 0},
2258 static PyGetSetDef bufferedrandom_getset
[] = {
2259 {"closed", (getter
)buffered_closed_get
, NULL
, NULL
},
2260 {"name", (getter
)buffered_name_get
, NULL
, NULL
},
2261 {"mode", (getter
)buffered_mode_get
, NULL
, NULL
},
2266 PyTypeObject PyBufferedRandom_Type
= {
2267 PyVarObject_HEAD_INIT(NULL
, 0)
2268 "_io.BufferedRandom", /*tp_name*/
2269 sizeof(buffered
), /*tp_basicsize*/
2271 (destructor
)buffered_dealloc
, /*tp_dealloc*/
2276 (reprfunc
)buffered_repr
, /*tp_repr*/
2278 0, /*tp_as_sequence*/
2279 0, /*tp_as_mapping*/
2286 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
2287 | Py_TPFLAGS_HAVE_GC
, /*tp_flags*/
2288 bufferedrandom_doc
, /* tp_doc */
2289 (traverseproc
)buffered_traverse
, /* tp_traverse */
2290 (inquiry
)buffered_clear
, /* tp_clear */
2291 0, /* tp_richcompare */
2292 offsetof(buffered
, weakreflist
), /*tp_weaklistoffset*/
2294 (iternextfunc
)buffered_iternext
, /* tp_iternext */
2295 bufferedrandom_methods
, /* tp_methods */
2296 bufferedrandom_members
, /* tp_members */
2297 bufferedrandom_getset
, /* tp_getset */
2300 0, /* tp_descr_get */
2301 0, /* tp_descr_set */
2302 offsetof(buffered
, dict
), /*tp_dictoffset*/
2303 (initproc
)bufferedrandom_init
, /* tp_init */
2305 PyType_GenericNew
, /* tp_new */