Coverage Report

Created: 2026-09-01 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython3/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
20
#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
3
{
253
254
3
    if (errors == NULL) {
255
3
        errors = &_Py_ID(strict);
256
3
    }
257
0
    else {
258
0
        errors = Py_NewRef(errors);
259
0
    }
260
261
3
    Py_XSETREF(self->errors, errors);
262
3
    Py_XSETREF(self->decoder, Py_NewRef(decoder));
263
3
    self->translate = translate ? 1 : 0;
264
3
    self->seennl = 0;
265
3
    self->pendingcr = 0;
266
267
3
    return 0;
268
3
}
269
270
static int
271
incrementalnewlinedecoder_traverse(PyObject *op, visitproc visit, void *arg)
272
0
{
273
0
    nldecoder_object *self = nldecoder_object_CAST(op);
274
0
    Py_VISIT(Py_TYPE(self));
275
0
    Py_VISIT(self->decoder);
276
0
    Py_VISIT(self->errors);
277
0
    return 0;
278
0
}
279
280
static int
281
incrementalnewlinedecoder_clear(PyObject *op)
282
3
{
283
3
    nldecoder_object *self = nldecoder_object_CAST(op);
284
3
    Py_CLEAR(self->decoder);
285
3
    Py_CLEAR(self->errors);
286
3
    return 0;
287
3
}
288
289
static void
290
incrementalnewlinedecoder_dealloc(PyObject *op)
291
3
{
292
3
    nldecoder_object *self = nldecoder_object_CAST(op);
293
3
    PyTypeObject *tp = Py_TYPE(self);
294
3
    _PyObject_GC_UNTRACK(self);
295
3
    (void)incrementalnewlinedecoder_clear(op);
296
3
    tp->tp_free(self);
297
3
    Py_DECREF(tp);
298
3
}
299
300
static int
301
check_decoded(PyObject *decoded)
302
28
{
303
28
    if (decoded == NULL)
304
0
        return -1;
305
28
    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
28
    return 0;
313
28
}
314
315
#define CHECK_INITIALIZED_DECODER(self) \
316
14
    if (self->errors == NULL) { \
317
0
        PyErr_SetString(PyExc_ValueError, \
318
0
                        "IncrementalNewlineDecoder.__init__() not called"); \
319
0
        return NULL; \
320
0
    }
321
322
0
#define SEEN_CR   1
323
25
#define SEEN_LF   2
324
0
#define SEEN_CRLF 4
325
0
#define SEEN_ALL (SEEN_CR | SEEN_LF | SEEN_CRLF)
326
327
PyObject *
328
_PyIncrementalNewlineDecoder_decode(PyObject *myself,
329
                                    PyObject *input, int final)
