Coverage Report

Created: 2026-09-27 06:15

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