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