blob: 01171cdc6a9db9402dbaee5979d264aface340a8 [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;
1147 static PyObject *sep = NULL;
1148
1149 /* Special case for when the number of bytes to read is unspecified. */
1150 if (n == -1) {
1151 PyObject *chunks = PyList_New(0);
1152 if (chunks == NULL)
1153 return NULL;
1154
1155 /* First copy what we have in the current buffer. */
1156 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1157 data = NULL;
1158 if (current_size) {
1159 data = PyBytes_FromStringAndSize(
1160 self->buffer + self->pos, current_size);
1161 if (data == NULL) {
1162 Py_DECREF(chunks);
1163 return NULL;
1164 }
1165 }
1166 _BufferedReader_reset_buf(self);
1167 /* We're going past the buffer's bounds, flush it */
1168 if (self->writable) {
1169 res = _BufferedWriter_flush_unlocked(self, 1);
1170 if (res == NULL) {
1171 Py_DECREF(chunks);
1172 return NULL;
1173 }
1174 Py_CLEAR(res);
1175 }
1176 while (1) {
1177 if (data) {
1178 if (PyList_Append(chunks, data) < 0) {
1179 Py_DECREF(data);
1180 Py_DECREF(chunks);
1181 return NULL;
1182 }
1183 Py_DECREF(data);
1184 }
1185
1186 /* Read until EOF or until read() would block. */
1187 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1188 if (data == NULL) {
1189 Py_DECREF(chunks);
1190 return NULL;
1191 }
1192 if (data != Py_None && !PyBytes_Check(data)) {
1193 Py_DECREF(data);
1194 Py_DECREF(chunks);
1195 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1196 return NULL;
1197 }
1198 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1199 if (current_size == 0) {
1200 Py_DECREF(chunks);
1201 return data;
1202 }
1203 else {
1204 if (sep == NULL) {
1205 sep = PyBytes_FromStringAndSize(NULL, 0);
1206 if (sep == NULL) {
1207 Py_DECREF(data);
1208 Py_DECREF(chunks);
1209 return NULL;
1210 }
1211 }
1212 res =_PyBytes_Join(sep, chunks);
1213 Py_DECREF(data);
1214 Py_DECREF(chunks);
1215 return res;
1216 }
1217 }
1218 current_size += PyBytes_GET_SIZE(data);
1219 if (self->abs_pos != -1)
1220 self->abs_pos += PyBytes_GET_SIZE(data);
1221 }
1222 }
1223
1224 /* The number of bytes to read is specified, return at most n bytes. */
1225 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1226 if (n <= current_size) {
1227 /* Fast path: the data to read is fully buffered. */
1228 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1229 if (res == NULL)
1230 goto error;
1231 self->pos += n;
1232 return res;
1233 }
1234
1235 /* Slow path: read from the stream until enough bytes are read,
1236 * or until an EOF occurs or until read() would block.
1237 */
1238 res = PyBytes_FromStringAndSize(NULL, n);
1239 if (res == NULL)
1240 goto error;
1241 out = PyBytes_AS_STRING(res);
1242 remaining = n;
1243 written = 0;
1244 if (current_size > 0) {
1245 memcpy(out, self->buffer + self->pos, current_size);
1246 remaining -= current_size;
1247 written += current_size;
1248 }
1249 _BufferedReader_reset_buf(self);
1250 while (remaining > 0) {
1251 /* We want to read a whole block at the end into buffer.
1252 If we had readv() we could do this in one pass. */
1253 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1254 if (r == 0)
1255 break;
1256 r = _BufferedReader_raw_read(self, out + written, r);
1257 if (r == -1)
1258 goto error;
1259 if (r == 0 || r == -2) {
1260 /* EOF occurred or read() would block. */
1261 if (r == 0 || written > 0) {
1262 if (_PyBytes_Resize(&res, written))
1263 goto error;
1264 return res;
1265 }
1266 Py_DECREF(res);
1267 Py_INCREF(Py_None);
1268 return Py_None;
1269 }
1270 remaining -= r;
1271 written += r;
1272 }
1273 assert(remaining <= self->buffer_size);
1274 self->pos = 0;
1275 self->raw_pos = 0;
1276 self->read_end = 0;
1277 while (self->read_end < self->buffer_size) {
1278 Py_ssize_t r = _BufferedReader_fill_buffer(self);
1279 if (r == -1)
1280 goto error;
1281 if (r == 0 || r == -2) {
1282 /* EOF occurred or read() would block. */
1283 if (r == 0 || written > 0) {
1284 if (_PyBytes_Resize(&res, written))
1285 goto error;
1286 return res;
1287 }
1288 Py_DECREF(res);
1289 Py_INCREF(Py_None);
1290 return Py_None;
1291 }
1292 if (remaining > r) {
1293 memcpy(out + written, self->buffer + self->pos, r);
1294 written += r;
1295 self->pos += r;
1296 remaining -= r;
1297 }
1298 else if (remaining > 0) {
1299 memcpy(out + written, self->buffer + self->pos, remaining);
1300 written += remaining;
1301 self->pos += remaining;
1302 remaining = 0;
1303 }
1304 if (remaining == 0)
1305 break;
1306 }
1307
1308 return res;
1309
1310error:
1311 Py_XDECREF(res);
1312 return NULL;
1313}
1314
1315static PyObject *
1316_BufferedReader_peek_unlocked(BufferedObject *self, Py_ssize_t n)
1317{
1318 Py_ssize_t have, r;
1319
1320 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1321 /* Constraints:
1322 1. we don't want to advance the file position.
1323 2. we don't want to lose block alignment, so we can't shift the buffer
1324 to make some place.
1325 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1326 */
1327 if (have > 0) {
1328 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1329 }
1330
1331 /* Fill the buffer from the raw stream, and copy it to the result. */
1332 _BufferedReader_reset_buf(self);
1333 r = _BufferedReader_fill_buffer(self);
1334 if (r == -1)
1335 return NULL;
1336 if (r == -2)
1337 r = 0;
1338 self->pos = 0;
1339 return PyBytes_FromStringAndSize(self->buffer, r);
1340}
1341
1342static PyMethodDef BufferedReader_methods[] = {
1343 /* BufferedIOMixin methods */
1344 {"flush", (PyCFunction)BufferedIOMixin_flush, METH_NOARGS},
1345 {"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS},
1346 {"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS},
1347 {"readable", (PyCFunction)BufferedIOMixin_readable, METH_NOARGS},
1348 {"writable", (PyCFunction)BufferedIOMixin_writable, METH_NOARGS},
1349 {"fileno", (PyCFunction)BufferedIOMixin_fileno, METH_NOARGS},
1350 {"isatty", (PyCFunction)BufferedIOMixin_isatty, METH_NOARGS},
1351
1352 {"read", (PyCFunction)Buffered_read, METH_VARARGS},
1353 {"peek", (PyCFunction)Buffered_peek, METH_VARARGS},
1354 {"read1", (PyCFunction)Buffered_read1, METH_VARARGS},
1355 {"readline", (PyCFunction)Buffered_readline, METH_VARARGS},
1356 {"seek", (PyCFunction)Buffered_seek, METH_VARARGS},
1357 {"tell", (PyCFunction)Buffered_tell, METH_NOARGS},
1358 {"truncate", (PyCFunction)Buffered_truncate, METH_VARARGS},
1359 {NULL, NULL}
1360};
1361
1362static PyMemberDef BufferedReader_members[] = {
1363 {"raw", T_OBJECT, offsetof(BufferedObject, raw), 0},
1364 {NULL}
1365};
1366
1367static PyGetSetDef BufferedReader_getset[] = {
1368 {"closed", (getter)BufferedIOMixin_closed_get, NULL, NULL},
1369 {"name", (getter)BufferedIOMixin_name_get, NULL, NULL},
1370 {"mode", (getter)BufferedIOMixin_mode_get, NULL, NULL},
1371 {0}
1372};
1373
1374
1375PyTypeObject PyBufferedReader_Type = {
1376 PyVarObject_HEAD_INIT(NULL, 0)
1377 "_io.BufferedReader", /*tp_name*/
1378 sizeof(BufferedObject), /*tp_basicsize*/
1379 0, /*tp_itemsize*/
1380 (destructor)BufferedObject_dealloc, /*tp_dealloc*/
1381 0, /*tp_print*/
1382 0, /*tp_getattr*/
1383 0, /*tp_setattr*/
1384 0, /*tp_compare */
1385 0, /*tp_repr*/
1386 0, /*tp_as_number*/
1387 0, /*tp_as_sequence*/
1388 0, /*tp_as_mapping*/
1389 0, /*tp_hash */
1390 0, /*tp_call*/
1391 0, /*tp_str*/
1392 0, /*tp_getattro*/
1393 0, /*tp_setattro*/
1394 0, /*tp_as_buffer*/
1395 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1396 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1397 BufferedReader_doc, /* tp_doc */
1398 (traverseproc)Buffered_traverse, /* tp_traverse */
1399 (inquiry)Buffered_clear, /* tp_clear */
1400 0, /* tp_richcompare */
1401 offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/
1402 0, /* tp_iter */
1403 (iternextfunc)Buffered_iternext, /* tp_iternext */
1404 BufferedReader_methods, /* tp_methods */
1405 BufferedReader_members, /* tp_members */
1406 BufferedReader_getset, /* tp_getset */
1407 0, /* tp_base */
1408 0, /* tp_dict */
1409 0, /* tp_descr_get */
1410 0, /* tp_descr_set */
1411 offsetof(BufferedObject, dict), /* tp_dictoffset */
1412 (initproc)BufferedReader_init, /* tp_init */
1413 0, /* tp_alloc */
1414 PyType_GenericNew, /* tp_new */
1415};
1416
1417
Benjamin Peterson59406a92009-03-26 17:10:29 +00001418
1419static int
1420complain_about_max_buffer_size(void)
1421{
1422 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1423 "max_buffer_size is deprecated", 1) < 0)
1424 return 0;
1425 return 1;
1426}
1427
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001428/*
1429 * class BufferedWriter
1430 */
1431PyDoc_STRVAR(BufferedWriter_doc,
1432 "A buffer for a writeable sequential RawIO object.\n"
1433 "\n"
1434 "The constructor creates a BufferedWriter for the given writeable raw\n"
1435 "stream. If the buffer_size is not given, it defaults to\n"
1436 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1437 );
1438
1439static void
1440_BufferedWriter_reset_buf(BufferedObject *self)
1441{
1442 self->write_pos = 0;
1443 self->write_end = -1;
1444}
1445
1446static int
1447BufferedWriter_init(BufferedObject *self, PyObject *args, PyObject *kwds)
1448{
1449 /* TODO: properly deprecate max_buffer_size */
1450 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1451 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001452 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001453 PyObject *raw;
1454
1455 self->ok = 0;
1456
1457 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1458 &raw, &buffer_size, &max_buffer_size)) {
1459 return -1;
1460 }
1461
Benjamin Peterson59406a92009-03-26 17:10:29 +00001462 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1463 return -1;
1464
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001465 if (_PyIOBase_checkWritable(raw, Py_True) == NULL)
1466 return -1;
1467
1468 Py_CLEAR(self->raw);
1469 Py_INCREF(raw);
1470 self->raw = raw;
1471 self->readable = 0;
1472 self->writable = 1;
1473
1474 self->buffer_size = buffer_size;
1475 if (_Buffered_init(self) < 0)
1476 return -1;
1477 _BufferedWriter_reset_buf(self);
1478 self->pos = 0;
1479
1480 self->ok = 1;
1481 return 0;
1482}
1483
1484static Py_ssize_t
1485_BufferedWriter_raw_write(BufferedObject *self, char *start, Py_ssize_t len)
1486{
1487 Py_buffer buf;
1488 PyObject *memobj, *res;
1489 Py_ssize_t n;
1490 /* NOTE: the buffer needn't be released as its object is NULL. */
1491 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1492 return -1;
1493 memobj = PyMemoryView_FromBuffer(&buf);
1494 if (memobj == NULL)
1495 return -1;
1496 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1497 Py_DECREF(memobj);
1498 if (res == NULL)
1499 return -1;
1500 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1501 Py_DECREF(res);
1502 if (n < 0 || n > len) {
1503 PyErr_Format(PyExc_IOError,
1504 "raw write() returned invalid length %zd "
1505 "(should have been between 0 and %zd)", n, len);
1506 return -1;
1507 }
1508 if (n > 0 && self->abs_pos != -1)
1509 self->abs_pos += n;
1510 return n;
1511}
1512
1513/* `restore_pos` is 1 if we need to restore the raw stream position at
1514 the end, 0 otherwise. */
1515static PyObject *
1516_BufferedWriter_flush_unlocked(BufferedObject *self, int restore_pos)
1517{
1518 Py_ssize_t written = 0;
1519 Py_off_t n, rewind;
1520
1521 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1522 goto end;
1523 /* First, rewind */
1524 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1525 if (rewind != 0) {
1526 n = _Buffered_raw_seek(self, -rewind, 1);
1527 if (n < 0) {
1528 goto error;
1529 }
1530 self->raw_pos -= rewind;
1531 }
1532 while (self->write_pos < self->write_end) {
1533 n = _BufferedWriter_raw_write(self,
1534 self->buffer + self->write_pos,
1535 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1536 Py_off_t, Py_ssize_t));
1537 if (n == -1) {
1538 Py_ssize_t *w = _Buffered_check_blocking_error();
1539 if (w == NULL)
1540 goto error;
1541 self->write_pos += *w;
1542 self->raw_pos = self->write_pos;
1543 written += *w;
1544 *w = written;
1545 /* Already re-raised */
1546 goto error;
1547 }
1548 self->write_pos += n;
1549 self->raw_pos = self->write_pos;
1550 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1551 }
1552
1553 if (restore_pos) {
1554 Py_off_t forward = rewind - written;
1555 if (forward != 0) {
1556 n = _Buffered_raw_seek(self, forward, 1);
1557 if (n < 0) {
1558 goto error;
1559 }
1560 self->raw_pos += forward;
1561 }
1562 }
1563 _BufferedWriter_reset_buf(self);
1564
1565end:
1566 Py_RETURN_NONE;
1567
1568error:
1569 return NULL;
1570}
1571
1572static PyObject *
1573BufferedWriter_write(BufferedObject *self, PyObject *args)
1574{
1575 PyObject *res = NULL;
1576 Py_buffer buf;
1577 Py_ssize_t written, avail, remaining, n;
1578
1579 CHECK_INITIALIZED(self)
1580 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1581 return NULL;
1582 }
1583
1584 if (BufferedIOMixin_closed(self)) {
1585 PyErr_SetString(PyExc_ValueError, "write to closed file");
1586 PyBuffer_Release(&buf);
1587 return NULL;
1588 }
1589
1590 ENTER_BUFFERED(self)
1591
1592 /* Fast path: the data to write can be fully buffered. */
1593 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1594 self->pos = 0;
1595 self->raw_pos = 0;
1596 }
1597 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1598 if (buf.len <= avail) {
1599 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1600 if (!VALID_WRITE_BUFFER(self)) {
1601 self->write_pos = self->pos;
1602 }
1603 ADJUST_POSITION(self, self->pos + buf.len);
1604 if (self->pos > self->write_end)
1605 self->write_end = self->pos;
1606 written = buf.len;
1607 goto end;
1608 }
1609
1610 /* First write the current buffer */
1611 res = _BufferedWriter_flush_unlocked(self, 0);
1612 if (res == NULL) {
1613 Py_ssize_t *w = _Buffered_check_blocking_error();
1614 if (w == NULL)
1615 goto error;
1616 if (self->readable)
1617 _BufferedReader_reset_buf(self);
1618 /* Make some place by shifting the buffer. */
1619 assert(VALID_WRITE_BUFFER(self));
1620 memmove(self->buffer, self->buffer + self->write_pos,
1621 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1622 Py_off_t, Py_ssize_t));
1623 self->write_end -= self->write_pos;
1624 self->raw_pos -= self->write_pos;
1625 self->pos -= self->write_pos;
1626 self->write_pos = 0;
1627 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1628 Py_off_t, Py_ssize_t);
1629 if (buf.len <= avail) {
1630 /* Everything can be buffered */
1631 PyErr_Clear();
1632 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1633 self->write_end += buf.len;
1634 written = buf.len;
1635 goto end;
1636 }
1637 /* Buffer as much as possible. */
1638 memcpy(self->buffer + self->write_end, buf.buf, avail);
1639 self->write_end += avail;
1640 /* Already re-raised */
1641 *w = avail;
1642 goto error;
1643 }
1644 Py_CLEAR(res);
1645
1646 /* Then write buf itself. At this point the buffer has been emptied. */
1647 remaining = buf.len;
1648 written = 0;
1649 while (remaining > self->buffer_size) {
1650 n = _BufferedWriter_raw_write(
1651 self, (char *) buf.buf + written, buf.len - written);
1652 if (n == -1) {
1653 Py_ssize_t *w = _Buffered_check_blocking_error();
1654 if (w == NULL)
1655 goto error;
1656 written += *w;
1657 remaining -= *w;
1658 if (remaining > self->buffer_size) {
1659 /* Can't buffer everything, still buffer as much as possible */
1660 memcpy(self->buffer,
1661 (char *) buf.buf + written, self->buffer_size);
1662 self->raw_pos = 0;
1663 ADJUST_POSITION(self, self->buffer_size);
1664 self->write_end = self->buffer_size;
1665 *w = written + self->buffer_size;
1666 /* Already re-raised */
1667 goto error;
1668 }
1669 PyErr_Clear();
1670 break;
1671 }
1672 written += n;
1673 remaining -= n;
1674 }
1675 if (self->readable)
1676 _BufferedReader_reset_buf(self);
1677 if (remaining > 0) {
1678 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1679 written += remaining;
1680 }
1681 self->write_pos = 0;
1682 /* TODO: sanity check (remaining >= 0) */
1683 self->write_end = remaining;
1684 ADJUST_POSITION(self, remaining);
1685 self->raw_pos = 0;
1686
1687end:
1688 res = PyLong_FromSsize_t(written);
1689
1690error:
1691 LEAVE_BUFFERED(self)
1692 PyBuffer_Release(&buf);
1693 return res;
1694}
1695
1696static PyMethodDef BufferedWriter_methods[] = {
1697 /* BufferedIOMixin methods */
1698 {"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS},
1699 {"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS},
1700 {"readable", (PyCFunction)BufferedIOMixin_readable, METH_NOARGS},
1701 {"writable", (PyCFunction)BufferedIOMixin_writable, METH_NOARGS},
1702 {"fileno", (PyCFunction)BufferedIOMixin_fileno, METH_NOARGS},
1703 {"isatty", (PyCFunction)BufferedIOMixin_isatty, METH_NOARGS},
1704
1705 {"write", (PyCFunction)BufferedWriter_write, METH_VARARGS},
1706 {"truncate", (PyCFunction)Buffered_truncate, METH_VARARGS},
1707 {"flush", (PyCFunction)Buffered_flush, METH_NOARGS},
1708 {"seek", (PyCFunction)Buffered_seek, METH_VARARGS},
1709 {"tell", (PyCFunction)Buffered_tell, METH_NOARGS},
1710 {NULL, NULL}
1711};
1712
1713static PyMemberDef BufferedWriter_members[] = {
1714 {"raw", T_OBJECT, offsetof(BufferedObject, raw), 0},
1715 {NULL}
1716};
1717
1718static PyGetSetDef BufferedWriter_getset[] = {
1719 {"closed", (getter)BufferedIOMixin_closed_get, NULL, NULL},
1720 {"name", (getter)BufferedIOMixin_name_get, NULL, NULL},
1721 {"mode", (getter)BufferedIOMixin_mode_get, NULL, NULL},
1722 {0}
1723};
1724
1725
1726PyTypeObject PyBufferedWriter_Type = {
1727 PyVarObject_HEAD_INIT(NULL, 0)
1728 "_io.BufferedWriter", /*tp_name*/
1729 sizeof(BufferedObject), /*tp_basicsize*/
1730 0, /*tp_itemsize*/
1731 (destructor)BufferedObject_dealloc, /*tp_dealloc*/
1732 0, /*tp_print*/
1733 0, /*tp_getattr*/
1734 0, /*tp_setattr*/
1735 0, /*tp_compare */
1736 0, /*tp_repr*/
1737 0, /*tp_as_number*/
1738 0, /*tp_as_sequence*/
1739 0, /*tp_as_mapping*/
1740 0, /*tp_hash */
1741 0, /*tp_call*/
1742 0, /*tp_str*/
1743 0, /*tp_getattro*/
1744 0, /*tp_setattro*/
1745 0, /*tp_as_buffer*/
1746 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1747 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1748 BufferedWriter_doc, /* tp_doc */
1749 (traverseproc)Buffered_traverse, /* tp_traverse */
1750 (inquiry)Buffered_clear, /* tp_clear */
1751 0, /* tp_richcompare */
1752 offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/
1753 0, /* tp_iter */
1754 0, /* tp_iternext */
1755 BufferedWriter_methods, /* tp_methods */
1756 BufferedWriter_members, /* tp_members */
1757 BufferedWriter_getset, /* tp_getset */
1758 0, /* tp_base */
1759 0, /* tp_dict */
1760 0, /* tp_descr_get */
1761 0, /* tp_descr_set */
1762 offsetof(BufferedObject, dict), /* tp_dictoffset */
1763 (initproc)BufferedWriter_init, /* tp_init */
1764 0, /* tp_alloc */
1765 PyType_GenericNew, /* tp_new */
1766};
1767
1768
1769
1770/*
1771 * BufferedRWPair
1772 */
1773
1774PyDoc_STRVAR(BufferedRWPair_doc,
1775 "A buffered reader and writer object together.\n"
1776 "\n"
1777 "A buffered reader object and buffered writer object put together to\n"
1778 "form a sequential IO object that can read and write. This is typically\n"
1779 "used with a socket or two-way pipe.\n"
1780 "\n"
1781 "reader and writer are RawIOBase objects that are readable and\n"
1782 "writeable respectively. If the buffer_size is omitted it defaults to\n"
Benjamin Peterson59406a92009-03-26 17:10:29 +00001783 "DEFAULT_BUFFER_SIZE.\n"
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001784 );
1785
1786/* XXX The usefulness of this (compared to having two separate IO objects) is
1787 * questionable.
1788 */
1789
1790typedef struct {
1791 PyObject_HEAD
1792 BufferedObject *reader;
1793 BufferedObject *writer;
1794 PyObject *dict;
1795 PyObject *weakreflist;
1796} BufferedRWPairObject;
1797
1798static int
1799BufferedRWPair_init(BufferedRWPairObject *self, PyObject *args,
1800 PyObject *kwds)
1801{
1802 PyObject *reader, *writer;
1803 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00001804 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001805
1806 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1807 &buffer_size, &max_buffer_size)) {
1808 return -1;
1809 }
1810
Benjamin Peterson59406a92009-03-26 17:10:29 +00001811 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1812 return -1;
1813
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001814 if (_PyIOBase_checkReadable(reader, Py_True) == NULL)
1815 return -1;
1816 if (_PyIOBase_checkWritable(writer, Py_True) == NULL)
1817 return -1;
1818
1819 args = Py_BuildValue("(n)", buffer_size);
1820 if (args == NULL) {
1821 Py_CLEAR(self->reader);
1822 return -1;
1823 }
1824 self->reader = (BufferedObject *)PyType_GenericNew(
1825 &PyBufferedReader_Type, args, NULL);
1826 Py_DECREF(args);
1827 if (self->reader == NULL)
1828 return -1;
1829
Benjamin Peterson59406a92009-03-26 17:10:29 +00001830 args = Py_BuildValue("(n)", buffer_size);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001831 if (args == NULL) {
1832 Py_CLEAR(self->reader);
1833 return -1;
1834 }
1835 self->writer = (BufferedObject *)PyType_GenericNew(
1836 &PyBufferedWriter_Type, args, NULL);
1837 Py_DECREF(args);
1838 if (self->writer == NULL) {
1839 Py_CLEAR(self->reader);
1840 return -1;
1841 }
1842 return 0;
1843}
1844
1845static int
1846BufferedRWPair_traverse(BufferedRWPairObject *self, visitproc visit, void *arg)
1847{
1848 Py_VISIT(self->dict);
1849 return 0;
1850}
1851
1852static int
1853BufferedRWPair_clear(BufferedRWPairObject *self)
1854{
1855 Py_CLEAR(self->reader);
1856 Py_CLEAR(self->writer);
1857 Py_CLEAR(self->dict);
1858 return 0;
1859}
1860
1861static void
1862BufferedRWPair_dealloc(BufferedRWPairObject *self)
1863{
1864 _PyObject_GC_UNTRACK(self);
1865 Py_CLEAR(self->reader);
1866 Py_CLEAR(self->writer);
1867 Py_CLEAR(self->dict);
1868 Py_TYPE(self)->tp_free((PyObject *) self);
1869}
1870
1871static PyObject *
1872_forward_call(BufferedObject *self, const char *name, PyObject *args)
1873{
1874 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
1875 PyObject *ret;
1876
1877 if (func == NULL) {
1878 PyErr_SetString(PyExc_AttributeError, name);
1879 return NULL;
1880 }
1881
1882 ret = PyObject_CallObject(func, args);
1883 Py_DECREF(func);
1884 return ret;
1885}
1886
1887static PyObject *
1888BufferedRWPair_read(BufferedRWPairObject *self, PyObject *args)
1889{
1890 return _forward_call(self->reader, "read", args);
1891}
1892
1893static PyObject *
1894BufferedRWPair_peek(BufferedRWPairObject *self, PyObject *args)
1895{
1896 return _forward_call(self->reader, "peek", args);
1897}
1898
1899static PyObject *
1900BufferedRWPair_read1(BufferedRWPairObject *self, PyObject *args)
1901{
1902 return _forward_call(self->reader, "read1", args);
1903}
1904
1905static PyObject *
1906BufferedRWPair_write(BufferedRWPairObject *self, PyObject *args)
1907{
1908 return _forward_call(self->writer, "write", args);
1909}
1910
1911static PyObject *
1912BufferedRWPair_flush(BufferedRWPairObject *self, PyObject *args)
1913{
1914 return _forward_call(self->writer, "flush", args);
1915}
1916
1917static PyObject *
1918BufferedRWPair_readable(BufferedRWPairObject *self, PyObject *args)
1919{
1920 return _forward_call(self->reader, "readable", args);
1921}
1922
1923static PyObject *
1924BufferedRWPair_writable(BufferedRWPairObject *self, PyObject *args)
1925{
1926 return _forward_call(self->writer, "writable", args);
1927}
1928
1929static PyObject *
1930BufferedRWPair_close(BufferedRWPairObject *self, PyObject *args)
1931{
1932 PyObject *ret = _forward_call(self->writer, "close", args);
1933 if (ret == NULL)
1934 return NULL;
1935 Py_DECREF(ret);
1936
1937 return _forward_call(self->reader, "close", args);
1938}
1939
1940static PyObject *
1941BufferedRWPair_isatty(BufferedRWPairObject *self, PyObject *args)
1942{
1943 PyObject *ret = _forward_call(self->writer, "isatty", args);
1944
1945 if (ret != Py_False) {
1946 /* either True or exception */
1947 return ret;
1948 }
1949 Py_DECREF(ret);
1950
1951 return _forward_call(self->reader, "isatty", args);
1952}
1953
1954
1955static PyMethodDef BufferedRWPair_methods[] = {
1956 {"read", (PyCFunction)BufferedRWPair_read, METH_VARARGS},
1957 {"peek", (PyCFunction)BufferedRWPair_peek, METH_VARARGS},
1958 {"read1", (PyCFunction)BufferedRWPair_read1, METH_VARARGS},
1959 {"readinto", (PyCFunction)Buffered_readinto, METH_VARARGS},
1960
1961 {"write", (PyCFunction)BufferedRWPair_write, METH_VARARGS},
1962 {"flush", (PyCFunction)BufferedRWPair_flush, METH_NOARGS},
1963
1964 {"readable", (PyCFunction)BufferedRWPair_readable, METH_NOARGS},
1965 {"writable", (PyCFunction)BufferedRWPair_writable, METH_NOARGS},
1966
1967 {"close", (PyCFunction)BufferedRWPair_close, METH_NOARGS},
1968 {"isatty", (PyCFunction)BufferedRWPair_isatty, METH_NOARGS},
1969
1970 {NULL, NULL}
1971};
1972
1973PyTypeObject PyBufferedRWPair_Type = {
1974 PyVarObject_HEAD_INIT(NULL, 0)
1975 "_io.BufferedRWPair", /*tp_name*/
1976 sizeof(BufferedRWPairObject), /*tp_basicsize*/
1977 0, /*tp_itemsize*/
1978 (destructor)BufferedRWPair_dealloc, /*tp_dealloc*/
1979 0, /*tp_print*/
1980 0, /*tp_getattr*/
1981 0, /*tp_setattr*/
1982 0, /*tp_compare */
1983 0, /*tp_repr*/
1984 0, /*tp_as_number*/
1985 0, /*tp_as_sequence*/
1986 0, /*tp_as_mapping*/
1987 0, /*tp_hash */
1988 0, /*tp_call*/
1989 0, /*tp_str*/
1990 0, /*tp_getattro*/
1991 0, /*tp_setattro*/
1992 0, /*tp_as_buffer*/
1993 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1994 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1995 BufferedRWPair_doc, /* tp_doc */
1996 (traverseproc)BufferedRWPair_traverse, /* tp_traverse */
1997 (inquiry)BufferedRWPair_clear, /* tp_clear */
1998 0, /* tp_richcompare */
1999 offsetof(BufferedRWPairObject, weakreflist), /*tp_weaklistoffset*/
2000 0, /* tp_iter */
2001 0, /* tp_iternext */
2002 BufferedRWPair_methods, /* tp_methods */
2003 0, /* tp_members */
2004 0, /* tp_getset */
2005 0, /* tp_base */
2006 0, /* tp_dict */
2007 0, /* tp_descr_get */
2008 0, /* tp_descr_set */
2009 offsetof(BufferedRWPairObject, dict), /* tp_dictoffset */
2010 (initproc)BufferedRWPair_init, /* tp_init */
2011 0, /* tp_alloc */
2012 PyType_GenericNew, /* tp_new */
2013};
2014
2015
2016
2017/*
2018 * BufferedRandom
2019 */
2020
2021PyDoc_STRVAR(BufferedRandom_doc,
2022 "A buffered interface to random access streams.\n"
2023 "\n"
2024 "The constructor creates a reader and writer for a seekable stream,\n"
2025 "raw, given in the first argument. If the buffer_size is omitted it\n"
2026 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2027 );
2028
2029static int
2030BufferedRandom_init(BufferedObject *self, PyObject *args, PyObject *kwds)
2031{
2032 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2033 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
Benjamin Peterson59406a92009-03-26 17:10:29 +00002034 Py_ssize_t max_buffer_size = -234;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002035 PyObject *raw;
2036
2037 self->ok = 0;
2038
2039 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2040 &raw, &buffer_size, &max_buffer_size)) {
2041 return -1;
2042 }
2043
Benjamin Peterson59406a92009-03-26 17:10:29 +00002044 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2045 return -1;
2046
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002047 if (_PyIOBase_checkSeekable(raw, Py_True) == NULL)
2048 return -1;
2049 if (_PyIOBase_checkReadable(raw, Py_True) == NULL)
2050 return -1;
2051 if (_PyIOBase_checkWritable(raw, Py_True) == NULL)
2052 return -1;
2053
2054 Py_CLEAR(self->raw);
2055 Py_INCREF(raw);
2056 self->raw = raw;
2057 self->buffer_size = buffer_size;
2058 self->readable = 1;
2059 self->writable = 1;
2060
2061 if (_Buffered_init(self) < 0)
2062 return -1;
2063 _BufferedReader_reset_buf(self);
2064 _BufferedWriter_reset_buf(self);
2065 self->pos = 0;
2066
2067 self->ok = 1;
2068 return 0;
2069}
2070
2071static PyMethodDef BufferedRandom_methods[] = {
2072 /* BufferedIOMixin methods */
2073 {"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS},
2074 {"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS},
2075 {"readable", (PyCFunction)BufferedIOMixin_readable, METH_NOARGS},
2076 {"writable", (PyCFunction)BufferedIOMixin_writable, METH_NOARGS},
2077 {"fileno", (PyCFunction)BufferedIOMixin_fileno, METH_NOARGS},
2078 {"isatty", (PyCFunction)BufferedIOMixin_isatty, METH_NOARGS},
2079
2080 {"flush", (PyCFunction)Buffered_flush, METH_NOARGS},
2081
2082 {"seek", (PyCFunction)Buffered_seek, METH_VARARGS},
2083 {"tell", (PyCFunction)Buffered_tell, METH_NOARGS},
2084 {"truncate", (PyCFunction)Buffered_truncate, METH_VARARGS},
2085 {"read", (PyCFunction)Buffered_read, METH_VARARGS},
2086 {"read1", (PyCFunction)Buffered_read1, METH_VARARGS},
2087 {"readinto", (PyCFunction)Buffered_readinto, METH_VARARGS},
2088 {"readline", (PyCFunction)Buffered_readline, METH_VARARGS},
2089 {"peek", (PyCFunction)Buffered_peek, METH_VARARGS},
2090 {"write", (PyCFunction)BufferedWriter_write, METH_VARARGS},
2091 {NULL, NULL}
2092};
2093
2094static PyMemberDef BufferedRandom_members[] = {
2095 {"raw", T_OBJECT, offsetof(BufferedObject, raw), 0},
2096 {NULL}
2097};
2098
2099static PyGetSetDef BufferedRandom_getset[] = {
2100 {"closed", (getter)BufferedIOMixin_closed_get, NULL, NULL},
2101 {"name", (getter)BufferedIOMixin_name_get, NULL, NULL},
2102 {"mode", (getter)BufferedIOMixin_mode_get, NULL, NULL},
2103 {0}
2104};
2105
2106
2107PyTypeObject PyBufferedRandom_Type = {
2108 PyVarObject_HEAD_INIT(NULL, 0)
2109 "_io.BufferedRandom", /*tp_name*/
2110 sizeof(BufferedObject), /*tp_basicsize*/
2111 0, /*tp_itemsize*/
2112 (destructor)BufferedObject_dealloc, /*tp_dealloc*/
2113 0, /*tp_print*/
2114 0, /*tp_getattr*/
2115 0, /*tp_setattr*/
2116 0, /*tp_compare */
2117 0, /*tp_repr*/
2118 0, /*tp_as_number*/
2119 0, /*tp_as_sequence*/
2120 0, /*tp_as_mapping*/
2121 0, /*tp_hash */
2122 0, /*tp_call*/
2123 0, /*tp_str*/
2124 0, /*tp_getattro*/
2125 0, /*tp_setattro*/
2126 0, /*tp_as_buffer*/
2127 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2128 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2129 BufferedRandom_doc, /* tp_doc */
2130 (traverseproc)Buffered_traverse, /* tp_traverse */
2131 (inquiry)Buffered_clear, /* tp_clear */
2132 0, /* tp_richcompare */
2133 offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/
2134 0, /* tp_iter */
2135 (iternextfunc)Buffered_iternext, /* tp_iternext */
2136 BufferedRandom_methods, /* tp_methods */
2137 BufferedRandom_members, /* tp_members */
2138 BufferedRandom_getset, /* tp_getset */
2139 0, /* tp_base */
2140 0, /*tp_dict*/
2141 0, /* tp_descr_get */
2142 0, /* tp_descr_set */
2143 offsetof(BufferedObject, dict), /*tp_dictoffset*/
2144 (initproc)BufferedRandom_init, /* tp_init */
2145 0, /* tp_alloc */
2146 PyType_GenericNew, /* tp_new */
2147};
2148