Coverage Report

Created: 2026-10-31 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Modules/_io/textio.c
Line
Count
Source
1
/*
2
    An implementation of Text I/O as defined by PEP 3116 - "New I/O"
3
4
    Classes defined here: TextIOBase, IncrementalNewlineDecoder, TextIOWrapper.
5
6
    Written by Amaury Forgeot d'Arc and Antoine Pitrou
7
*/
8
9
#include "Python.h"
10
#include "pycore_call.h"          // _PyObject_CallMethod()
11
#include "pycore_codecs.h"        // _PyCodecInfo_GetIncrementalDecoder()
12
#include "pycore_fileutils.h"     // _Py_GetLocaleEncoding()
13
#include "pycore_interp.h"        // PyInterpreterState.fs_codec
14
#include "pycore_long.h"          // _PyLong_GetZero()
15
#include "pycore_object.h"        // _PyObject_GC_UNTRACK()
16
#include "pycore_pyerrors.h"      // _PyErr_ChainExceptions1()
17
#include "pycore_pystate.h"       // _PyInterpreterState_GET()
18
#include "pycore_unicodeobject.h" // _PyUnicode_AsASCIIString()
19
#include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS()
20
21
#include "_iomodule.h"
22
23
/*[clinic input]
24
module _io
25
class _io.IncrementalNewlineDecoder "nldecoder_object *" "clinic_state()->PyIncrementalNewlineDecoder_Type"
26
class _io.TextIOWrapper "textio *" "clinic_state()->TextIOWrapper_Type"
27
class _io._TextIOBase "PyObject *" "&PyTextIOBase_Type"
28
[clinic start generated code]*/
29
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8b7f24fa13bfdd7f]*/
30
31
typedef struct nldecoder_object nldecoder_object;
32
typedef struct textio textio;
33
34
#define clinic_state() (find_io_state_by_def(Py_TYPE(self)))
35
#include "clinic/textio.c.h"
36
#undef clinic_state
37
38
/* TextIOBase */
39
40
PyDoc_STRVAR(textiobase_doc,
41
    "Base class for text I/O.\n"
42
    "\n"
43
    "This class provides a character and line based interface to stream\n"
44
    "I/O. There is no readinto method because Python's character strings\n"
45
    "are immutable.\n"
46
    );
47
48
static PyObject *
49
_unsupported(_PyIO_State *state, const char *message)
50
0
{
51
0
    PyErr_SetString(state->unsupported_operation, message);
52
0
    return NULL;
53
0
}
54
55
/*[clinic input]
56
_io._TextIOBase.detach
57
    cls: defining_class
58
    /
59
60
Separate the underlying buffer from the TextIOBase and return it.
61
62
After the underlying buffer has been detached, the TextIO is in
63
an unusable state.
64
[clinic start generated code]*/
65
66
static PyObject *
67
_io__TextIOBase_detach_impl(PyObject *self, PyTypeObject *cls)
68
/*[clinic end generated code: output=50915f40c609eaa4 input=8099c088abcb87d8]*/
69
0
{
70
0
    _PyIO_State *state = get_io_state_by_cls(cls);
71
0
    return _unsupported(state, "detach");
72
0
}
73
74
/*[clinic input]
75
_io._TextIOBase.read
76
    cls: defining_class
77
    size: int(unused=True) = -1
78
    /
79
80
Read at most size characters from stream.
81
82
Read from underlying buffer until we have size characters or we hit
83
EOF.  If size is negative or omitted, read until EOF.
84
[clinic start generated code]*/
85
86
static PyObject *
87
_io__TextIOBase_read_impl(PyObject *self, PyTypeObject *cls,
88
                          int Py_UNUSED(size))
89
/*[clinic end generated code: output=51a5178a309ce647 input=c9fd4cc1cf1b4614]*/
90
0
{
91
0
    _PyIO_State *state = get_io_state_by_cls(cls);
92
0
    return _unsupported(state, "read");
93
0
}
94
95
/*[clinic input]
96
_io._TextIOBase.readline
97
    cls: defining_class
98
    size: int(unused=True) = -1
99
    /
100
101
Read until newline or EOF.
102
103
Return an empty string if EOF is hit immediately.
104
If size is specified, at most size characters will be read.
105
[clinic start generated code]*/
106
107
static PyObject *
108
_io__TextIOBase_readline_impl(PyObject *self, PyTypeObject *cls,
109
                              int Py_UNUSED(size))
110
/*[clinic end generated code: output=3f47d7966d6d074e input=42eafec94107fa27]*/
111
0
{
112
0
    _PyIO_State *state = get_io_state_by_cls(cls);
113
0
    return _unsupported(state, "readline");
114
0
}
115
116
/*[clinic input]
117
_io._TextIOBase.write
118
    cls: defining_class
119
    s: str(unused=True)
120
    /
121
122
Write string s to stream.
123
124
Return the number of characters written
125
(which is always equal to the length of the string).
126
[clinic start generated code]*/
127
128
static PyObject *
129
_io__TextIOBase_write_impl(PyObject *self, PyTypeObject *cls,
130
                           const char *Py_UNUSED(s))
131
/*[clinic end generated code: output=18b28231460275de input=e9cabaa5f6732b07]*/
132
0
{
133
0
    _PyIO_State *state = get_io_state_by_cls(cls);
134
0
    return _unsupported(state, "write");
135
0
}
136
137
/*[clinic input]
138
@getter
139
_io._TextIOBase.encoding
140
141
Encoding of the text stream.
142
143
Subclasses should override.
144
[clinic start generated code]*/
145
146
static PyObject *
147
_io__TextIOBase_encoding_get_impl(PyObject *self)
148
/*[clinic end generated code: output=e0f5d8f548b92432 input=4736d7621dd38f43]*/
149
0
{
150
0
    Py_RETURN_NONE;
151
0
}
152
153
/*[clinic input]
154
@getter
155
_io._TextIOBase.newlines
156
157
Line endings translated so far.
158
159
Only line endings translated during reading are considered.
160
161
Subclasses should override.
162
[clinic start generated code]*/
163
164
static PyObject *
165
_io__TextIOBase_newlines_get_impl(PyObject *self)
166
/*[clinic end generated code: output=46ec147fb9f00c2a input=a5b196d076af1164]*/
167
0
{
168
0
    Py_RETURN_NONE;
169
0
}
170
171
/*[clinic input]
172
@getter
173
_io._TextIOBase.errors
174
175
The error setting of the decoder or encoder.
176
177
Subclasses should override.
178
[clinic start generated code]*/
179
180
static PyObject *
181
_io__TextIOBase_errors_get_impl(PyObject *self)
182
/*[clinic end generated code: output=c6623d6addcd087d input=974aa52d1db93a82]*/
183
0
{
184
0
    Py_RETURN_NONE;
185
0
}
186
187
188
static PyMethodDef textiobase_methods[] = {
189
    _IO__TEXTIOBASE_DETACH_METHODDEF
190
    _IO__TEXTIOBASE_READ_METHODDEF
191
    _IO__TEXTIOBASE_READLINE_METHODDEF
192
    _IO__TEXTIOBASE_WRITE_METHODDEF
193
    {NULL, NULL}
194
};
195
196
static PyGetSetDef textiobase_getset[] = {
197
    _IO__TEXTIOBASE_ENCODING_GETSETDEF
198
    _IO__TEXTIOBASE_NEWLINES_GETSETDEF
199
    _IO__TEXTIOBASE_ERRORS_GETSETDEF
200
    {NULL}
201
};
202
203
static PyType_Slot textiobase_slots[] = {
204
    {Py_tp_doc, (void *)textiobase_doc},
205
    {Py_tp_methods, textiobase_methods},
206
    {Py_tp_getset, textiobase_getset},
207
    {0, NULL},
208
};
209
210
/* Do not set Py_TPFLAGS_HAVE_GC so that tp_traverse and tp_clear are inherited */
211
PyType_Spec _Py_textiobase_spec = {
212
    .name = "_io._TextIOBase",
213
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
214
              Py_TPFLAGS_IMMUTABLETYPE),
215
    .slots = textiobase_slots,
216
};
217
218
/* IncrementalNewlineDecoder */
219
220
struct nldecoder_object {
221
    PyObject_HEAD
222
    PyObject *decoder;
223
    PyObject *errors;
224
    unsigned int pendingcr: 1;
225
    unsigned int translate: 1;
226
    unsigned int seennl: 3;
227
};
228
229
106k
#define nldecoder_object_CAST(op)   ((nldecoder_object *)(op))
230
231
/*[clinic input]
232
_io.IncrementalNewlineDecoder.__init__
233
    decoder: object
234
    translate: bool
235
    errors: object(c_default="NULL") = "strict"
236
237
Codec used when reading a file in universal newlines mode.
238
239
It wraps another incremental decoder, translating \r\n and \r into \n.
240
It also records the types of newlines encountered.  When used with
241
translate=False, it ensures that the newline sequence is returned in
242
one piece. When used with decoder=None, it expects unicode strings as
243
decode input and translates newlines without first invoking an external
244
decoder.
245
[clinic start generated code]*/
246
247
static int
248
_io_IncrementalNewlineDecoder___init___impl(nldecoder_object *self,
249
                                            PyObject *decoder, int translate,
250
                                            PyObject *errors)
251
/*[clinic end generated code: output=fbd04d443e764ec2 input=ed547aa257616b0e]*/
252
16.5k
{
253
254
16.5k
    if (errors == NULL) {
255
16.5k
        errors = &_Py_ID(strict);
256
16.5k
    }
257
0
    else {
258
0
        errors = Py_NewRef(errors);
259
0
    }
260
261
16.5k
    Py_XSETREF(self->errors, errors);
262
16.5k
    Py_XSETREF(self->decoder, Py_NewRef(decoder));
263
16.5k
    self->translate = translate ? 1 : 0;
264
16.5k
    self->seennl = 0;
265
16.5k
    self->pendingcr = 0;
266
267
16.5k
    return 0;
268
16.5k
}
269
270
static int
271
incrementalnewlinedecoder_traverse(PyObject *op, visitproc visit, void *arg)
272
5.65k
{
273
5.65k
    nldecoder_object *self = nldecoder_object_CAST(op);
274
5.65k
    Py_VISIT(Py_TYPE(self));
275
5.65k
    Py_VISIT(self->decoder);
276
5.65k
    Py_VISIT(self->errors);
277
5.65k
    return 0;
278
5.65k
}
279
280
static int
281
incrementalnewlinedecoder_clear(PyObject *op)
282
16.5k
{
283
16.5k
    nldecoder_object *self = nldecoder_object_CAST(op);
284
16.5k
    Py_CLEAR(self->decoder);
285
16.5k
    Py_CLEAR(self->errors);
286
16.5k
    return 0;
287
16.5k
}
288
289
static void
290
incrementalnewlinedecoder_dealloc(PyObject *op)
291
16.5k
{
292
16.5k
    nldecoder_object *self = nldecoder_object_CAST(op);
293
16.5k
    PyTypeObject *tp = Py_TYPE(self);
294
16.5k
    _PyObject_GC_UNTRACK(self);
295
16.5k
    (void)incrementalnewlinedecoder_clear(op);
296
16.5k
    tp->tp_free(self);
297
16.5k
    Py_DECREF(tp);
298
16.5k
}
299
300
static int
301
check_decoded(PyObject *decoded)
302
67.8k
{
303
67.8k
    if (decoded == NULL)
304
0
        return -1;
305
67.8k
    if (!PyUnicode_Check(decoded)) {
306
0
        PyErr_Format(PyExc_TypeError,
307
0
                     "decoder should return a string result, not '%.200s'",
308
0
                     Py_TYPE(decoded)->tp_name);
309
0
        Py_DECREF(decoded);
310
0
        return -1;
311
0
    }
312
67.8k
    return 0;
313
67.8k
}
314
315
#define CHECK_INITIALIZED_DECODER(self) \
316
67.6k
    if (self->errors == NULL) { \
317
0
        PyErr_SetString(PyExc_ValueError, \
318
0
                        "IncrementalNewlineDecoder.__init__() not called"); \
319
0
        return NULL; \
320
0
    }
321
322
38.5M
#define SEEN_CR   1
323
33.4M
#define SEEN_LF   2
324
31.5M
#define SEEN_CRLF 4
325
31.5M
#define SEEN_ALL (SEEN_CR | SEEN_LF | SEEN_CRLF)
326
327
PyObject *
328
_PyIncrementalNewlineDecoder_decode(PyObject *myself,
329
                                    PyObject *input, int final)
330
67.6k
{
331
67.6k
    PyObject *output;
332
67.6k
    Py_ssize_t output_len;
333
67.6k
    nldecoder_object *self = nldecoder_object_CAST(myself);
334
335
67.6k
    CHECK_INITIALIZED_DECODER(self);
336
337
    /* decode input (with the eventual \r from a previous pass) */
338
67.6k
    if (self->decoder != Py_None) {
339
        /* The wrapper can be reinitialized by a decoding callback. */
340
138
        PyObject *decoder = Py_NewRef(self->decoder);
341
138
        output = PyObject_CallMethodObjArgs(decoder,
342
138
            &_Py_ID(decode), input, final ? Py_True : Py_False, NULL);
343
138
        Py_DECREF(decoder);
344
138
    }
345
67.5k
    else {
346
67.5k
        output = Py_NewRef(input);
347
67.5k
    }
348
349
67.6k
    if (check_decoded(output) < 0)
350
0
        return NULL;
351
352
67.6k
    output_len = PyUnicode_GET_LENGTH(output);
353
67.6k
    if (self->pendingcr && (final || output_len > 0)) {
354
        /* Prefix output with CR */
355
0
        int kind;
356
0
        PyObject *modified;
357
0
        char *out;
358
359
0
        modified = PyUnicode_New(output_len + 1,
360
0
                                 PyUnicode_MAX_CHAR_VALUE(output));
361
0
        if (modified == NULL)
362
0
            goto error;
363
0
        kind = PyUnicode_KIND(modified);
364
0
        out = PyUnicode_DATA(modified);
365
0
        PyUnicode_WRITE(kind, out, 0, '\r');
366
0
        memcpy(out + kind, PyUnicode_DATA(output), kind * output_len);
367
0
        Py_SETREF(output, modified);
368
0
        self->pendingcr = 0;
369
0
        output_len++;
370
0
    }
371
372
    /* retain last \r even when not translating data:
373
     * then readline() is sure to get \r\n in one pass
374
     */
375
67.6k
    if (!final) {
376
120
        if (output_len > 0
377
120
            && PyUnicode_READ_CHAR(output, output_len - 1) == '\r')
378
0
        {
379
0
            PyObject *modified = PyUnicode_Substring(output, 0, output_len -1);
380
0
            if (modified == NULL)
381
0
                goto error;
382
0
            Py_SETREF(output, modified);
383
0
            self->pendingcr = 1;
384
0
        }
385
120
    }
386
387
    /* Record which newlines are read and do newline translation if desired,
388
       all in one pass. */
389
67.6k
    {
390
67.6k
        const void *in_str;
391
67.6k
        Py_ssize_t len;
392
67.6k
        int seennl = self->seennl;
393
67.6k
        int only_lf = 0;
394
67.6k
        int kind;
395
396
67.6k
        in_str = PyUnicode_DATA(output);
397
67.6k
        len = PyUnicode_GET_LENGTH(output);
398
67.6k
        kind = PyUnicode_KIND(output);
399
400
67.6k
        if (len == 0)
401
10
            return output;
402
403
        /* If, up to now, newlines are consistently \n, do a quick check
404
           for the \r *byte* with the libc's optimized memchr.
405
           */
406
67.6k
        if (seennl == SEEN_LF || seennl == 0) {
407
33.5k
            only_lf = (memchr(in_str, '\r', kind * len) == NULL);
408
33.5k
        }
409
410
67.6k
        if (only_lf) {
411
            /* If not already seen, quick scan for a possible "\n" character.
412
               (there's nothing else to be done, even when in translation mode)
413
            */
414
27.1k
            if (seennl == 0 &&
415
18.0k
                memchr(in_str, '\n', kind * len) != NULL) {
416
1.98k
                if (kind == PyUnicode_1BYTE_KIND)
417
905
                    seennl |= SEEN_LF;
418
1.08k
                else {
419
1.08k
                    Py_ssize_t i = 0;
420
208k
                    for (;;) {
421
208k
                        Py_UCS4 c;
422
                        /* Fast loop for non-control characters */
423
1.56M
                        while (PyUnicode_READ(kind, in_str, i) > '\n')
424
1.35M
                            i++;
425
208k
                        c = PyUnicode_READ(kind, in_str, i++);
426
208k
                        if (c == '\n') {
427
821
                            seennl |= SEEN_LF;
428
821
                            break;
429
821
                        }
430
207k
                        if (i >= len)
431
260
                            break;
432
207k
                    }
433
1.08k
                }
434
1.98k
            }
435
            /* Finished: we have scanned for newlines, and none of them
436
               need translating */
437
27.1k
        }
438
40.5k
        else if (!self->translate) {
439
40.5k
            Py_ssize_t i = 0;
440
            /* We have already seen all newline types, no need to scan again */
441
40.5k
            if (seennl == SEEN_ALL)
442
14.4k
                goto endscan;
443
31.5M
            for (;;) {
444
31.5M
                Py_UCS4 c;
445
                /* Fast loop for non-control characters */
446
85.0M
                while (PyUnicode_READ(kind, in_str, i) > '\r')
447
53.5M
                    i++;
448
31.5M
                c = PyUnicode_READ(kind, in_str, i++);
449
31.5M
                if (c == '\n')
450
1.83M
                    seennl |= SEEN_LF;
451
29.6M
                else if (c == '\r') {
452
7.05M
                    if (PyUnicode_READ(kind, in_str, i) == '\n') {
453
4.50k
                        seennl |= SEEN_CRLF;
454
4.50k
                        i++;
455
4.50k
                    }
456
7.05M
                    else
457
7.05M
                        seennl |= SEEN_CR;
458
7.05M
                }
459
31.5M
                if (i >= len)
460
24.7k
                    break;
461
31.4M
                if (seennl == SEEN_ALL)
462
1.29k
                    break;
463
31.4M
            }
464
40.5k
        endscan:
465
40.5k
            ;
466
40.5k
        }
467
0
        else {
468
0
            void *translated;
469
0
            int kind = PyUnicode_KIND(output);
470
0
            const void *in_str = PyUnicode_DATA(output);
471
0
            Py_ssize_t in, out;
472
            /* XXX: Previous in-place translation here is disabled as
473
               resizing is not possible anymore */
474
            /* We could try to optimize this so that we only do a copy
475
               when there is something to translate. On the other hand,
476
               we already know there is a \r byte, so chances are high
477
               that something needs to be done. */
478
0
            translated = PyMem_Malloc(kind * len);
479
0
            if (translated == NULL) {
480
0
                PyErr_NoMemory();
481
0
                goto error;
482
0
            }
483
0
            in = out = 0;
484
0
            for (;;) {
485
0
                Py_UCS4 c;
486
                /* Fast loop for non-control characters */
487
0
                while ((c = PyUnicode_READ(kind, in_str, in++)) > '\r')
488
0
                    PyUnicode_WRITE(kind, translated, out++, c);
489
0
                if (c == '\n') {
490
0
                    PyUnicode_WRITE(kind, translated, out++, c);
491
0
                    seennl |= SEEN_LF;
492
0
                    continue;
493
0
                }
494
0
                if (c == '\r') {
495
0
                    if (PyUnicode_READ(kind, in_str, in) == '\n') {
496
0
                        in++;
497
0
                        seennl |= SEEN_CRLF;
498
0
                    }
499
0
                    else
500
0
                        seennl |= SEEN_CR;
501
0
                    PyUnicode_WRITE(kind, translated, out++, '\n');
502
0
                    continue;
503
0
                }
504
0
                if (in > len)
505
0
                    break;
506
0
                PyUnicode_WRITE(kind, translated, out++, c);
507
0
            }
508
0
            Py_DECREF(output);
509
0
            output = PyUnicode_FromKindAndData(kind, translated, out);
510
0
            PyMem_Free(translated);
511
0
            if (!output)
512
0
                return NULL;
513
0
        }
514
67.6k
        self->seennl |= seennl;
515
67.6k
    }
516
517
0
    return output;
518
519
0
  error:
520
0
    Py_DECREF(output);
521
0
    return NULL;
522
67.6k
}
523
524
/*[clinic input]
525
@critical_section
526
_io.IncrementalNewlineDecoder.decode
527
    input: object
528
    final: bool = False
529
[clinic start generated code]*/
530
531
static PyObject *
532
_io_IncrementalNewlineDecoder_decode_impl(nldecoder_object *self,
533
                                          PyObject *input, int final)
