blob: a68f8fecf601698b5faccc8fd27c99d2148e9c0a [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) {
Antoine Pitrouf7fd8e42010-05-03 16:25:33 +0000443 goto end;
Antoine Pitrou19690592009-06-12 20:14:08 +0000444 }
445 Py_XDECREF(res);
446
447 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
448
449end:
450 LEAVE_BUFFERED(self)
451 return res;
452}
453
454/* detach */
455
456static PyObject *
457buffered_detach(buffered *self, PyObject *args)
458{
459 PyObject *raw, *res;
460 CHECK_INITIALIZED(self)
461 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
462 if (res == NULL)
463 return NULL;
464 Py_DECREF(res);
465 raw = self->raw;
466 self->raw = NULL;
467 self->detached = 1;
468 self->ok = 0;
469 return raw;
470}
471
472/* Inquiries */
473
474static PyObject *
475buffered_seekable(buffered *self, PyObject *args)
476{
477 CHECK_INITIALIZED(self)
478 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
479}
480
481static PyObject *
482buffered_readable(buffered *self, PyObject *args)
483{
484 CHECK_INITIALIZED(self)
485 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
486}
487
488static PyObject *
489buffered_writable(buffered *self, PyObject *args)
490{
491 CHECK_INITIALIZED(self)
492 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
493}
494
495static PyObject *
496buffered_name_get(buffered *self, void *context)
497{
498 CHECK_INITIALIZED(self)
499 return PyObject_GetAttrString(self->raw, "name");
500}
501
502static PyObject *
503buffered_mode_get(buffered *self, void *context)
504{
505 CHECK_INITIALIZED(self)
506 return PyObject_GetAttrString(self->raw, "mode");
507}
508
509/* Lower-level APIs */
510
511static PyObject *
512buffered_fileno(buffered *self, PyObject *args)
513{
514 CHECK_INITIALIZED(self)
515 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
516}
517
518static PyObject *
519buffered_isatty(buffered *self, PyObject *args)
520{
521 CHECK_INITIALIZED(self)
522 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
523}
524
525
526/* Forward decls */
527static PyObject *
528_bufferedwriter_flush_unlocked(buffered *, int);
529static Py_ssize_t
530_bufferedreader_fill_buffer(buffered *self);
531static void
532_bufferedreader_reset_buf(buffered *self);
533static void
534_bufferedwriter_reset_buf(buffered *self);
535static PyObject *
536_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t);
537static PyObject *
538_bufferedreader_read_all(buffered *self);
539static PyObject *
540_bufferedreader_read_fast(buffered *self, Py_ssize_t);
541static PyObject *
542_bufferedreader_read_generic(buffered *self, Py_ssize_t);
543
544
545/*
546 * Helpers
547 */
548
549/* Returns the address of the `written` member if a BlockingIOError was
550 raised, NULL otherwise. The error is always re-raised. */
551static Py_ssize_t *
552_buffered_check_blocking_error(void)
553{
554 PyObject *t, *v, *tb;
555 PyBlockingIOErrorObject *err;
556
557 PyErr_Fetch(&t, &v, &tb);
558 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
559 PyErr_Restore(t, v, tb);
560 return NULL;
561 }
562 err = (PyBlockingIOErrorObject *) v;
563 /* TODO: sanity check (err->written >= 0) */
564 PyErr_Restore(t, v, tb);
565 return &err->written;
566}
567
568static Py_off_t
569_buffered_raw_tell(buffered *self)
570{
571 Py_off_t n;
572 PyObject *res;
573 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
574 if (res == NULL)
575 return -1;
576 n = PyNumber_AsOff_t(res, PyExc_ValueError);
577 Py_DECREF(res);
578 if (n < 0) {
579 if (!PyErr_Occurred())
580 PyErr_Format(PyExc_IOError,
Mark Dickinson889d96452009-11-24 20:51:48 +0000581 "Raw stream returned invalid position %" PY_PRIdOFF,
582 (PY_OFF_T_COMPAT)n);
Antoine Pitrou19690592009-06-12 20:14:08 +0000583 return -1;
584 }
585 self->abs_pos = n;
586 return n;
587}
588
589static Py_off_t
590_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
591{
592 PyObject *res, *posobj, *whenceobj;
593 Py_off_t n;
594
595 posobj = PyLong_FromOff_t(target);
596 if (posobj == NULL)
597 return -1;
598 whenceobj = PyLong_FromLong(whence);
599 if (whenceobj == NULL) {
600 Py_DECREF(posobj);
601 return -1;
602 }
603 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
604 posobj, whenceobj, NULL);
605 Py_DECREF(posobj);
606 Py_DECREF(whenceobj);
607 if (res == NULL)
608 return -1;
609 n = PyNumber_AsOff_t(res, PyExc_ValueError);
610 Py_DECREF(res);
611 if (n < 0) {
612 if (!PyErr_Occurred())
613 PyErr_Format(PyExc_IOError,
Mark Dickinson889d96452009-11-24 20:51:48 +0000614 "Raw stream returned invalid position %" PY_PRIdOFF,
615 (PY_OFF_T_COMPAT)n);
Antoine Pitrou19690592009-06-12 20:14:08 +0000616 return -1;
617 }
618 self->abs_pos = n;
619 return n;
620}
621
622static int
623_buffered_init(buffered *self)
624{
625 Py_ssize_t n;
626 if (self->buffer_size <= 0) {
627 PyErr_SetString(PyExc_ValueError,
628 "buffer size must be strictly positive");
629 return -1;
630 }
631 if (self->buffer)
632 PyMem_Free(self->buffer);
633 self->buffer = PyMem_Malloc(self->buffer_size);
634 if (self->buffer == NULL) {
635 PyErr_NoMemory();
636 return -1;
637 }
638#ifdef WITH_THREAD
Antoine Pitrou607951d2010-08-01 16:57:17 +0000639 if (self->lock)
640 PyThread_free_lock(self->lock);
Antoine Pitrou19690592009-06-12 20:14:08 +0000641 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)
Benjamin Petersonddd392c2009-12-13 19:19:07 +0000721 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
Antoine Pitrou19690592009-06-12 20:14:08 +0000722 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{
Antoine Pitrou19690592009-06-12 20:14:08 +0000951 Py_ssize_t limit = -1;
952
953 CHECK_INITIALIZED(self)
Benjamin Petersonddd392c2009-12-13 19:19:07 +0000954 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
Antoine Pitrou19690592009-06-12 20:14:08 +0000955 return NULL;
Antoine Pitrou19690592009-06-12 20:14:08 +0000956 return _buffered_readline(self, limit);
957}
958
959
960static PyObject *
961buffered_tell(buffered *self, PyObject *args)
962{
963 Py_off_t pos;
964
965 CHECK_INITIALIZED(self)
966 pos = _buffered_raw_tell(self);
967 if (pos == -1)
968 return NULL;
969 pos -= RAW_OFFSET(self);
970 /* TODO: sanity check (pos >= 0) */
971 return PyLong_FromOff_t(pos);
972}
973
974static PyObject *
975buffered_seek(buffered *self, PyObject *args)
976{
977 Py_off_t target, n;
978 int whence = 0;
979 PyObject *targetobj, *res = NULL;
980
981 CHECK_INITIALIZED(self)
982 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
983 return NULL;
984 }
985 if (whence < 0 || whence > 2) {
986 PyErr_Format(PyExc_ValueError,
987 "whence must be between 0 and 2, not %d", whence);
988 return NULL;
989 }
990
991 CHECK_CLOSED(self, "seek of closed file")
992
993 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
994 if (target == -1 && PyErr_Occurred())
995 return NULL;
996
997 if (whence != 2 && self->readable) {
998 Py_off_t current, avail;
999 /* Check if seeking leaves us inside the current buffer,
1000 so as to return quickly if possible. Also, we needn't take the
1001 lock in this fast path.
1002 Don't know how to do that when whence == 2, though. */
1003 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1004 state at this point. */
1005 current = RAW_TELL(self);
1006 avail = READAHEAD(self);
1007 if (avail > 0) {
1008 Py_off_t offset;
1009 if (whence == 0)
1010 offset = target - (current - RAW_OFFSET(self));
1011 else
1012 offset = target;
1013 if (offset >= -self->pos && offset <= avail) {
1014 self->pos += offset;
1015 return PyLong_FromOff_t(current - avail + offset);
1016 }
1017 }
1018 }
1019
1020 ENTER_BUFFERED(self)
1021
1022 /* Fallback: invoke raw seek() method and clear buffer */
1023 if (self->writable) {
1024 res = _bufferedwriter_flush_unlocked(self, 0);
1025 if (res == NULL)
1026 goto end;
1027 Py_CLEAR(res);
1028 _bufferedwriter_reset_buf(self);
1029 }
1030
1031 /* TODO: align on block boundary and read buffer if needed? */
1032 if (whence == 1)
1033 target -= RAW_OFFSET(self);
1034 n = _buffered_raw_seek(self, target, whence);
1035 if (n == -1)
1036 goto end;
1037 self->raw_pos = -1;
1038 res = PyLong_FromOff_t(n);
1039 if (res != NULL && self->readable)
1040 _bufferedreader_reset_buf(self);
1041
1042end:
1043 LEAVE_BUFFERED(self)
1044 return res;
1045}
1046
1047static PyObject *
1048buffered_truncate(buffered *self, PyObject *args)
1049{
1050 PyObject *pos = Py_None;
1051 PyObject *res = NULL;
1052
1053 CHECK_INITIALIZED(self)
1054 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1055 return NULL;
1056 }
1057
1058 ENTER_BUFFERED(self)
1059
1060 if (self->writable) {
1061 res = _bufferedwriter_flush_unlocked(self, 0);
1062 if (res == NULL)
1063 goto end;
1064 Py_CLEAR(res);
1065 }
1066 if (self->readable) {
1067 if (pos == Py_None) {
1068 /* Rewind the raw stream so that its position corresponds to
1069 the current logical position. */
1070 if (_buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)
1071 goto end;
1072 }
1073 _bufferedreader_reset_buf(self);
1074 }
1075 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1076 if (res == NULL)
1077 goto end;
1078 /* Reset cached position */
1079 if (_buffered_raw_tell(self) == -1)
1080 PyErr_Clear();
1081
1082end:
1083 LEAVE_BUFFERED(self)
1084 return res;
1085}
1086
1087static PyObject *
1088buffered_iternext(buffered *self)
1089{
1090 PyObject *line;
1091 PyTypeObject *tp;
1092
1093 CHECK_INITIALIZED(self);
1094
1095 tp = Py_TYPE(self);
1096 if (tp == &PyBufferedReader_Type ||
1097 tp == &PyBufferedRandom_Type) {
1098 /* Skip method call overhead for speed */
1099 line = _buffered_readline(self, -1);
1100 }
1101 else {
1102 line = PyObject_CallMethodObjArgs((PyObject *)self,
1103 _PyIO_str_readline, NULL);
1104 if (line && !PyBytes_Check(line)) {
1105 PyErr_Format(PyExc_IOError,
1106 "readline() should have returned a bytes object, "
1107 "not '%.200s'", Py_TYPE(line)->tp_name);
1108 Py_DECREF(line);
1109 return NULL;
1110 }
1111 }
1112
1113 if (line == NULL)
1114 return NULL;
1115
1116 if (PyBytes_GET_SIZE(line) == 0) {
1117 /* Reached EOF or would have blocked */
1118 Py_DECREF(line);
1119 return NULL;
1120 }
1121
1122 return line;
1123}
1124
1125static PyObject *
1126buffered_repr(buffered *self)
1127{
1128 PyObject *nameobj, *res;
1129
1130 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1131 if (nameobj == NULL) {
1132 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1133 PyErr_Clear();
1134 else
1135 return NULL;
1136 res = PyString_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1137 }
1138 else {
1139 PyObject *repr = PyObject_Repr(nameobj);
1140 Py_DECREF(nameobj);
1141 if (repr == NULL)
1142 return NULL;
1143 res = PyString_FromFormat("<%s name=%s>",
1144 Py_TYPE(self)->tp_name,
1145 PyString_AS_STRING(repr));
1146 Py_DECREF(repr);
1147 }
1148 return res;
1149}
1150
1151/*
1152 * class BufferedReader
1153 */
1154
1155PyDoc_STRVAR(bufferedreader_doc,
1156 "Create a new buffered reader using the given readable raw IO object.");
1157
1158static void _bufferedreader_reset_buf(buffered *self)
1159{
1160 self->read_end = -1;
1161}
1162
1163static int
1164bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
1165{
1166 char *kwlist[] = {"raw", "buffer_size", NULL};
1167 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1168 PyObject *raw;
1169
1170 self->ok = 0;
1171 self->detached = 0;
1172
1173 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1174 &raw, &buffer_size)) {
1175 return -1;
1176 }
1177
1178 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
1179 return -1;
1180
1181 Py_CLEAR(self->raw);
1182 Py_INCREF(raw);
1183 self->raw = raw;
1184 self->buffer_size = buffer_size;
1185 self->readable = 1;
1186 self->writable = 0;
1187
1188 if (_buffered_init(self) < 0)
1189 return -1;
1190 _bufferedreader_reset_buf(self);
1191
1192 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1193 Py_TYPE(raw) == &PyFileIO_Type);
1194
1195 self->ok = 1;
1196 return 0;
1197}
1198
1199static Py_ssize_t
1200_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
1201{
1202 Py_buffer buf;
1203 PyObject *memobj, *res;
1204 Py_ssize_t n;
1205 /* NOTE: the buffer needn't be released as its object is NULL. */
1206 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1207 return -1;
1208 memobj = PyMemoryView_FromBuffer(&buf);
1209 if (memobj == NULL)
1210 return -1;
1211 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1212 Py_DECREF(memobj);
1213 if (res == NULL)
1214 return -1;
1215 if (res == Py_None) {
1216 /* Non-blocking stream would have blocked. Special return code! */
1217 Py_DECREF(res);
1218 return -2;
1219 }
1220 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1221 Py_DECREF(res);
1222 if (n < 0 || n > len) {
1223 PyErr_Format(PyExc_IOError,
1224 "raw readinto() returned invalid length %zd "
1225 "(should have been between 0 and %zd)", n, len);
1226 return -1;
1227 }
1228 if (n > 0 && self->abs_pos != -1)
1229 self->abs_pos += n;
1230 return n;
1231}
1232
1233static Py_ssize_t
1234_bufferedreader_fill_buffer(buffered *self)
1235{
1236 Py_ssize_t start, len, n;
1237 if (VALID_READ_BUFFER(self))
1238 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1239 else
1240 start = 0;
1241 len = self->buffer_size - start;
1242 n = _bufferedreader_raw_read(self, self->buffer + start, len);
1243 if (n <= 0)
1244 return n;
1245 self->read_end = start + n;
1246 self->raw_pos = start + n;
1247 return n;
1248}
1249
1250static PyObject *
1251_bufferedreader_read_all(buffered *self)
1252{
1253 Py_ssize_t current_size;
1254 PyObject *res, *data = NULL;
1255 PyObject *chunks = PyList_New(0);
1256
1257 if (chunks == NULL)
1258 return NULL;
1259
1260 /* First copy what we have in the current buffer. */
1261 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1262 if (current_size) {
1263 data = PyBytes_FromStringAndSize(
1264 self->buffer + self->pos, current_size);
1265 if (data == NULL) {
1266 Py_DECREF(chunks);
1267 return NULL;
1268 }
1269 }
1270 _bufferedreader_reset_buf(self);
1271 /* We're going past the buffer's bounds, flush it */
1272 if (self->writable) {
1273 res = _bufferedwriter_flush_unlocked(self, 1);
1274 if (res == NULL) {
1275 Py_DECREF(chunks);
1276 return NULL;
1277 }
1278 Py_CLEAR(res);
1279 }
1280 while (1) {
1281 if (data) {
1282 if (PyList_Append(chunks, data) < 0) {
1283 Py_DECREF(data);
1284 Py_DECREF(chunks);
1285 return NULL;
1286 }
1287 Py_DECREF(data);
1288 }
1289
1290 /* Read until EOF or until read() would block. */
1291 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1292 if (data == NULL) {
1293 Py_DECREF(chunks);
1294 return NULL;
1295 }
1296 if (data != Py_None && !PyBytes_Check(data)) {
1297 Py_DECREF(data);
1298 Py_DECREF(chunks);
1299 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1300 return NULL;
1301 }
1302 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1303 if (current_size == 0) {
1304 Py_DECREF(chunks);
1305 return data;
1306 }
1307 else {
1308 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1309 Py_DECREF(data);
1310 Py_DECREF(chunks);
1311 return res;
1312 }
1313 }
1314 current_size += PyBytes_GET_SIZE(data);
1315 if (self->abs_pos != -1)
1316 self->abs_pos += PyBytes_GET_SIZE(data);
1317 }
1318}
1319
1320/* Read n bytes from the buffer if it can, otherwise return None.
1321 This function is simple enough that it can run unlocked. */
1322static PyObject *
1323_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
1324{
1325 Py_ssize_t current_size;
1326
1327 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1328 if (n <= current_size) {
1329 /* Fast path: the data to read is fully buffered. */
1330 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1331 if (res != NULL)
1332 self->pos += n;
1333 return res;
1334 }
1335 Py_RETURN_NONE;
1336}
1337
1338/* Generic read function: read from the stream until enough bytes are read,
1339 * or until an EOF occurs or until read() would block.
1340 */
1341static PyObject *
1342_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
1343{
1344 PyObject *res = NULL;
1345 Py_ssize_t current_size, remaining, written;
1346 char *out;
1347
1348 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1349 if (n <= current_size)
1350 return _bufferedreader_read_fast(self, n);
1351
1352 res = PyBytes_FromStringAndSize(NULL, n);
1353 if (res == NULL)
1354 goto error;
1355 out = PyBytes_AS_STRING(res);
1356 remaining = n;
1357 written = 0;
1358 if (current_size > 0) {
1359 memcpy(out, self->buffer + self->pos, current_size);
1360 remaining -= current_size;
1361 written += current_size;
1362 }
1363 _bufferedreader_reset_buf(self);
1364 while (remaining > 0) {
1365 /* We want to read a whole block at the end into buffer.
1366 If we had readv() we could do this in one pass. */
1367 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1368 if (r == 0)
1369 break;
1370 r = _bufferedreader_raw_read(self, out + written, r);
1371 if (r == -1)
1372 goto error;
1373 if (r == 0 || r == -2) {
1374 /* EOF occurred or read() would block. */
1375 if (r == 0 || written > 0) {
1376 if (_PyBytes_Resize(&res, written))
1377 goto error;
1378 return res;
1379 }
1380 Py_DECREF(res);
1381 Py_INCREF(Py_None);
1382 return Py_None;
1383 }
1384 remaining -= r;
1385 written += r;
1386 }
1387 assert(remaining <= self->buffer_size);
1388 self->pos = 0;
1389 self->raw_pos = 0;
1390 self->read_end = 0;
Antoine Pitroucb4f47c2010-08-11 13:40:17 +00001391 /* NOTE: when the read is satisfied, we avoid issuing any additional
1392 reads, which could block indefinitely (e.g. on a socket).
1393 See issue #9550. */
1394 while (remaining > 0 && self->read_end < self->buffer_size) {
Antoine Pitrou19690592009-06-12 20:14:08 +00001395 Py_ssize_t r = _bufferedreader_fill_buffer(self);
1396 if (r == -1)
1397 goto error;
1398 if (r == 0 || r == -2) {
1399 /* EOF occurred or read() would block. */
1400 if (r == 0 || written > 0) {
1401 if (_PyBytes_Resize(&res, written))
1402 goto error;
1403 return res;
1404 }
1405 Py_DECREF(res);
1406 Py_INCREF(Py_None);
1407 return Py_None;
1408 }
1409 if (remaining > r) {
1410 memcpy(out + written, self->buffer + self->pos, r);
1411 written += r;
1412 self->pos += r;
1413 remaining -= r;
1414 }
1415 else if (remaining > 0) {
1416 memcpy(out + written, self->buffer + self->pos, remaining);
1417 written += remaining;
1418 self->pos += remaining;
1419 remaining = 0;
1420 }
1421 if (remaining == 0)
1422 break;
1423 }
1424
1425 return res;
1426
1427error:
1428 Py_XDECREF(res);
1429 return NULL;
1430}
1431
1432static PyObject *
1433_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
1434{
1435 Py_ssize_t have, r;
1436
1437 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1438 /* Constraints:
1439 1. we don't want to advance the file position.
1440 2. we don't want to lose block alignment, so we can't shift the buffer
1441 to make some place.
1442 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1443 */
1444 if (have > 0) {
1445 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1446 }
1447
1448 /* Fill the buffer from the raw stream, and copy it to the result. */
1449 _bufferedreader_reset_buf(self);
1450 r = _bufferedreader_fill_buffer(self);
1451 if (r == -1)
1452 return NULL;
1453 if (r == -2)
1454 r = 0;
1455 self->pos = 0;
1456 return PyBytes_FromStringAndSize(self->buffer, r);
1457}
1458
1459static PyMethodDef bufferedreader_methods[] = {
1460 /* BufferedIOMixin methods */
1461 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1462 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1463 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1464 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1465 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1466 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1467 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1468 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
1469
1470 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1471 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1472 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
1473 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1474 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1475 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1476 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1477 {NULL, NULL}
1478};
1479
1480static PyMemberDef bufferedreader_members[] = {
1481 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
1482 {NULL}
1483};
1484
1485static PyGetSetDef bufferedreader_getset[] = {
1486 {"closed", (getter)buffered_closed_get, NULL, NULL},
1487 {"name", (getter)buffered_name_get, NULL, NULL},
1488 {"mode", (getter)buffered_mode_get, NULL, NULL},
1489 {NULL}
1490};
1491
1492
1493PyTypeObject PyBufferedReader_Type = {
1494 PyVarObject_HEAD_INIT(NULL, 0)
1495 "_io.BufferedReader", /*tp_name*/
1496 sizeof(buffered), /*tp_basicsize*/
1497 0, /*tp_itemsize*/
1498 (destructor)buffered_dealloc, /*tp_dealloc*/
1499 0, /*tp_print*/
1500 0, /*tp_getattr*/
1501 0, /*tp_setattr*/
1502 0, /*tp_compare */
1503 (reprfunc)buffered_repr, /*tp_repr*/
1504 0, /*tp_as_number*/
1505 0, /*tp_as_sequence*/
1506 0, /*tp_as_mapping*/
1507 0, /*tp_hash */
1508 0, /*tp_call*/
1509 0, /*tp_str*/
1510 0, /*tp_getattro*/
1511 0, /*tp_setattro*/
1512 0, /*tp_as_buffer*/
1513 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1514 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1515 bufferedreader_doc, /* tp_doc */
1516 (traverseproc)buffered_traverse, /* tp_traverse */
1517 (inquiry)buffered_clear, /* tp_clear */
1518 0, /* tp_richcompare */
1519 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
1520 0, /* tp_iter */
1521 (iternextfunc)buffered_iternext, /* tp_iternext */
1522 bufferedreader_methods, /* tp_methods */
1523 bufferedreader_members, /* tp_members */
1524 bufferedreader_getset, /* tp_getset */
1525 0, /* tp_base */
1526 0, /* tp_dict */
1527 0, /* tp_descr_get */
1528 0, /* tp_descr_set */
1529 offsetof(buffered, dict), /* tp_dictoffset */
1530 (initproc)bufferedreader_init, /* tp_init */
1531 0, /* tp_alloc */
1532 PyType_GenericNew, /* tp_new */
1533};
1534
1535
1536
1537static int
1538complain_about_max_buffer_size(void)
1539{
1540 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1541 "max_buffer_size is deprecated", 1) < 0)
1542 return 0;
1543 return 1;
1544}
1545
1546/*
1547 * class BufferedWriter
1548 */
1549PyDoc_STRVAR(bufferedwriter_doc,
1550 "A buffer for a writeable sequential RawIO object.\n"
1551 "\n"
1552 "The constructor creates a BufferedWriter for the given writeable raw\n"
1553 "stream. If the buffer_size is not given, it defaults to\n"
1554 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1555 );
1556
1557static void
1558_bufferedwriter_reset_buf(buffered *self)
1559{
1560 self->write_pos = 0;
1561 self->write_end = -1;
1562}
1563
1564static int
1565bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
1566{
1567 /* TODO: properly deprecate max_buffer_size */
1568 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1569 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1570 Py_ssize_t max_buffer_size = -234;
1571 PyObject *raw;
1572
1573 self->ok = 0;
1574 self->detached = 0;
1575
1576 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1577 &raw, &buffer_size, &max_buffer_size)) {
1578 return -1;
1579 }
1580
1581 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1582 return -1;
1583
1584 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
1585 return -1;
1586
1587 Py_CLEAR(self->raw);
1588 Py_INCREF(raw);
1589 self->raw = raw;
1590 self->readable = 0;
1591 self->writable = 1;
1592
1593 self->buffer_size = buffer_size;
1594 if (_buffered_init(self) < 0)
1595 return -1;
1596 _bufferedwriter_reset_buf(self);
1597 self->pos = 0;
1598
1599 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1600 Py_TYPE(raw) == &PyFileIO_Type);
1601
1602 self->ok = 1;
1603 return 0;
1604}
1605
1606static Py_ssize_t
1607_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
1608{
1609 Py_buffer buf;
1610 PyObject *memobj, *res;
1611 Py_ssize_t n;
1612 /* NOTE: the buffer needn't be released as its object is NULL. */
1613 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1614 return -1;
1615 memobj = PyMemoryView_FromBuffer(&buf);
1616 if (memobj == NULL)
1617 return -1;
1618 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1619 Py_DECREF(memobj);
1620 if (res == NULL)
1621 return -1;
1622 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1623 Py_DECREF(res);
1624 if (n < 0 || n > len) {
1625 PyErr_Format(PyExc_IOError,
1626 "raw write() returned invalid length %zd "
1627 "(should have been between 0 and %zd)", n, len);
1628 return -1;
1629 }
1630 if (n > 0 && self->abs_pos != -1)
1631 self->abs_pos += n;
1632 return n;
1633}
1634
1635/* `restore_pos` is 1 if we need to restore the raw stream position at
1636 the end, 0 otherwise. */
1637static PyObject *
1638_bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
1639{
1640 Py_ssize_t written = 0;
1641 Py_off_t n, rewind;
1642
1643 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1644 goto end;
1645 /* First, rewind */
1646 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1647 if (rewind != 0) {
1648 n = _buffered_raw_seek(self, -rewind, 1);
1649 if (n < 0) {
1650 goto error;
1651 }
1652 self->raw_pos -= rewind;
1653 }
1654 while (self->write_pos < self->write_end) {
1655 n = _bufferedwriter_raw_write(self,
1656 self->buffer + self->write_pos,
1657 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1658 Py_off_t, Py_ssize_t));
1659 if (n == -1) {
1660 Py_ssize_t *w = _buffered_check_blocking_error();
1661 if (w == NULL)
1662 goto error;
1663 self->write_pos += *w;
1664 self->raw_pos = self->write_pos;
1665 written += *w;
1666 *w = written;
1667 /* Already re-raised */
1668 goto error;
1669 }
1670 self->write_pos += n;
1671 self->raw_pos = self->write_pos;
1672 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1673 }
1674
1675 if (restore_pos) {
1676 Py_off_t forward = rewind - written;
1677 if (forward != 0) {
1678 n = _buffered_raw_seek(self, forward, 1);
1679 if (n < 0) {
1680 goto error;
1681 }
1682 self->raw_pos += forward;
1683 }
1684 }
1685 _bufferedwriter_reset_buf(self);
1686
1687end:
1688 Py_RETURN_NONE;
1689
1690error:
1691 return NULL;
1692}
1693
1694static PyObject *
1695bufferedwriter_write(buffered *self, PyObject *args)
1696{
1697 PyObject *res = NULL;
1698 Py_buffer buf;
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001699 Py_ssize_t written, avail, remaining;
1700 Py_off_t offset;
Antoine Pitrou19690592009-06-12 20:14:08 +00001701
1702 CHECK_INITIALIZED(self)
1703 if (!PyArg_ParseTuple(args, "s*:write", &buf)) {
1704 return NULL;
1705 }
1706
1707 if (IS_CLOSED(self)) {
1708 PyErr_SetString(PyExc_ValueError, "write to closed file");
1709 PyBuffer_Release(&buf);
1710 return NULL;
1711 }
1712
1713 ENTER_BUFFERED(self)
1714
1715 /* Fast path: the data to write can be fully buffered. */
1716 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1717 self->pos = 0;
1718 self->raw_pos = 0;
1719 }
1720 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1721 if (buf.len <= avail) {
1722 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1723 if (!VALID_WRITE_BUFFER(self)) {
1724 self->write_pos = self->pos;
1725 }
1726 ADJUST_POSITION(self, self->pos + buf.len);
1727 if (self->pos > self->write_end)
1728 self->write_end = self->pos;
1729 written = buf.len;
1730 goto end;
1731 }
1732
1733 /* First write the current buffer */
1734 res = _bufferedwriter_flush_unlocked(self, 0);
1735 if (res == NULL) {
1736 Py_ssize_t *w = _buffered_check_blocking_error();
1737 if (w == NULL)
1738 goto error;
1739 if (self->readable)
1740 _bufferedreader_reset_buf(self);
1741 /* Make some place by shifting the buffer. */
1742 assert(VALID_WRITE_BUFFER(self));
1743 memmove(self->buffer, self->buffer + self->write_pos,
1744 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1745 Py_off_t, Py_ssize_t));
1746 self->write_end -= self->write_pos;
1747 self->raw_pos -= self->write_pos;
1748 self->pos -= self->write_pos;
1749 self->write_pos = 0;
1750 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1751 Py_off_t, Py_ssize_t);
1752 if (buf.len <= avail) {
1753 /* Everything can be buffered */
1754 PyErr_Clear();
1755 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1756 self->write_end += buf.len;
1757 written = buf.len;
1758 goto end;
1759 }
1760 /* Buffer as much as possible. */
1761 memcpy(self->buffer + self->write_end, buf.buf, avail);
1762 self->write_end += avail;
1763 /* Already re-raised */
1764 *w = avail;
1765 goto error;
1766 }
1767 Py_CLEAR(res);
1768
Antoine Pitrou20e1f932009-08-06 20:18:29 +00001769 /* Adjust the raw stream position if it is away from the logical stream
1770 position. This happens if the read buffer has been filled but not
1771 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1772 the raw stream by itself).
1773 Fixes issue #6629.
1774 */
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001775 offset = RAW_OFFSET(self);
1776 if (offset != 0) {
1777 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitrou20e1f932009-08-06 20:18:29 +00001778 goto error;
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001779 self->raw_pos -= offset;
Antoine Pitrou20e1f932009-08-06 20:18:29 +00001780 }
1781
Antoine Pitrou19690592009-06-12 20:14:08 +00001782 /* Then write buf itself. At this point the buffer has been emptied. */
1783 remaining = buf.len;
1784 written = 0;
1785 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001786 Py_ssize_t n = _bufferedwriter_raw_write(
Antoine Pitrou19690592009-06-12 20:14:08 +00001787 self, (char *) buf.buf + written, buf.len - written);
1788 if (n == -1) {
1789 Py_ssize_t *w = _buffered_check_blocking_error();
1790 if (w == NULL)
1791 goto error;
1792 written += *w;
1793 remaining -= *w;
1794 if (remaining > self->buffer_size) {
1795 /* Can't buffer everything, still buffer as much as possible */
1796 memcpy(self->buffer,
1797 (char *) buf.buf + written, self->buffer_size);
1798 self->raw_pos = 0;
1799 ADJUST_POSITION(self, self->buffer_size);
1800 self->write_end = self->buffer_size;
1801 *w = written + self->buffer_size;
1802 /* Already re-raised */
1803 goto error;
1804 }
1805 PyErr_Clear();
1806 break;
1807 }
1808 written += n;
1809 remaining -= n;
1810 }
1811 if (self->readable)
1812 _bufferedreader_reset_buf(self);
1813 if (remaining > 0) {
1814 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1815 written += remaining;
1816 }
1817 self->write_pos = 0;
1818 /* TODO: sanity check (remaining >= 0) */
1819 self->write_end = remaining;
1820 ADJUST_POSITION(self, remaining);
1821 self->raw_pos = 0;
1822
1823end:
1824 res = PyLong_FromSsize_t(written);
1825
1826error:
1827 LEAVE_BUFFERED(self)
1828 PyBuffer_Release(&buf);
1829 return res;
1830}
1831
1832static PyMethodDef bufferedwriter_methods[] = {
1833 /* BufferedIOMixin methods */
1834 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1835 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1836 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1837 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1838 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1839 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1840 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
1841
1842 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1843 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1844 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1845 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1846 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1847 {NULL, NULL}
1848};
1849
1850static PyMemberDef bufferedwriter_members[] = {
1851 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
1852 {NULL}
1853};
1854
1855static PyGetSetDef bufferedwriter_getset[] = {
1856 {"closed", (getter)buffered_closed_get, NULL, NULL},
1857 {"name", (getter)buffered_name_get, NULL, NULL},
1858 {"mode", (getter)buffered_mode_get, NULL, NULL},
1859 {NULL}
1860};
1861
1862
1863PyTypeObject PyBufferedWriter_Type = {
1864 PyVarObject_HEAD_INIT(NULL, 0)
1865 "_io.BufferedWriter", /*tp_name*/
1866 sizeof(buffered), /*tp_basicsize*/
1867 0, /*tp_itemsize*/
1868 (destructor)buffered_dealloc, /*tp_dealloc*/
1869 0, /*tp_print*/
1870 0, /*tp_getattr*/
1871 0, /*tp_setattr*/
1872 0, /*tp_compare */
1873 (reprfunc)buffered_repr, /*tp_repr*/
1874 0, /*tp_as_number*/
1875 0, /*tp_as_sequence*/
1876 0, /*tp_as_mapping*/
1877 0, /*tp_hash */
1878 0, /*tp_call*/
1879 0, /*tp_str*/
1880 0, /*tp_getattro*/
1881 0, /*tp_setattro*/
1882 0, /*tp_as_buffer*/
1883 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1884 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1885 bufferedwriter_doc, /* tp_doc */
1886 (traverseproc)buffered_traverse, /* tp_traverse */
1887 (inquiry)buffered_clear, /* tp_clear */
1888 0, /* tp_richcompare */
1889 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
1890 0, /* tp_iter */
1891 0, /* tp_iternext */
1892 bufferedwriter_methods, /* tp_methods */
1893 bufferedwriter_members, /* tp_members */
1894 bufferedwriter_getset, /* tp_getset */
1895 0, /* tp_base */
1896 0, /* tp_dict */
1897 0, /* tp_descr_get */
1898 0, /* tp_descr_set */
1899 offsetof(buffered, dict), /* tp_dictoffset */
1900 (initproc)bufferedwriter_init, /* tp_init */
1901 0, /* tp_alloc */
1902 PyType_GenericNew, /* tp_new */
1903};
1904
1905
1906
1907/*
1908 * BufferedRWPair
1909 */
1910
1911PyDoc_STRVAR(bufferedrwpair_doc,
1912 "A buffered reader and writer object together.\n"
1913 "\n"
1914 "A buffered reader object and buffered writer object put together to\n"
1915 "form a sequential IO object that can read and write. This is typically\n"
1916 "used with a socket or two-way pipe.\n"
1917 "\n"
1918 "reader and writer are RawIOBase objects that are readable and\n"
1919 "writeable respectively. If the buffer_size is omitted it defaults to\n"
1920 "DEFAULT_BUFFER_SIZE.\n"
1921 );
1922
1923/* XXX The usefulness of this (compared to having two separate IO objects) is
1924 * questionable.
1925 */
1926
1927typedef struct {
1928 PyObject_HEAD
1929 buffered *reader;
1930 buffered *writer;
1931 PyObject *dict;
1932 PyObject *weakreflist;
1933} rwpair;
1934
1935static int
1936bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
1937{
1938 PyObject *reader, *writer;
1939 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1940 Py_ssize_t max_buffer_size = -234;
1941
1942 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1943 &buffer_size, &max_buffer_size)) {
1944 return -1;
1945 }
1946
1947 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1948 return -1;
1949
1950 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
1951 return -1;
1952 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
1953 return -1;
1954
1955 self->reader = (buffered *) PyObject_CallFunction(
1956 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
1957 if (self->reader == NULL)
1958 return -1;
1959
1960 self->writer = (buffered *) PyObject_CallFunction(
1961 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
1962 if (self->writer == NULL) {
1963 Py_CLEAR(self->reader);
1964 return -1;
1965 }
1966
1967 return 0;
1968}
1969
1970static int
1971bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
1972{
1973 Py_VISIT(self->dict);
1974 return 0;
1975}
1976
1977static int
1978bufferedrwpair_clear(rwpair *self)
1979{
1980 Py_CLEAR(self->reader);
1981 Py_CLEAR(self->writer);
1982 Py_CLEAR(self->dict);
1983 return 0;
1984}
1985
1986static void
1987bufferedrwpair_dealloc(rwpair *self)
1988{
1989 _PyObject_GC_UNTRACK(self);
1990 Py_CLEAR(self->reader);
1991 Py_CLEAR(self->writer);
1992 Py_CLEAR(self->dict);
1993 Py_TYPE(self)->tp_free((PyObject *) self);
1994}
1995
1996static PyObject *
1997_forward_call(buffered *self, const char *name, PyObject *args)
1998{
1999 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
2000 PyObject *ret;
2001
2002 if (func == NULL) {
2003 PyErr_SetString(PyExc_AttributeError, name);
2004 return NULL;
2005 }
2006
2007 ret = PyObject_CallObject(func, args);
2008 Py_DECREF(func);
2009 return ret;
2010}
2011
2012static PyObject *
2013bufferedrwpair_read(rwpair *self, PyObject *args)
2014{
2015 return _forward_call(self->reader, "read", args);
2016}
2017
2018static PyObject *
2019bufferedrwpair_peek(rwpair *self, PyObject *args)
2020{
2021 return _forward_call(self->reader, "peek", args);
2022}
2023
2024static PyObject *
2025bufferedrwpair_read1(rwpair *self, PyObject *args)
2026{
2027 return _forward_call(self->reader, "read1", args);
2028}
2029
2030static PyObject *
2031bufferedrwpair_readinto(rwpair *self, PyObject *args)
2032{
2033 return _forward_call(self->reader, "readinto", args);
2034}
2035
2036static PyObject *
2037bufferedrwpair_write(rwpair *self, PyObject *args)
2038{
2039 return _forward_call(self->writer, "write", args);
2040}
2041
2042static PyObject *
2043bufferedrwpair_flush(rwpair *self, PyObject *args)
2044{
2045 return _forward_call(self->writer, "flush", args);
2046}
2047
2048static PyObject *
2049bufferedrwpair_readable(rwpair *self, PyObject *args)
2050{
2051 return _forward_call(self->reader, "readable", args);
2052}
2053
2054static PyObject *
2055bufferedrwpair_writable(rwpair *self, PyObject *args)
2056{
2057 return _forward_call(self->writer, "writable", args);
2058}
2059
2060static PyObject *
2061bufferedrwpair_close(rwpair *self, PyObject *args)
2062{
2063 PyObject *ret = _forward_call(self->writer, "close", args);
2064 if (ret == NULL)
2065 return NULL;
2066 Py_DECREF(ret);
2067
2068 return _forward_call(self->reader, "close", args);
2069}
2070
2071static PyObject *
2072bufferedrwpair_isatty(rwpair *self, PyObject *args)
2073{
2074 PyObject *ret = _forward_call(self->writer, "isatty", args);
2075
2076 if (ret != Py_False) {
2077 /* either True or exception */
2078 return ret;
2079 }
2080 Py_DECREF(ret);
2081
2082 return _forward_call(self->reader, "isatty", args);
2083}
2084
2085static PyObject *
2086bufferedrwpair_closed_get(rwpair *self, void *context)
2087{
2088 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2089}
2090
2091static PyMethodDef bufferedrwpair_methods[] = {
2092 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2093 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2094 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2095 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
2096
2097 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2098 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
2099
2100 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2101 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
2102
2103 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2104 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
2105
2106 {NULL, NULL}
2107};
2108
2109static PyGetSetDef bufferedrwpair_getset[] = {
2110 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
2111 {NULL}
2112};
2113
2114PyTypeObject PyBufferedRWPair_Type = {
2115 PyVarObject_HEAD_INIT(NULL, 0)
2116 "_io.BufferedRWPair", /*tp_name*/
2117 sizeof(rwpair), /*tp_basicsize*/
2118 0, /*tp_itemsize*/
2119 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
2120 0, /*tp_print*/
2121 0, /*tp_getattr*/
2122 0, /*tp_setattr*/
2123 0, /*tp_compare */
2124 0, /*tp_repr*/
2125 0, /*tp_as_number*/
2126 0, /*tp_as_sequence*/
2127 0, /*tp_as_mapping*/
2128 0, /*tp_hash */
2129 0, /*tp_call*/
2130 0, /*tp_str*/
2131 0, /*tp_getattro*/
2132 0, /*tp_setattro*/
2133 0, /*tp_as_buffer*/
2134 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2135 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
2136 bufferedrwpair_doc, /* tp_doc */
2137 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2138 (inquiry)bufferedrwpair_clear, /* tp_clear */
2139 0, /* tp_richcompare */
2140 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
2141 0, /* tp_iter */
2142 0, /* tp_iternext */
2143 bufferedrwpair_methods, /* tp_methods */
2144 0, /* tp_members */
2145 bufferedrwpair_getset, /* tp_getset */
2146 0, /* tp_base */
2147 0, /* tp_dict */
2148 0, /* tp_descr_get */
2149 0, /* tp_descr_set */
2150 offsetof(rwpair, dict), /* tp_dictoffset */
2151 (initproc)bufferedrwpair_init, /* tp_init */
2152 0, /* tp_alloc */
2153 PyType_GenericNew, /* tp_new */
2154};
2155
2156
2157
2158/*
2159 * BufferedRandom
2160 */
2161
2162PyDoc_STRVAR(bufferedrandom_doc,
2163 "A buffered interface to random access streams.\n"
2164 "\n"
2165 "The constructor creates a reader and writer for a seekable stream,\n"
2166 "raw, given in the first argument. If the buffer_size is omitted it\n"
2167 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2168 );
2169
2170static int
2171bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
2172{
2173 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2174 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
2175 Py_ssize_t max_buffer_size = -234;
2176 PyObject *raw;
2177
2178 self->ok = 0;
2179 self->detached = 0;
2180
2181 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2182 &raw, &buffer_size, &max_buffer_size)) {
2183 return -1;
2184 }
2185
2186 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2187 return -1;
2188
2189 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
2190 return -1;
2191 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
2192 return -1;
2193 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
2194 return -1;
2195
2196 Py_CLEAR(self->raw);
2197 Py_INCREF(raw);
2198 self->raw = raw;
2199 self->buffer_size = buffer_size;
2200 self->readable = 1;
2201 self->writable = 1;
2202
2203 if (_buffered_init(self) < 0)
2204 return -1;
2205 _bufferedreader_reset_buf(self);
2206 _bufferedwriter_reset_buf(self);
2207 self->pos = 0;
2208
2209 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2210 Py_TYPE(raw) == &PyFileIO_Type);
2211
2212 self->ok = 1;
2213 return 0;
2214}
2215
2216static PyMethodDef bufferedrandom_methods[] = {
2217 /* BufferedIOMixin methods */
2218 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2219 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2220 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2221 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2222 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2223 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2224 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2225
2226 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2227
2228 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2229 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2230 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2231 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2232 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2233 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2234 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2235 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2236 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
2237 {NULL, NULL}
2238};
2239
2240static PyMemberDef bufferedrandom_members[] = {
2241 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
2242 {NULL}
2243};
2244
2245static PyGetSetDef bufferedrandom_getset[] = {
2246 {"closed", (getter)buffered_closed_get, NULL, NULL},
2247 {"name", (getter)buffered_name_get, NULL, NULL},
2248 {"mode", (getter)buffered_mode_get, NULL, NULL},
2249 {NULL}
2250};
2251
2252
2253PyTypeObject PyBufferedRandom_Type = {
2254 PyVarObject_HEAD_INIT(NULL, 0)
2255 "_io.BufferedRandom", /*tp_name*/
2256 sizeof(buffered), /*tp_basicsize*/
2257 0, /*tp_itemsize*/
2258 (destructor)buffered_dealloc, /*tp_dealloc*/
2259 0, /*tp_print*/
2260 0, /*tp_getattr*/
2261 0, /*tp_setattr*/
2262 0, /*tp_compare */
2263 (reprfunc)buffered_repr, /*tp_repr*/
2264 0, /*tp_as_number*/
2265 0, /*tp_as_sequence*/
2266 0, /*tp_as_mapping*/
2267 0, /*tp_hash */
2268 0, /*tp_call*/
2269 0, /*tp_str*/
2270 0, /*tp_getattro*/
2271 0, /*tp_setattro*/
2272 0, /*tp_as_buffer*/
2273 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2274 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2275 bufferedrandom_doc, /* tp_doc */
2276 (traverseproc)buffered_traverse, /* tp_traverse */
2277 (inquiry)buffered_clear, /* tp_clear */
2278 0, /* tp_richcompare */
2279 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2280 0, /* tp_iter */
2281 (iternextfunc)buffered_iternext, /* tp_iternext */
2282 bufferedrandom_methods, /* tp_methods */
2283 bufferedrandom_members, /* tp_members */
2284 bufferedrandom_getset, /* tp_getset */
2285 0, /* tp_base */
2286 0, /*tp_dict*/
2287 0, /* tp_descr_get */
2288 0, /* tp_descr_set */
2289 offsetof(buffered, dict), /*tp_dictoffset*/
2290 (initproc)bufferedrandom_init, /* tp_init */
2291 0, /* tp_alloc */
2292 PyType_GenericNew, /* tp_new */
2293};
2294