Coverage Report

Created: 2026-10-31 06:21

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
60.4k
#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
420k
    ( (PyThread_acquire_lock(self->lock, 0) ? \
331
420k
       1 : _enter_buffered_busy(self)) \
332
420k
     && (self->owner = PyThread_get_thread_ident(), 1) )
333
334
#define LEAVE_BUFFERED(self) \
335
420k
    do { \
336
420k
        self->owner = 0; \
337
420k
        PyThread_release_lock(self->lock); \
338
420k
    } while(0);
339
340
#define CHECK_INITIALIZED(self) \
341
8.64M
    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
6.77M
    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
7.12M
    (!self->buffer ? 1 : \
366
7.12M
    (self->fast_closed_checks \
367
7.12M
     ? _PyFileIO_closed(self->raw) \
368
7.12M
     : buffered_closed(self)))
369
370
#define CHECK_CLOSED(self, error_msg) \
371
6.93M
    do { \
372
6.93M
        int _closed = IS_CLOSED(self); \
373
6.93M
        if (_closed < 0) { \
374
0
            return NULL; \
375
0
        } \
376
6.93M
        if (_closed && \
377
6.93M
            (Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t) == 0)) \
378
6.93M
        { \
379
0
            PyErr_SetString(PyExc_ValueError, error_msg); \
380
0
            return NULL; \
381
0
        } \
382
6.93M
    } while (0);
383
384
#define VALID_READ_BUFFER(self) \
385
2.48M
    (self->readable && self->read_end != -1)
386
387
#define VALID_WRITE_BUFFER(self) \
388
979k
    (self->writable && self->write_end != -1)
389
390
#define ADJUST_POSITION(self, _new_pos) \
391
161k
    do { \
392
161k
        self->pos = _new_pos; \
393
161k
        if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
394
161k
            self->read_end = self->pos; \
395
161k
    } while(0)
396
397
#define READAHEAD(self) \
398
1.45M
    ((self->readable && VALID_READ_BUFFER(self)) \
399
1.45M
        ? (self->read_end - self->pos) : 0)
400
401
#define RAW_OFFSET(self) \
402
173k
    (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
403
173k
        && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
404
405
#define RAW_TELL(self) \
406
1.45M
    (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
407
408
#define MINUS_LAST_BLOCK(self, size) \
409
28.8k
    (self->buffer_mask ? \
410
28.8k
        (size & ~self->buffer_mask) : \
411
28.8k
        (self->buffer_size * (size / self->buffer_size)))
412
413
414
static int
415
buffered_clear(PyObject *op)
416
27.6k
{
417
27.6k
    buffered *self = buffered_CAST(op);
418
27.6k
    self->ok = 0;
419
27.6k
    Py_CLEAR(self->raw);
420
27.6k
    Py_CLEAR(self->dict);
421
27.6k
    return 0;
422
27.6k
}
423
424
static void
425
buffered_dealloc(PyObject *op)
426
27.6k
{
427
27.6k
    buffered *self = buffered_CAST(op);
428
27.6k
    PyTypeObject *tp = Py_TYPE(self);
429
27.6k
    self->finalizing = 1;
430
27.6k
    if (_PyIOBase_finalize(op) < 0)
431
0
        return;
432
27.6k
    _PyObject_GC_UNTRACK(self);
433
27.6k
    self->ok = 0;
434
27.6k
    FT_CLEAR_WEAKREFS(op, self->weakreflist);
435
27.6k
    if (self->buffer) {
436
0
        PyMem_Free(self->buffer);
437
0
        self->buffer = NULL;
438
0
    }
439
27.6k
    if (self->lock) {
440
27.6k
        PyThread_free_lock(self->lock);
441
27.6k
        self->lock = NULL;
442
27.6k
    }
443
27.6k
    (void)buffered_clear(op);
444
27.6k
    tp->tp_free(self);
445
27.6k
    Py_DECREF(tp);
446
27.6k
}
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
5.23k
{
467
5.23k
    buffered *self = buffered_CAST(op);
468
5.23k
    Py_VISIT(Py_TYPE(self));
469
5.23k
    Py_VISIT(self->raw);
470
5.23k
    Py_VISIT(self->dict);
471
5.23k
    return 0;
472
5.23k
}
473
474
/* Because this can call arbitrary code, it shouldn't be called when
475
   the refcount is 0 (that is, not directly from tp_dealloc unless
476
   the refcount has been temporarily re-incremented). */
477
/*[clinic input]
478
_io._Buffered._dealloc_warn
479
480
    source: object
481
    /
482
483
[clinic start generated code]*/
484
485
static PyObject *
486
_io__Buffered__dealloc_warn_impl(buffered *self, PyObject *source)
487
/*[clinic end generated code: output=d8db21c6dec0e614 input=8f845f2a4786391c]*/
488
5
{
489
5
    if (self->ok && self->raw) {
490
5
        PyObject *r;
491
5
        r = PyObject_CallMethodOneArg(self->raw, &_Py_ID(_dealloc_warn), source);
492
5
        if (r)
493
0
            Py_DECREF(r);
494
5
        else
495
5
            PyErr_Clear();
496
5
    }
497
5
    Py_RETURN_NONE;
498
5
}
499
500
/*
501
 * _BufferedIOMixin methods
502
 * This is not a class, just a collection of methods that will be reused
503
 * by BufferedReader and BufferedWriter
504
 */
505
506
/* Flush and close */
507
/*[clinic input]
508
@critical_section
509
_io._Buffered.flush as _io__Buffered_simple_flush
510
[clinic start generated code]*/
511
512
static PyObject *
513
_io__Buffered_simple_flush_impl(buffered *self)
514
/*[clinic end generated code: output=29ebb3820db1bdfd input=5248cb84a65f80bd]*/
515
1.46M
{
516
1.46M
    CHECK_INITIALIZED(self)
517
1.46M
    return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(flush));
518
1.46M
}
519
520
static int
521
buffered_closed(buffered *self)
522
6.77M
{
523
6.77M
    int closed;
524
6.77M
    PyObject *res;
525
6.77M
    CHECK_INITIALIZED_INT(self)
526
6.77M
    res = PyObject_GetAttr(self->raw, &_Py_ID(closed));
527
6.77M
    if (res == NULL)
528
0
        return -1;
529
6.77M
    closed = PyObject_IsTrue(res);
530
6.77M
    Py_DECREF(res);
531
6.77M
    return closed;
532
6.77M
}
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
53.1k
{
544
53.1k
    CHECK_INITIALIZED(self)
545
53.1k
    return PyObject_GetAttr(self->raw, &_Py_ID(closed));
546
53.1k
}
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
27.6k
{
557
27.6k
    PyObject *res = NULL;
558
27.6k
    int r;
559
560
27.6k
    CHECK_INITIALIZED(self)
561
27.6k
    if (!ENTER_BUFFERED(self)) {
562
0
        return NULL;
563
0
    }
564
    /* gh-138720: Use IS_CLOSED to match flush CHECK_CLOSED. */
565
27.6k
    r = IS_CLOSED(self);
566
27.6k
    if (r < 0)
567
0
        goto end;
568
27.6k
    if (r > 0) {
569
0
        res = Py_NewRef(Py_None);
570
0
        goto end;
571
0
    }
572
573
27.6k
    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
27.6k
    LEAVE_BUFFERED(self)
582
27.6k
    r = _PyFile_Flush((PyObject *)self);
583
27.6k
    if (!ENTER_BUFFERED(self)) {
584
0
        return NULL;
585
0
    }
586
27.6k
    PyObject *exc = NULL;
587
27.6k
    if (r < 0) {
588
0
        exc = PyErr_GetRaisedException();
589
0
    }
590
591
27.6k
    res = PyObject_CallMethodNoArgs(self->raw, &_Py_ID(close));
592
593
27.6k
    if (self->buffer) {
594
27.6k
        PyMem_Free(self->buffer);
595
27.6k
        self->buffer = NULL;
596
27.6k
    }
597
598
27.6k
    if (exc != NULL) {
599
0
        _PyErr_ChainExceptions1(exc);
600
0
        Py_CLEAR(res);
601
0
    }
602
603
27.6k
    self->read_end = 0;
604
27.6k
    self->pos = 0;
605
606
27.6k
end:
607
27.6k
    LEAVE_BUFFERED(self)
608
27.6k
    return res;
609
27.6k
}
610
611
/*[clinic input]
612
@critical_section
613
_io._Buffered.detach
614
[clinic start generated code]*/
615
616
static PyObject *
617
_io__Buffered_detach_impl(buffered *self)
618
/*[clinic end generated code: output=dd0fc057b8b779f7 input=d4ef1828a678be37]*/
619
0
{
620
0
    PyObject *raw;
621
0
    CHECK_INITIALIZED(self)
622
0
    if (_PyFile_Flush((PyObject *)self) < 0) {
623
0
        return NULL;
624
0
    }
625
0
    raw = self->raw;
626
0
    self->raw = NULL;
627
0
    self->detached = 1;
628
0
    self->ok = 0;
629
0
    return raw;
630
0
}
631
632
/* Inquiries */
633
634
/*[clinic input]
635
@critical_section
636
_io._Buffered.seekable
637
[clinic start generated code]*/
638
639
static PyObject *
640
_io__Buffered_seekable_impl(buffered *self)
641
/*[clinic end generated code: output=90172abb5ceb6e8f input=e3a4fc1d297b2fd3]*/
642
131
{
643
131
    CHECK_INITIALIZED(self)
644
131
    return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(seekable));
645
131
}
646
647
/*[clinic input]
648
@critical_section
649
_io._Buffered.readable
650
[clinic start generated code]*/
651
652
static PyObject *
653
_io__Buffered_readable_impl(buffered *self)
654
/*[clinic end generated code: output=92afa07661ecb698 input=abe54107d59bca9a]*/
655
55
{
656
55
    CHECK_INITIALIZED(self)
657
55
    return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(readable));
658
55
}
659
660
/*[clinic input]
661
@critical_section
662
_io._Buffered.writable
663
[clinic start generated code]*/
664
665
static PyObject *
666
_io__Buffered_writable_impl(buffered *self)
667
/*[clinic end generated code: output=4e3eee8d6f9d8552 input=45eb76bf6a10e6f7]*/
668
75
{
669
75
    CHECK_INITIALIZED(self)
670
75
    return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(writable));
671
75
}
672
673
674
/*[clinic input]
675
@critical_section
676
@getter
677
_io._Buffered.name
678
[clinic start generated code]*/
679
680
static PyObject *
681
_io__Buffered_name_get_impl(buffered *self)
682
/*[clinic end generated code: output=d2adf384051d3d10 input=6b84a0e6126f545e]*/
683
10
{
684
10
    CHECK_INITIALIZED(self)
685
10
    return PyObject_GetAttr(self->raw, &_Py_ID(name));
686
10
}
687
688
/*[clinic input]
689
@critical_section
690
@getter
691
_io._Buffered.mode
692
[clinic start generated code]*/
693
694
static PyObject *
695
_io__Buffered_mode_get_impl(buffered *self)
696
/*[clinic end generated code: output=0feb205748892fa4 input=0762d5e28542fd8c]*/
697
3
{
698
3
    CHECK_INITIALIZED(self)
699
3
    return PyObject_GetAttr(self->raw, &_Py_ID(mode));
700
3
}
701
702
/* Lower-level APIs */
703
704
/*[clinic input]
705
@critical_section
706
_io._Buffered.fileno
707
[clinic start generated code]*/
708
709
static PyObject *
710
_io__Buffered_fileno_impl(buffered *self)
711
/*[clinic end generated code: output=b717648d58a95ee3 input=1c4fead777bae20a]*/
712
0
{
713
0
    CHECK_INITIALIZED(self)
714
0
    return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(fileno));
715
0
}
716
717
/*[clinic input]
718
@critical_section
719
_io._Buffered.isatty
720
[clinic start generated code]*/
721
722
static PyObject *
723
_io__Buffered_isatty_impl(buffered *self)
724
/*[clinic end generated code: output=c20e55caae67baea input=e53d182d7e490e3a]*/
725
0
{
726
0
    CHECK_INITIALIZED(self)
727
0
    return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(isatty));