534
/*[clinic end generated code: output=0d486755bb37a66e input=9475d16a73168504]*/
535
0
{
536
0
    return _PyIncrementalNewlineDecoder_decode((PyObject *) self, input, final);
537
0
}
538
539
/*[clinic input]
540
@critical_section
541
_io.IncrementalNewlineDecoder.getstate
542
[clinic start generated code]*/
543
544
static PyObject *
545
_io_IncrementalNewlineDecoder_getstate_impl(nldecoder_object *self)
546
/*[clinic end generated code: output=f0d2c9c136f4e0d0 input=dc3e1f27aa850f12]*/
547
0
{
548
0
    PyObject *buffer;
549
0
    unsigned long long flag;
550
551
0
    CHECK_INITIALIZED_DECODER(self);
552
553
0
    if (self->decoder != Py_None) {
554
0
        PyObject *state = PyObject_CallMethodNoArgs(self->decoder,
555
0
           &_Py_ID(getstate));
556
0
        if (state == NULL)
557
0
            return NULL;
558
0
        if (!PyTuple_Check(state)) {
559
0
            PyErr_SetString(PyExc_TypeError,
560
0
                            "illegal decoder state");
561
0
            Py_DECREF(state);
562
0
            return NULL;
563
0
        }
564
0
        if (!PyArg_ParseTuple(state, "OK;illegal decoder state",
565
0
                              &buffer, &flag))
566
0
        {
567
0
            Py_DECREF(state);
568
0
            return NULL;
569
0
        }
570
0
        Py_INCREF(buffer);
571
0
        Py_DECREF(state);
572
0
    }
573
0
    else {
574
0
        buffer = Py_GetConstant(Py_CONSTANT_EMPTY_BYTES);
575
0
        flag = 0;
576
0
    }
577
0
    flag <<= 1;
578
0
    if (self->pendingcr)
579
0
        flag |= 1;
580
0
    return Py_BuildValue("NK", buffer, flag);
581
0
}
582
583
/*[clinic input]
584
@critical_section
585
_io.IncrementalNewlineDecoder.setstate
586
    state: object
587
    /
588
[clinic start generated code]*/
589
590
static PyObject *
591
_io_IncrementalNewlineDecoder_setstate_impl(nldecoder_object *self,
592
                                            PyObject *state)
593
/*[clinic end generated code: output=09135cb6e78a1dc8 input=275fd3982d2b08cb]*/
594
0
{
595
0
    PyObject *buffer;
596
0
    unsigned long long flag;
597
598
0
    CHECK_INITIALIZED_DECODER(self);
599
600
0
    if (!PyTuple_Check(state)) {
601
0
        PyErr_SetString(PyExc_TypeError, "state argument must be a tuple");
602
0
        return NULL;
603
0
    }
604
0
    if (!PyArg_ParseTuple(state, "OK;setstate(): illegal state argument",
605
0
                          &buffer, &flag))
606
0
    {
607
0
        return NULL;
608
0
    }
609
610
0
    self->pendingcr = (int) (flag & 1);
611
0
    flag >>= 1;
612
613
0
    if (self->decoder != Py_None) {
614
0
        return _PyObject_CallMethod(self->decoder, &_Py_ID(setstate),
615
0
                                    "((OK))", buffer, flag);
616
0
    }
617
0
    else {
618
0
        Py_RETURN_NONE;
619
0
    }
620
0
}
621
622
/*[clinic input]
623
@critical_section
624
_io.IncrementalNewlineDecoder.reset
625
[clinic start generated code]*/
626
627
static PyObject *
628
_io_IncrementalNewlineDecoder_reset_impl(nldecoder_object *self)
629
/*[clinic end generated code: output=32fa40c7462aa8ff input=31bd8ae4e36cec83]*/
630
0
{
631
0
    CHECK_INITIALIZED_DECODER(self);
632
633
0
    self->seennl = 0;
634
0
    self->pendingcr = 0;
635
0
    if (self->decoder != Py_None)
636
0
        return PyObject_CallMethodNoArgs(self->decoder, &_Py_ID(reset));
637
0
    else
638
0
        Py_RETURN_NONE;
639
0
}
640
641
/*[clinic input]
642
@getter
643
_io.IncrementalNewlineDecoder.newlines
644
[clinic start generated code]*/
645
646
static PyObject *
647
_io_IncrementalNewlineDecoder_newlines_get_impl(nldecoder_object *self)
648
/*[clinic end generated code: output=4370cf5202a83d08 input=040f9a26aef317a8]*/
649
0
{
650
0
    CHECK_INITIALIZED_DECODER(self);
651
652
0
    switch (self->seennl) {
653
0
    case SEEN_CR:
654
0
        return PyUnicode_FromString("\r");
655
0
    case SEEN_LF:
656
0
        return PyUnicode_FromString("\n");
657
0
    case SEEN_CRLF:
658
0
        return PyUnicode_FromString("\r\n");
659
0
    case SEEN_CR | SEEN_LF:
660
0
        return Py_BuildValue("ss", "\r", "\n");
661
0
    case SEEN_CR | SEEN_CRLF:
662
0
        return Py_BuildValue("ss", "\r", "\r\n");
663
0
    case SEEN_LF | SEEN_CRLF:
664
0
        return Py_BuildValue("ss", "\n", "\r\n");
665
0
    case SEEN_CR | SEEN_LF | SEEN_CRLF:
666
0
        return Py_BuildValue("sss", "\r", "\n", "\r\n");
667
0
    default:
668
0
        Py_RETURN_NONE;
669
0
   }
670
671
0
}
672
673
/* TextIOWrapper */
674
675
typedef PyObject *(*encodefunc_t)(PyObject *, PyObject *);
676
677
struct textio
678
{
679
    PyObject_HEAD
680
    int ok; /* initialized? */
681
    int detached;
682
    Py_ssize_t chunk_size;
683
    /* Use helpers buffer_*() functions to access buffer; many operations can set it to
684
       NULL (see gh-143008, gh-142594). */
685
    PyObject *buffer;
686
    PyObject *encoding;
687
    PyObject *encoder;
688
    PyObject *decoder;
689
    PyObject *readnl;
690
    PyObject *errors;
691
    const char *writenl; /* ASCII-encoded; NULL stands for \n */
692
    char line_buffering;
693
    char write_through;
694
    char readuniversal;
695
    char readtranslate;
696
    char writetranslate;
697
    char seekable;
698
    char has_read1;
699
    char telling;
700
    char finalizing;
701
    /* Specialized encoding func (see below) */
702
    encodefunc_t encodefunc;
703
    /* Whether or not it's the start of the stream */
704
    char encoding_start_of_stream;
705
706
    /* Reads and writes are internally buffered in order to speed things up.
707
       However, any read will first flush the write buffer if itsn't empty.
708
709
       Please also note that text to be written is first encoded before being
710
       buffered. This is necessary so that encoding errors are immediately
711
       reported to the caller, but it unfortunately means that the
712
       IncrementalEncoder (whose encode() method is always written in Python)
713
       becomes a bottleneck for small writes.
714
    */
715
    PyObject *decoded_chars;       /* buffer for text returned from decoder */
716
    Py_ssize_t decoded_chars_used; /* offset into _decoded_chars for read() */
717
    PyObject *pending_bytes;       // data waiting to be written.
718
                                   // ascii unicode, bytes, or list of them.
719
    Py_ssize_t pending_bytes_count;
720
721
    /* snapshot is either NULL, or a tuple (dec_flags, next_input) where
722
     * dec_flags is the second (integer) item of the decoder state and
723
     * next_input is the chunk of input bytes that comes next after the
724
     * snapshot point.  We use this to reconstruct decoder states in tell().
725
     */
726
    PyObject *snapshot;
727
    /* Bytes-to-characters ratio for the current chunk. Serves as input for
728
       the heuristic in tell(). */
729
    double b2cratio;
730
731
    /* Cache raw object if it's a FileIO object */
732
    PyObject *raw;
733
734
    PyObject *weakreflist;
735
    PyObject *dict;
736
737
    _PyIO_State *state;
738
};
739
740
7.02k
#define textio_CAST(op) ((textio *)(op))
741
742
/* Helpers to safely operate on self->buffer.
743
744
   self->buffer can be detached (set to NULL) by any user code that is called
745
   leading to NULL pointer dereferences (see gh-143008, gh-142594). Protect
746
   against that by using helpers to check self->buffer validity at callsites. */
747
static PyObject *
748
buffer_access_safe(textio *self)
749
289k
{
750
    /* Check self->buffer directly but match errors of CHECK_ATTACHED since this
751
       is called during construction and finalization where self->ok == 0. */
752
289k
    if (self->buffer == NULL) {
753
0
        if (self->ok <= 0) {
754
0
            PyErr_SetString(PyExc_ValueError,
755
0
                            "I/O operation on uninitialized object");
756
0
        }
757
0
        else {
758
0
            PyErr_SetString(PyExc_ValueError,
759
0
                            "underlying buffer has been detached");
760
0
        }
761
0
        return NULL;
762
0
    }
763
764
289k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
765
289k
    return Py_NewRef(self->buffer);
766
289k
}
767
768
static PyObject *
769
buffer_getattr(textio *self, PyObject *attr_name)
770
67
{
771
67
    PyObject *buffer = buffer_access_safe(self);
772
67
    if (buffer == NULL) {
773
0
        return NULL;
774
0
    }
775
776
67
    PyObject *res = PyObject_GetAttr(buffer, attr_name);
777
67
    Py_DECREF(buffer);
778
67
    return res;
779
67
}
780
781
static PyObject *
782
buffer_callmethod_noargs(textio *self, PyObject *name)
783
381
{
784
381
    PyObject *buffer = buffer_access_safe(self);
785
381
    if (buffer == NULL) {
786
0
        return NULL;
787
0
    }
788
789
381
    PyObject *res = PyObject_CallMethodNoArgs(buffer, name);
790
381
    Py_DECREF(buffer);
791
381
    return res;
792
381
}
793
794
static PyObject *
795
buffer_callmethod_onearg(textio *self, PyObject *name, PyObject *arg)
796
144k
{
797
144k
    PyObject *buffer = buffer_access_safe(self);
798
144k
    if (buffer == NULL) {
799
0
        return NULL;
800
0
    }
801
802
144k
    PyObject *res = PyObject_CallMethodOneArg(buffer, name, arg);
803
144k
    Py_DECREF(buffer);
804
144k
    return res;
805
144k
}
806
807
static void
808
textiowrapper_set_decoded_chars(textio *self, PyObject *chars);
809
810
/* A couple of specialized cases in order to bypass the slow incremental
811
   encoding methods for the most popular encodings. */
812
813
static PyObject *
814
ascii_encode(PyObject *op, PyObject *text)
815
0
{
816
0
    textio *self = textio_CAST(op);
817
0
    return _PyUnicode_AsASCIIString(text, PyUnicode_AsUTF8(self->errors));
818
0
}
819
820
static PyObject *
821
utf16be_encode(PyObject *op, PyObject *text)
822
0
{
823
0
    textio *self = textio_CAST(op);
824
0
    return _PyUnicode_EncodeUTF16(text, PyUnicode_AsUTF8(self->errors), 1);
825
0
}
826
827
static PyObject *
828
utf16le_encode(PyObject *op, PyObject *text)
829
0
{
830
0
    textio *self = textio_CAST(op);
831
0
    return _PyUnicode_EncodeUTF16(text, PyUnicode_AsUTF8(self->errors), -1);
832
0
}
833
834
static PyObject *
835
utf16_encode(PyObject *op, PyObject *text)
836
0
{
837
0
    textio *self = textio_CAST(op);
838
0
    if (!self->encoding_start_of_stream) {
839
        /* Skip the BOM and use native byte ordering */
840
#if PY_BIG_ENDIAN
841
        return utf16be_encode(op, text);
842
#else
843
0
        return utf16le_encode(op, text);
844
0
#endif
845
0
    }
846
0
    return _PyUnicode_EncodeUTF16(text, PyUnicode_AsUTF8(self->errors), 0);
847
0
}
848
849
static PyObject *
850
utf32be_encode(PyObject *op, PyObject *text)
851
0
{
852
0
    textio *self = textio_CAST(op);
853
0
    return _PyUnicode_EncodeUTF32(text, PyUnicode_AsUTF8(self->errors), 1);
854
0
}
855
856
static PyObject *
857
utf32le_encode(PyObject *op, PyObject *text)
858
0
{
859
0
    textio *self = textio_CAST(op);
860
0
    return _PyUnicode_EncodeUTF32(text, PyUnicode_AsUTF8(self->errors), -1);
861
0
}
862
863
static PyObject *
864
utf32_encode(PyObject *op, PyObject *text)
865
0
{
866
0
    textio *self = textio_CAST(op);
867
0
    if (!self->encoding_start_of_stream) {
868
        /* Skip the BOM and use native byte ordering */
869
#if PY_BIG_ENDIAN
870
        return utf32be_encode(op, text);
871
#else
872
0
        return utf32le_encode(op, text);
873
0
#endif
874
0
    }
875
0
    return _PyUnicode_EncodeUTF32(text, PyUnicode_AsUTF8(self->errors), 0);
876
0
}
877
878
static PyObject *
879
utf8_encode(PyObject *op, PyObject *text)
880
2.04k
{
881
2.04k
    textio *self = textio_CAST(op);
882
2.04k
    return _PyUnicode_AsUTF8String(text, PyUnicode_AsUTF8(self->errors));
883
2.04k
}
884
885
static PyObject *
886
latin1_encode(PyObject *op, PyObject *text)
887
0
{
888
0
    textio *self = textio_CAST(op);
889
0
    return _PyUnicode_AsLatin1String(text, PyUnicode_AsUTF8(self->errors));
890
0
}
891
892
// Return true when encoding can be skipped when text is ascii.
893
static inline int
894
is_asciicompat_encoding(encodefunc_t f)
895
142k
{
896
142k
    return f == ascii_encode || f == latin1_encode || f == utf8_encode;
897
142k
}
898
899
/* Map normalized encoding names onto the specialized encoding funcs */
900
901
typedef struct {
902
    const char *name;
903
    encodefunc_t encodefunc;
904
} encodefuncentry;
905
906
static const encodefuncentry encodefuncs[] = {
907
    {"ascii",       ascii_encode},
908
    {"iso8859-1",   latin1_encode},
909
    {"utf-8",       utf8_encode},
910
    {"utf-16-be",   utf16be_encode},
911
    {"utf-16-le",   utf16le_encode},
912
    {"utf-16",      utf16_encode},
913
    {"utf-32-be",   utf32be_encode},
914
    {"utf-32-le",   utf32le_encode},
915
    {"utf-32",      utf32_encode},
916
    {NULL, NULL}
917
};
918
919
static int
920
validate_newline(const char *newline)
921
130
{
922
130
    if (newline && newline[0] != '\0'
923
111
        && !(newline[0] == '\n' && newline[1] == '\0')
924
0
        && !(newline[0] == '\r' && newline[1] == '\0')
925
0
        && !(newline[0] == '\r' && newline[1] == '\n' && newline[2] == '\0')) {
926
0
        PyErr_Format(PyExc_ValueError,
927
0
                     "illegal newline value: %s", newline);
928
0
        return -1;
929
0
    }
930
130
    return 0;
931
130
}
932
933
static int
934
set_newline(textio *self, const char *newline)
935
130
{
936
130
    PyObject *old = self->readnl;
937
130
    if (newline == NULL) {
938
19
        self->readnl = NULL;
939
19
    }
940
111
    else {
941
111
        self->readnl = PyUnicode_FromString(newline);
942
111
        if (self->readnl == NULL) {
943
0
            self->readnl = old;
944
0
            return -1;
945
0
        }
946
111
    }
947
130
    self->readuniversal = (newline == NULL || newline[0] == '\0');
948
130
    self->readtranslate = (newline == NULL);
949
130
    self->writetranslate = (newline == NULL || newline[0] != '\0');
950
130
    if (!self->readuniversal && self->readnl != NULL) {
951
        // validate_newline() accepts only ASCII newlines.
952
111
        assert(PyUnicode_KIND(self->readnl) == PyUnicode_1BYTE_KIND);
953
111
        self->writenl = (const char *)PyUnicode_1BYTE_DATA(self->readnl);
954
111
        if (strcmp(self->writenl, "\n") == 0) {
955
111
            self->writenl = NULL;
956
111
        }
957
111
    }
958
19
    else {
959
#ifdef MS_WINDOWS
960
        self->writenl = "\r\n";
961
#else
962
19
        self->writenl = NULL;
963
19
#endif
964
19
    }
965
130
    Py_XDECREF(old);
966
130
    return 0;
967
130
}
968
969
static int
970
_textiowrapper_set_decoder(textio *self, PyObject *codec_info,
971
                           const char *errors)
