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