728
0
}
729
730
/* Forward decls */
731
static PyObject *
732
_bufferedwriter_flush_unlocked(buffered *);
733
static Py_ssize_t
734
_bufferedreader_fill_buffer(buffered *self);
735
static void
736
_bufferedreader_reset_buf(buffered *self);
737
static void
738
_bufferedwriter_reset_buf(buffered *self);
739
static PyObject *
740
_bufferedreader_peek_unlocked(buffered *self);
741
static PyObject *
742
_bufferedreader_read_all(buffered *self);
743
static PyObject *
744
_bufferedreader_read_fast(buffered *self, Py_ssize_t);
745
static PyObject *
746
_bufferedreader_read_generic(buffered *self, Py_ssize_t);
747
static Py_ssize_t
748
_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len);
749
750
/*
751
 * Helpers
752
 */
753
754
/* Sets the current error to BlockingIOError */
755
static void
756
_set_BlockingIOError(const char *msg, Py_ssize_t written)
757
0
{
758
0
    PyObject *err;
759
0
    PyErr_Clear();
760
0
    err = PyObject_CallFunction(PyExc_BlockingIOError, "isn",
761
0
                                errno, msg, written);
762
0
    if (err)
763
0
        PyErr_SetObject(PyExc_BlockingIOError, err);
764
0
    Py_XDECREF(err);
765
0
}
766
767
/* Returns the address of the `written` member if a BlockingIOError was
768
   raised, NULL otherwise. The error is always re-raised. */
769
static Py_ssize_t *
770
_buffered_check_blocking_error(void)
771
0
{
772
0
    PyObject *exc = PyErr_GetRaisedException();
773
0
    if (exc == NULL || !PyErr_GivenExceptionMatches(exc, PyExc_BlockingIOError)) {
774
0
        PyErr_SetRaisedException(exc);
775
0
        return NULL;
776
0
    }
777
0
    PyOSErrorObject *err = (PyOSErrorObject *)exc;
778
    /* TODO: sanity check (err->written >= 0) */
779
0
    PyErr_SetRaisedException(exc);
780
0
    return &err->written;
781
0
}
782
783
static Py_off_t
784
_buffered_raw_tell(buffered *self)
785
32.0k
{
786
32.0k
    Py_off_t n;
787
32.0k
    PyObject *res;
788
32.0k
    res = PyObject_CallMethodNoArgs(self->raw, &_Py_ID(tell));
789
32.0k
    if (res == NULL)
790
5
        return -1;
791
32.0k
    n = PyNumber_AsOff_t(res, PyExc_ValueError);
792
32.0k
    Py_DECREF(res);
793
32.0k
    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
32.0k
    self->abs_pos = n;
801
32.0k
    return n;
802
32.0k
}
803
804
static Py_off_t
805
_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
806
7.13k
{
807
7.13k
    PyObject *res, *posobj, *whenceobj;
808
7.13k
    Py_off_t n;
809
810
7.13k
    posobj = PyLong_FromOff_t(target);
811
7.13k
    if (posobj == NULL)
812
0
        return -1;
813
7.13k
    whenceobj = PyLong_FromLong(whence);
814
7.13k
    if (whenceobj == NULL) {
815
0
        Py_DECREF(posobj);
816
0
        return -1;
817
0
    }
818
7.13k
    res = PyObject_CallMethodObjArgs(self->raw, &_Py_ID(seek),
819
7.13k
                                     posobj, whenceobj, NULL);
820
7.13k
    Py_DECREF(posobj);
821
7.13k
    Py_DECREF(whenceobj);
822
7.13k
    if (res == NULL)
823
5
        return -1;
824
7.12k
    n = PyNumber_AsOff_t(res, PyExc_ValueError);
825
7.12k
    Py_DECREF(res);
826
7.12k
    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
7.12k
    self->abs_pos = n;
834
7.12k
    return n;
835
7.12k
}
836
837
static int
838
_buffered_init(buffered *self)
839
27.7k
{
840
27.7k
    Py_ssize_t n;
841
27.7k
    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
27.7k
    if (self->buffer)
847
0
        PyMem_Free(self->buffer);
848
27.7k
    self->buffer = PyMem_Malloc(self->buffer_size);
849
27.7k
    if (self->buffer == NULL) {
850
0
        PyErr_NoMemory();
851
0
        return -1;
852
0
    }
853
27.7k
    if (self->lock)
854
0
        PyThread_free_lock(self->lock);
855
27.7k
    self->lock = PyThread_allocate_lock();
856
27.7k
    if (self->lock == NULL) {
857
0
        PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
858
0
        return -1;
859
0
    }
860
27.7k
    self->owner = 0;
861
    /* Find out whether buffer_size is a power of 2 */
862
    /* XXX is this optimization useful? */
863
498k
    for (n = self->buffer_size - 1; n & 1; n >>= 1)
864
471k
        ;
865
27.7k
    if (n == 0)
866
27.7k
        self->buffer_mask = self->buffer_size - 1;
867
0
    else
868
0
        self->buffer_mask = 0;
869
27.7k
    if (_buffered_raw_tell(self) == -1)
870
5
        PyErr_Clear();
871
27.7k
    return 0;
872
27.7k
}
873
874
/* Return 1 if an OSError with errno == EINTR is set (and then
875
   clears the error indicator), 0 otherwise.
876
   Should only be called when PyErr_Occurred() is true.
877
*/
878
int
879
_PyIO_trap_eintr(void)
880
4.31k
{
881
4.31k
    if (!PyErr_ExceptionMatches(PyExc_OSError)) {
882
2.34k
        return 0;
883
2.34k
    }
884
1.96k
    PyObject *exc = PyErr_GetRaisedException();
885
1.96k
    PyOSErrorObject *env_err = (PyOSErrorObject *)exc;
886
1.96k
    assert(env_err != NULL);
887
1.96k
    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
1.96k
    PyErr_SetRaisedException(exc);
900
1.96k
    return 0;
901
1.96k
}
902
903
/*
904
 * Shared methods and wrappers
905
 */