972
130
{
973
130
    PyObject *res;
974
130
    int r;
975
976
130
    res = buffer_callmethod_noargs(self, &_Py_ID(readable));
977
130
    if (res == NULL)
978
0
        return -1;
979
980
130
    r = PyObject_IsTrue(res);
981
130
    Py_DECREF(res);
982
130
    if (r == -1)
983
0
        return -1;
984
985
130
    if (r != 1)
986
75
        return 0;
987
988
55
    Py_CLEAR(self->decoder);
989
55
    self->decoder = _PyCodecInfo_GetIncrementalDecoder(codec_info, errors);
990
55
    if (self->decoder == NULL)
991
0
        return -1;
992
993
55
    if (self->readuniversal) {
994
18
        _PyIO_State *state = self->state;
995
18
        PyObject *incrementalDecoder = PyObject_CallFunctionObjArgs(
996
18
            (PyObject *)state->PyIncrementalNewlineDecoder_Type,
997
18
            self->decoder, self->readtranslate ? Py_True : Py_False, NULL);
998
18
        if (incrementalDecoder == NULL)
999
0
            return -1;
1000
18
        Py_XSETREF(self->decoder, incrementalDecoder);
1001
18
    }
1002
1003
55
    return 0;
1004
55
}
1005
1006
static PyObject*
1007
_textiowrapper_decode(_PyIO_State *state, PyObject *decoder, PyObject *bytes,
1008
                      int eof)
1009
138
{
1010
138
    PyObject *chars;
1011
1012
138
    if (decoder == NULL) {
1013
0
        return _unsupported(state, "not readable");
1014
0
    }
1015
    /* A codec callback may replace the wrapper's decoder. */
1016
138
    Py_INCREF(decoder);
1017
138
    if (Py_IS_TYPE(decoder, state->PyIncrementalNewlineDecoder_Type))
1018
138
        chars = _PyIncrementalNewlineDecoder_decode(decoder, bytes, eof);
1019
0
    else
1020
0
        chars = PyObject_CallMethodObjArgs(decoder, &_Py_ID(decode), bytes,
1021
0
                                           eof ? Py_True : Py_False, NULL);
1022
138
    Py_DECREF(decoder);
1023
1024
138
    if (check_decoded(chars) < 0)
1025
        // check_decoded already decreases refcount
1026
0
        return NULL;
1027
1028
138
    return chars;
1029
138
}
1030
1031
static int
1032
_textiowrapper_set_encoder(textio *self, PyObject *codec_info,
1033
                           const char *errors)
1034
130
{
1035
130
    PyObject *res;
1036
130
    int r;
1037
1038
130
    res = buffer_callmethod_noargs(self, &_Py_ID(writable));
1039
130
    if (res == NULL)
1040
0
        return -1;
1041
1042
130
    r = PyObject_IsTrue(res);
1043
130
    Py_DECREF(res);
1044
130
    if (r == -1)
1045
0
        return -1;
1046
1047
130
    if (r != 1)
1048
55
        return 0;
1049
1050
75
    Py_CLEAR(self->encoder);
1051
75
    self->encodefunc = NULL;
1052
75
    self->encoder = _PyCodecInfo_GetIncrementalEncoder(codec_info, errors);
1053
75
    if (self->encoder == NULL)
1054
0
        return -1;
1055
1056
    /* Get the normalized named of the codec */
1057
75
    if (PyObject_GetOptionalAttr(codec_info, &_Py_ID(name), &res) < 0) {
1058
0
        return -1;
1059
0
    }
1060
75
    if (res != NULL && PyUnicode_Check(res)) {
1061
75
        const encodefuncentry *e = encodefuncs;
1062
225
        while (e->name != NULL) {
1063
225
            if (_PyUnicode_EqualToASCIIString(res, e->name)) {
1064
75
                self->encodefunc = e->encodefunc;
1065
75
                break;
1066
75
            }
1067
150
            e++;
1068
150
        }
1069
75
    }
1070
75
    Py_XDECREF(res);
1071
1072
75
    return 0;
1073
75
}
1074
1075
static int
1076
_textiowrapper_fix_encoder_state(textio *self)
1077
130
{
1078
130
    if (!self->seekable || !self->encoder) {
1079
55
        return 0;
1080
55
    }
1081
1082
75
    self->encoding_start_of_stream = 1;
1083
1084
75
    PyObject *cookieObj = buffer_callmethod_noargs(self, &_Py_ID(tell));
1085
75
    if (cookieObj == NULL) {
1086
0
        return -1;
1087
0
    }
1088
1089
75
    int cmp = PyObject_RichCompareBool(cookieObj, _PyLong_GetZero(), Py_EQ);
1090
75
    Py_DECREF(cookieObj);
1091
75
    if (cmp < 0) {
1092
0
        return -1;
1093
0
    }
1094
1095
75
    if (cmp == 0) {
1096
36
        self->encoding_start_of_stream = 0;
1097
36
        PyObject *res = PyObject_CallMethodOneArg(
1098
36
            self->encoder, &_Py_ID(setstate), _PyLong_GetZero());
1099
36
        if (res == NULL) {
1100
0
            return -1;
1101
0
        }
1102
36
        Py_DECREF(res);
1103
36
    }
1104
1105
75
    return 0;
1106
75
}
1107
1108
static int
1109
io_check_errors(PyObject *errors)
1110
111
{
1111
111
    assert(errors != NULL && errors != Py_None);
1112
1113
111
    PyInterpreterState *interp = _PyInterpreterState_GET();
1114
111
#ifndef Py_DEBUG
1115
    /* In release mode, only check in development mode (-X dev) */
1116
111
    if (!_PyInterpreterState_GetConfig(interp)->dev_mode) {
1117
111
        return 0;
1118
111
    }
1119
#else
1120
    /* Always check in debug mode */
1121
#endif
1122
1123
    /* Avoid calling PyCodec_LookupError() before the codec registry is ready:
1124
       before_PyUnicode_InitEncodings() is called. */
1125
0
    if (!interp->unicode.fs_codec.encoding) {
1126
0
        return 0;
1127
0
    }
1128
1129
0
    const char *name = _PyUnicode_AsUTF8NoNUL(errors);
1130
0
    if (name == NULL) {
1131
0
        return -1;
1132
0
    }
1133
0
    PyObject *handler = PyCodec_LookupError(name);
1134
0
    if (handler != NULL) {
1135
0
        Py_DECREF(handler);
1136
0
        return 0;
1137
0
    }
1138
0
    return -1;
1139
0
}
1140
1141
1142
1143
/*[clinic input]
1144
@critical_section
1145
_io.TextIOWrapper.__init__
1146
    buffer: object
1147
    encoding: str(accept={str, NoneType}) = None
1148
    errors: object = None
1149
    newline: str(accept={str, NoneType}) = None
1150
    line_buffering: bool = False
1151
    write_through: bool = False
1152
1153
Character and line based layer over a BufferedIOBase object, buffer.
1154
1155
encoding gives the name of the encoding that the stream will be
1156
decoded or encoded with. It defaults to locale.getencoding().
1157
1158
errors determines the strictness of encoding and decoding (see
1159
help(codecs.Codec) or the documentation for codecs.register) and
1160
defaults to "strict".
1161
1162
newline controls how line endings are handled. It can be None, '',
1163
'\n', '\r', and '\r\n'.  It works as follows:
1164
1165
* On input, if newline is None, universal newlines mode is
1166
  enabled. Lines in the input can end in '\n', '\r', or '\r\n', and
1167
  these are translated into '\n' before being returned to the
1168
  caller. If it is '', universal newline mode is enabled, but line
1169
  endings are returned to the caller untranslated. If it has any of
1170
  the other legal values, input lines are only terminated by the given
1171
  string, and the line ending is returned to the caller untranslated.
1172
1173
* On output, if newline is None, any '\n' characters written are
1174
  translated to the system default line separator, os.linesep. If
1175
  newline is '' or '\n', no translation takes place. If newline is any
1176
  of the other legal values, any '\n' characters written are translated
1177
  to the given string.
1178
1179
If line_buffering is True, a call to flush is implied when a call to
1180
write contains a newline character.
1181
[clinic start generated code]*/
1182
1183
static int
1184
_io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
1185
                                const char *encoding, PyObject *errors,
1186
                                const char *newline, int line_buffering,
1187
                                int write_through)
1188
/*[clinic end generated code: output=72267c0c01032ed2 input=0f077220214c40a4]*/
1189
130
{
1190
130
    PyObject *raw, *codec_info = NULL;
1191
130
    PyObject *res;
1192
130
    int r;
1193
1194
130
    self->ok = 0;
1195
130
    self->detached = 0;
1196
1197
130
    if (encoding == NULL) {
1198
0
        PyInterpreterState *interp = _PyInterpreterState_GET();
1199
0
        if (_PyInterpreterState_GetConfig(interp)->warn_default_encoding) {
1200
0
            if (PyErr_WarnEx(PyExc_EncodingWarning,
1201
0
                             "'encoding' argument not specified", 1)) {
1202
0
                return -1;
1203
0
            }
1204
0
        }
1205
0
    }
1206
1207
130
    if (errors == Py_None) {
1208
19
        errors = &_Py_ID(strict);
1209
19
    }
1210
111
    else if (!PyUnicode_Check(errors)) {
1211
        // Check 'errors' argument here because Argument Clinic doesn't support
1212
        // 'str(accept={str, NoneType})' converter.
1213
0
        PyErr_Format(
1214
0
            PyExc_TypeError,
1215
0
            "TextIOWrapper() argument 'errors' must be str or None, not %.50s",
1216
0
            Py_TYPE(errors)->tp_name);
1217
0
        return -1;
1218
0
    }
1219
111
    else if (io_check_errors(errors)) {
1220
0
        return -1;
1221
0
    }
1222
130
    const char *errors_str = _PyUnicode_AsUTF8NoNUL(errors);
1223
130
    if (errors_str == NULL) {
1224
0
        return -1;
1225
0
    }
1226
1227
130
    if (validate_newline(newline) < 0) {
1228
0
        return -1;
1229
0
    }
1230
1231
130
    Py_CLEAR(self->buffer);
1232
130
    Py_CLEAR(self->encoding);
1233
130
    Py_CLEAR(self->encoder);
1234
130
    Py_CLEAR(self->decoder);
1235
130
    Py_CLEAR(self->readnl);
1236
130
    Py_CLEAR(self->decoded_chars);
1237
130
    Py_CLEAR(self->pending_bytes);
1238
130
    Py_CLEAR(self->snapshot);
1239
130
    Py_CLEAR(self->errors);
1240
130
    Py_CLEAR(self->raw);
1241
130
    self->decoded_chars_used = 0;
1242
130
    self->pending_bytes_count = 0;
1243
130
    self->encodefunc = NULL;
1244
130
    self->b2cratio = 0.0;
1245
1246
130
    if (encoding == NULL && _PyRuntime.preconfig.utf8_mode) {
1247
0
        _Py_DECLARE_STR(utf_8, "utf-8");
1248
0
        self->encoding = &_Py_STR(utf_8);
1249
0
    }
1250
130
    else if (encoding == NULL || (strcmp(encoding, "locale") == 0)) {
1251
0
        self->encoding = _Py_GetLocaleEncodingObject();
1252
0
        if (self->encoding == NULL) {
1253
0
            goto error;
1254
0
        }
1255
0
        assert(PyUnicode_Check(self->encoding));
1256
0
    }
1257
1258
130
    if (self->encoding != NULL) {
1259
0
        encoding = PyUnicode_AsUTF8(self->encoding);
1260
0
        if (encoding == NULL)
1261
0
            goto error;
1262
0
    }
1263
130
    else if (encoding != NULL) {
1264
130
        self->encoding = PyUnicode_FromString(encoding);
1265
130
        if (self->encoding == NULL)
1266
0
            goto error;
1267
130
    }
1268
0
    else {
1269
0
        PyErr_SetString(PyExc_OSError,
1270
0
                        "could not determine default encoding");
1271
0
        goto error;
1272
0
    }
1273
1274
    /* Check we have been asked for a real text encoding */
1275
130
    codec_info = _PyCodec_LookupTextEncoding(encoding, NULL);
1276
130
    if (codec_info == NULL) {
1277
0
        Py_CLEAR(self->encoding);
1278
0
        goto error;
1279
0
    }
1280
1281
    /* XXX: Failures beyond this point have the potential to leak elements
1282
     * of the partially constructed object (like self->encoding)
1283
     */
1284
1285
130
    self->errors = Py_NewRef(errors);
1286
130
    self->chunk_size = 8192;
1287
130
    self->line_buffering = line_buffering;
1288
130
    self->write_through = write_through;
1289
130
    if (set_newline(self, newline) < 0) {
1290
0
        goto error;
1291
0
    }
1292
1293
130
    self->buffer = Py_NewRef(buffer);
1294
1295
    /* Build the decoder object */
1296
130
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
1297
130
    self->state = state;
1298
130
    if (_textiowrapper_set_decoder(self, codec_info, errors_str) != 0)
1299
0
        goto error;
1300
1301
    /* Build the encoder object */
1302
130
    if (_textiowrapper_set_encoder(self, codec_info, errors_str) != 0)
1303
0
        goto error;
1304
1305
    /* Finished sorting out the codec details */
1306
130
    Py_CLEAR(codec_info);
1307
1308
130
    if (Py_IS_TYPE(buffer, state->PyBufferedReader_Type) ||
1309
75
        Py_IS_TYPE(buffer, state->PyBufferedWriter_Type) ||
1310
0
        Py_IS_TYPE(buffer, state->PyBufferedRandom_Type))
1311
130
    {
1312
130
        if (PyObject_GetOptionalAttr(buffer, &_Py_ID(raw), &raw) < 0)
1313
0
            goto error;
1314
        /* Cache the raw FileIO object to speed up 'closed' checks */
1315
130
        if (raw != NULL) {
1316
130
            if (Py_IS_TYPE(raw, state->PyFileIO_Type))
1317
130
                self->raw = raw;
1318
0
            else
1319
0
                Py_DECREF(raw);
1320
130
        }
1321
130
    }
1322
1323
130
    res = PyObject_CallMethodNoArgs(buffer, &_Py_ID(seekable));
1324
130
    if (res == NULL)
1325
0
        goto error;
1326
130
    r = PyObject_IsTrue(res);
1327
130
    Py_DECREF(res);
1328
130
    if (r < 0)
1329
0
        goto error;
1330
130
    self->seekable = self->telling = r;
1331
1332
130
    r = PyObject_HasAttrWithError(buffer, &_Py_ID(read1));
1333
130
    if (r < 0) {
1334
0
        goto error;
1335
0
    }
1336
130
    self->has_read1 = r;
1337
1338
130
    self->encoding_start_of_stream = 0;
1339
130
    if (_textiowrapper_fix_encoder_state(self) < 0) {
1340
0
        goto error;
1341
0
    }
1342
1343
130
    self->ok = 1;
1344
130
    return 0;
1345
1346
0
  error:
1347
0
    Py_XDECREF(codec_info);
1348
0
    return -1;
1349
130
}
1350
1351
/* Return *default_value* if ob is None, 0 if ob is false, 1 if ob is true,
1352
 * -1 on error.
1353
 */
1354
static int
1355
convert_optional_bool(PyObject *obj, int default_value)
1356
0
{
1357
0
    long v;
1358
0
    if (obj == Py_None) {
1359
0
        v = default_value;
1360
0
    }
1361
0
    else {
1362
0
        v = PyLong_AsLong(obj);
1363
0
        if (v == -1 && PyErr_Occurred())
1364
0
            return -1;
1365
0
    }
1366
0
    return v != 0;
1367
0
}
1368
1369
static int
1370
textiowrapper_change_encoding(textio *self, PyObject *encoding,
1371
                              PyObject *errors, int newline_changed)
1372
0
{
1373
    /* Use existing settings where new settings are not specified */
1374
0
    if (encoding == Py_None && errors == Py_None && !newline_changed) {
1375
0
        return 0;  // no change
1376
0
    }
1377
1378
0
    if (encoding == Py_None) {
1379
0
        encoding = self->encoding;
1380
0
        if (errors == Py_None) {
1381
0
            errors = self->errors;
1382
0
        }
1383
0
        Py_INCREF(encoding);
1384
0
    }
1385
0
    else {
1386
0
        if (_PyUnicode_EqualToASCIIString(encoding, "locale")) {
1387
0
            encoding = _Py_GetLocaleEncodingObject();
1388
0
            if (encoding == NULL) {
1389
0
                return -1;
1390
0
            }
1391
0
        } else {
1392
0
            Py_INCREF(encoding);
1393
0
        }
1394
0
        if (errors == Py_None) {
1395
0
            errors = &_Py_ID(strict);
1396
0
        }
1397
0
    }
1398
0
    Py_INCREF(errors);
1399
1400
0
    const char *c_encoding = PyUnicode_AsUTF8(encoding);
1401
0
    if (c_encoding == NULL) {
1402
0
        Py_DECREF(encoding);
1403
0
        Py_DECREF(errors);
1404
0
        return -1;
1405
0
    }
1406
0
    const char *c_errors = PyUnicode_AsUTF8(errors);
1407
0
    if (c_errors == NULL) {
1408
0
        Py_DECREF(encoding);
1409
0
        Py_DECREF(errors);
1410
0
        return -1;
1411
0
    }
1412
1413
    // Create new encoder & decoder
1414
0
    PyObject *codec_info = _PyCodec_LookupTextEncoding(c_encoding, NULL);
1415
0
    if (codec_info == NULL) {
1416
0
        Py_DECREF(encoding);
1417
0
        Py_DECREF(errors);
1418
0
        return -1;
1419
0
    }
1420
0
    if (_textiowrapper_set_decoder(self, codec_info, c_errors) != 0 ||
1421
0
            _textiowrapper_set_encoder(self, codec_info, c_errors) != 0) {
1422
0
        Py_DECREF(codec_info);
1423
0
        Py_DECREF(encoding);
1424
0
        Py_DECREF(errors);
1425
0
        return -1;
1426
0
    }
1427
0
    Py_DECREF(codec_info);
1428
1429
0
    Py_SETREF(self->encoding, encoding);
1430
0
    Py_SETREF(self->errors, errors);
1431
1432
0
    return _textiowrapper_fix_encoder_state(self);
1433
0
}
1434
1435
/*[clinic input]
1436
@critical_section
1437
_io.TextIOWrapper.reconfigure
1438
    *
1439
    encoding: object = None
1440
    errors: object = None
1441
    newline as newline_obj: object(c_default="NULL") = None
1442
    line_buffering as line_buffering_obj: object = None
1443
    write_through as write_through_obj: object = None
1444
1445
Reconfigure the text stream with new parameters.
1446
1447
This also does an implicit stream flush.
1448
1449
[clinic start generated code]*/
1450
1451
static PyObject *
1452
_io_TextIOWrapper_reconfigure_impl(textio *self, PyObject *encoding,
1453
                                   PyObject *errors, PyObject *newline_obj,
1454
                                   PyObject *line_buffering_obj,
1455
                                   PyObject *write_through_obj)
