Coverage Report

Created: 2025-07-11 06:59

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