Coverage Report

Created: 2026-10-17 06:15

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
64.0k
#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
582k
    ( (PyThread_acquire_lock(self->lock, 0) ? \
331
582k
       1 : _enter_buffered_busy(self)) \
332
582k
     && (self->owner = PyThread_get_thread_ident(), 1) )
333
334
#define LEAVE_BUFFERED(self) \
335
582k
    do { \
336
582k
        self->owner = 0; \
337
582k
        PyThread_release_lock(self->lock); \
338
582k
    } while(0);
339
340
#define CHECK_INITIALIZED(self) \
341
9.00M
    if (self->ok <= 0) { \
342
0
        if (self->detached) { \
343
0
            PyErr_SetString(PyExc_ValueError, \
344
0
                 "raw stream has been detached"); \
345
0
        } else { \
346
0
            PyErr_SetString(PyExc_ValueError, \
347
0
                "I/O operation on uninitialized object"); \
348
0
        } \
349
0
        return NULL; \
350
0
    }
351
352
#define CHECK_INITIALIZED_INT(self) \
353
7.04M
    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.55M
    (!self->buffer ? 1 : \
366
7.55M
    (self->fast_closed_checks \
367
7.55M
     ? _PyFileIO_closed(self->raw) \
368
7.55M
     : buffered_closed(self)))
369
370
#define CHECK_CLOSED(self, error_msg) \
371
7.28M
    do { \
372
7.28M
        int _closed = IS_CLOSED(self); \
373
7.28M
        if (_closed < 0) { \
374
0
            return NULL; \
375
0
        } \
376
7.28M
        if (_closed && \
377
7.28M
            (Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t) == 0)) \
378
7.28M
        { \
379
0
            PyErr_SetString(PyExc_ValueError, error_msg); \
380
0
            return NULL; \
381
0
        } \
382
7.28M
    } while (0);
383
384
#define VALID_READ_BUFFER(self) \
385
2.87M
    (self->readable && self->read_end != -1)
386
387
#define VALID_WRITE_BUFFER(self) \
388
1.45M
    (self->writable && self->write_end != -1)
389
390
#define ADJUST_POSITION(self, _new_pos) \
391
240k
    do { \
392
240k
        self->pos = _new_pos; \
393
240k
        if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
394
240k
            self->read_end = self->pos; \
395
240k
    } while(0)
396
397
#define READAHEAD(self) \
398
1.37M
    ((self->readable && VALID_READ_BUFFER(self)) \
399
1.37M
        ? (self->read_end - self->pos) : 0)
