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