1456
/*[clinic end generated code: output=52b812ff4b3d4b0f input=dc3bd35ebda702a7]*/
1457
0
{
1458
0
    int line_buffering;
1459
0
    int write_through;
1460
0
    const char *newline = NULL;
1461
1462
0
    if (encoding != Py_None && !PyUnicode_Check(encoding)) {
1463
0
        PyErr_Format(PyExc_TypeError,
1464
0
                "reconfigure() argument 'encoding' must be str or None, not %s",
1465
0
                Py_TYPE(encoding)->tp_name);
1466
0
        return NULL;
1467
0
    }
1468
0
    if (errors != Py_None && !PyUnicode_Check(errors)) {
1469
0
        PyErr_Format(PyExc_TypeError,
1470
0
                "reconfigure() argument 'errors' must be str or None, not %s",
1471
0
                Py_TYPE(errors)->tp_name);
1472
0
        return NULL;
1473
0
    }
1474
0
    if (newline_obj != NULL && newline_obj != Py_None &&
1475
0
        !PyUnicode_Check(newline_obj))
1476
0
    {
1477
0
        PyErr_Format(PyExc_TypeError,
1478
0
                "reconfigure() argument 'newline' must be str or None, not %s",
1479
0
                Py_TYPE(newline_obj)->tp_name);
1480
0
        return NULL;
1481
0
    }
1482
    /* Check if something is in the read buffer */
1483
0
    if (self->decoded_chars != NULL) {
1484
0
        if (encoding != Py_None || errors != Py_None || newline_obj != NULL) {
1485
0
            _unsupported(self->state,
1486
0
                         "It is not possible to set the encoding or newline "
1487
0
                         "of stream after the first read");
1488
0
            return NULL;
1489
0
        }
1490
0
    }
1491
1492
0
    if (newline_obj != NULL && newline_obj != Py_None) {
1493
0
        newline = PyUnicode_AsUTF8(newline_obj);
1494
0
        if (newline == NULL || validate_newline(newline) < 0) {
1495
0
            return NULL;
1496
0
        }
1497
0
    }
1498
1499
0
    line_buffering = convert_optional_bool(line_buffering_obj,
1500
0
                                           self->line_buffering);
1501
0
    if (line_buffering < 0) {
1502
0
        return NULL;
1503
0
    }
1504
0
    write_through = convert_optional_bool(write_through_obj,
1505
0
                                          self->write_through);
1506
0
    if (write_through < 0) {
1507
0
        return NULL;
1508
0
    }
1509
1510
0
    if (_PyFile_Flush((PyObject *)self) < 0) {
1511
0
        return NULL;
1512
0
    }
1513
0
    self->b2cratio = 0;
1514
1515
0
    if (newline_obj != NULL && set_newline(self, newline) < 0) {
1516
0
        return NULL;
1517
0
    }
1518
1519
0
    if (textiowrapper_change_encoding(
1520
0
            self, encoding, errors, newline_obj != NULL) < 0) {
1521
0
        return NULL;
1522
0
    }
1523
1524
0
    self->line_buffering = line_buffering;
1525
0
    self->write_through = write_through;
1526
0
    Py_RETURN_NONE;
1527
0
}
1528
1529
static int
1530
textiowrapper_clear(PyObject *op)
1531
19
{
1532
19
    textio *self = textio_CAST(op);
1533
19
    self->ok = 0;
1534
19
    Py_CLEAR(self->buffer);
1535
19
    Py_CLEAR(self->encoding);
1536
19
    Py_CLEAR(self->encoder);
1537
19
    Py_CLEAR(self->decoder);
1538
19
    Py_CLEAR(self->readnl);
1539
19
    Py_CLEAR(self->decoded_chars);
1540
19
    Py_CLEAR(self->pending_bytes);
1541
19
    Py_CLEAR(self->snapshot);
1542
19
    Py_CLEAR(self->errors);
1543
19
    Py_CLEAR(self->raw);
1544
1545
19
    Py_CLEAR(self->dict);
1546
19
    return 0;
1547
19
}
1548
1549
static void
1550
textiowrapper_dealloc(PyObject *op)
1551
19
{
1552
19
    textio *self = textio_CAST(op);
1553
19
    PyTypeObject *tp = Py_TYPE(self);
1554
19
    self->finalizing = 1;
1555
19
    if (_PyIOBase_finalize(op) < 0)
1556
0
        return;
1557
19
    self->ok = 0;
1558
19
    _PyObject_GC_UNTRACK(self);
1559
19
    FT_CLEAR_WEAKREFS(op, self->weakreflist);
1560
19
    (void)textiowrapper_clear(op);
1561
19
    tp->tp_free(self);
1562
19
    Py_DECREF(tp);
1563
19
}
1564
1565
static int
1566
textiowrapper_traverse(PyObject *op, visitproc visit, void *arg)
1567
4.93k
{
1568
4.93k
    textio *self = textio_CAST(op);
1569
4.93k
    Py_VISIT(Py_TYPE(self));
1570
4.93k
    Py_VISIT(self->buffer);
1571
4.93k
    Py_VISIT(self->encoding);
1572
4.93k
    Py_VISIT(self->encoder);
1573
4.93k
    Py_VISIT(self->decoder);
1574
4.93k
    Py_VISIT(self->readnl);
1575
4.93k
    Py_VISIT(self->decoded_chars);
1576
4.93k
    Py_VISIT(self->pending_bytes);
1577
4.93k
    Py_VISIT(self->snapshot);
1578
4.93k
    Py_VISIT(self->errors);
1579
4.93k
    Py_VISIT(self->raw);
1580
1581
4.93k
    Py_VISIT(self->dict);
1582
4.93k
    return 0;
1583
4.93k
}
1584
1585
static PyObject *
1586
_io_TextIOWrapper_closed_get_impl(textio *self);
1587
1588
/* This macro takes some shortcuts to make the common case faster. */
1589
#define CHECK_CLOSED(self) \
1590
167k
    do { \
1591
167k
        int r; \
1592
167k
        PyObject *_res; \
1593
167k
        if (Py_IS_TYPE(self, self->state->PyTextIOWrapper_Type)) { \
1594
167k
            if (self->raw != NULL) \
1595
167k
                r = _PyFileIO_closed(self->raw); \
1596
167k
            else { \
1597
0
                _res = _io_TextIOWrapper_closed_get_impl(self); \
1598
0
                if (_res == NULL) \
1599
0
                    return NULL; \
1600
0
                r = PyObject_IsTrue(_res); \
1601
0
                Py_DECREF(_res); \
1602
0
                if (r < 0) \
1603
0
                    return NULL; \
1604
0
            } \
1605
167k
            if (r > 0) { \
1606
0
                PyErr_SetString(PyExc_ValueError, \
1607
0
                                "I/O operation on closed file."); \
1608
0
                return NULL; \
1609
0
            } \
1610
167k
        } \
1611
167k
        else if (_PyIOBase_check_closed((PyObject *)self, Py_True) == NULL) \
1612
0
            return NULL; \
1613
167k
    } while (0)
1614
1615
#define CHECK_INITIALIZED(self) \
1616
168k
    if (self->ok <= 0) { \
1617
0
        PyErr_SetString(PyExc_ValueError, \
1618
0
            "I/O operation on uninitialized object"); \
1619
0
        return NULL; \
1620
0
    }
1621
1622
#define CHECK_ATTACHED(self) \
1623
168k
    CHECK_INITIALIZED(self); \
1624
168k
    if (self->detached) { \
1625
0
        PyErr_SetString(PyExc_ValueError, \
1626
0
             "underlying buffer has been detached"); \
1627
0
        return NULL; \
1628
0
    }
1629
1630
#define CHECK_ATTACHED_INT(self) \
1631
0
    if (self->ok <= 0) { \
1632
0
        PyErr_SetString(PyExc_ValueError, \
1633
0
            "I/O operation on uninitialized object"); \
1634
0
        return -1; \
1635
0
    } else if (self->detached) { \
1636
0
        PyErr_SetString(PyExc_ValueError, \
1637
0
             "underlying buffer has been detached"); \
1638
0
        return -1; \
1639
0
    }
1640
1641
1642
/*[clinic input]
1643
@critical_section
1644
_io.TextIOWrapper.detach
1645
[clinic start generated code]*/
1646
1647
static PyObject *
1648
_io_TextIOWrapper_detach_impl(textio *self)
1649
/*[clinic end generated code: output=7ba3715cd032d5f2 input=c908a3b4ef203b0f]*/
1650
0
{
1651
0
    PyObject *buffer;
1652
0
    if (_PyFile_Flush((PyObject *)self) < 0) {
1653
0
        return NULL;
1654
0
    }
1655
    /* _PyFile_Flush could detach before returning; raise an exception. */
1656
0
    buffer = buffer_access_safe(self);
1657
0
    if (buffer == NULL) {
1658
0
        return NULL;
1659
0
    }
1660
0
    Py_CLEAR(self->buffer);
1661
0
    self->detached = 1;
1662
0
    return buffer;
1663
0
}
1664
1665
/* Flush the internal write buffer. This doesn't explicitly flush the
1666
   underlying buffered object, though. */
1667
static int
1668
_textiowrapper_writeflush(textio *self)
1669
167k
{
1670
167k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
1671
1672
167k
    if (self->pending_bytes == NULL)
1673
23.6k
        return 0;
1674
1675
144k
    PyObject *pending = self->pending_bytes;
1676
144k
    PyObject *b;
1677
1678
144k
    if (PyBytes_Check(pending)) {
1679
2.04k
        b = Py_NewRef(pending);
1680
2.04k
    }
1681
142k
    else if (PyUnicode_Check(pending)) {
1682
142k
        assert(PyUnicode_IS_ASCII(pending));
1683
142k
        assert(PyUnicode_GET_LENGTH(pending) == self->pending_bytes_count);
1684
142k
        b = PyBytes_FromStringAndSize(
1685
142k
                PyUnicode_DATA(pending), PyUnicode_GET_LENGTH(pending));
1686
142k
        if (b == NULL) {
1687
0
            return -1;
1688
0
        }
1689
142k
    }
1690
0
    else {
1691
0
        assert(PyList_Check(pending));
1692
0
        PyBytesWriter *writer = PyBytesWriter_Create(self->pending_bytes_count);
1693
0
        if (writer == NULL) {
1694
0
            return -1;
1695
0
        }
1696
1697
0
        char *buf = PyBytesWriter_GetData(writer);
1698
0
        Py_ssize_t pos = 0;
1699
1700
0
        for (Py_ssize_t i = 0; i < PyList_GET_SIZE(pending); i++) {
1701
0
            PyObject *obj = PyList_GET_ITEM(pending, i);
1702
0
            const char *src;
1703
0
            Py_ssize_t len;
1704
0
            if (PyUnicode_Check(obj)) {
1705
0
                assert(PyUnicode_IS_ASCII(obj));
1706
0
                src = PyUnicode_DATA(obj);
1707
0
                len = PyUnicode_GET_LENGTH(obj);
1708
0
            }
1709
0
            else {
1710
0
                assert(PyBytes_Check(obj));
1711
0
                src = PyBytes_AS_STRING(obj);
1712
0
                len = PyBytes_GET_SIZE(obj);
1713
0
            }
1714
0
            memcpy(buf + pos, src, len);
1715
0
            pos += len;
1716
0
        }
1717
0
        assert(pos == self->pending_bytes_count);
1718
1719
0
        b = PyBytesWriter_Finish(writer);
1720
0
        if (b == NULL) {
1721
0
            return -1;
1722
0
        }
1723
0
    }
1724
1725
144k
    self->pending_bytes_count = 0;
1726
144k
    self->pending_bytes = NULL;
1727
144k
    Py_DECREF(pending);
1728
1729
144k
    PyObject *ret;
1730
144k
    do {
1731
144k
        ret = buffer_callmethod_onearg(self, &_Py_ID(write), b);
1732
144k
    } while (ret == NULL && _PyIO_trap_eintr());
1733
144k
    Py_DECREF(b);
1734
    // NOTE: We cleared buffer but we don't know how many bytes are actually written
1735
    // when an error occurred.
1736
144k
    if (ret == NULL)
1737
0
        return -1;
1738
144k
    Py_DECREF(ret);
1739
144k
    return 0;
1740
144k
}
1741
1742
/* Return borrowed Py_None on success, or NULL on error. */
1743
static PyObject *
1744
textiowrapper_check_write(textio *self)
1745
144k
{
1746
144k
    CHECK_ATTACHED(self);
1747
144k
    CHECK_CLOSED(self);
1748
1749
144k
    if (self->encoder == NULL) {
1750
0
        return _unsupported(self->state, "not writable");
1751
0
    }
1752
144k
    return Py_None;
1753
144k
}
1754
1755
/*[clinic input]
1756
@critical_section
1757
_io.TextIOWrapper.write
1758
    text: unicode
1759
    /
1760
[clinic start generated code]*/
1761
1762
static PyObject *
1763
_io_TextIOWrapper_write_impl(textio *self, PyObject *text)
1764
/*[clinic end generated code: output=d2deb0d50771fcec input=73ec95c5c4a3489c]*/
1765
144k
{
1766
144k
    PyObject *ret;
1767
144k
    PyObject *b;
1768
144k
    Py_ssize_t textlen;
1769
144k
    int haslf = 0;
1770
144k
    int needflush = 0, text_needflush = 0;
1771
1772
144k
    if (textiowrapper_check_write(self) == NULL) {
1773
0
        return NULL;
1774
0
    }
1775
1776
144k
    Py_INCREF(text);
1777
1778
144k
    textlen = PyUnicode_GET_LENGTH(text);
1779
1780
144k
    if ((self->writetranslate && self->writenl != NULL) || self->line_buffering)
1781
144k
        if (PyUnicode_FindChar(text, '\n', 0, PyUnicode_GET_LENGTH(text), 1) != -1)
1782
144k
            haslf = 1;
1783
1784
144k
    if (haslf && self->writetranslate && self->writenl != NULL) {
1785
0
        PyObject *newtext = _PyObject_CallMethod(text, &_Py_ID(replace),
1786
0
                                                 "ss", "\n", self->writenl);
1787
0
        Py_DECREF(text);
1788
0
        if (newtext == NULL)
1789
0
            return NULL;
1790
0
        if (!PyUnicode_Check(newtext)) {
1791
0
            PyErr_Format(PyExc_TypeError,
1792
0
                         "replace() should return a str, not %T", newtext);
1793
0
            Py_DECREF(newtext);
1794
0
            return NULL;
1795
0
        }
1796
        /* replace() may have closed, detached or reinitialized the stream. */
1797
0
        if (textiowrapper_check_write(self) == NULL) {
1798
0
            Py_DECREF(newtext);
1799
0
            return NULL;
1800
0
        }
1801
0
        text = newtext;
1802
0
    }
1803
1804
144k
    if (self->write_through)
1805
0
        text_needflush = 1;
1806
144k
    if (self->line_buffering &&
1807
144k
        (haslf ||
1808
0
         PyUnicode_FindChar(text, '\r', 0, PyUnicode_GET_LENGTH(text), 1) != -1))
1809
144k
        needflush = 1;
1810
1811
    /* XXX What if we were just reading? */
1812
144k
    if (self->encodefunc != NULL) {
1813
144k
        if (PyUnicode_IS_ASCII(text) &&
1814
                // See bpo-43260
1815
142k
                PyUnicode_GET_LENGTH(text) <= self->chunk_size &&
1816
142k
                is_asciicompat_encoding(self->encodefunc)) {
1817
142k
            b = Py_NewRef(text);
1818
142k
        }
1819
2.04k
        else {
1820
2.04k
            b = (*self->encodefunc)((PyObject *) self, text);
1821
2.04k
        }
1822
144k
        self->encoding_start_of_stream = 0;
1823
144k
    }
1824
0
    else {
1825
        /* A codec callback may reconfigure the stream. */
1826
0
        PyObject *encoder = Py_NewRef(self->encoder);
1827
0
        b = PyObject_CallMethodOneArg(encoder, &_Py_ID(encode), text);
1828
0
        Py_DECREF(encoder);
1829
0
    }
1830
1831
144k
    Py_DECREF(text);
1832
144k
    if (b == NULL)
1833
0
        return NULL;
1834
144k
    if (b != text && !PyBytes_Check(b)) {
1835
0
        PyErr_Format(PyExc_TypeError,
1836
0
                     "encoder should return a bytes object, not '%.200s'",
1837
0
                     Py_TYPE(b)->tp_name);
1838
0
        Py_DECREF(b);
1839
0
        return NULL;
1840
0
    }
1841
1842
144k
    Py_ssize_t bytes_len;
1843
144k
    if (b == text) {
1844
142k
        bytes_len = PyUnicode_GET_LENGTH(b);
1845
142k
    }
1846
2.04k
    else {
1847
2.04k
        bytes_len = PyBytes_GET_SIZE(b);
1848
2.04k
    }
1849
1850
    // We should avoid concatenating huge data.
1851
    // Flush the buffer before adding b to the buffer if b is not small.
1852
    // https://github.com/python/cpython/issues/87426
1853
144k
    if (bytes_len >= self->chunk_size) {
1854
        // _textiowrapper_writeflush() calls buffer.write().
1855
        // self->pending_bytes can be appended during buffer->write()
1856
        // or other thread.
1857
        // We need to loop until buffer becomes empty.
1858
        // https://github.com/python/cpython/issues/118138
1859
        // https://github.com/python/cpython/issues/119506
1860
0
        while (self->pending_bytes != NULL) {
1861
0
            if (_textiowrapper_writeflush(self) < 0) {
1862
0
                Py_DECREF(b);
1863
0
                return NULL;
1864
0
            }
1865
0
        }
1866
0
    }
1867
1868
144k
    if (bytes_len > 0) {
1869
144k
        if (self->pending_bytes == NULL) {
1870
144k
            assert(self->pending_bytes_count == 0);
1871
144k
            self->pending_bytes = b;
1872
144k
        }
1873
0
        else if (!PyList_CheckExact(self->pending_bytes)) {
1874
0
            PyObject *list = PyList_New(2);
1875
0
            if (list == NULL) {
1876
0
                Py_DECREF(b);
1877
0
                return NULL;
1878
0
            }
1879
            // Since Python 3.12, allocating GC object won't trigger GC and release
1880
            // GIL. See https://github.com/python/cpython/issues/97922
1881
0
            assert(!PyList_CheckExact(self->pending_bytes));
1882
0
            PyList_SET_ITEM(list, 0, self->pending_bytes);
1883
0
            PyList_SET_ITEM(list, 1, b);
1884
0
            self->pending_bytes = list;
1885
0
        }
1886
0
        else {
1887
0
            if (PyList_Append(self->pending_bytes, b) < 0) {
1888
0
                Py_DECREF(b);
1889
0
                return NULL;
1890
0
            }
1891
0
            Py_DECREF(b);
1892
0
        }
1893
1894
144k
        self->pending_bytes_count += bytes_len;
1895
144k
    }
1896
0
    else {
1897
0
        Py_DECREF(b);
1898
0
    }
1899
1900
144k
    if (self->pending_bytes_count >= self->chunk_size || needflush ||
1901
144k
        text_needflush) {
1902
144k
        if (_textiowrapper_writeflush(self) < 0)
1903
0
            return NULL;
1904
144k
    }
1905
1906
144k
    if (needflush) {
1907
144k
        PyObject *buffer = buffer_access_safe(self);
1908
144k
        if (buffer == NULL) {
1909
0
            return NULL;
1910
0
        }
1911
144k
        int res = _PyFile_Flush(buffer);
1912
144k
        Py_DECREF(buffer);
1913
144k
        if (res < 0) {
1914
0
            return NULL;
1915
0
        }
1916
144k
    }
1917
1918
144k
    if (self->snapshot != NULL) {
1919
0
        textiowrapper_set_decoded_chars(self, NULL);
1920
0
        Py_CLEAR(self->snapshot);
1921
0
    }
1922
1923
144k
    if (self->decoder) {
1924
0
        ret = PyObject_CallMethodNoArgs(self->decoder, &_Py_ID(reset));
1925
0
        if (ret == NULL)
1926
0
            return NULL;
1927
0
        Py_DECREF(ret);
1928
0
    }
1929
1930
144k
    return PyLong_FromSsize_t(textlen);
1931
144k
}
1932
1933
/* Steal a reference to chars and store it in the decoded_char buffer;
1934
 */