400
401
#define RAW_OFFSET(self) \
402
251k
    (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
403
251k
        && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
404
405
#define RAW_TELL(self) \
406
1.37M
    (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
407
408
#define MINUS_LAST_BLOCK(self, size) \
409
29.7k
    (self->buffer_mask ? \
410
29.7k
        (size & ~self->buffer_mask) : \
411
29.7k
        (self->buffer_size * (size / self->buffer_size)))
412
413
414
static int
415
buffered_clear(PyObject *op)
416
29.4k
{
417
29.4k
    buffered *self = buffered_CAST(op);
418
29.4k
    self->ok = 0;
419
29.4k
    Py_CLEAR(self->raw);
420
29.4k
    Py_CLEAR(self->dict);
421
29.4k
    return 0;
422
29.4k
}
423
424
static void
425
buffered_dealloc(PyObject *op)
426
29.4k
{
427
29.4k
    buffered *self = buffered_CAST(op);
428
29.4k
    PyTypeObject *tp = Py_TYPE(self);
429
29.4k
    self->finalizing = 1;
430
29.4k
    if (_PyIOBase_finalize(op) < 0)
431
0
        return;
432
29.4k
    _PyObject_GC_UNTRACK(self);
433
29.4k
    self->ok = 0;
434
29.4k
    FT_CLEAR_WEAKREFS(op, self->weakreflist);
435
29.4k
    if (self->buffer) {
436
0
        PyMem_Free(self->buffer);
437
0
        self->buffer = NULL;
438
0
    }
439
29.4k
    if (self->lock) {
440
29.4k
        PyThread_free_lock(self->lock);
441
29.4k
        self->lock = NULL;
442
29.4k
    }
443
29.4k
    (void)buffered_clear(op);
444
29.4k
    tp->tp_free(self);
445
29.4k
    Py_DECREF(tp);
446
29.4k
}
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.13k
{
467
5.13k
    buffered *self = buffered_CAST(op);
468
5.13k
    Py_VISIT(Py_TYPE(self));
469
5.13k
    Py_VISIT(self->raw);
470
5.13k
    Py_VISIT(self->dict);
471
5.13k
    return 0;
472
5.13k
}
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.38M
{
516
1.38M
    CHECK_INITIALIZED(self)
517
1.38M
    return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(flush));
518
1.38M
}
519
520
static int
521
buffered_closed(buffered *self)
522
7.04M
{
523
7.04M
    int closed;
524
7.04M
    PyObject *res;
525
7.04M
    CHECK_INITIALIZED_INT(self)
526
7.04M
    res = PyObject_GetAttr(self->raw, &_Py_ID(closed));
527
7.04M
    if (res == NULL)
528
0
        return -1;
529
7.04M
    closed = PyObject_IsTrue(res);
530
7.04M
    Py_DECREF(res);
531
7.04M
    return closed;
532
7.04M
}
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
56.7k
{
544
56.7k
    CHECK_INITIALIZED(self)
545
56.7k
    return PyObject_GetAttr(self->raw, &_Py_ID(closed));
546
56.7k
}
547
548
/*[clinic input]
549
@critical_section
550
_io._Buffered.close
551
[clinic start generated code]*/
552
553
static PyObject *
554
_io__Buffered_close_impl(buffered *self)
555
/*[clinic end generated code: output=7280b7b42033be0c input=56d95935b03fd326]*/
556
29.4k
{
557
29.4k
    PyObject *res = NULL;
558
29.4k
    int r;
559
560
29.4k
    CHECK_INITIALIZED(self)
561
29.4k
    if (!ENTER_BUFFERED(self)) {
562
0
        return NULL;
563
0
    }
564
    /* gh-138720: Use IS_CLOSED to match flush CHECK_CLOSED. */
565
29.4k
    r = IS_CLOSED(self);
566
29.4k
    if (r < 0)
567
0
        goto end;
568
29.4k
    if (r > 0) {
569
0
        res = Py_NewRef(Py_None);
570
0
        goto end;
571
0
    }
572
573
29.4k
    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
29.4k
    LEAVE_BUFFERED(self)
582
29.4k
    r = _PyFile_Flush((PyObject *)self);
583
29.4k
    if (!ENTER_BUFFERED(self)) {
584
0
        return NULL;
585
0
    }
586
29.4k
    PyObject *exc = NULL;
587
29.4k
    if (r < 0) {
588
0
        exc = PyErr_GetRaisedException();
589
0
    }
590
591
29.4k
    res = PyObject_CallMethodNoArgs(self->raw, &_Py_ID(close));
592
593
29.4k
    if (self->buffer) {
594
29.4k
        PyMem_Free(self->buffer);
595
29.4k
        self->buffer = NULL;
596
29.4k
    }
597
598
29.4k
    if (exc != NULL) {
599
0
        _PyErr_ChainExceptions1(exc);
600
0
        Py_CLEAR(res);
601
0
    }
602
603
29.4k
    self->read_end = 0;
604
29.4k
    self->pos = 0;
605
606
29.4k
end:
607
29.4k
    LEAVE_BUFFERED(self)
608
29.4k
    return res;
609
29.4k
}
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
132
{
643
132
    CHECK_INITIALIZED(self)
644
132
    return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(seekable));
645
132
}
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
34.1k
{
786
34.1k
    Py_off_t n;
787
34.1k
    PyObject *res;
788
34.1k
    res = PyObject_CallMethodNoArgs(self->raw, &_Py_ID(tell));
789
34.1k
    if (res == NULL)
790
5
        return -1;
791
34.1k
    n = PyNumber_AsOff_t(res, PyExc_ValueError);
792
34.1k
    Py_DECREF(res);
793
34.1k
    if (n < 0) {
794
0
        if (!PyErr_Occurred())
795
0
            PyErr_Format(PyExc_OSError,
796
0
                         "Raw stream returned invalid position %" PY_PRIdOFF,
797
0
                         (PY_OFF_T_COMPAT)n);
798
0
        return -1;
799
0
    }
800
34.1k
    self->abs_pos = n;
801
34.1k
    return n;
802
34.1k
}
803
804
static Py_off_t
805
_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
806
7.11k
{
807
7.11k
    PyObject *res, *posobj, *whenceobj;
808
7.11k
    Py_off_t n;
809
810
7.11k
    posobj = PyLong_FromOff_t(target);
811
7.11k
    if (posobj == NULL)
812
0
        return -1;
813
7.11k
    whenceobj = PyLong_FromLong(whence);
814
7.11k
    if (whenceobj == NULL) {
815
0
        Py_DECREF(posobj);
816
0
        return -1;
817
0
    }
818
7.11k
    res = PyObject_CallMethodObjArgs(self->raw, &_Py_ID(seek),
819
7.11k
                                     posobj, whenceobj, NULL);
820
7.11k
    Py_DECREF(posobj);
821
7.11k
    Py_DECREF(whenceobj);
822
7.11k
    if (res == NULL)
823
5
        return -1;
824
7.11k
    n = PyNumber_AsOff_t(res, PyExc_ValueError);
825
7.11k
    Py_DECREF(res);
826
7.11k
    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.11k
    self->abs_pos = n;
834
7.11k
    return n;
835
7.11k
}
836
837
static int
838
_buffered_init(buffered *self)
839
29.5k
{
840
29.5k
    Py_ssize_t n;
841
29.5k
    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
29.5k
    if (self->buffer)
847
0
        PyMem_Free(self->buffer);
848
29.5k
    self->buffer = PyMem_Malloc(self->buffer_size);
849
29.5k
    if (self->buffer == NULL) {
850
0
        PyErr_NoMemory();
851
0
        return -1;
852
0
    }
853
29.5k
    if (self->lock)
854
0
        PyThread_free_lock(self->lock);
855
29.5k
    self->lock = PyThread_allocate_lock();
856
29.5k
    if (self->lock == NULL) {
857
0
        PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
858
0
        return -1;
859
0
    }
860
29.5k
    self->owner = 0;
861
    /* Find out whether buffer_size is a power of 2 */
862
    /* XXX is this optimization useful? */
863
531k
    for (n = self->buffer_size - 1; n & 1; n >>= 1)
864
502k
        ;
865
29.5k
    if (n == 0)
866
29.5k
        self->buffer_mask = self->buffer_size - 1;
867
0
    else
868
0
        self->buffer_mask = 0;
869
29.5k
    if (_buffered_raw_tell(self) == -1)
870
5
        PyErr_Clear();
871
29.5k
    return 0;
872
29.5k
}
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.48k
{
881
4.48k
    if (!PyErr_ExceptionMatches(PyExc_OSError)) {
882
2.41k
        return 0;
883
2.41k
    }
884
2.07k
    PyObject *exc = PyErr_GetRaisedException();
885
2.07k
    PyOSErrorObject *env_err = (PyOSErrorObject *)exc;
886
2.07k
    assert(env_err != NULL);
887
2.07k
    if (env_err->myerrno != NULL) {
888
0
        assert(EINTR > 0 && EINTR < INT_MAX);
889
0
        assert(PyLong_CheckExact(env_err->myerrno));
890
0
        int overflow;
891
0
        int myerrno = PyLong_AsLongAndOverflow(env_err->myerrno, &overflow);
892
0
        PyErr_Clear();
893
0
        if (myerrno == EINTR) {
894
0
            Py_DECREF(exc);
895
0
            return 1;
896
0
        }
897
0
    }
898
    /* This silences any error set by PyObject_RichCompareBool() */
899
2.07k
    PyErr_SetRaisedException(exc);
900
2.07k
    return 0;
901
2.07k
}
902
903
/*
904
 * Shared methods and wrappers
905
 */
