blob: 3ab7906a9307af2b1f530abbce3ba81c2f0a3221 [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 Dickinson889d96452009-11-24 20:51:48 +0000585 "Raw stream returned invalid position %" PY_PRIdOFF,
586 (PY_OFF_T_COMPAT)n);
Antoine Pitrou19690592009-06-12 20:14:08 +0000587 return -1;
588 }
589 self->abs_pos = n;
590 return n;
591}
592
593static Py_off_t
594_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
595{
596 PyObject *res, *posobj, *whenceobj;
597 Py_off_t n;
598
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;
606 }
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,
Mark Dickinson889d96452009-11-24 20:51:48 +0000618 "Raw stream returned invalid position %" PY_PRIdOFF,
619 (PY_OFF_T_COMPAT)n);
Antoine Pitrou19690592009-06-12 20:14:08 +0000620 return -1;
621 }
622 self->abs_pos = n;
623 return n;
624}
625
626static int
627_buffered_init(buffered *self)
628{
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;
634 }
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;
641 }
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;
647 }
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)
652 ;
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;
660}
661
662/*
663 * Shared methods and wrappers
664 */
665
666static PyObject *
667buffered_flush(buffered *self, PyObject *args)
668{
669 PyObject *res;
670
671 CHECK_INITIALIZED(self)
672 CHECK_CLOSED(self, "flush of closed file")
673
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);
684 }
685 LEAVE_BUFFERED(self)
686
687 return res;
688}
689
690static PyObject *
691buffered_peek(buffered *self, PyObject *args)
692{
693 Py_ssize_t n = 0;
694 PyObject *res = NULL;
695
696 CHECK_INITIALIZED(self)
697 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
698 return NULL;
699 }
700
701 ENTER_BUFFERED(self)
702
703 if (self->writable) {
704 res = _bufferedwriter_flush_unlocked(self, 1);
705 if (res == NULL)
706 goto end;
707 Py_CLEAR(res);
708 }
709 res = _bufferedreader_peek_unlocked(self, n);
710
711end:
712 LEAVE_BUFFERED(self)
713 return res;
714}
715
716static PyObject *
717buffered_read(buffered *self, PyObject *args)
718{
719 Py_ssize_t n = -1;
720 PyObject *res;
721
722 CHECK_INITIALIZED(self)
723 if (!PyArg_ParseTuple(args, "|n:read", &n)) {
724 return NULL;
725 }
726 if (n < -1) {
727 PyErr_SetString(PyExc_ValueError,
728 "read length must be positive or -1");
729 return NULL;
730 }
731
732 CHECK_CLOSED(self, "read of closed file")
733
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)
739 }
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)
747 }
748 }
749
750 return res;
751}
752
753static PyObject *
754buffered_read1(buffered *self, PyObject *args)
755{
756 Py_ssize_t n, have, r;
757 PyObject *res = NULL;
758
759 CHECK_INITIALIZED(self)
760 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
761 return NULL;
762 }
763
764 if (n < 0) {
765 PyErr_SetString(PyExc_ValueError,
766 "read length must be positive");
767 return NULL;
768 }
769 if (n == 0)
770 return PyBytes_FromStringAndSize(NULL, 0);
771
772 ENTER_BUFFERED(self)
773
774 if (self->writable) {
775 res = _bufferedwriter_flush_unlocked(self, 1);
776 if (res == NULL)
777 goto end;
778 Py_CLEAR(res);
779 }
780
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. */
783
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). */
788
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;
798 }
799
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;
813
814end:
815 LEAVE_BUFFERED(self)
816 return res;
817}
818
819static PyObject *
820buffered_readinto(buffered *self, PyObject *args)
821{
822 PyObject *res = NULL;
823
824 CHECK_INITIALIZED(self)
825
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);
834 }
835 res = bufferediobase_readinto((PyObject *)self, args);
836
837end:
838 return res;
839}
840
841static PyObject *
842_buffered_readline(buffered *self, Py_ssize_t limit)
843{
844 PyObject *res = NULL;
845 PyObject *chunks = NULL;
846 Py_ssize_t n, written = 0;
847 const char *start, *s, *end;
848
849 CHECK_CLOSED(self, "readline of closed file")
850
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;
864 }
865 if (n == limit) {
866 res = PyBytes_FromStringAndSize(start, n);
867 if (res != NULL)
868 self->pos += n;
869 goto end_unlocked;
870 }
871
872 ENTER_BUFFERED(self)
873
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);
880 }
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;
891 }
892 Py_CLEAR(res);
893 written += n;
894 if (limit >= 0)
895 limit -= n;
896 }
897
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;
917 }
918 }
919 res = PyBytes_FromStringAndSize(start, n);
920 if (res == NULL)
921 goto end;
922 if (n == limit) {
923 self->pos = n;
924 break;
925 }
926 if (PyList_Append(chunks, res) < 0) {
927 Py_CLEAR(res);
928 goto end;
929 }
930 Py_CLEAR(res);
931 written += n;
932 if (limit >= 0)
933 limit -= n;
934 }
935found:
936 if (res != NULL && PyList_Append(chunks, res) < 0) {
937 Py_CLEAR(res);
938 goto end;
939 }
940 Py_CLEAR(res);
941 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
942
943end:
944 LEAVE_BUFFERED(self)
945end_unlocked:
946 Py_XDECREF(chunks);
947 return res;
948}
949
950static PyObject *
951buffered_readline(buffered *self, PyObject *args)
952{
953 PyObject *limitobj = NULL;
954 Py_ssize_t limit = -1;
955
956 CHECK_INITIALIZED(self)
957
958 if (!PyArg_ParseTuple(args, "|O:readline", &limitobj)) {
959 return NULL;
960 }
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;
967 }
968 limit = PyNumber_AsSsize_t(limitobj, PyExc_OverflowError);
969 if (limit == -1 && PyErr_Occurred())
970 return NULL;
971 }
972 return _buffered_readline(self, limit);
973}
974
975
976static PyObject *
977buffered_tell(buffered *self, PyObject *args)
978{
979 Py_off_t pos;
980
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);
988}
989
990static PyObject *
991buffered_seek(buffered *self, PyObject *args)
992{
993 Py_off_t target, n;
994 int whence = 0;
995 PyObject *targetobj, *res = NULL;
996
997 CHECK_INITIALIZED(self)
998 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
999 return NULL;
1000 }
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;
1005 }
1006
1007 CHECK_CLOSED(self, "seek of closed file")
1008
1009 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1010 if (target == -1 && PyErr_Occurred())
1011 return NULL;
1012
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);
1032 }
1033 }
1034 }
1035
1036 ENTER_BUFFERED(self)
1037
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);
1045 }
1046
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);
1057
1058end:
1059 LEAVE_BUFFERED(self)
1060 return res;
1061}
1062
1063static PyObject *
1064buffered_truncate(buffered *self, PyObject *args)
1065{
1066 PyObject *pos = Py_None;
1067 PyObject *res = NULL;
1068
1069 CHECK_INITIALIZED(self)
1070 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1071 return NULL;
1072 }
1073
1074 ENTER_BUFFERED(self)
1075
1076 if (self->writable) {
1077 res = _bufferedwriter_flush_unlocked(self, 0);
1078 if (res == NULL)
1079 goto end;
1080 Py_CLEAR(res);
1081 }
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;
1088 }
1089 _bufferedreader_reset_buf(self);
1090 }
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();
1097
1098end:
1099 LEAVE_BUFFERED(self)
1100 return res;
1101}
1102
1103static PyObject *
1104buffered_iternext(buffered *self)
1105{
1106 PyObject *line;
1107 PyTypeObject *tp;
1108
1109 CHECK_INITIALIZED(self);
1110
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);
1116 }
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;
1126 }
1127 }
1128
1129 if (line == NULL)
1130 return NULL;
1131
1132 if (PyBytes_GET_SIZE(line) == 0) {
1133 /* Reached EOF or would have blocked */
1134 Py_DECREF(line);
1135 return NULL;
1136 }
1137
1138 return line;
1139}
1140
1141static PyObject *
1142buffered_repr(buffered *self)
1143{
1144 PyObject *nameobj, *res;
1145
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);
1153 }
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);
1163 }
1164 return res;
1165}
1166
1167/*
1168 * class BufferedReader
1169 */
1170
1171PyDoc_STRVAR(bufferedreader_doc,
1172 "Create a new buffered reader using the given readable raw IO object.");
1173
1174static void _bufferedreader_reset_buf(buffered *self)
1175{
1176 self->read_end = -1;
1177}
1178
1179static int
1180bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
1181{
1182 char *kwlist[] = {"raw", "buffer_size", NULL};
1183 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1184 PyObject *raw;
1185
1186 self->ok = 0;
1187 self->detached = 0;
1188
1189 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1190 &raw, &buffer_size)) {
1191 return -1;
1192 }
1193
1194 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
1195 return -1;
1196
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;
1203
1204 if (_buffered_init(self) < 0)
1205 return -1;
1206 _bufferedreader_reset_buf(self);
1207
1208 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1209 Py_TYPE(raw) == &PyFileIO_Type);
1210
1211 self->ok = 1;
1212 return 0;
1213}
1214
1215static Py_ssize_t
1216_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
1217{
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;
1235 }
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;
1243 }
1244 if (n > 0 && self->abs_pos != -1)
1245 self->abs_pos += n;
1246 return n;
1247}
1248
1249static Py_ssize_t
1250_bufferedreader_fill_buffer(buffered *self)
1251{
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;
1264}
1265
1266static PyObject *
1267_bufferedreader_read_all(buffered *self)
1268{
1269 Py_ssize_t current_size;
1270 PyObject *res, *data = NULL;
1271 PyObject *chunks = PyList_New(0);
1272
1273 if (chunks == NULL)
1274 return NULL;
1275
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;
1284 }
1285 }
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;
1293 }
1294 Py_CLEAR(res);
1295 }
1296 while (1) {
1297 if (data) {
1298 if (PyList_Append(chunks, data) < 0) {
1299 Py_DECREF(data);
1300 Py_DECREF(chunks);
1301 return NULL;
1302 }
1303 Py_DECREF(data);
1304 }
1305
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;
1311 }
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;
1317 }
1318 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1319 if (current_size == 0) {
1320 Py_DECREF(chunks);
1321 return data;
1322 }
1323 else {
1324 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1325 Py_DECREF(data);
1326 Py_DECREF(chunks);
1327 return res;
1328 }
1329 }
1330 current_size += PyBytes_GET_SIZE(data);
1331 if (self->abs_pos != -1)
1332 self->abs_pos += PyBytes_GET_SIZE(data);
1333 }
1334}
1335
1336/* Read n bytes from the buffer if it can, otherwise return None.
1337 This function is simple enough that it can run unlocked. */
1338static PyObject *
1339_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
1340{
1341 Py_ssize_t current_size;
1342
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;
1350 }
1351 Py_RETURN_NONE;
1352}
1353
1354/* Generic read function: read from the stream until enough bytes are read,
1355 * or until an EOF occurs or until read() would block.
1356 */
1357static PyObject *
1358_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
1359{
1360 PyObject *res = NULL;
1361 Py_ssize_t current_size, remaining, written;
1362 char *out;
1363
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);
1367
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;
1378 }
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;
1395 }
1396 Py_DECREF(res);
1397 Py_INCREF(Py_None);
1398 return Py_None;
1399 }
1400 remaining -= r;
1401 written += r;
1402 }
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;
1417 }
1418 Py_DECREF(res);
1419 Py_INCREF(Py_None);
1420 return Py_None;
1421 }
1422 if (remaining > r) {
1423 memcpy(out + written, self->buffer + self->pos, r);
1424 written += r;
1425 self->pos += r;
1426 remaining -= r;
1427 }
1428 else if (remaining > 0) {
1429 memcpy(out + written, self->buffer + self->pos, remaining);
1430 written += remaining;
1431 self->pos += remaining;
1432 remaining = 0;
1433 }
1434 if (remaining == 0)
1435 break;
1436 }
1437
1438 return res;
1439
1440error:
1441 Py_XDECREF(res);
1442 return NULL;
1443}
1444
1445static PyObject *
1446_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
1447{
1448 Py_ssize_t have, r;
1449
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.
1456 */
1457 if (have > 0) {
1458 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1459 }
1460
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);
1470}
1471
1472static 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},
1482
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}
1491};
1492
1493static PyMemberDef bufferedreader_members[] = {
1494 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
1495 {NULL}
1496};
1497
1498static 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}
1503};
1504
1505
1506PyTypeObject 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 */
1546};
1547
1548
1549
1550static int
1551complain_about_max_buffer_size(void)
1552{
1553 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1554 "max_buffer_size is deprecated", 1) < 0)
1555 return 0;
1556 return 1;
1557}
1558
1559/*
1560 * class BufferedWriter
1561 */
1562PyDoc_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"
1568 );
1569
1570static void
1571_bufferedwriter_reset_buf(buffered *self)
1572{
1573 self->write_pos = 0;
1574 self->write_end = -1;
1575}
1576
1577static int
1578bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
1579{
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;
1585
1586 self->ok = 0;
1587 self->detached = 0;
1588
1589 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1590 &raw, &buffer_size, &max_buffer_size)) {
1591 return -1;
1592 }
1593
1594 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1595 return -1;
1596
1597 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
1598 return -1;
1599
1600 Py_CLEAR(self->raw);
1601 Py_INCREF(raw);
1602 self->raw = raw;
1603 self->readable = 0;
1604 self->writable = 1;
1605
1606 self->buffer_size = buffer_size;
1607 if (_buffered_init(self) < 0)
1608 return -1;
1609 _bufferedwriter_reset_buf(self);
1610 self->pos = 0;
1611
1612 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1613 Py_TYPE(raw) == &PyFileIO_Type);
1614
1615 self->ok = 1;
1616 return 0;
1617}
1618
1619static Py_ssize_t
1620_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
1621{
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;
1642 }
1643 if (n > 0 && self->abs_pos != -1)
1644 self->abs_pos += n;
1645 return n;
1646}
1647
1648/* `restore_pos` is 1 if we need to restore the raw stream position at
1649 the end, 0 otherwise. */
1650static PyObject *
1651_bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
1652{
1653 Py_ssize_t written = 0;
1654 Py_off_t n, rewind;
1655
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;
1664 }
1665 self->raw_pos -= rewind;
1666 }
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;
1682 }
1683 self->write_pos += n;
1684 self->raw_pos = self->write_pos;
1685 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1686 }
1687
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;
1694 }
1695 self->raw_pos += forward;
1696 }
1697 }
1698 _bufferedwriter_reset_buf(self);
1699
1700end:
1701 Py_RETURN_NONE;
1702
1703error:
1704 return NULL;
1705}
1706
1707static PyObject *
1708bufferedwriter_write(buffered *self, PyObject *args)
1709{
1710 PyObject *res = NULL;
1711 Py_buffer buf;
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001712 Py_ssize_t written, avail, remaining;
1713 Py_off_t offset;
Antoine Pitrou19690592009-06-12 20:14:08 +00001714
1715 CHECK_INITIALIZED(self)
1716 if (!PyArg_ParseTuple(args, "s*:write", &buf)) {
1717 return NULL;
1718 }
1719
1720 if (IS_CLOSED(self)) {
1721 PyErr_SetString(PyExc_ValueError, "write to closed file");
1722 PyBuffer_Release(&buf);
1723 return NULL;
1724 }
1725
1726 ENTER_BUFFERED(self)
1727
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;
1732 }
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;
1738 }
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;
1744 }
1745
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;
1772 }
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;
1779 }
1780 Py_CLEAR(res);
1781
Antoine Pitrou20e1f932009-08-06 20:18:29 +00001782 /* 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.
1787 */
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001788 offset = RAW_OFFSET(self);
1789 if (offset != 0) {
1790 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitrou20e1f932009-08-06 20:18:29 +00001791 goto error;
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001792 self->raw_pos -= offset;
Antoine Pitrou20e1f932009-08-06 20:18:29 +00001793 }
1794
Antoine Pitrou19690592009-06-12 20:14:08 +00001795 /* 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) {
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001799 Py_ssize_t n = _bufferedwriter_raw_write(
Antoine Pitrou19690592009-06-12 20:14:08 +00001800 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;
1817 }
1818 PyErr_Clear();
1819 break;
1820 }
1821 written += n;
1822 remaining -= n;
1823 }
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;
1829 }
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;
1835
1836end:
1837 res = PyLong_FromSsize_t(written);
1838
1839error:
1840 LEAVE_BUFFERED(self)
1841 PyBuffer_Release(&buf);
1842 return res;
1843}
1844
1845static 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},
1854
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}
1861};
1862
1863static PyMemberDef bufferedwriter_members[] = {
1864 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
1865 {NULL}
1866};
1867
1868static 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}
1873};
1874
1875
1876PyTypeObject 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 */
1916};
1917
1918
1919
1920/*
1921 * BufferedRWPair
1922 */
1923
1924PyDoc_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"
1934 );
1935
1936/* XXX The usefulness of this (compared to having two separate IO objects) is
1937 * questionable.
1938 */
1939
1940typedef struct {
1941 PyObject_HEAD
1942 buffered *reader;
1943 buffered *writer;
1944 PyObject *dict;
1945 PyObject *weakreflist;
1946} rwpair;
1947
1948static int
1949bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
1950{
1951 PyObject *reader, *writer;
1952 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1953 Py_ssize_t max_buffer_size = -234;
1954
1955 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1956 &buffer_size, &max_buffer_size)) {
1957 return -1;
1958 }
1959
1960 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1961 return -1;
1962
1963 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
1964 return -1;
1965 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
1966 return -1;
1967
1968 self->reader = (buffered *) PyObject_CallFunction(
1969 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
1970 if (self->reader == NULL)
1971 return -1;
1972
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;
1978 }
1979
1980 return 0;
1981}
1982
1983static int
1984bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
1985{
1986 Py_VISIT(self->dict);
1987 return 0;
1988}
1989
1990static int
1991bufferedrwpair_clear(rwpair *self)
1992{
1993 Py_CLEAR(self->reader);
1994 Py_CLEAR(self->writer);
1995 Py_CLEAR(self->dict);
1996 return 0;
1997}
1998
1999static void
2000bufferedrwpair_dealloc(rwpair *self)
2001{
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);
2007}
2008
2009static PyObject *
2010_forward_call(buffered *self, const char *name, PyObject *args)
2011{
2012 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
2013 PyObject *ret;
2014
2015 if (func == NULL) {
2016 PyErr_SetString(PyExc_AttributeError, name);
2017 return NULL;
2018 }
2019
2020 ret = PyObject_CallObject(func, args);
2021 Py_DECREF(func);
2022 return ret;
2023}
2024
2025static PyObject *
2026bufferedrwpair_read(rwpair *self, PyObject *args)
2027{
2028 return _forward_call(self->reader, "read", args);
2029}
2030
2031static PyObject *
2032bufferedrwpair_peek(rwpair *self, PyObject *args)
2033{
2034 return _forward_call(self->reader, "peek", args);
2035}
2036
2037static PyObject *
2038bufferedrwpair_read1(rwpair *self, PyObject *args)
2039{
2040 return _forward_call(self->reader, "read1", args);
2041}
2042
2043static PyObject *
2044bufferedrwpair_readinto(rwpair *self, PyObject *args)
2045{
2046 return _forward_call(self->reader, "readinto", args);
2047}
2048
2049static PyObject *
2050bufferedrwpair_write(rwpair *self, PyObject *args)
2051{
2052 return _forward_call(self->writer, "write", args);
2053}
2054
2055static PyObject *
2056bufferedrwpair_flush(rwpair *self, PyObject *args)
2057{
2058 return _forward_call(self->writer, "flush", args);
2059}
2060
2061static PyObject *
2062bufferedrwpair_readable(rwpair *self, PyObject *args)
2063{
2064 return _forward_call(self->reader, "readable", args);
2065}
2066
2067static PyObject *
2068bufferedrwpair_writable(rwpair *self, PyObject *args)
2069{
2070 return _forward_call(self->writer, "writable", args);
2071}
2072
2073static PyObject *
2074bufferedrwpair_close(rwpair *self, PyObject *args)
2075{
2076 PyObject *ret = _forward_call(self->writer, "close", args);
2077 if (ret == NULL)
2078 return NULL;
2079 Py_DECREF(ret);
2080
2081 return _forward_call(self->reader, "close", args);
2082}
2083
2084static PyObject *
2085bufferedrwpair_isatty(rwpair *self, PyObject *args)
2086{
2087 PyObject *ret = _forward_call(self->writer, "isatty", args);
2088
2089 if (ret != Py_False) {
2090 /* either True or exception */
2091 return ret;
2092 }
2093 Py_DECREF(ret);
2094
2095 return _forward_call(self->reader, "isatty", args);
2096}
2097
2098static PyObject *
2099bufferedrwpair_closed_get(rwpair *self, void *context)
2100{
2101 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2102}
2103
2104static 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},
2109
2110 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2111 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
2112
2113 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2114 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
2115
2116 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2117 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
2118
2119 {NULL, NULL}
2120};
2121
2122static PyGetSetDef bufferedrwpair_getset[] = {
2123 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
2124 {NULL}
2125};
2126
2127PyTypeObject 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 */
2167};
2168
2169
2170
2171/*
2172 * BufferedRandom
2173 */
2174
2175PyDoc_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"
2181 );
2182
2183static int
2184bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
2185{
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;
2190
2191 self->ok = 0;
2192 self->detached = 0;
2193
2194 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2195 &raw, &buffer_size, &max_buffer_size)) {
2196 return -1;
2197 }
2198
2199 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2200 return -1;
2201
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;
2208
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;
2215
2216 if (_buffered_init(self) < 0)
2217 return -1;
2218 _bufferedreader_reset_buf(self);
2219 _bufferedwriter_reset_buf(self);
2220 self->pos = 0;
2221
2222 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2223 Py_TYPE(raw) == &PyFileIO_Type);
2224
2225 self->ok = 1;
2226 return 0;
2227}
2228
2229static 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},
2238
2239 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2240
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}
2251};
2252
2253static PyMemberDef bufferedrandom_members[] = {
2254 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
2255 {NULL}
2256};
2257
2258static 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}
2263};
2264
2265
2266PyTypeObject 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 */
2306};
2307