Home | History | Annotate | Download | only in _io
      1 #define PY_SSIZE_T_CLEAN
      2 #include "Python.h"
      3 #include "structmember.h"
      4 #include "_iomodule.h"
      5 
      6 /* Implementation note: the buffer is always at least one character longer
      7    than the enclosed string, for proper functioning of _PyIO_find_line_ending.
      8 */
      9 
     10 typedef struct {
     11     PyObject_HEAD
     12     Py_UNICODE *buf;
     13     Py_ssize_t pos;
     14     Py_ssize_t string_size;
     15     size_t buf_size;
     16 
     17     char ok; /* initialized? */
     18     char closed;
     19     char readuniversal;
     20     char readtranslate;
     21     PyObject *decoder;
     22     PyObject *readnl;
     23     PyObject *writenl;
     24 
     25     PyObject *dict;
     26     PyObject *weakreflist;
     27 } stringio;
     28 
     29 #define CHECK_INITIALIZED(self) \
     30     if (self->ok <= 0) { \
     31         PyErr_SetString(PyExc_ValueError, \
     32             "I/O operation on uninitialized object"); \
     33         return NULL; \
     34     }
     35 
     36 #define CHECK_CLOSED(self) \
     37     if (self->closed) { \
     38         PyErr_SetString(PyExc_ValueError, \
     39             "I/O operation on closed file"); \
     40         return NULL; \
     41     }
     42 
     43 PyDoc_STRVAR(stringio_doc,
     44     "Text I/O implementation using an in-memory buffer.\n"
     45     "\n"
     46     "The initial_value argument sets the value of object.  The newline\n"
     47     "argument is like the one of TextIOWrapper's constructor.");
     48 
     49 
     50 /* Internal routine for changing the size, in terms of characters, of the
     51    buffer of StringIO objects.  The caller should ensure that the 'size'
     52    argument is non-negative.  Returns 0 on success, -1 otherwise. */
     53 static int
     54 resize_buffer(stringio *self, size_t size)
     55 {
     56     /* Here, unsigned types are used to avoid dealing with signed integer
     57        overflow, which is undefined in C. */
     58     size_t alloc = self->buf_size;
     59     Py_UNICODE *new_buf = NULL;
     60 
     61     assert(self->buf != NULL);
     62 
     63     /* Reserve one more char for line ending detection. */
     64     size = size + 1;
     65     /* For simplicity, stay in the range of the signed type. Anyway, Python
     66        doesn't allow strings to be longer than this. */
     67     if (size > PY_SSIZE_T_MAX)
     68         goto overflow;
     69 
     70     if (size < alloc / 2) {
     71         /* Major downsize; resize down to exact size. */
     72         alloc = size + 1;
     73     }
     74     else if (size < alloc) {
     75         /* Within allocated size; quick exit */
     76         return 0;
     77     }
     78     else if (size <= alloc * 1.125) {
     79         /* Moderate upsize; overallocate similar to list_resize() */
     80         alloc = size + (size >> 3) + (size < 9 ? 3 : 6);
     81     }
     82     else {
     83         /* Major upsize; resize up to exact size */
     84         alloc = size + 1;
     85     }
     86 
     87     if (alloc > ((size_t)-1) / sizeof(Py_UNICODE))
     88         goto overflow;
     89     new_buf = (Py_UNICODE *)PyMem_Realloc(self->buf,
     90                                           alloc * sizeof(Py_UNICODE));
     91     if (new_buf == NULL) {
     92         PyErr_NoMemory();
     93         return -1;
     94     }
     95     self->buf_size = alloc;
     96     self->buf = new_buf;
     97 
     98     return 0;
     99 
    100   overflow:
    101     PyErr_SetString(PyExc_OverflowError,
    102                     "new buffer size too large");
    103     return -1;
    104 }
    105 
    106 /* Internal routine for writing a whole PyUnicode object to the buffer of a
    107    StringIO object. Returns 0 on success, or -1 on error. */
    108 static Py_ssize_t
    109 write_str(stringio *self, PyObject *obj)
    110 {
    111     Py_UNICODE *str;
    112     Py_ssize_t len;
    113     PyObject *decoded = NULL;
    114     assert(self->buf != NULL);
    115     assert(self->pos >= 0);
    116 
    117     if (self->decoder != NULL) {
    118         decoded = _PyIncrementalNewlineDecoder_decode(
    119             self->decoder, obj, 1 /* always final */);
    120     }
    121     else {
    122         decoded = obj;
    123         Py_INCREF(decoded);
    124     }
    125     if (self->writenl) {
    126         PyObject *translated = PyUnicode_Replace(
    127             decoded, _PyIO_str_nl, self->writenl, -1);
    128         Py_DECREF(decoded);
    129         decoded = translated;
    130     }
    131     if (decoded == NULL)
    132         return -1;
    133 
    134     assert(PyUnicode_Check(decoded));
    135     str = PyUnicode_AS_UNICODE(decoded);
    136     len = PyUnicode_GET_SIZE(decoded);
    137 
    138     assert(len >= 0);
    139 
    140     /* This overflow check is not strictly necessary. However, it avoids us to
    141        deal with funky things like comparing an unsigned and a signed
    142        integer. */
    143     if (self->pos > PY_SSIZE_T_MAX - len) {
    144         PyErr_SetString(PyExc_OverflowError,
    145                         "new position too large");
    146         goto fail;
    147     }
    148     if (self->pos + len > self->string_size) {
    149         if (resize_buffer(self, self->pos + len) < 0)
    150             goto fail;
    151     }
    152 
    153     if (self->pos > self->string_size) {
    154         /* In case of overseek, pad with null bytes the buffer region between
    155            the end of stream and the current position.
    156 
    157           0   lo      string_size                           hi
    158           |   |<---used--->|<----------available----------->|
    159           |   |            <--to pad-->|<---to write--->    |
    160           0   buf                   position
    161 
    162         */
    163         memset(self->buf + self->string_size, '\0',
    164                (self->pos - self->string_size) * sizeof(Py_UNICODE));
    165     }
    166 
    167     /* Copy the data to the internal buffer, overwriting some of the
    168        existing data if self->pos < self->string_size. */
    169     memcpy(self->buf + self->pos, str, len * sizeof(Py_UNICODE));
    170     self->pos += len;
    171 
    172     /* Set the new length of the internal string if it has changed. */
    173     if (self->string_size < self->pos) {
    174         self->string_size = self->pos;
    175     }
    176 
    177     Py_DECREF(decoded);
    178     return 0;
    179 
    180 fail:
    181     Py_XDECREF(decoded);
    182     return -1;
    183 }
    184 
    185 PyDoc_STRVAR(stringio_getvalue_doc,
    186     "Retrieve the entire contents of the object.");
    187 
    188 static PyObject *
    189 stringio_getvalue(stringio *self)
    190 {
    191     CHECK_INITIALIZED(self);
    192     CHECK_CLOSED(self);
    193     return PyUnicode_FromUnicode(self->buf, self->string_size);
    194 }
    195 
    196 PyDoc_STRVAR(stringio_tell_doc,
    197     "Tell the current file position.");
    198 
    199 static PyObject *
    200 stringio_tell(stringio *self)
    201 {
    202     CHECK_INITIALIZED(self);
    203     CHECK_CLOSED(self);
    204     return PyLong_FromSsize_t(self->pos);
    205 }
    206 
    207 PyDoc_STRVAR(stringio_read_doc,
    208     "Read at most n characters, returned as a string.\n"
    209     "\n"
    210     "If the argument is negative or omitted, read until EOF\n"
    211     "is reached. Return an empty string at EOF.\n");
    212 
    213 static PyObject *
    214 stringio_read(stringio *self, PyObject *args)
    215 {
    216     Py_ssize_t size, n;
    217     Py_UNICODE *output;
    218     PyObject *arg = Py_None;
    219 
    220     CHECK_INITIALIZED(self);
    221     if (!PyArg_ParseTuple(args, "|O:read", &arg))
    222         return NULL;
    223     CHECK_CLOSED(self);
    224 
    225     if (PyNumber_Check(arg)) {
    226         size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
    227         if (size == -1 && PyErr_Occurred())
    228             return NULL;
    229     }
    230     else if (arg == Py_None) {
    231         /* Read until EOF is reached, by default. */
    232         size = -1;
    233     }
    234     else {
    235         PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
    236                      Py_TYPE(arg)->tp_name);
    237         return NULL;
    238     }
    239 
    240     /* adjust invalid sizes */
    241     n = self->string_size - self->pos;
    242     if (size < 0 || size > n) {
    243         size = n;
    244         if (size < 0)
    245             size = 0;
    246     }
    247 
    248     output = self->buf + self->pos;
    249     self->pos += size;
    250     return PyUnicode_FromUnicode(output, size);
    251 }
    252 
    253 /* Internal helper, used by stringio_readline and stringio_iternext */
    254 static PyObject *
    255 _stringio_readline(stringio *self, Py_ssize_t limit)
    256 {
    257     Py_UNICODE *start, *end, old_char;
    258     Py_ssize_t len, consumed;
    259 
    260     /* In case of overseek, return the empty string */
    261     if (self->pos >= self->string_size)
    262         return PyUnicode_FromString("");
    263 
    264     start = self->buf + self->pos;
    265     if (limit < 0 || limit > self->string_size - self->pos)
    266         limit = self->string_size - self->pos;
    267 
    268     end = start + limit;
    269     old_char = *end;
    270     *end = '\0';
    271     len = _PyIO_find_line_ending(
    272         self->readtranslate, self->readuniversal, self->readnl,
    273         start, end, &consumed);
    274     *end = old_char;
    275     /* If we haven't found any line ending, we just return everything
    276        (`consumed` is ignored). */
    277     if (len < 0)
    278         len = limit;
    279     self->pos += len;
    280     return PyUnicode_FromUnicode(start, len);
    281 }
    282 
    283 PyDoc_STRVAR(stringio_readline_doc,
    284     "Read until newline or EOF.\n"
    285     "\n"
    286     "Returns an empty string if EOF is hit immediately.\n");
    287 
    288 static PyObject *
    289 stringio_readline(stringio *self, PyObject *args)
    290 {
    291     PyObject *arg = Py_None;
    292     Py_ssize_t limit = -1;
    293 
    294     CHECK_INITIALIZED(self);
    295     if (!PyArg_ParseTuple(args, "|O:readline", &arg))
    296         return NULL;
    297     CHECK_CLOSED(self);
    298 
    299     if (PyNumber_Check(arg)) {
    300         limit = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
    301         if (limit == -1 && PyErr_Occurred())
    302             return NULL;
    303     }
    304     else if (arg != Py_None) {
    305         PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
    306                      Py_TYPE(arg)->tp_name);
    307         return NULL;
    308     }
    309     return _stringio_readline(self, limit);
    310 }
    311 
    312 static PyObject *
    313 stringio_iternext(stringio *self)
    314 {
    315     PyObject *line;
    316 
    317     CHECK_INITIALIZED(self);
    318     CHECK_CLOSED(self);
    319 
    320     if (Py_TYPE(self) == &PyStringIO_Type) {
    321         /* Skip method call overhead for speed */
    322         line = _stringio_readline(self, -1);
    323     }
    324     else {
    325         /* XXX is subclassing StringIO really supported? */
    326         line = PyObject_CallMethodObjArgs((PyObject *)self,
    327                                            _PyIO_str_readline, NULL);
    328         if (line && !PyUnicode_Check(line)) {
    329             PyErr_Format(PyExc_IOError,
    330                          "readline() should have returned an str object, "
    331                          "not '%.200s'", Py_TYPE(line)->tp_name);
    332             Py_DECREF(line);
    333             return NULL;
    334         }
    335     }
    336 
    337     if (line == NULL)
    338         return NULL;
    339 
    340     if (PyUnicode_GET_SIZE(line) == 0) {
    341         /* Reached EOF */
    342         Py_DECREF(line);
    343         return NULL;
    344     }
    345 
    346     return line;
    347 }
    348 
    349 PyDoc_STRVAR(stringio_truncate_doc,
    350     "Truncate size to pos.\n"
    351     "\n"
    352     "The pos argument defaults to the current file position, as\n"
    353     "returned by tell().  The current file position is unchanged.\n"
    354     "Returns the new absolute position.\n");
    355 
    356 static PyObject *
    357 stringio_truncate(stringio *self, PyObject *args)
    358 {
    359     Py_ssize_t size;
    360     PyObject *arg = Py_None;
    361 
    362     CHECK_INITIALIZED(self);
    363     if (!PyArg_ParseTuple(args, "|O:truncate", &arg))
    364         return NULL;
    365     CHECK_CLOSED(self);
    366 
    367     if (PyNumber_Check(arg)) {
    368         size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
    369         if (size == -1 && PyErr_Occurred())
    370             return NULL;
    371     }
    372     else if (arg == Py_None) {
    373         /* Truncate to current position if no argument is passed. */
    374         size = self->pos;
    375     }
    376     else {
    377         PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
    378                      Py_TYPE(arg)->tp_name);
    379         return NULL;
    380     }
    381 
    382     if (size < 0) {
    383         PyErr_Format(PyExc_ValueError,
    384                      "Negative size value %zd", size);
    385         return NULL;
    386     }
    387 
    388     if (size < self->string_size) {
    389         if (resize_buffer(self, size) < 0)
    390             return NULL;
    391         self->string_size = size;
    392     }
    393 
    394     return PyLong_FromSsize_t(size);
    395 }
    396 
    397 PyDoc_STRVAR(stringio_seek_doc,
    398     "Change stream position.\n"
    399     "\n"
    400     "Seek to character offset pos relative to position indicated by whence:\n"
    401     "    0  Start of stream (the default).  pos should be >= 0;\n"
    402     "    1  Current position - pos must be 0;\n"
    403     "    2  End of stream - pos must be 0.\n"
    404     "Returns the new absolute position.\n");
    405 
    406 static PyObject *
    407 stringio_seek(stringio *self, PyObject *args)
    408 {
    409     PyObject *posobj;
    410     Py_ssize_t pos;
    411     int mode = 0;
    412 
    413     CHECK_INITIALIZED(self);
    414     if (!PyArg_ParseTuple(args, "O|i:seek", &posobj, &mode))
    415         return NULL;
    416 
    417     pos = PyNumber_AsSsize_t(posobj, PyExc_OverflowError);
    418     if (pos == -1 && PyErr_Occurred())
    419         return NULL;
    420 
    421     CHECK_CLOSED(self);
    422 
    423     if (mode != 0 && mode != 1 && mode != 2) {
    424         PyErr_Format(PyExc_ValueError,
    425                      "Invalid whence (%i, should be 0, 1 or 2)", mode);
    426         return NULL;
    427     }
    428     else if (pos < 0 && mode == 0) {
    429         PyErr_Format(PyExc_ValueError,
    430                      "Negative seek position %zd", pos);
    431         return NULL;
    432     }
    433     else if (mode != 0 && pos != 0) {
    434         PyErr_SetString(PyExc_IOError,
    435                         "Can't do nonzero cur-relative seeks");
    436         return NULL;
    437     }
    438 
    439     /* mode 0: offset relative to beginning of the string.
    440        mode 1: no change to current position.
    441        mode 2: change position to end of file. */
    442     if (mode == 1) {
    443         pos = self->pos;
    444     }
    445     else if (mode == 2) {
    446         pos = self->string_size;
    447     }
    448 
    449     self->pos = pos;
    450 
    451     return PyLong_FromSsize_t(self->pos);
    452 }
    453 
    454 PyDoc_STRVAR(stringio_write_doc,
    455     "Write string to file.\n"
    456     "\n"
    457     "Returns the number of characters written, which is always equal to\n"
    458     "the length of the string.\n");
    459 
    460 static PyObject *
    461 stringio_write(stringio *self, PyObject *obj)
    462 {
    463     Py_ssize_t size;
    464 
    465     CHECK_INITIALIZED(self);
    466     if (!PyUnicode_Check(obj)) {
    467         PyErr_Format(PyExc_TypeError, "unicode argument expected, got '%s'",
    468                      Py_TYPE(obj)->tp_name);
    469         return NULL;
    470     }
    471     CHECK_CLOSED(self);
    472     size = PyUnicode_GET_SIZE(obj);
    473 
    474     if (size > 0 && write_str(self, obj) < 0)
    475         return NULL;
    476 
    477     return PyLong_FromSsize_t(size);
    478 }
    479 
    480 PyDoc_STRVAR(stringio_close_doc,
    481     "Close the IO object. Attempting any further operation after the\n"
    482     "object is closed will raise a ValueError.\n"
    483     "\n"
    484     "This method has no effect if the file is already closed.\n");
    485 
    486 static PyObject *
    487 stringio_close(stringio *self)
    488 {
    489     self->closed = 1;
    490     /* Free up some memory */
    491     if (resize_buffer(self, 0) < 0)
    492         return NULL;
    493     Py_CLEAR(self->readnl);
    494     Py_CLEAR(self->writenl);
    495     Py_CLEAR(self->decoder);
    496     Py_RETURN_NONE;
    497 }
    498 
    499 static int
    500 stringio_traverse(stringio *self, visitproc visit, void *arg)
    501 {
    502     Py_VISIT(self->dict);
    503     return 0;
    504 }
    505 
    506 static int
    507 stringio_clear(stringio *self)
    508 {
    509     Py_CLEAR(self->dict);
    510     return 0;
    511 }
    512 
    513 static void
    514 stringio_dealloc(stringio *self)
    515 {
    516     _PyObject_GC_UNTRACK(self);
    517     self->ok = 0;
    518     if (self->buf) {
    519         PyMem_Free(self->buf);
    520         self->buf = NULL;
    521     }
    522     Py_CLEAR(self->readnl);
    523     Py_CLEAR(self->writenl);
    524     Py_CLEAR(self->decoder);
    525     Py_CLEAR(self->dict);
    526     if (self->weakreflist != NULL)
    527         PyObject_ClearWeakRefs((PyObject *) self);
    528     Py_TYPE(self)->tp_free(self);
    529 }
    530 
    531 static PyObject *
    532 stringio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
    533 {
    534     stringio *self;
    535 
    536     assert(type != NULL && type->tp_alloc != NULL);
    537     self = (stringio *)type->tp_alloc(type, 0);
    538     if (self == NULL)
    539         return NULL;
    540 
    541     /* tp_alloc initializes all the fields to zero. So we don't have to
    542        initialize them here. */
    543 
    544     self->buf = (Py_UNICODE *)PyMem_Malloc(0);
    545     if (self->buf == NULL) {
    546         Py_DECREF(self);
    547         return PyErr_NoMemory();
    548     }
    549 
    550     return (PyObject *)self;
    551 }
    552 
    553 static int
    554 stringio_init(stringio *self, PyObject *args, PyObject *kwds)
    555 {
    556     char *kwlist[] = {"initial_value", "newline", NULL};
    557     PyObject *value = NULL;
    558     char *newline = "\n";
    559 
    560     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oz:__init__", kwlist,
    561                                      &value, &newline))
    562         return -1;
    563 
    564     if (newline && newline[0] != '\0'
    565         && !(newline[0] == '\n' && newline[1] == '\0')
    566         && !(newline[0] == '\r' && newline[1] == '\0')
    567         && !(newline[0] == '\r' && newline[1] == '\n' && newline[2] == '\0')) {
    568         PyErr_Format(PyExc_ValueError,
    569                      "illegal newline value: %s", newline);
    570         return -1;
    571     }
    572     if (value && value != Py_None && !PyUnicode_Check(value)) {
    573         PyErr_Format(PyExc_TypeError,
    574                      "initial_value must be unicode or None, not %.200s",
    575                      Py_TYPE(value)->tp_name);
    576         return -1;
    577     }
    578 
    579     self->ok = 0;
    580 
    581     Py_CLEAR(self->readnl);
    582     Py_CLEAR(self->writenl);
    583     Py_CLEAR(self->decoder);
    584 
    585     if (newline) {
    586         self->readnl = PyString_FromString(newline);
    587         if (self->readnl == NULL)
    588             return -1;
    589     }
    590     self->readuniversal = (newline == NULL || newline[0] == '\0');
    591     self->readtranslate = (newline == NULL);
    592     /* If newline == "", we don't translate anything.
    593        If newline == "\n" or newline == None, we translate to "\n", which is
    594        a no-op.
    595        (for newline == None, TextIOWrapper translates to os.sepline, but it
    596        is pointless for StringIO)
    597     */
    598     if (newline != NULL && newline[0] == '\r') {
    599         self->writenl = PyUnicode_FromString(newline);
    600     }
    601 
    602     if (self->readuniversal) {
    603         self->decoder = PyObject_CallFunction(
    604             (PyObject *)&PyIncrementalNewlineDecoder_Type,
    605             "Oi", Py_None, (int) self->readtranslate);
    606         if (self->decoder == NULL)
    607             return -1;
    608     }
    609 
    610     /* Now everything is set up, resize buffer to size of initial value,
    611        and copy it */
    612     self->string_size = 0;
    613     if (value && value != Py_None) {
    614         Py_ssize_t len = PyUnicode_GetSize(value);
    615         /* This is a heuristic, for newline translation might change
    616            the string length. */
    617         if (resize_buffer(self, len) < 0)
    618             return -1;
    619         self->pos = 0;
    620         if (write_str(self, value) < 0)
    621             return -1;
    622     }
    623     else {
    624         if (resize_buffer(self, 0) < 0)
    625             return -1;
    626     }
    627     self->pos = 0;
    628 
    629     self->closed = 0;
    630     self->ok = 1;
    631     return 0;
    632 }
    633 
    634 /* Properties and pseudo-properties */
    635 
    636 PyDoc_STRVAR(stringio_readable_doc,
    637 "readable() -> bool. Returns True if the IO object can be read.");
    638 
    639 PyDoc_STRVAR(stringio_writable_doc,
    640 "writable() -> bool. Returns True if the IO object can be written.");
    641 
    642 PyDoc_STRVAR(stringio_seekable_doc,
    643 "seekable() -> bool. Returns True if the IO object can be seeked.");
    644 
    645 static PyObject *
    646 stringio_seekable(stringio *self, PyObject *args)
    647 {
    648     CHECK_INITIALIZED(self);
    649     CHECK_CLOSED(self);
    650     Py_RETURN_TRUE;
    651 }
    652 
    653 static PyObject *
    654 stringio_readable(stringio *self, PyObject *args)
    655 {
    656     CHECK_INITIALIZED(self);
    657     CHECK_CLOSED(self);
    658     Py_RETURN_TRUE;
    659 }
    660 
    661 static PyObject *
    662 stringio_writable(stringio *self, PyObject *args)
    663 {
    664     CHECK_INITIALIZED(self);
    665     CHECK_CLOSED(self);
    666     Py_RETURN_TRUE;
    667 }
    668 
    669 /* Pickling support.
    670 
    671    The implementation of __getstate__ is similar to the one for BytesIO,
    672    except that we also save the newline parameter. For __setstate__ and unlike
    673    BytesIO, we call __init__ to restore the object's state. Doing so allows us
    674    to avoid decoding the complex newline state while keeping the object
    675    representation compact.
    676 
    677    See comment in bytesio.c regarding why only pickle protocols and onward are
    678    supported.
    679 */
    680 
    681 static PyObject *
    682 stringio_getstate(stringio *self)
    683 {
    684     PyObject *initvalue = stringio_getvalue(self);
    685     PyObject *dict;
    686     PyObject *state;
    687 
    688     if (initvalue == NULL)
    689         return NULL;
    690     if (self->dict == NULL) {
    691         Py_INCREF(Py_None);
    692         dict = Py_None;
    693     }
    694     else {
    695         dict = PyDict_Copy(self->dict);
    696         if (dict == NULL)
    697             return NULL;
    698     }
    699 
    700     state = Py_BuildValue("(OOnN)", initvalue,
    701                           self->readnl ? self->readnl : Py_None,
    702                           self->pos, dict);
    703     Py_DECREF(initvalue);
    704     return state;
    705 }
    706 
    707 static PyObject *
    708 stringio_setstate(stringio *self, PyObject *state)
    709 {
    710     PyObject *initarg;
    711     PyObject *position_obj;
    712     PyObject *dict;
    713     Py_ssize_t pos;
    714 
    715     assert(state != NULL);
    716     CHECK_CLOSED(self);
    717 
    718     /* We allow the state tuple to be longer than 4, because we may need
    719        someday to extend the object's state without breaking
    720        backward-compatibility. */
    721     if (!PyTuple_Check(state) || Py_SIZE(state) < 4) {
    722         PyErr_Format(PyExc_TypeError,
    723                      "%.200s.__setstate__ argument should be 4-tuple, got %.200s",
    724                      Py_TYPE(self)->tp_name, Py_TYPE(state)->tp_name);
    725         return NULL;
    726     }
    727 
    728     /* Initialize the object's state. */
    729     initarg = PyTuple_GetSlice(state, 0, 2);
    730     if (initarg == NULL)
    731         return NULL;
    732     if (stringio_init(self, initarg, NULL) < 0) {
    733         Py_DECREF(initarg);
    734         return NULL;
    735     }
    736     Py_DECREF(initarg);
    737 
    738     /* Restore the buffer state. Even if __init__ did initialize the buffer,
    739        we have to initialize it again since __init__ may translate the
    740        newlines in the initial_value string. We clearly do not want that
    741        because the string value in the state tuple has already been translated
    742        once by __init__. So we do not take any chance and replace object's
    743        buffer completely. */
    744     {
    745         Py_UNICODE *buf = PyUnicode_AS_UNICODE(PyTuple_GET_ITEM(state, 0));
    746         Py_ssize_t bufsize = PyUnicode_GET_SIZE(PyTuple_GET_ITEM(state, 0));
    747         if (resize_buffer(self, bufsize) < 0)
    748             return NULL;
    749         memcpy(self->buf, buf, bufsize * sizeof(Py_UNICODE));
    750         self->string_size = bufsize;
    751     }
    752 
    753     /* Set carefully the position value. Alternatively, we could use the seek
    754        method instead of modifying self->pos directly to better protect the
    755        object internal state against errneous (or malicious) inputs. */
    756     position_obj = PyTuple_GET_ITEM(state, 2);
    757     if (!PyIndex_Check(position_obj)) {
    758         PyErr_Format(PyExc_TypeError,
    759                      "third item of state must be an integer, got %.200s",
    760                      Py_TYPE(position_obj)->tp_name);
    761         return NULL;
    762     }
    763     pos = PyNumber_AsSsize_t(position_obj, PyExc_OverflowError);
    764     if (pos == -1 && PyErr_Occurred())
    765         return NULL;
    766     if (pos < 0) {
    767         PyErr_SetString(PyExc_ValueError,
    768                         "position value cannot be negative");
    769         return NULL;
    770     }
    771     self->pos = pos;
    772 
    773     /* Set the dictionary of the instance variables. */
    774     dict = PyTuple_GET_ITEM(state, 3);
    775     if (dict != Py_None) {
    776         if (!PyDict_Check(dict)) {
    777             PyErr_Format(PyExc_TypeError,
    778                          "fourth item of state should be a dict, got a %.200s",
    779                          Py_TYPE(dict)->tp_name);
    780             return NULL;
    781         }
    782         if (self->dict) {
    783             /* Alternatively, we could replace the internal dictionary
    784                completely. However, it seems more practical to just update it. */
    785             if (PyDict_Update(self->dict, dict) < 0)
    786                 return NULL;
    787         }
    788         else {
    789             Py_INCREF(dict);
    790             self->dict = dict;
    791         }
    792     }
    793 
    794     Py_RETURN_NONE;
    795 }
    796 
    797 
    798 static PyObject *
    799 stringio_closed(stringio *self, void *context)
    800 {
    801     CHECK_INITIALIZED(self);
    802     return PyBool_FromLong(self->closed);
    803 }
    804 
    805 static PyObject *
    806 stringio_line_buffering(stringio *self, void *context)
    807 {
    808     CHECK_INITIALIZED(self);
    809     CHECK_CLOSED(self);
    810     Py_RETURN_FALSE;
    811 }
    812 
    813 static PyObject *
    814 stringio_newlines(stringio *self, void *context)
    815 {
    816     CHECK_INITIALIZED(self);
    817     CHECK_CLOSED(self);
    818     if (self->decoder == NULL)
    819         Py_RETURN_NONE;
    820     return PyObject_GetAttr(self->decoder, _PyIO_str_newlines);
    821 }
    822 
    823 static struct PyMethodDef stringio_methods[] = {
    824     {"close",    (PyCFunction)stringio_close,    METH_NOARGS,  stringio_close_doc},
    825     {"getvalue", (PyCFunction)stringio_getvalue, METH_NOARGS,  stringio_getvalue_doc},
    826     {"read",     (PyCFunction)stringio_read,     METH_VARARGS, stringio_read_doc},
    827     {"readline", (PyCFunction)stringio_readline, METH_VARARGS, stringio_readline_doc},
    828     {"tell",     (PyCFunction)stringio_tell,     METH_NOARGS,  stringio_tell_doc},
    829     {"truncate", (PyCFunction)stringio_truncate, METH_VARARGS, stringio_truncate_doc},
    830     {"seek",     (PyCFunction)stringio_seek,     METH_VARARGS, stringio_seek_doc},
    831     {"write",    (PyCFunction)stringio_write,    METH_O,       stringio_write_doc},
    832 
    833     {"seekable", (PyCFunction)stringio_seekable, METH_NOARGS, stringio_seekable_doc},
    834     {"readable", (PyCFunction)stringio_readable, METH_NOARGS, stringio_readable_doc},
    835     {"writable", (PyCFunction)stringio_writable, METH_NOARGS, stringio_writable_doc},
    836 
    837     {"__getstate__", (PyCFunction)stringio_getstate, METH_NOARGS},
    838     {"__setstate__", (PyCFunction)stringio_setstate, METH_O},
    839     {NULL, NULL}        /* sentinel */
    840 };
    841 
    842 static PyGetSetDef stringio_getset[] = {
    843     {"closed",         (getter)stringio_closed,         NULL, NULL},
    844     {"newlines",       (getter)stringio_newlines,       NULL, NULL},
    845     /*  (following comments straight off of the original Python wrapper:)
    846         XXX Cruft to support the TextIOWrapper API. This would only
    847         be meaningful if StringIO supported the buffer attribute.
    848         Hopefully, a better solution, than adding these pseudo-attributes,
    849         will be found.
    850     */
    851     {"line_buffering", (getter)stringio_line_buffering, NULL, NULL},
    852     {NULL}
    853 };
    854 
    855 PyTypeObject PyStringIO_Type = {
    856     PyVarObject_HEAD_INIT(NULL, 0)
    857     "_io.StringIO",                            /*tp_name*/
    858     sizeof(stringio),                    /*tp_basicsize*/
    859     0,                                         /*tp_itemsize*/
    860     (destructor)stringio_dealloc,              /*tp_dealloc*/
    861     0,                                         /*tp_print*/
    862     0,                                         /*tp_getattr*/
    863     0,                                         /*tp_setattr*/
    864     0,                                         /*tp_reserved*/
    865     0,                                         /*tp_repr*/
    866     0,                                         /*tp_as_number*/
    867     0,                                         /*tp_as_sequence*/
    868     0,                                         /*tp_as_mapping*/
    869     0,                                         /*tp_hash*/
    870     0,                                         /*tp_call*/
    871     0,                                         /*tp_str*/
    872     0,                                         /*tp_getattro*/
    873     0,                                         /*tp_setattro*/
    874     0,                                         /*tp_as_buffer*/
    875     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
    876                        | Py_TPFLAGS_HAVE_GC,   /*tp_flags*/
    877     stringio_doc,                              /*tp_doc*/
    878     (traverseproc)stringio_traverse,           /*tp_traverse*/
    879     (inquiry)stringio_clear,                   /*tp_clear*/
    880     0,                                         /*tp_richcompare*/
    881     offsetof(stringio, weakreflist),            /*tp_weaklistoffset*/
    882     0,                                         /*tp_iter*/
    883     (iternextfunc)stringio_iternext,           /*tp_iternext*/
    884     stringio_methods,                          /*tp_methods*/
    885     0,                                         /*tp_members*/
    886     stringio_getset,                           /*tp_getset*/
    887     0,                                         /*tp_base*/
    888     0,                                         /*tp_dict*/
    889     0,                                         /*tp_descr_get*/
    890     0,                                         /*tp_descr_set*/
    891     offsetof(stringio, dict),                  /*tp_dictoffset*/
    892     (initproc)stringio_init,                   /*tp_init*/
    893     0,                                         /*tp_alloc*/
    894     stringio_new,                              /*tp_new*/
    895 };
    896