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