Coverage Report

Created: 2026-03-08 06:40

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
73.2k
#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
542k
    ( (PyThread_acquire_lock(self->lock, 0) ? \
331
542k
       1 : _enter_buffered_busy(self)) \
332
542k
     && (self->owner = PyThread_get_thread_ident(), 1) )
333
334
#define LEAVE_BUFFERED(self) \
335
542k
    do { \
336
542k
        self->owner = 0; \
337
542k
        PyThread_release_lock(self->lock); \
338
542k
    } while(0);
339
340
#define CHECK_INITIALIZED(self) \
341
584k
    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
32
    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
507k
    (!self->buffer ? 1 : \
366
507k
    (self->fast_closed_checks \
367
507k
     ? _PyFileIO_closed(self->raw) \
368
507k
     : buffered_closed(self)))
369
370
#define CHECK_CLOSED(self, error_msg) \
371
240k
    do { \
372
240k
        int _closed = IS_CLOSED(self); \
373
240k
        if (_closed < 0) { \
374
0
            return NULL; \
375
0
        } \
376
240k
        if (_closed && \
377
240k
            (Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t) == 0)) \
378
240k
        { \
379
0
            PyErr_SetString(PyExc_ValueError, error_msg); \
380
0
            return NULL; \
381
0
        } \
382
240k
    } while (0);
383
384
#define VALID_READ_BUFFER(self) \
385
1.39M
    (self->readable && self->read_end != -1)
386
387
#define VALID_WRITE_BUFFER(self) \
388
1.39M
    (self->writable && self->write_end != -1)
389
390
#define ADJUST_POSITION(self, _new_pos) \
391
232k
    do { \
392
232k
        self->pos = _new_pos; \
393
232k
        if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
394
232k
            self->read_end = self->pos; \
395
232k
    } while(0)
396
397
#define READAHEAD(self) \
398
33
    ((self->readable && VALID_READ_BUFFER(self)) \
399
33
        ? (self->read_end - self->pos) : 0)
400
401
#define RAW_OFFSET(self) \
402
232k
    (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
403
232k
        && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
404
405
#define RAW_TELL(self) \
406
33
    (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
407
408
#define MINUS_LAST_BLOCK(self, size) \
409
42
    (self->buffer_mask ? \
410
42
        (size & ~self->buffer_mask) : \
411
42
        (self->buffer_size * (size / self->buffer_size)))
412
413
414
static int
415
buffered_clear(PyObject *op)
416
34.3k
{
417
34.3k
    buffered *self = buffered_CAST(op);
418
34.3k
    self->ok = 0;
419
34.3k
    Py_CLEAR(self->raw);
420
34.3k
    Py_CLEAR(self->dict);
421
34.3k
    return 0;
422
34.3k
}
423
424
static void
425
buffered_dealloc(PyObject *op)
426
34.3k
{
427
34.3k
    buffered *self = buffered_CAST(op);
428
34.3k
    PyTypeObject *tp = Py_TYPE(self);
429
34.3k
    self->finalizing = 1;
430
34.3k
    if (_PyIOBase_finalize(op) < 0)
431
0
        return;
432
34.3k
    _PyObject_GC_UNTRACK(self);
433
34.3k
    self->ok = 0;
434
34.3k
    FT_CLEAR_WEAKREFS(op, self->weakreflist);
435
34.3k
    if (self->buffer) {
436
0
        PyMem_Free(self->buffer);
437
0
        self->buffer = NULL;
438
0
    }
439
34.3k
    if (self->lock) {
440
34.3k
        PyThread_free_lock(self->lock);
441
34.3k
        self->lock = NULL;
442
34.3k
    }
443
34.3k
    (void)buffered_clear(op);
444
34.3k
    tp->tp_free(self);
445
34.3k
    Py_DECREF(tp);
446
34.3k
}
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
7.71k
{
516
7.71k
    CHECK_INITIALIZED(self)
517
7.71k
    return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(flush));
518
7.71k
}
519
520
static int
521
buffered_closed(buffered *self)
522
32
{
523
32
    int closed;
524
32
    PyObject *res;
525
32
    CHECK_INITIALIZED_INT(self)
526
32
    res = PyObject_GetAttr(self->raw, &_Py_ID(closed));
527
32
    if (res == NULL)
528
0
        return -1;
529
32
    closed = PyObject_IsTrue(res);
530
32
    Py_DECREF(res);
531
32
    return closed;
532
32
}
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
68.7k
{
544
68.7k
    CHECK_INITIALIZED(self)
545
68.7k
    return PyObject_GetAttr(self->raw, &_Py_ID(closed));
546
68.7k
}
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
34.3k
{
557
34.3k
    PyObject *res = NULL;
558
34.3k
    int r;
559
560
34.3k
    CHECK_INITIALIZED(self)
561
34.3k
    if (!ENTER_BUFFERED(self)) {
562
0
        return NULL;
563
0
    }
564
    /* gh-138720: Use IS_CLOSED to match flush CHECK_CLOSED. */
565
34.3k
    r = IS_CLOSED(self);
566
34.3k
    if (r < 0)
567
0
        goto end;
568
34.3k
    if (r > 0) {
569
0
        res = Py_NewRef(Py_None);
570
0
        goto end;
571
0
    }
572
573
34.3k
    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
34.3k
    LEAVE_BUFFERED(self)
582
34.3k
    r = _PyFile_Flush((PyObject *)self);
583
34.3k
    if (!ENTER_BUFFERED(self)) {
584
0
        return NULL;
585
0
    }
586
34.3k
    PyObject *exc = NULL;
587
34.3k
    if (r < 0) {
588
0
        exc = PyErr_GetRaisedException();
589
0
    }
590
591
34.3k
    res = PyObject_CallMethodNoArgs(self->raw, &_Py_ID(close));
592
593
34.3k
    if (self->buffer) {
594
34.3k
        PyMem_Free(self->buffer);
595
34.3k
        self->buffer = NULL;
596
34.3k
    }
597
598
34.3k
    if (exc != NULL) {
599
0
        _PyErr_ChainExceptions1(exc);
600
0
        Py_CLEAR(res);
601
0
    }
602
603
34.3k
    self->read_end = 0;
604
34.3k
    self->pos = 0;
605
606
34.3k
end:
607
34.3k
    LEAVE_BUFFERED(self)
608
34.3k
    return res;
609
34.3k
}
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
119
{
643
119
    CHECK_INITIALIZED(self)
644
119
    return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(seekable));
645
119
}
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
51
{
656
51
    CHECK_INITIALIZED(self)
657
51
    return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(readable));
658
51
}
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
68
{
669
68
    CHECK_INITIALIZED(self)
670
68
    return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(writable));
671
68
}
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
9
{
684
9
    CHECK_INITIALIZED(self)
685
9
    return PyObject_GetAttr(self->raw, &_Py_ID(name));
686
9
}
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
34.5k
{
786
34.5k
    Py_off_t n;
787
34.5k
    PyObject *res;
788
34.5k
    res = PyObject_CallMethodNoArgs(self->raw, &_Py_ID(tell));
789
34.5k
    if (res == NULL)
790
5
        return -1;
791
34.5k
    n = PyNumber_AsOff_t(res, PyExc_ValueError);
792
34.5k
    Py_DECREF(res);
793
34.5k
    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
34.5k
    self->abs_pos = n;
801
34.5k
    return n;
802
34.5k
}
803
804
static Py_off_t
805
_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
806
42
{
807
42
    PyObject *res, *posobj, *whenceobj;
808
42
    Py_off_t n;
809
810
42
    posobj = PyLong_FromOff_t(target);
811
42
    if (posobj == NULL)
812
0
        return -1;
813
42
    whenceobj = PyLong_FromLong(whence);
814
42
    if (whenceobj == NULL) {
815
0
        Py_DECREF(posobj);
816
0
        return -1;
817
0
    }
818
42
    res = PyObject_CallMethodObjArgs(self->raw, &_Py_ID(seek),
819
42
                                     posobj, whenceobj, NULL);
820
42
    Py_DECREF(posobj);
821
42
    Py_DECREF(whenceobj);
822
42
    if (res == NULL)
823
0
        return -1;
824
42
    n = PyNumber_AsOff_t(res, PyExc_ValueError);
825
42
    Py_DECREF(res);
826
42
    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
42
    self->abs_pos = n;
834
42
    return n;
835
42
}
836
837
static int
838
_buffered_init(buffered *self)
839
34.4k
{
840
34.4k
    Py_ssize_t n;
841
34.4k
    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
34.4k
    if (self->buffer)
847
0
        PyMem_Free(self->buffer);
848
34.4k
    self->buffer = PyMem_Malloc(self->buffer_size);
849
34.4k
    if (self->buffer == NULL) {
850
0
        PyErr_NoMemory();
851
0
        return -1;
852
0
    }
853
34.4k
    if (self->lock)
854
0
        PyThread_free_lock(self->lock);
855
34.4k
    self->lock = PyThread_allocate_lock();
856
34.4k
    if (self->lock == NULL) {
857
0
        PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
858
0
        return -1;
859
0
    }
860
34.4k
    self->owner = 0;
861
    /* Find out whether buffer_size is a power of 2 */
862
    /* XXX is this optimization useful? */
863
620k
    for (n = self->buffer_size - 1; n & 1; n >>= 1)
864
586k
        ;
865
34.4k
    if (n == 0)
866
34.4k
        self->buffer_mask = self->buffer_size - 1;
867
0
    else
868
0
        self->buffer_mask = 0;
869
34.4k
    if (_buffered_raw_tell(self) == -1)
870
5
        PyErr_Clear();
871
34.4k
    return 0;
872
34.4k
}
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
0
{
881
0
    if (!PyErr_ExceptionMatches(PyExc_OSError)) {
882
0
        return 0;
883
0
    }
884
0
    PyObject *exc = PyErr_GetRaisedException();
885
0
    PyOSErrorObject *env_err = (PyOSErrorObject *)exc;
886
0
    assert(env_err != NULL);
887
0
    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
0
    PyErr_SetRaisedException(exc);
900
0
    return 0;
901
0
}
902
903
/*
904
 * Shared methods and wrappers
905
 */
