LCOV - code coverage report
Current view: | top level - Modules/_io - stringio.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 161 | 393 | 41.0 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 13 | 27 | 48.1 %
|  |  | Branches: | 92 | 322 | 28.6 %

               Branch data     Line data    Source code
           1                 :            : #define PY_SSIZE_T_CLEAN
           2                 :            : #include "Python.h"
           3                 :            : #include <stddef.h>               // offsetof()
           4                 :            : #include "pycore_object.h"
           5                 :            : #include "_iomodule.h"
           6                 :            :
           7                 :            : /* Implementation note: the buffer is always at least one character longer
           8                 :            :    than the enclosed string, for proper functioning of _PyIO_find_line_ending.
           9                 :            : */
          10                 :            :
          11                 :            : #define STATE_REALIZED 1
          12                 :            : #define STATE_ACCUMULATING 2
          13                 :            :
          14                 :            : /*[clinic input]
          15                 :            : module _io
          16                 :            : class _io.StringIO "stringio *" "clinic_state()->PyStringIO_Type"
          17                 :            : [clinic start generated code]*/
          18                 :            : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=2693eada0658d470]*/
          19                 :            :
          20                 :            : typedef struct {
          21                 :            :     PyObject_HEAD
          22                 :            :     Py_UCS4 *buf;
          23                 :            :     Py_ssize_t pos;
          24                 :            :     Py_ssize_t string_size;
          25                 :            :     size_t buf_size;
          26                 :            :
          27                 :            :     /* The stringio object can be in two states: accumulating or realized.
          28                 :            :        In accumulating state, the internal buffer contains nothing and
          29                 :            :        the contents are given by the embedded _PyUnicodeWriter structure.
          30                 :            :        In realized state, the internal buffer is meaningful and the
          31                 :            :        _PyUnicodeWriter is destroyed.
          32                 :            :     */
          33                 :            :     int state;
          34                 :            :     _PyUnicodeWriter writer;
          35                 :            :
          36                 :            :     char ok; /* initialized? */
          37                 :            :     char closed;
          38                 :            :     char readuniversal;
          39                 :            :     char readtranslate;
          40                 :            :     PyObject *decoder;
          41                 :            :     PyObject *readnl;
          42                 :            :     PyObject *writenl;
          43                 :            :
          44                 :            :     PyObject *dict;
          45                 :            :     PyObject *weakreflist;
          46                 :            :     _PyIO_State *module_state;
          47                 :            : } stringio;
          48                 :            :
          49                 :            : static int _io_StringIO___init__(PyObject *self, PyObject *args, PyObject *kwargs);
          50                 :            :
          51                 :            : #define CHECK_INITIALIZED(self) \
          52                 :            :     if (self->ok <= 0) { \
          53                 :            :         PyErr_SetString(PyExc_ValueError, \
          54                 :            :             "I/O operation on uninitialized object"); \
          55                 :            :         return NULL; \
          56                 :            :     }
          57                 :            :
          58                 :            : #define CHECK_CLOSED(self) \
          59                 :            :     if (self->closed) { \
          60                 :            :         PyErr_SetString(PyExc_ValueError, \
          61                 :            :             "I/O operation on closed file"); \
          62                 :            :         return NULL; \
          63                 :            :     }
          64                 :            :
          65                 :            : #define ENSURE_REALIZED(self) \
          66                 :            :     if (realize(self) < 0) { \
          67                 :            :         return NULL; \
          68                 :            :     }
          69                 :            :
          70                 :            :
          71                 :            : /* Internal routine for changing the size, in terms of characters, of the
          72                 :            :    buffer of StringIO objects.  The caller should ensure that the 'size'
          73                 :            :    argument is non-negative.  Returns 0 on success, -1 otherwise. */
          74                 :            : static int
          75                 :        125 : resize_buffer(stringio *self, size_t size)
          76                 :            : {
          77                 :            :     /* Here, unsigned types are used to avoid dealing with signed integer
          78                 :            :        overflow, which is undefined in C. */
          79                 :        125 :     size_t alloc = self->buf_size;
          80                 :        125 :     Py_UCS4 *new_buf = NULL;
          81                 :            :
          82                 :            :     assert(self->buf != NULL);
          83                 :            :
          84                 :            :     /* Reserve one more char for line ending detection. */
          85                 :        125 :     size = size + 1;
          86                 :            :     /* For simplicity, stay in the range of the signed type. Anyway, Python
          87                 :            :        doesn't allow strings to be longer than this. */
          88         [ -  + ]:        125 :     if (size > PY_SSIZE_T_MAX)
          89                 :          0 :         goto overflow;
          90                 :            :
          91         [ +  + ]:        125 :     if (size < alloc / 2) {
          92                 :            :         /* Major downsize; resize down to exact size. */
          93                 :         38 :         alloc = size + 1;
          94                 :            :     }
          95         [ +  + ]:         87 :     else if (size < alloc) {
          96                 :            :         /* Within allocated size; quick exit */
          97                 :          1 :         return 0;
          98                 :            :     }
          99         [ +  + ]:         86 :     else if (size <= alloc * 1.125) {
         100                 :            :         /* Moderate upsize; overallocate similar to list_resize() */
         101         [ +  + ]:         37 :         alloc = size + (size >> 3) + (size < 9 ? 3 : 6);
         102                 :            :     }
         103                 :            :     else {
         104                 :            :         /* Major upsize; resize up to exact size */
         105                 :         49 :         alloc = size + 1;
         106                 :            :     }
         107                 :            :
         108         [ -  + ]:        124 :     if (alloc > PY_SIZE_MAX / sizeof(Py_UCS4))
         109                 :          0 :         goto overflow;
         110                 :        124 :     new_buf = (Py_UCS4 *)PyMem_Realloc(self->buf, alloc * sizeof(Py_UCS4));
         111         [ -  + ]:        124 :     if (new_buf == NULL) {
         112                 :          0 :         PyErr_NoMemory();
         113                 :          0 :         return -1;
         114                 :            :     }
         115                 :        124 :     self->buf_size = alloc;
         116                 :        124 :     self->buf = new_buf;
         117                 :            :
         118                 :        124 :     return 0;
         119                 :            :
         120                 :          0 :   overflow:
         121                 :          0 :     PyErr_SetString(PyExc_OverflowError,
         122                 :            :                     "new buffer size too large");
         123                 :          0 :     return -1;
         124                 :            : }
         125                 :            :
         126                 :            : static PyObject *
         127                 :         19 : make_intermediate(stringio *self)
         128                 :            : {
         129                 :         19 :     PyObject *intermediate = _PyUnicodeWriter_Finish(&self->writer);
         130                 :         19 :     self->state = STATE_REALIZED;
         131         [ -  + ]:         19 :     if (intermediate == NULL)
         132                 :          0 :         return NULL;
         133                 :            :
         134                 :         19 :     _PyUnicodeWriter_Init(&self->writer);
         135                 :         19 :     self->writer.overallocate = 1;
         136         [ -  + ]:         19 :     if (_PyUnicodeWriter_WriteStr(&self->writer, intermediate)) {
         137                 :          0 :         Py_DECREF(intermediate);
         138                 :          0 :         return NULL;
         139                 :            :     }
         140                 :         19 :     self->state = STATE_ACCUMULATING;
         141                 :         19 :     return intermediate;
         142                 :            : }
         143                 :            :
         144                 :            : static int
         145                 :         38 : realize(stringio *self)
         146                 :            : {
         147                 :            :     Py_ssize_t len;
         148                 :            :     PyObject *intermediate;
         149                 :            :
         150         [ +  + ]:         38 :     if (self->state == STATE_REALIZED)
         151                 :         37 :         return 0;
         152                 :            :     assert(self->state == STATE_ACCUMULATING);
         153                 :          1 :     self->state = STATE_REALIZED;
         154                 :            :
         155                 :          1 :     intermediate = _PyUnicodeWriter_Finish(&self->writer);
         156         [ -  + ]:          1 :     if (intermediate == NULL)
         157                 :          0 :         return -1;
         158                 :            :
         159                 :            :     /* Append the intermediate string to the internal buffer.
         160                 :            :        The length should be equal to the current cursor position.
         161                 :            :      */
         162                 :          1 :     len = PyUnicode_GET_LENGTH(intermediate);
         163         [ -  + ]:          1 :     if (resize_buffer(self, len) < 0) {
         164                 :          0 :         Py_DECREF(intermediate);
         165                 :          0 :         return -1;
         166                 :            :     }
         167         [ -  + ]:          1 :     if (!PyUnicode_AsUCS4(intermediate, self->buf, len, 0)) {
         168                 :          0 :         Py_DECREF(intermediate);
         169                 :          0 :         return -1;
         170                 :            :     }
         171                 :            :
         172                 :          1 :     Py_DECREF(intermediate);
         173                 :          1 :     return 0;
         174                 :            : }
         175                 :            :
         176                 :            : /* Internal routine for writing a whole PyUnicode object to the buffer of a
         177                 :            :    StringIO object. Returns 0 on success, or -1 on error. */
         178                 :            : static Py_ssize_t
         179                 :        112 : write_str(stringio *self, PyObject *obj)
         180                 :            : {
         181                 :            :     Py_ssize_t len;
         182                 :        112 :     PyObject *decoded = NULL;
         183                 :            :
         184                 :            :     assert(self->buf != NULL);
         185                 :            :     assert(self->pos >= 0);
         186                 :            :
         187         [ -  + ]:        112 :     if (self->decoder != NULL) {
         188                 :          0 :         decoded = _PyIncrementalNewlineDecoder_decode(
         189                 :            :             self->decoder, obj, 1 /* always final */);
         190                 :            :     }
         191                 :            :     else {
         192                 :        112 :         decoded = Py_NewRef(obj);
         193                 :            :     }
         194         [ -  + ]:        112 :     if (self->writenl) {
         195                 :          0 :         PyObject *translated = PyUnicode_Replace(
         196                 :            :             decoded, &_Py_STR(newline), self->writenl, -1);
         197                 :          0 :         Py_SETREF(decoded, translated);
         198                 :            :     }
         199         [ -  + ]:        112 :     if (decoded == NULL)
         200                 :          0 :         return -1;
         201                 :            :
         202                 :            :     assert(PyUnicode_Check(decoded));
         203         [ -  + ]:        112 :     if (PyUnicode_READY(decoded)) {
         204                 :          0 :         Py_DECREF(decoded);
         205                 :          0 :         return -1;
         206                 :            :     }
         207                 :        112 :     len = PyUnicode_GET_LENGTH(decoded);
         208                 :            :     assert(len >= 0);
         209                 :            :
         210                 :            :     /* This overflow check is not strictly necessary. However, it avoids us to
         211                 :            :        deal with funky things like comparing an unsigned and a signed
         212                 :            :        integer. */
         213         [ -  + ]:        112 :     if (self->pos > PY_SSIZE_T_MAX - len) {
         214                 :          0 :         PyErr_SetString(PyExc_OverflowError,
         215                 :            :                         "new position too large");
         216                 :          0 :         goto fail;
         217                 :            :     }
         218                 :            :
         219         [ +  + ]:        112 :     if (self->state == STATE_ACCUMULATING) {
         220         [ +  - ]:         38 :         if (self->string_size == self->pos) {
         221         [ -  + ]:         38 :             if (_PyUnicodeWriter_WriteStr(&self->writer, decoded))
         222                 :          0 :                 goto fail;
         223                 :         38 :             goto success;
         224                 :            :         }
         225         [ #  # ]:          0 :         if (realize(self))
         226                 :          0 :             goto fail;
         227                 :            :     }
         228                 :            :
         229         [ +  - ]:         74 :     if (self->pos + len > self->string_size) {
         230         [ -  + ]:         74 :         if (resize_buffer(self, self->pos + len) < 0)
         231                 :          0 :             goto fail;
         232                 :            :     }
         233                 :            :
         234         [ -  + ]:         74 :     if (self->pos > self->string_size) {
         235                 :            :         /* In case of overseek, pad with null bytes the buffer region between
         236                 :            :            the end of stream and the current position.
         237                 :            :
         238                 :            :           0   lo      string_size                           hi
         239                 :            :           |   |<---used--->|<----------available----------->|
         240                 :            :           |   |            <--to pad-->|<---to write--->    |
         241                 :            :           0   buf                   position
         242                 :            :
         243                 :            :         */
         244                 :          0 :         memset(self->buf + self->string_size, '\0',
         245                 :          0 :                (self->pos - self->string_size) * sizeof(Py_UCS4));
         246                 :            :     }
         247                 :            :
         248                 :            :     /* Copy the data to the internal buffer, overwriting some of the
         249                 :            :        existing data if self->pos < self->string_size. */
         250         [ -  + ]:         74 :     if (!PyUnicode_AsUCS4(decoded,
         251                 :         74 :                           self->buf + self->pos,
         252                 :         74 :                           self->buf_size - self->pos,
         253                 :            :                           0))
         254                 :          0 :         goto fail;
         255                 :            :
         256                 :         74 : success:
         257                 :            :     /* Set the new length of the internal string if it has changed. */
         258                 :        112 :     self->pos += len;
         259         [ +  - ]:        112 :     if (self->string_size < self->pos)
         260                 :        112 :         self->string_size = self->pos;
         261                 :            :
         262                 :        112 :     Py_DECREF(decoded);
         263                 :        112 :     return 0;
         264                 :            :
         265                 :          0 : fail:
         266                 :          0 :     Py_XDECREF(decoded);
         267                 :          0 :     return -1;
         268                 :            : }
         269                 :            :
         270                 :            : /*[clinic input]
         271                 :            : _io.StringIO.getvalue
         272                 :            :
         273                 :            : Retrieve the entire contents of the object.
         274                 :            : [clinic start generated code]*/
         275                 :            :
         276                 :            : static PyObject *
         277                 :         65 : _io_StringIO_getvalue_impl(stringio *self)
         278                 :            : /*[clinic end generated code: output=27b6a7bfeaebce01 input=d23cb81d6791cf88]*/
         279                 :            : {
         280         [ -  + ]:         65 :     CHECK_INITIALIZED(self);
         281         [ -  + ]:         65 :     CHECK_CLOSED(self);
         282         [ +  + ]:         65 :     if (self->state == STATE_ACCUMULATING)
         283                 :         19 :         return make_intermediate(self);
         284                 :         46 :     return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, self->buf,
         285                 :            :                                      self->string_size);
         286                 :            : }
         287                 :            :
         288                 :            : /*[clinic input]
         289                 :            : _io.StringIO.tell
         290                 :            :
         291                 :            : Tell the current file position.
         292                 :            : [clinic start generated code]*/
         293                 :            :
         294                 :            : static PyObject *
         295                 :          0 : _io_StringIO_tell_impl(stringio *self)
         296                 :            : /*[clinic end generated code: output=2e87ac67b116c77b input=ec866ebaff02f405]*/
         297                 :            : {
         298         [ #  # ]:          0 :     CHECK_INITIALIZED(self);
         299         [ #  # ]:          0 :     CHECK_CLOSED(self);
         300                 :          0 :     return PyLong_FromSsize_t(self->pos);
         301                 :            : }
         302                 :            :
         303                 :            : /*[clinic input]
         304                 :            : _io.StringIO.read
         305                 :            :     size: Py_ssize_t(accept={int, NoneType}) = -1
         306                 :            :     /
         307                 :            :
         308                 :            : Read at most size characters, returned as a string.
         309                 :            :
         310                 :            : If the argument is negative or omitted, read until EOF
         311                 :            : is reached. Return an empty string at EOF.
         312                 :            : [clinic start generated code]*/
         313                 :            :
         314                 :            : static PyObject *
         315                 :          0 : _io_StringIO_read_impl(stringio *self, Py_ssize_t size)
         316                 :            : /*[clinic end generated code: output=ae8cf6002f71626c input=0921093383dfb92d]*/
         317                 :            : {
         318                 :            :     Py_ssize_t n;
         319                 :            :     Py_UCS4 *output;
         320                 :            :
         321         [ #  # ]:          0 :     CHECK_INITIALIZED(self);
         322         [ #  # ]:          0 :     CHECK_CLOSED(self);
         323                 :            :
         324                 :            :     /* adjust invalid sizes */
         325                 :          0 :     n = self->string_size - self->pos;
         326   [ #  #  #  # ]:          0 :     if (size < 0 || size > n) {
         327                 :          0 :         size = n;
         328         [ #  # ]:          0 :         if (size < 0)
         329                 :          0 :             size = 0;
         330                 :            :     }
         331                 :            :
         332                 :            :     /* Optimization for seek(0); read() */
         333   [ #  #  #  #  :          0 :     if (self->state == STATE_ACCUMULATING && self->pos == 0 && size == n) {
                       #  # ]
         334                 :          0 :         PyObject *result = make_intermediate(self);
         335                 :          0 :         self->pos = self->string_size;
         336                 :          0 :         return result;
         337                 :            :     }
         338                 :            :
         339         [ #  # ]:          0 :     ENSURE_REALIZED(self);
         340                 :          0 :     output = self->buf + self->pos;
         341                 :          0 :     self->pos += size;
         342                 :          0 :     return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, output, size);
         343                 :            : }
         344                 :            :
         345                 :            : /* Internal helper, used by stringio_readline and stringio_iternext */
         346                 :            : static PyObject *
         347                 :          0 : _stringio_readline(stringio *self, Py_ssize_t limit)
         348                 :            : {
         349                 :            :     Py_UCS4 *start, *end, old_char;
         350                 :            :     Py_ssize_t len, consumed;
         351                 :            :
         352                 :            :     /* In case of overseek, return the empty string */
         353         [ #  # ]:          0 :     if (self->pos >= self->string_size)
         354                 :          0 :         return PyUnicode_New(0, 0);
         355                 :            :
         356                 :          0 :     start = self->buf + self->pos;
         357   [ #  #  #  # ]:          0 :     if (limit < 0 || limit > self->string_size - self->pos)
         358                 :          0 :         limit = self->string_size - self->pos;
         359                 :            :
         360                 :          0 :     end = start + limit;
         361                 :          0 :     old_char = *end;
         362                 :          0 :     *end = '\0';
         363                 :          0 :     len = _PyIO_find_line_ending(
         364                 :          0 :         self->readtranslate, self->readuniversal, self->readnl,
         365                 :            :         PyUnicode_4BYTE_KIND, (char*)start, (char*)end, &consumed);
         366                 :          0 :     *end = old_char;
         367                 :            :     /* If we haven't found any line ending, we just return everything
         368                 :            :        (`consumed` is ignored). */
         369         [ #  # ]:          0 :     if (len < 0)
         370                 :          0 :         len = limit;
         371                 :          0 :     self->pos += len;
         372                 :          0 :     return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, start, len);
         373                 :            : }
         374                 :            :
         375                 :            : /*[clinic input]
         376                 :            : _io.StringIO.readline
         377                 :            :     size: Py_ssize_t(accept={int, NoneType}) = -1
         378                 :            :     /
         379                 :            :
         380                 :            : Read until newline or EOF.
         381                 :            :
         382                 :            : Returns an empty string if EOF is hit immediately.
         383                 :            : [clinic start generated code]*/
         384                 :            :
         385                 :            : static PyObject *
         386                 :          0 : _io_StringIO_readline_impl(stringio *self, Py_ssize_t size)
         387                 :            : /*[clinic end generated code: output=cabd6452f1b7e85d input=a5bd70bf682aa276]*/
         388                 :            : {
         389         [ #  # ]:          0 :     CHECK_INITIALIZED(self);
         390         [ #  # ]:          0 :     CHECK_CLOSED(self);
         391         [ #  # ]:          0 :     ENSURE_REALIZED(self);
         392                 :            :
         393                 :          0 :     return _stringio_readline(self, size);
         394                 :            : }
         395                 :            :
         396                 :            : static PyObject *
         397                 :          0 : stringio_iternext(stringio *self)
         398                 :            : {
         399                 :            :     PyObject *line;
         400                 :            :
         401         [ #  # ]:          0 :     CHECK_INITIALIZED(self);
         402         [ #  # ]:          0 :     CHECK_CLOSED(self);
         403         [ #  # ]:          0 :     ENSURE_REALIZED(self);
         404                 :            :
         405         [ #  # ]:          0 :     if (Py_IS_TYPE(self, self->module_state->PyStringIO_Type)) {
         406                 :            :         /* Skip method call overhead for speed */
         407                 :          0 :         line = _stringio_readline(self, -1);
         408                 :            :     }
         409                 :            :     else {
         410                 :            :         /* XXX is subclassing StringIO really supported? */
         411                 :          0 :         line = PyObject_CallMethodNoArgs((PyObject *)self,
         412                 :            :                                              &_Py_ID(readline));
         413   [ #  #  #  # ]:          0 :         if (line && !PyUnicode_Check(line)) {
         414                 :          0 :             PyErr_Format(PyExc_OSError,
         415                 :            :                          "readline() should have returned a str object, "
         416                 :          0 :                          "not '%.200s'", Py_TYPE(line)->tp_name);
         417                 :          0 :             Py_DECREF(line);
         418                 :          0 :             return NULL;
         419                 :            :         }
         420                 :            :     }
         421                 :            :
         422         [ #  # ]:          0 :     if (line == NULL)
         423                 :          0 :         return NULL;
         424                 :            :
         425         [ #  # ]:          0 :     if (PyUnicode_GET_LENGTH(line) == 0) {
         426                 :            :         /* Reached EOF */
         427                 :          0 :         Py_DECREF(line);
         428                 :          0 :         return NULL;
         429                 :            :     }
         430                 :            :
         431                 :          0 :     return line;
         432                 :            : }
         433                 :            :
         434                 :            : /*[clinic input]
         435                 :            : _io.StringIO.truncate
         436                 :            :     pos as size: Py_ssize_t(accept={int, NoneType}, c_default="self->pos") = None
         437                 :            :     /
         438                 :            :
         439                 :            : Truncate size to pos.
         440                 :            :
         441                 :            : The pos argument defaults to the current file position, as
         442                 :            : returned by tell().  The current file position is unchanged.
         443                 :            : Returns the new absolute position.
         444                 :            : [clinic start generated code]*/
         445                 :            :
         446                 :            : static PyObject *
         447                 :         56 : _io_StringIO_truncate_impl(stringio *self, Py_ssize_t size)
         448                 :            : /*[clinic end generated code: output=eb3aef8e06701365 input=5505cff90ca48b96]*/
         449                 :            : {
         450         [ -  + ]:         56 :     CHECK_INITIALIZED(self);
         451         [ -  + ]:         56 :     CHECK_CLOSED(self);
         452                 :            :
         453         [ -  + ]:         56 :     if (size < 0) {
         454                 :          0 :         PyErr_Format(PyExc_ValueError,
         455                 :            :                      "Negative size value %zd", size);
         456                 :          0 :         return NULL;
         457                 :            :     }
         458                 :            :
         459         [ +  + ]:         56 :     if (size < self->string_size) {
         460         [ -  + ]:         38 :         ENSURE_REALIZED(self);
         461         [ -  + ]:         38 :         if (resize_buffer(self, size) < 0)
         462                 :          0 :             return NULL;
         463                 :         38 :         self->string_size = size;
         464                 :            :     }
         465                 :            :
         466                 :         56 :     return PyLong_FromSsize_t(size);
         467                 :            : }
         468                 :            :
         469                 :            : /*[clinic input]
         470                 :            : _io.StringIO.seek
         471                 :            :     pos: Py_ssize_t
         472                 :            :     whence: int = 0
         473                 :            :     /
         474                 :            :
         475                 :            : Change stream position.
         476                 :            :
         477                 :            : Seek to character offset pos relative to position indicated by whence:
         478                 :            :     0  Start of stream (the default).  pos should be >= 0;
         479                 :            :     1  Current position - pos must be 0;
         480                 :            :     2  End of stream - pos must be 0.
         481                 :            : Returns the new absolute position.
         482                 :            : [clinic start generated code]*/
         483                 :            :
         484                 :            : static PyObject *
         485                 :         56 : _io_StringIO_seek_impl(stringio *self, Py_ssize_t pos, int whence)
         486                 :            : /*[clinic end generated code: output=e9e0ac9a8ae71c25 input=e3855b24e7cae06a]*/
         487                 :            : {
         488         [ -  + ]:         56 :     CHECK_INITIALIZED(self);
         489         [ -  + ]:         56 :     CHECK_CLOSED(self);
         490                 :            :
         491   [ -  +  -  -  :         56 :     if (whence != 0 && whence != 1 && whence != 2) {
                       -  - ]
         492                 :          0 :         PyErr_Format(PyExc_ValueError,
         493                 :            :                      "Invalid whence (%i, should be 0, 1 or 2)", whence);
         494                 :          0 :         return NULL;
         495                 :            :     }
         496   [ -  +  -  - ]:         56 :     else if (pos < 0 && whence == 0) {
         497                 :          0 :         PyErr_Format(PyExc_ValueError,
         498                 :            :                      "Negative seek position %zd", pos);
         499                 :          0 :         return NULL;
         500                 :            :     }
         501   [ -  +  -  - ]:         56 :     else if (whence != 0 && pos != 0) {
         502                 :          0 :         PyErr_SetString(PyExc_OSError,
         503                 :            :                         "Can't do nonzero cur-relative seeks");
         504                 :          0 :         return NULL;
         505                 :            :     }
         506                 :            :
         507                 :            :     /* whence = 0: offset relative to beginning of the string.
         508                 :            :        whence = 1: no change to current position.
         509                 :            :        whence = 2: change position to end of file. */
         510         [ -  + ]:         56 :     if (whence == 1) {
         511                 :          0 :         pos = self->pos;
         512                 :            :     }
         513         [ -  + ]:         56 :     else if (whence == 2) {
         514                 :          0 :         pos = self->string_size;
         515                 :            :     }
         516                 :            :
         517                 :         56 :     self->pos = pos;
         518                 :            :
         519                 :         56 :     return PyLong_FromSsize_t(self->pos);
         520                 :            : }
         521                 :            :
         522                 :            : /*[clinic input]
         523                 :            : _io.StringIO.write
         524                 :            :     s as obj: object
         525                 :            :     /
         526                 :            :
         527                 :            : Write string to file.
         528                 :            :
         529                 :            : Returns the number of characters written, which is always equal to
         530                 :            : the length of the string.
         531                 :            : [clinic start generated code]*/
         532                 :            :
         533                 :            : static PyObject *
         534                 :        148 : _io_StringIO_write(stringio *self, PyObject *obj)
         535                 :            : /*[clinic end generated code: output=0deaba91a15b94da input=cf96f3b16586e669]*/
         536                 :            : {
         537                 :            :     Py_ssize_t size;
         538                 :            :
         539         [ -  + ]:        148 :     CHECK_INITIALIZED(self);
         540         [ -  + ]:        148 :     if (!PyUnicode_Check(obj)) {
         541                 :          0 :         PyErr_Format(PyExc_TypeError, "string argument expected, got '%s'",
         542                 :          0 :                      Py_TYPE(obj)->tp_name);
         543                 :          0 :         return NULL;
         544                 :            :     }
         545         [ -  + ]:        148 :     if (PyUnicode_READY(obj))
         546                 :          0 :         return NULL;
         547         [ -  + ]:        148 :     CHECK_CLOSED(self);
         548                 :        148 :     size = PyUnicode_GET_LENGTH(obj);
         549                 :            :
         550   [ +  +  -  + ]:        148 :     if (size > 0 && write_str(self, obj) < 0)
         551                 :          0 :         return NULL;
         552                 :            :
         553                 :        148 :     return PyLong_FromSsize_t(size);
         554                 :            : }
         555                 :            :
         556                 :            : /*[clinic input]
         557                 :            : _io.StringIO.close
         558                 :            :
         559                 :            : Close the IO object.
         560                 :            :
         561                 :            : Attempting any further operation after the object is closed
         562                 :            : will raise a ValueError.
         563                 :            :
         564                 :            : This method has no effect if the file is already closed.
         565                 :            : [clinic start generated code]*/
         566                 :            :
         567                 :            : static PyObject *
         568                 :          1 : _io_StringIO_close_impl(stringio *self)
         569                 :            : /*[clinic end generated code: output=04399355cbe518f1 input=cbc10b45f35d6d46]*/
         570                 :            : {
         571                 :          1 :     self->closed = 1;
         572                 :            :     /* Free up some memory */
         573         [ -  + ]:          1 :     if (resize_buffer(self, 0) < 0)
         574                 :          0 :         return NULL;
         575                 :          1 :     _PyUnicodeWriter_Dealloc(&self->writer);
         576         [ +  - ]:          1 :     Py_CLEAR(self->readnl);
         577         [ -  + ]:          1 :     Py_CLEAR(self->writenl);
         578         [ -  + ]:          1 :     Py_CLEAR(self->decoder);
         579                 :          1 :     Py_RETURN_NONE;
         580                 :            : }
         581                 :            :
         582                 :            : static int
         583                 :          0 : stringio_traverse(stringio *self, visitproc visit, void *arg)
         584                 :            : {
         585   [ #  #  #  # ]:          0 :     Py_VISIT(Py_TYPE(self));
         586   [ #  #  #  # ]:          0 :     Py_VISIT(self->dict);
         587                 :          0 :     return 0;
         588                 :            : }
         589                 :            :
         590                 :            : static int
         591                 :          0 : stringio_clear(stringio *self)
         592                 :            : {
         593         [ #  # ]:          0 :     Py_CLEAR(self->dict);
         594                 :          0 :     return 0;
         595                 :            : }
         596                 :            :
         597                 :            : static void
         598                 :         11 : stringio_dealloc(stringio *self)
         599                 :            : {
         600                 :         11 :     PyTypeObject *tp = Py_TYPE(self);
         601                 :         11 :     _PyObject_GC_UNTRACK(self);
         602                 :         11 :     self->ok = 0;
         603         [ +  - ]:         11 :     if (self->buf) {
         604                 :         11 :         PyMem_Free(self->buf);
         605                 :         11 :         self->buf = NULL;
         606                 :            :     }
         607                 :         11 :     _PyUnicodeWriter_Dealloc(&self->writer);
         608         [ +  + ]:         11 :     Py_CLEAR(self->readnl);
         609         [ -  + ]:         11 :     Py_CLEAR(self->writenl);
         610         [ -  + ]:         11 :     Py_CLEAR(self->decoder);
         611         [ +  + ]:         11 :     Py_CLEAR(self->dict);
         612         [ -  + ]:         11 :     if (self->weakreflist != NULL) {
         613                 :          0 :         PyObject_ClearWeakRefs((PyObject *) self);
         614                 :            :     }
         615                 :         11 :     tp->tp_free(self);
         616                 :         11 :     Py_DECREF(tp);
         617                 :         11 : }
         618                 :            :
         619                 :            : static PyObject *
         620                 :         11 : stringio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         621                 :            : {
         622                 :            :     stringio *self;
         623                 :            :
         624                 :            :     assert(type != NULL && type->tp_alloc != NULL);
         625                 :         11 :     self = (stringio *)type->tp_alloc(type, 0);
         626         [ -  + ]:         11 :     if (self == NULL)
         627                 :          0 :         return NULL;
         628                 :            :
         629                 :            :     /* tp_alloc initializes all the fields to zero. So we don't have to
         630                 :            :        initialize them here. */
         631                 :            :
         632                 :         11 :     self->buf = (Py_UCS4 *)PyMem_Malloc(0);
         633         [ -  + ]:         11 :     if (self->buf == NULL) {
         634                 :          0 :         Py_DECREF(self);
         635                 :          0 :         return PyErr_NoMemory();
         636                 :            :     }
         637                 :            :
         638                 :         11 :     return (PyObject *)self;
         639                 :            : }
         640                 :            :
         641                 :            : /*[clinic input]
         642                 :            : _io.StringIO.__init__
         643                 :            :     initial_value as value: object(c_default="NULL") = ''
         644                 :            :     newline as newline_obj: object(c_default="NULL") = '\n'
         645                 :            :
         646                 :            : Text I/O implementation using an in-memory buffer.
         647                 :            :
         648                 :            : The initial_value argument sets the value of object.  The newline
         649                 :            : argument is like the one of TextIOWrapper's constructor.
         650                 :            : [clinic start generated code]*/
         651                 :            :
         652                 :            : static int
         653                 :         11 : _io_StringIO___init___impl(stringio *self, PyObject *value,
         654                 :            :                            PyObject *newline_obj)
         655                 :            : /*[clinic end generated code: output=a421ea023b22ef4e input=cee2d9181b2577a3]*/
         656                 :            : {
         657                 :         11 :     const char *newline = "\n";
         658                 :            :     Py_ssize_t value_len;
         659                 :            :
         660                 :            :     /* Parse the newline argument. We only want to allow unicode objects or
         661                 :            :        None. */
         662         [ -  + ]:         11 :     if (newline_obj == Py_None) {
         663                 :          0 :         newline = NULL;
         664                 :            :     }
         665         [ -  + ]:         11 :     else if (newline_obj) {
         666         [ #  # ]:          0 :         if (!PyUnicode_Check(newline_obj)) {
         667                 :          0 :             PyErr_Format(PyExc_TypeError,
         668                 :            :                          "newline must be str or None, not %.200s",
         669                 :          0 :                          Py_TYPE(newline_obj)->tp_name);
         670                 :          0 :             return -1;
         671                 :            :         }
         672                 :          0 :         newline = PyUnicode_AsUTF8(newline_obj);
         673         [ #  # ]:          0 :         if (newline == NULL)
         674                 :          0 :             return -1;
         675                 :            :     }
         676                 :            :
         677   [ +  -  +  - ]:         11 :     if (newline && newline[0] != '\0'
         678   [ +  -  -  + ]:         11 :         && !(newline[0] == '\n' && newline[1] == '\0')
         679   [ #  #  #  # ]:          0 :         && !(newline[0] == '\r' && newline[1] == '\0')
         680   [ #  #  #  #  :          0 :         && !(newline[0] == '\r' && newline[1] == '\n' && newline[2] == '\0')) {
                       #  # ]
         681                 :          0 :         PyErr_Format(PyExc_ValueError,
         682                 :            :                      "illegal newline value: %R", newline_obj);
         683                 :          0 :         return -1;
         684                 :            :     }
         685   [ -  +  -  -  :         11 :     if (value && value != Py_None && !PyUnicode_Check(value)) {
                       -  - ]
         686                 :          0 :         PyErr_Format(PyExc_TypeError,
         687                 :            :                      "initial_value must be str or None, not %.200s",
         688                 :          0 :                      Py_TYPE(value)->tp_name);
         689                 :          0 :         return -1;
         690                 :            :     }
         691                 :            :
         692                 :         11 :     self->ok = 0;
         693                 :            :
         694                 :         11 :     _PyUnicodeWriter_Dealloc(&self->writer);
         695         [ -  + ]:         11 :     Py_CLEAR(self->readnl);
         696         [ -  + ]:         11 :     Py_CLEAR(self->writenl);
         697         [ -  + ]:         11 :     Py_CLEAR(self->decoder);
         698                 :            :
         699                 :            :     assert((newline != NULL && newline_obj != Py_None) ||
         700                 :            :            (newline == NULL && newline_obj == Py_None));
         701                 :            :
         702         [ +  - ]:         11 :     if (newline) {
         703                 :         11 :         self->readnl = PyUnicode_FromString(newline);
         704         [ -  + ]:         11 :         if (self->readnl == NULL)
         705                 :          0 :             return -1;
         706                 :            :     }
         707   [ +  -  -  + ]:         11 :     self->readuniversal = (newline == NULL || newline[0] == '\0');
         708                 :         11 :     self->readtranslate = (newline == NULL);
         709                 :            :     /* If newline == "", we don't translate anything.
         710                 :            :        If newline == "\n" or newline == None, we translate to "\n", which is
         711                 :            :        a no-op.
         712                 :            :        (for newline == None, TextIOWrapper translates to os.linesep, but it
         713                 :            :        is pointless for StringIO)
         714                 :            :     */
         715   [ +  -  -  + ]:         11 :     if (newline != NULL && newline[0] == '\r') {
         716                 :          0 :         self->writenl = Py_NewRef(self->readnl);
         717                 :            :     }
         718                 :            :
         719         [ -  + ]:         11 :     if (self->readuniversal) {
         720                 :          0 :         self->decoder = PyObject_CallFunctionObjArgs(
         721                 :            :             (PyObject *)&PyIncrementalNewlineDecoder_Type,
         722         [ #  # ]:          0 :             Py_None, self->readtranslate ? Py_True : Py_False, NULL);
         723         [ #  # ]:          0 :         if (self->decoder == NULL)
         724                 :          0 :             return -1;
         725                 :            :     }
         726                 :            :
         727                 :            :     /* Now everything is set up, resize buffer to size of initial value,
         728                 :            :        and copy it */
         729                 :         11 :     self->string_size = 0;
         730   [ -  +  -  - ]:         11 :     if (value && value != Py_None)
         731                 :          0 :         value_len = PyUnicode_GetLength(value);
         732                 :            :     else
         733                 :         11 :         value_len = 0;
         734         [ -  + ]:         11 :     if (value_len > 0) {
         735                 :            :         /* This is a heuristic, for newline translation might change
         736                 :            :            the string length. */
         737         [ #  # ]:          0 :         if (resize_buffer(self, 0) < 0)
         738                 :          0 :             return -1;
         739                 :          0 :         self->state = STATE_REALIZED;
         740                 :          0 :         self->pos = 0;
         741         [ #  # ]:          0 :         if (write_str(self, value) < 0)
         742                 :          0 :             return -1;
         743                 :            :     }
         744                 :            :     else {
         745                 :            :         /* Empty stringio object, we can start by accumulating */
         746         [ -  + ]:         11 :         if (resize_buffer(self, 0) < 0)
         747                 :          0 :             return -1;
         748                 :         11 :         _PyUnicodeWriter_Init(&self->writer);
         749                 :         11 :         self->writer.overallocate = 1;
         750                 :         11 :         self->state = STATE_ACCUMULATING;
         751                 :            :     }
         752                 :         11 :     self->pos = 0;
         753                 :         11 :     self->module_state = find_io_state_by_def(Py_TYPE(self));
         754                 :         11 :     self->closed = 0;
         755                 :         11 :     self->ok = 1;
         756                 :         11 :     return 0;
         757                 :            : }
         758                 :            :
         759                 :            : /* Properties and pseudo-properties */
         760                 :            :
         761                 :            : /*[clinic input]
         762                 :            : _io.StringIO.readable
         763                 :            :
         764                 :            : Returns True if the IO object can be read.
         765                 :            : [clinic start generated code]*/
         766                 :            :
         767                 :            : static PyObject *
         768                 :          0 : _io_StringIO_readable_impl(stringio *self)
         769                 :            : /*[clinic end generated code: output=b19d44dd8b1ceb99 input=39ce068b224c21ad]*/
         770                 :            : {
         771         [ #  # ]:          0 :     CHECK_INITIALIZED(self);
         772         [ #  # ]:          0 :     CHECK_CLOSED(self);
         773                 :          0 :     Py_RETURN_TRUE;
         774                 :            : }
         775                 :            :
         776                 :            : /*[clinic input]
         777                 :            : _io.StringIO.writable
         778                 :            :
         779                 :            : Returns True if the IO object can be written.
         780                 :            : [clinic start generated code]*/
         781                 :            :
         782                 :            : static PyObject *
         783                 :          0 : _io_StringIO_writable_impl(stringio *self)
         784                 :            : /*[clinic end generated code: output=13e4dd77187074ca input=7a691353aac38835]*/
         785                 :            : {
         786         [ #  # ]:          0 :     CHECK_INITIALIZED(self);
         787         [ #  # ]:          0 :     CHECK_CLOSED(self);
         788                 :          0 :     Py_RETURN_TRUE;
         789                 :            : }
         790                 :            :
         791                 :            : /*[clinic input]
         792                 :            : _io.StringIO.seekable
         793                 :            :
         794                 :            : Returns True if the IO object can be seeked.
         795                 :            : [clinic start generated code]*/
         796                 :            :
         797                 :            : static PyObject *
         798                 :          0 : _io_StringIO_seekable_impl(stringio *self)
         799                 :            : /*[clinic end generated code: output=4d20b4641c756879 input=4c606d05b32952e6]*/
         800                 :            : {
         801         [ #  # ]:          0 :     CHECK_INITIALIZED(self);
         802         [ #  # ]:          0 :     CHECK_CLOSED(self);
         803                 :          0 :     Py_RETURN_TRUE;
         804                 :            : }
         805                 :            :
         806                 :            : /* Pickling support.
         807                 :            :
         808                 :            :    The implementation of __getstate__ is similar to the one for BytesIO,
         809                 :            :    except that we also save the newline parameter. For __setstate__ and unlike
         810                 :            :    BytesIO, we call __init__ to restore the object's state. Doing so allows us
         811                 :            :    to avoid decoding the complex newline state while keeping the object
         812                 :            :    representation compact.
         813                 :            :
         814                 :            :    See comment in bytesio.c regarding why only pickle protocols and onward are
         815                 :            :    supported.
         816                 :            : */
         817                 :            :
         818                 :            : static PyObject *
         819                 :          0 : stringio_getstate(stringio *self, PyObject *Py_UNUSED(ignored))
         820                 :            : {
         821                 :          0 :     PyObject *initvalue = _io_StringIO_getvalue_impl(self);
         822                 :            :     PyObject *dict;
         823                 :            :     PyObject *state;
         824                 :            :
         825         [ #  # ]:          0 :     if (initvalue == NULL)
         826                 :          0 :         return NULL;
         827         [ #  # ]:          0 :     if (self->dict == NULL) {
         828                 :          0 :         dict = Py_NewRef(Py_None);
         829                 :            :     }
         830                 :            :     else {
         831                 :          0 :         dict = PyDict_Copy(self->dict);
         832         [ #  # ]:          0 :         if (dict == NULL) {
         833                 :          0 :             Py_DECREF(initvalue);
         834                 :          0 :             return NULL;
         835                 :            :         }
         836                 :            :     }
         837                 :            :
         838                 :          0 :     state = Py_BuildValue("(OOnN)", initvalue,
         839         [ #  # ]:          0 :                           self->readnl ? self->readnl : Py_None,
         840                 :            :                           self->pos, dict);
         841                 :          0 :     Py_DECREF(initvalue);
         842                 :          0 :     return state;
         843                 :            : }
         844                 :            :
         845                 :            : static PyObject *
         846                 :          0 : stringio_setstate(stringio *self, PyObject *state)
         847                 :            : {
         848                 :            :     PyObject *initarg;
         849                 :            :     PyObject *position_obj;
         850                 :            :     PyObject *dict;
         851                 :            :     Py_ssize_t pos;
         852                 :            :
         853                 :            :     assert(state != NULL);
         854         [ #  # ]:          0 :     CHECK_CLOSED(self);
         855                 :            :
         856                 :            :     /* We allow the state tuple to be longer than 4, because we may need
         857                 :            :        someday to extend the object's state without breaking
         858                 :            :        backward-compatibility. */
         859   [ #  #  #  # ]:          0 :     if (!PyTuple_Check(state) || PyTuple_GET_SIZE(state) < 4) {
         860                 :          0 :         PyErr_Format(PyExc_TypeError,
         861                 :            :                      "%.200s.__setstate__ argument should be 4-tuple, got %.200s",
         862                 :          0 :                      Py_TYPE(self)->tp_name, Py_TYPE(state)->tp_name);
         863                 :          0 :         return NULL;
         864                 :            :     }
         865                 :            :
         866                 :            :     /* Initialize the object's state. */
         867                 :          0 :     initarg = PyTuple_GetSlice(state, 0, 2);
         868         [ #  # ]:          0 :     if (initarg == NULL)
         869                 :          0 :         return NULL;
         870         [ #  # ]:          0 :     if (_io_StringIO___init__((PyObject *)self, initarg, NULL) < 0) {
         871                 :          0 :         Py_DECREF(initarg);
         872                 :          0 :         return NULL;
         873                 :            :     }
         874                 :          0 :     Py_DECREF(initarg);
         875                 :            :
         876                 :            :     /* Restore the buffer state. Even if __init__ did initialize the buffer,
         877                 :            :        we have to initialize it again since __init__ may translate the
         878                 :            :        newlines in the initial_value string. We clearly do not want that
         879                 :            :        because the string value in the state tuple has already been translated
         880                 :            :        once by __init__. So we do not take any chance and replace object's
         881                 :            :        buffer completely. */
         882                 :            :     {
         883                 :            :         PyObject *item;
         884                 :            :         Py_UCS4 *buf;
         885                 :            :         Py_ssize_t bufsize;
         886                 :            :
         887                 :          0 :         item = PyTuple_GET_ITEM(state, 0);
         888                 :          0 :         buf = PyUnicode_AsUCS4Copy(item);
         889         [ #  # ]:          0 :         if (buf == NULL)
         890                 :          0 :             return NULL;
         891                 :          0 :         bufsize = PyUnicode_GET_LENGTH(item);
         892                 :            :
         893         [ #  # ]:          0 :         if (resize_buffer(self, bufsize) < 0) {
         894                 :          0 :             PyMem_Free(buf);
         895                 :          0 :             return NULL;
         896                 :            :         }
         897                 :          0 :         memcpy(self->buf, buf, bufsize * sizeof(Py_UCS4));
         898                 :          0 :         PyMem_Free(buf);
         899                 :          0 :         self->string_size = bufsize;
         900                 :            :     }
         901                 :            :
         902                 :            :     /* Set carefully the position value. Alternatively, we could use the seek
         903                 :            :        method instead of modifying self->pos directly to better protect the
         904                 :            :        object internal state against erroneous (or malicious) inputs. */
         905                 :          0 :     position_obj = PyTuple_GET_ITEM(state, 2);
         906         [ #  # ]:          0 :     if (!PyLong_Check(position_obj)) {
         907                 :          0 :         PyErr_Format(PyExc_TypeError,
         908                 :            :                      "third item of state must be an integer, got %.200s",
         909                 :          0 :                      Py_TYPE(position_obj)->tp_name);
         910                 :          0 :         return NULL;
         911                 :            :     }
         912                 :          0 :     pos = PyLong_AsSsize_t(position_obj);
         913   [ #  #  #  # ]:          0 :     if (pos == -1 && PyErr_Occurred())
         914                 :          0 :         return NULL;
         915         [ #  # ]:          0 :     if (pos < 0) {
         916                 :          0 :         PyErr_SetString(PyExc_ValueError,
         917                 :            :                         "position value cannot be negative");
         918                 :          0 :         return NULL;
         919                 :            :     }
         920                 :          0 :     self->pos = pos;
         921                 :            :
         922                 :            :     /* Set the dictionary of the instance variables. */
         923                 :          0 :     dict = PyTuple_GET_ITEM(state, 3);
         924         [ #  # ]:          0 :     if (dict != Py_None) {
         925         [ #  # ]:          0 :         if (!PyDict_Check(dict)) {
         926                 :          0 :             PyErr_Format(PyExc_TypeError,
         927                 :            :                          "fourth item of state should be a dict, got a %.200s",
         928                 :          0 :                          Py_TYPE(dict)->tp_name);
         929                 :          0 :             return NULL;
         930                 :            :         }
         931         [ #  # ]:          0 :         if (self->dict) {
         932                 :            :             /* Alternatively, we could replace the internal dictionary
         933                 :            :                completely. However, it seems more practical to just update it. */
         934         [ #  # ]:          0 :             if (PyDict_Update(self->dict, dict) < 0)
         935                 :          0 :                 return NULL;
         936                 :            :         }
         937                 :            :         else {
         938                 :          0 :             self->dict = Py_NewRef(dict);
         939                 :            :         }
         940                 :            :     }
         941                 :            :
         942                 :          0 :     Py_RETURN_NONE;
         943                 :            : }
         944                 :            :
         945                 :            :
         946                 :            : static PyObject *
         947                 :          1 : stringio_closed(stringio *self, void *context)
         948                 :            : {
         949         [ -  + ]:          1 :     CHECK_INITIALIZED(self);
         950                 :          1 :     return PyBool_FromLong(self->closed);
         951                 :            : }
         952                 :            :
         953                 :            : static PyObject *
         954                 :          0 : stringio_line_buffering(stringio *self, void *context)
         955                 :            : {
         956         [ #  # ]:          0 :     CHECK_INITIALIZED(self);
         957         [ #  # ]:          0 :     CHECK_CLOSED(self);
         958                 :          0 :     Py_RETURN_FALSE;
         959                 :            : }
         960                 :            :
         961                 :            : static PyObject *
         962                 :          0 : stringio_newlines(stringio *self, void *context)
         963                 :            : {
         964         [ #  # ]:          0 :     CHECK_INITIALIZED(self);
         965         [ #  # ]:          0 :     CHECK_CLOSED(self);
         966         [ #  # ]:          0 :     if (self->decoder == NULL)
         967                 :          0 :         Py_RETURN_NONE;
         968                 :          0 :     return PyObject_GetAttr(self->decoder, &_Py_ID(newlines));
         969                 :            : }
         970                 :            :
         971                 :            : #define clinic_state() (find_io_state_by_def(Py_TYPE(self)))
         972                 :            : #include "clinic/stringio.c.h"
         973                 :            : #undef clinic_state
         974                 :            :
         975                 :            : static struct PyMethodDef stringio_methods[] = {
         976                 :            :     _IO_STRINGIO_CLOSE_METHODDEF
         977                 :            :     _IO_STRINGIO_GETVALUE_METHODDEF
         978                 :            :     _IO_STRINGIO_READ_METHODDEF
         979                 :            :     _IO_STRINGIO_READLINE_METHODDEF
         980                 :            :     _IO_STRINGIO_TELL_METHODDEF
         981                 :            :     _IO_STRINGIO_TRUNCATE_METHODDEF
         982                 :            :     _IO_STRINGIO_SEEK_METHODDEF
         983                 :            :     _IO_STRINGIO_WRITE_METHODDEF
         984                 :            :
         985                 :            :     _IO_STRINGIO_SEEKABLE_METHODDEF
         986                 :            :     _IO_STRINGIO_READABLE_METHODDEF
         987                 :            :     _IO_STRINGIO_WRITABLE_METHODDEF
         988                 :            :
         989                 :            :     {"__getstate__", (PyCFunction)stringio_getstate, METH_NOARGS},
         990                 :            :     {"__setstate__", (PyCFunction)stringio_setstate, METH_O},
         991                 :            :     {NULL, NULL}        /* sentinel */
         992                 :            : };
         993                 :            :
         994                 :            : static PyGetSetDef stringio_getset[] = {
         995                 :            :     {"closed",         (getter)stringio_closed,         NULL, NULL},
         996                 :            :     {"newlines",       (getter)stringio_newlines,       NULL, NULL},
         997                 :            :     /*  (following comments straight off of the original Python wrapper:)
         998                 :            :         XXX Cruft to support the TextIOWrapper API. This would only
         999                 :            :         be meaningful if StringIO supported the buffer attribute.
        1000                 :            :         Hopefully, a better solution, than adding these pseudo-attributes,
        1001                 :            :         will be found.
        1002                 :            :     */
        1003                 :            :     {"line_buffering", (getter)stringio_line_buffering, NULL, NULL},
        1004                 :            :     {NULL}
        1005                 :            : };
        1006                 :            :
        1007                 :            : static struct PyMemberDef stringio_members[] = {
        1008                 :            :     {"__weaklistoffset__", T_PYSSIZET, offsetof(stringio, weakreflist), READONLY},
        1009                 :            :     {"__dictoffset__", T_PYSSIZET, offsetof(stringio, dict), READONLY},
        1010                 :            :     {NULL},
        1011                 :            : };
        1012                 :            :
        1013                 :            : static PyType_Slot stringio_slots[] = {
        1014                 :            :     {Py_tp_dealloc, stringio_dealloc},
        1015                 :            :     {Py_tp_doc, (void *)_io_StringIO___init____doc__},
        1016                 :            :     {Py_tp_traverse, stringio_traverse},
        1017                 :            :     {Py_tp_clear, stringio_clear},
        1018                 :            :     {Py_tp_iternext, stringio_iternext},
        1019                 :            :     {Py_tp_methods, stringio_methods},
        1020                 :            :     {Py_tp_members, stringio_members},
        1021                 :            :     {Py_tp_getset, stringio_getset},
        1022                 :            :     {Py_tp_init, _io_StringIO___init__},
        1023                 :            :     {Py_tp_new, stringio_new},
        1024                 :            :     {0, NULL},
        1025                 :            : };
        1026                 :            :
        1027                 :            : PyType_Spec stringio_spec = {
        1028                 :            :     .name = "_io.StringIO",
        1029                 :            :     .basicsize = sizeof(stringio),
        1030                 :            :     .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
        1031                 :            :               Py_TPFLAGS_IMMUTABLETYPE),
        1032                 :            :     .slots = stringio_slots,
        1033                 :            : };

Generated by: LCOV version 1.14