906
907
static PyObject *
908
buffered_flush_and_rewind_unlocked(buffered *self)
909
161k
{
910
161k
    PyObject *res;
911
912
161k
    res = _bufferedwriter_flush_unlocked(self);
913
161k
    if (res == NULL)
914
0
        return NULL;
915
161k
    Py_DECREF(res);
916
917
161k
    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
161k
    Py_RETURN_NONE;
927
161k
}
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
161k
{
938
161k
    PyObject *res;
939
940
161k
    CHECK_INITIALIZED(self)
941
161k
    CHECK_CLOSED(self, "flush of closed file")
942
943
161k
    if (!ENTER_BUFFERED(self))
944
0
        return NULL;
945
161k
    res = buffered_flush_and_rewind_unlocked(self);
946
161k
    LEAVE_BUFFERED(self)
947
948
161k
    return res;
949
161k
}
950
951
/*[clinic input]
952
@critical_section
953
_io._Buffered.peek
954
    size: Py_ssize_t = 0
955
    /
956
957
[clinic start generated code]*/
958
959
static PyObject *
960
_io__Buffered_peek_impl(buffered *self, Py_ssize_t size)
961
/*[clinic end generated code: output=ba7a097ca230102b input=56733376f926d982]*/
962
0
{
963
0
    PyObject *res = NULL;
964
965
0
    CHECK_INITIALIZED(self)
966
0
    CHECK_CLOSED(self, "peek of closed file")
967
968
0
    if (!ENTER_BUFFERED(self))
969
0
        return NULL;
970
971
0
    if (self->writable) {
972
0
        res = buffered_flush_and_rewind_unlocked(self);
973
0
        if (res == NULL)
974
0
            goto end;
975
0
        Py_CLEAR(res);
976
0
    }
977
0
    res = _bufferedreader_peek_unlocked(self);
978
979
0
end:
980
0
    LEAVE_BUFFERED(self)
981
0
    return res;
982
0
}
983
984
/*[clinic input]
985
@critical_section
986
_io._Buffered.read
987
    size as n: Py_ssize_t(accept={int, NoneType}) = -1
988
    /
989
[clinic start generated code]*/
990
991
static PyObject *
992
_io__Buffered_read_impl(buffered *self, Py_ssize_t n)
993
/*[clinic end generated code: output=f41c78bb15b9bbe9 input=bdb4b0425b295472]*/
994
5.32M
{
995
5.32M
    PyObject *res;
996
997
5.32M
    CHECK_INITIALIZED(self)
998
5.32M
    if (n < -1) {
999
0
        PyErr_SetString(PyExc_ValueError,
1000
0
                        "read length must be non-negative or -1");
1001
0
        return NULL;
1002
0
    }
1003
1004
5.32M
    CHECK_CLOSED(self, "read of closed file")
1005
1006
5.32M
    if (n == -1) {
1007
        /* The number of bytes is unspecified, read until the end of stream */
1008
5.53k
        if (!ENTER_BUFFERED(self))
1009
0
            return NULL;
1010
5.53k
        res = _bufferedreader_read_all(self);
1011
5.53k
    }
1012
5.31M
    else {
1013
5.31M
        res = _bufferedreader_read_fast(self, n);
1014
5.31M
        if (res != Py_None)
1015
5.28M
            return res;
1016
28.8k
        Py_DECREF(res);
1017
28.8k
        if (!ENTER_BUFFERED(self))
1018
0
            return NULL;
1019
28.8k
        res = _bufferedreader_read_generic(self, n);
1020
28.8k
    }
1021
1022
34.4k
    LEAVE_BUFFERED(self)
1023
34.4k
    return res;
1024
5.32M
}
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
130
{
1037
130
    CHECK_INITIALIZED(self)
1038
130
    if (n < 0) {
1039
0
        n = self->buffer_size;
1040
0
    }
1041
1042
130
    CHECK_CLOSED(self, "read of closed file")
1043
1044
130
    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
130
    Py_ssize_t have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1052
130
    if (have > 0) {
1053
120
        n = Py_MIN(have, n);
1054
120
        PyObject *res = _bufferedreader_read_fast(self, n);
1055
120
        assert(res != Py_None);
1056
120
        return res;
1057
120
    }
1058
1059
10
    if (!ENTER_BUFFERED(self)) {
1060
0
        return NULL;
1061
0
    }
1062
1063
    /* Flush the write buffer if necessary */
1064
10
    if (self->writable) {
1065
0
        PyObject *res = buffered_flush_and_rewind_unlocked(self);
1066
0
        if (res == NULL) {
1067
0
            LEAVE_BUFFERED(self)
1068
0
            return NULL;
1069
0
        }
1070
0
        Py_DECREF(res);
1071
0
    }
1072
10
    _bufferedreader_reset_buf(self);
1073
1074
10
    PyBytesWriter *writer = PyBytesWriter_Create(n);
1075
10
    if (writer == NULL) {
1076
0
        LEAVE_BUFFERED(self)
1077
0
        return NULL;
1078
0
    }
1079
1080
10
    Py_ssize_t r = _bufferedreader_raw_read(self,
1081
10
                                            PyBytesWriter_GetData(writer), n);
1082
10
    LEAVE_BUFFERED(self)
1083
10
    if (r == -1) {
1084
0
        PyBytesWriter_Discard(writer);
1085
0
        return NULL;
1086
0
    }
1087
10
    if (r == -2) {
1088
0
        r = 0;
1089
0
    }
1090
1091
10
    return PyBytesWriter_FinishWithSize(writer, r);
1092
10
}
1093
1094
static PyObject *
1095
_buffered_readinto_generic(buffered *self, Py_buffer *buffer, char readinto1)
1096
0
{
1097
0
    Py_ssize_t n, written = 0, remaining;
1098
0
    PyObject *res = NULL;
1099
1100
0
    CHECK_INITIALIZED(self)
1101
0
    CHECK_CLOSED(self, "readinto of closed file")
1102
1103
0
    n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1104
0
    if (n > 0) {
1105
0
        if (n >= buffer->len) {
1106
0
            memcpy(buffer->buf, self->buffer + self->pos, buffer->len);
1107
0
            self->pos += buffer->len;
1108
0
            return PyLong_FromSsize_t(buffer->len);
1109
0
        }
1110
0
        memcpy(buffer->buf, self->buffer + self->pos, n);
1111
0
        self->pos += n;
1112
0
        written = n;
1113
0
    }
1114
1115
0
    if (!ENTER_BUFFERED(self))
1116
0
        return NULL;
1117
1118
0
    if (self->writable) {
1119
0
        res = buffered_flush_and_rewind_unlocked(self);
1120
0
        if (res == NULL)
1121
0
            goto end;
1122
0
        Py_CLEAR(res);
1123
0
    }
1124
1125
0
    _bufferedreader_reset_buf(self);
1126
0
    self->pos = 0;
1127
1128
0
    for (remaining = buffer->len - written;
1129
0
         remaining > 0;
1130
0
         written += n, remaining -= n) {
1131
        /* If remaining bytes is larger than internal buffer size, copy
1132
         * directly into caller's buffer. */
1133
0
        if (remaining > self->buffer_size) {
1134
0
            n = _bufferedreader_raw_read(self, (char *) buffer->buf + written,
1135
0
                                         remaining);
1136
0
        }
1137
1138
        /* In readinto1 mode, we do not want to fill the internal
1139
           buffer if we already have some data to return */
1140
0
        else if (!(readinto1 && written)) {
1141
0
            n = _bufferedreader_fill_buffer(self);
1142
0
            if (n > 0) {
1143
0
                if (n > remaining)
1144
0
                    n = remaining;
1145
0
                memcpy((char *) buffer->buf + written,
1146
0
                       self->buffer + self->pos, n);
1147
0
                self->pos += n;
1148
0
                continue; /* short circuit */
1149
0
            }
1150
0
        }
1151
0
        else
1152
0
            n = 0;
1153
1154
0
        if (n == 0 || (n == -2 && written > 0))
1155
0
            break;
1156
0
        if (n < 0) {
1157
0
            if (n == -2) {
1158
0
                res = Py_NewRef(Py_None);
1159
0
            }
1160
0
            goto end;
1161
0
        }
1162
1163
        /* At most one read in readinto1 mode */
1164
0
        if (readinto1) {
1165
0
            written += n;
1166
0
            break;
1167
0
        }
1168
0
    }
1169
0
    res = PyLong_FromSsize_t(written);
1170
1171
0
end:
1172
0
    LEAVE_BUFFERED(self);
1173
0
    return res;
1174
0
}
1175
1176
/*[clinic input]
1177
@critical_section
1178
_io._Buffered.readinto
1179
    buffer: Py_buffer(accept={rwbuffer})
1180
    /
1181
[clinic start generated code]*/
1182
1183
static PyObject *
1184
_io__Buffered_readinto_impl(buffered *self, Py_buffer *buffer)
1185
/*[clinic end generated code: output=bcb376580b1d8170 input=777c33e7adaa2bcd]*/
1186
0
{
1187
0
    return _buffered_readinto_generic(self, buffer, 0);
1188
0
}
1189
1190
/*[clinic input]
1191
@critical_section
1192
_io._Buffered.readinto1
1193
    buffer: Py_buffer(accept={rwbuffer})
1194
    /
1195
[clinic start generated code]*/
1196
1197
static PyObject *
1198
_io__Buffered_readinto1_impl(buffered *self, Py_buffer *buffer)
1199
/*[clinic end generated code: output=6e5c6ac5868205d6 input=ef03cc5fc92a6895]*/
1200
0
{
1201
0
    return _buffered_readinto_generic(self, buffer, 1);
1202
0
}
1203
1204
1205
static PyObject *
1206
_buffered_readline(buffered *self, Py_ssize_t limit)
1207
18
{
1208
18
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
1209
1210
18
    CHECK_CLOSED(self, "readline of closed file")
1211
1212
    /* First, try to find a line in the buffer. This can run unlocked because
1213
       the calls to the C API are simple enough that they can't trigger
1214
       any thread switch. */
1215
18
    Py_ssize_t n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1216
18
    if (limit >= 0 && n > limit) {
1217
0
        n = limit;
1218
0
    }
1219
18
    const char *start = self->buffer + self->pos;
1220
18
    const char *s = memchr(start, '\n', n);
1221
18
    if (s != NULL) {
1222
8
        n = s - start + 1;
1223
8
        PyObject *res = PyBytes_FromStringAndSize(start, n);
1224
8
        if (res == NULL) {
1225
0
            return NULL;
1226
0
        }
1227
8
        self->pos += n;
1228
8
        return res;
1229
8
    }
1230
1231
10
    if (n == limit) {
1232
0
        PyObject *res = PyBytes_FromStringAndSize(start, n);
1233
0
        if (res == NULL) {
1234
0
            return NULL;
1235
0
        }
1236
0
        self->pos += n;
1237
0
        return res;
1238
0
    }
1239
1240
10
    PyBytesWriter *writer = NULL;
1241
10
    int locked = 0;
1242
10
    if (!ENTER_BUFFERED(self)) {
1243
0
        goto error;
1244
0
    }
1245
10
    locked = 1;
1246
1247
    /* Now we try to get some more from the raw stream */
1248
10
    writer = PyBytesWriter_Create(0);
1249
10
    if (writer == NULL) {
1250
0
        goto error;
1251
0
    }
1252
1253
10
    if (n > 0) {
1254
0
        if (PyBytesWriter_WriteBytes(writer, start, n) < 0) {
1255
0
            goto error;
1256
0
        }
1257
0
        self->pos += n;
1258
0
        if (limit >= 0) {
1259
0
            limit -= n;
1260
0
        }
1261
0
    }
1262
10
    if (self->writable) {
1263
0
        PyObject *res = buffered_flush_and_rewind_unlocked(self);
1264
0
        if (res == NULL) {
1265
0
            goto error;
1266
0
        }
1267
0
        Py_DECREF(res);
1268
0
    }
1269
1270
10
    for (;;) {
1271
10
        _bufferedreader_reset_buf(self);
1272
10
        n = _bufferedreader_fill_buffer(self);
1273
10
        if (n == -1) {
1274
0
            goto error;
1275
0
        }
1276
10
        if (n <= 0) {
1277
0
            break;
1278
0
        }
1279
10
        if (limit >= 0 && n > limit) {
1280
0
            n = limit;
1281
0
        }
1282
10
        start = self->buffer;
1283
10
        const char *newline = memchr(start, '\n', n);
1284
10
        if (newline != NULL) {
1285
10
            n = newline - start + 1;
1286
10
            if (PyBytesWriter_WriteBytes(writer, start, n) < 0) {
1287
0
                goto error;
1288
0
            }
1289
10
            self->pos = n;
1290
10
            goto found;
1291
10
        }
1292
1293
0
        if (PyBytesWriter_WriteBytes(writer, start, n) < 0) {
1294
0
            goto error;
1295
0
        }
1296
0
        if (n == limit) {
1297
0
            self->pos = n;
1298
0
            break;
1299
0
        }
1300
0
        if (limit >= 0) {
1301
0
            limit -= n;
1302
0
        }
1303
0
    }
1304
1305
10
found:
1306
10
    LEAVE_BUFFERED(self)
1307
10
    return PyBytesWriter_Finish(writer);
1308
1309
0
error:
1310
0
    PyBytesWriter_Discard(writer);
1311
0
    if (locked) {
1312
0
        LEAVE_BUFFERED(self)
1313
0
    }
1314
0
    return NULL;
1315
10
}
1316
1317
/*[clinic input]
1318
@critical_section
1319
_io._Buffered.readline
1320
    size: Py_ssize_t(accept={int, NoneType}) = -1
1321
    /
1322
[clinic start generated code]*/
1323
1324
static PyObject *
1325
_io__Buffered_readline_impl(buffered *self, Py_ssize_t size)
1326
/*[clinic end generated code: output=24dd2aa6e33be83c input=e81ca5abd4280776]*/
1327
18
{
1328
18
    CHECK_INITIALIZED(self)
1329
18
    return _buffered_readline(self, size);
1330
18
}
1331
1332
1333
/*[clinic input]
1334
@critical_section
1335
_io._Buffered.tell
1336
[clinic start generated code]*/
1337
1338
static PyObject *
1339
_io__Buffered_tell_impl(buffered *self)
1340
/*[clinic end generated code: output=386972ae84716c1e input=ab12e67d8abcb42f]*/
1341
4.33k
{
1342
4.33k
    Py_off_t pos;
1343
1344
4.33k
    CHECK_INITIALIZED(self)
1345
4.33k
    pos = _buffered_raw_tell(self);
1346
4.33k
    if (pos == -1)
1347
0
        return NULL;
1348
4.33k
    pos -= RAW_OFFSET(self);
1349
1350
    // GH-95782
1351
4.33k
    if (pos < 0)
1352
0
        pos = 0;
1353
1354
4.33k
    return PyLong_FromOff_t(pos);
1355
4.33k
}
1356
1357
/*[clinic input]
1358
@critical_section
1359
_io._Buffered.seek
1360
    target as targetobj: object
1361
    whence: int = 0
1362
    /
1363
[clinic start generated code]*/
1364
1365
static PyObject *
1366
_io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence)
1367
/*[clinic end generated code: output=7ae0e8dc46efdefb input=b5a12be70e0ad07b]*/
1368
1.45M
{
1369
1.45M
    Py_off_t target, n;
1370
1.45M
    PyObject *res = NULL;
1371
1372
1.45M
    CHECK_INITIALIZED(self)
1373
1374
    /* Do some error checking instead of trusting OS 'seek()'
1375
    ** error detection, just in case.
1376
    */
1377
1.45M
    if ((whence < 0 || whence >2)
1378
0
#ifdef SEEK_HOLE
1379
0
        && (whence != SEEK_HOLE)
1380
0
#endif
1381
0
#ifdef SEEK_DATA
1382
0
        && (whence != SEEK_DATA)
1383
1.45M
#endif
1384
1.45M
        ) {
1385
0
        PyErr_Format(PyExc_ValueError,
1386
0
                     "whence value %d unsupported", whence);
1387
0
        return NULL;
1388
0
    }
1389
1390
1.45M
    CHECK_CLOSED(self, "seek of closed file")
1391
1392
1.45M
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
1393
1.45M
    if (_PyIOBase_check_seekable(state, self->raw, Py_True) == NULL) {
1394
0
        return NULL;
1395
0
    }
1396
1397
1.45M
    target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1398
1.45M
    if (target == -1 && PyErr_Occurred())
1399
0
        return NULL;
1400
1401
    /* SEEK_SET and SEEK_CUR are special because we could seek inside the
1402
       buffer. Other whence values must be managed without this optimization.
1403
       Some Operating Systems can provide additional values, like
1404
       SEEK_HOLE/SEEK_DATA. */
1405
1.45M
    if (((whence == 0) || (whence == 1)) && self->readable) {
1406
1.45M
        Py_off_t current, avail;
1407
        /* Check if seeking leaves us inside the current buffer,
1408
           so as to return quickly if possible. Also, we needn't take the
1409
           lock in this fast path.
1410
           Don't know how to do that when whence == 2, though. */
1411
        /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1412
           state at this point. */
1413
1.45M
        current = RAW_TELL(self);
1414
1.45M
        avail = READAHEAD(self);
1415
1.45M
        if (avail > 0) {
1416
1.44M
            Py_off_t offset;
1417
1.44M
            if (whence == 0)
1418
16
                offset = target - (current - RAW_OFFSET(self));
1419
1.44M
            else
1420
1.44M
                offset = target;
1421
1.44M
            if (offset >= -self->pos && offset <= avail) {
1422
1.44M
                self->pos += offset;
1423
1424
                // GH-95782
1425
1.44M
                if (current - avail + offset < 0)
1426
0
                    return PyLong_FromOff_t(0);
1427
1428
1.44M
                return PyLong_FromOff_t(current - avail + offset);
1429
1.44M
            }
1430
1.44M
        }
1431
1.45M
    }
1432
1433
7.13k
    if (!ENTER_BUFFERED(self))
1434
0
        return NULL;
1435
1436
    /* Fallback: invoke raw seek() method and clear buffer */
1437
7.13k
    if (self->writable) {
1438
0
        res = _bufferedwriter_flush_unlocked(self);
1439
0
        if (res == NULL)
1440
0
            goto end;
1441
0
        Py_CLEAR(res);
1442
0
    }
1443
1444
    /* TODO: align on block boundary and read buffer if needed? */
1445
7.13k
    if (whence == 1)
1446
7.12k
        target -= RAW_OFFSET(self);
1447
7.13k
    n = _buffered_raw_seek(self, target, whence);
1448
7.13k
    if (n == -1)
1449
5
        goto end;
1450
7.12k
    self->raw_pos = -1;
1451
7.12k
    res = PyLong_FromOff_t(n);
1452
7.12k
    if (res != NULL && self->readable)
1453
7.12k
        _bufferedreader_reset_buf(self);
1454
1455
7.13k
end:
1456
7.13k
    LEAVE_BUFFERED(self)
1457
7.13k
    return res;
1458
7.12k
}
1459
1460
/*[clinic input]
1461
@critical_section
1462
_io._Buffered.truncate
1463
    cls: defining_class
1464
    pos: object = None
1465
    /
1466
[clinic start generated code]*/
1467
1468
static PyObject *
1469
_io__Buffered_truncate_impl(buffered *self, PyTypeObject *cls, PyObject *pos)
1470
/*[clinic end generated code: output=fe3882fbffe79f1a input=e3cbf794575bd794]*/
1471
0
{
1472
0
    PyObject *res = NULL;
1473
1474
0
    CHECK_INITIALIZED(self)
1475
0
    CHECK_CLOSED(self, "truncate of closed file")
1476
0
    if (!self->writable) {
1477
0
        _PyIO_State *state = get_io_state_by_cls(cls);
1478
0
        return bufferediobase_unsupported(state, "truncate");
1479
0
    }
1480
0
    if (!ENTER_BUFFERED(self))
1481
0
        return NULL;
1482
1483
0
    res = buffered_flush_and_rewind_unlocked(self);
1484
0
    if (res == NULL) {
1485
0
        goto end;
1486
0
    }
1487
0
    Py_CLEAR(res);
1488
1489
0
    res = PyObject_CallMethodOneArg(self->raw, &_Py_ID(truncate), pos);
1490
0
    if (res == NULL)
1491
0
        goto end;
1492
    /* Reset cached position */
1493
0
    if (_buffered_raw_tell(self) == -1)
1494
0
        PyErr_Clear();
1495
1496
0
end:
1497
0
    LEAVE_BUFFERED(self)
1498
0
    return res;
1499
0
}
1500
1501
static PyObject *
1502
buffered_iternext(PyObject *op)
1503
0
{
1504
0
    buffered *self = buffered_CAST(op);
1505
0
    PyObject *line;
1506
0
    PyTypeObject *tp;
1507
1508
0
    CHECK_INITIALIZED(self);
1509
1510
0
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
1511
0
    tp = Py_TYPE(self);
1512
0
    if (tp == state->PyBufferedReader_Type ||
1513
0
        tp == state->PyBufferedRandom_Type)
1514
0
    {
1515
        /* Skip method call overhead for speed */
1516
0
        Py_BEGIN_CRITICAL_SECTION(self);
1517
0
        line = _buffered_readline(self, -1);
1518
0
        Py_END_CRITICAL_SECTION();
1519
0
    }
1520
0
    else {
1521
0
        line = PyObject_CallMethodNoArgs((PyObject *)self,
1522
0
                                             &_Py_ID(readline));
1523
0
        if (line && !PyBytes_Check(line)) {
1524
0
            PyErr_Format(PyExc_OSError,
1525
0
                         "readline() should have returned a bytes object, "
1526
0
                         "not '%.200s'", Py_TYPE(line)->tp_name);
1527
0
            Py_DECREF(line);
1528
0
            return NULL;
1529
0
        }
1530
0
    }
1531
1532
0
    if (line == NULL)
1533
0
        return NULL;
1534
1535
0
    if (PyBytes_GET_SIZE(line) == 0) {
1536
        /* Reached EOF or would have blocked */
1537
0
        Py_DECREF(line);
1538
0
        return NULL;
1539
0
    }
1540
1541
0
    return line;
1542
0
}
1543
1544
static PyObject *
1545
buffered_repr(PyObject *op)
1546
0
{
1547
0
    buffered *self = buffered_CAST(op);
1548
0
    PyObject *nameobj, *res;
1549
1550
0
    if (PyObject_GetOptionalAttr((PyObject *) self, &_Py_ID(name), &nameobj) < 0) {
1551
0
        if (!PyErr_ExceptionMatches(PyExc_ValueError)) {
1552
0
            return NULL;
1553
0
        }
1554
        /* Ignore ValueError raised if the underlying stream was detached */
1555
0
        PyErr_Clear();
1556
0
    }
1557
0
    if (nameobj == NULL) {
1558
0
        res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1559
0
    }
1560
0
    else {
1561
0
        int status = Py_ReprEnter((PyObject *)self);
1562
0
        res = NULL;
1563
0
        if (status == 0) {
1564
0
            res = PyUnicode_FromFormat("<%s name=%R>",
1565
0
                                       Py_TYPE(self)->tp_name, nameobj);
1566
0
            Py_ReprLeave((PyObject *)self);
1567
0
        }
1568
0
        else if (status > 0) {
1569
0
            PyErr_Format(PyExc_RuntimeError,
1570
0
                         "reentrant call inside %s.__repr__",
1571
0
                         Py_TYPE(self)->tp_name);
1572
0
        }
1573
0
        Py_DECREF(nameobj);
1574
0
    }
1575
0
    return res;
1576
0
}
1577
1578
/*
1579
 * class BufferedReader
1580
 */
