blob: 88f4fbc5b1ebda9544bf2ab64b7421e71c20aa6c [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
1418/*
1419 * class BufferedWriter
1420 */
1421PyDoc_STRVAR(BufferedWriter_doc,
1422 "A buffer for a writeable sequential RawIO object.\n"
1423 "\n"
1424 "The constructor creates a BufferedWriter for the given writeable raw\n"
1425 "stream. If the buffer_size is not given, it defaults to\n"
1426 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1427 );
1428
1429static void
1430_BufferedWriter_reset_buf(BufferedObject *self)
1431{
1432 self->write_pos = 0;
1433 self->write_end = -1;
1434}
1435
1436static int
1437BufferedWriter_init(BufferedObject *self, PyObject *args, PyObject *kwds)
1438{
1439 /* TODO: properly deprecate max_buffer_size */
1440 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1441 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1442 Py_ssize_t max_buffer_size = -1;
1443 PyObject *raw;
1444
1445 self->ok = 0;
1446
1447 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1448 &raw, &buffer_size, &max_buffer_size)) {
1449 return -1;
1450 }
1451
1452 if (_PyIOBase_checkWritable(raw, Py_True) == NULL)
1453 return -1;
1454
1455 Py_CLEAR(self->raw);
1456 Py_INCREF(raw);
1457 self->raw = raw;
1458 self->readable = 0;
1459 self->writable = 1;
1460
1461 self->buffer_size = buffer_size;
1462 if (_Buffered_init(self) < 0)
1463 return -1;
1464 _BufferedWriter_reset_buf(self);
1465 self->pos = 0;
1466
1467 self->ok = 1;
1468 return 0;
1469}
1470
1471static Py_ssize_t
1472_BufferedWriter_raw_write(BufferedObject *self, char *start, Py_ssize_t len)
1473{
1474 Py_buffer buf;
1475 PyObject *memobj, *res;
1476 Py_ssize_t n;
1477 /* NOTE: the buffer needn't be released as its object is NULL. */
1478 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1479 return -1;
1480 memobj = PyMemoryView_FromBuffer(&buf);
1481 if (memobj == NULL)
1482 return -1;
1483 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1484 Py_DECREF(memobj);
1485 if (res == NULL)
1486 return -1;
1487 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1488 Py_DECREF(res);
1489 if (n < 0 || n > len) {
1490 PyErr_Format(PyExc_IOError,
1491 "raw write() returned invalid length %zd "
1492 "(should have been between 0 and %zd)", n, len);
1493 return -1;
1494 }
1495 if (n > 0 && self->abs_pos != -1)
1496 self->abs_pos += n;
1497 return n;
1498}
1499
1500/* `restore_pos` is 1 if we need to restore the raw stream position at
1501 the end, 0 otherwise. */
1502static PyObject *
1503_BufferedWriter_flush_unlocked(BufferedObject *self, int restore_pos)
1504{
1505 Py_ssize_t written = 0;
1506 Py_off_t n, rewind;
1507
1508 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1509 goto end;
1510 /* First, rewind */
1511 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1512 if (rewind != 0) {
1513 n = _Buffered_raw_seek(self, -rewind, 1);
1514 if (n < 0) {
1515 goto error;
1516 }
1517 self->raw_pos -= rewind;
1518 }
1519 while (self->write_pos < self->write_end) {
1520 n = _BufferedWriter_raw_write(self,
1521 self->buffer + self->write_pos,
1522 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1523 Py_off_t, Py_ssize_t));
1524 if (n == -1) {
1525 Py_ssize_t *w = _Buffered_check_blocking_error();
1526 if (w == NULL)
1527 goto error;
1528 self->write_pos += *w;
1529 self->raw_pos = self->write_pos;
1530 written += *w;
1531 *w = written;
1532 /* Already re-raised */
1533 goto error;
1534 }
1535 self->write_pos += n;
1536 self->raw_pos = self->write_pos;
1537 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1538 }
1539
1540 if (restore_pos) {
1541 Py_off_t forward = rewind - written;
1542 if (forward != 0) {
1543 n = _Buffered_raw_seek(self, forward, 1);
1544 if (n < 0) {
1545 goto error;
1546 }
1547 self->raw_pos += forward;
1548 }
1549 }
1550 _BufferedWriter_reset_buf(self);
1551
1552end:
1553 Py_RETURN_NONE;
1554
1555error:
1556 return NULL;
1557}
1558
1559static PyObject *
1560BufferedWriter_write(BufferedObject *self, PyObject *args)
1561{
1562 PyObject *res = NULL;
1563 Py_buffer buf;
1564 Py_ssize_t written, avail, remaining, n;
1565
1566 CHECK_INITIALIZED(self)
1567 if (!PyArg_ParseTuple(args, "y*:write", &buf)) {
1568 return NULL;
1569 }
1570
1571 if (BufferedIOMixin_closed(self)) {
1572 PyErr_SetString(PyExc_ValueError, "write to closed file");
1573 PyBuffer_Release(&buf);
1574 return NULL;
1575 }
1576
1577 ENTER_BUFFERED(self)
1578
1579 /* Fast path: the data to write can be fully buffered. */
1580 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1581 self->pos = 0;
1582 self->raw_pos = 0;
1583 }
1584 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1585 if (buf.len <= avail) {
1586 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1587 if (!VALID_WRITE_BUFFER(self)) {
1588 self->write_pos = self->pos;
1589 }
1590 ADJUST_POSITION(self, self->pos + buf.len);
1591 if (self->pos > self->write_end)
1592 self->write_end = self->pos;
1593 written = buf.len;
1594 goto end;
1595 }
1596
1597 /* First write the current buffer */
1598 res = _BufferedWriter_flush_unlocked(self, 0);
1599 if (res == NULL) {
1600 Py_ssize_t *w = _Buffered_check_blocking_error();
1601 if (w == NULL)
1602 goto error;
1603 if (self->readable)
1604 _BufferedReader_reset_buf(self);
1605 /* Make some place by shifting the buffer. */
1606 assert(VALID_WRITE_BUFFER(self));
1607 memmove(self->buffer, self->buffer + self->write_pos,
1608 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1609 Py_off_t, Py_ssize_t));
1610 self->write_end -= self->write_pos;
1611 self->raw_pos -= self->write_pos;
1612 self->pos -= self->write_pos;
1613 self->write_pos = 0;
1614 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1615 Py_off_t, Py_ssize_t);
1616 if (buf.len <= avail) {
1617 /* Everything can be buffered */
1618 PyErr_Clear();
1619 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1620 self->write_end += buf.len;
1621 written = buf.len;
1622 goto end;
1623 }
1624 /* Buffer as much as possible. */
1625 memcpy(self->buffer + self->write_end, buf.buf, avail);
1626 self->write_end += avail;
1627 /* Already re-raised */
1628 *w = avail;
1629 goto error;
1630 }
1631 Py_CLEAR(res);
1632
1633 /* Then write buf itself. At this point the buffer has been emptied. */
1634 remaining = buf.len;
1635 written = 0;
1636 while (remaining > self->buffer_size) {
1637 n = _BufferedWriter_raw_write(
1638 self, (char *) buf.buf + written, buf.len - written);
1639 if (n == -1) {
1640 Py_ssize_t *w = _Buffered_check_blocking_error();
1641 if (w == NULL)
1642 goto error;
1643 written += *w;
1644 remaining -= *w;
1645 if (remaining > self->buffer_size) {
1646 /* Can't buffer everything, still buffer as much as possible */
1647 memcpy(self->buffer,
1648 (char *) buf.buf + written, self->buffer_size);
1649 self->raw_pos = 0;
1650 ADJUST_POSITION(self, self->buffer_size);
1651 self->write_end = self->buffer_size;
1652 *w = written + self->buffer_size;
1653 /* Already re-raised */
1654 goto error;
1655 }
1656 PyErr_Clear();
1657 break;
1658 }
1659 written += n;
1660 remaining -= n;
1661 }
1662 if (self->readable)
1663 _BufferedReader_reset_buf(self);
1664 if (remaining > 0) {
1665 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1666 written += remaining;
1667 }
1668 self->write_pos = 0;
1669 /* TODO: sanity check (remaining >= 0) */
1670 self->write_end = remaining;
1671 ADJUST_POSITION(self, remaining);
1672 self->raw_pos = 0;
1673
1674end:
1675 res = PyLong_FromSsize_t(written);
1676
1677error:
1678 LEAVE_BUFFERED(self)
1679 PyBuffer_Release(&buf);
1680 return res;
1681}
1682
1683static PyMethodDef BufferedWriter_methods[] = {
1684 /* BufferedIOMixin methods */
1685 {"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS},
1686 {"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS},
1687 {"readable", (PyCFunction)BufferedIOMixin_readable, METH_NOARGS},
1688 {"writable", (PyCFunction)BufferedIOMixin_writable, METH_NOARGS},
1689 {"fileno", (PyCFunction)BufferedIOMixin_fileno, METH_NOARGS},
1690 {"isatty", (PyCFunction)BufferedIOMixin_isatty, METH_NOARGS},
1691
1692 {"write", (PyCFunction)BufferedWriter_write, METH_VARARGS},
1693 {"truncate", (PyCFunction)Buffered_truncate, METH_VARARGS},
1694 {"flush", (PyCFunction)Buffered_flush, METH_NOARGS},
1695 {"seek", (PyCFunction)Buffered_seek, METH_VARARGS},
1696 {"tell", (PyCFunction)Buffered_tell, METH_NOARGS},
1697 {NULL, NULL}
1698};
1699
1700static PyMemberDef BufferedWriter_members[] = {
1701 {"raw", T_OBJECT, offsetof(BufferedObject, raw), 0},
1702 {NULL}
1703};
1704
1705static PyGetSetDef BufferedWriter_getset[] = {
1706 {"closed", (getter)BufferedIOMixin_closed_get, NULL, NULL},
1707 {"name", (getter)BufferedIOMixin_name_get, NULL, NULL},
1708 {"mode", (getter)BufferedIOMixin_mode_get, NULL, NULL},
1709 {0}
1710};
1711
1712
1713PyTypeObject PyBufferedWriter_Type = {
1714 PyVarObject_HEAD_INIT(NULL, 0)
1715 "_io.BufferedWriter", /*tp_name*/
1716 sizeof(BufferedObject), /*tp_basicsize*/
1717 0, /*tp_itemsize*/
1718 (destructor)BufferedObject_dealloc, /*tp_dealloc*/
1719 0, /*tp_print*/
1720 0, /*tp_getattr*/
1721 0, /*tp_setattr*/
1722 0, /*tp_compare */
1723 0, /*tp_repr*/
1724 0, /*tp_as_number*/
1725 0, /*tp_as_sequence*/
1726 0, /*tp_as_mapping*/
1727 0, /*tp_hash */
1728 0, /*tp_call*/
1729 0, /*tp_str*/
1730 0, /*tp_getattro*/
1731 0, /*tp_setattro*/
1732 0, /*tp_as_buffer*/
1733 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1734 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1735 BufferedWriter_doc, /* tp_doc */
1736 (traverseproc)Buffered_traverse, /* tp_traverse */
1737 (inquiry)Buffered_clear, /* tp_clear */
1738 0, /* tp_richcompare */
1739 offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/
1740 0, /* tp_iter */
1741 0, /* tp_iternext */
1742 BufferedWriter_methods, /* tp_methods */
1743 BufferedWriter_members, /* tp_members */
1744 BufferedWriter_getset, /* tp_getset */
1745 0, /* tp_base */
1746 0, /* tp_dict */
1747 0, /* tp_descr_get */
1748 0, /* tp_descr_set */
1749 offsetof(BufferedObject, dict), /* tp_dictoffset */
1750 (initproc)BufferedWriter_init, /* tp_init */
1751 0, /* tp_alloc */
1752 PyType_GenericNew, /* tp_new */
1753};
1754
1755
1756
1757/*
1758 * BufferedRWPair
1759 */
1760
1761PyDoc_STRVAR(BufferedRWPair_doc,
1762 "A buffered reader and writer object together.\n"
1763 "\n"
1764 "A buffered reader object and buffered writer object put together to\n"
1765 "form a sequential IO object that can read and write. This is typically\n"
1766 "used with a socket or two-way pipe.\n"
1767 "\n"
1768 "reader and writer are RawIOBase objects that are readable and\n"
1769 "writeable respectively. If the buffer_size is omitted it defaults to\n"
1770 "DEFAULT_BUFFER_SIZE. The max_buffer_size (for the buffered writer)\n"
1771 "defaults to twice the buffer size.\n"
1772 );
1773
1774/* XXX The usefulness of this (compared to having two separate IO objects) is
1775 * questionable.
1776 */
1777
1778typedef struct {
1779 PyObject_HEAD
1780 BufferedObject *reader;
1781 BufferedObject *writer;
1782 PyObject *dict;
1783 PyObject *weakreflist;
1784} BufferedRWPairObject;
1785
1786static int
1787BufferedRWPair_init(BufferedRWPairObject *self, PyObject *args,
1788 PyObject *kwds)
1789{
1790 PyObject *reader, *writer;
1791 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1792 Py_ssize_t max_buffer_size = -1;
1793
1794 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1795 &buffer_size, &max_buffer_size)) {
1796 return -1;
1797 }
1798
1799 if (_PyIOBase_checkReadable(reader, Py_True) == NULL)
1800 return -1;
1801 if (_PyIOBase_checkWritable(writer, Py_True) == NULL)
1802 return -1;
1803
1804 args = Py_BuildValue("(n)", buffer_size);
1805 if (args == NULL) {
1806 Py_CLEAR(self->reader);
1807 return -1;
1808 }
1809 self->reader = (BufferedObject *)PyType_GenericNew(
1810 &PyBufferedReader_Type, args, NULL);
1811 Py_DECREF(args);
1812 if (self->reader == NULL)
1813 return -1;
1814
1815 args = Py_BuildValue("(nn)", buffer_size, max_buffer_size);
1816 if (args == NULL) {
1817 Py_CLEAR(self->reader);
1818 return -1;
1819 }
1820 self->writer = (BufferedObject *)PyType_GenericNew(
1821 &PyBufferedWriter_Type, args, NULL);
1822 Py_DECREF(args);
1823 if (self->writer == NULL) {
1824 Py_CLEAR(self->reader);
1825 return -1;
1826 }
1827 return 0;
1828}
1829
1830static int
1831BufferedRWPair_traverse(BufferedRWPairObject *self, visitproc visit, void *arg)
1832{
1833 Py_VISIT(self->dict);
1834 return 0;
1835}
1836
1837static int
1838BufferedRWPair_clear(BufferedRWPairObject *self)
1839{
1840 Py_CLEAR(self->reader);
1841 Py_CLEAR(self->writer);
1842 Py_CLEAR(self->dict);
1843 return 0;
1844}
1845
1846static void
1847BufferedRWPair_dealloc(BufferedRWPairObject *self)
1848{
1849 _PyObject_GC_UNTRACK(self);
1850 Py_CLEAR(self->reader);
1851 Py_CLEAR(self->writer);
1852 Py_CLEAR(self->dict);
1853 Py_TYPE(self)->tp_free((PyObject *) self);
1854}
1855
1856static PyObject *
1857_forward_call(BufferedObject *self, const char *name, PyObject *args)
1858{
1859 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
1860 PyObject *ret;
1861
1862 if (func == NULL) {
1863 PyErr_SetString(PyExc_AttributeError, name);
1864 return NULL;
1865 }
1866
1867 ret = PyObject_CallObject(func, args);
1868 Py_DECREF(func);
1869 return ret;
1870}
1871
1872static PyObject *
1873BufferedRWPair_read(BufferedRWPairObject *self, PyObject *args)
1874{
1875 return _forward_call(self->reader, "read", args);
1876}
1877
1878static PyObject *
1879BufferedRWPair_peek(BufferedRWPairObject *self, PyObject *args)
1880{
1881 return _forward_call(self->reader, "peek", args);
1882}
1883
1884static PyObject *
1885BufferedRWPair_read1(BufferedRWPairObject *self, PyObject *args)
1886{
1887 return _forward_call(self->reader, "read1", args);
1888}
1889
1890static PyObject *
1891BufferedRWPair_write(BufferedRWPairObject *self, PyObject *args)
1892{
1893 return _forward_call(self->writer, "write", args);
1894}
1895
1896static PyObject *
1897BufferedRWPair_flush(BufferedRWPairObject *self, PyObject *args)
1898{
1899 return _forward_call(self->writer, "flush", args);
1900}
1901
1902static PyObject *
1903BufferedRWPair_readable(BufferedRWPairObject *self, PyObject *args)
1904{
1905 return _forward_call(self->reader, "readable", args);
1906}
1907
1908static PyObject *
1909BufferedRWPair_writable(BufferedRWPairObject *self, PyObject *args)
1910{
1911 return _forward_call(self->writer, "writable", args);
1912}
1913
1914static PyObject *
1915BufferedRWPair_close(BufferedRWPairObject *self, PyObject *args)
1916{
1917 PyObject *ret = _forward_call(self->writer, "close", args);
1918 if (ret == NULL)
1919 return NULL;
1920 Py_DECREF(ret);
1921
1922 return _forward_call(self->reader, "close", args);
1923}
1924
1925static PyObject *
1926BufferedRWPair_isatty(BufferedRWPairObject *self, PyObject *args)
1927{
1928 PyObject *ret = _forward_call(self->writer, "isatty", args);
1929
1930 if (ret != Py_False) {
1931 /* either True or exception */
1932 return ret;
1933 }
1934 Py_DECREF(ret);
1935
1936 return _forward_call(self->reader, "isatty", args);
1937}
1938
1939
1940static PyMethodDef BufferedRWPair_methods[] = {
1941 {"read", (PyCFunction)BufferedRWPair_read, METH_VARARGS},
1942 {"peek", (PyCFunction)BufferedRWPair_peek, METH_VARARGS},
1943 {"read1", (PyCFunction)BufferedRWPair_read1, METH_VARARGS},
1944 {"readinto", (PyCFunction)Buffered_readinto, METH_VARARGS},
1945
1946 {"write", (PyCFunction)BufferedRWPair_write, METH_VARARGS},
1947 {"flush", (PyCFunction)BufferedRWPair_flush, METH_NOARGS},
1948
1949 {"readable", (PyCFunction)BufferedRWPair_readable, METH_NOARGS},
1950 {"writable", (PyCFunction)BufferedRWPair_writable, METH_NOARGS},
1951
1952 {"close", (PyCFunction)BufferedRWPair_close, METH_NOARGS},
1953 {"isatty", (PyCFunction)BufferedRWPair_isatty, METH_NOARGS},
1954
1955 {NULL, NULL}
1956};
1957
1958PyTypeObject PyBufferedRWPair_Type = {
1959 PyVarObject_HEAD_INIT(NULL, 0)
1960 "_io.BufferedRWPair", /*tp_name*/
1961 sizeof(BufferedRWPairObject), /*tp_basicsize*/
1962 0, /*tp_itemsize*/
1963 (destructor)BufferedRWPair_dealloc, /*tp_dealloc*/
1964 0, /*tp_print*/
1965 0, /*tp_getattr*/
1966 0, /*tp_setattr*/
1967 0, /*tp_compare */
1968 0, /*tp_repr*/
1969 0, /*tp_as_number*/
1970 0, /*tp_as_sequence*/
1971 0, /*tp_as_mapping*/
1972 0, /*tp_hash */
1973 0, /*tp_call*/
1974 0, /*tp_str*/
1975 0, /*tp_getattro*/
1976 0, /*tp_setattro*/
1977 0, /*tp_as_buffer*/
1978 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1979 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1980 BufferedRWPair_doc, /* tp_doc */
1981 (traverseproc)BufferedRWPair_traverse, /* tp_traverse */
1982 (inquiry)BufferedRWPair_clear, /* tp_clear */
1983 0, /* tp_richcompare */
1984 offsetof(BufferedRWPairObject, weakreflist), /*tp_weaklistoffset*/
1985 0, /* tp_iter */
1986 0, /* tp_iternext */
1987 BufferedRWPair_methods, /* tp_methods */
1988 0, /* tp_members */
1989 0, /* tp_getset */
1990 0, /* tp_base */
1991 0, /* tp_dict */
1992 0, /* tp_descr_get */
1993 0, /* tp_descr_set */
1994 offsetof(BufferedRWPairObject, dict), /* tp_dictoffset */
1995 (initproc)BufferedRWPair_init, /* tp_init */
1996 0, /* tp_alloc */
1997 PyType_GenericNew, /* tp_new */
1998};
1999
2000
2001
2002/*
2003 * BufferedRandom
2004 */
2005
2006PyDoc_STRVAR(BufferedRandom_doc,
2007 "A buffered interface to random access streams.\n"
2008 "\n"
2009 "The constructor creates a reader and writer for a seekable stream,\n"
2010 "raw, given in the first argument. If the buffer_size is omitted it\n"
2011 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2012 );
2013
2014static int
2015BufferedRandom_init(BufferedObject *self, PyObject *args, PyObject *kwds)
2016{
2017 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2018 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
2019 Py_ssize_t max_buffer_size = -1;
2020 PyObject *raw;
2021
2022 self->ok = 0;
2023
2024 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2025 &raw, &buffer_size, &max_buffer_size)) {
2026 return -1;
2027 }
2028
2029 if (_PyIOBase_checkSeekable(raw, Py_True) == NULL)
2030 return -1;
2031 if (_PyIOBase_checkReadable(raw, Py_True) == NULL)
2032 return -1;
2033 if (_PyIOBase_checkWritable(raw, Py_True) == NULL)
2034 return -1;
2035
2036 Py_CLEAR(self->raw);
2037 Py_INCREF(raw);
2038 self->raw = raw;
2039 self->buffer_size = buffer_size;
2040 self->readable = 1;
2041 self->writable = 1;
2042
2043 if (_Buffered_init(self) < 0)
2044 return -1;
2045 _BufferedReader_reset_buf(self);
2046 _BufferedWriter_reset_buf(self);
2047 self->pos = 0;
2048
2049 self->ok = 1;
2050 return 0;
2051}
2052
2053static PyMethodDef BufferedRandom_methods[] = {
2054 /* BufferedIOMixin methods */
2055 {"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS},
2056 {"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS},
2057 {"readable", (PyCFunction)BufferedIOMixin_readable, METH_NOARGS},
2058 {"writable", (PyCFunction)BufferedIOMixin_writable, METH_NOARGS},
2059 {"fileno", (PyCFunction)BufferedIOMixin_fileno, METH_NOARGS},
2060 {"isatty", (PyCFunction)BufferedIOMixin_isatty, METH_NOARGS},
2061
2062 {"flush", (PyCFunction)Buffered_flush, METH_NOARGS},
2063
2064 {"seek", (PyCFunction)Buffered_seek, METH_VARARGS},
2065 {"tell", (PyCFunction)Buffered_tell, METH_NOARGS},
2066 {"truncate", (PyCFunction)Buffered_truncate, METH_VARARGS},
2067 {"read", (PyCFunction)Buffered_read, METH_VARARGS},
2068 {"read1", (PyCFunction)Buffered_read1, METH_VARARGS},
2069 {"readinto", (PyCFunction)Buffered_readinto, METH_VARARGS},
2070 {"readline", (PyCFunction)Buffered_readline, METH_VARARGS},
2071 {"peek", (PyCFunction)Buffered_peek, METH_VARARGS},
2072 {"write", (PyCFunction)BufferedWriter_write, METH_VARARGS},
2073 {NULL, NULL}
2074};
2075
2076static PyMemberDef BufferedRandom_members[] = {
2077 {"raw", T_OBJECT, offsetof(BufferedObject, raw), 0},
2078 {NULL}
2079};
2080
2081static PyGetSetDef BufferedRandom_getset[] = {
2082 {"closed", (getter)BufferedIOMixin_closed_get, NULL, NULL},
2083 {"name", (getter)BufferedIOMixin_name_get, NULL, NULL},
2084 {"mode", (getter)BufferedIOMixin_mode_get, NULL, NULL},
2085 {0}
2086};
2087
2088
2089PyTypeObject PyBufferedRandom_Type = {
2090 PyVarObject_HEAD_INIT(NULL, 0)
2091 "_io.BufferedRandom", /*tp_name*/
2092 sizeof(BufferedObject), /*tp_basicsize*/
2093 0, /*tp_itemsize*/
2094 (destructor)BufferedObject_dealloc, /*tp_dealloc*/
2095 0, /*tp_print*/
2096 0, /*tp_getattr*/
2097 0, /*tp_setattr*/
2098 0, /*tp_compare */
2099 0, /*tp_repr*/
2100 0, /*tp_as_number*/
2101 0, /*tp_as_sequence*/
2102 0, /*tp_as_mapping*/
2103 0, /*tp_hash */
2104 0, /*tp_call*/
2105 0, /*tp_str*/
2106 0, /*tp_getattro*/
2107 0, /*tp_setattro*/
2108 0, /*tp_as_buffer*/
2109 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2110 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2111 BufferedRandom_doc, /* tp_doc */
2112 (traverseproc)Buffered_traverse, /* tp_traverse */
2113 (inquiry)Buffered_clear, /* tp_clear */
2114 0, /* tp_richcompare */
2115 offsetof(BufferedObject, weakreflist), /*tp_weaklistoffset*/
2116 0, /* tp_iter */
2117 (iternextfunc)Buffered_iternext, /* tp_iternext */
2118 BufferedRandom_methods, /* tp_methods */
2119 BufferedRandom_members, /* tp_members */
2120 BufferedRandom_getset, /* tp_getset */
2121 0, /* tp_base */
2122 0, /*tp_dict*/
2123 0, /* tp_descr_get */
2124 0, /* tp_descr_set */
2125 offsetof(BufferedObject, dict), /*tp_dictoffset*/
2126 (initproc)BufferedRandom_init, /* tp_init */
2127 0, /* tp_alloc */
2128 PyType_GenericNew, /* tp_new */
2129};
2130