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