Coverage Report

Created: 2025-07-04 06:49

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