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 "pycore_object.h"
13 #include "pycore_pystate.h"
14 #include "structmember.h"
15 #include "pythread.h"
16 #include "_iomodule.h"
17
18 /*[clinic input]
19 module _io
20 class _io._BufferedIOBase "PyObject *" "&PyBufferedIOBase_Type"
21 class _io._Buffered "buffered *" "&PyBufferedIOBase_Type"
22 class _io.BufferedReader "buffered *" "&PyBufferedReader_Type"
23 class _io.BufferedWriter "buffered *" "&PyBufferedWriter_Type"
24 class _io.BufferedRWPair "rwpair *" "&PyBufferedRWPair_Type"
25 class _io.BufferedRandom "buffered *" "&PyBufferedRandom_Type"
26 [clinic start generated code]*/
27 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=59460b9c5639984d]*/
28
29 _Py_IDENTIFIER(close);
30 _Py_IDENTIFIER(_dealloc_warn);
31 _Py_IDENTIFIER(flush);
32 _Py_IDENTIFIER(isatty);
33 _Py_IDENTIFIER(mode);
34 _Py_IDENTIFIER(name);
35 _Py_IDENTIFIER(peek);
36 _Py_IDENTIFIER(read);
37 _Py_IDENTIFIER(read1);
38 _Py_IDENTIFIER(readable);
39 _Py_IDENTIFIER(readinto);
40 _Py_IDENTIFIER(readinto1);
41 _Py_IDENTIFIER(writable);
42 _Py_IDENTIFIER(write);
43
44 /*
45 * BufferedIOBase class, inherits from IOBase.
46 */
47 PyDoc_STRVAR(bufferediobase_doc,
48 "Base class for buffered IO objects.\n"
49 "\n"
50 "The main difference with RawIOBase is that the read() method\n"
51 "supports omitting the size argument, and does not have a default\n"
52 "implementation that defers to readinto().\n"
53 "\n"
54 "In addition, read(), readinto() and write() may raise\n"
55 "BlockingIOError if the underlying raw stream is in non-blocking\n"
56 "mode and not ready; unlike their raw counterparts, they will never\n"
57 "return None.\n"
58 "\n"
59 "A typical implementation should not inherit from a RawIOBase\n"
60 "implementation, but wrap one.\n"
61 );
62
63 static PyObject *
_bufferediobase_readinto_generic(PyObject * self,Py_buffer * buffer,char readinto1)64 _bufferediobase_readinto_generic(PyObject *self, Py_buffer *buffer, char readinto1)
65 {
66 Py_ssize_t len;
67 PyObject *data;
68
69 data = _PyObject_CallMethodId(self,
70 readinto1 ? &PyId_read1 : &PyId_read,
71 "n", buffer->len);
72 if (data == NULL)
73 return NULL;
74
75 if (!PyBytes_Check(data)) {
76 Py_DECREF(data);
77 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
78 return NULL;
79 }
80
81 len = PyBytes_GET_SIZE(data);
82 if (len > buffer->len) {
83 PyErr_Format(PyExc_ValueError,
84 "read() returned too much data: "
85 "%zd bytes requested, %zd returned",
86 buffer->len, len);
87 Py_DECREF(data);
88 return NULL;
89 }
90 memcpy(buffer->buf, PyBytes_AS_STRING(data), len);
91
92 Py_DECREF(data);
93
94 return PyLong_FromSsize_t(len);
95 }
96
97 /*[clinic input]
98 _io._BufferedIOBase.readinto
99 buffer: Py_buffer(accept={rwbuffer})
100 /
101 [clinic start generated code]*/
102
103 static PyObject *
_io__BufferedIOBase_readinto_impl(PyObject * self,Py_buffer * buffer)104 _io__BufferedIOBase_readinto_impl(PyObject *self, Py_buffer *buffer)
105 /*[clinic end generated code: output=8c8cda6684af8038 input=00a6b9a38f29830a]*/
106 {
107 return _bufferediobase_readinto_generic(self, buffer, 0);
108 }
109
110 /*[clinic input]
111 _io._BufferedIOBase.readinto1
112 buffer: Py_buffer(accept={rwbuffer})
113 /
114 [clinic start generated code]*/
115
116 static PyObject *
_io__BufferedIOBase_readinto1_impl(PyObject * self,Py_buffer * buffer)117 _io__BufferedIOBase_readinto1_impl(PyObject *self, Py_buffer *buffer)
118 /*[clinic end generated code: output=358623e4fd2b69d3 input=ebad75b4aadfb9be]*/
119 {
120 return _bufferediobase_readinto_generic(self, buffer, 1);
121 }
122
123 static PyObject *
bufferediobase_unsupported(const char * message)124 bufferediobase_unsupported(const char *message)
125 {
126 _PyIO_State *state = IO_STATE();
127 if (state != NULL)
128 PyErr_SetString(state->unsupported_operation, message);
129 return NULL;
130 }
131
132 /*[clinic input]
133 _io._BufferedIOBase.detach
134
135 Disconnect this buffer from its underlying raw stream and return it.
136
137 After the raw stream has been detached, the buffer is in an unusable
138 state.
139 [clinic start generated code]*/
140
141 static PyObject *
_io__BufferedIOBase_detach_impl(PyObject * self)142 _io__BufferedIOBase_detach_impl(PyObject *self)
143 /*[clinic end generated code: output=754977c8d10ed88c input=822427fb58fe4169]*/
144 {
145 return bufferediobase_unsupported("detach");
146 }
147
148 PyDoc_STRVAR(bufferediobase_read_doc,
149 "Read and return up to n bytes.\n"
150 "\n"
151 "If the argument is omitted, None, or negative, reads and\n"
152 "returns all data until EOF.\n"
153 "\n"
154 "If the argument is positive, and the underlying raw stream is\n"
155 "not 'interactive', multiple raw reads may be issued to satisfy\n"
156 "the byte count (unless EOF is reached first). But for\n"
157 "interactive raw streams (as well as sockets and pipes), at most\n"
158 "one raw read will be issued, and a short result does not imply\n"
159 "that EOF is imminent.\n"
160 "\n"
161 "Returns an empty bytes object on EOF.\n"
162 "\n"
163 "Returns None if the underlying raw stream was open in non-blocking\n"
164 "mode and no data is available at the moment.\n");
165
166 static PyObject *
bufferediobase_read(PyObject * self,PyObject * args)167 bufferediobase_read(PyObject *self, PyObject *args)
168 {
169 return bufferediobase_unsupported("read");
170 }
171
172 PyDoc_STRVAR(bufferediobase_read1_doc,
173 "Read and return up to n bytes, with at most one read() call\n"
174 "to the underlying raw stream. A short result does not imply\n"
175 "that EOF is imminent.\n"
176 "\n"
177 "Returns an empty bytes object on EOF.\n");
178
179 static PyObject *
bufferediobase_read1(PyObject * self,PyObject * args)180 bufferediobase_read1(PyObject *self, PyObject *args)
181 {
182 return bufferediobase_unsupported("read1");
183 }
184
185 PyDoc_STRVAR(bufferediobase_write_doc,
186 "Write the given buffer to the IO stream.\n"
187 "\n"
188 "Returns the number of bytes written, which is always the length of b\n"
189 "in bytes.\n"
190 "\n"
191 "Raises BlockingIOError if the buffer is full and the\n"
192 "underlying raw stream cannot accept more data at the moment.\n");
193
194 static PyObject *
bufferediobase_write(PyObject * self,PyObject * args)195 bufferediobase_write(PyObject *self, PyObject *args)
196 {
197 return bufferediobase_unsupported("write");
198 }
199
200
201 typedef struct {
202 PyObject_HEAD
203
204 PyObject *raw;
205 int ok; /* Initialized? */
206 int detached;
207 int readable;
208 int writable;
209 char finalizing;
210
211 /* True if this is a vanilla Buffered object (rather than a user derived
212 class) *and* the raw stream is a vanilla FileIO object. */
213 int fast_closed_checks;
214
215 /* Absolute position inside the raw stream (-1 if unknown). */
216 Py_off_t abs_pos;
217
218 /* A static buffer of size `buffer_size` */
219 char *buffer;
220 /* Current logical position in the buffer. */
221 Py_off_t pos;
222 /* Position of the raw stream in the buffer. */
223 Py_off_t raw_pos;
224
225 /* Just after the last buffered byte in the buffer, or -1 if the buffer
226 isn't ready for reading. */
227 Py_off_t read_end;
228
229 /* Just after the last byte actually written */
230 Py_off_t write_pos;
231 /* Just after the last byte waiting to be written, or -1 if the buffer
232 isn't ready for writing. */
233 Py_off_t write_end;
234
235 PyThread_type_lock lock;
236 volatile unsigned long owner;
237
238 Py_ssize_t buffer_size;
239 Py_ssize_t buffer_mask;
240
241 PyObject *dict;
242 PyObject *weakreflist;
243 } buffered;
244
245 /*
246 Implementation notes:
247
248 * BufferedReader, BufferedWriter and BufferedRandom try to share most
249 methods (this is helped by the members `readable` and `writable`, which
250 are initialized in the respective constructors)
251 * They also share a single buffer for reading and writing. This enables
252 interleaved reads and writes without flushing. It also makes the logic
253 a bit trickier to get right.
254 * The absolute position of the raw stream is cached, if possible, in the
255 `abs_pos` member. It must be updated every time an operation is done
256 on the raw stream. If not sure, it can be reinitialized by calling
257 _buffered_raw_tell(), which queries the raw stream (_buffered_raw_seek()
258 also does it). To read it, use RAW_TELL().
259 * Three helpers, _bufferedreader_raw_read, _bufferedwriter_raw_write and
260 _bufferedwriter_flush_unlocked do a lot of useful housekeeping.
261
262 NOTE: we should try to maintain block alignment of reads and writes to the
263 raw stream (according to the buffer size), but for now it is only done
264 in read() and friends.
265
266 */
267
268 /* These macros protect the buffered object against concurrent operations. */
269
270 static int
_enter_buffered_busy(buffered * self)271 _enter_buffered_busy(buffered *self)
272 {
273 int relax_locking;
274 PyLockStatus st;
275 if (self->owner == PyThread_get_thread_ident()) {
276 PyErr_Format(PyExc_RuntimeError,
277 "reentrant call inside %R", self);
278 return 0;
279 }
280 relax_locking = _Py_IsFinalizing();
281 Py_BEGIN_ALLOW_THREADS
282 if (!relax_locking)
283 st = PyThread_acquire_lock(self->lock, 1);
284 else {
285 /* When finalizing, we don't want a deadlock to happen with daemon
286 * threads abruptly shut down while they owned the lock.
287 * Therefore, only wait for a grace period (1 s.).
288 * Note that non-daemon threads have already exited here, so this
289 * shouldn't affect carefully written threaded I/O code.
290 */
291 st = PyThread_acquire_lock_timed(self->lock, (PY_TIMEOUT_T)1e6, 0);
292 }
293 Py_END_ALLOW_THREADS
294 if (relax_locking && st != PY_LOCK_ACQUIRED) {
295 PyObject *msgobj = PyUnicode_FromFormat(
296 "could not acquire lock for %A at interpreter "
297 "shutdown, possibly due to daemon threads",
298 (PyObject *) self);
299 const char *msg = PyUnicode_AsUTF8(msgobj);
300 Py_FatalError(msg);
301 }
302 return 1;
303 }
304
305 #define ENTER_BUFFERED(self) \
306 ( (PyThread_acquire_lock(self->lock, 0) ? \
307 1 : _enter_buffered_busy(self)) \
308 && (self->owner = PyThread_get_thread_ident(), 1) )
309
310 #define LEAVE_BUFFERED(self) \
311 do { \
312 self->owner = 0; \
313 PyThread_release_lock(self->lock); \
314 } while(0);
315
316 #define CHECK_INITIALIZED(self) \
317 if (self->ok <= 0) { \
318 if (self->detached) { \
319 PyErr_SetString(PyExc_ValueError, \
320 "raw stream has been detached"); \
321 } else { \
322 PyErr_SetString(PyExc_ValueError, \
323 "I/O operation on uninitialized object"); \
324 } \
325 return NULL; \
326 }
327
328 #define CHECK_INITIALIZED_INT(self) \
329 if (self->ok <= 0) { \
330 if (self->detached) { \
331 PyErr_SetString(PyExc_ValueError, \
332 "raw stream has been detached"); \
333 } else { \
334 PyErr_SetString(PyExc_ValueError, \
335 "I/O operation on uninitialized object"); \
336 } \
337 return -1; \
338 }
339
340 #define IS_CLOSED(self) \
341 (!self->buffer || \
342 (self->fast_closed_checks \
343 ? _PyFileIO_closed(self->raw) \
344 : buffered_closed(self)))
345
346 #define CHECK_CLOSED(self, error_msg) \
347 if (IS_CLOSED(self)) { \
348 PyErr_SetString(PyExc_ValueError, error_msg); \
349 return NULL; \
350 }
351
352
353 #define VALID_READ_BUFFER(self) \
354 (self->readable && self->read_end != -1)
355
356 #define VALID_WRITE_BUFFER(self) \
357 (self->writable && self->write_end != -1)
358
359 #define ADJUST_POSITION(self, _new_pos) \
360 do { \
361 self->pos = _new_pos; \
362 if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
363 self->read_end = self->pos; \
364 } while(0)
365
366 #define READAHEAD(self) \
367 ((self->readable && VALID_READ_BUFFER(self)) \
368 ? (self->read_end - self->pos) : 0)
369
370 #define RAW_OFFSET(self) \
371 (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
372 && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
373
374 #define RAW_TELL(self) \
375 (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
376
377 #define MINUS_LAST_BLOCK(self, size) \
378 (self->buffer_mask ? \
379 (size & ~self->buffer_mask) : \
380 (self->buffer_size * (size / self->buffer_size)))
381
382
383 static void
buffered_dealloc(buffered * self)384 buffered_dealloc(buffered *self)
385 {
386 self->finalizing = 1;
387 if (_PyIOBase_finalize((PyObject *) self) < 0)
388 return;
389 _PyObject_GC_UNTRACK(self);
390 self->ok = 0;
391 if (self->weakreflist != NULL)
392 PyObject_ClearWeakRefs((PyObject *)self);
393 Py_CLEAR(self->raw);
394 if (self->buffer) {
395 PyMem_Free(self->buffer);
396 self->buffer = NULL;
397 }
398 if (self->lock) {
399 PyThread_free_lock(self->lock);
400 self->lock = NULL;
401 }
402 Py_CLEAR(self->dict);
403 Py_TYPE(self)->tp_free((PyObject *)self);
404 }
405
406 static PyObject *
buffered_sizeof(buffered * self,PyObject * Py_UNUSED (ignored))407 buffered_sizeof(buffered *self, PyObject *Py_UNUSED(ignored))
408 {
409 Py_ssize_t res;
410
411 res = _PyObject_SIZE(Py_TYPE(self));
412 if (self->buffer)
413 res += self->buffer_size;
414 return PyLong_FromSsize_t(res);
415 }
416
417 static int
buffered_traverse(buffered * self,visitproc visit,void * arg)418 buffered_traverse(buffered *self, visitproc visit, void *arg)
419 {
420 Py_VISIT(self->raw);
421 Py_VISIT(self->dict);
422 return 0;
423 }
424
425 static int
buffered_clear(buffered * self)426 buffered_clear(buffered *self)
427 {
428 self->ok = 0;
429 Py_CLEAR(self->raw);
430 Py_CLEAR(self->dict);
431 return 0;
432 }
433
434 /* Because this can call arbitrary code, it shouldn't be called when
435 the refcount is 0 (that is, not directly from tp_dealloc unless
436 the refcount has been temporarily re-incremented). */
437 static PyObject *
buffered_dealloc_warn(buffered * self,PyObject * source)438 buffered_dealloc_warn(buffered *self, PyObject *source)
439 {
440 if (self->ok && self->raw) {
441 PyObject *r;
442 r = _PyObject_CallMethodIdObjArgs(self->raw, &PyId__dealloc_warn,
443 source, NULL);
444 if (r)
445 Py_DECREF(r);
446 else
447 PyErr_Clear();
448 }
449 Py_RETURN_NONE;
450 }
451
452 /*
453 * _BufferedIOMixin methods
454 * This is not a class, just a collection of methods that will be reused
455 * by BufferedReader and BufferedWriter
456 */
457
458 /* Flush and close */
459
460 static PyObject *
buffered_simple_flush(buffered * self,PyObject * args)461 buffered_simple_flush(buffered *self, PyObject *args)
462 {
463 CHECK_INITIALIZED(self)
464 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
465 }
466
467 static int
buffered_closed(buffered * self)468 buffered_closed(buffered *self)
469 {
470 int closed;
471 PyObject *res;
472 CHECK_INITIALIZED_INT(self)
473 res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
474 if (res == NULL)
475 return -1;
476 closed = PyObject_IsTrue(res);
477 Py_DECREF(res);
478 return closed;
479 }
480
481 static PyObject *
buffered_closed_get(buffered * self,void * context)482 buffered_closed_get(buffered *self, void *context)
483 {
484 CHECK_INITIALIZED(self)
485 return PyObject_GetAttr(self->raw, _PyIO_str_closed);
486 }
487
488 static PyObject *
buffered_close(buffered * self,PyObject * args)489 buffered_close(buffered *self, PyObject *args)
490 {
491 PyObject *res = NULL, *exc = NULL, *val, *tb;
492 int r;
493
494 CHECK_INITIALIZED(self)
495 if (!ENTER_BUFFERED(self))
496 return NULL;
497
498 r = buffered_closed(self);
499 if (r < 0)
500 goto end;
501 if (r > 0) {
502 res = Py_None;
503 Py_INCREF(res);
504 goto end;
505 }
506
507 if (self->finalizing) {
508 PyObject *r = buffered_dealloc_warn(self, (PyObject *) self);
509 if (r)
510 Py_DECREF(r);
511 else
512 PyErr_Clear();
513 }
514 /* flush() will most probably re-take the lock, so drop it first */
515 LEAVE_BUFFERED(self)
516 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
517 if (!ENTER_BUFFERED(self))
518 return NULL;
519 if (res == NULL)
520 PyErr_Fetch(&exc, &val, &tb);
521 else
522 Py_DECREF(res);
523
524 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
525
526 if (self->buffer) {
527 PyMem_Free(self->buffer);
528 self->buffer = NULL;
529 }
530
531 if (exc != NULL) {
532 _PyErr_ChainExceptions(exc, val, tb);
533 Py_CLEAR(res);
534 }
535
536 end:
537 LEAVE_BUFFERED(self)
538 return res;
539 }
540
541 /* detach */
542
543 static PyObject *
buffered_detach(buffered * self,PyObject * Py_UNUSED (ignored))544 buffered_detach(buffered *self, PyObject *Py_UNUSED(ignored))
545 {
546 PyObject *raw, *res;
547 CHECK_INITIALIZED(self)
548 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
549 if (res == NULL)
550 return NULL;
551 Py_DECREF(res);
552 raw = self->raw;
553 self->raw = NULL;
554 self->detached = 1;
555 self->ok = 0;
556 return raw;
557 }
558
559 /* Inquiries */
560
561 static PyObject *
buffered_seekable(buffered * self,PyObject * Py_UNUSED (ignored))562 buffered_seekable(buffered *self, PyObject *Py_UNUSED(ignored))
563 {
564 CHECK_INITIALIZED(self)
565 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
566 }
567
568 static PyObject *
buffered_readable(buffered * self,PyObject * Py_UNUSED (ignored))569 buffered_readable(buffered *self, PyObject *Py_UNUSED(ignored))
570 {
571 CHECK_INITIALIZED(self)
572 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
573 }
574
575 static PyObject *
buffered_writable(buffered * self,PyObject * Py_UNUSED (ignored))576 buffered_writable(buffered *self, PyObject *Py_UNUSED(ignored))
577 {
578 CHECK_INITIALIZED(self)
579 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
580 }
581
582 static PyObject *
buffered_name_get(buffered * self,void * context)583 buffered_name_get(buffered *self, void *context)
584 {
585 CHECK_INITIALIZED(self)
586 return _PyObject_GetAttrId(self->raw, &PyId_name);
587 }
588
589 static PyObject *
buffered_mode_get(buffered * self,void * context)590 buffered_mode_get(buffered *self, void *context)
591 {
592 CHECK_INITIALIZED(self)
593 return _PyObject_GetAttrId(self->raw, &PyId_mode);
594 }
595
596 /* Lower-level APIs */
597
598 static PyObject *
buffered_fileno(buffered * self,PyObject * Py_UNUSED (ignored))599 buffered_fileno(buffered *self, PyObject *Py_UNUSED(ignored))
600 {
601 CHECK_INITIALIZED(self)
602 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
603 }
604
605 static PyObject *
buffered_isatty(buffered * self,PyObject * Py_UNUSED (ignored))606 buffered_isatty(buffered *self, PyObject *Py_UNUSED(ignored))
607 {
608 CHECK_INITIALIZED(self)
609 return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
610 }
611
612 /* Forward decls */
613 static PyObject *
614 _bufferedwriter_flush_unlocked(buffered *);
615 static Py_ssize_t
616 _bufferedreader_fill_buffer(buffered *self);
617 static void
618 _bufferedreader_reset_buf(buffered *self);
619 static void
620 _bufferedwriter_reset_buf(buffered *self);
621 static PyObject *
622 _bufferedreader_peek_unlocked(buffered *self);
623 static PyObject *
624 _bufferedreader_read_all(buffered *self);
625 static PyObject *
626 _bufferedreader_read_fast(buffered *self, Py_ssize_t);
627 static PyObject *
628 _bufferedreader_read_generic(buffered *self, Py_ssize_t);
629 static Py_ssize_t
630 _bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len);
631
632 /*
633 * Helpers
634 */
635
636 /* Sets the current error to BlockingIOError */
637 static void
_set_BlockingIOError(const char * msg,Py_ssize_t written)638 _set_BlockingIOError(const char *msg, Py_ssize_t written)
639 {
640 PyObject *err;
641 PyErr_Clear();
642 err = PyObject_CallFunction(PyExc_BlockingIOError, "isn",
643 errno, msg, written);
644 if (err)
645 PyErr_SetObject(PyExc_BlockingIOError, err);
646 Py_XDECREF(err);
647 }
648
649 /* Returns the address of the `written` member if a BlockingIOError was
650 raised, NULL otherwise. The error is always re-raised. */
651 static Py_ssize_t *
_buffered_check_blocking_error(void)652 _buffered_check_blocking_error(void)
653 {
654 PyObject *t, *v, *tb;
655 PyOSErrorObject *err;
656
657 PyErr_Fetch(&t, &v, &tb);
658 if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
659 PyErr_Restore(t, v, tb);
660 return NULL;
661 }
662 err = (PyOSErrorObject *) v;
663 /* TODO: sanity check (err->written >= 0) */
664 PyErr_Restore(t, v, tb);
665 return &err->written;
666 }
667
668 static Py_off_t
_buffered_raw_tell(buffered * self)669 _buffered_raw_tell(buffered *self)
670 {
671 Py_off_t n;
672 PyObject *res;
673 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
674 if (res == NULL)
675 return -1;
676 n = PyNumber_AsOff_t(res, PyExc_ValueError);
677 Py_DECREF(res);
678 if (n < 0) {
679 if (!PyErr_Occurred())
680 PyErr_Format(PyExc_OSError,
681 "Raw stream returned invalid position %" PY_PRIdOFF,
682 (PY_OFF_T_COMPAT)n);
683 return -1;
684 }
685 self->abs_pos = n;
686 return n;
687 }
688
689 static Py_off_t
_buffered_raw_seek(buffered * self,Py_off_t target,int whence)690 _buffered_raw_seek(buffered *self, Py_off_t target, int whence)
691 {
692 PyObject *res, *posobj, *whenceobj;
693 Py_off_t n;
694
695 posobj = PyLong_FromOff_t(target);
696 if (posobj == NULL)
697 return -1;
698 whenceobj = PyLong_FromLong(whence);
699 if (whenceobj == NULL) {
700 Py_DECREF(posobj);
701 return -1;
702 }
703 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
704 posobj, whenceobj, NULL);
705 Py_DECREF(posobj);
706 Py_DECREF(whenceobj);
707 if (res == NULL)
708 return -1;
709 n = PyNumber_AsOff_t(res, PyExc_ValueError);
710 Py_DECREF(res);
711 if (n < 0) {
712 if (!PyErr_Occurred())
713 PyErr_Format(PyExc_OSError,
714 "Raw stream returned invalid position %" PY_PRIdOFF,
715 (PY_OFF_T_COMPAT)n);
716 return -1;
717 }
718 self->abs_pos = n;
719 return n;
720 }
721
722 static int
_buffered_init(buffered * self)723 _buffered_init(buffered *self)
724 {
725 Py_ssize_t n;
726 if (self->buffer_size <= 0) {
727 PyErr_SetString(PyExc_ValueError,
728 "buffer size must be strictly positive");
729 return -1;
730 }
731 if (self->buffer)
732 PyMem_Free(self->buffer);
733 self->buffer = PyMem_Malloc(self->buffer_size);
734 if (self->buffer == NULL) {
735 PyErr_NoMemory();
736 return -1;
737 }
738 if (self->lock)
739 PyThread_free_lock(self->lock);
740 self->lock = PyThread_allocate_lock();
741 if (self->lock == NULL) {
742 PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
743 return -1;
744 }
745 self->owner = 0;
746 /* Find out whether buffer_size is a power of 2 */
747 /* XXX is this optimization useful? */
748 for (n = self->buffer_size - 1; n & 1; n >>= 1)
749 ;
750 if (n == 0)
751 self->buffer_mask = self->buffer_size - 1;
752 else
753 self->buffer_mask = 0;
754 if (_buffered_raw_tell(self) == -1)
755 PyErr_Clear();
756 return 0;
757 }
758
759 /* Return 1 if an OSError with errno == EINTR is set (and then
760 clears the error indicator), 0 otherwise.
761 Should only be called when PyErr_Occurred() is true.
762 */
763 int
_PyIO_trap_eintr(void)764 _PyIO_trap_eintr(void)
765 {
766 static PyObject *eintr_int = NULL;
767 PyObject *typ, *val, *tb;
768 PyOSErrorObject *env_err;
769
770 if (eintr_int == NULL) {
771 eintr_int = PyLong_FromLong(EINTR);
772 assert(eintr_int != NULL);
773 }
774 if (!PyErr_ExceptionMatches(PyExc_OSError))
775 return 0;
776 PyErr_Fetch(&typ, &val, &tb);
777 PyErr_NormalizeException(&typ, &val, &tb);
778 env_err = (PyOSErrorObject *) val;
779 assert(env_err != NULL);
780 if (env_err->myerrno != NULL &&
781 PyObject_RichCompareBool(env_err->myerrno, eintr_int, Py_EQ) > 0) {
782 Py_DECREF(typ);
783 Py_DECREF(val);
784 Py_XDECREF(tb);
785 return 1;
786 }
787 /* This silences any error set by PyObject_RichCompareBool() */
788 PyErr_Restore(typ, val, tb);
789 return 0;
790 }
791
792 /*
793 * Shared methods and wrappers
794 */
795
796 static PyObject *
buffered_flush_and_rewind_unlocked(buffered * self)797 buffered_flush_and_rewind_unlocked(buffered *self)
798 {
799 PyObject *res;
800
801 res = _bufferedwriter_flush_unlocked(self);
802 if (res == NULL)
803 return NULL;
804 Py_DECREF(res);
805
806 if (self->readable) {
807 /* Rewind the raw stream so that its position corresponds to
808 the current logical position. */
809 Py_off_t n;
810 n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
811 _bufferedreader_reset_buf(self);
812 if (n == -1)
813 return NULL;
814 }
815 Py_RETURN_NONE;
816 }
817
818 static PyObject *
buffered_flush(buffered * self,PyObject * args)819 buffered_flush(buffered *self, PyObject *args)
820 {
821 PyObject *res;
822
823 CHECK_INITIALIZED(self)
824 CHECK_CLOSED(self, "flush of closed file")
825
826 if (!ENTER_BUFFERED(self))
827 return NULL;
828 res = buffered_flush_and_rewind_unlocked(self);
829 LEAVE_BUFFERED(self)
830
831 return res;
832 }
833
834 /*[clinic input]
835 _io._Buffered.peek
836 size: Py_ssize_t = 0
837 /
838
839 [clinic start generated code]*/
840
841 static PyObject *
_io__Buffered_peek_impl(buffered * self,Py_ssize_t size)842 _io__Buffered_peek_impl(buffered *self, Py_ssize_t size)
843 /*[clinic end generated code: output=ba7a097ca230102b input=37ffb97d06ff4adb]*/
844 {
845 PyObject *res = NULL;
846
847 CHECK_INITIALIZED(self)
848 CHECK_CLOSED(self, "peek of closed file")
849
850 if (!ENTER_BUFFERED(self))
851 return NULL;
852
853 if (self->writable) {
854 res = buffered_flush_and_rewind_unlocked(self);
855 if (res == NULL)
856 goto end;
857 Py_CLEAR(res);
858 }
859 res = _bufferedreader_peek_unlocked(self);
860
861 end:
862 LEAVE_BUFFERED(self)
863 return res;
864 }
865
866 /*[clinic input]
867 _io._Buffered.read
868 size as n: Py_ssize_t(accept={int, NoneType}) = -1
869 /
870 [clinic start generated code]*/
871
872 static PyObject *
_io__Buffered_read_impl(buffered * self,Py_ssize_t n)873 _io__Buffered_read_impl(buffered *self, Py_ssize_t n)
874 /*[clinic end generated code: output=f41c78bb15b9bbe9 input=7df81e82e08a68a2]*/
875 {
876 PyObject *res;
877
878 CHECK_INITIALIZED(self)
879 if (n < -1) {
880 PyErr_SetString(PyExc_ValueError,
881 "read length must be non-negative or -1");
882 return NULL;
883 }
884
885 CHECK_CLOSED(self, "read of closed file")
886
887 if (n == -1) {
888 /* The number of bytes is unspecified, read until the end of stream */
889 if (!ENTER_BUFFERED(self))
890 return NULL;
891 res = _bufferedreader_read_all(self);
892 }
893 else {
894 res = _bufferedreader_read_fast(self, n);
895 if (res != Py_None)
896 return res;
897 Py_DECREF(res);
898 if (!ENTER_BUFFERED(self))
899 return NULL;
900 res = _bufferedreader_read_generic(self, n);
901 }
902
903 LEAVE_BUFFERED(self)
904 return res;
905 }
906
907 /*[clinic input]
908 _io._Buffered.read1
909 size as n: Py_ssize_t = -1
910 /
911 [clinic start generated code]*/
912
913 static PyObject *
_io__Buffered_read1_impl(buffered * self,Py_ssize_t n)914 _io__Buffered_read1_impl(buffered *self, Py_ssize_t n)
915 /*[clinic end generated code: output=bcc4fb4e54d103a3 input=7d22de9630b61774]*/
916 {
917 Py_ssize_t have, r;
918 PyObject *res = NULL;
919
920 CHECK_INITIALIZED(self)
921 if (n < 0) {
922 n = self->buffer_size;
923 }
924
925 CHECK_CLOSED(self, "read of closed file")
926
927 if (n == 0)
928 return PyBytes_FromStringAndSize(NULL, 0);
929
930 /* Return up to n bytes. If at least one byte is buffered, we
931 only return buffered bytes. Otherwise, we do one raw read. */
932
933 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
934 if (have > 0) {
935 n = Py_MIN(have, n);
936 res = _bufferedreader_read_fast(self, n);
937 assert(res != Py_None);
938 return res;
939 }
940 res = PyBytes_FromStringAndSize(NULL, n);
941 if (res == NULL)
942 return NULL;
943 if (!ENTER_BUFFERED(self)) {
944 Py_DECREF(res);
945 return NULL;
946 }
947 _bufferedreader_reset_buf(self);
948 r = _bufferedreader_raw_read(self, PyBytes_AS_STRING(res), n);
949 LEAVE_BUFFERED(self)
950 if (r == -1) {
951 Py_DECREF(res);
952 return NULL;
953 }
954 if (r == -2)
955 r = 0;
956 if (n > r)
957 _PyBytes_Resize(&res, r);
958 return res;
959 }
960
961 static PyObject *
_buffered_readinto_generic(buffered * self,Py_buffer * buffer,char readinto1)962 _buffered_readinto_generic(buffered *self, Py_buffer *buffer, char readinto1)
963 {
964 Py_ssize_t n, written = 0, remaining;
965 PyObject *res = NULL;
966
967 CHECK_INITIALIZED(self)
968 CHECK_CLOSED(self, "readinto of closed file")
969
970 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
971 if (n > 0) {
972 if (n >= buffer->len) {
973 memcpy(buffer->buf, self->buffer + self->pos, buffer->len);
974 self->pos += buffer->len;
975 return PyLong_FromSsize_t(buffer->len);
976 }
977 memcpy(buffer->buf, self->buffer + self->pos, n);
978 self->pos += n;
979 written = n;
980 }
981
982 if (!ENTER_BUFFERED(self))
983 return NULL;
984
985 if (self->writable) {
986 res = buffered_flush_and_rewind_unlocked(self);
987 if (res == NULL)
988 goto end;
989 Py_CLEAR(res);
990 }
991
992 _bufferedreader_reset_buf(self);
993 self->pos = 0;
994
995 for (remaining = buffer->len - written;
996 remaining > 0;
997 written += n, remaining -= n) {
998 /* If remaining bytes is larger than internal buffer size, copy
999 * directly into caller's buffer. */
1000 if (remaining > self->buffer_size) {
1001 n = _bufferedreader_raw_read(self, (char *) buffer->buf + written,
1002 remaining);
1003 }
1004
1005 /* In readinto1 mode, we do not want to fill the internal
1006 buffer if we already have some data to return */
1007 else if (!(readinto1 && written)) {
1008 n = _bufferedreader_fill_buffer(self);
1009 if (n > 0) {
1010 if (n > remaining)
1011 n = remaining;
1012 memcpy((char *) buffer->buf + written,
1013 self->buffer + self->pos, n);
1014 self->pos += n;
1015 continue; /* short circuit */
1016 }
1017 }
1018 else
1019 n = 0;
1020
1021 if (n == 0 || (n == -2 && written > 0))
1022 break;
1023 if (n < 0) {
1024 if (n == -2) {
1025 Py_INCREF(Py_None);
1026 res = Py_None;
1027 }
1028 goto end;
1029 }
1030
1031 /* At most one read in readinto1 mode */
1032 if (readinto1) {
1033 written += n;
1034 break;
1035 }
1036 }
1037 res = PyLong_FromSsize_t(written);
1038
1039 end:
1040 LEAVE_BUFFERED(self);
1041 return res;
1042 }
1043
1044 /*[clinic input]
1045 _io._Buffered.readinto
1046 buffer: Py_buffer(accept={rwbuffer})
1047 /
1048 [clinic start generated code]*/
1049
1050 static PyObject *
_io__Buffered_readinto_impl(buffered * self,Py_buffer * buffer)1051 _io__Buffered_readinto_impl(buffered *self, Py_buffer *buffer)
1052 /*[clinic end generated code: output=bcb376580b1d8170 input=ed6b98b7a20a3008]*/
1053 {
1054 return _buffered_readinto_generic(self, buffer, 0);
1055 }
1056
1057 /*[clinic input]
1058 _io._Buffered.readinto1
1059 buffer: Py_buffer(accept={rwbuffer})
1060 /
1061 [clinic start generated code]*/
1062
1063 static PyObject *
_io__Buffered_readinto1_impl(buffered * self,Py_buffer * buffer)1064 _io__Buffered_readinto1_impl(buffered *self, Py_buffer *buffer)
1065 /*[clinic end generated code: output=6e5c6ac5868205d6 input=4455c5d55fdf1687]*/
1066 {
1067 return _buffered_readinto_generic(self, buffer, 1);
1068 }
1069
1070
1071 static PyObject *
_buffered_readline(buffered * self,Py_ssize_t limit)1072 _buffered_readline(buffered *self, Py_ssize_t limit)
1073 {
1074 PyObject *res = NULL;
1075 PyObject *chunks = NULL;
1076 Py_ssize_t n, written = 0;
1077 const char *start, *s, *end;
1078
1079 CHECK_CLOSED(self, "readline of closed file")
1080
1081 /* First, try to find a line in the buffer. This can run unlocked because
1082 the calls to the C API are simple enough that they can't trigger
1083 any thread switch. */
1084 n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1085 if (limit >= 0 && n > limit)
1086 n = limit;
1087 start = self->buffer + self->pos;
1088 s = memchr(start, '\n', n);
1089 if (s != NULL) {
1090 res = PyBytes_FromStringAndSize(start, s - start + 1);
1091 if (res != NULL)
1092 self->pos += s - start + 1;
1093 goto end_unlocked;
1094 }
1095 if (n == limit) {
1096 res = PyBytes_FromStringAndSize(start, n);
1097 if (res != NULL)
1098 self->pos += n;
1099 goto end_unlocked;
1100 }
1101
1102 if (!ENTER_BUFFERED(self))
1103 goto end_unlocked;
1104
1105 /* Now we try to get some more from the raw stream */
1106 chunks = PyList_New(0);
1107 if (chunks == NULL)
1108 goto end;
1109 if (n > 0) {
1110 res = PyBytes_FromStringAndSize(start, n);
1111 if (res == NULL)
1112 goto end;
1113 if (PyList_Append(chunks, res) < 0) {
1114 Py_CLEAR(res);
1115 goto end;
1116 }
1117 Py_CLEAR(res);
1118 written += n;
1119 self->pos += n;
1120 if (limit >= 0)
1121 limit -= n;
1122 }
1123 if (self->writable) {
1124 PyObject *r = buffered_flush_and_rewind_unlocked(self);
1125 if (r == NULL)
1126 goto end;
1127 Py_DECREF(r);
1128 }
1129
1130 for (;;) {
1131 _bufferedreader_reset_buf(self);
1132 n = _bufferedreader_fill_buffer(self);
1133 if (n == -1)
1134 goto end;
1135 if (n <= 0)
1136 break;
1137 if (limit >= 0 && n > limit)
1138 n = limit;
1139 start = self->buffer;
1140 end = start + n;
1141 s = start;
1142 while (s < end) {
1143 if (*s++ == '\n') {
1144 res = PyBytes_FromStringAndSize(start, s - start);
1145 if (res == NULL)
1146 goto end;
1147 self->pos = s - start;
1148 goto found;
1149 }
1150 }
1151 res = PyBytes_FromStringAndSize(start, n);
1152 if (res == NULL)
1153 goto end;
1154 if (n == limit) {
1155 self->pos = n;
1156 break;
1157 }
1158 if (PyList_Append(chunks, res) < 0) {
1159 Py_CLEAR(res);
1160 goto end;
1161 }
1162 Py_CLEAR(res);
1163 written += n;
1164 if (limit >= 0)
1165 limit -= n;
1166 }
1167 found:
1168 if (res != NULL && PyList_Append(chunks, res) < 0) {
1169 Py_CLEAR(res);
1170 goto end;
1171 }
1172 Py_XSETREF(res, _PyBytes_Join(_PyIO_empty_bytes, chunks));
1173
1174 end:
1175 LEAVE_BUFFERED(self)
1176 end_unlocked:
1177 Py_XDECREF(chunks);
1178 return res;
1179 }
1180
1181 /*[clinic input]
1182 _io._Buffered.readline
1183 size: Py_ssize_t(accept={int, NoneType}) = -1
1184 /
1185 [clinic start generated code]*/
1186
1187 static PyObject *
_io__Buffered_readline_impl(buffered * self,Py_ssize_t size)1188 _io__Buffered_readline_impl(buffered *self, Py_ssize_t size)
1189 /*[clinic end generated code: output=24dd2aa6e33be83c input=673b6240e315ef8a]*/
1190 {
1191 CHECK_INITIALIZED(self)
1192 return _buffered_readline(self, size);
1193 }
1194
1195
1196 static PyObject *
buffered_tell(buffered * self,PyObject * Py_UNUSED (ignored))1197 buffered_tell(buffered *self, PyObject *Py_UNUSED(ignored))
1198 {
1199 Py_off_t pos;
1200
1201 CHECK_INITIALIZED(self)
1202 pos = _buffered_raw_tell(self);
1203 if (pos == -1)
1204 return NULL;
1205 pos -= RAW_OFFSET(self);
1206 /* TODO: sanity check (pos >= 0) */
1207 return PyLong_FromOff_t(pos);
1208 }
1209
1210 /*[clinic input]
1211 _io._Buffered.seek
1212 target as targetobj: object
1213 whence: int = 0
1214 /
1215 [clinic start generated code]*/
1216
1217 static PyObject *
_io__Buffered_seek_impl(buffered * self,PyObject * targetobj,int whence)1218 _io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence)
1219 /*[clinic end generated code: output=7ae0e8dc46efdefb input=a9c4920bfcba6163]*/
1220 {
1221 Py_off_t target, n;
1222 PyObject *res = NULL;
1223
1224 CHECK_INITIALIZED(self)
1225
1226 /* Do some error checking instead of trusting OS 'seek()'
1227 ** error detection, just in case.
1228 */
1229 if ((whence < 0 || whence >2)
1230 #ifdef SEEK_HOLE
1231 && (whence != SEEK_HOLE)
1232 #endif
1233 #ifdef SEEK_DATA
1234 && (whence != SEEK_DATA)
1235 #endif
1236 ) {
1237 PyErr_Format(PyExc_ValueError,
1238 "whence value %d unsupported", whence);
1239 return NULL;
1240 }
1241
1242 CHECK_CLOSED(self, "seek of closed file")
1243
1244 if (_PyIOBase_check_seekable(self->raw, Py_True) == NULL)
1245 return NULL;
1246
1247 target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1248 if (target == -1 && PyErr_Occurred())
1249 return NULL;
1250
1251 /* SEEK_SET and SEEK_CUR are special because we could seek inside the
1252 buffer. Other whence values must be managed without this optimization.
1253 Some Operating Systems can provide additional values, like
1254 SEEK_HOLE/SEEK_DATA. */
1255 if (((whence == 0) || (whence == 1)) && self->readable) {
1256 Py_off_t current, avail;
1257 /* Check if seeking leaves us inside the current buffer,
1258 so as to return quickly if possible. Also, we needn't take the
1259 lock in this fast path.
1260 Don't know how to do that when whence == 2, though. */
1261 /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1262 state at this point. */
1263 current = RAW_TELL(self);
1264 avail = READAHEAD(self);
1265 if (avail > 0) {
1266 Py_off_t offset;
1267 if (whence == 0)
1268 offset = target - (current - RAW_OFFSET(self));
1269 else
1270 offset = target;
1271 if (offset >= -self->pos && offset <= avail) {
1272 self->pos += offset;
1273 return PyLong_FromOff_t(current - avail + offset);
1274 }
1275 }
1276 }
1277
1278 if (!ENTER_BUFFERED(self))
1279 return NULL;
1280
1281 /* Fallback: invoke raw seek() method and clear buffer */
1282 if (self->writable) {
1283 res = _bufferedwriter_flush_unlocked(self);
1284 if (res == NULL)
1285 goto end;
1286 Py_CLEAR(res);
1287 }
1288
1289 /* TODO: align on block boundary and read buffer if needed? */
1290 if (whence == 1)
1291 target -= RAW_OFFSET(self);
1292 n = _buffered_raw_seek(self, target, whence);
1293 if (n == -1)
1294 goto end;
1295 self->raw_pos = -1;
1296 res = PyLong_FromOff_t(n);
1297 if (res != NULL && self->readable)
1298 _bufferedreader_reset_buf(self);
1299
1300 end:
1301 LEAVE_BUFFERED(self)
1302 return res;
1303 }
1304
1305 /*[clinic input]
1306 _io._Buffered.truncate
1307 pos: object = None
1308 /
1309 [clinic start generated code]*/
1310
1311 static PyObject *
_io__Buffered_truncate_impl(buffered * self,PyObject * pos)1312 _io__Buffered_truncate_impl(buffered *self, PyObject *pos)
1313 /*[clinic end generated code: output=667ca03c60c270de input=8a1be34d57cca2d3]*/
1314 {
1315 PyObject *res = NULL;
1316
1317 CHECK_INITIALIZED(self)
1318 if (!ENTER_BUFFERED(self))
1319 return NULL;
1320
1321 if (self->writable) {
1322 res = buffered_flush_and_rewind_unlocked(self);
1323 if (res == NULL)
1324 goto end;
1325 Py_CLEAR(res);
1326 }
1327 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1328 if (res == NULL)
1329 goto end;
1330 /* Reset cached position */
1331 if (_buffered_raw_tell(self) == -1)
1332 PyErr_Clear();
1333
1334 end:
1335 LEAVE_BUFFERED(self)
1336 return res;
1337 }
1338
1339 static PyObject *
buffered_iternext(buffered * self)1340 buffered_iternext(buffered *self)
1341 {
1342 PyObject *line;
1343 PyTypeObject *tp;
1344
1345 CHECK_INITIALIZED(self);
1346
1347 tp = Py_TYPE(self);
1348 if (tp == &PyBufferedReader_Type ||
1349 tp == &PyBufferedRandom_Type) {
1350 /* Skip method call overhead for speed */
1351 line = _buffered_readline(self, -1);
1352 }
1353 else {
1354 line = PyObject_CallMethodObjArgs((PyObject *)self,
1355 _PyIO_str_readline, NULL);
1356 if (line && !PyBytes_Check(line)) {
1357 PyErr_Format(PyExc_OSError,
1358 "readline() should have returned a bytes object, "
1359 "not '%.200s'", Py_TYPE(line)->tp_name);
1360 Py_DECREF(line);
1361 return NULL;
1362 }
1363 }
1364
1365 if (line == NULL)
1366 return NULL;
1367
1368 if (PyBytes_GET_SIZE(line) == 0) {
1369 /* Reached EOF or would have blocked */
1370 Py_DECREF(line);
1371 return NULL;
1372 }
1373
1374 return line;
1375 }
1376
1377 static PyObject *
buffered_repr(buffered * self)1378 buffered_repr(buffered *self)
1379 {
1380 PyObject *nameobj, *res;
1381
1382 if (_PyObject_LookupAttrId((PyObject *) self, &PyId_name, &nameobj) < 0) {
1383 if (!PyErr_ExceptionMatches(PyExc_ValueError)) {
1384 return NULL;
1385 }
1386 /* Ignore ValueError raised if the underlying stream was detached */
1387 PyErr_Clear();
1388 }
1389 if (nameobj == NULL) {
1390 res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1391 }
1392 else {
1393 int status = Py_ReprEnter((PyObject *)self);
1394 res = NULL;
1395 if (status == 0) {
1396 res = PyUnicode_FromFormat("<%s name=%R>",
1397 Py_TYPE(self)->tp_name, nameobj);
1398 Py_ReprLeave((PyObject *)self);
1399 }
1400 else if (status > 0) {
1401 PyErr_Format(PyExc_RuntimeError,
1402 "reentrant call inside %s.__repr__",
1403 Py_TYPE(self)->tp_name);
1404 }
1405 Py_DECREF(nameobj);
1406 }
1407 return res;
1408 }
1409
1410 /*
1411 * class BufferedReader
1412 */
1413
_bufferedreader_reset_buf(buffered * self)1414 static void _bufferedreader_reset_buf(buffered *self)
1415 {
1416 self->read_end = -1;
1417 }
1418
1419 /*[clinic input]
1420 _io.BufferedReader.__init__
1421 raw: object
1422 buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
1423
1424 Create a new buffered reader using the given readable raw IO object.
1425 [clinic start generated code]*/
1426
1427 static int
_io_BufferedReader___init___impl(buffered * self,PyObject * raw,Py_ssize_t buffer_size)1428 _io_BufferedReader___init___impl(buffered *self, PyObject *raw,
1429 Py_ssize_t buffer_size)
1430 /*[clinic end generated code: output=cddcfefa0ed294c4 input=fb887e06f11b4e48]*/
1431 {
1432 self->ok = 0;
1433 self->detached = 0;
1434
1435 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
1436 return -1;
1437
1438 Py_INCREF(raw);
1439 Py_XSETREF(self->raw, raw);
1440 self->buffer_size = buffer_size;
1441 self->readable = 1;
1442 self->writable = 0;
1443
1444 if (_buffered_init(self) < 0)
1445 return -1;
1446 _bufferedreader_reset_buf(self);
1447
1448 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1449 Py_TYPE(raw) == &PyFileIO_Type);
1450
1451 self->ok = 1;
1452 return 0;
1453 }
1454
1455 static Py_ssize_t
_bufferedreader_raw_read(buffered * self,char * start,Py_ssize_t len)1456 _bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
1457 {
1458 Py_buffer buf;
1459 PyObject *memobj, *res;
1460 Py_ssize_t n;
1461 /* NOTE: the buffer needn't be released as its object is NULL. */
1462 if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1463 return -1;
1464 memobj = PyMemoryView_FromBuffer(&buf);
1465 if (memobj == NULL)
1466 return -1;
1467 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1468 occurs so we needn't do it ourselves.
1469 We then retry reading, ignoring the signal if no handler has
1470 raised (see issue #10956).
1471 */
1472 do {
1473 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1474 } while (res == NULL && _PyIO_trap_eintr());
1475 Py_DECREF(memobj);
1476 if (res == NULL)
1477 return -1;
1478 if (res == Py_None) {
1479 /* Non-blocking stream would have blocked. Special return code! */
1480 Py_DECREF(res);
1481 return -2;
1482 }
1483 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1484 Py_DECREF(res);
1485 if (n < 0 || n > len) {
1486 PyErr_Format(PyExc_OSError,
1487 "raw readinto() returned invalid length %zd "
1488 "(should have been between 0 and %zd)", n, len);
1489 return -1;
1490 }
1491 if (n > 0 && self->abs_pos != -1)
1492 self->abs_pos += n;
1493 return n;
1494 }
1495
1496 static Py_ssize_t
_bufferedreader_fill_buffer(buffered * self)1497 _bufferedreader_fill_buffer(buffered *self)
1498 {
1499 Py_ssize_t start, len, n;
1500 if (VALID_READ_BUFFER(self))
1501 start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1502 else
1503 start = 0;
1504 len = self->buffer_size - start;
1505 n = _bufferedreader_raw_read(self, self->buffer + start, len);
1506 if (n <= 0)
1507 return n;
1508 self->read_end = start + n;
1509 self->raw_pos = start + n;
1510 return n;
1511 }
1512
1513 static PyObject *
_bufferedreader_read_all(buffered * self)1514 _bufferedreader_read_all(buffered *self)
1515 {
1516 Py_ssize_t current_size;
1517 PyObject *res = NULL, *data = NULL, *tmp = NULL, *chunks = NULL, *readall;
1518
1519 /* First copy what we have in the current buffer. */
1520 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1521 if (current_size) {
1522 data = PyBytes_FromStringAndSize(
1523 self->buffer + self->pos, current_size);
1524 if (data == NULL)
1525 return NULL;
1526 self->pos += current_size;
1527 }
1528 /* We're going past the buffer's bounds, flush it */
1529 if (self->writable) {
1530 tmp = buffered_flush_and_rewind_unlocked(self);
1531 if (tmp == NULL)
1532 goto cleanup;
1533 Py_CLEAR(tmp);
1534 }
1535 _bufferedreader_reset_buf(self);
1536
1537 if (_PyObject_LookupAttr(self->raw, _PyIO_str_readall, &readall) < 0) {
1538 goto cleanup;
1539 }
1540 if (readall) {
1541 tmp = _PyObject_CallNoArg(readall);
1542 Py_DECREF(readall);
1543 if (tmp == NULL)
1544 goto cleanup;
1545 if (tmp != Py_None && !PyBytes_Check(tmp)) {
1546 PyErr_SetString(PyExc_TypeError, "readall() should return bytes");
1547 goto cleanup;
1548 }
1549 if (current_size == 0) {
1550 res = tmp;
1551 } else {
1552 if (tmp != Py_None) {
1553 PyBytes_Concat(&data, tmp);
1554 }
1555 res = data;
1556 }
1557 goto cleanup;
1558 }
1559
1560 chunks = PyList_New(0);
1561 if (chunks == NULL)
1562 goto cleanup;
1563
1564 while (1) {
1565 if (data) {
1566 if (PyList_Append(chunks, data) < 0)
1567 goto cleanup;
1568 Py_CLEAR(data);
1569 }
1570
1571 /* Read until EOF or until read() would block. */
1572 data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1573 if (data == NULL)
1574 goto cleanup;
1575 if (data != Py_None && !PyBytes_Check(data)) {
1576 PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1577 goto cleanup;
1578 }
1579 if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1580 if (current_size == 0) {
1581 res = data;
1582 goto cleanup;
1583 }
1584 else {
1585 tmp = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1586 res = tmp;
1587 goto cleanup;
1588 }
1589 }
1590 current_size += PyBytes_GET_SIZE(data);
1591 if (self->abs_pos != -1)
1592 self->abs_pos += PyBytes_GET_SIZE(data);
1593 }
1594 cleanup:
1595 /* res is either NULL or a borrowed ref */
1596 Py_XINCREF(res);
1597 Py_XDECREF(data);
1598 Py_XDECREF(tmp);
1599 Py_XDECREF(chunks);
1600 return res;
1601 }
1602
1603 /* Read n bytes from the buffer if it can, otherwise return None.
1604 This function is simple enough that it can run unlocked. */
1605 static PyObject *
_bufferedreader_read_fast(buffered * self,Py_ssize_t n)1606 _bufferedreader_read_fast(buffered *self, Py_ssize_t n)
1607 {
1608 Py_ssize_t current_size;
1609
1610 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1611 if (n <= current_size) {
1612 /* Fast path: the data to read is fully buffered. */
1613 PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1614 if (res != NULL)
1615 self->pos += n;
1616 return res;
1617 }
1618 Py_RETURN_NONE;
1619 }
1620
1621 /* Generic read function: read from the stream until enough bytes are read,
1622 * or until an EOF occurs or until read() would block.
1623 */
1624 static PyObject *
_bufferedreader_read_generic(buffered * self,Py_ssize_t n)1625 _bufferedreader_read_generic(buffered *self, Py_ssize_t n)
1626 {
1627 PyObject *res = NULL;
1628 Py_ssize_t current_size, remaining, written;
1629 char *out;
1630
1631 current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1632 if (n <= current_size)
1633 return _bufferedreader_read_fast(self, n);
1634
1635 res = PyBytes_FromStringAndSize(NULL, n);
1636 if (res == NULL)
1637 goto error;
1638 out = PyBytes_AS_STRING(res);
1639 remaining = n;
1640 written = 0;
1641 if (current_size > 0) {
1642 memcpy(out, self->buffer + self->pos, current_size);
1643 remaining -= current_size;
1644 written += current_size;
1645 self->pos += current_size;
1646 }
1647 /* Flush the write buffer if necessary */
1648 if (self->writable) {
1649 PyObject *r = buffered_flush_and_rewind_unlocked(self);
1650 if (r == NULL)
1651 goto error;
1652 Py_DECREF(r);
1653 }
1654 _bufferedreader_reset_buf(self);
1655 while (remaining > 0) {
1656 /* We want to read a whole block at the end into buffer.
1657 If we had readv() we could do this in one pass. */
1658 Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1659 if (r == 0)
1660 break;
1661 r = _bufferedreader_raw_read(self, out + written, r);
1662 if (r == -1)
1663 goto error;
1664 if (r == 0 || r == -2) {
1665 /* EOF occurred or read() would block. */
1666 if (r == 0 || written > 0) {
1667 if (_PyBytes_Resize(&res, written))
1668 goto error;
1669 return res;
1670 }
1671 Py_DECREF(res);
1672 Py_RETURN_NONE;
1673 }
1674 remaining -= r;
1675 written += r;
1676 }
1677 assert(remaining <= self->buffer_size);
1678 self->pos = 0;
1679 self->raw_pos = 0;
1680 self->read_end = 0;
1681 /* NOTE: when the read is satisfied, we avoid issuing any additional
1682 reads, which could block indefinitely (e.g. on a socket).
1683 See issue #9550. */
1684 while (remaining > 0 && self->read_end < self->buffer_size) {
1685 Py_ssize_t r = _bufferedreader_fill_buffer(self);
1686 if (r == -1)
1687 goto error;
1688 if (r == 0 || r == -2) {
1689 /* EOF occurred or read() would block. */
1690 if (r == 0 || written > 0) {
1691 if (_PyBytes_Resize(&res, written))
1692 goto error;
1693 return res;
1694 }
1695 Py_DECREF(res);
1696 Py_RETURN_NONE;
1697 }
1698 if (remaining > r) {
1699 memcpy(out + written, self->buffer + self->pos, r);
1700 written += r;
1701 self->pos += r;
1702 remaining -= r;
1703 }
1704 else if (remaining > 0) {
1705 memcpy(out + written, self->buffer + self->pos, remaining);
1706 written += remaining;
1707 self->pos += remaining;
1708 remaining = 0;
1709 }
1710 if (remaining == 0)
1711 break;
1712 }
1713
1714 return res;
1715
1716 error:
1717 Py_XDECREF(res);
1718 return NULL;
1719 }
1720
1721 static PyObject *
_bufferedreader_peek_unlocked(buffered * self)1722 _bufferedreader_peek_unlocked(buffered *self)
1723 {
1724 Py_ssize_t have, r;
1725
1726 have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1727 /* Constraints:
1728 1. we don't want to advance the file position.
1729 2. we don't want to lose block alignment, so we can't shift the buffer
1730 to make some place.
1731 Therefore, we either return `have` bytes (if > 0), or a full buffer.
1732 */
1733 if (have > 0) {
1734 return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1735 }
1736
1737 /* Fill the buffer from the raw stream, and copy it to the result. */
1738 _bufferedreader_reset_buf(self);
1739 r = _bufferedreader_fill_buffer(self);
1740 if (r == -1)
1741 return NULL;
1742 if (r == -2)
1743 r = 0;
1744 self->pos = 0;
1745 return PyBytes_FromStringAndSize(self->buffer, r);
1746 }
1747
1748
1749
1750 /*
1751 * class BufferedWriter
1752 */
1753 static void
_bufferedwriter_reset_buf(buffered * self)1754 _bufferedwriter_reset_buf(buffered *self)
1755 {
1756 self->write_pos = 0;
1757 self->write_end = -1;
1758 }
1759
1760 /*[clinic input]
1761 _io.BufferedWriter.__init__
1762 raw: object
1763 buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
1764
1765 A buffer for a writeable sequential RawIO object.
1766
1767 The constructor creates a BufferedWriter for the given writeable raw
1768 stream. If the buffer_size is not given, it defaults to
1769 DEFAULT_BUFFER_SIZE.
1770 [clinic start generated code]*/
1771
1772 static int
_io_BufferedWriter___init___impl(buffered * self,PyObject * raw,Py_ssize_t buffer_size)1773 _io_BufferedWriter___init___impl(buffered *self, PyObject *raw,
1774 Py_ssize_t buffer_size)
1775 /*[clinic end generated code: output=c8942a020c0dee64 input=914be9b95e16007b]*/
1776 {
1777 self->ok = 0;
1778 self->detached = 0;
1779
1780 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
1781 return -1;
1782
1783 Py_INCREF(raw);
1784 Py_XSETREF(self->raw, raw);
1785 self->readable = 0;
1786 self->writable = 1;
1787
1788 self->buffer_size = buffer_size;
1789 if (_buffered_init(self) < 0)
1790 return -1;
1791 _bufferedwriter_reset_buf(self);
1792 self->pos = 0;
1793
1794 self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1795 Py_TYPE(raw) == &PyFileIO_Type);
1796
1797 self->ok = 1;
1798 return 0;
1799 }
1800
1801 static Py_ssize_t
_bufferedwriter_raw_write(buffered * self,char * start,Py_ssize_t len)1802 _bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
1803 {
1804 Py_buffer buf;
1805 PyObject *memobj, *res;
1806 Py_ssize_t n;
1807 int errnum;
1808 /* NOTE: the buffer needn't be released as its object is NULL. */
1809 if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1810 return -1;
1811 memobj = PyMemoryView_FromBuffer(&buf);
1812 if (memobj == NULL)
1813 return -1;
1814 /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1815 occurs so we needn't do it ourselves.
1816 We then retry writing, ignoring the signal if no handler has
1817 raised (see issue #10956).
1818 */
1819 do {
1820 errno = 0;
1821 res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1822 errnum = errno;
1823 } while (res == NULL && _PyIO_trap_eintr());
1824 Py_DECREF(memobj);
1825 if (res == NULL)
1826 return -1;
1827 if (res == Py_None) {
1828 /* Non-blocking stream would have blocked. Special return code!
1829 Being paranoid we reset errno in case it is changed by code
1830 triggered by a decref. errno is used by _set_BlockingIOError(). */
1831 Py_DECREF(res);
1832 errno = errnum;
1833 return -2;
1834 }
1835 n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1836 Py_DECREF(res);
1837 if (n < 0 || n > len) {
1838 PyErr_Format(PyExc_OSError,
1839 "raw write() returned invalid length %zd "
1840 "(should have been between 0 and %zd)", n, len);
1841 return -1;
1842 }
1843 if (n > 0 && self->abs_pos != -1)
1844 self->abs_pos += n;
1845 return n;
1846 }
1847
1848 static PyObject *
_bufferedwriter_flush_unlocked(buffered * self)1849 _bufferedwriter_flush_unlocked(buffered *self)
1850 {
1851 Py_ssize_t written = 0;
1852 Py_off_t n, rewind;
1853
1854 if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1855 goto end;
1856 /* First, rewind */
1857 rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1858 if (rewind != 0) {
1859 n = _buffered_raw_seek(self, -rewind, 1);
1860 if (n < 0) {
1861 goto error;
1862 }
1863 self->raw_pos -= rewind;
1864 }
1865 while (self->write_pos < self->write_end) {
1866 n = _bufferedwriter_raw_write(self,
1867 self->buffer + self->write_pos,
1868 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1869 Py_off_t, Py_ssize_t));
1870 if (n == -1) {
1871 goto error;
1872 }
1873 else if (n == -2) {
1874 _set_BlockingIOError("write could not complete without blocking",
1875 0);
1876 goto error;
1877 }
1878 self->write_pos += n;
1879 self->raw_pos = self->write_pos;
1880 written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1881 /* Partial writes can return successfully when interrupted by a
1882 signal (see write(2)). We must run signal handlers before
1883 blocking another time, possibly indefinitely. */
1884 if (PyErr_CheckSignals() < 0)
1885 goto error;
1886 }
1887
1888
1889 end:
1890 /* This ensures that after return from this function,
1891 VALID_WRITE_BUFFER(self) returns false.
1892
1893 This is a required condition because when a tell() is called
1894 after flushing and if VALID_READ_BUFFER(self) is false, we need
1895 VALID_WRITE_BUFFER(self) to be false to have
1896 RAW_OFFSET(self) == 0.
1897
1898 Issue: https://bugs.python.org/issue32228 */
1899 _bufferedwriter_reset_buf(self);
1900 Py_RETURN_NONE;
1901
1902 error:
1903 return NULL;
1904 }
1905
1906 /*[clinic input]
1907 _io.BufferedWriter.write
1908 buffer: Py_buffer
1909 /
1910 [clinic start generated code]*/
1911
1912 static PyObject *
_io_BufferedWriter_write_impl(buffered * self,Py_buffer * buffer)1913 _io_BufferedWriter_write_impl(buffered *self, Py_buffer *buffer)
1914 /*[clinic end generated code: output=7f8d1365759bfc6b input=dd87dd85fc7f8850]*/
1915 {
1916 PyObject *res = NULL;
1917 Py_ssize_t written, avail, remaining;
1918 Py_off_t offset;
1919
1920 CHECK_INITIALIZED(self)
1921
1922 if (!ENTER_BUFFERED(self))
1923 return NULL;
1924
1925 /* Issue #31976: Check for closed file after acquiring the lock. Another
1926 thread could be holding the lock while closing the file. */
1927 if (IS_CLOSED(self)) {
1928 PyErr_SetString(PyExc_ValueError, "write to closed file");
1929 goto error;
1930 }
1931
1932 /* Fast path: the data to write can be fully buffered. */
1933 if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1934 self->pos = 0;
1935 self->raw_pos = 0;
1936 }
1937 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1938 if (buffer->len <= avail) {
1939 memcpy(self->buffer + self->pos, buffer->buf, buffer->len);
1940 if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
1941 self->write_pos = self->pos;
1942 }
1943 ADJUST_POSITION(self, self->pos + buffer->len);
1944 if (self->pos > self->write_end)
1945 self->write_end = self->pos;
1946 written = buffer->len;
1947 goto end;
1948 }
1949
1950 /* First write the current buffer */
1951 res = _bufferedwriter_flush_unlocked(self);
1952 if (res == NULL) {
1953 Py_ssize_t *w = _buffered_check_blocking_error();
1954 if (w == NULL)
1955 goto error;
1956 if (self->readable)
1957 _bufferedreader_reset_buf(self);
1958 /* Make some place by shifting the buffer. */
1959 assert(VALID_WRITE_BUFFER(self));
1960 memmove(self->buffer, self->buffer + self->write_pos,
1961 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1962 Py_off_t, Py_ssize_t));
1963 self->write_end -= self->write_pos;
1964 self->raw_pos -= self->write_pos;
1965 self->pos -= self->write_pos;
1966 self->write_pos = 0;
1967 avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1968 Py_off_t, Py_ssize_t);
1969 if (buffer->len <= avail) {
1970 /* Everything can be buffered */
1971 PyErr_Clear();
1972 memcpy(self->buffer + self->write_end, buffer->buf, buffer->len);
1973 self->write_end += buffer->len;
1974 self->pos += buffer->len;
1975 written = buffer->len;
1976 goto end;
1977 }
1978 /* Buffer as much as possible. */
1979 memcpy(self->buffer + self->write_end, buffer->buf, avail);
1980 self->write_end += avail;
1981 self->pos += avail;
1982 /* XXX Modifying the existing exception e using the pointer w
1983 will change e.characters_written but not e.args[2].
1984 Therefore we just replace with a new error. */
1985 _set_BlockingIOError("write could not complete without blocking",
1986 avail);
1987 goto error;
1988 }
1989 Py_CLEAR(res);
1990
1991 /* Adjust the raw stream position if it is away from the logical stream
1992 position. This happens if the read buffer has been filled but not
1993 modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1994 the raw stream by itself).
1995 Fixes issue #6629.
1996 */
1997 offset = RAW_OFFSET(self);
1998 if (offset != 0) {
1999 if (_buffered_raw_seek(self, -offset, 1) < 0)
2000 goto error;
2001 self->raw_pos -= offset;
2002 }
2003
2004 /* Then write buf itself. At this point the buffer has been emptied. */
2005 remaining = buffer->len;
2006 written = 0;
2007 while (remaining > self->buffer_size) {
2008 Py_ssize_t n = _bufferedwriter_raw_write(
2009 self, (char *) buffer->buf + written, buffer->len - written);
2010 if (n == -1) {
2011 goto error;
2012 } else if (n == -2) {
2013 /* Write failed because raw file is non-blocking */
2014 if (remaining > self->buffer_size) {
2015 /* Can't buffer everything, still buffer as much as possible */
2016 memcpy(self->buffer,
2017 (char *) buffer->buf + written, self->buffer_size);
2018 self->raw_pos = 0;
2019 ADJUST_POSITION(self, self->buffer_size);
2020 self->write_end = self->buffer_size;
2021 written += self->buffer_size;
2022 _set_BlockingIOError("write could not complete without "
2023 "blocking", written);
2024 goto error;
2025 }
2026 PyErr_Clear();
2027 break;
2028 }
2029 written += n;
2030 remaining -= n;
2031 /* Partial writes can return successfully when interrupted by a
2032 signal (see write(2)). We must run signal handlers before
2033 blocking another time, possibly indefinitely. */
2034 if (PyErr_CheckSignals() < 0)
2035 goto error;
2036 }
2037 if (self->readable)
2038 _bufferedreader_reset_buf(self);
2039 if (remaining > 0) {
2040 memcpy(self->buffer, (char *) buffer->buf + written, remaining);
2041 written += remaining;
2042 }
2043 self->write_pos = 0;
2044 /* TODO: sanity check (remaining >= 0) */
2045 self->write_end = remaining;
2046 ADJUST_POSITION(self, remaining);
2047 self->raw_pos = 0;
2048
2049 end:
2050 res = PyLong_FromSsize_t(written);
2051
2052 error:
2053 LEAVE_BUFFERED(self)
2054 return res;
2055 }
2056
2057
2058
2059 /*
2060 * BufferedRWPair
2061 */
2062
2063 /* XXX The usefulness of this (compared to having two separate IO objects) is
2064 * questionable.
2065 */
2066
2067 typedef struct {
2068 PyObject_HEAD
2069 buffered *reader;
2070 buffered *writer;
2071 PyObject *dict;
2072 PyObject *weakreflist;
2073 } rwpair;
2074
2075 /*[clinic input]
2076 _io.BufferedRWPair.__init__
2077 reader: object
2078 writer: object
2079 buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
2080 /
2081
2082 A buffered reader and writer object together.
2083
2084 A buffered reader object and buffered writer object put together to
2085 form a sequential IO object that can read and write. This is typically
2086 used with a socket or two-way pipe.
2087
2088 reader and writer are RawIOBase objects that are readable and
2089 writeable respectively. If the buffer_size is omitted it defaults to
2090 DEFAULT_BUFFER_SIZE.
2091 [clinic start generated code]*/
2092
2093 static int
_io_BufferedRWPair___init___impl(rwpair * self,PyObject * reader,PyObject * writer,Py_ssize_t buffer_size)2094 _io_BufferedRWPair___init___impl(rwpair *self, PyObject *reader,
2095 PyObject *writer, Py_ssize_t buffer_size)
2096 /*[clinic end generated code: output=327e73d1aee8f984 input=620d42d71f33a031]*/
2097 {
2098 if (_PyIOBase_check_readable(reader, Py_True) == NULL)
2099 return -1;
2100 if (_PyIOBase_check_writable(writer, Py_True) == NULL)
2101 return -1;
2102
2103 self->reader = (buffered *) PyObject_CallFunction(
2104 (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
2105 if (self->reader == NULL)
2106 return -1;
2107
2108 self->writer = (buffered *) PyObject_CallFunction(
2109 (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
2110 if (self->writer == NULL) {
2111 Py_CLEAR(self->reader);
2112 return -1;
2113 }
2114
2115 return 0;
2116 }
2117
2118 static int
bufferedrwpair_traverse(rwpair * self,visitproc visit,void * arg)2119 bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
2120 {
2121 Py_VISIT(self->dict);
2122 return 0;
2123 }
2124
2125 static int
bufferedrwpair_clear(rwpair * self)2126 bufferedrwpair_clear(rwpair *self)
2127 {
2128 Py_CLEAR(self->reader);
2129 Py_CLEAR(self->writer);
2130 Py_CLEAR(self->dict);
2131 return 0;
2132 }
2133
2134 static void
bufferedrwpair_dealloc(rwpair * self)2135 bufferedrwpair_dealloc(rwpair *self)
2136 {
2137 _PyObject_GC_UNTRACK(self);
2138 if (self->weakreflist != NULL)
2139 PyObject_ClearWeakRefs((PyObject *)self);
2140 Py_CLEAR(self->reader);
2141 Py_CLEAR(self->writer);
2142 Py_CLEAR(self->dict);
2143 Py_TYPE(self)->tp_free((PyObject *) self);
2144 }
2145
2146 static PyObject *
_forward_call(buffered * self,_Py_Identifier * name,PyObject * args)2147 _forward_call(buffered *self, _Py_Identifier *name, PyObject *args)
2148 {
2149 PyObject *func, *ret;
2150 if (self == NULL) {
2151 PyErr_SetString(PyExc_ValueError,
2152 "I/O operation on uninitialized object");
2153 return NULL;
2154 }
2155
2156 func = _PyObject_GetAttrId((PyObject *)self, name);
2157 if (func == NULL) {
2158 PyErr_SetString(PyExc_AttributeError, name->string);
2159 return NULL;
2160 }
2161
2162 ret = PyObject_CallObject(func, args);
2163 Py_DECREF(func);
2164 return ret;
2165 }
2166
2167 static PyObject *
bufferedrwpair_read(rwpair * self,PyObject * args)2168 bufferedrwpair_read(rwpair *self, PyObject *args)
2169 {
2170 return _forward_call(self->reader, &PyId_read, args);
2171 }
2172
2173 static PyObject *
bufferedrwpair_peek(rwpair * self,PyObject * args)2174 bufferedrwpair_peek(rwpair *self, PyObject *args)
2175 {
2176 return _forward_call(self->reader, &PyId_peek, args);
2177 }
2178
2179 static PyObject *
bufferedrwpair_read1(rwpair * self,PyObject * args)2180 bufferedrwpair_read1(rwpair *self, PyObject *args)
2181 {
2182 return _forward_call(self->reader, &PyId_read1, args);
2183 }
2184
2185 static PyObject *
bufferedrwpair_readinto(rwpair * self,PyObject * args)2186 bufferedrwpair_readinto(rwpair *self, PyObject *args)
2187 {
2188 return _forward_call(self->reader, &PyId_readinto, args);
2189 }
2190
2191 static PyObject *
bufferedrwpair_readinto1(rwpair * self,PyObject * args)2192 bufferedrwpair_readinto1(rwpair *self, PyObject *args)
2193 {
2194 return _forward_call(self->reader, &PyId_readinto1, args);
2195 }
2196
2197 static PyObject *
bufferedrwpair_write(rwpair * self,PyObject * args)2198 bufferedrwpair_write(rwpair *self, PyObject *args)
2199 {
2200 return _forward_call(self->writer, &PyId_write, args);
2201 }
2202
2203 static PyObject *
bufferedrwpair_flush(rwpair * self,PyObject * Py_UNUSED (ignored))2204 bufferedrwpair_flush(rwpair *self, PyObject *Py_UNUSED(ignored))
2205 {
2206 return _forward_call(self->writer, &PyId_flush, NULL);
2207 }
2208
2209 static PyObject *
bufferedrwpair_readable(rwpair * self,PyObject * Py_UNUSED (ignored))2210 bufferedrwpair_readable(rwpair *self, PyObject *Py_UNUSED(ignored))
2211 {
2212 return _forward_call(self->reader, &PyId_readable, NULL);
2213 }
2214
2215 static PyObject *
bufferedrwpair_writable(rwpair * self,PyObject * Py_UNUSED (ignored))2216 bufferedrwpair_writable(rwpair *self, PyObject *Py_UNUSED(ignored))
2217 {
2218 return _forward_call(self->writer, &PyId_writable, NULL);
2219 }
2220
2221 static PyObject *
bufferedrwpair_close(rwpair * self,PyObject * Py_UNUSED (ignored))2222 bufferedrwpair_close(rwpair *self, PyObject *Py_UNUSED(ignored))
2223 {
2224 PyObject *exc = NULL, *val, *tb;
2225 PyObject *ret = _forward_call(self->writer, &PyId_close, NULL);
2226 if (ret == NULL)
2227 PyErr_Fetch(&exc, &val, &tb);
2228 else
2229 Py_DECREF(ret);
2230 ret = _forward_call(self->reader, &PyId_close, NULL);
2231 if (exc != NULL) {
2232 _PyErr_ChainExceptions(exc, val, tb);
2233 Py_CLEAR(ret);
2234 }
2235 return ret;
2236 }
2237
2238 static PyObject *
bufferedrwpair_isatty(rwpair * self,PyObject * Py_UNUSED (ignored))2239 bufferedrwpair_isatty(rwpair *self, PyObject *Py_UNUSED(ignored))
2240 {
2241 PyObject *ret = _forward_call(self->writer, &PyId_isatty, NULL);
2242
2243 if (ret != Py_False) {
2244 /* either True or exception */
2245 return ret;
2246 }
2247 Py_DECREF(ret);
2248
2249 return _forward_call(self->reader, &PyId_isatty, NULL);
2250 }
2251
2252 static PyObject *
bufferedrwpair_closed_get(rwpair * self,void * context)2253 bufferedrwpair_closed_get(rwpair *self, void *context)
2254 {
2255 if (self->writer == NULL) {
2256 PyErr_SetString(PyExc_RuntimeError,
2257 "the BufferedRWPair object is being garbage-collected");
2258 return NULL;
2259 }
2260 return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2261 }
2262
2263
2264
2265 /*
2266 * BufferedRandom
2267 */
2268
2269 /*[clinic input]
2270 _io.BufferedRandom.__init__
2271 raw: object
2272 buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
2273
2274 A buffered interface to random access streams.
2275
2276 The constructor creates a reader and writer for a seekable stream,
2277 raw, given in the first argument. If the buffer_size is omitted it
2278 defaults to DEFAULT_BUFFER_SIZE.
2279 [clinic start generated code]*/
2280
2281 static int
_io_BufferedRandom___init___impl(buffered * self,PyObject * raw,Py_ssize_t buffer_size)2282 _io_BufferedRandom___init___impl(buffered *self, PyObject *raw,
2283 Py_ssize_t buffer_size)
2284 /*[clinic end generated code: output=d3d64eb0f64e64a3 input=a4e818fb86d0e50c]*/
2285 {
2286 self->ok = 0;
2287 self->detached = 0;
2288
2289 if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
2290 return -1;
2291 if (_PyIOBase_check_readable(raw, Py_True) == NULL)
2292 return -1;
2293 if (_PyIOBase_check_writable(raw, Py_True) == NULL)
2294 return -1;
2295
2296 Py_INCREF(raw);
2297 Py_XSETREF(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
2315 #include "clinic/bufferedio.c.h"
2316
2317
2318 static PyMethodDef bufferediobase_methods[] = {
2319 _IO__BUFFEREDIOBASE_DETACH_METHODDEF
2320 {"read", bufferediobase_read, METH_VARARGS, bufferediobase_read_doc},
2321 {"read1", bufferediobase_read1, METH_VARARGS, bufferediobase_read1_doc},
2322 _IO__BUFFEREDIOBASE_READINTO_METHODDEF
2323 _IO__BUFFEREDIOBASE_READINTO1_METHODDEF
2324 {"write", bufferediobase_write, METH_VARARGS, bufferediobase_write_doc},
2325 {NULL, NULL}
2326 };
2327
2328 PyTypeObject PyBufferedIOBase_Type = {
2329 PyVarObject_HEAD_INIT(NULL, 0)
2330 "_io._BufferedIOBase", /*tp_name*/
2331 0, /*tp_basicsize*/
2332 0, /*tp_itemsize*/
2333 0, /*tp_dealloc*/
2334 0, /*tp_vectorcall_offset*/
2335 0, /*tp_getattr*/
2336 0, /*tp_setattr*/
2337 0, /*tp_as_async*/
2338 0, /*tp_repr*/
2339 0, /*tp_as_number*/
2340 0, /*tp_as_sequence*/
2341 0, /*tp_as_mapping*/
2342 0, /*tp_hash */
2343 0, /*tp_call*/
2344 0, /*tp_str*/
2345 0, /*tp_getattro*/
2346 0, /*tp_setattro*/
2347 0, /*tp_as_buffer*/
2348 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
2349 bufferediobase_doc, /* tp_doc */
2350 0, /* tp_traverse */
2351 0, /* tp_clear */
2352 0, /* tp_richcompare */
2353 0, /* tp_weaklistoffset */
2354 0, /* tp_iter */
2355 0, /* tp_iternext */
2356 bufferediobase_methods, /* tp_methods */
2357 0, /* tp_members */
2358 0, /* tp_getset */
2359 &PyIOBase_Type, /* tp_base */
2360 0, /* tp_dict */
2361 0, /* tp_descr_get */
2362 0, /* tp_descr_set */
2363 0, /* tp_dictoffset */
2364 0, /* tp_init */
2365 0, /* tp_alloc */
2366 0, /* tp_new */
2367 0, /* tp_free */
2368 0, /* tp_is_gc */
2369 0, /* tp_bases */
2370 0, /* tp_mro */
2371 0, /* tp_cache */
2372 0, /* tp_subclasses */
2373 0, /* tp_weaklist */
2374 0, /* tp_del */
2375 0, /* tp_version_tag */
2376 0, /* tp_finalize */
2377 };
2378
2379
2380 static PyMethodDef bufferedreader_methods[] = {
2381 /* BufferedIOMixin methods */
2382 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2383 {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
2384 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2385 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2386 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2387 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2388 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2389 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
2390
2391 _IO__BUFFERED_READ_METHODDEF
2392 _IO__BUFFERED_PEEK_METHODDEF
2393 _IO__BUFFERED_READ1_METHODDEF
2394 _IO__BUFFERED_READINTO_METHODDEF
2395 _IO__BUFFERED_READINTO1_METHODDEF
2396 _IO__BUFFERED_READLINE_METHODDEF
2397 _IO__BUFFERED_SEEK_METHODDEF
2398 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2399 _IO__BUFFERED_TRUNCATE_METHODDEF
2400 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
2401 {NULL, NULL}
2402 };
2403
2404 static PyMemberDef bufferedreader_members[] = {
2405 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
2406 {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
2407 {NULL}
2408 };
2409
2410 static PyGetSetDef bufferedreader_getset[] = {
2411 {"closed", (getter)buffered_closed_get, NULL, NULL},
2412 {"name", (getter)buffered_name_get, NULL, NULL},
2413 {"mode", (getter)buffered_mode_get, NULL, NULL},
2414 {NULL}
2415 };
2416
2417
2418 PyTypeObject PyBufferedReader_Type = {
2419 PyVarObject_HEAD_INIT(NULL, 0)
2420 "_io.BufferedReader", /*tp_name*/
2421 sizeof(buffered), /*tp_basicsize*/
2422 0, /*tp_itemsize*/
2423 (destructor)buffered_dealloc, /*tp_dealloc*/
2424 0, /*tp_vectorcall_offset*/
2425 0, /*tp_getattr*/
2426 0, /*tp_setattr*/
2427 0, /*tp_as_async*/
2428 (reprfunc)buffered_repr, /*tp_repr*/
2429 0, /*tp_as_number*/
2430 0, /*tp_as_sequence*/
2431 0, /*tp_as_mapping*/
2432 0, /*tp_hash */
2433 0, /*tp_call*/
2434 0, /*tp_str*/
2435 0, /*tp_getattro*/
2436 0, /*tp_setattro*/
2437 0, /*tp_as_buffer*/
2438 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2439 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2440 _io_BufferedReader___init____doc__, /* tp_doc */
2441 (traverseproc)buffered_traverse, /* tp_traverse */
2442 (inquiry)buffered_clear, /* tp_clear */
2443 0, /* tp_richcompare */
2444 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2445 0, /* tp_iter */
2446 (iternextfunc)buffered_iternext, /* tp_iternext */
2447 bufferedreader_methods, /* tp_methods */
2448 bufferedreader_members, /* tp_members */
2449 bufferedreader_getset, /* tp_getset */
2450 0, /* tp_base */
2451 0, /* tp_dict */
2452 0, /* tp_descr_get */
2453 0, /* tp_descr_set */
2454 offsetof(buffered, dict), /* tp_dictoffset */
2455 _io_BufferedReader___init__, /* tp_init */
2456 0, /* tp_alloc */
2457 PyType_GenericNew, /* tp_new */
2458 0, /* tp_free */
2459 0, /* tp_is_gc */
2460 0, /* tp_bases */
2461 0, /* tp_mro */
2462 0, /* tp_cache */
2463 0, /* tp_subclasses */
2464 0, /* tp_weaklist */
2465 0, /* tp_del */
2466 0, /* tp_version_tag */
2467 0, /* tp_finalize */
2468 };
2469
2470
2471 static PyMethodDef bufferedwriter_methods[] = {
2472 /* BufferedIOMixin methods */
2473 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2474 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2475 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2476 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2477 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2478 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2479 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
2480
2481 _IO_BUFFEREDWRITER_WRITE_METHODDEF
2482 _IO__BUFFERED_TRUNCATE_METHODDEF
2483 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2484 _IO__BUFFERED_SEEK_METHODDEF
2485 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2486 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
2487 {NULL, NULL}
2488 };
2489
2490 static PyMemberDef bufferedwriter_members[] = {
2491 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
2492 {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
2493 {NULL}
2494 };
2495
2496 static PyGetSetDef bufferedwriter_getset[] = {
2497 {"closed", (getter)buffered_closed_get, NULL, NULL},
2498 {"name", (getter)buffered_name_get, NULL, NULL},
2499 {"mode", (getter)buffered_mode_get, NULL, NULL},
2500 {NULL}
2501 };
2502
2503
2504 PyTypeObject PyBufferedWriter_Type = {
2505 PyVarObject_HEAD_INIT(NULL, 0)
2506 "_io.BufferedWriter", /*tp_name*/
2507 sizeof(buffered), /*tp_basicsize*/
2508 0, /*tp_itemsize*/
2509 (destructor)buffered_dealloc, /*tp_dealloc*/
2510 0, /*tp_vectorcall_offset*/
2511 0, /*tp_getattr*/
2512 0, /*tp_setattr*/
2513 0, /*tp_as_async*/
2514 (reprfunc)buffered_repr, /*tp_repr*/
2515 0, /*tp_as_number*/
2516 0, /*tp_as_sequence*/
2517 0, /*tp_as_mapping*/
2518 0, /*tp_hash */
2519 0, /*tp_call*/
2520 0, /*tp_str*/
2521 0, /*tp_getattro*/
2522 0, /*tp_setattro*/
2523 0, /*tp_as_buffer*/
2524 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2525 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2526 _io_BufferedWriter___init____doc__, /* tp_doc */
2527 (traverseproc)buffered_traverse, /* tp_traverse */
2528 (inquiry)buffered_clear, /* tp_clear */
2529 0, /* tp_richcompare */
2530 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2531 0, /* tp_iter */
2532 0, /* tp_iternext */
2533 bufferedwriter_methods, /* tp_methods */
2534 bufferedwriter_members, /* tp_members */
2535 bufferedwriter_getset, /* tp_getset */
2536 0, /* tp_base */
2537 0, /* tp_dict */
2538 0, /* tp_descr_get */
2539 0, /* tp_descr_set */
2540 offsetof(buffered, dict), /* tp_dictoffset */
2541 _io_BufferedWriter___init__, /* tp_init */
2542 0, /* tp_alloc */
2543 PyType_GenericNew, /* tp_new */
2544 0, /* tp_free */
2545 0, /* tp_is_gc */
2546 0, /* tp_bases */
2547 0, /* tp_mro */
2548 0, /* tp_cache */
2549 0, /* tp_subclasses */
2550 0, /* tp_weaklist */
2551 0, /* tp_del */
2552 0, /* tp_version_tag */
2553 0, /* tp_finalize */
2554 };
2555
2556
2557 static PyMethodDef bufferedrwpair_methods[] = {
2558 {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2559 {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2560 {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2561 {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
2562 {"readinto1", (PyCFunction)bufferedrwpair_readinto1, METH_VARARGS},
2563
2564 {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2565 {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
2566
2567 {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2568 {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
2569
2570 {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2571 {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
2572
2573 {NULL, NULL}
2574 };
2575
2576 static PyGetSetDef bufferedrwpair_getset[] = {
2577 {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
2578 {NULL}
2579 };
2580
2581 PyTypeObject PyBufferedRWPair_Type = {
2582 PyVarObject_HEAD_INIT(NULL, 0)
2583 "_io.BufferedRWPair", /*tp_name*/
2584 sizeof(rwpair), /*tp_basicsize*/
2585 0, /*tp_itemsize*/
2586 (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
2587 0, /*tp_vectorcall_offset*/
2588 0, /*tp_getattr*/
2589 0, /*tp_setattr*/
2590 0, /*tp_as_async*/
2591 0, /*tp_repr*/
2592 0, /*tp_as_number*/
2593 0, /*tp_as_sequence*/
2594 0, /*tp_as_mapping*/
2595 0, /*tp_hash */
2596 0, /*tp_call*/
2597 0, /*tp_str*/
2598 0, /*tp_getattro*/
2599 0, /*tp_setattro*/
2600 0, /*tp_as_buffer*/
2601 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2602 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
2603 _io_BufferedRWPair___init____doc__, /* tp_doc */
2604 (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2605 (inquiry)bufferedrwpair_clear, /* tp_clear */
2606 0, /* tp_richcompare */
2607 offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
2608 0, /* tp_iter */
2609 0, /* tp_iternext */
2610 bufferedrwpair_methods, /* tp_methods */
2611 0, /* tp_members */
2612 bufferedrwpair_getset, /* tp_getset */
2613 0, /* tp_base */
2614 0, /* tp_dict */
2615 0, /* tp_descr_get */
2616 0, /* tp_descr_set */
2617 offsetof(rwpair, dict), /* tp_dictoffset */
2618 _io_BufferedRWPair___init__, /* tp_init */
2619 0, /* tp_alloc */
2620 PyType_GenericNew, /* tp_new */
2621 0, /* tp_free */
2622 0, /* tp_is_gc */
2623 0, /* tp_bases */
2624 0, /* tp_mro */
2625 0, /* tp_cache */
2626 0, /* tp_subclasses */
2627 0, /* tp_weaklist */
2628 0, /* tp_del */
2629 0, /* tp_version_tag */
2630 0, /* tp_finalize */
2631 };
2632
2633
2634 static PyMethodDef bufferedrandom_methods[] = {
2635 /* BufferedIOMixin methods */
2636 {"close", (PyCFunction)buffered_close, METH_NOARGS},
2637 {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2638 {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2639 {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2640 {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2641 {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2642 {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2643 {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
2644
2645 {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2646
2647 _IO__BUFFERED_SEEK_METHODDEF
2648 {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2649 _IO__BUFFERED_TRUNCATE_METHODDEF
2650 _IO__BUFFERED_READ_METHODDEF
2651 _IO__BUFFERED_READ1_METHODDEF
2652 _IO__BUFFERED_READINTO_METHODDEF
2653 _IO__BUFFERED_READINTO1_METHODDEF
2654 _IO__BUFFERED_READLINE_METHODDEF
2655 _IO__BUFFERED_PEEK_METHODDEF
2656 _IO_BUFFEREDWRITER_WRITE_METHODDEF
2657 {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
2658 {NULL, NULL}
2659 };
2660
2661 static PyMemberDef bufferedrandom_members[] = {
2662 {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
2663 {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
2664 {NULL}
2665 };
2666
2667 static PyGetSetDef bufferedrandom_getset[] = {
2668 {"closed", (getter)buffered_closed_get, NULL, NULL},
2669 {"name", (getter)buffered_name_get, NULL, NULL},
2670 {"mode", (getter)buffered_mode_get, NULL, NULL},
2671 {NULL}
2672 };
2673
2674
2675 PyTypeObject PyBufferedRandom_Type = {
2676 PyVarObject_HEAD_INIT(NULL, 0)
2677 "_io.BufferedRandom", /*tp_name*/
2678 sizeof(buffered), /*tp_basicsize*/
2679 0, /*tp_itemsize*/
2680 (destructor)buffered_dealloc, /*tp_dealloc*/
2681 0, /*tp_vectorcall_offset*/
2682 0, /*tp_getattr*/
2683 0, /*tp_setattr*/
2684 0, /*tp_as_async*/
2685 (reprfunc)buffered_repr, /*tp_repr*/
2686 0, /*tp_as_number*/
2687 0, /*tp_as_sequence*/
2688 0, /*tp_as_mapping*/
2689 0, /*tp_hash */
2690 0, /*tp_call*/
2691 0, /*tp_str*/
2692 0, /*tp_getattro*/
2693 0, /*tp_setattro*/
2694 0, /*tp_as_buffer*/
2695 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2696 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2697 _io_BufferedRandom___init____doc__, /* tp_doc */
2698 (traverseproc)buffered_traverse, /* tp_traverse */
2699 (inquiry)buffered_clear, /* tp_clear */
2700 0, /* tp_richcompare */
2701 offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2702 0, /* tp_iter */
2703 (iternextfunc)buffered_iternext, /* tp_iternext */
2704 bufferedrandom_methods, /* tp_methods */
2705 bufferedrandom_members, /* tp_members */
2706 bufferedrandom_getset, /* tp_getset */
2707 0, /* tp_base */
2708 0, /*tp_dict*/
2709 0, /* tp_descr_get */
2710 0, /* tp_descr_set */
2711 offsetof(buffered, dict), /*tp_dictoffset*/
2712 _io_BufferedRandom___init__, /* tp_init */
2713 0, /* tp_alloc */
2714 PyType_GenericNew, /* tp_new */
2715 0, /* tp_free */
2716 0, /* tp_is_gc */
2717 0, /* tp_bases */
2718 0, /* tp_mro */
2719 0, /* tp_cache */
2720 0, /* tp_subclasses */
2721 0, /* tp_weaklist */
2722 0, /* tp_del */
2723 0, /* tp_version_tag */
2724 0, /* tp_finalize */
2725 };
2726