1935
static void
1936
textiowrapper_set_decoded_chars(textio *self, PyObject *chars)
1937
260
{
1938
260
    Py_XSETREF(self->decoded_chars, chars);
1939
260
    self->decoded_chars_used = 0;
1940
260
}
1941
1942
static PyObject *
1943
textiowrapper_get_decoded_chars(textio *self, Py_ssize_t n)
1944
8
{
1945
8
    PyObject *chars;
1946
8
    Py_ssize_t avail;
1947
1948
8
    if (self->decoded_chars == NULL)
1949
8
        return Py_GetConstant(Py_CONSTANT_EMPTY_STR);
1950
1951
0
    avail = (PyUnicode_GET_LENGTH(self->decoded_chars)
1952
0
             - self->decoded_chars_used);
1953
1954
0
    assert(avail >= 0);
1955
1956
0
    if (n < 0 || n > avail)
1957
0
        n = avail;
1958
1959
0
    if (self->decoded_chars_used > 0 || n < avail) {
1960
0
        chars = PyUnicode_Substring(self->decoded_chars,
1961
0
                                    self->decoded_chars_used,
1962
0
                                    self->decoded_chars_used + n);
1963
0
        if (chars == NULL)
1964
0
            return NULL;
1965
0
    }
1966
0
    else {
1967
0
        chars = Py_NewRef(self->decoded_chars);
1968
0
    }
1969
1970
0
    self->decoded_chars_used += n;
1971
0
    return chars;
1972
0
}
1973
1974
/* Read and decode the next chunk of data from the BufferedReader.
1975
 */
1976
static int
1977
textiowrapper_read_chunk(textio *self, Py_ssize_t size_hint)
1978
130
{
1979
130
    PyObject *dec_buffer = NULL;
1980
130
    PyObject *dec_flags = NULL;
1981
130
    PyObject *input_chunk = NULL;
1982
130
    Py_buffer input_chunk_buf;
1983
130
    PyObject *decoded_chars, *chunk_size;
1984
130
    Py_ssize_t nbytes, nchars;
1985
130
    int eof;
1986
1987
    /* The return value is True unless EOF was reached.  The decoded string is
1988
     * placed in self._decoded_chars (replacing its previous value).  The
1989
     * entire input chunk is sent to the decoder, though some of it may remain
1990
     * buffered in the decoder, yet to be converted.
1991
     */
1992
1993
130
    if (self->decoder == NULL) {
1994
0
        _unsupported(self->state, "not readable");
1995
0
        return -1;
1996
0
    }
1997
1998
130
    if (self->telling) {
1999
        /* To prepare for tell(), we need to snapshot a point in the file
2000
         * where the decoder's input buffer is empty.
2001
         */
2002
0
        PyObject *state = PyObject_CallMethodNoArgs(self->decoder,
2003
0
                                                     &_Py_ID(getstate));
2004
0
        if (state == NULL)
2005
0
            return -1;
2006
        /* Given this, we know there was a valid snapshot point
2007
         * len(dec_buffer) bytes ago with decoder state (b'', dec_flags).
2008
         */
2009
0
        if (!PyTuple_Check(state)) {
2010
0
            PyErr_SetString(PyExc_TypeError,
2011
0
                            "illegal decoder state");
2012
0
            Py_DECREF(state);
2013
0
            return -1;
2014
0
        }
2015
0
        if (!PyArg_ParseTuple(state,
2016
0
                              "OO;illegal decoder state", &dec_buffer, &dec_flags))
2017
0
        {
2018
0
            Py_DECREF(state);
2019
0
            return -1;
2020
0
        }
2021
2022
0
        if (!PyBytes_Check(dec_buffer)) {
2023
0
            PyErr_Format(PyExc_TypeError,
2024
0
                         "illegal decoder state: the first item should be a "
2025
0
                         "bytes object, not '%.200s'",
2026
0
                         Py_TYPE(dec_buffer)->tp_name);
2027
0
            Py_DECREF(state);
2028
0
            return -1;
2029
0
        }
2030
0
        Py_INCREF(dec_buffer);
2031
0
        Py_INCREF(dec_flags);
2032
0
        Py_DECREF(state);
2033
0
    }
2034
2035
    /* Read a chunk, decode it, and put the result in self._decoded_chars. */
2036
130
    if (size_hint > 0) {
2037
0
        size_hint = (Py_ssize_t)(Py_MAX(self->b2cratio, 1.0) * size_hint);
2038
0
    }
2039
130
    chunk_size = PyLong_FromSsize_t(Py_MAX(self->chunk_size, size_hint));
2040
130
    if (chunk_size == NULL)
2041
0
        goto fail;
2042
2043
130
    input_chunk = buffer_callmethod_onearg(self,
2044
130
                                           (self->has_read1 ? &_Py_ID(read1) :
2045
130
                                                              &_Py_ID(read)),
2046
130
                                           chunk_size);
2047
130
    Py_DECREF(chunk_size);
2048
130
    if (input_chunk == NULL)
2049
0
        goto fail;
2050
2051
130
    if (PyObject_GetBuffer(input_chunk, &input_chunk_buf, 0) != 0) {
2052
0
        PyErr_Format(PyExc_TypeError,
2053
0
                     "underlying %s() should have returned a bytes-like object, "
2054
0
                     "not '%.200s'", (self->has_read1 ? "read1": "read"),
2055
0
                     Py_TYPE(input_chunk)->tp_name);
2056
0
        goto fail;
2057
0
    }
2058
2059
130
    nbytes = input_chunk_buf.len;
2060
130
    eof = (nbytes == 0);
2061
2062
130
    decoded_chars = _textiowrapper_decode(self->state, self->decoder,
2063
130
                                          input_chunk, eof);
2064
130
    PyBuffer_Release(&input_chunk_buf);
2065
130
    if (decoded_chars == NULL)
2066
0
        goto fail;
2067
2068
    /* The old chunk's finalizer can clear the new chunk. */
2069
130
    nchars = PyUnicode_GET_LENGTH(decoded_chars);
2070
130
    textiowrapper_set_decoded_chars(self, decoded_chars);
2071
130
    if (nchars > 0)
2072
120
        self->b2cratio = (double) nbytes / nchars;
2073
10
    else
2074
10
        self->b2cratio = 0.0;
2075
130
    if (nchars > 0)
2076
120
        eof = 0;
2077
2078
130
    if (self->telling) {
2079
        /* At the snapshot point, len(dec_buffer) bytes before the read, the
2080
         * next input to be decoded is dec_buffer + input_chunk.
2081
         */
2082
0
        PyObject *next_input = dec_buffer;
2083
0
        PyBytes_Concat(&next_input, input_chunk);
2084
0
        dec_buffer = NULL; /* Reference lost to PyBytes_Concat */
2085
0
        if (next_input == NULL) {
2086
0
            goto fail;
2087
0
        }
2088
0
        PyObject *snapshot = Py_BuildValue("NN", dec_flags, next_input);
2089
0
        if (snapshot == NULL) {
2090
0
            dec_flags = NULL;
2091
0
            goto fail;
2092
0
        }
2093
0
        Py_XSETREF(self->snapshot, snapshot);
2094
0
    }
2095
130
    Py_DECREF(input_chunk);
2096
2097
130
    return (eof == 0);
2098
2099
0
  fail:
2100
0
    Py_XDECREF(dec_buffer);
2101
0
    Py_XDECREF(dec_flags);
2102
0
    Py_XDECREF(input_chunk);
2103
0
    return -1;
2104
130
}
2105
2106
/*[clinic input]
2107
@critical_section
2108
_io.TextIOWrapper.read
2109
    size as n: Py_ssize_t(accept={int, NoneType}) = -1
2110
    /
2111
[clinic start generated code]*/
2112
2113
static PyObject *
2114
_io_TextIOWrapper_read_impl(textio *self, Py_ssize_t n)
2115
/*[clinic end generated code: output=7e651ce6cc6a25a6 input=67d14c5661121377]*/
2116
8
{
2117
8
    PyObject *result = NULL, *chunks = NULL;
2118
2119
8
    CHECK_ATTACHED(self);
2120
8
    CHECK_CLOSED(self);
2121
2122
8
    if (self->decoder == NULL) {
2123
0
        return _unsupported(self->state, "not readable");
2124
0
    }
2125
2126
8
    if (_textiowrapper_writeflush(self) < 0)
2127
0
        return NULL;
2128
2129
8
    if (n < 0) {
2130
        /* Read everything */
2131
8
        PyObject *bytes = buffer_callmethod_noargs(self, &_Py_ID(read));
2132
8
        PyObject *decoded;
2133
8
        if (bytes == NULL)
2134
0
            goto fail;
2135
2136
8
        if (bytes == Py_None){
2137
0
            Py_DECREF(bytes);
2138
0
            PyErr_SetString(PyExc_BlockingIOError, "Read returned None.");
2139
0
            return NULL;
2140
0
        }
2141
2142
8
        decoded = _textiowrapper_decode(self->state, self->decoder, bytes, 1);
2143
8
        Py_DECREF(bytes);
2144
8
        if (decoded == NULL)
2145
0
            goto fail;
2146
2147
8
        result = textiowrapper_get_decoded_chars(self, -1);
2148
2149
8
        if (result == NULL) {
2150
0
            Py_DECREF(decoded);
2151
0
            return NULL;
2152
0
        }
2153
2154
8
        PyUnicode_AppendAndDel(&result, decoded);
2155
8
        if (result == NULL)
2156
0
            goto fail;
2157
2158
8
        if (self->snapshot != NULL) {
2159
0
            textiowrapper_set_decoded_chars(self, NULL);
2160
0
            Py_CLEAR(self->snapshot);
2161
0
        }
2162
8
        return result;
2163
8
    }
2164
0
    else {
2165
0
        int res = 1;
2166
0
        Py_ssize_t remaining = n;
2167
2168
0
        result = textiowrapper_get_decoded_chars(self, n);
2169
0
        if (result == NULL)
2170
0
            goto fail;
2171
0
        remaining -= PyUnicode_GET_LENGTH(result);
2172
2173
        /* Keep reading chunks until we have n characters to return */
2174
0
        while (remaining > 0) {
2175
0
            res = textiowrapper_read_chunk(self, remaining);
2176
0
            if (res < 0) {
2177
                /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals()
2178
                   when EINTR occurs so we needn't do it ourselves. */
2179
0
                if (_PyIO_trap_eintr()) {
2180
0
                    continue;
2181
0
                }
2182
0
                goto fail;
2183
0
            }
2184
0
            if (res == 0)  /* EOF */
2185
0
                break;
2186
0
            if (chunks == NULL) {
2187
0
                chunks = PyList_New(0);
2188
0
                if (chunks == NULL)
2189
0
                    goto fail;
2190
0
            }
2191
0
            if (PyUnicode_GET_LENGTH(result) > 0 &&
2192
0
                PyList_Append(chunks, result) < 0)
2193
0
                goto fail;
2194
0
            Py_DECREF(result);
2195
0
            result = textiowrapper_get_decoded_chars(self, remaining);
2196
0
            if (result == NULL)
2197
0
                goto fail;
2198
0
            remaining -= PyUnicode_GET_LENGTH(result);
2199
0
        }
2200
0
        if (chunks != NULL) {
2201
0
            if (result != NULL && PyList_Append(chunks, result) < 0)
2202
0
                goto fail;
2203
0
            _Py_DECLARE_STR(empty, "");
2204
0
            Py_XSETREF(result, PyUnicode_Join(&_Py_STR(empty), chunks));
2205
0
            if (result == NULL)
2206
0
                goto fail;
2207
0
            Py_CLEAR(chunks);
2208
0
        }
2209
0
        return result;
2210
0
    }
2211
0
  fail:
2212
0
    Py_XDECREF(result);
2213
0
    Py_XDECREF(chunks);
2214
0
    return NULL;
2215
8
}
2216
2217
2218
/* NOTE: `end` must point to the real end of the Py_UCS4 storage,
2219
   that is to the NUL character. Otherwise the function will produce
2220
   incorrect results. */
2221
static const char *
2222
find_control_char(int kind, const char *s, const char *end, Py_UCS4 ch)
2223
7.55M
{
2224
7.55M
    if (kind == PyUnicode_1BYTE_KIND) {
2225
22.9k
        assert(ch < 256);
2226
22.9k
        return (char *) memchr((const void *) s, (char) ch, end - s);
2227
22.9k
    }
2228
127M
    for (;;) {
2229
204M
        while (PyUnicode_READ(kind, s, 0) > ch)
2230
76.1M
            s += kind;
2231
127M
        if (PyUnicode_READ(kind, s, 0) == ch)
2232
7.52M
            return s;
2233
120M
        if (s == end)
2234
4.83k
            return NULL;
2235
120M
        s += kind;
2236
120M
    }
2237
7.52M
}
2238
2239
Py_ssize_t
2240
_PyIO_find_line_ending(
2241
    int translated, int universal, PyObject *readnl,
2242
    int kind, const char *start, const char *end, Py_ssize_t *consumed)
