Coverage Report

Created: 2026-01-17 06:16

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
84.4k
#define buffered_CAST(op)   ((buffered *)(op))
268
269
/*
270
    Implementation notes:
271
272
    * BufferedReader, BufferedWriter and BufferedRandom try to share most
273
      methods (this is helped by the members `readable` and `writable`, which
274
      are initialized in the respective constructors)
275
    * They also share a single buffer for reading and writing. This enables
276
      interleaved reads and writes without flushing. It also makes the logic
277
      a bit trickier to get right.
278
    * The absolute position of the raw stream is cached, if possible, in the
279
      `abs_pos` member. It must be updated every time an operation is done
280
      on the raw stream. If not sure, it can be reinitialized by calling
281
      _buffered_raw_tell(), which queries the raw stream (_buffered_raw_seek()
282
      also does it). To read it, use RAW_TELL().
283
    * Three helpers, _bufferedreader_raw_read, _bufferedwriter_raw_write and
284
      _bufferedwriter_flush_unlocked do a lot of useful housekeeping.
285
286
    NOTE: we should try to maintain block alignment of reads and writes to the
287
    raw stream (according to the buffer size), but for now it is only done
288
    in read() and friends.
289
290
*/
291
292
/* These macros protect the buffered object against concurrent operations. */
293
294
static int
295
_enter_buffered_busy(buffered *self)
296
0
{
297
0
    int relax_locking;
298
0
    PyLockStatus st;
299
0
    if (self->owner == PyThread_get_thread_ident()) {
300
0
        PyErr_Format(PyExc_RuntimeError,
301
0
                     "reentrant call inside %R", self);
302
0
        return 0;
303
0
    }
304
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
305
0
    relax_locking = _Py_IsInterpreterFinalizing(interp);
306
0
    Py_BEGIN_ALLOW_THREADS
307
0
    if (!relax_locking)
308
0
        st = PyThread_acquire_lock(self->lock, 1);
309
0
    else {
310
        /* When finalizing, we don't want a deadlock to happen with daemon
311
         * threads abruptly shut down while they owned the lock.
312
         * Therefore, only wait for a grace period (1 s.).
313
         * Note that non-daemon threads have already exited here, so this
314
         * shouldn't affect carefully written threaded I/O code.
315
         */
316
0
        st = PyThread_acquire_lock_timed(self->lock, (PY_TIMEOUT_T)1e6, 0);
317
0
    }
318
0
    Py_END_ALLOW_THREADS
319
0
    if (relax_locking && st != PY_LOCK_ACQUIRED) {
320
0
        PyObject *ascii = PyObject_ASCII((PyObject*)self);
321
0
        _Py_FatalErrorFormat(__func__,
322
0
            "could not acquire lock for %s at interpreter "
323
0
            "shutdown, possibly due to daemon threads",
324
0
            ascii ? PyUnicode_AsUTF8(ascii) : "<ascii(self) failed>");
325
0
    }
326
0
    return 1;
327
0
}
328
329
#define ENTER_BUFFERED(self) \
330
641k
    ( (PyThread_acquire_lock(self->lock, 0) ? \
331
641k
       1 : _enter_buffered_busy(self)) \
332
641k
     && (self->owner = PyThread_get_thread_ident(), 1) )
333
334
#define LEAVE_BUFFERED(self) \
335
641k
    do { \
336
641k
        self->owner = 0; \
337
641k
        PyThread_release_lock(self->lock); \
338
641k
    } while(0);
339
340
#define CHECK_INITIALIZED(self) \
341
12.9M
    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
9.64M
    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
10.1M
    (!self->buffer ? 1 : \
366
10.1M
    (self->fast_closed_checks \
367
10.1M
     ? _PyFileIO_closed(self->raw) \
368
10.1M
     : buffered_closed(self)))
369
370
#define CHECK_CLOSED(self, error_msg) \
371
9.90M
    do { \
372
9.90M
        int _closed = IS_CLOSED(self); \
373
9.90M
        if (_closed < 0) { \
374
0
            return NULL; \
375
0
        } \
376
9.90M
        if (_closed && \
377
9.90M
            (Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t) == 0)) \
378
9.90M
        { \
379
0
            PyErr_SetString(PyExc_ValueError, error_msg); \
380
0
            return NULL; \
381
0
        } \
382
9.90M
    } while (0);
383
384
#define VALID_READ_BUFFER(self) \
385
4.26M
    (self->readable && self->read_end != -1)
386
387
#define VALID_WRITE_BUFFER(self) \
388
1.54M
    (self->writable && self->write_end != -1)
389
390
#define ADJUST_POSITION(self, _new_pos) \
391
254k
    do { \
392
254k
        self->pos = _new_pos; \
393
254k
        if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
394
254k
            self->read_end = self->pos; \
395
254k
    } while(0)
396
397
#define READAHEAD(self) \
398
2.67M
    ((self->readable && VALID_READ_BUFFER(self)) \
399
2.67M
        ? (self->read_end - self->pos) : 0)
400
401
#define RAW_OFFSET(self) \
402
270k
    (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
403
270k
        && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
404
405
#define RAW_TELL(self) \
406
2.67M
    (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
407
408
#define MINUS_LAST_BLOCK(self, size) \
409
35.3k
    (self->buffer_mask ? \
410
35.3k
        (size & ~self->buffer_mask) : \
411
35.3k
        (self->buffer_size * (size / self->buffer_size)))
412
413
414
static int
415
buffered_clear(PyObject *op)
416
39.9k
{
417
39.9k
    buffered *self = buffered_CAST(op);
418
39.9k
    self->ok = 0;
419
39.9k
    Py_CLEAR(self->raw);
420
39.9k
    Py_CLEAR(self->dict);
421
39.9k
    return 0;
422
39.9k
}
423
424
static void
425
buffered_dealloc(PyObject *op)
426
39.9k
{
427
39.9k
    buffered *self = buffered_CAST(op);
428
39.9k
    PyTypeObject *tp = Py_TYPE(self);
429
39.9k
    self->finalizing = 1;
430
39.9k
    if (_PyIOBase_finalize(op) < 0)
431
0
        return;
432
39.9k
    _PyObject_GC_UNTRACK(self);
433
39.9k
    self->ok = 0;
434
39.9k
    FT_CLEAR_WEAKREFS(op, self->weakreflist);
435
39.9k
    if (self->buffer) {
436
0
        PyMem_Free(self->buffer);
437
0
        self->buffer = NULL;
438
0
    }
439
39.9k
    if (self->lock) {
440
39.9k
        PyThread_free_lock(self->lock);
441
39.9k
        self->lock = NULL;
442
39.9k
    }
443
39.9k
    (void)buffered_clear(op);
444
39.9k
    tp->tp_free(self);
445
39.9k
    Py_DECREF(tp);
446
39.9k
}
447
448
/*[clinic input]
449
@critical_section
450
_io._Buffered.__sizeof__
451
[clinic start generated code]*/
452
453
static PyObject *
454
_io__Buffered___sizeof___impl(buffered *self)
455
/*[clinic end generated code: output=0231ef7f5053134e input=07a32d578073ea64]*/
456
0
{
457
0
    size_t res = _PyObject_SIZE(Py_TYPE(self));
458
0
    if (self->buffer) {
459
0
        res += (size_t)self->buffer_size;
460
0
    }
461
0
    return PyLong_FromSize_t(res);
462
0
}
463
464
static int
465
buffered_traverse(PyObject *op, visitproc visit, void *arg)
466
4.62k
{
467
4.62k
    buffered *self = buffered_CAST(op);
468
4.62k
    Py_VISIT(Py_TYPE(self));
469
4.62k
    Py_VISIT(self->raw);
470
4.62k
    Py_VISIT(self->dict);
471
4.62k
    return 0;
472
4.62k
}
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
0
{
489
0
    if (self->ok && self->raw) {
490
0
        PyObject *r;
491
0
        r = PyObject_CallMethodOneArg(self->raw, &_Py_ID(_dealloc_warn), source);
492
0
        if (r)
493
0
            Py_DECREF(r);
494
0
        else
495
0
            PyErr_Clear();
496
0
    }
497
0
    Py_RETURN_NONE;
498
0
}
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
2.68M
{
516
2.68M
    CHECK_INITIALIZED(self)
517
2.68M
    return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(flush));
518
2.68M
}
519
520
static int
521
buffered_closed(buffered *self)
522
9.64M
{
523
9.64M
    int closed;
524
9.64M
    PyObject *res;
525
9.64M
    CHECK_INITIALIZED_INT(self)
526
9.64M
    res = PyObject_GetAttr(self->raw, &_Py_ID(closed));
527
9.64M
    if (res == NULL)
528
0
        return -1;
529
9.64M
    closed = PyObject_IsTrue(res);
530
9.64M
    Py_DECREF(res);
531
9.64M
    return closed;
532
9.64M
}
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
77.5k
{
544
77.5k
    CHECK_INITIALIZED(self)
545
77.5k
    return PyObject_GetAttr(self->raw, &_Py_ID(closed));
546
77.5k
}
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
39.9k
{
557
39.9k
    PyObject *res = NULL;
558
39.9k
    int r;
559
560
39.9k
    CHECK_INITIALIZED(self)
561
39.9k
    if (!ENTER_BUFFERED(self)) {
562
0
        return NULL;
563
0
    }
564
    /* gh-138720: Use IS_CLOSED to match flush CHECK_CLOSED. */
565
39.9k
    r = IS_CLOSED(self);
566
39.9k
    if (r < 0)
567
0
        goto end;
568
39.9k
    if (r > 0) {
569
0
        res = Py_NewRef(Py_None);
570
0
        goto end;
571
0
    }
572
573
39.9k
    if (self->finalizing) {
574
0
        PyObject *r = _io__Buffered__dealloc_warn_impl(self, (PyObject *)self);
575
0
        if (r)
576
0
            Py_DECREF(r);
577
0
        else
578
0
            PyErr_Clear();
579
0
    }
580
    /* flush() will most probably re-take the lock, so drop it first */
581
39.9k
    LEAVE_BUFFERED(self)
582
39.9k
    r = _PyFile_Flush((PyObject *)self);
583
39.9k
    if (!ENTER_BUFFERED(self)) {
584
0
        return NULL;
585
0
    }
586
39.9k
    PyObject *exc = NULL;
587
39.9k
    if (r < 0) {
588
0
        exc = PyErr_GetRaisedException();
589
0
    }
590
591
39.9k
    res = PyObject_CallMethodNoArgs(self->raw, &_Py_ID(close));
592
593
39.9k
    if (self->buffer) {
594
39.9k
        PyMem_Free(self->buffer);
595
39.9k
        self->buffer = NULL;
596
39.9k
    }
597
598
39.9k
    if (exc != NULL) {
599
0
        _PyErr_ChainExceptions1(exc);
600
0
        Py_CLEAR(res);
601
0
    }
602
603
39.9k
    self->read_end = 0;
604
39.9k
    self->pos = 0;
605
606
39.9k
end:
607
39.9k
    LEAVE_BUFFERED(self)
608
39.9k
    return res;
609
39.9k
}
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
84
{
643
84
    CHECK_INITIALIZED(self)
644
84
    return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(seekable));
645
84
}
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
28
{
656
28
    CHECK_INITIALIZED(self)
657
28
    return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(readable));
