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(IO_STATE->unsupported_operation, message);
76
PyDoc_STRVAR(BufferedIOBase_read_doc,
77
"Read and return up to n bytes.\n"
79
"If the argument is omitted, None, or negative, reads and\n"
80
"returns all data until EOF.\n"
82
"If the argument is positive, and the underlying raw stream is\n"
83
"not 'interactive', multiple raw reads may be issued to satisfy\n"
84
"the byte count (unless EOF is reached first). But for\n"
85
"interactive raw streams (as well as sockets and pipes), at most\n"
86
"one raw read will be issued, and a short result does not imply\n"
87
"that EOF is imminent.\n"
89
"Returns an empty bytes object on EOF.\n"
91
"Returns None if the underlying raw stream was open in non-blocking\n"
92
"mode and no data is available at the moment.\n");
95
BufferedIOBase_read(PyObject *self, PyObject *args)
97
return BufferedIOBase_unsupported("read");
100
PyDoc_STRVAR(BufferedIOBase_read1_doc,
101
"Read and return up to n bytes, with at most one read() call\n"
102
"to the underlying raw stream. A short result does not imply\n"
103
"that EOF is imminent.\n"
105
"Returns an empty bytes object on EOF.\n");
108
BufferedIOBase_read1(PyObject *self, PyObject *args)
110
return BufferedIOBase_unsupported("read1");
113
PyDoc_STRVAR(BufferedIOBase_write_doc,
114
"Write the given buffer to the IO stream.\n"
116
"Returns the number of bytes written, which is never less than\n"
119
"Raises BlockingIOError if the buffer is full and the\n"
120
"underlying raw stream cannot accept more data at the moment.\n");
123
BufferedIOBase_write(PyObject *self, PyObject *args)
125
return BufferedIOBase_unsupported("write");
129
static PyMethodDef BufferedIOBase_methods[] = {
130
{"read", BufferedIOBase_read, METH_VARARGS, BufferedIOBase_read_doc},
131
{"read1", BufferedIOBase_read1, METH_VARARGS, BufferedIOBase_read1_doc},
132
{"readinto", BufferedIOBase_readinto, METH_VARARGS, NULL},
133
{"write", BufferedIOBase_write, METH_VARARGS, BufferedIOBase_write_doc},
137
PyTypeObject PyBufferedIOBase_Type = {
138
PyVarObject_HEAD_INIT(NULL, 0)
139
"_io._BufferedIOBase", /*tp_name*/
149
0, /*tp_as_sequence*/
157
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
158
BufferedIOBase_doc, /* tp_doc */
161
0, /* tp_richcompare */
162
0, /* tp_weaklistoffset */
165
BufferedIOBase_methods, /* tp_methods */
168
&PyIOBase_Type, /* tp_base */
170
0, /* tp_descr_get */
171
0, /* tp_descr_set */
172
0, /* tp_dictoffset */
183
int ok; /* Initialized? */
187
/* Absolute position inside the raw stream (-1 if unknown). */
190
/* A static buffer of size `buffer_size` */
192
/* Current logical position in the buffer. */
194
/* Position of the raw stream in the buffer. */
197
/* Just after the last buffered byte in the buffer, or -1 if the buffer
198
isn't ready for reading. */
201
/* Just after the last byte actually written */
203
/* Just after the last byte waiting to be written, or -1 if the buffer
204
isn't ready for writing. */
207
PyThread_type_lock lock;
209
Py_ssize_t buffer_size;
210
Py_ssize_t buffer_mask;
213
PyObject *weakreflist;
217
Implementation notes:
219
* BufferedReader, BufferedWriter and BufferedRandom try to share most
220
methods (this is helped by the members `readable` and `writable`, which
221
are initialized in the respective constructors)
222
* They also share a single buffer for reading and writing. This enables
223
interleaved reads and writes without flushing. It also makes the logic
224
a bit trickier to get right.
225
* The absolute position of the raw stream is cached, if possible, in the
226
`abs_pos` member. It must be updated every time an operation is done
227
on the raw stream. If not sure, it can be reinitialized by calling
228
_Buffered_raw_tell(), which queries the raw stream (_Buffered_raw_seek()
229
also does it). To read it, use RAW_TELL().
230
* Three helpers, _BufferedReader_raw_read, _BufferedWriter_raw_write and
231
_BufferedWriter_flush_unlocked do a lot of useful housekeeping.
233
NOTE: we should try to maintain block alignment of reads and writes to the
234
raw stream (according to the buffer size), but for now it is only done
235
in read() and friends.
237
XXX: method naming is a bit messy.
240
/* These macros protect the BufferedObject against concurrent operations. */
242
#define ENTER_BUFFERED(self) \
243
Py_BEGIN_ALLOW_THREADS \
244
PyThread_acquire_lock(self->lock, 1); \
247
#define LEAVE_BUFFERED(self) \
248
PyThread_release_lock(self->lock);
250
#define CHECK_INITIALIZED(self) \
251
if (self->ok <= 0) { \
252
PyErr_SetString(PyExc_ValueError, \
253
"I/O operation on uninitialized object"); \
257
#define CHECK_INITIALIZED_INT(self) \
258
if (self->ok <= 0) { \
259
PyErr_SetString(PyExc_ValueError, \
260
"I/O operation on uninitialized object"); \
264
#define VALID_READ_BUFFER(self) \
265
(self->readable && self->read_end != -1)
267
#define VALID_WRITE_BUFFER(self) \
268
(self->writable && self->write_end != -1)
270
#define ADJUST_POSITION(self, _new_pos) \
272
self->pos = _new_pos; \
273
if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
274
self->read_end = self->pos; \
277
#define READAHEAD(self) \
278
((self->readable && VALID_READ_BUFFER(self)) \
279
? (self->read_end - self->pos) : 0)
281
#define RAW_OFFSET(self) \
282
(((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
283
&& self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
285
#define RAW_TELL(self) \
286
(self->abs_pos != -1 ? self->abs_pos : _Buffered_raw_tell(self))
288
#define MINUS_LAST_BLOCK(self, size) \
289
(self->buffer_mask ? \
290
(size & ~self->buffer_mask) : \
291
(self->buffer_size * (size / self->buffer_size)))
295
BufferedObject_dealloc(BufferedObject *self)
297
if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
299
_PyObject_GC_UNTRACK(self);
301
if (self->weakreflist != NULL)
302
PyObject_ClearWeakRefs((PyObject *)self);
305
PyMem_Free(self->buffer);
309
PyThread_free_lock(self->lock);
312
Py_CLEAR(self->dict);
313
Py_TYPE(self)->tp_free((PyObject *)self);
317
Buffered_traverse(BufferedObject *self, visitproc visit, void *arg)
320
Py_VISIT(self->dict);
325
Buffered_clear(BufferedObject *self)
327
if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
331
Py_CLEAR(self->dict);
336
* _BufferedIOMixin methods
337
* This is not a class, just a collection of methods that will be reused
338
* by BufferedReader and BufferedWriter
341
/* Flush and close */
344
BufferedIOMixin_flush(BufferedObject *self, PyObject *args)
346
CHECK_INITIALIZED(self)
347
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
351
BufferedIOMixin_closed(BufferedObject *self)
355
CHECK_INITIALIZED_INT(self)
356
res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
359
closed = PyObject_IsTrue(res);
365
BufferedIOMixin_closed_get(BufferedObject *self, void *context)
367
CHECK_INITIALIZED(self)
368
return PyObject_GetAttr(self->raw, _PyIO_str_closed);
372
BufferedIOMixin_close(BufferedObject *self, PyObject *args)
374
PyObject *res = NULL;
377
CHECK_INITIALIZED(self)
380
r = BufferedIOMixin_closed(self);
388
/* flush() will most probably re-take the lock, so drop it first */
390
res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
393
/* If flush() fails, just give up */
394
if (PyErr_ExceptionMatches(PyExc_IOError))
401
res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
411
BufferedIOMixin_seekable(BufferedObject *self, PyObject *args)
413
CHECK_INITIALIZED(self)
414
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
418
BufferedIOMixin_readable(BufferedObject *self, PyObject *args)
420
CHECK_INITIALIZED(self)
421
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
425
BufferedIOMixin_writable(BufferedObject *self, PyObject *args)
427
CHECK_INITIALIZED(self)
428
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
432
BufferedIOMixin_name_get(BufferedObject *self, void *context)
434
CHECK_INITIALIZED(self)
435
return PyObject_GetAttrString(self->raw, "name");
439
BufferedIOMixin_mode_get(BufferedObject *self, void *context)
441
CHECK_INITIALIZED(self)
442
return PyObject_GetAttrString(self->raw, "mode");
445
/* Lower-level APIs */
448
BufferedIOMixin_fileno(BufferedObject *self, PyObject *args)
450
CHECK_INITIALIZED(self)
451
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
455
BufferedIOMixin_isatty(BufferedObject *self, PyObject *args)
457
CHECK_INITIALIZED(self)
458
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
464
_BufferedWriter_flush_unlocked(BufferedObject *, int);
466
_BufferedReader_fill_buffer(BufferedObject *self);
468
_BufferedReader_reset_buf(BufferedObject *self);
470
_BufferedWriter_reset_buf(BufferedObject *self);
472
_BufferedReader_peek_unlocked(BufferedObject *self, Py_ssize_t);
474
_BufferedReader_read_unlocked(BufferedObject *self, Py_ssize_t);
481
/* Returns the address of the `written` member if a BlockingIOError was
482
raised, NULL otherwise. The error is always re-raised. */
484
_Buffered_check_blocking_error(void)
486
PyObject *t, *v, *tb;
487
PyBlockingIOErrorObject *err;
489
PyErr_Fetch(&t, &v, &tb);
490
if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
491
PyErr_Restore(t, v, tb);
494
err = (PyBlockingIOErrorObject *) v;
495
/* TODO: sanity check (err->written >= 0) */
496
PyErr_Restore(t, v, tb);
497
return &err->written;
501
_Buffered_raw_tell(BufferedObject *self)
505
res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
508
n = PyNumber_AsOff_t(res, PyExc_ValueError);
511
if (!PyErr_Occurred())
512
PyErr_Format(PyExc_IOError,
513
"Raw stream returned invalid position %zd", n);
521
_Buffered_raw_seek(BufferedObject *self, Py_off_t target, int whence)
523
PyObject *res, *posobj, *whenceobj;
526
posobj = PyLong_FromOff_t(target);
529
whenceobj = PyLong_FromLong(whence);
530
if (whenceobj == NULL) {
534
res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
535
posobj, whenceobj, NULL);
537
Py_DECREF(whenceobj);
540
n = PyNumber_AsOff_t(res, PyExc_ValueError);
543
if (!PyErr_Occurred())
544
PyErr_Format(PyExc_IOError,
545
"Raw stream returned invalid position %zd", n);
553
_Buffered_init(BufferedObject *self)
556
if (self->buffer_size <= 0) {
557
PyErr_SetString(PyExc_ValueError,
558
"buffer size must be strictly positive");
562
PyMem_Free(self->buffer);
563
self->buffer = PyMem_Malloc(self->buffer_size);
564
if (self->buffer == NULL) {
568
self->lock = PyThread_allocate_lock();
569
if (self->lock == NULL) {
570
PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
573
/* Find out whether buffer_size is a power of 2 */
574
/* XXX is this optimization useful? */
575
for (n = self->buffer_size - 1; n & 1; n >>= 1)
578
self->buffer_mask = self->buffer_size - 1;
580
self->buffer_mask = 0;
581
if (_Buffered_raw_tell(self) == -1)
587
* Shared methods and wrappers
591
Buffered_flush(BufferedObject *self, PyObject *args)
595
CHECK_INITIALIZED(self)
596
if (BufferedIOMixin_closed(self)) {
597
PyErr_SetString(PyExc_ValueError, "flush of closed file");
602
res = _BufferedWriter_flush_unlocked(self, 0);
603
if (res != NULL && self->readable) {
604
/* Rewind the raw stream so that its position corresponds to
605
the current logical position. */
607
n = _Buffered_raw_seek(self, -RAW_OFFSET(self), 1);
610
_BufferedReader_reset_buf(self);
618
Buffered_peek(BufferedObject *self, PyObject *args)
621
PyObject *res = NULL;
623
CHECK_INITIALIZED(self)
624
if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
630
if (self->writable) {
631
res = _BufferedWriter_flush_unlocked(self, 1);
636
res = _BufferedReader_peek_unlocked(self, n);
644
Buffered_read(BufferedObject *self, PyObject *args)
649
CHECK_INITIALIZED(self)
650
if (!PyArg_ParseTuple(args, "|n:read", &n)) {
654
PyErr_SetString(PyExc_ValueError,
655
"read length must be positive or -1");
659
if (BufferedIOMixin_closed(self)) {
660
PyErr_SetString(PyExc_ValueError, "read of closed file");
665
res = _BufferedReader_read_unlocked(self, n);
672
Buffered_read1(BufferedObject *self, PyObject *args)
674
Py_ssize_t n, have, r;
675
PyObject *res = NULL;
677
CHECK_INITIALIZED(self)
678
if (!PyArg_ParseTuple(args, "n:read1", &n)) {
683
PyErr_SetString(PyExc_ValueError,
684
"read length must be positive");
688
return PyBytes_FromStringAndSize(NULL, 0);
692
if (self->writable) {
693
res = _BufferedWriter_flush_unlocked(self, 1);
699
/* Return up to n bytes. If at least one byte is buffered, we
700
only return buffered bytes. Otherwise, we do one raw read. */
702
/* XXX: this mimicks the io.py implementation but is probably wrong.
703
If we need to read from the raw stream, then we could actually read
704
all `n` bytes asked by the caller (and possibly more, so as to fill
705
our buffer for the next reads). */
707
have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
711
res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
718
/* Fill the buffer from the raw stream, and copy it to the result. */
719
_BufferedReader_reset_buf(self);
720
r = _BufferedReader_fill_buffer(self);
727
res = PyBytes_FromStringAndSize(self->buffer, n);
738
Buffered_readinto(BufferedObject *self, PyObject *args)
740
PyObject *res = NULL;
742
CHECK_INITIALIZED(self)
744
/* TODO: use raw.readinto() instead! */
745
if (self->writable) {
747
res = _BufferedWriter_flush_unlocked(self, 0);
753
res = BufferedIOBase_readinto((PyObject *)self, args);
760
_Buffered_readline(BufferedObject *self, Py_ssize_t limit)
762
PyObject *res = NULL;
763
PyObject *chunks = NULL;
764
Py_ssize_t n, written = 0;
765
const char *start, *s, *end;
767
if (BufferedIOMixin_closed(self)) {
768
PyErr_SetString(PyExc_ValueError, "readline of closed file");
774
/* First, try to find a line in the buffer */
775
n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
776
if (limit >= 0 && n > limit)
778
start = self->buffer + self->pos;
783
res = PyBytes_FromStringAndSize(start, s - start);
785
self->pos += s - start;
790
res = PyBytes_FromStringAndSize(start, n);
796
/* Now we try to get some more from the raw stream */
797
if (self->writable) {
798
res = _BufferedWriter_flush_unlocked(self, 1);
803
chunks = PyList_New(0);
807
res = PyBytes_FromStringAndSize(start, n);
810
if (PyList_Append(chunks, res) < 0) {
821
_BufferedReader_reset_buf(self);
822
n = _BufferedReader_fill_buffer(self);
827
if (limit >= 0 && n > limit)
829
start = self->buffer;
834
res = PyBytes_FromStringAndSize(start, s - start);
837
self->pos = s - start;
841
res = PyBytes_FromStringAndSize(start, n);
848
if (PyList_Append(chunks, res) < 0) {
858
if (res != NULL && PyList_Append(chunks, res) < 0) {
863
res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
872
Buffered_readline(BufferedObject *self, PyObject *args)
874
Py_ssize_t limit = -1;
876
CHECK_INITIALIZED(self)
878
if (!PyArg_ParseTuple(args, "|n:readline", &limit)) {
881
return _Buffered_readline(self, limit);
886
Buffered_tell(BufferedObject *self, PyObject *args)
890
CHECK_INITIALIZED(self)
891
pos = _Buffered_raw_tell(self);
894
pos -= RAW_OFFSET(self);
895
/* TODO: sanity check (pos >= 0) */
896
return PyLong_FromOff_t(pos);
900
Buffered_seek(BufferedObject *self, PyObject *args)
904
PyObject *targetobj, *res = NULL;
906
CHECK_INITIALIZED(self)
907
if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
911
if (whence < 0 || whence > 2) {
912
PyErr_Format(PyExc_ValueError,
913
"whence must be between 0 and 2, not %d", whence);
916
target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
917
if (target == -1 && PyErr_Occurred())
922
if (whence != 2 && self->readable) {
923
Py_off_t current, avail;
924
/* Check if seeking leaves us inside the current buffer,
925
so as to return quickly if possible.
926
Don't know how to do that when whence == 2, though. */
927
current = RAW_TELL(self);
928
avail = READAHEAD(self);
932
offset = target - (current - RAW_OFFSET(self));
935
if (offset >= -self->pos && offset <= avail) {
937
res = PyLong_FromOff_t(current - avail + offset);
943
/* Fallback: invoke raw seek() method and clear buffer */
944
if (self->writable) {
945
res = _BufferedWriter_flush_unlocked(self, 0);
949
_BufferedWriter_reset_buf(self);
952
/* TODO: align on block boundary and read buffer if needed? */
954
target -= RAW_OFFSET(self);
955
n = _Buffered_raw_seek(self, target, whence);
959
res = PyLong_FromOff_t(n);
960
if (res != NULL && self->readable)
961
_BufferedReader_reset_buf(self);
969
Buffered_truncate(BufferedObject *self, PyObject *args)
971
PyObject *pos = Py_None;
972
PyObject *res = NULL;
974
CHECK_INITIALIZED(self)
975
if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
981
if (self->writable) {
982
res = _BufferedWriter_flush_unlocked(self, 0);
987
if (self->readable) {
988
if (pos == Py_None) {
989
/* Rewind the raw stream so that its position corresponds to
990
the current logical position. */
991
if (_Buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)
994
_BufferedReader_reset_buf(self);
996
res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
999
/* Reset cached position */
1000
if (_Buffered_raw_tell(self) == -1)
1004
LEAVE_BUFFERED(self)
1009
Buffered_iternext(BufferedObject *self)
1014
CHECK_INITIALIZED(self);
1017
if (tp == &PyBufferedReader_Type ||
1018
tp == &PyBufferedRandom_Type) {
1019
/* Skip method call overhead for speed */
1020
line = _Buffered_readline(self, -1);
1023
line = PyObject_CallMethodObjArgs((PyObject *)self,
1024
_PyIO_str_readline, NULL);
1025
if (line && !PyBytes_Check(line)) {
1026
PyErr_Format(PyExc_IOError,
1027
"readline() should have returned a bytes object, "
1028
"not '%.200s'", Py_TYPE(line)->tp_name);
1037
if (PyBytes_GET_SIZE(line) == 0) {
1038
/* Reached EOF or would have blocked */
1047
* class BufferedReader
1050
PyDoc_STRVAR(BufferedReader_doc,
1051
"Create a new buffered reader using the given readable raw IO object.");
1053
static void _BufferedReader_reset_buf(BufferedObject *self)
1055
self->read_end = -1;
1059
BufferedReader_init(BufferedObject *self, PyObject *args, PyObject *kwds)
1061
char *kwlist[] = {"raw", "buffer_size", NULL};
1062
Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1067
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1068
&raw, &buffer_size)) {
1072
if (_PyIOBase_checkReadable(raw, Py_True) == NULL)
1075
Py_CLEAR(self->raw);
1078
self->buffer_size = buffer_size;
1082
if (_Buffered_init(self) < 0)
1084
_BufferedReader_reset_buf(self);
1091
_BufferedReader_raw_read(BufferedObject *self, char *start, Py_ssize_t len)
1094
PyObject *memobj, *res;
1096
/* NOTE: the buffer needn't be released as its object is NULL. */
1097
if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1099
memobj = PyMemoryView_FromBuffer(&buf);
1102
res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1106
if (res == Py_None) {
1107
/* Non-blocking stream would have blocked. Special return code! */
1111
n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1113
if (n < 0 || n > len) {
1114
PyErr_Format(PyExc_IOError,
1115
"raw readinto() returned invalid length %zd "
1116
"(should have been between 0 and %zd)", n, len);
1119
if (n > 0 && self->abs_pos != -1)
1125
_BufferedReader_fill_buffer(BufferedObject *self)
1127
Py_ssize_t start, len, n;
1128
if (VALID_READ_BUFFER(self))
1129
start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1132
len = self->buffer_size - start;
1133
n = _BufferedReader_raw_read(self, self->buffer + start, len);
1136
self->read_end = start + n;
1137
self->raw_pos = start + n;
1142
_BufferedReader_read_unlocked(BufferedObject *self, Py_ssize_t n)
1144
PyObject *data, *res = NULL;
1145
Py_ssize_t current_size, remaining, written;
1147
static PyObject *sep = NULL;
1149
/* Special case for when the number of bytes to read is unspecified. */
1151
PyObject *chunks = PyList_New(0);
1155
/* First copy what we have in the current buffer. */
1156
current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1159
data = PyBytes_FromStringAndSize(
1160
self->buffer + self->pos, current_size);
1166
_BufferedReader_reset_buf(self);
1167
/* We're going past the buffer's bounds, flush it */
1168
if (self->writable) {
1169
res = _BufferedWriter_flush_unlocked(self, 1);
1178
if (PyList_Append(chunks, data) < 0) {
1186
/* Read until EOF or until read() would block. */
1187
data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1192
if (data != Py_None && !PyBytes_Check(data)) {
1195
PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1198
if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1199
if (current_size == 0) {
1205
sep = PyBytes_FromStringAndSize(NULL, 0);
1212
res =_PyBytes_Join(sep, chunks);
1218
current_size += PyBytes_GET_SIZE(data);
1219
if (self->abs_pos != -1)
1220
self->abs_pos += PyBytes_GET_SIZE(data);
1224
/* The number of bytes to read is specified, return at most n bytes. */
1225
current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1226
if (n <= current_size) {
1227
/* Fast path: the data to read is fully buffered. */
1228
res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1235
/* Slow path: read from the stream until enough bytes are read,
1236
* or until an EOF occurs or until read() would block.
1238
res = PyBytes_FromStringAndSize(NULL, n);
1241
out = PyBytes_AS_STRING(res);
1244
if (current_size > 0) {
1245
memcpy(out, self->buffer + self->pos, current_size);
1246
remaining -= current_size;
1247
written += current_size;
1249
_BufferedReader_reset_buf(self);
1250
while (remaining > 0) {
1251
/* We want to read a whole block at the end into buffer.
1252
If we had readv() we could do this in one pass. */
1253
Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1256
r = _BufferedReader_raw_read(self, out + written, r);
1259
if (r == 0 || r == -2) {
1260
/* EOF occurred or read() would block. */
1261
if (r == 0 || written > 0) {
1262
if (_PyBytes_Resize(&res, written))
1273
assert(remaining <= self->buffer_size);
1277
while (self->read_end < self->buffer_size) {
1278
Py_ssize_t r = _BufferedReader_fill_buffer(self);
1281
if (r == 0 || r == -2) {
1282
/* EOF occurred or read() would block. */
1283
if (r == 0 || written > 0) {
1284
if (_PyBytes_Resize(&res, written))
1292
if (remaining > r) {
1293
memcpy(out + written, self->buffer + self->pos, r);
1298
else if (remaining > 0) {
1299
memcpy(out + written, self->buffer + self->pos, remaining);
1300
written += remaining;
1301
self->pos += remaining;
1316
_BufferedReader_peek_unlocked(BufferedObject *self, Py_ssize_t n)
1320
have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1322
1. we don't want to advance the file position.
1323
2. we don't want to lose block alignment, so we can't shift the buffer
1325
Therefore, we either return `have` bytes (if > 0), or a full buffer.
1328
return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1331
/* Fill the buffer from the raw stream, and copy it to the result. */
1332
_BufferedReader_reset_buf(self);
1333
r = _BufferedReader_fill_buffer(self);
1339
return PyBytes_FromStringAndSize(self->buffer, r);
1342
static PyMethodDef BufferedReader_methods[] = {
1343
/* BufferedIOMixin methods */
1344
{"flush", (PyCFunction)BufferedIOMixin_flush, METH_NOARGS},
1345
{"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS},
1346
{"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS},
1347
{"readable", (PyCFunction)BufferedIOMixin_readable, METH_NOARGS},
1348
{"writable", (PyCFunction)BufferedIOMixin_writable, METH_NOARGS},
1349
{"fileno", (PyCFunction)BufferedIOMixin_fileno, METH_NOARGS},
1350
{"isatty", (PyCFunction)BufferedIOMixin_isatty, METH_NOARGS},
1352
{"read", (PyCFunction)Buffered_read, METH_VARARGS},
1353
{"peek", (PyCFunction)Buffered_peek, METH_VARARGS},
1354
{"read1", (PyCFunction)Buffered_read1, METH_VARARGS},
1355
{"readline", (PyCFunction)Buffered_readline, METH_VARARGS},
1356
{"seek", (PyCFunction)Buffered_seek, METH_VARARGS},
1357
{"tell", (PyCFunction)Buffered_tell, METH_NOARGS},
1358
{"truncate", (PyCFunction)Buffered_truncate, METH_VARARGS},
1362
static PyMemberDef BufferedReader_members[] = {
1363
{"raw", T_OBJECT, offsetof(BufferedObject, raw), 0},
1367
static PyGetSetDef BufferedReader_getset[] = {
1368
{"closed", (getter)BufferedIOMixin_closed_get, NULL, NULL},
1369
{"name", (getter)BufferedIOMixin_name_get, NULL, NULL},
1370
{"mode", (getter)BufferedIOMixin_mode_get, NULL, NULL},
1375
PyTypeObject PyBufferedReader_Type = {
1376
PyVarObject_HEAD_INIT(NULL, 0)
1377
"_io.BufferedReader", /*tp_name*/
1378
sizeof(BufferedObject), /*tp_basicsize*/
1380
(destructor)BufferedObject_dealloc, /*tp_dealloc*/
1387
0, /*tp_as_sequence*/
1388
0, /*tp_as_mapping*/
1395
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1396
| Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1397
BufferedReader_doc, /* tp_doc */
1398
(traverseproc)Buffered_traverse, /* tp_traverse */
1399
(inquiry)Buffered_clear, /* tp_clear */
1400
0, /* tp_richcompare */
1401
offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/
1403
(iternextfunc)Buffered_iternext, /* tp_iternext */
1404
BufferedReader_methods, /* tp_methods */
1405
BufferedReader_members, /* tp_members */
1406
BufferedReader_getset, /* tp_getset */
1409
0, /* tp_descr_get */
1410
0, /* tp_descr_set */
1411
offsetof(BufferedObject, dict), /* tp_dictoffset */
1412
(initproc)BufferedReader_init, /* tp_init */
1414
PyType_GenericNew, /* tp_new */
1419
* class BufferedWriter
1421
PyDoc_STRVAR(BufferedWriter_doc,
1422
"A buffer for a writeable sequential RawIO object.\n"
1424
"The constructor creates a BufferedWriter for the given writeable raw\n"
1425
"stream. If the buffer_size is not given, it defaults to\n"
1426
"DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1430
_BufferedWriter_reset_buf(BufferedObject *self)
1432
self->write_pos = 0;
1433
self->write_end = -1;
1437
BufferedWriter_init(BufferedObject *self, PyObject *args, PyObject *kwds)
1439
/* TODO: properly deprecate max_buffer_size */
1440
char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1441
Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1442
Py_ssize_t max_buffer_size = -1;
1447
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1448
&raw, &buffer_size, &max_buffer_size)) {
1452
if (_PyIOBase_checkWritable(raw, Py_True) == NULL)
1455
Py_CLEAR(self->raw);
1461
self->buffer_size = buffer_size;
1462
if (_Buffered_init(self) < 0)
1464
_BufferedWriter_reset_buf(self);
1472
_BufferedWriter_raw_write(BufferedObject *self, char *start, Py_ssize_t len)
1475
PyObject *memobj, *res;
1477
/* NOTE: the buffer needn't be released as its object is NULL. */
1478
if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1480
memobj = PyMemoryView_FromBuffer(&buf);
1483
res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1487
n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1489
if (n < 0 || n > len) {
1490
PyErr_Format(PyExc_IOError,
1491
"raw write() returned invalid length %zd "
1492
"(should have been between 0 and %zd)", n, len);
1495
if (n > 0 && self->abs_pos != -1)
1500
/* `restore_pos` is 1 if we need to restore the raw stream position at
1501
the end, 0 otherwise. */
1503
_BufferedWriter_flush_unlocked(BufferedObject *self, int restore_pos)
1505
Py_ssize_t written = 0;
1508
if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1511
rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1513
n = _Buffered_raw_seek(self, -rewind, 1);
1517
self->raw_pos -= rewind;
1519
while (self->write_pos < self->write_end) {
1520
n = _BufferedWriter_raw_write(self,
1521
self->buffer + self->write_pos,
1522
Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1523
Py_off_t, Py_ssize_t));
1525
Py_ssize_t *w = _Buffered_check_blocking_error();
1528
self->write_pos += *w;
1529
self->raw_pos = self->write_pos;
1532
/* Already re-raised */
1535
self->write_pos += n;
1536
self->raw_pos = self->write_pos;
1537
written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1541
Py_off_t forward = rewind - written;
1543
n = _Buffered_raw_seek(self, forward, 1);
1547
self->raw_pos += forward;
1550
_BufferedWriter_reset_buf(self);
1560
BufferedWriter_write(BufferedObject *self, PyObject *args)
1562
PyObject *res = NULL;
1564
Py_ssize_t written, avail, remaining, n;
1566
CHECK_INITIALIZED(self)
1567
if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1571
if (BufferedIOMixin_closed(self)) {
1572
PyErr_SetString(PyExc_ValueError, "write to closed file");
1573
PyBuffer_Release(&buf);
1577
ENTER_BUFFERED(self)
1579
/* Fast path: the data to write can be fully buffered. */
1580
if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1584
avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1585
if (buf.len <= avail) {
1586
memcpy(self->buffer + self->pos, buf.buf, buf.len);
1587
if (!VALID_WRITE_BUFFER(self)) {
1588
self->write_pos = self->pos;
1590
ADJUST_POSITION(self, self->pos + buf.len);
1591
if (self->pos > self->write_end)
1592
self->write_end = self->pos;
1597
/* First write the current buffer */
1598
res = _BufferedWriter_flush_unlocked(self, 0);
1600
Py_ssize_t *w = _Buffered_check_blocking_error();
1604
_BufferedReader_reset_buf(self);
1605
/* Make some place by shifting the buffer. */
1606
assert(VALID_WRITE_BUFFER(self));
1607
memmove(self->buffer, self->buffer + self->write_pos,
1608
Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1609
Py_off_t, Py_ssize_t));
1610
self->write_end -= self->write_pos;
1611
self->raw_pos -= self->write_pos;
1612
self->pos -= self->write_pos;
1613
self->write_pos = 0;
1614
avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1615
Py_off_t, Py_ssize_t);
1616
if (buf.len <= avail) {
1617
/* Everything can be buffered */
1619
memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1620
self->write_end += buf.len;
1624
/* Buffer as much as possible. */
1625
memcpy(self->buffer + self->write_end, buf.buf, avail);
1626
self->write_end += avail;
1627
/* Already re-raised */
1633
/* Then write buf itself. At this point the buffer has been emptied. */
1634
remaining = buf.len;
1636
while (remaining > self->buffer_size) {
1637
n = _BufferedWriter_raw_write(
1638
self, (char *) buf.buf + written, buf.len - written);
1640
Py_ssize_t *w = _Buffered_check_blocking_error();
1645
if (remaining > self->buffer_size) {
1646
/* Can't buffer everything, still buffer as much as possible */
1647
memcpy(self->buffer,
1648
(char *) buf.buf + written, self->buffer_size);
1650
ADJUST_POSITION(self, self->buffer_size);
1651
self->write_end = self->buffer_size;
1652
*w = written + self->buffer_size;
1653
/* Already re-raised */
1663
_BufferedReader_reset_buf(self);
1664
if (remaining > 0) {
1665
memcpy(self->buffer, (char *) buf.buf + written, remaining);
1666
written += remaining;
1668
self->write_pos = 0;
1669
/* TODO: sanity check (remaining >= 0) */
1670
self->write_end = remaining;
1671
ADJUST_POSITION(self, remaining);
1675
res = PyLong_FromSsize_t(written);
1678
LEAVE_BUFFERED(self)
1679
PyBuffer_Release(&buf);
1683
static PyMethodDef BufferedWriter_methods[] = {
1684
/* BufferedIOMixin methods */
1685
{"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS},
1686
{"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS},
1687
{"readable", (PyCFunction)BufferedIOMixin_readable, METH_NOARGS},
1688
{"writable", (PyCFunction)BufferedIOMixin_writable, METH_NOARGS},
1689
{"fileno", (PyCFunction)BufferedIOMixin_fileno, METH_NOARGS},
1690
{"isatty", (PyCFunction)BufferedIOMixin_isatty, METH_NOARGS},
1692
{"write", (PyCFunction)BufferedWriter_write, METH_VARARGS},
1693
{"truncate", (PyCFunction)Buffered_truncate, METH_VARARGS},
1694
{"flush", (PyCFunction)Buffered_flush, METH_NOARGS},
1695
{"seek", (PyCFunction)Buffered_seek, METH_VARARGS},
1696
{"tell", (PyCFunction)Buffered_tell, METH_NOARGS},
1700
static PyMemberDef BufferedWriter_members[] = {
1701
{"raw", T_OBJECT, offsetof(BufferedObject, raw), 0},
1705
static PyGetSetDef BufferedWriter_getset[] = {
1706
{"closed", (getter)BufferedIOMixin_closed_get, NULL, NULL},
1707
{"name", (getter)BufferedIOMixin_name_get, NULL, NULL},
1708
{"mode", (getter)BufferedIOMixin_mode_get, NULL, NULL},
1713
PyTypeObject PyBufferedWriter_Type = {
1714
PyVarObject_HEAD_INIT(NULL, 0)
1715
"_io.BufferedWriter", /*tp_name*/
1716
sizeof(BufferedObject), /*tp_basicsize*/
1718
(destructor)BufferedObject_dealloc, /*tp_dealloc*/
1725
0, /*tp_as_sequence*/
1726
0, /*tp_as_mapping*/
1733
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1734
| Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1735
BufferedWriter_doc, /* tp_doc */
1736
(traverseproc)Buffered_traverse, /* tp_traverse */
1737
(inquiry)Buffered_clear, /* tp_clear */
1738
0, /* tp_richcompare */
1739
offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/
1741
0, /* tp_iternext */
1742
BufferedWriter_methods, /* tp_methods */
1743
BufferedWriter_members, /* tp_members */
1744
BufferedWriter_getset, /* tp_getset */
1747
0, /* tp_descr_get */
1748
0, /* tp_descr_set */
1749
offsetof(BufferedObject, dict), /* tp_dictoffset */
1750
(initproc)BufferedWriter_init, /* tp_init */
1752
PyType_GenericNew, /* tp_new */
1761
PyDoc_STRVAR(BufferedRWPair_doc,
1762
"A buffered reader and writer object together.\n"
1764
"A buffered reader object and buffered writer object put together to\n"
1765
"form a sequential IO object that can read and write. This is typically\n"
1766
"used with a socket or two-way pipe.\n"
1768
"reader and writer are RawIOBase objects that are readable and\n"
1769
"writeable respectively. If the buffer_size is omitted it defaults to\n"
1770
"DEFAULT_BUFFER_SIZE. The max_buffer_size (for the buffered writer)\n"
1771
"defaults to twice the buffer size.\n"
1774
/* XXX The usefulness of this (compared to having two separate IO objects) is
1780
BufferedObject *reader;
1781
BufferedObject *writer;
1783
PyObject *weakreflist;
1784
} BufferedRWPairObject;
1787
BufferedRWPair_init(BufferedRWPairObject *self, PyObject *args,
1790
PyObject *reader, *writer;
1791
Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1792
Py_ssize_t max_buffer_size = -1;
1794
if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1795
&buffer_size, &max_buffer_size)) {
1799
if (_PyIOBase_checkReadable(reader, Py_True) == NULL)
1801
if (_PyIOBase_checkWritable(writer, Py_True) == NULL)
1804
args = Py_BuildValue("(n)", buffer_size);
1806
Py_CLEAR(self->reader);
1809
self->reader = (BufferedObject *)PyType_GenericNew(
1810
&PyBufferedReader_Type, args, NULL);
1812
if (self->reader == NULL)
1815
args = Py_BuildValue("(nn)", buffer_size, max_buffer_size);
1817
Py_CLEAR(self->reader);
1820
self->writer = (BufferedObject *)PyType_GenericNew(
1821
&PyBufferedWriter_Type, args, NULL);
1823
if (self->writer == NULL) {
1824
Py_CLEAR(self->reader);
1831
BufferedRWPair_traverse(BufferedRWPairObject *self, visitproc visit, void *arg)
1833
Py_VISIT(self->dict);
1838
BufferedRWPair_clear(BufferedRWPairObject *self)
1840
Py_CLEAR(self->reader);
1841
Py_CLEAR(self->writer);
1842
Py_CLEAR(self->dict);
1847
BufferedRWPair_dealloc(BufferedRWPairObject *self)
1849
_PyObject_GC_UNTRACK(self);
1850
Py_CLEAR(self->reader);
1851
Py_CLEAR(self->writer);
1852
Py_CLEAR(self->dict);
1853
Py_TYPE(self)->tp_free((PyObject *) self);
1857
_forward_call(BufferedObject *self, const char *name, PyObject *args)
1859
PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
1863
PyErr_SetString(PyExc_AttributeError, name);
1867
ret = PyObject_CallObject(func, args);
1873
BufferedRWPair_read(BufferedRWPairObject *self, PyObject *args)
1875
return _forward_call(self->reader, "read", args);
1879
BufferedRWPair_peek(BufferedRWPairObject *self, PyObject *args)
1881
return _forward_call(self->reader, "peek", args);
1885
BufferedRWPair_read1(BufferedRWPairObject *self, PyObject *args)
1887
return _forward_call(self->reader, "read1", args);
1891
BufferedRWPair_write(BufferedRWPairObject *self, PyObject *args)
1893
return _forward_call(self->writer, "write", args);
1897
BufferedRWPair_flush(BufferedRWPairObject *self, PyObject *args)
1899
return _forward_call(self->writer, "flush", args);
1903
BufferedRWPair_readable(BufferedRWPairObject *self, PyObject *args)
1905
return _forward_call(self->reader, "readable", args);
1909
BufferedRWPair_writable(BufferedRWPairObject *self, PyObject *args)
1911
return _forward_call(self->writer, "writable", args);
1915
BufferedRWPair_close(BufferedRWPairObject *self, PyObject *args)
1917
PyObject *ret = _forward_call(self->writer, "close", args);
1922
return _forward_call(self->reader, "close", args);
1926
BufferedRWPair_isatty(BufferedRWPairObject *self, PyObject *args)
1928
PyObject *ret = _forward_call(self->writer, "isatty", args);
1930
if (ret != Py_False) {
1931
/* either True or exception */
1936
return _forward_call(self->reader, "isatty", args);
1940
static PyMethodDef BufferedRWPair_methods[] = {
1941
{"read", (PyCFunction)BufferedRWPair_read, METH_VARARGS},
1942
{"peek", (PyCFunction)BufferedRWPair_peek, METH_VARARGS},
1943
{"read1", (PyCFunction)BufferedRWPair_read1, METH_VARARGS},
1944
{"readinto", (PyCFunction)Buffered_readinto, METH_VARARGS},
1946
{"write", (PyCFunction)BufferedRWPair_write, METH_VARARGS},
1947
{"flush", (PyCFunction)BufferedRWPair_flush, METH_NOARGS},
1949
{"readable", (PyCFunction)BufferedRWPair_readable, METH_NOARGS},
1950
{"writable", (PyCFunction)BufferedRWPair_writable, METH_NOARGS},
1952
{"close", (PyCFunction)BufferedRWPair_close, METH_NOARGS},
1953
{"isatty", (PyCFunction)BufferedRWPair_isatty, METH_NOARGS},
1958
PyTypeObject PyBufferedRWPair_Type = {
1959
PyVarObject_HEAD_INIT(NULL, 0)
1960
"_io.BufferedRWPair", /*tp_name*/
1961
sizeof(BufferedRWPairObject), /*tp_basicsize*/
1963
(destructor)BufferedRWPair_dealloc, /*tp_dealloc*/
1970
0, /*tp_as_sequence*/
1971
0, /*tp_as_mapping*/
1978
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1979
| Py_TPFLAGS_HAVE_GC, /* tp_flags */
1980
BufferedRWPair_doc, /* tp_doc */
1981
(traverseproc)BufferedRWPair_traverse, /* tp_traverse */
1982
(inquiry)BufferedRWPair_clear, /* tp_clear */
1983
0, /* tp_richcompare */
1984
offsetof(BufferedRWPairObject, weakreflist), /*tp_weaklistoffset*/
1986
0, /* tp_iternext */
1987
BufferedRWPair_methods, /* tp_methods */
1992
0, /* tp_descr_get */
1993
0, /* tp_descr_set */
1994
offsetof(BufferedRWPairObject, dict), /* tp_dictoffset */
1995
(initproc)BufferedRWPair_init, /* tp_init */
1997
PyType_GenericNew, /* tp_new */
2006
PyDoc_STRVAR(BufferedRandom_doc,
2007
"A buffered interface to random access streams.\n"
2009
"The constructor creates a reader and writer for a seekable stream,\n"
2010
"raw, given in the first argument. If the buffer_size is omitted it\n"
2011
"defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2015
BufferedRandom_init(BufferedObject *self, PyObject *args, PyObject *kwds)
2017
char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2018
Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
2019
Py_ssize_t max_buffer_size = -1;
2024
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2025
&raw, &buffer_size, &max_buffer_size)) {
2029
if (_PyIOBase_checkSeekable(raw, Py_True) == NULL)
2031
if (_PyIOBase_checkReadable(raw, Py_True) == NULL)
2033
if (_PyIOBase_checkWritable(raw, Py_True) == NULL)
2036
Py_CLEAR(self->raw);
2039
self->buffer_size = buffer_size;
2043
if (_Buffered_init(self) < 0)
2045
_BufferedReader_reset_buf(self);
2046
_BufferedWriter_reset_buf(self);
2053
static PyMethodDef BufferedRandom_methods[] = {
2054
/* BufferedIOMixin methods */
2055
{"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS},
2056
{"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS},
2057
{"readable", (PyCFunction)BufferedIOMixin_readable, METH_NOARGS},
2058
{"writable", (PyCFunction)BufferedIOMixin_writable, METH_NOARGS},
2059
{"fileno", (PyCFunction)BufferedIOMixin_fileno, METH_NOARGS},
2060
{"isatty", (PyCFunction)BufferedIOMixin_isatty, METH_NOARGS},
2062
{"flush", (PyCFunction)Buffered_flush, METH_NOARGS},
2064
{"seek", (PyCFunction)Buffered_seek, METH_VARARGS},
2065
{"tell", (PyCFunction)Buffered_tell, METH_NOARGS},
2066
{"truncate", (PyCFunction)Buffered_truncate, METH_VARARGS},
2067
{"read", (PyCFunction)Buffered_read, METH_VARARGS},
2068
{"read1", (PyCFunction)Buffered_read1, METH_VARARGS},
2069
{"readinto", (PyCFunction)Buffered_readinto, METH_VARARGS},
2070
{"readline", (PyCFunction)Buffered_readline, METH_VARARGS},
2071
{"peek", (PyCFunction)Buffered_peek, METH_VARARGS},
2072
{"write", (PyCFunction)BufferedWriter_write, METH_VARARGS},
2076
static PyMemberDef BufferedRandom_members[] = {
2077
{"raw", T_OBJECT, offsetof(BufferedObject, raw), 0},
2081
static PyGetSetDef BufferedRandom_getset[] = {
2082
{"closed", (getter)BufferedIOMixin_closed_get, NULL, NULL},
2083
{"name", (getter)BufferedIOMixin_name_get, NULL, NULL},
2084
{"mode", (getter)BufferedIOMixin_mode_get, NULL, NULL},
2089
PyTypeObject PyBufferedRandom_Type = {
2090
PyVarObject_HEAD_INIT(NULL, 0)
2091
"_io.BufferedRandom", /*tp_name*/
2092
sizeof(BufferedObject), /*tp_basicsize*/
2094
(destructor)BufferedObject_dealloc, /*tp_dealloc*/
2101
0, /*tp_as_sequence*/
2102
0, /*tp_as_mapping*/
2109
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2110
| Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2111
BufferedRandom_doc, /* tp_doc */
2112
(traverseproc)Buffered_traverse, /* tp_traverse */
2113
(inquiry)Buffered_clear, /* tp_clear */
2114
0, /* tp_richcompare */
2115
offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/
2117
(iternextfunc)Buffered_iternext, /* tp_iternext */
2118
BufferedRandom_methods, /* tp_methods */
2119
BufferedRandom_members, /* tp_members */
2120
BufferedRandom_getset, /* tp_getset */
2123
0, /* tp_descr_get */
2124
0, /* tp_descr_set */
2125
offsetof(BufferedObject, dict), /*tp_dictoffset*/
2126
(initproc)BufferedRandom_init, /* tp_init */
2128
PyType_GenericNew, /* tp_new */