blob: 9aa7d4b8b8c40c4270bec4644431a8cc5a8a3a86 [file] [log] [blame]
Antoine Pitrou19690592009-06-12 20:14:08 +00001/*
2 An implementation of Buffered I/O as defined by PEP 3116 - "New I/O"
3
4 Classes defined here: BufferedIOBase, BufferedReader, BufferedWriter,
5 BufferedRandom.
6
7 Written by Amaury Forgeot d'Arc and Antoine Pitrou
8*/
9
10#define PY_SSIZE_T_CLEAN
11#include "Python.h"
12#include "structmember.h"
13#include "pythread.h"
14#include "_iomodule.h"
15
16/*
17 * BufferedIOBase class, inherits from IOBase.
18 */
19PyDoc_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"
33 );
34
35static PyObject *
36bufferediobase_readinto(PyObject *self, PyObject *args)
37{
38 Py_buffer buf;
39 Py_ssize_t len;
40 PyObject *data;
41
42 if (!PyArg_ParseTuple(args, "w*:readinto", &buf)) {
43 return NULL;
44 }
45
46 data = PyObject_CallMethod(self, "read", "n", buf.len);
47 if (data == NULL)
48 goto error;
49
50 if (!PyBytes_Check(data)) {
51 Py_DECREF(data);
52 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
53 goto error;
54 }
55
56 len = Py_SIZE(data);
57 memcpy(buf.buf, PyBytes_AS_STRING(data), len);
58
59 PyBuffer_Release(&buf);
60 Py_DECREF(data);
61
62 return PyLong_FromSsize_t(len);
63
64 error:
65 PyBuffer_Release(&buf);
66 return NULL;
67}
68
69static PyObject *
70bufferediobase_unsupported(const char *message)
71{
72 PyErr_SetString(_PyIO_unsupported_operation, message);
73 return NULL;
74}
75
76PyDoc_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");
81
82static PyObject *
83bufferediobase_detach(PyObject *self)
84{
85 return bufferediobase_unsupported("detach");
86}
87
88PyDoc_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");
105
106static PyObject *
107bufferediobase_read(PyObject *self, PyObject *args)
108{
109 return bufferediobase_unsupported("read");
110}
111
112PyDoc_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");
118
119static PyObject *
120bufferediobase_read1(PyObject *self, PyObject *args)
121{
122 return bufferediobase_unsupported("read1");
123}
124
125PyDoc_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");
133
134static PyObject *
135bufferediobase_write(PyObject *self, PyObject *args)
136{
137 return bufferediobase_unsupported("write");
138}
139
140
141static 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}
148};
149
150PyTypeObject 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 */
189};
190
191
192typedef struct {
193 PyObject_HEAD
194
195 PyObject *raw;
196 int ok; /* Initialized? */
197 int detached;
198 int readable;
199 int writable;
200
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;
204
205 /* Absolute position inside the raw stream (-1 if unknown). */
206 Py_off_t abs_pos;
207
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;
214
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;
218
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;
224
225#ifdef WITH_THREAD
226 PyThread_type_lock lock;
227#endif
228
229 Py_ssize_t buffer_size;
230 Py_ssize_t buffer_mask;
231
232 PyObject *dict;
233 PyObject *weakreflist;
234} buffered;
235
236/*
237 Implementation notes:
238
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.
252
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.
256
257*/
258
259/* These macros protect the buffered object against concurrent operations. */
260
261#ifdef WITH_THREAD
262#define ENTER_BUFFERED(self) \
Antoine Pitroue50efaa2009-11-01 11:58:22 +0000263 if (!PyThread_acquire_lock(self->lock, 0)) { \
264 Py_BEGIN_ALLOW_THREADS \
265 PyThread_acquire_lock(self->lock, 1); \
266 Py_END_ALLOW_THREADS \
267 }
Antoine Pitrou19690592009-06-12 20:14:08 +0000268
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
275
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"); \
284 } \
285 return NULL; \
286 }
287
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"); \
296 } \
297 return -1; \
298 }
299
300#define IS_CLOSED(self) \
301 (self->fast_closed_checks \
302 ? _PyFileIO_closed(self->raw) \
303 : buffered_closed(self))
304
305#define CHECK_CLOSED(self, error_msg) \
306 if (IS_CLOSED(self)) { \
307 PyErr_SetString(PyExc_ValueError, error_msg); \
308 return NULL; \
309 }
310
311
312#define VALID_READ_BUFFER(self) \
313 (self->readable && self->read_end != -1)
314
315#define VALID_WRITE_BUFFER(self) \
316 (self->writable && self->write_end != -1)
317
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)
324
325#define READAHEAD(self) \
326 ((self->readable && VALID_READ_BUFFER(self)) \
327 ? (self->read_end - self->pos) : 0)
328
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)
332
333#define RAW_TELL(self) \
334 (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
335
336#define MINUS_LAST_BLOCK(self, size) \
337 (self->buffer_mask ? \
338 (size & ~self->buffer_mask) : \
339 (self->buffer_size * (size / self->buffer_size)))
340
341
342static void
343buffered_dealloc(buffered *self)
344{
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;
355 }
356#ifdef WITH_THREAD
357 if (self->lock) {
358 PyThread_free_lock(self->lock);
359 self->lock = NULL;
360 }
361#endif
362 Py_CLEAR(self->dict);
363 Py_TYPE(self)->tp_free((PyObject *)self);
364}
365
366static int
367buffered_traverse(buffered *self, visitproc visit, void *arg)
368{
369 Py_VISIT(self->raw);
370 Py_VISIT(self->dict);
371 return 0;
372}
373
374static int
375buffered_clear(buffered *self)
376{
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;
383}
384
385/*
386 * _BufferedIOMixin methods
387 * This is not a class, just a collection of methods that will be reused
388 * by BufferedReader and BufferedWriter
389 */
390
391/* Flush and close */
392
393static PyObject *
394buffered_simple_flush(buffered *self, PyObject *args)
395{
396 CHECK_INITIALIZED(self)
397 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
398}
399
400static int
401buffered_closed(buffered *self)
402{
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;
412}
413
414static PyObject *
415buffered_closed_get(buffered *self, void *context)
416{
417 CHECK_INITIALIZED(self)
418 return PyObject_GetAttr(self->raw, _PyIO_str_closed);
419}
420
421static PyObject *
422buffered_close(buffered *self, PyObject *args)
423{
424 PyObject *res = NULL;
425 int r;
426
427 CHECK_INITIALIZED(self)
428 ENTER_BUFFERED(self)
429
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;
437 }
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;
448 }
449 Py_XDECREF(res);
450
451 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
452
453end:
454 LEAVE_BUFFERED(self)
455 return res;
456}
457
458/* detach */
459
460static PyObject *
461buffered_detach(buffered *self, PyObject *args)
462{
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;
474}
475
476/* Inquiries */
477
478static PyObject *
479buffered_seekable(buffered *self, PyObject *args)
480{
481 CHECK_INITIALIZED(self)
482 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
483}
484
485static PyObject *
486buffered_readable(buffered *self, PyObject *args)
487{
488 CHECK_INITIALIZED(self)
489 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
490}
491
492static PyObject *
493buffered_writable(buffered *self, PyObject *args)
494{
495 CHECK_INITIALIZED(self)
496 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
497}
498
499static PyObject *
500buffered_name_get(buffered *self, void *context)
501{
502 CHECK_INITIALIZED(self)
503 return PyObject_GetAttrString(self->raw, "name");
504}
505
506static PyObject *
507buffered_mode_get(buffered *self, void *context)
508{
509 CHECK_INITIALIZED(self)
510 return PyObject_GetAttrString(self->raw, "mode");
511}
512
513/* Lower-level APIs */
514
515static PyObject *
516buffered_fileno(buffered *self, PyObject *args)
517{
518 CHECK_INITIALIZED(self)
519 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
520}
521
522static PyObject *
523buffered_isatty(buffered *self, PyObject *args)
524{
525 CHECK_INITIALIZED(self)
526 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
527}
528
529
530/* Forward decls */
531static PyObject *
532_bufferedwriter_flush_unlocked(buffered *, int);
533static Py_ssize_t
534_bufferedreader_fill_buffer(buffered *self);
535static void
536_bufferedreader_reset_buf(buffered *self);
537static void
538_bufferedwriter_reset_buf(buffered *self);
539static PyObject *
540_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t);
541static PyObject *
542_bufferedreader_read_all(buffered *self);
543static PyObject *
544_bufferedreader_read_fast(buffered *self, Py_ssize_t);
545static PyObject *
546_bufferedreader_read_generic(buffered *self, Py_ssize_t);
547
548
549/*
550 * Helpers
551 */
552
553/* Returns the address of the `written` member if a BlockingIOError was
554 raised, NULL otherwise. The error is always re-raised. */
555static Py_ssize_t *
556_buffered_check_blocking_error(void)
557{
558 PyObject *t, *v, *tb;
559 PyBlockingIOErrorObject *err;
560
561 PyErr_Fetch(&t, &v, &tb);
562 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
563 PyErr_Restore(t, v, tb);
564 return NULL;
565 }
566 err = (PyBlockingIOErrorObject *) v;
567 /* TODO: sanity check (err->written >= 0) */
568 PyErr_Restore(t, v, tb);
569 return &err->written;
570}
571
572static Py_off_t
573_buffered_raw_tell(buffered *self)
574{
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,
Mark Dickinson3ddb5272009-10-29 09:46:04 +0000585 "Raw stream returned invalid position %zd", n);
Antoine Pitrou19690592009-06-12 20:14:08 +0000586 return -1;
587 }
588 self->abs_pos = n;
589 return n;
590}
591
592static Py_off_t
593_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
594{
595 PyObject *res, *posobj, *whenceobj;
596 Py_off_t n;
597
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;
605 }
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,
Mark Dickinson3ddb5272009-10-29 09:46:04 +0000617 "Raw stream returned invalid position %zd", n);
Antoine Pitrou19690592009-06-12 20:14:08 +0000618 return -1;
619 }
620 self->abs_pos = n;
621 return n;
622}
623
624static int
625_buffered_init(buffered *self)
626{
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;
632 }
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;
639 }
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;
645 }
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)
650 ;
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;
658}
659
660/*
661 * Shared methods and wrappers
662 */
663
664static PyObject *
665buffered_flush(buffered *self, PyObject *args)
666{
667 PyObject *res;
668
669 CHECK_INITIALIZED(self)
670 CHECK_CLOSED(self, "flush of closed file")
671
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);
682 }
683 LEAVE_BUFFERED(self)
684
685 return res;
686}
687
688static PyObject *
689buffered_peek(buffered *self, PyObject *args)
690{
691 Py_ssize_t n = 0;
692 PyObject *res = NULL;
693
694 CHECK_INITIALIZED(self)
695 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
696 return NULL;
697 }
698
699 ENTER_BUFFERED(self)
700
701 if (self->writable) {
702 res = _bufferedwriter_flush_unlocked(self, 1);
703 if (res == NULL)
704 goto end;
705 Py_CLEAR(res);
706 }
707 res = _bufferedreader_peek_unlocked(self, n);
708
709end:
710 LEAVE_BUFFERED(self)
711 return res;
712}
713
714static PyObject *
715buffered_read(buffered *self, PyObject *args)
716{
717 Py_ssize_t n = -1;
718 PyObject *res;
719
720 CHECK_INITIALIZED(self)
721 if (!PyArg_ParseTuple(args, "|n:read", &n)) {
722 return NULL;
723 }
724 if (n < -1) {
725 PyErr_SetString(PyExc_ValueError,
726 "read length must be positive or -1");
727 return NULL;
728 }
729
730 CHECK_CLOSED(self, "read of closed file")
731
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)
737 }
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)
745 }
746 }
747
748 return res;
749}
750
751static PyObject *
752buffered_read1(buffered *self, PyObject *args)
753{
754 Py_ssize_t n, have, r;
755 PyObject *res = NULL;
756
757 CHECK_INITIALIZED(self)
758 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
759 return NULL;
760 }
761
762 if (n < 0) {
763 PyErr_SetString(PyExc_ValueError,
764 "read length must be positive");
765 return NULL;
766 }
767 if (n == 0)
768 return PyBytes_FromStringAndSize(NULL, 0);
769
770 ENTER_BUFFERED(self)
771
772 if (self->writable) {
773 res = _bufferedwriter_flush_unlocked(self, 1);
774 if (res == NULL)
775 goto end;
776 Py_CLEAR(res);
777 }
778
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. */
781
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). */
786
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;
796 }
797
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;
811
812end:
813 LEAVE_BUFFERED(self)
814 return res;
815}
816
817static PyObject *
818buffered_readinto(buffered *self, PyObject *args)
819{
820 PyObject *res = NULL;
821
822 CHECK_INITIALIZED(self)
823
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);
832 }
833 res = bufferediobase_readinto((PyObject *)self, args);
834
835end:
836 return res;
837}
838
839static PyObject *
840_buffered_readline(buffered *self, Py_ssize_t limit)
841{
842 PyObject *res = NULL;
843 PyObject *chunks = NULL;
844 Py_ssize_t n, written = 0;
845 const char *start, *s, *end;
846
847 CHECK_CLOSED(self, "readline of closed file")
848
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;
862 }
863 if (n == limit) {
864 res = PyBytes_FromStringAndSize(start, n);
865 if (res != NULL)
866 self->pos += n;
867 goto end_unlocked;
868 }
869
870 ENTER_BUFFERED(self)
871
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);
878 }
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;
889 }
890 Py_CLEAR(res);
891 written += n;
892 if (limit >= 0)
893 limit -= n;
894 }
895
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;
915 }
916 }
917 res = PyBytes_FromStringAndSize(start, n);
918 if (res == NULL)
919 goto end;
920 if (n == limit) {
921 self->pos = n;
922 break;
923 }
924 if (PyList_Append(chunks, res) < 0) {
925 Py_CLEAR(res);
926 goto end;
927 }
928 Py_CLEAR(res);
929 written += n;
930 if (limit >= 0)
931 limit -= n;
932 }
933found:
934 if (res != NULL && PyList_Append(chunks, res) < 0) {
935 Py_CLEAR(res);
936 goto end;
937 }
938 Py_CLEAR(res);
939 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
940
941end:
942 LEAVE_BUFFERED(self)
943end_unlocked:
944 Py_XDECREF(chunks);
945 return res;
946}
947
948static PyObject *
949buffered_readline(buffered *self, PyObject *args)
950{
951 PyObject *limitobj = NULL;
952 Py_ssize_t limit = -1;
953
954 CHECK_INITIALIZED(self)
955
956 if (!PyArg_ParseTuple(args, "|O:readline", &limitobj)) {
957 return NULL;
958 }
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;
965 }
966 limit = PyNumber_AsSsize_t(limitobj, PyExc_OverflowError);
967 if (limit == -1 && PyErr_Occurred())
968 return NULL;
969 }
970 return _buffered_readline(self, limit);
971}
972
973
974static PyObject *
975buffered_tell(buffered *self, PyObject *args)
976{
977 Py_off_t pos;
978
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);
986}
987
988static PyObject *
989buffered_seek(buffered *self, PyObject *args)
990{
991 Py_off_t target, n;
992 int whence = 0;
993 PyObject *targetobj, *res = NULL;
994
995 CHECK_INITIALIZED(self)
996 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
997 return NULL;
998 }
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;
1003 }
1004
1005 CHECK_CLOSED(self, "seek of closed file")
1006
1007 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1008 if (target == -1 && PyErr_Occurred())
1009 return NULL;
1010
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);
1030 }
1031 }
1032 }
1033
1034 ENTER_BUFFERED(self)
1035
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);
1043 }
1044
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);
1055
1056end:
1057 LEAVE_BUFFERED(self)
1058 return res;
1059}
1060
1061static PyObject *
1062buffered_truncate(buffered *self, PyObject *args)
1063{
1064 PyObject *pos = Py_None;
1065 PyObject *res = NULL;
1066
1067 CHECK_INITIALIZED(self)
1068 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1069 return NULL;
1070 }
1071
1072 ENTER_BUFFERED(self)
1073
1074 if (self->writable) {
1075 res = _bufferedwriter_flush_unlocked(self, 0);
1076 if (res == NULL)
1077 goto end;
1078 Py_CLEAR(res);
1079 }
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;
1086 }
1087 _bufferedreader_reset_buf(self);
1088 }
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();
1095
1096end:
1097 LEAVE_BUFFERED(self)
1098 return res;
1099}
1100
1101static PyObject *
1102buffered_iternext(buffered *self)
1103{
1104 PyObject *line;
1105 PyTypeObject *tp;
1106
1107 CHECK_INITIALIZED(self);
1108
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);
1114 }
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;
1124 }
1125 }
1126
1127 if (line == NULL)
1128 return NULL;
1129
1130 if (PyBytes_GET_SIZE(line) == 0) {
1131 /* Reached EOF or would have blocked */
1132 Py_DECREF(line);
1133 return NULL;
1134 }
1135
1136 return line;
1137}
1138
1139static PyObject *
1140buffered_repr(buffered *self)
1141{
1142 PyObject *nameobj, *res;
1143
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);
1151 }
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);
1161 }
1162 return res;
1163}
1164
1165/*
1166 * class BufferedReader
1167 */
1168
1169PyDoc_STRVAR(bufferedreader_doc,
1170 "Create a new buffered reader using the given readable raw IO object.");
1171
1172static void _bufferedreader_reset_buf(buffered *self)
1173{
1174 self->read_end = -1;
1175}
1176
1177static int
1178bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
1179{
1180 char *kwlist[] = {"raw", "buffer_size", NULL};
1181 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1182 PyObject *raw;
1183
1184 self->ok = 0;
1185 self->detached = 0;
1186
1187 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1188 &raw, &buffer_size)) {
1189 return -1;
1190 }
1191
1192 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
1193 return -1;
1194
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;
1201
1202 if (_buffered_init(self) < 0)
1203 return -1;
1204 _bufferedreader_reset_buf(self);
1205
1206 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1207 Py_TYPE(raw) == &PyFileIO_Type);
1208
1209 self->ok = 1;
1210 return 0;
1211}
1212
1213static Py_ssize_t
1214_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
1215{
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;
1233 }
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;
1241 }
1242 if (n > 0 && self->abs_pos != -1)
1243 self->abs_pos += n;
1244 return n;
1245}
1246
1247static Py_ssize_t
1248_bufferedreader_fill_buffer(buffered *self)
1249{
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;
1262}
1263
1264static PyObject *
1265_bufferedreader_read_all(buffered *self)
1266{
1267 Py_ssize_t current_size;
1268 PyObject *res, *data = NULL;
1269 PyObject *chunks = PyList_New(0);
1270
1271 if (chunks == NULL)
1272 return NULL;
1273
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;
1282 }
1283 }
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;
1291 }
1292 Py_CLEAR(res);
1293 }
1294 while (1) {
1295 if (data) {
1296 if (PyList_Append(chunks, data) < 0) {
1297 Py_DECREF(data);
1298 Py_DECREF(chunks);
1299 return NULL;
1300 }
1301 Py_DECREF(data);
1302 }
1303
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;
1309 }
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;
1315 }
1316 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1317 if (current_size == 0) {
1318 Py_DECREF(chunks);
1319 return data;
1320 }
1321 else {
1322 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1323 Py_DECREF(data);
1324 Py_DECREF(chunks);
1325 return res;
1326 }
1327 }
1328 current_size += PyBytes_GET_SIZE(data);
1329 if (self->abs_pos != -1)
1330 self->abs_pos += PyBytes_GET_SIZE(data);
1331 }
1332}
1333
1334/* Read n bytes from the buffer if it can, otherwise return None.
1335 This function is simple enough that it can run unlocked. */
1336static PyObject *
1337_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
1338{
1339 Py_ssize_t current_size;
1340
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;
1348 }
1349 Py_RETURN_NONE;
1350}
1351
1352/* Generic read function: read from the stream until enough bytes are read,
1353 * or until an EOF occurs or until read() would block.
1354 */
1355static PyObject *
1356_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
1357{
1358 PyObject *res = NULL;
1359 Py_ssize_t current_size, remaining, written;
1360 char *out;
1361
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);
1365
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;
1376 }
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;
1393 }
1394 Py_DECREF(res);
1395 Py_INCREF(Py_None);
1396 return Py_None;
1397 }
1398 remaining -= r;
1399 written += r;
1400 }
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;
1415 }
1416 Py_DECREF(res);
1417 Py_INCREF(Py_None);
1418 return Py_None;
1419 }
1420 if (remaining > r) {
1421 memcpy(out + written, self->buffer + self->pos, r);
1422 written += r;
1423 self->pos += r;
1424 remaining -= r;
1425 }
1426 else if (remaining > 0) {
1427 memcpy(out + written, self->buffer + self->pos, remaining);
1428 written += remaining;
1429 self->pos += remaining;
1430 remaining = 0;
1431 }
1432 if (remaining == 0)
1433 break;
1434 }
1435
1436 return res;
1437
1438error:
1439 Py_XDECREF(res);
1440 return NULL;
1441}
1442
1443static PyObject *
1444_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
1445{
1446 Py_ssize_t have, r;
1447
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.
1454 */
1455 if (have > 0) {
1456 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1457 }
1458
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);
1468}
1469
1470static 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},
1480
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}
1489};
1490
1491static PyMemberDef bufferedreader_members[] = {
1492 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
1493 {NULL}
1494};
1495
1496static 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}
1501};
1502
1503
1504PyTypeObject 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 */
1544};
1545
1546
1547
1548static int
1549complain_about_max_buffer_size(void)
1550{
1551 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1552 "max_buffer_size is deprecated", 1) < 0)
1553 return 0;
1554 return 1;
1555}
1556
1557/*
1558 * class BufferedWriter
1559 */
1560PyDoc_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"
1566 );
1567
1568static void
1569_bufferedwriter_reset_buf(buffered *self)
1570{
1571 self->write_pos = 0;
1572 self->write_end = -1;
1573}
1574
1575static int
1576bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
1577{
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;
1583
1584 self->ok = 0;
1585 self->detached = 0;
1586
1587 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1588 &raw, &buffer_size, &max_buffer_size)) {
1589 return -1;
1590 }
1591
1592 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1593 return -1;
1594
1595 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
1596 return -1;
1597
1598 Py_CLEAR(self->raw);
1599 Py_INCREF(raw);
1600 self->raw = raw;
1601 self->readable = 0;
1602 self->writable = 1;
1603
1604 self->buffer_size = buffer_size;
1605 if (_buffered_init(self) < 0)
1606 return -1;
1607 _bufferedwriter_reset_buf(self);
1608 self->pos = 0;
1609
1610 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1611 Py_TYPE(raw) == &PyFileIO_Type);
1612
1613 self->ok = 1;
1614 return 0;
1615}
1616
1617static Py_ssize_t
1618_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
1619{
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;
1640 }
1641 if (n > 0 && self->abs_pos != -1)
1642 self->abs_pos += n;
1643 return n;
1644}
1645
1646/* `restore_pos` is 1 if we need to restore the raw stream position at
1647 the end, 0 otherwise. */
1648static PyObject *
1649_bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
1650{
1651 Py_ssize_t written = 0;
1652 Py_off_t n, rewind;
1653
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;
1662 }
1663 self->raw_pos -= rewind;
1664 }
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;
1680 }
1681 self->write_pos += n;
1682 self->raw_pos = self->write_pos;
1683 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1684 }
1685
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;
1692 }
1693 self->raw_pos += forward;
1694 }
1695 }
1696 _bufferedwriter_reset_buf(self);
1697
1698end:
1699 Py_RETURN_NONE;
1700
1701error:
1702 return NULL;
1703}
1704
1705static PyObject *
1706bufferedwriter_write(buffered *self, PyObject *args)
1707{
1708 PyObject *res = NULL;
1709 Py_buffer buf;
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001710 Py_ssize_t written, avail, remaining;
1711 Py_off_t offset;
Antoine Pitrou19690592009-06-12 20:14:08 +00001712
1713 CHECK_INITIALIZED(self)
1714 if (!PyArg_ParseTuple(args, "s*:write", &buf)) {
1715 return NULL;
1716 }
1717
1718 if (IS_CLOSED(self)) {
1719 PyErr_SetString(PyExc_ValueError, "write to closed file");
1720 PyBuffer_Release(&buf);
1721 return NULL;
1722 }
1723
1724 ENTER_BUFFERED(self)
1725
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;
1730 }
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;
1736 }
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;
1742 }
1743
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;
1770 }
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;
1777 }
1778 Py_CLEAR(res);
1779
Antoine Pitrou20e1f932009-08-06 20:18:29 +00001780 /* 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.
1785 */
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001786 offset = RAW_OFFSET(self);
1787 if (offset != 0) {
1788 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitrou20e1f932009-08-06 20:18:29 +00001789 goto error;
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001790 self->raw_pos -= offset;
Antoine Pitrou20e1f932009-08-06 20:18:29 +00001791 }
1792
Antoine Pitrou19690592009-06-12 20:14:08 +00001793 /* 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) {
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001797 Py_ssize_t n = _bufferedwriter_raw_write(
Antoine Pitrou19690592009-06-12 20:14:08 +00001798 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;
1815 }
1816 PyErr_Clear();
1817 break;
1818 }
1819 written += n;
1820 remaining -= n;
1821 }
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;
1827 }
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;
1833
1834end:
1835 res = PyLong_FromSsize_t(written);
1836
1837error:
1838 LEAVE_BUFFERED(self)
1839 PyBuffer_Release(&buf);
1840 return res;
1841}
1842
1843static 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},
1852
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}
1859};
1860
1861static PyMemberDef bufferedwriter_members[] = {
1862 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
1863 {NULL}
1864};
1865
1866static 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}
1871};
1872
1873
1874PyTypeObject 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 */
1914};
1915
1916
1917
1918/*
1919 * BufferedRWPair
1920 */
1921
1922PyDoc_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"
1932 );
1933
1934/* XXX The usefulness of this (compared to having two separate IO objects) is
1935 * questionable.
1936 */
1937
1938typedef struct {
1939 PyObject_HEAD
1940 buffered *reader;
1941 buffered *writer;
1942 PyObject *dict;
1943 PyObject *weakreflist;
1944} rwpair;
1945
1946static int
1947bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
1948{
1949 PyObject *reader, *writer;
1950 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1951 Py_ssize_t max_buffer_size = -234;
1952
1953 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1954 &buffer_size, &max_buffer_size)) {
1955 return -1;
1956 }
1957
1958 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1959 return -1;
1960
1961 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
1962 return -1;
1963 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
1964 return -1;
1965
1966 self->reader = (buffered *) PyObject_CallFunction(
1967 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
1968 if (self->reader == NULL)
1969 return -1;
1970
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;
1976 }
1977
1978 return 0;
1979}
1980
1981static int
1982bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
1983{
1984 Py_VISIT(self->dict);
1985 return 0;
1986}
1987
1988static int
1989bufferedrwpair_clear(rwpair *self)
1990{
1991 Py_CLEAR(self->reader);
1992 Py_CLEAR(self->writer);
1993 Py_CLEAR(self->dict);
1994 return 0;
1995}
1996
1997static void
1998bufferedrwpair_dealloc(rwpair *self)
1999{
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);
2005}
2006
2007static PyObject *
2008_forward_call(buffered *self, const char *name, PyObject *args)
2009{
2010 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
2011 PyObject *ret;
2012
2013 if (func == NULL) {
2014 PyErr_SetString(PyExc_AttributeError, name);
2015 return NULL;
2016 }
2017
2018 ret = PyObject_CallObject(func, args);
2019 Py_DECREF(func);
2020 return ret;
2021}
2022
2023static PyObject *
2024bufferedrwpair_read(rwpair *self, PyObject *args)
2025{
2026 return _forward_call(self->reader, "read", args);
2027}
2028
2029static PyObject *
2030bufferedrwpair_peek(rwpair *self, PyObject *args)
2031{
2032 return _forward_call(self->reader, "peek", args);
2033}
2034
2035static PyObject *
2036bufferedrwpair_read1(rwpair *self, PyObject *args)
2037{
2038 return _forward_call(self->reader, "read1", args);
2039}
2040
2041static PyObject *
2042bufferedrwpair_readinto(rwpair *self, PyObject *args)
2043{
2044 return _forward_call(self->reader, "readinto", args);
2045}
2046
2047static PyObject *
2048bufferedrwpair_write(rwpair *self, PyObject *args)
2049{
2050 return _forward_call(self->writer, "write", args);
2051}
2052
2053static PyObject *
2054bufferedrwpair_flush(rwpair *self, PyObject *args)
2055{
2056 return _forward_call(self->writer, "flush", args);
2057}
2058
2059static PyObject *
2060bufferedrwpair_readable(rwpair *self, PyObject *args)
2061{
2062 return _forward_call(self->reader, "readable", args);
2063}
2064
2065static PyObject *
2066bufferedrwpair_writable(rwpair *self, PyObject *args)
2067{
2068 return _forward_call(self->writer, "writable", args);
2069}
2070
2071static PyObject *
2072bufferedrwpair_close(rwpair *self, PyObject *args)
2073{
2074 PyObject *ret = _forward_call(self->writer, "close", args);
2075 if (ret == NULL)
2076 return NULL;
2077 Py_DECREF(ret);
2078
2079 return _forward_call(self->reader, "close", args);
2080}
2081
2082static PyObject *
2083bufferedrwpair_isatty(rwpair *self, PyObject *args)
2084{
2085 PyObject *ret = _forward_call(self->writer, "isatty", args);
2086
2087 if (ret != Py_False) {
2088 /* either True or exception */
2089 return ret;
2090 }
2091 Py_DECREF(ret);
2092
2093 return _forward_call(self->reader, "isatty", args);
2094}
2095
2096static PyObject *
2097bufferedrwpair_closed_get(rwpair *self, void *context)
2098{
2099 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2100}
2101
2102static 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},
2107
2108 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2109 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
2110
2111 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2112 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
2113
2114 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2115 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
2116
2117 {NULL, NULL}
2118};
2119
2120static PyGetSetDef bufferedrwpair_getset[] = {
2121 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
2122 {NULL}
2123};
2124
2125PyTypeObject 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 */
2165};
2166
2167
2168
2169/*
2170 * BufferedRandom
2171 */
2172
2173PyDoc_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"
2179 );
2180
2181static int
2182bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
2183{
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;
2188
2189 self->ok = 0;
2190 self->detached = 0;
2191
2192 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2193 &raw, &buffer_size, &max_buffer_size)) {
2194 return -1;
2195 }
2196
2197 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2198 return -1;
2199
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;
2206
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;
2213
2214 if (_buffered_init(self) < 0)
2215 return -1;
2216 _bufferedreader_reset_buf(self);
2217 _bufferedwriter_reset_buf(self);
2218 self->pos = 0;
2219
2220 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2221 Py_TYPE(raw) == &PyFileIO_Type);
2222
2223 self->ok = 1;
2224 return 0;
2225}
2226
2227static 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},
2236
2237 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2238
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}
2249};
2250
2251static PyMemberDef bufferedrandom_members[] = {
2252 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
2253 {NULL}
2254};
2255
2256static 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}
2261};
2262
2263
2264PyTypeObject 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 */
2304};
2305