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