330
14
{
331
14
    PyObject *output;
332
14
    Py_ssize_t output_len;
333
14
    nldecoder_object *self = nldecoder_object_CAST(myself);
334
335
14
    CHECK_INITIALIZED_DECODER(self);
336
337
    /* decode input (with the eventual \r from a previous pass) */
338
14
    if (self->decoder != Py_None) {
339
14
        output = PyObject_CallMethodObjArgs(self->decoder,
340
14
            &_Py_ID(decode), input, final ? Py_True : Py_False, NULL);
341
14
    }
342
0
    else {
343
0
        output = Py_NewRef(input);
344
0
    }
345
346
14
    if (check_decoded(output) < 0)
347
0
        return NULL;
348
349
14
    output_len = PyUnicode_GET_LENGTH(output);
350
14
    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
14
    if (!final) {
373
11
        if (output_len > 0
374
11
            && 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
11
    }
383
384
    /* Record which newlines are read and do newline translation if desired,
385
       all in one pass. */
386
14
    {
387
14
        const void *in_str;
388
14
        Py_ssize_t len;
389
14
        int seennl = self->seennl;
390
14
        int only_lf = 0;
391
14
        int kind;
392
393
14
        in_str = PyUnicode_DATA(output);
394
14
        len = PyUnicode_GET_LENGTH(output);
395
14
        kind = PyUnicode_KIND(output);
396
397
14
        if (len == 0)
398
3
            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
11
        if (seennl == SEEN_LF || seennl == 0) {
404
11
            only_lf = (memchr(in_str, '\r', kind * len) == NULL);
405
11
        }
406
407
11
        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
11
            if (seennl == 0 &&
412
3
                memchr(in_str, '\n', kind * len) != NULL) {
413
3
                if (kind == PyUnicode_1BYTE_KIND)
414
3
                    seennl |= SEEN_LF;
415
0
                else {
416
0
                    Py_ssize_t i = 0;
417
0
                    for (;;) {
418
0
                        Py_UCS4 c;
419
                        /* Fast loop for non-control characters */
420
0
                        while (PyUnicode_READ(kind, in_str, i) > '\n')
421
0
                            i++;
422
0
                        c = PyUnicode_READ(kind, in_str, i++);
423
0
                        if (c == '\n') {
424
0
                            seennl |= SEEN_LF;
425
0
                            break;
426
0
                        }
427
0
                        if (i >= len)
428
0
                            break;
429
0
                    }
430
0
                }
431
3
            }
432
            /* Finished: we have scanned for newlines, and none of them
433
               need translating */
434
11
        }
435
0
        else if (!self->translate) {
436
0
            Py_ssize_t i = 0;
437
            /* We have already seen all newline types, no need to scan again */
438
0
            if (seennl == SEEN_ALL)
439
0
                goto endscan;
440
0
            for (;;) {
441
0
                Py_UCS4 c;
442
                /* Fast loop for non-control characters */
443
0
                while (PyUnicode_READ(kind, in_str, i) > '\r')
444
0
                    i++;
445
0
                c = PyUnicode_READ(kind, in_str, i++);
446
0
                if (c == '\n')
447
0
                    seennl |= SEEN_LF;
448
0
                else if (c == '\r') {
449
0
                    if (PyUnicode_READ(kind, in_str, i) == '\n') {
450
0
                        seennl |= SEEN_CRLF;
451
0
                        i++;
452
0
                    }
453
0
                    else
454
0
                        seennl |= SEEN_CR;
455
0
                }
456
0
                if (i >= len)
457
0
                    break;
458
0
                if (seennl == SEEN_ALL)
459
0
                    break;
460
0
            }
461
0
        endscan:
462
0
            ;
463
0
        }
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
11
        self->seennl |= seennl;
512
11
    }
513
514
0
    return output;
515
516
0
  error:
517
0
    Py_DECREF(output);
518
0
    return NULL;
519
11
}
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
3.18k
#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
697k
{
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
697k
    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
697k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
759
697k
    return self->buffer;
760
697k
}
761
762
static PyObject *
763
buffer_getattr(textio *self, PyObject *attr_name)
764
12
{
765
12
    PyObject *buffer = buffer_access_safe(self);
766
12
    if (buffer == NULL) {
767
0
        return NULL;
768
0
    }
769
770
12
    return PyObject_GetAttr(buffer, attr_name);
771
12
}
772
773
static PyObject *
774
buffer_callmethod_noargs(textio *self, PyObject *name)
775
180
{
776
180
    PyObject *buffer = buffer_access_safe(self);
777
180
    if (buffer == NULL) {
778
0
        return NULL;
779
0
    }
780
781
180
    return PyObject_CallMethodNoArgs(buffer, name);
782
180
}
783
784
static PyObject *
785
buffer_callmethod_onearg(textio *self, PyObject *name, PyObject *arg)
786
348k
{
787
348k
    PyObject *buffer = buffer_access_safe(self);
788
348k
    if (buffer == NULL) {
789
0
        return NULL;
790
0
    }
791
792
348k
    return PyObject_CallMethodOneArg(buffer, name, arg);
793
348k
}
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
0
{
869
0
    textio *self = textio_CAST(op);
870
0
    return _PyUnicode_AsUTF8String(text, PyUnicode_AsUTF8(self->errors));
871
0
}
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
348k
{
884
348k
    return f == ascii_encode || f == latin1_encode || f == utf8_encode;
885
348k
}
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
66
{
910
66
    if (newline && newline[0] != '\0'
911
63
        && !(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
66
    return 0;
919
66
}
920
921
static int
922
set_newline(textio *self, const char *newline)
923
66
{
924
66
    PyObject *old = self->readnl;
925
66
    if (newline == NULL) {
926
3
        self->readnl = NULL;
927
3
    }
928
63
    else {
929
63
        self->readnl = PyUnicode_FromString(newline);
930
63
        if (self->readnl == NULL) {
931
0
            self->readnl = old;
932
0
            return -1;
933
0
        }
934
63
    }
935
66
    self->readuniversal = (newline == NULL || newline[0] == '\0');
936
66
    self->readtranslate = (newline == NULL);
937
66
    self->writetranslate = (newline == NULL || newline[0] != '\0');
938
66
    if (!self->readuniversal && self->readnl != NULL) {
939
        // validate_newline() accepts only ASCII newlines.
940
63
        assert(PyUnicode_KIND(self->readnl) == PyUnicode_1BYTE_KIND);
941
63
        self->writenl = (const char *)PyUnicode_1BYTE_DATA(self->readnl);
942
63
        if (strcmp(self->writenl, "\n") == 0) {
943
63
            self->writenl = NULL;
944
63
        }
945
63
    }
946
3
    else {
947
#ifdef MS_WINDOWS
948
        self->writenl = "\r\n";
949
#else
950
3
        self->writenl = NULL;
951
3
#endif
952
3
    }
953
66
    Py_XDECREF(old);
954
66
    return 0;
955
66
}
956
957
static int
958
_textiowrapper_set_decoder(textio *self, PyObject *codec_info,
959
                           const char *errors)
960
66
{
961
66
    PyObject *res;
962
66
    int r;
963
964
66
    res = buffer_callmethod_noargs(self, &_Py_ID(readable));
965
66
    if (res == NULL)
966
0
        return -1;
967
968
66
    r = PyObject_IsTrue(res);
969
66
    Py_DECREF(res);
970
66
    if (r == -1)
971
0
        return -1;
972
973
66
    if (r != 1)
974
42
        return 0;
975
976
24
    Py_CLEAR(self->decoder);
977
24
    self->decoder = _PyCodecInfo_GetIncrementalDecoder(codec_info, errors);
978
24
    if (self->decoder == NULL)
979
0
        return -1;
980
981
24
    if (self->readuniversal) {
982
3
        _PyIO_State *state = self->state;
983
3
        PyObject *incrementalDecoder = PyObject_CallFunctionObjArgs(
984
3
            (PyObject *)state->PyIncrementalNewlineDecoder_Type,
985
3
            self->decoder, self->readtranslate ? Py_True : Py_False, NULL);
986
3
        if (incrementalDecoder == NULL)
987
0
            return -1;
988
3
        Py_XSETREF(self->decoder, incrementalDecoder);
989
3
    }
990
991
24
    return 0;
992
24
}
993
994
static PyObject*
995
_textiowrapper_decode(_PyIO_State *state, PyObject *decoder, PyObject *bytes,
996
                      int eof)
997
14
{
998
14
    PyObject *chars;
999
1000
14
    if (Py_IS_TYPE(decoder, state->PyIncrementalNewlineDecoder_Type))
1001
14
        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
14
    if (check_decoded(chars) < 0)
1007
        // check_decoded already decreases refcount
1008
0
        return NULL;
1009
1010
14
    return chars;
1011
14
}
1012
1013
static int
1014
_textiowrapper_set_encoder(textio *self, PyObject *codec_info,
1015
                           const char *errors)
1016
66
{
1017
66
    PyObject *res;
1018
66
    int r;
1019
1020
66
    res = buffer_callmethod_noargs(self, &_Py_ID(writable));
1021
66
    if (res == NULL)
1022
0
        return -1;
1023
1024
66
    r = PyObject_IsTrue(res);
1025
66
    Py_DECREF(res);
1026
66
    if (r == -1)
1027
0
        return -1;
1028
1029
66
    if (r != 1)
1030
24
        return 0;
1031
1032
42
    Py_CLEAR(self->encoder);
1033
42
    self->encodefunc = NULL;
1034
42
    self->encoder = _PyCodecInfo_GetIncrementalEncoder(codec_info, errors);
1035
42
    if (self->encoder == NULL)
1036
0
        return -1;
1037
1038
    /* Get the normalized named of the codec */
1039
42
    if (PyObject_GetOptionalAttr(codec_info, &_Py_ID(name), &res) < 0) {
1040
0
        return -1;
1041
0
    }
1042
42
    if (res != NULL && PyUnicode_Check(res)) {
1043
42
        const encodefuncentry *e = encodefuncs;
1044
126
        while (e->name != NULL) {
1045
126
            if (_PyUnicode_EqualToASCIIString(res, e->name)) {
1046
42
                self->encodefunc = e->encodefunc;
1047
42
                break;
1048
42
            }
1049
84
            e++;
1050
84
        }
1051
42
    }
1052
42
    Py_XDECREF(res);
1053
1054
42
    return 0;
1055
42
}
1056
1057
static int
1058
_textiowrapper_fix_encoder_state(textio *self)
1059
66
{
1060
66
    if (!self->seekable || !self->encoder) {
1061
24
        return 0;
1062
24
    }
1063
1064
42
    self->encoding_start_of_stream = 1;
1065
1066
42
    PyObject *cookieObj = buffer_callmethod_noargs(self, &_Py_ID(tell));
1067
42
    if (cookieObj == NULL) {
1068
0
        return -1;
1069
0
    }
1070
1071
42
    int cmp = PyObject_RichCompareBool(cookieObj, _PyLong_GetZero(), Py_EQ);
1072
42
    Py_DECREF(cookieObj);
1073
42
    if (cmp < 0) {
1074
0
        return -1;
1075
0
    }
1076
1077
42
    if (cmp == 0) {
1078
20
        self->encoding_start_of_stream = 0;
1079
20
        PyObject *res = PyObject_CallMethodOneArg(
1080
20
            self->encoder, &_Py_ID(setstate), _PyLong_GetZero());
1081
20
        if (res == NULL) {
1082
0
            return -1;
1083
0
        }
1084
20
        Py_DECREF(res);
1085
20
    }
1086
1087
42
    return 0;
1088
42
}
1089
1090
static int
1091
io_check_errors(PyObject *errors)
1092
63
{
1093
63
    assert(errors != NULL && errors != Py_None);
1094
1095
63
    PyInterpreterState *interp = _PyInterpreterState_GET();
1096
63
#ifndef Py_DEBUG
1097
    /* In release mode, only check in development mode (-X dev) */
1098
63
    if (!_PyInterpreterState_GetConfig(interp)->dev_mode) {
1099
63
        return 0;
1100
63
    }
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
66
{
1172
66
    PyObject *raw, *codec_info = NULL;
1173
66
    PyObject *res;
1174
66
    int r;
1175
1176
66
    self->ok = 0;
1177
66
    self->detached = 0;
1178
1179
66
    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
66
    if (errors == Py_None) {
1190
3
        errors = &_Py_ID(strict);
1191
3
    }
1192
63
    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
63
    else if (io_check_errors(errors)) {
1202
0
        return -1;
1203
0
    }
1204
66
    const char *errors_str = _PyUnicode_AsUTF8NoNUL(errors);
1205
66
    if (errors_str == NULL) {
1206
0
        return -1;
1207
0
    }
1208
1209
66
    if (validate_newline(newline) < 0) {
1210
0
        return -1;
1211
0
    }
1212
1213
66
    Py_CLEAR(self->buffer);
1214
66
    Py_CLEAR(self->encoding);
1215
66
    Py_CLEAR(self->encoder);
1216
66
    Py_CLEAR(self->decoder);
1217
66
    Py_CLEAR(self->readnl);
1218
66
    Py_CLEAR(self->decoded_chars);
1219
66
    Py_CLEAR(self->pending_bytes);
1220
66
    Py_CLEAR(self->snapshot);
1221
66
    Py_CLEAR(self->errors);
1222
66
    Py_CLEAR(self->raw);
1223
66
    self->decoded_chars_used = 0;
1224
66
    self->pending_bytes_count = 0;
1225
66
    self->encodefunc = NULL;
1226
66
    self->b2cratio = 0.0;
1227
1228
66
    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
66
    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
66
    if (self->encoding != NULL) {
1241
0
        encoding = PyUnicode_AsUTF8(self->encoding);
1242
0
        if (encoding == NULL)
1243
0
            goto error;
1244
0
    }
1245
66
    else if (encoding != NULL) {
1246
66
        self->encoding = PyUnicode_FromString(encoding);
1247
66
        if (self->encoding == NULL)
1248
0
            goto error;
1249
66
    }
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
66
    codec_info = _PyCodec_LookupTextEncoding(encoding, NULL);
1258
66
    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
66
    self->errors = Py_NewRef(errors);
1268
66
    self->chunk_size = 8192;
1269
66
    self->line_buffering = line_buffering;
1270
66
    self->write_through = write_through;
1271
66
    if (set_newline(self, newline) < 0) {
1272
0
        goto error;
1273
0
    }
1274
1275
66
    self->buffer = Py_NewRef(buffer);
1276
1277
    /* Build the decoder object */
1278
66
    _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
1279
66
    self->state = state;
1280
66
    if (_textiowrapper_set_decoder(self, codec_info, errors_str) != 0)
1281
0
        goto error;
1282
1283
    /* Build the encoder object */
1284
66
    if (_textiowrapper_set_encoder(self, codec_info, errors_str) != 0)
1285
0
        goto error;
1286
1287
    /* Finished sorting out the codec details */
1288
66
    Py_CLEAR(codec_info);
1289
1290
66
    if (Py_IS_TYPE(buffer, state->PyBufferedReader_Type) ||
1291
42
        Py_IS_TYPE(buffer, state->PyBufferedWriter_Type) ||
1292
0
        Py_IS_TYPE(buffer, state->PyBufferedRandom_Type))
1293
66
    {
1294
66
        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
66
        if (raw != NULL) {
1298
66
            if (Py_IS_TYPE(raw, state->PyFileIO_Type))
1299
66
                self->raw = raw;
1300
0
            else
1301
0
                Py_DECREF(raw);
1302
66
        }
1303
66
    }
1304
1305
66
    res = PyObject_CallMethodNoArgs(buffer, &_Py_ID(seekable));
1306
66
    if (res == NULL)
1307
0
        goto error;
1308
66
    r = PyObject_IsTrue(res);
1309
66
    Py_DECREF(res);
1310
66
    if (r < 0)
1311
0
        goto error;
1312
66
    self->seekable = self->telling = r;
1313
1314
66
    r = PyObject_HasAttrWithError(buffer, &_Py_ID(read1));
1315
66
    if (r < 0) {
1316
0
        goto error;
1317
0
    }
1318
66
    self->has_read1 = r;
1319
1320
66
    self->encoding_start_of_stream = 0;
1321
66
    if (_textiowrapper_fix_encoder_state(self) < 0) {
1322
0
        goto error;
1323
0
    }
1324
1325
66
    self->ok = 1;
1326
66
    return 0;
1327
1328
0
  error:
1329
0
    Py_XDECREF(codec_info);
1330
0
    return -1;
1331
66
}
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
3
{
1514
3
    textio *self = textio_CAST(op);
1515
3
    self->ok = 0;
1516
3
    Py_CLEAR(self->buffer);
1517
3
    Py_CLEAR(self->encoding);
1518
3
    Py_CLEAR(self->encoder);
1519
3
    Py_CLEAR(self->decoder);
1520
3
    Py_CLEAR(self->readnl);
1521
3
    Py_CLEAR(self->decoded_chars);
1522
3
    Py_CLEAR(self->pending_bytes);
1523
3
    Py_CLEAR(self->snapshot);
1524
3
    Py_CLEAR(self->errors);
1525
3
    Py_CLEAR(self->raw);
1526
1527
3
    Py_CLEAR(self->dict);
1528
3
    return 0;
1529
3
}
1530
1531
static void
1532
textiowrapper_dealloc(PyObject *op)
1533
3
{
1534
3
    textio *self = textio_CAST(op);
1535
3
    PyTypeObject *tp = Py_TYPE(self);
1536
3
    self->finalizing = 1;
1537
3
    if (_PyIOBase_finalize(op) < 0)
1538
0
        return;
1539
3
    self->ok = 0;
1540
3
    _PyObject_GC_UNTRACK(self);
1541
3
    FT_CLEAR_WEAKREFS(op, self->weakreflist);
1542
3
    (void)textiowrapper_clear(op);
1543
3
    tp->tp_free(self);
1544
3
    Py_DECREF(tp);
1545
3
}
1546
1547
static int
1548
textiowrapper_traverse(PyObject *op, visitproc visit, void *arg)
1549
1.09k
{
1550
1.09k
    textio *self = textio_CAST(op);
1551
1.09k
    Py_VISIT(Py_TYPE(self));
1552
1.09k
    Py_VISIT(self->buffer);
1553
1.09k
    Py_VISIT(self->encoding);
1554
1.09k
    Py_VISIT(self->encoder);
1555
1.09k
    Py_VISIT(self->decoder);
1556
1.09k
    Py_VISIT(self->readnl);
1557
1.09k
    Py_VISIT(self->decoded_chars);
1558
1.09k
    Py_VISIT(self->pending_bytes);
1559
1.09k
    Py_VISIT(self->snapshot);
1560
1.09k
    Py_VISIT(self->errors);
1561
1.09k
    Py_VISIT(self->raw);
1562
1563
1.09k
    Py_VISIT(self->dict);
1564
1.09k
    return 0;
1565
1.09k
}
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
350k
    do { \
1573
350k
        int r; \
1574
350k
        PyObject *_res; \
1575
350k
        if (Py_IS_TYPE(self, self->state->PyTextIOWrapper_Type)) { \
1576
350k
            if (self->raw != NULL) \
1577
350k
                r = _PyFileIO_closed(self->raw); \
1578
350k
            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
350k
            if (r > 0) { \
1588
0
                PyErr_SetString(PyExc_ValueError, \
1589
0
                                "I/O operation on closed file."); \
1590
0
                return NULL; \
1591
0
            } \
1592
350k
        } \
1593
350k
        else if (_PyIOBase_check_closed((PyObject *)self, Py_True) == NULL) \
1594
0
            return NULL; \
1595
350k
    } while (0)
1596
1597
#define CHECK_INITIALIZED(self) \
1598
350k
    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
350k
    CHECK_INITIALIZED(self); \
1606
350k
    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
350k
{
1652
350k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
1653
1654
350k
    if (self->pending_bytes == NULL)
1655
2.08k
        return 0;
1656
1657
348k
    PyObject *pending = self->pending_bytes;
1658
348k
    PyObject *b;
1659
1660
348k
    if (PyBytes_Check(pending)) {
1661
0
        b = Py_NewRef(pending);
1662
0
    }
1663
348k
    else if (PyUnicode_Check(pending)) {
1664
348k
        assert(PyUnicode_IS_ASCII(pending));
1665
348k
        assert(PyUnicode_GET_LENGTH(pending) == self->pending_bytes_count);
1666
348k
        b = PyBytes_FromStringAndSize(
1667
348k
                PyUnicode_DATA(pending), PyUnicode_GET_LENGTH(pending));
1668
348k
        if (b == NULL) {
1669
0
            return -1;
1670
0
        }
1671
348k
    }
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
348k
    self->pending_bytes_count = 0;
1705
348k
    self->pending_bytes = NULL;
1706
348k
    Py_DECREF(pending);
1707
1708
348k
    PyObject *ret;
1709
348k
    do {
1710
348k
        ret = buffer_callmethod_onearg(self, &_Py_ID(write), b);
1711
348k
    } while (ret == NULL && _PyIO_trap_eintr());
1712
348k
    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
348k
    if (ret == NULL)
1716
0
        return -1;
1717
348k
    Py_DECREF(ret);
1718
348k
    return 0;
1719
348k
}
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
348k
{
1732
348k
    PyObject *ret;
1733
348k
    PyObject *b;
1734
348k
    Py_ssize_t textlen;
1735
348k
    int haslf = 0;
1736
348k
    int needflush = 0, text_needflush = 0;
1737
1738
348k
    CHECK_ATTACHED(self);
1739
348k
    CHECK_CLOSED(self);
1740
1741
348k
    if (self->encoder == NULL) {
1742
0
        return _unsupported(self->state, "not writable");
1743
0
    }
1744
1745
348k
    Py_INCREF(text);
1746
1747
348k
    textlen = PyUnicode_GET_LENGTH(text);
1748
1749
348k
    if ((self->writetranslate && self->writenl != NULL) || self->line_buffering)
1750
348k
        if (PyUnicode_FindChar(text, '\n', 0, PyUnicode_GET_LENGTH(text), 1) != -1)
1751
348k
            haslf = 1;
1752
1753
348k
    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
348k
    if (self->write_through)
1763
0
        text_needflush = 1;
1764
348k
    if (self->line_buffering &&
1765
348k
        (haslf ||
1766
0
         PyUnicode_FindChar(text, '\r', 0, PyUnicode_GET_LENGTH(text), 1) != -1))
1767
348k
        needflush = 1;
1768
1769
    /* XXX What if we were just reading? */
1770
348k
    if (self->encodefunc != NULL) {
1771
348k
        if (PyUnicode_IS_ASCII(text) &&
1772
                // See bpo-43260
1773
348k
                PyUnicode_GET_LENGTH(text) <= self->chunk_size &&
1774
348k
                is_asciicompat_encoding(self->encodefunc)) {
1775
348k
            b = Py_NewRef(text);
1776
348k
        }
1777
0
        else {
1778
0
            b = (*self->encodefunc)((PyObject *) self, text);
1779
0
        }
1780
348k
        self->encoding_start_of_stream = 0;
1781
348k
    }
1782
0
    else {
1783
0
        b = PyObject_CallMethodOneArg(self->encoder, &_Py_ID(encode), text);
1784
0
    }
1785
1786
348k
    Py_DECREF(text);
1787
348k
    if (b == NULL)
1788
0
        return NULL;
1789
348k
    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
348k
    Py_ssize_t bytes_len;
1798
348k
    if (b == text) {
1799
348k
        bytes_len = PyUnicode_GET_LENGTH(b);
1800
348k
    }
1801
0
    else {
1802
0
        bytes_len = PyBytes_GET_SIZE(b);
1803
0
    }
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
348k
    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
348k
    if (bytes_len > 0) {
1824
348k
        if (self->pending_bytes == NULL) {
1825
348k
            assert(self->pending_bytes_count == 0);
1826
348k
            self->pending_bytes = b;
1827
348k
        }
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
348k
        self->pending_bytes_count += bytes_len;
1850
348k
    }
1851
0
    else {
1852
0
        Py_DECREF(b);
1853
0
    }
1854
1855
348k
    if (self->pending_bytes_count >= self->chunk_size || needflush ||
1856
348k
        text_needflush) {
1857
348k
        if (_textiowrapper_writeflush(self) < 0)
1858
0
            return NULL;
1859
348k
    }
1860
1861
348k
    if (needflush) {
1862
348k
        PyObject *buffer = buffer_access_safe(self);
1863
348k
        if (buffer == NULL || _PyFile_Flush(buffer) < 0) {
1864
0
            return NULL;
1865
0
        }
1866
348k
    }
1867
1868
348k
    if (self->snapshot != NULL) {
1869
0
        textiowrapper_set_decoded_chars(self, NULL);
1870
0
        Py_CLEAR(self->snapshot);
1871
0
    }
1872
1873
348k
    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
348k
    return PyLong_FromSsize_t(textlen);
1881
348k
}
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
28
{
1888
28
    Py_XSETREF(self->decoded_chars, chars);
1889
28
    self->decoded_chars_used = 0;
1890
28
}
1891
1892
static PyObject *
1893
textiowrapper_get_decoded_chars(textio *self, Py_ssize_t n)
1894
0
{
1895
0
    PyObject *chars;
1896
0
    Py_ssize_t avail;
1897
1898
0
    if (self->decoded_chars == NULL)
1899
0
        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
14
{
1929
14
    PyObject *dec_buffer = NULL;
1930
14
    PyObject *dec_flags = NULL;
1931
14
    PyObject *input_chunk = NULL;
1932
14
    Py_buffer input_chunk_buf;
1933
14
    PyObject *decoded_chars, *chunk_size;
1934
14
    Py_ssize_t nbytes, nchars;
1935
14
    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
14
    if (self->decoder == NULL) {
1944
0
        _unsupported(self->state, "not readable");
1945
0
        return -1;
1946
0
    }
1947
1948
14
    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
14
    if (size_hint > 0) {
1987
0
        size_hint = (Py_ssize_t)(Py_MAX(self->b2cratio, 1.0) * size_hint);
1988
0
    }
1989
14
    chunk_size = PyLong_FromSsize_t(Py_MAX(self->chunk_size, size_hint));
1990
14
    if (chunk_size == NULL)
1991
0
        goto fail;
1992
1993
14
    input_chunk = buffer_callmethod_onearg(self,
1994
14
                                           (self->has_read1 ? &_Py_ID(read1) :
1995
14
                                                              &_Py_ID(read)),
1996
14
                                           chunk_size);
1997
14
    Py_DECREF(chunk_size);
1998
14
    if (input_chunk == NULL)
1999
0
        goto fail;
2000
2001
14
    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
14
    nbytes = input_chunk_buf.len;
2010
14
    eof = (nbytes == 0);
2011
2012
14
    decoded_chars = _textiowrapper_decode(self->state, self->decoder,
2013
14
                                          input_chunk, eof);
2014
14
    PyBuffer_Release(&input_chunk_buf);
2015
14
    if (decoded_chars == NULL)
2016
0
        goto fail;
2017
2018
14
    textiowrapper_set_decoded_chars(self, decoded_chars);
2019
14
    nchars = PyUnicode_GET_LENGTH(decoded_chars);
2020
14
    if (nchars > 0)
2021
11
        self->b2cratio = (double) nbytes / nchars;
2022
3
    else
2023
3
        self->b2cratio = 0.0;
2024
14
    if (nchars > 0)
2025
11
        eof = 0;
2026
2027
14
    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
14
    Py_DECREF(input_chunk);
2045
2046
14
    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
14
}
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
0
{
2066
0
    PyObject *result = NULL, *chunks = NULL;
2067
2068
0
    CHECK_ATTACHED(self);
2069
0
    CHECK_CLOSED(self);
2070
2071
0
    if (self->decoder == NULL) {
2072
0
        return _unsupported(self->state, "not readable");
2073
0
    }
2074
2075
0
    if (_textiowrapper_writeflush(self) < 0)
2076
0
        return NULL;
2077
2078
0
    if (n < 0) {
2079
        /* Read everything */
2080
0
        PyObject *bytes = buffer_callmethod_noargs(self, &_Py_ID(read));
2081
0
        PyObject *decoded;
2082
0
        if (bytes == NULL)
2083
0
            goto fail;
2084
2085
0
        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
0
        _PyIO_State *state = self->state;
2092
0
        if (Py_IS_TYPE(self->decoder, state->PyIncrementalNewlineDecoder_Type))
2093
0
            decoded = _PyIncrementalNewlineDecoder_decode(self->decoder,
2094
0
                                                          bytes, 1);
2095
0
        else
2096
0
            decoded = PyObject_CallMethodObjArgs(
2097
0
                self->decoder, &_Py_ID(decode), bytes, Py_True, NULL);
2098
0
        Py_DECREF(bytes);
2099
0
        if (check_decoded(decoded) < 0)
2100
0
            goto fail;
2101
2102
0
        result = textiowrapper_get_decoded_chars(self, -1);
2103
2104
0
        if (result == NULL) {
2105
0
            Py_DECREF(decoded);
2106
0
            return NULL;
2107
0
        }
2108
2109
0
        PyUnicode_AppendAndDel(&result, decoded);
2110
0
        if (result == NULL)
2111
0
            goto fail;
2112
2113
0
        if (self->snapshot != NULL) {
2114
0
            textiowrapper_set_decoded_chars(self, NULL);
2115
0
            Py_CLEAR(self->snapshot);
2116
0
        }
2117
0
        return result;
2118
0
    }
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
0
}
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
2.08k
{
2179
2.08k
    if (kind == PyUnicode_1BYTE_KIND) {
2180
2.08k
        assert(ch < 256);
2181
2.08k
        return (char *) memchr((const void *) s, (char) ch, end - s);
2182
2.08k
    }
2183
0
    for (;;) {
2184
0
        while (PyUnicode_READ(kind, s, 0) > ch)
2185
0
            s += kind;
2186
0
        if (PyUnicode_READ(kind, s, 0) == ch)
2187
0
            return s;
2188
0
        if (s == end)
2189
0
            return NULL;
2190
0
        s += kind;
2191
0
    }
2192
0
}
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
2.08k
{
2199
2.08k
    Py_ssize_t len = (end - start)/kind;
2200
2201
2.08k
    if (translated) {
2202
        /* Newlines are already translated, only search for \n */
2203
2.08k
        const char *pos = find_control_char(kind, start, end, '\n');
2204
2.08k
        if (pos != NULL)
2205
2.07k
            return (pos - start)/kind + 1;
2206
11
        else {
2207
11
            *consumed = len;
2208
11
            return -1;
2209
11
        }
2210
2.08k
    }
2211
0
    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
0
        const char *s = start;
2216
0
        for (;;) {
2217
0
            Py_UCS4 ch;
2218
            /* Fast path for non-control chars. The loop always ends
2219
               since the Unicode string is NUL-terminated. */
2220
0
            while (PyUnicode_READ(kind, s, 0) > '\r')
2221
0
                s += kind;
2222
0
            if (s >= end) {
2223
0
                *consumed = len;
2224
0
                return -1;
2225
0
            }
2226
0
            ch = PyUnicode_READ(kind, s, 0);
2227
0
            s += kind;
2228
0
            if (ch == '\n')
2229
0
                return (s - start)/kind;
2230
0
            if (ch == '\r') {
2231
0
                if (PyUnicode_READ(kind, s, 0) == '\n')
2232
0
                    return (s - start)/kind + 1;
2233
0
                else
2234
0
                    return (s - start)/kind;
2235
0
            }
2236
0
        }
2237
0
    }
2238
0
    else {
2239
        /* Non-universal mode. */
2240
0
        Py_ssize_t readnl_len = PyUnicode_GET_LENGTH(readnl);
2241
0
        const Py_UCS1 *nl = PyUnicode_1BYTE_DATA(readnl);
2242
        /* Assume that readnl is an ASCII character. */
2243
0
        assert(PyUnicode_KIND(readnl) == PyUnicode_1BYTE_KIND);
2244
0
        if (readnl_len == 1) {
2245
0
            const char *pos = find_control_char(kind, start, end, nl[0]);
2246
0
            if (pos != NULL)
2247
0
                return (pos - start)/kind + 1;
2248
0
            *consumed = len;
2249
0
            return -1;
2250
0
        }
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
0
    }
2278
2.08k
}
2279
2280
static PyObject *
2281
_textiowrapper_readline(textio *self, Py_ssize_t limit)
2282
2.08k
{
2283
2.08k
    PyObject *line = NULL, *chunks = NULL, *remaining = NULL;
2284
2.08k
    Py_ssize_t start, endpos, chunked, offset_to_buffer;
2285
2.08k
    int res;
2286
2287
2.08k
    CHECK_CLOSED(self);
2288
2289
2.08k
    if (_textiowrapper_writeflush(self) < 0)
2290
0
        return NULL;
2291
2292
2.08k
    chunked = 0;
2293
2294
2.09k
    while (1) {
2295
2.09k
        const char *ptr;
2296
2.09k
        Py_ssize_t line_len;
2297
2.09k
        int kind;
2298
2.09k
        Py_ssize_t consumed = 0;
2299
2300
        /* First, get some data if necessary */
2301
2.09k
        res = 1;
2302
2.10k
        while (!self->decoded_chars ||
2303
2.08k
               !PyUnicode_GET_LENGTH(self->decoded_chars)) {
2304
14
            res = textiowrapper_read_chunk(self, 0);
2305
14
            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
14
            if (res == 0)
2314
3
                break;
2315
14
        }
2316
2.09k
        if (res == 0) {
2317
            /* end of file */
2318
3
            textiowrapper_set_decoded_chars(self, NULL);
2319
3
            Py_CLEAR(self->snapshot);
2320
3
            start = endpos = offset_to_buffer = 0;
2321
3
            break;
2322
3
        }
2323
2324
2.08k
        if (remaining == NULL) {
2325
2.08k
            line = Py_NewRef(self->decoded_chars);
2326
2.08k
            start = self->decoded_chars_used;
2327
2.08k
            offset_to_buffer = 0;
2328
2.08k
        }
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
2.08k
        ptr = PyUnicode_DATA(line);
2340
2.08k
        line_len = PyUnicode_GET_LENGTH(line);
2341
2.08k
        kind = PyUnicode_KIND(line);
2342
2343
0
        endpos = _PyIO_find_line_ending(
2344
2.08k
            self->readtranslate, self->readuniversal, self->readnl,
2345
2.08k
            kind,
2346
2.08k
            ptr + kind * start,
2347
2.08k
            ptr + kind * line_len,
2348
2.08k
            &consumed);
2349
2.08k
        if (endpos >= 0) {
2350
2.07k
            endpos += start;
2351
2.07k
            if (limit >= 0 && (endpos - start) + chunked >= limit)
2352
0
                endpos = start + limit - chunked;
2353
2.07k
            break;
2354
2.07k
        }
2355
2356
        /* We can put aside up to `endpos` */
2357
11
        endpos = consumed + start;
2358
11
        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
11
        if (endpos > start) {
2365
            /* No line ending seen yet - put aside current data */
2366
7
            PyObject *s;
2367
7
            if (chunks == NULL) {
2368
7
                chunks = PyList_New(0);
2369
7
                if (chunks == NULL)
2370
0
                    goto error;
2371
7
            }
2372
7
            s = PyUnicode_Substring(line, start, endpos);
2373
7
            if (s == NULL)
2374
0
                goto error;
2375
7
            if (PyList_Append(chunks, s) < 0) {
2376
0
                Py_DECREF(s);
2377
0
                goto error;
2378
0
            }
2379
7
            chunked += PyUnicode_GET_LENGTH(s);
2380
7
            Py_DECREF(s);
2381
7
        }
2382
        /* There may be some remaining bytes we'll have to prepend to the
2383
           next chunk of data */
2384
11
        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
11
        Py_CLEAR(line);
2390
        /* We have consumed the buffer */
2391
11
        textiowrapper_set_decoded_chars(self, NULL);
2392
11
    }
2393
2394
2.08k
    if (line != NULL) {
2395
        /* Our line ends in the current buffer */
2396
2.07k
        self->decoded_chars_used = endpos - offset_to_buffer;
2397
2.07k
        if (start > 0 || endpos < PyUnicode_GET_LENGTH(line)) {
2398
2.07k
            PyObject *s = PyUnicode_Substring(line, start, endpos);
2399
2.07k
            Py_CLEAR(line);
2400
2.07k
            if (s == NULL)
2401
0
                goto error;
2402
2.07k
            line = s;
2403
2.07k
        }
2404
2.07k
    }
2405
2.08k
    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
2.08k
    if (chunks != NULL) {
2416
7
        if (line != NULL) {
2417
7
            if (PyList_Append(chunks, line) < 0)
2418
0
                goto error;
2419
7
            Py_DECREF(line);
2420
7
        }
2421
7
        line = PyUnicode_Join(&_Py_STR(empty), chunks);
2422
7
        if (line == NULL)
2423
0
            goto error;
2424
7
        Py_CLEAR(chunks);
2425
7
    }
2426
2.08k
    if (line == NULL) {
2427
3
        line = &_Py_STR(empty);
2428
3
    }
2429
2430
2.08k
    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
2.08k
}
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 = NULL;
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
    /* Own next_input: a reentrant or concurrent seek can drop the snapshot. */
2879
0
    Py_INCREF(next_input);
2880
2881
0
    cookie.start_pos -= PyBytes_GET_SIZE(next_input);
2882
2883
    /* How many decoded characters have been used up since the snapshot? */
2884
0
    if (self->decoded_chars_used == 0)  {
2885
        /* We haven't moved from the snapshot point. */
2886
0
        Py_DECREF(next_input);
2887
0
        return textiowrapper_build_cookie(&cookie);
2888
0
    }
2889
2890
0
    chars_to_skip = self->decoded_chars_used;
2891
2892
    /* Decoder state will be restored at the end */
2893
0
    saved_state = PyObject_CallMethodNoArgs(self->decoder,
2894
0
                                             &_Py_ID(getstate));
2895
0
    if (saved_state == NULL)
2896
0
        goto fail;
2897
2898
0
#define DECODER_GETSTATE() do { \
2899
0
        PyObject *dec_buffer; \
2900
0
        PyObject *_state = PyObject_CallMethodNoArgs(self->decoder, \
2901
0
            &_Py_ID(getstate)); \
2902
0
        if (_state == NULL) \
2903
0
            goto fail; \
2904
0
        if (!PyTuple_Check(_state)) { \
2905
0
            PyErr_SetString(PyExc_TypeError, \
2906
0
                            "illegal decoder state"); \
2907
0
            Py_DECREF(_state); \
2908
0
            goto fail; \
2909
0
        } \
2910
0
        if (!PyArg_ParseTuple(_state, "Oi;illegal decoder state", \
2911
0
                              &dec_buffer, &dec_flags)) \
2912
0
        { \
2913
0
            Py_DECREF(_state); \
2914
0
            goto fail; \
2915
0
        } \
2916
0
        if (!PyBytes_Check(dec_buffer)) { \
2917
0
            PyErr_Format(PyExc_TypeError, \
2918
0
                         "illegal decoder state: the first item should be a " \
2919
0
                         "bytes object, not '%.200s'", \
2920
0
                         Py_TYPE(dec_buffer)->tp_name); \
2921
0
            Py_DECREF(_state); \
2922
0
            goto fail; \
2923
0
        } \
2924
0
        dec_buffer_len = PyBytes_GET_SIZE(dec_buffer); \
2925
0
        Py_DECREF(_state); \
2926
0
    } while (0)
2927
2928
0
#define DECODER_DECODE(start, len, res) do { \
2929
0
        PyObject *_decoded = _PyObject_CallMethod( \
2930
0
            self->decoder, &_Py_ID(decode), "y#", start, len); \
2931
0
        if (check_decoded(_decoded) < 0) \
2932
0
            goto fail; \
2933
0
        res = PyUnicode_GET_LENGTH(_decoded); \
2934
0
        Py_DECREF(_decoded); \
2935
0
    } while (0)
2936
2937
    /* Fast search for an acceptable start point, close to our
2938
       current pos */
2939
0
    skip_bytes = (Py_ssize_t) (self->b2cratio * chars_to_skip);
2940
0
    skip_back = 1;
2941
0
    assert(skip_bytes <= PyBytes_GET_SIZE(next_input));
2942
0
    input = PyBytes_AS_STRING(next_input);
2943
0
    while (skip_bytes > 0) {
2944
        /* Decode up to temptative start point */
2945
0
        if (_textiowrapper_decoder_setstate(self, &cookie) < 0)
2946
0
            goto fail;
2947
0
        DECODER_DECODE(input, skip_bytes, chars_decoded);
2948
0
        if (chars_decoded <= chars_to_skip) {
2949
0
            DECODER_GETSTATE();
2950
0
            if (dec_buffer_len == 0) {
2951
                /* Before pos and no bytes buffered in decoder => OK */
2952
0
                cookie.dec_flags = dec_flags;
2953
0
                chars_to_skip -= chars_decoded;
2954
0
                break;
2955
0
            }
2956
            /* Skip back by buffered amount and reset heuristic */
2957
0
            skip_bytes -= dec_buffer_len;
2958
0
            skip_back = 1;
2959
0
        }
2960
0
        else {
2961
            /* We're too far ahead, skip back a bit */
2962
0
            skip_bytes -= skip_back;
2963
0
            skip_back *= 2;
2964
0
        }
2965
0
    }
2966
0
    if (skip_bytes <= 0) {
2967
0
        skip_bytes = 0;
2968
0
        if (_textiowrapper_decoder_setstate(self, &cookie) < 0)
2969
0
            goto fail;
2970
0
    }
2971
2972
    /* Note our initial start point. */
2973
0
    cookie.start_pos += skip_bytes;
2974
0
    cookie.chars_to_skip = Py_SAFE_DOWNCAST(chars_to_skip, Py_ssize_t, int);
2975
0
    if (chars_to_skip == 0)
2976
0
        goto finally;
2977
2978
    /* We should be close to the desired position.  Now feed the decoder one
2979
     * byte at a time until we reach the `chars_to_skip` target.
2980
     * As we go, note the nearest "safe start point" before the current
2981
     * location (a point where the decoder has nothing buffered, so seek()
2982
     * can safely start from there and advance to this location).
2983
     */
2984
0
    chars_decoded = 0;
2985
0
    input = PyBytes_AS_STRING(next_input);
2986
0
    input_end = input + PyBytes_GET_SIZE(next_input);
2987
0
    input += skip_bytes;
2988
0
    while (input < input_end) {
2989
0
        Py_ssize_t n;
2990
2991
0
        DECODER_DECODE(input, (Py_ssize_t)1, n);
2992
        /* We got n chars for 1 byte */
2993
0
        chars_decoded += n;
2994
0
        cookie.bytes_to_feed += 1;
2995
0
        DECODER_GETSTATE();
2996
2997
0
        if (dec_buffer_len == 0 && chars_decoded <= chars_to_skip) {
2998
            /* Decoder buffer is empty, so this is a safe start point. */
2999
0
            cookie.start_pos += cookie.bytes_to_feed;
3000
0
            chars_to_skip -= chars_decoded;
3001
0
            cookie.dec_flags = dec_flags;
3002
0
            cookie.bytes_to_feed = 0;
3003
0
            chars_decoded = 0;
3004
0
        }
3005
0
        if (chars_decoded >= chars_to_skip)
3006
0
            break;
3007
0
        input++;
3008
0
    }
3009
0
    if (input == input_end) {
3010
        /* We didn't get enough decoded data; signal EOF to get more. */
3011
0
        PyObject *decoded = _PyObject_CallMethod(
3012
0
            self->decoder, &_Py_ID(decode), "yO", "", /* final = */ Py_True);
3013
0
        if (check_decoded(decoded) < 0)
3014
0
            goto fail;
3015
0
        chars_decoded += PyUnicode_GET_LENGTH(decoded);
3016
0
        Py_DECREF(decoded);
3017
0
        cookie.need_eof = 1;
3018
3019
0
        if (chars_decoded < chars_to_skip) {
3020
0
            PyErr_SetString(PyExc_OSError,
3021
0
                            "can't reconstruct logical file position");
3022
0
            goto fail;
3023
0
        }
3024
0
    }
3025
3026
0
finally:
3027
0
    Py_XDECREF(next_input);
3028
0
    res = PyObject_CallMethodOneArg(
3029
0
            self->decoder, &_Py_ID(setstate), saved_state);
3030
0
    Py_DECREF(saved_state);
3031
0
    if (res == NULL)
3032
0
        return NULL;
3033
0
    Py_DECREF(res);
3034
3035
    /* The returned cookie corresponds to the last safe start point. */
3036
0
    cookie.chars_to_skip = Py_SAFE_DOWNCAST(chars_to_skip, Py_ssize_t, int);
3037
0
    return textiowrapper_build_cookie(&cookie);
3038
3039
0
fail:
3040
0
    Py_XDECREF(next_input);
3041
0
    if (saved_state) {
3042
0
        PyObject *exc = PyErr_GetRaisedException();
3043
0
        res = PyObject_CallMethodOneArg(
3044
0
                self->decoder, &_Py_ID(setstate), saved_state);
3045
0
        _PyErr_ChainExceptions1(exc);
3046
0
        Py_DECREF(saved_state);
3047
0
        Py_XDECREF(res);
3048
0
    }
3049
0
    return NULL;
3050
0
}
3051
3052
/*[clinic input]
3053
@critical_section
3054
_io.TextIOWrapper.truncate
3055
    pos: object = None
3056
    /
3057
[clinic start generated code]*/
3058
3059
static PyObject *
3060
_io_TextIOWrapper_truncate_impl(textio *self, PyObject *pos)
3061
/*[clinic end generated code: output=90ec2afb9bb7745f input=8bddb320834c93ee]*/
3062
0
{
3063
0
    CHECK_ATTACHED(self)
3064
3065
0
    if (_PyFile_Flush((PyObject *)self) < 0) {
3066
0
        return NULL;
3067
0
    }
3068
3069
0
    return buffer_callmethod_onearg(self, &_Py_ID(truncate), pos);
3070
0
}
3071
3072
static PyObject *
3073
textiowrapper_repr(PyObject *op)
3074
0
{
3075
0
    PyObject *nameobj, *modeobj, *res, *s;
3076
0
    int status;
3077
0
    textio *self = textio_CAST(op);
3078
0
    const char *type_name = Py_TYPE(self)->tp_name;
3079
3080
0
    CHECK_INITIALIZED(self);
3081
3082
0
    res = PyUnicode_FromFormat("<%.100s", type_name);
3083
0
    if (res == NULL)
3084
0
        return NULL;
3085
3086
0
    status = Py_ReprEnter(op);
3087
0
    if (status != 0) {
3088
0
        if (status > 0) {
3089
0
            PyErr_Format(PyExc_RuntimeError,
3090
0
                         "reentrant call inside %.100s.__repr__",
3091
0
                         type_name);
3092
0
        }
3093
0
        goto error;
3094
0
    }
3095
0
    if (PyObject_GetOptionalAttr(op, &_Py_ID(name), &nameobj) < 0) {
3096
0
        if (!PyErr_ExceptionMatches(PyExc_ValueError)) {
3097
0
            goto error;
3098
0
        }
3099
        /* Ignore ValueError raised if the underlying stream was detached */
3100
0
        PyErr_Clear();
3101
0
    }
3102
0
    if (nameobj != NULL) {
3103
0
        s = PyUnicode_FromFormat(" name=%R", nameobj);
3104
0
        Py_DECREF(nameobj);
3105
0
        if (s == NULL)
3106
0
            goto error;
3107
0
        PyUnicode_AppendAndDel(&res, s);
3108
0
        if (res == NULL)
3109
0
            goto error;
3110
0
    }
3111
0
    if (PyObject_GetOptionalAttr(op, &_Py_ID(mode), &modeobj) < 0) {
3112
0
        goto error;
3113
0
    }
3114
0
    if (modeobj != NULL) {
3115
0
        s = PyUnicode_FromFormat(" mode=%R", modeobj);
3116
0
        Py_DECREF(modeobj);
3117
0
        if (s == NULL)
3118
0
            goto error;
3119
0
        PyUnicode_AppendAndDel(&res, s);
3120
0
        if (res == NULL)
3121
0
            goto error;
3122
0
    }
3123
0
    s = PyUnicode_FromFormat("%U encoding=%R>",
3124
0
                             res, self->encoding);
3125
0
    Py_DECREF(res);
3126
0
    if (status == 0) {
3127
0
        Py_ReprLeave(op);
3128
0
    }
3129
0
    return s;
3130
3131
0
  error:
3132
0
    Py_XDECREF(res);
3133
0
    if (status == 0) {
3134
0
        Py_ReprLeave(op);
3135
0
    }
3136
0
    return NULL;
3137
0
}
3138
3139
3140
/* Inquiries */
3141
3142
/*[clinic input]
3143
@critical_section
3144
_io.TextIOWrapper.fileno
3145
[clinic start generated code]*/
3146
3147
static PyObject *
3148
_io_TextIOWrapper_fileno_impl(textio *self)
3149
/*[clinic end generated code: output=21490a4c3da13e6c input=515e1196aceb97ab]*/
3150
0
{
3151
0
    return buffer_callmethod_noargs(self, &_Py_ID(fileno));
3152
0
}
3153
3154
/*[clinic input]
3155
@critical_section
3156
_io.TextIOWrapper.seekable
3157
[clinic start generated code]*/
3158
3159
static PyObject *
3160
_io_TextIOWrapper_seekable_impl(textio *self)
3161
/*[clinic end generated code: output=ab223dbbcffc0f00 input=71c4c092736c549b]*/
3162
0
{
3163
0
    return buffer_callmethod_noargs(self, &_Py_ID(seekable));
3164
0
}
3165
3166
/*[clinic input]
3167
@critical_section
3168
_io.TextIOWrapper.readable
3169
[clinic start generated code]*/
3170
3171
static PyObject *
3172
_io_TextIOWrapper_readable_impl(textio *self)
3173
/*[clinic end generated code: output=72ff7ba289a8a91b input=80438d1f01b0a89b]*/
3174
0
{
3175
0
    return buffer_callmethod_noargs(self, &_Py_ID(readable));
3176
0
}
3177
3178
/*[clinic input]
3179
@critical_section
3180
_io.TextIOWrapper.writable
3181
[clinic start generated code]*/
3182
3183
static PyObject *
3184
_io_TextIOWrapper_writable_impl(textio *self)
3185
/*[clinic end generated code: output=a728c71790d03200 input=9d6c22befb0c340a]*/
3186
0
{
3187
0
    return buffer_callmethod_noargs(self, &_Py_ID(writable));
3188
0
}
3189
3190
/*[clinic input]
3191
@critical_section
3192
_io.TextIOWrapper.isatty
3193
[clinic start generated code]*/
3194
3195
static PyObject *
3196
_io_TextIOWrapper_isatty_impl(textio *self)
3197
/*[clinic end generated code: output=12be1a35bace882e input=7f83ff04d4d1733d]*/
3198
0
{
3199
0
    return buffer_callmethod_noargs(self, &_Py_ID(isatty));
3200
0
}
3201
3202
/*[clinic input]
3203
@critical_section
3204
_io.TextIOWrapper.flush
3205
[clinic start generated code]*/
3206
3207
static PyObject *
3208
_io_TextIOWrapper_flush_impl(textio *self)
3209
/*[clinic end generated code: output=59de9165f9c2e4d2 input=3ac3bf521bfed59d]*/
3210
3
{
3211
3
    CHECK_ATTACHED(self);
3212
3
    CHECK_CLOSED(self);
3213
3
    self->telling = self->seekable;
3214
3
    if (_textiowrapper_writeflush(self) < 0)
3215
0
        return NULL;
3216
3
    return buffer_callmethod_noargs(self, &_Py_ID(flush));
3217
3
}
3218
3219
/*[clinic input]
3220
@critical_section
3221
_io.TextIOWrapper.close
3222
[clinic start generated code]*/
3223
3224
static PyObject *
3225
_io_TextIOWrapper_close_impl(textio *self)
3226
/*[clinic end generated code: output=056ccf8b4876e4f4 input=8e12d7079d5ac5c1]*/
3227
3
{
3228
3
    PyObject *res;
3229
3
    int r;
3230
3
    CHECK_ATTACHED(self);
3231
3232
3
    res = _io_TextIOWrapper_closed_get_impl(self);
3233
3
    if (res == NULL)
3234
0
        return NULL;
3235
3
    r = PyObject_IsTrue(res);
3236
3
    Py_DECREF(res);
3237
3
    if (r < 0)
3238
0
        return NULL;
3239
3240
3
    if (r > 0) {
3241
0
        Py_RETURN_NONE; /* stream already closed */
3242
0
    }
3243
3
    if (self->detached) {
3244
0
        Py_RETURN_NONE; /* gh-142594 null pointer issue */
3245
0
    }
3246
3
    else {
3247
3
        PyObject *exc = NULL;
3248
3
        if (self->finalizing) {
3249
0
            res = buffer_callmethod_onearg(self,
3250
0
                                           &_Py_ID(_dealloc_warn),
3251
0
                                           (PyObject *)self);
3252
0
            if (res) {
3253
0
                Py_DECREF(res);
3254
0
            }
3255
0
            else {
3256
0
                PyErr_Clear();
3257
0
            }
3258
0
        }
3259
3
        if (_PyFile_Flush((PyObject *)self) < 0) {
3260
0
            exc = PyErr_GetRaisedException();
3261
0
        }
3262
3263
3
        res = buffer_callmethod_noargs(self, &_Py_ID(close));
3264
3
        if (exc != NULL) {
3265
0
            _PyErr_ChainExceptions1(exc);
3266
0
            Py_CLEAR(res);
3267
0
        }
3268
3
        return res;
3269
3
    }
3270
3
}
3271
3272
static PyObject *
3273
textiowrapper_iternext_lock_held(PyObject *op)
3274
2.08k
{
3275
2.08k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
3276
2.08k
    PyObject *line;
3277
2.08k
    textio *self = textio_CAST(op);
3278
3279
2.08k
    CHECK_ATTACHED(self);
3280
3281
2.08k
    self->telling = 0;
3282
2.08k
    if (Py_IS_TYPE(self, self->state->PyTextIOWrapper_Type)) {
3283
        /* Skip method call overhead for speed */
3284
2.08k
        line = _textiowrapper_readline(self, -1);
3285
2.08k
    }
3286
0
    else {
3287
0
        line = PyObject_CallMethodNoArgs(op, &_Py_ID(readline));
3288
0
        if (line && !PyUnicode_Check(line)) {
3289
0
            PyErr_Format(PyExc_OSError,
3290
0
                         "readline() should have returned a str object, "
3291
0
                         "not '%.200s'", Py_TYPE(line)->tp_name);
3292
0
            Py_DECREF(line);
3293
0
            return NULL;
3294
0
        }
3295
0
    }
3296
3297
2.08k
    if (line == NULL)
3298
0
        return NULL;
3299
3300
2.08k
    if (PyUnicode_GET_LENGTH(line) == 0) {
3301
        /* Reached EOF or would have blocked */
3302
3
        Py_DECREF(line);
3303
3
        Py_CLEAR(self->snapshot);
3304
3
        self->telling = self->seekable;
3305
3
        return NULL;
3306
3
    }
3307
3308
2.07k
    return line;
3309
2.08k
}
3310
3311
static PyObject *
3312
textiowrapper_iternext(PyObject *op)
3313
2.08k
{
3314
2.08k
    PyObject *result;
3315
2.08k
    Py_BEGIN_CRITICAL_SECTION(op);
3316
2.08k
    result = textiowrapper_iternext_lock_held(op);
3317
2.08k
    Py_END_CRITICAL_SECTION();
3318
2.08k
    return result;
3319
2.08k
}
3320
3321
/*[clinic input]
3322
@critical_section
3323
@getter
3324
_io.TextIOWrapper.name
3325
[clinic start generated code]*/
3326
3327
static PyObject *
3328
_io_TextIOWrapper_name_get_impl(textio *self)
3329
/*[clinic end generated code: output=8c2f1d6d8756af40 input=26ecec9b39e30e07]*/
3330
0
{
3331
0
    return buffer_getattr(self, &_Py_ID(name));
3332
0
}
3333
3334
/*[clinic input]
3335
@critical_section
3336
@getter
3337
_io.TextIOWrapper.closed
3338
[clinic start generated code]*/
3339
3340
static PyObject *
3341
_io_TextIOWrapper_closed_get_impl(textio *self)
3342
/*[clinic end generated code: output=b49b68f443a85e3c input=7dfcf43f63c7003d]*/
3343
12
{
3344
    /* If partially constructed or deconstructed, return that the underlying
3345
       buffer is closed.
3346
3347
       The code managing the transition is responsible for closing. The closed
3348
       attribute is often called in re-initalization, as part of repr in error
3349
       cases, and when the I/O stack is garbage collected. */
3350
12
    if (self->ok <= 0) {
3351
0
        Py_RETURN_TRUE;
3352
0
    }
3353
3354
12
    return buffer_getattr(self, &_Py_ID(closed));
3355
12
}
3356
3357
/*[clinic input]
3358
@critical_section
3359
@getter
3360
_io.TextIOWrapper.newlines
3361
[clinic start generated code]*/
3362
3363
static PyObject *
3364
_io_TextIOWrapper_newlines_get_impl(textio *self)
3365
/*[clinic end generated code: output=53aa03ac35573180 input=610df647e514b3e8]*/
3366
0
{
3367
0
    PyObject *res;
3368
0
    CHECK_ATTACHED(self);
3369
0
    if (self->decoder == NULL ||
3370
0
        PyObject_GetOptionalAttr(self->decoder, &_Py_ID(newlines), &res) == 0)
3371
0
    {
3372
0
        Py_RETURN_NONE;
3373
0
    }
3374
0
    return res;
3375
0
}
3376
3377
/*[clinic input]
3378
@critical_section
3379
@getter
3380
_io.TextIOWrapper.errors
3381
[clinic start generated code]*/
3382
3383
static PyObject *
3384
_io_TextIOWrapper_errors_get_impl(textio *self)
3385
/*[clinic end generated code: output=dca3a3ef21b09484 input=b45f983e6d43c4d8]*/
3386
0
{
3387
0
    CHECK_INITIALIZED(self);
3388
0
    return Py_NewRef(self->errors);
3389
0
}
3390
3391
/*[clinic input]
3392
@critical_section
3393
@getter
3394
_io.TextIOWrapper._CHUNK_SIZE
3395
[clinic start generated code]*/
3396
3397
static PyObject *
3398
_io_TextIOWrapper__CHUNK_SIZE_get_impl(textio *self)
3399
/*[clinic end generated code: output=039925cd2df375bc input=e9715b0e06ff0fa6]*/
3400
0
{
3401
0
    CHECK_ATTACHED(self);
3402
0
    return PyLong_FromSsize_t(self->chunk_size);
3403
0
}
3404
3405
/*[clinic input]
3406
@critical_section
3407
@setter
3408
_io.TextIOWrapper._CHUNK_SIZE
3409
[clinic start generated code]*/
3410
3411
static int
3412
_io_TextIOWrapper__CHUNK_SIZE_set_impl(textio *self, PyObject *value)
3413
/*[clinic end generated code: output=edb86d2db660a5ab input=32fc99861db02a0a]*/
3414
0
{
3415
0
    Py_ssize_t n;
3416
0
    CHECK_ATTACHED_INT(self);
3417
0
    n = PyNumber_AsSsize_t(value, PyExc_ValueError);
3418
0
    if (n == -1 && PyErr_Occurred())
3419
0
        return -1;
3420
0
    if (n <= 0) {
3421
0
        PyErr_SetString(PyExc_ValueError,
3422
0
                        "a strictly positive integer is required");
3423
0
        return -1;
3424
0
    }
3425
0
    self->chunk_size = n;
3426
0
    return 0;
3427
0
}
3428
3429
/*[clinic input]
3430
@critical_section
3431
@getter
3432
_io.TextIOWrapper.buffer
3433
[clinic start generated code]*/
3434
3435
static PyObject *
3436
_io_TextIOWrapper_buffer_get_impl(textio *self)
3437
/*[clinic end generated code: output=d265a34555aa5d4b input=5951cfa148f7350a]*/
3438
0
{
3439
0
    return Py_XNewRef(buffer_access_safe(self));
3440
0
}
3441
3442
static PyMethodDef incrementalnewlinedecoder_methods[] = {
3443
    _IO_INCREMENTALNEWLINEDECODER_DECODE_METHODDEF
3444
    _IO_INCREMENTALNEWLINEDECODER_GETSTATE_METHODDEF
3445
    _IO_INCREMENTALNEWLINEDECODER_SETSTATE_METHODDEF
3446
    _IO_INCREMENTALNEWLINEDECODER_RESET_METHODDEF
3447
    {NULL}
3448
};
3449
3450
static PyGetSetDef incrementalnewlinedecoder_getset[] = {
3451
    {"newlines", incrementalnewlinedecoder_newlines_get, NULL, NULL},
3452
    {NULL}
3453
};
3454
3455
static PyType_Slot nldecoder_slots[] = {
3456
    {Py_tp_dealloc, incrementalnewlinedecoder_dealloc},
3457
    {Py_tp_doc, (void *)_io_IncrementalNewlineDecoder___init____doc__},
3458
    {Py_tp_methods, incrementalnewlinedecoder_methods},
3459
    {Py_tp_getset, incrementalnewlinedecoder_getset},
3460
    {Py_tp_traverse, incrementalnewlinedecoder_traverse},
3461
    {Py_tp_clear, incrementalnewlinedecoder_clear},
3462
    {Py_tp_init, _io_IncrementalNewlineDecoder___init__},
3463
    {0, NULL},
3464
};
3465
3466
PyType_Spec _Py_nldecoder_spec = {
3467
    .name = "_io.IncrementalNewlineDecoder",
3468
    .basicsize = sizeof(nldecoder_object),
3469
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
3470
              Py_TPFLAGS_IMMUTABLETYPE),
