blob: 9b2e5b26f17bb749f31a5f0ba33c919b4d89d43a [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;
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000227 volatile long owner;
Antoine Pitrou19690592009-06-12 20:14:08 +0000228#endif
229
230 Py_ssize_t buffer_size;
231 Py_ssize_t buffer_mask;
232
233 PyObject *dict;
234 PyObject *weakreflist;
235} buffered;
236
237/*
238 Implementation notes:
239
240 * BufferedReader, BufferedWriter and BufferedRandom try to share most
241 methods (this is helped by the members `readable` and `writable`, which
242 are initialized in the respective constructors)
243 * They also share a single buffer for reading and writing. This enables
244 interleaved reads and writes without flushing. It also makes the logic
245 a bit trickier to get right.
246 * The absolute position of the raw stream is cached, if possible, in the
247 `abs_pos` member. It must be updated every time an operation is done
248 on the raw stream. If not sure, it can be reinitialized by calling
249 _buffered_raw_tell(), which queries the raw stream (_buffered_raw_seek()
250 also does it). To read it, use RAW_TELL().
251 * Three helpers, _bufferedreader_raw_read, _bufferedwriter_raw_write and
252 _bufferedwriter_flush_unlocked do a lot of useful housekeeping.
253
254 NOTE: we should try to maintain block alignment of reads and writes to the
255 raw stream (according to the buffer size), but for now it is only done
256 in read() and friends.
257
258*/
259
260/* These macros protect the buffered object against concurrent operations. */
261
262#ifdef WITH_THREAD
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000263
264static int
265_enter_buffered_busy(buffered *self)
266{
267 if (self->owner == PyThread_get_thread_ident()) {
268 PyObject *r = PyObject_Repr((PyObject *) self);
269 if (r != NULL) {
270 PyErr_Format(PyExc_RuntimeError,
271 "reentrant call inside %s",
272 PyString_AS_STRING(r));
273 Py_DECREF(r);
274 }
275 return 0;
Antoine Pitroue50efaa2009-11-01 11:58:22 +0000276 }
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000277 Py_BEGIN_ALLOW_THREADS
278 PyThread_acquire_lock(self->lock, 1);
279 Py_END_ALLOW_THREADS
280 return 1;
281}
282
283#define ENTER_BUFFERED(self) \
284 ( (PyThread_acquire_lock(self->lock, 0) ? \
285 1 : _enter_buffered_busy(self)) \
286 && (self->owner = PyThread_get_thread_ident(), 1) )
Antoine Pitrou19690592009-06-12 20:14:08 +0000287
288#define LEAVE_BUFFERED(self) \
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000289 do { \
290 self->owner = 0; \
291 PyThread_release_lock(self->lock); \
292 } while(0);
293
Antoine Pitrou19690592009-06-12 20:14:08 +0000294#else
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000295#define ENTER_BUFFERED(self) 1
Antoine Pitrou19690592009-06-12 20:14:08 +0000296#define LEAVE_BUFFERED(self)
297#endif
298
299#define CHECK_INITIALIZED(self) \
300 if (self->ok <= 0) { \
301 if (self->detached) { \
302 PyErr_SetString(PyExc_ValueError, \
303 "raw stream has been detached"); \
304 } else { \
305 PyErr_SetString(PyExc_ValueError, \
306 "I/O operation on uninitialized object"); \
307 } \
308 return NULL; \
309 }
310
311#define CHECK_INITIALIZED_INT(self) \
312 if (self->ok <= 0) { \
313 if (self->detached) { \
314 PyErr_SetString(PyExc_ValueError, \
315 "raw stream has been detached"); \
316 } else { \
317 PyErr_SetString(PyExc_ValueError, \
318 "I/O operation on uninitialized object"); \
319 } \
320 return -1; \
321 }
322
323#define IS_CLOSED(self) \
324 (self->fast_closed_checks \
325 ? _PyFileIO_closed(self->raw) \
326 : buffered_closed(self))
327
328#define CHECK_CLOSED(self, error_msg) \
329 if (IS_CLOSED(self)) { \
330 PyErr_SetString(PyExc_ValueError, error_msg); \
331 return NULL; \
332 }
333
334
335#define VALID_READ_BUFFER(self) \
336 (self->readable && self->read_end != -1)
337
338#define VALID_WRITE_BUFFER(self) \
339 (self->writable && self->write_end != -1)
340
341#define ADJUST_POSITION(self, _new_pos) \
342 do { \
343 self->pos = _new_pos; \
344 if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
345 self->read_end = self->pos; \
346 } while(0)
347
348#define READAHEAD(self) \
349 ((self->readable && VALID_READ_BUFFER(self)) \
350 ? (self->read_end - self->pos) : 0)
351
352#define RAW_OFFSET(self) \
353 (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
354 && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
355
356#define RAW_TELL(self) \
357 (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
358
359#define MINUS_LAST_BLOCK(self, size) \
360 (self->buffer_mask ? \
361 (size & ~self->buffer_mask) : \
362 (self->buffer_size * (size / self->buffer_size)))
363
364
365static void
366buffered_dealloc(buffered *self)
367{
368 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
369 return;
370 _PyObject_GC_UNTRACK(self);
371 self->ok = 0;
372 if (self->weakreflist != NULL)
373 PyObject_ClearWeakRefs((PyObject *)self);
374 Py_CLEAR(self->raw);
375 if (self->buffer) {
376 PyMem_Free(self->buffer);
377 self->buffer = NULL;
378 }
379#ifdef WITH_THREAD
380 if (self->lock) {
381 PyThread_free_lock(self->lock);
382 self->lock = NULL;
383 }
384#endif
385 Py_CLEAR(self->dict);
386 Py_TYPE(self)->tp_free((PyObject *)self);
387}
388
Antoine Pitroubff5df02012-07-29 19:02:46 +0200389static PyObject *
390buffered_sizeof(buffered *self, void *unused)
391{
392 Py_ssize_t res;
393
Serhiy Storchakac06a6d02015-12-19 20:07:48 +0200394 res = _PyObject_SIZE(Py_TYPE(self));
Antoine Pitroubff5df02012-07-29 19:02:46 +0200395 if (self->buffer)
396 res += self->buffer_size;
397 return PyLong_FromSsize_t(res);
398}
399
Antoine Pitrou19690592009-06-12 20:14:08 +0000400static int
401buffered_traverse(buffered *self, visitproc visit, void *arg)
402{
403 Py_VISIT(self->raw);
404 Py_VISIT(self->dict);
405 return 0;
406}
407
408static int
409buffered_clear(buffered *self)
410{
411 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
412 return -1;
413 self->ok = 0;
414 Py_CLEAR(self->raw);
415 Py_CLEAR(self->dict);
416 return 0;
417}
418
419/*
420 * _BufferedIOMixin methods
421 * This is not a class, just a collection of methods that will be reused
422 * by BufferedReader and BufferedWriter
423 */
424
425/* Flush and close */
426
427static PyObject *
428buffered_simple_flush(buffered *self, PyObject *args)
429{
430 CHECK_INITIALIZED(self)
431 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
432}
433
434static int
435buffered_closed(buffered *self)
436{
437 int closed;
438 PyObject *res;
439 CHECK_INITIALIZED_INT(self)
440 res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
441 if (res == NULL)
442 return -1;
443 closed = PyObject_IsTrue(res);
444 Py_DECREF(res);
445 return closed;
446}
447
448static PyObject *
449buffered_closed_get(buffered *self, void *context)
450{
451 CHECK_INITIALIZED(self)
452 return PyObject_GetAttr(self->raw, _PyIO_str_closed);
453}
454
455static PyObject *
456buffered_close(buffered *self, PyObject *args)
457{
Benjamin Petersona2d6d712012-12-20 12:24:10 -0600458 PyObject *res = NULL, *exc = NULL, *val, *tb;
Antoine Pitrou19690592009-06-12 20:14:08 +0000459 int r;
460
461 CHECK_INITIALIZED(self)
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000462 if (!ENTER_BUFFERED(self))
463 return NULL;
Antoine Pitrou19690592009-06-12 20:14:08 +0000464
465 r = buffered_closed(self);
466 if (r < 0)
467 goto end;
468 if (r > 0) {
469 res = Py_None;
470 Py_INCREF(res);
471 goto end;
472 }
473 /* flush() will most probably re-take the lock, so drop it first */
474 LEAVE_BUFFERED(self)
475 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000476 if (!ENTER_BUFFERED(self))
477 return NULL;
Benjamin Petersona2d6d712012-12-20 12:24:10 -0600478 if (res == NULL)
479 PyErr_Fetch(&exc, &val, &tb);
480 else
481 Py_DECREF(res);
Antoine Pitrou19690592009-06-12 20:14:08 +0000482
483 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
484
Benjamin Petersona2d6d712012-12-20 12:24:10 -0600485 if (exc != NULL) {
Serhiy Storchakaaa64c462015-03-30 09:48:42 +0300486 _PyErr_ReplaceException(exc, val, tb);
487 Py_CLEAR(res);
Benjamin Petersona2d6d712012-12-20 12:24:10 -0600488 }
489
Antoine Pitrou19690592009-06-12 20:14:08 +0000490end:
491 LEAVE_BUFFERED(self)
492 return res;
493}
494
495/* detach */
496
497static PyObject *
498buffered_detach(buffered *self, PyObject *args)
499{
500 PyObject *raw, *res;
501 CHECK_INITIALIZED(self)
502 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
503 if (res == NULL)
504 return NULL;
505 Py_DECREF(res);
506 raw = self->raw;
507 self->raw = NULL;
508 self->detached = 1;
509 self->ok = 0;
510 return raw;
511}
512
513/* Inquiries */
514
515static PyObject *
516buffered_seekable(buffered *self, PyObject *args)
517{
518 CHECK_INITIALIZED(self)
519 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
520}
521
522static PyObject *
523buffered_readable(buffered *self, PyObject *args)
524{
525 CHECK_INITIALIZED(self)
526 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
527}
528
529static PyObject *
530buffered_writable(buffered *self, PyObject *args)
531{
532 CHECK_INITIALIZED(self)
533 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
534}
535
536static PyObject *
537buffered_name_get(buffered *self, void *context)
538{
539 CHECK_INITIALIZED(self)
540 return PyObject_GetAttrString(self->raw, "name");
541}
542
543static PyObject *
544buffered_mode_get(buffered *self, void *context)
545{
546 CHECK_INITIALIZED(self)
547 return PyObject_GetAttrString(self->raw, "mode");
548}
549
550/* Lower-level APIs */
551
552static PyObject *
553buffered_fileno(buffered *self, PyObject *args)
554{
555 CHECK_INITIALIZED(self)
556 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
557}
558
559static PyObject *
560buffered_isatty(buffered *self, PyObject *args)
561{
562 CHECK_INITIALIZED(self)
563 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
564}
565
566
567/* Forward decls */
568static PyObject *
Antoine Pitrou5aa7df32011-11-21 20:16:44 +0100569_bufferedwriter_flush_unlocked(buffered *);
Antoine Pitrou19690592009-06-12 20:14:08 +0000570static Py_ssize_t
571_bufferedreader_fill_buffer(buffered *self);
572static void
573_bufferedreader_reset_buf(buffered *self);
574static void
575_bufferedwriter_reset_buf(buffered *self);
576static PyObject *
577_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t);
578static PyObject *
579_bufferedreader_read_all(buffered *self);
580static PyObject *
581_bufferedreader_read_fast(buffered *self, Py_ssize_t);
582static PyObject *
583_bufferedreader_read_generic(buffered *self, Py_ssize_t);
584
585
586/*
587 * Helpers
588 */
589
Antoine Pitrou5aa7df32011-11-21 20:16:44 +0100590/* Sets the current error to BlockingIOError */
591static void
592_set_BlockingIOError(char *msg, Py_ssize_t written)
593{
594 PyObject *err;
595 err = PyObject_CallFunction(PyExc_BlockingIOError, "isn",
596 errno, msg, written);
597 if (err)
598 PyErr_SetObject(PyExc_BlockingIOError, err);
599 Py_XDECREF(err);
600}
601
Antoine Pitrou19690592009-06-12 20:14:08 +0000602/* Returns the address of the `written` member if a BlockingIOError was
603 raised, NULL otherwise. The error is always re-raised. */
604static Py_ssize_t *
605_buffered_check_blocking_error(void)
606{
607 PyObject *t, *v, *tb;
608 PyBlockingIOErrorObject *err;
609
610 PyErr_Fetch(&t, &v, &tb);
611 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
612 PyErr_Restore(t, v, tb);
613 return NULL;
614 }
615 err = (PyBlockingIOErrorObject *) v;
616 /* TODO: sanity check (err->written >= 0) */
617 PyErr_Restore(t, v, tb);
618 return &err->written;
619}
620
621static Py_off_t
622_buffered_raw_tell(buffered *self)
623{
624 Py_off_t n;
625 PyObject *res;
626 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
627 if (res == NULL)
628 return -1;
629 n = PyNumber_AsOff_t(res, PyExc_ValueError);
630 Py_DECREF(res);
631 if (n < 0) {
632 if (!PyErr_Occurred())
633 PyErr_Format(PyExc_IOError,
Mark Dickinson889d96452009-11-24 20:51:48 +0000634 "Raw stream returned invalid position %" PY_PRIdOFF,
635 (PY_OFF_T_COMPAT)n);
Antoine Pitrou19690592009-06-12 20:14:08 +0000636 return -1;
637 }
638 self->abs_pos = n;
639 return n;
640}
641
642static Py_off_t
643_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
644{
645 PyObject *res, *posobj, *whenceobj;
646 Py_off_t n;
647
648 posobj = PyLong_FromOff_t(target);
649 if (posobj == NULL)
650 return -1;
651 whenceobj = PyLong_FromLong(whence);
652 if (whenceobj == NULL) {
653 Py_DECREF(posobj);
654 return -1;
655 }
656 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
657 posobj, whenceobj, NULL);
658 Py_DECREF(posobj);
659 Py_DECREF(whenceobj);
660 if (res == NULL)
661 return -1;
662 n = PyNumber_AsOff_t(res, PyExc_ValueError);
663 Py_DECREF(res);
664 if (n < 0) {
665 if (!PyErr_Occurred())
666 PyErr_Format(PyExc_IOError,
Mark Dickinson889d96452009-11-24 20:51:48 +0000667 "Raw stream returned invalid position %" PY_PRIdOFF,
668 (PY_OFF_T_COMPAT)n);
Antoine Pitrou19690592009-06-12 20:14:08 +0000669 return -1;
670 }
671 self->abs_pos = n;
672 return n;
673}
674
675static int
676_buffered_init(buffered *self)
677{
678 Py_ssize_t n;
679 if (self->buffer_size <= 0) {
680 PyErr_SetString(PyExc_ValueError,
681 "buffer size must be strictly positive");
682 return -1;
683 }
684 if (self->buffer)
685 PyMem_Free(self->buffer);
686 self->buffer = PyMem_Malloc(self->buffer_size);
687 if (self->buffer == NULL) {
688 PyErr_NoMemory();
689 return -1;
690 }
691#ifdef WITH_THREAD
Antoine Pitrou607951d2010-08-01 16:57:17 +0000692 if (self->lock)
693 PyThread_free_lock(self->lock);
Antoine Pitrou19690592009-06-12 20:14:08 +0000694 self->lock = PyThread_allocate_lock();
695 if (self->lock == NULL) {
696 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
697 return -1;
698 }
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000699 self->owner = 0;
Antoine Pitrou19690592009-06-12 20:14:08 +0000700#endif
701 /* Find out whether buffer_size is a power of 2 */
702 /* XXX is this optimization useful? */
703 for (n = self->buffer_size - 1; n & 1; n >>= 1)
704 ;
705 if (n == 0)
706 self->buffer_mask = self->buffer_size - 1;
707 else
708 self->buffer_mask = 0;
709 if (_buffered_raw_tell(self) == -1)
710 PyErr_Clear();
711 return 0;
712}
713
Antoine Pitrou6439c002011-02-25 21:35:47 +0000714/* Return 1 if an EnvironmentError with errno == EINTR is set (and then
715 clears the error indicator), 0 otherwise.
716 Should only be called when PyErr_Occurred() is true.
717*/
Gregory P. Smith99716162012-10-12 13:02:06 -0700718int
719_PyIO_trap_eintr(void)
Antoine Pitrou6439c002011-02-25 21:35:47 +0000720{
721 static PyObject *eintr_int = NULL;
722 PyObject *typ, *val, *tb;
723 PyEnvironmentErrorObject *env_err;
724
725 if (eintr_int == NULL) {
726 eintr_int = PyLong_FromLong(EINTR);
727 assert(eintr_int != NULL);
728 }
729 if (!PyErr_ExceptionMatches(PyExc_EnvironmentError))
730 return 0;
731 PyErr_Fetch(&typ, &val, &tb);
732 PyErr_NormalizeException(&typ, &val, &tb);
733 env_err = (PyEnvironmentErrorObject *) val;
734 assert(env_err != NULL);
735 if (env_err->myerrno != NULL &&
736 PyObject_RichCompareBool(env_err->myerrno, eintr_int, Py_EQ) > 0) {
737 Py_DECREF(typ);
738 Py_DECREF(val);
739 Py_XDECREF(tb);
740 return 1;
741 }
742 /* This silences any error set by PyObject_RichCompareBool() */
743 PyErr_Restore(typ, val, tb);
744 return 0;
745}
746
Antoine Pitrou19690592009-06-12 20:14:08 +0000747/*
748 * Shared methods and wrappers
749 */
750
751static PyObject *
Antoine Pitrou808cec52011-08-20 15:40:58 +0200752buffered_flush_and_rewind_unlocked(buffered *self)
753{
754 PyObject *res;
755
Antoine Pitrou5aa7df32011-11-21 20:16:44 +0100756 res = _bufferedwriter_flush_unlocked(self);
Antoine Pitrou808cec52011-08-20 15:40:58 +0200757 if (res == NULL)
758 return NULL;
759 Py_DECREF(res);
760
761 if (self->readable) {
762 /* Rewind the raw stream so that its position corresponds to
763 the current logical position. */
764 Py_off_t n;
765 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
766 _bufferedreader_reset_buf(self);
767 if (n == -1)
768 return NULL;
769 }
770 Py_RETURN_NONE;
771}
772
773static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000774buffered_flush(buffered *self, PyObject *args)
775{
776 PyObject *res;
777
778 CHECK_INITIALIZED(self)
779 CHECK_CLOSED(self, "flush of closed file")
780
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000781 if (!ENTER_BUFFERED(self))
782 return NULL;
Antoine Pitrou808cec52011-08-20 15:40:58 +0200783 res = buffered_flush_and_rewind_unlocked(self);
Antoine Pitrou19690592009-06-12 20:14:08 +0000784 LEAVE_BUFFERED(self)
785
786 return res;
787}
788
789static PyObject *
790buffered_peek(buffered *self, PyObject *args)
791{
792 Py_ssize_t n = 0;
793 PyObject *res = NULL;
794
795 CHECK_INITIALIZED(self)
796 if (!PyArg_ParseTuple(args, "|n:peek", &n)) {
797 return NULL;
798 }
799
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000800 if (!ENTER_BUFFERED(self))
801 return NULL;
Antoine Pitrou19690592009-06-12 20:14:08 +0000802
803 if (self->writable) {
Antoine Pitrou808cec52011-08-20 15:40:58 +0200804 res = buffered_flush_and_rewind_unlocked(self);
Antoine Pitrou19690592009-06-12 20:14:08 +0000805 if (res == NULL)
806 goto end;
807 Py_CLEAR(res);
808 }
809 res = _bufferedreader_peek_unlocked(self, n);
810
811end:
812 LEAVE_BUFFERED(self)
813 return res;
814}
815
816static PyObject *
817buffered_read(buffered *self, PyObject *args)
818{
819 Py_ssize_t n = -1;
820 PyObject *res;
821
822 CHECK_INITIALIZED(self)
Benjamin Petersonddd392c2009-12-13 19:19:07 +0000823 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
Antoine Pitrou19690592009-06-12 20:14:08 +0000824 return NULL;
825 }
826 if (n < -1) {
827 PyErr_SetString(PyExc_ValueError,
828 "read length must be positive or -1");
829 return NULL;
830 }
831
832 CHECK_CLOSED(self, "read of closed file")
833
834 if (n == -1) {
835 /* The number of bytes is unspecified, read until the end of stream */
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000836 if (!ENTER_BUFFERED(self))
837 return NULL;
Antoine Pitrou19690592009-06-12 20:14:08 +0000838 res = _bufferedreader_read_all(self);
Antoine Pitrou19690592009-06-12 20:14:08 +0000839 }
840 else {
841 res = _bufferedreader_read_fast(self, n);
Antoine Pitrou808cec52011-08-20 15:40:58 +0200842 if (res != Py_None)
843 return res;
844 Py_DECREF(res);
845 if (!ENTER_BUFFERED(self))
846 return NULL;
847 res = _bufferedreader_read_generic(self, n);
Antoine Pitrou19690592009-06-12 20:14:08 +0000848 }
849
Antoine Pitrou808cec52011-08-20 15:40:58 +0200850 LEAVE_BUFFERED(self)
Antoine Pitrou19690592009-06-12 20:14:08 +0000851 return res;
852}
853
854static PyObject *
855buffered_read1(buffered *self, PyObject *args)
856{
857 Py_ssize_t n, have, r;
858 PyObject *res = NULL;
859
860 CHECK_INITIALIZED(self)
861 if (!PyArg_ParseTuple(args, "n:read1", &n)) {
862 return NULL;
863 }
864
865 if (n < 0) {
866 PyErr_SetString(PyExc_ValueError,
867 "read length must be positive");
868 return NULL;
869 }
870 if (n == 0)
871 return PyBytes_FromStringAndSize(NULL, 0);
872
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000873 if (!ENTER_BUFFERED(self))
874 return NULL;
Antoine Pitrou19690592009-06-12 20:14:08 +0000875
Antoine Pitrou19690592009-06-12 20:14:08 +0000876 /* Return up to n bytes. If at least one byte is buffered, we
877 only return buffered bytes. Otherwise, we do one raw read. */
878
879 /* XXX: this mimicks the io.py implementation but is probably wrong.
880 If we need to read from the raw stream, then we could actually read
881 all `n` bytes asked by the caller (and possibly more, so as to fill
882 our buffer for the next reads). */
883
884 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
885 if (have > 0) {
886 if (n > have)
887 n = have;
888 res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
889 if (res == NULL)
890 goto end;
891 self->pos += n;
892 goto end;
893 }
894
Antoine Pitrou808cec52011-08-20 15:40:58 +0200895 if (self->writable) {
896 res = buffered_flush_and_rewind_unlocked(self);
897 if (res == NULL)
898 goto end;
899 Py_DECREF(res);
900 }
901
Antoine Pitrou19690592009-06-12 20:14:08 +0000902 /* Fill the buffer from the raw stream, and copy it to the result. */
903 _bufferedreader_reset_buf(self);
904 r = _bufferedreader_fill_buffer(self);
905 if (r == -1)
906 goto end;
907 if (r == -2)
908 r = 0;
909 if (n > r)
910 n = r;
911 res = PyBytes_FromStringAndSize(self->buffer, n);
912 if (res == NULL)
913 goto end;
914 self->pos = n;
915
916end:
917 LEAVE_BUFFERED(self)
918 return res;
919}
920
921static PyObject *
922buffered_readinto(buffered *self, PyObject *args)
923{
Antoine Pitrou19690592009-06-12 20:14:08 +0000924 CHECK_INITIALIZED(self)
925
Antoine Pitrou808cec52011-08-20 15:40:58 +0200926 /* TODO: use raw.readinto() (or a direct copy from our buffer) instead! */
927 return bufferediobase_readinto((PyObject *)self, args);
Antoine Pitrou19690592009-06-12 20:14:08 +0000928}
929
930static PyObject *
931_buffered_readline(buffered *self, Py_ssize_t limit)
932{
933 PyObject *res = NULL;
934 PyObject *chunks = NULL;
935 Py_ssize_t n, written = 0;
936 const char *start, *s, *end;
937
938 CHECK_CLOSED(self, "readline of closed file")
939
940 /* First, try to find a line in the buffer. This can run unlocked because
941 the calls to the C API are simple enough that they can't trigger
942 any thread switch. */
943 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
944 if (limit >= 0 && n > limit)
945 n = limit;
946 start = self->buffer + self->pos;
947 s = memchr(start, '\n', n);
948 if (s != NULL) {
949 res = PyBytes_FromStringAndSize(start, s - start + 1);
950 if (res != NULL)
951 self->pos += s - start + 1;
952 goto end_unlocked;
953 }
954 if (n == limit) {
955 res = PyBytes_FromStringAndSize(start, n);
956 if (res != NULL)
957 self->pos += n;
958 goto end_unlocked;
959 }
960
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +0000961 if (!ENTER_BUFFERED(self))
962 goto end_unlocked;
Antoine Pitrou19690592009-06-12 20:14:08 +0000963
964 /* Now we try to get some more from the raw stream */
Antoine Pitrou19690592009-06-12 20:14:08 +0000965 chunks = PyList_New(0);
966 if (chunks == NULL)
967 goto end;
968 if (n > 0) {
969 res = PyBytes_FromStringAndSize(start, n);
970 if (res == NULL)
971 goto end;
972 if (PyList_Append(chunks, res) < 0) {
973 Py_CLEAR(res);
974 goto end;
975 }
976 Py_CLEAR(res);
977 written += n;
Antoine Pitrou808cec52011-08-20 15:40:58 +0200978 self->pos += n;
Antoine Pitrou19690592009-06-12 20:14:08 +0000979 if (limit >= 0)
980 limit -= n;
981 }
Antoine Pitrou808cec52011-08-20 15:40:58 +0200982 if (self->writable) {
983 PyObject *r = buffered_flush_and_rewind_unlocked(self);
984 if (r == NULL)
985 goto end;
986 Py_DECREF(r);
987 }
Antoine Pitrou19690592009-06-12 20:14:08 +0000988
989 for (;;) {
990 _bufferedreader_reset_buf(self);
991 n = _bufferedreader_fill_buffer(self);
992 if (n == -1)
993 goto end;
994 if (n <= 0)
995 break;
996 if (limit >= 0 && n > limit)
997 n = limit;
998 start = self->buffer;
999 end = start + n;
1000 s = start;
1001 while (s < end) {
1002 if (*s++ == '\n') {
1003 res = PyBytes_FromStringAndSize(start, s - start);
1004 if (res == NULL)
1005 goto end;
1006 self->pos = s - start;
1007 goto found;
1008 }
1009 }
1010 res = PyBytes_FromStringAndSize(start, n);
1011 if (res == NULL)
1012 goto end;
1013 if (n == limit) {
1014 self->pos = n;
1015 break;
1016 }
1017 if (PyList_Append(chunks, res) < 0) {
1018 Py_CLEAR(res);
1019 goto end;
1020 }
1021 Py_CLEAR(res);
1022 written += n;
1023 if (limit >= 0)
1024 limit -= n;
1025 }
1026found:
1027 if (res != NULL && PyList_Append(chunks, res) < 0) {
1028 Py_CLEAR(res);
1029 goto end;
1030 }
Serhiy Storchaka8688aca2015-12-27 12:38:48 +02001031 Py_SETREF(res, _PyBytes_Join(_PyIO_empty_bytes, chunks));
Antoine Pitrou19690592009-06-12 20:14:08 +00001032
1033end:
1034 LEAVE_BUFFERED(self)
1035end_unlocked:
1036 Py_XDECREF(chunks);
1037 return res;
1038}
1039
1040static PyObject *
1041buffered_readline(buffered *self, PyObject *args)
1042{
Antoine Pitrou19690592009-06-12 20:14:08 +00001043 Py_ssize_t limit = -1;
1044
1045 CHECK_INITIALIZED(self)
Benjamin Petersonddd392c2009-12-13 19:19:07 +00001046 if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
Antoine Pitrou19690592009-06-12 20:14:08 +00001047 return NULL;
Antoine Pitrou19690592009-06-12 20:14:08 +00001048 return _buffered_readline(self, limit);
1049}
1050
1051
1052static PyObject *
1053buffered_tell(buffered *self, PyObject *args)
1054{
1055 Py_off_t pos;
1056
1057 CHECK_INITIALIZED(self)
1058 pos = _buffered_raw_tell(self);
1059 if (pos == -1)
1060 return NULL;
1061 pos -= RAW_OFFSET(self);
1062 /* TODO: sanity check (pos >= 0) */
1063 return PyLong_FromOff_t(pos);
1064}
1065
1066static PyObject *
1067buffered_seek(buffered *self, PyObject *args)
1068{
1069 Py_off_t target, n;
1070 int whence = 0;
1071 PyObject *targetobj, *res = NULL;
1072
1073 CHECK_INITIALIZED(self)
1074 if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
1075 return NULL;
1076 }
1077 if (whence < 0 || whence > 2) {
1078 PyErr_Format(PyExc_ValueError,
1079 "whence must be between 0 and 2, not %d", whence);
1080 return NULL;
1081 }
1082
1083 CHECK_CLOSED(self, "seek of closed file")
1084
1085 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1086 if (target == -1 && PyErr_Occurred())
1087 return NULL;
1088
1089 if (whence != 2 && self->readable) {
1090 Py_off_t current, avail;
1091 /* Check if seeking leaves us inside the current buffer,
1092 so as to return quickly if possible. Also, we needn't take the
1093 lock in this fast path.
1094 Don't know how to do that when whence == 2, though. */
1095 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1096 state at this point. */
1097 current = RAW_TELL(self);
1098 avail = READAHEAD(self);
1099 if (avail > 0) {
1100 Py_off_t offset;
1101 if (whence == 0)
1102 offset = target - (current - RAW_OFFSET(self));
1103 else
1104 offset = target;
1105 if (offset >= -self->pos && offset <= avail) {
1106 self->pos += offset;
1107 return PyLong_FromOff_t(current - avail + offset);
1108 }
1109 }
1110 }
1111
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +00001112 if (!ENTER_BUFFERED(self))
1113 return NULL;
Antoine Pitrou19690592009-06-12 20:14:08 +00001114
1115 /* Fallback: invoke raw seek() method and clear buffer */
1116 if (self->writable) {
Antoine Pitrou5aa7df32011-11-21 20:16:44 +01001117 res = _bufferedwriter_flush_unlocked(self);
Antoine Pitrou19690592009-06-12 20:14:08 +00001118 if (res == NULL)
1119 goto end;
1120 Py_CLEAR(res);
1121 _bufferedwriter_reset_buf(self);
1122 }
1123
1124 /* TODO: align on block boundary and read buffer if needed? */
1125 if (whence == 1)
1126 target -= RAW_OFFSET(self);
1127 n = _buffered_raw_seek(self, target, whence);
1128 if (n == -1)
1129 goto end;
1130 self->raw_pos = -1;
1131 res = PyLong_FromOff_t(n);
1132 if (res != NULL && self->readable)
1133 _bufferedreader_reset_buf(self);
1134
1135end:
1136 LEAVE_BUFFERED(self)
1137 return res;
1138}
1139
1140static PyObject *
1141buffered_truncate(buffered *self, PyObject *args)
1142{
1143 PyObject *pos = Py_None;
1144 PyObject *res = NULL;
1145
1146 CHECK_INITIALIZED(self)
1147 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
1148 return NULL;
1149 }
1150
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +00001151 if (!ENTER_BUFFERED(self))
1152 return NULL;
Antoine Pitrou19690592009-06-12 20:14:08 +00001153
1154 if (self->writable) {
Antoine Pitrou808cec52011-08-20 15:40:58 +02001155 res = buffered_flush_and_rewind_unlocked(self);
Antoine Pitrou19690592009-06-12 20:14:08 +00001156 if (res == NULL)
1157 goto end;
1158 Py_CLEAR(res);
1159 }
Antoine Pitrou19690592009-06-12 20:14:08 +00001160 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1161 if (res == NULL)
1162 goto end;
1163 /* Reset cached position */
1164 if (_buffered_raw_tell(self) == -1)
1165 PyErr_Clear();
1166
1167end:
1168 LEAVE_BUFFERED(self)
1169 return res;
1170}
1171
1172static PyObject *
1173buffered_iternext(buffered *self)
1174{
1175 PyObject *line;
1176 PyTypeObject *tp;
1177
1178 CHECK_INITIALIZED(self);
1179
1180 tp = Py_TYPE(self);
1181 if (tp == &PyBufferedReader_Type ||
1182 tp == &PyBufferedRandom_Type) {
1183 /* Skip method call overhead for speed */
1184 line = _buffered_readline(self, -1);
1185 }
1186 else {
1187 line = PyObject_CallMethodObjArgs((PyObject *)self,
1188 _PyIO_str_readline, NULL);
1189 if (line && !PyBytes_Check(line)) {
1190 PyErr_Format(PyExc_IOError,
1191 "readline() should have returned a bytes object, "
1192 "not '%.200s'", Py_TYPE(line)->tp_name);
1193 Py_DECREF(line);
1194 return NULL;
1195 }
1196 }
1197
1198 if (line == NULL)
1199 return NULL;
1200
1201 if (PyBytes_GET_SIZE(line) == 0) {
1202 /* Reached EOF or would have blocked */
1203 Py_DECREF(line);
1204 return NULL;
1205 }
1206
1207 return line;
1208}
1209
1210static PyObject *
1211buffered_repr(buffered *self)
1212{
1213 PyObject *nameobj, *res;
1214
1215 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
1216 if (nameobj == NULL) {
Benjamin Peterson53ae6142014-12-21 20:51:50 -06001217 if (PyErr_ExceptionMatches(PyExc_Exception))
Antoine Pitrou19690592009-06-12 20:14:08 +00001218 PyErr_Clear();
1219 else
1220 return NULL;
1221 res = PyString_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1222 }
1223 else {
1224 PyObject *repr = PyObject_Repr(nameobj);
1225 Py_DECREF(nameobj);
1226 if (repr == NULL)
1227 return NULL;
1228 res = PyString_FromFormat("<%s name=%s>",
1229 Py_TYPE(self)->tp_name,
1230 PyString_AS_STRING(repr));
1231 Py_DECREF(repr);
1232 }
1233 return res;
1234}
1235
1236/*
1237 * class BufferedReader
1238 */
1239
1240PyDoc_STRVAR(bufferedreader_doc,
1241 "Create a new buffered reader using the given readable raw IO object.");
1242
1243static void _bufferedreader_reset_buf(buffered *self)
1244{
1245 self->read_end = -1;
1246}
1247
1248static int
1249bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds)
1250{
1251 char *kwlist[] = {"raw", "buffer_size", NULL};
1252 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1253 PyObject *raw;
1254
1255 self->ok = 0;
1256 self->detached = 0;
1257
1258 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist,
1259 &raw, &buffer_size)) {
1260 return -1;
1261 }
1262
1263 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
1264 return -1;
1265
Antoine Pitrou19690592009-06-12 20:14:08 +00001266 Py_INCREF(raw);
Serhiy Storchaka8688aca2015-12-27 12:38:48 +02001267 Py_SETREF(self->raw, raw);
Antoine Pitrou19690592009-06-12 20:14:08 +00001268 self->buffer_size = buffer_size;
1269 self->readable = 1;
1270 self->writable = 0;
1271
1272 if (_buffered_init(self) < 0)
1273 return -1;
1274 _bufferedreader_reset_buf(self);
1275
1276 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1277 Py_TYPE(raw) == &PyFileIO_Type);
1278
1279 self->ok = 1;
1280 return 0;
1281}
1282
1283static Py_ssize_t
1284_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
1285{
1286 Py_buffer buf;
1287 PyObject *memobj, *res;
1288 Py_ssize_t n;
1289 /* NOTE: the buffer needn't be released as its object is NULL. */
1290 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1291 return -1;
1292 memobj = PyMemoryView_FromBuffer(&buf);
1293 if (memobj == NULL)
1294 return -1;
Antoine Pitrou6439c002011-02-25 21:35:47 +00001295 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1296 occurs so we needn't do it ourselves.
1297 We then retry reading, ignoring the signal if no handler has
1298 raised (see issue #10956).
1299 */
1300 do {
1301 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
Gregory P. Smith99716162012-10-12 13:02:06 -07001302 } while (res == NULL && _PyIO_trap_eintr());
Antoine Pitrou19690592009-06-12 20:14:08 +00001303 Py_DECREF(memobj);
1304 if (res == NULL)
1305 return -1;
1306 if (res == Py_None) {
1307 /* Non-blocking stream would have blocked. Special return code! */
1308 Py_DECREF(res);
1309 return -2;
1310 }
1311 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1312 Py_DECREF(res);
1313 if (n < 0 || n > len) {
1314 PyErr_Format(PyExc_IOError,
1315 "raw readinto() returned invalid length %zd "
1316 "(should have been between 0 and %zd)", n, len);
1317 return -1;
1318 }
1319 if (n > 0 && self->abs_pos != -1)
1320 self->abs_pos += n;
1321 return n;
1322}
1323
1324static Py_ssize_t
1325_bufferedreader_fill_buffer(buffered *self)
1326{
1327 Py_ssize_t start, len, n;
1328 if (VALID_READ_BUFFER(self))
1329 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1330 else
1331 start = 0;
1332 len = self->buffer_size - start;
1333 n = _bufferedreader_raw_read(self, self->buffer + start, len);
1334 if (n <= 0)
1335 return n;
1336 self->read_end = start + n;
1337 self->raw_pos = start + n;
1338 return n;
1339}
1340
1341static PyObject *
1342_bufferedreader_read_all(buffered *self)
1343{
1344 Py_ssize_t current_size;
1345 PyObject *res, *data = NULL;
1346 PyObject *chunks = PyList_New(0);
1347
1348 if (chunks == NULL)
1349 return NULL;
1350
1351 /* First copy what we have in the current buffer. */
1352 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1353 if (current_size) {
1354 data = PyBytes_FromStringAndSize(
1355 self->buffer + self->pos, current_size);
1356 if (data == NULL) {
1357 Py_DECREF(chunks);
1358 return NULL;
1359 }
Antoine Pitrou808cec52011-08-20 15:40:58 +02001360 self->pos += current_size;
Antoine Pitrou19690592009-06-12 20:14:08 +00001361 }
Antoine Pitrou19690592009-06-12 20:14:08 +00001362 /* We're going past the buffer's bounds, flush it */
1363 if (self->writable) {
Antoine Pitrou808cec52011-08-20 15:40:58 +02001364 res = buffered_flush_and_rewind_unlocked(self);
Antoine Pitrou19690592009-06-12 20:14:08 +00001365 if (res == NULL) {
1366 Py_DECREF(chunks);
1367 return NULL;
1368 }
1369 Py_CLEAR(res);
1370 }
Antoine Pitrou808cec52011-08-20 15:40:58 +02001371 _bufferedreader_reset_buf(self);
Antoine Pitrou19690592009-06-12 20:14:08 +00001372 while (1) {
1373 if (data) {
1374 if (PyList_Append(chunks, data) < 0) {
1375 Py_DECREF(data);
1376 Py_DECREF(chunks);
1377 return NULL;
1378 }
1379 Py_DECREF(data);
1380 }
1381
1382 /* Read until EOF or until read() would block. */
1383 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1384 if (data == NULL) {
1385 Py_DECREF(chunks);
1386 return NULL;
1387 }
1388 if (data != Py_None && !PyBytes_Check(data)) {
1389 Py_DECREF(data);
1390 Py_DECREF(chunks);
1391 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1392 return NULL;
1393 }
1394 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1395 if (current_size == 0) {
1396 Py_DECREF(chunks);
1397 return data;
1398 }
1399 else {
1400 res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1401 Py_DECREF(data);
1402 Py_DECREF(chunks);
1403 return res;
1404 }
1405 }
1406 current_size += PyBytes_GET_SIZE(data);
1407 if (self->abs_pos != -1)
1408 self->abs_pos += PyBytes_GET_SIZE(data);
1409 }
1410}
1411
1412/* Read n bytes from the buffer if it can, otherwise return None.
1413 This function is simple enough that it can run unlocked. */
1414static PyObject *
1415_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
1416{
1417 Py_ssize_t current_size;
1418
1419 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1420 if (n <= current_size) {
1421 /* Fast path: the data to read is fully buffered. */
1422 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1423 if (res != NULL)
1424 self->pos += n;
1425 return res;
1426 }
1427 Py_RETURN_NONE;
1428}
1429
1430/* Generic read function: read from the stream until enough bytes are read,
1431 * or until an EOF occurs or until read() would block.
1432 */
1433static PyObject *
1434_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
1435{
1436 PyObject *res = NULL;
1437 Py_ssize_t current_size, remaining, written;
1438 char *out;
1439
1440 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1441 if (n <= current_size)
1442 return _bufferedreader_read_fast(self, n);
1443
1444 res = PyBytes_FromStringAndSize(NULL, n);
1445 if (res == NULL)
1446 goto error;
1447 out = PyBytes_AS_STRING(res);
1448 remaining = n;
1449 written = 0;
1450 if (current_size > 0) {
1451 memcpy(out, self->buffer + self->pos, current_size);
1452 remaining -= current_size;
1453 written += current_size;
Antoine Pitrou808cec52011-08-20 15:40:58 +02001454 self->pos += current_size;
1455 }
1456 /* Flush the write buffer if necessary */
1457 if (self->writable) {
1458 PyObject *r = buffered_flush_and_rewind_unlocked(self);
1459 if (r == NULL)
1460 goto error;
1461 Py_DECREF(r);
Antoine Pitrou19690592009-06-12 20:14:08 +00001462 }
1463 _bufferedreader_reset_buf(self);
1464 while (remaining > 0) {
1465 /* We want to read a whole block at the end into buffer.
1466 If we had readv() we could do this in one pass. */
1467 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1468 if (r == 0)
1469 break;
1470 r = _bufferedreader_raw_read(self, out + written, r);
1471 if (r == -1)
1472 goto error;
1473 if (r == 0 || r == -2) {
1474 /* EOF occurred or read() would block. */
1475 if (r == 0 || written > 0) {
1476 if (_PyBytes_Resize(&res, written))
1477 goto error;
1478 return res;
1479 }
1480 Py_DECREF(res);
1481 Py_INCREF(Py_None);
1482 return Py_None;
1483 }
1484 remaining -= r;
1485 written += r;
1486 }
1487 assert(remaining <= self->buffer_size);
1488 self->pos = 0;
1489 self->raw_pos = 0;
1490 self->read_end = 0;
Antoine Pitroucb4f47c2010-08-11 13:40:17 +00001491 /* NOTE: when the read is satisfied, we avoid issuing any additional
1492 reads, which could block indefinitely (e.g. on a socket).
1493 See issue #9550. */
1494 while (remaining > 0 && self->read_end < self->buffer_size) {
Antoine Pitrou19690592009-06-12 20:14:08 +00001495 Py_ssize_t r = _bufferedreader_fill_buffer(self);
1496 if (r == -1)
1497 goto error;
1498 if (r == 0 || r == -2) {
1499 /* EOF occurred or read() would block. */
1500 if (r == 0 || written > 0) {
1501 if (_PyBytes_Resize(&res, written))
1502 goto error;
1503 return res;
1504 }
1505 Py_DECREF(res);
1506 Py_INCREF(Py_None);
1507 return Py_None;
1508 }
1509 if (remaining > r) {
1510 memcpy(out + written, self->buffer + self->pos, r);
1511 written += r;
1512 self->pos += r;
1513 remaining -= r;
1514 }
1515 else if (remaining > 0) {
1516 memcpy(out + written, self->buffer + self->pos, remaining);
1517 written += remaining;
1518 self->pos += remaining;
1519 remaining = 0;
1520 }
1521 if (remaining == 0)
1522 break;
1523 }
1524
1525 return res;
1526
1527error:
1528 Py_XDECREF(res);
1529 return NULL;
1530}
1531
1532static PyObject *
1533_bufferedreader_peek_unlocked(buffered *self, Py_ssize_t n)
1534{
1535 Py_ssize_t have, r;
1536
1537 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1538 /* Constraints:
1539 1. we don't want to advance the file position.
1540 2. we don't want to lose block alignment, so we can't shift the buffer
1541 to make some place.
1542 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1543 */
1544 if (have > 0) {
1545 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1546 }
1547
1548 /* Fill the buffer from the raw stream, and copy it to the result. */
1549 _bufferedreader_reset_buf(self);
1550 r = _bufferedreader_fill_buffer(self);
1551 if (r == -1)
1552 return NULL;
1553 if (r == -2)
1554 r = 0;
1555 self->pos = 0;
1556 return PyBytes_FromStringAndSize(self->buffer, r);
1557}
1558
1559static PyMethodDef bufferedreader_methods[] = {
1560 /* BufferedIOMixin methods */
1561 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1562 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
1563 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1564 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1565 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1566 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1567 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1568 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
1569
1570 {"read", (PyCFunction)buffered_read, METH_VARARGS},
1571 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
1572 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
1573 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
1574 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1575 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
1576 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
Antoine Pitroubff5df02012-07-29 19:02:46 +02001577 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
Antoine Pitrou19690592009-06-12 20:14:08 +00001578 {NULL, NULL}
1579};
1580
1581static PyMemberDef bufferedreader_members[] = {
Antoine Pitroufc9ead62010-12-21 21:26:55 +00001582 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Antoine Pitrou19690592009-06-12 20:14:08 +00001583 {NULL}
1584};
1585
1586static PyGetSetDef bufferedreader_getset[] = {
1587 {"closed", (getter)buffered_closed_get, NULL, NULL},
1588 {"name", (getter)buffered_name_get, NULL, NULL},
1589 {"mode", (getter)buffered_mode_get, NULL, NULL},
1590 {NULL}
1591};
1592
1593
1594PyTypeObject PyBufferedReader_Type = {
1595 PyVarObject_HEAD_INIT(NULL, 0)
1596 "_io.BufferedReader", /*tp_name*/
1597 sizeof(buffered), /*tp_basicsize*/
1598 0, /*tp_itemsize*/
1599 (destructor)buffered_dealloc, /*tp_dealloc*/
1600 0, /*tp_print*/
1601 0, /*tp_getattr*/
1602 0, /*tp_setattr*/
1603 0, /*tp_compare */
1604 (reprfunc)buffered_repr, /*tp_repr*/
1605 0, /*tp_as_number*/
1606 0, /*tp_as_sequence*/
1607 0, /*tp_as_mapping*/
1608 0, /*tp_hash */
1609 0, /*tp_call*/
1610 0, /*tp_str*/
1611 0, /*tp_getattro*/
1612 0, /*tp_setattro*/
1613 0, /*tp_as_buffer*/
1614 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1615 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1616 bufferedreader_doc, /* tp_doc */
1617 (traverseproc)buffered_traverse, /* tp_traverse */
1618 (inquiry)buffered_clear, /* tp_clear */
1619 0, /* tp_richcompare */
1620 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
1621 0, /* tp_iter */
1622 (iternextfunc)buffered_iternext, /* tp_iternext */
1623 bufferedreader_methods, /* tp_methods */
1624 bufferedreader_members, /* tp_members */
1625 bufferedreader_getset, /* tp_getset */
1626 0, /* tp_base */
1627 0, /* tp_dict */
1628 0, /* tp_descr_get */
1629 0, /* tp_descr_set */
1630 offsetof(buffered, dict), /* tp_dictoffset */
1631 (initproc)bufferedreader_init, /* tp_init */
1632 0, /* tp_alloc */
1633 PyType_GenericNew, /* tp_new */
1634};
1635
1636
1637
1638static int
1639complain_about_max_buffer_size(void)
1640{
1641 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1642 "max_buffer_size is deprecated", 1) < 0)
1643 return 0;
1644 return 1;
1645}
1646
1647/*
1648 * class BufferedWriter
1649 */
1650PyDoc_STRVAR(bufferedwriter_doc,
1651 "A buffer for a writeable sequential RawIO object.\n"
1652 "\n"
1653 "The constructor creates a BufferedWriter for the given writeable raw\n"
1654 "stream. If the buffer_size is not given, it defaults to\n"
1655 "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
1656 );
1657
1658static void
1659_bufferedwriter_reset_buf(buffered *self)
1660{
1661 self->write_pos = 0;
1662 self->write_end = -1;
1663}
1664
1665static int
1666bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds)
1667{
1668 /* TODO: properly deprecate max_buffer_size */
1669 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
1670 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
1671 Py_ssize_t max_buffer_size = -234;
1672 PyObject *raw;
1673
1674 self->ok = 0;
1675 self->detached = 0;
1676
R David Murray5b2cf5e2013-02-23 22:11:21 -05001677 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedWriter", kwlist,
Antoine Pitrou19690592009-06-12 20:14:08 +00001678 &raw, &buffer_size, &max_buffer_size)) {
1679 return -1;
1680 }
1681
1682 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
1683 return -1;
1684
1685 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
1686 return -1;
1687
Antoine Pitrou19690592009-06-12 20:14:08 +00001688 Py_INCREF(raw);
Serhiy Storchaka8688aca2015-12-27 12:38:48 +02001689 Py_SETREF(self->raw, raw);
Antoine Pitrou19690592009-06-12 20:14:08 +00001690 self->readable = 0;
1691 self->writable = 1;
1692
1693 self->buffer_size = buffer_size;
1694 if (_buffered_init(self) < 0)
1695 return -1;
1696 _bufferedwriter_reset_buf(self);
1697 self->pos = 0;
1698
1699 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1700 Py_TYPE(raw) == &PyFileIO_Type);
1701
1702 self->ok = 1;
1703 return 0;
1704}
1705
1706static Py_ssize_t
1707_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
1708{
1709 Py_buffer buf;
1710 PyObject *memobj, *res;
1711 Py_ssize_t n;
Antoine Pitrou5aa7df32011-11-21 20:16:44 +01001712 int errnum;
Antoine Pitrou19690592009-06-12 20:14:08 +00001713 /* NOTE: the buffer needn't be released as its object is NULL. */
1714 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1715 return -1;
1716 memobj = PyMemoryView_FromBuffer(&buf);
1717 if (memobj == NULL)
1718 return -1;
Antoine Pitrou6439c002011-02-25 21:35:47 +00001719 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1720 occurs so we needn't do it ourselves.
1721 We then retry writing, ignoring the signal if no handler has
1722 raised (see issue #10956).
1723 */
1724 do {
Antoine Pitrou5aa7df32011-11-21 20:16:44 +01001725 errno = 0;
Antoine Pitrou6439c002011-02-25 21:35:47 +00001726 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
Antoine Pitrou5aa7df32011-11-21 20:16:44 +01001727 errnum = errno;
Gregory P. Smith99716162012-10-12 13:02:06 -07001728 } while (res == NULL && _PyIO_trap_eintr());
Antoine Pitrou19690592009-06-12 20:14:08 +00001729 Py_DECREF(memobj);
1730 if (res == NULL)
1731 return -1;
Antoine Pitrou5aa7df32011-11-21 20:16:44 +01001732 if (res == Py_None) {
1733 /* Non-blocking stream would have blocked. Special return code!
1734 Being paranoid we reset errno in case it is changed by code
1735 triggered by a decref. errno is used by _set_BlockingIOError(). */
1736 Py_DECREF(res);
1737 errno = errnum;
1738 return -2;
1739 }
Antoine Pitrou19690592009-06-12 20:14:08 +00001740 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1741 Py_DECREF(res);
1742 if (n < 0 || n > len) {
1743 PyErr_Format(PyExc_IOError,
1744 "raw write() returned invalid length %zd "
1745 "(should have been between 0 and %zd)", n, len);
1746 return -1;
1747 }
1748 if (n > 0 && self->abs_pos != -1)
1749 self->abs_pos += n;
1750 return n;
1751}
1752
1753/* `restore_pos` is 1 if we need to restore the raw stream position at
1754 the end, 0 otherwise. */
1755static PyObject *
Antoine Pitrou5aa7df32011-11-21 20:16:44 +01001756_bufferedwriter_flush_unlocked(buffered *self)
Antoine Pitrou19690592009-06-12 20:14:08 +00001757{
1758 Py_ssize_t written = 0;
1759 Py_off_t n, rewind;
1760
1761 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1762 goto end;
1763 /* First, rewind */
1764 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1765 if (rewind != 0) {
1766 n = _buffered_raw_seek(self, -rewind, 1);
1767 if (n < 0) {
1768 goto error;
1769 }
1770 self->raw_pos -= rewind;
1771 }
1772 while (self->write_pos < self->write_end) {
1773 n = _bufferedwriter_raw_write(self,
1774 self->buffer + self->write_pos,
1775 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1776 Py_off_t, Py_ssize_t));
1777 if (n == -1) {
Antoine Pitrou5aa7df32011-11-21 20:16:44 +01001778 goto error;
1779 }
1780 else if (n == -2) {
1781 _set_BlockingIOError("write could not complete without blocking",
1782 0);
Antoine Pitrou19690592009-06-12 20:14:08 +00001783 goto error;
1784 }
1785 self->write_pos += n;
1786 self->raw_pos = self->write_pos;
1787 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
Antoine Pitrou3ebaed62010-08-21 19:17:25 +00001788 /* Partial writes can return successfully when interrupted by a
1789 signal (see write(2)). We must run signal handlers before
1790 blocking another time, possibly indefinitely. */
1791 if (PyErr_CheckSignals() < 0)
1792 goto error;
Antoine Pitrou19690592009-06-12 20:14:08 +00001793 }
1794
Antoine Pitrou19690592009-06-12 20:14:08 +00001795 _bufferedwriter_reset_buf(self);
1796
1797end:
1798 Py_RETURN_NONE;
1799
1800error:
1801 return NULL;
1802}
1803
1804static PyObject *
1805bufferedwriter_write(buffered *self, PyObject *args)
1806{
1807 PyObject *res = NULL;
1808 Py_buffer buf;
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001809 Py_ssize_t written, avail, remaining;
1810 Py_off_t offset;
Antoine Pitrou19690592009-06-12 20:14:08 +00001811
1812 CHECK_INITIALIZED(self)
1813 if (!PyArg_ParseTuple(args, "s*:write", &buf)) {
1814 return NULL;
1815 }
1816
1817 if (IS_CLOSED(self)) {
1818 PyErr_SetString(PyExc_ValueError, "write to closed file");
1819 PyBuffer_Release(&buf);
1820 return NULL;
1821 }
1822
Antoine Pitrou4cb64ad2010-12-03 19:31:52 +00001823 if (!ENTER_BUFFERED(self)) {
1824 PyBuffer_Release(&buf);
1825 return NULL;
1826 }
Antoine Pitrou19690592009-06-12 20:14:08 +00001827
1828 /* Fast path: the data to write can be fully buffered. */
1829 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1830 self->pos = 0;
1831 self->raw_pos = 0;
1832 }
1833 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1834 if (buf.len <= avail) {
1835 memcpy(self->buffer + self->pos, buf.buf, buf.len);
Antoine Pitrouee46a7b2011-05-13 00:31:52 +02001836 if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
Antoine Pitrou19690592009-06-12 20:14:08 +00001837 self->write_pos = self->pos;
1838 }
1839 ADJUST_POSITION(self, self->pos + buf.len);
1840 if (self->pos > self->write_end)
1841 self->write_end = self->pos;
1842 written = buf.len;
1843 goto end;
1844 }
1845
1846 /* First write the current buffer */
Antoine Pitrou5aa7df32011-11-21 20:16:44 +01001847 res = _bufferedwriter_flush_unlocked(self);
Antoine Pitrou19690592009-06-12 20:14:08 +00001848 if (res == NULL) {
1849 Py_ssize_t *w = _buffered_check_blocking_error();
1850 if (w == NULL)
1851 goto error;
1852 if (self->readable)
1853 _bufferedreader_reset_buf(self);
1854 /* Make some place by shifting the buffer. */
1855 assert(VALID_WRITE_BUFFER(self));
1856 memmove(self->buffer, self->buffer + self->write_pos,
1857 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1858 Py_off_t, Py_ssize_t));
1859 self->write_end -= self->write_pos;
1860 self->raw_pos -= self->write_pos;
1861 self->pos -= self->write_pos;
1862 self->write_pos = 0;
1863 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1864 Py_off_t, Py_ssize_t);
1865 if (buf.len <= avail) {
1866 /* Everything can be buffered */
1867 PyErr_Clear();
1868 memcpy(self->buffer + self->write_end, buf.buf, buf.len);
1869 self->write_end += buf.len;
Antoine Pitrou5aa7df32011-11-21 20:16:44 +01001870 self->pos += buf.len;
Antoine Pitrou19690592009-06-12 20:14:08 +00001871 written = buf.len;
1872 goto end;
1873 }
1874 /* Buffer as much as possible. */
1875 memcpy(self->buffer + self->write_end, buf.buf, avail);
1876 self->write_end += avail;
Antoine Pitrou5aa7df32011-11-21 20:16:44 +01001877 self->pos += avail;
1878 /* XXX Modifying the existing exception e using the pointer w
1879 will change e.characters_written but not e.args[2].
1880 Therefore we just replace with a new error. */
1881 _set_BlockingIOError("write could not complete without blocking",
1882 avail);
Antoine Pitrou19690592009-06-12 20:14:08 +00001883 goto error;
1884 }
1885 Py_CLEAR(res);
1886
Antoine Pitrou20e1f932009-08-06 20:18:29 +00001887 /* Adjust the raw stream position if it is away from the logical stream
1888 position. This happens if the read buffer has been filled but not
1889 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1890 the raw stream by itself).
1891 Fixes issue #6629.
1892 */
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001893 offset = RAW_OFFSET(self);
1894 if (offset != 0) {
1895 if (_buffered_raw_seek(self, -offset, 1) < 0)
Antoine Pitrou20e1f932009-08-06 20:18:29 +00001896 goto error;
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001897 self->raw_pos -= offset;
Antoine Pitrou20e1f932009-08-06 20:18:29 +00001898 }
1899
Antoine Pitrou19690592009-06-12 20:14:08 +00001900 /* Then write buf itself. At this point the buffer has been emptied. */
1901 remaining = buf.len;
1902 written = 0;
1903 while (remaining > self->buffer_size) {
Amaury Forgeot d'Arc3de46472009-10-05 20:18:05 +00001904 Py_ssize_t n = _bufferedwriter_raw_write(
Antoine Pitrou19690592009-06-12 20:14:08 +00001905 self, (char *) buf.buf + written, buf.len - written);
1906 if (n == -1) {
Antoine Pitrou5aa7df32011-11-21 20:16:44 +01001907 goto error;
1908 } else if (n == -2) {
1909 /* Write failed because raw file is non-blocking */
Antoine Pitrou19690592009-06-12 20:14:08 +00001910 if (remaining > self->buffer_size) {
1911 /* Can't buffer everything, still buffer as much as possible */
1912 memcpy(self->buffer,
1913 (char *) buf.buf + written, self->buffer_size);
1914 self->raw_pos = 0;
1915 ADJUST_POSITION(self, self->buffer_size);
1916 self->write_end = self->buffer_size;
Antoine Pitrou5aa7df32011-11-21 20:16:44 +01001917 written += self->buffer_size;
1918 _set_BlockingIOError("write could not complete without "
1919 "blocking", written);
Antoine Pitrou19690592009-06-12 20:14:08 +00001920 goto error;
1921 }
1922 PyErr_Clear();
1923 break;
1924 }
1925 written += n;
1926 remaining -= n;
Antoine Pitrou3ebaed62010-08-21 19:17:25 +00001927 /* Partial writes can return successfully when interrupted by a
1928 signal (see write(2)). We must run signal handlers before
1929 blocking another time, possibly indefinitely. */
1930 if (PyErr_CheckSignals() < 0)
1931 goto error;
Antoine Pitrou19690592009-06-12 20:14:08 +00001932 }
1933 if (self->readable)
1934 _bufferedreader_reset_buf(self);
1935 if (remaining > 0) {
1936 memcpy(self->buffer, (char *) buf.buf + written, remaining);
1937 written += remaining;
1938 }
1939 self->write_pos = 0;
1940 /* TODO: sanity check (remaining >= 0) */
1941 self->write_end = remaining;
1942 ADJUST_POSITION(self, remaining);
1943 self->raw_pos = 0;
1944
1945end:
1946 res = PyLong_FromSsize_t(written);
1947
1948error:
1949 LEAVE_BUFFERED(self)
1950 PyBuffer_Release(&buf);
1951 return res;
1952}
1953
1954static PyMethodDef bufferedwriter_methods[] = {
1955 /* BufferedIOMixin methods */
1956 {"close", (PyCFunction)buffered_close, METH_NOARGS},
1957 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
1958 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
1959 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
1960 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
1961 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
1962 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
1963
1964 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
1965 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
1966 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
1967 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
1968 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
Antoine Pitroubff5df02012-07-29 19:02:46 +02001969 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
Antoine Pitrou19690592009-06-12 20:14:08 +00001970 {NULL, NULL}
1971};
1972
1973static PyMemberDef bufferedwriter_members[] = {
Antoine Pitroufc9ead62010-12-21 21:26:55 +00001974 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Antoine Pitrou19690592009-06-12 20:14:08 +00001975 {NULL}
1976};
1977
1978static PyGetSetDef bufferedwriter_getset[] = {
1979 {"closed", (getter)buffered_closed_get, NULL, NULL},
1980 {"name", (getter)buffered_name_get, NULL, NULL},
1981 {"mode", (getter)buffered_mode_get, NULL, NULL},
1982 {NULL}
1983};
1984
1985
1986PyTypeObject PyBufferedWriter_Type = {
1987 PyVarObject_HEAD_INIT(NULL, 0)
1988 "_io.BufferedWriter", /*tp_name*/
1989 sizeof(buffered), /*tp_basicsize*/
1990 0, /*tp_itemsize*/
1991 (destructor)buffered_dealloc, /*tp_dealloc*/
1992 0, /*tp_print*/
1993 0, /*tp_getattr*/
1994 0, /*tp_setattr*/
1995 0, /*tp_compare */
1996 (reprfunc)buffered_repr, /*tp_repr*/
1997 0, /*tp_as_number*/
1998 0, /*tp_as_sequence*/
1999 0, /*tp_as_mapping*/
2000 0, /*tp_hash */
2001 0, /*tp_call*/
2002 0, /*tp_str*/
2003 0, /*tp_getattro*/
2004 0, /*tp_setattro*/
2005 0, /*tp_as_buffer*/
2006 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2007 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2008 bufferedwriter_doc, /* tp_doc */
2009 (traverseproc)buffered_traverse, /* tp_traverse */
2010 (inquiry)buffered_clear, /* tp_clear */
2011 0, /* tp_richcompare */
2012 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2013 0, /* tp_iter */
2014 0, /* tp_iternext */
2015 bufferedwriter_methods, /* tp_methods */
2016 bufferedwriter_members, /* tp_members */
2017 bufferedwriter_getset, /* tp_getset */
2018 0, /* tp_base */
2019 0, /* tp_dict */
2020 0, /* tp_descr_get */
2021 0, /* tp_descr_set */
2022 offsetof(buffered, dict), /* tp_dictoffset */
2023 (initproc)bufferedwriter_init, /* tp_init */
2024 0, /* tp_alloc */
2025 PyType_GenericNew, /* tp_new */
2026};
2027
2028
2029
2030/*
2031 * BufferedRWPair
2032 */
2033
2034PyDoc_STRVAR(bufferedrwpair_doc,
2035 "A buffered reader and writer object together.\n"
2036 "\n"
2037 "A buffered reader object and buffered writer object put together to\n"
2038 "form a sequential IO object that can read and write. This is typically\n"
2039 "used with a socket or two-way pipe.\n"
2040 "\n"
2041 "reader and writer are RawIOBase objects that are readable and\n"
2042 "writeable respectively. If the buffer_size is omitted it defaults to\n"
2043 "DEFAULT_BUFFER_SIZE.\n"
2044 );
2045
2046/* XXX The usefulness of this (compared to having two separate IO objects) is
2047 * questionable.
2048 */
2049
2050typedef struct {
2051 PyObject_HEAD
2052 buffered *reader;
2053 buffered *writer;
2054 PyObject *dict;
2055 PyObject *weakreflist;
2056} rwpair;
2057
2058static int
2059bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds)
2060{
2061 PyObject *reader, *writer;
2062 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
2063 Py_ssize_t max_buffer_size = -234;
2064
2065 if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer,
2066 &buffer_size, &max_buffer_size)) {
2067 return -1;
2068 }
2069
2070 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2071 return -1;
2072
2073 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
2074 return -1;
2075 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
2076 return -1;
2077
2078 self->reader = (buffered *) PyObject_CallFunction(
2079 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
2080 if (self->reader == NULL)
2081 return -1;
2082
2083 self->writer = (buffered *) PyObject_CallFunction(
2084 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
2085 if (self->writer == NULL) {
2086 Py_CLEAR(self->reader);
2087 return -1;
2088 }
2089
2090 return 0;
2091}
2092
2093static int
2094bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
2095{
2096 Py_VISIT(self->dict);
2097 return 0;
2098}
2099
2100static int
2101bufferedrwpair_clear(rwpair *self)
2102{
2103 Py_CLEAR(self->reader);
2104 Py_CLEAR(self->writer);
2105 Py_CLEAR(self->dict);
2106 return 0;
2107}
2108
2109static void
2110bufferedrwpair_dealloc(rwpair *self)
2111{
2112 _PyObject_GC_UNTRACK(self);
Benjamin Peterson1c873bf2014-09-29 22:46:57 -04002113 if (self->weakreflist != NULL)
2114 PyObject_ClearWeakRefs((PyObject *)self);
Antoine Pitrou19690592009-06-12 20:14:08 +00002115 Py_CLEAR(self->reader);
2116 Py_CLEAR(self->writer);
2117 Py_CLEAR(self->dict);
2118 Py_TYPE(self)->tp_free((PyObject *) self);
2119}
2120
2121static PyObject *
2122_forward_call(buffered *self, const char *name, PyObject *args)
2123{
Serhiy Storchaka1d19f972014-02-12 10:52:07 +02002124 PyObject *func, *ret;
2125 if (self == NULL) {
2126 PyErr_SetString(PyExc_ValueError,
2127 "I/O operation on uninitialized object");
2128 return NULL;
2129 }
Antoine Pitrou19690592009-06-12 20:14:08 +00002130
Serhiy Storchaka1d19f972014-02-12 10:52:07 +02002131 func = PyObject_GetAttrString((PyObject *)self, name);
Antoine Pitrou19690592009-06-12 20:14:08 +00002132 if (func == NULL) {
2133 PyErr_SetString(PyExc_AttributeError, name);
2134 return NULL;
2135 }
2136
2137 ret = PyObject_CallObject(func, args);
2138 Py_DECREF(func);
2139 return ret;
2140}
2141
2142static PyObject *
2143bufferedrwpair_read(rwpair *self, PyObject *args)
2144{
2145 return _forward_call(self->reader, "read", args);
2146}
2147
2148static PyObject *
2149bufferedrwpair_peek(rwpair *self, PyObject *args)
2150{
2151 return _forward_call(self->reader, "peek", args);
2152}
2153
2154static PyObject *
2155bufferedrwpair_read1(rwpair *self, PyObject *args)
2156{
2157 return _forward_call(self->reader, "read1", args);
2158}
2159
2160static PyObject *
2161bufferedrwpair_readinto(rwpair *self, PyObject *args)
2162{
2163 return _forward_call(self->reader, "readinto", args);
2164}
2165
2166static PyObject *
2167bufferedrwpair_write(rwpair *self, PyObject *args)
2168{
2169 return _forward_call(self->writer, "write", args);
2170}
2171
2172static PyObject *
2173bufferedrwpair_flush(rwpair *self, PyObject *args)
2174{
2175 return _forward_call(self->writer, "flush", args);
2176}
2177
2178static PyObject *
2179bufferedrwpair_readable(rwpair *self, PyObject *args)
2180{
2181 return _forward_call(self->reader, "readable", args);
2182}
2183
2184static PyObject *
2185bufferedrwpair_writable(rwpair *self, PyObject *args)
2186{
2187 return _forward_call(self->writer, "writable", args);
2188}
2189
2190static PyObject *
2191bufferedrwpair_close(rwpair *self, PyObject *args)
2192{
Serhiy Storchakaf95a57f2015-03-24 23:23:42 +02002193 PyObject *exc = NULL, *val, *tb;
Antoine Pitrou19690592009-06-12 20:14:08 +00002194 PyObject *ret = _forward_call(self->writer, "close", args);
2195 if (ret == NULL)
Serhiy Storchakaf95a57f2015-03-24 23:23:42 +02002196 PyErr_Fetch(&exc, &val, &tb);
2197 else
2198 Py_DECREF(ret);
2199 ret = _forward_call(self->reader, "close", args);
2200 if (exc != NULL) {
2201 if (ret != NULL) {
2202 Py_CLEAR(ret);
2203 PyErr_Restore(exc, val, tb);
2204 }
2205 else {
2206 Py_DECREF(exc);
2207 Py_XDECREF(val);
2208 Py_XDECREF(tb);
2209 }
2210 }
2211 return ret;
Antoine Pitrou19690592009-06-12 20:14:08 +00002212}
2213
2214static PyObject *
2215bufferedrwpair_isatty(rwpair *self, PyObject *args)
2216{
2217 PyObject *ret = _forward_call(self->writer, "isatty", args);
2218
2219 if (ret != Py_False) {
2220 /* either True or exception */
2221 return ret;
2222 }
2223 Py_DECREF(ret);
2224
2225 return _forward_call(self->reader, "isatty", args);
2226}
2227
2228static PyObject *
2229bufferedrwpair_closed_get(rwpair *self, void *context)
2230{
Charles-François Natali9ffcbf72011-10-06 19:09:45 +02002231 if (self->writer == NULL) {
2232 PyErr_SetString(PyExc_RuntimeError,
2233 "the BufferedRWPair object is being garbage-collected");
2234 return NULL;
2235 }
Antoine Pitrou19690592009-06-12 20:14:08 +00002236 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2237}
2238
2239static PyMethodDef bufferedrwpair_methods[] = {
2240 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2241 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2242 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2243 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
2244
2245 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2246 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
2247
2248 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2249 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
2250
2251 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2252 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
2253
2254 {NULL, NULL}
2255};
2256
2257static PyGetSetDef bufferedrwpair_getset[] = {
2258 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
2259 {NULL}
2260};
2261
2262PyTypeObject PyBufferedRWPair_Type = {
2263 PyVarObject_HEAD_INIT(NULL, 0)
2264 "_io.BufferedRWPair", /*tp_name*/
2265 sizeof(rwpair), /*tp_basicsize*/
2266 0, /*tp_itemsize*/
2267 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
2268 0, /*tp_print*/
2269 0, /*tp_getattr*/
2270 0, /*tp_setattr*/
2271 0, /*tp_compare */
2272 0, /*tp_repr*/
2273 0, /*tp_as_number*/
2274 0, /*tp_as_sequence*/
2275 0, /*tp_as_mapping*/
2276 0, /*tp_hash */
2277 0, /*tp_call*/
2278 0, /*tp_str*/
2279 0, /*tp_getattro*/
2280 0, /*tp_setattro*/
2281 0, /*tp_as_buffer*/
2282 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2283 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
2284 bufferedrwpair_doc, /* tp_doc */
2285 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2286 (inquiry)bufferedrwpair_clear, /* tp_clear */
2287 0, /* tp_richcompare */
2288 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
2289 0, /* tp_iter */
2290 0, /* tp_iternext */
2291 bufferedrwpair_methods, /* tp_methods */
2292 0, /* tp_members */
2293 bufferedrwpair_getset, /* tp_getset */
2294 0, /* tp_base */
2295 0, /* tp_dict */
2296 0, /* tp_descr_get */
2297 0, /* tp_descr_set */
2298 offsetof(rwpair, dict), /* tp_dictoffset */
2299 (initproc)bufferedrwpair_init, /* tp_init */
2300 0, /* tp_alloc */
2301 PyType_GenericNew, /* tp_new */
2302};
2303
2304
2305
2306/*
2307 * BufferedRandom
2308 */
2309
2310PyDoc_STRVAR(bufferedrandom_doc,
2311 "A buffered interface to random access streams.\n"
2312 "\n"
2313 "The constructor creates a reader and writer for a seekable stream,\n"
2314 "raw, given in the first argument. If the buffer_size is omitted it\n"
2315 "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n"
2316 );
2317
2318static int
2319bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds)
2320{
2321 char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL};
2322 Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
2323 Py_ssize_t max_buffer_size = -234;
2324 PyObject *raw;
2325
2326 self->ok = 0;
2327 self->detached = 0;
2328
R David Murray5b2cf5e2013-02-23 22:11:21 -05002329 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedRandom", kwlist,
Antoine Pitrou19690592009-06-12 20:14:08 +00002330 &raw, &buffer_size, &max_buffer_size)) {
2331 return -1;
2332 }
2333
2334 if (max_buffer_size != -234 && !complain_about_max_buffer_size())
2335 return -1;
2336
2337 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
2338 return -1;
2339 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
2340 return -1;
2341 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
2342 return -1;
2343
Antoine Pitrou19690592009-06-12 20:14:08 +00002344 Py_INCREF(raw);
Serhiy Storchaka8688aca2015-12-27 12:38:48 +02002345 Py_SETREF(self->raw, raw);
Antoine Pitrou19690592009-06-12 20:14:08 +00002346 self->buffer_size = buffer_size;
2347 self->readable = 1;
2348 self->writable = 1;
2349
2350 if (_buffered_init(self) < 0)
2351 return -1;
2352 _bufferedreader_reset_buf(self);
2353 _bufferedwriter_reset_buf(self);
2354 self->pos = 0;
2355
2356 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2357 Py_TYPE(raw) == &PyFileIO_Type);
2358
2359 self->ok = 1;
2360 return 0;
2361}
2362
2363static PyMethodDef bufferedrandom_methods[] = {
2364 /* BufferedIOMixin methods */
2365 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2366 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2367 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2368 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2369 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2370 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2371 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2372
2373 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2374
2375 {"seek", (PyCFunction)buffered_seek, METH_VARARGS},
2376 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2377 {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
2378 {"read", (PyCFunction)buffered_read, METH_VARARGS},
2379 {"read1", (PyCFunction)buffered_read1, METH_VARARGS},
2380 {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS},
2381 {"readline", (PyCFunction)buffered_readline, METH_VARARGS},
2382 {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
2383 {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
Antoine Pitroubff5df02012-07-29 19:02:46 +02002384 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
Antoine Pitrou19690592009-06-12 20:14:08 +00002385 {NULL, NULL}
2386};
2387
2388static PyMemberDef bufferedrandom_members[] = {
Antoine Pitroufc9ead62010-12-21 21:26:55 +00002389 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
Antoine Pitrou19690592009-06-12 20:14:08 +00002390 {NULL}
2391};
2392
2393static PyGetSetDef bufferedrandom_getset[] = {
2394 {"closed", (getter)buffered_closed_get, NULL, NULL},
2395 {"name", (getter)buffered_name_get, NULL, NULL},
2396 {"mode", (getter)buffered_mode_get, NULL, NULL},
2397 {NULL}
2398};
2399
2400
2401PyTypeObject PyBufferedRandom_Type = {
2402 PyVarObject_HEAD_INIT(NULL, 0)
2403 "_io.BufferedRandom", /*tp_name*/
2404 sizeof(buffered), /*tp_basicsize*/
2405 0, /*tp_itemsize*/
2406 (destructor)buffered_dealloc, /*tp_dealloc*/
2407 0, /*tp_print*/
2408 0, /*tp_getattr*/
2409 0, /*tp_setattr*/
2410 0, /*tp_compare */
2411 (reprfunc)buffered_repr, /*tp_repr*/
2412 0, /*tp_as_number*/
2413 0, /*tp_as_sequence*/
2414 0, /*tp_as_mapping*/
2415 0, /*tp_hash */
2416 0, /*tp_call*/
2417 0, /*tp_str*/
2418 0, /*tp_getattro*/
2419 0, /*tp_setattro*/
2420 0, /*tp_as_buffer*/
2421 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2422 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2423 bufferedrandom_doc, /* tp_doc */
2424 (traverseproc)buffered_traverse, /* tp_traverse */
2425 (inquiry)buffered_clear, /* tp_clear */
2426 0, /* tp_richcompare */
2427 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2428 0, /* tp_iter */
2429 (iternextfunc)buffered_iternext, /* tp_iternext */
2430 bufferedrandom_methods, /* tp_methods */
2431 bufferedrandom_members, /* tp_members */
2432 bufferedrandom_getset, /* tp_getset */
2433 0, /* tp_base */
2434 0, /*tp_dict*/
2435 0, /* tp_descr_get */
2436 0, /* tp_descr_set */
2437 offsetof(buffered, dict), /*tp_dictoffset*/
2438 (initproc)bufferedrandom_init, /* tp_init */
2439 0, /* tp_alloc */
2440 PyType_GenericNew, /* tp_new */
2441};
2442