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