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