658
28
}
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
56
{
669
56
    CHECK_INITIALIZED(self)
670
56
    return PyObject_CallMethodNoArgs(self->raw, &_Py_ID(writable));
671
56
}
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
0
{
684
0
    CHECK_INITIALIZED(self)
685
0
    return PyObject_GetAttr(self->raw, &_Py_ID(name));
686
0
}
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
0
{
698
0
    CHECK_INITIALIZED(self)
699
0
    return PyObject_GetAttr(self->raw, &_Py_ID(mode));
700
0
}
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
44.7k
{
786
44.7k
    Py_off_t n;
787
44.7k
    PyObject *res;
788
44.7k
    res = PyObject_CallMethodNoArgs(self->raw, &_Py_ID(tell));
789
44.7k
    if (res == NULL)
790
0
        return -1;
791
44.7k
    n = PyNumber_AsOff_t(res, PyExc_ValueError);
792
44.7k
    Py_DECREF(res);
793
44.7k
    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
44.7k
    self->abs_pos = n;
801
44.7k
    return n;
802
44.7k
}
803
804
static Py_off_t
805
_buffered_raw_seek(buffered *self, Py_off_t target, int whence)
806
11.2k
{
807
11.2k
    PyObject *res, *posobj, *whenceobj;
808
11.2k
    Py_off_t n;
809
810
11.2k
    posobj = PyLong_FromOff_t(target);
811
11.2k
    if (posobj == NULL)
812
0
        return -1;
813
11.2k
    whenceobj = PyLong_FromLong(whence);
814
11.2k
    if (whenceobj == NULL) {
815
0
        Py_DECREF(posobj);
816
0
        return -1;
817
0
    }
818
11.2k
    res = PyObject_CallMethodObjArgs(self->raw, &_Py_ID(seek),
819
11.2k
                                     posobj, whenceobj, NULL);
820
11.2k
    Py_DECREF(posobj);
821
11.2k
    Py_DECREF(whenceobj);
822
11.2k
    if (res == NULL)
823
0
        return -1;
824
11.2k
    n = PyNumber_AsOff_t(res, PyExc_ValueError);
825
11.2k
    Py_DECREF(res);
826
11.2k
    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
11.2k
    self->abs_pos = n;
834
11.2k
    return n;
835
11.2k
}
836
837
static int
838
_buffered_init(buffered *self)
839
40.0k
{
840
40.0k
    Py_ssize_t n;
841
40.0k
    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
40.0k
    if (self->buffer)
847
0
        PyMem_Free(self->buffer);
848
40.0k
    self->buffer = PyMem_Malloc(self->buffer_size);
849
40.0k
    if (self->buffer == NULL) {
850
0
        PyErr_NoMemory();
851
0
        return -1;
852
0
    }
853
40.0k
    if (self->lock)
854
0
        PyThread_free_lock(self->lock);
855
40.0k
    self->lock = PyThread_allocate_lock();
856
40.0k
    if (self->lock == NULL) {
857
0
        PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
858
0
        return -1;
859
0
    }
860
40.0k
    self->owner = 0;
861
    /* Find out whether buffer_size is a power of 2 */
862
    /* XXX is this optimization useful? */
863
720k
    for (n = self->buffer_size - 1; n & 1; n >>= 1)
864
680k
        ;
865
40.0k
    if (n == 0)
866
40.0k
        self->buffer_mask = self->buffer_size - 1;
867
0
    else
868
0
        self->buffer_mask = 0;
869
40.0k
    if (_buffered_raw_tell(self) == -1)
870
0
        PyErr_Clear();
871
40.0k
    return 0;
872
40.0k
}
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
6.03k
{
881
6.03k
    if (!PyErr_ExceptionMatches(PyExc_OSError)) {
882
1.93k
        return 0;
883
1.93k
    }
884
4.09k
    PyObject *exc = PyErr_GetRaisedException();
885
4.09k
    PyOSErrorObject *env_err = (PyOSErrorObject *)exc;
886
4.09k
    assert(env_err != NULL);
887
4.09k
    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
4.09k
    PyErr_SetRaisedException(exc);
900
4.09k
    return 0;
901
4.09k
}
902
903
/*
904
 * Shared methods and wrappers
905
 */
