Coverage Report

Created: 2026-10-17 06:15

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