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