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