Coverage Report

Created: 2026-05-30 06:18

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