906
907
static PyObject *
908
buffered_flush_and_rewind_unlocked(buffered *self)
909
232k
{
910
232k
    PyObject *res;
911
912
232k
    res = _bufferedwriter_flush_unlocked(self);
913
232k
    if (res == NULL)
914
0
        return NULL;
915
232k
    Py_DECREF(res);
916
917
232k
    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
232k
    Py_RETURN_NONE;
927
232k
}
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
232k
{
938
232k
    PyObject *res;
939
940
232k
    CHECK_INITIALIZED(self)
941
232k
    CHECK_CLOSED(self, "flush of closed file")
942
943
232k
    if (!ENTER_BUFFERED(self))
944
0
        return NULL;
945
232k
    res = buffered_flush_and_rewind_unlocked(self);
946
232k
    LEAVE_BUFFERED(self)
947
948
232k
    return res;
949
232k
}
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
7.78k
{
995
7.78k
    PyObject *res;
996
997
7.78k
    CHECK_INITIALIZED(self)
998
7.78k
    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
7.78k
    CHECK_CLOSED(self, "read of closed file")
1005
1006
7.78k
    if (n == -1) {
1007
        /* The number of bytes is unspecified, read until the end of stream */
1008
7.66k
        if (!ENTER_BUFFERED(self))
1009
0
            return NULL;
1010
7.66k
        res = _bufferedreader_read_all(self);
1011
7.66k
    }
1012
120
    else {
1013
120
        res = _bufferedreader_read_fast(self, n);
1014
120
        if (res != Py_None)
1015
78
            return res;
1016
42
        Py_DECREF(res);
1017
42
        if (!ENTER_BUFFERED(self))
1018
0
            return NULL;
1019
42
        res = _bufferedreader_read_generic(self, n);
1020
42
    }
1021
1022
7.70k
    LEAVE_BUFFERED(self)
1023
7.70k
    return res;
1024
7.78k
}
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
104
{
1037
104
    CHECK_INITIALIZED(self)
1038
104
    if (n < 0) {
1039
0
        n = self->buffer_size;
1040
0
    }
1041
1042
104
    CHECK_CLOSED(self, "read of closed file")
1043
1044
104
    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
104
    Py_ssize_t have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1052
104
    if (have > 0) {
1053
95
        n = Py_MIN(have, n);
1054
95
        PyObject *res = _bufferedreader_read_fast(self, n);
1055
95
        assert(res != Py_None);
1056
95
        return res;
1057
95
    }
1058
1059
9
    if (!ENTER_BUFFERED(self)) {
1060
0
        return NULL;
1061
0
    }
1062
1063
    /* Flush the write buffer if necessary */
1064
9
    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
9
    _bufferedreader_reset_buf(self);
1073
1074
9
    PyBytesWriter *writer = PyBytesWriter_Create(n);
1075
9
    if (writer == NULL) {
1076
0
        LEAVE_BUFFERED(self)
1077
0
        return NULL;
1078
0
    }
1079
1080
9
    Py_ssize_t r = _bufferedreader_raw_read(self,
1081
9
                                            PyBytesWriter_GetData(writer), n);
1082
9
    LEAVE_BUFFERED(self)
1083
9
    if (r == -1) {
1084
0
        PyBytesWriter_Discard(writer);
1085
0
        return NULL;
1086
0
    }
1087
9
    if (r == -2) {
1088
0
        r = 0;
1089
0
    }
1090
1091
9
    return PyBytesWriter_FinishWithSize(writer, r);
1092
9
}
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
17
{
1208
17
    PyObject *res = NULL;
1209
17
    PyObject *chunks = NULL;
1210
17
    Py_ssize_t n;
1211
17
    const char *start, *s, *end;
1212
1213
17
    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
17
    n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1219
17
    if (limit >= 0 && n > limit)
1220
0
        n = limit;
1221
17
    start = self->buffer + self->pos;
1222
17
    s = memchr(start, '\n', n);
1223
17
    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
9
    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
9
    if (!ENTER_BUFFERED(self))
1237
0
        goto end_unlocked;
1238
1239
    /* Now we try to get some more from the raw stream */
1240
9
    chunks = PyList_New(0);
1241
9
    if (chunks == NULL)
1242
0
        goto end;
1243
9
    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
9
    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
9
    for (;;) {
1264
9
        _bufferedreader_reset_buf(self);
1265
9
        n = _bufferedreader_fill_buffer(self);
1266
9
        if (n == -1)
1267
0
            goto end;
1268
9
        if (n <= 0)
1269
0
            break;
1270
9
        if (limit >= 0 && n > limit)
1271
0
            n = limit;
1272
9
        start = self->buffer;
1273
9
        end = start + n;
1274
9
        s = start;
1275
460
        while (s < end) {
1276
460
            if (*s++ == '\n') {
1277
9
                res = PyBytes_FromStringAndSize(start, s - start);
1278
9
                if (res == NULL)
1279
0
                    goto end;
1280
9
                self->pos = s - start;
1281
9
                goto found;
1282
9
            }
1283
460
        }
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
9
found:
1300
9
    if (res != NULL && PyList_Append(chunks, res) < 0) {
1301
0
        Py_CLEAR(res);
1302
0
        goto end;
1303
0
    }
1304
9
    Py_XSETREF(res, PyBytes_Join((PyObject *)&_Py_SINGLETON(bytes_empty), chunks));
1305
1306
9
end:
1307
9
    LEAVE_BUFFERED(self)
1308
17
end_unlocked:
1309
17
    Py_XDECREF(chunks);
1310
17
    return res;
1311
9
}
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
17
{
1324
17
    CHECK_INITIALIZED(self)
1325
17
    return _buffered_readline(self, size);
1326
17
}
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
92
{
1338
92
    Py_off_t pos;
1339
1340
92
    CHECK_INITIALIZED(self)
1341
92
    pos = _buffered_raw_tell(self);
1342
92
    if (pos == -1)
1343
0
        return NULL;
1344
92
    pos -= RAW_OFFSET(self);
1345
1346
    // GH-95782
1347
92
    if (pos < 0)
1348
0
        pos = 0;
1349
1350
92
    return PyLong_FromOff_t(pos);
1351
92
}
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
51
{
1365
51
    Py_off_t target, n;
1366
51
    PyObject *res = NULL;
1367
1368
51
    CHECK_INITIALIZED(self)
1369
1370
    /* Do some error checking instead of trusting OS 'seek()'
1371
    ** error detection, just in case.
1372
    */
1373
51
    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
51
#endif
1380
51
        ) {
1381
0
        PyErr_Format(PyExc_ValueError,
1382
0
                     "whence value %d unsupported", whence);
1383
0
        return NULL;
1384
0
    }
1385
1386
51
    CHECK_CLOSED(self, "seek of closed file")
1387
1388
51
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
1389
51
    if (_PyIOBase_check_seekable(state, self->raw, Py_True) == NULL) {
1390
0
        return NULL;
1391
0
    }
1392
1393
51
    target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1394
51
    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
51
    if (((whence == 0) || (whence == 1)) && self->readable) {
1402
33
        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
33
        current = RAW_TELL(self);
1410
33
        avail = READAHEAD(self);
1411
33
        if (avail > 0) {
1412
9
            Py_off_t offset;
1413
9
            if (whence == 0)
1414
9
                offset = target - (current - RAW_OFFSET(self));
1415
0
            else
1416
0
                offset = target;
1417
9
            if (offset >= -self->pos && offset <= avail) {
1418
9
                self->pos += offset;
1419
1420
                // GH-95782
1421
9
                if (current - avail + offset < 0)
1422
0
                    return PyLong_FromOff_t(0);
1423
1424
9
                return PyLong_FromOff_t(current - avail + offset);
1425
9
            }
1426
9
        }
1427
33
    }
1428
1429
42
    if (!ENTER_BUFFERED(self))
1430
0
        return NULL;
1431
1432
    /* Fallback: invoke raw seek() method and clear buffer */
1433
42
    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
42
    if (whence == 1)
1442
0
        target -= RAW_OFFSET(self);
1443
42
    n = _buffered_raw_seek(self, target, whence);
1444
42
    if (n == -1)
1445
0
        goto end;
1446
42
    self->raw_pos = -1;
1447
42
    res = PyLong_FromOff_t(n);
1448
42
    if (res != NULL && self->readable)
1449
42
        _bufferedreader_reset_buf(self);
1450
1451
42
end:
1452
42
    LEAVE_BUFFERED(self)
1453
42
    return res;
1454
42
}
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
        line = _buffered_readline(self, -1);
