blob: 3d175c7c8cf16298300218ee365a590202e00155 [file] [log] [blame]
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +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(IO_STATE->unsupported_operation, message);
73 return NULL;
74}
75
76PyDoc_STRVAR(BufferedIOBase_read_doc,
77 "Read and return up to n bytes.\n"
78 "\n"
79 "If the argument is omitted, None, or negative, reads and\n"
80 "returns all data until EOF.\n"
81 "\n"
82 "If the argument is positive, and the underlying raw stream is\n"
83 "not 'interactive', multiple raw reads may be issued to satisfy\n"
84 "the byte count (unless EOF is reached first). But for\n"
85 "interactive raw streams (as well as sockets and pipes), at most\n"
86 "one raw read will be issued, and a short result does not imply\n"
87 "that EOF is imminent.\n"
88 "\n"
89 "Returns an empty bytes object on EOF.\n"
90 "\n"
91 "Returns None if the underlying raw stream was open in non-blocking\n"
92 "mode and no data is available at the moment.\n");
93
94static PyObject *
95BufferedIOBase_read(PyObject *self, PyObject *args)
96{
97 return BufferedIOBase_unsupported("read");
98}
99
100PyDoc_STRVAR(BufferedIOBase_read1_doc,
101 "Read and return up to n bytes, with at most one read() call\n"
102 "to the underlying raw stream. A short result does not imply\n"
103 "that EOF is imminent.\n"
104 "\n"
105 "Returns an empty bytes object on EOF.\n");
106
107static PyObject *
108BufferedIOBase_read1(PyObject *self, PyObject *args)
109{
110 return BufferedIOBase_unsupported("read1");
111}
112
113PyDoc_STRVAR(BufferedIOBase_write_doc,
114 "Write the given buffer to the IO stream.\n"
115 "\n"
116 "Returns the number of bytes written, which is never less than\n"
117 "len(b).\n"
118 "\n"
119 "Raises BlockingIOError if the buffer is full and the\n"
120 "underlying raw stream cannot accept more data at the moment.\n");
121
122static PyObject *
123BufferedIOBase_write(PyObject *self, PyObject *args)
124{
125 return BufferedIOBase_unsupported("write");
126}
127
128
129static PyMethodDef BufferedIOBase_methods[] = {
130 {"read", BufferedIOBase_read, METH_VARARGS, BufferedIOBase_read_doc},
131 {"read1", BufferedIOBase_read1, METH_VARARGS, BufferedIOBase_read1_doc},
132 {"readinto", BufferedIOBase_readinto, METH_VARARGS, NULL},
133 {"write", BufferedIOBase_write, METH_VARARGS, BufferedIOBase_write_doc},
134 {NULL, NULL}
135};
136
137PyTypeObject PyBufferedIOBase_Type = {
138 PyVarObject_HEAD_INIT(NULL, 0)
139 "_io._BufferedIOBase", /*tp_name*/
140 0, /*tp_basicsize*/
141 0, /*tp_itemsize*/
142 0, /*tp_dealloc*/
143 0, /*tp_print*/
144 0, /*tp_getattr*/
145 0, /*tp_setattr*/
146 0, /*tp_compare */
147 0, /*tp_repr*/
148 0, /*tp_as_number*/
149 0, /*tp_as_sequence*/
150 0, /*tp_as_mapping*/
151 0, /*tp_hash */
152 0, /*tp_call*/
153 0, /*tp_str*/
154 0, /*tp_getattro*/
155 0, /*tp_setattro*/
156 0, /*tp_as_buffer*/
157 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
158 BufferedIOBase_doc, /* tp_doc */
159 0, /* tp_traverse */
160 0, /* tp_clear */
161 0, /* tp_richcompare */
162 0, /* tp_weaklistoffset */
163 0, /* tp_iter */
164 0, /* tp_iternext */
165 BufferedIOBase_methods, /* tp_methods */
166 0, /* tp_members */
167 0, /* tp_getset */
168 &PyIOBase_Type, /* tp_base */
169 0, /* tp_dict */
170 0, /* tp_descr_get */
171 0, /* tp_descr_set */
172 0, /* tp_dictoffset */
173 0, /* tp_init */
174 0, /* tp_alloc */
175 0, /* tp_new */
176};
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000177
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000178
179typedef struct {
180 PyObject_HEAD
181
182 PyObject *raw;
183 int ok; /* Initialized? */
184 int readable;
185 int writable;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000186
187 /* True if this is a vanilla Buffered object (rather than a user derived
188 class) *and* the raw stream is a vanilla FileIO object. */
189 int fast_closed_checks;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000190
191 /* Absolute position inside the raw stream (-1 if unknown). */
192 Py_off_t abs_pos;
193
194 /* A static buffer of size `buffer_size` */
195 char *buffer;
196 /* Current logical position in the buffer. */
197 Py_off_t pos;
198 /* Position of the raw stream in the buffer. */
199 Py_off_t raw_pos;
200
201 /* Just after the last buffered byte in the buffer, or -1 if the buffer
202 isn't ready for reading. */
203 Py_off_t read_end;
204
205 /* Just after the last byte actually written */
206 Py_off_t write_pos;
207 /* Just after the last byte waiting to be written, or -1 if the buffer
208 isn't ready for writing. */
209 Py_off_t write_end;
210
Georg Brandldfd73442009-04-05 11:47:34 +0000211#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000212 PyThread_type_lock lock;
Georg Brandldfd73442009-04-05 11:47:34 +0000213#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000214
215 Py_ssize_t buffer_size;
216 Py_ssize_t buffer_mask;
217
218 PyObject *dict;
219 PyObject *weakreflist;
220} BufferedObject;
221
222/*
223 Implementation notes:
224
225 * BufferedReader, BufferedWriter and BufferedRandom try to share most
226 methods (this is helped by the members `readable` and `writable`, which
227 are initialized in the respective constructors)
228 * They also share a single buffer for reading and writing. This enables
229 interleaved reads and writes without flushing. It also makes the logic
230 a bit trickier to get right.
231 * The absolute position of the raw stream is cached, if possible, in the
232 `abs_pos` member. It must be updated every time an operation is done
233 on the raw stream. If not sure, it can be reinitialized by calling
234 _Buffered_raw_tell(), which queries the raw stream (_Buffered_raw_seek()
235 also does it). To read it, use RAW_TELL().
236 * Three helpers, _BufferedReader_raw_read, _BufferedWriter_raw_write and
237 _BufferedWriter_flush_unlocked do a lot of useful housekeeping.
238
239 NOTE: we should try to maintain block alignment of reads and writes to the
240 raw stream (according to the buffer size), but for now it is only done
241 in read() and friends.
242
243 XXX: method naming is a bit messy.
244*/
245
246/* These macros protect the BufferedObject against concurrent operations. */
247
Georg Brandldfd73442009-04-05 11:47:34 +0000248#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000249#define ENTER_BUFFERED(self) \
250 Py_BEGIN_ALLOW_THREADS \
251 PyThread_acquire_lock(self->lock, 1); \
252 Py_END_ALLOW_THREADS
253
254#define LEAVE_BUFFERED(self) \
255 PyThread_release_lock(self->lock);
Georg Brandldfd73442009-04-05 11:47:34 +0000256#else
257#define ENTER_BUFFERED(self)
258#define LEAVE_BUFFERED(self)
259#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000260
261#define CHECK_INITIALIZED(self) \
262 if (self->ok <= 0) { \
263 PyErr_SetString(PyExc_ValueError, \
264 "I/O operation on uninitialized object"); \
265 return NULL; \
266 }
267
268#define CHECK_INITIALIZED_INT(self) \
269 if (self->ok <= 0) { \
270 PyErr_SetString(PyExc_ValueError, \
271 "I/O operation on uninitialized object"); \
272 return -1; \
273 }
274
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000275#define IS_CLOSED(self) \
276 (self->fast_closed_checks \
277 ? _PyFileIO_closed(self->raw) \
278 : BufferedIOMixin_closed(self))
279
280#define CHECK_CLOSED(self, error_msg) \
281 if (IS_CLOSED(self)) { \
282 PyErr_SetString(PyExc_ValueError, error_msg); \
283 return NULL; \
284 }
285
286
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000287#define VALID_READ_BUFFER(self) \
288 (self->readable && self->read_end != -1)
289
290#define VALID_WRITE_BUFFER(self) \
291 (self->writable && self->write_end != -1)
292
293#define ADJUST_POSITION(self, _new_pos) \
294 do { \
295 self->pos = _new_pos; \
296 if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
297 self->read_end = self->pos; \
298 } while(0)
299
300#define READAHEAD(self) \
301 ((self->readable && VALID_READ_BUFFER(self)) \
302 ? (self->read_end - self->pos) : 0)
303
304#define RAW_OFFSET(self) \
305 (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
306 && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
307
308#define RAW_TELL(self) \
309 (self->abs_pos != -1 ? self->abs_pos : _Buffered_raw_tell(self))
310
311#define MINUS_LAST_BLOCK(self, size) \
312 (self->buffer_mask ? \
313 (size & ~self->buffer_mask) : \
314 (self->buffer_size * (size / self->buffer_size)))
315
316
317static void
318BufferedObject_dealloc(BufferedObject *self)
319{
320 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
321 return;
322 _PyObject_GC_UNTRACK(self);
323 self->ok = 0;
324 if (self->weakreflist != NULL)
325 PyObject_ClearWeakRefs((PyObject *)self);
326 Py_CLEAR(self->raw);
327 if (self->buffer) {
328 PyMem_Free(self->buffer);
329 self->buffer = NULL;
330 }
Georg Brandldfd73442009-04-05 11:47:34 +0000331#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000332 if (self->lock) {
333 PyThread_free_lock(self->lock);
334 self->lock = NULL;
335 }
Georg Brandldfd73442009-04-05 11:47:34 +0000336#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000337 Py_CLEAR(self->dict);
338 Py_TYPE(self)->tp_free((PyObject *)self);
339}
340
341static int
342Buffered_traverse(BufferedObject *self, visitproc visit, void *arg)
343{
344 Py_VISIT(self->raw);
345 Py_VISIT(self->dict);
346 return 0;
347}
348
349static int
350Buffered_clear(BufferedObject *self)
351{
352 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
353 return -1;
354 self->ok = 0;
355 Py_CLEAR(self->raw);
356 Py_CLEAR(self->dict);
357 return 0;
358}
359
360/*
361 * _BufferedIOMixin methods
362 * This is not a class, just a collection of methods that will be reused
363 * by BufferedReader and BufferedWriter
364 */
365
366/* Flush and close */
367
368static PyObject *
369BufferedIOMixin_flush(BufferedObject *self, PyObject *args)
370{
371 CHECK_INITIALIZED(self)
372 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
373}
374
375static int
376BufferedIOMixin_closed(BufferedObject *self)
377{
378 int closed;
379 PyObject *res;
380 CHECK_INITIALIZED_INT(self)
381 res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
382 if (res == NULL)
383 return -1;
384 closed = PyObject_IsTrue(res);
385 Py_DECREF(res);
386 return closed;
387}
388
389static PyObject *
390BufferedIOMixin_closed_get(BufferedObject *self, void *context)
391{
392 CHECK_INITIALIZED(self)
393 return PyObject_GetAttr(self->raw, _PyIO_str_closed);
394}
395
396static PyObject *
397BufferedIOMixin_close(BufferedObject *self, PyObject *args)
398{
399 PyObject *res = NULL;
400 int r;
401
402 CHECK_INITIALIZED(self)
403 ENTER_BUFFERED(self)
404
405 r = BufferedIOMixin_closed(self);
406 if (r < 0)
407 goto end;
408 if (r > 0) {
409 res = Py_None;
410 Py_INCREF(res);
411 goto end;
412 }
413 /* flush() will most probably re-take the lock, so drop it first */
414 LEAVE_BUFFERED(self)
415 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
416 ENTER_BUFFERED(self)
417 if (res == NULL) {
418 /* If flush() fails, just give up */
419 if (PyErr_ExceptionMatches(PyExc_IOError))
420 PyErr_Clear();
421 else
422 goto end;
423 }
424 Py_XDECREF(res);
425
426 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
427
428end:
429 LEAVE_BUFFERED(self)
430 return res;
431}
432
433/* Inquiries */
434
435static PyObject *
436BufferedIOMixin_seekable(BufferedObject *self, PyObject *args)
437{
438 CHECK_INITIALIZED(self)
439 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
440}
441
442static PyObject *
443BufferedIOMixin_readable(BufferedObject *self, PyObject *args)
444{
445 CHECK_INITIALIZED(self)
446 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
447}
448
449static PyObject *
450BufferedIOMixin_writable(BufferedObject *self, PyObject *args)
451{
452 CHECK_INITIALIZED(self)
453 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
454}
455
456static PyObject *
457BufferedIOMixin_name_get(BufferedObject *self, void *context)
458{
459 CHECK_INITIALIZED(self)
460 return PyObject_GetAttrString(self->raw, "name");
461}
462
463static PyObject *
464BufferedIOMixin_mode_get(BufferedObject *self, void *context)
465{
466 CHECK_INITIALIZED(self)
467 return PyObject_GetAttrString(self->raw, "mode");
468}
469
470/* Lower-level APIs */
471
472static PyObject *
473BufferedIOMixin_fileno(BufferedObject *self, PyObject *args)
474{
475 CHECK_INITIALIZED(self)
476 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
477}
478
479static PyObject *
480BufferedIOMixin_isatty(BufferedObject *self, PyObject *args)
481{
482 CHECK_INITIALIZED(self)
483 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
484}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000485
486
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000487/* Forward decls */
488static PyObject *
489_BufferedWriter_flush_unlocked(BufferedObject *, int);
490static Py_ssize_t
491_BufferedReader_fill_buffer(BufferedObject *self);
492static void
493_BufferedReader_reset_buf(BufferedObject *self);
494static void
495_BufferedWriter_reset_buf(BufferedObject *self);
496static PyObject *
497_BufferedReader_peek_unlocked(BufferedObject *self, Py_ssize_t);
498static PyObject *
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000499_BufferedReader_read_all(BufferedObject *self);
500static PyObject *
501_BufferedReader_read_fast(BufferedObject *self, Py_ssize_t);
502static PyObject *
503_BufferedReader_read_generic(BufferedObject *self, Py_ssize_t);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000504
505
506/*
507 * Helpers
508 */
509
510/* Returns the address of the `written` member if a BlockingIOError was
511 raised, NULL otherwise. The error is always re-raised. */
512static Py_ssize_t *
513_Buffered_check_blocking_error(void)
514{
515 PyObject *t, *v, *tb;
516 PyBlockingIOErrorObject *err;
517
518 PyErr_Fetch(&t, &v, &tb);
519 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
520 PyErr_Restore(t, v, tb);
521 return NULL;
522 }
523 err = (PyBlockingIOErrorObject *) v;
524 /* TODO: sanity check (err->written >= 0) */
525 PyErr_Restore(t, v, tb);
526 return &err->written;
527}
528
529static Py_off_t
530_Buffered_raw_tell(BufferedObject *self)
531{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000532 Py_off_t n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000533 PyObject *res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000534 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
535 if (res == NULL)
536 return -1;
537 n = PyNumber_AsOff_t(res, PyExc_ValueError);
538 Py_DECREF(res);
539 if (n < 0) {
540 if (!PyErr_Occurred())
541 PyErr_Format(PyExc_IOError,
542 "Raw stream returned invalid position %zd", n);
543 return -1;
544 }
545 self->abs_pos = n;
546 return n;
547}
548
549static Py_off_t
550_Buffered_raw_seek(BufferedObject *self, Py_off_t target, int whence)
551{
552 PyObject *res, *posobj, *whenceobj;
553 Py_off_t n;
554
555 posobj = PyLong_FromOff_t(target);
556 if (posobj == NULL)
557 return -1;
558 whenceobj = PyLong_FromLong(whence);
559 if (whenceobj == NULL) {
560 Py_DECREF(posobj);
561 return -1;
562 }
563 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
564 posobj, whenceobj, NULL);
565 Py_DECREF(posobj);
566 Py_DECREF(whenceobj);
567 if (res == NULL)
568 return -1;
569 n = PyNumber_AsOff_t(res, PyExc_ValueError);
570 Py_DECREF(res);
571 if (n < 0) {
572 if (!PyErr_Occurred())
573 PyErr_Format(PyExc_IOError,
574 "Raw stream returned invalid position %zd", n);
575 return -1;
576 }
577 self->abs_pos = n;
578 return n;
579}
580
581static int
582_Buffered_init(BufferedObject *self)
583{
584 Py_ssize_t n;
585 if (self->buffer_size <= 0) {
586 PyErr_SetString(PyExc_ValueError,
587 "buffer size must be strictly positive");
588 return -1;
589 }
590 if (self->buffer)
591 PyMem_Free(self->buffer);
592 self->buffer = PyMem_Malloc(self->buffer_size);
593 if (self->buffer == NULL) {
594 PyErr_NoMemory();
595 return -1;
596 }
Georg Brandldfd73442009-04-05 11:47:34 +0000597#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000598 self->lock = PyThread_allocate_lock();
599 if (self->lock == NULL) {
600 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
601 return -1;
602 }
Georg Brandldfd73442009-04-05 11:47:34 +0000603#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000604 /* Find out whether buffer_size is a power of 2 */
605 /* XXX is this optimization useful? */
606 for (n = self->buffer_size - 1; n & 1; n >>= 1)
607 ;
608 if (n == 0)
609 self->buffer_mask = self->buffer_size - 1;
610 else
611 self->buffer_mask = 0;
612 if (_Buffered_raw_tell(self) == -1)
613 PyErr_Clear();
614 return 0;
615}
616
617/*
618 * Shared methods and wrappers
619 */
620
621static PyObject *
622Buffered_flush(BufferedObject *self, PyObject *args)
623{
624 PyObject *res;
625
626 CHECK_INITIALIZED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000627 CHECK_CLOSED(self, "flush of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000628
629 ENTER_BUFFERED(self)
630 res = _BufferedWriter_flush_unlocked(self, 0);
631 if (res != NULL && self->readable) {
632 /* Rewind the raw stream so that its position corresponds to
633 the current logical position. */
634 Py_off_t n;
635 n = _Buffered_raw_seek(self, -RAW_OFFSET(self), 1);
636 if (n == -1)
637 Py_CLEAR(res);
638 _BufferedReader_reset_buf(self);
639 }
640 LEAVE_BUFFERED(self)
641
642 return res;
643}
644
645static PyObject *
646Buffered_peek(BufferedObject *self, PyObject *args)
647{
648 Py_ssize_t n = 0;
649 PyObject *res = NULL;
650
651 CHECK_INITIALIZED(self)
652 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
653 return NULL;
654 }
655
656 ENTER_BUFFERED(self)
657
658 if (self->writable) {
659 res = _BufferedWriter_flush_unlocked(self, 1);
660 if (res == NULL)
661 goto end;
662 Py_CLEAR(res);
663 }
664 res = _BufferedReader_peek_unlocked(self, n);
665
666end:
667 LEAVE_BUFFERED(self)
668 return res;
669}
670
671static PyObject *
672Buffered_read(BufferedObject *self, PyObject *args)
673{
674 Py_ssize_t n = -1;
675 PyObject *res;
676
677 CHECK_INITIALIZED(self)
678 if (!PyArg_ParseTuple(args, "|n:read", &n)) {
679 return NULL;
680 }
681 if (n < -1) {
682 PyErr_SetString(PyExc_ValueError,
683 "read length must be positive or -1");
684 return NULL;
685 }
686
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000687 CHECK_CLOSED(self, "read of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000688
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000689 if (n == -1) {
690 /* The number of bytes is unspecified, read until the end of stream */
691 ENTER_BUFFERED(self)
692 res = _BufferedReader_read_all(self);
693 LEAVE_BUFFERED(self)
694 }
695 else {
696 res = _BufferedReader_read_fast(self, n);
697 if (res == Py_None) {
698 Py_DECREF(res);
699 ENTER_BUFFERED(self)
700 res = _BufferedReader_read_generic(self, n);
701 LEAVE_BUFFERED(self)
702 }
703 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000704
705 return res;
706}
707
708static PyObject *
709Buffered_read1(BufferedObject *self, PyObject *args)
710{
711 Py_ssize_t n, have, r;
712 PyObject *res = NULL;
713
714 CHECK_INITIALIZED(self)
715 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
716 return NULL;
717 }
718
719 if (n < 0) {
720 PyErr_SetString(PyExc_ValueError,
721 "read length must be positive");
722 return NULL;
723 }
724 if (n == 0)
725 return PyBytes_FromStringAndSize(NULL, 0);
726
727 ENTER_BUFFERED(self)
728
729 if (self->writable) {
730 res = _BufferedWriter_flush_unlocked(self, 1);
731 if (res == NULL)
732 goto end;
733 Py_CLEAR(res);
734 }
735
736 /* Return up to n bytes. If at least one byte is buffered, we
737 only return buffered bytes. Otherwise, we do one raw read. */
738
739 /* XXX: this mimicks the io.py implementation but is probably wrong.
740 If we need to read from the raw stream, then we could actually read
741 all `n` bytes asked by the caller (and possibly more, so as to fill
742 our buffer for the next reads). */
743
744 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
745 if (have > 0) {
746 if (n > have)
747 n = have;
748 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
749 if (res == NULL)
750 goto end;
751 self->pos += n;
752 goto end;
753 }
754
755 /* Fill the buffer from the raw stream, and copy it to the result. */
756 _BufferedReader_reset_buf(self);
757 r = _BufferedReader_fill_buffer(self);
758 if (r == -1)
759 goto end;
760 if (r == -2)
761 r = 0;
762 if (n > r)
763 n = r;
764 res = PyBytes_FromStringAndSize(self->buffer, n);
765 if (res == NULL)
766 goto end;
767 self->pos = n;
768
769end:
770 LEAVE_BUFFERED(self)
771 return res;
772}
773
774static PyObject *
775Buffered_readinto(BufferedObject *self, PyObject *args)
776{
777 PyObject *res = NULL;
778
779 CHECK_INITIALIZED(self)
780
781 /* TODO: use raw.readinto() instead! */
782 if (self->writable) {
783 ENTER_BUFFERED(self)
784 res = _BufferedWriter_flush_unlocked(self, 0);
785 LEAVE_BUFFERED(self)
786 if (res == NULL)
787 goto end;
788 Py_DECREF(res);
789 }
790 res = BufferedIOBase_readinto((PyObject *)self, args);
791
792end:
793 return res;
794}
795
796static PyObject *
797_Buffered_readline(BufferedObject *self, Py_ssize_t limit)
798{
799 PyObject *res = NULL;
800 PyObject *chunks = NULL;
801 Py_ssize_t n, written = 0;
802 const char *start, *s, *end;
803
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000804 CHECK_CLOSED(self, "readline of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000805
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000806 /* First, try to find a line in the buffer. This can run unlocked because
807 the calls to the C API are simple enough that they can't trigger
808 any thread switch. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000809 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
810 if (limit >= 0 && n > limit)
811 n = limit;
812 start = self->buffer + self->pos;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000813 s = memchr(start, '\n', n);
814 if (s != NULL) {
815 res = PyBytes_FromStringAndSize(start, s - start + 1);
816 if (res != NULL)
817 self->pos += s - start + 1;
818 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000819 }
820 if (n == limit) {
821 res = PyBytes_FromStringAndSize(start, n);
822 if (res != NULL)
823 self->pos += n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000824 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000825 }
826
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000827 ENTER_BUFFERED(self)
828
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000829 /* Now we try to get some more from the raw stream */
830 if (self->writable) {
831 res = _BufferedWriter_flush_unlocked(self, 1);
832 if (res == NULL)
833 goto end;
834 Py_CLEAR(res);
835 }
836 chunks = PyList_New(0);
837 if (chunks == NULL)
838 goto end;
839 if (n > 0) {
840 res = PyBytes_FromStringAndSize(start, n);
841 if (res == NULL)
842 goto end;
843 if (PyList_Append(chunks, res) < 0) {
844 Py_CLEAR(res);
845 goto end;
846 }
847 Py_CLEAR(res);
848 written += n;
849 if (limit >= 0)
850 limit -= n;
851 }
852
853 for (;;) {
854 _BufferedReader_reset_buf(self);
855 n = _BufferedReader_fill_buffer(self);
856 if (n == -1)
857 goto end;
858 if (n <= 0)
859 break;
860 if (limit >= 0 && n > limit)
861 n = limit;
862 start = self->buffer;
863 end = start + n;
864 s = start;
865 while (s < end) {
866 if (*s++ == '\n') {
867 res = PyBytes_FromStringAndSize(start, s - start);
868 if (res == NULL)
869 goto end;
870 self->pos = s - start;
871 goto found;
872 }
873 }
874 res = PyBytes_FromStringAndSize(start, n);
875 if (res == NULL)
876 goto end;
877 if (n == limit) {
878 self->pos = n;
879 break;
880 }
881 if (PyList_Append(chunks, res) < 0) {
882 Py_CLEAR(res);
883 goto end;
884 }
885 Py_CLEAR(res);
886 written += n;
887 if (limit >= 0)
888 limit -= n;
889 }
890found:
891 if (res != NULL && PyList_Append(chunks, res) < 0) {
892 Py_CLEAR(res);
893 goto end;
894 }
895 Py_CLEAR(res);
896 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
897
898end:
899 LEAVE_BUFFERED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000900end_unlocked:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000901 Py_XDECREF(chunks);
902 return res;
903}
904
905static PyObject *
906Buffered_readline(BufferedObject *self, PyObject *args)
907{
908 Py_ssize_t limit = -1;
909
910 CHECK_INITIALIZED(self)
911
912 if (!PyArg_ParseTuple(args, "|n:readline", &limit)) {
913 return NULL;
914 }
915 return _Buffered_readline(self, limit);
916}
917
918
919static PyObject *
920Buffered_tell(BufferedObject *self, PyObject *args)
921{
922 Py_off_t pos;
923
924 CHECK_INITIALIZED(self)
925 pos = _Buffered_raw_tell(self);
926 if (pos == -1)
927 return NULL;
928 pos -= RAW_OFFSET(self);
929 /* TODO: sanity check (pos >= 0) */
930 return PyLong_FromOff_t(pos);
931}
932
933static PyObject *
934Buffered_seek(BufferedObject *self, PyObject *args)
935{
936 Py_off_t target, n;
937 int whence = 0;
938 PyObject *targetobj, *res = NULL;
939
940 CHECK_INITIALIZED(self)
941 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
942 return NULL;
943 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000944 if (whence < 0 || whence > 2) {
945 PyErr_Format(PyExc_ValueError,
946 "whence must be between 0 and 2, not %d", whence);
947 return NULL;
948 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000949
950 CHECK_CLOSED(self, "seek of closed file")
951
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000952 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
953 if (target == -1 && PyErr_Occurred())
954 return NULL;
955
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000956 if (whence != 2 && self->readable) {
957 Py_off_t current, avail;
958 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000959 so as to return quickly if possible. Also, we needn't take the
960 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000961 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000962 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
963 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000964 current = RAW_TELL(self);
965 avail = READAHEAD(self);
966 if (avail > 0) {
967 Py_off_t offset;
968 if (whence == 0)
969 offset = target - (current - RAW_OFFSET(self));
970 else
971 offset = target;
972 if (offset >= -self->pos && offset <= avail) {
973 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000974 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000975 }
976 }
977 }
978
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000979 ENTER_BUFFERED(self)
980
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000981 /* Fallback: invoke raw seek() method and clear buffer */
982 if (self->writable) {
983 res = _BufferedWriter_flush_unlocked(self, 0);
984 if (res == NULL)
985 goto end;
986 Py_CLEAR(res);
987 _BufferedWriter_reset_buf(self);
988 }
989
990 /* TODO: align on block boundary and read buffer if needed? */
991 if (whence == 1)
992 target -= RAW_OFFSET(self);
993 n = _Buffered_raw_seek(self, target, whence);
994 if (n == -1)
995 goto end;
996 self->raw_pos = -1;
997 res = PyLong_FromOff_t(n);
998 if (res != NULL && self->readable)
999 _BufferedReader_reset_buf(self);
1000
1001end:
1002 LEAVE_BUFFERED(self)
1003 return res;
1004}
1005
1006static PyObject *
1007Buffered_truncate(BufferedObject *self, PyObject *args)
1008{
1009 PyObject *pos = Py_None;
1010 PyObject *res = NULL;
1011
1012 CHECK_INITIALIZED(self)
1013 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1014 return NULL;
1015 }
1016
1017 ENTER_BUFFERED(self)
1018
1019 if (self->writable) {
1020 res = _BufferedWriter_flush_unlocked(self, 0);
1021 if (res == NULL)
1022 goto end;
1023 Py_CLEAR(res);
1024 }
1025 if (self->readable) {
1026 if (pos == Py_None) {
1027 /* Rewind the raw stream so that its position corresponds to
1028 the current logical position. */
1029 if (_Buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)
1030 goto end;
1031 }
1032 _BufferedReader_reset_buf(self);
1033 }
1034 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1035 if (res == NULL)
1036 goto end;
1037 /* Reset cached position */
1038 if (_Buffered_raw_tell(self) == -1)
1039 PyErr_Clear();
1040
1041end:
1042 LEAVE_BUFFERED(self)
1043 return res;
1044}
1045
1046static PyObject *
1047Buffered_iternext(BufferedObject *self)
1048{
1049 PyObject *line;
1050 PyTypeObject *tp;
1051
1052 CHECK_INITIALIZED(self);
1053
1054 tp = Py_TYPE(self);
1055 if (tp == &PyBufferedReader_Type ||
1056 tp == &PyBufferedRandom_Type) {
1057 /* Skip method call overhead for speed */
1058 line = _Buffered_readline(self, -1);
1059 }
1060 else {
1061 line = PyObject_CallMethodObjArgs((PyObject *)self,
1062 _PyIO_str_readline, NULL);
1063 if (line && !PyBytes_Check(line)) {
1064 PyErr_Format(PyExc_IOError,
1065 "readline() should have returned a bytes object, "
1066 "not '%.200s'", Py_TYPE(line)->tp_name);
1067 Py_DECREF(line);
1068 return NULL;
1069 }
1070 }
1071
1072 if (line == NULL)
1073 return NULL;
1074
1075 if (PyBytes_GET_SIZE(line) == 0) {
1076 /* Reached EOF or would have blocked */
1077 Py_DECREF(line);
1078 return NULL;
1079 }
1080
1081 return line;
1082}
1083
1084/*
1085 * class BufferedReader
1086 */
1087
1088PyDoc_STRVAR(BufferedReader_doc,
1089 "Create a new buffered reader using the given readable raw IO object.");
1090
1091static void _BufferedReader_reset_buf(BufferedObject *self)
1092{
1093 self->read_end = -1;
1094}
1095
1096static int
1097BufferedReader_init(BufferedObject *self, PyObject *args, PyObject *kwds)
1098{
1099 char *kwlist[] = {"raw", "buffer_size", NULL};
1100 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1101 PyObject *raw;
1102
1103 self->ok = 0;
1104
1105 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1106 &raw, &buffer_size)) {
1107 return -1;
1108 }
1109
1110 if (_PyIOBase_checkReadable(raw, Py_True) == NULL)
1111 return -1;
1112
1113 Py_CLEAR(self->raw);
1114 Py_INCREF(raw);
1115 self->raw = raw;
1116 self->buffer_size = buffer_size;
1117 self->readable = 1;
1118 self->writable = 0;
1119
1120 if (_Buffered_init(self) < 0)
1121 return -1;
1122 _BufferedReader_reset_buf(self);
1123
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001124 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1125 Py_TYPE(raw) == &PyFileIO_Type);
1126
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001127 self->ok = 1;
1128 return 0;
1129}
1130
1131static Py_ssize_t
1132_BufferedReader_raw_read(BufferedObject *self, char *start, Py_ssize_t len)
1133{
1134 Py_buffer buf;
1135 PyObject *memobj, *res;
1136 Py_ssize_t n;
1137 /* NOTE: the buffer needn't be released as its object is NULL. */
1138 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1139 return -1;
1140 memobj = PyMemoryView_FromBuffer(&buf);
1141 if (memobj == NULL)
1142 return -1;
1143 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1144 Py_DECREF(memobj);
1145 if (res == NULL)
1146 return -1;
1147 if (res == Py_None) {
1148 /* Non-blocking stream would have blocked. Special return code! */
1149 Py_DECREF(res);
1150 return -2;
1151 }
1152 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1153 Py_DECREF(res);
1154 if (n < 0 || n > len) {
1155 PyErr_Format(PyExc_IOError,
1156 "raw readinto() returned invalid length %zd "
1157 "(should have been between 0 and %zd)", n, len);
1158 return -1;
1159 }
1160 if (n > 0 && self->abs_pos != -1)
1161 self->abs_pos += n;
1162 return n;
1163}
1164
1165static Py_ssize_t
1166_BufferedReader_fill_buffer(BufferedObject *self)
1167{
1168 Py_ssize_t start, len, n;
1169 if (VALID_READ_BUFFER(self))
1170 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1171 else
1172 start = 0;
1173 len = self->buffer_size - start;
1174 n = _BufferedReader_raw_read(self, self->buffer + start, len);
1175 if (n <= 0)
1176 return n;
1177 self->read_end = start + n;
1178 self->raw_pos = start + n;
1179 return n;
1180}
1181
1182static PyObject *
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001183_BufferedReader_read_all(BufferedObject *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001184{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001185 Py_ssize_t current_size;
1186 PyObject *res, *data = NULL;
1187 PyObject *chunks = PyList_New(0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001188
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001189 if (chunks == NULL)
1190 return NULL;
1191
1192 /* First copy what we have in the current buffer. */
1193 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1194 if (current_size) {
1195 data = PyBytes_FromStringAndSize(
1196 self->buffer + self->pos, current_size);
1197 if (data == NULL) {
1198 Py_DECREF(chunks);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001199 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001200 }
1201 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001202 _BufferedReader_reset_buf(self);
1203 /* We're going past the buffer's bounds, flush it */
1204 if (self->writable) {
1205 res = _BufferedWriter_flush_unlocked(self, 1);
1206 if (res == NULL) {
1207 Py_DECREF(chunks);
1208 return NULL;
1209 }
1210 Py_CLEAR(res);
1211 }
1212 while (1) {
1213 if (data) {
1214 if (PyList_Append(chunks, data) < 0) {
1215 Py_DECREF(data);
1216 Py_DECREF(chunks);
1217 return NULL;
1218 }
1219 Py_DECREF(data);
1220 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001221
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001222 /* Read until EOF or until read() would block. */
1223 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1224 if (data == NULL) {
1225 Py_DECREF(chunks);
1226 return NULL;
1227 }
1228 if (data != Py_None && !PyBytes_Check(data)) {
1229 Py_DECREF(data);
1230 Py_DECREF(chunks);
1231 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1232 return NULL;
1233 }
1234 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1235 if (current_size == 0) {
1236 Py_DECREF(chunks);
1237 return data;
1238 }
1239 else {
1240 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1241 Py_DECREF(data);
1242 Py_DECREF(chunks);
1243 return res;
1244 }
1245 }
1246 current_size += PyBytes_GET_SIZE(data);
1247 if (self->abs_pos != -1)
1248 self->abs_pos += PyBytes_GET_SIZE(data);
1249 }
1250}
1251
1252/* Read n bytes from the buffer if it can, otherwise return None.
1253 This function is simple enough that it can run unlocked. */
1254static PyObject *
1255_BufferedReader_read_fast(BufferedObject *self, Py_ssize_t n)
1256{
1257 Py_ssize_t current_size;
1258
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001259 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1260 if (n <= current_size) {
1261 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001262 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1263 if (res != NULL)
1264 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001265 return res;
1266 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001267 Py_RETURN_NONE;
1268}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001269
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001270/* Generic read function: read from the stream until enough bytes are read,
1271 * or until an EOF occurs or until read() would block.
1272 */
1273static PyObject *
1274_BufferedReader_read_generic(BufferedObject *self, Py_ssize_t n)
1275{
1276 PyObject *res = NULL;
1277 Py_ssize_t current_size, remaining, written;
1278 char *out;
1279
1280 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1281 if (n <= current_size)
1282 return _BufferedReader_read_fast(self, n);
1283
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001284 res = PyBytes_FromStringAndSize(NULL, n);
1285 if (res == NULL)
1286 goto error;
1287 out = PyBytes_AS_STRING(res);
1288 remaining = n;
1289 written = 0;
1290 if (current_size > 0) {
1291 memcpy(out, self->buffer + self->pos, current_size);
1292 remaining -= current_size;
1293 written += current_size;
1294 }
1295 _BufferedReader_reset_buf(self);
1296 while (remaining > 0) {
1297 /* We want to read a whole block at the end into buffer.
1298 If we had readv() we could do this in one pass. */
1299 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1300 if (r == 0)
1301 break;
1302 r = _BufferedReader_raw_read(self, out + written, r);
1303 if (r == -1)
1304 goto error;
1305 if (r == 0 || r == -2) {
1306 /* EOF occurred or read() would block. */
1307 if (r == 0 || written > 0) {
1308 if (_PyBytes_Resize(&res, written))
1309 goto error;
1310 return res;
1311 }
1312 Py_DECREF(res);
1313 Py_INCREF(Py_None);
1314 return Py_None;
1315 }
1316 remaining -= r;
1317 written += r;
1318 }
1319 assert(remaining <= self->buffer_size);
1320 self->pos = 0;
1321 self->raw_pos = 0;
1322 self->read_end = 0;
1323 while (self->read_end < self->buffer_size) {
1324 Py_ssize_t r = _BufferedReader_fill_buffer(self);
1325 if (r == -1)
1326 goto error;
1327 if (r == 0 || r == -2) {
1328 /* EOF occurred or read() would block. */
1329 if (r == 0 || written > 0) {
1330 if (_PyBytes_Resize(&res, written))
1331 goto error;
1332 return res;
1333 }
1334 Py_DECREF(res);
1335 Py_INCREF(Py_None);
1336 return Py_None;
1337 }
1338 if (remaining > r) {
1339 memcpy(out + written, self->buffer + self->pos, r);
1340 written += r;
1341 self->pos += r;
1342 remaining -= r;
1343 }
1344 else if (remaining > 0) {
1345 memcpy(out + written, self->buffer + self->pos, remaining);
1346 written += remaining;
1347 self->pos += remaining;
1348 remaining = 0;
1349 }
1350 if (remaining == 0)
1351 break;
1352 }
1353
1354 return res;
1355
1356error:
1357 Py_XDECREF(res);
1358 return NULL;
1359}
1360
1361static PyObject *
1362_BufferedReader_peek_unlocked(BufferedObject *self, Py_ssize_t n)
1363{
1364 Py_ssize_t have, r;
1365
1366 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1367 /* Constraints:
1368 1. we don't want to advance the file position.
1369 2. we don't want to lose block alignment, so we can't shift the buffer
1370 to make some place.
1371 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1372 */
1373 if (have > 0) {
1374 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1375 }
1376
1377 /* Fill the buffer from the raw stream, and copy it to the result. */
1378 _BufferedReader_reset_buf(self);
1379 r = _BufferedReader_fill_buffer(self);
1380 if (r == -1)
1381 return NULL;
1382 if (r == -2)
1383 r = 0;
1384 self->pos = 0;
1385 return PyBytes_FromStringAndSize(self->buffer, r);
1386}
1387
1388static PyMethodDef BufferedReader_methods[] = {
1389 /* BufferedIOMixin methods */
1390 {"flush", (PyCFunction)BufferedIOMixin_flush, METH_NOARGS},
1391 {"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS},
1392 {"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS},
1393 {"readable", (PyCFunction)BufferedIOMixin_readable, METH_NOARGS},
1394 {"writable", (PyCFunction)BufferedIOMixin_writable, METH_NOARGS},
1395 {"fileno", (PyCFunction)BufferedIOMixin_fileno, METH_NOARGS},
1396 {"isatty", (PyCFunction)BufferedIOMixin_isatty, METH_NOARGS},
1397
1398 {"read", (PyCFunction)Buffered_read, METH_VARARGS},
1399 {"peek", (PyCFunction)Buffered_peek, METH_VARARGS},
1400 {"read1", (PyCFunction)Buffered_read1, METH_VARARGS},
1401 {"readline", (PyCFunction)Buffered_readline, METH_VARARGS},
1402 {"seek", (PyCFunction)Buffered_seek, METH_VARARGS},
1403 {"tell", (PyCFunction)Buffered_tell, METH_NOARGS},
1404 {"truncate", (PyCFunction)Buffered_truncate, METH_VARARGS},
1405 {NULL, NULL}
1406};
1407
1408static PyMemberDef BufferedReader_members[] = {
1409 {"raw", T_OBJECT, offsetof(BufferedObject, raw), 0},
1410 {NULL}
1411};
1412
1413static PyGetSetDef BufferedReader_getset[] = {
1414 {"closed", (getter)BufferedIOMixin_closed_get, NULL, NULL},
1415 {"name", (getter)BufferedIOMixin_name_get, NULL, NULL},
1416 {"mode", (getter)BufferedIOMixin_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001417 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001418};
1419
1420
1421PyTypeObject PyBufferedReader_Type = {
1422 PyVarObject_HEAD_INIT(NULL, 0)
1423 "_io.BufferedReader", /*tp_name*/
1424 sizeof(BufferedObject), /*tp_basicsize*/
1425 0, /*tp_itemsize*/
1426 (destructor)BufferedObject_dealloc, /*tp_dealloc*/
1427 0, /*tp_print*/
1428 0, /*tp_getattr*/
1429 0, /*tp_setattr*/
1430 0, /*tp_compare */
1431 0, /*tp_repr*/
1432 0, /*tp_as_number*/
1433 0, /*tp_as_sequence*/
1434 0, /*tp_as_mapping*/
1435 0, /*tp_hash */
1436 0, /*tp_call*/
1437 0, /*tp_str*/
1438 0, /*tp_getattro*/
1439 0, /*tp_setattro*/
1440 0, /*tp_as_buffer*/
1441 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1442 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1443 BufferedReader_doc, /* tp_doc */
1444 (traverseproc)Buffered_traverse, /* tp_traverse */
1445 (inquiry)Buffered_clear, /* tp_clear */
1446 0, /* tp_richcompare */
1447 offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/
1448 0, /* tp_iter */
1449 (iternextfunc)Buffered_iternext, /* tp_iternext */
1450 BufferedReader_methods, /* tp_methods */
1451 BufferedReader_members, /* tp_members */
1452 BufferedReader_getset, /* tp_getset */
1453 0, /* tp_base */
1454 0, /* tp_dict */
1455 0, /* tp_descr_get */
1456 0, /* tp_descr_set */
1457 offsetof(BufferedObject, dict), /* tp_dictoffset */
1458 (initproc)BufferedReader_init, /* tp_init */
1459 0, /* tp_alloc */
1460 PyType_GenericNew, /* tp_new */
1461};
1462
1463
Benjamin Peterson59406a92009-03-26 17:10:29 +00001464
1465static int
1466complain_about_max_buffer_size(void)
1467{
1468 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1469 "max_buffer_size is deprecated", 1) < 0)
1470 return 0;
1471 return 1;
1472}
1473
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001474/*
1475 * class BufferedWriter
1476 */
1477PyDoc_STRVAR(BufferedWriter_doc,
1478 "A buffer for a writeable sequential RawIO object.\n"
1479 "\n"
1480 "The constructor creates a BufferedWriter for the given writeable raw\n"
1481 "stream. If the buffer_size is not given, it defaults to\n"
1482 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1483 );
1484
1485static void
1486_BufferedWriter_reset_buf(BufferedObject *self)
1487{
1488 self->write_pos = 0;
1489 self->write_end = -1;
1490}
1491
1492static int
1493BufferedWriter_init(BufferedObject *self, PyObject *args, PyObject *kwds)
1494{
1495 /* TODO: properly deprecate max_buffer_size */
1496 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1497 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001498 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001499 PyObject *raw;
1500
1501 self->ok = 0;
1502
1503 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1504 &raw, &buffer_size, &max_buffer_size)) {
1505 return -1;
1506 }
1507
Benjamin Peterson59406a92009-03-26 17:10:29 +00001508 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1509 return -1;
1510
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001511 if (_PyIOBase_checkWritable(raw, Py_True) == NULL)
1512 return -1;
1513
1514 Py_CLEAR(self->raw);
1515 Py_INCREF(raw);
1516 self->raw = raw;
1517 self->readable = 0;
1518 self->writable = 1;
1519
1520 self->buffer_size = buffer_size;
1521 if (_Buffered_init(self) < 0)
1522 return -1;
1523 _BufferedWriter_reset_buf(self);
1524 self->pos = 0;
1525
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001526 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1527 Py_TYPE(raw) == &PyFileIO_Type);
1528
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001529 self->ok = 1;
1530 return 0;
1531}
1532
1533static Py_ssize_t
1534_BufferedWriter_raw_write(BufferedObject *self, char *start, Py_ssize_t len)
1535{
1536 Py_buffer buf;
1537 PyObject *memobj, *res;
1538 Py_ssize_t n;
1539 /* NOTE: the buffer needn't be released as its object is NULL. */
1540 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1541 return -1;
1542 memobj = PyMemoryView_FromBuffer(&buf);
1543 if (memobj == NULL)
1544 return -1;
1545 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1546 Py_DECREF(memobj);
1547 if (res == NULL)
1548 return -1;
1549 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1550 Py_DECREF(res);
1551 if (n < 0 || n > len) {
1552 PyErr_Format(PyExc_IOError,
1553 "raw write() returned invalid length %zd "
1554 "(should have been between 0 and %zd)", n, len);
1555 return -1;
1556 }
1557 if (n > 0 && self->abs_pos != -1)
1558 self->abs_pos += n;
1559 return n;
1560}
1561
1562/* `restore_pos` is 1 if we need to restore the raw stream position at
1563 the end, 0 otherwise. */
1564static PyObject *
1565_BufferedWriter_flush_unlocked(BufferedObject *self, int restore_pos)
1566{
1567 Py_ssize_t written = 0;
1568 Py_off_t n, rewind;
1569
1570 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1571 goto end;
1572 /* First, rewind */
1573 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1574 if (rewind != 0) {
1575 n = _Buffered_raw_seek(self, -rewind, 1);
1576 if (n < 0) {
1577 goto error;
1578 }
1579 self->raw_pos -= rewind;
1580 }
1581 while (self->write_pos < self->write_end) {
1582 n = _BufferedWriter_raw_write(self,
1583 self->buffer + self->write_pos,
1584 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1585 Py_off_t, Py_ssize_t));
1586 if (n == -1) {
1587 Py_ssize_t *w = _Buffered_check_blocking_error();
1588 if (w == NULL)
1589 goto error;
1590 self->write_pos += *w;
1591 self->raw_pos = self->write_pos;
1592 written += *w;
1593 *w = written;
1594 /* Already re-raised */
1595 goto error;
1596 }
1597 self->write_pos += n;
1598 self->raw_pos = self->write_pos;
1599 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1600 }
1601
1602 if (restore_pos) {
1603 Py_off_t forward = rewind - written;
1604 if (forward != 0) {
1605 n = _Buffered_raw_seek(self, forward, 1);
1606 if (n < 0) {
1607 goto error;
1608 }
1609 self->raw_pos += forward;
1610 }
1611 }
1612 _BufferedWriter_reset_buf(self);
1613
1614end:
1615 Py_RETURN_NONE;
1616
1617error:
1618 return NULL;
1619}
1620
1621static PyObject *
1622BufferedWriter_write(BufferedObject *self, PyObject *args)
1623{
1624 PyObject *res = NULL;
1625 Py_buffer buf;
1626 Py_ssize_t written, avail, remaining, n;
1627
1628 CHECK_INITIALIZED(self)
1629 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1630 return NULL;
1631 }
1632
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001633 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001634 PyErr_SetString(PyExc_ValueError, "write to closed file");
1635 PyBuffer_Release(&buf);
1636 return NULL;
1637 }
1638
1639 ENTER_BUFFERED(self)
1640
1641 /* Fast path: the data to write can be fully buffered. */
1642 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1643 self->pos = 0;
1644 self->raw_pos = 0;
1645 }
1646 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1647 if (buf.len <= avail) {
1648 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1649 if (!VALID_WRITE_BUFFER(self)) {
1650 self->write_pos = self->pos;
1651 }
1652 ADJUST_POSITION(self, self->pos + buf.len);
1653 if (self->pos > self->write_end)
1654 self->write_end = self->pos;
1655 written = buf.len;
1656 goto end;
1657 }
1658
1659 /* First write the current buffer */
1660 res = _BufferedWriter_flush_unlocked(self, 0);
1661 if (res == NULL) {
1662 Py_ssize_t *w = _Buffered_check_blocking_error();
1663 if (w == NULL)
1664 goto error;
1665 if (self->readable)
1666 _BufferedReader_reset_buf(self);
1667 /* Make some place by shifting the buffer. */
1668 assert(VALID_WRITE_BUFFER(self));
1669 memmove(self->buffer, self->buffer + self->write_pos,
1670 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1671 Py_off_t, Py_ssize_t));
1672 self->write_end -= self->write_pos;
1673 self->raw_pos -= self->write_pos;
1674 self->pos -= self->write_pos;
1675 self->write_pos = 0;
1676 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1677 Py_off_t, Py_ssize_t);
1678 if (buf.len <= avail) {
1679 /* Everything can be buffered */
1680 PyErr_Clear();
1681 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1682 self->write_end += buf.len;
1683 written = buf.len;
1684 goto end;
1685 }
1686 /* Buffer as much as possible. */
1687 memcpy(self->buffer + self->write_end, buf.buf, avail);
1688 self->write_end += avail;
1689 /* Already re-raised */
1690 *w = avail;
1691 goto error;
1692 }
1693 Py_CLEAR(res);
1694
1695 /* Then write buf itself. At this point the buffer has been emptied. */
1696 remaining = buf.len;
1697 written = 0;
1698 while (remaining > self->buffer_size) {
1699 n = _BufferedWriter_raw_write(
1700 self, (char *) buf.buf + written, buf.len - written);
1701 if (n == -1) {
1702 Py_ssize_t *w = _Buffered_check_blocking_error();
1703 if (w == NULL)
1704 goto error;
1705 written += *w;
1706 remaining -= *w;
1707 if (remaining > self->buffer_size) {
1708 /* Can't buffer everything, still buffer as much as possible */
1709 memcpy(self->buffer,
1710 (char *) buf.buf + written, self->buffer_size);
1711 self->raw_pos = 0;
1712 ADJUST_POSITION(self, self->buffer_size);
1713 self->write_end = self->buffer_size;
1714 *w = written + self->buffer_size;
1715 /* Already re-raised */
1716 goto error;
1717 }
1718 PyErr_Clear();
1719 break;
1720 }
1721 written += n;
1722 remaining -= n;
1723 }
1724 if (self->readable)
1725 _BufferedReader_reset_buf(self);
1726 if (remaining > 0) {
1727 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1728 written += remaining;
1729 }
1730 self->write_pos = 0;
1731 /* TODO: sanity check (remaining >= 0) */
1732 self->write_end = remaining;
1733 ADJUST_POSITION(self, remaining);
1734 self->raw_pos = 0;
1735
1736end:
1737 res = PyLong_FromSsize_t(written);
1738
1739error:
1740 LEAVE_BUFFERED(self)
1741 PyBuffer_Release(&buf);
1742 return res;
1743}
1744
1745static PyMethodDef BufferedWriter_methods[] = {
1746 /* BufferedIOMixin methods */
1747 {"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS},
1748 {"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS},
1749 {"readable", (PyCFunction)BufferedIOMixin_readable, METH_NOARGS},
1750 {"writable", (PyCFunction)BufferedIOMixin_writable, METH_NOARGS},
1751 {"fileno", (PyCFunction)BufferedIOMixin_fileno, METH_NOARGS},
1752 {"isatty", (PyCFunction)BufferedIOMixin_isatty, METH_NOARGS},
1753
1754 {"write", (PyCFunction)BufferedWriter_write, METH_VARARGS},
1755 {"truncate", (PyCFunction)Buffered_truncate, METH_VARARGS},
1756 {"flush", (PyCFunction)Buffered_flush, METH_NOARGS},
1757 {"seek", (PyCFunction)Buffered_seek, METH_VARARGS},
1758 {"tell", (PyCFunction)Buffered_tell, METH_NOARGS},
1759 {NULL, NULL}
1760};
1761
1762static PyMemberDef BufferedWriter_members[] = {
1763 {"raw", T_OBJECT, offsetof(BufferedObject, raw), 0},
1764 {NULL}
1765};
1766
1767static PyGetSetDef BufferedWriter_getset[] = {
1768 {"closed", (getter)BufferedIOMixin_closed_get, NULL, NULL},
1769 {"name", (getter)BufferedIOMixin_name_get, NULL, NULL},
1770 {"mode", (getter)BufferedIOMixin_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001771 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001772};
1773
1774
1775PyTypeObject PyBufferedWriter_Type = {
1776 PyVarObject_HEAD_INIT(NULL, 0)
1777 "_io.BufferedWriter", /*tp_name*/
1778 sizeof(BufferedObject), /*tp_basicsize*/
1779 0, /*tp_itemsize*/
1780 (destructor)BufferedObject_dealloc, /*tp_dealloc*/
1781 0, /*tp_print*/
1782 0, /*tp_getattr*/
1783 0, /*tp_setattr*/
1784 0, /*tp_compare */
1785 0, /*tp_repr*/
1786 0, /*tp_as_number*/
1787 0, /*tp_as_sequence*/
1788 0, /*tp_as_mapping*/
1789 0, /*tp_hash */
1790 0, /*tp_call*/
1791 0, /*tp_str*/
1792 0, /*tp_getattro*/
1793 0, /*tp_setattro*/
1794 0, /*tp_as_buffer*/
1795 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1796 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1797 BufferedWriter_doc, /* tp_doc */
1798 (traverseproc)Buffered_traverse, /* tp_traverse */
1799 (inquiry)Buffered_clear, /* tp_clear */
1800 0, /* tp_richcompare */
1801 offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/
1802 0, /* tp_iter */
1803 0, /* tp_iternext */
1804 BufferedWriter_methods, /* tp_methods */
1805 BufferedWriter_members, /* tp_members */
1806 BufferedWriter_getset, /* tp_getset */
1807 0, /* tp_base */
1808 0, /* tp_dict */
1809 0, /* tp_descr_get */
1810 0, /* tp_descr_set */
1811 offsetof(BufferedObject, dict), /* tp_dictoffset */
1812 (initproc)BufferedWriter_init, /* tp_init */
1813 0, /* tp_alloc */
1814 PyType_GenericNew, /* tp_new */
1815};
1816
1817
1818
1819/*
1820 * BufferedRWPair
1821 */
1822
1823PyDoc_STRVAR(BufferedRWPair_doc,
1824 "A buffered reader and writer object together.\n"
1825 "\n"
1826 "A buffered reader object and buffered writer object put together to\n"
1827 "form a sequential IO object that can read and write. This is typically\n"
1828 "used with a socket or two-way pipe.\n"
1829 "\n"
1830 "reader and writer are RawIOBase objects that are readable and\n"
1831 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00001832 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001833 );
1834
1835/* XXX The usefulness of this (compared to having two separate IO objects) is
1836 * questionable.
1837 */
1838
1839typedef struct {
1840 PyObject_HEAD
1841 BufferedObject *reader;
1842 BufferedObject *writer;
1843 PyObject *dict;
1844 PyObject *weakreflist;
1845} BufferedRWPairObject;
1846
1847static int
1848BufferedRWPair_init(BufferedRWPairObject *self, PyObject *args,
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001849 PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001850{
1851 PyObject *reader, *writer;
1852 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001853 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001854
1855 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1856 &buffer_size, &max_buffer_size)) {
1857 return -1;
1858 }
1859
Benjamin Peterson59406a92009-03-26 17:10:29 +00001860 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1861 return -1;
1862
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001863 if (_PyIOBase_checkReadable(reader, Py_True) == NULL)
1864 return -1;
1865 if (_PyIOBase_checkWritable(writer, Py_True) == NULL)
1866 return -1;
1867
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001868 self->reader = (BufferedObject *) PyObject_CallFunction(
1869 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001870 if (self->reader == NULL)
1871 return -1;
1872
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001873 self->writer = (BufferedObject *) PyObject_CallFunction(
1874 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001875 if (self->writer == NULL) {
1876 Py_CLEAR(self->reader);
1877 return -1;
1878 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001879
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001880 return 0;
1881}
1882
1883static int
1884BufferedRWPair_traverse(BufferedRWPairObject *self, visitproc visit, void *arg)
1885{
1886 Py_VISIT(self->dict);
1887 return 0;
1888}
1889
1890static int
1891BufferedRWPair_clear(BufferedRWPairObject *self)
1892{
1893 Py_CLEAR(self->reader);
1894 Py_CLEAR(self->writer);
1895 Py_CLEAR(self->dict);
1896 return 0;
1897}
1898
1899static void
1900BufferedRWPair_dealloc(BufferedRWPairObject *self)
1901{
1902 _PyObject_GC_UNTRACK(self);
1903 Py_CLEAR(self->reader);
1904 Py_CLEAR(self->writer);
1905 Py_CLEAR(self->dict);
1906 Py_TYPE(self)->tp_free((PyObject *) self);
1907}
1908
1909static PyObject *
1910_forward_call(BufferedObject *self, const char *name, PyObject *args)
1911{
1912 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
1913 PyObject *ret;
1914
1915 if (func == NULL) {
1916 PyErr_SetString(PyExc_AttributeError, name);
1917 return NULL;
1918 }
1919
1920 ret = PyObject_CallObject(func, args);
1921 Py_DECREF(func);
1922 return ret;
1923}
1924
1925static PyObject *
1926BufferedRWPair_read(BufferedRWPairObject *self, PyObject *args)
1927{
1928 return _forward_call(self->reader, "read", args);
1929}
1930
1931static PyObject *
1932BufferedRWPair_peek(BufferedRWPairObject *self, PyObject *args)
1933{
1934 return _forward_call(self->reader, "peek", args);
1935}
1936
1937static PyObject *
1938BufferedRWPair_read1(BufferedRWPairObject *self, PyObject *args)
1939{
1940 return _forward_call(self->reader, "read1", args);
1941}
1942
1943static PyObject *
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001944BufferedRWPair_readinto(BufferedRWPairObject *self, PyObject *args)
1945{
1946 return _forward_call(self->reader, "readinto", args);
1947}
1948
1949static PyObject *
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001950BufferedRWPair_write(BufferedRWPairObject *self, PyObject *args)
1951{
1952 return _forward_call(self->writer, "write", args);
1953}
1954
1955static PyObject *
1956BufferedRWPair_flush(BufferedRWPairObject *self, PyObject *args)
1957{
1958 return _forward_call(self->writer, "flush", args);
1959}
1960
1961static PyObject *
1962BufferedRWPair_readable(BufferedRWPairObject *self, PyObject *args)
1963{
1964 return _forward_call(self->reader, "readable", args);
1965}
1966
1967static PyObject *
1968BufferedRWPair_writable(BufferedRWPairObject *self, PyObject *args)
1969{
1970 return _forward_call(self->writer, "writable", args);
1971}
1972
1973static PyObject *
1974BufferedRWPair_close(BufferedRWPairObject *self, PyObject *args)
1975{
1976 PyObject *ret = _forward_call(self->writer, "close", args);
1977 if (ret == NULL)
1978 return NULL;
1979 Py_DECREF(ret);
1980
1981 return _forward_call(self->reader, "close", args);
1982}
1983
1984static PyObject *
1985BufferedRWPair_isatty(BufferedRWPairObject *self, PyObject *args)
1986{
1987 PyObject *ret = _forward_call(self->writer, "isatty", args);
1988
1989 if (ret != Py_False) {
1990 /* either True or exception */
1991 return ret;
1992 }
1993 Py_DECREF(ret);
1994
1995 return _forward_call(self->reader, "isatty", args);
1996}
1997
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001998static PyObject *
1999BufferedRWPair_closed_get(BufferedRWPairObject *self, void *context)
2000{
2001 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2002}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002003
2004static PyMethodDef BufferedRWPair_methods[] = {
2005 {"read", (PyCFunction)BufferedRWPair_read, METH_VARARGS},
2006 {"peek", (PyCFunction)BufferedRWPair_peek, METH_VARARGS},
2007 {"read1", (PyCFunction)BufferedRWPair_read1, METH_VARARGS},
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002008 {"readinto", (PyCFunction)BufferedRWPair_readinto, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002009
2010 {"write", (PyCFunction)BufferedRWPair_write, METH_VARARGS},
2011 {"flush", (PyCFunction)BufferedRWPair_flush, METH_NOARGS},
2012
2013 {"readable", (PyCFunction)BufferedRWPair_readable, METH_NOARGS},
2014 {"writable", (PyCFunction)BufferedRWPair_writable, METH_NOARGS},
2015
2016 {"close", (PyCFunction)BufferedRWPair_close, METH_NOARGS},
2017 {"isatty", (PyCFunction)BufferedRWPair_isatty, METH_NOARGS},
2018
2019 {NULL, NULL}
2020};
2021
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002022static PyGetSetDef BufferedRWPair_getset[] = {
2023 {"closed", (getter)BufferedRWPair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002024 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002025};
2026
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002027PyTypeObject PyBufferedRWPair_Type = {
2028 PyVarObject_HEAD_INIT(NULL, 0)
2029 "_io.BufferedRWPair", /*tp_name*/
2030 sizeof(BufferedRWPairObject), /*tp_basicsize*/
2031 0, /*tp_itemsize*/
2032 (destructor)BufferedRWPair_dealloc, /*tp_dealloc*/
2033 0, /*tp_print*/
2034 0, /*tp_getattr*/
2035 0, /*tp_setattr*/
2036 0, /*tp_compare */
2037 0, /*tp_repr*/
2038 0, /*tp_as_number*/
2039 0, /*tp_as_sequence*/
2040 0, /*tp_as_mapping*/
2041 0, /*tp_hash */
2042 0, /*tp_call*/
2043 0, /*tp_str*/
2044 0, /*tp_getattro*/
2045 0, /*tp_setattro*/
2046 0, /*tp_as_buffer*/
2047 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2048 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
2049 BufferedRWPair_doc, /* tp_doc */
2050 (traverseproc)BufferedRWPair_traverse, /* tp_traverse */
2051 (inquiry)BufferedRWPair_clear, /* tp_clear */
2052 0, /* tp_richcompare */
2053 offsetof(BufferedRWPairObject, weakreflist), /*tp_weaklistoffset*/
2054 0, /* tp_iter */
2055 0, /* tp_iternext */
2056 BufferedRWPair_methods, /* tp_methods */
2057 0, /* tp_members */
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002058 BufferedRWPair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002059 0, /* tp_base */
2060 0, /* tp_dict */
2061 0, /* tp_descr_get */
2062 0, /* tp_descr_set */
2063 offsetof(BufferedRWPairObject, dict), /* tp_dictoffset */
2064 (initproc)BufferedRWPair_init, /* tp_init */
2065 0, /* tp_alloc */
2066 PyType_GenericNew, /* tp_new */
2067};
2068
2069
2070
2071/*
2072 * BufferedRandom
2073 */
2074
2075PyDoc_STRVAR(BufferedRandom_doc,
2076 "A buffered interface to random access streams.\n"
2077 "\n"
2078 "The constructor creates a reader and writer for a seekable stream,\n"
2079 "raw, given in the first argument. If the buffer_size is omitted it\n"
2080 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2081 );
2082
2083static int
2084BufferedRandom_init(BufferedObject *self, PyObject *args, PyObject *kwds)
2085{
2086 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2087 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002088 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002089 PyObject *raw;
2090
2091 self->ok = 0;
2092
2093 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2094 &raw, &buffer_size, &max_buffer_size)) {
2095 return -1;
2096 }
2097
Benjamin Peterson59406a92009-03-26 17:10:29 +00002098 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2099 return -1;
2100
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002101 if (_PyIOBase_checkSeekable(raw, Py_True) == NULL)
2102 return -1;
2103 if (_PyIOBase_checkReadable(raw, Py_True) == NULL)
2104 return -1;
2105 if (_PyIOBase_checkWritable(raw, Py_True) == NULL)
2106 return -1;
2107
2108 Py_CLEAR(self->raw);
2109 Py_INCREF(raw);
2110 self->raw = raw;
2111 self->buffer_size = buffer_size;
2112 self->readable = 1;
2113 self->writable = 1;
2114
2115 if (_Buffered_init(self) < 0)
2116 return -1;
2117 _BufferedReader_reset_buf(self);
2118 _BufferedWriter_reset_buf(self);
2119 self->pos = 0;
2120
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002121 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2122 Py_TYPE(raw) == &PyFileIO_Type);
2123
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002124 self->ok = 1;
2125 return 0;
2126}
2127
2128static PyMethodDef BufferedRandom_methods[] = {
2129 /* BufferedIOMixin methods */
2130 {"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS},
2131 {"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS},
2132 {"readable", (PyCFunction)BufferedIOMixin_readable, METH_NOARGS},
2133 {"writable", (PyCFunction)BufferedIOMixin_writable, METH_NOARGS},
2134 {"fileno", (PyCFunction)BufferedIOMixin_fileno, METH_NOARGS},
2135 {"isatty", (PyCFunction)BufferedIOMixin_isatty, METH_NOARGS},
2136
2137 {"flush", (PyCFunction)Buffered_flush, METH_NOARGS},
2138
2139 {"seek", (PyCFunction)Buffered_seek, METH_VARARGS},
2140 {"tell", (PyCFunction)Buffered_tell, METH_NOARGS},
2141 {"truncate", (PyCFunction)Buffered_truncate, METH_VARARGS},
2142 {"read", (PyCFunction)Buffered_read, METH_VARARGS},
2143 {"read1", (PyCFunction)Buffered_read1, METH_VARARGS},
2144 {"readinto", (PyCFunction)Buffered_readinto, METH_VARARGS},
2145 {"readline", (PyCFunction)Buffered_readline, METH_VARARGS},
2146 {"peek", (PyCFunction)Buffered_peek, METH_VARARGS},
2147 {"write", (PyCFunction)BufferedWriter_write, METH_VARARGS},
2148 {NULL, NULL}
2149};
2150
2151static PyMemberDef BufferedRandom_members[] = {
2152 {"raw", T_OBJECT, offsetof(BufferedObject, raw), 0},
2153 {NULL}
2154};
2155
2156static PyGetSetDef BufferedRandom_getset[] = {
2157 {"closed", (getter)BufferedIOMixin_closed_get, NULL, NULL},
2158 {"name", (getter)BufferedIOMixin_name_get, NULL, NULL},
2159 {"mode", (getter)BufferedIOMixin_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002160 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002161};
2162
2163
2164PyTypeObject PyBufferedRandom_Type = {
2165 PyVarObject_HEAD_INIT(NULL, 0)
2166 "_io.BufferedRandom", /*tp_name*/
2167 sizeof(BufferedObject), /*tp_basicsize*/
2168 0, /*tp_itemsize*/
2169 (destructor)BufferedObject_dealloc, /*tp_dealloc*/
2170 0, /*tp_print*/
2171 0, /*tp_getattr*/
2172 0, /*tp_setattr*/
2173 0, /*tp_compare */
2174 0, /*tp_repr*/
2175 0, /*tp_as_number*/
2176 0, /*tp_as_sequence*/
2177 0, /*tp_as_mapping*/
2178 0, /*tp_hash */
2179 0, /*tp_call*/
2180 0, /*tp_str*/
2181 0, /*tp_getattro*/
2182 0, /*tp_setattro*/
2183 0, /*tp_as_buffer*/
2184 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2185 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2186 BufferedRandom_doc, /* tp_doc */
2187 (traverseproc)Buffered_traverse, /* tp_traverse */
2188 (inquiry)Buffered_clear, /* tp_clear */
2189 0, /* tp_richcompare */
2190 offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/
2191 0, /* tp_iter */
2192 (iternextfunc)Buffered_iternext, /* tp_iternext */
2193 BufferedRandom_methods, /* tp_methods */
2194 BufferedRandom_members, /* tp_members */
2195 BufferedRandom_getset, /* tp_getset */
2196 0, /* tp_base */
2197 0, /*tp_dict*/
2198 0, /* tp_descr_get */
2199 0, /* tp_descr_set */
2200 offsetof(BufferedObject, dict), /*tp_dictoffset*/
2201 (initproc)BufferedRandom_init, /* tp_init */
2202 0, /* tp_alloc */
2203 PyType_GenericNew, /* tp_new */
2204};
2205