1581
1582
static void _bufferedreader_reset_buf(buffered *self)
1583
51.8k
{
1584
51.8k
    self->read_end = -1;
1585
51.8k
}
1586
1587
/*[clinic input]
1588
_io.BufferedReader.__init__
1589
    raw: object
1590
    buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
1591
1592
Create a new buffered reader using the given readable raw IO object.
1593
[clinic start generated code]*/
1594
1595
static int
1596
_io_BufferedReader___init___impl(buffered *self, PyObject *raw,
1597
                                 Py_ssize_t buffer_size)
1598
/*[clinic end generated code: output=cddcfefa0ed294c4 input=fb887e06f11b4e48]*/
1599
10.2k
{
1600
10.2k
    self->ok = 0;
1601
10.2k
    self->detached = 0;
1602
1603
10.2k
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
1604
10.2k
    if (_PyIOBase_check_readable(state, raw, Py_True) == NULL) {
1605
0
        return -1;
1606
0
    }
1607
1608
10.2k
    Py_XSETREF(self->raw, Py_NewRef(raw));
1609
10.2k
    self->buffer_size = buffer_size;
1610
10.2k
    self->readable = 1;
1611
10.2k
    self->writable = 0;
1612
1613
10.2k
    if (_buffered_init(self) < 0)
1614
0
        return -1;
1615
10.2k
    _bufferedreader_reset_buf(self);
1616
1617
10.2k
    self->fast_closed_checks = (
1618
10.2k
        Py_IS_TYPE(self, state->PyBufferedReader_Type) &&
1619
10.2k
        Py_IS_TYPE(raw, state->PyFileIO_Type)
1620
10.2k
    );
1621
1622
10.2k
    self->ok = 1;
1623
10.2k
    return 0;
1624
10.2k
}
1625
1626
static Py_ssize_t
1627
_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
1628
35.1k
{
1629
35.1k
    Py_buffer buf;
1630
35.1k
    PyObject *memobj, *res;
1631
35.1k
    Py_ssize_t n;
1632
    /* NOTE: the buffer needn't be released as its object is NULL. */
1633
35.1k
    if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1634
0
        return -1;
1635
35.1k
    memobj = PyMemoryView_FromBuffer(&buf);
1636
35.1k
    if (memobj == NULL)
1637
0
        return -1;
1638
    /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1639
       occurs so we needn't do it ourselves.
1640
       We then retry reading, ignoring the signal if no handler has
1641
       raised (see issue #10956).
1642
    */
1643
35.1k
    do {
1644
35.1k
        res = PyObject_CallMethodOneArg(self->raw, &_Py_ID(readinto), memobj);
1645
35.1k
    } while (res == NULL && _PyIO_trap_eintr());
1646
35.1k
    Py_DECREF(memobj);
1647
35.1k
    if (res == NULL)
1648
4.31k
        return -1;
1649
30.8k
    if (res == Py_None) {
1650
        /* Non-blocking stream would have blocked. Special return code! */
1651
0
        Py_DECREF(res);
1652
0
        return -2;
1653
0
    }
1654
30.8k
    n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1655
30.8k
    Py_DECREF(res);
1656
1657
30.8k
    if (n == -1 && PyErr_Occurred()) {
1658
0
        _PyErr_FormatFromCause(
1659
0
            PyExc_OSError,
1660
0
            "raw readinto() failed"
1661
0
        );
1662
0
        return -1;
1663
0
    }
1664
1665
30.8k
    if (n < 0 || n > len) {
1666
0
        PyErr_Format(PyExc_OSError,
1667
0
                     "raw readinto() returned invalid length %zd "
1668
0
                     "(should have been between 0 and %zd)", n, len);
1669
0
        return -1;
1670
0
    }
1671
30.8k
    if (n > 0 && self->abs_pos != -1)
1672
30.5k
        self->abs_pos += n;
1673
30.8k
    return n;
1674
30.8k
}
1675
1676
static Py_ssize_t
1677
_bufferedreader_fill_buffer(buffered *self)
1678
35.1k
{
1679
35.1k
    Py_ssize_t start, len, n;
1680
35.1k
    if (VALID_READ_BUFFER(self))
1681
35.1k
        start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1682
10
    else
1683
10
        start = 0;
1684
35.1k
    len = self->buffer_size - start;
1685
35.1k
    n = _bufferedreader_raw_read(self, self->buffer + start, len);
1686
35.1k
    if (n <= 0)
1687
4.65k
        return n;
1688
30.5k
    self->read_end = start + n;
1689
30.5k
    self->raw_pos = start + n;
1690
30.5k
    return n;
1691
35.1k
}
1692
1693
static PyObject *
1694
_bufferedreader_read_all(buffered *self)
1695
5.53k
{
1696
5.53k
    Py_ssize_t current_size;
1697
5.53k
    PyObject *res = NULL, *data = NULL, *tmp = NULL, *chunks = NULL, *readall;
1698
1699
    /* First copy what we have in the current buffer. */
1700
5.53k
    current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1701
5.53k
    if (current_size) {
1702
0
        data = PyBytes_FromStringAndSize(
1703
0
            self->buffer + self->pos, current_size);
1704
0
        if (data == NULL)
1705
0
            return NULL;
1706
0
        self->pos += current_size;
1707
0
    }
1708
    /* We're going past the buffer's bounds, flush it */
1709
5.53k
    if (self->writable) {
1710
0
        tmp = buffered_flush_and_rewind_unlocked(self);
1711
0
        if (tmp == NULL)
1712
0
            goto cleanup;
1713
0
        Py_CLEAR(tmp);
1714
0
    }
1715
5.53k
    _bufferedreader_reset_buf(self);
1716
1717
5.53k
    if (PyObject_GetOptionalAttr(self->raw, &_Py_ID(readall), &readall) < 0) {
1718
0
        goto cleanup;
1719
0
    }
1720
5.53k
    if (readall) {
1721
5.53k
        tmp = _PyObject_CallNoArgs(readall);
1722
5.53k
        Py_DECREF(readall);
1723
5.53k
        if (tmp == NULL)
1724
0
            goto cleanup;
1725
5.53k
        if (tmp != Py_None && !PyBytes_Check(tmp)) {
1726
0
            PyErr_SetString(PyExc_TypeError, "readall() should return bytes");
1727
0
            goto cleanup;
1728
0
        }
1729
5.53k
        if (current_size == 0) {
1730
5.53k
            res = tmp;
1731
5.53k
        } else {
1732
0
            if (tmp != Py_None) {
1733
0
                PyBytes_Concat(&data, tmp);
1734
0
            }
1735
0
            res = data;
1736
0
        }
1737
5.53k
        goto cleanup;
1738
5.53k
    }
1739
1740
0
    chunks = PyList_New(0);
1741
0
    if (chunks == NULL)
1742
0
        goto cleanup;
1743
1744
0
    while (1) {
1745
0
        if (data) {
1746
0
            if (PyList_Append(chunks, data) < 0)
1747
0
                goto cleanup;
1748
0
            Py_CLEAR(data);
1749
0
        }
1750
1751
        /* Read until EOF or until read() would block. */
1752
0
        data = PyObject_CallMethodNoArgs(self->raw, &_Py_ID(read));
1753
0
        if (data == NULL)
1754
0
            goto cleanup;
1755
0
        if (data != Py_None && !PyBytes_Check(data)) {
1756
0
            PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1757
0
            goto cleanup;
1758
0
        }
1759
0
        if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1760
0
            if (current_size == 0) {
1761
0
                res = data;
1762
0
                goto cleanup;
1763
0
            }
1764
0
            else {
1765
0
                tmp = PyBytes_Join((PyObject *)&_Py_SINGLETON(bytes_empty), chunks);
1766
0
                res = tmp;
1767
0
                goto cleanup;
1768
0
            }
1769
0
        }
1770
0
        current_size += PyBytes_GET_SIZE(data);
1771
0
        if (self->abs_pos != -1)
1772
0
            self->abs_pos += PyBytes_GET_SIZE(data);
1773
0
    }
1774
5.53k
cleanup:
1775
    /* res is either NULL or a borrowed ref */
1776
5.53k
    Py_XINCREF(res);
1777
5.53k
    Py_XDECREF(data);
1778
5.53k
    Py_XDECREF(tmp);
1779
5.53k
    Py_XDECREF(chunks);
1780
5.53k
    return res;
1781
0
}
1782
1783
/* Read n bytes from the buffer if it can, otherwise return None.
1784
   This function is simple enough that it can run unlocked. */