1513
0
    }
1514
0
    else {
1515
0
        line = PyObject_CallMethodNoArgs((PyObject *)self,
1516
0
                                             &_Py_ID(readline));
1517
0
        if (line && !PyBytes_Check(line)) {
1518
0
            PyErr_Format(PyExc_OSError,
1519
0
                         "readline() should have returned a bytes object, "
1520
0
                         "not '%.200s'", Py_TYPE(line)->tp_name);
1521
0
            Py_DECREF(line);
1522
0
            return NULL;
1523
0
        }
1524
0
    }
1525
1526
0
    if (line == NULL)
1527
0
        return NULL;
1528
1529
0
    if (PyBytes_GET_SIZE(line) == 0) {
1530
        /* Reached EOF or would have blocked */
1531
0
        Py_DECREF(line);
1532
0
        return NULL;
1533
0
    }
1534
1535
0
    return line;
1536
0
}
1537
1538
static PyObject *
1539
buffered_repr(PyObject *op)
1540
0
{
1541
0
    buffered *self = buffered_CAST(op);
1542
0
    PyObject *nameobj, *res;
1543
1544
0
    if (PyObject_GetOptionalAttr((PyObject *) self, &_Py_ID(name), &nameobj) < 0) {
1545
0
        if (!PyErr_ExceptionMatches(PyExc_ValueError)) {
1546
0
            return NULL;
1547
0
        }
1548
        /* Ignore ValueError raised if the underlying stream was detached */
1549
0
        PyErr_Clear();
1550
0
    }
1551
0
    if (nameobj == NULL) {
1552
0
        res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1553
0
    }
1554
0
    else {
1555
0
        int status = Py_ReprEnter((PyObject *)self);
1556
0
        res = NULL;
1557
0
        if (status == 0) {
1558
0
            res = PyUnicode_FromFormat("<%s name=%R>",
1559
0
                                       Py_TYPE(self)->tp_name, nameobj);
1560
0
            Py_ReprLeave((PyObject *)self);
1561
0
        }
1562
0
        else if (status > 0) {
1563
0
            PyErr_Format(PyExc_RuntimeError,
1564
0
                         "reentrant call inside %s.__repr__",
1565
0
                         Py_TYPE(self)->tp_name);
1566
0
        }
1567
0
        Py_DECREF(nameobj);
1568
0
    }
1569
0
    return res;
1570
0
}
1571
1572
/*
1573
 * class BufferedReader
1574
 */
1575
1576
static void _bufferedreader_reset_buf(buffered *self)
1577
15.4k
{
1578
15.4k
    self->read_end = -1;
1579
15.4k
}
1580
1581
/*[clinic input]
1582
_io.BufferedReader.__init__
1583
    raw: object
1584
    buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
1585
1586
Create a new buffered reader using the given readable raw IO object.
1587
[clinic start generated code]*/
1588
1589
static int
1590
_io_BufferedReader___init___impl(buffered *self, PyObject *raw,
1591
                                 Py_ssize_t buffer_size)
1592
/*[clinic end generated code: output=cddcfefa0ed294c4 input=fb887e06f11b4e48]*/
1593
7.72k
{
1594
7.72k
    self->ok = 0;
1595
7.72k
    self->detached = 0;
1596
1597
7.72k
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
1598
7.72k
    if (_PyIOBase_check_readable(state, raw, Py_True) == NULL) {
1599
0
        return -1;
1600
0
    }
1601
1602
7.72k
    Py_XSETREF(self->raw, Py_NewRef(raw));
1603
7.72k
    self->buffer_size = buffer_size;
1604
7.72k
    self->readable = 1;
1605
7.72k
    self->writable = 0;
1606
1607
7.72k
    if (_buffered_init(self) < 0)
1608
0
        return -1;
1609
7.72k
    _bufferedreader_reset_buf(self);
1610
1611
7.72k
    self->fast_closed_checks = (
1612
7.72k
        Py_IS_TYPE(self, state->PyBufferedReader_Type) &&
1613
7.72k
        Py_IS_TYPE(raw, state->PyFileIO_Type)
1614
7.72k
    );
1615
1616
7.72k
    self->ok = 1;
1617
7.72k
    return 0;
1618
7.72k
}
1619
1620
static Py_ssize_t
1621
_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
1622
74
{
1623
74
    Py_buffer buf;
1624
74
    PyObject *memobj, *res;
1625
74
    Py_ssize_t n;
1626
    /* NOTE: the buffer needn't be released as its object is NULL. */
1627
74
    if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1628
0
        return -1;
1629
74
    memobj = PyMemoryView_FromBuffer(&buf);
1630
74
    if (memobj == NULL)
1631
0
        return -1;
1632
    /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1633
       occurs so we needn't do it ourselves.
1634
       We then retry reading, ignoring the signal if no handler has
1635
       raised (see issue #10956).
1636
    */
1637
74
    do {
1638
74
        res = PyObject_CallMethodOneArg(self->raw, &_Py_ID(readinto), memobj);
1639
74
    } while (res == NULL && _PyIO_trap_eintr());
1640
74
    Py_DECREF(memobj);
1641
74
    if (res == NULL)
1642
0
        return -1;
1643
74
    if (res == Py_None) {
1644
        /* Non-blocking stream would have blocked. Special return code! */
1645
0
        Py_DECREF(res);
1646
0
        return -2;
1647
0
    }
1648
74
    n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1649
74
    Py_DECREF(res);
1650
1651
74
    if (n == -1 && PyErr_Occurred()) {
1652
0
        _PyErr_FormatFromCause(
1653
0
            PyExc_OSError,
1654
0
            "raw readinto() failed"
1655
0
        );
1656
0
        return -1;
1657
0
    }
1658
1659
74
    if (n < 0 || n > len) {
1660
0
        PyErr_Format(PyExc_OSError,
1661
0
                     "raw readinto() returned invalid length %zd "
1662
0
                     "(should have been between 0 and %zd)", n, len);
1663
0
        return -1;
1664
0
    }
1665
74
    if (n > 0 && self->abs_pos != -1)
1666
33
        self->abs_pos += n;
1667
74
    return n;
1668
74
}
1669
1670
static Py_ssize_t
1671
_bufferedreader_fill_buffer(buffered *self)
1672
65
{
1673
65
    Py_ssize_t start, len, n;
1674
65
    if (VALID_READ_BUFFER(self))
1675
56
        start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1676
9
    else
1677
9
        start = 0;
1678
65
    len = self->buffer_size - start;
1679
65
    n = _bufferedreader_raw_read(self, self->buffer + start, len);
1680
65
    if (n <= 0)
1681
32
        return n;
1682
33
    self->read_end = start + n;
1683
33
    self->raw_pos = start + n;
1684
33
    return n;
1685
65
}
1686
1687
static PyObject *
1688
_bufferedreader_read_all(buffered *self)
1689
7.66k
{
1690
7.66k
    Py_ssize_t current_size;
1691
7.66k
    PyObject *res = NULL, *data = NULL, *tmp = NULL, *chunks = NULL, *readall;
1692
1693
    /* First copy what we have in the current buffer. */
1694
7.66k
    current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1695
7.66k
    if (current_size) {
1696
0
        data = PyBytes_FromStringAndSize(
1697
0
            self->buffer + self->pos, current_size);
1698
0
        if (data == NULL)
1699
0
            return NULL;
1700
0
        self->pos += current_size;
1701
0
    }
1702
    /* We're going past the buffer's bounds, flush it */
1703
7.66k
    if (self->writable) {
1704
0
        tmp = buffered_flush_and_rewind_unlocked(self);
1705
0
        if (tmp == NULL)
1706
0
            goto cleanup;
1707
0
        Py_CLEAR(tmp);
1708
0
    }
1709
7.66k
    _bufferedreader_reset_buf(self);
1710
1711
7.66k
    if (PyObject_GetOptionalAttr(self->raw, &_Py_ID(readall), &readall) < 0) {
1712
0
        goto cleanup;
1713
0
    }
1714
7.66k
    if (readall) {
1715
7.66k
        tmp = _PyObject_CallNoArgs(readall);
1716
7.66k
        Py_DECREF(readall);
1717
7.66k
        if (tmp == NULL)
1718
0
            goto cleanup;
1719
7.66k
        if (tmp != Py_None && !PyBytes_Check(tmp)) {
1720
0
            PyErr_SetString(PyExc_TypeError, "readall() should return bytes");
1721
0
            goto cleanup;
1722
0
        }
1723
7.66k
        if (current_size == 0) {
1724
7.66k
            res = tmp;
1725
7.66k
        } else {
1726
0
            if (tmp != Py_None) {
1727
0
                PyBytes_Concat(&data, tmp);
1728
0
            }
1729
0
            res = data;
1730
0
        }
1731
7.66k
        goto cleanup;
1732
7.66k
    }
1733
1734
0
    chunks = PyList_New(0);
1735
0
    if (chunks == NULL)
1736
0
        goto cleanup;
1737
1738
0
    while (1) {
1739
0
        if (data) {
1740
0
            if (PyList_Append(chunks, data) < 0)
1741
0
                goto cleanup;
1742
0
            Py_CLEAR(data);
1743
0
        }
1744
1745
        /* Read until EOF or until read() would block. */
1746
0
        data = PyObject_CallMethodNoArgs(self->raw, &_Py_ID(read));
1747
0
        if (data == NULL)
1748
0
            goto cleanup;
1749
0
        if (data != Py_None && !PyBytes_Check(data)) {
1750
0
            PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1751
0
            goto cleanup;
1752
0
        }
1753
0
        if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1754
0
            if (current_size == 0) {
1755
0
                res = data;
1756
0
                goto cleanup;
1757
0
            }
1758
0
            else {
1759
0
                tmp = PyBytes_Join((PyObject *)&_Py_SINGLETON(bytes_empty), chunks);
1760
0
                res = tmp;
1761
0
                goto cleanup;
1762
0
            }
1763
0
        }
1764
0
        current_size += PyBytes_GET_SIZE(data);
1765
0
        if (self->abs_pos != -1)
1766
0
            self->abs_pos += PyBytes_GET_SIZE(data);
1767
0
    }
1768
7.66k
cleanup:
1769
    /* res is either NULL or a borrowed ref */
1770
7.66k
    Py_XINCREF(res);
1771
7.66k
    Py_XDECREF(data);
1772
7.66k
    Py_XDECREF(tmp);
1773
7.66k
    Py_XDECREF(chunks);
1774
7.66k
    return res;
1775
0
}
1776
1777
/* Read n bytes from the buffer if it can, otherwise return None.
1778
   This function is simple enough that it can run unlocked. */
