blob: feee9be0087de9bdb1ea8e920c7ba239d4a482f0 [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
639 self->lock = PyThread_allocate_lock();
640 if (self->lock == NULL) {
641 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
642 return -1;
643 }
644#endif
645 /* Find out whether buffer_size is a power of 2 */
646 /* XXX is this optimization useful? */
647 for (n = self->buffer_size - 1; n & 1; n >>= 1)
648 ;
649 if (n == 0)
650 self->buffer_mask = self->buffer_size - 1;
651 else
652 self->buffer_mask = 0;
653 if (_buffered_raw_tell(self) == -1)
654 PyErr_Clear();
655 return 0;
656}
657
658/*
659 * Shared methods and wrappers
660 */
661
662static PyObject *
663buffered_flush(buffered *self, PyObject *args)
664{
665 PyObject *res;
666
667 CHECK_INITIALIZED(self)
668 CHECK_CLOSED(self, "flush of closed file")
669
670 ENTER_BUFFERED(self)
671 res = _bufferedwriter_flush_unlocked(self, 0);
672 if (res != NULL && self->readable) {
673 /* Rewind the raw stream so that its position corresponds to
674 the current logical position. */
675 Py_off_t n;
676 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
677 if (n == -1)
678 Py_CLEAR(res);
679 _bufferedreader_reset_buf(self);
680 }
681 LEAVE_BUFFERED(self)
682
683 return res;
684}
685
686static PyObject *
687buffered_peek(buffered *self, PyObject *args)
688{
689 Py_ssize_t n = 0;
690 PyObject *res = NULL;
691
692 CHECK_INITIALIZED(self)
693 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
694 return NULL;
695 }
696
697 ENTER_BUFFERED(self)
698
699 if (self->writable) {
700 res = _bufferedwriter_flush_unlocked(self, 1);
701 if (res == NULL)
702 goto end;
703 Py_CLEAR(res);
704 }
705 res = _bufferedreader_peek_unlocked(self, n);
706
707end:
708 LEAVE_BUFFERED(self)
709 return res;
710}
711
712static PyObject *
713buffered_read(buffered *self, PyObject *args)
714{
715 Py_ssize_t n = -1;
716 PyObject *res;
717
718 CHECK_INITIALIZED(self)
Benjamin Petersonddd392c2009-12-13 19:19:07 +0000719 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
Antoine Pitrou19690592009-06-12 20:14:08 +0000720 return NULL;
721 }
722 if (n < -1) {
723 PyErr_SetString(PyExc_ValueError,
724 "read length must be positive or -1");
725 return NULL;
726 }
727
728 CHECK_CLOSED(self, "read of closed file")
729
730 if (n == -1) {
731 /* The number of bytes is unspecified, read until the end of stream */
732 ENTER_BUFFERED(self)
733 res = _bufferedreader_read_all(self);
734 LEAVE_BUFFERED(self)
735 }
736 else {
737 res = _bufferedreader_read_fast(self, n);
738 if (res == Py_None) {
739 Py_DECREF(res);
740 ENTER_BUFFERED(self)
741 res = _bufferedreader_read_generic(self, n);
742 LEAVE_BUFFERED(self)
743 }
744 }
745
746 return res;
747}
748
749static PyObject *
750buffered_read1(buffered *self, PyObject *args)
751{
752 Py_ssize_t n, have, r;
753 PyObject *res = NULL;
754
755 CHECK_INITIALIZED(self)
756 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
757 return NULL;
758 }
759
760 if (n < 0) {
761 PyErr_SetString(PyExc_ValueError,
762 "read length must be positive");
763 return NULL;
764 }
765 if (n == 0)
766 return PyBytes_FromStringAndSize(NULL, 0);
767
768 ENTER_BUFFERED(self)
769
770 if (self->writable) {
771 res = _bufferedwriter_flush_unlocked(self, 1);
772 if (res == NULL)
773 goto end;
774 Py_CLEAR(res);
775 }
776
777 /* Return up to n bytes. If at least one byte is buffered, we
778 only return buffered bytes. Otherwise, we do one raw read. */
779
780 /* XXX: this mimicks the io.py implementation but is probably wrong.
781 If we need to read from the raw stream, then we could actually read
782 all `n` bytes asked by the caller (and possibly more, so as to fill
783 our buffer for the next reads). */
784
785 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
786 if (have > 0) {
787 if (n > have)
788 n = have;
789 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
790 if (res == NULL)
791 goto end;
792 self->pos += n;
793 goto end;
794 }
795
796 /* Fill the buffer from the raw stream, and copy it to the result. */
797 _bufferedreader_reset_buf(self);
798 r = _bufferedreader_fill_buffer(self);
799 if (r == -1)
800 goto end;
801 if (r == -2)
802 r = 0;
803 if (n > r)
804 n = r;
805 res = PyBytes_FromStringAndSize(self->buffer, n);
806 if (res == NULL)
807 goto end;
808 self->pos = n;
809
810end:
811 LEAVE_BUFFERED(self)
812 return res;
813}
814
815static PyObject *
816buffered_readinto(buffered *self, PyObject *args)
817{
818 PyObject *res = NULL;
819
820 CHECK_INITIALIZED(self)
821
822 /* TODO: use raw.readinto() instead! */
823 if (self->writable) {
824 ENTER_BUFFERED(self)
825 res = _bufferedwriter_flush_unlocked(self, 0);
826 LEAVE_BUFFERED(self)
827 if (res == NULL)
828 goto end;
829 Py_DECREF(res);
830 }
831 res = bufferediobase_readinto((PyObject *)self, args);
832
833end:
834 return res;
835}
836
837static PyObject *
838_buffered_readline(buffered *self, Py_ssize_t limit)
839{
840 PyObject *res = NULL;
841 PyObject *chunks = NULL;
842 Py_ssize_t n, written = 0;
843 const char *start, *s, *end;
844
845 CHECK_CLOSED(self, "readline of closed file")
846
847 /* First, try to find a line in the buffer. This can run unlocked because
848 the calls to the C API are simple enough that they can't trigger
849 any thread switch. */
850 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
851 if (limit >= 0 && n > limit)
852 n = limit;
853 start = self->buffer + self->pos;
854 s = memchr(start, '\n', n);
855 if (s != NULL) {
856 res = PyBytes_FromStringAndSize(start, s - start + 1);
857 if (res != NULL)
858 self->pos += s - start + 1;
859 goto end_unlocked;
860 }
861 if (n == limit) {
862 res = PyBytes_FromStringAndSize(start, n);
863 if (res != NULL)
864 self->pos += n;
865 goto end_unlocked;
866 }
867
868 ENTER_BUFFERED(self)
869
870 /* Now we try to get some more from the raw stream */
871 if (self->writable) {
872 res = _bufferedwriter_flush_unlocked(self, 1);
873 if (res == NULL)
874 goto end;
875 Py_CLEAR(res);
876 }
877 chunks = PyList_New(0);
878 if (chunks == NULL)
879 goto end;
880 if (n > 0) {
881 res = PyBytes_FromStringAndSize(start, n);
882 if (res == NULL)
883 goto end;
884 if (PyList_Append(chunks, res) < 0) {
885 Py_CLEAR(res);
886 goto end;
887 }
888 Py_CLEAR(res);
889 written += n;
890 if (limit >= 0)
891 limit -= n;
892 }
893
894 for (;;) {
895 _bufferedreader_reset_buf(self);
896 n = _bufferedreader_fill_buffer(self);
897 if (n == -1)
898 goto end;
899 if (n <= 0)
900 break;
901 if (limit >= 0 && n > limit)
902 n = limit;
903 start = self->buffer;
904 end = start + n;
905 s = start;
906 while (s < end) {
907 if (*s++ == '\n') {
908 res = PyBytes_FromStringAndSize(start, s - start);
909 if (res == NULL)
910 goto end;
911 self->pos = s - start;
912 goto found;
913 }
914 }
915 res = PyBytes_FromStringAndSize(start, n);
916 if (res == NULL)
917 goto end;
918 if (n == limit) {
919 self->pos = n;
920 break;
921 }
922 if (PyList_Append(chunks, res) < 0) {
923 Py_CLEAR(res);
924 goto end;
925 }
926 Py_CLEAR(res);
927 written += n;
928 if (limit >= 0)
929 limit -= n;
930 }
931found:
932 if (res != NULL && PyList_Append(chunks, res) < 0) {
933 Py_CLEAR(res);
934 goto end;
935 }
936 Py_CLEAR(res);
937 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
938
939end:
940 LEAVE_BUFFERED(self)
941end_unlocked:
942 Py_XDECREF(chunks);
943 return res;
944}
945
946static PyObject *
947buffered_readline(buffered *self, PyObject *args)
948{
Antoine Pitrou19690592009-06-12 20:14:08 +0000949 Py_ssize_t limit = -1;
950
951 CHECK_INITIALIZED(self)
Benjamin Petersonddd392c2009-12-13 19:19:07 +0000952 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
Antoine Pitrou19690592009-06-12 20:14:08 +0000953 return NULL;
Antoine Pitrou19690592009-06-12 20:14:08 +0000954 return _buffered_readline(self, limit);
955}
956
957
958static PyObject *
959buffered_tell(buffered *self, PyObject *args)
960{
961 Py_off_t pos;
962
963 CHECK_INITIALIZED(self)
964 pos = _buffered_raw_tell(self);
965 if (pos == -1)
966 return NULL;
967 pos -= RAW_OFFSET(self);
968 /* TODO: sanity check (pos >= 0) */
969 return PyLong_FromOff_t(pos);
970}
971
972static PyObject *
973buffered_seek(buffered *self, PyObject *args)
974{
975 Py_off_t target, n;
976 int whence = 0;
977 PyObject *targetobj, *res = NULL;
978
979 CHECK_INITIALIZED(self)
980 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
981 return NULL;
982 }
983 if (whence < 0 || whence > 2) {
984 PyErr_Format(PyExc_ValueError,
985 "whence must be between 0 and 2, not %d", whence);
986 return NULL;
987 }
988
989 CHECK_CLOSED(self, "seek of closed file")
990
991 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
992 if (target == -1 && PyErr_Occurred())
993 return NULL;
994
995 if (whence != 2 && self->readable) {
996 Py_off_t current, avail;
997 /* Check if seeking leaves us inside the current buffer,
998 so as to return quickly if possible. Also, we needn't take the
999 lock in this fast path.
1000 Don't know how to do that when whence == 2, though. */
1001 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1002 state at this point. */
1003 current = RAW_TELL(self);
1004 avail = READAHEAD(self);
1005 if (avail > 0) {
1006 Py_off_t offset;
1007 if (whence == 0)
1008 offset = target - (current - RAW_OFFSET(self));
1009 else
1010 offset = target;
1011 if (offset >= -self->pos && offset <= avail) {
1012 self->pos += offset;
1013 return PyLong_FromOff_t(current - avail + offset);
1014 }
1015 }
1016 }
1017
1018 ENTER_BUFFERED(self)
1019
1020 /* Fallback: invoke raw seek() method and clear buffer */
1021 if (self->writable) {
1022 res = _bufferedwriter_flush_unlocked(self, 0);
1023 if (res == NULL)
1024 goto end;
1025 Py_CLEAR(res);
1026 _bufferedwriter_reset_buf(self);
1027 }
1028
1029 /* TODO: align on block boundary and read buffer if needed? */
1030 if (whence == 1)
1031 target -= RAW_OFFSET(self);
1032 n = _buffered_raw_seek(self, target, whence);
1033 if (n == -1)
1034 goto end;
1035 self->raw_pos = -1;
1036 res = PyLong_FromOff_t(n);
1037 if (res != NULL && self->readable)
1038 _bufferedreader_reset_buf(self);
1039
1040end:
1041 LEAVE_BUFFERED(self)
1042 return res;
1043}
1044
1045static PyObject *
1046buffered_truncate(buffered *self, PyObject *args)
1047{
1048 PyObject *pos = Py_None;
1049 PyObject *res = NULL;
1050
1051 CHECK_INITIALIZED(self)
1052 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1053 return NULL;
1054 }
1055
1056 ENTER_BUFFERED(self)
1057
1058 if (self->writable) {
1059 res = _bufferedwriter_flush_unlocked(self, 0);
1060 if (res == NULL)
1061 goto end;
1062 Py_CLEAR(res);
1063 }
1064 if (self->readable) {
1065 if (pos == Py_None) {
1066 /* Rewind the raw stream so that its position corresponds to
1067 the current logical position. */
1068 if (_buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)
1069 goto end;
1070 }
1071 _bufferedreader_reset_buf(self);
1072 }
1073 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1074 if (res == NULL)
1075 goto end;
1076 /* Reset cached position */
1077 if (_buffered_raw_tell(self) == -1)
1078 PyErr_Clear();
1079
1080end:
1081 LEAVE_BUFFERED(self)
1082 return res;
1083}
1084
1085static PyObject *
1086buffered_iternext(buffered *self)
1087{
1088 PyObject *line;
1089 PyTypeObject *tp;
1090
1091 CHECK_INITIALIZED(self);
1092
1093 tp = Py_TYPE(self);
1094 if (tp == &PyBufferedReader_Type ||
1095 tp == &PyBufferedRandom_Type) {
1096 /* Skip method call overhead for speed */
1097 line = _buffered_readline(self, -1);
1098 }
1099 else {
1100 line = PyObject_CallMethodObjArgs((PyObject *)self,
1101 _PyIO_str_readline, NULL);
1102 if (line && !PyBytes_Check(line)) {
1103 PyErr_Format(PyExc_IOError,
1104 "readline() should have returned a bytes object, "
1105 "not '%.200s'", Py_TYPE(line)->tp_name);
1106 Py_DECREF(line);
1107 return NULL;
1108 }
1109 }
1110
1111 if (line == NULL)
1112 return NULL;
1113
1114 if (PyBytes_GET_SIZE(line) == 0) {
1115 /* Reached EOF or would have blocked */
1116 Py_DECREF(line);
1117 return NULL;
1118 }
1119
1120 return line;
1121}
1122
1123static PyObject *
1124buffered_repr(buffered *self)
1125{
1126 PyObject *nameobj, *res;
1127
1128 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1129 if (nameobj == NULL) {
1130 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1131 PyErr_Clear();
1132 else
1133 return NULL;
1134 res = PyString_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1135 }
1136 else {
1137 PyObject *repr = PyObject_Repr(nameobj);
1138 Py_DECREF(nameobj);
1139 if (repr == NULL)
1140 return NULL;
1141 res = PyString_FromFormat("<%s name=%s>",
1142 Py_TYPE(self)->tp_name,
1143 PyString_AS_STRING(repr));
1144 Py_DECREF(repr);
1145 }
1146 return res;
1147}
1148
1149/*
1150 * class BufferedReader
1151 */
1152
1153PyDoc_STRVAR(bufferedreader_doc,
1154 "Create a new buffered reader using the given readable raw IO object.");
1155
1156static void _bufferedreader_reset_buf(buffered *self)
1157{
1158 self->read_end = -1;
1159}
1160
1161static int
1162bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
1163{
1164 char *kwlist[] = {"raw", "buffer_size", NULL};
1165 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1166 PyObject *raw;
1167
1168 self->ok = 0;
1169 self->detached = 0;
1170
1171 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1172 &raw, &buffer_size)) {
1173 return -1;
1174 }
1175
1176 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
1177 return -1;
1178
1179 Py_CLEAR(self->raw);
1180 Py_INCREF(raw);
1181 self->raw = raw;
1182 self->buffer_size = buffer_size;
1183 self->readable = 1;
1184 self->writable = 0;
1185
1186 if (_buffered_init(self) < 0)
1187 return -1;
1188 _bufferedreader_reset_buf(self);
1189
1190 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1191 Py_TYPE(raw) == &PyFileIO_Type);
1192
1193 self->ok = 1;
1194 return 0;
1195}
1196
1197static Py_ssize_t
1198_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
1199{
1200 Py_buffer buf;
1201 PyObject *memobj, *res;
1202 Py_ssize_t n;
1203 /* NOTE: the buffer needn't be released as its object is NULL. */
1204 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1205 return -1;
1206 memobj = PyMemoryView_FromBuffer(&buf);
1207 if (memobj == NULL)
1208 return -1;
1209 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1210 Py_DECREF(memobj);
1211 if (res == NULL)
1212 return -1;
1213 if (res == Py_None) {
1214 /* Non-blocking stream would have blocked. Special return code! */
1215 Py_DECREF(res);
1216 return -2;
1217 }
1218 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1219 Py_DECREF(res);
1220 if (n < 0 || n > len) {
1221 PyErr_Format(PyExc_IOError,
1222 "raw readinto() returned invalid length %zd "
1223 "(should have been between 0 and %zd)", n, len);
1224 return -1;
1225 }
1226 if (n > 0 && self->abs_pos != -1)
1227 self->abs_pos += n;
1228 return n;
1229}
1230
1231static Py_ssize_t
1232_bufferedreader_fill_buffer(buffered *self)
1233{
1234 Py_ssize_t start, len, n;
1235 if (VALID_READ_BUFFER(self))
1236 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1237 else
1238 start = 0;
1239 len = self->buffer_size - start;
1240 n = _bufferedreader_raw_read(self, self->buffer + start, len);
1241 if (n <= 0)
1242 return n;
1243 self->read_end = start + n;
1244 self->raw_pos = start + n;
1245 return n;
1246}
1247
1248static PyObject *
1249_bufferedreader_read_all(buffered *self)
1250{
1251 Py_ssize_t current_size;
1252 PyObject *res, *data = NULL;
1253 PyObject *chunks = PyList_New(0);
1254
1255 if (chunks == NULL)
1256 return NULL;
1257
1258 /* First copy what we have in the current buffer. */
1259 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1260 if (current_size) {
1261 data = PyBytes_FromStringAndSize(
1262 self->buffer + self->pos, current_size);
1263 if (data == NULL) {
1264 Py_DECREF(chunks);
1265 return NULL;
1266 }
1267 }
1268 _bufferedreader_reset_buf(self);
1269 /* We're going past the buffer's bounds, flush it */
1270 if (self->writable) {
1271 res = _bufferedwriter_flush_unlocked(self, 1);
1272 if (res == NULL) {
1273 Py_DECREF(chunks);
1274 return NULL;
1275 }
1276 Py_CLEAR(res);
1277 }
1278 while (1) {
1279 if (data) {
1280 if (PyList_Append(chunks, data) < 0) {
1281 Py_DECREF(data);
1282 Py_DECREF(chunks);
1283 return NULL;
1284 }
1285 Py_DECREF(data);
1286 }
1287
1288 /* Read until EOF or until read() would block. */
1289 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1290 if (data == NULL) {
1291 Py_DECREF(chunks);
1292 return NULL;
1293 }
1294 if (data != Py_None && !PyBytes_Check(data)) {
1295 Py_DECREF(data);
1296 Py_DECREF(chunks);
1297 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1298 return NULL;
1299 }
1300 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1301 if (current_size == 0) {
1302 Py_DECREF(chunks);
1303 return data;
1304 }
1305 else {
1306 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1307 Py_DECREF(data);
1308 Py_DECREF(chunks);
1309 return res;
1310 }
1311 }
1312 current_size += PyBytes_GET_SIZE(data);
1313 if (self->abs_pos != -1)
1314 self->abs_pos += PyBytes_GET_SIZE(data);
1315 }
1316}
1317
1318/* Read n bytes from the buffer if it can, otherwise return None.
1319 This function is simple enough that it can run unlocked. */
1320static PyObject *
1321_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
1322{
1323 Py_ssize_t current_size;
1324
1325 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1326 if (n <= current_size) {
1327 /* Fast path: the data to read is fully buffered. */
1328 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1329 if (res != NULL)
1330 self->pos += n;
1331 return res;
1332 }
1333 Py_RETURN_NONE;
1334}
1335
1336/* Generic read function: read from the stream until enough bytes are read,
1337 * or until an EOF occurs or until read() would block.
1338 */
1339static PyObject *
1340_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
1341{
1342 PyObject *res = NULL;
1343 Py_ssize_t current_size, remaining, written;
1344 char *out;
1345
1346 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1347 if (n <= current_size)
1348 return _bufferedreader_read_fast(self, n);
1349
1350 res = PyBytes_FromStringAndSize(NULL, n);
1351 if (res == NULL)
1352 goto error;
1353 out = PyBytes_AS_STRING(res);
1354 remaining = n;
1355 written = 0;
1356 if (current_size > 0) {
1357 memcpy(out, self->buffer + self->pos, current_size);
1358 remaining -= current_size;
1359 written += current_size;
1360 }
1361 _bufferedreader_reset_buf(self);
1362 while (remaining > 0) {
1363 /* We want to read a whole block at the end into buffer.
1364 If we had readv() we could do this in one pass. */
1365 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1366 if (r == 0)
1367 break;
1368 r = _bufferedreader_raw_read(self, out + written, r);
1369 if (r == -1)
1370 goto error;
1371 if (r == 0 || r == -2) {
1372 /* EOF occurred or read() would block. */
1373 if (r == 0 || written > 0) {
1374 if (_PyBytes_Resize(&res, written))
1375 goto error;
1376 return res;
1377 }
1378 Py_DECREF(res);
1379 Py_INCREF(Py_None);
1380 return Py_None;
1381 }
1382 remaining -= r;
1383 written += r;
1384 }
1385 assert(remaining <= self->buffer_size);
1386 self->pos = 0;
1387 self->raw_pos = 0;
1388 self->read_end = 0;
1389 while (self->read_end < self->buffer_size) {
1390 Py_ssize_t r = _bufferedreader_fill_buffer(self);
1391 if (r == -1)
1392 goto error;
1393 if (r == 0 || r == -2) {
1394 /* EOF occurred or read() would block. */
1395 if (r == 0 || written > 0) {
1396 if (_PyBytes_Resize(&res, written))
1397 goto error;
1398 return res;
1399 }
1400 Py_DECREF(res);
1401 Py_INCREF(Py_None);
1402 return Py_None;
1403 }
1404 if (remaining > r) {
1405 memcpy(out + written, self->buffer + self->pos, r);
1406 written += r;
1407 self->pos += r;
1408 remaining -= r;
1409 }
1410 else if (remaining > 0) {
1411 memcpy(out + written, self->buffer + self->pos, remaining);
1412 written += remaining;
1413 self->pos += remaining;
1414 remaining = 0;
1415 }
1416 if (remaining == 0)
1417 break;
1418 }
1419
1420 return res;
1421
1422error:
1423 Py_XDECREF(res);
1424 return NULL;
1425}
1426
1427static PyObject *
1428_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
1429{
1430 Py_ssize_t have, r;
1431
1432 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1433 /* Constraints:
1434 1. we don't want to advance the file position.
1435 2. we don't want to lose block alignment, so we can't shift the buffer
1436 to make some place.
1437 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1438 */
1439 if (have > 0) {
1440 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1441 }
1442
1443 /* Fill the buffer from the raw stream, and copy it to the result. */
1444 _bufferedreader_reset_buf(self);
1445 r = _bufferedreader_fill_buffer(self);
1446 if (r == -1)
1447 return NULL;
1448 if (r == -2)
1449 r = 0;
1450 self->pos = 0;
1451 return PyBytes_FromStringAndSize(self->buffer, r);
1452}
1453
1454static PyMethodDef bufferedreader_methods[] = {
1455 /* BufferedIOMixin methods */
1456 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1457 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1458 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1459 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1460 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1461 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1462 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1463 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
1464
1465 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1466 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1467 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
1468 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1469 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1470 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1471 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1472 {NULL, NULL}
1473};
1474
1475static PyMemberDef bufferedreader_members[] = {
1476 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
1477 {NULL}
1478};
1479
1480static PyGetSetDef bufferedreader_getset[] = {
1481 {"closed", (getter)buffered_closed_get, NULL, NULL},
1482 {"name", (getter)buffered_name_get, NULL, NULL},
1483 {"mode", (getter)buffered_mode_get, NULL, NULL},
1484 {NULL}
1485};
1486
1487
1488PyTypeObject PyBufferedReader_Type = {
1489 PyVarObject_HEAD_INIT(NULL, 0)
1490 "_io.BufferedReader", /*tp_name*/
1491 sizeof(buffered), /*tp_basicsize*/
1492 0, /*tp_itemsize*/
1493 (destructor)buffered_dealloc, /*tp_dealloc*/
1494 0, /*tp_print*/
1495 0, /*tp_getattr*/
1496 0, /*tp_setattr*/
1497 0, /*tp_compare */
1498 (reprfunc)buffered_repr, /*tp_repr*/
1499 0, /*tp_as_number*/
1500 0, /*tp_as_sequence*/
1501 0, /*tp_as_mapping*/
1502 0, /*tp_hash */
1503 0, /*tp_call*/
1504 0, /*tp_str*/
1505 0, /*tp_getattro*/
1506 0, /*tp_setattro*/
1507 0, /*tp_as_buffer*/
1508 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1509 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1510 bufferedreader_doc, /* tp_doc */
1511 (traverseproc)buffered_traverse, /* tp_traverse */
1512 (inquiry)buffered_clear, /* tp_clear */
1513 0, /* tp_richcompare */
1514 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
1515 0, /* tp_iter */
1516 (iternextfunc)buffered_iternext, /* tp_iternext */
1517 bufferedreader_methods, /* tp_methods */
1518 bufferedreader_members, /* tp_members */
1519 bufferedreader_getset, /* tp_getset */
1520 0, /* tp_base */
1521 0, /* tp_dict */
1522 0, /* tp_descr_get */
1523 0, /* tp_descr_set */
1524 offsetof(buffered, dict), /* tp_dictoffset */
1525 (initproc)bufferedreader_init, /* tp_init */
1526 0, /* tp_alloc */
1527 PyType_GenericNew, /* tp_new */
1528};
1529
1530
1531
1532static int
1533complain_about_max_buffer_size(void)
1534{
1535 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1536 "max_buffer_size is deprecated", 1) < 0)
1537 return 0;
1538 return 1;
1539}
1540
1541/*
1542 * class BufferedWriter
1543 */
1544PyDoc_STRVAR(bufferedwriter_doc,
1545 "A buffer for a writeable sequential RawIO object.\n"
1546 "\n"
1547 "The constructor creates a BufferedWriter for the given writeable raw\n"
1548 "stream. If the buffer_size is not given, it defaults to\n"
1549 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1550 );
1551
1552static void
1553_bufferedwriter_reset_buf(buffered *self)
1554{
1555 self->write_pos = 0;
1556 self->write_end = -1;
1557}
1558
1559static int
1560bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
1561{
1562 /* TODO: properly deprecate max_buffer_size */
1563 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1564 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1565 Py_ssize_t max_buffer_size = -234;
1566 PyObject *raw;
1567
1568 self->ok = 0;
1569 self->detached = 0;
1570
1571 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1572 &raw, &buffer_size, &max_buffer_size)) {
1573 return -1;
1574 }
1575
1576 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1577 return -1;
1578
1579 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
1580 return -1;
1581
1582 Py_CLEAR(self->raw);
1583 Py_INCREF(raw);
1584 self->raw = raw;
1585 self->readable = 0;
1586 self->writable = 1;
1587
1588 self->buffer_size = buffer_size;
1589 if (_buffered_init(self) < 0)
1590 return -1;
1591 _bufferedwriter_reset_buf(self);
1592 self->pos = 0;
1593
1594 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1595 Py_TYPE(raw) == &PyFileIO_Type);
1596
1597 self->ok = 1;
1598 return 0;
1599}
1600
1601static Py_ssize_t
1602_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
1603{
1604 Py_buffer buf;
1605 PyObject *memobj, *res;
1606 Py_ssize_t n;
1607 /* NOTE: the buffer needn't be released as its object is NULL. */
1608 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1609 return -1;
1610 memobj = PyMemoryView_FromBuffer(&buf);
1611 if (memobj == NULL)
1612 return -1;
1613 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1614 Py_DECREF(memobj);
1615 if (res == NULL)
1616 return -1;
1617 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1618 Py_DECREF(res);
1619 if (n < 0 || n > len) {
1620 PyErr_Format(PyExc_IOError,
1621 "raw write() returned invalid length %zd "
1622 "(should have been between 0 and %zd)", n, len);
1623 return -1;
1624 }
1625 if (n > 0 && self->abs_pos != -1)
1626 self->abs_pos += n;
1627 return n;
1628}
1629
1630/* `restore_pos` is 1 if we need to restore the raw stream position at
1631 the end, 0 otherwise. */
1632static PyObject *
1633_bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
1634{
1635 Py_ssize_t written = 0;
1636 Py_off_t n, rewind;
1637
1638 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1639 goto end;
1640 /* First, rewind */
1641 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1642 if (rewind != 0) {
1643 n = _buffered_raw_seek(self, -rewind, 1);
1644 if (n < 0) {
1645 goto error;
1646 }
1647 self->raw_pos -= rewind;
1648 }
1649 while (self->write_pos < self->write_end) {
1650 n = _bufferedwriter_raw_write(self,
1651 self->buffer + self->write_pos,
1652 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1653 Py_off_t, Py_ssize_t));
1654 if (n == -1) {
1655 Py_ssize_t *w = _buffered_check_blocking_error();
1656 if (w == NULL)
1657 goto error;
1658 self->write_pos += *w;
1659 self->raw_pos = self->write_pos;
1660 written += *w;
1661 *w = written;
1662 /* Already re-raised */
1663 goto error;
1664 }
1665 self->write_pos += n;
1666 self->raw_pos = self->write_pos;
1667 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1668 }
1669
1670 if (restore_pos) {
1671 Py_off_t forward = rewind - written;
1672 if (forward != 0) {
1673 n = _buffered_raw_seek(self, forward, 1);
1674 if (n < 0) {
1675 goto error;
1676 }
1677 self->raw_pos += forward;
1678 }
1679 }
1680 _bufferedwriter_reset_buf(self);
1681
1682end:
1683 Py_RETURN_NONE;
1684
1685error:
1686 return NULL;
1687}
1688
1689static PyObject *
1690bufferedwriter_write(buffered *self, PyObject *args)
1691{
1692 PyObject *res = NULL;
1693 Py_buffer buf;
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001694 Py_ssize_t written, avail, remaining;
1695 Py_off_t offset;
Antoine Pitrou19690592009-06-12 20:14:08 +00001696
1697 CHECK_INITIALIZED(self)
1698 if (!PyArg_ParseTuple(args, "s*:write", &buf)) {
1699 return NULL;
1700 }
1701
1702 if (IS_CLOSED(self)) {
1703 PyErr_SetString(PyExc_ValueError, "write to closed file");
1704 PyBuffer_Release(&buf);
1705 return NULL;
1706 }
1707
1708 ENTER_BUFFERED(self)
1709
1710 /* Fast path: the data to write can be fully buffered. */
1711 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1712 self->pos = 0;
1713 self->raw_pos = 0;
1714 }
1715 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1716 if (buf.len <= avail) {
1717 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1718 if (!VALID_WRITE_BUFFER(self)) {
1719 self->write_pos = self->pos;
1720 }
1721 ADJUST_POSITION(self, self->pos + buf.len);
1722 if (self->pos > self->write_end)
1723 self->write_end = self->pos;
1724 written = buf.len;
1725 goto end;
1726 }
1727
1728 /* First write the current buffer */
1729 res = _bufferedwriter_flush_unlocked(self, 0);
1730 if (res == NULL) {
1731 Py_ssize_t *w = _buffered_check_blocking_error();
1732 if (w == NULL)
1733 goto error;
1734 if (self->readable)
1735 _bufferedreader_reset_buf(self);
1736 /* Make some place by shifting the buffer. */
1737 assert(VALID_WRITE_BUFFER(self));
1738 memmove(self->buffer, self->buffer + self->write_pos,
1739 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1740 Py_off_t, Py_ssize_t));
1741 self->write_end -= self->write_pos;
1742 self->raw_pos -= self->write_pos;
1743 self->pos -= self->write_pos;
1744 self->write_pos = 0;
1745 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1746 Py_off_t, Py_ssize_t);
1747 if (buf.len <= avail) {
1748 /* Everything can be buffered */
1749 PyErr_Clear();
1750 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1751 self->write_end += buf.len;
1752 written = buf.len;
1753 goto end;
1754 }
1755 /* Buffer as much as possible. */
1756 memcpy(self->buffer + self->write_end, buf.buf, avail);
1757 self->write_end += avail;
1758 /* Already re-raised */
1759 *w = avail;
1760 goto error;
1761 }
1762 Py_CLEAR(res);
1763
Antoine Pitrou20e1f932009-08-06 20:18:29 +00001764 /* Adjust the raw stream position if it is away from the logical stream
1765 position. This happens if the read buffer has been filled but not
1766 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1767 the raw stream by itself).
1768 Fixes issue #6629.
1769 */
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001770 offset = RAW_OFFSET(self);
1771 if (offset != 0) {
1772 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitrou20e1f932009-08-06 20:18:29 +00001773 goto error;
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001774 self->raw_pos -= offset;
Antoine Pitrou20e1f932009-08-06 20:18:29 +00001775 }
1776
Antoine Pitrou19690592009-06-12 20:14:08 +00001777 /* Then write buf itself. At this point the buffer has been emptied. */
1778 remaining = buf.len;
1779 written = 0;
1780 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001781 Py_ssize_t n = _bufferedwriter_raw_write(
Antoine Pitrou19690592009-06-12 20:14:08 +00001782 self, (char *) buf.buf + written, buf.len - written);
1783 if (n == -1) {
1784 Py_ssize_t *w = _buffered_check_blocking_error();
1785 if (w == NULL)
1786 goto error;
1787 written += *w;
1788 remaining -= *w;
1789 if (remaining > self->buffer_size) {
1790 /* Can't buffer everything, still buffer as much as possible */
1791 memcpy(self->buffer,
1792 (char *) buf.buf + written, self->buffer_size);
1793 self->raw_pos = 0;
1794 ADJUST_POSITION(self, self->buffer_size);
1795 self->write_end = self->buffer_size;
1796 *w = written + self->buffer_size;
1797 /* Already re-raised */
1798 goto error;
1799 }
1800 PyErr_Clear();
1801 break;
1802 }
1803 written += n;
1804 remaining -= n;
1805 }
1806 if (self->readable)
1807 _bufferedreader_reset_buf(self);
1808 if (remaining > 0) {
1809 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1810 written += remaining;
1811 }
1812 self->write_pos = 0;
1813 /* TODO: sanity check (remaining >= 0) */
1814 self->write_end = remaining;
1815 ADJUST_POSITION(self, remaining);
1816 self->raw_pos = 0;
1817
1818end:
1819 res = PyLong_FromSsize_t(written);
1820
1821error:
1822 LEAVE_BUFFERED(self)
1823 PyBuffer_Release(&buf);
1824 return res;
1825}
1826
1827static PyMethodDef bufferedwriter_methods[] = {
1828 /* BufferedIOMixin methods */
1829 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1830 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1831 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1832 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1833 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1834 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1835 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
1836
1837 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1838 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1839 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1840 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1841 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1842 {NULL, NULL}
1843};
1844
1845static PyMemberDef bufferedwriter_members[] = {
1846 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
1847 {NULL}
1848};
1849
1850static PyGetSetDef bufferedwriter_getset[] = {
1851 {"closed", (getter)buffered_closed_get, NULL, NULL},
1852 {"name", (getter)buffered_name_get, NULL, NULL},
1853 {"mode", (getter)buffered_mode_get, NULL, NULL},
1854 {NULL}
1855};
1856
1857
1858PyTypeObject PyBufferedWriter_Type = {
1859 PyVarObject_HEAD_INIT(NULL, 0)
1860 "_io.BufferedWriter", /*tp_name*/
1861 sizeof(buffered), /*tp_basicsize*/
1862 0, /*tp_itemsize*/
1863 (destructor)buffered_dealloc, /*tp_dealloc*/
1864 0, /*tp_print*/
1865 0, /*tp_getattr*/
1866 0, /*tp_setattr*/
1867 0, /*tp_compare */
1868 (reprfunc)buffered_repr, /*tp_repr*/
1869 0, /*tp_as_number*/
1870 0, /*tp_as_sequence*/
1871 0, /*tp_as_mapping*/
1872 0, /*tp_hash */
1873 0, /*tp_call*/
1874 0, /*tp_str*/
1875 0, /*tp_getattro*/
1876 0, /*tp_setattro*/
1877 0, /*tp_as_buffer*/
1878 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1879 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1880 bufferedwriter_doc, /* tp_doc */
1881 (traverseproc)buffered_traverse, /* tp_traverse */
1882 (inquiry)buffered_clear, /* tp_clear */
1883 0, /* tp_richcompare */
1884 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
1885 0, /* tp_iter */
1886 0, /* tp_iternext */
1887 bufferedwriter_methods, /* tp_methods */
1888 bufferedwriter_members, /* tp_members */
1889 bufferedwriter_getset, /* tp_getset */
1890 0, /* tp_base */
1891 0, /* tp_dict */
1892 0, /* tp_descr_get */
1893 0, /* tp_descr_set */
1894 offsetof(buffered, dict), /* tp_dictoffset */
1895 (initproc)bufferedwriter_init, /* tp_init */
1896 0, /* tp_alloc */
1897 PyType_GenericNew, /* tp_new */
1898};
1899
1900
1901
1902/*
1903 * BufferedRWPair
1904 */
1905
1906PyDoc_STRVAR(bufferedrwpair_doc,
1907 "A buffered reader and writer object together.\n"
1908 "\n"
1909 "A buffered reader object and buffered writer object put together to\n"
1910 "form a sequential IO object that can read and write. This is typically\n"
1911 "used with a socket or two-way pipe.\n"
1912 "\n"
1913 "reader and writer are RawIOBase objects that are readable and\n"
1914 "writeable respectively. If the buffer_size is omitted it defaults to\n"
1915 "DEFAULT_BUFFER_SIZE.\n"
1916 );
1917
1918/* XXX The usefulness of this (compared to having two separate IO objects) is
1919 * questionable.
1920 */
1921
1922typedef struct {
1923 PyObject_HEAD
1924 buffered *reader;
1925 buffered *writer;
1926 PyObject *dict;
1927 PyObject *weakreflist;
1928} rwpair;
1929
1930static int
1931bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
1932{
1933 PyObject *reader, *writer;
1934 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1935 Py_ssize_t max_buffer_size = -234;
1936
1937 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1938 &buffer_size, &max_buffer_size)) {
1939 return -1;
1940 }
1941
1942 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1943 return -1;
1944
1945 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
1946 return -1;
1947 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
1948 return -1;
1949
1950 self->reader = (buffered *) PyObject_CallFunction(
1951 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
1952 if (self->reader == NULL)
1953 return -1;
1954
1955 self->writer = (buffered *) PyObject_CallFunction(
1956 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
1957 if (self->writer == NULL) {
1958 Py_CLEAR(self->reader);
1959 return -1;
1960 }
1961
1962 return 0;
1963}
1964
1965static int
1966bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
1967{
1968 Py_VISIT(self->dict);
1969 return 0;
1970}
1971
1972static int
1973bufferedrwpair_clear(rwpair *self)
1974{
1975 Py_CLEAR(self->reader);
1976 Py_CLEAR(self->writer);
1977 Py_CLEAR(self->dict);
1978 return 0;
1979}
1980
1981static void
1982bufferedrwpair_dealloc(rwpair *self)
1983{
1984 _PyObject_GC_UNTRACK(self);
1985 Py_CLEAR(self->reader);
1986 Py_CLEAR(self->writer);
1987 Py_CLEAR(self->dict);
1988 Py_TYPE(self)->tp_free((PyObject *) self);
1989}
1990
1991static PyObject *
1992_forward_call(buffered *self, const char *name, PyObject *args)
1993{
1994 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
1995 PyObject *ret;
1996
1997 if (func == NULL) {
1998 PyErr_SetString(PyExc_AttributeError, name);
1999 return NULL;
2000 }
2001
2002 ret = PyObject_CallObject(func, args);
2003 Py_DECREF(func);
2004 return ret;
2005}
2006
2007static PyObject *
2008bufferedrwpair_read(rwpair *self, PyObject *args)
2009{
2010 return _forward_call(self->reader, "read", args);
2011}
2012
2013static PyObject *
2014bufferedrwpair_peek(rwpair *self, PyObject *args)
2015{
2016 return _forward_call(self->reader, "peek", args);
2017}
2018
2019static PyObject *
2020bufferedrwpair_read1(rwpair *self, PyObject *args)
2021{
2022 return _forward_call(self->reader, "read1", args);
2023}
2024
2025static PyObject *
2026bufferedrwpair_readinto(rwpair *self, PyObject *args)
2027{
2028 return _forward_call(self->reader, "readinto", args);
2029}
2030
2031static PyObject *
2032bufferedrwpair_write(rwpair *self, PyObject *args)
2033{
2034 return _forward_call(self->writer, "write", args);
2035}
2036
2037static PyObject *
2038bufferedrwpair_flush(rwpair *self, PyObject *args)
2039{
2040 return _forward_call(self->writer, "flush", args);
2041}
2042
2043static PyObject *
2044bufferedrwpair_readable(rwpair *self, PyObject *args)
2045{
2046 return _forward_call(self->reader, "readable", args);
2047}
2048
2049static PyObject *
2050bufferedrwpair_writable(rwpair *self, PyObject *args)
2051{
2052 return _forward_call(self->writer, "writable", args);
2053}
2054
2055static PyObject *
2056bufferedrwpair_close(rwpair *self, PyObject *args)
2057{
2058 PyObject *ret = _forward_call(self->writer, "close", args);
2059 if (ret == NULL)
2060 return NULL;
2061 Py_DECREF(ret);
2062
2063 return _forward_call(self->reader, "close", args);
2064}
2065
2066static PyObject *
2067bufferedrwpair_isatty(rwpair *self, PyObject *args)
2068{
2069 PyObject *ret = _forward_call(self->writer, "isatty", args);
2070
2071 if (ret != Py_False) {
2072 /* either True or exception */
2073 return ret;
2074 }
2075 Py_DECREF(ret);
2076
2077 return _forward_call(self->reader, "isatty", args);
2078}
2079
2080static PyObject *
2081bufferedrwpair_closed_get(rwpair *self, void *context)
2082{
2083 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2084}
2085
2086static PyMethodDef bufferedrwpair_methods[] = {
2087 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2088 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2089 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2090 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
2091
2092 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2093 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
2094
2095 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2096 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
2097
2098 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2099 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
2100
2101 {NULL, NULL}
2102};
2103
2104static PyGetSetDef bufferedrwpair_getset[] = {
2105 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
2106 {NULL}
2107};
2108
2109PyTypeObject PyBufferedRWPair_Type = {
2110 PyVarObject_HEAD_INIT(NULL, 0)
2111 "_io.BufferedRWPair", /*tp_name*/
2112 sizeof(rwpair), /*tp_basicsize*/
2113 0, /*tp_itemsize*/
2114 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
2115 0, /*tp_print*/
2116 0, /*tp_getattr*/
2117 0, /*tp_setattr*/
2118 0, /*tp_compare */
2119 0, /*tp_repr*/
2120 0, /*tp_as_number*/
2121 0, /*tp_as_sequence*/
2122 0, /*tp_as_mapping*/
2123 0, /*tp_hash */
2124 0, /*tp_call*/
2125 0, /*tp_str*/
2126 0, /*tp_getattro*/
2127 0, /*tp_setattro*/
2128 0, /*tp_as_buffer*/
2129 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2130 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
2131 bufferedrwpair_doc, /* tp_doc */
2132 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2133 (inquiry)bufferedrwpair_clear, /* tp_clear */
2134 0, /* tp_richcompare */
2135 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
2136 0, /* tp_iter */
2137 0, /* tp_iternext */
2138 bufferedrwpair_methods, /* tp_methods */
2139 0, /* tp_members */
2140 bufferedrwpair_getset, /* tp_getset */
2141 0, /* tp_base */
2142 0, /* tp_dict */
2143 0, /* tp_descr_get */
2144 0, /* tp_descr_set */
2145 offsetof(rwpair, dict), /* tp_dictoffset */
2146 (initproc)bufferedrwpair_init, /* tp_init */
2147 0, /* tp_alloc */
2148 PyType_GenericNew, /* tp_new */
2149};
2150
2151
2152
2153/*
2154 * BufferedRandom
2155 */
2156
2157PyDoc_STRVAR(bufferedrandom_doc,
2158 "A buffered interface to random access streams.\n"
2159 "\n"
2160 "The constructor creates a reader and writer for a seekable stream,\n"
2161 "raw, given in the first argument. If the buffer_size is omitted it\n"
2162 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2163 );
2164
2165static int
2166bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
2167{
2168 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2169 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
2170 Py_ssize_t max_buffer_size = -234;
2171 PyObject *raw;
2172
2173 self->ok = 0;
2174 self->detached = 0;
2175
2176 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2177 &raw, &buffer_size, &max_buffer_size)) {
2178 return -1;
2179 }
2180
2181 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2182 return -1;
2183
2184 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
2185 return -1;
2186 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
2187 return -1;
2188 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
2189 return -1;
2190
2191 Py_CLEAR(self->raw);
2192 Py_INCREF(raw);
2193 self->raw = raw;
2194 self->buffer_size = buffer_size;
2195 self->readable = 1;
2196 self->writable = 1;
2197
2198 if (_buffered_init(self) < 0)
2199 return -1;
2200 _bufferedreader_reset_buf(self);
2201 _bufferedwriter_reset_buf(self);
2202 self->pos = 0;
2203
2204 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2205 Py_TYPE(raw) == &PyFileIO_Type);
2206
2207 self->ok = 1;
2208 return 0;
2209}
2210
2211static PyMethodDef bufferedrandom_methods[] = {
2212 /* BufferedIOMixin methods */
2213 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2214 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2215 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2216 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2217 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2218 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2219 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2220
2221 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2222
2223 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2224 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2225 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2226 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2227 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2228 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2229 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2230 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2231 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
2232 {NULL, NULL}
2233};
2234
2235static PyMemberDef bufferedrandom_members[] = {
2236 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
2237 {NULL}
2238};
2239
2240static PyGetSetDef bufferedrandom_getset[] = {
2241 {"closed", (getter)buffered_closed_get, NULL, NULL},
2242 {"name", (getter)buffered_name_get, NULL, NULL},
2243 {"mode", (getter)buffered_mode_get, NULL, NULL},
2244 {NULL}
2245};
2246
2247
2248PyTypeObject PyBufferedRandom_Type = {
2249 PyVarObject_HEAD_INIT(NULL, 0)
2250 "_io.BufferedRandom", /*tp_name*/
2251 sizeof(buffered), /*tp_basicsize*/
2252 0, /*tp_itemsize*/
2253 (destructor)buffered_dealloc, /*tp_dealloc*/
2254 0, /*tp_print*/
2255 0, /*tp_getattr*/
2256 0, /*tp_setattr*/
2257 0, /*tp_compare */
2258 (reprfunc)buffered_repr, /*tp_repr*/
2259 0, /*tp_as_number*/
2260 0, /*tp_as_sequence*/
2261 0, /*tp_as_mapping*/
2262 0, /*tp_hash */
2263 0, /*tp_call*/
2264 0, /*tp_str*/
2265 0, /*tp_getattro*/
2266 0, /*tp_setattro*/
2267 0, /*tp_as_buffer*/
2268 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2269 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2270 bufferedrandom_doc, /* tp_doc */
2271 (traverseproc)buffered_traverse, /* tp_traverse */
2272 (inquiry)buffered_clear, /* tp_clear */
2273 0, /* tp_richcompare */
2274 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2275 0, /* tp_iter */
2276 (iternextfunc)buffered_iternext, /* tp_iternext */
2277 bufferedrandom_methods, /* tp_methods */
2278 bufferedrandom_members, /* tp_members */
2279 bufferedrandom_getset, /* tp_getset */
2280 0, /* tp_base */
2281 0, /*tp_dict*/
2282 0, /* tp_descr_get */
2283 0, /* tp_descr_set */
2284 offsetof(buffered, dict), /*tp_dictoffset*/
2285 (initproc)bufferedrandom_init, /* tp_init */
2286 0, /* tp_alloc */
2287 PyType_GenericNew, /* tp_new */
2288};
2289