1785
static PyObject *
1786
_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
1787
5.31M
{
1788
5.31M
    Py_ssize_t current_size;
1789
1790
5.31M
    current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1791
5.31M
    if (n <= current_size) {
1792
        /* Fast path: the data to read is fully buffered. */
1793
5.28M
        PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1794
5.28M
        if (res != NULL)
1795
5.28M
            self->pos += n;
1796
5.28M
        return res;
1797
5.28M
    }
1798
5.31M
    Py_RETURN_NONE;
1799
5.31M
}
1800
1801
/* Generic read function: read from the stream until enough bytes are read,
1802
 * or until an EOF occurs or until read() would block.
1803
 */
1804
static PyObject *
1805
_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
1806
28.8k
{
1807
28.8k
    Py_ssize_t current_size, remaining, written;
1808
1809
28.8k
    current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1810
28.8k
    if (n <= current_size)
1811
0
        return _bufferedreader_read_fast(self, n);
1812
1813
28.8k
    PyBytesWriter *writer = PyBytesWriter_Create(n);
1814
28.8k
    if (writer == NULL) {
1815
0
        goto error;
1816
0
    }
1817
28.8k
    char *out = PyBytesWriter_GetData(writer);
1818
1819
28.8k
    remaining = n;
1820
28.8k
    written = 0;
1821
28.8k
    if (current_size > 0) {
1822
4.77k
        memcpy(out, self->buffer + self->pos, current_size);
1823
4.77k
        remaining -= current_size;
1824
4.77k
        written += current_size;
1825
4.77k
        self->pos += current_size;
1826
4.77k
    }
1827
    /* Flush the write buffer if necessary */
1828
28.8k
    if (self->writable) {
1829
0
        PyObject *r = buffered_flush_and_rewind_unlocked(self);
1830
0
        if (r == NULL)
1831
0
            goto error;
1832
0
        Py_DECREF(r);
1833
0
    }
1834
28.8k
    _bufferedreader_reset_buf(self);
1835
28.8k
    while (remaining > 0) {
1836
        /* We want to read a whole block at the end into buffer.
1837
           If we had readv() we could do this in one pass. */
1838
28.8k
        Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1839
28.8k
        if (r == 0)
1840
28.8k
            break;
1841
0
        r = _bufferedreader_raw_read(self, out + written, r);
1842
0
        if (r == -1)
1843
0
            goto error;
1844
0
        if (r == 0 || r == -2) {
1845
            /* EOF occurred or read() would block. */
1846
0
            if (r == 0 || written > 0) {
1847
0
                return PyBytesWriter_FinishWithSize(writer, written);
1848
0
            }
1849
0
            PyBytesWriter_Discard(writer);
1850
0
            Py_RETURN_NONE;
1851
0
        }
1852
0
        remaining -= r;
1853
0
        written += r;
1854
0
    }
1855
28.8k
    assert(remaining <= self->buffer_size);
1856
28.8k
    self->pos = 0;
1857
28.8k
    self->raw_pos = 0;
1858
28.8k
    self->read_end = 0;
1859
    /* NOTE: when the read is satisfied, we avoid issuing any additional
1860
       reads, which could block indefinitely (e.g. on a socket).
1861
       See issue #9550. */
1862
35.1k
    while (remaining > 0 && self->read_end < self->buffer_size) {
1863
35.1k
        Py_ssize_t r = _bufferedreader_fill_buffer(self);
1864
35.1k
        if (r == -1)
1865
4.31k
            goto error;
1866
30.8k
        if (r == 0 || r == -2) {
1867
            /* EOF occurred or read() would block. */
1868
336
            if (r == 0 || written > 0) {
1869
336
                return PyBytesWriter_FinishWithSize(writer, written);
1870
336
            }
1871
0
            PyBytesWriter_Discard(writer);
1872
0
            Py_RETURN_NONE;
1873
336
        }
1874
30.5k
        if (remaining > r) {
1875
6.28k
            memcpy(out + written, self->buffer + self->pos, r);
1876
6.28k
            written += r;
1877
6.28k
            self->pos += r;
1878
6.28k
            remaining -= r;
1879
6.28k
        }
1880
24.2k
        else if (remaining > 0) {
1881
24.2k
            memcpy(out + written, self->buffer + self->pos, remaining);
1882
24.2k
            written += remaining;
1883
24.2k
            self->pos += remaining;
1884
24.2k
            remaining = 0;
1885
24.2k
        }
1886
30.5k
        if (remaining == 0)
1887
24.2k
            break;
1888
30.5k
    }
1889
1890
24.2k
    return PyBytesWriter_Finish(writer);
1891
1892
4.31k
error:
1893
4.31k
    PyBytesWriter_Discard(writer);
1894
4.31k
    return NULL;
1895
28.8k
}
1896
1897
static PyObject *
1898
_bufferedreader_peek_unlocked(buffered *self)
1899
0
{
1900
0
    Py_ssize_t have, r;
1901
1902
0
    have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1903
    /* Constraints:
1904
       1. we don't want to advance the file position.
1905
       2. we don't want to lose block alignment, so we can't shift the buffer
1906
          to make some place.
1907
       Therefore, we either return `have` bytes (if > 0), or a full buffer.
1908
    */
1909
0
    if (have > 0) {
1910
0
        return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1911
0
    }
1912
1913
    /* Fill the buffer from the raw stream, and copy it to the result. */
1914
0
    _bufferedreader_reset_buf(self);
1915
0
    r = _bufferedreader_fill_buffer(self);
1916
0
    if (r == -1)
1917
0
        return NULL;
1918
0
    if (r == -2)
1919
0
        r = 0;
1920
0
    self->pos = 0;
1921
0
    return PyBytes_FromStringAndSize(self->buffer, r);
1922
0
}
1923
1924
1925
/*
1926
 * class BufferedWriter
1927
 */
1928
static void
1929
_bufferedwriter_reset_buf(buffered *self)
1930
179k
{
1931
179k
    self->write_pos = 0;
1932
179k
    self->write_end = -1;
1933
179k
}
1934
1935
/*[clinic input]
1936
_io.BufferedWriter.__init__
1937
    raw: object
1938
    buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
1939
1940
A buffer for a writeable sequential RawIO object.
1941
1942
The constructor creates a BufferedWriter for the given writeable raw
1943
stream. If the buffer_size is not given, it defaults to
1944
DEFAULT_BUFFER_SIZE.
1945
[clinic start generated code]*/
1946
1947
static int
1948
_io_BufferedWriter___init___impl(buffered *self, PyObject *raw,
1949
                                 Py_ssize_t buffer_size)