1779
static PyObject *
1780
_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
1781
215
{
1782
215
    Py_ssize_t current_size;
1783
1784
215
    current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1785
215
    if (n <= current_size) {
1786
        /* Fast path: the data to read is fully buffered. */
1787
173
        PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1788
173
        if (res != NULL)
1789
173
            self->pos += n;
1790
173
        return res;
1791
173
    }
1792
215
    Py_RETURN_NONE;
1793
215
}
1794
1795
/* Generic read function: read from the stream until enough bytes are read,
1796
 * or until an EOF occurs or until read() would block.
1797
 */
1798
static PyObject *
1799
_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
1800
42
{
1801
42
    Py_ssize_t current_size, remaining, written;
1802
1803
42
    current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1804
42
    if (n <= current_size)
1805
0
        return _bufferedreader_read_fast(self, n);
1806
1807
42
    PyBytesWriter *writer = PyBytesWriter_Create(n);
1808
42
    if (writer == NULL) {
1809
0
        goto error;
1810
0
    }
1811
42
    char *out = PyBytesWriter_GetData(writer);
1812
1813
42
    remaining = n;
1814
42
    written = 0;
1815
42
    if (current_size > 0) {
1816
6
        memcpy(out, self->buffer + self->pos, current_size);
1817
6
        remaining -= current_size;
1818
6
        written += current_size;
1819
6
        self->pos += current_size;
1820
6
    }
1821
    /* Flush the write buffer if necessary */
1822
42
    if (self->writable) {
1823
0
        PyObject *r = buffered_flush_and_rewind_unlocked(self);
1824
0
        if (r == NULL)
1825
0
            goto error;
1826
0
        Py_DECREF(r);
1827
0
    }
1828
42
    _bufferedreader_reset_buf(self);
1829
42
    while (remaining > 0) {
1830
        /* We want to read a whole block at the end into buffer.
1831
           If we had readv() we could do this in one pass. */
1832
42
        Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1833
42
        if (r == 0)
1834
42
            break;
1835
0
        r = _bufferedreader_raw_read(self, out + written, r);
1836
0
        if (r == -1)
1837
0
            goto error;
1838
0
        if (r == 0 || r == -2) {
1839
            /* EOF occurred or read() would block. */
1840
0
            if (r == 0 || written > 0) {
1841
0
                return PyBytesWriter_FinishWithSize(writer, written);
1842
0
            }
1843
0
            PyBytesWriter_Discard(writer);
1844
0
            Py_RETURN_NONE;
1845
0
        }
1846
0
        remaining -= r;
1847
0
        written += r;
1848
0
    }
1849
42
    assert(remaining <= self->buffer_size);
1850
42
    self->pos = 0;
1851
42
    self->raw_pos = 0;
1852
42
    self->read_end = 0;
1853
    /* NOTE: when the read is satisfied, we avoid issuing any additional
1854
       reads, which could block indefinitely (e.g. on a socket).
1855
       See issue #9550. */
1856
56
    while (remaining > 0 && self->read_end < self->buffer_size) {
1857
56
        Py_ssize_t r = _bufferedreader_fill_buffer(self);
1858
56
        if (r == -1)
1859
0
            goto error;
1860
56
        if (r == 0 || r == -2) {
1861
            /* EOF occurred or read() would block. */
1862
32
            if (r == 0 || written > 0) {
1863
32
                return PyBytesWriter_FinishWithSize(writer, written);
1864
32
            }
1865
0
            PyBytesWriter_Discard(writer);
1866
0
            Py_RETURN_NONE;
1867
32
        }
1868
24
        if (remaining > r) {
1869
14
            memcpy(out + written, self->buffer + self->pos, r);
1870
14
            written += r;
1871
14
            self->pos += r;
1872
14
            remaining -= r;
1873
14
        }
1874
10
        else if (remaining > 0) {
1875
10
            memcpy(out + written, self->buffer + self->pos, remaining);
1876
10
            written += remaining;
1877
10
            self->pos += remaining;
1878
10
            remaining = 0;
1879
10
        }
1880
24
        if (remaining == 0)
1881
10
            break;
1882
24
    }
1883
1884
10
    return PyBytesWriter_Finish(writer);
1885
1886
0
error:
1887
0
    PyBytesWriter_Discard(writer);
1888
0
    return NULL;
1889
42
}
1890
1891
static PyObject *
1892
_bufferedreader_peek_unlocked(buffered *self)
1893
0
{
1894
0
    Py_ssize_t have, r;
1895
1896
0
    have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1897
    /* Constraints:
1898
       1. we don't want to advance the file position.
1899
       2. we don't want to lose block alignment, so we can't shift the buffer
1900
          to make some place.
1901
       Therefore, we either return `have` bytes (if > 0), or a full buffer.
1902
    */
1903
0
    if (have > 0) {
1904
0
        return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1905
0
    }
1906
1907
    /* Fill the buffer from the raw stream, and copy it to the result. */
1908
0
    _bufferedreader_reset_buf(self);
1909
0
    r = _bufferedreader_fill_buffer(self);
1910
0
    if (r == -1)
1911
0
        return NULL;
1912
0
    if (r == -2)
1913
0
        r = 0;
1914
0
    self->pos = 0;
1915
0
    return PyBytes_FromStringAndSize(self->buffer, r);
1916
0
}
1917
1918
1919
/*
1920
 * class BufferedWriter
1921
 */
1922
static void
1923
_bufferedwriter_reset_buf(buffered *self)
1924
260k
{
1925
260k
    self->write_pos = 0;
1926
260k
    self->write_end = -1;
1927
260k
}
1928
1929
/*[clinic input]
1930
_io.BufferedWriter.__init__
1931
    raw: object
1932
    buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
1933
1934
A buffer for a writeable sequential RawIO object.
1935
1936
The constructor creates a BufferedWriter for the given writeable raw
1937
stream. If the buffer_size is not given, it defaults to
1938
DEFAULT_BUFFER_SIZE.
1939
[clinic start generated code]*/
1940
1941
static int
1942
_io_BufferedWriter___init___impl(buffered *self, PyObject *raw,
1943
                                 Py_ssize_t buffer_size)