2243
26.5M
{
2244
26.5M
    Py_ssize_t len = (end - start)/kind;
2245
2246
26.5M
    if (translated) {
2247
        /* Newlines are already translated, only search for \n */
2248
23.7k
        const char *pos = find_control_char(kind, start, end, '\n');
2249
23.7k
        if (pos != NULL)
2250
23.6k
            return (pos - start)/kind + 1;
2251
120
        else {
2252
120
            *consumed = len;
2253
120
            return -1;
2254
120
        }
2255
23.7k
    }
2256
26.5M
    else if (universal) {
2257
        /* Universal newline search. Find any of \r, \r\n, \n
2258
         * The decoder ensures that \r\n are not split in two pieces
2259
         */
2260
19.0M
        const char *s = start;
2261
96.5M
        for (;;) {
2262
96.5M
            Py_UCS4 ch;
2263
            /* Fast path for non-control chars. The loop always ends
2264
               since the Unicode string is NUL-terminated. */
2265
272M
            while (PyUnicode_READ(kind, s, 0) > '\r')
2266
176M
                s += kind;
2267
96.5M
            if (s >= end) {
2268
33.1k
                *consumed = len;
2269
33.1k
                return -1;
2270
33.1k
            }
2271
96.5M
            ch = PyUnicode_READ(kind, s, 0);
2272
96.5M
            s += kind;
2273
96.5M
            if (ch == '\n')
2274
5.63M
                return (s - start)/kind;
2275
90.8M
            if (ch == '\r') {
2276
13.3M
                if (PyUnicode_READ(kind, s, 0) == '\n')
2277
442k
                    return (s - start)/kind + 1;
2278
12.9M
                else
2279
12.9M
                    return (s - start)/kind;
2280
13.3M
            }
2281
90.8M
        }
2282
19.0M
    }
2283
7.52M
    else {
2284
        /* Non-universal mode. */
2285
7.52M
        Py_ssize_t readnl_len = PyUnicode_GET_LENGTH(readnl);
2286
7.52M
        const Py_UCS1 *nl = PyUnicode_1BYTE_DATA(readnl);
2287
        /* Assume that readnl is an ASCII character. */
2288
7.52M
        assert(PyUnicode_KIND(readnl) == PyUnicode_1BYTE_KIND);
2289
7.52M
        if (readnl_len == 1) {
2290
7.52M
            const char *pos = find_control_char(kind, start, end, nl[0]);
2291
7.52M
            if (pos != NULL)
2292
7.52M
                return (pos - start)/kind + 1;
2293
4.82k
            *consumed = len;
2294
4.82k
            return -1;
2295
7.52M
        }
2296
0
        else {
2297
0
            const char *s = start;
2298
0
            const char *e = end - (readnl_len - 1)*kind;
2299
0
            const char *pos;
2300
0
            if (e < s)
2301
0
                e = s;
2302
0
            while (s < e) {
2303
0
                Py_ssize_t i;
2304
0
                const char *pos = find_control_char(kind, s, end, nl[0]);
2305
0
                if (pos == NULL || pos >= e)
2306
0
                    break;
2307
0
                for (i = 1; i < readnl_len; i++) {
2308
0
                    if (PyUnicode_READ(kind, pos, i) != nl[i])
2309
0
                        break;
2310
0
                }
2311
0
                if (i == readnl_len)
2312
0
                    return (pos - start)/kind + readnl_len;
2313
0
                s = pos + kind;
2314
0
            }
2315
0
            pos = find_control_char(kind, e, end, nl[0]);
2316
0
            if (pos == NULL)
2317
0
                *consumed = len;
2318
0
            else
2319
0
                *consumed = (pos - start)/kind;
2320
0
            return -1;
2321
0
        }
2322
7.52M
    }
2323
26.5M
}
2324
2325
static PyObject *
2326
_textiowrapper_readline(textio *self, Py_ssize_t limit)
2327
23.6k
{
2328
23.6k
    PyObject *line = NULL, *chunks = NULL, *remaining = NULL;
2329
23.6k
    Py_ssize_t start, endpos, chunked, offset_to_buffer;
2330
23.6k
    int res;
2331
2332
23.6k
    CHECK_CLOSED(self);
2333
2334
23.6k
    if (_textiowrapper_writeflush(self) < 0)
2335
0
        return NULL;
2336
2337
23.6k
    chunked = 0;
2338
2339
23.7k
    while (1) {
2340
23.7k
        const char *ptr;
2341
23.7k
        Py_ssize_t line_len;
2342
23.7k
        int kind;
2343
23.7k
        Py_ssize_t consumed = 0;
2344
2345
        /* First, get some data if necessary */
2346
23.7k
        res = 1;
2347
23.8k
        while (!self->decoded_chars ||
2348
23.7k
               !PyUnicode_GET_LENGTH(self->decoded_chars)) {
2349
130
            res = textiowrapper_read_chunk(self, 0);
2350
130
            if (res < 0) {
2351
                /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals()
2352
                   when EINTR occurs so we needn't do it ourselves. */
2353
0
                if (_PyIO_trap_eintr()) {
2354
0
                    continue;
2355
0
                }
2356
0
                goto error;
2357
0
            }
2358
130
            if (res == 0)
2359
10
                break;
2360
130
        }
2361
23.7k
        if (res == 0) {
2362
            /* end of file */
2363
10
            textiowrapper_set_decoded_chars(self, NULL);
2364
10
            Py_CLEAR(self->snapshot);
2365
10
            start = endpos = offset_to_buffer = 0;
2366
10
            break;
2367
10
        }
2368
2369
23.7k
        if (remaining == NULL) {
2370
23.7k
            line = Py_NewRef(self->decoded_chars);
2371
23.7k
            start = self->decoded_chars_used;
2372
23.7k
            offset_to_buffer = 0;
2373
23.7k
        }
2374
0
        else {
2375
0
            assert(self->decoded_chars_used == 0);
2376
0
            line = PyUnicode_Concat(remaining, self->decoded_chars);
2377
0
            start = 0;
2378
0
            offset_to_buffer = PyUnicode_GET_LENGTH(remaining);
2379
0
            Py_CLEAR(remaining);
2380
0
            if (line == NULL)
2381
0
                goto error;
2382
0
        }
2383
2384
23.7k
        ptr = PyUnicode_DATA(line);
2385
23.7k
        line_len = PyUnicode_GET_LENGTH(line);
2386
23.7k
        kind = PyUnicode_KIND(line);
2387
2388
23.7k
        endpos = _PyIO_find_line_ending(
2389
23.7k
            self->readtranslate, self->readuniversal, self->readnl,
2390
23.7k
            kind,
2391
23.7k
            ptr + kind * start,
2392
23.7k
            ptr + kind * line_len,
2393
23.7k
            &consumed);
2394
23.7k
        if (endpos >= 0) {
2395
23.6k
            endpos += start;
2396
23.6k
            if (limit >= 0 && (endpos - start) + chunked >= limit)
2397
0
                endpos = start + limit - chunked;
2398
23.6k
            break;
2399
23.6k
        }
2400
2401
        /* We can put aside up to `endpos` */
2402
120
        endpos = consumed + start;
2403
120
        if (limit >= 0 && (endpos - start) + chunked >= limit) {
2404
            /* Didn't find line ending, but reached length limit */
2405
0
            endpos = start + limit - chunked;
2406
0
            break;
2407
0
        }
2408
2409
120
        if (endpos > start) {
2410
            /* No line ending seen yet - put aside current data */
2411
100
            PyObject *s;
2412
100
            if (chunks == NULL) {
2413
100
                chunks = PyList_New(0);
2414
100
                if (chunks == NULL)
2415
0
                    goto error;
2416
100
            }
2417
100
            s = PyUnicode_Substring(line, start, endpos);
2418
100
            if (s == NULL)
2419
0
                goto error;
2420
100
            if (PyList_Append(chunks, s) < 0) {
2421
0
                Py_DECREF(s);
2422
0
                goto error;
2423
0
            }
2424
100
            chunked += PyUnicode_GET_LENGTH(s);
2425
100
            Py_DECREF(s);
2426
100
        }
2427
        /* There may be some remaining bytes we'll have to prepend to the
2428
           next chunk of data */
2429
120
        if (endpos < line_len) {
2430
0
            remaining = PyUnicode_Substring(line, endpos, line_len);
2431
0
            if (remaining == NULL)
2432
0
                goto error;
2433
0
        }
2434
120
        Py_CLEAR(line);
2435
        /* We have consumed the buffer */
2436
120
        textiowrapper_set_decoded_chars(self, NULL);
2437
120
    }
2438
2439
23.6k
    if (line != NULL) {
2440
        /* Our line ends in the current buffer */
2441
23.6k
        self->decoded_chars_used = endpos - offset_to_buffer;
2442
23.6k
        if (start > 0 || endpos < PyUnicode_GET_LENGTH(line)) {
2443
23.6k
            PyObject *s = PyUnicode_Substring(line, start, endpos);
2444
23.6k
            Py_CLEAR(line);
2445
23.6k
            if (s == NULL)
2446
0
                goto error;
2447
23.6k
            line = s;
2448
23.6k
        }
2449
23.6k
    }
2450
23.6k
    if (remaining != NULL) {
2451
0
        if (chunks == NULL) {
2452
0
            chunks = PyList_New(0);
2453
0
            if (chunks == NULL)
2454
0
                goto error;
2455
0
        }
2456
0
        if (PyList_Append(chunks, remaining) < 0)
2457
0
            goto error;
2458
0
        Py_CLEAR(remaining);
2459
0
    }
2460
23.6k
    if (chunks != NULL) {
2461
100
        if (line != NULL) {
2462
100
            if (PyList_Append(chunks, line) < 0)
2463
0
                goto error;
2464
100
            Py_DECREF(line);
2465
100
        }
2466
100
        line = PyUnicode_Join(&_Py_STR(empty), chunks);
2467
100
        if (line == NULL)
2468
0
            goto error;
2469
100
        Py_CLEAR(chunks);
2470
100
    }
2471
23.6k
    if (line == NULL) {
2472
10
        line = &_Py_STR(empty);
2473
10
    }
2474
2475
23.6k
    return line;
2476
2477
0
  error:
2478
0
    Py_XDECREF(chunks);
2479
0
    Py_XDECREF(remaining);
2480
0
    Py_XDECREF(line);
2481
0
    return NULL;
2482
23.6k
}
2483
2484
/*[clinic input]
2485
@critical_section
2486
_io.TextIOWrapper.readline
2487
    size: Py_ssize_t = -1
2488
    /
2489
[clinic start generated code]*/
2490
2491
static PyObject *
2492
_io_TextIOWrapper_readline_impl(textio *self, Py_ssize_t size)
2493
/*[clinic end generated code: output=344afa98804e8b25 input=b65bab871dc3ddba]*/
2494
0
{
2495
0
    CHECK_ATTACHED(self);
2496
0
    return _textiowrapper_readline(self, size);
2497
0
}
2498
2499
/* Seek and Tell */
2500
2501
typedef struct {
2502
    Py_off_t start_pos;
2503
    int dec_flags;
2504
    int bytes_to_feed;
2505
    int chars_to_skip;
2506
    char need_eof;
2507
} cookie_type;
2508
2509
/*
2510
   To speed up cookie packing/unpacking, we store the fields in a temporary
2511
   string and call _PyLong_FromByteArray() or _PyLong_AsByteArray (resp.).
2512
   The following macros define at which offsets in the intermediary byte
2513
   string the various CookieStruct fields will be stored.
2514
 */
2515
2516
#define COOKIE_BUF_LEN      (sizeof(Py_off_t) + 3 * sizeof(int) + sizeof(char))
2517
2518
#if PY_BIG_ENDIAN
2519
/* We want the least significant byte of start_pos to also be the least
2520
   significant byte of the cookie, which means that in big-endian mode we
2521
   must copy the fields in reverse order. */
2522
2523
# define OFF_START_POS      (sizeof(char) + 3 * sizeof(int))
2524
# define OFF_DEC_FLAGS      (sizeof(char) + 2 * sizeof(int))
2525
# define OFF_BYTES_TO_FEED  (sizeof(char) + sizeof(int))
2526
# define OFF_CHARS_TO_SKIP  (sizeof(char))
2527
# define OFF_NEED_EOF       0
2528
2529
#else
2530
/* Little-endian mode: the least significant byte of start_pos will
2531
   naturally end up the least significant byte of the cookie. */
2532
2533
0
# define OFF_START_POS      0
2534
0
# define OFF_DEC_FLAGS      (sizeof(Py_off_t))
2535
0
# define OFF_BYTES_TO_FEED  (sizeof(Py_off_t) + sizeof(int))
2536
0
# define OFF_CHARS_TO_SKIP  (sizeof(Py_off_t) + 2 * sizeof(int))
2537
0
# define OFF_NEED_EOF       (sizeof(Py_off_t) + 3 * sizeof(int))
2538
2539
#endif
2540
2541
static int
2542
textiowrapper_parse_cookie(cookie_type *cookie, PyObject *cookieObj)
2543
0
{
2544
0
    unsigned char buffer[COOKIE_BUF_LEN];
2545
0
    PyLongObject *cookieLong = (PyLongObject *)PyNumber_Long(cookieObj);
2546
0
    if (cookieLong == NULL)
2547
0
        return -1;
2548
2549
0
    if (_PyLong_AsByteArray(cookieLong, buffer, sizeof(buffer),
2550
0
                            PY_LITTLE_ENDIAN, 0, 1) < 0) {
2551
0
        Py_DECREF(cookieLong);
2552
0
        return -1;
2553
0
    }
2554
0
    Py_DECREF(cookieLong);
2555
2556
0
    memcpy(&cookie->start_pos, buffer + OFF_START_POS, sizeof(cookie->start_pos));
2557
0
    memcpy(&cookie->dec_flags, buffer + OFF_DEC_FLAGS, sizeof(cookie->dec_flags));
2558
0
    memcpy(&cookie->bytes_to_feed, buffer + OFF_BYTES_TO_FEED, sizeof(cookie->bytes_to_feed));
2559
0
    memcpy(&cookie->chars_to_skip, buffer + OFF_CHARS_TO_SKIP, sizeof(cookie->chars_to_skip));
2560
0
    memcpy(&cookie->need_eof, buffer + OFF_NEED_EOF, sizeof(cookie->need_eof));
2561
2562
0
    return 0;
2563
0
}
2564
2565
static PyObject *
2566
textiowrapper_build_cookie(cookie_type *cookie)
2567
0
{
2568
0
    unsigned char buffer[COOKIE_BUF_LEN];
2569
2570
0
    memcpy(buffer + OFF_START_POS, &cookie->start_pos, sizeof(cookie->start_pos));
2571
0
    memcpy(buffer + OFF_DEC_FLAGS, &cookie->dec_flags, sizeof(cookie->dec_flags));
2572
0
    memcpy(buffer + OFF_BYTES_TO_FEED, &cookie->bytes_to_feed, sizeof(cookie->bytes_to_feed));
2573
0
    memcpy(buffer + OFF_CHARS_TO_SKIP, &cookie->chars_to_skip, sizeof(cookie->chars_to_skip));
2574
0
    memcpy(buffer + OFF_NEED_EOF, &cookie->need_eof, sizeof(cookie->need_eof));
2575
2576
0
    return _PyLong_FromByteArray(buffer, sizeof(buffer),
2577
0
                                 PY_LITTLE_ENDIAN, 0);
2578
0
}
2579
2580
static int
2581
_textiowrapper_decoder_setstate(textio *self, cookie_type *cookie)
2582
0
{
2583
0
    PyObject *res;
2584
    /* When seeking to the start of the stream, we call decoder.reset()
2585
       rather than decoder.getstate().
2586
       This is for a few decoders such as utf-16 for which the state value
2587
       at start is not (b"", 0) but e.g. (b"", 2) (meaning, in the case of
2588
       utf-16, that we are expecting a BOM).
2589
    */
2590
0
    if (cookie->start_pos == 0 && cookie->dec_flags == 0) {
2591
0
        res = PyObject_CallMethodNoArgs(self->decoder, &_Py_ID(reset));
2592
0
    }
2593
0
    else {
2594
0
        res = _PyObject_CallMethod(self->decoder, &_Py_ID(setstate),
2595
0
                                   "((yi))", "", cookie->dec_flags);
2596
0
    }
2597
0
    if (res == NULL) {
2598
0
        return -1;
2599
0
    }
2600
0
    Py_DECREF(res);
2601
0
    return 0;
2602
0
}
2603
2604
static int
2605
_textiowrapper_encoder_reset(textio *self, int start_of_stream)
2606
0
{
2607
0
    PyObject *res;
2608
0
    if (start_of_stream) {
2609
0
        res = PyObject_CallMethodNoArgs(self->encoder, &_Py_ID(reset));
2610
0
        self->encoding_start_of_stream = 1;
2611
0
    }
2612
0
    else {
2613
0
        res = PyObject_CallMethodOneArg(self->encoder, &_Py_ID(setstate),
2614
0
                                        _PyLong_GetZero());
2615
0
        self->encoding_start_of_stream = 0;
2616
0
    }
2617
0
    if (res == NULL)
2618
0
        return -1;
2619
0
    Py_DECREF(res);
2620
0
    return 0;
2621
0
}
2622
2623
static int
2624
_textiowrapper_encoder_setstate(textio *self, cookie_type *cookie)
2625
0
{
2626
    /* Same as _textiowrapper_decoder_setstate() above. */
2627
0
    return _textiowrapper_encoder_reset(
2628
0
        self, cookie->start_pos == 0 && cookie->dec_flags == 0);
2629
0
}
2630
2631
/*[clinic input]
2632
@critical_section
2633
_io.TextIOWrapper.seek
2634
    cookie as cookieObj: object
2635
      Zero or an opaque number returned by tell().
2636
    whence: int(c_default='0') = os.SEEK_SET
2637
      The relative position to seek from.
2638
    /
2639
2640
Set the stream position, and return the new stream position.
2641
2642
Four operations are supported, given by the following argument
2643
combinations:
2644
2645
- seek(0, SEEK_SET): Rewind to the start of the stream.
2646
- seek(cookie, SEEK_SET): Restore a previous position;
2647
  'cookie' must be a number returned by tell().
2648
- seek(0, SEEK_END): Fast-forward to the end of the stream.
2649
- seek(0, SEEK_CUR): Leave the current stream position unchanged.
2650
2651
Any other argument combinations are invalid,
2652
and may raise exceptions.
2653
[clinic start generated code]*/
2654
2655
static PyObject *
2656
_io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence)
2657
/*[clinic end generated code: output=0a15679764e2d04d input=4bea78698be23d7e]*/
2658
0
{
2659
0
    PyObject *posobj;
2660
0
    cookie_type cookie;
2661
0
    PyObject *res;
2662
0
    int cmp;
2663
0
    PyObject *snapshot;
2664
2665
0
    CHECK_ATTACHED(self);
2666
0
    CHECK_CLOSED(self);
2667
2668
0
    Py_INCREF(cookieObj);
2669
2670
0
    if (!self->seekable) {
2671
0
        _unsupported(self->state, "underlying stream is not seekable");
2672
0
        goto fail;
2673
0
    }
2674
2675
0
    PyObject *zero = _PyLong_GetZero();  // borrowed reference
2676
2677
0
    switch (whence) {
2678
0
    case SEEK_CUR:
2679
        /* seek relative to current position */
2680
0
        cmp = PyObject_RichCompareBool(cookieObj, zero, Py_EQ);
2681
0
        if (cmp < 0)
2682
0
            goto fail;
2683
2684
0
        if (cmp == 0) {
2685
0
            _unsupported(self->state, "can't do nonzero cur-relative seeks");
2686
0
            goto fail;
2687
0
        }
2688
2689
        /* Seeking to the current position should attempt to
2690
         * sync the underlying buffer with the current position.
2691
         */
2692
0
        Py_DECREF(cookieObj);
2693
0
        cookieObj = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(tell));
2694
0
        if (cookieObj == NULL)
2695
0
            goto fail;
2696
0
        break;
2697
2698
0
    case SEEK_END:
2699
        /* seek relative to end of file */
2700
0
        cmp = PyObject_RichCompareBool(cookieObj, zero, Py_EQ);
2701
0
        if (cmp < 0)
2702
0
            goto fail;
2703
2704
0
        if (cmp == 0) {
2705
0
            _unsupported(self->state, "can't do nonzero end-relative seeks");
2706
0
            goto fail;
2707
0
        }
2708
2709
0
        if (_PyFile_Flush((PyObject *)self) < 0) {
2710
0
            goto fail;
2711
0
        }
2712
2713
0
        textiowrapper_set_decoded_chars(self, NULL);
2714
0
        Py_CLEAR(self->snapshot);
2715
0
        if (self->decoder) {
2716
0
            res = PyObject_CallMethodNoArgs(self->decoder, &_Py_ID(reset));
2717
0
            if (res == NULL)
2718
0
                goto fail;
2719
0
            Py_DECREF(res);
2720
0
        }
2721
2722
0
        PyObject *buf = buffer_access_safe(self);
2723
0
        if (buf == NULL) {
2724
0
            goto fail;
2725
0
        }
2726
0
        res = _PyObject_CallMethod(buf, &_Py_ID(seek), "ii", 0, 2);
2727
0
        Py_DECREF(buf);
2728
0
        Py_CLEAR(cookieObj);
2729
0
        if (res == NULL)
2730
0
            goto fail;
2731
0
        if (self->encoder) {
2732
            /* If seek() == 0, we are at the start of stream, otherwise not */
2733
0
            cmp = PyObject_RichCompareBool(res, zero, Py_EQ);
2734
0
            if (cmp < 0 || _textiowrapper_encoder_reset(self, cmp)) {
2735
0
                Py_DECREF(res);
2736
0
                goto fail;
2737
0
            }
2738
0
        }
2739
0
        return res;
2740
2741
0
    case SEEK_SET:
2742
0
        break;
2743
2744
0
    default:
2745
0
        PyErr_Format(PyExc_ValueError,
2746
0
                     "invalid whence (%d, should be %d, %d or %d)", whence,
2747
0
                     SEEK_SET, SEEK_CUR, SEEK_END);
2748
0
        goto fail;
2749
0
    }