906
907
static PyObject *
908
buffered_flush_and_rewind_unlocked(buffered *self)
909
240k
{
910
240k
    PyObject *res;
911
912
240k
    res = _bufferedwriter_flush_unlocked(self);
913
240k
    if (res == NULL)
914
0
        return NULL;
915
240k
    Py_DECREF(res);
916
917
240k
    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
240k
    Py_RETURN_NONE;
927
240k
}
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
240k
{
938
240k
    PyObject *res;
939
940
240k
    CHECK_INITIALIZED(self)
941
240k
    CHECK_CLOSED(self, "flush of closed file")
942
943
240k
    if (!ENTER_BUFFERED(self))
944
0
        return NULL;
945
240k
    res = buffered_flush_and_rewind_unlocked(self);
946
240k
    LEAVE_BUFFERED(self)
947
948
240k
    return res;
949
240k
}
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.67M
{
995
5.67M
    PyObject *res;
996
997
5.67M
    CHECK_INITIALIZED(self)
998
5.67M
    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.67M
    CHECK_CLOSED(self, "read of closed file")
1005
1006
5.67M
    if (n == -1) {
1007
        /* The number of bytes is unspecified, read until the end of stream */
1008
5.78k
        if (!ENTER_BUFFERED(self))
1009
0
            return NULL;
1010
5.78k
        res = _bufferedreader_read_all(self);
1011
5.78k
    }
1012
5.67M
    else {
1013
5.67M
        res = _bufferedreader_read_fast(self, n);
1014
5.67M
        if (res != Py_None)
1015
5.64M
            return res;
1016
29.7k
        Py_DECREF(res);
1017
29.7k
        if (!ENTER_BUFFERED(self))
1018
0
            return NULL;
1019
29.7k
        res = _bufferedreader_read_generic(self, n);
1020
29.7k
    }
1021
1022
35.5k
    LEAVE_BUFFERED(self)
1023
35.5k
    return res;
1024
5.67M
}
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.58k
{
1342
4.58k
    Py_off_t pos;
1343
1344
4.58k
    CHECK_INITIALIZED(self)
1345
4.58k
    pos = _buffered_raw_tell(self);
1346
4.58k
    if (pos == -1)
1347
0
        return NULL;
1348
4.58k
    pos -= RAW_OFFSET(self);
1349
1350
    // GH-95782
1351
4.58k
    if (pos < 0)
1352
0
        pos = 0;
1353
1354
4.58k
    return PyLong_FromOff_t(pos);
1355
4.58k
}
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.37M
{
1369
1.37M
    Py_off_t target, n;
1370
1.37M
    PyObject *res = NULL;
1371
1372
1.37M
    CHECK_INITIALIZED(self)
1373
1374
    /* Do some error checking instead of trusting OS 'seek()'
1375
    ** error detection, just in case.
1376
    */
1377
1.37M
    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.37M
#endif
1384
1.37M
        ) {
1385
0
        PyErr_Format(PyExc_ValueError,
1386
0
                     "whence value %d unsupported", whence);
1387
0
        return NULL;
1388
0
    }
