blob: 554e113daa37084a73e31d31464a15d3f84d5ebf [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,
583 "Raw stream returned invalid position %zd", n);
584 return -1;
585 }
586 self->abs_pos = n;
587 return n;
588}
589
590static Py_off_t
591_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
592{
593 PyObject *res, *posobj, *whenceobj;
594 Py_off_t n;
595
596 posobj = PyLong_FromOff_t(target);
597 if (posobj == NULL)
598 return -1;
599 whenceobj = PyLong_FromLong(whence);
600 if (whenceobj == NULL) {
601 Py_DECREF(posobj);
602 return -1;
603 }
604 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
605 posobj, whenceobj, NULL);
606 Py_DECREF(posobj);
607 Py_DECREF(whenceobj);
608 if (res == NULL)
609 return -1;
610 n = PyNumber_AsOff_t(res, PyExc_ValueError);
611 Py_DECREF(res);
612 if (n < 0) {
613 if (!PyErr_Occurred())
614 PyErr_Format(PyExc_IOError,
615 "Raw stream returned invalid position %zd", n);
616 return -1;
617 }
618 self->abs_pos = n;
619 return n;
620}
621
622static int
623_buffered_init(buffered *self)
624{
625 Py_ssize_t n;
626 if (self->buffer_size <= 0) {
627 PyErr_SetString(PyExc_ValueError,
628 "buffer size must be strictly positive");
629 return -1;
630 }
631 if (self->buffer)
632 PyMem_Free(self->buffer);
633 self->buffer = PyMem_Malloc(self->buffer_size);
634 if (self->buffer == NULL) {
635 PyErr_NoMemory();
636 return -1;
637 }
638#ifdef WITH_THREAD
639 self->lock = PyThread_allocate_lock();
640 if (self->lock == NULL) {
641 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
642 return -1;
643 }
644#endif
645 /* Find out whether buffer_size is a power of 2 */
646 /* XXX is this optimization useful? */
647 for (n = self->buffer_size - 1; n & 1; n >>= 1)
648 ;
649 if (n == 0)
650 self->buffer_mask = self->buffer_size - 1;
651 else
652 self->buffer_mask = 0;
653 if (_buffered_raw_tell(self) == -1)
654 PyErr_Clear();
655 return 0;
656}
657
658/*
659 * Shared methods and wrappers
660 */
661
662static PyObject *
663buffered_flush(buffered *self, PyObject *args)
664{
665 PyObject *res;
666
667 CHECK_INITIALIZED(self)
668 CHECK_CLOSED(self, "flush of closed file")
669
670 ENTER_BUFFERED(self)
671 res = _bufferedwriter_flush_unlocked(self, 0);
672 if (res != NULL && self->readable) {
673 /* Rewind the raw stream so that its position corresponds to
674 the current logical position. */
675 Py_off_t n;
676 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
677 if (n == -1)
678 Py_CLEAR(res);
679 _bufferedreader_reset_buf(self);
680 }
681 LEAVE_BUFFERED(self)
682
683 return res;
684}
685
686static PyObject *
687buffered_peek(buffered *self, PyObject *args)
688{
689 Py_ssize_t n = 0;
690 PyObject *res = NULL;
691
692 CHECK_INITIALIZED(self)
693 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
694 return NULL;
695 }
696
697 ENTER_BUFFERED(self)
698
699 if (self->writable) {
700 res = _bufferedwriter_flush_unlocked(self, 1);
701 if (res == NULL)
702 goto end;
703 Py_CLEAR(res);
704 }
705 res = _bufferedreader_peek_unlocked(self, n);
706
707end:
708 LEAVE_BUFFERED(self)
709 return res;
710}
711
712static PyObject *
713buffered_read(buffered *self, PyObject *args)
714{
715 Py_ssize_t n = -1;
716 PyObject *res;
717
718 CHECK_INITIALIZED(self)
719 if (!PyArg_ParseTuple(args, "|n:read", &n)) {
720 return NULL;
721 }
722 if (n < -1) {
723 PyErr_SetString(PyExc_ValueError,
724 "read length must be positive or -1");
725 return NULL;
726 }
727
728 CHECK_CLOSED(self, "read of closed file")
729
730 if (n == -1) {
731 /* The number of bytes is unspecified, read until the end of stream */
732 ENTER_BUFFERED(self)
733 res = _bufferedreader_read_all(self);
734 LEAVE_BUFFERED(self)
735 }
736 else {
737 res = _bufferedreader_read_fast(self, n);
738 if (res == Py_None) {
739 Py_DECREF(res);
740 ENTER_BUFFERED(self)
741 res = _bufferedreader_read_generic(self, n);
742 LEAVE_BUFFERED(self)
743 }
744 }
745
746 return res;
747}
748
749static PyObject *
750buffered_read1(buffered *self, PyObject *args)
751{
752 Py_ssize_t n, have, r;
753 PyObject *res = NULL;
754
755 CHECK_INITIALIZED(self)
756 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
757 return NULL;
758 }
759
760 if (n < 0) {
761 PyErr_SetString(PyExc_ValueError,
762 "read length must be positive");
763 return NULL;
764 }
765 if (n == 0)
766 return PyBytes_FromStringAndSize(NULL, 0);
767
768 ENTER_BUFFERED(self)
769
770 if (self->writable) {
771 res = _bufferedwriter_flush_unlocked(self, 1);
772 if (res == NULL)
773 goto end;
774 Py_CLEAR(res);
775 }
776
777 /* Return up to n bytes. If at least one byte is buffered, we
778 only return buffered bytes. Otherwise, we do one raw read. */
779
780 /* XXX: this mimicks the io.py implementation but is probably wrong.
781 If we need to read from the raw stream, then we could actually read
782 all `n` bytes asked by the caller (and possibly more, so as to fill
783 our buffer for the next reads). */
784
785 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
786 if (have > 0) {
787 if (n > have)
788 n = have;
789 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
790 if (res == NULL)
791 goto end;
792 self->pos += n;
793 goto end;
794 }
795
796 /* Fill the buffer from the raw stream, and copy it to the result. */
797 _bufferedreader_reset_buf(self);
798 r = _bufferedreader_fill_buffer(self);
799 if (r == -1)
800 goto end;
801 if (r == -2)
802 r = 0;
803 if (n > r)
804 n = r;
805 res = PyBytes_FromStringAndSize(self->buffer, n);
806 if (res == NULL)
807 goto end;
808 self->pos = n;
809
810end:
811 LEAVE_BUFFERED(self)
812 return res;
813}
814
815static PyObject *
816buffered_readinto(buffered *self, PyObject *args)
817{
818 PyObject *res = NULL;
819
820 CHECK_INITIALIZED(self)
821
822 /* TODO: use raw.readinto() instead! */
823 if (self->writable) {
824 ENTER_BUFFERED(self)
825 res = _bufferedwriter_flush_unlocked(self, 0);
826 LEAVE_BUFFERED(self)
827 if (res == NULL)
828 goto end;
829 Py_DECREF(res);
830 }
831 res = bufferediobase_readinto((PyObject *)self, args);
832
833end:
834 return res;
835}
836
837static PyObject *
838_buffered_readline(buffered *self, Py_ssize_t limit)
839{
840 PyObject *res = NULL;
841 PyObject *chunks = NULL;
842 Py_ssize_t n, written = 0;
843 const char *start, *s, *end;
844
845 CHECK_CLOSED(self, "readline of closed file")
846
847 /* First, try to find a line in the buffer. This can run unlocked because
848 the calls to the C API are simple enough that they can't trigger
849 any thread switch. */
850 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
851 if (limit >= 0 && n > limit)
852 n = limit;
853 start = self->buffer + self->pos;
854 s = memchr(start, '\n', n);
855 if (s != NULL) {
856 res = PyBytes_FromStringAndSize(start, s - start + 1);
857 if (res != NULL)
858 self->pos += s - start + 1;
859 goto end_unlocked;
860 }
861 if (n == limit) {
862 res = PyBytes_FromStringAndSize(start, n);
863 if (res != NULL)
864 self->pos += n;
865 goto end_unlocked;
866 }
867
868 ENTER_BUFFERED(self)
869
870 /* Now we try to get some more from the raw stream */
871 if (self->writable) {
872 res = _bufferedwriter_flush_unlocked(self, 1);
873 if (res == NULL)
874 goto end;
875 Py_CLEAR(res);
876 }
877 chunks = PyList_New(0);
878 if (chunks == NULL)
879 goto end;
880 if (n > 0) {
881 res = PyBytes_FromStringAndSize(start, n);
882 if (res == NULL)
883 goto end;
884 if (PyList_Append(chunks, res) < 0) {
885 Py_CLEAR(res);
886 goto end;
887 }
888 Py_CLEAR(res);
889 written += n;
890 if (limit >= 0)
891 limit -= n;
892 }
893
894 for (;;) {
895 _bufferedreader_reset_buf(self);
896 n = _bufferedreader_fill_buffer(self);
897 if (n == -1)
898 goto end;
899 if (n <= 0)
900 break;
901 if (limit >= 0 && n > limit)
902 n = limit;
903 start = self->buffer;
904 end = start + n;
905 s = start;
906 while (s < end) {
907 if (*s++ == '\n') {
908 res = PyBytes_FromStringAndSize(start, s - start);
909 if (res == NULL)
910 goto end;
911 self->pos = s - start;
912 goto found;
913 }
914 }
915 res = PyBytes_FromStringAndSize(start, n);
916 if (res == NULL)
917 goto end;
918 if (n == limit) {
919 self->pos = n;
920 break;
921 }
922 if (PyList_Append(chunks, res) < 0) {
923 Py_CLEAR(res);
924 goto end;
925 }
926 Py_CLEAR(res);
927 written += n;
928 if (limit >= 0)
929 limit -= n;
930 }
931found:
932 if (res != NULL && PyList_Append(chunks, res) < 0) {
933 Py_CLEAR(res);
934 goto end;
935 }
936 Py_CLEAR(res);
937 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
938
939end:
940 LEAVE_BUFFERED(self)
941end_unlocked:
942 Py_XDECREF(chunks);
943 return res;
944}
945
946static PyObject *
947buffered_readline(buffered *self, PyObject *args)
948{
949 PyObject *limitobj = NULL;
950 Py_ssize_t limit = -1;
951
952 CHECK_INITIALIZED(self)
953
954 if (!PyArg_ParseTuple(args, "|O:readline", &limitobj)) {
955 return NULL;
956 }
957 if (limitobj) {
958 if (!PyNumber_Check(limitobj)) {
959 PyErr_Format(PyExc_TypeError,
960 "integer argument expected, got '%.200s'",
961 Py_TYPE(limitobj)->tp_name);
962 return NULL;
963 }
964 limit = PyNumber_AsSsize_t(limitobj, PyExc_OverflowError);
965 if (limit == -1 && PyErr_Occurred())
966 return NULL;
967 }
968 return _buffered_readline(self, limit);
969}
970
971
972static PyObject *
973buffered_tell(buffered *self, PyObject *args)
974{
975 Py_off_t pos;
976
977 CHECK_INITIALIZED(self)
978 pos = _buffered_raw_tell(self);
979 if (pos == -1)
980 return NULL;
981 pos -= RAW_OFFSET(self);
982 /* TODO: sanity check (pos >= 0) */
983 return PyLong_FromOff_t(pos);
984}
985
986static PyObject *
987buffered_seek(buffered *self, PyObject *args)
988{
989 Py_off_t target, n;
990 int whence = 0;
991 PyObject *targetobj, *res = NULL;
992
993 CHECK_INITIALIZED(self)
994 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
995 return NULL;
996 }
997 if (whence < 0 || whence > 2) {
998 PyErr_Format(PyExc_ValueError,
999 "whence must be between 0 and 2, not %d", whence);
1000 return NULL;
1001 }
1002
1003 CHECK_CLOSED(self, "seek of closed file")
1004
1005 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1006 if (target == -1 && PyErr_Occurred())
1007 return NULL;
1008
1009 if (whence != 2 && self->readable) {
1010 Py_off_t current, avail;
1011 /* Check if seeking leaves us inside the current buffer,
1012 so as to return quickly if possible. Also, we needn't take the
1013 lock in this fast path.
1014 Don't know how to do that when whence == 2, though. */
1015 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1016 state at this point. */
1017 current = RAW_TELL(self);
1018 avail = READAHEAD(self);
1019 if (avail > 0) {
1020 Py_off_t offset;
1021 if (whence == 0)
1022 offset = target - (current - RAW_OFFSET(self));
1023 else
1024 offset = target;
1025 if (offset >= -self->pos && offset <= avail) {
1026 self->pos += offset;
1027 return PyLong_FromOff_t(current - avail + offset);
1028 }
1029 }
1030 }
1031
1032 ENTER_BUFFERED(self)
1033
1034 /* Fallback: invoke raw seek() method and clear buffer */
1035 if (self->writable) {
1036 res = _bufferedwriter_flush_unlocked(self, 0);
1037 if (res == NULL)
1038 goto end;
1039 Py_CLEAR(res);
1040 _bufferedwriter_reset_buf(self);
1041 }
1042
1043 /* TODO: align on block boundary and read buffer if needed? */
1044 if (whence == 1)
1045 target -= RAW_OFFSET(self);
1046 n = _buffered_raw_seek(self, target, whence);
1047 if (n == -1)
1048 goto end;
1049 self->raw_pos = -1;
1050 res = PyLong_FromOff_t(n);
1051 if (res != NULL && self->readable)
1052 _bufferedreader_reset_buf(self);
1053
1054end:
1055 LEAVE_BUFFERED(self)
1056 return res;
1057}
1058
1059static PyObject *
1060buffered_truncate(buffered *self, PyObject *args)
1061{
1062 PyObject *pos = Py_None;
1063 PyObject *res = NULL;
1064
1065 CHECK_INITIALIZED(self)
1066 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1067 return NULL;
1068 }
1069
1070 ENTER_BUFFERED(self)
1071
1072 if (self->writable) {
1073 res = _bufferedwriter_flush_unlocked(self, 0);
1074 if (res == NULL)
1075 goto end;
1076 Py_CLEAR(res);
1077 }
1078 if (self->readable) {
1079 if (pos == Py_None) {
1080 /* Rewind the raw stream so that its position corresponds to
1081 the current logical position. */
1082 if (_buffered_raw_seek(self, -RAW_OFFSET(self), 1) == -1)
1083 goto end;
1084 }
1085 _bufferedreader_reset_buf(self);
1086 }
1087 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1088 if (res == NULL)
1089 goto end;
1090 /* Reset cached position */
1091 if (_buffered_raw_tell(self) == -1)
1092 PyErr_Clear();
1093
1094end:
1095 LEAVE_BUFFERED(self)
1096 return res;
1097}
1098
1099static PyObject *
1100buffered_iternext(buffered *self)
1101{
1102 PyObject *line;
1103 PyTypeObject *tp;
1104
1105 CHECK_INITIALIZED(self);
1106
1107 tp = Py_TYPE(self);
1108 if (tp == &PyBufferedReader_Type ||
1109 tp == &PyBufferedRandom_Type) {
1110 /* Skip method call overhead for speed */
1111 line = _buffered_readline(self, -1);
1112 }
1113 else {
1114 line = PyObject_CallMethodObjArgs((PyObject *)self,
1115 _PyIO_str_readline, NULL);
1116 if (line && !PyBytes_Check(line)) {
1117 PyErr_Format(PyExc_IOError,
1118 "readline() should have returned a bytes object, "
1119 "not '%.200s'", Py_TYPE(line)->tp_name);
1120 Py_DECREF(line);
1121 return NULL;
1122 }
1123 }
1124
1125 if (line == NULL)
1126 return NULL;
1127
1128 if (PyBytes_GET_SIZE(line) == 0) {
1129 /* Reached EOF or would have blocked */
1130 Py_DECREF(line);
1131 return NULL;
1132 }
1133
1134 return line;
1135}
1136
1137static PyObject *
1138buffered_repr(buffered *self)
1139{
1140 PyObject *nameobj, *res;
1141
1142 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1143 if (nameobj == NULL) {
1144 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1145 PyErr_Clear();
1146 else
1147 return NULL;
1148 res = PyString_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1149 }
1150 else {
1151 PyObject *repr = PyObject_Repr(nameobj);
1152 Py_DECREF(nameobj);
1153 if (repr == NULL)
1154 return NULL;
1155 res = PyString_FromFormat("<%s name=%s>",
1156 Py_TYPE(self)->tp_name,
1157 PyString_AS_STRING(repr));
1158 Py_DECREF(repr);
1159 }
1160 return res;
1161}
1162
1163/*
1164 * class BufferedReader
1165 */
1166
1167PyDoc_STRVAR(bufferedreader_doc,
1168 "Create a new buffered reader using the given readable raw IO object.");
1169
1170static void _bufferedreader_reset_buf(buffered *self)
1171{
1172 self->read_end = -1;
1173}
1174
1175static int
1176bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
1177{
1178 char *kwlist[] = {"raw", "buffer_size", NULL};
1179 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1180 PyObject *raw;
1181
1182 self->ok = 0;
1183 self->detached = 0;
1184
1185 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1186 &raw, &buffer_size)) {
1187 return -1;
1188 }
1189
1190 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
1191 return -1;
1192
1193 Py_CLEAR(self->raw);
1194 Py_INCREF(raw);
1195 self->raw = raw;
1196 self->buffer_size = buffer_size;
1197 self->readable = 1;
1198 self->writable = 0;
1199
1200 if (_buffered_init(self) < 0)
1201 return -1;
1202 _bufferedreader_reset_buf(self);
1203
1204 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1205 Py_TYPE(raw) == &PyFileIO_Type);
1206
1207 self->ok = 1;
1208 return 0;
1209}
1210
1211static Py_ssize_t
1212_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
1213{
1214 Py_buffer buf;
1215 PyObject *memobj, *res;
1216 Py_ssize_t n;
1217 /* NOTE: the buffer needn't be released as its object is NULL. */
1218 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1219 return -1;
1220 memobj = PyMemoryView_FromBuffer(&buf);
1221 if (memobj == NULL)
1222 return -1;
1223 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1224 Py_DECREF(memobj);
1225 if (res == NULL)
1226 return -1;
1227 if (res == Py_None) {
1228 /* Non-blocking stream would have blocked. Special return code! */
1229 Py_DECREF(res);
1230 return -2;
1231 }
1232 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1233 Py_DECREF(res);
1234 if (n < 0 || n > len) {
1235 PyErr_Format(PyExc_IOError,
1236 "raw readinto() returned invalid length %zd "
1237 "(should have been between 0 and %zd)", n, len);
1238 return -1;
1239 }
1240 if (n > 0 && self->abs_pos != -1)
1241 self->abs_pos += n;
1242 return n;
1243}
1244
1245static Py_ssize_t
1246_bufferedreader_fill_buffer(buffered *self)
1247{
1248 Py_ssize_t start, len, n;
1249 if (VALID_READ_BUFFER(self))
1250 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1251 else
1252 start = 0;
1253 len = self->buffer_size - start;
1254 n = _bufferedreader_raw_read(self, self->buffer + start, len);
1255 if (n <= 0)
1256 return n;
1257 self->read_end = start + n;
1258 self->raw_pos = start + n;
1259 return n;
1260}
1261
1262static PyObject *
1263_bufferedreader_read_all(buffered *self)
1264{
1265 Py_ssize_t current_size;
1266 PyObject *res, *data = NULL;
1267 PyObject *chunks = PyList_New(0);
1268
1269 if (chunks == NULL)
1270 return NULL;
1271
1272 /* First copy what we have in the current buffer. */
1273 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1274 if (current_size) {
1275 data = PyBytes_FromStringAndSize(
1276 self->buffer + self->pos, current_size);
1277 if (data == NULL) {
1278 Py_DECREF(chunks);
1279 return NULL;
1280 }
1281 }
1282 _bufferedreader_reset_buf(self);
1283 /* We're going past the buffer's bounds, flush it */
1284 if (self->writable) {
1285 res = _bufferedwriter_flush_unlocked(self, 1);
1286 if (res == NULL) {
1287 Py_DECREF(chunks);
1288 return NULL;
1289 }
1290 Py_CLEAR(res);
1291 }
1292 while (1) {
1293 if (data) {
1294 if (PyList_Append(chunks, data) < 0) {
1295 Py_DECREF(data);
1296 Py_DECREF(chunks);
1297 return NULL;
1298 }
1299 Py_DECREF(data);
1300 }
1301
1302 /* Read until EOF or until read() would block. */
1303 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1304 if (data == NULL) {
1305 Py_DECREF(chunks);
1306 return NULL;
1307 }
1308 if (data != Py_None && !PyBytes_Check(data)) {
1309 Py_DECREF(data);
1310 Py_DECREF(chunks);
1311 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1312 return NULL;
1313 }
1314 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1315 if (current_size == 0) {
1316 Py_DECREF(chunks);
1317 return data;
1318 }
1319 else {
1320 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1321 Py_DECREF(data);
1322 Py_DECREF(chunks);
1323 return res;
1324 }
1325 }
1326 current_size += PyBytes_GET_SIZE(data);
1327 if (self->abs_pos != -1)
1328 self->abs_pos += PyBytes_GET_SIZE(data);
1329 }
1330}
1331
1332/* Read n bytes from the buffer if it can, otherwise return None.
1333 This function is simple enough that it can run unlocked. */
1334static PyObject *
1335_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
1336{
1337 Py_ssize_t current_size;
1338
1339 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1340 if (n <= current_size) {
1341 /* Fast path: the data to read is fully buffered. */
1342 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1343 if (res != NULL)
1344 self->pos += n;
1345 return res;
1346 }
1347 Py_RETURN_NONE;
1348}
1349
1350/* Generic read function: read from the stream until enough bytes are read,
1351 * or until an EOF occurs or until read() would block.
1352 */
1353static PyObject *
1354_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
1355{
1356 PyObject *res = NULL;
1357 Py_ssize_t current_size, remaining, written;
1358 char *out;
1359
1360 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1361 if (n <= current_size)
1362 return _bufferedreader_read_fast(self, n);
1363
1364 res = PyBytes_FromStringAndSize(NULL, n);
1365 if (res == NULL)
1366 goto error;
1367 out = PyBytes_AS_STRING(res);
1368 remaining = n;
1369 written = 0;
1370 if (current_size > 0) {
1371 memcpy(out, self->buffer + self->pos, current_size);
1372 remaining -= current_size;
1373 written += current_size;
1374 }
1375 _bufferedreader_reset_buf(self);
1376 while (remaining > 0) {
1377 /* We want to read a whole block at the end into buffer.
1378 If we had readv() we could do this in one pass. */
1379 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1380 if (r == 0)
1381 break;
1382 r = _bufferedreader_raw_read(self, out + written, r);
1383 if (r == -1)
1384 goto error;
1385 if (r == 0 || r == -2) {
1386 /* EOF occurred or read() would block. */
1387 if (r == 0 || written > 0) {
1388 if (_PyBytes_Resize(&res, written))
1389 goto error;
1390 return res;
1391 }
1392 Py_DECREF(res);
1393 Py_INCREF(Py_None);
1394 return Py_None;
1395 }
1396 remaining -= r;
1397 written += r;
1398 }
1399 assert(remaining <= self->buffer_size);
1400 self->pos = 0;
1401 self->raw_pos = 0;
1402 self->read_end = 0;
1403 while (self->read_end < self->buffer_size) {
1404 Py_ssize_t r = _bufferedreader_fill_buffer(self);
1405 if (r == -1)
1406 goto error;
1407 if (r == 0 || r == -2) {
1408 /* EOF occurred or read() would block. */
1409 if (r == 0 || written > 0) {
1410 if (_PyBytes_Resize(&res, written))
1411 goto error;
1412 return res;
1413 }
1414 Py_DECREF(res);
1415 Py_INCREF(Py_None);
1416 return Py_None;
1417 }
1418 if (remaining > r) {
1419 memcpy(out + written, self->buffer + self->pos, r);
1420 written += r;
1421 self->pos += r;
1422 remaining -= r;
1423 }
1424 else if (remaining > 0) {
1425 memcpy(out + written, self->buffer + self->pos, remaining);
1426 written += remaining;
1427 self->pos += remaining;
1428 remaining = 0;
1429 }
1430 if (remaining == 0)
1431 break;
1432 }
1433
1434 return res;
1435
1436error:
1437 Py_XDECREF(res);
1438 return NULL;
1439}
1440
1441static PyObject *
1442_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
1443{
1444 Py_ssize_t have, r;
1445
1446 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1447 /* Constraints:
1448 1. we don't want to advance the file position.
1449 2. we don't want to lose block alignment, so we can't shift the buffer
1450 to make some place.
1451 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1452 */
1453 if (have > 0) {
1454 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1455 }
1456
1457 /* Fill the buffer from the raw stream, and copy it to the result. */
1458 _bufferedreader_reset_buf(self);
1459 r = _bufferedreader_fill_buffer(self);
1460 if (r == -1)
1461 return NULL;
1462 if (r == -2)
1463 r = 0;
1464 self->pos = 0;
1465 return PyBytes_FromStringAndSize(self->buffer, r);
1466}
1467
1468static PyMethodDef bufferedreader_methods[] = {
1469 /* BufferedIOMixin methods */
1470 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1471 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1472 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1473 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1474 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1475 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1476 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1477 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
1478
1479 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1480 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1481 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
1482 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1483 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1484 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1485 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1486 {NULL, NULL}
1487};
1488
1489static PyMemberDef bufferedreader_members[] = {
1490 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
1491 {NULL}
1492};
1493
1494static PyGetSetDef bufferedreader_getset[] = {
1495 {"closed", (getter)buffered_closed_get, NULL, NULL},
1496 {"name", (getter)buffered_name_get, NULL, NULL},
1497 {"mode", (getter)buffered_mode_get, NULL, NULL},
1498 {NULL}
1499};
1500
1501
1502PyTypeObject PyBufferedReader_Type = {
1503 PyVarObject_HEAD_INIT(NULL, 0)
1504 "_io.BufferedReader", /*tp_name*/
1505 sizeof(buffered), /*tp_basicsize*/
1506 0, /*tp_itemsize*/
1507 (destructor)buffered_dealloc, /*tp_dealloc*/
1508 0, /*tp_print*/
1509 0, /*tp_getattr*/
1510 0, /*tp_setattr*/
1511 0, /*tp_compare */
1512 (reprfunc)buffered_repr, /*tp_repr*/
1513 0, /*tp_as_number*/
1514 0, /*tp_as_sequence*/
1515 0, /*tp_as_mapping*/
1516 0, /*tp_hash */
1517 0, /*tp_call*/
1518 0, /*tp_str*/
1519 0, /*tp_getattro*/
1520 0, /*tp_setattro*/
1521 0, /*tp_as_buffer*/
1522 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1523 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1524 bufferedreader_doc, /* tp_doc */
1525 (traverseproc)buffered_traverse, /* tp_traverse */
1526 (inquiry)buffered_clear, /* tp_clear */
1527 0, /* tp_richcompare */
1528 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
1529 0, /* tp_iter */
1530 (iternextfunc)buffered_iternext, /* tp_iternext */
1531 bufferedreader_methods, /* tp_methods */
1532 bufferedreader_members, /* tp_members */
1533 bufferedreader_getset, /* tp_getset */
1534 0, /* tp_base */
1535 0, /* tp_dict */
1536 0, /* tp_descr_get */
1537 0, /* tp_descr_set */
1538 offsetof(buffered, dict), /* tp_dictoffset */
1539 (initproc)bufferedreader_init, /* tp_init */
1540 0, /* tp_alloc */
1541 PyType_GenericNew, /* tp_new */
1542};
1543
1544
1545
1546static int
1547complain_about_max_buffer_size(void)
1548{
1549 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1550 "max_buffer_size is deprecated", 1) < 0)
1551 return 0;
1552 return 1;
1553}
1554
1555/*
1556 * class BufferedWriter
1557 */
1558PyDoc_STRVAR(bufferedwriter_doc,
1559 "A buffer for a writeable sequential RawIO object.\n"
1560 "\n"
1561 "The constructor creates a BufferedWriter for the given writeable raw\n"
1562 "stream. If the buffer_size is not given, it defaults to\n"
1563 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1564 );
1565
1566static void
1567_bufferedwriter_reset_buf(buffered *self)
1568{
1569 self->write_pos = 0;
1570 self->write_end = -1;
1571}
1572
1573static int
1574bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
1575{
1576 /* TODO: properly deprecate max_buffer_size */
1577 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1578 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1579 Py_ssize_t max_buffer_size = -234;
1580 PyObject *raw;
1581
1582 self->ok = 0;
1583 self->detached = 0;
1584
1585 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
1586 &raw, &buffer_size, &max_buffer_size)) {
1587 return -1;
1588 }
1589
1590 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1591 return -1;
1592
1593 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
1594 return -1;
1595
1596 Py_CLEAR(self->raw);
1597 Py_INCREF(raw);
1598 self->raw = raw;
1599 self->readable = 0;
1600 self->writable = 1;
1601
1602 self->buffer_size = buffer_size;
1603 if (_buffered_init(self) < 0)
1604 return -1;
1605 _bufferedwriter_reset_buf(self);
1606 self->pos = 0;
1607
1608 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1609 Py_TYPE(raw) == &PyFileIO_Type);
1610
1611 self->ok = 1;
1612 return 0;
1613}
1614
1615static Py_ssize_t
1616_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
1617{
1618 Py_buffer buf;
1619 PyObject *memobj, *res;
1620 Py_ssize_t n;
1621 /* NOTE: the buffer needn't be released as its object is NULL. */
1622 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1623 return -1;
1624 memobj = PyMemoryView_FromBuffer(&buf);
1625 if (memobj == NULL)
1626 return -1;
1627 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1628 Py_DECREF(memobj);
1629 if (res == NULL)
1630 return -1;
1631 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1632 Py_DECREF(res);
1633 if (n < 0 || n > len) {
1634 PyErr_Format(PyExc_IOError,
1635 "raw write() returned invalid length %zd "
1636 "(should have been between 0 and %zd)", n, len);
1637 return -1;
1638 }
1639 if (n > 0 && self->abs_pos != -1)
1640 self->abs_pos += n;
1641 return n;
1642}
1643
1644/* `restore_pos` is 1 if we need to restore the raw stream position at
1645 the end, 0 otherwise. */
1646static PyObject *
1647_bufferedwriter_flush_unlocked(buffered *self, int restore_pos)
1648{
1649 Py_ssize_t written = 0;
1650 Py_off_t n, rewind;
1651
1652 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1653 goto end;
1654 /* First, rewind */
1655 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1656 if (rewind != 0) {
1657 n = _buffered_raw_seek(self, -rewind, 1);
1658 if (n < 0) {
1659 goto error;
1660 }
1661 self->raw_pos -= rewind;
1662 }
1663 while (self->write_pos < self->write_end) {
1664 n = _bufferedwriter_raw_write(self,
1665 self->buffer + self->write_pos,
1666 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1667 Py_off_t, Py_ssize_t));
1668 if (n == -1) {
1669 Py_ssize_t *w = _buffered_check_blocking_error();
1670 if (w == NULL)
1671 goto error;
1672 self->write_pos += *w;
1673 self->raw_pos = self->write_pos;
1674 written += *w;
1675 *w = written;
1676 /* Already re-raised */
1677 goto error;
1678 }
1679 self->write_pos += n;
1680 self->raw_pos = self->write_pos;
1681 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1682 }
1683
1684 if (restore_pos) {
1685 Py_off_t forward = rewind - written;
1686 if (forward != 0) {
1687 n = _buffered_raw_seek(self, forward, 1);
1688 if (n < 0) {
1689 goto error;
1690 }
1691 self->raw_pos += forward;
1692 }
1693 }
1694 _bufferedwriter_reset_buf(self);
1695
1696end:
1697 Py_RETURN_NONE;
1698
1699error:
1700 return NULL;
1701}
1702
1703static PyObject *
1704bufferedwriter_write(buffered *self, PyObject *args)
1705{
1706 PyObject *res = NULL;
1707 Py_buffer buf;
1708 Py_ssize_t written, avail, remaining, n;
1709
1710 CHECK_INITIALIZED(self)
1711 if (!PyArg_ParseTuple(args, "s*:write", &buf)) {
1712 return NULL;
1713 }
1714
1715 if (IS_CLOSED(self)) {
1716 PyErr_SetString(PyExc_ValueError, "write to closed file");
1717 PyBuffer_Release(&buf);
1718 return NULL;
1719 }
1720
1721 ENTER_BUFFERED(self)
1722
1723 /* Fast path: the data to write can be fully buffered. */
1724 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1725 self->pos = 0;
1726 self->raw_pos = 0;
1727 }
1728 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1729 if (buf.len <= avail) {
1730 memcpy(self->buffer + self->pos, buf.buf, buf.len);
1731 if (!VALID_WRITE_BUFFER(self)) {
1732 self->write_pos = self->pos;
1733 }
1734 ADJUST_POSITION(self, self->pos + buf.len);
1735 if (self->pos > self->write_end)
1736 self->write_end = self->pos;
1737 written = buf.len;
1738 goto end;
1739 }
1740
1741 /* First write the current buffer */
1742 res = _bufferedwriter_flush_unlocked(self, 0);
1743 if (res == NULL) {
1744 Py_ssize_t *w = _buffered_check_blocking_error();
1745 if (w == NULL)
1746 goto error;
1747 if (self->readable)
1748 _bufferedreader_reset_buf(self);
1749 /* Make some place by shifting the buffer. */
1750 assert(VALID_WRITE_BUFFER(self));
1751 memmove(self->buffer, self->buffer + self->write_pos,
1752 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1753 Py_off_t, Py_ssize_t));
1754 self->write_end -= self->write_pos;
1755 self->raw_pos -= self->write_pos;
1756 self->pos -= self->write_pos;
1757 self->write_pos = 0;
1758 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1759 Py_off_t, Py_ssize_t);
1760 if (buf.len <= avail) {
1761 /* Everything can be buffered */
1762 PyErr_Clear();
1763 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1764 self->write_end += buf.len;
1765 written = buf.len;
1766 goto end;
1767 }
1768 /* Buffer as much as possible. */
1769 memcpy(self->buffer + self->write_end, buf.buf, avail);
1770 self->write_end += avail;
1771 /* Already re-raised */
1772 *w = avail;
1773 goto error;
1774 }
1775 Py_CLEAR(res);
1776
1777 /* Then write buf itself. At this point the buffer has been emptied. */
1778 remaining = buf.len;
1779 written = 0;
1780 while (remaining > self->buffer_size) {
1781 n = _bufferedwriter_raw_write(
1782 self, (char *) buf.buf + written, buf.len - written);
1783 if (n == -1) {
1784 Py_ssize_t *w = _buffered_check_blocking_error();
1785 if (w == NULL)
1786 goto error;
1787 written += *w;
1788 remaining -= *w;
1789 if (remaining > self->buffer_size) {
1790 /* Can't buffer everything, still buffer as much as possible */
1791 memcpy(self->buffer,
1792 (char *) buf.buf + written, self->buffer_size);
1793 self->raw_pos = 0;
1794 ADJUST_POSITION(self, self->buffer_size);
1795 self->write_end = self->buffer_size;
1796 *w = written + self->buffer_size;
1797 /* Already re-raised */
1798 goto error;
1799 }
1800 PyErr_Clear();
1801 break;
1802 }
1803 written += n;
1804 remaining -= n;
1805 }
1806 if (self->readable)
1807 _bufferedreader_reset_buf(self);
1808 if (remaining > 0) {
1809 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1810 written += remaining;
1811 }
1812 self->write_pos = 0;
1813 /* TODO: sanity check (remaining >= 0) */
1814 self->write_end = remaining;
1815 ADJUST_POSITION(self, remaining);
1816 self->raw_pos = 0;
1817
1818end:
1819 res = PyLong_FromSsize_t(written);
1820
1821error:
1822 LEAVE_BUFFERED(self)
1823 PyBuffer_Release(&buf);
1824 return res;
1825}
1826
1827static PyMethodDef bufferedwriter_methods[] = {
1828 /* BufferedIOMixin methods */
1829 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1830 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1831 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1832 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1833 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1834 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1835 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
1836
1837 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1838 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1839 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1840 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1841 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1842 {NULL, NULL}
1843};
1844
1845static PyMemberDef bufferedwriter_members[] = {
1846 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
1847 {NULL}
1848};
1849
1850static PyGetSetDef bufferedwriter_getset[] = {
1851 {"closed", (getter)buffered_closed_get, NULL, NULL},
1852 {"name", (getter)buffered_name_get, NULL, NULL},
1853 {"mode", (getter)buffered_mode_get, NULL, NULL},
1854 {NULL}
1855};
1856
1857
1858PyTypeObject PyBufferedWriter_Type = {
1859 PyVarObject_HEAD_INIT(NULL, 0)
1860 "_io.BufferedWriter", /*tp_name*/
1861 sizeof(buffered), /*tp_basicsize*/
1862 0, /*tp_itemsize*/
1863 (destructor)buffered_dealloc, /*tp_dealloc*/
1864 0, /*tp_print*/
1865 0, /*tp_getattr*/
1866 0, /*tp_setattr*/
1867 0, /*tp_compare */
1868 (reprfunc)buffered_repr, /*tp_repr*/
1869 0, /*tp_as_number*/
1870 0, /*tp_as_sequence*/
1871 0, /*tp_as_mapping*/
1872 0, /*tp_hash */
1873 0, /*tp_call*/
1874 0, /*tp_str*/
1875 0, /*tp_getattro*/
1876 0, /*tp_setattro*/
1877 0, /*tp_as_buffer*/
1878 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1879 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1880 bufferedwriter_doc, /* tp_doc */
1881 (traverseproc)buffered_traverse, /* tp_traverse */
1882 (inquiry)buffered_clear, /* tp_clear */
1883 0, /* tp_richcompare */
1884 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
1885 0, /* tp_iter */
1886 0, /* tp_iternext */
1887 bufferedwriter_methods, /* tp_methods */
1888 bufferedwriter_members, /* tp_members */
1889 bufferedwriter_getset, /* tp_getset */
1890 0, /* tp_base */
1891 0, /* tp_dict */
1892 0, /* tp_descr_get */
1893 0, /* tp_descr_set */
1894 offsetof(buffered, dict), /* tp_dictoffset */
1895 (initproc)bufferedwriter_init, /* tp_init */
1896 0, /* tp_alloc */
1897 PyType_GenericNew, /* tp_new */
1898};
1899
1900
1901
1902/*
1903 * BufferedRWPair
1904 */
1905
1906PyDoc_STRVAR(bufferedrwpair_doc,
1907 "A buffered reader and writer object together.\n"
1908 "\n"
1909 "A buffered reader object and buffered writer object put together to\n"
1910 "form a sequential IO object that can read and write. This is typically\n"
1911 "used with a socket or two-way pipe.\n"
1912 "\n"
1913 "reader and writer are RawIOBase objects that are readable and\n"
1914 "writeable respectively. If the buffer_size is omitted it defaults to\n"
1915 "DEFAULT_BUFFER_SIZE.\n"
1916 );
1917
1918/* XXX The usefulness of this (compared to having two separate IO objects) is
1919 * questionable.
1920 */
1921
1922typedef struct {
1923 PyObject_HEAD
1924 buffered *reader;
1925 buffered *writer;
1926 PyObject *dict;
1927 PyObject *weakreflist;
1928} rwpair;
1929
1930static int
1931bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
1932{
1933 PyObject *reader, *writer;
1934 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1935 Py_ssize_t max_buffer_size = -234;
1936
1937 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
1938 &buffer_size, &max_buffer_size)) {
1939 return -1;
1940 }
1941
1942 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1943 return -1;
1944
1945 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
1946 return -1;
1947 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
1948 return -1;
1949
1950 self->reader = (buffered *) PyObject_CallFunction(
1951 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
1952 if (self->reader == NULL)
1953 return -1;
1954
1955 self->writer = (buffered *) PyObject_CallFunction(
1956 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
1957 if (self->writer == NULL) {
1958 Py_CLEAR(self->reader);
1959 return -1;
1960 }
1961
1962 return 0;
1963}
1964
1965static int
1966bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
1967{
1968 Py_VISIT(self->dict);
1969 return 0;
1970}
1971
1972static int
1973bufferedrwpair_clear(rwpair *self)
1974{
1975 Py_CLEAR(self->reader);
1976 Py_CLEAR(self->writer);
1977 Py_CLEAR(self->dict);
1978 return 0;
1979}
1980
1981static void
1982bufferedrwpair_dealloc(rwpair *self)
1983{
1984 _PyObject_GC_UNTRACK(self);
1985 Py_CLEAR(self->reader);
1986 Py_CLEAR(self->writer);
1987 Py_CLEAR(self->dict);
1988 Py_TYPE(self)->tp_free((PyObject *) self);
1989}
1990
1991static PyObject *
1992_forward_call(buffered *self, const char *name, PyObject *args)
1993{
1994 PyObject *func = PyObject_GetAttrString((PyObject *)self, name);
1995 PyObject *ret;
1996
1997 if (func == NULL) {
1998 PyErr_SetString(PyExc_AttributeError, name);
1999 return NULL;
2000 }
2001
2002 ret = PyObject_CallObject(func, args);
2003 Py_DECREF(func);
2004 return ret;
2005}
2006
2007static PyObject *
2008bufferedrwpair_read(rwpair *self, PyObject *args)
2009{
2010 return _forward_call(self->reader, "read", args);
2011}
2012
2013static PyObject *
2014bufferedrwpair_peek(rwpair *self, PyObject *args)
2015{
2016 return _forward_call(self->reader, "peek", args);
2017}
2018
2019static PyObject *
2020bufferedrwpair_read1(rwpair *self, PyObject *args)
2021{
2022 return _forward_call(self->reader, "read1", args);
2023}
2024
2025static PyObject *
2026bufferedrwpair_readinto(rwpair *self, PyObject *args)
2027{
2028 return _forward_call(self->reader, "readinto", args);
2029}
2030
2031static PyObject *
2032bufferedrwpair_write(rwpair *self, PyObject *args)
2033{
2034 return _forward_call(self->writer, "write", args);
2035}
2036
2037static PyObject *
2038bufferedrwpair_flush(rwpair *self, PyObject *args)
2039{
2040 return _forward_call(self->writer, "flush", args);
2041}
2042
2043static PyObject *
2044bufferedrwpair_readable(rwpair *self, PyObject *args)
2045{
2046 return _forward_call(self->reader, "readable", args);
2047}
2048
2049static PyObject *
2050bufferedrwpair_writable(rwpair *self, PyObject *args)
2051{
2052 return _forward_call(self->writer, "writable", args);
2053}
2054
2055static PyObject *
2056bufferedrwpair_close(rwpair *self, PyObject *args)
2057{
2058 PyObject *ret = _forward_call(self->writer, "close", args);
2059 if (ret == NULL)
2060 return NULL;
2061 Py_DECREF(ret);
2062
2063 return _forward_call(self->reader, "close", args);
2064}
2065
2066static PyObject *
2067bufferedrwpair_isatty(rwpair *self, PyObject *args)
2068{
2069 PyObject *ret = _forward_call(self->writer, "isatty", args);
2070
2071 if (ret != Py_False) {
2072 /* either True or exception */
2073 return ret;
2074 }
2075 Py_DECREF(ret);
2076
2077 return _forward_call(self->reader, "isatty", args);
2078}
2079
2080static PyObject *
2081bufferedrwpair_closed_get(rwpair *self, void *context)
2082{
2083 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2084}
2085
2086static PyMethodDef bufferedrwpair_methods[] = {
2087 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2088 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2089 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2090 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
2091
2092 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2093 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
2094
2095 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2096 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
2097
2098 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2099 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
2100
2101 {NULL, NULL}
2102};
2103
2104static PyGetSetDef bufferedrwpair_getset[] = {
2105 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
2106 {NULL}
2107};
2108
2109PyTypeObject PyBufferedRWPair_Type = {
2110 PyVarObject_HEAD_INIT(NULL, 0)
2111 "_io.BufferedRWPair", /*tp_name*/
2112 sizeof(rwpair), /*tp_basicsize*/
2113 0, /*tp_itemsize*/
2114 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
2115 0, /*tp_print*/
2116 0, /*tp_getattr*/
2117 0, /*tp_setattr*/
2118 0, /*tp_compare */
2119 0, /*tp_repr*/
2120 0, /*tp_as_number*/
2121 0, /*tp_as_sequence*/
2122 0, /*tp_as_mapping*/
2123 0, /*tp_hash */
2124 0, /*tp_call*/
2125 0, /*tp_str*/
2126 0, /*tp_getattro*/
2127 0, /*tp_setattro*/
2128 0, /*tp_as_buffer*/
2129 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2130 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
2131 bufferedrwpair_doc, /* tp_doc */
2132 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2133 (inquiry)bufferedrwpair_clear, /* tp_clear */
2134 0, /* tp_richcompare */
2135 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
2136 0, /* tp_iter */
2137 0, /* tp_iternext */
2138 bufferedrwpair_methods, /* tp_methods */
2139 0, /* tp_members */
2140 bufferedrwpair_getset, /* tp_getset */
2141 0, /* tp_base */
2142 0, /* tp_dict */
2143 0, /* tp_descr_get */
2144 0, /* tp_descr_set */
2145 offsetof(rwpair, dict), /* tp_dictoffset */
2146 (initproc)bufferedrwpair_init, /* tp_init */
2147 0, /* tp_alloc */
2148 PyType_GenericNew, /* tp_new */
2149};
2150
2151
2152
2153/*
2154 * BufferedRandom
2155 */
2156
2157PyDoc_STRVAR(bufferedrandom_doc,
2158 "A buffered interface to random access streams.\n"
2159 "\n"
2160 "The constructor creates a reader and writer for a seekable stream,\n"
2161 "raw, given in the first argument. If the buffer_size is omitted it\n"
2162 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2163 );
2164
2165static int
2166bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
2167{
2168 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2169 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
2170 Py_ssize_t max_buffer_size = -234;
2171 PyObject *raw;
2172
2173 self->ok = 0;
2174 self->detached = 0;
2175
2176 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist,
2177 &raw, &buffer_size, &max_buffer_size)) {
2178 return -1;
2179 }
2180
2181 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2182 return -1;
2183
2184 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
2185 return -1;
2186 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
2187 return -1;
2188 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
2189 return -1;
2190
2191 Py_CLEAR(self->raw);
2192 Py_INCREF(raw);
2193 self->raw = raw;
2194 self->buffer_size = buffer_size;
2195 self->readable = 1;
2196 self->writable = 1;
2197
2198 if (_buffered_init(self) < 0)
2199 return -1;
2200 _bufferedreader_reset_buf(self);
2201 _bufferedwriter_reset_buf(self);
2202 self->pos = 0;
2203
2204 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2205 Py_TYPE(raw) == &PyFileIO_Type);
2206
2207 self->ok = 1;
2208 return 0;
2209}
2210
2211static PyMethodDef bufferedrandom_methods[] = {
2212 /* BufferedIOMixin methods */
2213 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2214 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2215 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2216 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2217 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2218 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2219 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2220
2221 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2222
2223 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2224 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2225 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2226 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2227 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2228 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2229 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2230 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2231 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
2232 {NULL, NULL}
2233};
2234
2235static PyMemberDef bufferedrandom_members[] = {
2236 {"raw", T_OBJECT, offsetof(buffered, raw), 0},
2237 {NULL}
2238};
2239
2240static PyGetSetDef bufferedrandom_getset[] = {
2241 {"closed", (getter)buffered_closed_get, NULL, NULL},
2242 {"name", (getter)buffered_name_get, NULL, NULL},
2243 {"mode", (getter)buffered_mode_get, NULL, NULL},
2244 {NULL}
2245};
2246
2247
2248PyTypeObject PyBufferedRandom_Type = {
2249 PyVarObject_HEAD_INIT(NULL, 0)
2250 "_io.BufferedRandom", /*tp_name*/
2251 sizeof(buffered), /*tp_basicsize*/
2252 0, /*tp_itemsize*/
2253 (destructor)buffered_dealloc, /*tp_dealloc*/
2254 0, /*tp_print*/
2255 0, /*tp_getattr*/
2256 0, /*tp_setattr*/
2257 0, /*tp_compare */
2258 (reprfunc)buffered_repr, /*tp_repr*/
2259 0, /*tp_as_number*/
2260 0, /*tp_as_sequence*/
2261 0, /*tp_as_mapping*/
2262 0, /*tp_hash */
2263 0, /*tp_call*/
2264 0, /*tp_str*/
2265 0, /*tp_getattro*/
2266 0, /*tp_setattro*/
2267 0, /*tp_as_buffer*/
2268 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2269 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2270 bufferedrandom_doc, /* tp_doc */
2271 (traverseproc)buffered_traverse, /* tp_traverse */
2272 (inquiry)buffered_clear, /* tp_clear */
2273 0, /* tp_richcompare */
2274 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2275 0, /* tp_iter */
2276 (iternextfunc)buffered_iternext, /* tp_iternext */
2277 bufferedrandom_methods, /* tp_methods */
2278 bufferedrandom_members, /* tp_members */
2279 bufferedrandom_getset, /* tp_getset */
2280 0, /* tp_base */
2281 0, /*tp_dict*/
2282 0, /* tp_descr_get */
2283 0, /* tp_descr_set */
2284 offsetof(buffered, dict), /*tp_dictoffset*/
2285 (initproc)bufferedrandom_init, /* tp_init */
2286 0, /* tp_alloc */
2287 PyType_GenericNew, /* tp_new */
2288};
2289