14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/*
24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    An implementation of Text I/O as defined by PEP 3116 - "New I/O"
34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Classes defined here: TextIOBase, IncrementalNewlineDecoder, TextIOWrapper.
54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Written by Amaury Forgeot d'Arc and Antoine Pitrou
74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm*/
84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define PY_SSIZE_T_CLEAN
104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "Python.h"
114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "structmember.h"
124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "_iomodule.h"
134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* TextIOBase */
154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(textiobase_doc,
174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "Base class for text I/O.\n"
184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "\n"
194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "This class provides a character and line based interface to stream\n"
204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "I/O. There is no readinto method because Python's character strings\n"
214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "are immutable. There is no public constructor.\n"
224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    );
234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm_unsupported(const char *message)
264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyErr_SetString(_PyIO_unsupported_operation, message);
284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return NULL;
294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(textiobase_detach_doc,
324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "Separate the underlying buffer from the TextIOBase and return it.\n"
334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "\n"
344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "After the underlying buffer has been detached, the TextIO is in an\n"
354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "unusable state.\n"
364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    );
374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiobase_detach(PyObject *self)
404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return _unsupported("detach");
424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(textiobase_read_doc,
454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "Read at most n characters from stream.\n"
464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "\n"
474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "Read from underlying buffer until we have n characters or we hit EOF.\n"
484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "If n is negative or omitted, read until EOF.\n"
494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    );
504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiobase_read(PyObject *self, PyObject *args)
534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return _unsupported("read");
554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(textiobase_readline_doc,
584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "Read until newline or EOF.\n"
594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "\n"
604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "Returns an empty string if EOF is hit immediately.\n"
614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    );
624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiobase_readline(PyObject *self, PyObject *args)
654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return _unsupported("readline");
674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(textiobase_write_doc,
704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "Write string to stream.\n"
714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "Returns the number of characters written (which is always equal to\n"
724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "the length of the string).\n"
734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    );
744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiobase_write(PyObject *self, PyObject *args)
774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return _unsupported("write");
794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(textiobase_encoding_doc,
824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "Encoding of the text stream.\n"
834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "\n"
844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "Subclasses should override.\n"
854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    );
864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiobase_encoding_get(PyObject *self, void *context)
894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_RETURN_NONE;
914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(textiobase_newlines_doc,
944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "Line endings translated so far.\n"
954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "\n"
964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "Only line endings translated during reading are considered.\n"
974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "\n"
984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "Subclasses should override.\n"
994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    );
1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiobase_newlines_get(PyObject *self, void *context)
1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_RETURN_NONE;
1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(textiobase_errors_doc,
1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "The error setting of the decoder or encoder.\n"
1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "\n"
1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "Subclasses should override.\n"
1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    );
1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiobase_errors_get(PyObject *self, void *context)
1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_RETURN_NONE;
1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyMethodDef textiobase_methods[] = {
1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"detach", (PyCFunction)textiobase_detach, METH_NOARGS, textiobase_detach_doc},
1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"read", textiobase_read, METH_VARARGS, textiobase_read_doc},
1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"readline", textiobase_readline, METH_VARARGS, textiobase_readline_doc},
1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"write", textiobase_write, METH_VARARGS, textiobase_write_doc},
1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {NULL, NULL}
1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyGetSetDef textiobase_getset[] = {
1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"encoding", (getter)textiobase_encoding_get, NULL, textiobase_encoding_doc},
1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"newlines", (getter)textiobase_newlines_get, NULL, textiobase_newlines_doc},
1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"errors", (getter)textiobase_errors_get, NULL, textiobase_errors_doc},
1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {NULL}
1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyTypeObject PyTextIOBase_Type = {
1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyVarObject_HEAD_INIT(NULL, 0)
1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "_io._TextIOBase",          /*tp_name*/
1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_basicsize*/
1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_itemsize*/
1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_dealloc*/
1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_print*/
1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_getattr*/
1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_setattr*/
1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_compare */
1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_repr*/
1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_as_number*/
1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_as_sequence*/
1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_as_mapping*/
1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_hash */
1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_call*/
1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_str*/
1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_getattro*/
1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_setattro*/
1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_as_buffer*/
1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,  /*tp_flags*/
1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    textiobase_doc,             /* tp_doc */
1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_traverse */
1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_clear */
1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_richcompare */
1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_weaklistoffset */
1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_iter */
1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_iternext */
1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    textiobase_methods,         /* tp_methods */
1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_members */
1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    textiobase_getset,          /* tp_getset */
1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    &PyIOBase_Type,             /* tp_base */
1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_dict */
1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_descr_get */
1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_descr_set */
1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_dictoffset */
1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_init */
1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_alloc */
1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_new */
1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* IncrementalNewlineDecoder */
1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(incrementalnewlinedecoder_doc,
1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "Codec used when reading a file in universal newlines mode.  It wraps\n"
1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "another incremental decoder, translating \\r\\n and \\r into \\n.  It also\n"
1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "records the types of newlines encountered.  When used with\n"
1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "translate=False, it ensures that the newline sequence is returned in\n"
1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "one piece. When used with decoder=None, it expects unicode strings as\n"
1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "decode input and translates newlines without first invoking an external\n"
1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "decoder.\n"
1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    );
1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtypedef struct {
1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject_HEAD
1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *decoder;
1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *errors;
1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    signed int pendingcr: 1;
1944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    signed int translate: 1;
1954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    unsigned int seennl: 3;
1964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} nldecoder_object;
1974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
1994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmincrementalnewlinedecoder_init(nldecoder_object *self,
2004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                               PyObject *args, PyObject *kwds)
2014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
2024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *decoder;
2034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int translate;
2044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *errors = NULL;
2054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    char *kwlist[] = {"decoder", "translate", "errors", NULL};
2064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oi|O:IncrementalNewlineDecoder",
2084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                     kwlist, &decoder, &translate, &errors))
2094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
2104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->decoder = decoder;
2124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_INCREF(decoder);
2134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (errors == NULL) {
2154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->errors = PyUnicode_FromString("strict");
2164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (self->errors == NULL)
2174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return -1;
2184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
2194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
2204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_INCREF(errors);
2214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->errors = errors;
2224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
2234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->translate = translate;
2254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->seennl = 0;
2264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->pendingcr = 0;
2274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
2294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
2304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void
2324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmincrementalnewlinedecoder_dealloc(nldecoder_object *self)
2334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
2344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->decoder);
2354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->errors);
2364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_TYPE(self)->tp_free((PyObject *)self);
2374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
2384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define SEEN_CR   1
2404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define SEEN_LF   2
2414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define SEEN_CRLF 4
2424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define SEEN_ALL (SEEN_CR | SEEN_LF | SEEN_CRLF)
2434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyObject *
2454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm_PyIncrementalNewlineDecoder_decode(PyObject *_self,
2464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                    PyObject *input, int final)
2474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
2484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *output;
2494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t output_len;
2504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    nldecoder_object *self = (nldecoder_object *) _self;
2514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->decoder == NULL) {
2534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_ValueError,
2544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        "IncrementalNewlineDecoder.__init__ not called");
2554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
2564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
2574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* decode input (with the eventual \r from a previous pass) */
2594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->decoder != Py_None) {
2604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        output = PyObject_CallMethodObjArgs(self->decoder,
2614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            _PyIO_str_decode, input, final ? Py_True : Py_False, NULL);
2624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
2634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
2644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        output = input;
2654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_INCREF(output);
2664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
2674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (output == NULL)
2694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
2704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyUnicode_Check(output)) {
2724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_TypeError,
2734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        "decoder should return a string result");
2744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto error;
2754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
2764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    output_len = PyUnicode_GET_SIZE(output);
2784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->pendingcr && (final || output_len > 0)) {
2794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_UNICODE *out;
2804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject *modified = PyUnicode_FromUnicode(NULL, output_len + 1);
2814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (modified == NULL)
2824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto error;
2834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        out = PyUnicode_AS_UNICODE(modified);
2844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        out[0] = '\r';
2854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        memcpy(out + 1, PyUnicode_AS_UNICODE(output),
2864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm               output_len * sizeof(Py_UNICODE));
2874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(output);
2884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        output = modified;
2894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->pendingcr = 0;
2904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        output_len++;
2914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
2924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* retain last \r even when not translating data:
2944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * then readline() is sure to get \r\n in one pass
2954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     */
2964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!final) {
2974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (output_len > 0
2984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            && PyUnicode_AS_UNICODE(output)[output_len - 1] == '\r') {
2994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (Py_REFCNT(output) == 1) {
3014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (PyUnicode_Resize(&output, output_len - 1) < 0)
3024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    goto error;
3034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            }
3044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else {
3054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                PyObject *modified = PyUnicode_FromUnicode(
3064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    PyUnicode_AS_UNICODE(output),
3074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    output_len - 1);
3084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (modified == NULL)
3094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    goto error;
3104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                Py_DECREF(output);
3114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                output = modified;
3124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            }
3134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self->pendingcr = 1;
3144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
3154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
3164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* Record which newlines are read and do newline translation if desired,
3184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm       all in one pass. */
3194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {
3204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_UNICODE *in_str;
3214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_ssize_t len;
3224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        int seennl = self->seennl;
3234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        int only_lf = 0;
3244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        in_str = PyUnicode_AS_UNICODE(output);
3264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        len = PyUnicode_GET_SIZE(output);
3274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (len == 0)
3294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return output;
3304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* If, up to now, newlines are consistently \n, do a quick check
3324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm           for the \r *byte* with the libc's optimized memchr.
3334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm           */
3344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (seennl == SEEN_LF || seennl == 0) {
3354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            only_lf = (memchr(in_str, '\r', len * sizeof(Py_UNICODE)) == NULL);
3364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
3374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (only_lf) {
3394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            /* If not already seen, quick scan for a possible "\n" character.
3404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm               (there's nothing else to be done, even when in translation mode)
3414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            */
3424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (seennl == 0 &&
3434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                memchr(in_str, '\n', len * sizeof(Py_UNICODE)) != NULL) {
3444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                Py_UNICODE *s, *end;
3454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                s = in_str;
3464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                end = in_str + len;
3474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                for (;;) {
3484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    Py_UNICODE c;
3494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    /* Fast loop for non-control characters */
3504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    while (*s > '\n')
3514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        s++;
3524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    c = *s++;
3534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    if (c == '\n') {
3544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        seennl |= SEEN_LF;
3554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        break;
3564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    }
3574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    if (s > end)
3584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        break;
3594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                }
3604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            }
3614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            /* Finished: we have scanned for newlines, and none of them
3624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm               need translating */
3634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
3644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else if (!self->translate) {
3654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_UNICODE *s, *end;
3664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            /* We have already seen all newline types, no need to scan again */
3674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (seennl == SEEN_ALL)
3684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto endscan;
3694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            s = in_str;
3704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            end = in_str + len;
3714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            for (;;) {
3724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                Py_UNICODE c;
3734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                /* Fast loop for non-control characters */
3744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                while (*s > '\r')
3754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    s++;
3764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                c = *s++;
3774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (c == '\n')
3784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    seennl |= SEEN_LF;
3794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                else if (c == '\r') {
3804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    if (*s == '\n') {
3814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        seennl |= SEEN_CRLF;
3824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        s++;
3834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    }
3844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    else
3854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        seennl |= SEEN_CR;
3864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                }
3874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (s > end)
3884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    break;
3894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (seennl == SEEN_ALL)
3904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    break;
3914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            }
3924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        endscan:
3934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ;
3944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
3954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else {
3964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyObject *translated = NULL;
3974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_UNICODE *out_str;
3984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_UNICODE *in, *out, *end;
3994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (Py_REFCNT(output) != 1) {
4004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                /* We could try to optimize this so that we only do a copy
4014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                   when there is something to translate. On the other hand,
4024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                   most decoders should only output non-shared strings, i.e.
4034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                   translation is done in place. */
4044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                translated = PyUnicode_FromUnicode(NULL, len);
4054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (translated == NULL)
4064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    goto error;
4074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                assert(Py_REFCNT(translated) == 1);
4084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                memcpy(PyUnicode_AS_UNICODE(translated),
4094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       PyUnicode_AS_UNICODE(output),
4104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       len * sizeof(Py_UNICODE));
4114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            }
4124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else {
4134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                translated = output;
4144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            }
4154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            out_str = PyUnicode_AS_UNICODE(translated);
4164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            in = in_str;
4174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            out = out_str;
4184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            end = in_str + len;
4194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            for (;;) {
4204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                Py_UNICODE c;
4214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                /* Fast loop for non-control characters */
4224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                while ((c = *in++) > '\r')
4234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    *out++ = c;
4244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (c == '\n') {
4254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    *out++ = c;
4264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    seennl |= SEEN_LF;
4274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    continue;
4284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                }
4294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (c == '\r') {
4304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    if (*in == '\n') {
4314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        in++;
4324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        seennl |= SEEN_CRLF;
4334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    }
4344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    else
4354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        seennl |= SEEN_CR;
4364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    *out++ = '\n';
4374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    continue;
4384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                }
4394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (in > end)
4404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    break;
4414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                *out++ = c;
4424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            }
4434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (translated != output) {
4444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                Py_DECREF(output);
4454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                output = translated;
4464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            }
4474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (out - out_str != len) {
4484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (PyUnicode_Resize(&output, out - out_str) < 0)
4494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    goto error;
4504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            }
4514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
4524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->seennl |= seennl;
4534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
4544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return output;
4564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm  error:
4584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(output);
4594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return NULL;
4604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
4614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
4634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmincrementalnewlinedecoder_decode(nldecoder_object *self,
4644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                 PyObject *args, PyObject *kwds)
4654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
4664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    char *kwlist[] = {"input", "final", NULL};
4674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *input;
4684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int final = 0;
4694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:IncrementalNewlineDecoder",
4714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                     kwlist, &input, &final))
4724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
4734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return _PyIncrementalNewlineDecoder_decode((PyObject *) self, input, final);
4744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
4754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
4774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmincrementalnewlinedecoder_getstate(nldecoder_object *self, PyObject *args)
4784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
4794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *buffer;
4804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    unsigned PY_LONG_LONG flag;
4814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->decoder != Py_None) {
4834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject *state = PyObject_CallMethodObjArgs(self->decoder,
4844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm           _PyIO_str_getstate, NULL);
4854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (state == NULL)
4864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
4874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (!PyArg_Parse(state, "(OK)", &buffer, &flag)) {
4884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_DECREF(state);
4894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
4904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
4914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_INCREF(buffer);
4924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(state);
4934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
4944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
4954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        buffer = PyBytes_FromString("");
4964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        flag = 0;
4974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
4984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    flag <<= 1;
4994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->pendingcr)
5004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        flag |= 1;
5014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return Py_BuildValue("NK", buffer, flag);
5024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
5034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
5054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmincrementalnewlinedecoder_setstate(nldecoder_object *self, PyObject *state)
5064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
5074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *buffer;
5084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    unsigned PY_LONG_LONG flag;
5094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_Parse(state, "(OK)", &buffer, &flag))
5114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
5124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->pendingcr = (int) flag & 1;
5144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    flag >>= 1;
5154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->decoder != Py_None)
5174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return PyObject_CallMethod(self->decoder,
5184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                   "setstate", "((OK))", buffer, flag);
5194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else
5204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_RETURN_NONE;
5214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
5224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
5244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmincrementalnewlinedecoder_reset(nldecoder_object *self, PyObject *args)
5254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
5264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->seennl = 0;
5274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->pendingcr = 0;
5284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->decoder != Py_None)
5294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return PyObject_CallMethodObjArgs(self->decoder, _PyIO_str_reset, NULL);
5304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else
5314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_RETURN_NONE;
5324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
5334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
5354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmincrementalnewlinedecoder_newlines_get(nldecoder_object *self, void *context)
5364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
5374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    switch (self->seennl) {
5384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    case SEEN_CR:
5394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return PyUnicode_FromString("\r");
5404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    case SEEN_LF:
5414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return PyUnicode_FromString("\n");
5424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    case SEEN_CRLF:
5434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return PyUnicode_FromString("\r\n");
5444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    case SEEN_CR | SEEN_LF:
5454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return Py_BuildValue("ss", "\r", "\n");
5464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    case SEEN_CR | SEEN_CRLF:
5474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return Py_BuildValue("ss", "\r", "\r\n");
5484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    case SEEN_LF | SEEN_CRLF:
5494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return Py_BuildValue("ss", "\n", "\r\n");
5504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    case SEEN_CR | SEEN_LF | SEEN_CRLF:
5514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return Py_BuildValue("sss", "\r", "\n", "\r\n");
5524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    default:
5534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_RETURN_NONE;
5544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm   }
5554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
5574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyMethodDef incrementalnewlinedecoder_methods[] = {
5604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"decode", (PyCFunction)incrementalnewlinedecoder_decode, METH_VARARGS|METH_KEYWORDS},
5614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"getstate", (PyCFunction)incrementalnewlinedecoder_getstate, METH_NOARGS},
5624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"setstate", (PyCFunction)incrementalnewlinedecoder_setstate, METH_O},
5634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"reset", (PyCFunction)incrementalnewlinedecoder_reset, METH_NOARGS},
5644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {NULL}
5654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
5664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyGetSetDef incrementalnewlinedecoder_getset[] = {
5684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"newlines", (getter)incrementalnewlinedecoder_newlines_get, NULL, NULL},
5694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {NULL}
5704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
5714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyTypeObject PyIncrementalNewlineDecoder_Type = {
5734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyVarObject_HEAD_INIT(NULL, 0)
5744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "_io.IncrementalNewlineDecoder", /*tp_name*/
5754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    sizeof(nldecoder_object), /*tp_basicsize*/
5764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_itemsize*/
5774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    (destructor)incrementalnewlinedecoder_dealloc, /*tp_dealloc*/
5784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_print*/
5794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_getattr*/
5804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_setattr*/
5814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_compare */
5824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_repr*/
5834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_as_number*/
5844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_as_sequence*/
5854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_as_mapping*/
5864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_hash */
5874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_call*/
5884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_str*/
5894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_getattro*/
5904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_setattro*/
5914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_as_buffer*/
5924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,  /*tp_flags*/
5934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    incrementalnewlinedecoder_doc,          /* tp_doc */
5944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_traverse */
5954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_clear */
5964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_richcompare */
5974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_weaklistoffset*/
5984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_iter */
5994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_iternext */
6004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    incrementalnewlinedecoder_methods, /* tp_methods */
6014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_members */
6024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    incrementalnewlinedecoder_getset, /* tp_getset */
6034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_base */
6044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_dict */
6054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_descr_get */
6064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_descr_set */
6074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_dictoffset */
6084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    (initproc)incrementalnewlinedecoder_init, /* tp_init */
6094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_alloc */
6104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyType_GenericNew,          /* tp_new */
6114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
6124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* TextIOWrapper */
6154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(textiowrapper_doc,
6174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "Character and line based layer over a BufferedIOBase object, buffer.\n"
6184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "\n"
6194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "encoding gives the name of the encoding that the stream will be\n"
6204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "decoded or encoded with. It defaults to locale.getpreferredencoding.\n"
6214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "\n"
6224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "errors determines the strictness of encoding and decoding (see the\n"
6234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "codecs.register) and defaults to \"strict\".\n"
6244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "\n"
6254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "newline can be None, '', '\\n', '\\r', or '\\r\\n'.  It controls the\n"
6264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "handling of line endings. If it is None, universal newlines is\n"
6274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "enabled.  With this enabled, on input, the lines endings '\\n', '\\r',\n"
6284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "or '\\r\\n' are translated to '\\n' before being returned to the\n"
6294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "caller. Conversely, on output, '\\n' is translated to the system\n"
6304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "default line seperator, os.linesep. If newline is any other of its\n"
6314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "legal values, that newline becomes the newline when the file is read\n"
6324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "and it is returned untranslated. On output, '\\n' is converted to the\n"
6334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "newline.\n"
6344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "\n"
6354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "If line_buffering is True, a call to flush is implied when a call to\n"
6364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "write contains a newline character."
6374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    );
6384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtypedef PyObject *
6404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        (*encodefunc_t)(PyObject *, PyObject *);
6414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtypedef struct
6434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
6444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject_HEAD
6454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int ok; /* initialized? */
6464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int detached;
6474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t chunk_size;
6484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *buffer;
6494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *encoding;
6504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *encoder;
6514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *decoder;
6524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *readnl;
6534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *errors;
6544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    const char *writenl; /* utf-8 encoded, NULL stands for \n */
6554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    char line_buffering;
6564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    char readuniversal;
6574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    char readtranslate;
6584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    char writetranslate;
6594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    char seekable;
6604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    char telling;
6614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* Specialized encoding func (see below) */
6624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    encodefunc_t encodefunc;
6634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* Whether or not it's the start of the stream */
6644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    char encoding_start_of_stream;
6654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* Reads and writes are internally buffered in order to speed things up.
6674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm       However, any read will first flush the write buffer if itsn't empty.
6684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm       Please also note that text to be written is first encoded before being
6704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm       buffered. This is necessary so that encoding errors are immediately
6714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm       reported to the caller, but it unfortunately means that the
6724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm       IncrementalEncoder (whose encode() method is always written in Python)
6734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm       becomes a bottleneck for small writes.
6744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    */
6754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *decoded_chars;       /* buffer for text returned from decoder */
6764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t decoded_chars_used; /* offset into _decoded_chars for read() */
6774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *pending_bytes;       /* list of bytes objects waiting to be
6784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                      written, or NULL */
6794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t pending_bytes_count;
6804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *snapshot;
6814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* snapshot is either None, or a tuple (dec_flags, next_input) where
6824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * dec_flags is the second (integer) item of the decoder state and
6834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * next_input is the chunk of input bytes that comes next after the
6844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * snapshot point.  We use this to reconstruct decoder states in tell().
6854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     */
6864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* Cache raw object if it's a FileIO object */
6884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *raw;
6894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *weakreflist;
6914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *dict;
6924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} textio;
6934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* A couple of specialized cases in order to bypass the slow incremental
6964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm   encoding methods for the most popular encodings. */
6974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
6994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmascii_encode(textio *self, PyObject *text)
7004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
7014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return PyUnicode_EncodeASCII(PyUnicode_AS_UNICODE(text),
7024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                 PyUnicode_GET_SIZE(text),
7034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                 PyBytes_AS_STRING(self->errors));
7044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
7054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
7074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmutf16be_encode(textio *self, PyObject *text)
7084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
7094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return PyUnicode_EncodeUTF16(PyUnicode_AS_UNICODE(text),
7104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                 PyUnicode_GET_SIZE(text),
7114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                 PyBytes_AS_STRING(self->errors), 1);
7124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
7134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
7154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmutf16le_encode(textio *self, PyObject *text)
7164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
7174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return PyUnicode_EncodeUTF16(PyUnicode_AS_UNICODE(text),
7184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                 PyUnicode_GET_SIZE(text),
7194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                 PyBytes_AS_STRING(self->errors), -1);
7204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
7214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
7234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmutf16_encode(textio *self, PyObject *text)
7244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
7254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!self->encoding_start_of_stream) {
7264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* Skip the BOM and use native byte ordering */
7274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#if defined(WORDS_BIGENDIAN)
7284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return utf16be_encode(self, text);
7294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else
7304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return utf16le_encode(self, text);
7314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif
7324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
7334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return PyUnicode_EncodeUTF16(PyUnicode_AS_UNICODE(text),
7344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                 PyUnicode_GET_SIZE(text),
7354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                 PyBytes_AS_STRING(self->errors), 0);
7364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
7374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
7394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmutf32be_encode(textio *self, PyObject *text)
7404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
7414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return PyUnicode_EncodeUTF32(PyUnicode_AS_UNICODE(text),
7424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                 PyUnicode_GET_SIZE(text),
7434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                 PyBytes_AS_STRING(self->errors), 1);
7444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
7454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
7474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmutf32le_encode(textio *self, PyObject *text)
7484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
7494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return PyUnicode_EncodeUTF32(PyUnicode_AS_UNICODE(text),
7504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                 PyUnicode_GET_SIZE(text),
7514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                 PyBytes_AS_STRING(self->errors), -1);
7524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
7534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
7554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmutf32_encode(textio *self, PyObject *text)
7564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
7574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!self->encoding_start_of_stream) {
7584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* Skip the BOM and use native byte ordering */
7594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#if defined(WORDS_BIGENDIAN)
7604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return utf32be_encode(self, text);
7614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else
7624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return utf32le_encode(self, text);
7634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif
7644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
7654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return PyUnicode_EncodeUTF32(PyUnicode_AS_UNICODE(text),
7664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                 PyUnicode_GET_SIZE(text),
7674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                 PyBytes_AS_STRING(self->errors), 0);
7684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
7694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
7714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmutf8_encode(textio *self, PyObject *text)
7724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
7734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(text),
7744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                PyUnicode_GET_SIZE(text),
7754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                PyBytes_AS_STRING(self->errors));
7764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
7774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
7794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmlatin1_encode(textio *self, PyObject *text)
7804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
7814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return PyUnicode_EncodeLatin1(PyUnicode_AS_UNICODE(text),
7824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                  PyUnicode_GET_SIZE(text),
7834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                  PyBytes_AS_STRING(self->errors));
7844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
7854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* Map normalized encoding names onto the specialized encoding funcs */
7874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtypedef struct {
7894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    const char *name;
7904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    encodefunc_t encodefunc;
7914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} encodefuncentry;
7924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic encodefuncentry encodefuncs[] = {
7944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"ascii",       (encodefunc_t) ascii_encode},
7954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"iso8859-1",   (encodefunc_t) latin1_encode},
7964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"utf-8",       (encodefunc_t) utf8_encode},
7974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"utf-16-be",   (encodefunc_t) utf16be_encode},
7984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"utf-16-le",   (encodefunc_t) utf16le_encode},
7994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"utf-16",      (encodefunc_t) utf16_encode},
8004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"utf-32-be",   (encodefunc_t) utf32be_encode},
8014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"utf-32-le",   (encodefunc_t) utf32le_encode},
8024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"utf-32",      (encodefunc_t) utf32_encode},
8034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {NULL, NULL}
8044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
8054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
8084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_init(textio *self, PyObject *args, PyObject *kwds)
8094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
8104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    char *kwlist[] = {"buffer", "encoding", "errors",
8114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                      "newline", "line_buffering",
8124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                      NULL};
8134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *buffer, *raw;
8144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    char *encoding = NULL;
8154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    char *errors = NULL;
8164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    char *newline = NULL;
8174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int line_buffering = 0;
8184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *res;
8204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int r;
8214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->ok = 0;
8234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->detached = 0;
8244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|zzzi:fileio",
8254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                     kwlist, &buffer, &encoding, &errors,
8264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                     &newline, &line_buffering))
8274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
8284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (newline && newline[0] != '\0'
8304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        && !(newline[0] == '\n' && newline[1] == '\0')
8314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        && !(newline[0] == '\r' && newline[1] == '\0')
8324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        && !(newline[0] == '\r' && newline[1] == '\n' && newline[2] == '\0')) {
8334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_Format(PyExc_ValueError,
8344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                     "illegal newline value: %s", newline);
8354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
8364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
8374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->buffer);
8394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->encoding);
8404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->encoder);
8414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->decoder);
8424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->readnl);
8434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->decoded_chars);
8444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->pending_bytes);
8454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->snapshot);
8464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->errors);
8474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->raw);
8484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->decoded_chars_used = 0;
8494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->pending_bytes_count = 0;
8504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->encodefunc = NULL;
8514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->writenl = NULL;
8524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (encoding == NULL && self->encoding == NULL) {
8544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (_PyIO_locale_module == NULL) {
8554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            _PyIO_locale_module = PyImport_ImportModule("locale");
8564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (_PyIO_locale_module == NULL)
8574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto catch_ImportError;
8584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else
8594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto use_locale;
8604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
8614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else {
8624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm          use_locale:
8634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self->encoding = PyObject_CallMethod(
8644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                _PyIO_locale_module, "getpreferredencoding", NULL);
8654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (self->encoding == NULL) {
8664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm              catch_ImportError:
8674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                /*
8684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                 Importing locale can raise a ImportError because of
8694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                 _functools, and locale.getpreferredencoding can raise a
8704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                 ImportError if _locale is not available.  These will happen
8714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                 during module building.
8724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                */
8734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (PyErr_ExceptionMatches(PyExc_ImportError)) {
8744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    PyErr_Clear();
8754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    self->encoding = PyString_FromString("ascii");
8764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                }
8774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                else
8784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    goto error;
8794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            }
8804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else if (!PyString_Check(self->encoding))
8814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                Py_CLEAR(self->encoding);
8824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
8834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
8844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->encoding != NULL)
8854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        encoding = PyString_AsString(self->encoding);
8864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else if (encoding != NULL) {
8874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->encoding = PyString_FromString(encoding);
8884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (self->encoding == NULL)
8894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto error;
8904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
8914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
8924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_IOError,
8934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        "could not determine default encoding");
8944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
8954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (errors == NULL)
8974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        errors = "strict";
8984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->errors = PyBytes_FromString(errors);
8994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->errors == NULL)
9004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto error;
9014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->chunk_size = 8192;
9034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->readuniversal = (newline == NULL || newline[0] == '\0');
9044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->line_buffering = line_buffering;
9054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->readtranslate = (newline == NULL);
9064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (newline) {
9074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->readnl = PyString_FromString(newline);
9084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (self->readnl == NULL)
9094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return -1;
9104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
9114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->writetranslate = (newline == NULL || newline[0] != '\0');
9124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!self->readuniversal && self->writetranslate) {
9134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->writenl = PyString_AsString(self->readnl);
9144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (!strcmp(self->writenl, "\n"))
9154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self->writenl = NULL;
9164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
9174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef MS_WINDOWS
9184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else
9194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->writenl = "\r\n";
9204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif
9214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* Build the decoder object */
9234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    res = PyObject_CallMethod(buffer, "readable", NULL);
9244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (res == NULL)
9254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto error;
9264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    r = PyObject_IsTrue(res);
9274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(res);
9284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (r == -1)
9294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto error;
9304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (r == 1) {
9314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->decoder = PyCodec_IncrementalDecoder(
9324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            encoding, errors);
9334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (self->decoder == NULL)
9344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto error;
9354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (self->readuniversal) {
9374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyObject *incrementalDecoder = PyObject_CallFunction(
9384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                (PyObject *)&PyIncrementalNewlineDecoder_Type,
9394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                "Oi", self->decoder, (int)self->readtranslate);
9404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (incrementalDecoder == NULL)
9414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto error;
9424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_CLEAR(self->decoder);
9434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self->decoder = incrementalDecoder;
9444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
9454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
9464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* Build the encoder object */
9484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    res = PyObject_CallMethod(buffer, "writable", NULL);
9494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (res == NULL)
9504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto error;
9514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    r = PyObject_IsTrue(res);
9524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(res);
9534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (r == -1)
9544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto error;
9554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (r == 1) {
9564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject *ci;
9574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->encoder = PyCodec_IncrementalEncoder(
9584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            encoding, errors);
9594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (self->encoder == NULL)
9604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto error;
9614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* Get the normalized named of the codec */
9624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ci = _PyCodec_Lookup(encoding);
9634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (ci == NULL)
9644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto error;
9654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        res = PyObject_GetAttrString(ci, "name");
9664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(ci);
9674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (res == NULL) {
9684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (PyErr_ExceptionMatches(PyExc_AttributeError))
9694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                PyErr_Clear();
9704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else
9714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto error;
9724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
9734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else if (PyString_Check(res)) {
9744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            encodefuncentry *e = encodefuncs;
9754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            while (e->name != NULL) {
9764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (!strcmp(PyString_AS_STRING(res), e->name)) {
9774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    self->encodefunc = e->encodefunc;
9784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    break;
9794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                }
9804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                e++;
9814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            }
9824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
9834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_XDECREF(res);
9844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
9854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->buffer = buffer;
9874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_INCREF(buffer);
9884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (Py_TYPE(buffer) == &PyBufferedReader_Type ||
9904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_TYPE(buffer) == &PyBufferedWriter_Type ||
9914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_TYPE(buffer) == &PyBufferedRandom_Type) {
9924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        raw = PyObject_GetAttrString(buffer, "raw");
9934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* Cache the raw FileIO object to speed up 'closed' checks */
9944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (raw == NULL) {
9954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (PyErr_ExceptionMatches(PyExc_AttributeError))
9964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                PyErr_Clear();
9974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else
9984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto error;
9994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
10004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else if (Py_TYPE(raw) == &PyFileIO_Type)
10014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self->raw = raw;
10024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else
10034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_DECREF(raw);
10044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
10054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    res = PyObject_CallMethod(buffer, "seekable", NULL);
10074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (res == NULL)
10084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto error;
10094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->seekable = self->telling = PyObject_IsTrue(res);
10104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(res);
10114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->encoding_start_of_stream = 0;
10134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->seekable && self->encoder) {
10144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject *cookieObj;
10154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        int cmp;
10164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->encoding_start_of_stream = 1;
10184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cookieObj = PyObject_CallMethodObjArgs(buffer, _PyIO_str_tell, NULL);
10204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (cookieObj == NULL)
10214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto error;
10224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmp = PyObject_RichCompareBool(cookieObj, _PyIO_zero, Py_EQ);
10244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(cookieObj);
10254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (cmp < 0) {
10264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto error;
10274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
10284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (cmp == 0) {
10304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self->encoding_start_of_stream = 0;
10314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            res = PyObject_CallMethodObjArgs(self->encoder, _PyIO_str_setstate,
10324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                             _PyIO_zero, NULL);
10334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (res == NULL)
10344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto error;
10354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_DECREF(res);
10364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
10374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
10384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->ok = 1;
10404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
10414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm  error:
10434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return -1;
10444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
10454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
10474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm_textiowrapper_clear(textio *self)
10484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
10494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
10504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
10514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->ok = 0;
10524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->buffer);
10534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->encoding);
10544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->encoder);
10554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->decoder);
10564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->readnl);
10574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->decoded_chars);
10584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->pending_bytes);
10594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->snapshot);
10604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->errors);
10614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->raw);
10624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
10634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
10644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void
10664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_dealloc(textio *self)
10674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
10684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (_textiowrapper_clear(self) < 0)
10694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return;
10704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    _PyObject_GC_UNTRACK(self);
10714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->weakreflist != NULL)
10724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject_ClearWeakRefs((PyObject *)self);
10734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->dict);
10744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_TYPE(self)->tp_free((PyObject *)self);
10754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
10764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
10784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_traverse(textio *self, visitproc visit, void *arg)
10794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
10804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_VISIT(self->buffer);
10814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_VISIT(self->encoding);
10824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_VISIT(self->encoder);
10834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_VISIT(self->decoder);
10844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_VISIT(self->readnl);
10854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_VISIT(self->decoded_chars);
10864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_VISIT(self->pending_bytes);
10874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_VISIT(self->snapshot);
10884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_VISIT(self->errors);
10894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_VISIT(self->raw);
10904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_VISIT(self->dict);
10924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
10934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
10944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
10964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_clear(textio *self)
10974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
10984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (_textiowrapper_clear(self) < 0)
10994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
11004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->dict);
11014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
11024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
11034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
11054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_closed_get(textio *self, void *context);
11064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* This macro takes some shortcuts to make the common case faster. */
11084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define CHECK_CLOSED(self) \
11094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    do { \
11104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        int r; \
11114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject *_res; \
11124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (Py_TYPE(self) == &PyTextIOWrapper_Type) { \
11134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (self->raw != NULL) \
11144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                r = _PyFileIO_closed(self->raw); \
11154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else { \
11164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                _res = textiowrapper_closed_get(self, NULL); \
11174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (_res == NULL) \
11184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    return NULL; \
11194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                r = PyObject_IsTrue(_res); \
11204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                Py_DECREF(_res); \
11214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (r < 0) \
11224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    return NULL; \
11234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            } \
11244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (r > 0) { \
11254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                PyErr_SetString(PyExc_ValueError, \
11264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                "I/O operation on closed file."); \
11274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return NULL; \
11284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            } \
11294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        } \
11304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else if (_PyIOBase_check_closed((PyObject *)self, Py_True) == NULL) \
11314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL; \
11324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    } while (0)
11334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define CHECK_INITIALIZED(self) \
11354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->ok <= 0) { \
11364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (self->detached) { \
11374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_SetString(PyExc_ValueError, \
11384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                 "underlying buffer has been detached"); \
11394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        } else {                                   \
11404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_SetString(PyExc_ValueError, \
11414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                "I/O operation on uninitialized object"); \
11424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        } \
11434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL; \
11444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
11454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define CHECK_INITIALIZED_INT(self) \
11474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->ok <= 0) { \
11484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (self->detached) { \
11494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_SetString(PyExc_ValueError, \
11504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                 "underlying buffer has been detached"); \
11514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        } else {                                   \
11524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_SetString(PyExc_ValueError, \
11534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                "I/O operation on uninitialized object"); \
11544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        } \
11554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1; \
11564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
11574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
11604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_detach(textio *self)
11614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
11624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *buffer, *res;
11634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_INITIALIZED(self);
11644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
11654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (res == NULL)
11664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
11674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(res);
11684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buffer = self->buffer;
11694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->buffer = NULL;
11704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->detached = 1;
11714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->ok = 0;
11724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return buffer;
11734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
11744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPy_LOCAL_INLINE(const Py_UNICODE *)
11764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfindchar(const Py_UNICODE *s, Py_ssize_t size, Py_UNICODE ch)
11774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
11784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* like wcschr, but doesn't stop at NULL characters */
11794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    while (size-- > 0) {
11804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (*s == ch)
11814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return s;
11824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        s++;
11834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
11844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return NULL;
11854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
11864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* Flush the internal write buffer. This doesn't explicitly flush the
11884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm   underlying buffered object, though. */
11894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
11904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm_textiowrapper_writeflush(textio *self)
11914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
11924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *pending, *b, *ret;
11934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->pending_bytes == NULL)
11954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return 0;
11964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    pending = self->pending_bytes;
11984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_INCREF(pending);
11994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->pending_bytes_count = 0;
12004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->pending_bytes);
12014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    b = _PyBytes_Join(_PyIO_empty_bytes, pending);
12034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(pending);
12044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (b == NULL)
12054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
12064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ret = PyObject_CallMethodObjArgs(self->buffer,
12074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                     _PyIO_str_write, b, NULL);
12084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(b);
12094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (ret == NULL)
12104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
12114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(ret);
12124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
12134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
12144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
12164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_write(textio *self, PyObject *args)
12174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
12184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *ret;
12194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *text; /* owned reference */
12204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *b;
12214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t textlen;
12224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int haslf = 0;
12234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int needflush = 0;
12244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_INITIALIZED(self);
12264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_ParseTuple(args, "U:write", &text)) {
12284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
12294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
12304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_CLOSED(self);
12324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->encoder == NULL) {
12344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_IOError, "not writable");
12354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
12364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
12374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_INCREF(text);
12394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    textlen = PyUnicode_GetSize(text);
12414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if ((self->writetranslate && self->writenl != NULL) || self->line_buffering)
12434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (findchar(PyUnicode_AS_UNICODE(text),
12444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                     PyUnicode_GET_SIZE(text), '\n'))
12454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            haslf = 1;
12464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (haslf && self->writetranslate && self->writenl != NULL) {
12484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject *newtext = PyObject_CallMethod(
12494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            text, "replace", "ss", "\n", self->writenl);
12504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(text);
12514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (newtext == NULL)
12524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
12534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        text = newtext;
12544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
12554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->line_buffering &&
12574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        (haslf ||
12584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm         findchar(PyUnicode_AS_UNICODE(text),
12594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                  PyUnicode_GET_SIZE(text), '\r')))
12604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        needflush = 1;
12614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* XXX What if we were just reading? */
12634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->encodefunc != NULL) {
12644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        b = (*self->encodefunc)((PyObject *) self, text);
12654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->encoding_start_of_stream = 0;
12664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
12674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else
12684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        b = PyObject_CallMethodObjArgs(self->encoder,
12694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                       _PyIO_str_encode, text, NULL);
12704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(text);
12714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (b == NULL)
12724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
12734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->pending_bytes == NULL) {
12754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->pending_bytes = PyList_New(0);
12764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (self->pending_bytes == NULL) {
12774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_DECREF(b);
12784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
12794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
12804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->pending_bytes_count = 0;
12814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
12824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (PyList_Append(self->pending_bytes, b) < 0) {
12834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(b);
12844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
12854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
12864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->pending_bytes_count += PyBytes_GET_SIZE(b);
12874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(b);
12884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->pending_bytes_count > self->chunk_size || needflush) {
12894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (_textiowrapper_writeflush(self) < 0)
12904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
12914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
12924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (needflush) {
12944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ret = PyObject_CallMethodObjArgs(self->buffer, _PyIO_str_flush, NULL);
12954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (ret == NULL)
12964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
12974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(ret);
12984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
12994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->snapshot);
13014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->decoder) {
13034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ret = PyObject_CallMethod(self->decoder, "reset", NULL);
13044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (ret == NULL)
13054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
13064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(ret);
13074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
13084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return PyLong_FromSsize_t(textlen);
13104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
13114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* Steal a reference to chars and store it in the decoded_char buffer;
13134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */
13144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void
13154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_set_decoded_chars(textio *self, PyObject *chars)
13164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
13174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->decoded_chars);
13184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->decoded_chars = chars;
13194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->decoded_chars_used = 0;
13204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
13214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
13234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_get_decoded_chars(textio *self, Py_ssize_t n)
13244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
13254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *chars;
13264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t avail;
13274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->decoded_chars == NULL)
13294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return PyUnicode_FromStringAndSize(NULL, 0);
13304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    avail = (PyUnicode_GET_SIZE(self->decoded_chars)
13324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm             - self->decoded_chars_used);
13334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    assert(avail >= 0);
13354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (n < 0 || n > avail)
13374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        n = avail;
13384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->decoded_chars_used > 0 || n < avail) {
13404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        chars = PyUnicode_FromUnicode(
13414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyUnicode_AS_UNICODE(self->decoded_chars)
13424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            + self->decoded_chars_used, n);
13434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (chars == NULL)
13444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
13454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
13464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
13474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        chars = self->decoded_chars;
13484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_INCREF(chars);
13494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
13504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->decoded_chars_used += n;
13524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return chars;
13534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
13544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* Read and decode the next chunk of data from the BufferedReader.
13564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */
13574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
13584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_read_chunk(textio *self)
13594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
13604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *dec_buffer = NULL;
13614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *dec_flags = NULL;
13624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *input_chunk = NULL;
13634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *decoded_chars, *chunk_size;
13644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int eof;
13654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* The return value is True unless EOF was reached.  The decoded string is
13674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * placed in self._decoded_chars (replacing its previous value).  The
13684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * entire input chunk is sent to the decoder, though some of it may remain
13694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * buffered in the decoder, yet to be converted.
13704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     */
13714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->decoder == NULL) {
13734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_IOError, "not readable");
13744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
13754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
13764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->telling) {
13784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* To prepare for tell(), we need to snapshot a point in the file
13794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm         * where the decoder's input buffer is empty.
13804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm         */
13814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject *state = PyObject_CallMethodObjArgs(self->decoder,
13834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                                     _PyIO_str_getstate, NULL);
13844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (state == NULL)
13854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return -1;
13864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* Given this, we know there was a valid snapshot point
13874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm         * len(dec_buffer) bytes ago with decoder state (b'', dec_flags).
13884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm         */
13894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (PyArg_Parse(state, "(OO)", &dec_buffer, &dec_flags) < 0) {
13904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_DECREF(state);
13914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return -1;
13924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
13934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_INCREF(dec_buffer);
13944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_INCREF(dec_flags);
13954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(state);
13964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
13974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* Read a chunk, decode it, and put the result in self._decoded_chars. */
13994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    chunk_size = PyLong_FromSsize_t(self->chunk_size);
14004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (chunk_size == NULL)
14014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto fail;
14024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    input_chunk = PyObject_CallMethodObjArgs(self->buffer,
14034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        _PyIO_str_read1, chunk_size, NULL);
14044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(chunk_size);
14054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (input_chunk == NULL)
14064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto fail;
14074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    assert(PyBytes_Check(input_chunk));
14084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    eof = (PyBytes_Size(input_chunk) == 0);
14104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (Py_TYPE(self->decoder) == &PyIncrementalNewlineDecoder_Type) {
14124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        decoded_chars = _PyIncrementalNewlineDecoder_decode(
14134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self->decoder, input_chunk, eof);
14144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
14154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
14164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        decoded_chars = PyObject_CallMethodObjArgs(self->decoder,
14174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            _PyIO_str_decode, input_chunk, eof ? Py_True : Py_False, NULL);
14184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
14194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* TODO sanity check: isinstance(decoded_chars, unicode) */
14214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (decoded_chars == NULL)
14224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto fail;
14234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    textiowrapper_set_decoded_chars(self, decoded_chars);
14244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (PyUnicode_GET_SIZE(decoded_chars) > 0)
14254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eof = 0;
14264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->telling) {
14284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* At the snapshot point, len(dec_buffer) bytes before the read, the
14294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm         * next input to be decoded is dec_buffer + input_chunk.
14304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm         */
14314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject *next_input = PyNumber_Add(dec_buffer, input_chunk);
14324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (next_input == NULL)
14334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
14344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        assert (PyBytes_Check(next_input));
14354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(dec_buffer);
14364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_CLEAR(self->snapshot);
14374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->snapshot = Py_BuildValue("NN", dec_flags, next_input);
14384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
14394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(input_chunk);
14404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return (eof == 0);
14424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm  fail:
14444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(dec_buffer);
14454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(dec_flags);
14464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(input_chunk);
14474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return -1;
14484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
14494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
14514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_read(textio *self, PyObject *args)
14524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
14534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t n = -1;
14544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *result = NULL, *chunks = NULL;
14554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_INITIALIZED(self);
14574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n))
14594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
14604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_CLOSED(self);
14624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->decoder == NULL) {
14644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_IOError, "not readable");
14654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
14664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
14674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (_textiowrapper_writeflush(self) < 0)
14694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
14704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (n < 0) {
14724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* Read everything */
14734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject *bytes = PyObject_CallMethod(self->buffer, "read", NULL);
14744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject *decoded, *final;
14754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (bytes == NULL)
14764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
14774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        decoded = PyObject_CallMethodObjArgs(self->decoder, _PyIO_str_decode,
14784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                             bytes, Py_True, NULL);
14794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(bytes);
14804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (decoded == NULL)
14814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
14824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        result = textiowrapper_get_decoded_chars(self, -1);
14844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (result == NULL) {
14864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_DECREF(decoded);
14874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
14884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
14894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        final = PyUnicode_Concat(result, decoded);
14914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(result);
14924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(decoded);
14934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (final == NULL)
14944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
14954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_CLEAR(self->snapshot);
14974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return final;
14984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
14994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
15004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        int res = 1;
15014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_ssize_t remaining = n;
15024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        result = textiowrapper_get_decoded_chars(self, n);
15044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (result == NULL)
15054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
15064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        remaining -= PyUnicode_GET_SIZE(result);
15074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* Keep reading chunks until we have n characters to return */
15094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        while (remaining > 0) {
15104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            res = textiowrapper_read_chunk(self);
15114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (res < 0)
15124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto fail;
15134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (res == 0)  /* EOF */
15144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                break;
15154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (chunks == NULL) {
15164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                chunks = PyList_New(0);
15174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (chunks == NULL)
15184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    goto fail;
15194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            }
15204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (PyList_Append(chunks, result) < 0)
15214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto fail;
15224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_DECREF(result);
15234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            result = textiowrapper_get_decoded_chars(self, remaining);
15244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (result == NULL)
15254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto fail;
15264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            remaining -= PyUnicode_GET_SIZE(result);
15274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
15284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (chunks != NULL) {
15294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (result != NULL && PyList_Append(chunks, result) < 0)
15304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto fail;
15314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_CLEAR(result);
15324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            result = PyUnicode_Join(_PyIO_empty_str, chunks);
15334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (result == NULL)
15344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto fail;
15354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_CLEAR(chunks);
15364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
15374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return result;
15384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
15394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm  fail:
15404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(result);
15414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(chunks);
15424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return NULL;
15434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
15444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* NOTE: `end` must point to the real end of the Py_UNICODE storage,
15474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm   that is to the NUL character. Otherwise the function will produce
15484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm   incorrect results. */
15494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic Py_UNICODE *
15504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfind_control_char(Py_UNICODE *start, Py_UNICODE *end, Py_UNICODE ch)
15514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
15524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_UNICODE *s = start;
15534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    for (;;) {
15544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        while (*s > ch)
15554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            s++;
15564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (*s == ch)
15574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return s;
15584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (s == end)
15594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
15604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        s++;
15614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
15624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
15634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPy_ssize_t
15654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm_PyIO_find_line_ending(
15664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int translated, int universal, PyObject *readnl,
15674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_UNICODE *start, Py_UNICODE *end, Py_ssize_t *consumed)
15684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
15694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t len = end - start;
15704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (translated) {
15724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* Newlines are already translated, only search for \n */
15734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_UNICODE *pos = find_control_char(start, end, '\n');
15744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (pos != NULL)
15754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return pos - start + 1;
15764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else {
15774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            *consumed = len;
15784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return -1;
15794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
15804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
15814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else if (universal) {
15824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* Universal newline search. Find any of \r, \r\n, \n
15834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm         * The decoder ensures that \r\n are not split in two pieces
15844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm         */
15854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_UNICODE *s = start;
15864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for (;;) {
15874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_UNICODE ch;
15884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            /* Fast path for non-control chars. The loop always ends
15894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm               since the Py_UNICODE storage is NUL-terminated. */
15904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            while (*s > '\r')
15914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                s++;
15924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (s >= end) {
15934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                *consumed = len;
15944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return -1;
15954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            }
15964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ch = *s++;
15974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (ch == '\n')
15984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return s - start;
15994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (ch == '\r') {
16004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (*s == '\n')
16014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    return s - start + 1;
16024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                else
16034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    return s - start;
16044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            }
16054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
16064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
16074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
16084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* Non-universal mode. */
16094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_ssize_t readnl_len = PyString_GET_SIZE(readnl);
16104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        unsigned char *nl = (unsigned char *) PyString_AS_STRING(readnl);
16114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (readnl_len == 1) {
16124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_UNICODE *pos = find_control_char(start, end, nl[0]);
16134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (pos != NULL)
16144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return pos - start + 1;
16154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            *consumed = len;
16164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return -1;
16174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
16184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else {
16194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_UNICODE *s = start;
16204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_UNICODE *e = end - readnl_len + 1;
16214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_UNICODE *pos;
16224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (e < s)
16234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                e = s;
16244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            while (s < e) {
16254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                Py_ssize_t i;
16264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                Py_UNICODE *pos = find_control_char(s, end, nl[0]);
16274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (pos == NULL || pos >= e)
16284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    break;
16294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                for (i = 1; i < readnl_len; i++) {
16304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    if (pos[i] != nl[i])
16314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        break;
16324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                }
16334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (i == readnl_len)
16344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    return pos - start + readnl_len;
16354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                s = pos + 1;
16364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            }
16374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            pos = find_control_char(e, end, nl[0]);
16384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (pos == NULL)
16394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                *consumed = len;
16404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else
16414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                *consumed = pos - start;
16424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return -1;
16434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
16444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
16454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
16464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
16484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm_textiowrapper_readline(textio *self, Py_ssize_t limit)
16494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
16504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *line = NULL, *chunks = NULL, *remaining = NULL;
16514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t start, endpos, chunked, offset_to_buffer;
16524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int res;
16534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_CLOSED(self);
16554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (_textiowrapper_writeflush(self) < 0)
16574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
16584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    chunked = 0;
16604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    while (1) {
16624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_UNICODE *ptr;
16634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_ssize_t line_len;
16644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_ssize_t consumed = 0;
16654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* First, get some data if necessary */
16674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        res = 1;
16684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        while (!self->decoded_chars ||
16694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm               !PyUnicode_GET_SIZE(self->decoded_chars)) {
16704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            res = textiowrapper_read_chunk(self);
16714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (res < 0)
16724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto error;
16734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (res == 0)
16744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                break;
16754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
16764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (res == 0) {
16774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            /* end of file */
16784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            textiowrapper_set_decoded_chars(self, NULL);
16794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_CLEAR(self->snapshot);
16804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            start = endpos = offset_to_buffer = 0;
16814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            break;
16824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
16834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (remaining == NULL) {
16854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            line = self->decoded_chars;
16864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            start = self->decoded_chars_used;
16874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            offset_to_buffer = 0;
16884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_INCREF(line);
16894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
16904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else {
16914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            assert(self->decoded_chars_used == 0);
16924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            line = PyUnicode_Concat(remaining, self->decoded_chars);
16934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            start = 0;
16944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            offset_to_buffer = PyUnicode_GET_SIZE(remaining);
16954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_CLEAR(remaining);
16964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (line == NULL)
16974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto error;
16984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
16994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ptr = PyUnicode_AS_UNICODE(line);
17014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        line_len = PyUnicode_GET_SIZE(line);
17024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        endpos = _PyIO_find_line_ending(
17044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self->readtranslate, self->readuniversal, self->readnl,
17054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ptr + start, ptr + line_len, &consumed);
17064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (endpos >= 0) {
17074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            endpos += start;
17084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (limit >= 0 && (endpos - start) + chunked >= limit)
17094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                endpos = start + limit - chunked;
17104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            break;
17114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
17124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* We can put aside up to `endpos` */
17144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        endpos = consumed + start;
17154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (limit >= 0 && (endpos - start) + chunked >= limit) {
17164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            /* Didn't find line ending, but reached length limit */
17174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            endpos = start + limit - chunked;
17184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            break;
17194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
17204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (endpos > start) {
17224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            /* No line ending seen yet - put aside current data */
17234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyObject *s;
17244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (chunks == NULL) {
17254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                chunks = PyList_New(0);
17264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (chunks == NULL)
17274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    goto error;
17284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            }
17294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            s = PyUnicode_FromUnicode(ptr + start, endpos - start);
17304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (s == NULL)
17314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto error;
17324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (PyList_Append(chunks, s) < 0) {
17334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                Py_DECREF(s);
17344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto error;
17354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            }
17364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            chunked += PyUnicode_GET_SIZE(s);
17374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_DECREF(s);
17384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
17394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* There may be some remaining bytes we'll have to prepend to the
17404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm           next chunk of data */
17414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (endpos < line_len) {
17424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            remaining = PyUnicode_FromUnicode(
17434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    ptr + endpos, line_len - endpos);
17444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (remaining == NULL)
17454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto error;
17464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
17474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_CLEAR(line);
17484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* We have consumed the buffer */
17494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        textiowrapper_set_decoded_chars(self, NULL);
17504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
17514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (line != NULL) {
17534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* Our line ends in the current buffer */
17544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->decoded_chars_used = endpos - offset_to_buffer;
17554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (start > 0 || endpos < PyUnicode_GET_SIZE(line)) {
17564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (start == 0 && Py_REFCNT(line) == 1) {
17574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (PyUnicode_Resize(&line, endpos) < 0)
17584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    goto error;
17594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            }
17604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else {
17614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                PyObject *s = PyUnicode_FromUnicode(
17624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        PyUnicode_AS_UNICODE(line) + start, endpos - start);
17634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                Py_CLEAR(line);
17644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (s == NULL)
17654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    goto error;
17664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                line = s;
17674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            }
17684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
17694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
17704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (remaining != NULL) {
17714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (chunks == NULL) {
17724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            chunks = PyList_New(0);
17734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (chunks == NULL)
17744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto error;
17754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
17764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (PyList_Append(chunks, remaining) < 0)
17774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto error;
17784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_CLEAR(remaining);
17794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
17804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (chunks != NULL) {
17814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (line != NULL && PyList_Append(chunks, line) < 0)
17824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto error;
17834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_CLEAR(line);
17844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        line = PyUnicode_Join(_PyIO_empty_str, chunks);
17854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (line == NULL)
17864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto error;
17874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(chunks);
17884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
17894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (line == NULL)
17904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        line = PyUnicode_FromStringAndSize(NULL, 0);
17914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return line;
17934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm  error:
17954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(chunks);
17964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(remaining);
17974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(line);
17984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return NULL;
17994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
18004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
18024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_readline(textio *self, PyObject *args)
18034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
18044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *limitobj = NULL;
18054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t limit = -1;
18064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_INITIALIZED(self);
18084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_ParseTuple(args, "|O:readline", &limitobj)) {
18094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
18104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
18114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (limitobj) {
18124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (!PyNumber_Check(limitobj)) {
18134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_Format(PyExc_TypeError,
18144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         "integer argument expected, got '%.200s'",
18154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         Py_TYPE(limitobj)->tp_name);
18164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
18174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
18184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        limit = PyNumber_AsSsize_t(limitobj, PyExc_OverflowError);
18194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (limit == -1 && PyErr_Occurred())
18204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
18214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
18224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return _textiowrapper_readline(self, limit);
18234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
18244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* Seek and Tell */
18264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtypedef struct {
18284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_off_t start_pos;
18294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int dec_flags;
18304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int bytes_to_feed;
18314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int chars_to_skip;
18324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    char need_eof;
18334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} cookie_type;
18344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/*
18364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm   To speed up cookie packing/unpacking, we store the fields in a temporary
18374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm   string and call _PyLong_FromByteArray() or _PyLong_AsByteArray (resp.).
18384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm   The following macros define at which offsets in the intermediary byte
18394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm   string the various CookieStruct fields will be stored.
18404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */
18414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define COOKIE_BUF_LEN      (sizeof(Py_off_t) + 3 * sizeof(int) + sizeof(char))
18434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#if defined(WORDS_BIGENDIAN)
18454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# define IS_LITTLE_ENDIAN   0
18474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* We want the least significant byte of start_pos to also be the least
18494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm   significant byte of the cookie, which means that in big-endian mode we
18504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm   must copy the fields in reverse order. */
18514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# define OFF_START_POS      (sizeof(char) + 3 * sizeof(int))
18534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# define OFF_DEC_FLAGS      (sizeof(char) + 2 * sizeof(int))
18544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# define OFF_BYTES_TO_FEED  (sizeof(char) + sizeof(int))
18554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# define OFF_CHARS_TO_SKIP  (sizeof(char))
18564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# define OFF_NEED_EOF       0
18574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else
18594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# define IS_LITTLE_ENDIAN   1
18614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* Little-endian mode: the least significant byte of start_pos will
18634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm   naturally end up the least significant byte of the cookie. */
18644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# define OFF_START_POS      0
18664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# define OFF_DEC_FLAGS      (sizeof(Py_off_t))
18674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# define OFF_BYTES_TO_FEED  (sizeof(Py_off_t) + sizeof(int))
18684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# define OFF_CHARS_TO_SKIP  (sizeof(Py_off_t) + 2 * sizeof(int))
18694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# define OFF_NEED_EOF       (sizeof(Py_off_t) + 3 * sizeof(int))
18704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif
18724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
18744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_parse_cookie(cookie_type *cookie, PyObject *cookieObj)
18754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
18764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    unsigned char buffer[COOKIE_BUF_LEN];
18774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyLongObject *cookieLong = (PyLongObject *)PyNumber_Long(cookieObj);
18784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (cookieLong == NULL)
18794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
18804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (_PyLong_AsByteArray(cookieLong, buffer, sizeof(buffer),
18824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            IS_LITTLE_ENDIAN, 0) < 0) {
18834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(cookieLong);
18844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
18854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
18864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(cookieLong);
18874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    memcpy(&cookie->start_pos, buffer + OFF_START_POS, sizeof(cookie->start_pos));
18894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    memcpy(&cookie->dec_flags, buffer + OFF_DEC_FLAGS, sizeof(cookie->dec_flags));
18904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    memcpy(&cookie->bytes_to_feed, buffer + OFF_BYTES_TO_FEED, sizeof(cookie->bytes_to_feed));
18914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    memcpy(&cookie->chars_to_skip, buffer + OFF_CHARS_TO_SKIP, sizeof(cookie->chars_to_skip));
18924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    memcpy(&cookie->need_eof, buffer + OFF_NEED_EOF, sizeof(cookie->need_eof));
18934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
18954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
18964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
18984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_build_cookie(cookie_type *cookie)
18994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
19004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    unsigned char buffer[COOKIE_BUF_LEN];
19014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    memcpy(buffer + OFF_START_POS, &cookie->start_pos, sizeof(cookie->start_pos));
19034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    memcpy(buffer + OFF_DEC_FLAGS, &cookie->dec_flags, sizeof(cookie->dec_flags));
19044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    memcpy(buffer + OFF_BYTES_TO_FEED, &cookie->bytes_to_feed, sizeof(cookie->bytes_to_feed));
19054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    memcpy(buffer + OFF_CHARS_TO_SKIP, &cookie->chars_to_skip, sizeof(cookie->chars_to_skip));
19064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    memcpy(buffer + OFF_NEED_EOF, &cookie->need_eof, sizeof(cookie->need_eof));
19074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return _PyLong_FromByteArray(buffer, sizeof(buffer), IS_LITTLE_ENDIAN, 0);
19094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
19104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#undef IS_LITTLE_ENDIAN
19114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
19134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm_textiowrapper_decoder_setstate(textio *self, cookie_type *cookie)
19144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
19154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *res;
19164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* When seeking to the start of the stream, we call decoder.reset()
19174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm       rather than decoder.getstate().
19184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm       This is for a few decoders such as utf-16 for which the state value
19194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm       at start is not (b"", 0) but e.g. (b"", 2) (meaning, in the case of
19204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm       utf-16, that we are expecting a BOM).
19214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    */
19224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (cookie->start_pos == 0 && cookie->dec_flags == 0)
19234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        res = PyObject_CallMethodObjArgs(self->decoder, _PyIO_str_reset, NULL);
19244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else
19254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        res = PyObject_CallMethod(self->decoder, "setstate",
19264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                  "((si))", "", cookie->dec_flags);
19274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (res == NULL)
19284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
19294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(res);
19304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
19314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
19324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
19344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm_textiowrapper_encoder_setstate(textio *self, cookie_type *cookie)
19354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
19364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *res;
19374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* Same as _textiowrapper_decoder_setstate() above. */
19384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (cookie->start_pos == 0 && cookie->dec_flags == 0) {
19394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        res = PyObject_CallMethodObjArgs(self->encoder, _PyIO_str_reset, NULL);
19404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->encoding_start_of_stream = 1;
19414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
19424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
19434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        res = PyObject_CallMethodObjArgs(self->encoder, _PyIO_str_setstate,
19444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                         _PyIO_zero, NULL);
19454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->encoding_start_of_stream = 0;
19464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
19474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (res == NULL)
19484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
19494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(res);
19504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
19514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
19524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
19544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_seek(textio *self, PyObject *args)
19554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
19564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *cookieObj, *posobj;
19574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    cookie_type cookie;
19584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int whence = 0;
19594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *res;
19604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int cmp;
19614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_INITIALIZED(self);
19634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_ParseTuple(args, "O|i:seek", &cookieObj, &whence))
19654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
19664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_CLOSED(self);
19674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_INCREF(cookieObj);
19694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!self->seekable) {
19714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_IOError,
19724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        "underlying stream is not seekable");
19734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto fail;
19744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
19754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (whence == 1) {
19774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* seek relative to current position */
19784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmp = PyObject_RichCompareBool(cookieObj, _PyIO_zero, Py_EQ);
19794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (cmp < 0)
19804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
19814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (cmp == 0) {
19834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_SetString(PyExc_IOError,
19844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            "can't do nonzero cur-relative seeks");
19854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
19864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
19874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* Seeking to the current position should attempt to
19894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm         * sync the underlying buffer with the current position.
19904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm         */
19914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(cookieObj);
19924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cookieObj = PyObject_CallMethod((PyObject *)self, "tell", NULL);
19934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (cookieObj == NULL)
19944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
19954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
19964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else if (whence == 2) {
19974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* seek relative to end of file */
19984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmp = PyObject_RichCompareBool(cookieObj, _PyIO_zero, Py_EQ);
20004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (cmp < 0)
20014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
20024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (cmp == 0) {
20044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_SetString(PyExc_IOError,
20054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            "can't do nonzero end-relative seeks");
20064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
20074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
20084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        res = PyObject_CallMethod((PyObject *)self, "flush", NULL);
20104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (res == NULL)
20114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
20124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(res);
20134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        textiowrapper_set_decoded_chars(self, NULL);
20154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_CLEAR(self->snapshot);
20164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (self->decoder) {
20174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            res = PyObject_CallMethod(self->decoder, "reset", NULL);
20184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (res == NULL)
20194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto fail;
20204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_DECREF(res);
20214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
20224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        res = PyObject_CallMethod(self->buffer, "seek", "ii", 0, 2);
20244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_XDECREF(cookieObj);
20254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return res;
20264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
20274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else if (whence != 0) {
20284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_Format(PyExc_ValueError,
20294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                     "invalid whence (%d, should be 0, 1 or 2)", whence);
20304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto fail;
20314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
20324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    cmp = PyObject_RichCompareBool(cookieObj, _PyIO_zero, Py_LT);
20344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (cmp < 0)
20354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto fail;
20364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (cmp == 1) {
20384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject *repr = PyObject_Repr(cookieObj);
20394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (repr != NULL) {
20404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_Format(PyExc_ValueError,
20414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         "negative seek position %s",
20424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         PyString_AS_STRING(repr));
20434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_DECREF(repr);
20444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
20454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto fail;
20464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
20474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
20494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (res == NULL)
20504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto fail;
20514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(res);
20524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* The strategy of seek() is to go back to the safe start point
20544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * and replay the effect of read(chars_to_skip) from there.
20554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     */
20564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (textiowrapper_parse_cookie(&cookie, cookieObj) < 0)
20574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto fail;
20584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* Seek back to the safe start point. */
20604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    posobj = PyLong_FromOff_t(cookie.start_pos);
20614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (posobj == NULL)
20624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto fail;
20634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    res = PyObject_CallMethodObjArgs(self->buffer,
20644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                     _PyIO_str_seek, posobj, NULL);
20654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(posobj);
20664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (res == NULL)
20674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto fail;
20684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(res);
20694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    textiowrapper_set_decoded_chars(self, NULL);
20714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_CLEAR(self->snapshot);
20724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* Restore the decoder to its state from the safe start point. */
20744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->decoder) {
20754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (_textiowrapper_decoder_setstate(self, &cookie) < 0)
20764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
20774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
20784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (cookie.chars_to_skip) {
20804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* Just like _read_chunk, feed the decoder and save a snapshot. */
20814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject *input_chunk = PyObject_CallMethod(
20824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self->buffer, "read", "i", cookie.bytes_to_feed);
20834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject *decoded;
20844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (input_chunk == NULL)
20864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
20874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        assert (PyBytes_Check(input_chunk));
20894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->snapshot = Py_BuildValue("iN", cookie.dec_flags, input_chunk);
20914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (self->snapshot == NULL) {
20924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_DECREF(input_chunk);
20934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
20944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
20954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        decoded = PyObject_CallMethod(self->decoder, "decode",
20974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                      "Oi", input_chunk, (int)cookie.need_eof);
20984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (decoded == NULL)
21004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
21014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        textiowrapper_set_decoded_chars(self, decoded);
21034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* Skip chars_to_skip of the decoded characters. */
21054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (PyUnicode_GetSize(self->decoded_chars) < cookie.chars_to_skip) {
21064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_SetString(PyExc_IOError, "can't restore logical file position");
21074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
21084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
21094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->decoded_chars_used = cookie.chars_to_skip;
21104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
21114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
21124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->snapshot = Py_BuildValue("is", cookie.dec_flags, "");
21134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (self->snapshot == NULL)
21144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
21154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
21164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* Finally, reset the encoder (merely useful for proper BOM handling) */
21184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->encoder) {
21194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (_textiowrapper_encoder_setstate(self, &cookie) < 0)
21204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
21214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
21224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return cookieObj;
21234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm  fail:
21244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(cookieObj);
21254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return NULL;
21264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
21284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
21304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_tell(textio *self, PyObject *args)
21314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
21324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *res;
21334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *posobj = NULL;
21344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    cookie_type cookie = {0,0,0,0,0};
21354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *next_input;
21364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t chars_to_skip, chars_decoded;
21374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *saved_state = NULL;
21384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    char *input, *input_end;
21394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_INITIALIZED(self);
21414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_CLOSED(self);
21424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!self->seekable) {
21444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_IOError,
21454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        "underlying stream is not seekable");
21464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto fail;
21474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
21484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!self->telling) {
21494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_IOError,
21504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        "telling position disabled by next() call");
21514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto fail;
21524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
21534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (_textiowrapper_writeflush(self) < 0)
21554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
21564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    res = PyObject_CallMethod((PyObject *)self, "flush", NULL);
21574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (res == NULL)
21584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto fail;
21594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(res);
21604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    posobj = PyObject_CallMethod(self->buffer, "tell", NULL);
21624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (posobj == NULL)
21634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto fail;
21644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->decoder == NULL || self->snapshot == NULL) {
21664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        assert (self->decoded_chars == NULL || PyUnicode_GetSize(self->decoded_chars) == 0);
21674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return posobj;
21684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
21694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#if defined(HAVE_LARGEFILE_SUPPORT)
21714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    cookie.start_pos = PyLong_AsLongLong(posobj);
21724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else
21734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    cookie.start_pos = PyLong_AsLong(posobj);
21744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif
21754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (PyErr_Occurred())
21764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto fail;
21774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* Skip backward to the snapshot point (see _read_chunk). */
21794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_Parse(self->snapshot, "(iO)", &cookie.dec_flags, &next_input))
21804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto fail;
21814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    assert (PyBytes_Check(next_input));
21834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    cookie.start_pos -= PyBytes_GET_SIZE(next_input);
21854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* How many decoded characters have been used up since the snapshot? */
21874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->decoded_chars_used == 0)  {
21884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* We haven't moved from the snapshot point. */
21894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(posobj);
21904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return textiowrapper_build_cookie(&cookie);
21914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
21924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    chars_to_skip = self->decoded_chars_used;
21944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* Starting from the snapshot position, we will walk the decoder
21964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * forward until it gives us enough decoded characters.
21974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     */
21984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    saved_state = PyObject_CallMethodObjArgs(self->decoder,
21994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                             _PyIO_str_getstate, NULL);
22004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (saved_state == NULL)
22014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto fail;
22024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* Note our initial start point. */
22044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (_textiowrapper_decoder_setstate(self, &cookie) < 0)
22054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto fail;
22064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* Feed the decoder one byte at a time.  As we go, note the
22084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * nearest "safe start point" before the current location
22094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * (a point where the decoder has nothing buffered, so seek()
22104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * can safely start from there and advance to this location).
22114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     */
22124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    chars_decoded = 0;
22134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    input = PyBytes_AS_STRING(next_input);
22144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    input_end = input + PyBytes_GET_SIZE(next_input);
22154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    while (input < input_end) {
22164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject *state;
22174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        char *dec_buffer;
22184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_ssize_t dec_buffer_len;
22194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        int dec_flags;
22204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject *decoded = PyObject_CallMethod(
22224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self->decoder, "decode", "s#", input, 1);
22234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (decoded == NULL)
22244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
22254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        assert (PyUnicode_Check(decoded));
22264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        chars_decoded += PyUnicode_GET_SIZE(decoded);
22274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(decoded);
22284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cookie.bytes_to_feed += 1;
22304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        state = PyObject_CallMethodObjArgs(self->decoder,
22324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                           _PyIO_str_getstate, NULL);
22334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (state == NULL)
22344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
22354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (!PyArg_Parse(state, "(s#i)", &dec_buffer, &dec_buffer_len, &dec_flags)) {
22364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_DECREF(state);
22374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
22384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
22394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(state);
22404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (dec_buffer_len == 0 && chars_decoded <= chars_to_skip) {
22424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            /* Decoder buffer is empty, so this is a safe start point. */
22434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            cookie.start_pos += cookie.bytes_to_feed;
22444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            chars_to_skip -= chars_decoded;
22454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            cookie.dec_flags = dec_flags;
22464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            cookie.bytes_to_feed = 0;
22474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            chars_decoded = 0;
22484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
22494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (chars_decoded >= chars_to_skip)
22504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            break;
22514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        input++;
22524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
22534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (input == input_end) {
22544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* We didn't get enough decoded data; signal EOF to get more. */
22554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject *decoded = PyObject_CallMethod(
22564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self->decoder, "decode", "si", "", /* final = */ 1);
22574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (decoded == NULL)
22584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
22594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        assert (PyUnicode_Check(decoded));
22604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        chars_decoded += PyUnicode_GET_SIZE(decoded);
22614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(decoded);
22624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cookie.need_eof = 1;
22634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (chars_decoded < chars_to_skip) {
22654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_SetString(PyExc_IOError,
22664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            "can't reconstruct logical file position");
22674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto fail;
22684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
22694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
22704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* finally */
22724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(posobj);
22734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    res = PyObject_CallMethod(self->decoder, "setstate", "(O)", saved_state);
22744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(saved_state);
22754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (res == NULL)
22764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
22774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(res);
22784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* The returned cookie corresponds to the last safe start point. */
22804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    cookie.chars_to_skip = Py_SAFE_DOWNCAST(chars_to_skip, Py_ssize_t, int);
22814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return textiowrapper_build_cookie(&cookie);
22824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm  fail:
22844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(posobj);
22854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (saved_state) {
22864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject *type, *value, *traceback;
22874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_Fetch(&type, &value, &traceback);
22884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        res = PyObject_CallMethod(self->decoder, "setstate", "(O)", saved_state);
22904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(saved_state);
22914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (res == NULL)
22924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
22934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(res);
22944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_Restore(type, value, traceback);
22964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
22974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return NULL;
22984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
22994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
23014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_truncate(textio *self, PyObject *args)
23024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
23034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *pos = Py_None;
23044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *res;
23054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_INITIALIZED(self)
23074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
23084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
23094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
23104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    res = PyObject_CallMethodObjArgs((PyObject *) self, _PyIO_str_flush, NULL);
23124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (res == NULL)
23134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
23144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(res);
23154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return PyObject_CallMethodObjArgs(self->buffer, _PyIO_str_truncate, pos, NULL);
23174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
23184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
23204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_repr(textio *self)
23214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
23224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *nameobj, *res;
23234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *namerepr = NULL, *encrepr = NULL;
23244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_INITIALIZED(self);
23264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    nameobj = PyObject_GetAttrString((PyObject *) self, "name");
23284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (nameobj == NULL) {
23294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (PyErr_ExceptionMatches(PyExc_AttributeError))
23304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_Clear();
23314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else
23324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto error;
23334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        encrepr = PyObject_Repr(self->encoding);
23344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        res = PyString_FromFormat("<_io.TextIOWrapper encoding=%s>",
23354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                   PyString_AS_STRING(encrepr));
23364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
23374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
23384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        encrepr = PyObject_Repr(self->encoding);
23394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        namerepr = PyObject_Repr(nameobj);
23404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        res = PyString_FromFormat("<_io.TextIOWrapper name=%s encoding=%s>",
23414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                   PyString_AS_STRING(namerepr),
23424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                   PyString_AS_STRING(encrepr));
23434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(nameobj);
23444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
23454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(namerepr);
23464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(encrepr);
23474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return res;
23484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmerror:
23504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(namerepr);
23514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(encrepr);
23524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return NULL;
23534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
23544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* Inquiries */
23574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
23594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_fileno(textio *self, PyObject *args)
23604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
23614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_INITIALIZED(self);
23624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return PyObject_CallMethod(self->buffer, "fileno", NULL);
23634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
23644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
23664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_seekable(textio *self, PyObject *args)
23674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
23684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_INITIALIZED(self);
23694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return PyObject_CallMethod(self->buffer, "seekable", NULL);
23704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
23714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
23734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_readable(textio *self, PyObject *args)
23744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
23754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_INITIALIZED(self);
23764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return PyObject_CallMethod(self->buffer, "readable", NULL);
23774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
23784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
23804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_writable(textio *self, PyObject *args)
23814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
23824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_INITIALIZED(self);
23834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return PyObject_CallMethod(self->buffer, "writable", NULL);
23844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
23854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
23874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_isatty(textio *self, PyObject *args)
23884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
23894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_INITIALIZED(self);
23904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return PyObject_CallMethod(self->buffer, "isatty", NULL);
23914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
23924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
23944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_flush(textio *self, PyObject *args)
23954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
23964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_INITIALIZED(self);
23974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_CLOSED(self);
23984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->telling = self->seekable;
23994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (_textiowrapper_writeflush(self) < 0)
24004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
24014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return PyObject_CallMethod(self->buffer, "flush", NULL);
24024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
24034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
24054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_close(textio *self, PyObject *args)
24064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
24074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *res;
24084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int r;
24094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_INITIALIZED(self);
24104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    res = textiowrapper_closed_get(self, NULL);
24124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (res == NULL)
24134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
24144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    r = PyObject_IsTrue(res);
24154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(res);
24164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (r < 0)
24174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
24184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (r > 0) {
24204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_RETURN_NONE; /* stream already closed */
24214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
24224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
24234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        res = PyObject_CallMethod((PyObject *)self, "flush", NULL);
24244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (res == NULL) {
24254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
24264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
24274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else
24284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_DECREF(res);
24294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return PyObject_CallMethod(self->buffer, "close", NULL);
24314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
24324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
24334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
24354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_iternext(textio *self)
24364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
24374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *line;
24384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_INITIALIZED(self);
24404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->telling = 0;
24424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (Py_TYPE(self) == &PyTextIOWrapper_Type) {
24434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* Skip method call overhead for speed */
24444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        line = _textiowrapper_readline(self, -1);
24454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
24464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
24474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        line = PyObject_CallMethodObjArgs((PyObject *)self,
24484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                           _PyIO_str_readline, NULL);
24494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (line && !PyUnicode_Check(line)) {
24504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_Format(PyExc_IOError,
24514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         "readline() should have returned an str object, "
24524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         "not '%.200s'", Py_TYPE(line)->tp_name);
24534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_DECREF(line);
24544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
24554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
24564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
24574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (line == NULL)
24594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
24604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (PyUnicode_GET_SIZE(line) == 0) {
24624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* Reached EOF or would have blocked */
24634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(line);
24644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_CLEAR(self->snapshot);
24654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->telling = self->seekable;
24664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
24674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
24684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return line;
24704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
24714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
24734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_name_get(textio *self, void *context)
24744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
24754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_INITIALIZED(self);
24764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return PyObject_GetAttrString(self->buffer, "name");
24774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
24784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
24804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_closed_get(textio *self, void *context)
24814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
24824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_INITIALIZED(self);
24834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return PyObject_GetAttr(self->buffer, _PyIO_str_closed);
24844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
24854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
24874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_newlines_get(textio *self, void *context)
24884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
24894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *res;
24904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_INITIALIZED(self);
24914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->decoder == NULL)
24924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_RETURN_NONE;
24934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    res = PyObject_GetAttr(self->decoder, _PyIO_str_newlines);
24944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (res == NULL) {
24954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
24964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_Clear();
24974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_RETURN_NONE;
24984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
24994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else {
25004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
25014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
25024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
25034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return res;
25044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
25054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
25064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
25074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_errors_get(textio *self, void *context)
25084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
25094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_INITIALIZED(self);
25104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_INCREF(self->errors);
25114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return self->errors;
25124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
25134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
25144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
25154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_chunk_size_get(textio *self, void *context)
25164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
25174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_INITIALIZED(self);
25184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return PyLong_FromSsize_t(self->chunk_size);
25194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
25204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
25214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
25224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtextiowrapper_chunk_size_set(textio *self, PyObject *arg, void *context)
25234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
25244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t n;
25254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    CHECK_INITIALIZED_INT(self);
25264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    n = PyNumber_AsSsize_t(arg, PyExc_TypeError);
25274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (n == -1 && PyErr_Occurred())
25284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
25294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (n <= 0) {
25304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_ValueError,
25314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        "a strictly positive integer is required");
25324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
25334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
25344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->chunk_size = n;
25354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
25364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
25374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
25384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyMethodDef textiowrapper_methods[] = {
25394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"detach", (PyCFunction)textiowrapper_detach, METH_NOARGS},
25404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"write", (PyCFunction)textiowrapper_write, METH_VARARGS},
25414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"read", (PyCFunction)textiowrapper_read, METH_VARARGS},
25424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"readline", (PyCFunction)textiowrapper_readline, METH_VARARGS},
25434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"flush", (PyCFunction)textiowrapper_flush, METH_NOARGS},
25444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"close", (PyCFunction)textiowrapper_close, METH_NOARGS},
25454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
25464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"fileno", (PyCFunction)textiowrapper_fileno, METH_NOARGS},
25474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"seekable", (PyCFunction)textiowrapper_seekable, METH_NOARGS},
25484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"readable", (PyCFunction)textiowrapper_readable, METH_NOARGS},
25494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"writable", (PyCFunction)textiowrapper_writable, METH_NOARGS},
25504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"isatty", (PyCFunction)textiowrapper_isatty, METH_NOARGS},
25514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
25524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"seek", (PyCFunction)textiowrapper_seek, METH_VARARGS},
25534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"tell", (PyCFunction)textiowrapper_tell, METH_NOARGS},
25544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"truncate", (PyCFunction)textiowrapper_truncate, METH_VARARGS},
25554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {NULL, NULL}
25564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
25574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
25584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyMemberDef textiowrapper_members[] = {
25594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"encoding", T_OBJECT, offsetof(textio, encoding), READONLY},
25604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"buffer", T_OBJECT, offsetof(textio, buffer), READONLY},
25614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"line_buffering", T_BOOL, offsetof(textio, line_buffering), READONLY},
25624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {NULL}
25634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
25644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
25654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyGetSetDef textiowrapper_getset[] = {
25664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"name", (getter)textiowrapper_name_get, NULL, NULL},
25674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"closed", (getter)textiowrapper_closed_get, NULL, NULL},
25684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/*    {"mode", (getter)TextIOWrapper_mode_get, NULL, NULL},
25694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm*/
25704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"newlines", (getter)textiowrapper_newlines_get, NULL, NULL},
25714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"errors", (getter)textiowrapper_errors_get, NULL, NULL},
25724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"_CHUNK_SIZE", (getter)textiowrapper_chunk_size_get,
25734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (setter)textiowrapper_chunk_size_set, NULL},
25744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {NULL}
25754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
25764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
25774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyTypeObject PyTextIOWrapper_Type = {
25784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyVarObject_HEAD_INIT(NULL, 0)
25794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "_io.TextIOWrapper",        /*tp_name*/
25804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    sizeof(textio), /*tp_basicsize*/
25814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_itemsize*/
25824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    (destructor)textiowrapper_dealloc, /*tp_dealloc*/
25834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_print*/
25844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_getattr*/
25854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tps_etattr*/
25864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_compare */
25874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    (reprfunc)textiowrapper_repr,/*tp_repr*/
25884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_as_number*/
25894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_as_sequence*/
25904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_as_mapping*/
25914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_hash */
25924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_call*/
25934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_str*/
25944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_getattro*/
25954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_setattro*/
25964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /*tp_as_buffer*/
25974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
25984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
25994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    textiowrapper_doc,          /* tp_doc */
26004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    (traverseproc)textiowrapper_traverse, /* tp_traverse */
26014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    (inquiry)textiowrapper_clear, /* tp_clear */
26024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_richcompare */
26034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    offsetof(textio, weakreflist), /*tp_weaklistoffset*/
26044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_iter */
26054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    (iternextfunc)textiowrapper_iternext, /* tp_iternext */
26064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    textiowrapper_methods,      /* tp_methods */
26074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    textiowrapper_members,      /* tp_members */
26084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    textiowrapper_getset,       /* tp_getset */
26094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_base */
26104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_dict */
26114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_descr_get */
26124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_descr_set */
26134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    offsetof(textio, dict), /*tp_dictoffset*/
26144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    (initproc)textiowrapper_init, /* tp_init */
26154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                          /* tp_alloc */
26164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyType_GenericNew,          /* tp_new */
26174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
2618