2750
2751
0
    cmp = PyObject_RichCompareBool(cookieObj, zero, Py_LT);
2752
0
    if (cmp < 0)
2753
0
        goto fail;
2754
2755
0
    if (cmp == 1) {
2756
0
        PyErr_Format(PyExc_ValueError,
2757
0
                     "negative seek position %R", cookieObj);
2758
0
        goto fail;
2759
0
    }
2760
2761
0
    if (_PyFile_Flush((PyObject *)self) < 0) {
2762
0
        goto fail;
2763
0
    }
2764
2765
    /* The strategy of seek() is to go back to the safe start point
2766
     * and replay the effect of read(chars_to_skip) from there.
2767
     */
2768
0
    if (textiowrapper_parse_cookie(&cookie, cookieObj) < 0)
2769
0
        goto fail;
2770
2771
    /* Seek back to the safe start point. */
2772
0
    posobj = PyLong_FromOff_t(cookie.start_pos);
2773
0
    if (posobj == NULL)
2774
0
        goto fail;
2775
0
    res = buffer_callmethod_onearg(self, &_Py_ID(seek), posobj);
2776
0
    Py_DECREF(posobj);
2777
0
    if (res == NULL)
2778
0
        goto fail;
2779
0
    Py_DECREF(res);
2780
2781
0
    textiowrapper_set_decoded_chars(self, NULL);
2782
0
    Py_CLEAR(self->snapshot);
2783
2784
    /* Restore the decoder to its state from the safe start point. */
2785
0
    if (self->decoder) {
2786
0
        if (_textiowrapper_decoder_setstate(self, &cookie) < 0)
2787
0
            goto fail;
2788
0
    }
2789
2790
0
    if (cookie.chars_to_skip) {
2791
        /* Just like _read_chunk, feed the decoder and save a snapshot. */
2792
0
        PyObject *bytes_to_feed = PyLong_FromLong(cookie.bytes_to_feed);
2793
0
        if (bytes_to_feed == NULL) {
2794
0
            goto fail;
2795
0
        }
2796
0
        PyObject *input_chunk = buffer_callmethod_onearg(self,
2797
0
                                                         &_Py_ID(read),
2798
0
                                                         bytes_to_feed);
2799
0
        Py_DECREF(bytes_to_feed);
2800
2801
0
        PyObject *decoded;
2802
2803
0
        if (input_chunk == NULL)
2804
0
            goto fail;
2805
2806
0
        if (!PyBytes_Check(input_chunk)) {
2807
0
            PyErr_Format(PyExc_TypeError,
2808
0
                         "underlying read() should have returned a bytes "
2809
0
                         "object, not '%.200s'",
2810
0
                         Py_TYPE(input_chunk)->tp_name);
2811
0
            Py_DECREF(input_chunk);
2812
0
            goto fail;
2813
0
        }
2814
2815
0
        snapshot = Py_BuildValue("iN", cookie.dec_flags, input_chunk);
2816
0
        if (snapshot == NULL) {
2817
0
            goto fail;
2818
0
        }
2819
0
        Py_XSETREF(self->snapshot, snapshot);
2820
2821
0
        decoded = PyObject_CallMethodObjArgs(self->decoder, &_Py_ID(decode),
2822
0
            input_chunk, cookie.need_eof ? Py_True : Py_False, NULL);
2823
2824
0
        if (check_decoded(decoded) < 0)
2825
0
            goto fail;
2826
2827
0
        textiowrapper_set_decoded_chars(self, decoded);
2828
2829
        /* Skip chars_to_skip of the decoded characters. */
2830
0
        if (PyUnicode_GetLength(self->decoded_chars) < cookie.chars_to_skip) {
2831
0
            PyErr_SetString(PyExc_OSError, "can't restore logical file position");
2832
0
            goto fail;
2833
0
        }
2834
0
        self->decoded_chars_used = cookie.chars_to_skip;
2835
0
    }
2836
0
    else {
2837
0
        snapshot = Py_BuildValue("iy", cookie.dec_flags, "");
2838
0
        if (snapshot == NULL)
2839
0
            goto fail;
2840
0
        Py_XSETREF(self->snapshot, snapshot);
2841
0
    }
2842
2843
    /* Finally, reset the encoder (merely useful for proper BOM handling) */
2844
0
    if (self->encoder) {
2845
0
        if (_textiowrapper_encoder_setstate(self, &cookie) < 0)
2846
0
            goto fail;
2847
0
    }
2848
0
    return cookieObj;
2849
0
  fail:
2850
0
    Py_XDECREF(cookieObj);
2851
0
    return NULL;
2852
2853
0
}
2854
2855
/*[clinic input]
2856
@critical_section
2857
_io.TextIOWrapper.tell
2858
2859
Return the stream position as an opaque number.
2860
2861
The return value of tell() can be given as input to seek(), to
2862
restore a previous stream position.
2863
[clinic start generated code]*/
2864
2865
static PyObject *
2866
_io_TextIOWrapper_tell_impl(textio *self)
2867
/*[clinic end generated code: output=4f168c08bf34ad5f input=aeece020f747fd92]*/
2868
0
{
2869
0
    PyObject *res;
2870
0
    PyObject *posobj = NULL;
2871
0
    cookie_type cookie = {0,0,0,0,0};
2872
0
    PyObject *next_input = NULL;
2873
0
    Py_ssize_t chars_to_skip, chars_decoded;
2874
0
    Py_ssize_t skip_bytes, skip_back;
2875
0
    PyObject *saved_state = NULL;
2876
0
    const char *input, *input_end;
2877
0
    Py_ssize_t dec_buffer_len;
2878
0
    int dec_flags;
2879
2880
0
    CHECK_ATTACHED(self);
2881
0
    CHECK_CLOSED(self);
2882
2883
0
    if (!self->seekable) {
2884
0
        _unsupported(self->state, "underlying stream is not seekable");
2885
0
        goto fail;
2886
0
    }
2887
0
    if (!self->telling) {
2888
0
        PyErr_SetString(PyExc_OSError,
2889
0
                        "telling position disabled by next() call");
2890
0
        goto fail;
2891
0
    }
2892
2893
0
    if (_textiowrapper_writeflush(self) < 0)
2894
0
        return NULL;
2895
0
    if (_PyFile_Flush((PyObject *)self) < 0) {
2896
0
        goto fail;
2897
0
    }
2898
2899
0
    posobj = buffer_callmethod_noargs(self, &_Py_ID(tell));
2900
0
    if (posobj == NULL)
2901
0
        goto fail;
2902
2903
0
    if (self->decoder == NULL || self->snapshot == NULL) {
2904
0
        assert (self->decoded_chars == NULL || PyUnicode_GetLength(self->decoded_chars) == 0);
2905
0
        return posobj;
2906
0
    }
2907
2908
#if defined(HAVE_LARGEFILE_SUPPORT)
2909
    cookie.start_pos = PyLong_AsLongLong(posobj);
2910
#else
2911
0
    cookie.start_pos = PyLong_AsLong(posobj);
2912
0
#endif
2913
0
    Py_DECREF(posobj);
2914
0
    if (PyErr_Occurred())
2915
0
        goto fail;
2916
2917
    /* Skip backward to the snapshot point (see _read_chunk). */
2918
0
    assert(PyTuple_Check(self->snapshot));
2919
0
    if (!PyArg_ParseTuple(self->snapshot, "iO", &cookie.dec_flags, &next_input))
2920
0
        goto fail;
2921
2922
0
    assert (PyBytes_Check(next_input));
2923
2924
    /* Own next_input: a reentrant or concurrent seek can drop the snapshot. */
2925
0
    Py_INCREF(next_input);
2926
2927
0
    cookie.start_pos -= PyBytes_GET_SIZE(next_input);
2928
2929
    /* How many decoded characters have been used up since the snapshot? */
2930
0
    if (self->decoded_chars_used == 0)  {
2931
        /* We haven't moved from the snapshot point. */
2932
0
        Py_DECREF(next_input);
2933
0
        return textiowrapper_build_cookie(&cookie);
2934
0
    }
2935
2936
0
    chars_to_skip = self->decoded_chars_used;
2937
2938
    /* Decoder state will be restored at the end */
2939
0
    saved_state = PyObject_CallMethodNoArgs(self->decoder,
2940
0
                                             &_Py_ID(getstate));
2941
0
    if (saved_state == NULL)
2942
0
        goto fail;
2943
2944
0
#define DECODER_GETSTATE() do { \
2945
0
        PyObject *dec_buffer; \
2946
0
        PyObject *_state = PyObject_CallMethodNoArgs(self->decoder, \
2947
0
            &_Py_ID(getstate)); \
2948
0
        if (_state == NULL) \
2949
0
            goto fail; \
2950
0
        if (!PyTuple_Check(_state)) { \
2951
0
            PyErr_SetString(PyExc_TypeError, \
2952
0
                            "illegal decoder state"); \
2953
0
            Py_DECREF(_state); \
2954
0
            goto fail; \
2955
0
        } \
2956
0
        if (!PyArg_ParseTuple(_state, "Oi;illegal decoder state", \
2957
0
                              &dec_buffer, &dec_flags)) \
2958
0
        { \
2959
0
            Py_DECREF(_state); \
2960
0
            goto fail; \
2961
0
        } \
2962
0
        if (!PyBytes_Check(dec_buffer)) { \
2963
0
            PyErr_Format(PyExc_TypeError, \
2964
0
                         "illegal decoder state: the first item should be a " \
2965
0
                         "bytes object, not '%.200s'", \
2966
0
                         Py_TYPE(dec_buffer)->tp_name); \
2967
0
            Py_DECREF(_state); \
2968
0
            goto fail; \
2969
0
        } \
2970
0
        dec_buffer_len = PyBytes_GET_SIZE(dec_buffer); \
2971
0
        Py_DECREF(_state); \
2972
0
    } while (0)
2973
2974
0
#define DECODER_DECODE(start, len, res) do { \
2975
0
        PyObject *_decoded = _PyObject_CallMethod( \
2976
0
            self->decoder, &_Py_ID(decode), "y#", start, len); \
2977
0
        if (check_decoded(_decoded) < 0) \
2978
0
            goto fail; \
2979
0
        res = PyUnicode_GET_LENGTH(_decoded); \
2980
0
        Py_DECREF(_decoded); \
2981
0
    } while (0)
2982
2983
    /* Fast search for an acceptable start point, close to our
2984
       current pos */
2985
0
    skip_bytes = (Py_ssize_t) (self->b2cratio * chars_to_skip);
2986
0
    skip_back = 1;
2987
0
    assert(skip_bytes <= PyBytes_GET_SIZE(next_input));
2988
0
    input = PyBytes_AS_STRING(next_input);
2989
0
    while (skip_bytes > 0) {
2990
        /* Decode up to temptative start point */
2991
0
        if (_textiowrapper_decoder_setstate(self, &cookie) < 0)
2992
0
            goto fail;
2993
0
        DECODER_DECODE(input, skip_bytes, chars_decoded);
2994
0
        if (chars_decoded <= chars_to_skip) {
2995
0
            DECODER_GETSTATE();
2996
0
            if (dec_buffer_len == 0) {
2997
                /* Before pos and no bytes buffered in decoder => OK */
2998
0
                cookie.dec_flags = dec_flags;
2999
0
                chars_to_skip -= chars_decoded;
3000
0
                break;
3001
0
            }
3002
            /* Skip back by buffered amount and reset heuristic */
3003
0
            skip_bytes -= dec_buffer_len;
3004
0
            skip_back = 1;
3005
0
        }
3006
0
        else {
3007
            /* We're too far ahead, skip back a bit */
3008
0
            skip_bytes -= skip_back;
3009
0
            skip_back *= 2;
3010
0
        }
3011
0
    }
3012
0
    if (skip_bytes <= 0) {
3013
0
        skip_bytes = 0;
3014
0
        if (_textiowrapper_decoder_setstate(self, &cookie) < 0)
3015
0
            goto fail;
3016
0
    }
3017
3018
    /* Note our initial start point. */
3019
0
    cookie.start_pos += skip_bytes;
3020
0
    cookie.chars_to_skip = Py_SAFE_DOWNCAST(chars_to_skip, Py_ssize_t, int);
3021
0
    if (chars_to_skip == 0)
3022
0
        goto finally;
3023
3024
    /* We should be close to the desired position.  Now feed the decoder one
3025
     * byte at a time until we reach the `chars_to_skip` target.
3026
     * As we go, note the nearest "safe start point" before the current
3027
     * location (a point where the decoder has nothing buffered, so seek()
3028
     * can safely start from there and advance to this location).
3029
     */
3030
0
    chars_decoded = 0;
3031
0
    input = PyBytes_AS_STRING(next_input);
3032
0
    input_end = input + PyBytes_GET_SIZE(next_input);
3033
0
    input += skip_bytes;
3034
0
    while (input < input_end) {
3035
0
        Py_ssize_t n;
3036
3037
0
        DECODER_DECODE(input, (Py_ssize_t)1, n);
3038
        /* We got n chars for 1 byte */
3039
0
        chars_decoded += n;
3040
0
        cookie.bytes_to_feed += 1;
3041
0
        DECODER_GETSTATE();
3042
3043
0
        if (dec_buffer_len == 0 && chars_decoded <= chars_to_skip) {
3044
            /* Decoder buffer is empty, so this is a safe start point. */
3045
0
            cookie.start_pos += cookie.bytes_to_feed;
3046
0
            chars_to_skip -= chars_decoded;
3047
0
            cookie.dec_flags = dec_flags;
3048
0
            cookie.bytes_to_feed = 0;
3049
0
            chars_decoded = 0;
3050
0
        }
3051
0
        if (chars_decoded >= chars_to_skip)
3052
0
            break;
3053
0
        input++;
3054
0
    }
3055
0
    if (input == input_end) {
3056
        /* We didn't get enough decoded data; signal EOF to get more. */
3057
0
        PyObject *decoded = _PyObject_CallMethod(
3058
0
            self->decoder, &_Py_ID(decode), "yO", "", /* final = */ Py_True);
3059
0
        if (check_decoded(decoded) < 0)
3060
0
            goto fail;
3061
0
        chars_decoded += PyUnicode_GET_LENGTH(decoded);
3062
0
        Py_DECREF(decoded);
3063
0
        cookie.need_eof = 1;
3064
3065
0
        if (chars_decoded < chars_to_skip) {
3066
0
            PyErr_SetString(PyExc_OSError,
3067
0
                            "can't reconstruct logical file position");
3068
0
            goto fail;
3069
0
        }
3070
0
    }
3071
3072
0
finally:
3073
0
    Py_XDECREF(next_input);
3074
0
    res = PyObject_CallMethodOneArg(
3075
0
            self->decoder, &_Py_ID(setstate), saved_state);
3076
0
    Py_DECREF(saved_state);
3077
0
    if (res == NULL)
3078
0
        return NULL;
3079
0
    Py_DECREF(res);
3080
3081
    /* The returned cookie corresponds to the last safe start point. */
3082
0
    cookie.chars_to_skip = Py_SAFE_DOWNCAST(chars_to_skip, Py_ssize_t, int);
3083
0
    return textiowrapper_build_cookie(&cookie);
3084
3085
0
fail:
3086
0
    Py_XDECREF(next_input);
3087
0
    if (saved_state) {
3088
0
        PyObject *exc = PyErr_GetRaisedException();
3089
0
        res = PyObject_CallMethodOneArg(
3090
0
                self->decoder, &_Py_ID(setstate), saved_state);
3091
0
        _PyErr_ChainExceptions1(exc);
3092
0
        Py_DECREF(saved_state);
3093
0
        Py_XDECREF(res);
3094
0
    }
3095
0
    return NULL;