1389
1390
1.37M
    CHECK_CLOSED(self, "seek of closed file")
1391
1392
1.37M
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
1393
1.37M
    if (_PyIOBase_check_seekable(state, self->raw, Py_True) == NULL) {
1394
0
        return NULL;
1395
0
    }
1396
1397
1.37M
    target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1398
1.37M
    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.37M
    if (((whence == 0) || (whence == 1)) && self->readable) {
1406
1.37M
        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.37M
        current = RAW_TELL(self);
1414
1.37M
        avail = READAHEAD(self);
1415
1.37M
        if (avail > 0) {
1416
1.36M
            Py_off_t offset;
1417
1.36M
            if (whence == 0)
1418
17
                offset = target - (current - RAW_OFFSET(self));
1419
1.36M
            else
1420
1.36M
                offset = target;
1421
1.36M
            if (offset >= -self->pos && offset <= avail) {
1422
1.36M
                self->pos += offset;
1423
1424
                // GH-95782
1425
1.36M
                if (current - avail + offset < 0)
1426
0
                    return PyLong_FromOff_t(0);
1427
1428
1.36M
                return PyLong_FromOff_t(current - avail + offset);
1429
1.36M
            }
1430
1.36M
        }
1431
1.37M
    }
1432
1433
7.11k
    if (!ENTER_BUFFERED(self))
