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