1944
/*[clinic end generated code: output=c8942a020c0dee64 input=914be9b95e16007b]*/
1945
26.7k
{
1946
26.7k
    self->ok = 0;
1947
26.7k
    self->detached = 0;
1948
1949
26.7k
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
1950
26.7k
    if (_PyIOBase_check_writable(state, raw, Py_True) == NULL) {
1951
0
        return -1;
1952
0
    }
1953
1954
26.7k
    Py_INCREF(raw);
1955
26.7k
    Py_XSETREF(self->raw, raw);
1956
26.7k
    self->readable = 0;
1957
26.7k
    self->writable = 1;
1958
1959
26.7k
    self->buffer_size = buffer_size;
1960
26.7k
    if (_buffered_init(self) < 0)
1961
0
        return -1;
1962
26.7k
    _bufferedwriter_reset_buf(self);
1963
26.7k
    self->pos = 0;
1964
1965
26.7k
    self->fast_closed_checks = (
1966
26.7k
        Py_IS_TYPE(self, state->PyBufferedWriter_Type) &&
1967
26.7k
        Py_IS_TYPE(raw, state->PyFileIO_Type)
1968
26.7k
    );
1969
1970
26.7k
    self->ok = 1;
1971
26.7k
    return 0;
1972
26.7k
}
1973
1974
static Py_ssize_t
1975
_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
1976
232k
{
1977
232k
    Py_buffer buf;
1978
232k
    PyObject *memobj, *res;
1979
232k
    Py_ssize_t n;
1980
232k
    int errnum;
1981
    /* NOTE: the buffer needn't be released as its object is NULL. */
1982
232k
    if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1983
0
        return -1;
1984
232k
    memobj = PyMemoryView_FromBuffer(&buf);
1985
232k
    if (memobj == NULL)
1986
0
        return -1;
1987
    /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1988
       occurs so we needn't do it ourselves.
1989
       We then retry writing, ignoring the signal if no handler has
1990
       raised (see issue #10956).
1991
    */
1992
232k
    do {
1993
232k
        errno = 0;
1994
232k
        res = PyObject_CallMethodOneArg(self->raw, &_Py_ID(write), memobj);
1995
232k
        errnum = errno;
1996
232k
    } while (res == NULL && _PyIO_trap_eintr());
1997
232k
    Py_DECREF(memobj);
1998
232k
    if (res == NULL)
1999
0
        return -1;
2000
232k
    if (res == Py_None) {
2001
        /* Non-blocking stream would have blocked. Special return code!
2002
           Being paranoid we reset errno in case it is changed by code
2003
           triggered by a decref.  errno is used by _set_BlockingIOError(). */
2004
0
        Py_DECREF(res);
2005
0
        errno = errnum;
2006
0
        return -2;
2007
0
    }
2008
232k
    n = PyNumber_AsSsize_t(res, PyExc_ValueError);
2009
232k
    Py_DECREF(res);
2010
232k
    if (n < 0 || n > len) {
2011
0
        PyErr_Format(PyExc_OSError,
2012
0
                     "raw write() returned invalid length %zd "
2013
0
                     "(should have been between 0 and %zd)", n, len);
2014
0
        return -1;
2015
0
    }
2016
232k
    if (n > 0 && self->abs_pos != -1)
2017
232k
        self->abs_pos += n;
2018
232k
    return n;
2019
232k
}
2020
2021
static PyObject *
2022
_bufferedwriter_flush_unlocked(buffered *self)
2023
233k
{
2024
233k
    Py_off_t n, rewind;
2025
2026
233k
    if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
2027
1.30k
        goto end;
2028
    /* First, rewind */
2029
232k
    rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
2030
232k
    if (rewind != 0) {
2031
0
        n = _buffered_raw_seek(self, -rewind, 1);
2032
0
        if (n < 0) {
2033
0
            goto error;
2034
0
        }
2035
0
        self->raw_pos -= rewind;
2036
0
    }
2037
464k
    while (self->write_pos < self->write_end) {
2038
232k
        n = _bufferedwriter_raw_write(self,
2039
232k
            self->buffer + self->write_pos,
2040
232k
            Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
2041
232k
                             Py_off_t, Py_ssize_t));
2042
232k
        if (n == -1) {
2043
0
            goto error;
2044
0
        }
2045
232k
        else if (n == -2) {
2046
0
            _set_BlockingIOError("write could not complete without blocking",
2047
0
                                 0);
2048
0
            goto error;
2049
0
        }
2050
232k
        self->write_pos += n;
2051
232k
        self->raw_pos = self->write_pos;
2052
        /* Partial writes can return successfully when interrupted by a
2053
           signal (see write(2)).  We must run signal handlers before
2054
           blocking another time, possibly indefinitely. */
2055
232k
        if (PyErr_CheckSignals() < 0)
2056
0
            goto error;
2057
232k
    }
2058
2059
2060
233k
end:
2061
    /* This ensures that after return from this function,
2062
       VALID_WRITE_BUFFER(self) returns false.
2063
2064
       This is a required condition because when a tell() is called
2065
       after flushing and if VALID_READ_BUFFER(self) is false, we need
2066
       VALID_WRITE_BUFFER(self) to be false to have
2067
       RAW_OFFSET(self) == 0.
2068
2069
       Issue: https://bugs.python.org/issue32228 */
2070
233k
    _bufferedwriter_reset_buf(self);
2071
233k
    Py_RETURN_NONE;
2072
2073
0
error:
2074
0
    return NULL;
2075
232k
}
2076
2077
/*[clinic input]
2078
@critical_section
2079
_io.BufferedWriter.write
2080
    buffer: Py_buffer
2081
    /
2082
[clinic start generated code]*/
2083
2084
static PyObject *
2085
_io_BufferedWriter_write_impl(buffered *self, Py_buffer *buffer)
2086
/*[clinic end generated code: output=7f8d1365759bfc6b input=6a9c041de0c337be]*/
2087
232k
{
2088
232k
    PyObject *res = NULL;
2089
232k
    Py_ssize_t written, avail, remaining;
2090
232k
    Py_off_t offset;
2091
232k
    int r;
2092
2093
232k
    CHECK_INITIALIZED(self)
2094
2095
232k
    if (!ENTER_BUFFERED(self))
2096
0
        return NULL;
2097
2098
    /* Issue #31976: Check for closed file after acquiring the lock. Another
2099
       thread could be holding the lock while closing the file. */
2100
232k
    r = IS_CLOSED(self);
2101
232k
    if (r < 0) {
2102
0
        goto error;
2103
0
    }
2104
232k
    if (r > 0) {
2105
0
        PyErr_SetString(PyExc_ValueError, "write to closed file");
2106
0
        goto error;
2107
0
    }
2108
2109
    /* Fast path: the data to write can be fully buffered. */
2110
232k
    if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
2111
232k
        self->pos = 0;
2112
232k
        self->raw_pos = 0;
2113
232k
    }
2114
232k
    avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
2115
232k
    if (buffer->len <= avail && buffer->len < self->buffer_size) {
2116
232k
        memcpy(self->buffer + self->pos, buffer->buf, buffer->len);
2117
232k
        if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
2118
232k
            self->write_pos = self->pos;
2119
232k
        }
2120
232k
        ADJUST_POSITION(self, self->pos + buffer->len);
2121
232k
        if (self->pos > self->write_end)
2122
232k
            self->write_end = self->pos;
2123
232k
        written = buffer->len;
2124
232k
        goto end;
2125
232k
    }
2126
2127
    /* First write the current buffer */
2128
792
    res = _bufferedwriter_flush_unlocked(self);
2129
792
    if (res == NULL) {
2130
0
        Py_ssize_t *w = _buffered_check_blocking_error();
2131
0
        if (w == NULL)
2132
0
            goto error;
2133
0
        if (self->readable)
2134
0
            _bufferedreader_reset_buf(self);
2135
        /* Make some place by shifting the buffer. */
2136
0
        assert(VALID_WRITE_BUFFER(self));
2137
0
        memmove(self->buffer, self->buffer + self->write_pos,
2138
0
                Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
2139
0
                                 Py_off_t, Py_ssize_t));
2140
0
        self->write_end -= self->write_pos;
2141
0
        self->raw_pos -= self->write_pos;
2142
0
        self->pos -= self->write_pos;
2143
0
        self->write_pos = 0;
2144
0
        avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
2145
0
                                 Py_off_t, Py_ssize_t);
2146
0
        if (buffer->len <= avail) {
2147
            /* Everything can be buffered */
2148
0
            PyErr_Clear();
2149
0
            memcpy(self->buffer + self->write_end, buffer->buf, buffer->len);
2150
0
            self->write_end += buffer->len;
2151
0
            self->pos += buffer->len;
2152
0
            written = buffer->len;
2153
0
            goto end;
2154
0
        }
2155
        /* Buffer as much as possible. */
2156
0
        memcpy(self->buffer + self->write_end, buffer->buf, avail);
2157
0
        self->write_end += avail;
2158
0
        self->pos += avail;
2159
        /* XXX Modifying the existing exception e using the pointer w
2160
           will change e.characters_written but not e.args[2].
2161
           Therefore we just replace with a new error. */
2162
0
        _set_BlockingIOError("write could not complete without blocking",
2163
0
                             avail);
2164
0
        goto error;
2165
0
    }
2166
792
    Py_CLEAR(res);
2167
2168
    /* Adjust the raw stream position if it is away from the logical stream
2169
       position. This happens if the read buffer has been filled but not
2170
       modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
2171
       the raw stream by itself).
2172
       Fixes issue #6629.
2173
    */
2174
792
    offset = RAW_OFFSET(self);
2175
792
    if (offset != 0) {
2176
0
        if (_buffered_raw_seek(self, -offset, 1) < 0)
2177
0
            goto error;
2178
0
        self->raw_pos -= offset;
2179
0
    }
2180
2181
    /* Then write buf itself. At this point the buffer has been emptied. */
2182
792
    remaining = buffer->len;
2183
792
    written = 0;