906
907
static PyObject *
908
buffered_flush_and_rewind_unlocked(buffered *self)
909
254k
{
910
254k
    PyObject *res;
911
912
254k
    res = _bufferedwriter_flush_unlocked(self);
913
254k
    if (res == NULL)
914
0
        return NULL;
915
254k
    Py_DECREF(res);
916
917
254k
    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
254k
    Py_RETURN_NONE;
927
254k
}
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
254k
{
938
254k
    PyObject *res;
939
940
254k
    CHECK_INITIALIZED(self)
941
254k
    CHECK_CLOSED(self, "flush of closed file")
942
943
254k
    if (!ENTER_BUFFERED(self))
944
0
        return NULL;
945
254k
    res = buffered_flush_and_rewind_unlocked(self);
946
254k
    LEAVE_BUFFERED(self)
947
948
254k
    return res;
949
254k
}
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
6.97M
{
995
6.97M
    PyObject *res;
996
997
6.97M
    CHECK_INITIALIZED(self)
998
6.97M
    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
6.97M
    CHECK_CLOSED(self, "read of closed file")
1005
1006
6.97M
    if (n == -1) {
1007
        /* The number of bytes is unspecified, read until the end of stream */
1008
6.11k
        if (!ENTER_BUFFERED(self))
1009
0
            return NULL;
1010
6.11k
        res = _bufferedreader_read_all(self);
1011
6.11k
    }
1012
6.97M
    else {
1013
6.97M
        res = _bufferedreader_read_fast(self, n);
1014
6.97M
        if (res != Py_None)
1015
6.93M
            return res;
1016
35.3k
        Py_DECREF(res);
1017
35.3k
        if (!ENTER_BUFFERED(self))
1018
0
            return NULL;
1019
35.3k
        res = _bufferedreader_read_generic(self, n);
1020
35.3k
    }
1021
1022
41.4k
    LEAVE_BUFFERED(self)
1023
41.4k
    return res;
1024
6.97M
}
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
0
{
1037
0
    CHECK_INITIALIZED(self)
1038
0
    if (n < 0) {
1039
0
        n = self->buffer_size;
1040
0
    }
1041
1042
0
    CHECK_CLOSED(self, "read of closed file")
1043
1044
0
    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
0
    Py_ssize_t have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1052
0
    if (have > 0) {
1053
0
        n = Py_MIN(have, n);
1054
0
        PyObject *res = _bufferedreader_read_fast(self, n);
1055
0
        assert(res != Py_None);
1056
0
        return res;
1057
0
    }
1058
1059
0
    if (!ENTER_BUFFERED(self)) {
1060
0
        return NULL;
1061
0
    }
1062
1063
    /* Flush the write buffer if necessary */
1064
0
    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
0
    _bufferedreader_reset_buf(self);
1073
1074
0
    PyBytesWriter *writer = PyBytesWriter_Create(n);
1075
0
    if (writer == NULL) {
1076
0
        return NULL;
1077
0
    }
1078
1079
0
    Py_ssize_t r = _bufferedreader_raw_read(self,
1080
0
                                            PyBytesWriter_GetData(writer), n);
1081
0
    LEAVE_BUFFERED(self)
1082
0
    if (r == -1) {
1083
0
        PyBytesWriter_Discard(writer);
1084
0
        return NULL;
1085
0
    }
1086
0
    if (r == -2) {
1087
0
        r = 0;
1088
0
    }
1089
1090
0
    return PyBytesWriter_FinishWithSize(writer, r);
1091
0
}
1092
1093
static PyObject *
1094
_buffered_readinto_generic(buffered *self, Py_buffer *buffer, char readinto1)
1095
0
{
1096
0
    Py_ssize_t n, written = 0, remaining;
1097
0
    PyObject *res = NULL;
1098
1099
0
    CHECK_INITIALIZED(self)
1100
0
    CHECK_CLOSED(self, "readinto of closed file")
1101
1102
0
    n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1103
0
    if (n > 0) {
1104
0
        if (n >= buffer->len) {
1105
0
            memcpy(buffer->buf, self->buffer + self->pos, buffer->len);
1106
0
            self->pos += buffer->len;
1107
0
            return PyLong_FromSsize_t(buffer->len);
1108
0
        }
1109
0
        memcpy(buffer->buf, self->buffer + self->pos, n);
1110
0
        self->pos += n;
1111
0
        written = n;
1112
0
    }
1113
1114
0
    if (!ENTER_BUFFERED(self))
1115
0
        return NULL;
1116
1117
0
    if (self->writable) {
1118
0
        res = buffered_flush_and_rewind_unlocked(self);
1119
0
        if (res == NULL)
1120
0
            goto end;
1121
0
        Py_CLEAR(res);
1122
0
    }
1123
1124
0
    _bufferedreader_reset_buf(self);
1125
0
    self->pos = 0;
1126
1127
0
    for (remaining = buffer->len - written;
1128
0
         remaining > 0;
1129
0
         written += n, remaining -= n) {
1130
        /* If remaining bytes is larger than internal buffer size, copy
1131
         * directly into caller's buffer. */
1132
0
        if (remaining > self->buffer_size) {
1133
0
            n = _bufferedreader_raw_read(self, (char *) buffer->buf + written,
1134
0
                                         remaining);
1135
0
        }
1136
1137
        /* In readinto1 mode, we do not want to fill the internal
1138
           buffer if we already have some data to return */
1139
0
        else if (!(readinto1 && written)) {
1140
0
            n = _bufferedreader_fill_buffer(self);
1141
0
            if (n > 0) {
1142
0
                if (n > remaining)
1143
0
                    n = remaining;
1144
0
                memcpy((char *) buffer->buf + written,
1145
0
                       self->buffer + self->pos, n);
1146
0
                self->pos += n;
1147
0
                continue; /* short circuit */
1148
0
            }
1149
0
        }
1150
0
        else
1151
0
            n = 0;
1152
1153
0
        if (n == 0 || (n == -2 && written > 0))
1154
0
            break;
1155
0
        if (n < 0) {
1156
0
            if (n == -2) {
1157
0
                res = Py_NewRef(Py_None);
1158
0
            }
1159
0
            goto end;
1160
0
        }
1161
1162
        /* At most one read in readinto1 mode */
1163
0
        if (readinto1) {
1164
0
            written += n;
1165
0
            break;
1166
0
        }
1167
0
    }
1168
0
    res = PyLong_FromSsize_t(written);
1169
1170
0
end:
1171
0
    LEAVE_BUFFERED(self);
1172
0
    return res;
1173
0
}
1174
1175
/*[clinic input]
1176
@critical_section
1177
_io._Buffered.readinto
1178
    buffer: Py_buffer(accept={rwbuffer})
1179
    /
1180
[clinic start generated code]*/
1181
1182
static PyObject *
1183
_io__Buffered_readinto_impl(buffered *self, Py_buffer *buffer)
1184
/*[clinic end generated code: output=bcb376580b1d8170 input=777c33e7adaa2bcd]*/
1185
0
{
1186
0
    return _buffered_readinto_generic(self, buffer, 0);
1187
0
}
1188
1189
/*[clinic input]
1190
@critical_section
1191
_io._Buffered.readinto1
1192
    buffer: Py_buffer(accept={rwbuffer})
1193
    /
1194
[clinic start generated code]*/
1195
1196
static PyObject *
1197
_io__Buffered_readinto1_impl(buffered *self, Py_buffer *buffer)
1198
/*[clinic end generated code: output=6e5c6ac5868205d6 input=ef03cc5fc92a6895]*/
1199
0
{
1200
0
    return _buffered_readinto_generic(self, buffer, 1);
1201
0
}
1202
1203
1204
static PyObject *
1205
_buffered_readline(buffered *self, Py_ssize_t limit)
1206
0
{
1207
0
    PyObject *res = NULL;
1208
0
    PyObject *chunks = NULL;
1209
0
    Py_ssize_t n;
1210
0
    const char *start, *s, *end;
1211
1212
0
    CHECK_CLOSED(self, "readline of closed file")
1213
1214
    /* First, try to find a line in the buffer. This can run unlocked because
1215
       the calls to the C API are simple enough that they can't trigger
1216
       any thread switch. */
1217
0
    n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1218
0
    if (limit >= 0 && n > limit)
1219
0
        n = limit;
1220
0
    start = self->buffer + self->pos;
1221
0
    s = memchr(start, '\n', n);
1222
0
    if (s != NULL) {
1223
0
        res = PyBytes_FromStringAndSize(start, s - start + 1);
1224
0
        if (res != NULL)
1225
0
            self->pos += s - start + 1;
1226
0
        goto end_unlocked;
1227
0
    }
1228
0
    if (n == limit) {
1229
0
        res = PyBytes_FromStringAndSize(start, n);
1230
0
        if (res != NULL)
1231
0
            self->pos += n;
1232
0
        goto end_unlocked;
1233
0
    }
1234
1235
0
    if (!ENTER_BUFFERED(self))
1236
0
        goto end_unlocked;
1237
1238
    /* Now we try to get some more from the raw stream */
1239
0
    chunks = PyList_New(0);
1240
0
    if (chunks == NULL)
1241
0
        goto end;
1242
0
    if (n > 0) {
1243
0
        res = PyBytes_FromStringAndSize(start, n);
1244
0
        if (res == NULL)
1245
0
            goto end;
1246
0
        if (PyList_Append(chunks, res) < 0) {
1247
0
            Py_CLEAR(res);
1248
0
            goto end;
1249
0
        }
1250
0
        Py_CLEAR(res);
1251
0
        self->pos += n;
1252
0
        if (limit >= 0)
1253
0
            limit -= n;
1254
0
    }
1255
0
    if (self->writable) {
1256
0
        PyObject *r = buffered_flush_and_rewind_unlocked(self);
1257
0
        if (r == NULL)
1258
0
            goto end;
1259
0
        Py_DECREF(r);
1260
0
    }
1261
1262
0
    for (;;) {
1263
0
        _bufferedreader_reset_buf(self);
1264
0
        n = _bufferedreader_fill_buffer(self);
1265
0
        if (n == -1)
1266
0
            goto end;
1267
0
        if (n <= 0)
1268
0
            break;
1269
0
        if (limit >= 0 && n > limit)
1270
0
            n = limit;
1271
0
        start = self->buffer;
1272
0
        end = start + n;
1273
0
        s = start;
1274
0
        while (s < end) {
1275
0
            if (*s++ == '\n') {
1276
0
                res = PyBytes_FromStringAndSize(start, s - start);
1277
0
                if (res == NULL)
1278
0
                    goto end;
1279
0
                self->pos = s - start;
1280
0
                goto found;
1281
0
            }
1282
0
        }
1283
0
        res = PyBytes_FromStringAndSize(start, n);
1284
0
        if (res == NULL)
1285
0
            goto end;
1286
0
        if (n == limit) {
1287
0
            self->pos = n;
1288
0
            break;
1289
0
        }
1290
0
        if (PyList_Append(chunks, res) < 0) {
1291
0
            Py_CLEAR(res);
1292
0
            goto end;
1293
0
        }
1294
0
        Py_CLEAR(res);
1295
0
        if (limit >= 0)
1296
0
            limit -= n;
1297
0
    }
1298
0
found:
1299
0
    if (res != NULL && PyList_Append(chunks, res) < 0) {
1300
0
        Py_CLEAR(res);
1301
0
        goto end;
1302
0
    }
1303
0
    Py_XSETREF(res, PyBytes_Join((PyObject *)&_Py_SINGLETON(bytes_empty), chunks));
1304
1305
0
end:
1306
0
    LEAVE_BUFFERED(self)
1307
0
end_unlocked:
1308
0
    Py_XDECREF(chunks);
1309
0
    return res;
1310
0
}
1311
1312
/*[clinic input]
1313
@critical_section
1314
_io._Buffered.readline
1315
    size: Py_ssize_t(accept={int, NoneType}) = -1
1316
    /
1317
[clinic start generated code]*/
1318
1319
static PyObject *
1320
_io__Buffered_readline_impl(buffered *self, Py_ssize_t size)
1321
/*[clinic end generated code: output=24dd2aa6e33be83c input=e81ca5abd4280776]*/
1322
0
{
1323
0
    CHECK_INITIALIZED(self)
1324
0
    return _buffered_readline(self, size);
1325
0
}
1326
1327
1328
/*[clinic input]
1329
@critical_section
1330
_io._Buffered.tell
1331
[clinic start generated code]*/
1332
1333
static PyObject *
1334
_io__Buffered_tell_impl(buffered *self)
1335
/*[clinic end generated code: output=386972ae84716c1e input=ab12e67d8abcb42f]*/
1336
4.77k
{
1337
4.77k
    Py_off_t pos;
1338
1339
4.77k
    CHECK_INITIALIZED(self)
1340
4.77k
    pos = _buffered_raw_tell(self);
1341
4.77k
    if (pos == -1)
1342
0
        return NULL;
1343
4.77k
    pos -= RAW_OFFSET(self);
1344
1345
    // GH-95782
1346
4.77k
    if (pos < 0)
1347
0
        pos = 0;
1348
1349
4.77k
    return PyLong_FromOff_t(pos);
1350
4.77k
}
1351
1352
/*[clinic input]
1353
@critical_section
1354
_io._Buffered.seek
1355
    target as targetobj: object
1356
    whence: int = 0
1357
    /
1358
[clinic start generated code]*/
1359
1360
static PyObject *
1361
_io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence)
1362
/*[clinic end generated code: output=7ae0e8dc46efdefb input=b5a12be70e0ad07b]*/
1363
2.67M
{
1364
2.67M
    Py_off_t target, n;
1365
2.67M
    PyObject *res = NULL;
1366
1367
2.67M
    CHECK_INITIALIZED(self)
1368
1369
    /* Do some error checking instead of trusting OS 'seek()'
1370
    ** error detection, just in case.
1371
    */
1372
2.67M
    if ((whence < 0 || whence >2)
1373
0
#ifdef SEEK_HOLE
1374
0
        && (whence != SEEK_HOLE)
1375
0
#endif
1376
0
#ifdef SEEK_DATA
1377
0
        && (whence != SEEK_DATA)
1378
2.67M
#endif
1379
2.67M
        ) {
1380
0
        PyErr_Format(PyExc_ValueError,
1381
0
                     "whence value %d unsupported", whence);
1382
0
        return NULL;
1383
0
    }
1384
1385
2.67M
    CHECK_CLOSED(self, "seek of closed file")
1386
1387
2.67M
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
1388
2.67M
    if (_PyIOBase_check_seekable(state, self->raw, Py_True) == NULL) {
1389
0
        return NULL;
1390
0
    }
1391
1392
2.67M
    target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1393
2.67M
    if (target == -1 && PyErr_Occurred())
1394
0
        return NULL;
1395
1396
    /* SEEK_SET and SEEK_CUR are special because we could seek inside the
1397
       buffer. Other whence values must be managed without this optimization.
1398
       Some Operating Systems can provide additional values, like
1399
       SEEK_HOLE/SEEK_DATA. */
1400
2.67M
    if (((whence == 0) || (whence == 1)) && self->readable) {
1401
2.67M
        Py_off_t current, avail;
1402
        /* Check if seeking leaves us inside the current buffer,
1403
           so as to return quickly if possible. Also, we needn't take the
1404
           lock in this fast path.
1405
           Don't know how to do that when whence == 2, though. */
1406
        /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1407
           state at this point. */
1408
2.67M
        current = RAW_TELL(self);
1409
2.67M
        avail = READAHEAD(self);
1410
2.67M
        if (avail > 0) {
1411
2.66M
            Py_off_t offset;
1412
2.66M
            if (whence == 0)
1413
0
                offset = target - (current - RAW_OFFSET(self));
1414
2.66M
            else
1415
2.66M
                offset = target;
1416
2.66M
            if (offset >= -self->pos && offset <= avail) {
1417
2.66M
                self->pos += offset;
1418
1419
                // GH-95782
1420
2.66M
                if (current - avail + offset < 0)
1421
0
                    return PyLong_FromOff_t(0);
1422
1423
2.66M
                return PyLong_FromOff_t(current - avail + offset);
1424
2.66M
            }
1425
2.66M
        }
1426
2.67M
    }
1427
1428
11.2k
    if (!ENTER_BUFFERED(self))
1429
0
        return NULL;
1430
1431
    /* Fallback: invoke raw seek() method and clear buffer */
1432
11.2k
    if (self->writable) {
1433
0
        res = _bufferedwriter_flush_unlocked(self);
1434
0
        if (res == NULL)
1435
0
            goto end;
1436
0
        Py_CLEAR(res);
1437
0
    }
1438
1439
    /* TODO: align on block boundary and read buffer if needed? */
1440
11.2k
    if (whence == 1)
1441
11.2k
        target -= RAW_OFFSET(self);
1442
11.2k
    n = _buffered_raw_seek(self, target, whence);
1443
11.2k
    if (n == -1)
1444
0
        goto end;
1445
11.2k
    self->raw_pos = -1;
1446
11.2k
    res = PyLong_FromOff_t(n);
1447
11.2k
    if (res != NULL && self->readable)
1448
11.2k
        _bufferedreader_reset_buf(self);
1449
1450
11.2k
end:
1451
11.2k
    LEAVE_BUFFERED(self)
1452
11.2k
    return res;
1453
11.2k
}
1454
1455
/*[clinic input]
1456
@critical_section
1457
_io._Buffered.truncate
1458
    cls: defining_class
1459
    pos: object = None
1460
    /
1461
[clinic start generated code]*/
1462
1463
static PyObject *
1464
_io__Buffered_truncate_impl(buffered *self, PyTypeObject *cls, PyObject *pos)
1465
/*[clinic end generated code: output=fe3882fbffe79f1a input=e3cbf794575bd794]*/
1466
0
{
1467
0
    PyObject *res = NULL;
1468
1469
0
    CHECK_INITIALIZED(self)
1470
0
    CHECK_CLOSED(self, "truncate of closed file")
1471
0
    if (!self->writable) {
1472
0
        _PyIO_State *state = get_io_state_by_cls(cls);
1473
0
        return bufferediobase_unsupported(state, "truncate");
1474
0
    }
1475
0
    if (!ENTER_BUFFERED(self))
1476
0
        return NULL;
1477
1478
0
    res = buffered_flush_and_rewind_unlocked(self);
1479
0
    if (res == NULL) {
1480
0
        goto end;
1481
0
    }
1482
0
    Py_CLEAR(res);
1483
1484
0
    res = PyObject_CallMethodOneArg(self->raw, &_Py_ID(truncate), pos);
1485
0
    if (res == NULL)
1486
0
        goto end;
1487
    /* Reset cached position */
1488
0
    if (_buffered_raw_tell(self) == -1)
1489
0
        PyErr_Clear();
1490
1491
0
end:
1492
0
    LEAVE_BUFFERED(self)
1493
0
    return res;
1494
0
}
1495
1496
static PyObject *
1497
buffered_iternext(PyObject *op)
1498
0
{
1499
0
    buffered *self = buffered_CAST(op);
1500
0
    PyObject *line;
1501
0
    PyTypeObject *tp;
1502
1503
0
    CHECK_INITIALIZED(self);
1504
1505
0
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
1506
0
    tp = Py_TYPE(self);
1507
0
    if (Py_IS_TYPE(tp, state->PyBufferedReader_Type) ||
1508
0
        Py_IS_TYPE(tp, state->PyBufferedRandom_Type))
1509
0
    {
1510
        /* Skip method call overhead for speed */
1511
0
        line = _buffered_readline(self, -1);
1512
0
    }
1513
0
    else {
1514
0
        line = PyObject_CallMethodNoArgs((PyObject *)self,
1515
0
                                             &_Py_ID(readline));
1516
0
        if (line && !PyBytes_Check(line)) {
1517
0
            PyErr_Format(PyExc_OSError,
1518
0
                         "readline() should have returned a bytes object, "
1519
0
                         "not '%.200s'", Py_TYPE(line)->tp_name);
1520
0
            Py_DECREF(line);
1521
0
            return NULL;
1522
0
        }
1523
0
    }
1524
1525
0
    if (line == NULL)
1526
0
        return NULL;
1527
1528
0
    if (PyBytes_GET_SIZE(line) == 0) {
1529
        /* Reached EOF or would have blocked */
1530
0
        Py_DECREF(line);
1531
0
        return NULL;
1532
0
    }
1533
1534
0
    return line;
1535
0
}
1536
1537
static PyObject *
1538
buffered_repr(PyObject *op)
1539
0
{
1540
0
    buffered *self = buffered_CAST(op);
1541
0
    PyObject *nameobj, *res;
1542
1543
0
    if (PyObject_GetOptionalAttr((PyObject *) self, &_Py_ID(name), &nameobj) < 0) {
1544
0
        if (!PyErr_ExceptionMatches(PyExc_ValueError)) {
1545
0
            return NULL;
1546
0
        }
1547
        /* Ignore ValueError raised if the underlying stream was detached */
1548
0
        PyErr_Clear();
1549
0
    }
1550
0
    if (nameobj == NULL) {
1551
0
        res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1552
0
    }
1553
0
    else {
1554
0
        int status = Py_ReprEnter((PyObject *)self);
1555
0
        res = NULL;
1556
0
        if (status == 0) {
1557
0
            res = PyUnicode_FromFormat("<%s name=%R>",
1558
0
                                       Py_TYPE(self)->tp_name, nameobj);
1559
0
            Py_ReprLeave((PyObject *)self);
1560
0
        }
1561
0
        else if (status > 0) {
1562
0
            PyErr_Format(PyExc_RuntimeError,
1563
0
                         "reentrant call inside %s.__repr__",
1564
0
                         Py_TYPE(self)->tp_name);
1565
0
        }
1566
0
        Py_DECREF(nameobj);
1567
0
    }
1568
0
    return res;
1569
0
}
1570
1571
/*
1572
 * class BufferedReader
1573
 */