3096
0
}
3097
3098
/*[clinic input]
3099
@critical_section
3100
_io.TextIOWrapper.truncate
3101
    pos: object = None
3102
    /
3103
[clinic start generated code]*/
3104
3105
static PyObject *
3106
_io_TextIOWrapper_truncate_impl(textio *self, PyObject *pos)
3107
/*[clinic end generated code: output=90ec2afb9bb7745f input=8bddb320834c93ee]*/
3108
0
{
3109
0
    CHECK_ATTACHED(self)
3110
3111
0
    if (_PyFile_Flush((PyObject *)self) < 0) {
3112
0
        return NULL;
3113
0
    }
3114
3115
0
    return buffer_callmethod_onearg(self, &_Py_ID(truncate), pos);
3116
0
}
3117
3118
static PyObject *
3119
textiowrapper_repr(PyObject *op)
3120
0
{
3121
0
    PyObject *nameobj, *modeobj, *res, *s;
3122
0
    int status;
3123
0
    textio *self = textio_CAST(op);
3124
0
    const char *type_name = Py_TYPE(self)->tp_name;
3125
3126
0
    CHECK_INITIALIZED(self);
3127
3128
0
    res = PyUnicode_FromFormat("<%.100s", type_name);
3129
0
    if (res == NULL)
3130
0
        return NULL;
3131
3132
0
    status = Py_ReprEnter(op);
3133
0
    if (status != 0) {
3134
0
        if (status > 0) {
3135
0
            PyErr_Format(PyExc_RuntimeError,
3136
0
                         "reentrant call inside %.100s.__repr__",
3137
0
                         type_name);
3138
0
        }
3139
0
        goto error;
3140
0
    }
3141
0
    if (PyObject_GetOptionalAttr(op, &_Py_ID(name), &nameobj) < 0) {
3142
0
        if (!PyErr_ExceptionMatches(PyExc_ValueError)) {
3143
0
            goto error;
3144
0
        }
3145
        /* Ignore ValueError raised if the underlying stream was detached */
3146
0
        PyErr_Clear();
3147
0
    }
3148
0
    if (nameobj != NULL) {
3149
0
        s = PyUnicode_FromFormat(" name=%R", nameobj);
3150
0
        Py_DECREF(nameobj);
3151
0
        if (s == NULL)
3152
0
            goto error;
3153
0
        PyUnicode_AppendAndDel(&res, s);
3154
0
        if (res == NULL)
3155
0
            goto error;
3156
0
    }
3157
0
    if (PyObject_GetOptionalAttr(op, &_Py_ID(mode), &modeobj) < 0) {
3158
0
        goto error;
3159
0
    }
3160
0
    if (modeobj != NULL) {
3161
0
        s = PyUnicode_FromFormat(" mode=%R", modeobj);
3162
0
        Py_DECREF(modeobj);
3163
0
        if (s == NULL)
3164
0
            goto error;
3165
0
        PyUnicode_AppendAndDel(&res, s);
3166
0
        if (res == NULL)
3167
0
            goto error;
3168
0
    }
3169
0
    s = PyUnicode_FromFormat("%U encoding=%R>",
3170
0
                             res, self->encoding);
3171
0
    Py_DECREF(res);
3172
0
    if (status == 0) {
3173
0
        Py_ReprLeave(op);
3174
0
    }
3175
0
    return s;
3176
3177
0
  error:
3178
0
    Py_XDECREF(res);
3179
0
    if (status == 0) {
3180
0
        Py_ReprLeave(op);
3181
0
    }
3182
0
    return NULL;
3183
0
}
3184
3185
3186
/* Inquiries */
3187
3188
/*[clinic input]
3189
@critical_section
3190
_io.TextIOWrapper.fileno
3191
[clinic start generated code]*/
3192
3193
static PyObject *
3194
_io_TextIOWrapper_fileno_impl(textio *self)
3195
/*[clinic end generated code: output=21490a4c3da13e6c input=515e1196aceb97ab]*/
3196
0
{
3197
0
    return buffer_callmethod_noargs(self, &_Py_ID(fileno));
3198
0
}
3199
3200
/*[clinic input]
3201
@critical_section
3202
_io.TextIOWrapper.seekable
3203
[clinic start generated code]*/
3204
3205
static PyObject *
3206
_io_TextIOWrapper_seekable_impl(textio *self)
3207
/*[clinic end generated code: output=ab223dbbcffc0f00 input=71c4c092736c549b]*/
3208
0
{
3209
0
    return buffer_callmethod_noargs(self, &_Py_ID(seekable));
3210
0
}
3211
3212
/*[clinic input]
3213
@critical_section
3214
_io.TextIOWrapper.readable
3215
[clinic start generated code]*/
3216
3217
static PyObject *
3218
_io_TextIOWrapper_readable_impl(textio *self)
3219
/*[clinic end generated code: output=72ff7ba289a8a91b input=80438d1f01b0a89b]*/
3220
0
{
3221
0
    return buffer_callmethod_noargs(self, &_Py_ID(readable));
3222
0
}
3223
3224
/*[clinic input]
3225
@critical_section
3226
_io.TextIOWrapper.writable
3227
[clinic start generated code]*/
3228
3229
static PyObject *
3230
_io_TextIOWrapper_writable_impl(textio *self)
3231
/*[clinic end generated code: output=a728c71790d03200 input=9d6c22befb0c340a]*/
3232
0
{
3233
0
    return buffer_callmethod_noargs(self, &_Py_ID(writable));
3234
0
}
3235
3236
/*[clinic input]
3237
@critical_section
3238
_io.TextIOWrapper.isatty
3239
[clinic start generated code]*/
3240
3241
static PyObject *
3242
_io_TextIOWrapper_isatty_impl(textio *self)
3243
/*[clinic end generated code: output=12be1a35bace882e input=7f83ff04d4d1733d]*/
3244
0
{
3245
0
    return buffer_callmethod_noargs(self, &_Py_ID(isatty));
3246
0
}
3247
3248
/*[clinic input]
3249
@critical_section
3250
_io.TextIOWrapper.flush
3251
[clinic start generated code]*/
3252
3253
static PyObject *
3254
_io_TextIOWrapper_flush_impl(textio *self)
3255
/*[clinic end generated code: output=59de9165f9c2e4d2 input=3ac3bf521bfed59d]*/
3256
19
{
3257
19
    CHECK_ATTACHED(self);
3258
19
    CHECK_CLOSED(self);
3259
19
    self->telling = self->seekable;
3260
19
    if (_textiowrapper_writeflush(self) < 0)
3261
0
        return NULL;
3262
19
    return buffer_callmethod_noargs(self, &_Py_ID(flush));
3263
19
}
3264
3265
/*[clinic input]
3266
@critical_section
3267
_io.TextIOWrapper.close
3268
[clinic start generated code]*/
3269
3270
static PyObject *
3271
_io_TextIOWrapper_close_impl(textio *self)
3272
/*[clinic end generated code: output=056ccf8b4876e4f4 input=8e12d7079d5ac5c1]*/
3273
19
{
3274
19
    PyObject *res;
3275
19
    int r;
3276
19
    CHECK_ATTACHED(self);
3277
3278
19
    res = _io_TextIOWrapper_closed_get_impl(self);
3279
19
    if (res == NULL)
3280
0
        return NULL;
3281
19
    r = PyObject_IsTrue(res);
3282
19
    Py_DECREF(res);
3283
19
    if (r < 0)
3284
0
        return NULL;
3285
3286
19
    if (r > 0) {
3287
0
        Py_RETURN_NONE; /* stream already closed */
3288
0
    }
3289
19
    if (self->detached) {
3290
0
        Py_RETURN_NONE; /* gh-142594 null pointer issue */
3291
0
    }
3292
19
    else {
3293
19
        PyObject *exc = NULL;
3294
19
        if (self->finalizing) {
3295
0
            res = buffer_callmethod_onearg(self,
3296
0
                                           &_Py_ID(_dealloc_warn),
3297
0
                                           (PyObject *)self);
3298
0
            if (res) {
3299
0
                Py_DECREF(res);
3300
0
            }
3301
0
            else {
3302
0
                PyErr_Clear();
3303
0
            }
3304
0
        }
3305
19
        if (_PyFile_Flush((PyObject *)self) < 0) {
3306
0
            exc = PyErr_GetRaisedException();
3307
0
        }
3308
3309
19
        res = buffer_callmethod_noargs(self, &_Py_ID(close));
3310
19
        if (exc != NULL) {
3311
0
            _PyErr_ChainExceptions1(exc);
3312
0
            Py_CLEAR(res);
3313
0
        }
3314
19
        return res;
3315
19
    }
3316
19
}
3317
3318
/*[clinic input]
3319
@critical_section
3320
_io.TextIOWrapper.__next__ as textiowrapper_iternext
3321
[clinic start generated code]*/
3322
3323
static PyObject *
3324
textiowrapper_iternext_impl(textio *self)
3325
/*[clinic end generated code: output=f365c4287cd43a1f input=c5b4c79faf0c98cb]*/
3326
23.6k
{
3327
23.6k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
3328
23.6k
    PyObject *line;
3329
3330
23.6k
    CHECK_ATTACHED(self);
3331
3332
23.6k
    self->telling = 0;
3333
23.6k
    if (Py_IS_TYPE(self, self->state->PyTextIOWrapper_Type)) {
3334
        /* Skip method call overhead for speed */
3335
23.6k
        line = _textiowrapper_readline(self, -1);
3336
23.6k
    }
3337
0
    else {
3338
0
        line = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(readline));
3339
0
        if (line && !PyUnicode_Check(line)) {
3340
0
            PyErr_Format(PyExc_OSError,
3341
0
                         "readline() should have returned a str object, "
3342
0
                         "not '%.200s'", Py_TYPE(line)->tp_name);
3343
0
            Py_DECREF(line);
3344
0
            return NULL;
3345
0
        }
3346
0
    }
3347
3348
23.6k
    if (line == NULL)
3349
0
        return NULL;
3350
3351
23.6k
    if (PyUnicode_GET_LENGTH(line) == 0) {
3352
        /* Reached EOF or would have blocked */
3353
10
        Py_DECREF(line);
3354
10
        Py_CLEAR(self->snapshot);
3355
10
        self->telling = self->seekable;
3356
10
        return NULL;
3357
10
    }
3358
3359
23.6k
    return line;
3360
23.6k
}
3361
3362
/*[clinic input]
3363
@critical_section
3364
@getter
3365
_io.TextIOWrapper.name
3366
[clinic start generated code]*/
3367
3368
static PyObject *
3369
_io_TextIOWrapper_name_get_impl(textio *self)
3370
/*[clinic end generated code: output=8c2f1d6d8756af40 input=26ecec9b39e30e07]*/
3371
0
{
3372
0
    return buffer_getattr(self, &_Py_ID(name));
3373
0
}
3374
3375
/*[clinic input]
3376
@critical_section
3377
@getter
3378
_io.TextIOWrapper.closed
3379
[clinic start generated code]*/
3380
3381
static PyObject *
3382
_io_TextIOWrapper_closed_get_impl(textio *self)
3383
/*[clinic end generated code: output=b49b68f443a85e3c input=7dfcf43f63c7003d]*/
3384
67
{
3385
    /* If partially constructed or deconstructed, return that the underlying
3386
       buffer is closed.
3387
3388
       The code managing the transition is responsible for closing. The closed
3389
       attribute is often called in re-initalization, as part of repr in error
3390
       cases, and when the I/O stack is garbage collected. */
3391
67
    if (self->ok <= 0) {
3392
0
        Py_RETURN_TRUE;
3393
0
    }
3394
3395
67
    return buffer_getattr(self, &_Py_ID(closed));
3396
67
}
3397
3398
/*[clinic input]
3399
@critical_section
3400
@getter
3401
_io.TextIOWrapper.newlines
3402
[clinic start generated code]*/
3403
3404
static PyObject *
3405
_io_TextIOWrapper_newlines_get_impl(textio *self)
3406
/*[clinic end generated code: output=53aa03ac35573180 input=610df647e514b3e8]*/
3407
0
{
3408
0
    PyObject *res;
3409
0
    CHECK_ATTACHED(self);
3410
0
    if (self->decoder == NULL ||
3411
0
        PyObject_GetOptionalAttr(self->decoder, &_Py_ID(newlines), &res) == 0)
3412
0
    {
3413
0
        Py_RETURN_NONE;
3414
0
    }
3415
0
    return res;
3416
0
}
3417
3418
/*[clinic input]
3419
@critical_section
3420
@getter
3421
_io.TextIOWrapper.errors
3422
[clinic start generated code]*/
3423
3424
static PyObject *
3425
_io_TextIOWrapper_errors_get_impl(textio *self)
3426
/*[clinic end generated code: output=dca3a3ef21b09484 input=b45f983e6d43c4d8]*/
3427
0
{
3428
0
    CHECK_INITIALIZED(self);
3429
0
    return Py_NewRef(self->errors);
3430
0
}
3431
3432
/*[clinic input]
3433
@critical_section
3434
@getter
3435
_io.TextIOWrapper._CHUNK_SIZE -> Py_ssize_t
3436
[clinic start generated code]*/
3437
3438
static Py_ssize_t
3439
_io_TextIOWrapper__CHUNK_SIZE_get_impl(textio *self)
3440
/*[clinic end generated code: output=3fe34b873b6b2c8c input=cae767b74b6b46bd]*/
3441
0
{
3442
0
    CHECK_ATTACHED_INT(self);
3443
0
    return self->chunk_size;
3444
0
}
3445
3446
/*[clinic input]
3447
@critical_section
3448
@setter
3449
_io.TextIOWrapper._CHUNK_SIZE
3450
    value: Py_ssize_t
3451
[clinic start generated code]*/
3452
3453
static int
3454
_io_TextIOWrapper__CHUNK_SIZE_set_impl(textio *self, Py_ssize_t value)
3455
/*[clinic end generated code: output=5170a93dd4d74917 input=ede7bae6145f941b]*/
3456
0
{
3457
0
    CHECK_ATTACHED_INT(self);
3458
0
    if (value <= 0) {
3459
0
        PyErr_SetString(PyExc_ValueError,
3460
0
                        "a strictly positive integer is required");
3461
0
        return -1;
3462
0
    }
3463
0
    self->chunk_size = value;
3464
0
    return 0;
3465
0
}
3466
3467
/*[clinic input]
3468
@critical_section
3469
@getter
3470
_io.TextIOWrapper.buffer
3471
[clinic start generated code]*/
3472
3473
static PyObject *
3474
_io_TextIOWrapper_buffer_get_impl(textio *self)
3475
/*[clinic end generated code: output=d265a34555aa5d4b input=5951cfa148f7350a]*/
3476
0
{
3477
0
    return buffer_access_safe(self);
3478
0
}
3479
3480
static PyMethodDef incrementalnewlinedecoder_methods[] = {
3481
    _IO_INCREMENTALNEWLINEDECODER_DECODE_METHODDEF
3482
    _IO_INCREMENTALNEWLINEDECODER_GETSTATE_METHODDEF
3483
    _IO_INCREMENTALNEWLINEDECODER_SETSTATE_METHODDEF
3484
    _IO_INCREMENTALNEWLINEDECODER_RESET_METHODDEF
3485
    {NULL}
3486
};
3487
3488
static PyGetSetDef incrementalnewlinedecoder_getset[] = {
3489
    _IO_INCREMENTALNEWLINEDECODER_NEWLINES_GETSETDEF
3490
    {NULL}
3491
};
3492
3493
static PyType_Slot nldecoder_slots[] = {
3494
    {Py_tp_dealloc, incrementalnewlinedecoder_dealloc},
3495
    {Py_tp_doc, (void *)_io_IncrementalNewlineDecoder___init____doc__},
3496
    {Py_tp_methods, incrementalnewlinedecoder_methods},
3497
    {Py_tp_getset, incrementalnewlinedecoder_getset},
3498
    {Py_tp_traverse, incrementalnewlinedecoder_traverse},
3499
    {Py_tp_clear, incrementalnewlinedecoder_clear},
3500
    {Py_tp_init, _io_IncrementalNewlineDecoder___init__},
3501
    {0, NULL},
3502
};
3503
3504
PyType_Spec _Py_nldecoder_spec = {
3505
    .name = "_io.IncrementalNewlineDecoder",
3506
    .basicsize = sizeof(nldecoder_object),
3507
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
3508
              Py_TPFLAGS_IMMUTABLETYPE),
3509
    .slots = nldecoder_slots,
3510
};
3511
3512
3513
static PyMethodDef textiowrapper_methods[] = {
3514
    _IO_TEXTIOWRAPPER_DETACH_METHODDEF
3515
    _IO_TEXTIOWRAPPER_RECONFIGURE_METHODDEF
3516
    _IO_TEXTIOWRAPPER_WRITE_METHODDEF
3517
    _IO_TEXTIOWRAPPER_READ_METHODDEF
3518
    _IO_TEXTIOWRAPPER_READLINE_METHODDEF
3519
    _IO_TEXTIOWRAPPER_FLUSH_METHODDEF
3520
    _IO_TEXTIOWRAPPER_CLOSE_METHODDEF
3521
3522
    _IO_TEXTIOWRAPPER_FILENO_METHODDEF
3523
    _IO_TEXTIOWRAPPER_SEEKABLE_METHODDEF
3524
    _IO_TEXTIOWRAPPER_READABLE_METHODDEF
3525
    _IO_TEXTIOWRAPPER_WRITABLE_METHODDEF
3526
    _IO_TEXTIOWRAPPER_ISATTY_METHODDEF
3527
3528
    _IO_TEXTIOWRAPPER_SEEK_METHODDEF
3529
    _IO_TEXTIOWRAPPER_TELL_METHODDEF
3530
    _IO_TEXTIOWRAPPER_TRUNCATE_METHODDEF
3531
3532
    {"__getstate__", _PyIOBase_cannot_pickle, METH_NOARGS},
3533
    {NULL, NULL}
3534
};
3535
3536
static PyMemberDef textiowrapper_members[] = {
3537
    {"encoding", _Py_T_OBJECT, offsetof(textio, encoding), Py_READONLY},
3538
    {"line_buffering", Py_T_BOOL, offsetof(textio, line_buffering), Py_READONLY},
3539
    {"write_through", Py_T_BOOL, offsetof(textio, write_through), Py_READONLY},
3540
    {"_finalizing", Py_T_BOOL, offsetof(textio, finalizing), 0},
3541
    {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(textio, weakreflist), Py_READONLY},
3542
    {"__dictoffset__", Py_T_PYSSIZET, offsetof(textio, dict), Py_READONLY},
3543
    {NULL}
3544
};
3545
3546
static PyGetSetDef textiowrapper_getset[] = {
3547
    _IO_TEXTIOWRAPPER_NAME_GETSETDEF
3548
    _IO_TEXTIOWRAPPER_CLOSED_GETSETDEF
3549
    _IO_TEXTIOWRAPPER_NEWLINES_GETSETDEF
3550
    _IO_TEXTIOWRAPPER_ERRORS_GETSETDEF
3551
    _IO_TEXTIOWRAPPER__CHUNK_SIZE_GETSETDEF
3552
    _IO_TEXTIOWRAPPER_BUFFER_GETSETDEF
3553
    {NULL}
3554
};
3555
3556
static PyType_Slot textiowrapper_slots[] = {
3557
    {Py_tp_dealloc, textiowrapper_dealloc},
3558
    {Py_tp_repr, textiowrapper_repr},
3559
    {Py_tp_doc, (void *)_io_TextIOWrapper___init____doc__},
3560
    {Py_tp_traverse, textiowrapper_traverse},
3561
    {Py_tp_clear, textiowrapper_clear},
3562
    {Py_tp_iternext, textiowrapper_iternext},
3563
    {Py_tp_methods, textiowrapper_methods},
3564
    {Py_tp_members, textiowrapper_members},
3565
    {Py_tp_getset, textiowrapper_getset},
3566
    {Py_tp_init, _io_TextIOWrapper___init__},
3567
    {0, NULL},
3568
};
3569
3570
PyType_Spec _Py_textiowrapper_spec = {
3571
    .name = "_io.TextIOWrapper",
3572
    .basicsize = sizeof(textio),
3573
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
3574
              Py_TPFLAGS_IMMUTABLETYPE),
3575
    .slots = textiowrapper_slots,
3576
};