1434
0
        return NULL;
1435
1436
    /* Fallback: invoke raw seek() method and clear buffer */
1437
7.11k
    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.11k
    if (whence == 1)
1446
7.11k
        target -= RAW_OFFSET(self);
1447
7.11k
    n = _buffered_raw_seek(self, target, whence);
1448
7.11k
    if (n == -1)
1449
5
        goto end;
1450
7.11k
    self->raw_pos = -1;
1451
7.11k
    res = PyLong_FromOff_t(n);
1452
7.11k
    if (res != NULL && self->readable)
1453
7.11k
        _bufferedreader_reset_buf(self);
1454
1455
7.11k
end:
1456
7.11k
    LEAVE_BUFFERED(self)
1457
7.11k
    return res;
1458
7.11k
}
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
53.3k
{
1584
53.3k
    self->read_end = -1;
1585
53.3k
}
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.6k
{
1600
10.6k
    self->ok = 0;
1601
10.6k
    self->detached = 0;
1602
1603
10.6k
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
1604
10.6k
    if (_PyIOBase_check_readable(state, raw, Py_True) == NULL) {
1605
0
        return -1;
1606
0
    }
1607
1608
10.6k
    Py_XSETREF(self->raw, Py_NewRef(raw));
1609
10.6k
    self->buffer_size = buffer_size;
1610
10.6k
    self->readable = 1;
1611
10.6k
    self->writable = 0;
1612
1613
10.6k
    if (_buffered_init(self) < 0)
1614
0
        return -1;
1615
10.6k
    _bufferedreader_reset_buf(self);
1616
1617
10.6k
    self->fast_closed_checks = (
1618
10.6k
        Py_IS_TYPE(self, state->PyBufferedReader_Type) &&
1619
10.6k
        Py_IS_TYPE(raw, state->PyFileIO_Type)
1620
10.6k
    );
1621
1622
10.6k
    self->ok = 1;
1623
10.6k
    return 0;
1624
10.6k
}
1625
1626
static Py_ssize_t
1627
_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
1628
34.1k
{
1629
34.1k
    Py_buffer buf;
1630
34.1k
    PyObject *memobj, *res;
1631
34.1k
    Py_ssize_t n;
1632
    /* NOTE: the buffer needn't be released as its object is NULL. */
1633
34.1k
    if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1634
0
        return -1;
1635
34.1k
    memobj = PyMemoryView_FromBuffer(&buf);
1636
34.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
34.1k
    do {
1644
34.1k
        res = PyObject_CallMethodOneArg(self->raw, &_Py_ID(readinto), memobj);
1645
34.1k
    } while (res == NULL && _PyIO_trap_eintr());
1646
34.1k
    Py_DECREF(memobj);
1647
34.1k
    if (res == NULL)
1648
4.48k
        return -1;
1649
29.6k
    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
29.6k
    n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1655
29.6k
    Py_DECREF(res);
1656
1657
29.6k
    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
29.6k
    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
29.6k
    if (n > 0 && self->abs_pos != -1)
1672
29.2k
        self->abs_pos += n;
1673
29.6k
    return n;
1674
29.6k
}
1675
1676
static Py_ssize_t
1677
_bufferedreader_fill_buffer(buffered *self)
1678
34.1k
{
1679
34.1k
    Py_ssize_t start, len, n;
1680
34.1k
    if (VALID_READ_BUFFER(self))
1681
34.0k
        start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1682
10
    else
1683
10
        start = 0;
1684
34.1k
    len = self->buffer_size - start;
1685
34.1k
    n = _bufferedreader_raw_read(self, self->buffer + start, len);
1686
34.1k
    if (n <= 0)
1687
4.83k
        return n;
1688
29.2k
    self->read_end = start + n;
1689
29.2k
    self->raw_pos = start + n;
1690
29.2k
    return n;
1691
34.1k
}
1692
1693
static PyObject *
1694
_bufferedreader_read_all(buffered *self)
1695
5.78k
{
1696
5.78k
    Py_ssize_t current_size;
1697
5.78k
    PyObject *res = NULL, *data = NULL, *tmp = NULL, *chunks = NULL, *readall;
1698
1699
    /* First copy what we have in the current buffer. */
1700
5.78k
    current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1701
5.78k
    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.78k
    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.78k
    _bufferedreader_reset_buf(self);
1716
1717
5.78k
    if (PyObject_GetOptionalAttr(self->raw, &_Py_ID(readall), &readall) < 0) {
1718
0
        goto cleanup;
1719
0
    }
1720
5.78k
    if (readall) {
1721
5.78k
        tmp = _PyObject_CallNoArgs(readall);
1722
5.78k
        Py_DECREF(readall);
1723
5.78k
        if (tmp == NULL)
1724
0
            goto cleanup;
1725
5.78k
        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.78k
        if (current_size == 0) {
1730
5.78k
            res = tmp;
1731
5.78k
        } else {
1732
0
            if (tmp != Py_None) {
1733
0
                PyBytes_Concat(&data, tmp);
1734
0
            }
1735
0
            res = data;
1736
0
        }
1737
5.78k
        goto cleanup;
1738
5.78k
    }
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.78k
cleanup:
1775
    /* res is either NULL or a borrowed ref */
1776
5.78k
    Py_XINCREF(res);
1777
5.78k
    Py_XDECREF(data);
1778
5.78k
    Py_XDECREF(tmp);
1779
5.78k
    Py_XDECREF(chunks);
1780
5.78k
    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.67M
{
1788
5.67M
    Py_ssize_t current_size;
1789
1790
5.67M
    current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1791
5.67M
    if (n <= current_size) {
1792
        /* Fast path: the data to read is fully buffered. */
1793
5.64M
        PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1794
5.64M
        if (res != NULL)
1795
5.64M
            self->pos += n;
1796
5.64M
        return res;
1797
5.64M
    }
1798
5.67M
    Py_RETURN_NONE;
1799
5.67M
}
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
29.7k
{
1807
29.7k
    Py_ssize_t current_size, remaining, written;
1808
1809
29.7k
    current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1810
29.7k
    if (n <= current_size)
1811
0
        return _bufferedreader_read_fast(self, n);
1812
1813
29.7k
    PyBytesWriter *writer = PyBytesWriter_Create(n);
1814
29.7k
    if (writer == NULL) {
1815
0
        goto error;
1816
0
    }
1817
29.7k
    char *out = PyBytesWriter_GetData(writer);
1818
1819
29.7k
    remaining = n;
1820
29.7k
    written = 0;
1821
29.7k
    if (current_size > 0) {
1822
4.13k
        memcpy(out, self->buffer + self->pos, current_size);
1823
4.13k
        remaining -= current_size;
1824
4.13k
        written += current_size;
1825
4.13k
        self->pos += current_size;
1826
4.13k
    }
1827
    /* Flush the write buffer if necessary */
1828
29.7k
    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
29.7k
    _bufferedreader_reset_buf(self);
1835
29.7k
    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
29.7k
        Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1839
29.7k
        if (r == 0)
1840
29.7k
            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
29.7k
    assert(remaining <= self->buffer_size);
1856
29.7k
    self->pos = 0;
1857
29.7k
    self->raw_pos = 0;
1858
29.7k
    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
34.0k
    while (remaining > 0 && self->read_end < self->buffer_size) {
1863
34.0k
        Py_ssize_t r = _bufferedreader_fill_buffer(self);
1864
34.0k
        if (r == -1)
1865
4.48k
            goto error;
1866
29.6k
        if (r == 0 || r == -2) {
1867
            /* EOF occurred or read() would block. */
1868
347
            if (r == 0 || written > 0) {
1869
347
                return PyBytesWriter_FinishWithSize(writer, written);
1870
347
            }
1871
0
            PyBytesWriter_Discard(writer);
1872
0
            Py_RETURN_NONE;
1873
347
        }
1874
29.2k
        if (remaining > r) {
1875
4.33k
            memcpy(out + written, self->buffer + self->pos, r);
1876
4.33k
            written += r;
1877
4.33k
            self->pos += r;
1878
4.33k
            remaining -= r;
1879
4.33k
        }
1880
24.9k
        else if (remaining > 0) {
1881
24.9k
            memcpy(out + written, self->buffer + self->pos, remaining);
1882
24.9k
            written += remaining;
1883
24.9k
            self->pos += remaining;
1884
24.9k
            remaining = 0;
1885
24.9k
        }
1886
29.2k
        if (remaining == 0)
1887
24.9k
            break;
1888
29.2k
    }
1889
1890
24.9k
    return PyBytesWriter_Finish(writer);
1891
1892
4.48k
error:
1893
4.48k
    PyBytesWriter_Discard(writer);
1894
4.48k
    return NULL;
1895
29.7k
}
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
259k
{
1931
259k
    self->write_pos = 0;
1932
259k
    self->write_end = -1;
1933
259k
}
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
18.8k
{
1952
18.8k
    self->ok = 0;
1953
18.8k
    self->detached = 0;
1954
1955
18.8k
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
1956
18.8k
    if (_PyIOBase_check_writable(state, raw, Py_True) == NULL) {
1957
0
        return -1;
1958
0
    }
1959
1960
18.8k
    Py_INCREF(raw);
1961
18.8k
    Py_XSETREF(self->raw, raw);
1962
18.8k
    self->readable = 0;
1963
18.8k
    self->writable = 1;
1964
1965
18.8k
    self->buffer_size = buffer_size;
1966
18.8k
    if (_buffered_init(self) < 0)
1967
0
        return -1;
1968
18.8k
    _bufferedwriter_reset_buf(self);
1969
18.8k
    self->pos = 0;
1970
1971
18.8k
    self->fast_closed_checks = (
1972
18.8k
        Py_IS_TYPE(self, state->PyBufferedWriter_Type) &&
1973
18.8k
        Py_IS_TYPE(raw, state->PyFileIO_Type)
1974
18.8k
    );
1975
1976
18.8k
    self->ok = 1;
1977
18.8k
    return 0;
1978
18.8k
}
1979
1980
static Py_ssize_t
1981
_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
1982
240k
{
1983
240k
    Py_buffer buf;
1984
240k
    PyObject *memobj, *res;
1985
240k
    Py_ssize_t n;
1986
240k
    int errnum;
1987
    /* NOTE: the buffer needn't be released as its object is NULL. */
1988
240k
    if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1989
0
        return -1;
1990
240k
    memobj = PyMemoryView_FromBuffer(&buf);
1991
240k
    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
240k
    do {
1999
240k
        errno = 0;
2000
240k
        res = PyObject_CallMethodOneArg(self->raw, &_Py_ID(write), memobj);
2001
240k
        errnum = errno;
2002
240k
    } while (res == NULL && _PyIO_trap_eintr());
2003
240k
    Py_DECREF(memobj);
2004
240k
    if (res == NULL)
2005
0
        return -1;
2006
240k
    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
240k
    n = PyNumber_AsSsize_t(res, PyExc_ValueError);
2015
240k
    Py_DECREF(res);
2016
240k
    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
240k
    if (n > 0 && self->abs_pos != -1)
2023
240k
        self->abs_pos += n;
2024
240k
    return n;
2025
240k
}
2026
2027
static PyObject *
2028
_bufferedwriter_flush_unlocked(buffered *self)
2029
240k
{
2030
240k
    Py_off_t n, rewind;
2031
2032
240k
    if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
2033
875
        goto end;
2034
    /* First, rewind */
2035
239k
    rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
2036
239k
    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
479k
    while (self->write_pos < self->write_end) {
2044
239k
        n = _bufferedwriter_raw_write(self,
2045
239k
            self->buffer + self->write_pos,
2046
239k
            Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
2047
239k
                             Py_off_t, Py_ssize_t));
2048
239k
        if (n == -1) {
2049
0
            goto error;
2050
0
        }
2051
239k
        else if (n == -2) {
2052
0
            _set_BlockingIOError("write could not complete without blocking",
2053
0
                                 0);
2054
0
            goto error;
2055
0
        }
2056
239k
        self->write_pos += n;
2057
239k
        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
239k
        if (PyErr_CheckSignals() < 0)
2062
0
            goto error;
2063
239k
    }
2064
2065
2066
240k
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
240k
    _bufferedwriter_reset_buf(self);
2077
240k
    Py_RETURN_NONE;
2078
2079
0
error:
2080
0
    return NULL;
2081
239k
}
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
240k
{
2094
240k
    PyObject *res = NULL;
2095
240k
    Py_ssize_t written, avail, remaining;
2096
240k
    Py_off_t offset;
2097
240k
    int r;
2098
2099
240k
    CHECK_INITIALIZED(self)
2100
2101
240k
    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
240k
    r = IS_CLOSED(self);
2107
240k
    if (r < 0) {
2108
0
        goto error;
2109
0
    }
2110
240k
    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
240k
    if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
2117
239k
        self->pos = 0;
2118
239k
        self->raw_pos = 0;
2119
239k
    }