2184
1.58k
    while (remaining >= self->buffer_size) {
2185
792
        Py_ssize_t n = _bufferedwriter_raw_write(
2186
792
            self, (char *) buffer->buf + written, buffer->len - written);
2187
792
        if (n == -1) {
2188
0
            goto error;
2189
792
        } else if (n == -2) {
2190
            /* Write failed because raw file is non-blocking */
2191
0
            if (remaining > self->buffer_size) {
2192
                /* Can't buffer everything, still buffer as much as possible */
2193
0
                memcpy(self->buffer,
2194
0
                       (char *) buffer->buf + written, self->buffer_size);
2195
0
                self->raw_pos = 0;
2196
0
                ADJUST_POSITION(self, self->buffer_size);
2197
0
                self->write_end = self->buffer_size;
2198
0
                written += self->buffer_size;
2199
0
                _set_BlockingIOError("write could not complete without "
2200
0
                                     "blocking", written);
2201
0
                goto error;
2202
0
            }
2203
0
            PyErr_Clear();
2204
0
            break;
2205
0
        }
2206
792
        written += n;
2207
792
        remaining -= n;
2208
        /* Partial writes can return successfully when interrupted by a
2209
           signal (see write(2)).  We must run signal handlers before
2210
           blocking another time, possibly indefinitely. */
2211
792
        if (PyErr_CheckSignals() < 0)
2212
0
            goto error;
2213
792
    }
2214
792
    if (self->readable)
2215
0
        _bufferedreader_reset_buf(self);
2216
792
    if (remaining > 0) {
2217
0
        memcpy(self->buffer, (char *) buffer->buf + written, remaining);
2218
0
        written += remaining;
2219
0
    }
2220
792
    self->write_pos = 0;
2221
    /* TODO: sanity check (remaining >= 0) */
2222
792
    self->write_end = remaining;
2223
792
    ADJUST_POSITION(self, remaining);
2224
792
    self->raw_pos = 0;
2225
2226
232k
end:
2227
232k
    res = PyLong_FromSsize_t(written);
2228
2229
232k
error:
2230
232k
    LEAVE_BUFFERED(self)
2231
232k
    return res;
2232
232k
}
2233
2234
2235
/*
2236
 * BufferedRWPair
2237
 */
2238
2239
/* XXX The usefulness of this (compared to having two separate IO objects) is
2240
 * questionable.
2241
 */
2242
2243
typedef struct {
2244
    PyObject_HEAD
2245
    buffered *reader;
2246
    buffered *writer;
2247
    PyObject *dict;
2248
    PyObject *weakreflist;
2249
} rwpair;
2250
2251
0
#define rwpair_CAST(op) ((rwpair *)(op))
2252
2253
/*[clinic input]
2254
_io.BufferedRWPair.__init__
2255
    reader: object
2256
    writer: object
2257
    buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
2258
    /
2259
2260
A buffered reader and writer object together.
2261
2262
A buffered reader object and buffered writer object put together to
2263
form a sequential IO object that can read and write. This is typically
2264
used with a socket or two-way pipe.
2265
2266
reader and writer are RawIOBase objects that are readable and
2267
writeable respectively. If the buffer_size is omitted it defaults to
2268
DEFAULT_BUFFER_SIZE.
2269
[clinic start generated code]*/
2270
2271
static int
2272
_io_BufferedRWPair___init___impl(rwpair *self, PyObject *reader,
2273
                                 PyObject *writer, Py_ssize_t buffer_size)
2274
/*[clinic end generated code: output=327e73d1aee8f984 input=620d42d71f33a031]*/
2275
0
{
2276
0
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
2277
0
    if (_PyIOBase_check_readable(state, reader, Py_True) == NULL) {
2278
0
        return -1;
2279
0
    }
2280
0
    if (_PyIOBase_check_writable(state, writer, Py_True) == NULL) {
2281
0
        return -1;
2282
0
    }
2283
2284
0
    self->reader = (buffered *) PyObject_CallFunction(
2285
0
            (PyObject *)state->PyBufferedReader_Type,
2286
0
            "On", reader, buffer_size);
2287
0
    if (self->reader == NULL)
2288
0
        return -1;
2289
2290
0
    self->writer = (buffered *) PyObject_CallFunction(
2291
0
            (PyObject *)state->PyBufferedWriter_Type,
2292
0
            "On", writer, buffer_size);
2293
0
    if (self->writer == NULL) {
2294
0
        Py_CLEAR(self->reader);
2295
0
        return -1;
2296
0
    }
2297
2298
0
    return 0;
2299
0
}
2300
2301
static int
2302
bufferedrwpair_traverse(PyObject *op, visitproc visit, void *arg)
2303
0
{
2304
0
    rwpair *self = rwpair_CAST(op);
2305
0
    Py_VISIT(Py_TYPE(self));
2306
0
    Py_VISIT(self->dict);
2307
0
    Py_VISIT(self->reader);
2308
0
    Py_VISIT(self->writer);
2309
0
    return 0;
2310
0
}
2311
2312
static int
2313
bufferedrwpair_clear(PyObject *op)
2314
0
{
2315
0
    rwpair *self = rwpair_CAST(op);
2316
0
    Py_CLEAR(self->reader);
2317
0
    Py_CLEAR(self->writer);
2318
0
    Py_CLEAR(self->dict);
2319
0
    return 0;
2320
0
}
2321
2322
static void
2323
bufferedrwpair_dealloc(PyObject *op)
2324
0
{
2325
0
    rwpair *self = rwpair_CAST(op);
2326
0
    PyTypeObject *tp = Py_TYPE(self);
2327
0
    _PyObject_GC_UNTRACK(self);
2328
0
    FT_CLEAR_WEAKREFS(op, self->weakreflist);
2329
0
    (void)bufferedrwpair_clear(op);
2330
0
    tp->tp_free(self);
2331
0
    Py_DECREF(tp);
2332
0
}
2333
2334
static PyObject *
2335
_forward_call(buffered *self, PyObject *name, PyObject *args)
2336
0
{
2337
0
    PyObject *func, *ret;
2338
0
    if (self == NULL) {
2339
0
        PyErr_SetString(PyExc_ValueError,
2340
0
                        "I/O operation on uninitialized object");
2341
0
        return NULL;
2342
0
    }
2343
2344
0
    func = PyObject_GetAttr((PyObject *)self, name);
2345
0
    if (func == NULL) {
2346
0
        PyErr_SetObject(PyExc_AttributeError, name);
2347
0
        return NULL;
2348
0
    }
2349
2350
0
    ret = PyObject_CallObject(func, args);
2351
0
    Py_DECREF(func);
2352
0
    return ret;
2353
0
}
2354
2355
static PyObject *
2356
bufferedrwpair_read(PyObject *op, PyObject *args)
2357
0
{
2358
0
    rwpair *self = rwpair_CAST(op);
2359
0
    return _forward_call(self->reader, &_Py_ID(read), args);
2360
0
}
2361
2362
static PyObject *
2363
bufferedrwpair_peek(PyObject *op, PyObject *args)
2364
0
{
2365
0
    rwpair *self = rwpair_CAST(op);
2366
0
    return _forward_call(self->reader, &_Py_ID(peek), args);
2367
0
}
2368
2369
static PyObject *
2370
bufferedrwpair_read1(PyObject *op, PyObject *args)
2371
0
{
2372
0
    rwpair *self = rwpair_CAST(op);
2373
0
    return _forward_call(self->reader, &_Py_ID(read1), args);
2374
0
}
2375
2376
static PyObject *
2377
bufferedrwpair_readinto(PyObject *op, PyObject *args)
2378
0
{
2379
0
    rwpair *self = rwpair_CAST(op);
2380
0
    return _forward_call(self->reader, &_Py_ID(readinto), args);
2381
0
}
2382
2383
static PyObject *
2384
bufferedrwpair_readinto1(PyObject *op, PyObject *args)
2385
0
{
2386
0
    rwpair *self = rwpair_CAST(op);
2387
0
    return _forward_call(self->reader, &_Py_ID(readinto1), args);
2388
0
}
2389
2390
static PyObject *
2391
bufferedrwpair_write(PyObject *op, PyObject *args)
2392
0
{
2393
0
    rwpair *self = rwpair_CAST(op);
2394
0
    return _forward_call(self->writer, &_Py_ID(write), args);
2395
0
}
2396
2397
static PyObject *
2398
bufferedrwpair_flush(PyObject *op, PyObject *Py_UNUSED(dummy))
2399
0
{
2400
0
    rwpair *self = rwpair_CAST(op);
2401
0
    return _forward_call(self->writer, &_Py_ID(flush), NULL);
2402
0
}
2403
2404
static PyObject *
2405
bufferedrwpair_readable(PyObject *op, PyObject *Py_UNUSED(dummy))
2406
0
{
2407
0
    rwpair *self = rwpair_CAST(op);
2408
0
    return _forward_call(self->reader, &_Py_ID(readable), NULL);
2409
0
}
2410
2411
static PyObject *
2412
bufferedrwpair_writable(PyObject *op, PyObject *Py_UNUSED(dummy))
2413
0
{
2414
0
    rwpair *self = rwpair_CAST(op);
2415
0
    return _forward_call(self->writer, &_Py_ID(writable), NULL);
2416
0
}
2417
2418
static PyObject *
2419
bufferedrwpair_close(PyObject *op, PyObject *Py_UNUSED(dummy))
2420
0
{
2421
0
    rwpair *self = rwpair_CAST(op);
2422
0
    PyObject *exc = NULL;
2423
0
    PyObject *ret = _forward_call(self->writer, &_Py_ID(close), NULL);
2424
0
    if (ret == NULL) {
2425
0
        exc = PyErr_GetRaisedException();
2426
0
    }
2427
0
    else {
2428
0
        Py_DECREF(ret);
2429
0
    }
2430
0
    ret = _forward_call(self->reader, &_Py_ID(close), NULL);
2431
0
    if (exc != NULL) {
2432
0
        _PyErr_ChainExceptions1(exc);
2433
0
        Py_CLEAR(ret);
2434
0
    }
2435
0
    return ret;
2436
0
}
2437
2438
static PyObject *
2439
bufferedrwpair_isatty(PyObject *op, PyObject *Py_UNUSED(dummy))
2440
0
{
2441
0
    rwpair *self = rwpair_CAST(op);
2442
0
    PyObject *ret = _forward_call(self->writer, &_Py_ID(isatty), NULL);
2443
2444
0
    if (ret != Py_False) {
2445
        /* either True or exception */
2446
0
        return ret;
2447
0
    }
2448
0
    Py_DECREF(ret);
2449
2450
0
    return _forward_call(self->reader, &_Py_ID(isatty), NULL);
2451
0
}
2452
2453
static PyObject *
2454
bufferedrwpair_closed_get(PyObject *op, void *Py_UNUSED(dummy))
2455
0
{
2456
0
    rwpair *self = rwpair_CAST(op);
2457
0
    if (self->writer == NULL) {
2458
0
        PyErr_SetString(PyExc_RuntimeError,
2459
0
                "the BufferedRWPair object is being garbage-collected");
2460
0
        return NULL;
2461
0
    }
2462
0
    return PyObject_GetAttr((PyObject *) self->writer, &_Py_ID(closed));
2463
0
}
2464
2465
2466
/*
2467
 * BufferedRandom
2468
 */