3471
    .slots = nldecoder_slots,
3472
};
3473
3474
3475
static PyMethodDef textiowrapper_methods[] = {
3476
    _IO_TEXTIOWRAPPER_DETACH_METHODDEF
3477
    _IO_TEXTIOWRAPPER_RECONFIGURE_METHODDEF
3478
    _IO_TEXTIOWRAPPER_WRITE_METHODDEF
3479
    _IO_TEXTIOWRAPPER_READ_METHODDEF
3480
    _IO_TEXTIOWRAPPER_READLINE_METHODDEF
3481
    _IO_TEXTIOWRAPPER_FLUSH_METHODDEF
3482
    _IO_TEXTIOWRAPPER_CLOSE_METHODDEF
3483
3484
    _IO_TEXTIOWRAPPER_FILENO_METHODDEF
3485
    _IO_TEXTIOWRAPPER_SEEKABLE_METHODDEF
3486
    _IO_TEXTIOWRAPPER_READABLE_METHODDEF
3487
    _IO_TEXTIOWRAPPER_WRITABLE_METHODDEF
3488
    _IO_TEXTIOWRAPPER_ISATTY_METHODDEF
3489
3490
    _IO_TEXTIOWRAPPER_SEEK_METHODDEF
3491
    _IO_TEXTIOWRAPPER_TELL_METHODDEF
3492
    _IO_TEXTIOWRAPPER_TRUNCATE_METHODDEF
3493
3494
    {"__getstate__", _PyIOBase_cannot_pickle, METH_NOARGS},
3495
    {NULL, NULL}
3496
};
3497
3498
static PyMemberDef textiowrapper_members[] = {
3499
    {"encoding", _Py_T_OBJECT, offsetof(textio, encoding), Py_READONLY},
3500
    {"line_buffering", Py_T_BOOL, offsetof(textio, line_buffering), Py_READONLY},
3501
    {"write_through", Py_T_BOOL, offsetof(textio, write_through), Py_READONLY},
3502
    {"_finalizing", Py_T_BOOL, offsetof(textio, finalizing), 0},
3503
    {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(textio, weakreflist), Py_READONLY},
3504
    {"__dictoffset__", Py_T_PYSSIZET, offsetof(textio, dict), Py_READONLY},
3505
    {NULL}
3506
};
3507
3508
static PyGetSetDef textiowrapper_getset[] = {
3509
    _IO_TEXTIOWRAPPER_NAME_GETSETDEF
3510
    _IO_TEXTIOWRAPPER_CLOSED_GETSETDEF
3511
    _IO_TEXTIOWRAPPER_NEWLINES_GETSETDEF
3512
    _IO_TEXTIOWRAPPER_ERRORS_GETSETDEF
3513
    _IO_TEXTIOWRAPPER__CHUNK_SIZE_GETSETDEF
3514
    _IO_TEXTIOWRAPPER_BUFFER_GETSETDEF
3515
    {NULL}
3516
};
3517
3518
static PyType_Slot textiowrapper_slots[] = {
3519
    {Py_tp_dealloc, textiowrapper_dealloc},
3520
    {Py_tp_repr, textiowrapper_repr},
3521
    {Py_tp_doc, (void *)_io_TextIOWrapper___init____doc__},
3522
    {Py_tp_traverse, textiowrapper_traverse},
3523
    {Py_tp_clear, textiowrapper_clear},
3524
    {Py_tp_iternext, textiowrapper_iternext},
3525
    {Py_tp_methods, textiowrapper_methods},
3526
    {Py_tp_members, textiowrapper_members},
3527
    {Py_tp_getset, textiowrapper_getset},
3528
    {Py_tp_init, _io_TextIOWrapper___init__},
3529
    {0, NULL},
3530
};
3531
3532
PyType_Spec _Py_textiowrapper_spec = {
3533
    .name = "_io.TextIOWrapper",
3534
    .basicsize = sizeof(textio),
3535
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
3536
              Py_TPFLAGS_IMMUTABLETYPE),
3537
    .slots = textiowrapper_slots,
3538
};