1574
1575
static void _bufferedreader_reset_buf(buffered *self)
1576
65.1k
{
1577
65.1k
    self->read_end = -1;
1578
65.1k
}
1579
1580
/*[clinic input]
1581
_io.BufferedReader.__init__
1582
    raw: object
1583
    buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
1584
1585
Create a new buffered reader using the given readable raw IO object.
1586
[clinic start generated code]*/
1587
1588
static int
1589
_io_BufferedReader___init___impl(buffered *self, PyObject *raw,
1590
                                 Py_ssize_t buffer_size)
1591
/*[clinic end generated code: output=cddcfefa0ed294c4 input=fb887e06f11b4e48]*/
1592
12.3k
{
1593
12.3k
    self->ok = 0;
1594
12.3k
    self->detached = 0;
1595
1596
12.3k
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
1597
12.3k
    if (_PyIOBase_check_readable(state, raw, Py_True) == NULL) {
1598
0
        return -1;
1599
0
    }
1600
1601
12.3k
    Py_XSETREF(self->raw, Py_NewRef(raw));
1602
12.3k
    self->buffer_size = buffer_size;
1603
12.3k
    self->readable = 1;
1604
12.3k
    self->writable = 0;
1605
1606
12.3k
    if (_buffered_init(self) < 0)
1607
0
        return -1;
1608
12.3k
    _bufferedreader_reset_buf(self);
1609
1610
12.3k
    self->fast_closed_checks = (
1611
12.3k
        Py_IS_TYPE(self, state->PyBufferedReader_Type) &&
1612
12.3k
        Py_IS_TYPE(raw, state->PyFileIO_Type)
1613
12.3k
    );
1614
1615
12.3k
    self->ok = 1;
1616
12.3k
    return 0;
1617
12.3k
}
1618
1619
static Py_ssize_t
1620
_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
1621
36.6k
{
1622
36.6k
    Py_buffer buf;
1623
36.6k
    PyObject *memobj, *res;
1624
36.6k
    Py_ssize_t n;
1625
    /* NOTE: the buffer needn't be released as its object is NULL. */
1626
36.6k
    if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1627
0
        return -1;
1628
36.6k
    memobj = PyMemoryView_FromBuffer(&buf);
1629
36.6k
    if (memobj == NULL)
1630
0
        return -1;
1631
    /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1632
       occurs so we needn't do it ourselves.
1633
       We then retry reading, ignoring the signal if no handler has
1634
       raised (see issue #10956).
1635
    */
1636
36.6k
    do {
1637
36.6k
        res = PyObject_CallMethodOneArg(self->raw, &_Py_ID(readinto), memobj);
1638
36.6k
    } while (res == NULL && _PyIO_trap_eintr());
1639
36.6k
    Py_DECREF(memobj);
1640
36.6k
    if (res == NULL)
1641
6.03k
        return -1;
1642
30.5k
    if (res == Py_None) {
1643
        /* Non-blocking stream would have blocked. Special return code! */
1644
0
        Py_DECREF(res);
1645
0
        return -2;
1646
0
    }
1647
30.5k
    n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1648
30.5k
    Py_DECREF(res);
1649
1650
30.5k
    if (n == -1 && PyErr_Occurred()) {
1651
0
        _PyErr_FormatFromCause(
1652
0
            PyExc_OSError,
1653
0
            "raw readinto() failed"
1654
0
        );
1655
0
        return -1;
1656
0
    }
1657
1658
30.5k
    if (n < 0 || n > len) {
1659
0
        PyErr_Format(PyExc_OSError,
1660
0
                     "raw readinto() returned invalid length %zd "
1661
0
                     "(should have been between 0 and %zd)", n, len);
1662
0
        return -1;
1663
0
    }
1664
30.5k
    if (n > 0 && self->abs_pos != -1)
1665
30.4k
        self->abs_pos += n;
1666
30.5k
    return n;
1667
30.5k
}
1668
1669
static Py_ssize_t
1670
_bufferedreader_fill_buffer(buffered *self)
1671
36.6k
{
1672
36.6k
    Py_ssize_t start, len, n;
1673
36.6k
    if (VALID_READ_BUFFER(self))
1674
36.6k
        start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1675
0
    else
1676
0
        start = 0;
1677
36.6k
    len = self->buffer_size - start;
1678
36.6k
    n = _bufferedreader_raw_read(self, self->buffer + start, len);
1679
36.6k
    if (n <= 0)
1680
6.17k
        return n;
1681
30.4k
    self->read_end = start + n;
1682
30.4k
    self->raw_pos = start + n;
1683
30.4k
    return n;
1684
36.6k
}
1685
1686
static PyObject *
1687
_bufferedreader_read_all(buffered *self)
1688
6.11k
{
1689
6.11k
    Py_ssize_t current_size;
1690
6.11k
    PyObject *res = NULL, *data = NULL, *tmp = NULL, *chunks = NULL, *readall;
1691
1692
    /* First copy what we have in the current buffer. */
1693
6.11k
    current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1694
6.11k
    if (current_size) {
1695
0
        data = PyBytes_FromStringAndSize(
1696
0
            self->buffer + self->pos, current_size);
1697
0
        if (data == NULL)
1698
0
            return NULL;
1699
0
        self->pos += current_size;
1700
0
    }
1701
    /* We're going past the buffer's bounds, flush it */
1702
6.11k
    if (self->writable) {
1703
0
        tmp = buffered_flush_and_rewind_unlocked(self);
1704
0
        if (tmp == NULL)
1705
0
            goto cleanup;
1706
0
        Py_CLEAR(tmp);
1707
0
    }
1708
6.11k
    _bufferedreader_reset_buf(self);
1709
1710
6.11k
    if (PyObject_GetOptionalAttr(self->raw, &_Py_ID(readall), &readall) < 0) {
1711
0
        goto cleanup;
1712
0
    }
1713
6.11k
    if (readall) {
1714
6.11k
        tmp = _PyObject_CallNoArgs(readall);
1715
6.11k
        Py_DECREF(readall);
1716
6.11k
        if (tmp == NULL)
1717
0
            goto cleanup;
1718
6.11k
        if (tmp != Py_None && !PyBytes_Check(tmp)) {
1719
0
            PyErr_SetString(PyExc_TypeError, "readall() should return bytes");
1720
0
            goto cleanup;
1721
0
        }
1722
6.11k
        if (current_size == 0) {
1723
6.11k
            res = tmp;
1724
6.11k
        } else {
1725
0
            if (tmp != Py_None) {
1726
0
                PyBytes_Concat(&data, tmp);
1727
0
            }
1728
0
            res = data;
1729
0
        }
1730
6.11k
        goto cleanup;
1731
6.11k
    }
1732
1733
0
    chunks = PyList_New(0);
1734
0
    if (chunks == NULL)
1735
0
        goto cleanup;
1736
1737
0
    while (1) {
1738
0
        if (data) {
1739
0
            if (PyList_Append(chunks, data) < 0)
1740
0
                goto cleanup;
1741
0
            Py_CLEAR(data);
1742
0
        }
1743
1744
        /* Read until EOF or until read() would block. */
1745
0
        data = PyObject_CallMethodNoArgs(self->raw, &_Py_ID(read));
1746
0
        if (data == NULL)
1747
0
            goto cleanup;
1748
0
        if (data != Py_None && !PyBytes_Check(data)) {
1749
0
            PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1750
0
            goto cleanup;
1751
0
        }
1752
0
        if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1753
0
            if (current_size == 0) {
1754
0
                res = data;
1755
0
                goto cleanup;
1756
0
            }
1757
0
            else {
1758
0
                tmp = PyBytes_Join((PyObject *)&_Py_SINGLETON(bytes_empty), chunks);
1759
0
                res = tmp;
1760
0
                goto cleanup;
1761
0
            }
1762
0
        }
1763
0
        current_size += PyBytes_GET_SIZE(data);
1764
0
        if (self->abs_pos != -1)
1765
0
            self->abs_pos += PyBytes_GET_SIZE(data);
1766
0
    }
1767
6.11k
cleanup:
1768
    /* res is either NULL or a borrowed ref */
1769
6.11k
    Py_XINCREF(res);
1770
6.11k
    Py_XDECREF(data);
1771
6.11k
    Py_XDECREF(tmp);
1772
6.11k
    Py_XDECREF(chunks);
1773
6.11k
    return res;
1774
0
}
1775
1776
/* Read n bytes from the buffer if it can, otherwise return None.
1777
   This function is simple enough that it can run unlocked. */
