blob: c6373c6680b08e787470cc1874792c69701fb0db [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;
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000227 volatile long owner;
Antoine Pitrou19690592009-06-12 20:14:08 +0000228#endif
229
230 Py_ssize_t buffer_size;
231 Py_ssize_t buffer_mask;
232
233 PyObject *dict;
234 PyObject *weakreflist;
235} buffered;
236
237/*
238 Implementation notes:
239
240 * BufferedReader, BufferedWriter and BufferedRandom try to share most
241 methods (this is helped by the members `readable` and `writable`, which
242 are initialized in the respective constructors)
243 * They also share a single buffer for reading and writing. This enables
244 interleaved reads and writes without flushing. It also makes the logic
245 a bit trickier to get right.
246 * The absolute position of the raw stream is cached, if possible, in the
247 `abs_pos` member. It must be updated every time an operation is done
248 on the raw stream. If not sure, it can be reinitialized by calling
249 _buffered_raw_tell(), which queries the raw stream (_buffered_raw_seek()
250 also does it). To read it, use RAW_TELL().
251 * Three helpers, _bufferedreader_raw_read, _bufferedwriter_raw_write and
252 _bufferedwriter_flush_unlocked do a lot of useful housekeeping.
253
254 NOTE: we should try to maintain block alignment of reads and writes to the
255 raw stream (according to the buffer size), but for now it is only done
256 in read() and friends.
257
258*/
259
260/* These macros protect the buffered object against concurrent operations. */
261
262#ifdef WITH_THREAD
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000263
264static int
265_enter_buffered_busy(buffered *self)
266{
267 if (self->owner == PyThread_get_thread_ident()) {
268 PyObject *r = PyObject_Repr((PyObject *) self);
269 if (r != NULL) {
270 PyErr_Format(PyExc_RuntimeError,
271 "reentrant call inside %s",
272 PyString_AS_STRING(r));
273 Py_DECREF(r);
274 }
275 return 0;
Antoine Pitroue50efaa2009-11-01 11:58:22 +0000276 }
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000277 Py_BEGIN_ALLOW_THREADS
278 PyThread_acquire_lock(self->lock, 1);
279 Py_END_ALLOW_THREADS
280 return 1;
281}
282
283#define ENTER_BUFFERED(self) \
284 ( (PyThread_acquire_lock(self->lock, 0) ? \
285 1 : _enter_buffered_busy(self)) \
286 && (self->owner = PyThread_get_thread_ident(), 1) )
Antoine Pitrou19690592009-06-12 20:14:08 +0000287
288#define LEAVE_BUFFERED(self) \
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000289 do { \
290 self->owner = 0; \
291 PyThread_release_lock(self->lock); \
292 } while(0);
293
Antoine Pitrou19690592009-06-12 20:14:08 +0000294#else
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000295#define ENTER_BUFFERED(self) 1
Antoine Pitrou19690592009-06-12 20:14:08 +0000296#define LEAVE_BUFFERED(self)
297#endif
298
299#define CHECK_INITIALIZED(self) \
300 if (self->ok <= 0) { \
301 if (self->detached) { \
302 PyErr_SetString(PyExc_ValueError, \
303 "raw stream has been detached"); \
304 } else { \
305 PyErr_SetString(PyExc_ValueError, \
306 "I/O operation on uninitialized object"); \
307 } \
308 return NULL; \
309 }
310
311#define CHECK_INITIALIZED_INT(self) \
312 if (self->ok <= 0) { \
313 if (self->detached) { \
314 PyErr_SetString(PyExc_ValueError, \
315 "raw stream has been detached"); \
316 } else { \
317 PyErr_SetString(PyExc_ValueError, \
318 "I/O operation on uninitialized object"); \
319 } \
320 return -1; \
321 }
322
323#define IS_CLOSED(self) \
324 (self->fast_closed_checks \
325 ? _PyFileIO_closed(self->raw) \
326 : buffered_closed(self))
327
328#define CHECK_CLOSED(self, error_msg) \
329 if (IS_CLOSED(self)) { \
330 PyErr_SetString(PyExc_ValueError, error_msg); \
331 return NULL; \
332 }
333
334
335#define VALID_READ_BUFFER(self) \
336 (self->readable && self->read_end != -1)
337
338#define VALID_WRITE_BUFFER(self) \
339 (self->writable && self->write_end != -1)
340
341#define ADJUST_POSITION(self, _new_pos) \
342 do { \
343 self->pos = _new_pos; \
344 if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
345 self->read_end = self->pos; \
346 } while(0)
347
348#define READAHEAD(self) \
349 ((self->readable && VALID_READ_BUFFER(self)) \
350 ? (self->read_end - self->pos) : 0)
351
352#define RAW_OFFSET(self) \
353 (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
354 && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
355
356#define RAW_TELL(self) \
357 (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
358
359#define MINUS_LAST_BLOCK(self, size) \
360 (self->buffer_mask ? \
361 (size & ~self->buffer_mask) : \
362 (self->buffer_size * (size / self->buffer_size)))
363
364
365static void
366buffered_dealloc(buffered *self)
367{
368 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
369 return;
370 _PyObject_GC_UNTRACK(self);
371 self->ok = 0;
372 if (self->weakreflist != NULL)
373 PyObject_ClearWeakRefs((PyObject *)self);
374 Py_CLEAR(self->raw);
375 if (self->buffer) {
376 PyMem_Free(self->buffer);
377 self->buffer = NULL;
378 }
379#ifdef WITH_THREAD
380 if (self->lock) {
381 PyThread_free_lock(self->lock);
382 self->lock = NULL;
383 }
384#endif
385 Py_CLEAR(self->dict);
386 Py_TYPE(self)->tp_free((PyObject *)self);
387}
388
389static int
390buffered_traverse(buffered *self, visitproc visit, void *arg)
391{
392 Py_VISIT(self->raw);
393 Py_VISIT(self->dict);
394 return 0;
395}
396
397static int
398buffered_clear(buffered *self)
399{
400 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
401 return -1;
402 self->ok = 0;
403 Py_CLEAR(self->raw);
404 Py_CLEAR(self->dict);
405 return 0;
406}
407
408/*
409 * _BufferedIOMixin methods
410 * This is not a class, just a collection of methods that will be reused
411 * by BufferedReader and BufferedWriter
412 */
413
414/* Flush and close */
415
416static PyObject *
417buffered_simple_flush(buffered *self, PyObject *args)
418{
419 CHECK_INITIALIZED(self)
420 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
421}
422
423static int
424buffered_closed(buffered *self)
425{
426 int closed;
427 PyObject *res;
428 CHECK_INITIALIZED_INT(self)
429 res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
430 if (res == NULL)
431 return -1;
432 closed = PyObject_IsTrue(res);
433 Py_DECREF(res);
434 return closed;
435}
436
437static PyObject *
438buffered_closed_get(buffered *self, void *context)
439{
440 CHECK_INITIALIZED(self)
441 return PyObject_GetAttr(self->raw, _PyIO_str_closed);
442}
443
444static PyObject *
445buffered_close(buffered *self, PyObject *args)
446{
447 PyObject *res = NULL;
448 int r;
449
450 CHECK_INITIALIZED(self)
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000451 if (!ENTER_BUFFERED(self))
452 return NULL;
Antoine Pitrou19690592009-06-12 20:14:08 +0000453
454 r = buffered_closed(self);
455 if (r < 0)
456 goto end;
457 if (r > 0) {
458 res = Py_None;
459 Py_INCREF(res);
460 goto end;
461 }
462 /* flush() will most probably re-take the lock, so drop it first */
463 LEAVE_BUFFERED(self)
464 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000465 if (!ENTER_BUFFERED(self))
466 return NULL;
Antoine Pitrou19690592009-06-12 20:14:08 +0000467 if (res == NULL) {
Antoine Pitrouf7fd8e42010-05-03 16:25:33 +0000468 goto end;
Antoine Pitrou19690592009-06-12 20:14:08 +0000469 }
470 Py_XDECREF(res);
471
472 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
473
474end:
475 LEAVE_BUFFERED(self)
476 return res;
477}
478
479/* detach */
480
481static PyObject *
482buffered_detach(buffered *self, PyObject *args)
483{
484 PyObject *raw, *res;
485 CHECK_INITIALIZED(self)
486 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
487 if (res == NULL)
488 return NULL;
489 Py_DECREF(res);
490 raw = self->raw;
491 self->raw = NULL;
492 self->detached = 1;
493 self->ok = 0;
494 return raw;
495}
496
497/* Inquiries */
498
499static PyObject *
500buffered_seekable(buffered *self, PyObject *args)
501{
502 CHECK_INITIALIZED(self)
503 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
504}
505
506static PyObject *
507buffered_readable(buffered *self, PyObject *args)
508{
509 CHECK_INITIALIZED(self)
510 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
511}
512
513static PyObject *
514buffered_writable(buffered *self, PyObject *args)
515{
516 CHECK_INITIALIZED(self)
517 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
518}
519
520static PyObject *
521buffered_name_get(buffered *self, void *context)
522{
523 CHECK_INITIALIZED(self)
524 return PyObject_GetAttrString(self->raw, "name");
525}
526
527static PyObject *
528buffered_mode_get(buffered *self, void *context)
529{
530 CHECK_INITIALIZED(self)
531 return PyObject_GetAttrString(self->raw, "mode");
532}
533
534/* Lower-level APIs */
535
536static PyObject *
537buffered_fileno(buffered *self, PyObject *args)
538{
539 CHECK_INITIALIZED(self)
540 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
541}
542
543static PyObject *
544buffered_isatty(buffered *self, PyObject *args)
545{
546 CHECK_INITIALIZED(self)
547 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
548}
549
550
551/* Forward decls */
552static PyObject *
553_bufferedwriter_flush_unlocked(buffered *, int);
554static Py_ssize_t
555_bufferedreader_fill_buffer(buffered *self);
556static void
557_bufferedreader_reset_buf(buffered *self);
558static void
559_bufferedwriter_reset_buf(buffered *self);
560static PyObject *
561_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t);
562static PyObject *
563_bufferedreader_read_all(buffered *self);
564static PyObject *
565_bufferedreader_read_fast(buffered *self, Py_ssize_t);
566static PyObject *
567_bufferedreader_read_generic(buffered *self, Py_ssize_t);
568
569
570/*
571 * Helpers
572 */
573
574/* Returns the address of the `written` member if a BlockingIOError was
575 raised, NULL otherwise. The error is always re-raised. */
576static Py_ssize_t *
577_buffered_check_blocking_error(void)
578{
579 PyObject *t, *v, *tb;
580 PyBlockingIOErrorObject *err;
581
582 PyErr_Fetch(&t, &v, &tb);
583 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
584 PyErr_Restore(t, v, tb);
585 return NULL;
586 }
587 err = (PyBlockingIOErrorObject *) v;
588 /* TODO: sanity check (err->written >= 0) */
589 PyErr_Restore(t, v, tb);
590 return &err->written;
591}
592
593static Py_off_t
594_buffered_raw_tell(buffered *self)
595{
596 Py_off_t n;
597 PyObject *res;
598 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
599 if (res == NULL)
600 return -1;
601 n = PyNumber_AsOff_t(res, PyExc_ValueError);
602 Py_DECREF(res);
603 if (n < 0) {
604 if (!PyErr_Occurred())
605 PyErr_Format(PyExc_IOError,
Mark Dickinson889d96452009-11-24 20:51:48 +0000606 "Raw stream returned invalid position %" PY_PRIdOFF,
607 (PY_OFF_T_COMPAT)n);
Antoine Pitrou19690592009-06-12 20:14:08 +0000608 return -1;
609 }
610 self->abs_pos = n;
611 return n;
612}
613
614static Py_off_t
615_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
616{
617 PyObject *res, *posobj, *whenceobj;
618 Py_off_t n;
619
620 posobj = PyLong_FromOff_t(target);
621 if (posobj == NULL)
622 return -1;
623 whenceobj = PyLong_FromLong(whence);
624 if (whenceobj == NULL) {
625 Py_DECREF(posobj);
626 return -1;
627 }
628 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
629 posobj, whenceobj, NULL);
630 Py_DECREF(posobj);
631 Py_DECREF(whenceobj);
632 if (res == NULL)
633 return -1;
634 n = PyNumber_AsOff_t(res, PyExc_ValueError);
635 Py_DECREF(res);
636 if (n < 0) {
637 if (!PyErr_Occurred())
638 PyErr_Format(PyExc_IOError,
Mark Dickinson889d96452009-11-24 20:51:48 +0000639 "Raw stream returned invalid position %" PY_PRIdOFF,
640 (PY_OFF_T_COMPAT)n);
Antoine Pitrou19690592009-06-12 20:14:08 +0000641 return -1;
642 }
643 self->abs_pos = n;
644 return n;
645}
646
647static int
648_buffered_init(buffered *self)
649{
650 Py_ssize_t n;
651 if (self->buffer_size <= 0) {
652 PyErr_SetString(PyExc_ValueError,
653 "buffer size must be strictly positive");
654 return -1;
655 }
656 if (self->buffer)
657 PyMem_Free(self->buffer);
658 self->buffer = PyMem_Malloc(self->buffer_size);
659 if (self->buffer == NULL) {
660 PyErr_NoMemory();
661 return -1;
662 }
663#ifdef WITH_THREAD
Antoine Pitrou607951d2010-08-01 16:57:17 +0000664 if (self->lock)
665 PyThread_free_lock(self->lock);
Antoine Pitrou19690592009-06-12 20:14:08 +0000666 self->lock = PyThread_allocate_lock();
667 if (self->lock == NULL) {
668 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
669 return -1;
670 }
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000671 self->owner = 0;
Antoine Pitrou19690592009-06-12 20:14:08 +0000672#endif
673 /* Find out whether buffer_size is a power of 2 */
674 /* XXX is this optimization useful? */
675 for (n = self->buffer_size - 1; n & 1; n >>= 1)
676 ;
677 if (n == 0)
678 self->buffer_mask = self->buffer_size - 1;
679 else
680 self->buffer_mask = 0;
681 if (_buffered_raw_tell(self) == -1)
682 PyErr_Clear();
683 return 0;
684}
685
686/*
687 * Shared methods and wrappers
688 */
689
690static PyObject *
691buffered_flush(buffered *self, PyObject *args)
692{
693 PyObject *res;
694
695 CHECK_INITIALIZED(self)
696 CHECK_CLOSED(self, "flush of closed file")
697
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000698 if (!ENTER_BUFFERED(self))
699 return NULL;
Antoine Pitrou19690592009-06-12 20:14:08 +0000700 res = _bufferedwriter_flush_unlocked(self, 0);
701 if (res != NULL && self->readable) {
702 /* Rewind the raw stream so that its position corresponds to
703 the current logical position. */
704 Py_off_t n;
705 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
706 if (n == -1)
707 Py_CLEAR(res);
708 _bufferedreader_reset_buf(self);
709 }
710 LEAVE_BUFFERED(self)
711
712 return res;
713}
714
715static PyObject *
716buffered_peek(buffered *self, PyObject *args)
717{
718 Py_ssize_t n = 0;
719 PyObject *res = NULL;
720
721 CHECK_INITIALIZED(self)
722 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
723 return NULL;
724 }
725
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000726 if (!ENTER_BUFFERED(self))
727 return NULL;
Antoine Pitrou19690592009-06-12 20:14:08 +0000728
729 if (self->writable) {
730 res = _bufferedwriter_flush_unlocked(self, 1);
731 if (res == NULL)
732 goto end;
733 Py_CLEAR(res);
734 }
735 res = _bufferedreader_peek_unlocked(self, n);
736
737end:
738 LEAVE_BUFFERED(self)
739 return res;
740}
741
742static PyObject *
743buffered_read(buffered *self, PyObject *args)
744{
745 Py_ssize_t n = -1;
746 PyObject *res;
747
748 CHECK_INITIALIZED(self)
Benjamin Petersonddd392c2009-12-13 19:19:07 +0000749 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
Antoine Pitrou19690592009-06-12 20:14:08 +0000750 return NULL;
751 }
752 if (n < -1) {
753 PyErr_SetString(PyExc_ValueError,
754 "read length must be positive or -1");
755 return NULL;
756 }
757
758 CHECK_CLOSED(self, "read of closed file")
759
760 if (n == -1) {
761 /* The number of bytes is unspecified, read until the end of stream */
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000762 if (!ENTER_BUFFERED(self))
763 return NULL;
Antoine Pitrou19690592009-06-12 20:14:08 +0000764 res = _bufferedreader_read_all(self);
765 LEAVE_BUFFERED(self)
766 }
767 else {
768 res = _bufferedreader_read_fast(self, n);
769 if (res == Py_None) {
770 Py_DECREF(res);
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000771 if (!ENTER_BUFFERED(self))
772 return NULL;
Antoine Pitrou19690592009-06-12 20:14:08 +0000773 res = _bufferedreader_read_generic(self, n);
774 LEAVE_BUFFERED(self)
775 }
776 }
777
778 return res;
779}
780
781static PyObject *
782buffered_read1(buffered *self, PyObject *args)
783{
784 Py_ssize_t n, have, r;
785 PyObject *res = NULL;
786
787 CHECK_INITIALIZED(self)
788 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
789 return NULL;
790 }
791
792 if (n < 0) {
793 PyErr_SetString(PyExc_ValueError,
794 "read length must be positive");
795 return NULL;
796 }
797 if (n == 0)
798 return PyBytes_FromStringAndSize(NULL, 0);
799
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000800 if (!ENTER_BUFFERED(self))
801 return NULL;
Antoine Pitrou19690592009-06-12 20:14:08 +0000802
803 if (self->writable) {
804 res = _bufferedwriter_flush_unlocked(self, 1);
805 if (res == NULL)
806 goto end;
807 Py_CLEAR(res);
808 }
809
810 /* Return up to n bytes. If at least one byte is buffered, we
811 only return buffered bytes. Otherwise, we do one raw read. */
812
813 /* XXX: this mimicks the io.py implementation but is probably wrong.
814 If we need to read from the raw stream, then we could actually read
815 all `n` bytes asked by the caller (and possibly more, so as to fill
816 our buffer for the next reads). */
817
818 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
819 if (have > 0) {
820 if (n > have)
821 n = have;
822 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
823 if (res == NULL)
824 goto end;
825 self->pos += n;
826 goto end;
827 }
828
829 /* Fill the buffer from the raw stream, and copy it to the result. */
830 _bufferedreader_reset_buf(self);
831 r = _bufferedreader_fill_buffer(self);
832 if (r == -1)
833 goto end;
834 if (r == -2)
835 r = 0;
836 if (n > r)
837 n = r;
838 res = PyBytes_FromStringAndSize(self->buffer, n);
839 if (res == NULL)
840 goto end;
841 self->pos = n;
842
843end:
844 LEAVE_BUFFERED(self)
845 return res;
846}
847
848static PyObject *
849buffered_readinto(buffered *self, PyObject *args)
850{
851 PyObject *res = NULL;
852
853 CHECK_INITIALIZED(self)
854
855 /* TODO: use raw.readinto() instead! */
856 if (self->writable) {
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000857 if (!ENTER_BUFFERED(self))
858 return NULL;
Antoine Pitrou19690592009-06-12 20:14:08 +0000859 res = _bufferedwriter_flush_unlocked(self, 0);
860 LEAVE_BUFFERED(self)
861 if (res == NULL)
862 goto end;
863 Py_DECREF(res);
864 }
865 res = bufferediobase_readinto((PyObject *)self, args);
866
867end:
868 return res;
869}
870
871static PyObject *
872_buffered_readline(buffered *self, Py_ssize_t limit)
873{
874 PyObject *res = NULL;
875 PyObject *chunks = NULL;
876 Py_ssize_t n, written = 0;
877 const char *start, *s, *end;
878
879 CHECK_CLOSED(self, "readline of closed file")
880
881 /* First, try to find a line in the buffer. This can run unlocked because
882 the calls to the C API are simple enough that they can't trigger
883 any thread switch. */
884 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
885 if (limit >= 0 && n > limit)
886 n = limit;
887 start = self->buffer + self->pos;
888 s = memchr(start, '\n', n);
889 if (s != NULL) {
890 res = PyBytes_FromStringAndSize(start, s - start + 1);
891 if (res != NULL)
892 self->pos += s - start + 1;
893 goto end_unlocked;
894 }
895 if (n == limit) {
896 res = PyBytes_FromStringAndSize(start, n);
897 if (res != NULL)
898 self->pos += n;
899 goto end_unlocked;
900 }
901
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000902 if (!ENTER_BUFFERED(self))
903 goto end_unlocked;
Antoine Pitrou19690592009-06-12 20:14:08 +0000904
905 /* Now we try to get some more from the raw stream */
906 if (self->writable) {
907 res = _bufferedwriter_flush_unlocked(self, 1);
908 if (res == NULL)
909 goto end;
910 Py_CLEAR(res);
911 }
912 chunks = PyList_New(0);
913 if (chunks == NULL)
914 goto end;
915 if (n > 0) {
916 res = PyBytes_FromStringAndSize(start, n);
917 if (res == NULL)
918 goto end;
919 if (PyList_Append(chunks, res) < 0) {
920 Py_CLEAR(res);
921 goto end;
922 }
923 Py_CLEAR(res);
924 written += n;
925 if (limit >= 0)
926 limit -= n;
927 }
928
929 for (;;) {
930 _bufferedreader_reset_buf(self);
931 n = _bufferedreader_fill_buffer(self);
932 if (n == -1)
933 goto end;
934 if (n <= 0)
935 break;
936 if (limit >= 0 && n > limit)
937 n = limit;
938 start = self->buffer;
939 end = start + n;
940 s = start;
941 while (s < end) {
942 if (*s++ == '\n') {
943 res = PyBytes_FromStringAndSize(start, s - start);
944 if (res == NULL)
945 goto end;
946 self->pos = s - start;
947 goto found;
948 }
949 }
950 res = PyBytes_FromStringAndSize(start, n);
951 if (res == NULL)
952 goto end;
953 if (n == limit) {
954 self->pos = n;
955 break;
956 }
957 if (PyList_Append(chunks, res) < 0) {
958 Py_CLEAR(res);
959 goto end;
960 }
961 Py_CLEAR(res);
962 written += n;
963 if (limit >= 0)
964 limit -= n;
965 }
966found:
967 if (res != NULL && PyList_Append(chunks, res) < 0) {
968 Py_CLEAR(res);
969 goto end;
970 }
971 Py_CLEAR(res);
972 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
973
974end:
975 LEAVE_BUFFERED(self)
976end_unlocked:
977 Py_XDECREF(chunks);
978 return res;
979}
980
981static PyObject *
982buffered_readline(buffered *self, PyObject *args)
983{
Antoine Pitrou19690592009-06-12 20:14:08 +0000984 Py_ssize_t limit = -1;
985
986 CHECK_INITIALIZED(self)
Benjamin Petersonddd392c2009-12-13 19:19:07 +0000987 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
Antoine Pitrou19690592009-06-12 20:14:08 +0000988 return NULL;
Antoine Pitrou19690592009-06-12 20:14:08 +0000989 return _buffered_readline(self, limit);
990}
991
992
993static PyObject *
994buffered_tell(buffered *self, PyObject *args)
995{
996 Py_off_t pos;
997
998 CHECK_INITIALIZED(self)
999 pos = _buffered_raw_tell(self);
1000 if (pos == -1)
1001 return NULL;
1002 pos -= RAW_OFFSET(self);
1003 /* TODO: sanity check (pos >= 0) */
1004 return PyLong_FromOff_t(pos);
1005}
1006
1007static PyObject *
1008buffered_seek(buffered *self, PyObject *args)
1009{
1010 Py_off_t target, n;
1011 int whence = 0;
1012 PyObject *targetobj, *res = NULL;
1013
1014 CHECK_INITIALIZED(self)
1015 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
1016 return NULL;
1017 }
1018 if (whence < 0 || whence > 2) {
1019 PyErr_Format(PyExc_ValueError,
1020 "whence must be between 0 and 2, not %d", whence);
1021 return NULL;
1022 }
1023
1024 CHECK_CLOSED(self, "seek of closed file")
1025
1026 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1027 if (target == -1 && PyErr_Occurred())
1028 return NULL;
1029
1030 if (whence != 2 && self->readable) {
1031 Py_off_t current, avail;
1032 /* Check if seeking leaves us inside the current buffer,
1033 so as to return quickly if possible. Also, we needn't take the
1034 lock in this fast path.
1035 Don't know how to do that when whence == 2, though. */
1036 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1037 state at this point. */
1038 current = RAW_TELL(self);
1039 avail = READAHEAD(self);
1040 if (avail > 0) {
1041 Py_off_t offset;
1042 if (whence == 0)
1043 offset = target - (current - RAW_OFFSET(self));
1044 else
1045 offset = target;
1046 if (offset >= -self->pos && offset <= avail) {
1047 self->pos += offset;
1048 return PyLong_FromOff_t(current - avail + offset);
1049 }
1050 }
1051 }
1052
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +00001053 if (!ENTER_BUFFERED(self))
1054 return NULL;
Antoine Pitrou19690592009-06-12 20:14:08 +00001055
1056 /* Fallback: invoke raw seek() method and clear buffer */
1057 if (self->writable) {
1058 res = _bufferedwriter_flush_unlocked(self, 0);
1059 if (res == NULL)
1060 goto end;
1061 Py_CLEAR(res);
1062 _bufferedwriter_reset_buf(self);
1063 }
1064
1065 /* TODO: align on block boundary and read buffer if needed? */
1066 if (whence == 1)
1067 target -= RAW_OFFSET(self);
1068 n = _buffered_raw_seek(self, target, whence);
1069 if (n == -1)
1070 goto end;
1071 self->raw_pos = -1;
1072 res = PyLong_FromOff_t(n);
1073 if (res != NULL && self->readable)
1074 _bufferedreader_reset_buf(self);
1075
1076end:
1077 LEAVE_BUFFERED(self)
1078 return res;
1079}
1080
1081static PyObject *
1082buffered_truncate(buffered *self, PyObject *args)
1083{
1084 PyObject *pos = Py_None;
1085 PyObject *res = NULL;
1086
1087 CHECK_INITIALIZED(self)
1088 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1089 return NULL;
1090 }
1091
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +00001092 if (!ENTER_BUFFERED(self))
1093 return NULL;
Antoine Pitrou19690592009-06-12 20:14:08 +00001094
1095 if (self->writable) {
1096 res = _bufferedwriter_flush_unlocked(self, 0);
1097 if (res == NULL)
1098 goto end;
1099 Py_CLEAR(res);
1100 }
1101 if (self->readable) {
1102 if (pos == Py_None) {
1103 /* Rewind the raw stream so that its position corresponds to
1104 the current logical position. */
1105 if (_buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)
1106 goto end;
1107 }
1108 _bufferedreader_reset_buf(self);
1109 }
1110 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1111 if (res == NULL)
1112 goto end;
1113 /* Reset cached position */
1114 if (_buffered_raw_tell(self) == -1)
1115 PyErr_Clear();
1116
1117end:
1118 LEAVE_BUFFERED(self)
1119 return res;
1120}
1121
1122static PyObject *
1123buffered_iternext(buffered *self)
1124{
1125 PyObject *line;
1126 PyTypeObject *tp;
1127
1128 CHECK_INITIALIZED(self);
1129
1130 tp = Py_TYPE(self);
1131 if (tp == &PyBufferedReader_Type ||
1132 tp == &PyBufferedRandom_Type) {
1133 /* Skip method call overhead for speed */
1134 line = _buffered_readline(self, -1);
1135 }
1136 else {
1137 line = PyObject_CallMethodObjArgs((PyObject *)self,
1138 _PyIO_str_readline, NULL);
1139 if (line && !PyBytes_Check(line)) {
1140 PyErr_Format(PyExc_IOError,
1141 "readline() should have returned a bytes object, "
1142 "not '%.200s'", Py_TYPE(line)->tp_name);
1143 Py_DECREF(line);
1144 return NULL;
1145 }
1146 }
1147
1148 if (line == NULL)
1149 return NULL;
1150
1151 if (PyBytes_GET_SIZE(line) == 0) {
1152 /* Reached EOF or would have blocked */
1153 Py_DECREF(line);
1154 return NULL;
1155 }
1156
1157 return line;
1158}
1159
1160static PyObject *
1161buffered_repr(buffered *self)
1162{
1163 PyObject *nameobj, *res;
1164
1165 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1166 if (nameobj == NULL) {
1167 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1168 PyErr_Clear();
1169 else
1170 return NULL;
1171 res = PyString_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1172 }
1173 else {
1174 PyObject *repr = PyObject_Repr(nameobj);
1175 Py_DECREF(nameobj);
1176 if (repr == NULL)
1177 return NULL;
1178 res = PyString_FromFormat("<%s name=%s>",
1179 Py_TYPE(self)->tp_name,
1180 PyString_AS_STRING(repr));
1181 Py_DECREF(repr);
1182 }
1183 return res;
1184}
1185
1186/*
1187 * class BufferedReader
1188 */
1189
1190PyDoc_STRVAR(bufferedreader_doc,
1191 "Create a new buffered reader using the given readable raw IO object.");
1192
1193static void _bufferedreader_reset_buf(buffered *self)
1194{
1195 self->read_end = -1;
1196}
1197
1198static int
1199bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
1200{
1201 char *kwlist[] = {"raw", "buffer_size", NULL};
1202 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1203 PyObject *raw;
1204
1205 self->ok = 0;
1206 self->detached = 0;
1207
1208 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1209 &raw, &buffer_size)) {
1210 return -1;
1211 }
1212
1213 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
1214 return -1;
1215
1216 Py_CLEAR(self->raw);
1217 Py_INCREF(raw);
1218 self->raw = raw;
1219 self->buffer_size = buffer_size;
1220 self->readable = 1;
1221 self->writable = 0;
1222
1223 if (_buffered_init(self) < 0)
1224 return -1;
1225 _bufferedreader_reset_buf(self);
1226
1227 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1228 Py_TYPE(raw) == &PyFileIO_Type);
1229
1230 self->ok = 1;
1231 return 0;
1232}
1233
1234static Py_ssize_t
1235_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
1236{
1237 Py_buffer buf;
1238 PyObject *memobj, *res;
1239 Py_ssize_t n;
1240 /* NOTE: the buffer needn't be released as its object is NULL. */
1241 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1242 return -1;
1243 memobj = PyMemoryView_FromBuffer(&buf);
1244 if (memobj == NULL)
1245 return -1;
1246 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1247 Py_DECREF(memobj);
1248 if (res == NULL)
1249 return -1;
1250 if (res == Py_None) {
1251 /* Non-blocking stream would have blocked. Special return code! */
1252 Py_DECREF(res);
1253 return -2;
1254 }
1255 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1256 Py_DECREF(res);
1257 if (n < 0 || n > len) {
1258 PyErr_Format(PyExc_IOError,
1259 "raw readinto() returned invalid length %zd "
1260 "(should have been between 0 and %zd)", n, len);
1261 return -1;
1262 }
1263 if (n > 0 && self->abs_pos != -1)
1264 self->abs_pos += n;
1265 return n;
1266}
1267
1268static Py_ssize_t
1269_bufferedreader_fill_buffer(buffered *self)
1270{
1271 Py_ssize_t start, len, n;
1272 if (VALID_READ_BUFFER(self))
1273 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1274 else
1275 start = 0;
1276 len = self->buffer_size - start;
1277 n = _bufferedreader_raw_read(self, self->buffer + start, len);
1278 if (n <= 0)
1279 return n;
1280 self->read_end = start + n;
1281 self->raw_pos = start + n;
1282 return n;
1283}
1284
1285static PyObject *
1286_bufferedreader_read_all(buffered *self)
1287{
1288 Py_ssize_t current_size;
1289 PyObject *res, *data = NULL;
1290 PyObject *chunks = PyList_New(0);
1291
1292 if (chunks == NULL)
1293 return NULL;
1294
1295 /* First copy what we have in the current buffer. */
1296 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1297 if (current_size) {
1298 data = PyBytes_FromStringAndSize(
1299 self->buffer + self->pos, current_size);
1300 if (data == NULL) {
1301 Py_DECREF(chunks);
1302 return NULL;
1303 }
1304 }
1305 _bufferedreader_reset_buf(self);
1306 /* We're going past the buffer's bounds, flush it */
1307 if (self->writable) {
1308 res = _bufferedwriter_flush_unlocked(self, 1);
1309 if (res == NULL) {
1310 Py_DECREF(chunks);
1311 return NULL;
1312 }
1313 Py_CLEAR(res);
1314 }
1315 while (1) {
1316 if (data) {
1317 if (PyList_Append(chunks, data) < 0) {
1318 Py_DECREF(data);
1319 Py_DECREF(chunks);
1320 return NULL;
1321 }
1322 Py_DECREF(data);
1323 }
1324
1325 /* Read until EOF or until read() would block. */
1326 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1327 if (data == NULL) {
1328 Py_DECREF(chunks);
1329 return NULL;
1330 }
1331 if (data != Py_None && !PyBytes_Check(data)) {
1332 Py_DECREF(data);
1333 Py_DECREF(chunks);
1334 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1335 return NULL;
1336 }
1337 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1338 if (current_size == 0) {
1339 Py_DECREF(chunks);
1340 return data;
1341 }
1342 else {
1343 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1344 Py_DECREF(data);
1345 Py_DECREF(chunks);
1346 return res;
1347 }
1348 }
1349 current_size += PyBytes_GET_SIZE(data);
1350 if (self->abs_pos != -1)
1351 self->abs_pos += PyBytes_GET_SIZE(data);
1352 }
1353}
1354
1355/* Read n bytes from the buffer if it can, otherwise return None.
1356 This function is simple enough that it can run unlocked. */
1357static PyObject *
1358_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
1359{
1360 Py_ssize_t current_size;
1361
1362 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1363 if (n <= current_size) {
1364 /* Fast path: the data to read is fully buffered. */
1365 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1366 if (res != NULL)
1367 self->pos += n;
1368 return res;
1369 }
1370 Py_RETURN_NONE;
1371}
1372
1373/* Generic read function: read from the stream until enough bytes are read,
1374 * or until an EOF occurs or until read() would block.
1375 */
1376static PyObject *
1377_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
1378{
1379 PyObject *res = NULL;
1380 Py_ssize_t current_size, remaining, written;
1381 char *out;
1382
1383 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1384 if (n <= current_size)
1385 return _bufferedreader_read_fast(self, n);
1386
1387 res = PyBytes_FromStringAndSize(NULL, n);
1388 if (res == NULL)
1389 goto error;
1390 out = PyBytes_AS_STRING(res);
1391 remaining = n;
1392 written = 0;
1393 if (current_size > 0) {
1394 memcpy(out, self->buffer + self->pos, current_size);
1395 remaining -= current_size;
1396 written += current_size;
1397 }
1398 _bufferedreader_reset_buf(self);
1399 while (remaining > 0) {
1400 /* We want to read a whole block at the end into buffer.
1401 If we had readv() we could do this in one pass. */
1402 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1403 if (r == 0)
1404 break;
1405 r = _bufferedreader_raw_read(self, out + written, r);
1406 if (r == -1)
1407 goto error;
1408 if (r == 0 || r == -2) {
1409 /* EOF occurred or read() would block. */
1410 if (r == 0 || written > 0) {
1411 if (_PyBytes_Resize(&res, written))
1412 goto error;
1413 return res;
1414 }
1415 Py_DECREF(res);
1416 Py_INCREF(Py_None);
1417 return Py_None;
1418 }
1419 remaining -= r;
1420 written += r;
1421 }
1422 assert(remaining <= self->buffer_size);
1423 self->pos = 0;
1424 self->raw_pos = 0;
1425 self->read_end = 0;
Antoine Pitroucb4f47c2010-08-11 13:40:17 +00001426 /* NOTE: when the read is satisfied, we avoid issuing any additional
1427 reads, which could block indefinitely (e.g. on a socket).
1428 See issue #9550. */
1429 while (remaining > 0 && self->read_end < self->buffer_size) {
Antoine Pitrou19690592009-06-12 20:14:08 +00001430 Py_ssize_t r = _bufferedreader_fill_buffer(self);
1431 if (r == -1)
1432 goto error;
1433 if (r == 0 || r == -2) {
1434 /* EOF occurred or read() would block. */
1435 if (r == 0 || written > 0) {
1436 if (_PyBytes_Resize(&res, written))
1437 goto error;
1438 return res;
1439 }
1440 Py_DECREF(res);
1441 Py_INCREF(Py_None);
1442 return Py_None;
1443 }
1444 if (remaining > r) {
1445 memcpy(out + written, self->buffer + self->pos, r);
1446 written += r;
1447 self->pos += r;
1448 remaining -= r;
1449 }
1450 else if (remaining > 0) {
1451 memcpy(out + written, self->buffer + self->pos, remaining);
1452 written += remaining;
1453 self->pos += remaining;
1454 remaining = 0;
1455 }
1456 if (remaining == 0)
1457 break;
1458 }
1459
1460 return res;
1461
1462error:
1463 Py_XDECREF(res);
1464 return NULL;
1465}
1466
1467static PyObject *
1468_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
1469{
1470 Py_ssize_t have, r;
1471
1472 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1473 /* Constraints:
1474 1. we don't want to advance the file position.
1475 2. we don't want to lose block alignment, so we can't shift the buffer
1476 to make some place.
1477 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1478 */
1479 if (have > 0) {
1480 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1481 }
1482
1483 /* Fill the buffer from the raw stream, and copy it to the result. */
1484 _bufferedreader_reset_buf(self);
1485 r = _bufferedreader_fill_buffer(self);
1486 if (r == -1)
1487 return NULL;
1488 if (r == -2)
1489 r = 0;
1490 self->pos = 0;
1491 return PyBytes_FromStringAndSize(self->buffer, r);
1492}
1493
1494static PyMethodDef bufferedreader_methods[] = {
1495 /* BufferedIOMixin methods */
1496 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1497 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1498 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1499 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1500 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1501 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1502 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1503 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
1504
1505 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1506 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1507 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
1508 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1509 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1510 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1511 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1512 {NULL, NULL}
1513};
1514
1515static PyMemberDef bufferedreader_members[] = {
1516 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
1517 {NULL}
1518};
1519
1520static PyGetSetDef bufferedreader_getset[] = {
1521 {"closed", (getter)buffered_closed_get, NULL, NULL},
1522 {"name", (getter)buffered_name_get, NULL, NULL},
1523 {"mode", (getter)buffered_mode_get, NULL, NULL},
1524 {NULL}
1525};
1526
1527
1528PyTypeObject PyBufferedReader_Type = {
1529 PyVarObject_HEAD_INIT(NULL, 0)
1530 "_io.BufferedReader", /*tp_name*/
1531 sizeof(buffered), /*tp_basicsize*/
1532 0, /*tp_itemsize*/
1533 (destructor)buffered_dealloc, /*tp_dealloc*/
1534 0, /*tp_print*/
1535 0, /*tp_getattr*/
1536 0, /*tp_setattr*/
1537 0, /*tp_compare */
1538 (reprfunc)buffered_repr, /*tp_repr*/
1539 0, /*tp_as_number*/
1540 0, /*tp_as_sequence*/
1541 0, /*tp_as_mapping*/
1542 0, /*tp_hash */
1543 0, /*tp_call*/
1544 0, /*tp_str*/
1545 0, /*tp_getattro*/
1546 0, /*tp_setattro*/
1547 0, /*tp_as_buffer*/
1548 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1549 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1550 bufferedreader_doc, /* tp_doc */
1551 (traverseproc)buffered_traverse, /* tp_traverse */
1552 (inquiry)buffered_clear, /* tp_clear */
1553 0, /* tp_richcompare */
1554 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
1555 0, /* tp_iter */
1556 (iternextfunc)buffered_iternext, /* tp_iternext */
1557 bufferedreader_methods, /* tp_methods */
1558 bufferedreader_members, /* tp_members */
1559 bufferedreader_getset, /* tp_getset */
1560 0, /* tp_base */
1561 0, /* tp_dict */
1562 0, /* tp_descr_get */
1563 0, /* tp_descr_set */
1564 offsetof(buffered, dict), /* tp_dictoffset */
1565 (initproc)bufferedreader_init, /* tp_init */
1566 0, /* tp_alloc */
1567 PyType_GenericNew, /* tp_new */
1568};
1569
1570
1571
1572static int
1573complain_about_max_buffer_size(void)
1574{
1575 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1576 "max_buffer_size is deprecated", 1) < 0)
1577 return 0;
1578 return 1;
1579}
1580
1581/*
1582 * class BufferedWriter
1583 */
1584PyDoc_STRVAR(bufferedwriter_doc,
1585 "A buffer for a writeable sequential RawIO object.\n"
1586 "\n"
1587 "The constructor creates a BufferedWriter for the given writeable raw\n"
1588 "stream. If the buffer_size is not given, it defaults to\n"
1589 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1590 );
1591
1592static void
1593_bufferedwriter_reset_buf(buffered *self)
1594{
1595 self->write_pos = 0;
1596 self->write_end = -1;
1597}
1598
1599static int
1600bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
1601{
1602 /* TODO: properly deprecate max_buffer_size */
1603 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1604 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1605 Py_ssize_t max_buffer_size = -234;
1606 PyObject *raw;
1607
1608 self->ok = 0;
1609 self->detached = 0;
1610
1611 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1612 &raw, &buffer_size, &max_buffer_size)) {
1613 return -1;
1614 }
1615
1616 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1617 return -1;
1618
1619 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
1620 return -1;
1621
1622 Py_CLEAR(self->raw);
1623 Py_INCREF(raw);
1624 self->raw = raw;
1625 self->readable = 0;
1626 self->writable = 1;
1627
1628 self->buffer_size = buffer_size;
1629 if (_buffered_init(self) < 0)
1630 return -1;
1631 _bufferedwriter_reset_buf(self);
1632 self->pos = 0;
1633
1634 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1635 Py_TYPE(raw) == &PyFileIO_Type);
1636
1637 self->ok = 1;
1638 return 0;
1639}
1640
1641static Py_ssize_t
1642_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
1643{
1644 Py_buffer buf;
1645 PyObject *memobj, *res;
1646 Py_ssize_t n;
1647 /* NOTE: the buffer needn't be released as its object is NULL. */
1648 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1649 return -1;
1650 memobj = PyMemoryView_FromBuffer(&buf);
1651 if (memobj == NULL)
1652 return -1;
1653 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1654 Py_DECREF(memobj);
1655 if (res == NULL)
1656 return -1;
1657 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1658 Py_DECREF(res);
1659 if (n < 0 || n > len) {
1660 PyErr_Format(PyExc_IOError,
1661 "raw write() returned invalid length %zd "
1662 "(should have been between 0 and %zd)", n, len);
1663 return -1;
1664 }
1665 if (n > 0 && self->abs_pos != -1)
1666 self->abs_pos += n;
1667 return n;
1668}
1669
1670/* `restore_pos` is 1 if we need to restore the raw stream position at
1671 the end, 0 otherwise. */
1672static PyObject *
1673_bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
1674{
1675 Py_ssize_t written = 0;
1676 Py_off_t n, rewind;
1677
1678 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1679 goto end;
1680 /* First, rewind */
1681 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1682 if (rewind != 0) {
1683 n = _buffered_raw_seek(self, -rewind, 1);
1684 if (n < 0) {
1685 goto error;
1686 }
1687 self->raw_pos -= rewind;
1688 }
1689 while (self->write_pos < self->write_end) {
1690 n = _bufferedwriter_raw_write(self,
1691 self->buffer + self->write_pos,
1692 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1693 Py_off_t, Py_ssize_t));
1694 if (n == -1) {
1695 Py_ssize_t *w = _buffered_check_blocking_error();
1696 if (w == NULL)
1697 goto error;
1698 self->write_pos += *w;
1699 self->raw_pos = self->write_pos;
1700 written += *w;
1701 *w = written;
1702 /* Already re-raised */
1703 goto error;
1704 }
1705 self->write_pos += n;
1706 self->raw_pos = self->write_pos;
1707 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
Antoine Pitrou3ebaed62010-08-21 19:17:25 +00001708 /* Partial writes can return successfully when interrupted by a
1709 signal (see write(2)). We must run signal handlers before
1710 blocking another time, possibly indefinitely. */
1711 if (PyErr_CheckSignals() < 0)
1712 goto error;
Antoine Pitrou19690592009-06-12 20:14:08 +00001713 }
1714
1715 if (restore_pos) {
1716 Py_off_t forward = rewind - written;
1717 if (forward != 0) {
1718 n = _buffered_raw_seek(self, forward, 1);
1719 if (n < 0) {
1720 goto error;
1721 }
1722 self->raw_pos += forward;
1723 }
1724 }
1725 _bufferedwriter_reset_buf(self);
1726
1727end:
1728 Py_RETURN_NONE;
1729
1730error:
1731 return NULL;
1732}
1733
1734static PyObject *
1735bufferedwriter_write(buffered *self, PyObject *args)
1736{
1737 PyObject *res = NULL;
1738 Py_buffer buf;
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001739 Py_ssize_t written, avail, remaining;
1740 Py_off_t offset;
Antoine Pitrou19690592009-06-12 20:14:08 +00001741
1742 CHECK_INITIALIZED(self)
1743 if (!PyArg_ParseTuple(args, "s*:write", &buf)) {
1744 return NULL;
1745 }
1746
1747 if (IS_CLOSED(self)) {
1748 PyErr_SetString(PyExc_ValueError, "write to closed file");
1749 PyBuffer_Release(&buf);
1750 return NULL;
1751 }
1752
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +00001753 if (!ENTER_BUFFERED(self)) {
1754 PyBuffer_Release(&buf);
1755 return NULL;
1756 }
Antoine Pitrou19690592009-06-12 20:14:08 +00001757
1758 /* Fast path: the data to write can be fully buffered. */
1759 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1760 self->pos = 0;
1761 self->raw_pos = 0;
1762 }
1763 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1764 if (buf.len <= avail) {
1765 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1766 if (!VALID_WRITE_BUFFER(self)) {
1767 self->write_pos = self->pos;
1768 }
1769 ADJUST_POSITION(self, self->pos + buf.len);
1770 if (self->pos > self->write_end)
1771 self->write_end = self->pos;
1772 written = buf.len;
1773 goto end;
1774 }
1775
1776 /* First write the current buffer */
1777 res = _bufferedwriter_flush_unlocked(self, 0);
1778 if (res == NULL) {
1779 Py_ssize_t *w = _buffered_check_blocking_error();
1780 if (w == NULL)
1781 goto error;
1782 if (self->readable)
1783 _bufferedreader_reset_buf(self);
1784 /* Make some place by shifting the buffer. */
1785 assert(VALID_WRITE_BUFFER(self));
1786 memmove(self->buffer, self->buffer + self->write_pos,
1787 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1788 Py_off_t, Py_ssize_t));
1789 self->write_end -= self->write_pos;
1790 self->raw_pos -= self->write_pos;
1791 self->pos -= self->write_pos;
1792 self->write_pos = 0;
1793 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1794 Py_off_t, Py_ssize_t);
1795 if (buf.len <= avail) {
1796 /* Everything can be buffered */
1797 PyErr_Clear();
1798 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1799 self->write_end += buf.len;
1800 written = buf.len;
1801 goto end;
1802 }
1803 /* Buffer as much as possible. */
1804 memcpy(self->buffer + self->write_end, buf.buf, avail);
1805 self->write_end += avail;
1806 /* Already re-raised */
1807 *w = avail;
1808 goto error;
1809 }
1810 Py_CLEAR(res);
1811
Antoine Pitrou20e1f932009-08-06 20:18:29 +00001812 /* Adjust the raw stream position if it is away from the logical stream
1813 position. This happens if the read buffer has been filled but not
1814 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1815 the raw stream by itself).
1816 Fixes issue #6629.
1817 */
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001818 offset = RAW_OFFSET(self);
1819 if (offset != 0) {
1820 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitrou20e1f932009-08-06 20:18:29 +00001821 goto error;
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001822 self->raw_pos -= offset;
Antoine Pitrou20e1f932009-08-06 20:18:29 +00001823 }
1824
Antoine Pitrou19690592009-06-12 20:14:08 +00001825 /* Then write buf itself. At this point the buffer has been emptied. */
1826 remaining = buf.len;
1827 written = 0;
1828 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001829 Py_ssize_t n = _bufferedwriter_raw_write(
Antoine Pitrou19690592009-06-12 20:14:08 +00001830 self, (char *) buf.buf + written, buf.len - written);
1831 if (n == -1) {
1832 Py_ssize_t *w = _buffered_check_blocking_error();
1833 if (w == NULL)
1834 goto error;
1835 written += *w;
1836 remaining -= *w;
1837 if (remaining > self->buffer_size) {
1838 /* Can't buffer everything, still buffer as much as possible */
1839 memcpy(self->buffer,
1840 (char *) buf.buf + written, self->buffer_size);
1841 self->raw_pos = 0;
1842 ADJUST_POSITION(self, self->buffer_size);
1843 self->write_end = self->buffer_size;
1844 *w = written + self->buffer_size;
1845 /* Already re-raised */
1846 goto error;
1847 }
1848 PyErr_Clear();
1849 break;
1850 }
1851 written += n;
1852 remaining -= n;
Antoine Pitrou3ebaed62010-08-21 19:17:25 +00001853 /* Partial writes can return successfully when interrupted by a
1854 signal (see write(2)). We must run signal handlers before
1855 blocking another time, possibly indefinitely. */
1856 if (PyErr_CheckSignals() < 0)
1857 goto error;
Antoine Pitrou19690592009-06-12 20:14:08 +00001858 }
1859 if (self->readable)
1860 _bufferedreader_reset_buf(self);
1861 if (remaining > 0) {
1862 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1863 written += remaining;
1864 }
1865 self->write_pos = 0;
1866 /* TODO: sanity check (remaining >= 0) */
1867 self->write_end = remaining;
1868 ADJUST_POSITION(self, remaining);
1869 self->raw_pos = 0;
1870
1871end:
1872 res = PyLong_FromSsize_t(written);
1873
1874error:
1875 LEAVE_BUFFERED(self)
1876 PyBuffer_Release(&buf);
1877 return res;
1878}
1879
1880static PyMethodDef bufferedwriter_methods[] = {
1881 /* BufferedIOMixin methods */
1882 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1883 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1884 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1885 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1886 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1887 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1888 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
1889
1890 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1891 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1892 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1893 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1894 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1895 {NULL, NULL}
1896};
1897
1898static PyMemberDef bufferedwriter_members[] = {
1899 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
1900 {NULL}
1901};
1902
1903static PyGetSetDef bufferedwriter_getset[] = {
1904 {"closed", (getter)buffered_closed_get, NULL, NULL},
1905 {"name", (getter)buffered_name_get, NULL, NULL},
1906 {"mode", (getter)buffered_mode_get, NULL, NULL},
1907 {NULL}
1908};
1909
1910
1911PyTypeObject PyBufferedWriter_Type = {
1912 PyVarObject_HEAD_INIT(NULL, 0)
1913 "_io.BufferedWriter", /*tp_name*/
1914 sizeof(buffered), /*tp_basicsize*/
1915 0, /*tp_itemsize*/
1916 (destructor)buffered_dealloc, /*tp_dealloc*/
1917 0, /*tp_print*/
1918 0, /*tp_getattr*/
1919 0, /*tp_setattr*/
1920 0, /*tp_compare */
1921 (reprfunc)buffered_repr, /*tp_repr*/
1922 0, /*tp_as_number*/
1923 0, /*tp_as_sequence*/
1924 0, /*tp_as_mapping*/
1925 0, /*tp_hash */
1926 0, /*tp_call*/
1927 0, /*tp_str*/
1928 0, /*tp_getattro*/
1929 0, /*tp_setattro*/
1930 0, /*tp_as_buffer*/
1931 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1932 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1933 bufferedwriter_doc, /* tp_doc */
1934 (traverseproc)buffered_traverse, /* tp_traverse */
1935 (inquiry)buffered_clear, /* tp_clear */
1936 0, /* tp_richcompare */
1937 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
1938 0, /* tp_iter */
1939 0, /* tp_iternext */
1940 bufferedwriter_methods, /* tp_methods */
1941 bufferedwriter_members, /* tp_members */
1942 bufferedwriter_getset, /* tp_getset */
1943 0, /* tp_base */
1944 0, /* tp_dict */
1945 0, /* tp_descr_get */
1946 0, /* tp_descr_set */
1947 offsetof(buffered, dict), /* tp_dictoffset */
1948 (initproc)bufferedwriter_init, /* tp_init */
1949 0, /* tp_alloc */
1950 PyType_GenericNew, /* tp_new */
1951};
1952
1953
1954
1955/*
1956 * BufferedRWPair
1957 */
1958
1959PyDoc_STRVAR(bufferedrwpair_doc,
1960 "A buffered reader and writer object together.\n"
1961 "\n"
1962 "A buffered reader object and buffered writer object put together to\n"
1963 "form a sequential IO object that can read and write. This is typically\n"
1964 "used with a socket or two-way pipe.\n"
1965 "\n"
1966 "reader and writer are RawIOBase objects that are readable and\n"
1967 "writeable respectively. If the buffer_size is omitted it defaults to\n"
1968 "DEFAULT_BUFFER_SIZE.\n"
1969 );
1970
1971/* XXX The usefulness of this (compared to having two separate IO objects) is
1972 * questionable.
1973 */
1974
1975typedef struct {
1976 PyObject_HEAD
1977 buffered *reader;
1978 buffered *writer;
1979 PyObject *dict;
1980 PyObject *weakreflist;
1981} rwpair;
1982
1983static int
1984bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
1985{
1986 PyObject *reader, *writer;
1987 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1988 Py_ssize_t max_buffer_size = -234;
1989
1990 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1991 &buffer_size, &max_buffer_size)) {
1992 return -1;
1993 }
1994
1995 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1996 return -1;
1997
1998 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
1999 return -1;
2000 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
2001 return -1;
2002
2003 self->reader = (buffered *) PyObject_CallFunction(
2004 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
2005 if (self->reader == NULL)
2006 return -1;
2007
2008 self->writer = (buffered *) PyObject_CallFunction(
2009 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
2010 if (self->writer == NULL) {
2011 Py_CLEAR(self->reader);
2012 return -1;
2013 }
2014
2015 return 0;
2016}
2017
2018static int
2019bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
2020{
2021 Py_VISIT(self->dict);
2022 return 0;
2023}
2024
2025static int
2026bufferedrwpair_clear(rwpair *self)
2027{
2028 Py_CLEAR(self->reader);
2029 Py_CLEAR(self->writer);
2030 Py_CLEAR(self->dict);
2031 return 0;
2032}
2033
2034static void
2035bufferedrwpair_dealloc(rwpair *self)
2036{
2037 _PyObject_GC_UNTRACK(self);
2038 Py_CLEAR(self->reader);
2039 Py_CLEAR(self->writer);
2040 Py_CLEAR(self->dict);
2041 Py_TYPE(self)->tp_free((PyObject *) self);
2042}
2043
2044static PyObject *
2045_forward_call(buffered *self, const char *name, PyObject *args)
2046{
2047 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
2048 PyObject *ret;
2049
2050 if (func == NULL) {
2051 PyErr_SetString(PyExc_AttributeError, name);
2052 return NULL;
2053 }
2054
2055 ret = PyObject_CallObject(func, args);
2056 Py_DECREF(func);
2057 return ret;
2058}
2059
2060static PyObject *
2061bufferedrwpair_read(rwpair *self, PyObject *args)
2062{
2063 return _forward_call(self->reader, "read", args);
2064}
2065
2066static PyObject *
2067bufferedrwpair_peek(rwpair *self, PyObject *args)
2068{
2069 return _forward_call(self->reader, "peek", args);
2070}
2071
2072static PyObject *
2073bufferedrwpair_read1(rwpair *self, PyObject *args)
2074{
2075 return _forward_call(self->reader, "read1", args);
2076}
2077
2078static PyObject *
2079bufferedrwpair_readinto(rwpair *self, PyObject *args)
2080{
2081 return _forward_call(self->reader, "readinto", args);
2082}
2083
2084static PyObject *
2085bufferedrwpair_write(rwpair *self, PyObject *args)
2086{
2087 return _forward_call(self->writer, "write", args);
2088}
2089
2090static PyObject *
2091bufferedrwpair_flush(rwpair *self, PyObject *args)
2092{
2093 return _forward_call(self->writer, "flush", args);
2094}
2095
2096static PyObject *
2097bufferedrwpair_readable(rwpair *self, PyObject *args)
2098{
2099 return _forward_call(self->reader, "readable", args);
2100}
2101
2102static PyObject *
2103bufferedrwpair_writable(rwpair *self, PyObject *args)
2104{
2105 return _forward_call(self->writer, "writable", args);
2106}
2107
2108static PyObject *
2109bufferedrwpair_close(rwpair *self, PyObject *args)
2110{
2111 PyObject *ret = _forward_call(self->writer, "close", args);
2112 if (ret == NULL)
2113 return NULL;
2114 Py_DECREF(ret);
2115
2116 return _forward_call(self->reader, "close", args);
2117}
2118
2119static PyObject *
2120bufferedrwpair_isatty(rwpair *self, PyObject *args)
2121{
2122 PyObject *ret = _forward_call(self->writer, "isatty", args);
2123
2124 if (ret != Py_False) {
2125 /* either True or exception */
2126 return ret;
2127 }
2128 Py_DECREF(ret);
2129
2130 return _forward_call(self->reader, "isatty", args);
2131}
2132
2133static PyObject *
2134bufferedrwpair_closed_get(rwpair *self, void *context)
2135{
2136 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2137}
2138
2139static PyMethodDef bufferedrwpair_methods[] = {
2140 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2141 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2142 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2143 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
2144
2145 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2146 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
2147
2148 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2149 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
2150
2151 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2152 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
2153
2154 {NULL, NULL}
2155};
2156
2157static PyGetSetDef bufferedrwpair_getset[] = {
2158 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
2159 {NULL}
2160};
2161
2162PyTypeObject PyBufferedRWPair_Type = {
2163 PyVarObject_HEAD_INIT(NULL, 0)
2164 "_io.BufferedRWPair", /*tp_name*/
2165 sizeof(rwpair), /*tp_basicsize*/
2166 0, /*tp_itemsize*/
2167 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
2168 0, /*tp_print*/
2169 0, /*tp_getattr*/
2170 0, /*tp_setattr*/
2171 0, /*tp_compare */
2172 0, /*tp_repr*/
2173 0, /*tp_as_number*/
2174 0, /*tp_as_sequence*/
2175 0, /*tp_as_mapping*/
2176 0, /*tp_hash */
2177 0, /*tp_call*/
2178 0, /*tp_str*/
2179 0, /*tp_getattro*/
2180 0, /*tp_setattro*/
2181 0, /*tp_as_buffer*/
2182 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2183 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
2184 bufferedrwpair_doc, /* tp_doc */
2185 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2186 (inquiry)bufferedrwpair_clear, /* tp_clear */
2187 0, /* tp_richcompare */
2188 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
2189 0, /* tp_iter */
2190 0, /* tp_iternext */
2191 bufferedrwpair_methods, /* tp_methods */
2192 0, /* tp_members */
2193 bufferedrwpair_getset, /* tp_getset */
2194 0, /* tp_base */
2195 0, /* tp_dict */
2196 0, /* tp_descr_get */
2197 0, /* tp_descr_set */
2198 offsetof(rwpair, dict), /* tp_dictoffset */
2199 (initproc)bufferedrwpair_init, /* tp_init */
2200 0, /* tp_alloc */
2201 PyType_GenericNew, /* tp_new */
2202};
2203
2204
2205
2206/*
2207 * BufferedRandom
2208 */
2209
2210PyDoc_STRVAR(bufferedrandom_doc,
2211 "A buffered interface to random access streams.\n"
2212 "\n"
2213 "The constructor creates a reader and writer for a seekable stream,\n"
2214 "raw, given in the first argument. If the buffer_size is omitted it\n"
2215 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2216 );
2217
2218static int
2219bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
2220{
2221 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2222 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
2223 Py_ssize_t max_buffer_size = -234;
2224 PyObject *raw;
2225
2226 self->ok = 0;
2227 self->detached = 0;
2228
2229 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2230 &raw, &buffer_size, &max_buffer_size)) {
2231 return -1;
2232 }
2233
2234 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2235 return -1;
2236
2237 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
2238 return -1;
2239 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
2240 return -1;
2241 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
2242 return -1;
2243
2244 Py_CLEAR(self->raw);
2245 Py_INCREF(raw);
2246 self->raw = raw;
2247 self->buffer_size = buffer_size;
2248 self->readable = 1;
2249 self->writable = 1;
2250
2251 if (_buffered_init(self) < 0)
2252 return -1;
2253 _bufferedreader_reset_buf(self);
2254 _bufferedwriter_reset_buf(self);
2255 self->pos = 0;
2256
2257 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2258 Py_TYPE(raw) == &PyFileIO_Type);
2259
2260 self->ok = 1;
2261 return 0;
2262}
2263
2264static PyMethodDef bufferedrandom_methods[] = {
2265 /* BufferedIOMixin methods */
2266 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2267 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2268 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2269 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2270 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2271 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2272 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2273
2274 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2275
2276 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2277 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2278 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2279 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2280 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2281 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2282 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2283 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2284 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
2285 {NULL, NULL}
2286};
2287
2288static PyMemberDef bufferedrandom_members[] = {
2289 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
2290 {NULL}
2291};
2292
2293static PyGetSetDef bufferedrandom_getset[] = {
2294 {"closed", (getter)buffered_closed_get, NULL, NULL},
2295 {"name", (getter)buffered_name_get, NULL, NULL},
2296 {"mode", (getter)buffered_mode_get, NULL, NULL},
2297 {NULL}
2298};
2299
2300
2301PyTypeObject PyBufferedRandom_Type = {
2302 PyVarObject_HEAD_INIT(NULL, 0)
2303 "_io.BufferedRandom", /*tp_name*/
2304 sizeof(buffered), /*tp_basicsize*/
2305 0, /*tp_itemsize*/
2306 (destructor)buffered_dealloc, /*tp_dealloc*/
2307 0, /*tp_print*/
2308 0, /*tp_getattr*/
2309 0, /*tp_setattr*/
2310 0, /*tp_compare */
2311 (reprfunc)buffered_repr, /*tp_repr*/
2312 0, /*tp_as_number*/
2313 0, /*tp_as_sequence*/
2314 0, /*tp_as_mapping*/
2315 0, /*tp_hash */
2316 0, /*tp_call*/
2317 0, /*tp_str*/
2318 0, /*tp_getattro*/
2319 0, /*tp_setattro*/
2320 0, /*tp_as_buffer*/
2321 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2322 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2323 bufferedrandom_doc, /* tp_doc */
2324 (traverseproc)buffered_traverse, /* tp_traverse */
2325 (inquiry)buffered_clear, /* tp_clear */
2326 0, /* tp_richcompare */
2327 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2328 0, /* tp_iter */
2329 (iternextfunc)buffered_iternext, /* tp_iternext */
2330 bufferedrandom_methods, /* tp_methods */
2331 bufferedrandom_members, /* tp_members */
2332 bufferedrandom_getset, /* tp_getset */
2333 0, /* tp_base */
2334 0, /*tp_dict*/
2335 0, /* tp_descr_get */
2336 0, /* tp_descr_set */
2337 offsetof(buffered, dict), /*tp_dictoffset*/
2338 (initproc)bufferedrandom_init, /* tp_init */
2339 0, /* tp_alloc */
2340 PyType_GenericNew, /* tp_new */
2341};
2342