2120
240k
    avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
2121
240k
    if (buffer->len <= avail && buffer->len < self->buffer_size) {
2122
239k
        memcpy(self->buffer + self->pos, buffer->buf, buffer->len);
2123
239k
        if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
2124
239k
            self->write_pos = self->pos;
2125
239k
        }
2126
239k
        ADJUST_POSITION(self, self->pos + buffer->len);
2127
239k
        if (self->pos > self->write_end)
2128
239k
            self->write_end = self->pos;
2129
239k
        written = buffer->len;
2130
239k
        goto end;
2131
239k
    }
2132
2133
    /* First write the current buffer */
2134
379
    res = _bufferedwriter_flush_unlocked(self);
2135
379
    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
379
    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
379
    offset = RAW_OFFSET(self);
2181
379
    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
379
    remaining = buffer->len;
2189
379
    written = 0;
2190
758
    while (remaining >= self->buffer_size) {
2191
379
        Py_ssize_t n = _bufferedwriter_raw_write(
2192
379
            self, (char *) buffer->buf + written, buffer->len - written);
2193
379
        if (n == -1) {
2194
0
            goto error;
2195
379
        } 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
379
        written += n;
2213
379
        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
379
        if (PyErr_CheckSignals() < 0)
2218
0
            goto error;
2219
379
    }
2220
379
    if (self->readable)
2221
0
        _bufferedreader_reset_buf(self);
2222
379
    if (remaining > 0) {
2223
0
        memcpy(self->buffer, (char *) buffer->buf + written, remaining);
2224
0
        written += remaining;
2225
0
    }
2226
379
    self->write_pos = 0;
2227
    /* TODO: sanity check (remaining >= 0) */
2228
379
    self->write_end = remaining;
2229
379
    ADJUST_POSITION(self, remaining);
2230
379
    self->raw_pos = 0;
2231
2232
240k
end:
2233
240k
    res = PyLong_FromSsize_t(written);
2234
2235
240k
error:
2236
240k
    LEAVE_BUFFERED(self)
2237
240k
    return res;
2238
240k
}
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
};