1778
static PyObject *
1779
_bufferedreader_read_fast(buffered *self, Py_ssize_t n)
1780
6.97M
{
1781
6.97M
    Py_ssize_t current_size;
1782
1783
6.97M
    current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1784
6.97M
    if (n <= current_size) {
1785
        /* Fast path: the data to read is fully buffered. */
1786
6.93M
        PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1787
6.93M
        if (res != NULL)
1788
6.93M
            self->pos += n;
1789
6.93M
        return res;
1790
6.93M
    }
1791
6.97M
    Py_RETURN_NONE;
1792
6.97M
}
1793
1794
/* Generic read function: read from the stream until enough bytes are read,
1795
 * or until an EOF occurs or until read() would block.
1796
 */
1797
static PyObject *
1798
_bufferedreader_read_generic(buffered *self, Py_ssize_t n)
1799
35.3k
{
1800
35.3k
    Py_ssize_t current_size, remaining, written;
1801
1802
35.3k
    current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1803
35.3k
    if (n <= current_size)
1804
0
        return _bufferedreader_read_fast(self, n);
1805
1806
35.3k
    PyBytesWriter *writer = PyBytesWriter_Create(n);
1807
35.3k
    if (writer == NULL) {
1808
0
        goto error;
1809
0
    }
1810
35.3k
    char *out = PyBytesWriter_GetData(writer);
1811
1812
35.3k
    remaining = n;
1813
35.3k
    written = 0;
1814
35.3k
    if (current_size > 0) {
1815
6.35k
        memcpy(out, self->buffer + self->pos, current_size);
1816
6.35k
        remaining -= current_size;
1817
6.35k
        written += current_size;
1818
6.35k
        self->pos += current_size;
1819
6.35k
    }
1820
    /* Flush the write buffer if necessary */
1821
35.3k
    if (self->writable) {
1822
0
        PyObject *r = buffered_flush_and_rewind_unlocked(self);
1823
0
        if (r == NULL)
1824
0
            goto error;
1825
0
        Py_DECREF(r);
1826
0
    }
1827
35.3k
    _bufferedreader_reset_buf(self);
1828
35.3k
    while (remaining > 0) {
1829
        /* We want to read a whole block at the end into buffer.
1830
           If we had readv() we could do this in one pass. */
1831
35.3k
        Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1832
35.3k
        if (r == 0)
1833
35.3k
            break;
1834
0
        r = _bufferedreader_raw_read(self, out + written, r);
1835
0
        if (r == -1)
1836
0
            goto error;
1837
0
        if (r == 0 || r == -2) {
1838
            /* EOF occurred or read() would block. */
1839
0
            if (r == 0 || written > 0) {
1840
0
                return PyBytesWriter_FinishWithSize(writer, written);
1841
0
            }
1842
0
            PyBytesWriter_Discard(writer);
1843
0
            Py_RETURN_NONE;
1844
0
        }
1845
0
        remaining -= r;
1846
0
        written += r;
1847
0
    }
1848
35.3k
    assert(remaining <= self->buffer_size);
1849
35.3k
    self->pos = 0;
1850
35.3k
    self->raw_pos = 0;
1851
35.3k
    self->read_end = 0;
1852
    /* NOTE: when the read is satisfied, we avoid issuing any additional
1853
       reads, which could block indefinitely (e.g. on a socket).
1854
       See issue #9550. */
1855
36.6k
    while (remaining > 0 && self->read_end < self->buffer_size) {
1856
36.6k
        Py_ssize_t r = _bufferedreader_fill_buffer(self);
1857
36.6k
        if (r == -1)
1858
6.03k
            goto error;
1859
30.5k
        if (r == 0 || r == -2) {
1860
            /* EOF occurred or read() would block. */
1861
146
            if (r == 0 || written > 0) {
1862
146
                return PyBytesWriter_FinishWithSize(writer, written);
1863
146
            }
1864
0
            PyBytesWriter_Discard(writer);
1865
0
            Py_RETURN_NONE;
1866
146
        }
1867
30.4k
        if (remaining > r) {
1868
1.25k
            memcpy(out + written, self->buffer + self->pos, r);
1869
1.25k
            written += r;
1870
1.25k
            self->pos += r;
1871
1.25k
            remaining -= r;
1872
1.25k
        }
1873
29.1k
        else if (remaining > 0) {
1874
29.1k
            memcpy(out + written, self->buffer + self->pos, remaining);
1875
29.1k
            written += remaining;
1876
29.1k
            self->pos += remaining;
1877
29.1k
            remaining = 0;
1878
29.1k
        }
1879
30.4k
        if (remaining == 0)
1880
29.1k
            break;
1881
30.4k
    }
1882
1883
29.1k
    return PyBytesWriter_Finish(writer);
1884
1885
6.03k
error:
1886
6.03k
    PyBytesWriter_Discard(writer);
1887
6.03k
    return NULL;
1888
35.3k
}
1889
1890
static PyObject *
1891
_bufferedreader_peek_unlocked(buffered *self)
1892
0
{
1893
0
    Py_ssize_t have, r;
1894
1895
0
    have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1896
    /* Constraints:
1897
       1. we don't want to advance the file position.
1898
       2. we don't want to lose block alignment, so we can't shift the buffer
1899
          to make some place.
1900
       Therefore, we either return `have` bytes (if > 0), or a full buffer.
1901
    */
1902
0
    if (have > 0) {
1903
0
        return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1904
0
    }
1905
1906
    /* Fill the buffer from the raw stream, and copy it to the result. */
1907
0
    _bufferedreader_reset_buf(self);
1908
0
    r = _bufferedreader_fill_buffer(self);
1909
0
    if (r == -1)
1910
0
        return NULL;
1911
0
    if (r == -2)
1912
0
        r = 0;
1913
0
    self->pos = 0;
1914
0
    return PyBytes_FromStringAndSize(self->buffer, r);
1915
0
}
1916
1917
1918
/*
1919
 * class BufferedWriter
1920
 */
1921
static void
1922
_bufferedwriter_reset_buf(buffered *self)
1923
282k
{
1924
282k
    self->write_pos = 0;
1925
282k
    self->write_end = -1;
1926
282k
}
1927
1928
/*[clinic input]
1929
_io.BufferedWriter.__init__
1930
    raw: object
1931
    buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
1932
1933
A buffer for a writeable sequential RawIO object.
1934
1935
The constructor creates a BufferedWriter for the given writeable raw
1936
stream. If the buffer_size is not given, it defaults to
1937
DEFAULT_BUFFER_SIZE.
1938
[clinic start generated code]*/
1939
1940
static int
1941
_io_BufferedWriter___init___impl(buffered *self, PyObject *raw,
1942
                                 Py_ssize_t buffer_size)
1943
/*[clinic end generated code: output=c8942a020c0dee64 input=914be9b95e16007b]*/
1944
27.6k
{
1945
27.6k
    self->ok = 0;
1946
27.6k
    self->detached = 0;
1947
1948
27.6k
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
1949
27.6k
    if (_PyIOBase_check_writable(state, raw, Py_True) == NULL) {
1950
0
        return -1;
1951
0
    }
1952
1953
27.6k
    Py_INCREF(raw);
1954
27.6k
    Py_XSETREF(self->raw, raw);
1955
27.6k
    self->readable = 0;
1956
27.6k
    self->writable = 1;
1957
1958
27.6k
    self->buffer_size = buffer_size;
1959
27.6k
    if (_buffered_init(self) < 0)
1960
0
        return -1;
1961
27.6k
    _bufferedwriter_reset_buf(self);
1962
27.6k
    self->pos = 0;
1963
1964
27.6k
    self->fast_closed_checks = (
1965
27.6k
        Py_IS_TYPE(self, state->PyBufferedWriter_Type) &&
1966
27.6k
        Py_IS_TYPE(raw, state->PyFileIO_Type)
1967
27.6k
    );
1968
1969
27.6k
    self->ok = 1;
1970
27.6k
    return 0;
1971
27.6k
}
1972
1973
static Py_ssize_t
1974
_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
1975
254k
{
1976
254k
    Py_buffer buf;
1977
254k
    PyObject *memobj, *res;
1978
254k
    Py_ssize_t n;
1979
254k
    int errnum;
1980
    /* NOTE: the buffer needn't be released as its object is NULL. */
1981
254k
    if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1982
0
        return -1;
1983
254k
    memobj = PyMemoryView_FromBuffer(&buf);
1984
254k
    if (memobj == NULL)
1985
0
        return -1;
1986
    /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1987
       occurs so we needn't do it ourselves.
1988
       We then retry writing, ignoring the signal if no handler has
1989
       raised (see issue #10956).
1990
    */
1991
254k
    do {
1992
254k
        errno = 0;
1993
254k
        res = PyObject_CallMethodOneArg(self->raw, &_Py_ID(write), memobj);
1994
254k
        errnum = errno;
1995
254k
    } while (res == NULL && _PyIO_trap_eintr());
1996
254k
    Py_DECREF(memobj);
1997
254k
    if (res == NULL)
1998
0
        return -1;
1999
254k
    if (res == Py_None) {
2000
        /* Non-blocking stream would have blocked. Special return code!
2001
           Being paranoid we reset errno in case it is changed by code
2002
           triggered by a decref.  errno is used by _set_BlockingIOError(). */
2003
0
        Py_DECREF(res);
2004
0
        errno = errnum;
2005
0
        return -2;
2006
0
    }
2007
254k
    n = PyNumber_AsSsize_t(res, PyExc_ValueError);
2008
254k
    Py_DECREF(res);
2009
254k
    if (n < 0 || n > len) {
2010
0
        PyErr_Format(PyExc_OSError,
2011
0
                     "raw write() returned invalid length %zd "
2012
0
                     "(should have been between 0 and %zd)", n, len);
2013
0
        return -1;
2014
0
    }
2015
254k
    if (n > 0 && self->abs_pos != -1)
2016
254k
        self->abs_pos += n;
2017
254k
    return n;
2018
254k
}
2019
2020
static PyObject *
2021
_bufferedwriter_flush_unlocked(buffered *self)
2022
255k
{
2023
255k
    Py_off_t n, rewind;
2024
2025
255k
    if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
2026
1.23k
        goto end;
2027
    /* First, rewind */
2028
253k
    rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
2029
253k
    if (rewind != 0) {
2030
0
        n = _buffered_raw_seek(self, -rewind, 1);
2031
0
        if (n < 0) {
2032
0
            goto error;
2033
0
        }
2034
0
        self->raw_pos -= rewind;
2035
0
    }
2036
507k
    while (self->write_pos < self->write_end) {
2037
253k
        n = _bufferedwriter_raw_write(self,
2038
253k
            self->buffer + self->write_pos,
2039
253k
            Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
2040
253k
                             Py_off_t, Py_ssize_t));
2041
253k
        if (n == -1) {
2042
0
            goto error;
2043
0
        }
2044
253k
        else if (n == -2) {
2045
0
            _set_BlockingIOError("write could not complete without blocking",
2046
0
                                 0);
2047
0
            goto error;
2048
0
        }
2049
253k
        self->write_pos += n;
2050
253k
        self->raw_pos = self->write_pos;
2051
        /* Partial writes can return successfully when interrupted by a
2052
           signal (see write(2)).  We must run signal handlers before
2053
           blocking another time, possibly indefinitely. */
2054
253k
        if (PyErr_CheckSignals() < 0)
2055
0
            goto error;
2056
253k
    }
2057
2058
2059
255k
end:
2060
    /* This ensures that after return from this function,
2061
       VALID_WRITE_BUFFER(self) returns false.
2062
2063
       This is a required condition because when a tell() is called
2064
       after flushing and if VALID_READ_BUFFER(self) is false, we need
2065
       VALID_WRITE_BUFFER(self) to be false to have
2066
       RAW_OFFSET(self) == 0.
2067
2068
       Issue: https://bugs.python.org/issue32228 */
2069
255k
    _bufferedwriter_reset_buf(self);
2070
255k
    Py_RETURN_NONE;
2071
2072
0
error:
2073
0
    return NULL;
2074
253k
}
2075
2076
/*[clinic input]
2077
@critical_section
2078
_io.BufferedWriter.write
2079
    buffer: Py_buffer
2080
    /
2081
[clinic start generated code]*/
2082
2083
static PyObject *
2084
_io_BufferedWriter_write_impl(buffered *self, Py_buffer *buffer)
2085
/*[clinic end generated code: output=7f8d1365759bfc6b input=6a9c041de0c337be]*/
2086
254k
{
2087
254k
    PyObject *res = NULL;
2088
254k
    Py_ssize_t written, avail, remaining;
2089
254k
    Py_off_t offset;
2090
254k
    int r;
2091
2092
254k
    CHECK_INITIALIZED(self)
2093
2094
254k
    if (!ENTER_BUFFERED(self))
2095
0
        return NULL;
2096
2097
    /* Issue #31976: Check for closed file after acquiring the lock. Another
2098
       thread could be holding the lock while closing the file. */
2099
254k
    r = IS_CLOSED(self);
2100
254k
    if (r < 0) {
2101
0
        goto error;
2102
0
    }
2103
254k
    if (r > 0) {
2104
0
        PyErr_SetString(PyExc_ValueError, "write to closed file");
2105
0
        goto error;
2106
0
    }
2107
2108
    /* Fast path: the data to write can be fully buffered. */
2109
254k
    if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
2110
254k
        self->pos = 0;
2111
254k
        self->raw_pos = 0;
2112
254k
    }