2469
2470
/*[clinic input]
2471
_io.BufferedRandom.__init__
2472
    raw: object
2473
    buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
2474
2475
A buffered interface to random access streams.
2476
2477
The constructor creates a reader and writer for a seekable stream,
2478
raw, given in the first argument. If the buffer_size is omitted it
2479
defaults to DEFAULT_BUFFER_SIZE.
2480
[clinic start generated code]*/
2481
2482
static int
2483
_io_BufferedRandom___init___impl(buffered *self, PyObject *raw,
2484
                                 Py_ssize_t buffer_size)
2485
/*[clinic end generated code: output=d3d64eb0f64e64a3 input=a4e818fb86d0e50c]*/
2486
0
{
2487
0
    self->ok = 0;
2488
0
    self->detached = 0;
2489
2490
0
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
2491
0
    if (_PyIOBase_check_seekable(state, raw, Py_True) == NULL) {
2492
0
        return -1;
2493
0
    }
2494
0
    if (_PyIOBase_check_readable(state, raw, Py_True) == NULL) {
2495
0
        return -1;
2496
0
    }
2497
0
    if (_PyIOBase_check_writable(state, raw, Py_True) == NULL) {
2498
0
        return -1;
2499
0
    }
2500
2501
0
    Py_INCREF(raw);
2502
0
    Py_XSETREF(self->raw, raw);
2503
0
    self->buffer_size = buffer_size;
2504
0
    self->readable = 1;
2505
0
    self->writable = 1;
2506
2507
0
    if (_buffered_init(self) < 0)
2508
0
        return -1;
2509
0
    _bufferedreader_reset_buf(self);
2510
0
    _bufferedwriter_reset_buf(self);
2511
0
    self->pos = 0;
2512
2513
0
    self->fast_closed_checks = (Py_IS_TYPE(self, state->PyBufferedRandom_Type) &&
2514
0
                                Py_IS_TYPE(raw, state->PyFileIO_Type));
2515
2516
0
    self->ok = 1;
2517
0
    return 0;
2518
0
}
2519
2520
0
#define clinic_state() (find_io_state_by_def(Py_TYPE(self)))
2521
#include "clinic/bufferedio.c.h"
2522
#undef clinic_state
2523
2524
static PyMethodDef bufferediobase_methods[] = {
2525
    _IO__BUFFEREDIOBASE_DETACH_METHODDEF
2526
    _IO__BUFFEREDIOBASE_READ_METHODDEF
2527
    _IO__BUFFEREDIOBASE_READ1_METHODDEF
2528
    _IO__BUFFEREDIOBASE_READINTO_METHODDEF
2529
    _IO__BUFFEREDIOBASE_READINTO1_METHODDEF
2530
    _IO__BUFFEREDIOBASE_WRITE_METHODDEF
2531
    {NULL, NULL}
2532
};
2533
2534
static PyType_Slot bufferediobase_slots[] = {
2535
    {Py_tp_doc, (void *)bufferediobase_doc},
2536
    {Py_tp_methods, bufferediobase_methods},
2537
    {0, NULL},
2538
};
2539
2540
/* Do not set Py_TPFLAGS_HAVE_GC so that tp_traverse and tp_clear are inherited */
2541
PyType_Spec _Py_bufferediobase_spec = {
2542
    .name = "_io._BufferedIOBase",
2543
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
2544
              Py_TPFLAGS_IMMUTABLETYPE),
2545
    .slots = bufferediobase_slots,
2546
};
2547
2548
static PyMethodDef bufferedreader_methods[] = {
2549
    /* BufferedIOMixin methods */
2550
    _IO__BUFFERED_DETACH_METHODDEF
2551
    _IO__BUFFERED_SIMPLE_FLUSH_METHODDEF
2552
    _IO__BUFFERED_CLOSE_METHODDEF
2553
    _IO__BUFFERED_SEEKABLE_METHODDEF
2554
    _IO__BUFFERED_READABLE_METHODDEF
2555
    _IO__BUFFERED_FILENO_METHODDEF
2556
    _IO__BUFFERED_ISATTY_METHODDEF
2557
    _IO__BUFFERED__DEALLOC_WARN_METHODDEF
2558
2559
    _IO__BUFFERED_READ_METHODDEF
2560
    _IO__BUFFERED_PEEK_METHODDEF
2561
    _IO__BUFFERED_READ1_METHODDEF
2562
    _IO__BUFFERED_READINTO_METHODDEF
2563
    _IO__BUFFERED_READINTO1_METHODDEF
2564
    _IO__BUFFERED_READLINE_METHODDEF
2565
    _IO__BUFFERED_SEEK_METHODDEF
2566
    _IO__BUFFERED_TELL_METHODDEF
2567
    _IO__BUFFERED_TRUNCATE_METHODDEF
2568
    _IO__BUFFERED___SIZEOF___METHODDEF
2569
2570
    {"__getstate__", _PyIOBase_cannot_pickle, METH_NOARGS},
2571
    {NULL, NULL}
2572
};
2573
2574
static PyMemberDef bufferedreader_members[] = {
2575
    {"raw", _Py_T_OBJECT, offsetof(buffered, raw), Py_READONLY},
2576
    {"_finalizing", Py_T_BOOL, offsetof(buffered, finalizing), 0},
2577
    {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(buffered, weakreflist), Py_READONLY},
2578
    {"__dictoffset__", Py_T_PYSSIZET, offsetof(buffered, dict), Py_READONLY},
2579
    {NULL}
2580
};
2581
2582
static PyGetSetDef bufferedreader_getset[] = {
2583
    _IO__BUFFERED_CLOSED_GETSETDEF
2584
    _IO__BUFFERED_NAME_GETSETDEF
2585
    _IO__BUFFERED_MODE_GETSETDEF
2586
    {NULL}
2587
};
2588
2589
2590
static PyType_Slot bufferedreader_slots[] = {
2591
    {Py_tp_dealloc, buffered_dealloc},
2592
    {Py_tp_repr, buffered_repr},
2593
    {Py_tp_doc, (void *)_io_BufferedReader___init____doc__},
2594
    {Py_tp_traverse, buffered_traverse},
2595
    {Py_tp_clear, buffered_clear},
2596
    {Py_tp_iternext, buffered_iternext},
2597
    {Py_tp_methods, bufferedreader_methods},
2598
    {Py_tp_members, bufferedreader_members},
2599
    {Py_tp_getset, bufferedreader_getset},
2600
    {Py_tp_init, _io_BufferedReader___init__},
2601
    {0, NULL},
2602
};
2603
2604
PyType_Spec _Py_bufferedreader_spec = {
2605
    .name = "_io.BufferedReader",
2606
    .basicsize = sizeof(buffered),
2607
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
2608
              Py_TPFLAGS_IMMUTABLETYPE),
2609
    .slots = bufferedreader_slots,