1950
/*[clinic end generated code: output=c8942a020c0dee64 input=914be9b95e16007b]*/
1951
17.4k
{
1952
17.4k
    self->ok = 0;
1953
17.4k
    self->detached = 0;
1954
1955
17.4k
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
1956
17.4k
    if (_PyIOBase_check_writable(state, raw, Py_True) == NULL) {
1957
0
        return -1;
1958
0
    }
1959
1960
17.4k
    Py_INCREF(raw);
1961
17.4k
    Py_XSETREF(self->raw, raw);
1962
17.4k
    self->readable = 0;
1963
17.4k
    self->writable = 1;
1964
1965
17.4k
    self->buffer_size = buffer_size;
1966
17.4k
    if (_buffered_init(self) < 0)
1967
0
        return -1;
1968
17.4k
    _bufferedwriter_reset_buf(self);
1969
17.4k
    self->pos = 0;
1970
1971
17.4k
    self->fast_closed_checks = (
1972
17.4k
        Py_IS_TYPE(self, state->PyBufferedWriter_Type) &&
1973
17.4k
        Py_IS_TYPE(raw, state->PyFileIO_Type)
1974
17.4k
    );
1975
1976
17.4k
    self->ok = 1;
1977
17.4k
    return 0;
1978
17.4k
}
1979
1980
static Py_ssize_t
1981
_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
1982
161k
{
1983
161k
    Py_buffer buf;
1984
161k
    PyObject *memobj, *res;
1985
161k
    Py_ssize_t n;
1986
161k
    int errnum;
1987
    /* NOTE: the buffer needn't be released as its object is NULL. */
1988
161k
    if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1989
0
        return -1;
1990
161k
    memobj = PyMemoryView_FromBuffer(&buf);
1991
161k
    if (memobj == NULL)
1992
0
        return -1;
1993
    /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1994
       occurs so we needn't do it ourselves.
1995
       We then retry writing, ignoring the signal if no handler has
1996
       raised (see issue #10956).
1997
    */
1998
161k
    do {
1999
161k
        errno = 0;
2000
161k
        res = PyObject_CallMethodOneArg(self->raw, &_Py_ID(write), memobj);
2001
161k
        errnum = errno;
2002
161k
    } while (res == NULL && _PyIO_trap_eintr());
2003
161k
    Py_DECREF(memobj);
2004
161k
    if (res == NULL)
2005
0
        return -1;
2006
161k
    if (res == Py_None) {
2007
        /* Non-blocking stream would have blocked. Special return code!
2008
           Being paranoid we reset errno in case it is changed by code
2009
           triggered by a decref.  errno is used by _set_BlockingIOError(). */
2010
0
        Py_DECREF(res);
2011
0
        errno = errnum;
2012
0
        return -2;
2013
0
    }
2014
161k
    n = PyNumber_AsSsize_t(res, PyExc_ValueError);
2015
161k
    Py_DECREF(res);
2016
161k
    if (n < 0 || n > len) {
2017
0
        PyErr_Format(PyExc_OSError,
2018
0
                     "raw write() returned invalid length %zd "
2019
0
                     "(should have been between 0 and %zd)", n, len);
2020
0
        return -1;
2021
0
    }
2022
161k
    if (n > 0 && self->abs_pos != -1)
2023
161k
        self->abs_pos += n;
2024
161k
    return n;
2025
161k
}
2026
2027
static PyObject *
2028
_bufferedwriter_flush_unlocked(buffered *self)
2029
162k
{
2030
162k
    Py_off_t n, rewind;
2031
2032
162k
    if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
2033
790
        goto end;
2034
    /* First, rewind */
2035
161k
    rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
2036
161k
    if (rewind != 0) {
2037
0
        n = _buffered_raw_seek(self, -rewind, 1);
2038
0
        if (n < 0) {
2039
0
            goto error;
2040
0
        }
2041
0
        self->raw_pos -= rewind;
2042
0
    }
2043
322k
    while (self->write_pos < self->write_end) {
2044
161k
        n = _bufferedwriter_raw_write(self,
2045
161k
            self->buffer + self->write_pos,
2046
161k
            Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
2047
161k
                             Py_off_t, Py_ssize_t));
2048
161k
        if (n == -1) {
2049
0
            goto error;
2050
0
        }
2051
161k
        else if (n == -2) {
2052
0
            _set_BlockingIOError("write could not complete without blocking",
2053
0
                                 0);
2054
0
            goto error;
2055
0
        }
2056
161k
        self->write_pos += n;
2057
161k
        self->raw_pos = self->write_pos;
2058
        /* Partial writes can return successfully when interrupted by a
2059
           signal (see write(2)).  We must run signal handlers before
2060
           blocking another time, possibly indefinitely. */
2061
161k
        if (PyErr_CheckSignals() < 0)
2062
0
            goto error;
2063
161k
    }
2064
2065
2066
162k
end:
2067
    /* This ensures that after return from this function,
2068
       VALID_WRITE_BUFFER(self) returns false.
2069
2070
       This is a required condition because when a tell() is called
2071
       after flushing and if VALID_READ_BUFFER(self) is false, we need
2072
       VALID_WRITE_BUFFER(self) to be false to have
2073
       RAW_OFFSET(self) == 0.
2074
2075
       Issue: https://bugs.python.org/issue32228 */
2076
162k
    _bufferedwriter_reset_buf(self);
2077
162k
    Py_RETURN_NONE;
2078
2079
0
error:
2080
0
    return NULL;
2081
161k
}
2082
2083
/*[clinic input]
2084
@critical_section
2085
_io.BufferedWriter.write
2086
    buffer: Py_buffer
2087
    /
2088
[clinic start generated code]*/
2089
2090
static PyObject *
2091
_io_BufferedWriter_write_impl(buffered *self, Py_buffer *buffer)
2092
/*[clinic end generated code: output=7f8d1365759bfc6b input=6a9c041de0c337be]*/
2093
161k
{
2094
161k
    PyObject *res = NULL;
2095
161k
    Py_ssize_t written, avail, remaining;
2096
161k
    Py_off_t offset;
2097
161k
    int r;
2098
2099
161k
    CHECK_INITIALIZED(self)
2100
2101
161k
    if (!ENTER_BUFFERED(self))
2102
0
        return NULL;
2103
2104
    /* Issue #31976: Check for closed file after acquiring the lock. Another
2105
       thread could be holding the lock while closing the file. */
2106
161k
    r = IS_CLOSED(self);
2107
161k
    if (r < 0) {
2108
0
        goto error;
2109
0
    }
2110
161k
    if (r > 0) {
2111
0
        PyErr_SetString(PyExc_ValueError, "write to closed file");
2112
0
        goto error;
2113
0
    }
2114
2115
    /* Fast path: the data to write can be fully buffered. */
2116
161k
    if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
2117
161k
        self->pos = 0;
2118
161k
        self->raw_pos = 0;
2119
161k
    }
2120
161k
    avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
2121
161k
    if (buffer->len <= avail && buffer->len < self->buffer_size) {
2122
161k
        memcpy(self->buffer + self->pos, buffer->buf, buffer->len);
2123
161k
        if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
2124
161k
            self->write_pos = self->pos;
2125
161k
        }
2126
161k
        ADJUST_POSITION(self, self->pos + buffer->len);
2127
161k
        if (self->pos > self->write_end)
2128
161k
            self->write_end = self->pos;
2129
161k
        written = buffer->len;
2130
161k
        goto end;
2131
161k
    }
2132
2133
    /* First write the current buffer */
2134
286
    res = _bufferedwriter_flush_unlocked(self);
2135
286
    if (res == NULL) {
2136
0
        Py_ssize_t *w = _buffered_check_blocking_error();
2137
0
        if (w == NULL)
2138
0
            goto error;
2139
0
        if (self->readable)
2140
0
            _bufferedreader_reset_buf(self);
2141
        /* Make some place by shifting the buffer. */
2142
0
        assert(VALID_WRITE_BUFFER(self));
2143
0
        memmove(self->buffer, self->buffer + self->write_pos,
2144
0
                Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
2145
0
                                 Py_off_t, Py_ssize_t));
2146
0
        self->write_end -= self->write_pos;
2147
0
        self->raw_pos -= self->write_pos;
2148
0
        self->pos -= self->write_pos;
2149
0
        self->write_pos = 0;
2150
0
        avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
2151
0
                                 Py_off_t, Py_ssize_t);
2152
0
        if (buffer->len <= avail) {
2153
            /* Everything can be buffered */
2154
0
            PyErr_Clear();
2155
0
            memcpy(self->buffer + self->write_end, buffer->buf, buffer->len);
2156
0
            self->write_end += buffer->len;
2157
0
            self->pos += buffer->len;
2158
0
            written = buffer->len;
2159
0
            goto end;
2160
0
        }
2161
        /* Buffer as much as possible. */
2162
0
        memcpy(self->buffer + self->write_end, buffer->buf, avail);
2163
0
        self->write_end += avail;
2164
0
        self->pos += avail;
2165
        /* XXX Modifying the existing exception e using the pointer w
2166
           will change e.characters_written but not e.args[2].
2167
           Therefore we just replace with a new error. */
2168
0
        _set_BlockingIOError("write could not complete without blocking",
2169
0
                             avail);
2170
0
        goto error;
2171
0
    }
2172
286
    Py_CLEAR(res);
2173
2174
    /* Adjust the raw stream position if it is away from the logical stream
2175
       position. This happens if the read buffer has been filled but not
2176
       modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
2177
       the raw stream by itself).
2178
       Fixes issue #6629.
2179
    */
2180
286
    offset = RAW_OFFSET(self);
2181
286
    if (offset != 0) {
2182
0
        if (_buffered_raw_seek(self, -offset, 1) < 0)
2183
0
            goto error;
2184
0
        self->raw_pos -= offset;
2185
0
    }
2186
2187
    /* Then write buf itself. At this point the buffer has been emptied. */
2188
286
    remaining = buffer->len;
2189
286
    written = 0;
2190
572
    while (remaining >= self->buffer_size) {
2191
286
        Py_ssize_t n = _bufferedwriter_raw_write(
2192
286
            self, (char *) buffer->buf + written, buffer->len - written);
2193
286
        if (n == -1) {
2194
0
            goto error;
2195
286
        } else if (n == -2) {
2196
            /* Write failed because raw file is non-blocking */
2197
0
            if (remaining > self->buffer_size) {
2198
                /* Can't buffer everything, still buffer as much as possible */
2199
0
                memcpy(self->buffer,
2200
0
                       (char *) buffer->buf + written, self->buffer_size);
2201
0
                self->raw_pos = 0;
2202
0
                ADJUST_POSITION(self, self->buffer_size);
2203
0
                self->write_end = self->buffer_size;
2204
0
                written += self->buffer_size;
2205
0
                _set_BlockingIOError("write could not complete without "
2206
0
                                     "blocking", written);
2207
0
                goto error;
2208
0
            }
2209
0
            PyErr_Clear();
2210
0
            break;
2211
0
        }
2212
286
        written += n;
2213
286
        remaining -= n;
2214
        /* Partial writes can return successfully when interrupted by a
2215
           signal (see write(2)).  We must run signal handlers before
2216
           blocking another time, possibly indefinitely. */
2217
286
        if (PyErr_CheckSignals() < 0)
2218
0
            goto error;
2219
286
    }
2220
286
    if (self->readable)
2221
0
        _bufferedreader_reset_buf(self);
2222
286
    if (remaining > 0) {
2223
0
        memcpy(self->buffer, (char *) buffer->buf + written, remaining);
2224
0
        written += remaining;
2225
0
    }
2226
286
    self->write_pos = 0;
2227
    /* TODO: sanity check (remaining >= 0) */
2228
286
    self->write_end = remaining;
2229
286
    ADJUST_POSITION(self, remaining);
2230
286
    self->raw_pos = 0;
2231
2232
161k
end:
2233
161k
    res = PyLong_FromSsize_t(written);
2234
2235
161k
error:
2236
161k
    LEAVE_BUFFERED(self)
2237
161k
    return res;
2238
161k
}
2239
2240
2241
/*
2242
 * BufferedRWPair
2243
 */
2244
2245
/* XXX The usefulness of this (compared to having two separate IO objects) is
2246
 * questionable.
2247
 */
2248
2249
typedef struct {
2250
    PyObject_HEAD
2251
    buffered *reader;
2252
    buffered *writer;
2253
    PyObject *dict;
2254
    PyObject *weakreflist;
2255
} rwpair;
2256
2257
0
#define rwpair_CAST(op) ((rwpair *)(op))
2258
2259
/*[clinic input]
2260
_io.BufferedRWPair.__init__
2261
    reader: object
2262
    writer: object
2263
    buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
2264
    /
2265
2266
A buffered reader and writer object together.
2267
2268
A buffered reader object and buffered writer object put together to
2269
form a sequential IO object that can read and write. This is typically
2270
used with a socket or two-way pipe.
2271
2272
reader and writer are RawIOBase objects that are readable and
2273
writeable respectively. If the buffer_size is omitted it defaults to
2274
DEFAULT_BUFFER_SIZE.
2275
[clinic start generated code]*/
2276
2277
static int
2278
_io_BufferedRWPair___init___impl(rwpair *self, PyObject *reader,
2279
                                 PyObject *writer, Py_ssize_t buffer_size)
2280
/*[clinic end generated code: output=327e73d1aee8f984 input=620d42d71f33a031]*/
2281
0
{
2282
0
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
2283
0
    if (_PyIOBase_check_readable(state, reader, Py_True) == NULL) {
2284
0
        return -1;
2285
0
    }
2286
0
    if (_PyIOBase_check_writable(state, writer, Py_True) == NULL) {
2287
0
        return -1;
2288
0
    }
2289
2290
0
    self->reader = (buffered *) PyObject_CallFunction(
2291
0
            (PyObject *)state->PyBufferedReader_Type,
2292
0
            "On", reader, buffer_size);
2293
0
    if (self->reader == NULL)
2294
0
        return -1;
2295
2296
0
    self->writer = (buffered *) PyObject_CallFunction(
2297
0
            (PyObject *)state->PyBufferedWriter_Type,
2298
0
            "On", writer, buffer_size);
2299
0
    if (self->writer == NULL) {
2300
0
        Py_CLEAR(self->reader);
2301
0
        return -1;
2302
0
    }
2303
2304
0
    return 0;
2305
0
}
2306
2307
static int
2308
bufferedrwpair_traverse(PyObject *op, visitproc visit, void *arg)
2309
0
{
2310
0
    rwpair *self = rwpair_CAST(op);
2311
0
    Py_VISIT(Py_TYPE(self));
2312
0
    Py_VISIT(self->dict);
2313
0
    Py_VISIT(self->reader);
2314
0
    Py_VISIT(self->writer);
2315
0
    return 0;
2316
0
}
2317
2318
static int
2319
bufferedrwpair_clear(PyObject *op)
2320
0
{
2321
0
    rwpair *self = rwpair_CAST(op);
2322
0
    Py_CLEAR(self->reader);
2323
0
    Py_CLEAR(self->writer);
2324
0
    Py_CLEAR(self->dict);
2325
0
    return 0;
2326
0
}
2327
2328
static void
2329
bufferedrwpair_dealloc(PyObject *op)
2330
0
{
2331
0
    rwpair *self = rwpair_CAST(op);
2332
0
    PyTypeObject *tp = Py_TYPE(self);
2333
0
    _PyObject_GC_UNTRACK(self);
2334
0
    FT_CLEAR_WEAKREFS(op, self->weakreflist);
2335
0
    (void)bufferedrwpair_clear(op);
2336
0
    tp->tp_free(self);
2337
0
    Py_DECREF(tp);
2338
0
}
2339
2340
/* Call the method of the underlying reader or writer.  The argument is
2341
   only passed if it is not NULL, so that the default of that method is
2342
   used otherwise. */