2113
254k
    avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
2114
254k
    if (buffer->len <= avail && buffer->len < self->buffer_size) {
2115
253k
        memcpy(self->buffer + self->pos, buffer->buf, buffer->len);
2116
253k
        if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
2117
253k
            self->write_pos = self->pos;
2118
253k
        }
2119
253k
        ADJUST_POSITION(self, self->pos + buffer->len);
2120
253k
        if (self->pos > self->write_end)
2121
253k
            self->write_end = self->pos;
2122
253k
        written = buffer->len;
2123
253k
        goto end;
2124
253k
    }
2125
2126
    /* First write the current buffer */
2127
704
    res = _bufferedwriter_flush_unlocked(self);
2128
704
    if (res == NULL) {
2129
0
        Py_ssize_t *w = _buffered_check_blocking_error();
2130
0
        if (w == NULL)
2131
0
            goto error;
2132
0
        if (self->readable)
2133
0
            _bufferedreader_reset_buf(self);
2134
        /* Make some place by shifting the buffer. */
2135
0
        assert(VALID_WRITE_BUFFER(self));
2136
0
        memmove(self->buffer, self->buffer + self->write_pos,
2137
0
                Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
2138
0
                                 Py_off_t, Py_ssize_t));
2139
0
        self->write_end -= self->write_pos;
2140
0
        self->raw_pos -= self->write_pos;
2141
0
        self->pos -= self->write_pos;
2142
0
        self->write_pos = 0;
2143
0
        avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
2144
0
                                 Py_off_t, Py_ssize_t);
2145
0
        if (buffer->len <= avail) {
2146
            /* Everything can be buffered */
2147
0
            PyErr_Clear();
2148
0
            memcpy(self->buffer + self->write_end, buffer->buf, buffer->len);
2149
0
            self->write_end += buffer->len;
2150
0
            self->pos += buffer->len;
2151
0
            written = buffer->len;
2152
0
            goto end;
2153
0
        }
2154
        /* Buffer as much as possible. */
2155
0
        memcpy(self->buffer + self->write_end, buffer->buf, avail);
2156
0
        self->write_end += avail;
2157
0
        self->pos += avail;
2158
        /* XXX Modifying the existing exception e using the pointer w
2159
           will change e.characters_written but not e.args[2].
2160
           Therefore we just replace with a new error. */
2161
0
        _set_BlockingIOError("write could not complete without blocking",
2162
0
                             avail);
2163
0
        goto error;
2164
0
    }
2165
704
    Py_CLEAR(res);
2166
2167
    /* Adjust the raw stream position if it is away from the logical stream
2168
       position. This happens if the read buffer has been filled but not
2169
       modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
2170
       the raw stream by itself).
2171
       Fixes issue #6629.
2172
    */
2173
704
    offset = RAW_OFFSET(self);
2174
704
    if (offset != 0) {
2175
0
        if (_buffered_raw_seek(self, -offset, 1) < 0)
2176
0
            goto error;
2177
0
        self->raw_pos -= offset;
2178
0
    }
2179
2180
    /* Then write buf itself. At this point the buffer has been emptied. */
2181
704
    remaining = buffer->len;
2182
704
    written = 0;
2183
1.40k
    while (remaining >= self->buffer_size) {
2184
704
        Py_ssize_t n = _bufferedwriter_raw_write(
2185
704
            self, (char *) buffer->buf + written, buffer->len - written);
2186
704
        if (n == -1) {
2187
0
            goto error;
2188
704
        } else if (n == -2) {
2189
            /* Write failed because raw file is non-blocking */
2190
0
            if (remaining > self->buffer_size) {
2191
                /* Can't buffer everything, still buffer as much as possible */
2192
0
                memcpy(self->buffer,
2193
0
                       (char *) buffer->buf + written, self->buffer_size);
2194
0
                self->raw_pos = 0;
2195
0
                ADJUST_POSITION(self, self->buffer_size);
2196
0
                self->write_end = self->buffer_size;
2197
0
                written += self->buffer_size;
2198
0
                _set_BlockingIOError("write could not complete without "
2199
0
                                     "blocking", written);
2200
0
                goto error;
2201
0
            }
2202
0
            PyErr_Clear();
2203
0
            break;
2204
0
        }
2205
704
        written += n;
2206
704
        remaining -= n;
2207
        /* Partial writes can return successfully when interrupted by a
2208
           signal (see write(2)).  We must run signal handlers before
2209
           blocking another time, possibly indefinitely. */
2210
704
        if (PyErr_CheckSignals() < 0)
2211
0
            goto error;
2212
704
    }
2213
704
    if (self->readable)
2214
0
        _bufferedreader_reset_buf(self);
2215
704
    if (remaining > 0) {
2216
0
        memcpy(self->buffer, (char *) buffer->buf + written, remaining);
2217
0
        written += remaining;
2218
0
    }
2219
704
    self->write_pos = 0;
2220
    /* TODO: sanity check (remaining >= 0) */
2221
704
    self->write_end = remaining;
2222
704
    ADJUST_POSITION(self, remaining);
2223
704
    self->raw_pos = 0;
2224
2225
254k
end:
2226
254k
    res = PyLong_FromSsize_t(written);
2227
2228
254k
error:
2229
254k
    LEAVE_BUFFERED(self)
2230
254k
    return res;
2231
254k
}
2232
2233
2234
/*
2235
 * BufferedRWPair
2236
 */
2237
2238
/* XXX The usefulness of this (compared to having two separate IO objects) is
2239
 * questionable.
2240
 */
2241
2242
typedef struct {
2243
    PyObject_HEAD
2244
    buffered *reader;
2245
    buffered *writer;
2246
    PyObject *dict;
2247
    PyObject *weakreflist;
2248
} rwpair;
2249
2250
0
#define rwpair_CAST(op) ((rwpair *)(op))
2251
2252
/*[clinic input]
2253
_io.BufferedRWPair.__init__
2254
    reader: object
2255
    writer: object
2256
    buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
2257
    /
2258
2259
A buffered reader and writer object together.
2260
2261
A buffered reader object and buffered writer object put together to
2262
form a sequential IO object that can read and write. This is typically
2263
used with a socket or two-way pipe.
2264
2265
reader and writer are RawIOBase objects that are readable and
2266
writeable respectively. If the buffer_size is omitted it defaults to
2267
DEFAULT_BUFFER_SIZE.
2268
[clinic start generated code]*/
2269
2270
static int
2271
_io_BufferedRWPair___init___impl(rwpair *self, PyObject *reader,
2272
                                 PyObject *writer, Py_ssize_t buffer_size)
