Buffered I/O: optimize lock taking in the common non-contended case.
[python.git] / Modules / _io / bufferedio.c
blob9aa7d4b8b8c40c4270bec4644431a8cc5a8a3a86
1 /*
2 An implementation of Buffered I/O as defined by PEP 3116 - "New I/O"
4 Classes defined here: BufferedIOBase, BufferedReader, BufferedWriter,
5 BufferedRandom.
7 Written by Amaury Forgeot d'Arc and Antoine Pitrou
8 */
10 #define PY_SSIZE_T_CLEAN
11 #include "Python.h"
12 #include "structmember.h"
13 #include "pythread.h"
14 #include "_iomodule.h"
17 * BufferedIOBase class, inherits from IOBase.
19 PyDoc_STRVAR(bufferediobase_doc,
20 "Base class for buffered IO objects.\n"
21 "\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"
25 "\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"
29 "return None.\n"
30 "\n"
31 "A typical implementation should not inherit from a RawIOBase\n"
32 "implementation, but wrap one.\n"
35 static PyObject *
36 bufferediobase_readinto(PyObject *self, PyObject *args)
38 Py_buffer buf;
39 Py_ssize_t len;
40 PyObject *data;
42 if (!PyArg_ParseTuple(args, "w*:readinto", &buf)) {
43 return NULL;
46 data = PyObject_CallMethod(self, "read", "n", buf.len);
47 if (data == NULL)
48 goto error;
50 if (!PyBytes_Check(data)) {
51 Py_DECREF(data);
52 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
53 goto error;
56 len = Py_SIZE(data);
57 memcpy(buf.buf, PyBytes_AS_STRING(data), len);
59 PyBuffer_Release(&buf);
60 Py_DECREF(data);
62 return PyLong_FromSsize_t(len);
64 error:
65 PyBuffer_Release(&buf);
66 return NULL;
69 static PyObject *
70 bufferediobase_unsupported(const char *message)
72 PyErr_SetString(_PyIO_unsupported_operation, message);
73 return NULL;
76 PyDoc_STRVAR(bufferediobase_detach_doc,
77 "Disconnect this buffer from its underlying raw stream and return it.\n"
78 "\n"
79 "After the raw stream has been detached, the buffer is in an unusable\n"
80 "state.\n");
82 static PyObject *
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"
90 "\n"
91 "If the argument is omitted, None, or negative, reads and\n"
92 "returns all data until EOF.\n"
93 "\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"
100 "\n"
101 "Returns an empty bytes object on EOF.\n"
102 "\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");
106 static PyObject *
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"
116 "\n"
117 "Returns an empty bytes object on EOF.\n");
119 static PyObject *
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"
127 "\n"
128 "Returns the number of bytes written, which is never less than\n"
129 "len(b).\n"
130 "\n"
131 "Raises BlockingIOError if the buffer is full and the\n"
132 "underlying raw stream cannot accept more data at the moment.\n");
134 static PyObject *
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},
147 {NULL, NULL}
150 PyTypeObject PyBufferedIOBase_Type = {
151 PyVarObject_HEAD_INIT(NULL, 0)
152 "_io._BufferedIOBase", /*tp_name*/
153 0, /*tp_basicsize*/
154 0, /*tp_itemsize*/
155 0, /*tp_dealloc*/
156 0, /*tp_print*/
157 0, /*tp_getattr*/
158 0, /*tp_setattr*/
159 0, /*tp_compare */
160 0, /*tp_repr*/
161 0, /*tp_as_number*/
162 0, /*tp_as_sequence*/
163 0, /*tp_as_mapping*/
164 0, /*tp_hash */
165 0, /*tp_call*/
166 0, /*tp_str*/
167 0, /*tp_getattro*/
168 0, /*tp_setattro*/
169 0, /*tp_as_buffer*/
170 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
171 bufferediobase_doc, /* tp_doc */
172 0, /* tp_traverse */
173 0, /* tp_clear */
174 0, /* tp_richcompare */
175 0, /* tp_weaklistoffset */
176 0, /* tp_iter */
177 0, /* tp_iternext */
178 bufferediobase_methods, /* tp_methods */
179 0, /* tp_members */
180 0, /* tp_getset */
181 &PyIOBase_Type, /* tp_base */
182 0, /* tp_dict */
183 0, /* tp_descr_get */
184 0, /* tp_descr_set */
185 0, /* tp_dictoffset */
186 0, /* tp_init */
187 0, /* tp_alloc */
188 0, /* tp_new */
192 typedef struct {
193 PyObject_HEAD
195 PyObject *raw;
196 int ok; /* Initialized? */
197 int detached;
198 int readable;
199 int writable;
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). */
206 Py_off_t abs_pos;
208 /* A static buffer of size `buffer_size` */
209 char *buffer;
210 /* Current logical position in the buffer. */
211 Py_off_t pos;
212 /* Position of the raw stream in the buffer. */
213 Py_off_t raw_pos;
215 /* Just after the last buffered byte in the buffer, or -1 if the buffer
216 isn't ready for reading. */
217 Py_off_t read_end;
219 /* Just after the last byte actually written */
220 Py_off_t write_pos;
221 /* Just after the last byte waiting to be written, or -1 if the buffer
222 isn't ready for writing. */
223 Py_off_t write_end;
225 #ifdef WITH_THREAD
226 PyThread_type_lock lock;
227 #endif
229 Py_ssize_t buffer_size;
230 Py_ssize_t buffer_mask;
232 PyObject *dict;
233 PyObject *weakreflist;
234 } buffered;
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. */
261 #ifdef WITH_THREAD
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);
271 #else
272 #define ENTER_BUFFERED(self)
273 #define LEAVE_BUFFERED(self)
274 #endif
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"); \
281 } else { \
282 PyErr_SetString(PyExc_ValueError, \
283 "I/O operation on uninitialized object"); \
285 return NULL; \
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"); \
293 } else { \
294 PyErr_SetString(PyExc_ValueError, \
295 "I/O operation on uninitialized object"); \
297 return -1; \
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); \
308 return NULL; \
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) \
319 do { \
320 self->pos = _new_pos; \
321 if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
322 self->read_end = self->pos; \
323 } while(0)
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)))
342 static void
343 buffered_dealloc(buffered *self)
345 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
346 return;
347 _PyObject_GC_UNTRACK(self);
348 self->ok = 0;
349 if (self->weakreflist != NULL)
350 PyObject_ClearWeakRefs((PyObject *)self);
351 Py_CLEAR(self->raw);
352 if (self->buffer) {
353 PyMem_Free(self->buffer);
354 self->buffer = NULL;
356 #ifdef WITH_THREAD
357 if (self->lock) {
358 PyThread_free_lock(self->lock);
359 self->lock = NULL;
361 #endif
362 Py_CLEAR(self->dict);
363 Py_TYPE(self)->tp_free((PyObject *)self);
366 static int
367 buffered_traverse(buffered *self, visitproc visit, void *arg)
369 Py_VISIT(self->raw);
370 Py_VISIT(self->dict);
371 return 0;
374 static int
375 buffered_clear(buffered *self)
377 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
378 return -1;
379 self->ok = 0;
380 Py_CLEAR(self->raw);
381 Py_CLEAR(self->dict);
382 return 0;
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 */
393 static PyObject *
394 buffered_simple_flush(buffered *self, PyObject *args)
396 CHECK_INITIALIZED(self)
397 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
400 static int
401 buffered_closed(buffered *self)
403 int closed;
404 PyObject *res;
405 CHECK_INITIALIZED_INT(self)
406 res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
407 if (res == NULL)
408 return -1;
409 closed = PyObject_IsTrue(res);
410 Py_DECREF(res);
411 return closed;
414 static PyObject *
415 buffered_closed_get(buffered *self, void *context)
417 CHECK_INITIALIZED(self)
418 return PyObject_GetAttr(self->raw, _PyIO_str_closed);
421 static PyObject *
422 buffered_close(buffered *self, PyObject *args)
424 PyObject *res = NULL;
425 int r;
427 CHECK_INITIALIZED(self)
428 ENTER_BUFFERED(self)
430 r = buffered_closed(self);
431 if (r < 0)
432 goto end;
433 if (r > 0) {
434 res = Py_None;
435 Py_INCREF(res);
436 goto end;
438 /* flush() will most probably re-take the lock, so drop it first */
439 LEAVE_BUFFERED(self)
440 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
441 ENTER_BUFFERED(self)
442 if (res == NULL) {
443 /* If flush() fails, just give up */
444 if (PyErr_ExceptionMatches(PyExc_IOError))
445 PyErr_Clear();
446 else
447 goto end;
449 Py_XDECREF(res);
451 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
453 end:
454 LEAVE_BUFFERED(self)
455 return res;
458 /* detach */
460 static PyObject *
461 buffered_detach(buffered *self, PyObject *args)
463 PyObject *raw, *res;
464 CHECK_INITIALIZED(self)
465 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
466 if (res == NULL)
467 return NULL;
468 Py_DECREF(res);
469 raw = self->raw;
470 self->raw = NULL;
471 self->detached = 1;
472 self->ok = 0;
473 return raw;
476 /* Inquiries */
478 static PyObject *
479 buffered_seekable(buffered *self, PyObject *args)
481 CHECK_INITIALIZED(self)
482 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
485 static PyObject *
486 buffered_readable(buffered *self, PyObject *args)
488 CHECK_INITIALIZED(self)
489 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
492 static PyObject *
493 buffered_writable(buffered *self, PyObject *args)
495 CHECK_INITIALIZED(self)
496 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
499 static PyObject *
500 buffered_name_get(buffered *self, void *context)
502 CHECK_INITIALIZED(self)
503 return PyObject_GetAttrString(self->raw, "name");
506 static PyObject *
507 buffered_mode_get(buffered *self, void *context)
509 CHECK_INITIALIZED(self)
510 return PyObject_GetAttrString(self->raw, "mode");
513 /* Lower-level APIs */
515 static PyObject *
516 buffered_fileno(buffered *self, PyObject *args)
518 CHECK_INITIALIZED(self)
519 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
522 static PyObject *
523 buffered_isatty(buffered *self, PyObject *args)
525 CHECK_INITIALIZED(self)
526 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
530 /* Forward decls */
531 static PyObject *
532 _bufferedwriter_flush_unlocked(buffered *, int);
533 static Py_ssize_t
534 _bufferedreader_fill_buffer(buffered *self);
535 static void
536 _bufferedreader_reset_buf(buffered *self);
537 static void
538 _bufferedwriter_reset_buf(buffered *self);
539 static PyObject *
540 _bufferedreader_peek_unlocked(buffered *self, Py_ssize_t);
541 static PyObject *
542 _bufferedreader_read_all(buffered *self);
543 static PyObject *
544 _bufferedreader_read_fast(buffered *self, Py_ssize_t);
545 static PyObject *
546 _bufferedreader_read_generic(buffered *self, Py_ssize_t);
550 * Helpers
553 /* Returns the address of the `written` member if a BlockingIOError was
554 raised, NULL otherwise. The error is always re-raised. */
555 static Py_ssize_t *
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);
564 return NULL;
566 err = (PyBlockingIOErrorObject *) v;
567 /* TODO: sanity check (err->written >= 0) */
568 PyErr_Restore(t, v, tb);
569 return &err->written;
572 static Py_off_t
573 _buffered_raw_tell(buffered *self)
575 Py_off_t n;
576 PyObject *res;
577 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
578 if (res == NULL)
579 return -1;
580 n = PyNumber_AsOff_t(res, PyExc_ValueError);
581 Py_DECREF(res);
582 if (n < 0) {
583 if (!PyErr_Occurred())
584 PyErr_Format(PyExc_IOError,
585 "Raw stream returned invalid position %zd", n);
586 return -1;
588 self->abs_pos = n;
589 return n;
592 static Py_off_t
593 _buffered_raw_seek(buffered *self, Py_off_t target, int whence)
595 PyObject *res, *posobj, *whenceobj;
596 Py_off_t n;
598 posobj = PyLong_FromOff_t(target);
599 if (posobj == NULL)
600 return -1;
601 whenceobj = PyLong_FromLong(whence);
602 if (whenceobj == NULL) {
603 Py_DECREF(posobj);
604 return -1;
606 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
607 posobj, whenceobj, NULL);
608 Py_DECREF(posobj);
609 Py_DECREF(whenceobj);
610 if (res == NULL)
611 return -1;
612 n = PyNumber_AsOff_t(res, PyExc_ValueError);
613 Py_DECREF(res);
614 if (n < 0) {
615 if (!PyErr_Occurred())
616 PyErr_Format(PyExc_IOError,
617 "Raw stream returned invalid position %zd", n);
618 return -1;
620 self->abs_pos = n;
621 return n;
624 static int
625 _buffered_init(buffered *self)
627 Py_ssize_t n;
628 if (self->buffer_size <= 0) {
629 PyErr_SetString(PyExc_ValueError,
630 "buffer size must be strictly positive");
631 return -1;
633 if (self->buffer)
634 PyMem_Free(self->buffer);
635 self->buffer = PyMem_Malloc(self->buffer_size);
636 if (self->buffer == NULL) {
637 PyErr_NoMemory();
638 return -1;
640 #ifdef WITH_THREAD
641 self->lock = PyThread_allocate_lock();
642 if (self->lock == NULL) {
643 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
644 return -1;
646 #endif
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)
651 if (n == 0)
652 self->buffer_mask = self->buffer_size - 1;
653 else
654 self->buffer_mask = 0;
655 if (_buffered_raw_tell(self) == -1)
656 PyErr_Clear();
657 return 0;
661 * Shared methods and wrappers
664 static PyObject *
665 buffered_flush(buffered *self, PyObject *args)
667 PyObject *res;
669 CHECK_INITIALIZED(self)
670 CHECK_CLOSED(self, "flush of closed file")
672 ENTER_BUFFERED(self)
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. */
677 Py_off_t n;
678 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
679 if (n == -1)
680 Py_CLEAR(res);
681 _bufferedreader_reset_buf(self);
683 LEAVE_BUFFERED(self)
685 return res;
688 static PyObject *
689 buffered_peek(buffered *self, PyObject *args)
691 Py_ssize_t n = 0;
692 PyObject *res = NULL;
694 CHECK_INITIALIZED(self)
695 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
696 return NULL;
699 ENTER_BUFFERED(self)
701 if (self->writable) {
702 res = _bufferedwriter_flush_unlocked(self, 1);
703 if (res == NULL)
704 goto end;
705 Py_CLEAR(res);
707 res = _bufferedreader_peek_unlocked(self, n);
709 end:
710 LEAVE_BUFFERED(self)
711 return res;
714 static PyObject *
715 buffered_read(buffered *self, PyObject *args)
717 Py_ssize_t n = -1;
718 PyObject *res;
720 CHECK_INITIALIZED(self)
721 if (!PyArg_ParseTuple(args, "|n:read", &n)) {
722 return NULL;
724 if (n < -1) {
725 PyErr_SetString(PyExc_ValueError,
726 "read length must be positive or -1");
727 return NULL;
730 CHECK_CLOSED(self, "read of closed file")
732 if (n == -1) {
733 /* The number of bytes is unspecified, read until the end of stream */
734 ENTER_BUFFERED(self)
735 res = _bufferedreader_read_all(self);
736 LEAVE_BUFFERED(self)
738 else {
739 res = _bufferedreader_read_fast(self, n);
740 if (res == Py_None) {
741 Py_DECREF(res);
742 ENTER_BUFFERED(self)
743 res = _bufferedreader_read_generic(self, n);
744 LEAVE_BUFFERED(self)
748 return res;
751 static PyObject *
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)) {
759 return NULL;
762 if (n < 0) {
763 PyErr_SetString(PyExc_ValueError,
764 "read length must be positive");
765 return NULL;
767 if (n == 0)
768 return PyBytes_FromStringAndSize(NULL, 0);
770 ENTER_BUFFERED(self)
772 if (self->writable) {
773 res = _bufferedwriter_flush_unlocked(self, 1);
774 if (res == NULL)
775 goto end;
776 Py_CLEAR(res);
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);
788 if (have > 0) {
789 if (n > have)
790 n = have;
791 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
792 if (res == NULL)
793 goto end;
794 self->pos += n;
795 goto end;
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);
801 if (r == -1)
802 goto end;
803 if (r == -2)
804 r = 0;
805 if (n > r)
806 n = r;
807 res = PyBytes_FromStringAndSize(self->buffer, n);
808 if (res == NULL)
809 goto end;
810 self->pos = n;
812 end:
813 LEAVE_BUFFERED(self)
814 return res;
817 static PyObject *
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) {
826 ENTER_BUFFERED(self)
827 res = _bufferedwriter_flush_unlocked(self, 0);
828 LEAVE_BUFFERED(self)
829 if (res == NULL)
830 goto end;
831 Py_DECREF(res);
833 res = bufferediobase_readinto((PyObject *)self, args);
835 end:
836 return res;
839 static PyObject *
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)
854 n = limit;
855 start = self->buffer + self->pos;
856 s = memchr(start, '\n', n);
857 if (s != NULL) {
858 res = PyBytes_FromStringAndSize(start, s - start + 1);
859 if (res != NULL)
860 self->pos += s - start + 1;
861 goto end_unlocked;
863 if (n == limit) {
864 res = PyBytes_FromStringAndSize(start, n);
865 if (res != NULL)
866 self->pos += n;
867 goto end_unlocked;
870 ENTER_BUFFERED(self)
872 /* Now we try to get some more from the raw stream */
873 if (self->writable) {
874 res = _bufferedwriter_flush_unlocked(self, 1);
875 if (res == NULL)
876 goto end;
877 Py_CLEAR(res);
879 chunks = PyList_New(0);
880 if (chunks == NULL)
881 goto end;
882 if (n > 0) {
883 res = PyBytes_FromStringAndSize(start, n);
884 if (res == NULL)
885 goto end;
886 if (PyList_Append(chunks, res) < 0) {
887 Py_CLEAR(res);
888 goto end;
890 Py_CLEAR(res);
891 written += n;
892 if (limit >= 0)
893 limit -= n;
896 for (;;) {
897 _bufferedreader_reset_buf(self);
898 n = _bufferedreader_fill_buffer(self);
899 if (n == -1)
900 goto end;
901 if (n <= 0)
902 break;
903 if (limit >= 0 && n > limit)
904 n = limit;
905 start = self->buffer;
906 end = start + n;
907 s = start;
908 while (s < end) {
909 if (*s++ == '\n') {
910 res = PyBytes_FromStringAndSize(start, s - start);
911 if (res == NULL)
912 goto end;
913 self->pos = s - start;
914 goto found;
917 res = PyBytes_FromStringAndSize(start, n);
918 if (res == NULL)
919 goto end;
920 if (n == limit) {
921 self->pos = n;
922 break;
924 if (PyList_Append(chunks, res) < 0) {
925 Py_CLEAR(res);
926 goto end;
928 Py_CLEAR(res);
929 written += n;
930 if (limit >= 0)
931 limit -= n;
933 found:
934 if (res != NULL && PyList_Append(chunks, res) < 0) {
935 Py_CLEAR(res);
936 goto end;
938 Py_CLEAR(res);
939 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
941 end:
942 LEAVE_BUFFERED(self)
943 end_unlocked:
944 Py_XDECREF(chunks);
945 return res;
948 static PyObject *
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)) {
957 return NULL;
959 if (limitobj) {
960 if (!PyNumber_Check(limitobj)) {
961 PyErr_Format(PyExc_TypeError,
962 "integer argument expected, got '%.200s'",
963 Py_TYPE(limitobj)->tp_name);
964 return NULL;
966 limit = PyNumber_AsSsize_t(limitobj, PyExc_OverflowError);
967 if (limit == -1 && PyErr_Occurred())
968 return NULL;
970 return _buffered_readline(self, limit);
974 static PyObject *
975 buffered_tell(buffered *self, PyObject *args)
977 Py_off_t pos;
979 CHECK_INITIALIZED(self)
980 pos = _buffered_raw_tell(self);
981 if (pos == -1)
982 return NULL;
983 pos -= RAW_OFFSET(self);
984 /* TODO: sanity check (pos >= 0) */
985 return PyLong_FromOff_t(pos);
988 static PyObject *
989 buffered_seek(buffered *self, PyObject *args)
991 Py_off_t target, n;
992 int whence = 0;
993 PyObject *targetobj, *res = NULL;
995 CHECK_INITIALIZED(self)
996 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
997 return NULL;
999 if (whence < 0 || whence > 2) {
1000 PyErr_Format(PyExc_ValueError,
1001 "whence must be between 0 and 2, not %d", whence);
1002 return NULL;
1005 CHECK_CLOSED(self, "seek of closed file")
1007 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1008 if (target == -1 && PyErr_Occurred())
1009 return NULL;
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);
1021 if (avail > 0) {
1022 Py_off_t offset;
1023 if (whence == 0)
1024 offset = target - (current - RAW_OFFSET(self));
1025 else
1026 offset = target;
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);
1039 if (res == NULL)
1040 goto end;
1041 Py_CLEAR(res);
1042 _bufferedwriter_reset_buf(self);
1045 /* TODO: align on block boundary and read buffer if needed? */
1046 if (whence == 1)
1047 target -= RAW_OFFSET(self);
1048 n = _buffered_raw_seek(self, target, whence);
1049 if (n == -1)
1050 goto end;
1051 self->raw_pos = -1;
1052 res = PyLong_FromOff_t(n);
1053 if (res != NULL && self->readable)
1054 _bufferedreader_reset_buf(self);
1056 end:
1057 LEAVE_BUFFERED(self)
1058 return res;
1061 static PyObject *
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)) {
1069 return NULL;
1072 ENTER_BUFFERED(self)
1074 if (self->writable) {
1075 res = _bufferedwriter_flush_unlocked(self, 0);
1076 if (res == NULL)
1077 goto end;
1078 Py_CLEAR(res);
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)
1085 goto end;
1087 _bufferedreader_reset_buf(self);
1089 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1090 if (res == NULL)
1091 goto end;
1092 /* Reset cached position */
1093 if (_buffered_raw_tell(self) == -1)
1094 PyErr_Clear();
1096 end:
1097 LEAVE_BUFFERED(self)
1098 return res;
1101 static PyObject *
1102 buffered_iternext(buffered *self)
1104 PyObject *line;
1105 PyTypeObject *tp;
1107 CHECK_INITIALIZED(self);
1109 tp = Py_TYPE(self);
1110 if (tp == &PyBufferedReader_Type ||
1111 tp == &PyBufferedRandom_Type) {
1112 /* Skip method call overhead for speed */
1113 line = _buffered_readline(self, -1);
1115 else {
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);
1122 Py_DECREF(line);
1123 return NULL;
1127 if (line == NULL)
1128 return NULL;
1130 if (PyBytes_GET_SIZE(line) == 0) {
1131 /* Reached EOF or would have blocked */
1132 Py_DECREF(line);
1133 return NULL;
1136 return line;
1139 static PyObject *
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))
1147 PyErr_Clear();
1148 else
1149 return NULL;
1150 res = PyString_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1152 else {
1153 PyObject *repr = PyObject_Repr(nameobj);
1154 Py_DECREF(nameobj);
1155 if (repr == NULL)
1156 return NULL;
1157 res = PyString_FromFormat("<%s name=%s>",
1158 Py_TYPE(self)->tp_name,
1159 PyString_AS_STRING(repr));
1160 Py_DECREF(repr);
1162 return res;
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;
1177 static int
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;
1182 PyObject *raw;
1184 self->ok = 0;
1185 self->detached = 0;
1187 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1188 &raw, &buffer_size)) {
1189 return -1;
1192 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
1193 return -1;
1195 Py_CLEAR(self->raw);
1196 Py_INCREF(raw);
1197 self->raw = raw;
1198 self->buffer_size = buffer_size;
1199 self->readable = 1;
1200 self->writable = 0;
1202 if (_buffered_init(self) < 0)
1203 return -1;
1204 _bufferedreader_reset_buf(self);
1206 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1207 Py_TYPE(raw) == &PyFileIO_Type);
1209 self->ok = 1;
1210 return 0;
1213 static Py_ssize_t
1214 _bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
1216 Py_buffer buf;
1217 PyObject *memobj, *res;
1218 Py_ssize_t n;
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)
1221 return -1;
1222 memobj = PyMemoryView_FromBuffer(&buf);
1223 if (memobj == NULL)
1224 return -1;
1225 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1226 Py_DECREF(memobj);
1227 if (res == NULL)
1228 return -1;
1229 if (res == Py_None) {
1230 /* Non-blocking stream would have blocked. Special return code! */
1231 Py_DECREF(res);
1232 return -2;
1234 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1235 Py_DECREF(res);
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);
1240 return -1;
1242 if (n > 0 && self->abs_pos != -1)
1243 self->abs_pos += n;
1244 return n;
1247 static Py_ssize_t
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);
1253 else
1254 start = 0;
1255 len = self->buffer_size - start;
1256 n = _bufferedreader_raw_read(self, self->buffer + start, len);
1257 if (n <= 0)
1258 return n;
1259 self->read_end = start + n;
1260 self->raw_pos = start + n;
1261 return n;
1264 static PyObject *
1265 _bufferedreader_read_all(buffered *self)
1267 Py_ssize_t current_size;
1268 PyObject *res, *data = NULL;
1269 PyObject *chunks = PyList_New(0);
1271 if (chunks == NULL)
1272 return NULL;
1274 /* First copy what we have in the current buffer. */
1275 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1276 if (current_size) {
1277 data = PyBytes_FromStringAndSize(
1278 self->buffer + self->pos, current_size);
1279 if (data == NULL) {
1280 Py_DECREF(chunks);
1281 return NULL;
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);
1288 if (res == NULL) {
1289 Py_DECREF(chunks);
1290 return NULL;
1292 Py_CLEAR(res);
1294 while (1) {
1295 if (data) {
1296 if (PyList_Append(chunks, data) < 0) {
1297 Py_DECREF(data);
1298 Py_DECREF(chunks);
1299 return NULL;
1301 Py_DECREF(data);
1304 /* Read until EOF or until read() would block. */
1305 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1306 if (data == NULL) {
1307 Py_DECREF(chunks);
1308 return NULL;
1310 if (data != Py_None && !PyBytes_Check(data)) {
1311 Py_DECREF(data);
1312 Py_DECREF(chunks);
1313 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1314 return NULL;
1316 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1317 if (current_size == 0) {
1318 Py_DECREF(chunks);
1319 return data;
1321 else {
1322 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1323 Py_DECREF(data);
1324 Py_DECREF(chunks);
1325 return res;
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. */
1336 static PyObject *
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);
1345 if (res != NULL)
1346 self->pos += n;
1347 return res;
1349 Py_RETURN_NONE;
1352 /* Generic read function: read from the stream until enough bytes are read,
1353 * or until an EOF occurs or until read() would block.
1355 static PyObject *
1356 _bufferedreader_read_generic(buffered *self, Py_ssize_t n)
1358 PyObject *res = NULL;
1359 Py_ssize_t current_size, remaining, written;
1360 char *out;
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);
1367 if (res == NULL)
1368 goto error;
1369 out = PyBytes_AS_STRING(res);
1370 remaining = n;
1371 written = 0;
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);
1382 if (r == 0)
1383 break;
1384 r = _bufferedreader_raw_read(self, out + written, r);
1385 if (r == -1)
1386 goto error;
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))
1391 goto error;
1392 return res;
1394 Py_DECREF(res);
1395 Py_INCREF(Py_None);
1396 return Py_None;
1398 remaining -= r;
1399 written += r;
1401 assert(remaining <= self->buffer_size);
1402 self->pos = 0;
1403 self->raw_pos = 0;
1404 self->read_end = 0;
1405 while (self->read_end < self->buffer_size) {
1406 Py_ssize_t r = _bufferedreader_fill_buffer(self);
1407 if (r == -1)
1408 goto error;
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))
1413 goto error;
1414 return res;
1416 Py_DECREF(res);
1417 Py_INCREF(Py_None);
1418 return Py_None;
1420 if (remaining > r) {
1421 memcpy(out + written, self->buffer + self->pos, r);
1422 written += r;
1423 self->pos += r;
1424 remaining -= r;
1426 else if (remaining > 0) {
1427 memcpy(out + written, self->buffer + self->pos, remaining);
1428 written += remaining;
1429 self->pos += remaining;
1430 remaining = 0;
1432 if (remaining == 0)
1433 break;
1436 return res;
1438 error:
1439 Py_XDECREF(res);
1440 return NULL;
1443 static PyObject *
1444 _bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
1446 Py_ssize_t have, r;
1448 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1449 /* Constraints:
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
1452 to make some place.
1453 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1455 if (have > 0) {
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);
1462 if (r == -1)
1463 return NULL;
1464 if (r == -2)
1465 r = 0;
1466 self->pos = 0;
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},
1488 {NULL, NULL}
1491 static PyMemberDef bufferedreader_members[] = {
1492 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
1493 {NULL}
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},
1500 {NULL}
1504 PyTypeObject PyBufferedReader_Type = {
1505 PyVarObject_HEAD_INIT(NULL, 0)
1506 "_io.BufferedReader", /*tp_name*/
1507 sizeof(buffered), /*tp_basicsize*/
1508 0, /*tp_itemsize*/
1509 (destructor)buffered_dealloc, /*tp_dealloc*/
1510 0, /*tp_print*/
1511 0, /*tp_getattr*/
1512 0, /*tp_setattr*/
1513 0, /*tp_compare */
1514 (reprfunc)buffered_repr, /*tp_repr*/
1515 0, /*tp_as_number*/
1516 0, /*tp_as_sequence*/
1517 0, /*tp_as_mapping*/
1518 0, /*tp_hash */
1519 0, /*tp_call*/
1520 0, /*tp_str*/
1521 0, /*tp_getattro*/
1522 0, /*tp_setattro*/
1523 0, /*tp_as_buffer*/
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*/
1531 0, /* tp_iter */
1532 (iternextfunc)buffered_iternext, /* tp_iternext */
1533 bufferedreader_methods, /* tp_methods */
1534 bufferedreader_members, /* tp_members */
1535 bufferedreader_getset, /* tp_getset */
1536 0, /* tp_base */
1537 0, /* tp_dict */
1538 0, /* tp_descr_get */
1539 0, /* tp_descr_set */
1540 offsetof(buffered, dict), /* tp_dictoffset */
1541 (initproc)bufferedreader_init, /* tp_init */
1542 0, /* tp_alloc */
1543 PyType_GenericNew, /* tp_new */
1548 static int
1549 complain_about_max_buffer_size(void)
1551 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1552 "max_buffer_size is deprecated", 1) < 0)
1553 return 0;
1554 return 1;
1558 * class BufferedWriter
1560 PyDoc_STRVAR(bufferedwriter_doc,
1561 "A buffer for a writeable sequential RawIO object.\n"
1562 "\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"
1568 static void
1569 _bufferedwriter_reset_buf(buffered *self)
1571 self->write_pos = 0;
1572 self->write_end = -1;
1575 static int
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;
1582 PyObject *raw;
1584 self->ok = 0;
1585 self->detached = 0;
1587 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1588 &raw, &buffer_size, &max_buffer_size)) {
1589 return -1;
1592 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1593 return -1;
1595 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
1596 return -1;
1598 Py_CLEAR(self->raw);
1599 Py_INCREF(raw);
1600 self->raw = raw;
1601 self->readable = 0;
1602 self->writable = 1;
1604 self->buffer_size = buffer_size;
1605 if (_buffered_init(self) < 0)
1606 return -1;
1607 _bufferedwriter_reset_buf(self);
1608 self->pos = 0;
1610 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1611 Py_TYPE(raw) == &PyFileIO_Type);
1613 self->ok = 1;
1614 return 0;
1617 static Py_ssize_t
1618 _bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
1620 Py_buffer buf;
1621 PyObject *memobj, *res;
1622 Py_ssize_t n;
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)
1625 return -1;
1626 memobj = PyMemoryView_FromBuffer(&buf);
1627 if (memobj == NULL)
1628 return -1;
1629 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1630 Py_DECREF(memobj);
1631 if (res == NULL)
1632 return -1;
1633 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1634 Py_DECREF(res);
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);
1639 return -1;
1641 if (n > 0 && self->abs_pos != -1)
1642 self->abs_pos += n;
1643 return n;
1646 /* `restore_pos` is 1 if we need to restore the raw stream position at
1647 the end, 0 otherwise. */
1648 static PyObject *
1649 _bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
1651 Py_ssize_t written = 0;
1652 Py_off_t n, rewind;
1654 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1655 goto end;
1656 /* First, rewind */
1657 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1658 if (rewind != 0) {
1659 n = _buffered_raw_seek(self, -rewind, 1);
1660 if (n < 0) {
1661 goto error;
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));
1670 if (n == -1) {
1671 Py_ssize_t *w = _buffered_check_blocking_error();
1672 if (w == NULL)
1673 goto error;
1674 self->write_pos += *w;
1675 self->raw_pos = self->write_pos;
1676 written += *w;
1677 *w = written;
1678 /* Already re-raised */
1679 goto error;
1681 self->write_pos += n;
1682 self->raw_pos = self->write_pos;
1683 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1686 if (restore_pos) {
1687 Py_off_t forward = rewind - written;
1688 if (forward != 0) {
1689 n = _buffered_raw_seek(self, forward, 1);
1690 if (n < 0) {
1691 goto error;
1693 self->raw_pos += forward;
1696 _bufferedwriter_reset_buf(self);
1698 end:
1699 Py_RETURN_NONE;
1701 error:
1702 return NULL;
1705 static PyObject *
1706 bufferedwriter_write(buffered *self, PyObject *args)
1708 PyObject *res = NULL;
1709 Py_buffer buf;
1710 Py_ssize_t written, avail, remaining;
1711 Py_off_t offset;
1713 CHECK_INITIALIZED(self)
1714 if (!PyArg_ParseTuple(args, "s*:write", &buf)) {
1715 return NULL;
1718 if (IS_CLOSED(self)) {
1719 PyErr_SetString(PyExc_ValueError, "write to closed file");
1720 PyBuffer_Release(&buf);
1721 return NULL;
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)) {
1728 self->pos = 0;
1729 self->raw_pos = 0;
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;
1740 written = buf.len;
1741 goto end;
1744 /* First write the current buffer */
1745 res = _bufferedwriter_flush_unlocked(self, 0);
1746 if (res == NULL) {
1747 Py_ssize_t *w = _buffered_check_blocking_error();
1748 if (w == NULL)
1749 goto error;
1750 if (self->readable)
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 */
1765 PyErr_Clear();
1766 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1767 self->write_end += buf.len;
1768 written = buf.len;
1769 goto end;
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 */
1775 *w = avail;
1776 goto error;
1778 Py_CLEAR(res);
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).
1784 Fixes issue #6629.
1786 offset = RAW_OFFSET(self);
1787 if (offset != 0) {
1788 if (_buffered_raw_seek(self, -offset, 1) < 0)
1789 goto error;
1790 self->raw_pos -= offset;
1793 /* Then write buf itself. At this point the buffer has been emptied. */
1794 remaining = buf.len;
1795 written = 0;
1796 while (remaining > self->buffer_size) {
1797 Py_ssize_t n = _bufferedwriter_raw_write(
1798 self, (char *) buf.buf + written, buf.len - written);
1799 if (n == -1) {
1800 Py_ssize_t *w = _buffered_check_blocking_error();
1801 if (w == NULL)
1802 goto error;
1803 written += *w;
1804 remaining -= *w;
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);
1809 self->raw_pos = 0;
1810 ADJUST_POSITION(self, self->buffer_size);
1811 self->write_end = self->buffer_size;
1812 *w = written + self->buffer_size;
1813 /* Already re-raised */
1814 goto error;
1816 PyErr_Clear();
1817 break;
1819 written += n;
1820 remaining -= n;
1822 if (self->readable)
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);
1832 self->raw_pos = 0;
1834 end:
1835 res = PyLong_FromSsize_t(written);
1837 error:
1838 LEAVE_BUFFERED(self)
1839 PyBuffer_Release(&buf);
1840 return res;
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},
1858 {NULL, NULL}
1861 static PyMemberDef bufferedwriter_members[] = {
1862 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
1863 {NULL}
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},
1870 {NULL}
1874 PyTypeObject PyBufferedWriter_Type = {
1875 PyVarObject_HEAD_INIT(NULL, 0)
1876 "_io.BufferedWriter", /*tp_name*/
1877 sizeof(buffered), /*tp_basicsize*/
1878 0, /*tp_itemsize*/
1879 (destructor)buffered_dealloc, /*tp_dealloc*/
1880 0, /*tp_print*/
1881 0, /*tp_getattr*/
1882 0, /*tp_setattr*/
1883 0, /*tp_compare */
1884 (reprfunc)buffered_repr, /*tp_repr*/
1885 0, /*tp_as_number*/
1886 0, /*tp_as_sequence*/
1887 0, /*tp_as_mapping*/
1888 0, /*tp_hash */
1889 0, /*tp_call*/
1890 0, /*tp_str*/
1891 0, /*tp_getattro*/
1892 0, /*tp_setattro*/
1893 0, /*tp_as_buffer*/
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*/
1901 0, /* tp_iter */
1902 0, /* tp_iternext */
1903 bufferedwriter_methods, /* tp_methods */
1904 bufferedwriter_members, /* tp_members */
1905 bufferedwriter_getset, /* tp_getset */
1906 0, /* tp_base */
1907 0, /* tp_dict */
1908 0, /* tp_descr_get */
1909 0, /* tp_descr_set */
1910 offsetof(buffered, dict), /* tp_dictoffset */
1911 (initproc)bufferedwriter_init, /* tp_init */
1912 0, /* tp_alloc */
1913 PyType_GenericNew, /* tp_new */
1919 * BufferedRWPair
1922 PyDoc_STRVAR(bufferedrwpair_doc,
1923 "A buffered reader and writer object together.\n"
1924 "\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"
1928 "\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
1935 * questionable.
1938 typedef struct {
1939 PyObject_HEAD
1940 buffered *reader;
1941 buffered *writer;
1942 PyObject *dict;
1943 PyObject *weakreflist;
1944 } rwpair;
1946 static int
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)) {
1955 return -1;
1958 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1959 return -1;
1961 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
1962 return -1;
1963 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
1964 return -1;
1966 self->reader = (buffered *) PyObject_CallFunction(
1967 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
1968 if (self->reader == NULL)
1969 return -1;
1971 self->writer = (buffered *) PyObject_CallFunction(
1972 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
1973 if (self->writer == NULL) {
1974 Py_CLEAR(self->reader);
1975 return -1;
1978 return 0;
1981 static int
1982 bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
1984 Py_VISIT(self->dict);
1985 return 0;
1988 static int
1989 bufferedrwpair_clear(rwpair *self)
1991 Py_CLEAR(self->reader);
1992 Py_CLEAR(self->writer);
1993 Py_CLEAR(self->dict);
1994 return 0;
1997 static void
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);
2007 static PyObject *
2008 _forward_call(buffered *self, const char *name, PyObject *args)
2010 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
2011 PyObject *ret;
2013 if (func == NULL) {
2014 PyErr_SetString(PyExc_AttributeError, name);
2015 return NULL;
2018 ret = PyObject_CallObject(func, args);
2019 Py_DECREF(func);
2020 return ret;
2023 static PyObject *
2024 bufferedrwpair_read(rwpair *self, PyObject *args)
2026 return _forward_call(self->reader, "read", args);
2029 static PyObject *
2030 bufferedrwpair_peek(rwpair *self, PyObject *args)
2032 return _forward_call(self->reader, "peek", args);
2035 static PyObject *
2036 bufferedrwpair_read1(rwpair *self, PyObject *args)
2038 return _forward_call(self->reader, "read1", args);
2041 static PyObject *
2042 bufferedrwpair_readinto(rwpair *self, PyObject *args)
2044 return _forward_call(self->reader, "readinto", args);
2047 static PyObject *
2048 bufferedrwpair_write(rwpair *self, PyObject *args)
2050 return _forward_call(self->writer, "write", args);
2053 static PyObject *
2054 bufferedrwpair_flush(rwpair *self, PyObject *args)
2056 return _forward_call(self->writer, "flush", args);
2059 static PyObject *
2060 bufferedrwpair_readable(rwpair *self, PyObject *args)
2062 return _forward_call(self->reader, "readable", args);
2065 static PyObject *
2066 bufferedrwpair_writable(rwpair *self, PyObject *args)
2068 return _forward_call(self->writer, "writable", args);
2071 static PyObject *
2072 bufferedrwpair_close(rwpair *self, PyObject *args)
2074 PyObject *ret = _forward_call(self->writer, "close", args);
2075 if (ret == NULL)
2076 return NULL;
2077 Py_DECREF(ret);
2079 return _forward_call(self->reader, "close", args);
2082 static PyObject *
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 */
2089 return ret;
2091 Py_DECREF(ret);
2093 return _forward_call(self->reader, "isatty", args);
2096 static PyObject *
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},
2117 {NULL, NULL}
2120 static PyGetSetDef bufferedrwpair_getset[] = {
2121 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
2122 {NULL}
2125 PyTypeObject PyBufferedRWPair_Type = {
2126 PyVarObject_HEAD_INIT(NULL, 0)
2127 "_io.BufferedRWPair", /*tp_name*/
2128 sizeof(rwpair), /*tp_basicsize*/
2129 0, /*tp_itemsize*/
2130 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
2131 0, /*tp_print*/
2132 0, /*tp_getattr*/
2133 0, /*tp_setattr*/
2134 0, /*tp_compare */
2135 0, /*tp_repr*/
2136 0, /*tp_as_number*/
2137 0, /*tp_as_sequence*/
2138 0, /*tp_as_mapping*/
2139 0, /*tp_hash */
2140 0, /*tp_call*/
2141 0, /*tp_str*/
2142 0, /*tp_getattro*/
2143 0, /*tp_setattro*/
2144 0, /*tp_as_buffer*/
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*/
2152 0, /* tp_iter */
2153 0, /* tp_iternext */
2154 bufferedrwpair_methods, /* tp_methods */
2155 0, /* tp_members */
2156 bufferedrwpair_getset, /* tp_getset */
2157 0, /* tp_base */
2158 0, /* tp_dict */
2159 0, /* tp_descr_get */
2160 0, /* tp_descr_set */
2161 offsetof(rwpair, dict), /* tp_dictoffset */
2162 (initproc)bufferedrwpair_init, /* tp_init */
2163 0, /* tp_alloc */
2164 PyType_GenericNew, /* tp_new */
2170 * BufferedRandom
2173 PyDoc_STRVAR(bufferedrandom_doc,
2174 "A buffered interface to random access streams.\n"
2175 "\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"
2181 static int
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;
2187 PyObject *raw;
2189 self->ok = 0;
2190 self->detached = 0;
2192 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2193 &raw, &buffer_size, &max_buffer_size)) {
2194 return -1;
2197 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2198 return -1;
2200 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
2201 return -1;
2202 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
2203 return -1;
2204 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
2205 return -1;
2207 Py_CLEAR(self->raw);
2208 Py_INCREF(raw);
2209 self->raw = raw;
2210 self->buffer_size = buffer_size;
2211 self->readable = 1;
2212 self->writable = 1;
2214 if (_buffered_init(self) < 0)
2215 return -1;
2216 _bufferedreader_reset_buf(self);
2217 _bufferedwriter_reset_buf(self);
2218 self->pos = 0;
2220 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2221 Py_TYPE(raw) == &PyFileIO_Type);
2223 self->ok = 1;
2224 return 0;
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},
2248 {NULL, NULL}
2251 static PyMemberDef bufferedrandom_members[] = {
2252 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
2253 {NULL}
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},
2260 {NULL}
2264 PyTypeObject PyBufferedRandom_Type = {
2265 PyVarObject_HEAD_INIT(NULL, 0)
2266 "_io.BufferedRandom", /*tp_name*/
2267 sizeof(buffered), /*tp_basicsize*/
2268 0, /*tp_itemsize*/
2269 (destructor)buffered_dealloc, /*tp_dealloc*/
2270 0, /*tp_print*/
2271 0, /*tp_getattr*/
2272 0, /*tp_setattr*/
2273 0, /*tp_compare */
2274 (reprfunc)buffered_repr, /*tp_repr*/
2275 0, /*tp_as_number*/
2276 0, /*tp_as_sequence*/
2277 0, /*tp_as_mapping*/
2278 0, /*tp_hash */
2279 0, /*tp_call*/
2280 0, /*tp_str*/
2281 0, /*tp_getattro*/
2282 0, /*tp_setattro*/
2283 0, /*tp_as_buffer*/
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*/
2291 0, /* tp_iter */
2292 (iternextfunc)buffered_iternext, /* tp_iternext */
2293 bufferedrandom_methods, /* tp_methods */
2294 bufferedrandom_members, /* tp_members */
2295 bufferedrandom_getset, /* tp_getset */
2296 0, /* tp_base */
2297 0, /*tp_dict*/
2298 0, /* tp_descr_get */
2299 0, /* tp_descr_set */
2300 offsetof(buffered, dict), /*tp_dictoffset*/
2301 (initproc)bufferedrandom_init, /* tp_init */
2302 0, /* tp_alloc */
2303 PyType_GenericNew, /* tp_new */