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