blob: 034fe51f3a5f310d43594a038fbccda4e569bb79 [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
Antoine Pitrou716c4442009-05-23 19:04:03 +00001126static PyObject *
1127Buffered_repr(BufferedObject *self)
1128{
1129 PyObject *nameobj, *res;
1130
1131 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1132 if (nameobj == NULL) {
1133 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1134 PyErr_Clear();
1135 else
1136 return NULL;
1137 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1138 }
1139 else {
1140 res = PyUnicode_FromFormat("<%s name=%R>",
1141 Py_TYPE(self)->tp_name, nameobj);
1142 Py_DECREF(nameobj);
1143 }
1144 return res;
1145}
1146
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001147/*
1148 * class BufferedReader
1149 */
1150
1151PyDoc_STRVAR(BufferedReader_doc,
1152 "Create a new buffered reader using the given readable raw IO object.");
1153
1154static void _BufferedReader_reset_buf(BufferedObject *self)
1155{
1156 self->read_end = -1;
1157}
1158
1159static int
1160BufferedReader_init(BufferedObject *self, PyObject *args, PyObject *kwds)
1161{
1162 char *kwlist[] = {"raw", "buffer_size", NULL};
1163 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1164 PyObject *raw;
1165
1166 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001167 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001168
1169 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1170 &raw, &buffer_size)) {
1171 return -1;
1172 }
1173
1174 if (_PyIOBase_checkReadable(raw, Py_True) == NULL)
1175 return -1;
1176
1177 Py_CLEAR(self->raw);
1178 Py_INCREF(raw);
1179 self->raw = raw;
1180 self->buffer_size = buffer_size;
1181 self->readable = 1;
1182 self->writable = 0;
1183
1184 if (_Buffered_init(self) < 0)
1185 return -1;
1186 _BufferedReader_reset_buf(self);
1187
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001188 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1189 Py_TYPE(raw) == &PyFileIO_Type);
1190
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001191 self->ok = 1;
1192 return 0;
1193}
1194
1195static Py_ssize_t
1196_BufferedReader_raw_read(BufferedObject *self, char *start, Py_ssize_t len)
1197{
1198 Py_buffer buf;
1199 PyObject *memobj, *res;
1200 Py_ssize_t n;
1201 /* NOTE: the buffer needn't be released as its object is NULL. */
1202 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1203 return -1;
1204 memobj = PyMemoryView_FromBuffer(&buf);
1205 if (memobj == NULL)
1206 return -1;
1207 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1208 Py_DECREF(memobj);
1209 if (res == NULL)
1210 return -1;
1211 if (res == Py_None) {
1212 /* Non-blocking stream would have blocked. Special return code! */
1213 Py_DECREF(res);
1214 return -2;
1215 }
1216 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1217 Py_DECREF(res);
1218 if (n < 0 || n > len) {
1219 PyErr_Format(PyExc_IOError,
1220 "raw readinto() returned invalid length %zd "
1221 "(should have been between 0 and %zd)", n, len);
1222 return -1;
1223 }
1224 if (n > 0 && self->abs_pos != -1)
1225 self->abs_pos += n;
1226 return n;
1227}
1228
1229static Py_ssize_t
1230_BufferedReader_fill_buffer(BufferedObject *self)
1231{
1232 Py_ssize_t start, len, n;
1233 if (VALID_READ_BUFFER(self))
1234 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1235 else
1236 start = 0;
1237 len = self->buffer_size - start;
1238 n = _BufferedReader_raw_read(self, self->buffer + start, len);
1239 if (n <= 0)
1240 return n;
1241 self->read_end = start + n;
1242 self->raw_pos = start + n;
1243 return n;
1244}
1245
1246static PyObject *
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001247_BufferedReader_read_all(BufferedObject *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001248{
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001249 Py_ssize_t current_size;
1250 PyObject *res, *data = NULL;
1251 PyObject *chunks = PyList_New(0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001252
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001253 if (chunks == NULL)
1254 return NULL;
1255
1256 /* First copy what we have in the current buffer. */
1257 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1258 if (current_size) {
1259 data = PyBytes_FromStringAndSize(
1260 self->buffer + self->pos, current_size);
1261 if (data == NULL) {
1262 Py_DECREF(chunks);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001263 return NULL;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001264 }
1265 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001266 _BufferedReader_reset_buf(self);
1267 /* We're going past the buffer's bounds, flush it */
1268 if (self->writable) {
1269 res = _BufferedWriter_flush_unlocked(self, 1);
1270 if (res == NULL) {
1271 Py_DECREF(chunks);
1272 return NULL;
1273 }
1274 Py_CLEAR(res);
1275 }
1276 while (1) {
1277 if (data) {
1278 if (PyList_Append(chunks, data) < 0) {
1279 Py_DECREF(data);
1280 Py_DECREF(chunks);
1281 return NULL;
1282 }
1283 Py_DECREF(data);
1284 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001285
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001286 /* Read until EOF or until read() would block. */
1287 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1288 if (data == NULL) {
1289 Py_DECREF(chunks);
1290 return NULL;
1291 }
1292 if (data != Py_None && !PyBytes_Check(data)) {
1293 Py_DECREF(data);
1294 Py_DECREF(chunks);
1295 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1296 return NULL;
1297 }
1298 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1299 if (current_size == 0) {
1300 Py_DECREF(chunks);
1301 return data;
1302 }
1303 else {
1304 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1305 Py_DECREF(data);
1306 Py_DECREF(chunks);
1307 return res;
1308 }
1309 }
1310 current_size += PyBytes_GET_SIZE(data);
1311 if (self->abs_pos != -1)
1312 self->abs_pos += PyBytes_GET_SIZE(data);
1313 }
1314}
1315
1316/* Read n bytes from the buffer if it can, otherwise return None.
1317 This function is simple enough that it can run unlocked. */
1318static PyObject *
1319_BufferedReader_read_fast(BufferedObject *self, Py_ssize_t n)
1320{
1321 Py_ssize_t current_size;
1322
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001323 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1324 if (n <= current_size) {
1325 /* Fast path: the data to read is fully buffered. */
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001326 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1327 if (res != NULL)
1328 self->pos += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001329 return res;
1330 }
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001331 Py_RETURN_NONE;
1332}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001333
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001334/* Generic read function: read from the stream until enough bytes are read,
1335 * or until an EOF occurs or until read() would block.
1336 */
1337static PyObject *
1338_BufferedReader_read_generic(BufferedObject *self, Py_ssize_t n)
1339{
1340 PyObject *res = NULL;
1341 Py_ssize_t current_size, remaining, written;
1342 char *out;
1343
1344 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1345 if (n <= current_size)
1346 return _BufferedReader_read_fast(self, n);
1347
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001348 res = PyBytes_FromStringAndSize(NULL, n);
1349 if (res == NULL)
1350 goto error;
1351 out = PyBytes_AS_STRING(res);
1352 remaining = n;
1353 written = 0;
1354 if (current_size > 0) {
1355 memcpy(out, self->buffer + self->pos, current_size);
1356 remaining -= current_size;
1357 written += current_size;
1358 }
1359 _BufferedReader_reset_buf(self);
1360 while (remaining > 0) {
1361 /* We want to read a whole block at the end into buffer.
1362 If we had readv() we could do this in one pass. */
1363 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1364 if (r == 0)
1365 break;
1366 r = _BufferedReader_raw_read(self, out + written, r);
1367 if (r == -1)
1368 goto error;
1369 if (r == 0 || r == -2) {
1370 /* EOF occurred or read() would block. */
1371 if (r == 0 || written > 0) {
1372 if (_PyBytes_Resize(&res, written))
1373 goto error;
1374 return res;
1375 }
1376 Py_DECREF(res);
1377 Py_INCREF(Py_None);
1378 return Py_None;
1379 }
1380 remaining -= r;
1381 written += r;
1382 }
1383 assert(remaining <= self->buffer_size);
1384 self->pos = 0;
1385 self->raw_pos = 0;
1386 self->read_end = 0;
1387 while (self->read_end < self->buffer_size) {
1388 Py_ssize_t r = _BufferedReader_fill_buffer(self);
1389 if (r == -1)
1390 goto error;
1391 if (r == 0 || r == -2) {
1392 /* EOF occurred or read() would block. */
1393 if (r == 0 || written > 0) {
1394 if (_PyBytes_Resize(&res, written))
1395 goto error;
1396 return res;
1397 }
1398 Py_DECREF(res);
1399 Py_INCREF(Py_None);
1400 return Py_None;
1401 }
1402 if (remaining > r) {
1403 memcpy(out + written, self->buffer + self->pos, r);
1404 written += r;
1405 self->pos += r;
1406 remaining -= r;
1407 }
1408 else if (remaining > 0) {
1409 memcpy(out + written, self->buffer + self->pos, remaining);
1410 written += remaining;
1411 self->pos += remaining;
1412 remaining = 0;
1413 }
1414 if (remaining == 0)
1415 break;
1416 }
1417
1418 return res;
1419
1420error:
1421 Py_XDECREF(res);
1422 return NULL;
1423}
1424
1425static PyObject *
1426_BufferedReader_peek_unlocked(BufferedObject *self, Py_ssize_t n)
1427{
1428 Py_ssize_t have, r;
1429
1430 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1431 /* Constraints:
1432 1. we don't want to advance the file position.
1433 2. we don't want to lose block alignment, so we can't shift the buffer
1434 to make some place.
1435 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1436 */
1437 if (have > 0) {
1438 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1439 }
1440
1441 /* Fill the buffer from the raw stream, and copy it to the result. */
1442 _BufferedReader_reset_buf(self);
1443 r = _BufferedReader_fill_buffer(self);
1444 if (r == -1)
1445 return NULL;
1446 if (r == -2)
1447 r = 0;
1448 self->pos = 0;
1449 return PyBytes_FromStringAndSize(self->buffer, r);
1450}
1451
1452static PyMethodDef BufferedReader_methods[] = {
1453 /* BufferedIOMixin methods */
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001454 {"detach", (PyCFunction)BufferedIOMixin_detach, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001455 {"flush", (PyCFunction)BufferedIOMixin_flush, METH_NOARGS},
1456 {"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS},
1457 {"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS},
1458 {"readable", (PyCFunction)BufferedIOMixin_readable, METH_NOARGS},
1459 {"writable", (PyCFunction)BufferedIOMixin_writable, METH_NOARGS},
1460 {"fileno", (PyCFunction)BufferedIOMixin_fileno, METH_NOARGS},
1461 {"isatty", (PyCFunction)BufferedIOMixin_isatty, METH_NOARGS},
1462
1463 {"read", (PyCFunction)Buffered_read, METH_VARARGS},
1464 {"peek", (PyCFunction)Buffered_peek, METH_VARARGS},
1465 {"read1", (PyCFunction)Buffered_read1, METH_VARARGS},
1466 {"readline", (PyCFunction)Buffered_readline, METH_VARARGS},
1467 {"seek", (PyCFunction)Buffered_seek, METH_VARARGS},
1468 {"tell", (PyCFunction)Buffered_tell, METH_NOARGS},
1469 {"truncate", (PyCFunction)Buffered_truncate, METH_VARARGS},
1470 {NULL, NULL}
1471};
1472
1473static PyMemberDef BufferedReader_members[] = {
1474 {"raw", T_OBJECT, offsetof(BufferedObject, raw), 0},
1475 {NULL}
1476};
1477
1478static PyGetSetDef BufferedReader_getset[] = {
1479 {"closed", (getter)BufferedIOMixin_closed_get, NULL, NULL},
1480 {"name", (getter)BufferedIOMixin_name_get, NULL, NULL},
1481 {"mode", (getter)BufferedIOMixin_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001482 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001483};
1484
1485
1486PyTypeObject PyBufferedReader_Type = {
1487 PyVarObject_HEAD_INIT(NULL, 0)
1488 "_io.BufferedReader", /*tp_name*/
1489 sizeof(BufferedObject), /*tp_basicsize*/
1490 0, /*tp_itemsize*/
1491 (destructor)BufferedObject_dealloc, /*tp_dealloc*/
1492 0, /*tp_print*/
1493 0, /*tp_getattr*/
1494 0, /*tp_setattr*/
1495 0, /*tp_compare */
Antoine Pitrou716c4442009-05-23 19:04:03 +00001496 (reprfunc)Buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001497 0, /*tp_as_number*/
1498 0, /*tp_as_sequence*/
1499 0, /*tp_as_mapping*/
1500 0, /*tp_hash */
1501 0, /*tp_call*/
1502 0, /*tp_str*/
1503 0, /*tp_getattro*/
1504 0, /*tp_setattro*/
1505 0, /*tp_as_buffer*/
1506 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1507 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1508 BufferedReader_doc, /* tp_doc */
1509 (traverseproc)Buffered_traverse, /* tp_traverse */
1510 (inquiry)Buffered_clear, /* tp_clear */
1511 0, /* tp_richcompare */
1512 offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/
1513 0, /* tp_iter */
1514 (iternextfunc)Buffered_iternext, /* tp_iternext */
1515 BufferedReader_methods, /* tp_methods */
1516 BufferedReader_members, /* tp_members */
1517 BufferedReader_getset, /* tp_getset */
1518 0, /* tp_base */
1519 0, /* tp_dict */
1520 0, /* tp_descr_get */
1521 0, /* tp_descr_set */
1522 offsetof(BufferedObject, dict), /* tp_dictoffset */
1523 (initproc)BufferedReader_init, /* tp_init */
1524 0, /* tp_alloc */
1525 PyType_GenericNew, /* tp_new */
1526};
1527
1528
Benjamin Peterson59406a92009-03-26 17:10:29 +00001529
1530static int
1531complain_about_max_buffer_size(void)
1532{
1533 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1534 "max_buffer_size is deprecated", 1) < 0)
1535 return 0;
1536 return 1;
1537}
1538
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001539/*
1540 * class BufferedWriter
1541 */
1542PyDoc_STRVAR(BufferedWriter_doc,
1543 "A buffer for a writeable sequential RawIO object.\n"
1544 "\n"
1545 "The constructor creates a BufferedWriter for the given writeable raw\n"
1546 "stream. If the buffer_size is not given, it defaults to\n"
1547 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1548 );
1549
1550static void
1551_BufferedWriter_reset_buf(BufferedObject *self)
1552{
1553 self->write_pos = 0;
1554 self->write_end = -1;
1555}
1556
1557static int
1558BufferedWriter_init(BufferedObject *self, PyObject *args, PyObject *kwds)
1559{
1560 /* TODO: properly deprecate max_buffer_size */
1561 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1562 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001563 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001564 PyObject *raw;
1565
1566 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001567 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001568
1569 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1570 &raw, &buffer_size, &max_buffer_size)) {
1571 return -1;
1572 }
1573
Benjamin Peterson59406a92009-03-26 17:10:29 +00001574 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1575 return -1;
1576
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001577 if (_PyIOBase_checkWritable(raw, Py_True) == NULL)
1578 return -1;
1579
1580 Py_CLEAR(self->raw);
1581 Py_INCREF(raw);
1582 self->raw = raw;
1583 self->readable = 0;
1584 self->writable = 1;
1585
1586 self->buffer_size = buffer_size;
1587 if (_Buffered_init(self) < 0)
1588 return -1;
1589 _BufferedWriter_reset_buf(self);
1590 self->pos = 0;
1591
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001592 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1593 Py_TYPE(raw) == &PyFileIO_Type);
1594
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001595 self->ok = 1;
1596 return 0;
1597}
1598
1599static Py_ssize_t
1600_BufferedWriter_raw_write(BufferedObject *self, char *start, Py_ssize_t len)
1601{
1602 Py_buffer buf;
1603 PyObject *memobj, *res;
1604 Py_ssize_t n;
1605 /* NOTE: the buffer needn't be released as its object is NULL. */
1606 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1607 return -1;
1608 memobj = PyMemoryView_FromBuffer(&buf);
1609 if (memobj == NULL)
1610 return -1;
1611 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1612 Py_DECREF(memobj);
1613 if (res == NULL)
1614 return -1;
1615 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1616 Py_DECREF(res);
1617 if (n < 0 || n > len) {
1618 PyErr_Format(PyExc_IOError,
1619 "raw write() returned invalid length %zd "
1620 "(should have been between 0 and %zd)", n, len);
1621 return -1;
1622 }
1623 if (n > 0 && self->abs_pos != -1)
1624 self->abs_pos += n;
1625 return n;
1626}
1627
1628/* `restore_pos` is 1 if we need to restore the raw stream position at
1629 the end, 0 otherwise. */
1630static PyObject *
1631_BufferedWriter_flush_unlocked(BufferedObject *self, int restore_pos)
1632{
1633 Py_ssize_t written = 0;
1634 Py_off_t n, rewind;
1635
1636 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1637 goto end;
1638 /* First, rewind */
1639 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1640 if (rewind != 0) {
1641 n = _Buffered_raw_seek(self, -rewind, 1);
1642 if (n < 0) {
1643 goto error;
1644 }
1645 self->raw_pos -= rewind;
1646 }
1647 while (self->write_pos < self->write_end) {
1648 n = _BufferedWriter_raw_write(self,
1649 self->buffer + self->write_pos,
1650 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1651 Py_off_t, Py_ssize_t));
1652 if (n == -1) {
1653 Py_ssize_t *w = _Buffered_check_blocking_error();
1654 if (w == NULL)
1655 goto error;
1656 self->write_pos += *w;
1657 self->raw_pos = self->write_pos;
1658 written += *w;
1659 *w = written;
1660 /* Already re-raised */
1661 goto error;
1662 }
1663 self->write_pos += n;
1664 self->raw_pos = self->write_pos;
1665 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1666 }
1667
1668 if (restore_pos) {
1669 Py_off_t forward = rewind - written;
1670 if (forward != 0) {
1671 n = _Buffered_raw_seek(self, forward, 1);
1672 if (n < 0) {
1673 goto error;
1674 }
1675 self->raw_pos += forward;
1676 }
1677 }
1678 _BufferedWriter_reset_buf(self);
1679
1680end:
1681 Py_RETURN_NONE;
1682
1683error:
1684 return NULL;
1685}
1686
1687static PyObject *
1688BufferedWriter_write(BufferedObject *self, PyObject *args)
1689{
1690 PyObject *res = NULL;
1691 Py_buffer buf;
1692 Py_ssize_t written, avail, remaining, n;
1693
1694 CHECK_INITIALIZED(self)
1695 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1696 return NULL;
1697 }
1698
Antoine Pitrou711af3a2009-04-11 15:39:24 +00001699 if (IS_CLOSED(self)) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001700 PyErr_SetString(PyExc_ValueError, "write to closed file");
1701 PyBuffer_Release(&buf);
1702 return NULL;
1703 }
1704
1705 ENTER_BUFFERED(self)
1706
1707 /* Fast path: the data to write can be fully buffered. */
1708 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1709 self->pos = 0;
1710 self->raw_pos = 0;
1711 }
1712 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1713 if (buf.len <= avail) {
1714 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1715 if (!VALID_WRITE_BUFFER(self)) {
1716 self->write_pos = self->pos;
1717 }
1718 ADJUST_POSITION(self, self->pos + buf.len);
1719 if (self->pos > self->write_end)
1720 self->write_end = self->pos;
1721 written = buf.len;
1722 goto end;
1723 }
1724
1725 /* First write the current buffer */
1726 res = _BufferedWriter_flush_unlocked(self, 0);
1727 if (res == NULL) {
1728 Py_ssize_t *w = _Buffered_check_blocking_error();
1729 if (w == NULL)
1730 goto error;
1731 if (self->readable)
1732 _BufferedReader_reset_buf(self);
1733 /* Make some place by shifting the buffer. */
1734 assert(VALID_WRITE_BUFFER(self));
1735 memmove(self->buffer, self->buffer + self->write_pos,
1736 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1737 Py_off_t, Py_ssize_t));
1738 self->write_end -= self->write_pos;
1739 self->raw_pos -= self->write_pos;
1740 self->pos -= self->write_pos;
1741 self->write_pos = 0;
1742 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1743 Py_off_t, Py_ssize_t);
1744 if (buf.len <= avail) {
1745 /* Everything can be buffered */
1746 PyErr_Clear();
1747 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1748 self->write_end += buf.len;
1749 written = buf.len;
1750 goto end;
1751 }
1752 /* Buffer as much as possible. */
1753 memcpy(self->buffer + self->write_end, buf.buf, avail);
1754 self->write_end += avail;
1755 /* Already re-raised */
1756 *w = avail;
1757 goto error;
1758 }
1759 Py_CLEAR(res);
1760
1761 /* Then write buf itself. At this point the buffer has been emptied. */
1762 remaining = buf.len;
1763 written = 0;
1764 while (remaining > self->buffer_size) {
1765 n = _BufferedWriter_raw_write(
1766 self, (char *) buf.buf + written, buf.len - written);
1767 if (n == -1) {
1768 Py_ssize_t *w = _Buffered_check_blocking_error();
1769 if (w == NULL)
1770 goto error;
1771 written += *w;
1772 remaining -= *w;
1773 if (remaining > self->buffer_size) {
1774 /* Can't buffer everything, still buffer as much as possible */
1775 memcpy(self->buffer,
1776 (char *) buf.buf + written, self->buffer_size);
1777 self->raw_pos = 0;
1778 ADJUST_POSITION(self, self->buffer_size);
1779 self->write_end = self->buffer_size;
1780 *w = written + self->buffer_size;
1781 /* Already re-raised */
1782 goto error;
1783 }
1784 PyErr_Clear();
1785 break;
1786 }
1787 written += n;
1788 remaining -= n;
1789 }
1790 if (self->readable)
1791 _BufferedReader_reset_buf(self);
1792 if (remaining > 0) {
1793 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1794 written += remaining;
1795 }
1796 self->write_pos = 0;
1797 /* TODO: sanity check (remaining >= 0) */
1798 self->write_end = remaining;
1799 ADJUST_POSITION(self, remaining);
1800 self->raw_pos = 0;
1801
1802end:
1803 res = PyLong_FromSsize_t(written);
1804
1805error:
1806 LEAVE_BUFFERED(self)
1807 PyBuffer_Release(&buf);
1808 return res;
1809}
1810
1811static PyMethodDef BufferedWriter_methods[] = {
1812 /* BufferedIOMixin methods */
1813 {"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS},
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001814 {"detach", (PyCFunction)BufferedIOMixin_detach, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001815 {"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS},
1816 {"readable", (PyCFunction)BufferedIOMixin_readable, METH_NOARGS},
1817 {"writable", (PyCFunction)BufferedIOMixin_writable, METH_NOARGS},
1818 {"fileno", (PyCFunction)BufferedIOMixin_fileno, METH_NOARGS},
1819 {"isatty", (PyCFunction)BufferedIOMixin_isatty, METH_NOARGS},
1820
1821 {"write", (PyCFunction)BufferedWriter_write, METH_VARARGS},
1822 {"truncate", (PyCFunction)Buffered_truncate, METH_VARARGS},
1823 {"flush", (PyCFunction)Buffered_flush, METH_NOARGS},
1824 {"seek", (PyCFunction)Buffered_seek, METH_VARARGS},
1825 {"tell", (PyCFunction)Buffered_tell, METH_NOARGS},
1826 {NULL, NULL}
1827};
1828
1829static PyMemberDef BufferedWriter_members[] = {
1830 {"raw", T_OBJECT, offsetof(BufferedObject, raw), 0},
1831 {NULL}
1832};
1833
1834static PyGetSetDef BufferedWriter_getset[] = {
1835 {"closed", (getter)BufferedIOMixin_closed_get, NULL, NULL},
1836 {"name", (getter)BufferedIOMixin_name_get, NULL, NULL},
1837 {"mode", (getter)BufferedIOMixin_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00001838 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001839};
1840
1841
1842PyTypeObject PyBufferedWriter_Type = {
1843 PyVarObject_HEAD_INIT(NULL, 0)
1844 "_io.BufferedWriter", /*tp_name*/
1845 sizeof(BufferedObject), /*tp_basicsize*/
1846 0, /*tp_itemsize*/
1847 (destructor)BufferedObject_dealloc, /*tp_dealloc*/
1848 0, /*tp_print*/
1849 0, /*tp_getattr*/
1850 0, /*tp_setattr*/
1851 0, /*tp_compare */
Antoine Pitrou716c4442009-05-23 19:04:03 +00001852 (reprfunc)Buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001853 0, /*tp_as_number*/
1854 0, /*tp_as_sequence*/
1855 0, /*tp_as_mapping*/
1856 0, /*tp_hash */
1857 0, /*tp_call*/
1858 0, /*tp_str*/
1859 0, /*tp_getattro*/
1860 0, /*tp_setattro*/
1861 0, /*tp_as_buffer*/
1862 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1863 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1864 BufferedWriter_doc, /* tp_doc */
1865 (traverseproc)Buffered_traverse, /* tp_traverse */
1866 (inquiry)Buffered_clear, /* tp_clear */
1867 0, /* tp_richcompare */
1868 offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/
1869 0, /* tp_iter */
1870 0, /* tp_iternext */
1871 BufferedWriter_methods, /* tp_methods */
1872 BufferedWriter_members, /* tp_members */
1873 BufferedWriter_getset, /* tp_getset */
1874 0, /* tp_base */
1875 0, /* tp_dict */
1876 0, /* tp_descr_get */
1877 0, /* tp_descr_set */
1878 offsetof(BufferedObject, dict), /* tp_dictoffset */
1879 (initproc)BufferedWriter_init, /* tp_init */
1880 0, /* tp_alloc */
1881 PyType_GenericNew, /* tp_new */
1882};
1883
1884
1885
1886/*
1887 * BufferedRWPair
1888 */
1889
1890PyDoc_STRVAR(BufferedRWPair_doc,
1891 "A buffered reader and writer object together.\n"
1892 "\n"
1893 "A buffered reader object and buffered writer object put together to\n"
1894 "form a sequential IO object that can read and write. This is typically\n"
1895 "used with a socket or two-way pipe.\n"
1896 "\n"
1897 "reader and writer are RawIOBase objects that are readable and\n"
1898 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00001899 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001900 );
1901
1902/* XXX The usefulness of this (compared to having two separate IO objects) is
1903 * questionable.
1904 */
1905
1906typedef struct {
1907 PyObject_HEAD
1908 BufferedObject *reader;
1909 BufferedObject *writer;
1910 PyObject *dict;
1911 PyObject *weakreflist;
1912} BufferedRWPairObject;
1913
1914static int
1915BufferedRWPair_init(BufferedRWPairObject *self, PyObject *args,
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001916 PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001917{
1918 PyObject *reader, *writer;
1919 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001920 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001921
1922 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1923 &buffer_size, &max_buffer_size)) {
1924 return -1;
1925 }
1926
Benjamin Peterson59406a92009-03-26 17:10:29 +00001927 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1928 return -1;
1929
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001930 if (_PyIOBase_checkReadable(reader, Py_True) == NULL)
1931 return -1;
1932 if (_PyIOBase_checkWritable(writer, Py_True) == NULL)
1933 return -1;
1934
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001935 self->reader = (BufferedObject *) PyObject_CallFunction(
1936 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001937 if (self->reader == NULL)
1938 return -1;
1939
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001940 self->writer = (BufferedObject *) PyObject_CallFunction(
1941 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001942 if (self->writer == NULL) {
1943 Py_CLEAR(self->reader);
1944 return -1;
1945 }
Antoine Pitroucf4c7492009-04-19 00:09:36 +00001946
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001947 return 0;
1948}
1949
1950static int
1951BufferedRWPair_traverse(BufferedRWPairObject *self, visitproc visit, void *arg)
1952{
1953 Py_VISIT(self->dict);
1954 return 0;
1955}
1956
1957static int
1958BufferedRWPair_clear(BufferedRWPairObject *self)
1959{
1960 Py_CLEAR(self->reader);
1961 Py_CLEAR(self->writer);
1962 Py_CLEAR(self->dict);
1963 return 0;
1964}
1965
1966static void
1967BufferedRWPair_dealloc(BufferedRWPairObject *self)
1968{
1969 _PyObject_GC_UNTRACK(self);
1970 Py_CLEAR(self->reader);
1971 Py_CLEAR(self->writer);
1972 Py_CLEAR(self->dict);
1973 Py_TYPE(self)->tp_free((PyObject *) self);
1974}
1975
1976static PyObject *
1977_forward_call(BufferedObject *self, const char *name, PyObject *args)
1978{
1979 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
1980 PyObject *ret;
1981
1982 if (func == NULL) {
1983 PyErr_SetString(PyExc_AttributeError, name);
1984 return NULL;
1985 }
1986
1987 ret = PyObject_CallObject(func, args);
1988 Py_DECREF(func);
1989 return ret;
1990}
1991
1992static PyObject *
1993BufferedRWPair_read(BufferedRWPairObject *self, PyObject *args)
1994{
1995 return _forward_call(self->reader, "read", args);
1996}
1997
1998static PyObject *
1999BufferedRWPair_peek(BufferedRWPairObject *self, PyObject *args)
2000{
2001 return _forward_call(self->reader, "peek", args);
2002}
2003
2004static PyObject *
2005BufferedRWPair_read1(BufferedRWPairObject *self, PyObject *args)
2006{
2007 return _forward_call(self->reader, "read1", args);
2008}
2009
2010static PyObject *
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002011BufferedRWPair_readinto(BufferedRWPairObject *self, PyObject *args)
2012{
2013 return _forward_call(self->reader, "readinto", args);
2014}
2015
2016static PyObject *
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002017BufferedRWPair_write(BufferedRWPairObject *self, PyObject *args)
2018{
2019 return _forward_call(self->writer, "write", args);
2020}
2021
2022static PyObject *
2023BufferedRWPair_flush(BufferedRWPairObject *self, PyObject *args)
2024{
2025 return _forward_call(self->writer, "flush", args);
2026}
2027
2028static PyObject *
2029BufferedRWPair_readable(BufferedRWPairObject *self, PyObject *args)
2030{
2031 return _forward_call(self->reader, "readable", args);
2032}
2033
2034static PyObject *
2035BufferedRWPair_writable(BufferedRWPairObject *self, PyObject *args)
2036{
2037 return _forward_call(self->writer, "writable", args);
2038}
2039
2040static PyObject *
2041BufferedRWPair_close(BufferedRWPairObject *self, PyObject *args)
2042{
2043 PyObject *ret = _forward_call(self->writer, "close", args);
2044 if (ret == NULL)
2045 return NULL;
2046 Py_DECREF(ret);
2047
2048 return _forward_call(self->reader, "close", args);
2049}
2050
2051static PyObject *
2052BufferedRWPair_isatty(BufferedRWPairObject *self, PyObject *args)
2053{
2054 PyObject *ret = _forward_call(self->writer, "isatty", args);
2055
2056 if (ret != Py_False) {
2057 /* either True or exception */
2058 return ret;
2059 }
2060 Py_DECREF(ret);
2061
2062 return _forward_call(self->reader, "isatty", args);
2063}
2064
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002065static PyObject *
2066BufferedRWPair_closed_get(BufferedRWPairObject *self, void *context)
2067{
2068 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2069}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002070
2071static PyMethodDef BufferedRWPair_methods[] = {
2072 {"read", (PyCFunction)BufferedRWPair_read, METH_VARARGS},
2073 {"peek", (PyCFunction)BufferedRWPair_peek, METH_VARARGS},
2074 {"read1", (PyCFunction)BufferedRWPair_read1, METH_VARARGS},
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002075 {"readinto", (PyCFunction)BufferedRWPair_readinto, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002076
2077 {"write", (PyCFunction)BufferedRWPair_write, METH_VARARGS},
2078 {"flush", (PyCFunction)BufferedRWPair_flush, METH_NOARGS},
2079
2080 {"readable", (PyCFunction)BufferedRWPair_readable, METH_NOARGS},
2081 {"writable", (PyCFunction)BufferedRWPair_writable, METH_NOARGS},
2082
2083 {"close", (PyCFunction)BufferedRWPair_close, METH_NOARGS},
2084 {"isatty", (PyCFunction)BufferedRWPair_isatty, METH_NOARGS},
2085
2086 {NULL, NULL}
2087};
2088
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002089static PyGetSetDef BufferedRWPair_getset[] = {
2090 {"closed", (getter)BufferedRWPair_closed_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002091 {NULL}
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002092};
2093
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002094PyTypeObject PyBufferedRWPair_Type = {
2095 PyVarObject_HEAD_INIT(NULL, 0)
2096 "_io.BufferedRWPair", /*tp_name*/
2097 sizeof(BufferedRWPairObject), /*tp_basicsize*/
2098 0, /*tp_itemsize*/
2099 (destructor)BufferedRWPair_dealloc, /*tp_dealloc*/
2100 0, /*tp_print*/
2101 0, /*tp_getattr*/
2102 0, /*tp_setattr*/
2103 0, /*tp_compare */
2104 0, /*tp_repr*/
2105 0, /*tp_as_number*/
2106 0, /*tp_as_sequence*/
2107 0, /*tp_as_mapping*/
2108 0, /*tp_hash */
2109 0, /*tp_call*/
2110 0, /*tp_str*/
2111 0, /*tp_getattro*/
2112 0, /*tp_setattro*/
2113 0, /*tp_as_buffer*/
2114 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2115 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
2116 BufferedRWPair_doc, /* tp_doc */
2117 (traverseproc)BufferedRWPair_traverse, /* tp_traverse */
2118 (inquiry)BufferedRWPair_clear, /* tp_clear */
2119 0, /* tp_richcompare */
2120 offsetof(BufferedRWPairObject, weakreflist), /*tp_weaklistoffset*/
2121 0, /* tp_iter */
2122 0, /* tp_iternext */
2123 BufferedRWPair_methods, /* tp_methods */
2124 0, /* tp_members */
Antoine Pitroucf4c7492009-04-19 00:09:36 +00002125 BufferedRWPair_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002126 0, /* tp_base */
2127 0, /* tp_dict */
2128 0, /* tp_descr_get */
2129 0, /* tp_descr_set */
2130 offsetof(BufferedRWPairObject, dict), /* tp_dictoffset */
2131 (initproc)BufferedRWPair_init, /* tp_init */
2132 0, /* tp_alloc */
2133 PyType_GenericNew, /* tp_new */
2134};
2135
2136
2137
2138/*
2139 * BufferedRandom
2140 */
2141
2142PyDoc_STRVAR(BufferedRandom_doc,
2143 "A buffered interface to random access streams.\n"
2144 "\n"
2145 "The constructor creates a reader and writer for a seekable stream,\n"
2146 "raw, given in the first argument. If the buffer_size is omitted it\n"
2147 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2148 );
2149
2150static int
2151BufferedRandom_init(BufferedObject *self, PyObject *args, PyObject *kwds)
2152{
2153 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2154 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002155 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002156 PyObject *raw;
2157
2158 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002159 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002160
2161 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2162 &raw, &buffer_size, &max_buffer_size)) {
2163 return -1;
2164 }
2165
Benjamin Peterson59406a92009-03-26 17:10:29 +00002166 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2167 return -1;
2168
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002169 if (_PyIOBase_checkSeekable(raw, Py_True) == NULL)
2170 return -1;
2171 if (_PyIOBase_checkReadable(raw, Py_True) == NULL)
2172 return -1;
2173 if (_PyIOBase_checkWritable(raw, Py_True) == NULL)
2174 return -1;
2175
2176 Py_CLEAR(self->raw);
2177 Py_INCREF(raw);
2178 self->raw = raw;
2179 self->buffer_size = buffer_size;
2180 self->readable = 1;
2181 self->writable = 1;
2182
2183 if (_Buffered_init(self) < 0)
2184 return -1;
2185 _BufferedReader_reset_buf(self);
2186 _BufferedWriter_reset_buf(self);
2187 self->pos = 0;
2188
Antoine Pitrou711af3a2009-04-11 15:39:24 +00002189 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2190 Py_TYPE(raw) == &PyFileIO_Type);
2191
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002192 self->ok = 1;
2193 return 0;
2194}
2195
2196static PyMethodDef BufferedRandom_methods[] = {
2197 /* BufferedIOMixin methods */
2198 {"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS},
Benjamin Petersond2e0c792009-05-01 20:40:59 +00002199 {"detach", (PyCFunction)BufferedIOMixin_detach, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002200 {"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS},
2201 {"readable", (PyCFunction)BufferedIOMixin_readable, METH_NOARGS},
2202 {"writable", (PyCFunction)BufferedIOMixin_writable, METH_NOARGS},
2203 {"fileno", (PyCFunction)BufferedIOMixin_fileno, METH_NOARGS},
2204 {"isatty", (PyCFunction)BufferedIOMixin_isatty, METH_NOARGS},
2205
2206 {"flush", (PyCFunction)Buffered_flush, METH_NOARGS},
2207
2208 {"seek", (PyCFunction)Buffered_seek, METH_VARARGS},
2209 {"tell", (PyCFunction)Buffered_tell, METH_NOARGS},
2210 {"truncate", (PyCFunction)Buffered_truncate, METH_VARARGS},
2211 {"read", (PyCFunction)Buffered_read, METH_VARARGS},
2212 {"read1", (PyCFunction)Buffered_read1, METH_VARARGS},
2213 {"readinto", (PyCFunction)Buffered_readinto, METH_VARARGS},
2214 {"readline", (PyCFunction)Buffered_readline, METH_VARARGS},
2215 {"peek", (PyCFunction)Buffered_peek, METH_VARARGS},
2216 {"write", (PyCFunction)BufferedWriter_write, METH_VARARGS},
2217 {NULL, NULL}
2218};
2219
2220static PyMemberDef BufferedRandom_members[] = {
2221 {"raw", T_OBJECT, offsetof(BufferedObject, raw), 0},
2222 {NULL}
2223};
2224
2225static PyGetSetDef BufferedRandom_getset[] = {
2226 {"closed", (getter)BufferedIOMixin_closed_get, NULL, NULL},
2227 {"name", (getter)BufferedIOMixin_name_get, NULL, NULL},
2228 {"mode", (getter)BufferedIOMixin_mode_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002229 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002230};
2231
2232
2233PyTypeObject PyBufferedRandom_Type = {
2234 PyVarObject_HEAD_INIT(NULL, 0)
2235 "_io.BufferedRandom", /*tp_name*/
2236 sizeof(BufferedObject), /*tp_basicsize*/
2237 0, /*tp_itemsize*/
2238 (destructor)BufferedObject_dealloc, /*tp_dealloc*/
2239 0, /*tp_print*/
2240 0, /*tp_getattr*/
2241 0, /*tp_setattr*/
2242 0, /*tp_compare */
Antoine Pitrou716c4442009-05-23 19:04:03 +00002243 (reprfunc)Buffered_repr, /*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002244 0, /*tp_as_number*/
2245 0, /*tp_as_sequence*/
2246 0, /*tp_as_mapping*/
2247 0, /*tp_hash */
2248 0, /*tp_call*/
2249 0, /*tp_str*/
2250 0, /*tp_getattro*/
2251 0, /*tp_setattro*/
2252 0, /*tp_as_buffer*/
2253 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2254 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2255 BufferedRandom_doc, /* tp_doc */
2256 (traverseproc)Buffered_traverse, /* tp_traverse */
2257 (inquiry)Buffered_clear, /* tp_clear */
2258 0, /* tp_richcompare */
2259 offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/
2260 0, /* tp_iter */
2261 (iternextfunc)Buffered_iternext, /* tp_iternext */
2262 BufferedRandom_methods, /* tp_methods */
2263 BufferedRandom_members, /* tp_members */
2264 BufferedRandom_getset, /* tp_getset */
2265 0, /* tp_base */
2266 0, /*tp_dict*/
2267 0, /* tp_descr_get */
2268 0, /* tp_descr_set */
2269 offsetof(BufferedObject, dict), /*tp_dictoffset*/
2270 (initproc)BufferedRandom_init, /* tp_init */
2271 0, /* tp_alloc */
2272 PyType_GenericNew, /* tp_new */
2273};
2274