2343
static PyObject *
2344
_forward_call(buffered *self, PyObject *name, PyObject *arg)
2345
0
{
2346
0
    if (self == NULL) {
2347
0
        PyErr_SetString(PyExc_ValueError,
2348
0
                        "I/O operation on uninitialized object");
2349
0
        return NULL;
2350
0
    }
2351
2352
0
    if (arg == NULL) {
2353
0
        return PyObject_CallMethodNoArgs((PyObject *)self, name);
2354
0
    }
2355
0
    return PyObject_CallMethodOneArg((PyObject *)self, name, arg);
2356
0
}
2357
2358
/*[clinic input]
2359
_io.BufferedRWPair.read
2360
    size: object(c_default="NULL") = -1
2361
    /
2362
[clinic start generated code]*/
2363
2364
static PyObject *
2365
_io_BufferedRWPair_read_impl(rwpair *self, PyObject *size)
2366
/*[clinic end generated code: output=0668e3c5dbd3e93d input=eddb5e52aba9ebe5]*/
2367
0
{
2368
0
    return _forward_call(self->reader, &_Py_ID(read), size);
2369
0
}
2370
2371
/*[clinic input]
2372
_io.BufferedRWPair.peek
2373
    size: object(c_default="NULL") = 0
2374
    /
2375
[clinic start generated code]*/
2376
2377
static PyObject *
2378
_io_BufferedRWPair_peek_impl(rwpair *self, PyObject *size)
2379
/*[clinic end generated code: output=190a267bd694efa0 input=36af95964bebe355]*/
2380
0
{
2381
0
    return _forward_call(self->reader, &_Py_ID(peek), size);
2382
0
}
2383
2384
/*[clinic input]
2385
_io.BufferedRWPair.read1
2386
    size: object(c_default="NULL") = -1
2387
    /
2388
[clinic start generated code]*/
2389
2390
static PyObject *
2391
_io_BufferedRWPair_read1_impl(rwpair *self, PyObject *size)
2392
/*[clinic end generated code: output=17ec19608f2bb825 input=9e94db423e490b58]*/
2393
0
{
2394
0
    return _forward_call(self->reader, &_Py_ID(read1), size);
2395
0
}
2396
2397
/*[clinic input]
2398
_io.BufferedRWPair.readinto
2399
    buffer: object
2400
    /
2401
[clinic start generated code]*/
2402
2403
static PyObject *
2404
_io_BufferedRWPair_readinto_impl(rwpair *self, PyObject *buffer)
2405
/*[clinic end generated code: output=16c86b071015f7a4 input=ccd86ce2666261f7]*/
2406
0
{
2407
0
    return _forward_call(self->reader, &_Py_ID(readinto), buffer);
2408
0
}
2409
2410
/*[clinic input]
2411
_io.BufferedRWPair.readinto1
2412
    buffer: object
2413
    /
2414
[clinic start generated code]*/
2415
2416
static PyObject *
2417
_io_BufferedRWPair_readinto1_impl(rwpair *self, PyObject *buffer)
2418
/*[clinic end generated code: output=f1577b6f54c2b02a input=613d9bf127f88a4a]*/
2419
0
{
2420
0
    return _forward_call(self->reader, &_Py_ID(readinto1), buffer);
2421
0
}
2422
2423
/*[clinic input]
2424
_io.BufferedRWPair.write
2425
    buffer: object
2426
    /
2427
[clinic start generated code]*/
2428
2429
static PyObject *
2430
_io_BufferedRWPair_write_impl(rwpair *self, PyObject *buffer)
2431
/*[clinic end generated code: output=6f7509a747410c68 input=66c602422e3ec36f]*/
2432
0
{
2433
0
    return _forward_call(self->writer, &_Py_ID(write), buffer);
2434
0
}
2435
2436
/*[clinic input]
2437
_io.BufferedRWPair.flush
2438
[clinic start generated code]*/
2439
2440
static PyObject *
2441
_io_BufferedRWPair_flush_impl(rwpair *self)
2442
/*[clinic end generated code: output=0b2dcbe828718d6b input=e853da796ee61df1]*/
2443
0
{
2444
0
    return _forward_call(self->writer, &_Py_ID(flush), NULL);
2445
0
}
2446
2447
/*[clinic input]
2448
_io.BufferedRWPair.readable
2449
[clinic start generated code]*/
2450
2451
static PyObject *
2452
_io_BufferedRWPair_readable_impl(rwpair *self)
2453
/*[clinic end generated code: output=615967d4aa58f122 input=0475ed73d0a3167f]*/
2454
0
{
2455
0
    return _forward_call(self->reader, &_Py_ID(readable), NULL);
2456
0
}
2457
2458
/*[clinic input]
2459
_io.BufferedRWPair.writable
2460
[clinic start generated code]*/
2461
2462
static PyObject *
2463
_io_BufferedRWPair_writable_impl(rwpair *self)
2464
/*[clinic end generated code: output=c5a43c84e0195c11 input=3cfd44fb4757082f]*/
2465
0
{
2466
0
    return _forward_call(self->writer, &_Py_ID(writable), NULL);
2467
0
}
2468
2469
/*[clinic input]
2470
_io.BufferedRWPair.close
2471
[clinic start generated code]*/
2472
2473
static PyObject *
2474
_io_BufferedRWPair_close_impl(rwpair *self)
2475
/*[clinic end generated code: output=5924ba5ecc78752a input=4087d69f2d8fc368]*/
2476
0
{
2477
0
    PyObject *exc = NULL;
2478
0
    PyObject *ret = _forward_call(self->writer, &_Py_ID(close), NULL);
2479
0
    if (ret == NULL) {
2480
0
        exc = PyErr_GetRaisedException();
2481
0
    }
2482
0
    else {
2483
0
        Py_DECREF(ret);
2484
0
    }
2485
0
    ret = _forward_call(self->reader, &_Py_ID(close), NULL);
2486
0
    if (exc != NULL) {
2487
0
        _PyErr_ChainExceptions1(exc);
2488
0
        Py_CLEAR(ret);
2489
0
    }
2490
0
    return ret;
2491
0
}
2492
2493
/*[clinic input]
2494
_io.BufferedRWPair.isatty
2495
[clinic start generated code]*/
2496
2497
static PyObject *
2498
_io_BufferedRWPair_isatty_impl(rwpair *self)
2499
/*[clinic end generated code: output=d017c621ed879cb7 input=92833e3d60586e14]*/
2500
0
{
2501
0
    PyObject *ret = _forward_call(self->writer, &_Py_ID(isatty), NULL);
2502
2503
0
    if (ret != Py_False) {
2504
        /* either True or exception */
2505
0
        return ret;
2506
0
    }
2507
0
    Py_DECREF(ret);
2508
2509
0
    return _forward_call(self->reader, &_Py_ID(isatty), NULL);
2510
0
}
2511
2512
/*[clinic input]
2513
@getter
2514
_io.BufferedRWPair.closed
2515
[clinic start generated code]*/
2516
2517
static PyObject *
2518
_io_BufferedRWPair_closed_get_impl(rwpair *self)
2519
/*[clinic end generated code: output=4117400c74766f21 input=8248430ac54e5b25]*/
2520
0
{
2521
0
    if (self->writer == NULL) {
2522
0
        PyErr_SetString(PyExc_RuntimeError,
2523
0
                "the BufferedRWPair object is being garbage-collected");
2524
0
        return NULL;
2525
0
    }
2526
0
    return PyObject_GetAttr((PyObject *) self->writer, &_Py_ID(closed));
2527
0
}
2528
2529
2530
/*
2531
 * BufferedRandom
2532
 */
2533
2534
/*[clinic input]
2535
_io.BufferedRandom.__init__
2536
    raw: object
2537
    buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
2538
2539
A buffered interface to random access streams.
2540
2541
The constructor creates a reader and writer for a seekable stream,
2542
raw, given in the first argument. If the buffer_size is omitted it
2543
defaults to DEFAULT_BUFFER_SIZE.
2544
[clinic start generated code]*/
2545
2546
static int
2547
_io_BufferedRandom___init___impl(buffered *self, PyObject *raw,
2548
                                 Py_ssize_t buffer_size)
2549
/*[clinic end generated code: output=d3d64eb0f64e64a3 input=a4e818fb86d0e50c]*/
2550
0
{
2551
0
    self->ok = 0;
2552
0
    self->detached = 0;
2553
2554
0
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
2555
0
    if (_PyIOBase_check_seekable(state, raw, Py_True) == NULL) {
2556
0
        return -1;
2557
0
    }
2558
0
    if (_PyIOBase_check_readable(state, raw, Py_True) == NULL) {
2559
0
        return -1;
2560
0
    }
2561
0
    if (_PyIOBase_check_writable(state, raw, Py_True) == NULL) {
2562
0
        return -1;
2563
0
    }
2564
2565
0
    Py_INCREF(raw);
2566
0
    Py_XSETREF(self->raw, raw);
2567
0
    self->buffer_size = buffer_size;
2568
0
    self->readable = 1;
2569
0
    self->writable = 1;
2570
2571
0
    if (_buffered_init(self) < 0)
2572
0
        return -1;
2573
0
    _bufferedreader_reset_buf(self);
2574
0
    _bufferedwriter_reset_buf(self);
2575
0
    self->pos = 0;
2576
2577
0
    self->fast_closed_checks = (Py_IS_TYPE(self, state->PyBufferedRandom_Type) &&
2578
0
                                Py_IS_TYPE(raw, state->PyFileIO_Type));
2579
2580
0
    self->ok = 1;
2581
0
    return 0;
2582
0
}
2583
2584
0
#define clinic_state() (find_io_state_by_def(Py_TYPE(self)))
2585
#include "clinic/bufferedio.c.h"
2586
#undef clinic_state
2587
2588
static PyMethodDef bufferediobase_methods[] = {
2589
    _IO__BUFFEREDIOBASE_DETACH_METHODDEF
2590
    _IO__BUFFEREDIOBASE_READ_METHODDEF
2591
    _IO__BUFFEREDIOBASE_READ1_METHODDEF
2592
    _IO__BUFFEREDIOBASE_READINTO_METHODDEF
2593
    _IO__BUFFEREDIOBASE_READINTO1_METHODDEF
2594
    _IO__BUFFEREDIOBASE_WRITE_METHODDEF
2595
    {NULL, NULL}
2596
};
2597
2598
static PyType_Slot bufferediobase_slots[] = {
2599
    {Py_tp_doc, (void *)bufferediobase_doc},
2600
    {Py_tp_methods, bufferediobase_methods},
2601
    {0, NULL},
2602
};
2603
2604
/* Do not set Py_TPFLAGS_HAVE_GC so that tp_traverse and tp_clear are inherited */
2605
PyType_Spec _Py_bufferediobase_spec = {
2606
    .name = "_io._BufferedIOBase",
2607
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
2608
              Py_TPFLAGS_IMMUTABLETYPE),
2609
    .slots = bufferediobase_slots,
