Coverage Report

Created: 2025-08-26 06:26

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