2273
/*[clinic end generated code: output=327e73d1aee8f984 input=620d42d71f33a031]*/
2274
0
{
2275
0
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
2276
0
    if (_PyIOBase_check_readable(state, reader, Py_True) == NULL) {
2277
0
        return -1;
2278
0
    }
2279
0
    if (_PyIOBase_check_writable(state, writer, Py_True) == NULL) {
2280
0
        return -1;
2281
0
    }
2282
2283
0
    self->reader = (buffered *) PyObject_CallFunction(
2284
0
            (PyObject *)state->PyBufferedReader_Type,
2285
0
            "On", reader, buffer_size);
2286
0
    if (self->reader == NULL)
2287
0
        return -1;
2288
2289
0
    self->writer = (buffered *) PyObject_CallFunction(
2290
0
            (PyObject *)state->PyBufferedWriter_Type,
2291
0
            "On", writer, buffer_size);
2292
0
    if (self->writer == NULL) {
2293
0
        Py_CLEAR(self->reader);
2294
0
        return -1;
2295
0
    }
2296
2297
0
    return 0;
2298
0
}
2299
2300
static int
2301
bufferedrwpair_traverse(PyObject *op, visitproc visit, void *arg)
2302
0
{
2303
0
    rwpair *self = rwpair_CAST(op);
2304
0
    Py_VISIT(Py_TYPE(self));
2305
0
    Py_VISIT(self->dict);
2306
0
    Py_VISIT(self->reader);
2307
0
    Py_VISIT(self->writer);
2308
0
    return 0;
2309
0
}
2310
2311
static int
2312
bufferedrwpair_clear(PyObject *op)
2313
0
{
2314
0
    rwpair *self = rwpair_CAST(op);
2315
0
    Py_CLEAR(self->reader);
2316
0
    Py_CLEAR(self->writer);
2317
0
    Py_CLEAR(self->dict);
2318
0
    return 0;
2319
0
}
2320
2321
static void
2322
bufferedrwpair_dealloc(PyObject *op)
2323
0
{
2324
0
    rwpair *self = rwpair_CAST(op);
2325
0
    PyTypeObject *tp = Py_TYPE(self);
2326
0
    _PyObject_GC_UNTRACK(self);
2327
0
    FT_CLEAR_WEAKREFS(op, self->weakreflist);
2328
0
    (void)bufferedrwpair_clear(op);
2329
0
    tp->tp_free(self);
2330
0
    Py_DECREF(tp);
2331
0
}
2332
2333
static PyObject *
2334
_forward_call(buffered *self, PyObject *name, PyObject *args)
2335
0
{
2336
0
    PyObject *func, *ret;
2337
0
    if (self == NULL) {
2338
0
        PyErr_SetString(PyExc_ValueError,
2339
0
                        "I/O operation on uninitialized object");
2340
0
        return NULL;
2341
0
    }
2342
2343
0
    func = PyObject_GetAttr((PyObject *)self, name);
2344
0
    if (func == NULL) {
2345
0
        PyErr_SetObject(PyExc_AttributeError, name);
2346
0
        return NULL;
2347
0
    }
2348
2349
0
    ret = PyObject_CallObject(func, args);
2350
0
    Py_DECREF(func);
2351
0
    return ret;
2352
0
}
2353
2354
static PyObject *
2355
bufferedrwpair_read(PyObject *op, PyObject *args)
2356
0
{
2357
0
    rwpair *self = rwpair_CAST(op);
2358
0
    return _forward_call(self->reader, &_Py_ID(read), args);
2359
0
}
2360
2361
static PyObject *
2362
bufferedrwpair_peek(PyObject *op, PyObject *args)
2363
0
{
2364
0
    rwpair *self = rwpair_CAST(op);
2365
0
    return _forward_call(self->reader, &_Py_ID(peek), args);
2366
0
}
2367
2368
static PyObject *
2369
bufferedrwpair_read1(PyObject *op, PyObject *args)
2370
0
{
2371
0
    rwpair *self = rwpair_CAST(op);
2372
0
    return _forward_call(self->reader, &_Py_ID(read1), args);
2373
0
}
2374
2375
static PyObject *
2376
bufferedrwpair_readinto(PyObject *op, PyObject *args)
2377
0
{
2378
0
    rwpair *self = rwpair_CAST(op);
2379
0
    return _forward_call(self->reader, &_Py_ID(readinto), args);
2380
0
}
2381
2382
static PyObject *
2383
bufferedrwpair_readinto1(PyObject *op, PyObject *args)
2384
0
{
2385
0
    rwpair *self = rwpair_CAST(op);
2386
0
    return _forward_call(self->reader, &_Py_ID(readinto1), args);
2387
0
}
2388
2389
static PyObject *
2390
bufferedrwpair_write(PyObject *op, PyObject *args)
2391
0
{
2392
0
    rwpair *self = rwpair_CAST(op);
2393
0
    return _forward_call(self->writer, &_Py_ID(write), args);
2394
0
}
2395
2396
static PyObject *
2397
bufferedrwpair_flush(PyObject *op, PyObject *Py_UNUSED(dummy))
2398
0
{
2399
0
    rwpair *self = rwpair_CAST(op);
2400
0
    return _forward_call(self->writer, &_Py_ID(flush), NULL);
2401
0
}
2402
2403
static PyObject *
2404
bufferedrwpair_readable(PyObject *op, PyObject *Py_UNUSED(dummy))
2405
0
{
2406
0
    rwpair *self = rwpair_CAST(op);
2407
0
    return _forward_call(self->reader, &_Py_ID(readable), NULL);
2408
0
}
2409
2410
static PyObject *
2411
bufferedrwpair_writable(PyObject *op, PyObject *Py_UNUSED(dummy))
2412
0
{
2413
0
    rwpair *self = rwpair_CAST(op);
2414
0
    return _forward_call(self->writer, &_Py_ID(writable), NULL);
2415
0
}
2416
2417
static PyObject *
2418
bufferedrwpair_close(PyObject *op, PyObject *Py_UNUSED(dummy))
2419
0
{
2420
0
    rwpair *self = rwpair_CAST(op);
2421
0
    PyObject *exc = NULL;
2422
0
    PyObject *ret = _forward_call(self->writer, &_Py_ID(close), NULL);
2423
0
    if (ret == NULL) {
2424
0
        exc = PyErr_GetRaisedException();
2425
0
    }
2426
0
    else {
2427
0
        Py_DECREF(ret);
2428
0
    }
2429
0
    ret = _forward_call(self->reader, &_Py_ID(close), NULL);
2430
0
    if (exc != NULL) {
2431
0
        _PyErr_ChainExceptions1(exc);
2432
0
        Py_CLEAR(ret);
2433
0
    }
2434
0
    return ret;
2435
0
}
2436
2437
static PyObject *
2438
bufferedrwpair_isatty(PyObject *op, PyObject *Py_UNUSED(dummy))
2439
0
{
2440
0
    rwpair *self = rwpair_CAST(op);
2441
0
    PyObject *ret = _forward_call(self->writer, &_Py_ID(isatty), NULL);
2442
2443
0
    if (ret != Py_False) {
2444
        /* either True or exception */
2445
0
        return ret;
2446
0
    }
2447
0
    Py_DECREF(ret);
2448
2449
0
    return _forward_call(self->reader, &_Py_ID(isatty), NULL);
2450
0
}
2451
2452
static PyObject *
2453
bufferedrwpair_closed_get(PyObject *op, void *Py_UNUSED(dummy))
2454
0
{
2455
0
    rwpair *self = rwpair_CAST(op);
2456
0
    if (self->writer == NULL) {
2457
0
        PyErr_SetString(PyExc_RuntimeError,
2458
0
                "the BufferedRWPair object is being garbage-collected");
2459
0
        return NULL;
2460
0
    }
2461
0
    return PyObject_GetAttr((PyObject *) self->writer, &_Py_ID(closed));
2462
0
}
2463
2464
2465
/*
2466
 * BufferedRandom
2467
 */
2468
2469
/*[clinic input]
2470
_io.BufferedRandom.__init__
2471
    raw: object
2472
    buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
2473
2474
A buffered interface to random access streams.
2475
2476
The constructor creates a reader and writer for a seekable stream,
2477
raw, given in the first argument. If the buffer_size is omitted it
2478
defaults to DEFAULT_BUFFER_SIZE.
2479
[clinic start generated code]*/
2480
2481
static int
2482
_io_BufferedRandom___init___impl(buffered *self, PyObject *raw,
2483
                                 Py_ssize_t buffer_size)
2484
/*[clinic end generated code: output=d3d64eb0f64e64a3 input=a4e818fb86d0e50c]*/
2485
0
{
2486
0
    self->ok = 0;
2487
0
    self->detached = 0;
2488
2489
0
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
2490
0
    if (_PyIOBase_check_seekable(state, raw, Py_True) == NULL) {
2491
0
        return -1;
2492
0
    }
2493
0
    if (_PyIOBase_check_readable(state, raw, Py_True) == NULL) {
2494
0
        return -1;
2495
0
    }
2496
0
    if (_PyIOBase_check_writable(state, raw, Py_True) == NULL) {
2497
0
        return -1;
2498
0
    }
2499
2500
0
    Py_INCREF(raw);
2501
0
    Py_XSETREF(self->raw, raw);
2502
0
    self->buffer_size = buffer_size;
2503
0
    self->readable = 1;
2504
0
    self->writable = 1;
2505
2506
0
    if (_buffered_init(self) < 0)
2507
0
        return -1;
2508
0
    _bufferedreader_reset_buf(self);
2509
0
    _bufferedwriter_reset_buf(self);
2510
0
    self->pos = 0;
2511
2512
0
    self->fast_closed_checks = (Py_IS_TYPE(self, state->PyBufferedRandom_Type) &&
2513
0
                                Py_IS_TYPE(raw, state->PyFileIO_Type));
2514
2515
0
    self->ok = 1;
2516
0
    return 0;
2517
0
}
2518
2519
0
#define clinic_state() (find_io_state_by_def(Py_TYPE(self)))
2520
#include "clinic/bufferedio.c.h"
2521
#undef clinic_state
2522
2523
static PyMethodDef bufferediobase_methods[] = {
2524
    _IO__BUFFEREDIOBASE_DETACH_METHODDEF
2525
    _IO__BUFFEREDIOBASE_READ_METHODDEF
2526
    _IO__BUFFEREDIOBASE_READ1_METHODDEF
2527
    _IO__BUFFEREDIOBASE_READINTO_METHODDEF
2528
    _IO__BUFFEREDIOBASE_READINTO1_METHODDEF
2529
    _IO__BUFFEREDIOBASE_WRITE_METHODDEF
2530
    {NULL, NULL}
2531
};
2532
2533
static PyType_Slot bufferediobase_slots[] = {
2534
    {Py_tp_doc, (void *)bufferediobase_doc},
2535
    {Py_tp_methods, bufferediobase_methods},
2536
    {0, NULL},
2537
};
2538
2539
/* Do not set Py_TPFLAGS_HAVE_GC so that tp_traverse and tp_clear are inherited */
2540
PyType_Spec _Py_bufferediobase_spec = {
2541
    .name = "_io._BufferedIOBase",
2542
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
2543
              Py_TPFLAGS_IMMUTABLETYPE),
2544
    .slots = bufferediobase_slots,