2610
};
2611
2612
static PyMethodDef bufferedreader_methods[] = {
2613
    /* BufferedIOMixin methods */
2614
    _IO__BUFFERED_DETACH_METHODDEF
2615
    _IO__BUFFERED_SIMPLE_FLUSH_METHODDEF
2616
    _IO__BUFFERED_CLOSE_METHODDEF
2617
    _IO__BUFFERED_SEEKABLE_METHODDEF
2618
    _IO__BUFFERED_READABLE_METHODDEF
2619
    _IO__BUFFERED_FILENO_METHODDEF
2620
    _IO__BUFFERED_ISATTY_METHODDEF
2621
    _IO__BUFFERED__DEALLOC_WARN_METHODDEF
2622
2623
    _IO__BUFFERED_READ_METHODDEF
2624
    _IO__BUFFERED_PEEK_METHODDEF
2625
    _IO__BUFFERED_READ1_METHODDEF
2626
    _IO__BUFFERED_READINTO_METHODDEF
2627
    _IO__BUFFERED_READINTO1_METHODDEF
2628
    _IO__BUFFERED_READLINE_METHODDEF
2629
    _IO__BUFFERED_SEEK_METHODDEF
2630
    _IO__BUFFERED_TELL_METHODDEF
2631
    _IO__BUFFERED_TRUNCATE_METHODDEF
2632
    _IO__BUFFERED___SIZEOF___METHODDEF
2633
2634
    {"__getstate__", _PyIOBase_cannot_pickle, METH_NOARGS},
2635
    {NULL, NULL}
2636
};
2637
2638
static PyMemberDef bufferedreader_members[] = {
2639
    {"raw", _Py_T_OBJECT, offsetof(buffered, raw), Py_READONLY},
2640
    {"_finalizing", Py_T_BOOL, offsetof(buffered, finalizing), 0},
2641
    {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(buffered, weakreflist), Py_READONLY},
2642
    {"__dictoffset__", Py_T_PYSSIZET, offsetof(buffered, dict), Py_READONLY},
2643
    {NULL}
2644
};
2645
2646
static PyGetSetDef bufferedreader_getset[] = {
2647
    _IO__BUFFERED_CLOSED_GETSETDEF
2648
    _IO__BUFFERED_NAME_GETSETDEF
2649
    _IO__BUFFERED_MODE_GETSETDEF
2650
    {NULL}
2651
};
2652
2653
2654
static PyType_Slot bufferedreader_slots[] = {
2655
    {Py_tp_dealloc, buffered_dealloc},
2656
    {Py_tp_repr, buffered_repr},
2657
    {Py_tp_doc, (void *)_io_BufferedReader___init____doc__},
2658
    {Py_tp_traverse, buffered_traverse},
2659
    {Py_tp_clear, buffered_clear},
2660
    {Py_tp_iternext, buffered_iternext},
2661
    {Py_tp_methods, bufferedreader_methods},
2662
    {Py_tp_members, bufferedreader_members},
2663
    {Py_tp_getset, bufferedreader_getset},
2664
    {Py_tp_init, _io_BufferedReader___init__},
2665
    {0, NULL},
2666
};
2667
2668
PyType_Spec _Py_bufferedreader_spec = {
2669
    .name = "_io.BufferedReader",
2670
    .basicsize = sizeof(buffered),
2671
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
2672
              Py_TPFLAGS_IMMUTABLETYPE),
2673
    .slots = bufferedreader_slots,
2674
};
2675
2676
static PyMethodDef bufferedwriter_methods[] = {
2677
    /* BufferedIOMixin methods */
2678
    _IO__BUFFERED_CLOSE_METHODDEF
2679
    _IO__BUFFERED_DETACH_METHODDEF
2680
    _IO__BUFFERED_SEEKABLE_METHODDEF
2681
    _IO__BUFFERED_WRITABLE_METHODDEF
2682
    _IO__BUFFERED_FILENO_METHODDEF
2683
    _IO__BUFFERED_ISATTY_METHODDEF
2684
    _IO__BUFFERED__DEALLOC_WARN_METHODDEF
2685
2686
    _IO_BUFFEREDWRITER_WRITE_METHODDEF
2687
    _IO__BUFFERED_TRUNCATE_METHODDEF
2688
    _IO__BUFFERED_FLUSH_METHODDEF
2689
    _IO__BUFFERED_SEEK_METHODDEF
2690
    _IO__BUFFERED_TELL_METHODDEF
2691
    _IO__BUFFERED___SIZEOF___METHODDEF
2692
2693
    {"__getstate__", _PyIOBase_cannot_pickle, METH_NOARGS},
2694
    {NULL, NULL}
2695
};
2696
2697
static PyMemberDef bufferedwriter_members[] = {
2698
    {"raw", _Py_T_OBJECT, offsetof(buffered, raw), Py_READONLY},
2699
    {"_finalizing", Py_T_BOOL, offsetof(buffered, finalizing), 0},
2700
    {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(buffered, weakreflist), Py_READONLY},
2701
    {"__dictoffset__", Py_T_PYSSIZET, offsetof(buffered, dict), Py_READONLY},
2702
    {NULL}
2703
};
2704
2705
static PyGetSetDef bufferedwriter_getset[] = {
2706
    _IO__BUFFERED_CLOSED_GETSETDEF
2707
    _IO__BUFFERED_NAME_GETSETDEF
2708
    _IO__BUFFERED_MODE_GETSETDEF
2709
    {NULL}
2710
};
2711
2712
2713
static PyType_Slot bufferedwriter_slots[] = {
2714
    {Py_tp_dealloc, buffered_dealloc},
2715
    {Py_tp_repr, buffered_repr},
2716
    {Py_tp_doc, (void *)_io_BufferedWriter___init____doc__},
2717
    {Py_tp_traverse, buffered_traverse},
2718
    {Py_tp_clear, buffered_clear},
2719
    {Py_tp_methods, bufferedwriter_methods},
2720
    {Py_tp_members, bufferedwriter_members},
2721
    {Py_tp_getset, bufferedwriter_getset},
2722
    {Py_tp_init, _io_BufferedWriter___init__},
2723
    {0, NULL},
2724
};
2725
2726
PyType_Spec _Py_bufferedwriter_spec = {
2727
    .name = "_io.BufferedWriter",
2728
    .basicsize = sizeof(buffered),
2729
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
2730
              Py_TPFLAGS_IMMUTABLETYPE),
2731
    .slots = bufferedwriter_slots,
2732
};
2733
2734
static PyMethodDef bufferedrwpair_methods[] = {
2735
    _IO_BUFFEREDRWPAIR_READ_METHODDEF
2736
    _IO_BUFFEREDRWPAIR_PEEK_METHODDEF
2737
    _IO_BUFFEREDRWPAIR_READ1_METHODDEF
2738
    _IO_BUFFEREDRWPAIR_READINTO_METHODDEF
2739
    _IO_BUFFEREDRWPAIR_READINTO1_METHODDEF
2740
2741
    _IO_BUFFEREDRWPAIR_WRITE_METHODDEF
2742
    _IO_BUFFEREDRWPAIR_FLUSH_METHODDEF
2743
2744
    _IO_BUFFEREDRWPAIR_READABLE_METHODDEF
2745
    _IO_BUFFEREDRWPAIR_WRITABLE_METHODDEF
2746
2747
    _IO_BUFFEREDRWPAIR_CLOSE_METHODDEF
2748
    _IO_BUFFEREDRWPAIR_ISATTY_METHODDEF
2749
2750
    {NULL, NULL}
2751
};
2752
2753
static PyMemberDef bufferedrwpair_members[] = {
2754
    {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(rwpair, weakreflist), Py_READONLY},
2755
    {"__dictoffset__", Py_T_PYSSIZET, offsetof(rwpair, dict), Py_READONLY},
2756
    {NULL}
2757
};
2758
2759
static PyGetSetDef bufferedrwpair_getset[] = {
2760
    _IO_BUFFEREDRWPAIR_CLOSED_GETSETDEF
2761
    {NULL}
2762
};
2763
2764
static PyType_Slot bufferedrwpair_slots[] = {
2765
    {Py_tp_dealloc, bufferedrwpair_dealloc},
2766
    {Py_tp_doc, (void *)_io_BufferedRWPair___init____doc__},
2767
    {Py_tp_traverse, bufferedrwpair_traverse},
2768
    {Py_tp_clear, bufferedrwpair_clear},
2769
    {Py_tp_methods, bufferedrwpair_methods},
2770
    {Py_tp_members, bufferedrwpair_members},
2771
    {Py_tp_getset, bufferedrwpair_getset},
2772
    {Py_tp_init, _io_BufferedRWPair___init__},
2773
    {0, NULL},
2774
};
2775
2776
PyType_Spec _Py_bufferedrwpair_spec = {
2777
    .name = "_io.BufferedRWPair",
2778
    .basicsize = sizeof(rwpair),
2779
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
2780
              Py_TPFLAGS_IMMUTABLETYPE),
2781
    .slots = bufferedrwpair_slots,
2782
};
2783
2784
2785
static PyMethodDef bufferedrandom_methods[] = {
2786
    /* BufferedIOMixin methods */
2787
    _IO__BUFFERED_CLOSE_METHODDEF
2788
    _IO__BUFFERED_DETACH_METHODDEF
2789
    _IO__BUFFERED_SEEKABLE_METHODDEF
2790
    _IO__BUFFERED_READABLE_METHODDEF
2791
    _IO__BUFFERED_WRITABLE_METHODDEF
2792
    _IO__BUFFERED_FILENO_METHODDEF
2793
    _IO__BUFFERED_ISATTY_METHODDEF
2794
    _IO__BUFFERED__DEALLOC_WARN_METHODDEF
2795
2796
    _IO__BUFFERED_FLUSH_METHODDEF
2797
2798
    _IO__BUFFERED_SEEK_METHODDEF
2799
    _IO__BUFFERED_TELL_METHODDEF
2800
    _IO__BUFFERED_TRUNCATE_METHODDEF
2801
    _IO__BUFFERED_READ_METHODDEF
2802
    _IO__BUFFERED_READ1_METHODDEF
2803
    _IO__BUFFERED_READINTO_METHODDEF
2804
    _IO__BUFFERED_READINTO1_METHODDEF
2805
    _IO__BUFFERED_READLINE_METHODDEF
2806
    _IO__BUFFERED_PEEK_METHODDEF
2807
    _IO_BUFFEREDWRITER_WRITE_METHODDEF
2808
    _IO__BUFFERED___SIZEOF___METHODDEF
2809
2810
    {"__getstate__", _PyIOBase_cannot_pickle, METH_NOARGS},
2811
    {NULL, NULL}
2812
};
2813
2814
static PyMemberDef bufferedrandom_members[] = {
2815
    {"raw", _Py_T_OBJECT, offsetof(buffered, raw), Py_READONLY},
2816
    {"_finalizing", Py_T_BOOL, offsetof(buffered, finalizing), 0},
2817
    {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(buffered, weakreflist), Py_READONLY},
2818
    {"__dictoffset__", Py_T_PYSSIZET, offsetof(buffered, dict), Py_READONLY},
2819
    {NULL}
2820
};
2821
2822
static PyGetSetDef bufferedrandom_getset[] = {
2823
    _IO__BUFFERED_CLOSED_GETSETDEF
2824
    _IO__BUFFERED_NAME_GETSETDEF
2825
    _IO__BUFFERED_MODE_GETSETDEF
2826
    {NULL}
2827
};
2828
2829
2830
static PyType_Slot bufferedrandom_slots[] = {
2831
    {Py_tp_dealloc, buffered_dealloc},
2832
    {Py_tp_repr, buffered_repr},
2833
    {Py_tp_doc, (void *)_io_BufferedRandom___init____doc__},
2834
    {Py_tp_traverse, buffered_traverse},
2835
    {Py_tp_clear, buffered_clear},
2836
    {Py_tp_iternext, buffered_iternext},
2837
    {Py_tp_methods, bufferedrandom_methods},
2838
    {Py_tp_members, bufferedrandom_members},
2839
    {Py_tp_getset, bufferedrandom_getset},
2840
    {Py_tp_init, _io_BufferedRandom___init__},
2841
    {0, NULL},
2842
};
2843
2844
PyType_Spec _Py_bufferedrandom_spec = {
2845
    .name = "_io.BufferedRandom",
2846
    .basicsize = sizeof(buffered),
2847
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
2848
              Py_TPFLAGS_IMMUTABLETYPE),
2849
    .slots = bufferedrandom_slots,
2850
};