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