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