blob: 2c652078ee671ad94d6538feab0b9681687a6b3c [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
Benjamin Petersond2e0c792009-05-01 20:40:59 +000076PyDoc_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
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000088PyDoc_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[] = {
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000142 {"detach", (PyCFunction)BufferedIOBase_detach, METH_NOARGS, BufferedIOBase_detach_doc},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000143 {"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};
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000190
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000191
192typedef struct {
193 PyObject_HEAD
194
195 PyObject *raw;
196 int ok; /* Initialized? */
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000197 int detached;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000198 int readable;
199 int writable;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000200
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;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000204
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
Georg Brandldfd73442009-04-05 11:47:34 +0000225#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000226 PyThread_type_lock lock;
Georg Brandldfd73442009-04-05 11:47:34 +0000227#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000228
229 Py_ssize_t buffer_size;
230 Py_ssize_t buffer_mask;
231
232 PyObject *dict;
233 PyObject *weakreflist;
234} BufferedObject;
235
236/*
237 Implementation notes:
238
239 * BufferedReader, BufferedWriter and BufferedRandom try to share most
240 methods (this is helped by the members `readable` and `writable`, which
241 are initialized in the respective constructors)
242 * They also share a single buffer for reading and writing. This enables
243 interleaved reads and writes without flushing. It also makes the logic
244 a bit trickier to get right.
245 * The absolute position of the raw stream is cached, if possible, in the
246 `abs_pos` member. It must be updated every time an operation is done
247 on the raw stream. If not sure, it can be reinitialized by calling
248 _Buffered_raw_tell(), which queries the raw stream (_Buffered_raw_seek()
249 also does it). To read it, use RAW_TELL().
250 * Three helpers, _BufferedReader_raw_read, _BufferedWriter_raw_write and
251 _BufferedWriter_flush_unlocked do a lot of useful housekeeping.
252
253 NOTE: we should try to maintain block alignment of reads and writes to the
254 raw stream (according to the buffer size), but for now it is only done
255 in read() and friends.
256
257 XXX: method naming is a bit messy.
258*/
259
260/* These macros protect the BufferedObject against concurrent operations. */
261
Georg Brandldfd73442009-04-05 11:47:34 +0000262#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000263#define ENTER_BUFFERED(self) \
264 Py_BEGIN_ALLOW_THREADS \
265 PyThread_acquire_lock(self->lock, 1); \
266 Py_END_ALLOW_THREADS
267
268#define LEAVE_BUFFERED(self) \
269 PyThread_release_lock(self->lock);
Georg Brandldfd73442009-04-05 11:47:34 +0000270#else
271#define ENTER_BUFFERED(self)
272#define LEAVE_BUFFERED(self)
273#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000274
275#define CHECK_INITIALIZED(self) \
276 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000277 if (self->detached) { \
278 PyErr_SetString(PyExc_ValueError, \
279 "raw stream has been detached"); \
280 } else { \
281 PyErr_SetString(PyExc_ValueError, \
282 "I/O operation on uninitialized object"); \
283 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000284 return NULL; \
285 }
286
287#define CHECK_INITIALIZED_INT(self) \
288 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000289 if (self->detached) { \
290 PyErr_SetString(PyExc_ValueError, \
291 "raw stream has been detached"); \
292 } else { \
293 PyErr_SetString(PyExc_ValueError, \
294 "I/O operation on uninitialized object"); \
295 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000296 return -1; \
297 }
298
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000299#define IS_CLOSED(self) \
300 (self->fast_closed_checks \
301 ? _PyFileIO_closed(self->raw) \
302 : BufferedIOMixin_closed(self))
303
304#define CHECK_CLOSED(self, error_msg) \
305 if (IS_CLOSED(self)) { \
306 PyErr_SetString(PyExc_ValueError, error_msg); \
307 return NULL; \
308 }
309
310
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000311#define VALID_READ_BUFFER(self) \
312 (self->readable && self->read_end != -1)
313
314#define VALID_WRITE_BUFFER(self) \
315 (self->writable && self->write_end != -1)
316
317#define ADJUST_POSITION(self, _new_pos) \
318 do { \
319 self->pos = _new_pos; \
320 if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
321 self->read_end = self->pos; \
322 } while(0)
323
324#define READAHEAD(self) \
325 ((self->readable && VALID_READ_BUFFER(self)) \
326 ? (self->read_end - self->pos) : 0)
327
328#define RAW_OFFSET(self) \
329 (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
330 && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
331
332#define RAW_TELL(self) \
333 (self->abs_pos != -1 ? self->abs_pos : _Buffered_raw_tell(self))
334
335#define MINUS_LAST_BLOCK(self, size) \
336 (self->buffer_mask ? \
337 (size & ~self->buffer_mask) : \
338 (self->buffer_size * (size / self->buffer_size)))
339
340
341static void
342BufferedObject_dealloc(BufferedObject *self)
343{
344 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
345 return;
346 _PyObject_GC_UNTRACK(self);
347 self->ok = 0;
348 if (self->weakreflist != NULL)
349 PyObject_ClearWeakRefs((PyObject *)self);
350 Py_CLEAR(self->raw);
351 if (self->buffer) {
352 PyMem_Free(self->buffer);
353 self->buffer = NULL;
354 }
Georg Brandldfd73442009-04-05 11:47:34 +0000355#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000356 if (self->lock) {
357 PyThread_free_lock(self->lock);
358 self->lock = NULL;
359 }
Georg Brandldfd73442009-04-05 11:47:34 +0000360#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000361 Py_CLEAR(self->dict);
362 Py_TYPE(self)->tp_free((PyObject *)self);
363}
364
365static int
366Buffered_traverse(BufferedObject *self, visitproc visit, void *arg)
367{
368 Py_VISIT(self->raw);
369 Py_VISIT(self->dict);
370 return 0;
371}
372
373static int
374Buffered_clear(BufferedObject *self)
375{
376 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
377 return -1;
378 self->ok = 0;
379 Py_CLEAR(self->raw);
380 Py_CLEAR(self->dict);
381 return 0;
382}
383
384/*
385 * _BufferedIOMixin methods
386 * This is not a class, just a collection of methods that will be reused
387 * by BufferedReader and BufferedWriter
388 */
389
390/* Flush and close */
391
392static PyObject *
393BufferedIOMixin_flush(BufferedObject *self, PyObject *args)
394{
395 CHECK_INITIALIZED(self)
396 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
397}
398
399static int
400BufferedIOMixin_closed(BufferedObject *self)
401{
402 int closed;
403 PyObject *res;
404 CHECK_INITIALIZED_INT(self)
405 res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
406 if (res == NULL)
407 return -1;
408 closed = PyObject_IsTrue(res);
409 Py_DECREF(res);
410 return closed;
411}
412
413static PyObject *
414BufferedIOMixin_closed_get(BufferedObject *self, void *context)
415{
416 CHECK_INITIALIZED(self)
417 return PyObject_GetAttr(self->raw, _PyIO_str_closed);
418}
419
420static PyObject *
421BufferedIOMixin_close(BufferedObject *self, PyObject *args)
422{
423 PyObject *res = NULL;
424 int r;
425
426 CHECK_INITIALIZED(self)
427 ENTER_BUFFERED(self)
428
429 r = BufferedIOMixin_closed(self);
430 if (r < 0)
431 goto end;
432 if (r > 0) {
433 res = Py_None;
434 Py_INCREF(res);
435 goto end;
436 }
437 /* flush() will most probably re-take the lock, so drop it first */
438 LEAVE_BUFFERED(self)
439 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
440 ENTER_BUFFERED(self)
441 if (res == NULL) {
442 /* If flush() fails, just give up */
443 if (PyErr_ExceptionMatches(PyExc_IOError))
444 PyErr_Clear();
445 else
446 goto end;
447 }
448 Py_XDECREF(res);
449
450 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
451
452end:
453 LEAVE_BUFFERED(self)
454 return res;
455}
456
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000457/* detach */
458
459static PyObject *
460BufferedIOMixin_detach(BufferedObject *self, PyObject *args)
461{
462 PyObject *raw, *res;
463 CHECK_INITIALIZED(self)
464 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
465 if (res == NULL)
466 return NULL;
467 Py_DECREF(res);
468 raw = self->raw;
469 self->raw = NULL;
470 self->detached = 1;
471 self->ok = 0;
472 return raw;
473}
474
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000475/* Inquiries */
476
477static PyObject *
478BufferedIOMixin_seekable(BufferedObject *self, PyObject *args)
479{
480 CHECK_INITIALIZED(self)
481 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
482}
483
484static PyObject *
485BufferedIOMixin_readable(BufferedObject *self, PyObject *args)
486{
487 CHECK_INITIALIZED(self)
488 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
489}
490
491static PyObject *
492BufferedIOMixin_writable(BufferedObject *self, PyObject *args)
493{
494 CHECK_INITIALIZED(self)
495 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
496}
497
498static PyObject *
499BufferedIOMixin_name_get(BufferedObject *self, void *context)
500{
501 CHECK_INITIALIZED(self)
502 return PyObject_GetAttrString(self->raw, "name");
503}
504
505static PyObject *
506BufferedIOMixin_mode_get(BufferedObject *self, void *context)
507{
508 CHECK_INITIALIZED(self)
509 return PyObject_GetAttrString(self->raw, "mode");
510}
511
512/* Lower-level APIs */
513
514static PyObject *
515BufferedIOMixin_fileno(BufferedObject *self, PyObject *args)
516{
517 CHECK_INITIALIZED(self)
518 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
519}
520
521static PyObject *
522BufferedIOMixin_isatty(BufferedObject *self, PyObject *args)
523{
524 CHECK_INITIALIZED(self)
525 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
526}
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000527
528
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000529/* Forward decls */
530static PyObject *
531_BufferedWriter_flush_unlocked(BufferedObject *, int);
532static Py_ssize_t
533_BufferedReader_fill_buffer(BufferedObject *self);
534static void
535_BufferedReader_reset_buf(BufferedObject *self);
536static void
537_BufferedWriter_reset_buf(BufferedObject *self);
538static PyObject *
539_BufferedReader_peek_unlocked(BufferedObject *self, Py_ssize_t);
540static PyObject *
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000541_BufferedReader_read_all(BufferedObject *self);
542static PyObject *
543_BufferedReader_read_fast(BufferedObject *self, Py_ssize_t);
544static PyObject *
545_BufferedReader_read_generic(BufferedObject *self, Py_ssize_t);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000546
547
548/*
549 * Helpers
550 */
551
552/* Returns the address of the `written` member if a BlockingIOError was
553 raised, NULL otherwise. The error is always re-raised. */
554static Py_ssize_t *
555_Buffered_check_blocking_error(void)
556{
557 PyObject *t, *v, *tb;
558 PyBlockingIOErrorObject *err;
559
560 PyErr_Fetch(&t, &v, &tb);
561 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
562 PyErr_Restore(t, v, tb);
563 return NULL;
564 }
565 err = (PyBlockingIOErrorObject *) v;
566 /* TODO: sanity check (err->written >= 0) */
567 PyErr_Restore(t, v, tb);
568 return &err->written;
569}
570
571static Py_off_t
572_Buffered_raw_tell(BufferedObject *self)
573{
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000574 Py_off_t n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000575 PyObject *res;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000576 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
577 if (res == NULL)
578 return -1;
579 n = PyNumber_AsOff_t(res, PyExc_ValueError);
580 Py_DECREF(res);
581 if (n < 0) {
582 if (!PyErr_Occurred())
583 PyErr_Format(PyExc_IOError,
584 "Raw stream returned invalid position %zd", n);
585 return -1;
586 }
587 self->abs_pos = n;
588 return n;
589}
590
591static Py_off_t
592_Buffered_raw_seek(BufferedObject *self, Py_off_t target, int whence)
593{
594 PyObject *res, *posobj, *whenceobj;
595 Py_off_t n;
596
597 posobj = PyLong_FromOff_t(target);
598 if (posobj == NULL)
599 return -1;
600 whenceobj = PyLong_FromLong(whence);
601 if (whenceobj == NULL) {
602 Py_DECREF(posobj);
603 return -1;
604 }
605 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
606 posobj, whenceobj, NULL);
607 Py_DECREF(posobj);
608 Py_DECREF(whenceobj);
609 if (res == NULL)
610 return -1;
611 n = PyNumber_AsOff_t(res, PyExc_ValueError);
612 Py_DECREF(res);
613 if (n < 0) {
614 if (!PyErr_Occurred())
615 PyErr_Format(PyExc_IOError,
616 "Raw stream returned invalid position %zd", n);
617 return -1;
618 }
619 self->abs_pos = n;
620 return n;
621}
622
623static int
624_Buffered_init(BufferedObject *self)
625{
626 Py_ssize_t n;
627 if (self->buffer_size <= 0) {
628 PyErr_SetString(PyExc_ValueError,
629 "buffer size must be strictly positive");
630 return -1;
631 }
632 if (self->buffer)
633 PyMem_Free(self->buffer);
634 self->buffer = PyMem_Malloc(self->buffer_size);
635 if (self->buffer == NULL) {
636 PyErr_NoMemory();
637 return -1;
638 }
Georg Brandldfd73442009-04-05 11:47:34 +0000639#ifdef WITH_THREAD
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000640 self->lock = PyThread_allocate_lock();
641 if (self->lock == NULL) {
642 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
643 return -1;
644 }
Georg Brandldfd73442009-04-05 11:47:34 +0000645#endif
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000646 /* Find out whether buffer_size is a power of 2 */
647 /* XXX is this optimization useful? */
648 for (n = self->buffer_size - 1; n & 1; n >>= 1)
649 ;
650 if (n == 0)
651 self->buffer_mask = self->buffer_size - 1;
652 else
653 self->buffer_mask = 0;
654 if (_Buffered_raw_tell(self) == -1)
655 PyErr_Clear();
656 return 0;
657}
658
659/*
660 * Shared methods and wrappers
661 */
662
663static PyObject *
664Buffered_flush(BufferedObject *self, PyObject *args)
665{
666 PyObject *res;
667
668 CHECK_INITIALIZED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000669 CHECK_CLOSED(self, "flush of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000670
671 ENTER_BUFFERED(self)
672 res = _BufferedWriter_flush_unlocked(self, 0);
673 if (res != NULL && self->readable) {
674 /* Rewind the raw stream so that its position corresponds to
675 the current logical position. */
676 Py_off_t n;
677 n = _Buffered_raw_seek(self, -RAW_OFFSET(self), 1);
678 if (n == -1)
679 Py_CLEAR(res);
680 _BufferedReader_reset_buf(self);
681 }
682 LEAVE_BUFFERED(self)
683
684 return res;
685}
686
687static PyObject *
688Buffered_peek(BufferedObject *self, PyObject *args)
689{
690 Py_ssize_t n = 0;
691 PyObject *res = NULL;
692
693 CHECK_INITIALIZED(self)
694 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
695 return NULL;
696 }
697
698 ENTER_BUFFERED(self)
699
700 if (self->writable) {
701 res = _BufferedWriter_flush_unlocked(self, 1);
702 if (res == NULL)
703 goto end;
704 Py_CLEAR(res);
705 }
706 res = _BufferedReader_peek_unlocked(self, n);
707
708end:
709 LEAVE_BUFFERED(self)
710 return res;
711}
712
713static PyObject *
714Buffered_read(BufferedObject *self, PyObject *args)
715{
716 Py_ssize_t n = -1;
717 PyObject *res;
718
719 CHECK_INITIALIZED(self)
720 if (!PyArg_ParseTuple(args, "|n:read", &n)) {
721 return NULL;
722 }
723 if (n < -1) {
724 PyErr_SetString(PyExc_ValueError,
725 "read length must be positive or -1");
726 return NULL;
727 }
728
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000729 CHECK_CLOSED(self, "read of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000730
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000731 if (n == -1) {
732 /* The number of bytes is unspecified, read until the end of stream */
733 ENTER_BUFFERED(self)
734 res = _BufferedReader_read_all(self);
735 LEAVE_BUFFERED(self)
736 }
737 else {
738 res = _BufferedReader_read_fast(self, n);
739 if (res == Py_None) {
740 Py_DECREF(res);
741 ENTER_BUFFERED(self)
742 res = _BufferedReader_read_generic(self, n);
743 LEAVE_BUFFERED(self)
744 }
745 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000746
747 return res;
748}
749
750static PyObject *
751Buffered_read1(BufferedObject *self, PyObject *args)
752{
753 Py_ssize_t n, have, r;
754 PyObject *res = NULL;
755
756 CHECK_INITIALIZED(self)
757 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
758 return NULL;
759 }
760
761 if (n < 0) {
762 PyErr_SetString(PyExc_ValueError,
763 "read length must be positive");
764 return NULL;
765 }
766 if (n == 0)
767 return PyBytes_FromStringAndSize(NULL, 0);
768
769 ENTER_BUFFERED(self)
770
771 if (self->writable) {
772 res = _BufferedWriter_flush_unlocked(self, 1);
773 if (res == NULL)
774 goto end;
775 Py_CLEAR(res);
776 }
777
778 /* Return up to n bytes. If at least one byte is buffered, we
779 only return buffered bytes. Otherwise, we do one raw read. */
780
781 /* XXX: this mimicks the io.py implementation but is probably wrong.
782 If we need to read from the raw stream, then we could actually read
783 all `n` bytes asked by the caller (and possibly more, so as to fill
784 our buffer for the next reads). */
785
786 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
787 if (have > 0) {
788 if (n > have)
789 n = have;
790 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
791 if (res == NULL)
792 goto end;
793 self->pos += n;
794 goto end;
795 }
796
797 /* Fill the buffer from the raw stream, and copy it to the result. */
798 _BufferedReader_reset_buf(self);
799 r = _BufferedReader_fill_buffer(self);
800 if (r == -1)
801 goto end;
802 if (r == -2)
803 r = 0;
804 if (n > r)
805 n = r;
806 res = PyBytes_FromStringAndSize(self->buffer, n);
807 if (res == NULL)
808 goto end;
809 self->pos = n;
810
811end:
812 LEAVE_BUFFERED(self)
813 return res;
814}
815
816static PyObject *
817Buffered_readinto(BufferedObject *self, PyObject *args)
818{
819 PyObject *res = NULL;
820
821 CHECK_INITIALIZED(self)
822
823 /* TODO: use raw.readinto() instead! */
824 if (self->writable) {
825 ENTER_BUFFERED(self)
826 res = _BufferedWriter_flush_unlocked(self, 0);
827 LEAVE_BUFFERED(self)
828 if (res == NULL)
829 goto end;
830 Py_DECREF(res);
831 }
832 res = BufferedIOBase_readinto((PyObject *)self, args);
833
834end:
835 return res;
836}
837
838static PyObject *
839_Buffered_readline(BufferedObject *self, Py_ssize_t limit)
840{
841 PyObject *res = NULL;
842 PyObject *chunks = NULL;
843 Py_ssize_t n, written = 0;
844 const char *start, *s, *end;
845
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000846 CHECK_CLOSED(self, "readline of closed file")
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000847
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000848 /* First, try to find a line in the buffer. This can run unlocked because
849 the calls to the C API are simple enough that they can't trigger
850 any thread switch. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000851 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
852 if (limit >= 0 && n > limit)
853 n = limit;
854 start = self->buffer + self->pos;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000855 s = memchr(start, '\n', n);
856 if (s != NULL) {
857 res = PyBytes_FromStringAndSize(start, s - start + 1);
858 if (res != NULL)
859 self->pos += s - start + 1;
860 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000861 }
862 if (n == limit) {
863 res = PyBytes_FromStringAndSize(start, n);
864 if (res != NULL)
865 self->pos += n;
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000866 goto end_unlocked;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000867 }
868
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000869 ENTER_BUFFERED(self)
870
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000871 /* Now we try to get some more from the raw stream */
872 if (self->writable) {
873 res = _BufferedWriter_flush_unlocked(self, 1);
874 if (res == NULL)
875 goto end;
876 Py_CLEAR(res);
877 }
878 chunks = PyList_New(0);
879 if (chunks == NULL)
880 goto end;
881 if (n > 0) {
882 res = PyBytes_FromStringAndSize(start, n);
883 if (res == NULL)
884 goto end;
885 if (PyList_Append(chunks, res) < 0) {
886 Py_CLEAR(res);
887 goto end;
888 }
889 Py_CLEAR(res);
890 written += n;
891 if (limit >= 0)
892 limit -= n;
893 }
894
895 for (;;) {
896 _BufferedReader_reset_buf(self);
897 n = _BufferedReader_fill_buffer(self);
898 if (n == -1)
899 goto end;
900 if (n <= 0)
901 break;
902 if (limit >= 0 && n > limit)
903 n = limit;
904 start = self->buffer;
905 end = start + n;
906 s = start;
907 while (s < end) {
908 if (*s++ == '\n') {
909 res = PyBytes_FromStringAndSize(start, s - start);
910 if (res == NULL)
911 goto end;
912 self->pos = s - start;
913 goto found;
914 }
915 }
916 res = PyBytes_FromStringAndSize(start, n);
917 if (res == NULL)
918 goto end;
919 if (n == limit) {
920 self->pos = n;
921 break;
922 }
923 if (PyList_Append(chunks, res) < 0) {
924 Py_CLEAR(res);
925 goto end;
926 }
927 Py_CLEAR(res);
928 written += n;
929 if (limit >= 0)
930 limit -= n;
931 }
932found:
933 if (res != NULL && PyList_Append(chunks, res) < 0) {
934 Py_CLEAR(res);
935 goto end;
936 }
937 Py_CLEAR(res);
938 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
939
940end:
941 LEAVE_BUFFERED(self)
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000942end_unlocked:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000943 Py_XDECREF(chunks);
944 return res;
945}
946
947static PyObject *
948Buffered_readline(BufferedObject *self, PyObject *args)
949{
950 Py_ssize_t limit = -1;
951
952 CHECK_INITIALIZED(self)
953
954 if (!PyArg_ParseTuple(args, "|n:readline", &limit)) {
955 return NULL;
956 }
957 return _Buffered_readline(self, limit);
958}
959
960
961static PyObject *
962Buffered_tell(BufferedObject *self, PyObject *args)
963{
964 Py_off_t pos;
965
966 CHECK_INITIALIZED(self)
967 pos = _Buffered_raw_tell(self);
968 if (pos == -1)
969 return NULL;
970 pos -= RAW_OFFSET(self);
971 /* TODO: sanity check (pos >= 0) */
972 return PyLong_FromOff_t(pos);
973}
974
975static PyObject *
976Buffered_seek(BufferedObject *self, PyObject *args)
977{
978 Py_off_t target, n;
979 int whence = 0;
980 PyObject *targetobj, *res = NULL;
981
982 CHECK_INITIALIZED(self)
983 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
984 return NULL;
985 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000986 if (whence < 0 || whence > 2) {
987 PyErr_Format(PyExc_ValueError,
988 "whence must be between 0 and 2, not %d", whence);
989 return NULL;
990 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +0000991
992 CHECK_CLOSED(self, "seek of closed file")
993
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000994 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
995 if (target == -1 && PyErr_Occurred())
996 return NULL;
997
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000998 if (whence != 2 && self->readable) {
999 Py_off_t current, avail;
1000 /* Check if seeking leaves us inside the current buffer,
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001001 so as to return quickly if possible. Also, we needn't take the
1002 lock in this fast path.
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001003 Don't know how to do that when whence == 2, though. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001004 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1005 state at this point. */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001006 current = RAW_TELL(self);
1007 avail = READAHEAD(self);
1008 if (avail > 0) {
1009 Py_off_t offset;
1010 if (whence == 0)
1011 offset = target - (current - RAW_OFFSET(self));
1012 else
1013 offset = target;
1014 if (offset >= -self->pos && offset <= avail) {
1015 self->pos += offset;
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001016 return PyLong_FromOff_t(current - avail + offset);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001017 }
1018 }
1019 }
1020
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001021 ENTER_BUFFERED(self)
1022
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001023 /* Fallback: invoke raw seek() method and clear buffer */
1024 if (self->writable) {
1025 res = _BufferedWriter_flush_unlocked(self, 0);
1026 if (res == NULL)
1027 goto end;
1028 Py_CLEAR(res);
1029 _BufferedWriter_reset_buf(self);
1030 }
1031
1032 /* TODO: align on block boundary and read buffer if needed? */
1033 if (whence == 1)
1034 target -= RAW_OFFSET(self);
1035 n = _Buffered_raw_seek(self, target, whence);
1036 if (n == -1)
1037 goto end;
1038 self->raw_pos = -1;
1039 res = PyLong_FromOff_t(n);
1040 if (res != NULL && self->readable)
1041 _BufferedReader_reset_buf(self);
1042
1043end:
1044 LEAVE_BUFFERED(self)
1045 return res;
1046}
1047
1048static PyObject *
1049Buffered_truncate(BufferedObject *self, PyObject *args)
1050{
1051 PyObject *pos = Py_None;
1052 PyObject *res = NULL;
1053
1054 CHECK_INITIALIZED(self)
1055 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1056 return NULL;
1057 }
1058
1059 ENTER_BUFFERED(self)
1060
1061 if (self->writable) {
1062 res = _BufferedWriter_flush_unlocked(self, 0);
1063 if (res == NULL)
1064 goto end;
1065 Py_CLEAR(res);
1066 }
1067 if (self->readable) {
1068 if (pos == Py_None) {
1069 /* Rewind the raw stream so that its position corresponds to
1070 the current logical position. */
1071 if (_Buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)
1072 goto end;
1073 }
1074 _BufferedReader_reset_buf(self);
1075 }
1076 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1077 if (res == NULL)
1078 goto end;
1079 /* Reset cached position */
1080 if (_Buffered_raw_tell(self) == -1)
1081 PyErr_Clear();
1082
1083end:
1084 LEAVE_BUFFERED(self)
1085 return res;
1086}
1087
1088static PyObject *
1089Buffered_iternext(BufferedObject *self)
1090{
1091 PyObject *line;
1092 PyTypeObject *tp;
1093
1094 CHECK_INITIALIZED(self);
1095
1096 tp = Py_TYPE(self);
1097 if (tp == &PyBufferedReader_Type ||
1098 tp == &PyBufferedRandom_Type) {
1099 /* Skip method call overhead for speed */
1100 line = _Buffered_readline(self, -1);
1101 }
1102 else {
1103 line = PyObject_CallMethodObjArgs((PyObject *)self,
1104 _PyIO_str_readline, NULL);
1105 if (line && !PyBytes_Check(line)) {
1106 PyErr_Format(PyExc_IOError,
1107 "readline() should have returned a bytes object, "
1108 "not '%.200s'", Py_TYPE(line)->tp_name);
1109 Py_DECREF(line);
1110 return NULL;
1111 }
1112 }
1113
1114 if (line == NULL)
1115 return NULL;
1116
1117 if (PyBytes_GET_SIZE(line) == 0) {
1118 /* Reached EOF or would have blocked */
1119 Py_DECREF(line);
1120 return NULL;
1121 }
1122
1123 return line;
1124}
1125
1126/*
1127 * class BufferedReader
1128 */
1129
1130PyDoc_STRVAR(BufferedReader_doc,
1131 "Create a new buffered reader using the given readable raw IO object.");
1132
1133static void _BufferedReader_reset_buf(BufferedObject *self)
1134{
1135 self->read_end = -1;
1136}
1137
1138static int
1139BufferedReader_init(BufferedObject *self, PyObject *args, PyObject *kwds)
1140{
1141 char *kwlist[] = {"raw", "buffer_size", NULL};
1142 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1143 PyObject *raw;
1144
1145 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001146 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001147
1148 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1149 &raw, &buffer_size)) {
1150 return -1;
1151 }
1152
1153 if (_PyIOBase_checkReadable(raw, Py_True) == NULL)
1154 return -1;
1155
1156 Py_CLEAR(self->raw);
1157 Py_INCREF(raw);
1158 self->raw = raw;
1159 self->buffer_size = buffer_size;
1160 self->readable = 1;
1161 self->writable = 0;
1162
1163 if (_Buffered_init(self) < 0)
1164 return -1;
1165 _BufferedReader_reset_buf(self);
1166
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001167 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1168 Py_TYPE(raw) == &PyFileIO_Type);
1169
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001170 self->ok = 1;
1171 return 0;
1172}
1173
1174static Py_ssize_t
1175_BufferedReader_raw_read(BufferedObject *self, char *start, Py_ssize_t len)
1176{
1177 Py_buffer buf;
1178 PyObject *memobj, *res;
1179 Py_ssize_t n;
1180 /* NOTE: the buffer needn't be released as its object is NULL. */
1181 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1182 return -1;
1183 memobj = PyMemoryView_FromBuffer(&buf);
1184 if (memobj == NULL)
1185 return -1;
1186 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1187 Py_DECREF(memobj);
1188 if (res == NULL)
1189 return -1;
1190 if (res == Py_None) {
1191 /* Non-blocking stream would have blocked. Special return code! */
1192 Py_DECREF(res);
1193 return -2;
1194 }
1195 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1196 Py_DECREF(res);
1197 if (n < 0 || n > len) {
1198 PyErr_Format(PyExc_IOError,
1199 "raw readinto() returned invalid length %zd "
1200 "(should have been between 0 and %zd)", n, len);
1201 return -1;
1202 }
1203 if (n > 0 && self->abs_pos != -1)
1204 self->abs_pos += n;
1205 return n;
1206}
1207
1208static Py_ssize_t
1209_BufferedReader_fill_buffer(BufferedObject *self)
1210{
1211 Py_ssize_t start, len, n;
1212 if (VALID_READ_BUFFER(self))
1213 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1214 else
1215 start = 0;
1216 len = self->buffer_size - start;
1217 n = _BufferedReader_raw_read(self, self->buffer + start, len);
1218 if (n <= 0)
1219 return n;
1220 self->read_end = start + n;
1221 self->raw_pos = start + n;
1222 return n;
1223}
1224
1225static PyObject *
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001226_BufferedReader_read_all(BufferedObject *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001227{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001228 Py_ssize_t current_size;
1229 PyObject *res, *data = NULL;
1230 PyObject *chunks = PyList_New(0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001231
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001232 if (chunks == NULL)
1233 return NULL;
1234
1235 /* First copy what we have in the current buffer. */
1236 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1237 if (current_size) {
1238 data = PyBytes_FromStringAndSize(
1239 self->buffer + self->pos, current_size);
1240 if (data == NULL) {
1241 Py_DECREF(chunks);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001242 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001243 }
1244 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001245 _BufferedReader_reset_buf(self);
1246 /* We're going past the buffer's bounds, flush it */
1247 if (self->writable) {
1248 res = _BufferedWriter_flush_unlocked(self, 1);
1249 if (res == NULL) {
1250 Py_DECREF(chunks);
1251 return NULL;
1252 }
1253 Py_CLEAR(res);
1254 }
1255 while (1) {
1256 if (data) {
1257 if (PyList_Append(chunks, data) < 0) {
1258 Py_DECREF(data);
1259 Py_DECREF(chunks);
1260 return NULL;
1261 }
1262 Py_DECREF(data);
1263 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001264
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001265 /* Read until EOF or until read() would block. */
1266 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1267 if (data == NULL) {
1268 Py_DECREF(chunks);
1269 return NULL;
1270 }
1271 if (data != Py_None && !PyBytes_Check(data)) {
1272 Py_DECREF(data);
1273 Py_DECREF(chunks);
1274 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1275 return NULL;
1276 }
1277 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1278 if (current_size == 0) {
1279 Py_DECREF(chunks);
1280 return data;
1281 }
1282 else {
1283 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1284 Py_DECREF(data);
1285 Py_DECREF(chunks);
1286 return res;
1287 }
1288 }
1289 current_size += PyBytes_GET_SIZE(data);
1290 if (self->abs_pos != -1)
1291 self->abs_pos += PyBytes_GET_SIZE(data);
1292 }
1293}
1294
1295/* Read n bytes from the buffer if it can, otherwise return None.
1296 This function is simple enough that it can run unlocked. */
1297static PyObject *
1298_BufferedReader_read_fast(BufferedObject *self, Py_ssize_t n)
1299{
1300 Py_ssize_t current_size;
1301
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001302 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1303 if (n <= current_size) {
1304 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001305 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1306 if (res != NULL)
1307 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001308 return res;
1309 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001310 Py_RETURN_NONE;
1311}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001312
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001313/* Generic read function: read from the stream until enough bytes are read,
1314 * or until an EOF occurs or until read() would block.
1315 */
1316static PyObject *
1317_BufferedReader_read_generic(BufferedObject *self, Py_ssize_t n)
1318{
1319 PyObject *res = NULL;
1320 Py_ssize_t current_size, remaining, written;
1321 char *out;
1322
1323 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1324 if (n <= current_size)
1325 return _BufferedReader_read_fast(self, n);
1326
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001327 res = PyBytes_FromStringAndSize(NULL, n);
1328 if (res == NULL)
1329 goto error;
1330 out = PyBytes_AS_STRING(res);
1331 remaining = n;
1332 written = 0;
1333 if (current_size > 0) {
1334 memcpy(out, self->buffer + self->pos, current_size);
1335 remaining -= current_size;
1336 written += current_size;
1337 }
1338 _BufferedReader_reset_buf(self);
1339 while (remaining > 0) {
1340 /* We want to read a whole block at the end into buffer.
1341 If we had readv() we could do this in one pass. */
1342 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1343 if (r == 0)
1344 break;
1345 r = _BufferedReader_raw_read(self, out + written, r);
1346 if (r == -1)
1347 goto error;
1348 if (r == 0 || r == -2) {
1349 /* EOF occurred or read() would block. */
1350 if (r == 0 || written > 0) {
1351 if (_PyBytes_Resize(&res, written))
1352 goto error;
1353 return res;
1354 }
1355 Py_DECREF(res);
1356 Py_INCREF(Py_None);
1357 return Py_None;
1358 }
1359 remaining -= r;
1360 written += r;
1361 }
1362 assert(remaining <= self->buffer_size);
1363 self->pos = 0;
1364 self->raw_pos = 0;
1365 self->read_end = 0;
1366 while (self->read_end < self->buffer_size) {
1367 Py_ssize_t r = _BufferedReader_fill_buffer(self);
1368 if (r == -1)
1369 goto error;
1370 if (r == 0 || r == -2) {
1371 /* EOF occurred or read() would block. */
1372 if (r == 0 || written > 0) {
1373 if (_PyBytes_Resize(&res, written))
1374 goto error;
1375 return res;
1376 }
1377 Py_DECREF(res);
1378 Py_INCREF(Py_None);
1379 return Py_None;
1380 }
1381 if (remaining > r) {
1382 memcpy(out + written, self->buffer + self->pos, r);
1383 written += r;
1384 self->pos += r;
1385 remaining -= r;
1386 }
1387 else if (remaining > 0) {
1388 memcpy(out + written, self->buffer + self->pos, remaining);
1389 written += remaining;
1390 self->pos += remaining;
1391 remaining = 0;
1392 }
1393 if (remaining == 0)
1394 break;
1395 }
1396
1397 return res;
1398
1399error:
1400 Py_XDECREF(res);
1401 return NULL;
1402}
1403
1404static PyObject *
1405_BufferedReader_peek_unlocked(BufferedObject *self, Py_ssize_t n)
1406{
1407 Py_ssize_t have, r;
1408
1409 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1410 /* Constraints:
1411 1. we don't want to advance the file position.
1412 2. we don't want to lose block alignment, so we can't shift the buffer
1413 to make some place.
1414 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1415 */
1416 if (have > 0) {
1417 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1418 }
1419
1420 /* Fill the buffer from the raw stream, and copy it to the result. */
1421 _BufferedReader_reset_buf(self);
1422 r = _BufferedReader_fill_buffer(self);
1423 if (r == -1)
1424 return NULL;
1425 if (r == -2)
1426 r = 0;
1427 self->pos = 0;
1428 return PyBytes_FromStringAndSize(self->buffer, r);
1429}
1430
1431static PyMethodDef BufferedReader_methods[] = {
1432 /* BufferedIOMixin methods */
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001433 {"detach", (PyCFunction)BufferedIOMixin_detach, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001434 {"flush", (PyCFunction)BufferedIOMixin_flush, METH_NOARGS},
1435 {"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS},
1436 {"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS},
1437 {"readable", (PyCFunction)BufferedIOMixin_readable, METH_NOARGS},
1438 {"writable", (PyCFunction)BufferedIOMixin_writable, METH_NOARGS},
1439 {"fileno", (PyCFunction)BufferedIOMixin_fileno, METH_NOARGS},
1440 {"isatty", (PyCFunction)BufferedIOMixin_isatty, METH_NOARGS},
1441
1442 {"read", (PyCFunction)Buffered_read, METH_VARARGS},
1443 {"peek", (PyCFunction)Buffered_peek, METH_VARARGS},
1444 {"read1", (PyCFunction)Buffered_read1, METH_VARARGS},
1445 {"readline", (PyCFunction)Buffered_readline, METH_VARARGS},
1446 {"seek", (PyCFunction)Buffered_seek, METH_VARARGS},
1447 {"tell", (PyCFunction)Buffered_tell, METH_NOARGS},
1448 {"truncate", (PyCFunction)Buffered_truncate, METH_VARARGS},
1449 {NULL, NULL}
1450};
1451
1452static PyMemberDef BufferedReader_members[] = {
1453 {"raw", T_OBJECT, offsetof(BufferedObject, raw), 0},
1454 {NULL}
1455};
1456
1457static PyGetSetDef BufferedReader_getset[] = {
1458 {"closed", (getter)BufferedIOMixin_closed_get, NULL, NULL},
1459 {"name", (getter)BufferedIOMixin_name_get, NULL, NULL},
1460 {"mode", (getter)BufferedIOMixin_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001461 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001462};
1463
1464
1465PyTypeObject PyBufferedReader_Type = {
1466 PyVarObject_HEAD_INIT(NULL, 0)
1467 "_io.BufferedReader", /*tp_name*/
1468 sizeof(BufferedObject), /*tp_basicsize*/
1469 0, /*tp_itemsize*/
1470 (destructor)BufferedObject_dealloc, /*tp_dealloc*/
1471 0, /*tp_print*/
1472 0, /*tp_getattr*/
1473 0, /*tp_setattr*/
1474 0, /*tp_compare */
1475 0, /*tp_repr*/
1476 0, /*tp_as_number*/
1477 0, /*tp_as_sequence*/
1478 0, /*tp_as_mapping*/
1479 0, /*tp_hash */
1480 0, /*tp_call*/
1481 0, /*tp_str*/
1482 0, /*tp_getattro*/
1483 0, /*tp_setattro*/
1484 0, /*tp_as_buffer*/
1485 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1486 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1487 BufferedReader_doc, /* tp_doc */
1488 (traverseproc)Buffered_traverse, /* tp_traverse */
1489 (inquiry)Buffered_clear, /* tp_clear */
1490 0, /* tp_richcompare */
1491 offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/
1492 0, /* tp_iter */
1493 (iternextfunc)Buffered_iternext, /* tp_iternext */
1494 BufferedReader_methods, /* tp_methods */
1495 BufferedReader_members, /* tp_members */
1496 BufferedReader_getset, /* tp_getset */
1497 0, /* tp_base */
1498 0, /* tp_dict */
1499 0, /* tp_descr_get */
1500 0, /* tp_descr_set */
1501 offsetof(BufferedObject, dict), /* tp_dictoffset */
1502 (initproc)BufferedReader_init, /* tp_init */
1503 0, /* tp_alloc */
1504 PyType_GenericNew, /* tp_new */
1505};
1506
1507
Benjamin Peterson59406a92009-03-26 17:10:29 +00001508
1509static int
1510complain_about_max_buffer_size(void)
1511{
1512 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1513 "max_buffer_size is deprecated", 1) < 0)
1514 return 0;
1515 return 1;
1516}
1517
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001518/*
1519 * class BufferedWriter
1520 */
1521PyDoc_STRVAR(BufferedWriter_doc,
1522 "A buffer for a writeable sequential RawIO object.\n"
1523 "\n"
1524 "The constructor creates a BufferedWriter for the given writeable raw\n"
1525 "stream. If the buffer_size is not given, it defaults to\n"
1526 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1527 );
1528
1529static void
1530_BufferedWriter_reset_buf(BufferedObject *self)
1531{
1532 self->write_pos = 0;
1533 self->write_end = -1;
1534}
1535
1536static int
1537BufferedWriter_init(BufferedObject *self, PyObject *args, PyObject *kwds)
1538{
1539 /* TODO: properly deprecate max_buffer_size */
1540 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1541 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001542 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001543 PyObject *raw;
1544
1545 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001546 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001547
1548 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1549 &raw, &buffer_size, &max_buffer_size)) {
1550 return -1;
1551 }
1552
Benjamin Peterson59406a92009-03-26 17:10:29 +00001553 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1554 return -1;
1555
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001556 if (_PyIOBase_checkWritable(raw, Py_True) == NULL)
1557 return -1;
1558
1559 Py_CLEAR(self->raw);
1560 Py_INCREF(raw);
1561 self->raw = raw;
1562 self->readable = 0;
1563 self->writable = 1;
1564
1565 self->buffer_size = buffer_size;
1566 if (_Buffered_init(self) < 0)
1567 return -1;
1568 _BufferedWriter_reset_buf(self);
1569 self->pos = 0;
1570
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001571 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1572 Py_TYPE(raw) == &PyFileIO_Type);
1573
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001574 self->ok = 1;
1575 return 0;
1576}
1577
1578static Py_ssize_t
1579_BufferedWriter_raw_write(BufferedObject *self, char *start, Py_ssize_t len)
1580{
1581 Py_buffer buf;
1582 PyObject *memobj, *res;
1583 Py_ssize_t n;
1584 /* NOTE: the buffer needn't be released as its object is NULL. */
1585 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1586 return -1;
1587 memobj = PyMemoryView_FromBuffer(&buf);
1588 if (memobj == NULL)
1589 return -1;
1590 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1591 Py_DECREF(memobj);
1592 if (res == NULL)
1593 return -1;
1594 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1595 Py_DECREF(res);
1596 if (n < 0 || n > len) {
1597 PyErr_Format(PyExc_IOError,
1598 "raw write() returned invalid length %zd "
1599 "(should have been between 0 and %zd)", n, len);
1600 return -1;
1601 }
1602 if (n > 0 && self->abs_pos != -1)
1603 self->abs_pos += n;
1604 return n;
1605}
1606
1607/* `restore_pos` is 1 if we need to restore the raw stream position at
1608 the end, 0 otherwise. */
1609static PyObject *
1610_BufferedWriter_flush_unlocked(BufferedObject *self, int restore_pos)
1611{
1612 Py_ssize_t written = 0;
1613 Py_off_t n, rewind;
1614
1615 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1616 goto end;
1617 /* First, rewind */
1618 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1619 if (rewind != 0) {
1620 n = _Buffered_raw_seek(self, -rewind, 1);
1621 if (n < 0) {
1622 goto error;
1623 }
1624 self->raw_pos -= rewind;
1625 }
1626 while (self->write_pos < self->write_end) {
1627 n = _BufferedWriter_raw_write(self,
1628 self->buffer + self->write_pos,
1629 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1630 Py_off_t, Py_ssize_t));
1631 if (n == -1) {
1632 Py_ssize_t *w = _Buffered_check_blocking_error();
1633 if (w == NULL)
1634 goto error;
1635 self->write_pos += *w;
1636 self->raw_pos = self->write_pos;
1637 written += *w;
1638 *w = written;
1639 /* Already re-raised */
1640 goto error;
1641 }
1642 self->write_pos += n;
1643 self->raw_pos = self->write_pos;
1644 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1645 }
1646
1647 if (restore_pos) {
1648 Py_off_t forward = rewind - written;
1649 if (forward != 0) {
1650 n = _Buffered_raw_seek(self, forward, 1);
1651 if (n < 0) {
1652 goto error;
1653 }
1654 self->raw_pos += forward;
1655 }
1656 }
1657 _BufferedWriter_reset_buf(self);
1658
1659end:
1660 Py_RETURN_NONE;
1661
1662error:
1663 return NULL;
1664}
1665
1666static PyObject *
1667BufferedWriter_write(BufferedObject *self, PyObject *args)
1668{
1669 PyObject *res = NULL;
1670 Py_buffer buf;
1671 Py_ssize_t written, avail, remaining, n;
1672
1673 CHECK_INITIALIZED(self)
1674 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1675 return NULL;
1676 }
1677
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001678 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001679 PyErr_SetString(PyExc_ValueError, "write to closed file");
1680 PyBuffer_Release(&buf);
1681 return NULL;
1682 }
1683
1684 ENTER_BUFFERED(self)
1685
1686 /* Fast path: the data to write can be fully buffered. */
1687 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1688 self->pos = 0;
1689 self->raw_pos = 0;
1690 }
1691 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1692 if (buf.len <= avail) {
1693 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1694 if (!VALID_WRITE_BUFFER(self)) {
1695 self->write_pos = self->pos;
1696 }
1697 ADJUST_POSITION(self, self->pos + buf.len);
1698 if (self->pos > self->write_end)
1699 self->write_end = self->pos;
1700 written = buf.len;
1701 goto end;
1702 }
1703
1704 /* First write the current buffer */
1705 res = _BufferedWriter_flush_unlocked(self, 0);
1706 if (res == NULL) {
1707 Py_ssize_t *w = _Buffered_check_blocking_error();
1708 if (w == NULL)
1709 goto error;
1710 if (self->readable)
1711 _BufferedReader_reset_buf(self);
1712 /* Make some place by shifting the buffer. */
1713 assert(VALID_WRITE_BUFFER(self));
1714 memmove(self->buffer, self->buffer + self->write_pos,
1715 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1716 Py_off_t, Py_ssize_t));
1717 self->write_end -= self->write_pos;
1718 self->raw_pos -= self->write_pos;
1719 self->pos -= self->write_pos;
1720 self->write_pos = 0;
1721 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1722 Py_off_t, Py_ssize_t);
1723 if (buf.len <= avail) {
1724 /* Everything can be buffered */
1725 PyErr_Clear();
1726 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1727 self->write_end += buf.len;
1728 written = buf.len;
1729 goto end;
1730 }
1731 /* Buffer as much as possible. */
1732 memcpy(self->buffer + self->write_end, buf.buf, avail);
1733 self->write_end += avail;
1734 /* Already re-raised */
1735 *w = avail;
1736 goto error;
1737 }
1738 Py_CLEAR(res);
1739
1740 /* Then write buf itself. At this point the buffer has been emptied. */
1741 remaining = buf.len;
1742 written = 0;
1743 while (remaining > self->buffer_size) {
1744 n = _BufferedWriter_raw_write(
1745 self, (char *) buf.buf + written, buf.len - written);
1746 if (n == -1) {
1747 Py_ssize_t *w = _Buffered_check_blocking_error();
1748 if (w == NULL)
1749 goto error;
1750 written += *w;
1751 remaining -= *w;
1752 if (remaining > self->buffer_size) {
1753 /* Can't buffer everything, still buffer as much as possible */
1754 memcpy(self->buffer,
1755 (char *) buf.buf + written, self->buffer_size);
1756 self->raw_pos = 0;
1757 ADJUST_POSITION(self, self->buffer_size);
1758 self->write_end = self->buffer_size;
1759 *w = written + self->buffer_size;
1760 /* Already re-raised */
1761 goto error;
1762 }
1763 PyErr_Clear();
1764 break;
1765 }
1766 written += n;
1767 remaining -= n;
1768 }
1769 if (self->readable)
1770 _BufferedReader_reset_buf(self);
1771 if (remaining > 0) {
1772 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1773 written += remaining;
1774 }
1775 self->write_pos = 0;
1776 /* TODO: sanity check (remaining >= 0) */
1777 self->write_end = remaining;
1778 ADJUST_POSITION(self, remaining);
1779 self->raw_pos = 0;
1780
1781end:
1782 res = PyLong_FromSsize_t(written);
1783
1784error:
1785 LEAVE_BUFFERED(self)
1786 PyBuffer_Release(&buf);
1787 return res;
1788}
1789
1790static PyMethodDef BufferedWriter_methods[] = {
1791 /* BufferedIOMixin methods */
1792 {"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS},
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001793 {"detach", (PyCFunction)BufferedIOMixin_detach, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001794 {"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS},
1795 {"readable", (PyCFunction)BufferedIOMixin_readable, METH_NOARGS},
1796 {"writable", (PyCFunction)BufferedIOMixin_writable, METH_NOARGS},
1797 {"fileno", (PyCFunction)BufferedIOMixin_fileno, METH_NOARGS},
1798 {"isatty", (PyCFunction)BufferedIOMixin_isatty, METH_NOARGS},
1799
1800 {"write", (PyCFunction)BufferedWriter_write, METH_VARARGS},
1801 {"truncate", (PyCFunction)Buffered_truncate, METH_VARARGS},
1802 {"flush", (PyCFunction)Buffered_flush, METH_NOARGS},
1803 {"seek", (PyCFunction)Buffered_seek, METH_VARARGS},
1804 {"tell", (PyCFunction)Buffered_tell, METH_NOARGS},
1805 {NULL, NULL}
1806};
1807
1808static PyMemberDef BufferedWriter_members[] = {
1809 {"raw", T_OBJECT, offsetof(BufferedObject, raw), 0},
1810 {NULL}
1811};
1812
1813static PyGetSetDef BufferedWriter_getset[] = {
1814 {"closed", (getter)BufferedIOMixin_closed_get, NULL, NULL},
1815 {"name", (getter)BufferedIOMixin_name_get, NULL, NULL},
1816 {"mode", (getter)BufferedIOMixin_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001817 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001818};
1819
1820
1821PyTypeObject PyBufferedWriter_Type = {
1822 PyVarObject_HEAD_INIT(NULL, 0)
1823 "_io.BufferedWriter", /*tp_name*/
1824 sizeof(BufferedObject), /*tp_basicsize*/
1825 0, /*tp_itemsize*/
1826 (destructor)BufferedObject_dealloc, /*tp_dealloc*/
1827 0, /*tp_print*/
1828 0, /*tp_getattr*/
1829 0, /*tp_setattr*/
1830 0, /*tp_compare */
1831 0, /*tp_repr*/
1832 0, /*tp_as_number*/
1833 0, /*tp_as_sequence*/
1834 0, /*tp_as_mapping*/
1835 0, /*tp_hash */
1836 0, /*tp_call*/
1837 0, /*tp_str*/
1838 0, /*tp_getattro*/
1839 0, /*tp_setattro*/
1840 0, /*tp_as_buffer*/
1841 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1842 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1843 BufferedWriter_doc, /* tp_doc */
1844 (traverseproc)Buffered_traverse, /* tp_traverse */
1845 (inquiry)Buffered_clear, /* tp_clear */
1846 0, /* tp_richcompare */
1847 offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/
1848 0, /* tp_iter */
1849 0, /* tp_iternext */
1850 BufferedWriter_methods, /* tp_methods */
1851 BufferedWriter_members, /* tp_members */
1852 BufferedWriter_getset, /* tp_getset */
1853 0, /* tp_base */
1854 0, /* tp_dict */
1855 0, /* tp_descr_get */
1856 0, /* tp_descr_set */
1857 offsetof(BufferedObject, dict), /* tp_dictoffset */
1858 (initproc)BufferedWriter_init, /* tp_init */
1859 0, /* tp_alloc */
1860 PyType_GenericNew, /* tp_new */
1861};
1862
1863
1864
1865/*
1866 * BufferedRWPair
1867 */
1868
1869PyDoc_STRVAR(BufferedRWPair_doc,
1870 "A buffered reader and writer object together.\n"
1871 "\n"
1872 "A buffered reader object and buffered writer object put together to\n"
1873 "form a sequential IO object that can read and write. This is typically\n"
1874 "used with a socket or two-way pipe.\n"
1875 "\n"
1876 "reader and writer are RawIOBase objects that are readable and\n"
1877 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00001878 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001879 );
1880
1881/* XXX The usefulness of this (compared to having two separate IO objects) is
1882 * questionable.
1883 */
1884
1885typedef struct {
1886 PyObject_HEAD
1887 BufferedObject *reader;
1888 BufferedObject *writer;
1889 PyObject *dict;
1890 PyObject *weakreflist;
1891} BufferedRWPairObject;
1892
1893static int
1894BufferedRWPair_init(BufferedRWPairObject *self, PyObject *args,
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001895 PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001896{
1897 PyObject *reader, *writer;
1898 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001899 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001900
1901 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1902 &buffer_size, &max_buffer_size)) {
1903 return -1;
1904 }
1905
Benjamin Peterson59406a92009-03-26 17:10:29 +00001906 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1907 return -1;
1908
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001909 if (_PyIOBase_checkReadable(reader, Py_True) == NULL)
1910 return -1;
1911 if (_PyIOBase_checkWritable(writer, Py_True) == NULL)
1912 return -1;
1913
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001914 self->reader = (BufferedObject *) PyObject_CallFunction(
1915 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001916 if (self->reader == NULL)
1917 return -1;
1918
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001919 self->writer = (BufferedObject *) PyObject_CallFunction(
1920 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001921 if (self->writer == NULL) {
1922 Py_CLEAR(self->reader);
1923 return -1;
1924 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001925
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001926 return 0;
1927}
1928
1929static int
1930BufferedRWPair_traverse(BufferedRWPairObject *self, visitproc visit, void *arg)
1931{
1932 Py_VISIT(self->dict);
1933 return 0;
1934}
1935
1936static int
1937BufferedRWPair_clear(BufferedRWPairObject *self)
1938{
1939 Py_CLEAR(self->reader);
1940 Py_CLEAR(self->writer);
1941 Py_CLEAR(self->dict);
1942 return 0;
1943}
1944
1945static void
1946BufferedRWPair_dealloc(BufferedRWPairObject *self)
1947{
1948 _PyObject_GC_UNTRACK(self);
1949 Py_CLEAR(self->reader);
1950 Py_CLEAR(self->writer);
1951 Py_CLEAR(self->dict);
1952 Py_TYPE(self)->tp_free((PyObject *) self);
1953}
1954
1955static PyObject *
1956_forward_call(BufferedObject *self, const char *name, PyObject *args)
1957{
1958 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
1959 PyObject *ret;
1960
1961 if (func == NULL) {
1962 PyErr_SetString(PyExc_AttributeError, name);
1963 return NULL;
1964 }
1965
1966 ret = PyObject_CallObject(func, args);
1967 Py_DECREF(func);
1968 return ret;
1969}
1970
1971static PyObject *
1972BufferedRWPair_read(BufferedRWPairObject *self, PyObject *args)
1973{
1974 return _forward_call(self->reader, "read", args);
1975}
1976
1977static PyObject *
1978BufferedRWPair_peek(BufferedRWPairObject *self, PyObject *args)
1979{
1980 return _forward_call(self->reader, "peek", args);
1981}
1982
1983static PyObject *
1984BufferedRWPair_read1(BufferedRWPairObject *self, PyObject *args)
1985{
1986 return _forward_call(self->reader, "read1", args);
1987}
1988
1989static PyObject *
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001990BufferedRWPair_readinto(BufferedRWPairObject *self, PyObject *args)
1991{
1992 return _forward_call(self->reader, "readinto", args);
1993}
1994
1995static PyObject *
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001996BufferedRWPair_write(BufferedRWPairObject *self, PyObject *args)
1997{
1998 return _forward_call(self->writer, "write", args);
1999}
2000
2001static PyObject *
2002BufferedRWPair_flush(BufferedRWPairObject *self, PyObject *args)
2003{
2004 return _forward_call(self->writer, "flush", args);
2005}
2006
2007static PyObject *
2008BufferedRWPair_readable(BufferedRWPairObject *self, PyObject *args)
2009{
2010 return _forward_call(self->reader, "readable", args);
2011}
2012
2013static PyObject *
2014BufferedRWPair_writable(BufferedRWPairObject *self, PyObject *args)
2015{
2016 return _forward_call(self->writer, "writable", args);
2017}
2018
2019static PyObject *
2020BufferedRWPair_close(BufferedRWPairObject *self, PyObject *args)
2021{
2022 PyObject *ret = _forward_call(self->writer, "close", args);
2023 if (ret == NULL)
2024 return NULL;
2025 Py_DECREF(ret);
2026
2027 return _forward_call(self->reader, "close", args);
2028}
2029
2030static PyObject *
2031BufferedRWPair_isatty(BufferedRWPairObject *self, PyObject *args)
2032{
2033 PyObject *ret = _forward_call(self->writer, "isatty", args);
2034
2035 if (ret != Py_False) {
2036 /* either True or exception */
2037 return ret;
2038 }
2039 Py_DECREF(ret);
2040
2041 return _forward_call(self->reader, "isatty", args);
2042}
2043
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002044static PyObject *
2045BufferedRWPair_closed_get(BufferedRWPairObject *self, void *context)
2046{
2047 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2048}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002049
2050static PyMethodDef BufferedRWPair_methods[] = {
2051 {"read", (PyCFunction)BufferedRWPair_read, METH_VARARGS},
2052 {"peek", (PyCFunction)BufferedRWPair_peek, METH_VARARGS},
2053 {"read1", (PyCFunction)BufferedRWPair_read1, METH_VARARGS},
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002054 {"readinto", (PyCFunction)BufferedRWPair_readinto, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002055
2056 {"write", (PyCFunction)BufferedRWPair_write, METH_VARARGS},
2057 {"flush", (PyCFunction)BufferedRWPair_flush, METH_NOARGS},
2058
2059 {"readable", (PyCFunction)BufferedRWPair_readable, METH_NOARGS},
2060 {"writable", (PyCFunction)BufferedRWPair_writable, METH_NOARGS},
2061
2062 {"close", (PyCFunction)BufferedRWPair_close, METH_NOARGS},
2063 {"isatty", (PyCFunction)BufferedRWPair_isatty, METH_NOARGS},
2064
2065 {NULL, NULL}
2066};
2067
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002068static PyGetSetDef BufferedRWPair_getset[] = {
2069 {"closed", (getter)BufferedRWPair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002070 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002071};
2072
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002073PyTypeObject PyBufferedRWPair_Type = {
2074 PyVarObject_HEAD_INIT(NULL, 0)
2075 "_io.BufferedRWPair", /*tp_name*/
2076 sizeof(BufferedRWPairObject), /*tp_basicsize*/
2077 0, /*tp_itemsize*/
2078 (destructor)BufferedRWPair_dealloc, /*tp_dealloc*/
2079 0, /*tp_print*/
2080 0, /*tp_getattr*/
2081 0, /*tp_setattr*/
2082 0, /*tp_compare */
2083 0, /*tp_repr*/
2084 0, /*tp_as_number*/
2085 0, /*tp_as_sequence*/
2086 0, /*tp_as_mapping*/
2087 0, /*tp_hash */
2088 0, /*tp_call*/
2089 0, /*tp_str*/
2090 0, /*tp_getattro*/
2091 0, /*tp_setattro*/
2092 0, /*tp_as_buffer*/
2093 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2094 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
2095 BufferedRWPair_doc, /* tp_doc */
2096 (traverseproc)BufferedRWPair_traverse, /* tp_traverse */
2097 (inquiry)BufferedRWPair_clear, /* tp_clear */
2098 0, /* tp_richcompare */
2099 offsetof(BufferedRWPairObject, weakreflist), /*tp_weaklistoffset*/
2100 0, /* tp_iter */
2101 0, /* tp_iternext */
2102 BufferedRWPair_methods, /* tp_methods */
2103 0, /* tp_members */
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002104 BufferedRWPair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002105 0, /* tp_base */
2106 0, /* tp_dict */
2107 0, /* tp_descr_get */
2108 0, /* tp_descr_set */
2109 offsetof(BufferedRWPairObject, dict), /* tp_dictoffset */
2110 (initproc)BufferedRWPair_init, /* tp_init */
2111 0, /* tp_alloc */
2112 PyType_GenericNew, /* tp_new */
2113};
2114
2115
2116
2117/*
2118 * BufferedRandom
2119 */
2120
2121PyDoc_STRVAR(BufferedRandom_doc,
2122 "A buffered interface to random access streams.\n"
2123 "\n"
2124 "The constructor creates a reader and writer for a seekable stream,\n"
2125 "raw, given in the first argument. If the buffer_size is omitted it\n"
2126 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2127 );
2128
2129static int
2130BufferedRandom_init(BufferedObject *self, PyObject *args, PyObject *kwds)
2131{
2132 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2133 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002134 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002135 PyObject *raw;
2136
2137 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002138 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002139
2140 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2141 &raw, &buffer_size, &max_buffer_size)) {
2142 return -1;
2143 }
2144
Benjamin Peterson59406a92009-03-26 17:10:29 +00002145 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2146 return -1;
2147
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002148 if (_PyIOBase_checkSeekable(raw, Py_True) == NULL)
2149 return -1;
2150 if (_PyIOBase_checkReadable(raw, Py_True) == NULL)
2151 return -1;
2152 if (_PyIOBase_checkWritable(raw, Py_True) == NULL)
2153 return -1;
2154
2155 Py_CLEAR(self->raw);
2156 Py_INCREF(raw);
2157 self->raw = raw;
2158 self->buffer_size = buffer_size;
2159 self->readable = 1;
2160 self->writable = 1;
2161
2162 if (_Buffered_init(self) < 0)
2163 return -1;
2164 _BufferedReader_reset_buf(self);
2165 _BufferedWriter_reset_buf(self);
2166 self->pos = 0;
2167
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002168 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2169 Py_TYPE(raw) == &PyFileIO_Type);
2170
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002171 self->ok = 1;
2172 return 0;
2173}
2174
2175static PyMethodDef BufferedRandom_methods[] = {
2176 /* BufferedIOMixin methods */
2177 {"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS},
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002178 {"detach", (PyCFunction)BufferedIOMixin_detach, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002179 {"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS},
2180 {"readable", (PyCFunction)BufferedIOMixin_readable, METH_NOARGS},
2181 {"writable", (PyCFunction)BufferedIOMixin_writable, METH_NOARGS},
2182 {"fileno", (PyCFunction)BufferedIOMixin_fileno, METH_NOARGS},
2183 {"isatty", (PyCFunction)BufferedIOMixin_isatty, METH_NOARGS},
2184
2185 {"flush", (PyCFunction)Buffered_flush, METH_NOARGS},
2186
2187 {"seek", (PyCFunction)Buffered_seek, METH_VARARGS},
2188 {"tell", (PyCFunction)Buffered_tell, METH_NOARGS},
2189 {"truncate", (PyCFunction)Buffered_truncate, METH_VARARGS},
2190 {"read", (PyCFunction)Buffered_read, METH_VARARGS},
2191 {"read1", (PyCFunction)Buffered_read1, METH_VARARGS},
2192 {"readinto", (PyCFunction)Buffered_readinto, METH_VARARGS},
2193 {"readline", (PyCFunction)Buffered_readline, METH_VARARGS},
2194 {"peek", (PyCFunction)Buffered_peek, METH_VARARGS},
2195 {"write", (PyCFunction)BufferedWriter_write, METH_VARARGS},
2196 {NULL, NULL}
2197};
2198
2199static PyMemberDef BufferedRandom_members[] = {
2200 {"raw", T_OBJECT, offsetof(BufferedObject, raw), 0},
2201 {NULL}
2202};
2203
2204static PyGetSetDef BufferedRandom_getset[] = {
2205 {"closed", (getter)BufferedIOMixin_closed_get, NULL, NULL},
2206 {"name", (getter)BufferedIOMixin_name_get, NULL, NULL},
2207 {"mode", (getter)BufferedIOMixin_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002208 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002209};
2210
2211
2212PyTypeObject PyBufferedRandom_Type = {
2213 PyVarObject_HEAD_INIT(NULL, 0)
2214 "_io.BufferedRandom", /*tp_name*/
2215 sizeof(BufferedObject), /*tp_basicsize*/
2216 0, /*tp_itemsize*/
2217 (destructor)BufferedObject_dealloc, /*tp_dealloc*/
2218 0, /*tp_print*/
2219 0, /*tp_getattr*/
2220 0, /*tp_setattr*/
2221 0, /*tp_compare */
2222 0, /*tp_repr*/
2223 0, /*tp_as_number*/
2224 0, /*tp_as_sequence*/
2225 0, /*tp_as_mapping*/
2226 0, /*tp_hash */
2227 0, /*tp_call*/
2228 0, /*tp_str*/
2229 0, /*tp_getattro*/
2230 0, /*tp_setattro*/
2231 0, /*tp_as_buffer*/
2232 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2233 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2234 BufferedRandom_doc, /* tp_doc */
2235 (traverseproc)Buffered_traverse, /* tp_traverse */
2236 (inquiry)Buffered_clear, /* tp_clear */
2237 0, /* tp_richcompare */
2238 offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/
2239 0, /* tp_iter */
2240 (iternextfunc)Buffered_iternext, /* tp_iternext */
2241 BufferedRandom_methods, /* tp_methods */
2242 BufferedRandom_members, /* tp_members */
2243 BufferedRandom_getset, /* tp_getset */
2244 0, /* tp_base */
2245 0, /*tp_dict*/
2246 0, /* tp_descr_get */
2247 0, /* tp_descr_set */
2248 offsetof(BufferedObject, dict), /*tp_dictoffset*/
2249 (initproc)BufferedRandom_init, /* tp_init */
2250 0, /* tp_alloc */
2251 PyType_GenericNew, /* tp_new */
2252};
2253