LCOV - code coverage report
Current view: top level - Modules/_io - textio.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit 5e6661bce9] Lines: 545 1417 38.5 %
Date: 2023-03-20 08:15:36 Functions: 34 75 45.3 %
Branches: 369 1166 31.6 %

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

Generated by: LCOV version 1.14