2610
};
2611
2612
static PyMethodDef bufferedwriter_methods[] = {
2613
    /* BufferedIOMixin methods */
2614
    _IO__BUFFERED_CLOSE_METHODDEF
2615
    _IO__BUFFERED_DETACH_METHODDEF
2616
    _IO__BUFFERED_SEEKABLE_METHODDEF
2617
    _IO__BUFFERED_WRITABLE_METHODDEF
2618
    _IO__BUFFERED_FILENO_METHODDEF
2619
    _IO__BUFFERED_ISATTY_METHODDEF
2620
    _IO__BUFFERED__DEALLOC_WARN_METHODDEF
2621
2622
    _IO_BUFFEREDWRITER_WRITE_METHODDEF
2623
    _IO__BUFFERED_TRUNCATE_METHODDEF
2624
    _IO__BUFFERED_FLUSH_METHODDEF
2625
    _IO__BUFFERED_SEEK_METHODDEF
2626
    _IO__BUFFERED_TELL_METHODDEF
2627
    _IO__BUFFERED___SIZEOF___METHODDEF
2628
2629
    {"__getstate__", _PyIOBase_cannot_pickle, METH_NOARGS},
2630
    {NULL, NULL}
2631
};
2632
2633
static PyMemberDef bufferedwriter_members[] = {
2634
    {"raw", _Py_T_OBJECT, offsetof(buffered, raw), Py_READONLY},
2635
    {"_finalizing", Py_T_BOOL, offsetof(buffered, finalizing), 0},
2636
    {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(buffered, weakreflist), Py_READONLY},
2637
    {"__dictoffset__", Py_T_PYSSIZET, offsetof(buffered, dict), Py_READONLY},
2638
    {NULL}
2639
};
2640
2641
static PyGetSetDef bufferedwriter_getset[] = {
2642
    _IO__BUFFERED_CLOSED_GETSETDEF
2643
    _IO__BUFFERED_NAME_GETSETDEF
2644
    _IO__BUFFERED_MODE_GETSETDEF
2645
    {NULL}
2646
};
2647
2648
2649
static PyType_Slot bufferedwriter_slots[] = {
2650
    {Py_tp_dealloc, buffered_dealloc},
2651
    {Py_tp_repr, buffered_repr},
2652
    {Py_tp_doc, (void *)_io_BufferedWriter___init____doc__},
2653
    {Py_tp_traverse, buffered_traverse},
2654
    {Py_tp_clear, buffered_clear},
2655
    {Py_tp_methods, bufferedwriter_methods},
2656
    {Py_tp_members, bufferedwriter_members},
2657
    {Py_tp_getset, bufferedwriter_getset},
2658
    {Py_tp_init, _io_BufferedWriter___init__},
2659
    {0, NULL},
2660
};
2661
2662
PyType_Spec _Py_bufferedwriter_spec = {
2663
    .name = "_io.BufferedWriter",
2664
    .basicsize = sizeof(buffered),
2665
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
2666
              Py_TPFLAGS_IMMUTABLETYPE),
2667
    .slots = bufferedwriter_slots,
2668
};
2669
2670
static PyMethodDef bufferedrwpair_methods[] = {
2671
    {"read", bufferedrwpair_read, METH_VARARGS},
2672
    {"peek", bufferedrwpair_peek, METH_VARARGS},
2673
    {"read1", bufferedrwpair_read1, METH_VARARGS},
2674
    {"readinto", bufferedrwpair_readinto, METH_VARARGS},
2675
    {"readinto1", bufferedrwpair_readinto1, METH_VARARGS},
2676
2677
    {"write", bufferedrwpair_write, METH_VARARGS},
2678
    {"flush", bufferedrwpair_flush, METH_NOARGS},
2679
2680
    {"readable", bufferedrwpair_readable, METH_NOARGS},
2681
    {"writable", bufferedrwpair_writable, METH_NOARGS},
2682
2683
    {"close", bufferedrwpair_close, METH_NOARGS},
2684
    {"isatty", bufferedrwpair_isatty, METH_NOARGS},
2685
2686
    {NULL, NULL}
2687
};
2688
2689
static PyMemberDef bufferedrwpair_members[] = {
2690
    {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(rwpair, weakreflist), Py_READONLY},
2691
    {"__dictoffset__", Py_T_PYSSIZET, offsetof(rwpair, dict), Py_READONLY},
2692
    {NULL}
2693
};
2694
2695
static PyGetSetDef bufferedrwpair_getset[] = {
2696
    {"closed", bufferedrwpair_closed_get, NULL, NULL},
2697
    {NULL}
2698
};
2699
2700
static PyType_Slot bufferedrwpair_slots[] = {
2701
    {Py_tp_dealloc, bufferedrwpair_dealloc},
2702
    {Py_tp_doc, (void *)_io_BufferedRWPair___init____doc__},
2703
    {Py_tp_traverse, bufferedrwpair_traverse},
2704
    {Py_tp_clear, bufferedrwpair_clear},
2705
    {Py_tp_methods, bufferedrwpair_methods},
2706
    {Py_tp_members, bufferedrwpair_members},
2707
    {Py_tp_getset, bufferedrwpair_getset},
2708
    {Py_tp_init, _io_BufferedRWPair___init__},
2709
    {0, NULL},
2710
};
2711
2712
PyType_Spec _Py_bufferedrwpair_spec = {
2713
    .name = "_io.BufferedRWPair",
2714
    .basicsize = sizeof(rwpair),
2715
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
2716
              Py_TPFLAGS_IMMUTABLETYPE),
2717
    .slots = bufferedrwpair_slots,
2718
};
2719
2720
2721
static PyMethodDef bufferedrandom_methods[] = {
2722
    /* BufferedIOMixin methods */
2723
    _IO__BUFFERED_CLOSE_METHODDEF
2724
    _IO__BUFFERED_DETACH_METHODDEF
2725
    _IO__BUFFERED_SEEKABLE_METHODDEF
2726
    _IO__BUFFERED_READABLE_METHODDEF
2727
    _IO__BUFFERED_WRITABLE_METHODDEF
2728
    _IO__BUFFERED_FILENO_METHODDEF
2729
    _IO__BUFFERED_ISATTY_METHODDEF
2730
    _IO__BUFFERED__DEALLOC_WARN_METHODDEF
2731
2732
    _IO__BUFFERED_FLUSH_METHODDEF
2733
2734
    _IO__BUFFERED_SEEK_METHODDEF
2735
    _IO__BUFFERED_TELL_METHODDEF
2736
    _IO__BUFFERED_TRUNCATE_METHODDEF
2737
    _IO__BUFFERED_READ_METHODDEF
2738
    _IO__BUFFERED_READ1_METHODDEF
2739
    _IO__BUFFERED_READINTO_METHODDEF
2740
    _IO__BUFFERED_READINTO1_METHODDEF
2741
    _IO__BUFFERED_READLINE_METHODDEF
2742
    _IO__BUFFERED_PEEK_METHODDEF
2743
    _IO_BUFFEREDWRITER_WRITE_METHODDEF
2744
    _IO__BUFFERED___SIZEOF___METHODDEF
2745
2746
    {"__getstate__", _PyIOBase_cannot_pickle, METH_NOARGS},
2747
    {NULL, NULL}
2748
};
2749
2750
static PyMemberDef bufferedrandom_members[] = {
2751
    {"raw", _Py_T_OBJECT, offsetof(buffered, raw), Py_READONLY},
2752
    {"_finalizing", Py_T_BOOL, offsetof(buffered, finalizing), 0},
2753
    {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(buffered, weakreflist), Py_READONLY},
2754
    {"__dictoffset__", Py_T_PYSSIZET, offsetof(buffered, dict), Py_READONLY},
2755
    {NULL}
2756
};
2757
2758
static PyGetSetDef bufferedrandom_getset[] = {
2759
    _IO__BUFFERED_CLOSED_GETSETDEF
2760
    _IO__BUFFERED_NAME_GETSETDEF
2761
    _IO__BUFFERED_MODE_GETSETDEF
2762
    {NULL}
2763
};
2764
2765
2766
static PyType_Slot bufferedrandom_slots[] = {
2767
    {Py_tp_dealloc, buffered_dealloc},
2768
    {Py_tp_repr, buffered_repr},
2769
    {Py_tp_doc, (void *)_io_BufferedRandom___init____doc__},
2770
    {Py_tp_traverse, buffered_traverse},
2771
    {Py_tp_clear, buffered_clear},
2772
    {Py_tp_iternext, buffered_iternext},
2773
    {Py_tp_methods, bufferedrandom_methods},
2774
    {Py_tp_members, bufferedrandom_members},
2775
    {Py_tp_getset, bufferedrandom_getset},
2776
    {Py_tp_init, _io_BufferedRandom___init__},
2777
    {0, NULL},
2778
};
2779
2780
PyType_Spec _Py_bufferedrandom_spec = {
2781
    .name = "_io.BufferedRandom",
2782
    .basicsize = sizeof(buffered),
2783
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
2784
              Py_TPFLAGS_IMMUTABLETYPE),
2785
    .slots = bufferedrandom_slots,
2786
};