fix typo
[python.git] / Modules / _io / bufferedio.c
blob3ab7906a9307af2b1f530abbce3ba81c2f0a3221
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 %" PY_PRIdOFF,
586 (PY_OFF_T_COMPAT)n);
587 return -1;
589 self->abs_pos = n;
590 return n;
593 static Py_off_t
594 _buffered_raw_seek(buffered *self, Py_off_t target, int whence)
596 PyObject *res, *posobj, *whenceobj;
597 Py_off_t n;
599 posobj = PyLong_FromOff_t(target);
600 if (posobj == NULL)
601 return -1;
602 whenceobj = PyLong_FromLong(whence);
603 if (whenceobj == NULL) {
604 Py_DECREF(posobj);
605 return -1;
607 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
608 posobj, whenceobj, NULL);
609 Py_DECREF(posobj);
610 Py_DECREF(whenceobj);
611 if (res == NULL)
612 return -1;
613 n = PyNumber_AsOff_t(res, PyExc_ValueError);
614 Py_DECREF(res);
615 if (n < 0) {
616 if (!PyErr_Occurred())
617 PyErr_Format(PyExc_IOError,
618 "Raw stream returned invalid position %" PY_PRIdOFF,
619 (PY_OFF_T_COMPAT)n);
620 return -1;
622 self->abs_pos = n;
623 return n;
626 static int
627 _buffered_init(buffered *self)
629 Py_ssize_t n;
630 if (self->buffer_size <= 0) {
631 PyErr_SetString(PyExc_ValueError,
632 "buffer size must be strictly positive");
633 return -1;
635 if (self->buffer)
636 PyMem_Free(self->buffer);
637 self->buffer = PyMem_Malloc(self->buffer_size);
638 if (self->buffer == NULL) {
639 PyErr_NoMemory();
640 return -1;
642 #ifdef WITH_THREAD
643 self->lock = PyThread_allocate_lock();
644 if (self->lock == NULL) {
645 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
646 return -1;
648 #endif
649 /* Find out whether buffer_size is a power of 2 */
650 /* XXX is this optimization useful? */
651 for (n = self->buffer_size - 1; n & 1; n >>= 1)
653 if (n == 0)
654 self->buffer_mask = self->buffer_size - 1;
655 else
656 self->buffer_mask = 0;
657 if (_buffered_raw_tell(self) == -1)
658 PyErr_Clear();
659 return 0;
663 * Shared methods and wrappers
666 static PyObject *
667 buffered_flush(buffered *self, PyObject *args)
669 PyObject *res;
671 CHECK_INITIALIZED(self)
672 CHECK_CLOSED(self, "flush of closed file")
674 ENTER_BUFFERED(self)
675 res = _bufferedwriter_flush_unlocked(self, 0);
676 if (res != NULL && self->readable) {
677 /* Rewind the raw stream so that its position corresponds to
678 the current logical position. */
679 Py_off_t n;
680 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
681 if (n == -1)
682 Py_CLEAR(res);
683 _bufferedreader_reset_buf(self);
685 LEAVE_BUFFERED(self)
687 return res;
690 static PyObject *
691 buffered_peek(buffered *self, PyObject *args)
693 Py_ssize_t n = 0;
694 PyObject *res = NULL;
696 CHECK_INITIALIZED(self)
697 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
698 return NULL;
701 ENTER_BUFFERED(self)
703 if (self->writable) {
704 res = _bufferedwriter_flush_unlocked(self, 1);
705 if (res == NULL)
706 goto end;
707 Py_CLEAR(res);
709 res = _bufferedreader_peek_unlocked(self, n);
711 end:
712 LEAVE_BUFFERED(self)
713 return res;
716 static PyObject *
717 buffered_read(buffered *self, PyObject *args)
719 Py_ssize_t n = -1;
720 PyObject *res;
722 CHECK_INITIALIZED(self)
723 if (!PyArg_ParseTuple(args, "|n:read", &n)) {
724 return NULL;
726 if (n < -1) {
727 PyErr_SetString(PyExc_ValueError,
728 "read length must be positive or -1");
729 return NULL;
732 CHECK_CLOSED(self, "read of closed file")
734 if (n == -1) {
735 /* The number of bytes is unspecified, read until the end of stream */
736 ENTER_BUFFERED(self)
737 res = _bufferedreader_read_all(self);
738 LEAVE_BUFFERED(self)
740 else {
741 res = _bufferedreader_read_fast(self, n);
742 if (res == Py_None) {
743 Py_DECREF(res);
744 ENTER_BUFFERED(self)
745 res = _bufferedreader_read_generic(self, n);
746 LEAVE_BUFFERED(self)
750 return res;
753 static PyObject *
754 buffered_read1(buffered *self, PyObject *args)
756 Py_ssize_t n, have, r;
757 PyObject *res = NULL;
759 CHECK_INITIALIZED(self)
760 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
761 return NULL;
764 if (n < 0) {
765 PyErr_SetString(PyExc_ValueError,
766 "read length must be positive");
767 return NULL;
769 if (n == 0)
770 return PyBytes_FromStringAndSize(NULL, 0);
772 ENTER_BUFFERED(self)
774 if (self->writable) {
775 res = _bufferedwriter_flush_unlocked(self, 1);
776 if (res == NULL)
777 goto end;
778 Py_CLEAR(res);
781 /* Return up to n bytes. If at least one byte is buffered, we
782 only return buffered bytes. Otherwise, we do one raw read. */
784 /* XXX: this mimicks the io.py implementation but is probably wrong.
785 If we need to read from the raw stream, then we could actually read
786 all `n` bytes asked by the caller (and possibly more, so as to fill
787 our buffer for the next reads). */
789 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
790 if (have > 0) {
791 if (n > have)
792 n = have;
793 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
794 if (res == NULL)
795 goto end;
796 self->pos += n;
797 goto end;
800 /* Fill the buffer from the raw stream, and copy it to the result. */
801 _bufferedreader_reset_buf(self);
802 r = _bufferedreader_fill_buffer(self);
803 if (r == -1)
804 goto end;
805 if (r == -2)
806 r = 0;
807 if (n > r)
808 n = r;
809 res = PyBytes_FromStringAndSize(self->buffer, n);
810 if (res == NULL)
811 goto end;
812 self->pos = n;
814 end:
815 LEAVE_BUFFERED(self)
816 return res;
819 static PyObject *
820 buffered_readinto(buffered *self, PyObject *args)
822 PyObject *res = NULL;
824 CHECK_INITIALIZED(self)
826 /* TODO: use raw.readinto() instead! */
827 if (self->writable) {
828 ENTER_BUFFERED(self)
829 res = _bufferedwriter_flush_unlocked(self, 0);
830 LEAVE_BUFFERED(self)
831 if (res == NULL)
832 goto end;
833 Py_DECREF(res);
835 res = bufferediobase_readinto((PyObject *)self, args);
837 end:
838 return res;
841 static PyObject *
842 _buffered_readline(buffered *self, Py_ssize_t limit)
844 PyObject *res = NULL;
845 PyObject *chunks = NULL;
846 Py_ssize_t n, written = 0;
847 const char *start, *s, *end;
849 CHECK_CLOSED(self, "readline of closed file")
851 /* First, try to find a line in the buffer. This can run unlocked because
852 the calls to the C API are simple enough that they can't trigger
853 any thread switch. */
854 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
855 if (limit >= 0 && n > limit)
856 n = limit;
857 start = self->buffer + self->pos;
858 s = memchr(start, '\n', n);
859 if (s != NULL) {
860 res = PyBytes_FromStringAndSize(start, s - start + 1);
861 if (res != NULL)
862 self->pos += s - start + 1;
863 goto end_unlocked;
865 if (n == limit) {
866 res = PyBytes_FromStringAndSize(start, n);
867 if (res != NULL)
868 self->pos += n;
869 goto end_unlocked;
872 ENTER_BUFFERED(self)
874 /* Now we try to get some more from the raw stream */
875 if (self->writable) {
876 res = _bufferedwriter_flush_unlocked(self, 1);
877 if (res == NULL)
878 goto end;
879 Py_CLEAR(res);
881 chunks = PyList_New(0);
882 if (chunks == NULL)
883 goto end;
884 if (n > 0) {
885 res = PyBytes_FromStringAndSize(start, n);
886 if (res == NULL)
887 goto end;
888 if (PyList_Append(chunks, res) < 0) {
889 Py_CLEAR(res);
890 goto end;
892 Py_CLEAR(res);
893 written += n;
894 if (limit >= 0)
895 limit -= n;
898 for (;;) {
899 _bufferedreader_reset_buf(self);
900 n = _bufferedreader_fill_buffer(self);
901 if (n == -1)
902 goto end;
903 if (n <= 0)
904 break;
905 if (limit >= 0 && n > limit)
906 n = limit;
907 start = self->buffer;
908 end = start + n;
909 s = start;
910 while (s < end) {
911 if (*s++ == '\n') {
912 res = PyBytes_FromStringAndSize(start, s - start);
913 if (res == NULL)
914 goto end;
915 self->pos = s - start;
916 goto found;
919 res = PyBytes_FromStringAndSize(start, n);
920 if (res == NULL)
921 goto end;
922 if (n == limit) {
923 self->pos = n;
924 break;
926 if (PyList_Append(chunks, res) < 0) {
927 Py_CLEAR(res);
928 goto end;
930 Py_CLEAR(res);
931 written += n;
932 if (limit >= 0)
933 limit -= n;
935 found:
936 if (res != NULL && PyList_Append(chunks, res) < 0) {
937 Py_CLEAR(res);
938 goto end;
940 Py_CLEAR(res);
941 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
943 end:
944 LEAVE_BUFFERED(self)
945 end_unlocked:
946 Py_XDECREF(chunks);
947 return res;
950 static PyObject *
951 buffered_readline(buffered *self, PyObject *args)
953 PyObject *limitobj = NULL;
954 Py_ssize_t limit = -1;
956 CHECK_INITIALIZED(self)
958 if (!PyArg_ParseTuple(args, "|O:readline", &limitobj)) {
959 return NULL;
961 if (limitobj) {
962 if (!PyNumber_Check(limitobj)) {
963 PyErr_Format(PyExc_TypeError,
964 "integer argument expected, got '%.200s'",
965 Py_TYPE(limitobj)->tp_name);
966 return NULL;
968 limit = PyNumber_AsSsize_t(limitobj, PyExc_OverflowError);
969 if (limit == -1 && PyErr_Occurred())
970 return NULL;
972 return _buffered_readline(self, limit);
976 static PyObject *
977 buffered_tell(buffered *self, PyObject *args)
979 Py_off_t pos;
981 CHECK_INITIALIZED(self)
982 pos = _buffered_raw_tell(self);
983 if (pos == -1)
984 return NULL;
985 pos -= RAW_OFFSET(self);
986 /* TODO: sanity check (pos >= 0) */
987 return PyLong_FromOff_t(pos);
990 static PyObject *
991 buffered_seek(buffered *self, PyObject *args)
993 Py_off_t target, n;
994 int whence = 0;
995 PyObject *targetobj, *res = NULL;
997 CHECK_INITIALIZED(self)
998 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
999 return NULL;
1001 if (whence < 0 || whence > 2) {
1002 PyErr_Format(PyExc_ValueError,
1003 "whence must be between 0 and 2, not %d", whence);
1004 return NULL;
1007 CHECK_CLOSED(self, "seek of closed file")
1009 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1010 if (target == -1 && PyErr_Occurred())
1011 return NULL;
1013 if (whence != 2 && self->readable) {
1014 Py_off_t current, avail;
1015 /* Check if seeking leaves us inside the current buffer,
1016 so as to return quickly if possible. Also, we needn't take the
1017 lock in this fast path.
1018 Don't know how to do that when whence == 2, though. */
1019 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1020 state at this point. */
1021 current = RAW_TELL(self);
1022 avail = READAHEAD(self);
1023 if (avail > 0) {
1024 Py_off_t offset;
1025 if (whence == 0)
1026 offset = target - (current - RAW_OFFSET(self));
1027 else
1028 offset = target;
1029 if (offset >= -self->pos && offset <= avail) {
1030 self->pos += offset;
1031 return PyLong_FromOff_t(current - avail + offset);
1036 ENTER_BUFFERED(self)
1038 /* Fallback: invoke raw seek() method and clear buffer */
1039 if (self->writable) {
1040 res = _bufferedwriter_flush_unlocked(self, 0);
1041 if (res == NULL)
1042 goto end;
1043 Py_CLEAR(res);
1044 _bufferedwriter_reset_buf(self);
1047 /* TODO: align on block boundary and read buffer if needed? */
1048 if (whence == 1)
1049 target -= RAW_OFFSET(self);
1050 n = _buffered_raw_seek(self, target, whence);
1051 if (n == -1)
1052 goto end;
1053 self->raw_pos = -1;
1054 res = PyLong_FromOff_t(n);
1055 if (res != NULL && self->readable)
1056 _bufferedreader_reset_buf(self);
1058 end:
1059 LEAVE_BUFFERED(self)
1060 return res;
1063 static PyObject *
1064 buffered_truncate(buffered *self, PyObject *args)
1066 PyObject *pos = Py_None;
1067 PyObject *res = NULL;
1069 CHECK_INITIALIZED(self)
1070 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1071 return NULL;
1074 ENTER_BUFFERED(self)
1076 if (self->writable) {
1077 res = _bufferedwriter_flush_unlocked(self, 0);
1078 if (res == NULL)
1079 goto end;
1080 Py_CLEAR(res);
1082 if (self->readable) {
1083 if (pos == Py_None) {
1084 /* Rewind the raw stream so that its position corresponds to
1085 the current logical position. */
1086 if (_buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)
1087 goto end;
1089 _bufferedreader_reset_buf(self);
1091 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1092 if (res == NULL)
1093 goto end;
1094 /* Reset cached position */
1095 if (_buffered_raw_tell(self) == -1)
1096 PyErr_Clear();
1098 end:
1099 LEAVE_BUFFERED(self)
1100 return res;
1103 static PyObject *
1104 buffered_iternext(buffered *self)
1106 PyObject *line;
1107 PyTypeObject *tp;
1109 CHECK_INITIALIZED(self);
1111 tp = Py_TYPE(self);
1112 if (tp == &PyBufferedReader_Type ||
1113 tp == &PyBufferedRandom_Type) {
1114 /* Skip method call overhead for speed */
1115 line = _buffered_readline(self, -1);
1117 else {
1118 line = PyObject_CallMethodObjArgs((PyObject *)self,
1119 _PyIO_str_readline, NULL);
1120 if (line && !PyBytes_Check(line)) {
1121 PyErr_Format(PyExc_IOError,
1122 "readline() should have returned a bytes object, "
1123 "not '%.200s'", Py_TYPE(line)->tp_name);
1124 Py_DECREF(line);
1125 return NULL;
1129 if (line == NULL)
1130 return NULL;
1132 if (PyBytes_GET_SIZE(line) == 0) {
1133 /* Reached EOF or would have blocked */
1134 Py_DECREF(line);
1135 return NULL;
1138 return line;
1141 static PyObject *
1142 buffered_repr(buffered *self)
1144 PyObject *nameobj, *res;
1146 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1147 if (nameobj == NULL) {
1148 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1149 PyErr_Clear();
1150 else
1151 return NULL;
1152 res = PyString_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1154 else {
1155 PyObject *repr = PyObject_Repr(nameobj);
1156 Py_DECREF(nameobj);
1157 if (repr == NULL)
1158 return NULL;
1159 res = PyString_FromFormat("<%s name=%s>",
1160 Py_TYPE(self)->tp_name,
1161 PyString_AS_STRING(repr));
1162 Py_DECREF(repr);
1164 return res;
1168 * class BufferedReader
1171 PyDoc_STRVAR(bufferedreader_doc,
1172 "Create a new buffered reader using the given readable raw IO object.");
1174 static void _bufferedreader_reset_buf(buffered *self)
1176 self->read_end = -1;
1179 static int
1180 bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
1182 char *kwlist[] = {"raw", "buffer_size", NULL};
1183 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1184 PyObject *raw;
1186 self->ok = 0;
1187 self->detached = 0;
1189 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1190 &raw, &buffer_size)) {
1191 return -1;
1194 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
1195 return -1;
1197 Py_CLEAR(self->raw);
1198 Py_INCREF(raw);
1199 self->raw = raw;
1200 self->buffer_size = buffer_size;
1201 self->readable = 1;
1202 self->writable = 0;
1204 if (_buffered_init(self) < 0)
1205 return -1;
1206 _bufferedreader_reset_buf(self);
1208 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1209 Py_TYPE(raw) == &PyFileIO_Type);
1211 self->ok = 1;
1212 return 0;
1215 static Py_ssize_t
1216 _bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
1218 Py_buffer buf;
1219 PyObject *memobj, *res;
1220 Py_ssize_t n;
1221 /* NOTE: the buffer needn't be released as its object is NULL. */
1222 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1223 return -1;
1224 memobj = PyMemoryView_FromBuffer(&buf);
1225 if (memobj == NULL)
1226 return -1;
1227 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1228 Py_DECREF(memobj);
1229 if (res == NULL)
1230 return -1;
1231 if (res == Py_None) {
1232 /* Non-blocking stream would have blocked. Special return code! */
1233 Py_DECREF(res);
1234 return -2;
1236 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1237 Py_DECREF(res);
1238 if (n < 0 || n > len) {
1239 PyErr_Format(PyExc_IOError,
1240 "raw readinto() returned invalid length %zd "
1241 "(should have been between 0 and %zd)", n, len);
1242 return -1;
1244 if (n > 0 && self->abs_pos != -1)
1245 self->abs_pos += n;
1246 return n;
1249 static Py_ssize_t
1250 _bufferedreader_fill_buffer(buffered *self)
1252 Py_ssize_t start, len, n;
1253 if (VALID_READ_BUFFER(self))
1254 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1255 else
1256 start = 0;
1257 len = self->buffer_size - start;
1258 n = _bufferedreader_raw_read(self, self->buffer + start, len);
1259 if (n <= 0)
1260 return n;
1261 self->read_end = start + n;
1262 self->raw_pos = start + n;
1263 return n;
1266 static PyObject *
1267 _bufferedreader_read_all(buffered *self)
1269 Py_ssize_t current_size;
1270 PyObject *res, *data = NULL;
1271 PyObject *chunks = PyList_New(0);
1273 if (chunks == NULL)
1274 return NULL;
1276 /* First copy what we have in the current buffer. */
1277 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1278 if (current_size) {
1279 data = PyBytes_FromStringAndSize(
1280 self->buffer + self->pos, current_size);
1281 if (data == NULL) {
1282 Py_DECREF(chunks);
1283 return NULL;
1286 _bufferedreader_reset_buf(self);
1287 /* We're going past the buffer's bounds, flush it */
1288 if (self->writable) {
1289 res = _bufferedwriter_flush_unlocked(self, 1);
1290 if (res == NULL) {
1291 Py_DECREF(chunks);
1292 return NULL;
1294 Py_CLEAR(res);
1296 while (1) {
1297 if (data) {
1298 if (PyList_Append(chunks, data) < 0) {
1299 Py_DECREF(data);
1300 Py_DECREF(chunks);
1301 return NULL;
1303 Py_DECREF(data);
1306 /* Read until EOF or until read() would block. */
1307 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1308 if (data == NULL) {
1309 Py_DECREF(chunks);
1310 return NULL;
1312 if (data != Py_None && !PyBytes_Check(data)) {
1313 Py_DECREF(data);
1314 Py_DECREF(chunks);
1315 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1316 return NULL;
1318 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1319 if (current_size == 0) {
1320 Py_DECREF(chunks);
1321 return data;
1323 else {
1324 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1325 Py_DECREF(data);
1326 Py_DECREF(chunks);
1327 return res;
1330 current_size += PyBytes_GET_SIZE(data);
1331 if (self->abs_pos != -1)
1332 self->abs_pos += PyBytes_GET_SIZE(data);
1336 /* Read n bytes from the buffer if it can, otherwise return None.
1337 This function is simple enough that it can run unlocked. */
1338 static PyObject *
1339 _bufferedreader_read_fast(buffered *self, Py_ssize_t n)
1341 Py_ssize_t current_size;
1343 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1344 if (n <= current_size) {
1345 /* Fast path: the data to read is fully buffered. */
1346 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1347 if (res != NULL)
1348 self->pos += n;
1349 return res;
1351 Py_RETURN_NONE;
1354 /* Generic read function: read from the stream until enough bytes are read,
1355 * or until an EOF occurs or until read() would block.
1357 static PyObject *
1358 _bufferedreader_read_generic(buffered *self, Py_ssize_t n)
1360 PyObject *res = NULL;
1361 Py_ssize_t current_size, remaining, written;
1362 char *out;
1364 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1365 if (n <= current_size)
1366 return _bufferedreader_read_fast(self, n);
1368 res = PyBytes_FromStringAndSize(NULL, n);
1369 if (res == NULL)
1370 goto error;
1371 out = PyBytes_AS_STRING(res);
1372 remaining = n;
1373 written = 0;
1374 if (current_size > 0) {
1375 memcpy(out, self->buffer + self->pos, current_size);
1376 remaining -= current_size;
1377 written += current_size;
1379 _bufferedreader_reset_buf(self);
1380 while (remaining > 0) {
1381 /* We want to read a whole block at the end into buffer.
1382 If we had readv() we could do this in one pass. */
1383 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1384 if (r == 0)
1385 break;
1386 r = _bufferedreader_raw_read(self, out + written, r);
1387 if (r == -1)
1388 goto error;
1389 if (r == 0 || r == -2) {
1390 /* EOF occurred or read() would block. */
1391 if (r == 0 || written > 0) {
1392 if (_PyBytes_Resize(&res, written))
1393 goto error;
1394 return res;
1396 Py_DECREF(res);
1397 Py_INCREF(Py_None);
1398 return Py_None;
1400 remaining -= r;
1401 written += r;
1403 assert(remaining <= self->buffer_size);
1404 self->pos = 0;
1405 self->raw_pos = 0;
1406 self->read_end = 0;
1407 while (self->read_end < self->buffer_size) {
1408 Py_ssize_t r = _bufferedreader_fill_buffer(self);
1409 if (r == -1)
1410 goto error;
1411 if (r == 0 || r == -2) {
1412 /* EOF occurred or read() would block. */
1413 if (r == 0 || written > 0) {
1414 if (_PyBytes_Resize(&res, written))
1415 goto error;
1416 return res;
1418 Py_DECREF(res);
1419 Py_INCREF(Py_None);
1420 return Py_None;
1422 if (remaining > r) {
1423 memcpy(out + written, self->buffer + self->pos, r);
1424 written += r;
1425 self->pos += r;
1426 remaining -= r;
1428 else if (remaining > 0) {
1429 memcpy(out + written, self->buffer + self->pos, remaining);
1430 written += remaining;
1431 self->pos += remaining;
1432 remaining = 0;
1434 if (remaining == 0)
1435 break;
1438 return res;
1440 error:
1441 Py_XDECREF(res);
1442 return NULL;
1445 static PyObject *
1446 _bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
1448 Py_ssize_t have, r;
1450 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1451 /* Constraints:
1452 1. we don't want to advance the file position.
1453 2. we don't want to lose block alignment, so we can't shift the buffer
1454 to make some place.
1455 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1457 if (have > 0) {
1458 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1461 /* Fill the buffer from the raw stream, and copy it to the result. */
1462 _bufferedreader_reset_buf(self);
1463 r = _bufferedreader_fill_buffer(self);
1464 if (r == -1)
1465 return NULL;
1466 if (r == -2)
1467 r = 0;
1468 self->pos = 0;
1469 return PyBytes_FromStringAndSize(self->buffer, r);
1472 static PyMethodDef bufferedreader_methods[] = {
1473 /* BufferedIOMixin methods */
1474 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1475 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1476 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1477 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1478 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1479 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1480 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1481 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
1483 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1484 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1485 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
1486 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1487 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1488 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1489 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1490 {NULL, NULL}
1493 static PyMemberDef bufferedreader_members[] = {
1494 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
1495 {NULL}
1498 static PyGetSetDef bufferedreader_getset[] = {
1499 {"closed", (getter)buffered_closed_get, NULL, NULL},
1500 {"name", (getter)buffered_name_get, NULL, NULL},
1501 {"mode", (getter)buffered_mode_get, NULL, NULL},
1502 {NULL}
1506 PyTypeObject PyBufferedReader_Type = {
1507 PyVarObject_HEAD_INIT(NULL, 0)
1508 "_io.BufferedReader", /*tp_name*/
1509 sizeof(buffered), /*tp_basicsize*/
1510 0, /*tp_itemsize*/
1511 (destructor)buffered_dealloc, /*tp_dealloc*/
1512 0, /*tp_print*/
1513 0, /*tp_getattr*/
1514 0, /*tp_setattr*/
1515 0, /*tp_compare */
1516 (reprfunc)buffered_repr, /*tp_repr*/
1517 0, /*tp_as_number*/
1518 0, /*tp_as_sequence*/
1519 0, /*tp_as_mapping*/
1520 0, /*tp_hash */
1521 0, /*tp_call*/
1522 0, /*tp_str*/
1523 0, /*tp_getattro*/
1524 0, /*tp_setattro*/
1525 0, /*tp_as_buffer*/
1526 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1527 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1528 bufferedreader_doc, /* tp_doc */
1529 (traverseproc)buffered_traverse, /* tp_traverse */
1530 (inquiry)buffered_clear, /* tp_clear */
1531 0, /* tp_richcompare */
1532 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
1533 0, /* tp_iter */
1534 (iternextfunc)buffered_iternext, /* tp_iternext */
1535 bufferedreader_methods, /* tp_methods */
1536 bufferedreader_members, /* tp_members */
1537 bufferedreader_getset, /* tp_getset */
1538 0, /* tp_base */
1539 0, /* tp_dict */
1540 0, /* tp_descr_get */
1541 0, /* tp_descr_set */
1542 offsetof(buffered, dict), /* tp_dictoffset */
1543 (initproc)bufferedreader_init, /* tp_init */
1544 0, /* tp_alloc */
1545 PyType_GenericNew, /* tp_new */
1550 static int
1551 complain_about_max_buffer_size(void)
1553 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1554 "max_buffer_size is deprecated", 1) < 0)
1555 return 0;
1556 return 1;
1560 * class BufferedWriter
1562 PyDoc_STRVAR(bufferedwriter_doc,
1563 "A buffer for a writeable sequential RawIO object.\n"
1564 "\n"
1565 "The constructor creates a BufferedWriter for the given writeable raw\n"
1566 "stream. If the buffer_size is not given, it defaults to\n"
1567 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1570 static void
1571 _bufferedwriter_reset_buf(buffered *self)
1573 self->write_pos = 0;
1574 self->write_end = -1;
1577 static int
1578 bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
1580 /* TODO: properly deprecate max_buffer_size */
1581 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1582 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1583 Py_ssize_t max_buffer_size = -234;
1584 PyObject *raw;
1586 self->ok = 0;
1587 self->detached = 0;
1589 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1590 &raw, &buffer_size, &max_buffer_size)) {
1591 return -1;
1594 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1595 return -1;
1597 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
1598 return -1;
1600 Py_CLEAR(self->raw);
1601 Py_INCREF(raw);
1602 self->raw = raw;
1603 self->readable = 0;
1604 self->writable = 1;
1606 self->buffer_size = buffer_size;
1607 if (_buffered_init(self) < 0)
1608 return -1;
1609 _bufferedwriter_reset_buf(self);
1610 self->pos = 0;
1612 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1613 Py_TYPE(raw) == &PyFileIO_Type);
1615 self->ok = 1;
1616 return 0;
1619 static Py_ssize_t
1620 _bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
1622 Py_buffer buf;
1623 PyObject *memobj, *res;
1624 Py_ssize_t n;
1625 /* NOTE: the buffer needn't be released as its object is NULL. */
1626 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1627 return -1;
1628 memobj = PyMemoryView_FromBuffer(&buf);
1629 if (memobj == NULL)
1630 return -1;
1631 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1632 Py_DECREF(memobj);
1633 if (res == NULL)
1634 return -1;
1635 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1636 Py_DECREF(res);
1637 if (n < 0 || n > len) {
1638 PyErr_Format(PyExc_IOError,
1639 "raw write() returned invalid length %zd "
1640 "(should have been between 0 and %zd)", n, len);
1641 return -1;
1643 if (n > 0 && self->abs_pos != -1)
1644 self->abs_pos += n;
1645 return n;
1648 /* `restore_pos` is 1 if we need to restore the raw stream position at
1649 the end, 0 otherwise. */
1650 static PyObject *
1651 _bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
1653 Py_ssize_t written = 0;
1654 Py_off_t n, rewind;
1656 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1657 goto end;
1658 /* First, rewind */
1659 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1660 if (rewind != 0) {
1661 n = _buffered_raw_seek(self, -rewind, 1);
1662 if (n < 0) {
1663 goto error;
1665 self->raw_pos -= rewind;
1667 while (self->write_pos < self->write_end) {
1668 n = _bufferedwriter_raw_write(self,
1669 self->buffer + self->write_pos,
1670 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1671 Py_off_t, Py_ssize_t));
1672 if (n == -1) {
1673 Py_ssize_t *w = _buffered_check_blocking_error();
1674 if (w == NULL)
1675 goto error;
1676 self->write_pos += *w;
1677 self->raw_pos = self->write_pos;
1678 written += *w;
1679 *w = written;
1680 /* Already re-raised */
1681 goto error;
1683 self->write_pos += n;
1684 self->raw_pos = self->write_pos;
1685 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1688 if (restore_pos) {
1689 Py_off_t forward = rewind - written;
1690 if (forward != 0) {
1691 n = _buffered_raw_seek(self, forward, 1);
1692 if (n < 0) {
1693 goto error;
1695 self->raw_pos += forward;
1698 _bufferedwriter_reset_buf(self);
1700 end:
1701 Py_RETURN_NONE;
1703 error:
1704 return NULL;
1707 static PyObject *
1708 bufferedwriter_write(buffered *self, PyObject *args)
1710 PyObject *res = NULL;
1711 Py_buffer buf;
1712 Py_ssize_t written, avail, remaining;
1713 Py_off_t offset;
1715 CHECK_INITIALIZED(self)
1716 if (!PyArg_ParseTuple(args, "s*:write", &buf)) {
1717 return NULL;
1720 if (IS_CLOSED(self)) {
1721 PyErr_SetString(PyExc_ValueError, "write to closed file");
1722 PyBuffer_Release(&buf);
1723 return NULL;
1726 ENTER_BUFFERED(self)
1728 /* Fast path: the data to write can be fully buffered. */
1729 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1730 self->pos = 0;
1731 self->raw_pos = 0;
1733 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1734 if (buf.len <= avail) {
1735 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1736 if (!VALID_WRITE_BUFFER(self)) {
1737 self->write_pos = self->pos;
1739 ADJUST_POSITION(self, self->pos + buf.len);
1740 if (self->pos > self->write_end)
1741 self->write_end = self->pos;
1742 written = buf.len;
1743 goto end;
1746 /* First write the current buffer */
1747 res = _bufferedwriter_flush_unlocked(self, 0);
1748 if (res == NULL) {
1749 Py_ssize_t *w = _buffered_check_blocking_error();
1750 if (w == NULL)
1751 goto error;
1752 if (self->readable)
1753 _bufferedreader_reset_buf(self);
1754 /* Make some place by shifting the buffer. */
1755 assert(VALID_WRITE_BUFFER(self));
1756 memmove(self->buffer, self->buffer + self->write_pos,
1757 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1758 Py_off_t, Py_ssize_t));
1759 self->write_end -= self->write_pos;
1760 self->raw_pos -= self->write_pos;
1761 self->pos -= self->write_pos;
1762 self->write_pos = 0;
1763 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1764 Py_off_t, Py_ssize_t);
1765 if (buf.len <= avail) {
1766 /* Everything can be buffered */
1767 PyErr_Clear();
1768 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1769 self->write_end += buf.len;
1770 written = buf.len;
1771 goto end;
1773 /* Buffer as much as possible. */
1774 memcpy(self->buffer + self->write_end, buf.buf, avail);
1775 self->write_end += avail;
1776 /* Already re-raised */
1777 *w = avail;
1778 goto error;
1780 Py_CLEAR(res);
1782 /* Adjust the raw stream position if it is away from the logical stream
1783 position. This happens if the read buffer has been filled but not
1784 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1785 the raw stream by itself).
1786 Fixes issue #6629.
1788 offset = RAW_OFFSET(self);
1789 if (offset != 0) {
1790 if (_buffered_raw_seek(self, -offset, 1) < 0)
1791 goto error;
1792 self->raw_pos -= offset;
1795 /* Then write buf itself. At this point the buffer has been emptied. */
1796 remaining = buf.len;
1797 written = 0;
1798 while (remaining > self->buffer_size) {
1799 Py_ssize_t n = _bufferedwriter_raw_write(
1800 self, (char *) buf.buf + written, buf.len - written);
1801 if (n == -1) {
1802 Py_ssize_t *w = _buffered_check_blocking_error();
1803 if (w == NULL)
1804 goto error;
1805 written += *w;
1806 remaining -= *w;
1807 if (remaining > self->buffer_size) {
1808 /* Can't buffer everything, still buffer as much as possible */
1809 memcpy(self->buffer,
1810 (char *) buf.buf + written, self->buffer_size);
1811 self->raw_pos = 0;
1812 ADJUST_POSITION(self, self->buffer_size);
1813 self->write_end = self->buffer_size;
1814 *w = written + self->buffer_size;
1815 /* Already re-raised */
1816 goto error;
1818 PyErr_Clear();
1819 break;
1821 written += n;
1822 remaining -= n;
1824 if (self->readable)
1825 _bufferedreader_reset_buf(self);
1826 if (remaining > 0) {
1827 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1828 written += remaining;
1830 self->write_pos = 0;
1831 /* TODO: sanity check (remaining >= 0) */
1832 self->write_end = remaining;
1833 ADJUST_POSITION(self, remaining);
1834 self->raw_pos = 0;
1836 end:
1837 res = PyLong_FromSsize_t(written);
1839 error:
1840 LEAVE_BUFFERED(self)
1841 PyBuffer_Release(&buf);
1842 return res;
1845 static PyMethodDef bufferedwriter_methods[] = {
1846 /* BufferedIOMixin methods */
1847 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1848 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1849 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1850 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1851 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1852 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1853 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
1855 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1856 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1857 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1858 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1859 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1860 {NULL, NULL}
1863 static PyMemberDef bufferedwriter_members[] = {
1864 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
1865 {NULL}
1868 static PyGetSetDef bufferedwriter_getset[] = {
1869 {"closed", (getter)buffered_closed_get, NULL, NULL},
1870 {"name", (getter)buffered_name_get, NULL, NULL},
1871 {"mode", (getter)buffered_mode_get, NULL, NULL},
1872 {NULL}
1876 PyTypeObject PyBufferedWriter_Type = {
1877 PyVarObject_HEAD_INIT(NULL, 0)
1878 "_io.BufferedWriter", /*tp_name*/
1879 sizeof(buffered), /*tp_basicsize*/
1880 0, /*tp_itemsize*/
1881 (destructor)buffered_dealloc, /*tp_dealloc*/
1882 0, /*tp_print*/
1883 0, /*tp_getattr*/
1884 0, /*tp_setattr*/
1885 0, /*tp_compare */
1886 (reprfunc)buffered_repr, /*tp_repr*/
1887 0, /*tp_as_number*/
1888 0, /*tp_as_sequence*/
1889 0, /*tp_as_mapping*/
1890 0, /*tp_hash */
1891 0, /*tp_call*/
1892 0, /*tp_str*/
1893 0, /*tp_getattro*/
1894 0, /*tp_setattro*/
1895 0, /*tp_as_buffer*/
1896 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1897 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1898 bufferedwriter_doc, /* tp_doc */
1899 (traverseproc)buffered_traverse, /* tp_traverse */
1900 (inquiry)buffered_clear, /* tp_clear */
1901 0, /* tp_richcompare */
1902 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
1903 0, /* tp_iter */
1904 0, /* tp_iternext */
1905 bufferedwriter_methods, /* tp_methods */
1906 bufferedwriter_members, /* tp_members */
1907 bufferedwriter_getset, /* tp_getset */
1908 0, /* tp_base */
1909 0, /* tp_dict */
1910 0, /* tp_descr_get */
1911 0, /* tp_descr_set */
1912 offsetof(buffered, dict), /* tp_dictoffset */
1913 (initproc)bufferedwriter_init, /* tp_init */
1914 0, /* tp_alloc */
1915 PyType_GenericNew, /* tp_new */
1921 * BufferedRWPair
1924 PyDoc_STRVAR(bufferedrwpair_doc,
1925 "A buffered reader and writer object together.\n"
1926 "\n"
1927 "A buffered reader object and buffered writer object put together to\n"
1928 "form a sequential IO object that can read and write. This is typically\n"
1929 "used with a socket or two-way pipe.\n"
1930 "\n"
1931 "reader and writer are RawIOBase objects that are readable and\n"
1932 "writeable respectively. If the buffer_size is omitted it defaults to\n"
1933 "DEFAULT_BUFFER_SIZE.\n"
1936 /* XXX The usefulness of this (compared to having two separate IO objects) is
1937 * questionable.
1940 typedef struct {
1941 PyObject_HEAD
1942 buffered *reader;
1943 buffered *writer;
1944 PyObject *dict;
1945 PyObject *weakreflist;
1946 } rwpair;
1948 static int
1949 bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
1951 PyObject *reader, *writer;
1952 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1953 Py_ssize_t max_buffer_size = -234;
1955 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1956 &buffer_size, &max_buffer_size)) {
1957 return -1;
1960 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1961 return -1;
1963 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
1964 return -1;
1965 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
1966 return -1;
1968 self->reader = (buffered *) PyObject_CallFunction(
1969 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
1970 if (self->reader == NULL)
1971 return -1;
1973 self->writer = (buffered *) PyObject_CallFunction(
1974 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
1975 if (self->writer == NULL) {
1976 Py_CLEAR(self->reader);
1977 return -1;
1980 return 0;
1983 static int
1984 bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
1986 Py_VISIT(self->dict);
1987 return 0;
1990 static int
1991 bufferedrwpair_clear(rwpair *self)
1993 Py_CLEAR(self->reader);
1994 Py_CLEAR(self->writer);
1995 Py_CLEAR(self->dict);
1996 return 0;
1999 static void
2000 bufferedrwpair_dealloc(rwpair *self)
2002 _PyObject_GC_UNTRACK(self);
2003 Py_CLEAR(self->reader);
2004 Py_CLEAR(self->writer);
2005 Py_CLEAR(self->dict);
2006 Py_TYPE(self)->tp_free((PyObject *) self);
2009 static PyObject *
2010 _forward_call(buffered *self, const char *name, PyObject *args)
2012 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
2013 PyObject *ret;
2015 if (func == NULL) {
2016 PyErr_SetString(PyExc_AttributeError, name);
2017 return NULL;
2020 ret = PyObject_CallObject(func, args);
2021 Py_DECREF(func);
2022 return ret;
2025 static PyObject *
2026 bufferedrwpair_read(rwpair *self, PyObject *args)
2028 return _forward_call(self->reader, "read", args);
2031 static PyObject *
2032 bufferedrwpair_peek(rwpair *self, PyObject *args)
2034 return _forward_call(self->reader, "peek", args);
2037 static PyObject *
2038 bufferedrwpair_read1(rwpair *self, PyObject *args)
2040 return _forward_call(self->reader, "read1", args);
2043 static PyObject *
2044 bufferedrwpair_readinto(rwpair *self, PyObject *args)
2046 return _forward_call(self->reader, "readinto", args);
2049 static PyObject *
2050 bufferedrwpair_write(rwpair *self, PyObject *args)
2052 return _forward_call(self->writer, "write", args);
2055 static PyObject *
2056 bufferedrwpair_flush(rwpair *self, PyObject *args)
2058 return _forward_call(self->writer, "flush", args);
2061 static PyObject *
2062 bufferedrwpair_readable(rwpair *self, PyObject *args)
2064 return _forward_call(self->reader, "readable", args);
2067 static PyObject *
2068 bufferedrwpair_writable(rwpair *self, PyObject *args)
2070 return _forward_call(self->writer, "writable", args);
2073 static PyObject *
2074 bufferedrwpair_close(rwpair *self, PyObject *args)
2076 PyObject *ret = _forward_call(self->writer, "close", args);
2077 if (ret == NULL)
2078 return NULL;
2079 Py_DECREF(ret);
2081 return _forward_call(self->reader, "close", args);
2084 static PyObject *
2085 bufferedrwpair_isatty(rwpair *self, PyObject *args)
2087 PyObject *ret = _forward_call(self->writer, "isatty", args);
2089 if (ret != Py_False) {
2090 /* either True or exception */
2091 return ret;
2093 Py_DECREF(ret);
2095 return _forward_call(self->reader, "isatty", args);
2098 static PyObject *
2099 bufferedrwpair_closed_get(rwpair *self, void *context)
2101 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2104 static PyMethodDef bufferedrwpair_methods[] = {
2105 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2106 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2107 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2108 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
2110 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2111 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
2113 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2114 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
2116 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2117 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
2119 {NULL, NULL}
2122 static PyGetSetDef bufferedrwpair_getset[] = {
2123 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
2124 {NULL}
2127 PyTypeObject PyBufferedRWPair_Type = {
2128 PyVarObject_HEAD_INIT(NULL, 0)
2129 "_io.BufferedRWPair", /*tp_name*/
2130 sizeof(rwpair), /*tp_basicsize*/
2131 0, /*tp_itemsize*/
2132 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
2133 0, /*tp_print*/
2134 0, /*tp_getattr*/
2135 0, /*tp_setattr*/
2136 0, /*tp_compare */
2137 0, /*tp_repr*/
2138 0, /*tp_as_number*/
2139 0, /*tp_as_sequence*/
2140 0, /*tp_as_mapping*/
2141 0, /*tp_hash */
2142 0, /*tp_call*/
2143 0, /*tp_str*/
2144 0, /*tp_getattro*/
2145 0, /*tp_setattro*/
2146 0, /*tp_as_buffer*/
2147 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2148 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
2149 bufferedrwpair_doc, /* tp_doc */
2150 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2151 (inquiry)bufferedrwpair_clear, /* tp_clear */
2152 0, /* tp_richcompare */
2153 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
2154 0, /* tp_iter */
2155 0, /* tp_iternext */
2156 bufferedrwpair_methods, /* tp_methods */
2157 0, /* tp_members */
2158 bufferedrwpair_getset, /* tp_getset */
2159 0, /* tp_base */
2160 0, /* tp_dict */
2161 0, /* tp_descr_get */
2162 0, /* tp_descr_set */
2163 offsetof(rwpair, dict), /* tp_dictoffset */
2164 (initproc)bufferedrwpair_init, /* tp_init */
2165 0, /* tp_alloc */
2166 PyType_GenericNew, /* tp_new */
2172 * BufferedRandom
2175 PyDoc_STRVAR(bufferedrandom_doc,
2176 "A buffered interface to random access streams.\n"
2177 "\n"
2178 "The constructor creates a reader and writer for a seekable stream,\n"
2179 "raw, given in the first argument. If the buffer_size is omitted it\n"
2180 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2183 static int
2184 bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
2186 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2187 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
2188 Py_ssize_t max_buffer_size = -234;
2189 PyObject *raw;
2191 self->ok = 0;
2192 self->detached = 0;
2194 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2195 &raw, &buffer_size, &max_buffer_size)) {
2196 return -1;
2199 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2200 return -1;
2202 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
2203 return -1;
2204 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
2205 return -1;
2206 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
2207 return -1;
2209 Py_CLEAR(self->raw);
2210 Py_INCREF(raw);
2211 self->raw = raw;
2212 self->buffer_size = buffer_size;
2213 self->readable = 1;
2214 self->writable = 1;
2216 if (_buffered_init(self) < 0)
2217 return -1;
2218 _bufferedreader_reset_buf(self);
2219 _bufferedwriter_reset_buf(self);
2220 self->pos = 0;
2222 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2223 Py_TYPE(raw) == &PyFileIO_Type);
2225 self->ok = 1;
2226 return 0;
2229 static PyMethodDef bufferedrandom_methods[] = {
2230 /* BufferedIOMixin methods */
2231 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2232 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2233 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2234 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2235 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2236 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2237 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2239 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2241 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2242 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2243 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2244 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2245 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2246 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2247 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2248 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2249 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
2250 {NULL, NULL}
2253 static PyMemberDef bufferedrandom_members[] = {
2254 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
2255 {NULL}
2258 static PyGetSetDef bufferedrandom_getset[] = {
2259 {"closed", (getter)buffered_closed_get, NULL, NULL},
2260 {"name", (getter)buffered_name_get, NULL, NULL},
2261 {"mode", (getter)buffered_mode_get, NULL, NULL},
2262 {NULL}
2266 PyTypeObject PyBufferedRandom_Type = {
2267 PyVarObject_HEAD_INIT(NULL, 0)
2268 "_io.BufferedRandom", /*tp_name*/
2269 sizeof(buffered), /*tp_basicsize*/
2270 0, /*tp_itemsize*/
2271 (destructor)buffered_dealloc, /*tp_dealloc*/
2272 0, /*tp_print*/
2273 0, /*tp_getattr*/
2274 0, /*tp_setattr*/
2275 0, /*tp_compare */
2276 (reprfunc)buffered_repr, /*tp_repr*/
2277 0, /*tp_as_number*/
2278 0, /*tp_as_sequence*/
2279 0, /*tp_as_mapping*/
2280 0, /*tp_hash */
2281 0, /*tp_call*/
2282 0, /*tp_str*/
2283 0, /*tp_getattro*/
2284 0, /*tp_setattro*/
2285 0, /*tp_as_buffer*/
2286 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2287 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2288 bufferedrandom_doc, /* tp_doc */
2289 (traverseproc)buffered_traverse, /* tp_traverse */
2290 (inquiry)buffered_clear, /* tp_clear */
2291 0, /* tp_richcompare */
2292 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2293 0, /* tp_iter */
2294 (iternextfunc)buffered_iternext, /* tp_iternext */
2295 bufferedrandom_methods, /* tp_methods */
2296 bufferedrandom_members, /* tp_members */
2297 bufferedrandom_getset, /* tp_getset */
2298 0, /* tp_base */
2299 0, /*tp_dict*/
2300 0, /* tp_descr_get */
2301 0, /* tp_descr_set */
2302 offsetof(buffered, dict), /*tp_dictoffset*/
2303 (initproc)bufferedrandom_init, /* tp_init */
2304 0, /* tp_alloc */
2305 PyType_GenericNew, /* tp_new */