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