Coverage Report

Created: 2026-07-14 06:16

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