17eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#define PY_SSIZE_T_CLEAN
27eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#include "Python.h"
37eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#include "structmember.h"
47eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#include "_iomodule.h"
57eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
67eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel/* Implementation note: the buffer is always at least one character longer
77eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel   than the enclosed string, for proper functioning of _PyIO_find_line_ending.
87eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel*/
97eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanieltypedef struct {
117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject_HEAD
127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_UNICODE *buf;
137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t pos;
147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t string_size;
157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    size_t buf_size;
167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    char ok; /* initialized? */
187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    char closed;
197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    char readuniversal;
207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    char readtranslate;
217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *decoder;
227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *readnl;
237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *writenl;
247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *dict;
267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *weakreflist;
277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel} stringio;
287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#define CHECK_INITIALIZED(self) \
307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (self->ok <= 0) { \
317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_SetString(PyExc_ValueError, \
327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            "I/O operation on uninitialized object"); \
337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL; \
347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#define CHECK_CLOSED(self) \
377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (self->closed) { \
387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_SetString(PyExc_ValueError, \
397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            "I/O operation on closed file"); \
407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL; \
417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielPyDoc_STRVAR(stringio_doc,
447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "Text I/O implementation using an in-memory buffer.\n"
457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "\n"
467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "The initial_value argument sets the value of object.  The newline\n"
477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "argument is like the one of TextIOWrapper's constructor.");
487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel/* Internal routine for changing the size, in terms of characters, of the
517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel   buffer of StringIO objects.  The caller should ensure that the 'size'
527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel   argument is non-negative.  Returns 0 on success, -1 otherwise. */
537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielresize_buffer(stringio *self, size_t size)
557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Here, unsigned types are used to avoid dealing with signed integer
577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       overflow, which is undefined in C. */
587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    size_t alloc = self->buf_size;
597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_UNICODE *new_buf = NULL;
607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    assert(self->buf != NULL);
627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Reserve one more char for line ending detection. */
647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    size = size + 1;
657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* For simplicity, stay in the range of the signed type. Anyway, Python
667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       doesn't allow strings to be longer than this. */
677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (size > PY_SSIZE_T_MAX)
687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto overflow;
697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (size < alloc / 2) {
717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* Major downsize; resize down to exact size. */
727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        alloc = size + 1;
737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else if (size < alloc) {
757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* Within allocated size; quick exit */
767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return 0;
777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else if (size <= alloc * 1.125) {
797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* Moderate upsize; overallocate similar to list_resize() */
807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        alloc = size + (size >> 3) + (size < 9 ? 3 : 6);
817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else {
837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* Major upsize; resize up to exact size */
847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        alloc = size + 1;
857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (alloc > ((size_t)-1) / sizeof(Py_UNICODE))
887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto overflow;
897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    new_buf = (Py_UNICODE *)PyMem_Realloc(self->buf,
907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                                          alloc * sizeof(Py_UNICODE));
917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (new_buf == NULL) {
927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_NoMemory();
937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return -1;
947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    self->buf_size = alloc;
967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    self->buf = new_buf;
977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return 0;
997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel  overflow:
1017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyErr_SetString(PyExc_OverflowError,
1027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    "new buffer size too large");
1037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return -1;
1047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
1057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel/* Internal routine for writing a whole PyUnicode object to the buffer of a
1077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel   StringIO object. Returns 0 on success, or -1 on error. */
1087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic Py_ssize_t
1097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielwrite_str(stringio *self, PyObject *obj)
1107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
1117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_UNICODE *str;
1127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t len;
1137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *decoded = NULL;
1147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    assert(self->buf != NULL);
1157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    assert(self->pos >= 0);
1167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (self->decoder != NULL) {
1187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        decoded = _PyIncrementalNewlineDecoder_decode(
1197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            self->decoder, obj, 1 /* always final */);
1207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
1217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else {
1227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        decoded = obj;
1237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_INCREF(decoded);
1247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
1257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (self->writenl) {
1267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyObject *translated = PyUnicode_Replace(
1277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            decoded, _PyIO_str_nl, self->writenl, -1);
1287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(decoded);
1297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        decoded = translated;
1307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
1317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (decoded == NULL)
1327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return -1;
1337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    assert(PyUnicode_Check(decoded));
1357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    str = PyUnicode_AS_UNICODE(decoded);
1367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    len = PyUnicode_GET_SIZE(decoded);
1377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    assert(len >= 0);
1397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* This overflow check is not strictly necessary. However, it avoids us to
1417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       deal with funky things like comparing an unsigned and a signed
1427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       integer. */
1437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (self->pos > PY_SSIZE_T_MAX - len) {
1447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_SetString(PyExc_OverflowError,
1457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        "new position too large");
1467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto fail;
1477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
1487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (self->pos + len > self->string_size) {
1497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (resize_buffer(self, self->pos + len) < 0)
1507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto fail;
1517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
1527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (self->pos > self->string_size) {
1547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* In case of overseek, pad with null bytes the buffer region between
1557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel           the end of stream and the current position.
1567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel          0   lo      string_size                           hi
1587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel          |   |<---used--->|<----------available----------->|
1597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel          |   |            <--to pad-->|<---to write--->    |
1607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel          0   buf                   position
1617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        */
1637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        memset(self->buf + self->string_size, '\0',
1647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel               (self->pos - self->string_size) * sizeof(Py_UNICODE));
1657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
1667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Copy the data to the internal buffer, overwriting some of the
1687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       existing data if self->pos < self->string_size. */
1697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    memcpy(self->buf + self->pos, str, len * sizeof(Py_UNICODE));
1707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    self->pos += len;
1717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Set the new length of the internal string if it has changed. */
1737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (self->string_size < self->pos) {
1747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        self->string_size = self->pos;
1757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
1767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_DECREF(decoded);
1787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return 0;
1797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielfail:
1817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_XDECREF(decoded);
1827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return -1;
1837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
1847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielPyDoc_STRVAR(stringio_getvalue_doc,
1867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "Retrieve the entire contents of the object.");
1877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
1897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstringio_getvalue(stringio *self)
1907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
1917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_INITIALIZED(self);
1927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_CLOSED(self);
1937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return PyUnicode_FromUnicode(self->buf, self->string_size);
1947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
1957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielPyDoc_STRVAR(stringio_tell_doc,
1977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "Tell the current file position.");
1987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
2007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstringio_tell(stringio *self)
2017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
2027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_INITIALIZED(self);
2037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_CLOSED(self);
2047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return PyLong_FromSsize_t(self->pos);
2057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
2067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
2077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielPyDoc_STRVAR(stringio_read_doc,
2087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "Read at most n characters, returned as a string.\n"
2097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "\n"
2107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "If the argument is negative or omitted, read until EOF\n"
2117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "is reached. Return an empty string at EOF.\n");
2127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
2137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
2147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstringio_read(stringio *self, PyObject *args)
2157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
2167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t size, n;
2177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_UNICODE *output;
2187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *arg = Py_None;
2197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
2207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_INITIALIZED(self);
2217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (!PyArg_ParseTuple(args, "|O:read", &arg))
2227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
2237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_CLOSED(self);
2247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
2257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (PyNumber_Check(arg)) {
2267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
2277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (size == -1 && PyErr_Occurred())
2287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return NULL;
2297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
2307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else if (arg == Py_None) {
2317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* Read until EOF is reached, by default. */
2327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        size = -1;
2337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
2347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else {
2357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
2367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                     Py_TYPE(arg)->tp_name);
2377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
2387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
2397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
2407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* adjust invalid sizes */
2417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    n = self->string_size - self->pos;
2427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (size < 0 || size > n) {
2437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        size = n;
2447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (size < 0)
2457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            size = 0;
2467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
2477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
2487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    output = self->buf + self->pos;
2497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    self->pos += size;
2507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return PyUnicode_FromUnicode(output, size);
2517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
2527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
2537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel/* Internal helper, used by stringio_readline and stringio_iternext */
2547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
2557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel_stringio_readline(stringio *self, Py_ssize_t limit)
2567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
2577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_UNICODE *start, *end, old_char;
2587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t len, consumed;
2597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
2607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* In case of overseek, return the empty string */
2617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (self->pos >= self->string_size)
2627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return PyUnicode_FromString("");
2637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
2647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    start = self->buf + self->pos;
2657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (limit < 0 || limit > self->string_size - self->pos)
2667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        limit = self->string_size - self->pos;
2677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
2687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    end = start + limit;
2697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    old_char = *end;
2707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *end = '\0';
2717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    len = _PyIO_find_line_ending(
2727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        self->readtranslate, self->readuniversal, self->readnl,
2737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        start, end, &consumed);
2747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *end = old_char;
2757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* If we haven't found any line ending, we just return everything
2767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       (`consumed` is ignored). */
2777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (len < 0)
2787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        len = limit;
2797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    self->pos += len;
2807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return PyUnicode_FromUnicode(start, len);
2817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
2827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
2837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielPyDoc_STRVAR(stringio_readline_doc,
2847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "Read until newline or EOF.\n"
2857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "\n"
2867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "Returns an empty string if EOF is hit immediately.\n");
2877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
2887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
2897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstringio_readline(stringio *self, PyObject *args)
2907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
2917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *arg = Py_None;
2927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t limit = -1;
2937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
2947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_INITIALIZED(self);
2957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (!PyArg_ParseTuple(args, "|O:readline", &arg))
2967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
2977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_CLOSED(self);
2987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
2997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (PyNumber_Check(arg)) {
3007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        limit = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
3017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (limit == -1 && PyErr_Occurred())
3027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return NULL;
3037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
3047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else if (arg != Py_None) {
3057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
3067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                     Py_TYPE(arg)->tp_name);
3077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
3087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
3097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return _stringio_readline(self, limit);
3107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
3117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
3127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
3137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstringio_iternext(stringio *self)
3147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
3157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *line;
3167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
3177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_INITIALIZED(self);
3187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_CLOSED(self);
3197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
3207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (Py_TYPE(self) == &PyStringIO_Type) {
3217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* Skip method call overhead for speed */
3227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        line = _stringio_readline(self, -1);
3237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
3247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else {
3257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* XXX is subclassing StringIO really supported? */
3267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        line = PyObject_CallMethodObjArgs((PyObject *)self,
3277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                                           _PyIO_str_readline, NULL);
3287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (line && !PyUnicode_Check(line)) {
3297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            PyErr_Format(PyExc_IOError,
3307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                         "readline() should have returned an str object, "
3317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                         "not '%.200s'", Py_TYPE(line)->tp_name);
3327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_DECREF(line);
3337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return NULL;
3347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
3357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
3367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
3377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (line == NULL)
3387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
3397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
3407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (PyUnicode_GET_SIZE(line) == 0) {
3417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* Reached EOF */
3427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(line);
3437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
3447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
3457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
3467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return line;
3477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
3487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
3497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielPyDoc_STRVAR(stringio_truncate_doc,
3507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "Truncate size to pos.\n"
3517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "\n"
3527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "The pos argument defaults to the current file position, as\n"
3537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "returned by tell().  The current file position is unchanged.\n"
3547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "Returns the new absolute position.\n");
3557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
3567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
3577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstringio_truncate(stringio *self, PyObject *args)
3587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
3597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t size;
3607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *arg = Py_None;
3617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
3627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_INITIALIZED(self);
3637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (!PyArg_ParseTuple(args, "|O:truncate", &arg))
3647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
3657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_CLOSED(self);
3667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
3677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (PyNumber_Check(arg)) {
3687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
3697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (size == -1 && PyErr_Occurred())
3707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return NULL;
3717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
3727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else if (arg == Py_None) {
3737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* Truncate to current position if no argument is passed. */
3747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        size = self->pos;
3757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
3767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else {
3777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
3787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                     Py_TYPE(arg)->tp_name);
3797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
3807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
3817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
3827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (size < 0) {
3837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_Format(PyExc_ValueError,
3847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                     "Negative size value %zd", size);
3857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
3867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
3877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
3887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (size < self->string_size) {
3897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (resize_buffer(self, size) < 0)
3907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return NULL;
3917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        self->string_size = size;
3927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
3937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
3947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return PyLong_FromSsize_t(size);
3957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
3967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
3977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielPyDoc_STRVAR(stringio_seek_doc,
3987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "Change stream position.\n"
3997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "\n"
4007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "Seek to character offset pos relative to position indicated by whence:\n"
4017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "    0  Start of stream (the default).  pos should be >= 0;\n"
4027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "    1  Current position - pos must be 0;\n"
4037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "    2  End of stream - pos must be 0.\n"
4047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "Returns the new absolute position.\n");
4057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
4067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
4077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstringio_seek(stringio *self, PyObject *args)
4087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
4097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *posobj;
4107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t pos;
4117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    int mode = 0;
4127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
4137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_INITIALIZED(self);
4147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (!PyArg_ParseTuple(args, "O|i:seek", &posobj, &mode))
4157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
4167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
4177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    pos = PyNumber_AsSsize_t(posobj, PyExc_OverflowError);
4187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (pos == -1 && PyErr_Occurred())
4197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
4207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
4217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_CLOSED(self);
4227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
4237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (mode != 0 && mode != 1 && mode != 2) {
4247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_Format(PyExc_ValueError,
4257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                     "Invalid whence (%i, should be 0, 1 or 2)", mode);
4267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
4277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
4287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else if (pos < 0 && mode == 0) {
4297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_Format(PyExc_ValueError,
4307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                     "Negative seek position %zd", pos);
4317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
4327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
4337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else if (mode != 0 && pos != 0) {
4347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_SetString(PyExc_IOError,
4357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        "Can't do nonzero cur-relative seeks");
4367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
4377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
4387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
4397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* mode 0: offset relative to beginning of the string.
4407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       mode 1: no change to current position.
4417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       mode 2: change position to end of file. */
4427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (mode == 1) {
4437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        pos = self->pos;
4447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
4457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else if (mode == 2) {
4467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        pos = self->string_size;
4477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
4487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
4497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    self->pos = pos;
4507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
4517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return PyLong_FromSsize_t(self->pos);
4527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
4537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
4547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielPyDoc_STRVAR(stringio_write_doc,
4557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "Write string to file.\n"
4567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "\n"
4577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "Returns the number of characters written, which is always equal to\n"
4587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "the length of the string.\n");
4597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
4607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
4617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstringio_write(stringio *self, PyObject *obj)
4627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
4637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t size;
4647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
4657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_INITIALIZED(self);
4667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (!PyUnicode_Check(obj)) {
4677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_Format(PyExc_TypeError, "unicode argument expected, got '%s'",
4687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                     Py_TYPE(obj)->tp_name);
4697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
4707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
4717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_CLOSED(self);
4727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    size = PyUnicode_GET_SIZE(obj);
4737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
4747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (size > 0 && write_str(self, obj) < 0)
4757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
4767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
4777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return PyLong_FromSsize_t(size);
4787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
4797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
4807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielPyDoc_STRVAR(stringio_close_doc,
4817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "Close the IO object. Attempting any further operation after the\n"
4827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "object is closed will raise a ValueError.\n"
4837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "\n"
4847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "This method has no effect if the file is already closed.\n");
4857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
4867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
4877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstringio_close(stringio *self)
4887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
4897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    self->closed = 1;
4907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Free up some memory */
4917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (resize_buffer(self, 0) < 0)
4927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
4937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(self->readnl);
4947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(self->writenl);
4957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(self->decoder);
4967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_RETURN_NONE;
4977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
4987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
4997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
5007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstringio_traverse(stringio *self, visitproc visit, void *arg)
5017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
5027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_VISIT(self->dict);
5037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return 0;
5047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
5057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
5067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
5077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstringio_clear(stringio *self)
5087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
5097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(self->dict);
5107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return 0;
5117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
5127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
5137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic void
5147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstringio_dealloc(stringio *self)
5157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
5167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    _PyObject_GC_UNTRACK(self);
5177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    self->ok = 0;
5187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (self->buf) {
5197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyMem_Free(self->buf);
5207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        self->buf = NULL;
5217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
5227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(self->readnl);
5237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(self->writenl);
5247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(self->decoder);
5257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(self->dict);
5267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (self->weakreflist != NULL)
5277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyObject_ClearWeakRefs((PyObject *) self);
5287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_TYPE(self)->tp_free(self);
5297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
5307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
5317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
5327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstringio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
5337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
5347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    stringio *self;
5357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
5367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    assert(type != NULL && type->tp_alloc != NULL);
5377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    self = (stringio *)type->tp_alloc(type, 0);
5387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (self == NULL)
5397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
5407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
5417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* tp_alloc initializes all the fields to zero. So we don't have to
5427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       initialize them here. */
5437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
5447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    self->buf = (Py_UNICODE *)PyMem_Malloc(0);
5457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (self->buf == NULL) {
5467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(self);
5477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return PyErr_NoMemory();
5487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
5497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
5507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return (PyObject *)self;
5517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
5527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
5537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
5547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstringio_init(stringio *self, PyObject *args, PyObject *kwds)
5557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
5567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    char *kwlist[] = {"initial_value", "newline", NULL};
5577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *value = NULL;
5587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    char *newline = "\n";
5597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
5607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oz:__init__", kwlist,
5617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                                     &value, &newline))
5627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return -1;
5637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
5647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (newline && newline[0] != '\0'
5657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        && !(newline[0] == '\n' && newline[1] == '\0')
5667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        && !(newline[0] == '\r' && newline[1] == '\0')
5677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        && !(newline[0] == '\r' && newline[1] == '\n' && newline[2] == '\0')) {
5687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_Format(PyExc_ValueError,
5697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                     "illegal newline value: %s", newline);
5707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return -1;
5717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
5727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (value && value != Py_None && !PyUnicode_Check(value)) {
5737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_Format(PyExc_TypeError,
5747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                     "initial_value must be unicode or None, not %.200s",
5757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                     Py_TYPE(value)->tp_name);
5767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return -1;
5777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
5787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
5797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    self->ok = 0;
5807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
5817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(self->readnl);
5827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(self->writenl);
5837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(self->decoder);
5847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
5857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (newline) {
5867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        self->readnl = PyString_FromString(newline);
5877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (self->readnl == NULL)
5887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return -1;
5897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
5907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    self->readuniversal = (newline == NULL || newline[0] == '\0');
5917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    self->readtranslate = (newline == NULL);
5927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* If newline == "", we don't translate anything.
5937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       If newline == "\n" or newline == None, we translate to "\n", which is
5947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       a no-op.
5957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       (for newline == None, TextIOWrapper translates to os.sepline, but it
5967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       is pointless for StringIO)
5977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    */
5987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (newline != NULL && newline[0] == '\r') {
5997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        self->writenl = PyUnicode_FromString(newline);
6007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
6017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
6027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (self->readuniversal) {
6037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        self->decoder = PyObject_CallFunction(
6047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            (PyObject *)&PyIncrementalNewlineDecoder_Type,
6057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            "Oi", Py_None, (int) self->readtranslate);
6067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (self->decoder == NULL)
6077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return -1;
6087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
6097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
6107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Now everything is set up, resize buffer to size of initial value,
6117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       and copy it */
6127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    self->string_size = 0;
6137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (value && value != Py_None) {
6147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_ssize_t len = PyUnicode_GetSize(value);
6157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* This is a heuristic, for newline translation might change
6167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel           the string length. */
6177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (resize_buffer(self, len) < 0)
6187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return -1;
6197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        self->pos = 0;
6207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (write_str(self, value) < 0)
6217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return -1;
6227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
6237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else {
6247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (resize_buffer(self, 0) < 0)
6257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return -1;
6267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
6277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    self->pos = 0;
6287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
6297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    self->closed = 0;
6307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    self->ok = 1;
6317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return 0;
6327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
6337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
6347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel/* Properties and pseudo-properties */
6357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
6367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielPyDoc_STRVAR(stringio_readable_doc,
6377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel"readable() -> bool. Returns True if the IO object can be read.");
6387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
6397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielPyDoc_STRVAR(stringio_writable_doc,
6407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel"writable() -> bool. Returns True if the IO object can be written.");
6417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
6427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielPyDoc_STRVAR(stringio_seekable_doc,
6437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel"seekable() -> bool. Returns True if the IO object can be seeked.");
6447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
6457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
6467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstringio_seekable(stringio *self, PyObject *args)
6477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
6487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_INITIALIZED(self);
6497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_CLOSED(self);
6507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_RETURN_TRUE;
6517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
6527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
6537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
6547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstringio_readable(stringio *self, PyObject *args)
6557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
6567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_INITIALIZED(self);
6577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_CLOSED(self);
6587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_RETURN_TRUE;
6597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
6607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
6617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
6627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstringio_writable(stringio *self, PyObject *args)
6637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
6647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_INITIALIZED(self);
6657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_CLOSED(self);
6667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_RETURN_TRUE;
6677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
6687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
6697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel/* Pickling support.
6707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
6717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel   The implementation of __getstate__ is similar to the one for BytesIO,
6727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel   except that we also save the newline parameter. For __setstate__ and unlike
6737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel   BytesIO, we call __init__ to restore the object's state. Doing so allows us
6747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel   to avoid decoding the complex newline state while keeping the object
6757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel   representation compact.
6767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
6777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel   See comment in bytesio.c regarding why only pickle protocols and onward are
6787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel   supported.
6797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel*/
6807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
6817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
6827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstringio_getstate(stringio *self)
6837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
6847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *initvalue = stringio_getvalue(self);
6857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *dict;
6867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *state;
6877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
6887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (initvalue == NULL)
6897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
6907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (self->dict == NULL) {
6917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_INCREF(Py_None);
6927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        dict = Py_None;
6937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
6947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else {
6957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        dict = PyDict_Copy(self->dict);
6967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (dict == NULL)
6977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return NULL;
6987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
6997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
7007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    state = Py_BuildValue("(OOnN)", initvalue,
7017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                          self->readnl ? self->readnl : Py_None,
7027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                          self->pos, dict);
7037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_DECREF(initvalue);
7047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return state;
7057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
7067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
7077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
7087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstringio_setstate(stringio *self, PyObject *state)
7097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
7107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *initarg;
7117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *position_obj;
7127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *dict;
7137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t pos;
7147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
7157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    assert(state != NULL);
7167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_CLOSED(self);
7177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
7187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* We allow the state tuple to be longer than 4, because we may need
7197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       someday to extend the object's state without breaking
7207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       backward-compatibility. */
7217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (!PyTuple_Check(state) || Py_SIZE(state) < 4) {
7227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_Format(PyExc_TypeError,
7237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                     "%.200s.__setstate__ argument should be 4-tuple, got %.200s",
7247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                     Py_TYPE(self)->tp_name, Py_TYPE(state)->tp_name);
7257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
7267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
7277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
7287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Initialize the object's state. */
7297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    initarg = PyTuple_GetSlice(state, 0, 2);
7307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (initarg == NULL)
7317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
7327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (stringio_init(self, initarg, NULL) < 0) {
7337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(initarg);
7347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
7357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
7367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_DECREF(initarg);
7377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
7387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Restore the buffer state. Even if __init__ did initialize the buffer,
7397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       we have to initialize it again since __init__ may translates the
7407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       newlines in the inital_value string. We clearly do not want that
7417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       because the string value in the state tuple has already been translated
7427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       once by __init__. So we do not take any chance and replace object's
7437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       buffer completely. */
7447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {
7457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_UNICODE *buf = PyUnicode_AS_UNICODE(PyTuple_GET_ITEM(state, 0));
7467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_ssize_t bufsize = PyUnicode_GET_SIZE(PyTuple_GET_ITEM(state, 0));
7477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (resize_buffer(self, bufsize) < 0)
7487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return NULL;
7497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        memcpy(self->buf, buf, bufsize * sizeof(Py_UNICODE));
7507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        self->string_size = bufsize;
7517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
7527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
7537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Set carefully the position value. Alternatively, we could use the seek
7547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       method instead of modifying self->pos directly to better protect the
7557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel       object internal state against errneous (or malicious) inputs. */
7567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    position_obj = PyTuple_GET_ITEM(state, 2);
7577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (!PyIndex_Check(position_obj)) {
7587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_Format(PyExc_TypeError,
7597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                     "third item of state must be an integer, got %.200s",
7607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                     Py_TYPE(position_obj)->tp_name);
7617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
7627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
7637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    pos = PyNumber_AsSsize_t(position_obj, PyExc_OverflowError);
7647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (pos == -1 && PyErr_Occurred())
7657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
7667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (pos < 0) {
7677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_SetString(PyExc_ValueError,
7687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        "position value cannot be negative");
7697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
7707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
7717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    self->pos = pos;
7727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
7737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Set the dictionary of the instance variables. */
7747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    dict = PyTuple_GET_ITEM(state, 3);
7757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (dict != Py_None) {
7767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (!PyDict_Check(dict)) {
7777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            PyErr_Format(PyExc_TypeError,
7787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                         "fourth item of state should be a dict, got a %.200s",
7797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                         Py_TYPE(dict)->tp_name);
7807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return NULL;
7817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
7827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (self->dict) {
7837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* Alternatively, we could replace the internal dictionary
7847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel               completely. However, it seems more practical to just update it. */
7857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (PyDict_Update(self->dict, dict) < 0)
7867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return NULL;
7877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
7887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        else {
7897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_INCREF(dict);
7907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            self->dict = dict;
7917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
7927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
7937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
7947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_RETURN_NONE;
7957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
7967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
7977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
7987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
7997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstringio_closed(stringio *self, void *context)
8007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
8017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_INITIALIZED(self);
8027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return PyBool_FromLong(self->closed);
8037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
8047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
8057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
8067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstringio_line_buffering(stringio *self, void *context)
8077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
8087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_INITIALIZED(self);
8097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_CLOSED(self);
8107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_RETURN_FALSE;
8117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
8127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
8137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
8147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstringio_newlines(stringio *self, void *context)
8157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
8167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_INITIALIZED(self);
8177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    CHECK_CLOSED(self);
8187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (self->decoder == NULL)
8197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_RETURN_NONE;
8207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return PyObject_GetAttr(self->decoder, _PyIO_str_newlines);
8217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
8227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
8237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic struct PyMethodDef stringio_methods[] = {
8247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"close",    (PyCFunction)stringio_close,    METH_NOARGS,  stringio_close_doc},
8257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"getvalue", (PyCFunction)stringio_getvalue, METH_NOARGS,  stringio_getvalue_doc},
8267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"read",     (PyCFunction)stringio_read,     METH_VARARGS, stringio_read_doc},
8277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"readline", (PyCFunction)stringio_readline, METH_VARARGS, stringio_readline_doc},
8287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"tell",     (PyCFunction)stringio_tell,     METH_NOARGS,  stringio_tell_doc},
8297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"truncate", (PyCFunction)stringio_truncate, METH_VARARGS, stringio_truncate_doc},
8307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"seek",     (PyCFunction)stringio_seek,     METH_VARARGS, stringio_seek_doc},
8317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"write",    (PyCFunction)stringio_write,    METH_O,       stringio_write_doc},
8327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
8337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"seekable", (PyCFunction)stringio_seekable, METH_NOARGS, stringio_seekable_doc},
8347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"readable", (PyCFunction)stringio_readable, METH_NOARGS, stringio_readable_doc},
8357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"writable", (PyCFunction)stringio_writable, METH_NOARGS, stringio_writable_doc},
8367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
8377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"__getstate__", (PyCFunction)stringio_getstate, METH_NOARGS},
8387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"__setstate__", (PyCFunction)stringio_setstate, METH_O},
8397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {NULL, NULL}        /* sentinel */
8407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel};
8417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
8427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyGetSetDef stringio_getset[] = {
8437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"closed",         (getter)stringio_closed,         NULL, NULL},
8447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"newlines",       (getter)stringio_newlines,       NULL, NULL},
8457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /*  (following comments straight off of the original Python wrapper:)
8467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        XXX Cruft to support the TextIOWrapper API. This would only
8477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        be meaningful if StringIO supported the buffer attribute.
8487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Hopefully, a better solution, than adding these pseudo-attributes,
8497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        will be found.
8507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    */
8517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"line_buffering", (getter)stringio_line_buffering, NULL, NULL},
8527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {NULL}
8537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel};
8547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
8557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielPyTypeObject PyStringIO_Type = {
8567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyVarObject_HEAD_INIT(NULL, 0)
8577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "_io.StringIO",                            /*tp_name*/
8587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    sizeof(stringio),                    /*tp_basicsize*/
8597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_itemsize*/
8607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    (destructor)stringio_dealloc,              /*tp_dealloc*/
8617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_print*/
8627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_getattr*/
8637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_setattr*/
8647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_reserved*/
8657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_repr*/
8667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_as_number*/
8677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_as_sequence*/
8687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_as_mapping*/
8697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_hash*/
8707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_call*/
8717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_str*/
8727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_getattro*/
8737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_setattro*/
8747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_as_buffer*/
8757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
8767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                       | Py_TPFLAGS_HAVE_GC,   /*tp_flags*/
8777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    stringio_doc,                              /*tp_doc*/
8787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    (traverseproc)stringio_traverse,           /*tp_traverse*/
8797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    (inquiry)stringio_clear,                   /*tp_clear*/
8807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_richcompare*/
8817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    offsetof(stringio, weakreflist),            /*tp_weaklistoffset*/
8827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_iter*/
8837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    (iternextfunc)stringio_iternext,           /*tp_iternext*/
8847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    stringio_methods,                          /*tp_methods*/
8857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_members*/
8867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    stringio_getset,                           /*tp_getset*/
8877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_base*/
8887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_dict*/
8897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_descr_get*/
8907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_descr_set*/
8917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    offsetof(stringio, dict),                  /*tp_dictoffset*/
8927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    (initproc)stringio_init,                   /*tp_init*/
8937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                                         /*tp_alloc*/
8947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    stringio_new,                              /*tp_new*/
8957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel};
896