2545
};
2546
2547
static PyMethodDef bufferedreader_methods[] = {
2548
    /* BufferedIOMixin methods */
2549
    _IO__BUFFERED_DETACH_METHODDEF
2550
    _IO__BUFFERED_SIMPLE_FLUSH_METHODDEF
2551
    _IO__BUFFERED_CLOSE_METHODDEF
2552
    _IO__BUFFERED_SEEKABLE_METHODDEF
2553
    _IO__BUFFERED_READABLE_METHODDEF
2554
    _IO__BUFFERED_FILENO_METHODDEF
2555
    _IO__BUFFERED_ISATTY_METHODDEF
2556
    _IO__BUFFERED__DEALLOC_WARN_METHODDEF
2557
2558
    _IO__BUFFERED_READ_METHODDEF
2559
    _IO__BUFFERED_PEEK_METHODDEF
2560
    _IO__BUFFERED_READ1_METHODDEF
2561
    _IO__BUFFERED_READINTO_METHODDEF
2562
    _IO__BUFFERED_READINTO1_METHODDEF
2563
    _IO__BUFFERED_READLINE_METHODDEF
2564
    _IO__BUFFERED_SEEK_METHODDEF
2565
    _IO__BUFFERED_TELL_METHODDEF
2566
    _IO__BUFFERED_TRUNCATE_METHODDEF
2567
    _IO__BUFFERED___SIZEOF___METHODDEF
2568
2569
    {"__getstate__", _PyIOBase_cannot_pickle, METH_NOARGS},
2570
    {NULL, NULL}
2571
};
2572
2573
static PyMemberDef bufferedreader_members[] = {
2574
    {"raw", _Py_T_OBJECT, offsetof(buffered, raw), Py_READONLY},
2575
    {"_finalizing", Py_T_BOOL, offsetof(buffered, finalizing), 0},
2576
    {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(buffered, weakreflist), Py_READONLY},
2577
    {"__dictoffset__", Py_T_PYSSIZET, offsetof(buffered, dict), Py_READONLY},
2578
    {NULL}
2579
};
2580
2581
static PyGetSetDef bufferedreader_getset[] = {
2582
    _IO__BUFFERED_CLOSED_GETSETDEF
2583
    _IO__BUFFERED_NAME_GETSETDEF
2584
    _IO__BUFFERED_MODE_GETSETDEF
2585
    {NULL}
2586
};
2587
2588
2589
static PyType_Slot bufferedreader_slots[] = {
2590
    {Py_tp_dealloc, buffered_dealloc},
2591
    {Py_tp_repr, buffered_repr},
2592
    {Py_tp_doc, (void *)_io_BufferedReader___init____doc__},
2593
    {Py_tp_traverse, buffered_traverse},
2594
    {Py_tp_clear, buffered_clear},
2595
    {Py_tp_iternext, buffered_iternext},
2596
    {Py_tp_methods, bufferedreader_methods},
2597
    {Py_tp_members, bufferedreader_members},
2598
    {Py_tp_getset, bufferedreader_getset},
2599
    {Py_tp_init, _io_BufferedReader___init__},
2600
    {0, NULL},
2601
};
2602
2603
PyType_Spec _Py_bufferedreader_spec = {
2604
    .name = "_io.BufferedReader",
2605
    .basicsize = sizeof(buffered),
2606
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
2607
              Py_TPFLAGS_IMMUTABLETYPE),
2608
    .slots = bufferedreader_slots,
2609
};
2610
2611
static PyMethodDef bufferedwriter_methods[] = {
2612
    /* BufferedIOMixin methods */
2613
    _IO__BUFFERED_CLOSE_METHODDEF
2614
    _IO__BUFFERED_DETACH_METHODDEF
2615
    _IO__BUFFERED_SEEKABLE_METHODDEF
2616
    _IO__BUFFERED_WRITABLE_METHODDEF
2617
    _IO__BUFFERED_FILENO_METHODDEF
2618
    _IO__BUFFERED_ISATTY_METHODDEF
2619
    _IO__BUFFERED__DEALLOC_WARN_METHODDEF
2620
2621
    _IO_BUFFEREDWRITER_WRITE_METHODDEF
2622
    _IO__BUFFERED_TRUNCATE_METHODDEF
2623
    _IO__BUFFERED_FLUSH_METHODDEF
2624
    _IO__BUFFERED_SEEK_METHODDEF
2625
    _IO__BUFFERED_TELL_METHODDEF
2626
    _IO__BUFFERED___SIZEOF___METHODDEF
2627
2628
    {"__getstate__", _PyIOBase_cannot_pickle, METH_NOARGS},
2629
    {NULL, NULL}
2630
};
2631
2632
static PyMemberDef bufferedwriter_members[] = {
2633
    {"raw", _Py_T_OBJECT, offsetof(buffered, raw), Py_READONLY},
2634
    {"_finalizing", Py_T_BOOL, offsetof(buffered, finalizing), 0},
2635
    {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(buffered, weakreflist), Py_READONLY},
2636
    {"__dictoffset__", Py_T_PYSSIZET, offsetof(buffered, dict), Py_READONLY},
2637
    {NULL}
2638
};
2639
2640
static PyGetSetDef bufferedwriter_getset[] = {
2641
    _IO__BUFFERED_CLOSED_GETSETDEF
2642
    _IO__BUFFERED_NAME_GETSETDEF
2643
    _IO__BUFFERED_MODE_GETSETDEF
2644
    {NULL}
2645
};
2646
2647
2648
static PyType_Slot bufferedwriter_slots[] = {
2649
    {Py_tp_dealloc, buffered_dealloc},
2650
    {Py_tp_repr, buffered_repr},
2651
    {Py_tp_doc, (void *)_io_BufferedWriter___init____doc__},
2652
    {Py_tp_traverse, buffered_traverse},
2653
    {Py_tp_clear, buffered_clear},
2654
    {Py_tp_methods, bufferedwriter_methods},
2655
    {Py_tp_members, bufferedwriter_members},
2656
    {Py_tp_getset, bufferedwriter_getset},
2657
    {Py_tp_init, _io_BufferedWriter___init__},
2658
    {0, NULL},
2659
};
2660
2661
PyType_Spec _Py_bufferedwriter_spec = {
2662
    .name = "_io.BufferedWriter",
2663
    .basicsize = sizeof(buffered),
2664
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
2665
              Py_TPFLAGS_IMMUTABLETYPE),
2666
    .slots = bufferedwriter_slots,
2667
};
2668
2669
static PyMethodDef bufferedrwpair_methods[] = {
2670
    {"read", bufferedrwpair_read, METH_VARARGS},
2671
    {"peek", bufferedrwpair_peek, METH_VARARGS},
2672
    {"read1", bufferedrwpair_read1, METH_VARARGS},
2673
    {"readinto", bufferedrwpair_readinto, METH_VARARGS},
2674
    {"readinto1", bufferedrwpair_readinto1, METH_VARARGS},
2675
2676
    {"write", bufferedrwpair_write, METH_VARARGS},
2677
    {"flush", bufferedrwpair_flush, METH_NOARGS},
2678
2679
    {"readable", bufferedrwpair_readable, METH_NOARGS},
2680
    {"writable", bufferedrwpair_writable, METH_NOARGS},
2681
2682
    {"close", bufferedrwpair_close, METH_NOARGS},
2683
    {"isatty", bufferedrwpair_isatty, METH_NOARGS},
2684
2685
    {NULL, NULL}
2686
};
2687
2688
static PyMemberDef bufferedrwpair_members[] = {
2689
    {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(rwpair, weakreflist), Py_READONLY},
2690
    {"__dictoffset__", Py_T_PYSSIZET, offsetof(rwpair, dict), Py_READONLY},
2691
    {NULL}
2692
};
2693
2694
static PyGetSetDef bufferedrwpair_getset[] = {
2695
    {"closed", bufferedrwpair_closed_get, NULL, NULL},
2696
    {NULL}
2697
};
2698
2699
static PyType_Slot bufferedrwpair_slots[] = {
2700
    {Py_tp_dealloc, bufferedrwpair_dealloc},
2701
    {Py_tp_doc, (void *)_io_BufferedRWPair___init____doc__},
2702
    {Py_tp_traverse, bufferedrwpair_traverse},
2703
    {Py_tp_clear, bufferedrwpair_clear},
2704
    {Py_tp_methods, bufferedrwpair_methods},
2705
    {Py_tp_members, bufferedrwpair_members},
2706
    {Py_tp_getset, bufferedrwpair_getset},
2707
    {Py_tp_init, _io_BufferedRWPair___init__},
2708
    {0, NULL},
2709
};
2710
2711
PyType_Spec _Py_bufferedrwpair_spec = {
2712
    .name = "_io.BufferedRWPair",
2713
    .basicsize = sizeof(rwpair),
2714
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
2715
              Py_TPFLAGS_IMMUTABLETYPE),
2716
    .slots = bufferedrwpair_slots,
2717
};
2718
2719
2720
static PyMethodDef bufferedrandom_methods[] = {
2721
    /* BufferedIOMixin methods */
2722
    _IO__BUFFERED_CLOSE_METHODDEF
2723
    _IO__BUFFERED_DETACH_METHODDEF
2724
    _IO__BUFFERED_SEEKABLE_METHODDEF
2725
    _IO__BUFFERED_READABLE_METHODDEF
2726
    _IO__BUFFERED_WRITABLE_METHODDEF
2727
    _IO__BUFFERED_FILENO_METHODDEF
2728
    _IO__BUFFERED_ISATTY_METHODDEF
2729
    _IO__BUFFERED__DEALLOC_WARN_METHODDEF
2730
2731
    _IO__BUFFERED_FLUSH_METHODDEF
2732
2733
    _IO__BUFFERED_SEEK_METHODDEF
2734
    _IO__BUFFERED_TELL_METHODDEF
2735
    _IO__BUFFERED_TRUNCATE_METHODDEF
2736
    _IO__BUFFERED_READ_METHODDEF
2737
    _IO__BUFFERED_READ1_METHODDEF
2738
    _IO__BUFFERED_READINTO_METHODDEF
2739
    _IO__BUFFERED_READINTO1_METHODDEF
2740
    _IO__BUFFERED_READLINE_METHODDEF
2741
    _IO__BUFFERED_PEEK_METHODDEF
2742
    _IO_BUFFEREDWRITER_WRITE_METHODDEF
2743
    _IO__BUFFERED___SIZEOF___METHODDEF
2744
2745
    {"__getstate__", _PyIOBase_cannot_pickle, METH_NOARGS},
2746
    {NULL, NULL}
2747
};
2748
2749
static PyMemberDef bufferedrandom_members[] = {
2750
    {"raw", _Py_T_OBJECT, offsetof(buffered, raw), Py_READONLY},
2751
    {"_finalizing", Py_T_BOOL, offsetof(buffered, finalizing), 0},
2752
    {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(buffered, weakreflist), Py_READONLY},
2753
    {"__dictoffset__", Py_T_PYSSIZET, offsetof(buffered, dict), Py_READONLY},
2754
    {NULL}
2755
};
2756
2757
static PyGetSetDef bufferedrandom_getset[] = {
2758
    _IO__BUFFERED_CLOSED_GETSETDEF
2759
    _IO__BUFFERED_NAME_GETSETDEF
2760
    _IO__BUFFERED_MODE_GETSETDEF
2761
    {NULL}
2762
};
2763
2764
2765
static PyType_Slot bufferedrandom_slots[] = {
2766
    {Py_tp_dealloc, buffered_dealloc},
2767
    {Py_tp_repr, buffered_repr},
2768
    {Py_tp_doc, (void *)_io_BufferedRandom___init____doc__},
2769
    {Py_tp_traverse, buffered_traverse},
2770
    {Py_tp_clear, buffered_clear},
2771
    {Py_tp_iternext, buffered_iternext},
2772
    {Py_tp_methods, bufferedrandom_methods},
2773
    {Py_tp_members, bufferedrandom_members},
2774
    {Py_tp_getset, bufferedrandom_getset},
2775
    {Py_tp_init, _io_BufferedRandom___init__},
2776
    {0, NULL},
2777
};
2778
2779
PyType_Spec _Py_bufferedrandom_spec = {
2780
    .name = "_io.BufferedRandom",
2781
    .basicsize = sizeof(buffered),
2782
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
2783
              Py_TPFLAGS_IMMUTABLETYPE),
2784
    .slots = bufferedrandom_slots,
2785
};