blob: d96b7eee3ce06d80f2c98dfe9ed010476ca8c2c1 [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);
Antoine Pitrou3ebaed62010-08-21 19:17:25 +00001673 /* Partial writes can return successfully when interrupted by a
1674 signal (see write(2)). We must run signal handlers before
1675 blocking another time, possibly indefinitely. */
1676 if (PyErr_CheckSignals() < 0)
1677 goto error;
Antoine Pitrou19690592009-06-12 20:14:08 +00001678 }
1679
1680 if (restore_pos) {
1681 Py_off_t forward = rewind - written;
1682 if (forward != 0) {
1683 n = _buffered_raw_seek(self, forward, 1);
1684 if (n < 0) {
1685 goto error;
1686 }
1687 self->raw_pos += forward;
1688 }
1689 }
1690 _bufferedwriter_reset_buf(self);
1691
1692end:
1693 Py_RETURN_NONE;
1694
1695error:
1696 return NULL;
1697}
1698
1699static PyObject *
1700bufferedwriter_write(buffered *self, PyObject *args)
1701{
1702 PyObject *res = NULL;
1703 Py_buffer buf;
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001704 Py_ssize_t written, avail, remaining;
1705 Py_off_t offset;
Antoine Pitrou19690592009-06-12 20:14:08 +00001706
1707 CHECK_INITIALIZED(self)
1708 if (!PyArg_ParseTuple(args, "s*:write", &buf)) {
1709 return NULL;
1710 }
1711
1712 if (IS_CLOSED(self)) {
1713 PyErr_SetString(PyExc_ValueError, "write to closed file");
1714 PyBuffer_Release(&buf);
1715 return NULL;
1716 }
1717
1718 ENTER_BUFFERED(self)
1719
1720 /* Fast path: the data to write can be fully buffered. */
1721 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1722 self->pos = 0;
1723 self->raw_pos = 0;
1724 }
1725 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1726 if (buf.len <= avail) {
1727 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1728 if (!VALID_WRITE_BUFFER(self)) {
1729 self->write_pos = self->pos;
1730 }
1731 ADJUST_POSITION(self, self->pos + buf.len);
1732 if (self->pos > self->write_end)
1733 self->write_end = self->pos;
1734 written = buf.len;
1735 goto end;
1736 }
1737
1738 /* First write the current buffer */
1739 res = _bufferedwriter_flush_unlocked(self, 0);
1740 if (res == NULL) {
1741 Py_ssize_t *w = _buffered_check_blocking_error();
1742 if (w == NULL)
1743 goto error;
1744 if (self->readable)
1745 _bufferedreader_reset_buf(self);
1746 /* Make some place by shifting the buffer. */
1747 assert(VALID_WRITE_BUFFER(self));
1748 memmove(self->buffer, self->buffer + self->write_pos,
1749 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1750 Py_off_t, Py_ssize_t));
1751 self->write_end -= self->write_pos;
1752 self->raw_pos -= self->write_pos;
1753 self->pos -= self->write_pos;
1754 self->write_pos = 0;
1755 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1756 Py_off_t, Py_ssize_t);
1757 if (buf.len <= avail) {
1758 /* Everything can be buffered */
1759 PyErr_Clear();
1760 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1761 self->write_end += buf.len;
1762 written = buf.len;
1763 goto end;
1764 }
1765 /* Buffer as much as possible. */
1766 memcpy(self->buffer + self->write_end, buf.buf, avail);
1767 self->write_end += avail;
1768 /* Already re-raised */
1769 *w = avail;
1770 goto error;
1771 }
1772 Py_CLEAR(res);
1773
Antoine Pitrou20e1f932009-08-06 20:18:29 +00001774 /* Adjust the raw stream position if it is away from the logical stream
1775 position. This happens if the read buffer has been filled but not
1776 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1777 the raw stream by itself).
1778 Fixes issue #6629.
1779 */
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001780 offset = RAW_OFFSET(self);
1781 if (offset != 0) {
1782 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitrou20e1f932009-08-06 20:18:29 +00001783 goto error;
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001784 self->raw_pos -= offset;
Antoine Pitrou20e1f932009-08-06 20:18:29 +00001785 }
1786
Antoine Pitrou19690592009-06-12 20:14:08 +00001787 /* Then write buf itself. At this point the buffer has been emptied. */
1788 remaining = buf.len;
1789 written = 0;
1790 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001791 Py_ssize_t n = _bufferedwriter_raw_write(
Antoine Pitrou19690592009-06-12 20:14:08 +00001792 self, (char *) buf.buf + written, buf.len - written);
1793 if (n == -1) {
1794 Py_ssize_t *w = _buffered_check_blocking_error();
1795 if (w == NULL)
1796 goto error;
1797 written += *w;
1798 remaining -= *w;
1799 if (remaining > self->buffer_size) {
1800 /* Can't buffer everything, still buffer as much as possible */
1801 memcpy(self->buffer,
1802 (char *) buf.buf + written, self->buffer_size);
1803 self->raw_pos = 0;
1804 ADJUST_POSITION(self, self->buffer_size);
1805 self->write_end = self->buffer_size;
1806 *w = written + self->buffer_size;
1807 /* Already re-raised */
1808 goto error;
1809 }
1810 PyErr_Clear();
1811 break;
1812 }
1813 written += n;
1814 remaining -= n;
Antoine Pitrou3ebaed62010-08-21 19:17:25 +00001815 /* Partial writes can return successfully when interrupted by a
1816 signal (see write(2)). We must run signal handlers before
1817 blocking another time, possibly indefinitely. */
1818 if (PyErr_CheckSignals() < 0)
1819 goto error;
Antoine Pitrou19690592009-06-12 20:14:08 +00001820 }
1821 if (self->readable)
1822 _bufferedreader_reset_buf(self);
1823 if (remaining > 0) {
1824 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1825 written += remaining;
1826 }
1827 self->write_pos = 0;
1828 /* TODO: sanity check (remaining >= 0) */
1829 self->write_end = remaining;
1830 ADJUST_POSITION(self, remaining);
1831 self->raw_pos = 0;
1832
1833end:
1834 res = PyLong_FromSsize_t(written);
1835
1836error:
1837 LEAVE_BUFFERED(self)
1838 PyBuffer_Release(&buf);
1839 return res;
1840}
1841
1842static PyMethodDef bufferedwriter_methods[] = {
1843 /* BufferedIOMixin methods */
1844 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1845 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1846 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1847 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1848 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1849 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1850 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
1851
1852 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1853 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1854 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1855 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1856 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1857 {NULL, NULL}
1858};
1859
1860static PyMemberDef bufferedwriter_members[] = {
1861 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
1862 {NULL}
1863};
1864
1865static PyGetSetDef bufferedwriter_getset[] = {
1866 {"closed", (getter)buffered_closed_get, NULL, NULL},
1867 {"name", (getter)buffered_name_get, NULL, NULL},
1868 {"mode", (getter)buffered_mode_get, NULL, NULL},
1869 {NULL}
1870};
1871
1872
1873PyTypeObject PyBufferedWriter_Type = {
1874 PyVarObject_HEAD_INIT(NULL, 0)
1875 "_io.BufferedWriter", /*tp_name*/
1876 sizeof(buffered), /*tp_basicsize*/
1877 0, /*tp_itemsize*/
1878 (destructor)buffered_dealloc, /*tp_dealloc*/
1879 0, /*tp_print*/
1880 0, /*tp_getattr*/
1881 0, /*tp_setattr*/
1882 0, /*tp_compare */
1883 (reprfunc)buffered_repr, /*tp_repr*/
1884 0, /*tp_as_number*/
1885 0, /*tp_as_sequence*/
1886 0, /*tp_as_mapping*/
1887 0, /*tp_hash */
1888 0, /*tp_call*/
1889 0, /*tp_str*/
1890 0, /*tp_getattro*/
1891 0, /*tp_setattro*/
1892 0, /*tp_as_buffer*/
1893 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1894 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1895 bufferedwriter_doc, /* tp_doc */
1896 (traverseproc)buffered_traverse, /* tp_traverse */
1897 (inquiry)buffered_clear, /* tp_clear */
1898 0, /* tp_richcompare */
1899 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
1900 0, /* tp_iter */
1901 0, /* tp_iternext */
1902 bufferedwriter_methods, /* tp_methods */
1903 bufferedwriter_members, /* tp_members */
1904 bufferedwriter_getset, /* tp_getset */
1905 0, /* tp_base */
1906 0, /* tp_dict */
1907 0, /* tp_descr_get */
1908 0, /* tp_descr_set */
1909 offsetof(buffered, dict), /* tp_dictoffset */
1910 (initproc)bufferedwriter_init, /* tp_init */
1911 0, /* tp_alloc */
1912 PyType_GenericNew, /* tp_new */
1913};
1914
1915
1916
1917/*
1918 * BufferedRWPair
1919 */
1920
1921PyDoc_STRVAR(bufferedrwpair_doc,
1922 "A buffered reader and writer object together.\n"
1923 "\n"
1924 "A buffered reader object and buffered writer object put together to\n"
1925 "form a sequential IO object that can read and write. This is typically\n"
1926 "used with a socket or two-way pipe.\n"
1927 "\n"
1928 "reader and writer are RawIOBase objects that are readable and\n"
1929 "writeable respectively. If the buffer_size is omitted it defaults to\n"
1930 "DEFAULT_BUFFER_SIZE.\n"
1931 );
1932
1933/* XXX The usefulness of this (compared to having two separate IO objects) is
1934 * questionable.
1935 */
1936
1937typedef struct {
1938 PyObject_HEAD
1939 buffered *reader;
1940 buffered *writer;
1941 PyObject *dict;
1942 PyObject *weakreflist;
1943} rwpair;
1944
1945static int
1946bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
1947{
1948 PyObject *reader, *writer;
1949 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1950 Py_ssize_t max_buffer_size = -234;
1951
1952 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1953 &buffer_size, &max_buffer_size)) {
1954 return -1;
1955 }
1956
1957 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1958 return -1;
1959
1960 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
1961 return -1;
1962 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
1963 return -1;
1964
1965 self->reader = (buffered *) PyObject_CallFunction(
1966 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
1967 if (self->reader == NULL)
1968 return -1;
1969
1970 self->writer = (buffered *) PyObject_CallFunction(
1971 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
1972 if (self->writer == NULL) {
1973 Py_CLEAR(self->reader);
1974 return -1;
1975 }
1976
1977 return 0;
1978}
1979
1980static int
1981bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
1982{
1983 Py_VISIT(self->dict);
1984 return 0;
1985}
1986
1987static int
1988bufferedrwpair_clear(rwpair *self)
1989{
1990 Py_CLEAR(self->reader);
1991 Py_CLEAR(self->writer);
1992 Py_CLEAR(self->dict);
1993 return 0;
1994}
1995
1996static void
1997bufferedrwpair_dealloc(rwpair *self)
1998{
1999 _PyObject_GC_UNTRACK(self);
2000 Py_CLEAR(self->reader);
2001 Py_CLEAR(self->writer);
2002 Py_CLEAR(self->dict);
2003 Py_TYPE(self)->tp_free((PyObject *) self);
2004}
2005
2006static PyObject *
2007_forward_call(buffered *self, const char *name, PyObject *args)
2008{
2009 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
2010 PyObject *ret;
2011
2012 if (func == NULL) {
2013 PyErr_SetString(PyExc_AttributeError, name);
2014 return NULL;
2015 }
2016
2017 ret = PyObject_CallObject(func, args);
2018 Py_DECREF(func);
2019 return ret;
2020}
2021
2022static PyObject *
2023bufferedrwpair_read(rwpair *self, PyObject *args)
2024{
2025 return _forward_call(self->reader, "read", args);
2026}
2027
2028static PyObject *
2029bufferedrwpair_peek(rwpair *self, PyObject *args)
2030{
2031 return _forward_call(self->reader, "peek", args);
2032}
2033
2034static PyObject *
2035bufferedrwpair_read1(rwpair *self, PyObject *args)
2036{
2037 return _forward_call(self->reader, "read1", args);
2038}
2039
2040static PyObject *
2041bufferedrwpair_readinto(rwpair *self, PyObject *args)
2042{
2043 return _forward_call(self->reader, "readinto", args);
2044}
2045
2046static PyObject *
2047bufferedrwpair_write(rwpair *self, PyObject *args)
2048{
2049 return _forward_call(self->writer, "write", args);
2050}
2051
2052static PyObject *
2053bufferedrwpair_flush(rwpair *self, PyObject *args)
2054{
2055 return _forward_call(self->writer, "flush", args);
2056}
2057
2058static PyObject *
2059bufferedrwpair_readable(rwpair *self, PyObject *args)
2060{
2061 return _forward_call(self->reader, "readable", args);
2062}
2063
2064static PyObject *
2065bufferedrwpair_writable(rwpair *self, PyObject *args)
2066{
2067 return _forward_call(self->writer, "writable", args);
2068}
2069
2070static PyObject *
2071bufferedrwpair_close(rwpair *self, PyObject *args)
2072{
2073 PyObject *ret = _forward_call(self->writer, "close", args);
2074 if (ret == NULL)
2075 return NULL;
2076 Py_DECREF(ret);
2077
2078 return _forward_call(self->reader, "close", args);
2079}
2080
2081static PyObject *
2082bufferedrwpair_isatty(rwpair *self, PyObject *args)
2083{
2084 PyObject *ret = _forward_call(self->writer, "isatty", args);
2085
2086 if (ret != Py_False) {
2087 /* either True or exception */
2088 return ret;
2089 }
2090 Py_DECREF(ret);
2091
2092 return _forward_call(self->reader, "isatty", args);
2093}
2094
2095static PyObject *
2096bufferedrwpair_closed_get(rwpair *self, void *context)
2097{
2098 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2099}
2100
2101static PyMethodDef bufferedrwpair_methods[] = {
2102 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2103 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2104 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2105 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
2106
2107 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2108 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
2109
2110 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2111 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
2112
2113 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2114 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
2115
2116 {NULL, NULL}
2117};
2118
2119static PyGetSetDef bufferedrwpair_getset[] = {
2120 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
2121 {NULL}
2122};
2123
2124PyTypeObject PyBufferedRWPair_Type = {
2125 PyVarObject_HEAD_INIT(NULL, 0)
2126 "_io.BufferedRWPair", /*tp_name*/
2127 sizeof(rwpair), /*tp_basicsize*/
2128 0, /*tp_itemsize*/
2129 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
2130 0, /*tp_print*/
2131 0, /*tp_getattr*/
2132 0, /*tp_setattr*/
2133 0, /*tp_compare */
2134 0, /*tp_repr*/
2135 0, /*tp_as_number*/
2136 0, /*tp_as_sequence*/
2137 0, /*tp_as_mapping*/
2138 0, /*tp_hash */
2139 0, /*tp_call*/
2140 0, /*tp_str*/
2141 0, /*tp_getattro*/
2142 0, /*tp_setattro*/
2143 0, /*tp_as_buffer*/
2144 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2145 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
2146 bufferedrwpair_doc, /* tp_doc */
2147 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2148 (inquiry)bufferedrwpair_clear, /* tp_clear */
2149 0, /* tp_richcompare */
2150 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
2151 0, /* tp_iter */
2152 0, /* tp_iternext */
2153 bufferedrwpair_methods, /* tp_methods */
2154 0, /* tp_members */
2155 bufferedrwpair_getset, /* tp_getset */
2156 0, /* tp_base */
2157 0, /* tp_dict */
2158 0, /* tp_descr_get */
2159 0, /* tp_descr_set */
2160 offsetof(rwpair, dict), /* tp_dictoffset */
2161 (initproc)bufferedrwpair_init, /* tp_init */
2162 0, /* tp_alloc */
2163 PyType_GenericNew, /* tp_new */
2164};
2165
2166
2167
2168/*
2169 * BufferedRandom
2170 */
2171
2172PyDoc_STRVAR(bufferedrandom_doc,
2173 "A buffered interface to random access streams.\n"
2174 "\n"
2175 "The constructor creates a reader and writer for a seekable stream,\n"
2176 "raw, given in the first argument. If the buffer_size is omitted it\n"
2177 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2178 );
2179
2180static int
2181bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
2182{
2183 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2184 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
2185 Py_ssize_t max_buffer_size = -234;
2186 PyObject *raw;
2187
2188 self->ok = 0;
2189 self->detached = 0;
2190
2191 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2192 &raw, &buffer_size, &max_buffer_size)) {
2193 return -1;
2194 }
2195
2196 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2197 return -1;
2198
2199 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
2200 return -1;
2201 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
2202 return -1;
2203 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
2204 return -1;
2205
2206 Py_CLEAR(self->raw);
2207 Py_INCREF(raw);
2208 self->raw = raw;
2209 self->buffer_size = buffer_size;
2210 self->readable = 1;
2211 self->writable = 1;
2212
2213 if (_buffered_init(self) < 0)
2214 return -1;
2215 _bufferedreader_reset_buf(self);
2216 _bufferedwriter_reset_buf(self);
2217 self->pos = 0;
2218
2219 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2220 Py_TYPE(raw) == &PyFileIO_Type);
2221
2222 self->ok = 1;
2223 return 0;
2224}
2225
2226static PyMethodDef bufferedrandom_methods[] = {
2227 /* BufferedIOMixin methods */
2228 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2229 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2230 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2231 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2232 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2233 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2234 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2235
2236 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2237
2238 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2239 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2240 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2241 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2242 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2243 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2244 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2245 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2246 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
2247 {NULL, NULL}
2248};
2249
2250static PyMemberDef bufferedrandom_members[] = {
2251 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
2252 {NULL}
2253};
2254
2255static PyGetSetDef bufferedrandom_getset[] = {
2256 {"closed", (getter)buffered_closed_get, NULL, NULL},
2257 {"name", (getter)buffered_name_get, NULL, NULL},
2258 {"mode", (getter)buffered_mode_get, NULL, NULL},
2259 {NULL}
2260};
2261
2262
2263PyTypeObject PyBufferedRandom_Type = {
2264 PyVarObject_HEAD_INIT(NULL, 0)
2265 "_io.BufferedRandom", /*tp_name*/
2266 sizeof(buffered), /*tp_basicsize*/
2267 0, /*tp_itemsize*/
2268 (destructor)buffered_dealloc, /*tp_dealloc*/
2269 0, /*tp_print*/
2270 0, /*tp_getattr*/
2271 0, /*tp_setattr*/
2272 0, /*tp_compare */
2273 (reprfunc)buffered_repr, /*tp_repr*/
2274 0, /*tp_as_number*/
2275 0, /*tp_as_sequence*/
2276 0, /*tp_as_mapping*/
2277 0, /*tp_hash */
2278 0, /*tp_call*/
2279 0, /*tp_str*/
2280 0, /*tp_getattro*/
2281 0, /*tp_setattro*/
2282 0, /*tp_as_buffer*/
2283 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2284 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2285 bufferedrandom_doc, /* tp_doc */
2286 (traverseproc)buffered_traverse, /* tp_traverse */
2287 (inquiry)buffered_clear, /* tp_clear */
2288 0, /* tp_richcompare */
2289 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2290 0, /* tp_iter */
2291 (iternextfunc)buffered_iternext, /* tp_iternext */
2292 bufferedrandom_methods, /* tp_methods */
2293 bufferedrandom_members, /* tp_members */
2294 bufferedrandom_getset, /* tp_getset */
2295 0, /* tp_base */
2296 0, /*tp_dict*/
2297 0, /* tp_descr_get */
2298 0, /* tp_descr_set */
2299 offsetof(buffered, dict), /*tp_dictoffset*/
2300 (initproc)bufferedrandom_init, /* tp_init */
2301 0, /* tp_alloc */
2302 PyType_GenericNew, /* tp_new */
2303};
2304