Branch data Line data Source code
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 *
48 : 18 : _bufferediobase_readinto_generic(PyObject *self, Py_buffer *buffer, char readinto1)
49 : : {
50 : : Py_ssize_t len;
51 : : PyObject *data;
52 : :
53 : 18 : PyObject *attr = readinto1
54 : : ? &_Py_ID(read1)
55 [ + + ]: 18 : : &_Py_ID(read);
56 : 18 : data = _PyObject_CallMethod(self, attr, "n", buffer->len);
57 [ + + ]: 18 : if (data == NULL)
58 : 2 : return NULL;
59 : :
60 [ - + ]: 16 : if (!PyBytes_Check(data)) {
61 : 0 : Py_DECREF(data);
62 : 0 : PyErr_SetString(PyExc_TypeError, "read() should return bytes");
63 : 0 : return NULL;
64 : : }
65 : :
66 : 16 : len = PyBytes_GET_SIZE(data);
67 [ + + ]: 16 : if (len > buffer->len) {
68 : 1 : PyErr_Format(PyExc_ValueError,
69 : : "read() returned too much data: "
70 : : "%zd bytes requested, %zd returned",
71 : : buffer->len, len);
72 : 1 : Py_DECREF(data);
73 : 1 : return NULL;
74 : : }
75 : 15 : memcpy(buffer->buf, PyBytes_AS_STRING(data), len);
76 : :
77 : 15 : Py_DECREF(data);
78 : :
79 : 15 : 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 *
89 : 10 : _io__BufferedIOBase_readinto_impl(PyObject *self, Py_buffer *buffer)
90 : : /*[clinic end generated code: output=8c8cda6684af8038 input=00a6b9a38f29830a]*/
91 : : {
92 : 10 : 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 *
102 : 8 : _io__BufferedIOBase_readinto1_impl(PyObject *self, Py_buffer *buffer)
103 : : /*[clinic end generated code: output=358623e4fd2b69d3 input=ebad75b4aadfb9be]*/
104 : : {
105 : 8 : return _bufferediobase_readinto_generic(self, buffer, 1);
106 : : }
107 : :
108 : : static PyObject *
109 : 41 : bufferediobase_unsupported(const char *message)
110 : : {
111 : 41 : _PyIO_State *state = IO_STATE();
112 [ + - ]: 41 : if (state != NULL)
113 : 41 : PyErr_SetString(state->unsupported_operation, message);
114 : 41 : 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 *
127 : 2 : _io__BufferedIOBase_detach_impl(PyObject *self)
128 : : /*[clinic end generated code: output=754977c8d10ed88c input=822427fb58fe4169]*/
129 : : {
130 : 2 : 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 *
152 : 26 : bufferediobase_read(PyObject *self, PyObject *args)
153 : : {
154 : 26 : 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 *
165 : 3 : bufferediobase_read1(PyObject *self, PyObject *args)
166 : : {
167 : 3 : 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 *
180 : 4 : bufferediobase_write(PyObject *self, PyObject *args)
181 : : {
182 : 4 : 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
256 : 1238 : _enter_buffered_busy(buffered *self)
257 : : {
258 : : int relax_locking;
259 : : PyLockStatus st;
260 [ + + ]: 1238 : if (self->owner == PyThread_get_thread_ident()) {
261 : 1 : PyErr_Format(PyExc_RuntimeError,
262 : : "reentrant call inside %R", self);
263 : 1 : return 0;
264 : : }
265 : 1237 : relax_locking = _Py_IsFinalizing();
266 : 1237 : Py_BEGIN_ALLOW_THREADS
267 [ + - ]: 1237 : if (!relax_locking)
268 : 1237 : 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 : 0 : st = PyThread_acquire_lock_timed(self->lock, (PY_TIMEOUT_T)1e6, 0);
277 : : }
278 : 1237 : Py_END_ALLOW_THREADS
279 [ - + - - ]: 1236 : if (relax_locking && st != PY_LOCK_ACQUIRED) {
280 : 0 : 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 : 0 : ascii ? PyUnicode_AsUTF8(ascii) : "<ascii(self) failed>");
285 : : }
286 : 1236 : 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
367 : 324301 : buffered_dealloc(buffered *self)
368 : : {
369 : 324301 : self->finalizing = 1;
370 [ + + ]: 324301 : if (_PyIOBase_finalize((PyObject *) self) < 0)
371 : 6 : return;
372 : 324295 : _PyObject_GC_UNTRACK(self);
373 : 324295 : self->ok = 0;
374 [ + + ]: 324295 : if (self->weakreflist != NULL)
375 : 1 : PyObject_ClearWeakRefs((PyObject *)self);
376 [ + + ]: 324295 : Py_CLEAR(self->raw);
377 [ + + ]: 324295 : if (self->buffer) {
378 : 99 : PyMem_Free(self->buffer);
379 : 99 : self->buffer = NULL;
380 : : }
381 [ + + ]: 324295 : if (self->lock) {
382 : 324286 : PyThread_free_lock(self->lock);
383 : 324286 : self->lock = NULL;
384 : : }
385 [ + + ]: 324295 : Py_CLEAR(self->dict);
386 : 324295 : Py_TYPE(self)->tp_free((PyObject *)self);
387 : : }
388 : :
389 : : static PyObject *
390 : 12 : buffered_sizeof(buffered *self, PyObject *Py_UNUSED(ignored))
391 : : {
392 : : Py_ssize_t res;
393 : :
394 : 12 : res = _PyObject_SIZE(Py_TYPE(self));
395 [ + + ]: 12 : if (self->buffer)
396 : 9 : res += self->buffer_size;
397 : 12 : return PyLong_FromSsize_t(res);
398 : : }
399 : :
400 : : static int
401 : 139849 : buffered_traverse(buffered *self, visitproc visit, void *arg)
402 : : {
403 [ + + - + ]: 139849 : Py_VISIT(self->raw);
404 [ + + - + ]: 139849 : Py_VISIT(self->dict);
405 : 139849 : return 0;
406 : : }
407 : :
408 : : static int
409 : 71 : buffered_clear(buffered *self)
410 : : {
411 : 71 : self->ok = 0;
412 [ + - ]: 71 : Py_CLEAR(self->raw);
413 [ + + ]: 71 : Py_CLEAR(self->dict);
414 : 71 : 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 *
421 : 18574 : buffered_dealloc_warn(buffered *self, PyObject *source)
422 : : {
423 [ + - + - ]: 18574 : if (self->ok && self->raw) {
424 : : PyObject *r;
425 : 18574 : r = PyObject_CallMethodOneArg(self->raw, &_Py_ID(_dealloc_warn), source);
426 [ + + ]: 18574 : if (r)
427 : 8016 : Py_DECREF(r);
428 : : else
429 : 10558 : PyErr_Clear();
430 : : }
431 : 18574 : 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 *
443 : 279219 : buffered_simple_flush(buffered *self, PyObject *args)
444 : : {
445 [ - + - - ]: 279219 : CHECK_INITIALIZED(self)
446 : 279219 : return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(flush));
447 : : }
448 : :
449 : : static int
450 : 527864 : buffered_closed(buffered *self)
451 : : {
452 : : int closed;
453 : : PyObject *res;
454 [ - + - - ]: 527864 : CHECK_INITIALIZED_INT(self)
455 : 527864 : res = PyObject_GetAttr(self->raw, &_Py_ID(closed));
456 [ - + ]: 527864 : if (res == NULL)
457 : 0 : return -1;
458 : 527864 : closed = PyObject_IsTrue(res);
459 : 527864 : Py_DECREF(res);
460 : 527864 : return closed;
461 : : }
462 : :
463 : : static PyObject *
464 : 841501 : buffered_closed_get(buffered *self, void *context)
465 : : {
466 [ + + + + ]: 841501 : CHECK_INITIALIZED(self)
467 : 841478 : return PyObject_GetAttr(self->raw, &_Py_ID(closed));
468 : : }
469 : :
470 : : static PyObject *
471 : 328649 : buffered_close(buffered *self, PyObject *args)
472 : : {
473 : 328649 : PyObject *res = NULL, *exc = NULL, *val, *tb;
474 : : int r;
475 : :
476 [ - + - - ]: 328649 : CHECK_INITIALIZED(self)
477 [ - + - - ]: 328649 : if (!ENTER_BUFFERED(self))
478 : 0 : return NULL;
479 : :
480 : 328649 : r = buffered_closed(self);
481 [ - + ]: 328649 : if (r < 0)
482 : 0 : goto end;
483 [ + + ]: 328649 : if (r > 0) {
484 : 4431 : res = Py_None;
485 : 4431 : Py_INCREF(res);
486 : 4431 : goto end;
487 : : }
488 : :
489 [ + + ]: 324218 : if (self->finalizing) {
490 : 696 : PyObject *r = buffered_dealloc_warn(self, (PyObject *) self);
491 [ + - ]: 696 : if (r)
492 : 696 : Py_DECREF(r);
493 : : else
494 : 0 : PyErr_Clear();
495 : : }
496 : : /* flush() will most probably re-take the lock, so drop it first */
497 : 324218 : LEAVE_BUFFERED(self)
498 : 324218 : res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(flush));
499 [ - + - - ]: 324218 : if (!ENTER_BUFFERED(self))
500 : 0 : return NULL;
501 [ + + ]: 324218 : if (res == NULL)
502 : 20 : PyErr_Fetch(&exc, &val, &tb);
503 : : else
504 : 324198 : Py_DECREF(res);
505 : :
506 : 324218 : res = PyObject_CallMethodNoArgs(self->raw, &_Py_ID(close));
507 : :
508 [ + + ]: 324211 : if (self->buffer) {
509 : 324185 : PyMem_Free(self->buffer);
510 : 324185 : self->buffer = NULL;
511 : : }
512 : :
513 [ + + ]: 324211 : if (exc != NULL) {
514 : 20 : _PyErr_ChainExceptions(exc, val, tb);
515 [ + + ]: 20 : Py_CLEAR(res);
516 : : }
517 : :
518 : 324211 : self->read_end = 0;
519 : 324211 : self->pos = 0;
520 : :
521 : 328642 : end:
522 : 328642 : LEAVE_BUFFERED(self)
523 : 328642 : return res;
524 : : }
525 : :
526 : : /* detach */
527 : :
528 : : static PyObject *
529 : 11 : buffered_detach(buffered *self, PyObject *Py_UNUSED(ignored))
530 : : {
531 : : PyObject *raw, *res;
532 [ + + + - ]: 11 : CHECK_INITIALIZED(self)
533 : 8 : res = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(flush));
534 [ - + ]: 8 : if (res == NULL)
535 : 0 : return NULL;
536 : 8 : Py_DECREF(res);
537 : 8 : raw = self->raw;
538 : 8 : self->raw = NULL;
539 : 8 : self->detached = 1;
540 : 8 : self->ok = 0;
541 : 8 : return raw;
542 : : }
543 : :
544 : : /* Inquiries */
545 : :
546 : : static PyObject *
547 : 41602 : buffered_seekable(buffered *self, PyObject *Py_UNUSED(ignored))
548 : : {
549 [ - + - - ]: 41602 : CHECK_INITIALIZED(self)
550 : 41602 : return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(seekable));
551 : : }
552 : :
553 : : static PyObject *
554 : 19310 : buffered_readable(buffered *self, PyObject *Py_UNUSED(ignored))
555 : : {
556 [ - + - - ]: 19310 : CHECK_INITIALIZED(self)
557 : 19310 : return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(readable));
558 : : }
559 : :
560 : : static PyObject *
561 : 22608 : buffered_writable(buffered *self, PyObject *Py_UNUSED(ignored))
562 : : {
563 [ - + - - ]: 22608 : CHECK_INITIALIZED(self)
564 : 22608 : return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(writable));
565 : : }
566 : :
567 : : static PyObject *
568 : 3155 : buffered_name_get(buffered *self, void *context)
569 : : {
570 [ + + + - ]: 3155 : CHECK_INITIALIZED(self)
571 : 3151 : return PyObject_GetAttr(self->raw, &_Py_ID(name));
572 : : }
573 : :
574 : : static PyObject *
575 : 299 : buffered_mode_get(buffered *self, void *context)
576 : : {
577 [ - + - - ]: 299 : CHECK_INITIALIZED(self)
578 : 299 : return PyObject_GetAttr(self->raw, &_Py_ID(mode));
579 : : }
580 : :
581 : : /* Lower-level APIs */
582 : :
583 : : static PyObject *
584 : 53894 : buffered_fileno(buffered *self, PyObject *Py_UNUSED(ignored))
585 : : {
586 [ - + - - ]: 53894 : CHECK_INITIALIZED(self)
587 : 53894 : return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(fileno));
588 : : }
589 : :
590 : : static PyObject *
591 : 235 : buffered_isatty(buffered *self, PyObject *Py_UNUSED(ignored))
592 : : {
593 [ - + - - ]: 235 : CHECK_INITIALIZED(self)
594 : 235 : 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
623 : 13 : _set_BlockingIOError(const char *msg, Py_ssize_t written)
624 : : {
625 : : PyObject *err;
626 : 13 : PyErr_Clear();
627 : 13 : err = PyObject_CallFunction(PyExc_BlockingIOError, "isn",
628 : 13 : errno, msg, written);
629 [ + - ]: 13 : if (err)
630 : 13 : PyErr_SetObject(PyExc_BlockingIOError, err);
631 : 13 : Py_XDECREF(err);
632 : 13 : }
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 *
637 : 5 : _buffered_check_blocking_error(void)
638 : : {
639 : : PyObject *t, *v, *tb;
640 : : PyOSErrorObject *err;
641 : :
642 : 5 : PyErr_Fetch(&t, &v, &tb);
643 [ + - - + ]: 5 : if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
644 : 0 : PyErr_Restore(t, v, tb);
645 : 0 : return NULL;
646 : : }
647 : 5 : err = (PyOSErrorObject *) v;
648 : : /* TODO: sanity check (err->written >= 0) */
649 : 5 : PyErr_Restore(t, v, tb);
650 : 5 : return &err->written;
651 : : }
652 : :
653 : : static Py_off_t
654 : 416076 : _buffered_raw_tell(buffered *self)
655 : : {
656 : : Py_off_t n;
657 : : PyObject *res;
658 : 416076 : res = PyObject_CallMethodNoArgs(self->raw, &_Py_ID(tell));
659 [ + + ]: 416076 : if (res == NULL)
660 : 18606 : return -1;
661 : 397470 : n = PyNumber_AsOff_t(res, PyExc_ValueError);
662 : 397470 : Py_DECREF(res);
663 [ + + ]: 397470 : if (n < 0) {
664 [ + - ]: 9 : if (!PyErr_Occurred())
665 : 9 : PyErr_Format(PyExc_OSError,
666 : : "Raw stream returned invalid position %" PY_PRIdOFF,
667 : : (PY_OFF_T_COMPAT)n);
668 : 9 : return -1;
669 : : }
670 : 397461 : self->abs_pos = n;
671 : 397461 : return n;
672 : : }
673 : :
674 : : static Py_off_t
675 : 126208 : _buffered_raw_seek(buffered *self, Py_off_t target, int whence)
676 : : {
677 : : PyObject *res, *posobj, *whenceobj;
678 : : Py_off_t n;
679 : :
680 : 126208 : posobj = PyLong_FromOff_t(target);
681 [ - + ]: 126208 : if (posobj == NULL)
682 : 0 : return -1;
683 : 126208 : whenceobj = PyLong_FromLong(whence);
684 [ - + ]: 126208 : if (whenceobj == NULL) {
685 : 0 : Py_DECREF(posobj);
686 : 0 : return -1;
687 : : }
688 : 126208 : res = PyObject_CallMethodObjArgs(self->raw, &_Py_ID(seek),
689 : : posobj, whenceobj, NULL);
690 : 126208 : Py_DECREF(posobj);
691 : 126208 : Py_DECREF(whenceobj);
692 [ + + ]: 126208 : if (res == NULL)
693 : 26 : return -1;
694 : 126182 : n = PyNumber_AsOff_t(res, PyExc_ValueError);
695 : 126182 : Py_DECREF(res);
696 [ + + ]: 126182 : if (n < 0) {
697 [ + - ]: 4 : if (!PyErr_Occurred())
698 : 4 : PyErr_Format(PyExc_OSError,
699 : : "Raw stream returned invalid position %" PY_PRIdOFF,
700 : : (PY_OFF_T_COMPAT)n);
701 : 4 : return -1;
702 : : }
703 : 126178 : self->abs_pos = n;
704 : 126178 : return n;
705 : : }
706 : :
707 : : static int
708 : 324477 : _buffered_init(buffered *self)
709 : : {
710 : : Py_ssize_t n;
711 [ + + ]: 324477 : if (self->buffer_size <= 0) {
712 : 18 : PyErr_SetString(PyExc_ValueError,
713 : : "buffer size must be strictly positive");
714 : 18 : return -1;
715 : : }
716 [ + + ]: 324459 : if (self->buffer)
717 : 19 : PyMem_Free(self->buffer);
718 : 324459 : self->buffer = PyMem_Malloc(self->buffer_size);
719 [ + + ]: 324459 : if (self->buffer == NULL) {
720 : : PyErr_NoMemory();
721 : 3 : return -1;
722 : : }
723 [ + + ]: 324456 : if (self->lock)
724 : 16 : PyThread_free_lock(self->lock);
725 : 324456 : self->lock = PyThread_allocate_lock();
726 [ - + ]: 324456 : if (self->lock == NULL) {
727 : 0 : PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
728 : 0 : return -1;
729 : : }
730 : 324456 : self->owner = 0;
731 : : /* Find out whether buffer_size is a power of 2 */
732 : : /* XXX is this optimization useful? */
733 [ + + ]: 4230678 : for (n = self->buffer_size - 1; n & 1; n >>= 1)
734 : : ;
735 [ + + ]: 324456 : if (n == 0)
736 : 323929 : self->buffer_mask = self->buffer_size - 1;
737 : : else
738 : 527 : self->buffer_mask = 0;
739 [ + + ]: 324456 : if (_buffered_raw_tell(self) == -1)
740 : 18601 : PyErr_Clear();
741 : 324456 : 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
749 : 1567 : _PyIO_trap_eintr(void)
750 : : {
751 : : static PyObject *eintr_int = NULL;
752 : : PyObject *typ, *val, *tb;
753 : : PyOSErrorObject *env_err;
754 : :
755 [ + + ]: 1567 : if (eintr_int == NULL) {
756 : 58 : eintr_int = PyLong_FromLong(EINTR);
757 : : assert(eintr_int != NULL);
758 : : }
759 [ + + ]: 1567 : if (!PyErr_ExceptionMatches(PyExc_OSError))
760 : 655 : return 0;
761 : 912 : PyErr_Fetch(&typ, &val, &tb);
762 : 912 : PyErr_NormalizeException(&typ, &val, &tb);
763 : 912 : env_err = (PyOSErrorObject *) val;
764 : : assert(env_err != NULL);
765 [ + + - + ]: 923 : if (env_err->myerrno != NULL &&
766 : 11 : PyObject_RichCompareBool(env_err->myerrno, eintr_int, Py_EQ) > 0) {
767 : 0 : Py_DECREF(typ);
768 : 0 : Py_DECREF(val);
769 : 0 : Py_XDECREF(tb);
770 : 0 : return 1;
771 : : }
772 : : /* This silences any error set by PyObject_RichCompareBool() */
773 : 912 : PyErr_Restore(typ, val, tb);
774 : 912 : return 0;
775 : : }
776 : :
777 : : /*
778 : : * Shared methods and wrappers
779 : : */
780 : :
781 : : static PyObject *
782 : 282818 : buffered_flush_and_rewind_unlocked(buffered *self)
783 : : {
784 : : PyObject *res;
785 : :
786 : 282818 : res = _bufferedwriter_flush_unlocked(self);
787 [ + + ]: 282818 : if (res == NULL)
788 : 15 : return NULL;
789 : 282803 : Py_DECREF(res);
790 : :
791 [ + + ]: 282803 : 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 [ + - + + : 41365 : n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
+ - - + +
- ]
796 : 41365 : _bufferedreader_reset_buf(self);
797 [ - + ]: 41365 : if (n == -1)
798 : 0 : return NULL;
799 : : }
800 : 282803 : Py_RETURN_NONE;
801 : : }
802 : :
803 : : static PyObject *
804 : 249475 : buffered_flush(buffered *self, PyObject *args)
805 : : {
806 : : PyObject *res;
807 : :
808 [ - + - - ]: 249475 : CHECK_INITIALIZED(self)
809 [ + + + + : 249475 : CHECK_CLOSED(self, "flush of closed file")
- + - + +
+ + - + -
+ - ]
810 : :
811 [ + + + - ]: 249467 : if (!ENTER_BUFFERED(self))
812 : 0 : return NULL;
813 : 249467 : res = buffered_flush_and_rewind_unlocked(self);
814 : 249467 : LEAVE_BUFFERED(self)
815 : :
816 : 249467 : 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 *
827 : 8872 : _io__Buffered_peek_impl(buffered *self, Py_ssize_t size)
828 : : /*[clinic end generated code: output=ba7a097ca230102b input=37ffb97d06ff4adb]*/
829 : : {
830 : 8872 : PyObject *res = NULL;
831 : :
832 [ - + - - ]: 8872 : CHECK_INITIALIZED(self)
833 [ + + + + : 8872 : CHECK_CLOSED(self, "peek of closed file")
- + - + +
- + - + -
+ - ]
834 : :
835 [ - + - - ]: 8866 : if (!ENTER_BUFFERED(self))
836 : 0 : return NULL;
837 : :
838 [ + + ]: 8866 : if (self->writable) {
839 : 5948 : res = buffered_flush_and_rewind_unlocked(self);
840 [ - + ]: 5948 : if (res == NULL)
841 : 0 : goto end;
842 [ + - ]: 5948 : Py_CLEAR(res);
843 : : }
844 : 8866 : res = _bufferedreader_peek_unlocked(self);
845 : :
846 : 8866 : end:
847 : 8866 : LEAVE_BUFFERED(self)
848 : 8866 : 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 *
858 : 365463 : _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 [ + + - + ]: 365463 : CHECK_INITIALIZED(self)
864 [ + + ]: 365458 : if (n < -1) {
865 : 2 : PyErr_SetString(PyExc_ValueError,
866 : : "read length must be non-negative or -1");
867 : 2 : return NULL;
868 : : }
869 : :
870 [ + + + + : 365456 : CHECK_CLOSED(self, "read of closed file")
- + - + +
- + - + -
+ - ]
871 : :
872 [ + + ]: 365454 : if (n == -1) {
873 : : /* The number of bytes is unspecified, read until the end of stream */
874 [ - + - - ]: 181127 : if (!ENTER_BUFFERED(self))
875 : 0 : return NULL;
876 : 181127 : res = _bufferedreader_read_all(self);
877 : : }
878 : : else {
879 : 184327 : res = _bufferedreader_read_fast(self, n);
880 [ + + ]: 184327 : if (res != Py_None)
881 : 103840 : return res;
882 : 80487 : Py_DECREF(res);
883 [ + + + - ]: 80487 : if (!ENTER_BUFFERED(self))
884 : 0 : return NULL;
885 : 80487 : res = _bufferedreader_read_generic(self, n);
886 : : }
887 : :
888 : 261614 : LEAVE_BUFFERED(self)
889 : 261614 : 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 *
899 : 35792 : _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 : 35792 : PyObject *res = NULL;
904 : :
905 [ - + - - ]: 35792 : CHECK_INITIALIZED(self)
906 [ + + ]: 35792 : if (n < 0) {
907 : 13 : n = self->buffer_size;
908 : : }
909 : :
910 [ + + + + : 35792 : CHECK_CLOSED(self, "read of closed file")
- + - + +
- + - + -
+ - ]
911 : :
912 [ + + ]: 35784 : if (n == 0)
913 : 4 : 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 [ + - + - : 35780 : have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
+ + ]
919 [ + + ]: 35780 : if (have > 0) {
920 : 615 : n = Py_MIN(have, n);
921 : 615 : res = _bufferedreader_read_fast(self, n);
922 : : assert(res != Py_None);
923 : 615 : return res;
924 : : }
925 : 35165 : res = PyBytes_FromStringAndSize(NULL, n);
926 [ - + ]: 35165 : if (res == NULL)
927 : 0 : return NULL;
928 [ - + - - ]: 35165 : if (!ENTER_BUFFERED(self)) {
929 : 0 : Py_DECREF(res);
930 : 0 : return NULL;
931 : : }
932 : 35165 : _bufferedreader_reset_buf(self);
933 : 35165 : r = _bufferedreader_raw_read(self, PyBytes_AS_STRING(res), n);
934 : 35161 : LEAVE_BUFFERED(self)
935 [ + + ]: 35161 : if (r == -1) {
936 : 4 : Py_DECREF(res);
937 : 4 : return NULL;
938 : : }
939 [ - + ]: 35157 : if (r == -2)
940 : 0 : r = 0;
941 [ + + ]: 35157 : if (n > r)
942 : 15041 : _PyBytes_Resize(&res, r);
943 : 35157 : return res;
944 : : }
945 : :
946 : : static PyObject *
947 : 132949 : _buffered_readinto_generic(buffered *self, Py_buffer *buffer, char readinto1)
948 : : {
949 : 132949 : Py_ssize_t n, written = 0, remaining;
950 : 132949 : PyObject *res = NULL;
951 : :
952 [ - + - - ]: 132949 : CHECK_INITIALIZED(self)
953 [ + + + + : 132949 : CHECK_CLOSED(self, "readinto of closed file")
- + - + +
- + - + -
+ - ]
954 : :
955 [ + - + - : 132944 : n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
+ + ]
956 [ + + ]: 132944 : if (n > 0) {
957 [ + + ]: 119946 : if (n >= buffer->len) {
958 : 119802 : memcpy(buffer->buf, self->buffer + self->pos, buffer->len);
959 : 119802 : self->pos += buffer->len;
960 : 119802 : return PyLong_FromSsize_t(buffer->len);
961 : : }
962 : 144 : memcpy(buffer->buf, self->buffer + self->pos, n);
963 : 144 : self->pos += n;
964 : 144 : written = n;
965 : : }
966 : :
967 [ - + - - ]: 13142 : if (!ENTER_BUFFERED(self))
968 : 0 : return NULL;
969 : :
970 [ + + ]: 13142 : if (self->writable) {
971 : 2779 : res = buffered_flush_and_rewind_unlocked(self);
972 [ - + ]: 2779 : if (res == NULL)
973 : 0 : goto end;
974 [ + - ]: 2779 : Py_CLEAR(res);
975 : : }
976 : :
977 : 13142 : _bufferedreader_reset_buf(self);
978 : 13142 : self->pos = 0;
979 : :
980 : 13142 : for (remaining = buffer->len - written;
981 [ + + ]: 18767 : remaining > 0;
982 : 5625 : written += n, remaining -= n) {
983 : : /* If remaining bytes is larger than internal buffer size, copy
984 : : * directly into caller's buffer. */
985 [ + + ]: 16816 : if (remaining > self->buffer_size) {
986 : 12860 : 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 [ + + + + ]: 3956 : else if (!(readinto1 && written)) {
993 : 3952 : n = _bufferedreader_fill_buffer(self);
994 [ + + ]: 3952 : if (n > 0) {
995 [ + + ]: 1174 : if (n > remaining)
996 : 1162 : n = remaining;
997 : 1174 : memcpy((char *) buffer->buf + written,
998 : 1174 : self->buffer + self->pos, n);
999 : 1174 : self->pos += n;
1000 : 1174 : continue; /* short circuit */
1001 : : }
1002 : : }
1003 : : else
1004 : 4 : n = 0;
1005 : :
1006 [ + + + + : 15642 : if (n == 0 || (n == -2 && written > 0))
- + ]
1007 : : break;
1008 [ - + ]: 4453 : if (n < 0) {
1009 [ # # ]: 0 : if (n == -2) {
1010 : 0 : Py_INCREF(Py_None);
1011 : 0 : res = Py_None;
1012 : : }
1013 : 0 : goto end;
1014 : : }
1015 : :
1016 : : /* At most one read in readinto1 mode */
1017 [ + + ]: 4453 : if (readinto1) {
1018 : 2 : written += n;
1019 : 2 : break;
1020 : : }
1021 : : }
1022 : 13142 : res = PyLong_FromSsize_t(written);
1023 : :
1024 : 13142 : end:
1025 : 13142 : LEAVE_BUFFERED(self);
1026 : 13142 : 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 *
1036 : 132935 : _io__Buffered_readinto_impl(buffered *self, Py_buffer *buffer)
1037 : : /*[clinic end generated code: output=bcb376580b1d8170 input=ed6b98b7a20a3008]*/
1038 : : {
1039 : 132935 : 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 *
1049 : 14 : _io__Buffered_readinto1_impl(buffered *self, Py_buffer *buffer)
1050 : : /*[clinic end generated code: output=6e5c6ac5868205d6 input=4455c5d55fdf1687]*/
1051 : : {
1052 : 14 : return _buffered_readinto_generic(self, buffer, 1);
1053 : : }
1054 : :
1055 : :
1056 : : static PyObject *
1057 : 48105 : _buffered_readline(buffered *self, Py_ssize_t limit)
1058 : : {
1059 : 48105 : PyObject *res = NULL;
1060 : 48105 : PyObject *chunks = NULL;
1061 : : Py_ssize_t n;
1062 : : const char *start, *s, *end;
1063 : :
1064 [ + + + + : 48105 : 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 [ + - + - : 48101 : n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
+ + ]
1070 [ + + + + ]: 48101 : if (limit >= 0 && n > limit)
1071 : 458 : n = limit;
1072 : 48101 : start = self->buffer + self->pos;
1073 : 48101 : s = memchr(start, '\n', n);
1074 [ + + ]: 48101 : if (s != NULL) {
1075 : 25273 : res = PyBytes_FromStringAndSize(start, s - start + 1);
1076 [ + - ]: 25273 : if (res != NULL)
1077 : 25273 : self->pos += s - start + 1;
1078 : 25273 : goto end_unlocked;
1079 : : }
1080 [ + + ]: 22828 : if (n == limit) {
1081 : 192 : res = PyBytes_FromStringAndSize(start, n);
1082 [ + - ]: 192 : if (res != NULL)
1083 : 192 : self->pos += n;
1084 : 192 : goto end_unlocked;
1085 : : }
1086 : :
1087 [ - + - - ]: 22636 : if (!ENTER_BUFFERED(self))
1088 : 0 : goto end_unlocked;
1089 : :
1090 : : /* Now we try to get some more from the raw stream */
1091 : 22636 : chunks = PyList_New(0);
1092 [ - + ]: 22636 : if (chunks == NULL)
1093 : 0 : goto end;
1094 [ + + ]: 22636 : if (n > 0) {
1095 : 3231 : res = PyBytes_FromStringAndSize(start, n);
1096 [ - + ]: 3231 : if (res == NULL)
1097 : 0 : goto end;
1098 [ - + ]: 3231 : if (PyList_Append(chunks, res) < 0) {
1099 [ # # ]: 0 : Py_CLEAR(res);
1100 : 0 : goto end;
1101 : : }
1102 [ + - ]: 3231 : Py_CLEAR(res);
1103 : 3231 : self->pos += n;
1104 [ + + ]: 3231 : if (limit >= 0)
1105 : 1 : limit -= n;
1106 : : }
1107 [ + + ]: 22636 : if (self->writable) {
1108 : 499 : PyObject *r = buffered_flush_and_rewind_unlocked(self);
1109 [ - + ]: 499 : if (r == NULL)
1110 : 0 : goto end;
1111 : 499 : Py_DECREF(r);
1112 : : }
1113 : :
1114 : : for (;;) {
1115 : 29706 : _bufferedreader_reset_buf(self);
1116 : 29706 : n = _bufferedreader_fill_buffer(self);
1117 [ + + ]: 29705 : if (n == -1)
1118 : 5 : goto end;
1119 [ + + ]: 29700 : if (n <= 0)
1120 : 6840 : break;
1121 [ + + + + ]: 22860 : if (limit >= 0 && n > limit)
1122 : 14 : n = limit;
1123 : 22860 : start = self->buffer;
1124 : 22860 : end = start + n;
1125 : 22860 : s = start;
1126 [ + + ]: 30209152 : while (s < end) {
1127 [ + + ]: 30202067 : if (*s++ == '\n') {
1128 : 15775 : res = PyBytes_FromStringAndSize(start, s - start);
1129 [ - + ]: 15775 : if (res == NULL)
1130 : 0 : goto end;
1131 : 15775 : self->pos = s - start;
1132 : 15775 : goto found;
1133 : : }
1134 : : }
1135 : 7085 : res = PyBytes_FromStringAndSize(start, n);
1136 [ - + ]: 7085 : if (res == NULL)
1137 : 0 : goto end;
1138 [ + + ]: 7085 : if (n == limit) {
1139 : 15 : self->pos = n;
1140 : 15 : break;
1141 : : }
1142 [ - + ]: 7070 : if (PyList_Append(chunks, res) < 0) {
1143 [ # # ]: 0 : Py_CLEAR(res);
1144 : 0 : goto end;
1145 : : }
1146 [ + - ]: 7070 : Py_CLEAR(res);
1147 [ + + ]: 7070 : if (limit >= 0)
1148 : 318 : limit -= n;
1149 : : }
1150 : 22630 : found:
1151 [ + + - + ]: 22630 : if (res != NULL && PyList_Append(chunks, res) < 0) {
1152 [ # # ]: 0 : Py_CLEAR(res);
1153 : 0 : goto end;
1154 : : }
1155 : 22630 : Py_XSETREF(res, _PyBytes_Join((PyObject *)&_Py_SINGLETON(bytes_empty), chunks));
1156 : :
1157 : 22635 : end:
1158 : 22635 : LEAVE_BUFFERED(self)
1159 : 48100 : end_unlocked:
1160 : 48100 : Py_XDECREF(chunks);
1161 : 48100 : 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 *
1171 : 22140 : _io__Buffered_readline_impl(buffered *self, Py_ssize_t size)
1172 : : /*[clinic end generated code: output=24dd2aa6e33be83c input=673b6240e315ef8a]*/
1173 : : {
1174 [ - + - - ]: 22140 : CHECK_INITIALIZED(self)
1175 : 22140 : return _buffered_readline(self, size);
1176 : : }
1177 : :
1178 : :
1179 : : static PyObject *
1180 : 85990 : buffered_tell(buffered *self, PyObject *Py_UNUSED(ignored))
1181 : : {
1182 : : Py_off_t pos;
1183 : :
1184 [ - + - - ]: 85990 : CHECK_INITIALIZED(self)
1185 : 85990 : pos = _buffered_raw_tell(self);
1186 [ + + ]: 85990 : if (pos == -1)
1187 : 14 : return NULL;
1188 [ + + + + : 85976 : pos -= RAW_OFFSET(self);
+ + + + +
- ]
1189 : : /* TODO: sanity check (pos >= 0) */
1190 : 85976 : 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 *
1201 : 111182 : _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 : 111182 : PyObject *res = NULL;
1206 : :
1207 [ - + - - ]: 111182 : CHECK_INITIALIZED(self)
1208 : :
1209 : : /* Do some error checking instead of trusting OS 'seek()'
1210 : : ** error detection, just in case.
1211 : : */
1212 [ + + + + ]: 111182 : if ((whence < 0 || whence >2)
1213 : : #ifdef SEEK_HOLE
1214 [ + - ]: 7 : && (whence != SEEK_HOLE)
1215 : : #endif
1216 : : #ifdef SEEK_DATA
1217 [ + + ]: 7 : && (whence != SEEK_DATA)
1218 : : #endif
1219 : : ) {
1220 : 6 : PyErr_Format(PyExc_ValueError,
1221 : : "whence value %d unsupported", whence);
1222 : 6 : return NULL;
1223 : : }
1224 : :
1225 [ + + + + : 111176 : CHECK_CLOSED(self, "seek of closed file")
- + - + +
+ + - + -
+ - ]
1226 : :
1227 [ + + ]: 111172 : if (_PyIOBase_check_seekable(self->raw, Py_True) == NULL)
1228 : 5 : return NULL;
1229 : :
1230 : 111167 : target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1231 [ + + + + ]: 111167 : if (target == -1 && PyErr_Occurred())
1232 : 5 : 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 [ + + + + : 111162 : 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 [ + - ]: 84266 : current = RAW_TELL(self);
1247 [ + - + - : 84266 : avail = READAHEAD(self);
+ + ]
1248 [ + + ]: 84266 : if (avail > 0) {
1249 : : Py_off_t offset;
1250 [ + + ]: 31204 : if (whence == 0)
1251 [ + - - + : 24723 : offset = target - (current - RAW_OFFSET(self));
- - - - +
- ]
1252 : : else
1253 : 6481 : offset = target;
1254 [ + + + + ]: 31204 : if (offset >= -self->pos && offset <= avail) {
1255 : 26355 : self->pos += offset;
1256 : 26355 : return PyLong_FromOff_t(current - avail + offset);
1257 : : }
1258 : : }
1259 : : }
1260 : :
1261 [ - + - - ]: 84807 : if (!ENTER_BUFFERED(self))
1262 : 0 : return NULL;
1263 : :
1264 : : /* Fallback: invoke raw seek() method and clear buffer */
1265 [ + + ]: 84807 : if (self->writable) {
1266 : 69215 : res = _bufferedwriter_flush_unlocked(self);
1267 [ - + ]: 69215 : if (res == NULL)
1268 : 0 : goto end;
1269 [ + - ]: 69215 : Py_CLEAR(res);
1270 : : }
1271 : :
1272 : : /* TODO: align on block boundary and read buffer if needed? */
1273 [ + + ]: 84807 : if (whence == 1)
1274 [ + + + + : 29194 : target -= RAW_OFFSET(self);
+ + - + +
- ]
1275 : 84807 : n = _buffered_raw_seek(self, target, whence);
1276 [ + + ]: 84807 : if (n == -1)
1277 : 30 : goto end;
1278 : 84777 : self->raw_pos = -1;
1279 : 84777 : res = PyLong_FromOff_t(n);
1280 [ - + + + ]: 84777 : if (res != NULL && self->readable)
1281 : 61237 : _bufferedreader_reset_buf(self);
1282 : :
1283 : 23540 : end:
1284 : 84807 : LEAVE_BUFFERED(self)
1285 : 84807 : 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 *
1295 : 5642 : _io__Buffered_truncate_impl(buffered *self, PyObject *pos)
1296 : : /*[clinic end generated code: output=667ca03c60c270de input=8a1be34d57cca2d3]*/
1297 : : {
1298 : 5642 : PyObject *res = NULL;
1299 : :
1300 [ - + - - ]: 5642 : CHECK_INITIALIZED(self)
1301 [ + + + + : 5642 : CHECK_CLOSED(self, "truncate of closed file")
- + - + +
+ + - + -
+ - ]
1302 [ + + ]: 5638 : if (!self->writable) {
1303 : 6 : return bufferediobase_unsupported("truncate");
1304 : : }
1305 [ - + - - ]: 5632 : if (!ENTER_BUFFERED(self))
1306 : 0 : return NULL;
1307 : :
1308 : 5632 : res = buffered_flush_and_rewind_unlocked(self);
1309 [ - + ]: 5632 : if (res == NULL) {
1310 : 0 : goto end;
1311 : : }
1312 [ + - ]: 5632 : Py_CLEAR(res);
1313 : :
1314 : 5632 : res = PyObject_CallMethodOneArg(self->raw, &_Py_ID(truncate), pos);
1315 [ + + ]: 5632 : if (res == NULL)
1316 : 2 : goto end;
1317 : : /* Reset cached position */
1318 [ + - ]: 5630 : if (_buffered_raw_tell(self) == -1)
1319 : 0 : PyErr_Clear();
1320 : :
1321 : 5630 : end:
1322 : 5632 : LEAVE_BUFFERED(self)
1323 : 5632 : return res;
1324 : : }
1325 : :
1326 : : static PyObject *
1327 : 26813 : buffered_iternext(buffered *self)
1328 : : {
1329 : : PyObject *line;
1330 : : PyTypeObject *tp;
1331 : :
1332 [ - + - - ]: 26813 : CHECK_INITIALIZED(self);
1333 : :
1334 : 26813 : tp = Py_TYPE(self);
1335 [ + + + + ]: 26813 : if (tp == &PyBufferedReader_Type ||
1336 : : tp == &PyBufferedRandom_Type) {
1337 : : /* Skip method call overhead for speed */
1338 : 25965 : line = _buffered_readline(self, -1);
1339 : : }
1340 : : else {
1341 : 848 : line = PyObject_CallMethodNoArgs((PyObject *)self,
1342 : : &_Py_ID(readline));
1343 [ + - - + ]: 848 : if (line && !PyBytes_Check(line)) {
1344 : 0 : PyErr_Format(PyExc_OSError,
1345 : : "readline() should have returned a bytes object, "
1346 : 0 : "not '%.200s'", Py_TYPE(line)->tp_name);
1347 : 0 : Py_DECREF(line);
1348 : 0 : return NULL;
1349 : : }
1350 : : }
1351 : :
1352 [ + + ]: 26813 : if (line == NULL)
1353 : 2 : return NULL;
1354 : :
1355 [ + + ]: 26811 : if (PyBytes_GET_SIZE(line) == 0) {
1356 : : /* Reached EOF or would have blocked */
1357 : 97 : Py_DECREF(line);
1358 : 97 : return NULL;
1359 : : }
1360 : :
1361 : 26714 : return line;
1362 : : }
1363 : :
1364 : : static PyObject *
1365 : 130 : buffered_repr(buffered *self)
1366 : : {
1367 : : PyObject *nameobj, *res;
1368 : :
1369 [ + + ]: 130 : if (_PyObject_LookupAttr((PyObject *) self, &_Py_ID(name), &nameobj) < 0) {
1370 [ - + ]: 3 : if (!PyErr_ExceptionMatches(PyExc_ValueError)) {
1371 : 0 : return NULL;
1372 : : }
1373 : : /* Ignore ValueError raised if the underlying stream was detached */
1374 : 3 : PyErr_Clear();
1375 : : }
1376 [ + + ]: 130 : if (nameobj == NULL) {
1377 : 31 : res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1378 : : }
1379 : : else {
1380 : 99 : int status = Py_ReprEnter((PyObject *)self);
1381 : 99 : res = NULL;
1382 [ + + ]: 99 : if (status == 0) {
1383 : 96 : res = PyUnicode_FromFormat("<%s name=%R>",
1384 : 96 : Py_TYPE(self)->tp_name, nameobj);
1385 : 96 : Py_ReprLeave((PyObject *)self);
1386 : : }
1387 [ + - ]: 3 : else if (status > 0) {
1388 : 3 : PyErr_Format(PyExc_RuntimeError,
1389 : : "reentrant call inside %s.__repr__",
1390 : 3 : Py_TYPE(self)->tp_name);
1391 : : }
1392 : 99 : Py_DECREF(nameobj);
1393 : : }
1394 : 130 : return res;
1395 : : }
1396 : :
1397 : : /*
1398 : : * class BufferedReader
1399 : : */
1400 : :
1401 : 766138 : static void _bufferedreader_reset_buf(buffered *self)
1402 : : {
1403 : 766138 : self->read_end = -1;
1404 : 766138 : }
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
1415 : 263668 : _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 : 263668 : self->ok = 0;
1420 : 263668 : self->detached = 0;
1421 : :
1422 [ - + ]: 263668 : if (_PyIOBase_check_readable(raw, Py_True) == NULL)
1423 : 0 : return -1;
1424 : :
1425 : 263668 : Py_INCREF(raw);
1426 : 263668 : Py_XSETREF(self->raw, raw);
1427 : 263668 : self->buffer_size = buffer_size;
1428 : 263668 : self->readable = 1;
1429 : 263668 : self->writable = 0;
1430 : :
1431 [ + + ]: 263668 : if (_buffered_init(self) < 0)
1432 : 7 : return -1;
1433 : 263661 : _bufferedreader_reset_buf(self);
1434 : :
1435 [ + + + + ]: 526886 : self->fast_closed_checks = (Py_IS_TYPE(self, &PyBufferedReader_Type) &&
1436 : 263225 : Py_IS_TYPE(raw, &PyFileIO_Type));
1437 : :
1438 : 263661 : self->ok = 1;
1439 : 263661 : return 0;
1440 : : }
1441 : :
1442 : : static Py_ssize_t
1443 : 198247 : _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 [ - + ]: 198247 : if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1450 : 0 : return -1;
1451 : 198247 : memobj = PyMemoryView_FromBuffer(&buf);
1452 [ - + ]: 198247 : if (memobj == NULL)
1453 : 0 : 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 : 198247 : res = PyObject_CallMethodOneArg(self->raw, &_Py_ID(readinto), memobj);
1461 [ + + - + ]: 198242 : } while (res == NULL && _PyIO_trap_eintr());
1462 : 198242 : Py_DECREF(memobj);
1463 [ + + ]: 198242 : if (res == NULL)
1464 : 1499 : return -1;
1465 [ + + ]: 196743 : if (res == Py_None) {
1466 : : /* Non-blocking stream would have blocked. Special return code! */
1467 : 6 : Py_DECREF(res);
1468 : 6 : return -2;
1469 : : }
1470 : 196737 : n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1471 : 196737 : Py_DECREF(res);
1472 : :
1473 [ + + + + ]: 196737 : if (n == -1 && PyErr_Occurred()) {
1474 : 1 : _PyErr_FormatFromCause(
1475 : : PyExc_OSError,
1476 : : "raw readinto() failed"
1477 : : );
1478 : 1 : return -1;
1479 : : }
1480 : :
1481 [ + + + + ]: 196736 : if (n < 0 || n > len) {
1482 : 2 : PyErr_Format(PyExc_OSError,
1483 : : "raw readinto() returned invalid length %zd "
1484 : : "(should have been between 0 and %zd)", n, len);
1485 : 2 : return -1;
1486 : : }
1487 [ + + + - ]: 196734 : if (n > 0 && self->abs_pos != -1)
1488 : 153096 : self->abs_pos += n;
1489 : 196734 : return n;
1490 : : }
1491 : :
1492 : : static Py_ssize_t
1493 : 96561 : _bufferedreader_fill_buffer(buffered *self)
1494 : : {
1495 : : Py_ssize_t start, len, n;
1496 [ + - + + ]: 96561 : if (VALID_READ_BUFFER(self))
1497 : 55886 : start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1498 : : else
1499 : 40675 : start = 0;
1500 : 96561 : len = self->buffer_size - start;
1501 : 96561 : n = _bufferedreader_raw_read(self, self->buffer + start, len);
1502 [ + + ]: 96560 : if (n <= 0)
1503 : 22503 : return n;
1504 : 74057 : self->read_end = start + n;
1505 : 74057 : self->raw_pos = start + n;
1506 : 74057 : return n;
1507 : : }
1508 : :
1509 : : static PyObject *
1510 : 181127 : _bufferedreader_read_all(buffered *self)
1511 : : {
1512 : : Py_ssize_t current_size;
1513 : 181127 : PyObject *res = NULL, *data = NULL, *tmp = NULL, *chunks = NULL, *readall;
1514 : :
1515 : : /* First copy what we have in the current buffer. */
1516 [ + - + - : 181127 : current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
+ + ]
1517 [ + + ]: 181127 : if (current_size) {
1518 : 4018 : data = PyBytes_FromStringAndSize(
1519 : 2009 : self->buffer + self->pos, current_size);
1520 [ - + ]: 2009 : if (data == NULL)
1521 : 0 : return NULL;
1522 : 2009 : self->pos += current_size;
1523 : : }
1524 : : /* We're going past the buffer's bounds, flush it */
1525 [ + + ]: 181127 : if (self->writable) {
1526 : 911 : tmp = buffered_flush_and_rewind_unlocked(self);
1527 [ - + ]: 911 : if (tmp == NULL)
1528 : 0 : goto cleanup;
1529 [ + - ]: 911 : Py_CLEAR(tmp);
1530 : : }
1531 : 181127 : _bufferedreader_reset_buf(self);
1532 : :
1533 [ - + ]: 181127 : if (_PyObject_LookupAttr(self->raw, &_Py_ID(readall), &readall) < 0) {
1534 : 0 : goto cleanup;
1535 : : }
1536 [ + + ]: 181127 : if (readall) {
1537 : 180832 : tmp = _PyObject_CallNoArgs(readall);
1538 : 180832 : Py_DECREF(readall);
1539 [ + + ]: 180832 : if (tmp == NULL)
1540 : 6 : goto cleanup;
1541 [ + + - + ]: 180826 : if (tmp != Py_None && !PyBytes_Check(tmp)) {
1542 : 0 : PyErr_SetString(PyExc_TypeError, "readall() should return bytes");
1543 : 0 : goto cleanup;
1544 : : }
1545 [ + + ]: 180826 : if (current_size == 0) {
1546 : 178823 : res = tmp;
1547 : : } else {
1548 [ + + ]: 2003 : if (tmp != Py_None) {
1549 : 2001 : PyBytes_Concat(&data, tmp);
1550 : : }
1551 : 2003 : res = data;
1552 : : }
1553 : 180826 : goto cleanup;
1554 : : }
1555 : :
1556 : 295 : chunks = PyList_New(0);
1557 [ + - ]: 295 : if (chunks == NULL)
1558 : 0 : goto cleanup;
1559 : :
1560 : : while (1) {
1561 [ + + ]: 532 : if (data) {
1562 [ - + ]: 243 : if (PyList_Append(chunks, data) < 0)
1563 : 0 : goto cleanup;
1564 [ + - ]: 243 : Py_CLEAR(data);
1565 : : }
1566 : :
1567 : : /* Read until EOF or until read() would block. */
1568 : 532 : data = PyObject_CallMethodNoArgs(self->raw, &_Py_ID(read));
1569 [ + + ]: 532 : if (data == NULL)
1570 : 36 : goto cleanup;
1571 [ + - - + ]: 496 : if (data != Py_None && !PyBytes_Check(data)) {
1572 : 0 : PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1573 : 0 : goto cleanup;
1574 : : }
1575 [ + - + + ]: 496 : if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1576 [ + + ]: 259 : if (current_size == 0) {
1577 : 16 : res = data;
1578 : 16 : goto cleanup;
1579 : : }
1580 : : else {
1581 : 243 : tmp = _PyBytes_Join((PyObject *)&_Py_SINGLETON(bytes_empty), chunks);
1582 : 243 : res = tmp;
1583 : 243 : goto cleanup;
1584 : : }
1585 : : }
1586 : 237 : current_size += PyBytes_GET_SIZE(data);
1587 [ + - ]: 237 : if (self->abs_pos != -1)
1588 : 237 : self->abs_pos += PyBytes_GET_SIZE(data);
1589 : : }
1590 : 181127 : cleanup:
1591 : : /* res is either NULL or a borrowed ref */
1592 : 181127 : Py_XINCREF(res);
1593 : 181127 : Py_XDECREF(data);
1594 : 181127 : Py_XDECREF(tmp);
1595 : 181127 : Py_XDECREF(chunks);
1596 : 181127 : 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 *
1602 : 184967 : _bufferedreader_read_fast(buffered *self, Py_ssize_t n)
1603 : : {
1604 : : Py_ssize_t current_size;
1605 : :
1606 [ + - + - : 184967 : current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
+ + ]
1607 [ + + ]: 184967 : if (n <= current_size) {
1608 : : /* Fast path: the data to read is fully buffered. */
1609 : 104480 : PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1610 [ + - ]: 104480 : if (res != NULL)
1611 : 104480 : self->pos += n;
1612 : 104480 : return res;
1613 : : }
1614 : 80487 : 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 *
1621 : 80487 : _bufferedreader_read_generic(buffered *self, Py_ssize_t n)
1622 : : {
1623 : 80487 : PyObject *res = NULL;
1624 : : Py_ssize_t current_size, remaining, written;
1625 : : char *out;
1626 : :
1627 [ + - + - : 80487 : current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
+ + ]
1628 [ + + ]: 80487 : if (n <= current_size)
1629 : 25 : return _bufferedreader_read_fast(self, n);
1630 : :
1631 : 80462 : res = PyBytes_FromStringAndSize(NULL, n);
1632 [ - + ]: 80462 : if (res == NULL)
1633 : 0 : goto error;
1634 : 80462 : out = PyBytes_AS_STRING(res);
1635 : 80462 : remaining = n;
1636 : 80462 : written = 0;
1637 [ + + ]: 80462 : if (current_size > 0) {
1638 : 24660 : memcpy(out, self->buffer + self->pos, current_size);
1639 : 24660 : remaining -= current_size;
1640 : 24660 : written += current_size;
1641 : 24660 : self->pos += current_size;
1642 : : }
1643 : : /* Flush the write buffer if necessary */
1644 [ + + ]: 80462 : if (self->writable) {
1645 : 17582 : PyObject *r = buffered_flush_and_rewind_unlocked(self);
1646 [ - + ]: 17582 : if (r == NULL)
1647 : 0 : goto error;
1648 : 17582 : Py_DECREF(r);
1649 : : }
1650 : 80462 : _bufferedreader_reset_buf(self);
1651 [ + + ]: 128492 : 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 [ + + ]: 109209 : Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1655 [ + + ]: 109209 : if (r == 0)
1656 : 55548 : break;
1657 : 53661 : r = _bufferedreader_raw_read(self, out + written, r);
1658 [ + + ]: 53661 : if (r == -1)
1659 : 3 : goto error;
1660 [ + + - + ]: 53658 : if (r == 0 || r == -2) {
1661 : : /* EOF occurred or read() would block. */
1662 [ - + - - ]: 5628 : if (r == 0 || written > 0) {
1663 [ - + ]: 5628 : if (_PyBytes_Resize(&res, written))
1664 : 0 : goto error;
1665 : 5628 : return res;
1666 : : }
1667 : 0 : Py_DECREF(res);
1668 : 0 : Py_RETURN_NONE;
1669 : : }
1670 : 48030 : remaining -= r;
1671 : 48030 : written += r;
1672 : : }
1673 : : assert(remaining <= self->buffer_size);
1674 : 74831 : self->pos = 0;
1675 : 74831 : self->raw_pos = 0;
1676 : 74831 : 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 [ + + + - ]: 75165 : while (remaining > 0 && self->read_end < self->buffer_size) {
1681 : 55882 : Py_ssize_t r = _bufferedreader_fill_buffer(self);
1682 [ + + ]: 55882 : if (r == -1)
1683 : 1490 : goto error;
1684 [ + + + + ]: 54392 : if (r == 0 || r == -2) {
1685 : : /* EOF occurred or read() would block. */
1686 [ + + + - ]: 5854 : if (r == 0 || written > 0) {
1687 [ - + ]: 5854 : if (_PyBytes_Resize(&res, written))
1688 : 0 : goto error;
1689 : 5854 : return res;
1690 : : }
1691 : 0 : Py_DECREF(res);
1692 : 0 : Py_RETURN_NONE;
1693 : : }
1694 [ + + ]: 48538 : if (remaining > r) {
1695 : 334 : memcpy(out + written, self->buffer + self->pos, r);
1696 : 334 : written += r;
1697 : 334 : self->pos += r;
1698 : 334 : remaining -= r;
1699 : : }
1700 [ + - ]: 48204 : else if (remaining > 0) {
1701 : 48204 : memcpy(out + written, self->buffer + self->pos, remaining);
1702 : 48204 : written += remaining;
1703 : 48204 : self->pos += remaining;
1704 : 48204 : remaining = 0;
1705 : : }
1706 [ + + ]: 48538 : if (remaining == 0)
1707 : 48204 : break;
1708 : : }
1709 : :
1710 : 67487 : return res;
1711 : :
1712 : 1493 : error:
1713 : 1493 : Py_XDECREF(res);
1714 : 1493 : return NULL;
1715 : : }
1716 : :
1717 : : static PyObject *
1718 : 8866 : _bufferedreader_peek_unlocked(buffered *self)
1719 : : {
1720 : : Py_ssize_t have, r;
1721 : :
1722 [ + - + - : 8866 : 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 [ + + ]: 8866 : if (have > 0) {
1730 : 1845 : 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 : 7021 : _bufferedreader_reset_buf(self);
1735 : 7021 : r = _bufferedreader_fill_buffer(self);
1736 [ - + ]: 7021 : if (r == -1)
1737 : 0 : return NULL;
1738 [ + + ]: 7021 : if (r == -2)
1739 : 2 : r = 0;
1740 : 7021 : self->pos = 0;
1741 : 7021 : return PyBytes_FromStringAndSize(self->buffer, r);
1742 : : }
1743 : :
1744 : :
1745 : :
1746 : : /*
1747 : : * class BufferedWriter
1748 : : */
1749 : : static void
1750 : 541226 : _bufferedwriter_reset_buf(buffered *self)
1751 : : {
1752 : 541226 : self->write_pos = 0;
1753 : 541226 : self->write_end = -1;
1754 : 541226 : }
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
1769 : 56672 : _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 : 56672 : self->ok = 0;
1774 : 56672 : self->detached = 0;
1775 : :
1776 [ - + ]: 56672 : if (_PyIOBase_check_writable(raw, Py_True) == NULL)
1777 : 0 : return -1;
1778 : :
1779 : 56672 : Py_INCREF(raw);
1780 : 56672 : Py_XSETREF(self->raw, raw);
1781 : 56672 : self->readable = 0;
1782 : 56672 : self->writable = 1;
1783 : :
1784 : 56672 : self->buffer_size = buffer_size;
1785 [ + + ]: 56672 : if (_buffered_init(self) < 0)
1786 : 7 : return -1;
1787 : 56665 : _bufferedwriter_reset_buf(self);
1788 : 56665 : self->pos = 0;
1789 : :
1790 [ + + + + ]: 113328 : self->fast_closed_checks = (Py_IS_TYPE(self, &PyBufferedWriter_Type) &&
1791 : 56663 : Py_IS_TYPE(raw, &PyFileIO_Type));
1792 : :
1793 : 56665 : self->ok = 1;
1794 : 56665 : return 0;
1795 : : }
1796 : :
1797 : : static Py_ssize_t
1798 : 327132 : _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 [ - + ]: 327132 : if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1806 : 0 : return -1;
1807 : 327132 : memobj = PyMemoryView_FromBuffer(&buf);
1808 [ - + ]: 327132 : if (memobj == NULL)
1809 : 0 : 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 : 327132 : errno = 0;
1817 : 327132 : res = PyObject_CallMethodOneArg(self->raw, &_Py_ID(write), memobj);
1818 : 327132 : errnum = errno;
1819 [ + + - + ]: 327132 : } while (res == NULL && _PyIO_trap_eintr());
1820 : 327132 : Py_DECREF(memobj);
1821 [ + + ]: 327132 : if (res == NULL)
1822 : 15 : return -1;
1823 [ + + ]: 327117 : 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 : 9 : Py_DECREF(res);
1828 : 9 : errno = errnum;
1829 : 9 : return -2;
1830 : : }
1831 : 327108 : n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1832 : 327108 : Py_DECREF(res);
1833 [ + - + + ]: 327108 : if (n < 0 || n > len) {
1834 : 2 : PyErr_Format(PyExc_OSError,
1835 : : "raw write() returned invalid length %zd "
1836 : : "(should have been between 0 and %zd)", n, len);
1837 : 2 : return -1;
1838 : : }
1839 [ + - + - ]: 327106 : if (n > 0 && self->abs_pos != -1)
1840 : 327106 : self->abs_pos += n;
1841 : 327106 : return n;
1842 : : }
1843 : :
1844 : : static PyObject *
1845 : 480451 : _bufferedwriter_flush_unlocked(buffered *self)
1846 : : {
1847 : : Py_off_t n, rewind;
1848 : :
1849 [ + - + + : 480451 : if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
+ + ]
1850 : 280721 : goto end;
1851 : : /* First, rewind */
1852 [ + + + + : 199730 : rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
+ - + - +
- ]
1853 [ + + ]: 199730 : if (rewind != 0) {
1854 : 35 : n = _buffered_raw_seek(self, -rewind, 1);
1855 [ - + ]: 35 : if (n < 0) {
1856 : 0 : goto error;
1857 : : }
1858 : 35 : self->raw_pos -= rewind;
1859 : : }
1860 [ + + ]: 399442 : while (self->write_pos < self->write_end) {
1861 : 199732 : n = _bufferedwriter_raw_write(self,
1862 : 199732 : self->buffer + self->write_pos,
1863 : 199732 : Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1864 : : Py_off_t, Py_ssize_t));
1865 [ + + ]: 199732 : if (n == -1) {
1866 : 13 : goto error;
1867 : : }
1868 [ + + ]: 199719 : else if (n == -2) {
1869 : 5 : _set_BlockingIOError("write could not complete without blocking",
1870 : : 0);
1871 : 5 : goto error;
1872 : : }
1873 : 199714 : self->write_pos += n;
1874 : 199714 : 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 [ + + ]: 199714 : if (PyErr_CheckSignals() < 0)
1879 : 2 : goto error;
1880 : : }
1881 : :
1882 : :
1883 : 199710 : 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 : 480431 : _bufferedwriter_reset_buf(self);
1894 : 480431 : Py_RETURN_NONE;
1895 : :
1896 : 20 : error:
1897 : 20 : 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 *
1907 : 444317 : _io_BufferedWriter_write_impl(buffered *self, Py_buffer *buffer)
1908 : : /*[clinic end generated code: output=7f8d1365759bfc6b input=dd87dd85fc7f8850]*/
1909 : : {
1910 : 444317 : PyObject *res = NULL;
1911 : : Py_ssize_t written, avail, remaining;
1912 : : Py_off_t offset;
1913 : :
1914 [ + + - + ]: 444317 : CHECK_INITIALIZED(self)
1915 : :
1916 [ + + + + ]: 444312 : if (!ENTER_BUFFERED(self))
1917 : 1 : 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 [ + + + + : 444310 : if (IS_CLOSED(self)) {
- + - + ]
1922 : 10 : PyErr_SetString(PyExc_ValueError, "write to closed file");
1923 : 10 : goto error;
1924 : : }
1925 : :
1926 : : /* Fast path: the data to write can be fully buffered. */
1927 [ + + + + : 444300 : if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
+ - + + ]
1928 : 205794 : self->pos = 0;
1929 : 205794 : self->raw_pos = 0;
1930 : : }
1931 : 444300 : avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1932 [ + + ]: 444300 : if (buffer->len <= avail) {
1933 : 315882 : memcpy(self->buffer + self->pos, buffer->buf, buffer->len);
1934 [ + - + + : 315882 : if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
+ + ]
1935 : 173007 : self->write_pos = self->pos;
1936 : : }
1937 [ + + + + : 315882 : ADJUST_POSITION(self, self->pos + buffer->len);
+ + ]
1938 [ + + ]: 315882 : if (self->pos > self->write_end)
1939 : 246265 : self->write_end = self->pos;
1940 : 315882 : written = buffer->len;
1941 : 315882 : goto end;
1942 : : }
1943 : :
1944 : : /* First write the current buffer */
1945 : 128418 : res = _bufferedwriter_flush_unlocked(self);
1946 [ + + ]: 128418 : if (res == NULL) {
1947 : 5 : Py_ssize_t *w = _buffered_check_blocking_error();
1948 [ - + ]: 5 : if (w == NULL)
1949 : 0 : goto error;
1950 [ - + ]: 5 : if (self->readable)
1951 : 0 : _bufferedreader_reset_buf(self);
1952 : : /* Make some place by shifting the buffer. */
1953 : : assert(VALID_WRITE_BUFFER(self));
1954 : 5 : memmove(self->buffer, self->buffer + self->write_pos,
1955 : 5 : Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1956 : : Py_off_t, Py_ssize_t));
1957 : 5 : self->write_end -= self->write_pos;
1958 : 5 : self->raw_pos -= self->write_pos;
1959 : 5 : self->pos -= self->write_pos;
1960 : 5 : self->write_pos = 0;
1961 : 5 : avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1962 : : Py_off_t, Py_ssize_t);
1963 [ + + ]: 5 : if (buffer->len <= avail) {
1964 : : /* Everything can be buffered */
1965 : 1 : PyErr_Clear();
1966 : 1 : memcpy(self->buffer + self->write_end, buffer->buf, buffer->len);
1967 : 1 : self->write_end += buffer->len;
1968 : 1 : self->pos += buffer->len;
1969 : 1 : written = buffer->len;
1970 : 1 : goto end;
1971 : : }
1972 : : /* Buffer as much as possible. */
1973 : 4 : memcpy(self->buffer + self->write_end, buffer->buf, avail);
1974 : 4 : self->write_end += avail;
1975 : 4 : 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 : 4 : _set_BlockingIOError("write could not complete without blocking",
1980 : : avail);
1981 : 4 : goto error;
1982 : : }
1983 [ + - ]: 128413 : 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 [ + + + + : 128413 : offset = RAW_OFFSET(self);
+ - - + +
- ]
1992 [ + + ]: 128413 : if (offset != 0) {
1993 [ - + ]: 1 : if (_buffered_raw_seek(self, -offset, 1) < 0)
1994 : 0 : goto error;
1995 : 1 : self->raw_pos -= offset;
1996 : : }
1997 : :
1998 : : /* Then write buf itself. At this point the buffer has been emptied. */
1999 : 128413 : remaining = buffer->len;
2000 : 128413 : written = 0;
2001 [ + + ]: 255803 : while (remaining > self->buffer_size) {
2002 : 127400 : Py_ssize_t n = _bufferedwriter_raw_write(
2003 : 127400 : self, (char *) buffer->buf + written, buffer->len - written);
2004 [ + + ]: 127400 : if (n == -1) {
2005 : 4 : goto error;
2006 [ + + ]: 127396 : } else if (n == -2) {
2007 : : /* Write failed because raw file is non-blocking */
2008 [ + - ]: 4 : if (remaining > self->buffer_size) {
2009 : : /* Can't buffer everything, still buffer as much as possible */
2010 : 4 : memcpy(self->buffer,
2011 : 4 : (char *) buffer->buf + written, self->buffer_size);
2012 : 4 : self->raw_pos = 0;
2013 [ + + - + : 4 : ADJUST_POSITION(self, self->buffer_size);
- - ]
2014 : 4 : self->write_end = self->buffer_size;
2015 : 4 : written += self->buffer_size;
2016 : 4 : _set_BlockingIOError("write could not complete without "
2017 : : "blocking", written);
2018 : 4 : goto error;
2019 : : }
2020 : 0 : PyErr_Clear();
2021 : 0 : break;
2022 : : }
2023 : 127392 : written += n;
2024 : 127392 : 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 [ + + ]: 127392 : if (PyErr_CheckSignals() < 0)
2029 : 2 : goto error;
2030 : : }
2031 [ + + ]: 128403 : if (self->readable)
2032 : 49122 : _bufferedreader_reset_buf(self);
2033 [ + + ]: 128403 : if (remaining > 0) {
2034 : 1019 : memcpy(self->buffer, (char *) buffer->buf + written, remaining);
2035 : 1019 : written += remaining;
2036 : : }
2037 : 128403 : self->write_pos = 0;
2038 : : /* TODO: sanity check (remaining >= 0) */
2039 : 128403 : self->write_end = remaining;
2040 [ + + - + : 128403 : ADJUST_POSITION(self, remaining);
- - ]
2041 : 128403 : self->raw_pos = 0;
2042 : :
2043 : 444286 : end:
2044 : 444286 : res = PyLong_FromSsize_t(written);
2045 : :
2046 : 444310 : error:
2047 : 444310 : LEAVE_BUFFERED(self)
2048 : 444310 : 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
2088 : 2101 : _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 [ + + ]: 2101 : if (_PyIOBase_check_readable(reader, Py_True) == NULL)
2093 : 1 : return -1;
2094 [ + + ]: 2100 : if (_PyIOBase_check_writable(writer, Py_True) == NULL)
2095 : 1 : return -1;
2096 : :
2097 : 2099 : self->reader = (buffered *) PyObject_CallFunction(
2098 : : (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
2099 [ - + ]: 2099 : if (self->reader == NULL)
2100 : 0 : return -1;
2101 : :
2102 : 2099 : self->writer = (buffered *) PyObject_CallFunction(
2103 : : (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
2104 [ - + ]: 2099 : if (self->writer == NULL) {
2105 [ # # ]: 0 : Py_CLEAR(self->reader);
2106 : 0 : return -1;
2107 : : }
2108 : :
2109 : 2099 : return 0;
2110 : : }
2111 : :
2112 : : static int
2113 : 4252 : bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
2114 : : {
2115 [ + + - + ]: 4252 : Py_VISIT(self->dict);
2116 : 4252 : return 0;
2117 : : }
2118 : :
2119 : : static int
2120 : 984 : bufferedrwpair_clear(rwpair *self)
2121 : : {
2122 [ + - ]: 984 : Py_CLEAR(self->reader);
2123 [ + - ]: 984 : Py_CLEAR(self->writer);
2124 [ + - ]: 984 : Py_CLEAR(self->dict);
2125 : 984 : return 0;
2126 : : }
2127 : :
2128 : : static void
2129 : 2103 : bufferedrwpair_dealloc(rwpair *self)
2130 : : {
2131 : 2103 : _PyObject_GC_UNTRACK(self);
2132 [ + + ]: 2103 : if (self->weakreflist != NULL)
2133 : 1 : PyObject_ClearWeakRefs((PyObject *)self);
2134 [ + + ]: 2103 : Py_CLEAR(self->reader);
2135 [ + + ]: 2103 : Py_CLEAR(self->writer);
2136 [ + + ]: 2103 : Py_CLEAR(self->dict);
2137 : 2103 : Py_TYPE(self)->tp_free((PyObject *) self);
2138 : 2103 : }
2139 : :
2140 : : static PyObject *
2141 : 12967 : _forward_call(buffered *self, PyObject *name, PyObject *args)
2142 : : {
2143 : : PyObject *func, *ret;
2144 [ + + ]: 12967 : if (self == NULL) {
2145 : 2 : PyErr_SetString(PyExc_ValueError,
2146 : : "I/O operation on uninitialized object");
2147 : 2 : return NULL;
2148 : : }
2149 : :
2150 : 12965 : func = PyObject_GetAttr((PyObject *)self, name);
2151 [ - + ]: 12965 : if (func == NULL) {
2152 : 0 : PyErr_SetObject(PyExc_AttributeError, name);
2153 : 0 : return NULL;
2154 : : }
2155 : :
2156 : 12965 : ret = PyObject_CallObject(func, args);
2157 : 12965 : Py_DECREF(func);
2158 : 12965 : return ret;
2159 : : }
2160 : :
2161 : : static PyObject *
2162 : 1952 : bufferedrwpair_read(rwpair *self, PyObject *args)
2163 : : {
2164 : 1952 : return _forward_call(self->reader, &_Py_ID(read), args);
2165 : : }
2166 : :
2167 : : static PyObject *
2168 : 1944 : bufferedrwpair_peek(rwpair *self, PyObject *args)
2169 : : {
2170 : 1944 : return _forward_call(self->reader, &_Py_ID(peek), args);
2171 : : }
2172 : :
2173 : : static PyObject *
2174 : 2 : bufferedrwpair_read1(rwpair *self, PyObject *args)
2175 : : {
2176 : 2 : return _forward_call(self->reader, &_Py_ID(read1), args);
2177 : : }
2178 : :
2179 : : static PyObject *
2180 : 1 : bufferedrwpair_readinto(rwpair *self, PyObject *args)
2181 : : {
2182 : 1 : return _forward_call(self->reader, &_Py_ID(readinto), args);
2183 : : }
2184 : :
2185 : : static PyObject *
2186 : 1 : bufferedrwpair_readinto1(rwpair *self, PyObject *args)
2187 : : {
2188 : 1 : return _forward_call(self->reader, &_Py_ID(readinto1), args);
2189 : : }
2190 : :
2191 : : static PyObject *
2192 : 660 : bufferedrwpair_write(rwpair *self, PyObject *args)
2193 : : {
2194 : 660 : return _forward_call(self->writer, &_Py_ID(write), args);
2195 : : }
2196 : :
2197 : : static PyObject *
2198 : 339 : bufferedrwpair_flush(rwpair *self, PyObject *Py_UNUSED(ignored))
2199 : : {
2200 : 339 : return _forward_call(self->writer, &_Py_ID(flush), NULL);
2201 : : }
2202 : :
2203 : : static PyObject *
2204 : 2003 : bufferedrwpair_readable(rwpair *self, PyObject *Py_UNUSED(ignored))
2205 : : {
2206 : 2003 : return _forward_call(self->reader, &_Py_ID(readable), NULL);
2207 : : }
2208 : :
2209 : : static PyObject *
2210 : 2003 : bufferedrwpair_writable(rwpair *self, PyObject *Py_UNUSED(ignored))
2211 : : {
2212 : 2003 : return _forward_call(self->writer, &_Py_ID(writable), NULL);
2213 : : }
2214 : :
2215 : : static PyObject *
2216 : 2028 : bufferedrwpair_close(rwpair *self, PyObject *Py_UNUSED(ignored))
2217 : : {
2218 : 2028 : PyObject *exc = NULL, *val, *tb;
2219 : 2028 : PyObject *ret = _forward_call(self->writer, &_Py_ID(close), NULL);
2220 [ + + ]: 2028 : if (ret == NULL)
2221 : 3 : PyErr_Fetch(&exc, &val, &tb);
2222 : : else
2223 : 2025 : Py_DECREF(ret);
2224 : 2028 : ret = _forward_call(self->reader, &_Py_ID(close), NULL);
2225 [ + + ]: 2028 : if (exc != NULL) {
2226 : 3 : _PyErr_ChainExceptions(exc, val, tb);
2227 [ + + ]: 3 : Py_CLEAR(ret);
2228 : : }
2229 : 2028 : return ret;
2230 : : }
2231 : :
2232 : : static PyObject *
2233 : 4 : bufferedrwpair_isatty(rwpair *self, PyObject *Py_UNUSED(ignored))
2234 : : {
2235 : 4 : PyObject *ret = _forward_call(self->writer, &_Py_ID(isatty), NULL);
2236 : :
2237 [ + + ]: 4 : if (ret != Py_False) {
2238 : : /* either True or exception */
2239 : 2 : return ret;
2240 : : }
2241 : 2 : Py_DECREF(ret);
2242 : :
2243 : 2 : return _forward_call(self->reader, &_Py_ID(isatty), NULL);
2244 : : }
2245 : :
2246 : : static PyObject *
2247 : 4118 : bufferedrwpair_closed_get(rwpair *self, void *context)
2248 : : {
2249 [ - + ]: 4118 : if (self->writer == NULL) {
2250 : 0 : PyErr_SetString(PyExc_RuntimeError,
2251 : : "the BufferedRWPair object is being garbage-collected");
2252 : 0 : return NULL;
2253 : : }
2254 : 4118 : 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
2276 : 4137 : _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 : 4137 : self->ok = 0;
2281 : 4137 : self->detached = 0;
2282 : :
2283 [ - + ]: 4137 : if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
2284 : 0 : return -1;
2285 [ - + ]: 4137 : if (_PyIOBase_check_readable(raw, Py_True) == NULL)
2286 : 0 : return -1;
2287 [ - + ]: 4137 : if (_PyIOBase_check_writable(raw, Py_True) == NULL)
2288 : 0 : return -1;
2289 : :
2290 : 4137 : Py_INCREF(raw);
2291 : 4137 : Py_XSETREF(self->raw, raw);
2292 : 4137 : self->buffer_size = buffer_size;
2293 : 4137 : self->readable = 1;
2294 : 4137 : self->writable = 1;
2295 : :
2296 [ + + ]: 4137 : if (_buffered_init(self) < 0)
2297 : 7 : return -1;
2298 : 4130 : _bufferedreader_reset_buf(self);
2299 : 4130 : _bufferedwriter_reset_buf(self);
2300 : 4130 : self->pos = 0;
2301 : :
2302 [ + + + + ]: 8259 : self->fast_closed_checks = (Py_IS_TYPE(self, &PyBufferedRandom_Type) &&
2303 : 4129 : Py_IS_TYPE(raw, &PyFileIO_Type));
2304 : :
2305 : 4130 : self->ok = 1;
2306 : 4130 : 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 : : };
|