LCOV - code coverage report
Current view: top level - Modules/_io - textio.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 1217 1422 85.6 %
Date: 2022-07-20 13:12:14 Functions: 75 75 100.0 %
Branches: 865 1156 74.8 %

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

Generated by: LCOV version 1.14