14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/*
24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * multibytecodec.c: Common Multibyte Codec Implementation
34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm *
44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * Written by Hye-Shik Chang <perky@FreeBSD.org>
54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */
64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define PY_SSIZE_T_CLEAN
84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "Python.h"
94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "structmember.h"
104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "multibytecodec.h"
114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtypedef struct {
134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    const Py_UNICODE    *inbuf, *inbuf_top, *inbuf_end;
144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    unsigned char       *outbuf, *outbuf_end;
154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject            *excobj, *outobj;
164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} MultibyteEncodeBuffer;
174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtypedef struct {
194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    const unsigned char *inbuf, *inbuf_top, *inbuf_end;
204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_UNICODE          *outbuf, *outbuf_end;
214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject            *excobj, *outobj;
224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} MultibyteDecodeBuffer;
234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(MultibyteCodec_Encode__doc__,
254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"I.encode(unicode[, errors]) -> (string, length consumed)\n\
264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\n\
274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmReturn an encoded string version of `unicode'. errors may be given to\n\
284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmset a different error handling scheme. Default is 'strict' meaning that\n\
294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmencoding errors raise a UnicodeEncodeError. Other possible values are\n\
304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm'ignore', 'replace' and 'xmlcharrefreplace' as well as any other name\n\
314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmregistered with codecs.register_error that can handle UnicodeEncodeErrors.");
324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(MultibyteCodec_Decode__doc__,
344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"I.decode(string[, errors]) -> (unicodeobject, length consumed)\n\
354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\n\
364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmDecodes `string' using I, an MultibyteCodec instance. errors may be given\n\
374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmto set a different error handling scheme. Default is 'strict' meaning\n\
384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmthat encoding errors raise a UnicodeDecodeError. Other possible values\n\
394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmare 'ignore' and 'replace' as well as any other name registered with\n\
404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmcodecs.register_error that is able to handle UnicodeDecodeErrors.");
414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic char *codeckwarglist[] = {"input", "errors", NULL};
434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic char *incnewkwarglist[] = {"errors", NULL};
444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic char *incrementalkwarglist[] = {"input", "final", NULL};
454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic char *streamkwarglist[] = {"stream", "errors", NULL};
464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *multibytecodec_encode(MultibyteCodec *,
484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                MultibyteCodec_State *, const Py_UNICODE **, Py_ssize_t,
494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                PyObject *, int);
504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define MBENC_RESET     MBENC_MAX<<1 /* reset after an encoding session */
524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmake_tuple(PyObject *object, Py_ssize_t len)
554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *v, *w;
574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (object == NULL)
594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    v = PyTuple_New(2);
624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (v == NULL) {
634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(object);
644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyTuple_SET_ITEM(v, 0, object);
674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    w = PyInt_FromSsize_t(len);
694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (w == NULL) {
704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(v);
714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyTuple_SET_ITEM(v, 1, w);
744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return v;
764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylminternal_error_callback(const char *errors)
804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (errors == NULL || strcmp(errors, "strict") == 0)
824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return ERROR_STRICT;
834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else if (strcmp(errors, "ignore") == 0)
844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return ERROR_IGNORE;
854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else if (strcmp(errors, "replace") == 0)
864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return ERROR_REPLACE;
874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else
884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return PyString_FromString(errors);
894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmcall_error_callback(PyObject *errors, PyObject *exc)
934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *args, *cb, *r;
954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    assert(PyString_Check(errors));
974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    cb = PyCodec_LookupError(PyString_AS_STRING(errors));
984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (cb == NULL)
994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    args = PyTuple_New(1);
1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (args == NULL) {
1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(cb);
1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyTuple_SET_ITEM(args, 0, exc);
1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_INCREF(exc);
1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    r = PyObject_CallObject(cb, args);
1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(args);
1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(cb);
1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return r;
1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmcodecctx_errors_get(MultibyteStatefulCodecContext *self)
1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    const char *errors;
1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->errors == ERROR_STRICT)
1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        errors = "strict";
1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else if (self->errors == ERROR_IGNORE)
1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        errors = "ignore";
1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else if (self->errors == ERROR_REPLACE)
1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        errors = "replace";
1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_INCREF(self->errors);
1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return self->errors;
1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return PyString_FromString(errors);
1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmcodecctx_errors_set(MultibyteStatefulCodecContext *self, PyObject *value,
1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    void *closure)
1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *cb;
1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyString_Check(value)) {
1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_TypeError, "errors must be a string");
1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    cb = internal_error_callback(PyString_AS_STRING(value));
1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (cb == NULL)
1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ERROR_DECREF(self->errors);
1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->errors = cb;
1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* This getset handlers list is used by all the stateful codec objects */
1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyGetSetDef codecctx_getsets[] = {
1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"errors",          (getter)codecctx_errors_get,
1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (setter)codecctx_errors_set,
1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    PyDoc_STR("how to treat errors")},
1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {NULL,}
1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmexpand_encodebuffer(MultibyteEncodeBuffer *buf, Py_ssize_t esize)
1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t orgpos, orgsize, incsize;
1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    orgpos = (Py_ssize_t)((char *)buf->outbuf -
1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            PyString_AS_STRING(buf->outobj));
1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    orgsize = PyString_GET_SIZE(buf->outobj);
1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    incsize = (esize < (orgsize >> 1) ? (orgsize >> 1) | 1 : esize);
1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (orgsize > PY_SSIZE_T_MAX - incsize)
1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (_PyString_Resize(&buf->outobj, orgsize + incsize) == -1)
1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf->outbuf = (unsigned char *)PyString_AS_STRING(buf->outobj) +orgpos;
1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf->outbuf_end = (unsigned char *)PyString_AS_STRING(buf->outobj)
1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        + PyString_GET_SIZE(buf->outobj);
1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define REQUIRE_ENCODEBUFFER(buf, s) {                                  \
1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if ((s) < 1 || (buf)->outbuf + (s) > (buf)->outbuf_end)             \
1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (expand_encodebuffer(buf, s) == -1)                          \
1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;                                             \
1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmexpand_decodebuffer(MultibyteDecodeBuffer *buf, Py_ssize_t esize)
1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
1944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t orgpos, orgsize;
1954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    orgpos = (Py_ssize_t)(buf->outbuf - PyUnicode_AS_UNICODE(buf->outobj));
1974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    orgsize = PyUnicode_GET_SIZE(buf->outobj);
1984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (PyUnicode_Resize(&buf->outobj, orgsize + (
1994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        esize < (orgsize >> 1) ? (orgsize >> 1) | 1 : esize)) == -1)
2004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
2014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf->outbuf = PyUnicode_AS_UNICODE(buf->outobj) + orgpos;
2034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf->outbuf_end = PyUnicode_AS_UNICODE(buf->outobj)
2044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                      + PyUnicode_GET_SIZE(buf->outobj);
2054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
2074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
2084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define REQUIRE_DECODEBUFFER(buf, s) {                                  \
2094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if ((s) < 1 || (buf)->outbuf + (s) > (buf)->outbuf_end)             \
2104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (expand_decodebuffer(buf, s) == -1)                          \
2114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;                                             \
2124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
2134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/**
2164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * MultibyteCodec object
2174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */
2184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
2204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmultibytecodec_encerror(MultibyteCodec *codec,
2214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        MultibyteCodec_State *state,
2224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        MultibyteEncodeBuffer *buf,
2234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        PyObject *errors, Py_ssize_t e)
2244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
2254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *retobj = NULL, *retstr = NULL, *tobj;
2264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t retstrsize, newpos;
2274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t esize, start, end;
2284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    const char *reason;
2294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (e > 0) {
2314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        reason = "illegal multibyte sequence";
2324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        esize = e;
2334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
2344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
2354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        switch (e) {
2364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        case MBERR_TOOSMALL:
2374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            REQUIRE_ENCODEBUFFER(buf, -1);
2384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return 0; /* retry it */
2394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        case MBERR_TOOFEW:
2404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            reason = "incomplete multibyte sequence";
2414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            esize = (Py_ssize_t)(buf->inbuf_end - buf->inbuf);
2424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            break;
2434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        case MBERR_INTERNAL:
2444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_SetString(PyExc_RuntimeError,
2454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            "internal codec error");
2464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return -1;
2474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        default:
2484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_SetString(PyExc_RuntimeError,
2494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            "unknown runtime error");
2504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return -1;
2514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
2524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
2534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (errors == ERROR_REPLACE) {
2554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        const Py_UNICODE replchar = '?', *inbuf = &replchar;
2564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_ssize_t r;
2574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for (;;) {
2594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_ssize_t outleft;
2604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            outleft = (Py_ssize_t)(buf->outbuf_end - buf->outbuf);
2624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            r = codec->encode(state, codec->config, &inbuf, 1,
2634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                              &buf->outbuf, outleft, 0);
2644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (r == MBERR_TOOSMALL) {
2654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                REQUIRE_ENCODEBUFFER(buf, -1);
2664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                continue;
2674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            }
2684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else
2694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                break;
2704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
2714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (r != 0) {
2734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            REQUIRE_ENCODEBUFFER(buf, 1);
2744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            *buf->outbuf++ = '?';
2754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
2764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
2774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (errors == ERROR_IGNORE || errors == ERROR_REPLACE) {
2784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        buf->inbuf += esize;
2794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return 0;
2804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
2814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    start = (Py_ssize_t)(buf->inbuf - buf->inbuf_top);
2834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    end = start + esize;
2844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* use cached exception object if available */
2864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (buf->excobj == NULL) {
2874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        buf->excobj = PyUnicodeEncodeError_Create(codec->encoding,
2884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        buf->inbuf_top,
2894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        buf->inbuf_end - buf->inbuf_top,
2904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        start, end, reason);
2914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (buf->excobj == NULL)
2924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;
2934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
2944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else
2954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (PyUnicodeEncodeError_SetStart(buf->excobj, start) != 0 ||
2964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyUnicodeEncodeError_SetEnd(buf->excobj, end) != 0 ||
2974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyUnicodeEncodeError_SetReason(buf->excobj, reason) != 0)
2984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;
2994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (errors == ERROR_STRICT) {
3014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyCodec_StrictErrors(buf->excobj);
3024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
3034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
3044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    retobj = call_error_callback(errors, buf->excobj);
3064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (retobj == NULL)
3074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
3084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyTuple_Check(retobj) || PyTuple_GET_SIZE(retobj) != 2 ||
3104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        !PyUnicode_Check((tobj = PyTuple_GET_ITEM(retobj, 0))) ||
3114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        !(PyInt_Check(PyTuple_GET_ITEM(retobj, 1)) ||
3124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm          PyLong_Check(PyTuple_GET_ITEM(retobj, 1)))) {
3134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_TypeError,
3144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        "encoding error handler must return "
3154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        "(unicode, int) tuple");
3164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
3174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
3184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {
3204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        const Py_UNICODE *uraw = PyUnicode_AS_UNICODE(tobj);
3214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        retstr = multibytecodec_encode(codec, state, &uraw,
3234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        PyUnicode_GET_SIZE(tobj), ERROR_STRICT,
3244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        MBENC_FLUSH);
3254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (retstr == NULL)
3264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;
3274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
3284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    retstrsize = PyString_GET_SIZE(retstr);
3304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    REQUIRE_ENCODEBUFFER(buf, retstrsize);
3314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    memcpy(buf->outbuf, PyString_AS_STRING(retstr), retstrsize);
3334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf->outbuf += retstrsize;
3344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    newpos = PyInt_AsSsize_t(PyTuple_GET_ITEM(retobj, 1));
3364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (newpos < 0 && !PyErr_Occurred())
3374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        newpos += (Py_ssize_t)(buf->inbuf_end - buf->inbuf_top);
3384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (newpos < 0 || buf->inbuf_top + newpos > buf->inbuf_end) {
3394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_Clear();
3404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_Format(PyExc_IndexError,
3414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                     "position %zd from error handler out of bounds",
3424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                     newpos);
3434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
3444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
3454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf->inbuf = buf->inbuf_top + newpos;
3464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(retobj);
3484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(retstr);
3494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
3504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmerrorexit:
3524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(retobj);
3534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(retstr);
3544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return -1;
3554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
3564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
3584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmultibytecodec_decerror(MultibyteCodec *codec,
3594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        MultibyteCodec_State *state,
3604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        MultibyteDecodeBuffer *buf,
3614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        PyObject *errors, Py_ssize_t e)
3624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
3634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *retobj = NULL, *retuni = NULL;
3644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t retunisize, newpos;
3654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    const char *reason;
3664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t esize, start, end;
3674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (e > 0) {
3694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        reason = "illegal multibyte sequence";
3704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        esize = e;
3714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
3724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
3734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        switch (e) {
3744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        case MBERR_TOOSMALL:
3754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            REQUIRE_DECODEBUFFER(buf, -1);
3764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return 0; /* retry it */
3774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        case MBERR_TOOFEW:
3784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            reason = "incomplete multibyte sequence";
3794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            esize = (Py_ssize_t)(buf->inbuf_end - buf->inbuf);
3804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            break;
3814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        case MBERR_INTERNAL:
3824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_SetString(PyExc_RuntimeError,
3834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            "internal codec error");
3844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return -1;
3854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        default:
3864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_SetString(PyExc_RuntimeError,
3874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            "unknown runtime error");
3884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return -1;
3894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
3904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
3914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (errors == ERROR_REPLACE) {
3934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        REQUIRE_DECODEBUFFER(buf, 1);
3944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        *buf->outbuf++ = Py_UNICODE_REPLACEMENT_CHARACTER;
3954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
3964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (errors == ERROR_IGNORE || errors == ERROR_REPLACE) {
3974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        buf->inbuf += esize;
3984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return 0;
3994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
4004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    start = (Py_ssize_t)(buf->inbuf - buf->inbuf_top);
4024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    end = start + esize;
4034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* use cached exception object if available */
4054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (buf->excobj == NULL) {
4064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        buf->excobj = PyUnicodeDecodeError_Create(codec->encoding,
4074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        (const char *)buf->inbuf_top,
4084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        (Py_ssize_t)(buf->inbuf_end - buf->inbuf_top),
4094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        start, end, reason);
4104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (buf->excobj == NULL)
4114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;
4124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
4134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else
4144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (PyUnicodeDecodeError_SetStart(buf->excobj, start) ||
4154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyUnicodeDecodeError_SetEnd(buf->excobj, end) ||
4164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyUnicodeDecodeError_SetReason(buf->excobj, reason))
4174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;
4184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (errors == ERROR_STRICT) {
4204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyCodec_StrictErrors(buf->excobj);
4214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
4224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
4234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    retobj = call_error_callback(errors, buf->excobj);
4254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (retobj == NULL)
4264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
4274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyTuple_Check(retobj) || PyTuple_GET_SIZE(retobj) != 2 ||
4294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        !PyUnicode_Check((retuni = PyTuple_GET_ITEM(retobj, 0))) ||
4304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        !(PyInt_Check(PyTuple_GET_ITEM(retobj, 1)) ||
4314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm          PyLong_Check(PyTuple_GET_ITEM(retobj, 1)))) {
4324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_TypeError,
4334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        "decoding error handler must return "
4344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        "(unicode, int) tuple");
4354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
4364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
4374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    retunisize = PyUnicode_GET_SIZE(retuni);
4394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (retunisize > 0) {
4404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        REQUIRE_DECODEBUFFER(buf, retunisize);
4414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        memcpy((char *)buf->outbuf, PyUnicode_AS_DATA(retuni),
4424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        retunisize * Py_UNICODE_SIZE);
4434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        buf->outbuf += retunisize;
4444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
4454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    newpos = PyInt_AsSsize_t(PyTuple_GET_ITEM(retobj, 1));
4474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (newpos < 0 && !PyErr_Occurred())
4484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        newpos += (Py_ssize_t)(buf->inbuf_end - buf->inbuf_top);
4494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (newpos < 0 || buf->inbuf_top + newpos > buf->inbuf_end) {
4504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_Clear();
4514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_Format(PyExc_IndexError,
4524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                     "position %zd from error handler out of bounds",
4534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                     newpos);
4544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
4554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
4564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf->inbuf = buf->inbuf_top + newpos;
4574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(retobj);
4584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
4594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmerrorexit:
4614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(retobj);
4624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return -1;
4634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
4644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
4664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmultibytecodec_encode(MultibyteCodec *codec,
4674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                      MultibyteCodec_State *state,
4684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                      const Py_UNICODE **data, Py_ssize_t datalen,
4694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                      PyObject *errors, int flags)
4704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
4714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    MultibyteEncodeBuffer buf;
4724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t finalsize, r = 0;
4734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (datalen == 0 && !(flags & MBENC_RESET))
4754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return PyString_FromString("");
4764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf.excobj = NULL;
4784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf.inbuf = buf.inbuf_top = *data;
4794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf.inbuf_end = buf.inbuf_top + datalen;
4804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (datalen > (PY_SSIZE_T_MAX - 16) / 2) {
4824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_NoMemory();
4834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
4844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
4854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf.outobj = PyString_FromStringAndSize(NULL, datalen * 2 + 16);
4874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (buf.outobj == NULL)
4884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
4894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf.outbuf = (unsigned char *)PyString_AS_STRING(buf.outobj);
4904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf.outbuf_end = buf.outbuf + PyString_GET_SIZE(buf.outobj);
4914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    while (buf.inbuf < buf.inbuf_end) {
4934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_ssize_t inleft, outleft;
4944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* we don't reuse inleft and outleft here.
4964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm         * error callbacks can relocate the cursor anywhere on buffer*/
4974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        inleft = (Py_ssize_t)(buf.inbuf_end - buf.inbuf);
4984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        outleft = (Py_ssize_t)(buf.outbuf_end - buf.outbuf);
4994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        r = codec->encode(state, codec->config, &buf.inbuf, inleft,
5004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                          &buf.outbuf, outleft, flags);
5014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if ((r == 0) || (r == MBERR_TOOFEW && !(flags & MBENC_FLUSH)))
5024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            break;
5034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else if (multibytecodec_encerror(codec, state, &buf, errors,r))
5044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;
5054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else if (r == MBERR_TOOFEW)
5064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            break;
5074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
5084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (codec->encreset != NULL && (flags & MBENC_RESET))
5104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for (;;) {
5114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_ssize_t outleft;
5124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            outleft = (Py_ssize_t)(buf.outbuf_end - buf.outbuf);
5144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            r = codec->encreset(state, codec->config, &buf.outbuf,
5154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                outleft);
5164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (r == 0)
5174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                break;
5184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else if (multibytecodec_encerror(codec, state,
5194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                             &buf, errors, r))
5204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto errorexit;
5214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
5224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    finalsize = (Py_ssize_t)((char *)buf.outbuf -
5244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             PyString_AS_STRING(buf.outobj));
5254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (finalsize != PyString_GET_SIZE(buf.outobj))
5274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (_PyString_Resize(&buf.outobj, finalsize) == -1)
5284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;
5294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm	*data = buf.inbuf;
5314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(buf.excobj);
5324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return buf.outobj;
5334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmerrorexit:
5354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(buf.excobj);
5364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(buf.outobj);
5374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return NULL;
5384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
5394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
5414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMultibyteCodec_Encode(MultibyteCodecObject *self,
5424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                      PyObject *args, PyObject *kwargs)
5434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
5444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    MultibyteCodec_State state;
5454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_UNICODE *data;
5464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *errorcb, *r, *arg, *ucvt;
5474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    const char *errors = NULL;
5484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t datalen;
5494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|z:encode",
5514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            codeckwarglist, &arg, &errors))
5524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
5534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (PyUnicode_Check(arg))
5554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ucvt = NULL;
5564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
5574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        arg = ucvt = PyObject_Unicode(arg);
5584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (arg == NULL)
5594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
5604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else if (!PyUnicode_Check(arg)) {
5614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_SetString(PyExc_TypeError,
5624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                "couldn't convert the object to unicode.");
5634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_DECREF(ucvt);
5644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
5654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
5664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
5674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    data = PyUnicode_AS_UNICODE(arg);
5694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    datalen = PyUnicode_GET_SIZE(arg);
5704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    errorcb = internal_error_callback(errors);
5724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (errorcb == NULL) {
5734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_XDECREF(ucvt);
5744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
5754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
5764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->codec->encinit != NULL &&
5784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->codec->encinit(&state, self->codec->config) != 0)
5794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
5804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    r = multibytecodec_encode(self->codec, &state,
5814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (const Py_UNICODE **)&data, datalen, errorcb,
5824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    MBENC_FLUSH | MBENC_RESET);
5834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (r == NULL)
5844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
5854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ERROR_DECREF(errorcb);
5874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(ucvt);
5884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return make_tuple(r, datalen);
5894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmerrorexit:
5914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ERROR_DECREF(errorcb);
5924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(ucvt);
5934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return NULL;
5944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
5954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
5974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMultibyteCodec_Decode(MultibyteCodecObject *self,
5984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                      PyObject *args, PyObject *kwargs)
5994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
6004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    MultibyteCodec_State state;
6014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    MultibyteDecodeBuffer buf;
6024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *errorcb;
6034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_buffer pdata;
6044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    const char *data, *errors = NULL;
6054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t datalen, finalsize;
6064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|z:decode",
6084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            codeckwarglist, &pdata, &errors))
6094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
6104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    data = pdata.buf;
6114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    datalen = pdata.len;
6124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    errorcb = internal_error_callback(errors);
6144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (errorcb == NULL) {
6154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyBuffer_Release(&pdata);
6164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
6174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
6184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (datalen == 0) {
6204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyBuffer_Release(&pdata);
6214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ERROR_DECREF(errorcb);
6224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return make_tuple(PyUnicode_FromUnicode(NULL, 0), 0);
6234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
6244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf.excobj = NULL;
6264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf.inbuf = buf.inbuf_top = (unsigned char *)data;
6274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf.inbuf_end = buf.inbuf_top + datalen;
6284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf.outobj = PyUnicode_FromUnicode(NULL, datalen);
6294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (buf.outobj == NULL)
6304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
6314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf.outbuf = PyUnicode_AS_UNICODE(buf.outobj);
6324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf.outbuf_end = buf.outbuf + PyUnicode_GET_SIZE(buf.outobj);
6334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->codec->decinit != NULL &&
6354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->codec->decinit(&state, self->codec->config) != 0)
6364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
6374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    while (buf.inbuf < buf.inbuf_end) {
6394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_ssize_t inleft, outleft, r;
6404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        inleft = (Py_ssize_t)(buf.inbuf_end - buf.inbuf);
6424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        outleft = (Py_ssize_t)(buf.outbuf_end - buf.outbuf);
6434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        r = self->codec->decode(&state, self->codec->config,
6454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        &buf.inbuf, inleft, &buf.outbuf, outleft);
6464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (r == 0)
6474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            break;
6484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else if (multibytecodec_decerror(self->codec, &state,
6494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                         &buf, errorcb, r))
6504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;
6514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
6524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    finalsize = (Py_ssize_t)(buf.outbuf -
6544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             PyUnicode_AS_UNICODE(buf.outobj));
6554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (finalsize != PyUnicode_GET_SIZE(buf.outobj))
6574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (PyUnicode_Resize(&buf.outobj, finalsize) == -1)
6584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;
6594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyBuffer_Release(&pdata);
6614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(buf.excobj);
6624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ERROR_DECREF(errorcb);
6634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return make_tuple(buf.outobj, datalen);
6644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmerrorexit:
6664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyBuffer_Release(&pdata);
6674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ERROR_DECREF(errorcb);
6684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(buf.excobj);
6694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(buf.outobj);
6704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return NULL;
6724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
6734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic struct PyMethodDef multibytecodec_methods[] = {
6754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"encode",          (PyCFunction)MultibyteCodec_Encode,
6764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    METH_VARARGS | METH_KEYWORDS,
6774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    MultibyteCodec_Encode__doc__},
6784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"decode",          (PyCFunction)MultibyteCodec_Decode,
6794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    METH_VARARGS | METH_KEYWORDS,
6804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    MultibyteCodec_Decode__doc__},
6814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {NULL,              NULL},
6824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
6834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void
6854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmultibytecodec_dealloc(MultibyteCodecObject *self)
6864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
6874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject_Del(self);
6884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
6894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyTypeObject MultibyteCodec_Type = {
6914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyVarObject_HEAD_INIT(NULL, 0)
6924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "MultibyteCodec",                   /* tp_name */
6934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    sizeof(MultibyteCodecObject),       /* tp_basicsize */
6944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_itemsize */
6954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* methods */
6964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    (destructor)multibytecodec_dealloc, /* tp_dealloc */
6974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_print */
6984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_getattr */
6994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_setattr */
7004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_compare */
7014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_repr */
7024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_as_number */
7034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_as_sequence */
7044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_as_mapping */
7054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_hash */
7064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_call */
7074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_str */
7084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject_GenericGetAttr,            /* tp_getattro */
7094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_setattro */
7104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_as_buffer */
7114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_TPFLAGS_DEFAULT,                 /* tp_flags */
7124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_doc */
7134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_traverse */
7144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_clear */
7154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_richcompare */
7164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_weaklistoffset */
7174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_iter */
7184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_iterext */
7194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    multibytecodec_methods,             /* tp_methods */
7204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
7214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/**
7244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * Utility functions for stateful codec mechanism
7254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */
7264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define STATEFUL_DCTX(o)        ((MultibyteStatefulDecoderContext *)(o))
7284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define STATEFUL_ECTX(o)        ((MultibyteStatefulEncoderContext *)(o))
7294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
7314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmencoder_encode_stateful(MultibyteStatefulEncoderContext *ctx,
7324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        PyObject *unistr, int final)
7334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
7344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *ucvt, *r = NULL;
7354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_UNICODE *inbuf, *inbuf_end, *inbuf_tmp = NULL;
7364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t datalen, origpending;
7374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (PyUnicode_Check(unistr))
7394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ucvt = NULL;
7404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
7414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        unistr = ucvt = PyObject_Unicode(unistr);
7424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (unistr == NULL)
7434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
7444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else if (!PyUnicode_Check(unistr)) {
7454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_SetString(PyExc_TypeError,
7464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                "couldn't convert the object to unicode.");
7474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_DECREF(ucvt);
7484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
7494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
7504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
7514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    datalen = PyUnicode_GET_SIZE(unistr);
7534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    origpending = ctx->pendingsize;
7544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (origpending > 0) {
7564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (datalen > PY_SSIZE_T_MAX - ctx->pendingsize) {
7574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_NoMemory();
7584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            /* inbuf_tmp == NULL */
7594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;
7604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
7614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        inbuf_tmp = PyMem_New(Py_UNICODE, datalen + ctx->pendingsize);
7624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (inbuf_tmp == NULL)
7634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;
7644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        memcpy(inbuf_tmp, ctx->pending,
7654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_UNICODE_SIZE * ctx->pendingsize);
7664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        memcpy(inbuf_tmp + ctx->pendingsize,
7674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyUnicode_AS_UNICODE(unistr),
7684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_UNICODE_SIZE * datalen);
7694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        datalen += ctx->pendingsize;
7704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ctx->pendingsize = 0;
7714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        inbuf = inbuf_tmp;
7724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
7734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else
7744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        inbuf = (Py_UNICODE *)PyUnicode_AS_UNICODE(unistr);
7754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    inbuf_end = inbuf + datalen;
7774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    r = multibytecodec_encode(ctx->codec, &ctx->state,
7794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    (const Py_UNICODE **)&inbuf, datalen,
7804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    ctx->errors, final ? MBENC_FLUSH | MBENC_RESET : 0);
7814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (r == NULL) {
7824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* recover the original pending buffer */
7834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (origpending > 0)
7844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            memcpy(ctx->pending, inbuf_tmp,
7854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                Py_UNICODE_SIZE * origpending);
7864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ctx->pendingsize = origpending;
7874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
7884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
7894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (inbuf < inbuf_end) {
7914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ctx->pendingsize = (Py_ssize_t)(inbuf_end - inbuf);
7924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (ctx->pendingsize > MAXENCPENDING) {
7934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            /* normal codecs can't reach here */
7944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ctx->pendingsize = 0;
7954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_SetString(PyExc_UnicodeError,
7964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            "pending buffer overflow");
7974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;
7984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
7994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        memcpy(ctx->pending, inbuf,
8004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ctx->pendingsize * Py_UNICODE_SIZE);
8014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
8024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (inbuf_tmp != NULL)
8044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyMem_Del(inbuf_tmp);
8054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(ucvt);
8064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return r;
8074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmerrorexit:
8094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (inbuf_tmp != NULL)
8104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyMem_Del(inbuf_tmp);
8114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(r);
8124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(ucvt);
8134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return NULL;
8144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
8154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
8174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdecoder_append_pending(MultibyteStatefulDecoderContext *ctx,
8184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       MultibyteDecodeBuffer *buf)
8194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
8204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t npendings;
8214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    npendings = (Py_ssize_t)(buf->inbuf_end - buf->inbuf);
8234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (npendings + ctx->pendingsize > MAXDECPENDING ||
8244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        npendings > PY_SSIZE_T_MAX - ctx->pendingsize) {
8254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_SetString(PyExc_UnicodeError, "pending buffer overflow");
8264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return -1;
8274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
8284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    memcpy(ctx->pending + ctx->pendingsize, buf->inbuf, npendings);
8294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ctx->pendingsize += npendings;
8304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
8314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
8324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
8344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdecoder_prepare_buffer(MultibyteDecodeBuffer *buf, const char *data,
8354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       Py_ssize_t size)
8364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
8374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf->inbuf = buf->inbuf_top = (const unsigned char *)data;
8384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf->inbuf_end = buf->inbuf_top + size;
8394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (buf->outobj == NULL) { /* only if outobj is not allocated yet */
8404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        buf->outobj = PyUnicode_FromUnicode(NULL, size);
8414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (buf->outobj == NULL)
8424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return -1;
8434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        buf->outbuf = PyUnicode_AS_UNICODE(buf->outobj);
8444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        buf->outbuf_end = buf->outbuf +
8454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                          PyUnicode_GET_SIZE(buf->outobj);
8464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
8474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
8494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
8504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
8524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdecoder_feed_buffer(MultibyteStatefulDecoderContext *ctx,
8534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    MultibyteDecodeBuffer *buf)
8544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
8554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    while (buf->inbuf < buf->inbuf_end) {
8564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_ssize_t inleft, outleft;
8574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_ssize_t r;
8584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        inleft = (Py_ssize_t)(buf->inbuf_end - buf->inbuf);
8604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        outleft = (Py_ssize_t)(buf->outbuf_end - buf->outbuf);
8614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        r = ctx->codec->decode(&ctx->state, ctx->codec->config,
8634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            &buf->inbuf, inleft, &buf->outbuf, outleft);
8644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (r == 0 || r == MBERR_TOOFEW)
8654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            break;
8664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else if (multibytecodec_decerror(ctx->codec, &ctx->state,
8674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                         buf, ctx->errors, r))
8684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return -1;
8694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
8704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
8714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
8724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/**
8754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * MultibyteIncrementalEncoder object
8764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */
8774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
8794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbiencoder_encode(MultibyteIncrementalEncoderObject *self,
8804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                  PyObject *args, PyObject *kwargs)
8814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
8824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *data;
8834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int final = 0;
8844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:encode",
8864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    incrementalkwarglist, &data, &final))
8874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
8884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return encoder_encode_stateful(STATEFUL_ECTX(self), data, final);
8904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
8914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
8934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbiencoder_reset(MultibyteIncrementalEncoderObject *self)
8944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
8954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->codec->decreset != NULL &&
8964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->codec->decreset(&self->state, self->codec->config) != 0)
8974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
8984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->pendingsize = 0;
8994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_RETURN_NONE;
9014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
9024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic struct PyMethodDef mbiencoder_methods[] = {
9044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"encode",          (PyCFunction)mbiencoder_encode,
9054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    METH_VARARGS | METH_KEYWORDS, NULL},
9064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"reset",           (PyCFunction)mbiencoder_reset,
9074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    METH_NOARGS, NULL},
9084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {NULL,              NULL},
9094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
9104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
9124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbiencoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
9134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
9144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    MultibyteIncrementalEncoderObject *self;
9154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *codec = NULL;
9164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    char *errors = NULL;
9174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|s:IncrementalEncoder",
9194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                     incnewkwarglist, &errors))
9204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
9214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self = (MultibyteIncrementalEncoderObject *)type->tp_alloc(type, 0);
9234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self == NULL)
9244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
9254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    codec = PyObject_GetAttrString((PyObject *)type, "codec");
9274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (codec == NULL)
9284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
9294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!MultibyteCodec_Check(codec)) {
9304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_TypeError, "codec is unexpected type");
9314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
9324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
9334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->codec = ((MultibyteCodecObject *)codec)->codec;
9354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->pendingsize = 0;
9364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->errors = internal_error_callback(errors);
9374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->errors == NULL)
9384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
9394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->codec->encinit != NULL &&
9404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->codec->encinit(&self->state, self->codec->config) != 0)
9414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
9424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(codec);
9444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return (PyObject *)self;
9454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmerrorexit:
9474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(self);
9484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(codec);
9494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return NULL;
9504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
9514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
9534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbiencoder_init(PyObject *self, PyObject *args, PyObject *kwds)
9544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
9554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
9564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
9574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
9594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbiencoder_traverse(MultibyteIncrementalEncoderObject *self,
9604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    visitproc visit, void *arg)
9614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
9624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (ERROR_ISCUSTOM(self->errors))
9634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_VISIT(self->errors);
9644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
9654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
9664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void
9684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbiencoder_dealloc(MultibyteIncrementalEncoderObject *self)
9694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
9704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject_GC_UnTrack(self);
9714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ERROR_DECREF(self->errors);
9724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_TYPE(self)->tp_free(self);
9734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
9744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyTypeObject MultibyteIncrementalEncoder_Type = {
9764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyVarObject_HEAD_INIT(NULL, 0)
9774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "MultibyteIncrementalEncoder",      /* tp_name */
9784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    sizeof(MultibyteIncrementalEncoderObject), /* tp_basicsize */
9794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_itemsize */
9804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /*  methods  */
9814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    (destructor)mbiencoder_dealloc, /* tp_dealloc */
9824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_print */
9834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_getattr */
9844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_setattr */
9854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_compare */
9864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_repr */
9874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_as_number */
9884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_as_sequence */
9894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_as_mapping */
9904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_hash */
9914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_call */
9924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_str */
9934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject_GenericGetAttr,            /* tp_getattro */
9944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_setattro */
9954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_as_buffer */
9964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
9974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        | Py_TPFLAGS_BASETYPE,          /* tp_flags */
9984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_doc */
9994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    (traverseproc)mbiencoder_traverse,          /* tp_traverse */
10004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_clear */
10014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_richcompare */
10024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_weaklistoffset */
10034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_iter */
10044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_iterext */
10054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    mbiencoder_methods,                 /* tp_methods */
10064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_members */
10074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    codecctx_getsets,                   /* tp_getset */
10084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_base */
10094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_dict */
10104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_descr_get */
10114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_descr_set */
10124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_dictoffset */
10134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    mbiencoder_init,                    /* tp_init */
10144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_alloc */
10154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    mbiencoder_new,                     /* tp_new */
10164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
10174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/**
10204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * MultibyteIncrementalDecoder object
10214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */
10224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
10244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbidecoder_decode(MultibyteIncrementalDecoderObject *self,
10254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                  PyObject *args, PyObject *kwargs)
10264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
10274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    MultibyteDecodeBuffer buf;
10284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    char *data, *wdata = NULL;
10294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_buffer pdata;
10304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t wsize, finalsize = 0, size, origpending;
10314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int final = 0;
10324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|i:decode",
10344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    incrementalkwarglist, &pdata, &final))
10354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
10364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    data = pdata.buf;
10374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    size = pdata.len;
10384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf.outobj = buf.excobj = NULL;
10404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    origpending = self->pendingsize;
10414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->pendingsize == 0) {
10434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        wsize = size;
10444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        wdata = data;
10454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
10464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
10474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (size > PY_SSIZE_T_MAX - self->pendingsize) {
10484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_NoMemory();
10494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;
10504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
10514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        wsize = size + self->pendingsize;
10524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        wdata = PyMem_Malloc(wsize);
10534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (wdata == NULL)
10544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;
10554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        memcpy(wdata, self->pending, self->pendingsize);
10564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        memcpy(wdata + self->pendingsize, data, size);
10574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->pendingsize = 0;
10584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
10594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (decoder_prepare_buffer(&buf, wdata, wsize) != 0)
10614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
10624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (decoder_feed_buffer(STATEFUL_DCTX(self), &buf))
10644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
10654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (final && buf.inbuf < buf.inbuf_end) {
10674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (multibytecodec_decerror(self->codec, &self->state,
10684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        &buf, self->errors, MBERR_TOOFEW)) {
10694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            /* recover the original pending buffer */
10704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            memcpy(self->pending, wdata, origpending);
10714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self->pendingsize = origpending;
10724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;
10734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
10744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
10754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (buf.inbuf < buf.inbuf_end) { /* pending sequence still exists */
10774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (decoder_append_pending(STATEFUL_DCTX(self), &buf) != 0)
10784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;
10794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
10804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    finalsize = (Py_ssize_t)(buf.outbuf - PyUnicode_AS_UNICODE(buf.outobj));
10824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (finalsize != PyUnicode_GET_SIZE(buf.outobj))
10834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (PyUnicode_Resize(&buf.outobj, finalsize) == -1)
10844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;
10854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyBuffer_Release(&pdata);
10874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (wdata != data)
10884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyMem_Del(wdata);
10894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(buf.excobj);
10904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return buf.outobj;
10914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmerrorexit:
10934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyBuffer_Release(&pdata);
10944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (wdata != NULL && wdata != data)
10954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyMem_Del(wdata);
10964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(buf.excobj);
10974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(buf.outobj);
10984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return NULL;
10994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
11004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
11024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbidecoder_reset(MultibyteIncrementalDecoderObject *self)
11034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
11044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->codec->decreset != NULL &&
11054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->codec->decreset(&self->state, self->codec->config) != 0)
11064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
11074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->pendingsize = 0;
11084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_RETURN_NONE;
11104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
11114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic struct PyMethodDef mbidecoder_methods[] = {
11134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"decode",          (PyCFunction)mbidecoder_decode,
11144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    METH_VARARGS | METH_KEYWORDS, NULL},
11154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"reset",           (PyCFunction)mbidecoder_reset,
11164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    METH_NOARGS, NULL},
11174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {NULL,              NULL},
11184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
11194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
11214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbidecoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
11224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
11234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    MultibyteIncrementalDecoderObject *self;
11244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *codec = NULL;
11254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    char *errors = NULL;
11264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|s:IncrementalDecoder",
11284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                     incnewkwarglist, &errors))
11294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
11304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self = (MultibyteIncrementalDecoderObject *)type->tp_alloc(type, 0);
11324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self == NULL)
11334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
11344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    codec = PyObject_GetAttrString((PyObject *)type, "codec");
11364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (codec == NULL)
11374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
11384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!MultibyteCodec_Check(codec)) {
11394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_TypeError, "codec is unexpected type");
11404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
11414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
11424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->codec = ((MultibyteCodecObject *)codec)->codec;
11444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->pendingsize = 0;
11454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->errors = internal_error_callback(errors);
11464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->errors == NULL)
11474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
11484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->codec->decinit != NULL &&
11494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->codec->decinit(&self->state, self->codec->config) != 0)
11504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
11514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(codec);
11534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return (PyObject *)self;
11544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmerrorexit:
11564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(self);
11574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(codec);
11584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return NULL;
11594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
11604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
11624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbidecoder_init(PyObject *self, PyObject *args, PyObject *kwds)
11634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
11644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
11654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
11664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
11684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbidecoder_traverse(MultibyteIncrementalDecoderObject *self,
11694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    visitproc visit, void *arg)
11704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
11714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (ERROR_ISCUSTOM(self->errors))
11724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_VISIT(self->errors);
11734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
11744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
11754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void
11774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbidecoder_dealloc(MultibyteIncrementalDecoderObject *self)
11784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
11794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject_GC_UnTrack(self);
11804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ERROR_DECREF(self->errors);
11814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_TYPE(self)->tp_free(self);
11824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
11834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyTypeObject MultibyteIncrementalDecoder_Type = {
11854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyVarObject_HEAD_INIT(NULL, 0)
11864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "MultibyteIncrementalDecoder",      /* tp_name */
11874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    sizeof(MultibyteIncrementalDecoderObject), /* tp_basicsize */
11884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_itemsize */
11894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /*  methods  */
11904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    (destructor)mbidecoder_dealloc, /* tp_dealloc */
11914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_print */
11924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_getattr */
11934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_setattr */
11944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_compare */
11954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_repr */
11964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_as_number */
11974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_as_sequence */
11984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_as_mapping */
11994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_hash */
12004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_call */
12014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_str */
12024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject_GenericGetAttr,            /* tp_getattro */
12034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_setattro */
12044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_as_buffer */
12054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
12064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        | Py_TPFLAGS_BASETYPE,          /* tp_flags */
12074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_doc */
12084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    (traverseproc)mbidecoder_traverse,          /* tp_traverse */
12094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_clear */
12104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_richcompare */
12114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_weaklistoffset */
12124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_iter */
12134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_iterext */
12144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    mbidecoder_methods,                 /* tp_methods */
12154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_members */
12164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    codecctx_getsets,                   /* tp_getset */
12174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_base */
12184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_dict */
12194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_descr_get */
12204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_descr_set */
12214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_dictoffset */
12224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    mbidecoder_init,                    /* tp_init */
12234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_alloc */
12244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    mbidecoder_new,                     /* tp_new */
12254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
12264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/**
12294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * MultibyteStreamReader object
12304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */
12314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
12334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbstreamreader_iread(MultibyteStreamReaderObject *self,
12344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                     const char *method, Py_ssize_t sizehint)
12354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
12364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    MultibyteDecodeBuffer buf;
12374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *cres;
12384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t rsize, finalsize = 0;
12394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (sizehint == 0)
12414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return PyUnicode_FromUnicode(NULL, 0);
12424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    buf.outobj = buf.excobj = NULL;
12444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    cres = NULL;
12454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    for (;;) {
12474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        int endoffile;
12484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (sizehint < 0)
12504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            cres = PyObject_CallMethod(self->stream,
12514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            (char *)method, NULL);
12524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else
12534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            cres = PyObject_CallMethod(self->stream,
12544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            (char *)method, "i", sizehint);
12554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (cres == NULL)
12564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;
12574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (!PyString_Check(cres)) {
12594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyErr_SetString(PyExc_TypeError,
12604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            "stream function returned a "
12614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            "non-string object");
12624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;
12634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
12644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        endoffile = (PyString_GET_SIZE(cres) == 0);
12664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (self->pendingsize > 0) {
12684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyObject *ctr;
12694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            char *ctrdata;
12704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (PyString_GET_SIZE(cres) > PY_SSIZE_T_MAX - self->pendingsize) {
12724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                PyErr_NoMemory();
12734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto errorexit;
12744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
12754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    rsize = PyString_GET_SIZE(cres) + self->pendingsize;
12764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    ctr = PyString_FromStringAndSize(NULL, rsize);
12774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    if (ctr == NULL)
12784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            goto errorexit;
12794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    ctrdata = PyString_AS_STRING(ctr);
12804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    memcpy(ctrdata, self->pending, self->pendingsize);
12814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    memcpy(ctrdata + self->pendingsize,
12824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            PyString_AS_STRING(cres),
12834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            PyString_GET_SIZE(cres));
12844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    Py_DECREF(cres);
12854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    cres = ctr;
12864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    self->pendingsize = 0;
12874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
12884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        rsize = PyString_GET_SIZE(cres);
12904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (decoder_prepare_buffer(&buf, PyString_AS_STRING(cres),
12914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                   rsize) != 0)
12924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;
12934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (rsize > 0 && decoder_feed_buffer(
12954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        (MultibyteStatefulDecoderContext *)self, &buf))
12964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;
12974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (endoffile || sizehint < 0) {
12994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (buf.inbuf < buf.inbuf_end &&
13004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                multibytecodec_decerror(self->codec, &self->state,
13014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            &buf, self->errors, MBERR_TOOFEW))
13024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto errorexit;
13034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
13044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (buf.inbuf < buf.inbuf_end) { /* pending sequence exists */
13064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (decoder_append_pending(STATEFUL_DCTX(self),
13074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                       &buf) != 0)
13084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                goto errorexit;
13094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
13104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        finalsize = (Py_ssize_t)(buf.outbuf -
13124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        PyUnicode_AS_UNICODE(buf.outobj));
13134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(cres);
13144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cres = NULL;
13154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (sizehint < 0 || finalsize != 0 || rsize == 0)
13174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            break;
13184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        sizehint = 1; /* read 1 more byte and retry */
13204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
13214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (finalsize != PyUnicode_GET_SIZE(buf.outobj))
13234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (PyUnicode_Resize(&buf.outobj, finalsize) == -1)
13244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto errorexit;
13254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(cres);
13274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(buf.excobj);
13284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return buf.outobj;
13294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmerrorexit:
13314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(cres);
13324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(buf.excobj);
13334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(buf.outobj);
13344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return NULL;
13354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
13364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
13384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbstreamreader_read(MultibyteStreamReaderObject *self, PyObject *args)
13394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
13404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *sizeobj = NULL;
13414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t size;
13424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_UnpackTuple(args, "read", 0, 1, &sizeobj))
13444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
13454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (sizeobj == Py_None || sizeobj == NULL)
13474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        size = -1;
13484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else if (PyInt_Check(sizeobj))
13494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        size = PyInt_AsSsize_t(sizeobj);
13504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
13514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_TypeError, "arg 1 must be an integer");
13524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
13534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
13544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return mbstreamreader_iread(self, "read", size);
13564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
13574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
13594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbstreamreader_readline(MultibyteStreamReaderObject *self, PyObject *args)
13604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
13614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *sizeobj = NULL;
13624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t size;
13634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_UnpackTuple(args, "readline", 0, 1, &sizeobj))
13654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
13664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (sizeobj == Py_None || sizeobj == NULL)
13684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        size = -1;
13694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else if (PyInt_Check(sizeobj))
13704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        size = PyInt_AsSsize_t(sizeobj);
13714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
13724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_TypeError, "arg 1 must be an integer");
13734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
13744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
13754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return mbstreamreader_iread(self, "readline", size);
13774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
13784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
13804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbstreamreader_readlines(MultibyteStreamReaderObject *self, PyObject *args)
13814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
13824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *sizehintobj = NULL, *r, *sr;
13834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_ssize_t sizehint;
13844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_UnpackTuple(args, "readlines", 0, 1, &sizehintobj))
13864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
13874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (sizehintobj == Py_None || sizehintobj == NULL)
13894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        sizehint = -1;
13904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else if (PyInt_Check(sizehintobj))
13914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        sizehint = PyInt_AsSsize_t(sizehintobj);
13924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
13934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_TypeError, "arg 1 must be an integer");
13944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
13954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
13964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    r = mbstreamreader_iread(self, "read", sizehint);
13984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (r == NULL)
13994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
14004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    sr = PyUnicode_Splitlines(r, 1);
14024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(r);
14034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return sr;
14044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
14054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
14074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbstreamreader_reset(MultibyteStreamReaderObject *self)
14084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
14094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->codec->decreset != NULL &&
14104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->codec->decreset(&self->state, self->codec->config) != 0)
14114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
14124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->pendingsize = 0;
14134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_RETURN_NONE;
14154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
14164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic struct PyMethodDef mbstreamreader_methods[] = {
14184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"read",            (PyCFunction)mbstreamreader_read,
14194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    METH_VARARGS, NULL},
14204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"readline",        (PyCFunction)mbstreamreader_readline,
14214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    METH_VARARGS, NULL},
14224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"readlines",       (PyCFunction)mbstreamreader_readlines,
14234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    METH_VARARGS, NULL},
14244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"reset",           (PyCFunction)mbstreamreader_reset,
14254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    METH_NOARGS, NULL},
14264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {NULL,              NULL},
14274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
14284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyMemberDef mbstreamreader_members[] = {
14304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"stream",          T_OBJECT,
14314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    offsetof(MultibyteStreamReaderObject, stream),
14324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    READONLY, NULL},
14334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {NULL,}
14344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
14354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
14374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbstreamreader_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
14384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
14394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    MultibyteStreamReaderObject *self;
14404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *stream, *codec = NULL;
14414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    char *errors = NULL;
14424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|s:StreamReader",
14444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            streamkwarglist, &stream, &errors))
14454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
14464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self = (MultibyteStreamReaderObject *)type->tp_alloc(type, 0);
14484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self == NULL)
14494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
14504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    codec = PyObject_GetAttrString((PyObject *)type, "codec");
14524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (codec == NULL)
14534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
14544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!MultibyteCodec_Check(codec)) {
14554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_TypeError, "codec is unexpected type");
14564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
14574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
14584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->codec = ((MultibyteCodecObject *)codec)->codec;
14604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->stream = stream;
14614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_INCREF(stream);
14624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->pendingsize = 0;
14634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->errors = internal_error_callback(errors);
14644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->errors == NULL)
14654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
14664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->codec->decinit != NULL &&
14674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->codec->decinit(&self->state, self->codec->config) != 0)
14684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
14694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(codec);
14714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return (PyObject *)self;
14724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmerrorexit:
14744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(self);
14754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(codec);
14764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return NULL;
14774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
14784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
14804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbstreamreader_init(PyObject *self, PyObject *args, PyObject *kwds)
14814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
14824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
14834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
14844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
14864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbstreamreader_traverse(MultibyteStreamReaderObject *self,
14874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        visitproc visit, void *arg)
14884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
14894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (ERROR_ISCUSTOM(self->errors))
14904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_VISIT(self->errors);
14914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_VISIT(self->stream);
14924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
14934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
14944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void
14964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbstreamreader_dealloc(MultibyteStreamReaderObject *self)
14974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
14984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject_GC_UnTrack(self);
14994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ERROR_DECREF(self->errors);
15004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(self->stream);
15014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_TYPE(self)->tp_free(self);
15024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
15034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyTypeObject MultibyteStreamReader_Type = {
15054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyVarObject_HEAD_INIT(NULL, 0)
15064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "MultibyteStreamReader",            /* tp_name */
15074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    sizeof(MultibyteStreamReaderObject), /* tp_basicsize */
15084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_itemsize */
15094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /*  methods  */
15104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    (destructor)mbstreamreader_dealloc, /* tp_dealloc */
15114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_print */
15124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_getattr */
15134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_setattr */
15144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_compare */
15154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_repr */
15164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_as_number */
15174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_as_sequence */
15184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_as_mapping */
15194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_hash */
15204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_call */
15214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_str */
15224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject_GenericGetAttr,            /* tp_getattro */
15234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_setattro */
15244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_as_buffer */
15254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
15264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        | Py_TPFLAGS_BASETYPE,          /* tp_flags */
15274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_doc */
15284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    (traverseproc)mbstreamreader_traverse,      /* tp_traverse */
15294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_clear */
15304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_richcompare */
15314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_weaklistoffset */
15324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_iter */
15334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_iterext */
15344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    mbstreamreader_methods,             /* tp_methods */
15354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    mbstreamreader_members,             /* tp_members */
15364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    codecctx_getsets,                   /* tp_getset */
15374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_base */
15384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_dict */
15394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_descr_get */
15404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_descr_set */
15414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_dictoffset */
15424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    mbstreamreader_init,                /* tp_init */
15434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_alloc */
15444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    mbstreamreader_new,                 /* tp_new */
15454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
15464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/**
15494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * MultibyteStreamWriter object
15504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */
15514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
15534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbstreamwriter_iwrite(MultibyteStreamWriterObject *self,
15544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                      PyObject *unistr)
15554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
15564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *str, *wr;
15574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    str = encoder_encode_stateful(STATEFUL_ECTX(self), unistr, 0);
15594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (str == NULL)
15604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
15614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    wr = PyObject_CallMethod(self->stream, "write", "O", str);
15634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(str);
15644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (wr == NULL)
15654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
15664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(wr);
15684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
15694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
15704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
15724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbstreamwriter_write(MultibyteStreamWriterObject *self, PyObject *strobj)
15734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
15744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (mbstreamwriter_iwrite(self, strobj))
15754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
15764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else
15774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_RETURN_NONE;
15784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
15794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
15814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbstreamwriter_writelines(MultibyteStreamWriterObject *self, PyObject *lines)
15824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
15834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *strobj;
15844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int i, r;
15854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PySequence_Check(lines)) {
15874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_TypeError,
15884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        "arg must be a sequence object");
15894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
15904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
15914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    for (i = 0; i < PySequence_Length(lines); i++) {
15934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* length can be changed even within this loop */
15944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        strobj = PySequence_GetItem(lines, i);
15954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (strobj == NULL)
15964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
15974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        r = mbstreamwriter_iwrite(self, strobj);
15994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(strobj);
16004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (r == -1)
16014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
16024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
16034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_RETURN_NONE;
16054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
16064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
16084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbstreamwriter_reset(MultibyteStreamWriterObject *self)
16094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
16104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    const Py_UNICODE *pending;
16114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *pwrt;
16124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    pending = self->pending;
16144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    pwrt = multibytecodec_encode(self->codec, &self->state,
16154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    &pending, self->pendingsize, self->errors,
16164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    MBENC_FLUSH | MBENC_RESET);
16174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* some pending buffer can be truncated when UnicodeEncodeError is
16184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * raised on 'strict' mode. but, 'reset' method is designed to
16194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * reset the pending buffer or states so failed string sequence
16204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * ought to be missed */
16214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->pendingsize = 0;
16224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (pwrt == NULL)
16234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
16244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (PyString_Size(pwrt) > 0) {
16264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject *wr;
16274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        wr = PyObject_CallMethod(self->stream, "write", "O", pwrt);
16284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (wr == NULL) {
16294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_DECREF(pwrt);
16304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NULL;
16314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
16324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
16334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(pwrt);
16344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_RETURN_NONE;
16364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
16374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
16394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbstreamwriter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
16404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
16414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    MultibyteStreamWriterObject *self;
16424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *stream, *codec = NULL;
16434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    char *errors = NULL;
16444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|s:StreamWriter",
16464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            streamkwarglist, &stream, &errors))
16474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
16484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self = (MultibyteStreamWriterObject *)type->tp_alloc(type, 0);
16504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self == NULL)
16514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
16524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    codec = PyObject_GetAttrString((PyObject *)type, "codec");
16544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (codec == NULL)
16554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
16564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!MultibyteCodec_Check(codec)) {
16574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_TypeError, "codec is unexpected type");
16584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
16594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
16604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->codec = ((MultibyteCodecObject *)codec)->codec;
16624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->stream = stream;
16634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_INCREF(stream);
16644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->pendingsize = 0;
16654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->errors = internal_error_callback(errors);
16664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->errors == NULL)
16674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
16684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->codec->encinit != NULL &&
16694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->codec->encinit(&self->state, self->codec->config) != 0)
16704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        goto errorexit;
16714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(codec);
16734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return (PyObject *)self;
16744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmerrorexit:
16764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(self);
16774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(codec);
16784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return NULL;
16794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
16804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
16824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbstreamwriter_init(PyObject *self, PyObject *args, PyObject *kwds)
16834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
16844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
16854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
16864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
16884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbstreamwriter_traverse(MultibyteStreamWriterObject *self,
16894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        visitproc visit, void *arg)
16904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
16914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (ERROR_ISCUSTOM(self->errors))
16924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_VISIT(self->errors);
16934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_VISIT(self->stream);
16944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
16954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
16964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void
16984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmbstreamwriter_dealloc(MultibyteStreamWriterObject *self)
16994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
17004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject_GC_UnTrack(self);
17014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ERROR_DECREF(self->errors);
17024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(self->stream);
17034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_TYPE(self)->tp_free(self);
17044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
17054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic struct PyMethodDef mbstreamwriter_methods[] = {
17074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"write",           (PyCFunction)mbstreamwriter_write,
17084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    METH_O, NULL},
17094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"writelines",      (PyCFunction)mbstreamwriter_writelines,
17104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    METH_O, NULL},
17114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"reset",           (PyCFunction)mbstreamwriter_reset,
17124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    METH_NOARGS, NULL},
17134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {NULL,              NULL},
17144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
17154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyMemberDef mbstreamwriter_members[] = {
17174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"stream",          T_OBJECT,
17184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    offsetof(MultibyteStreamWriterObject, stream),
17194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    READONLY, NULL},
17204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {NULL,}
17214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
17224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyTypeObject MultibyteStreamWriter_Type = {
17244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyVarObject_HEAD_INIT(NULL, 0)
17254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "MultibyteStreamWriter",            /* tp_name */
17264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    sizeof(MultibyteStreamWriterObject), /* tp_basicsize */
17274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_itemsize */
17284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /*  methods  */
17294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    (destructor)mbstreamwriter_dealloc, /* tp_dealloc */
17304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_print */
17314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_getattr */
17324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_setattr */
17334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_compare */
17344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_repr */
17354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_as_number */
17364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_as_sequence */
17374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_as_mapping */
17384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_hash */
17394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_call */
17404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_str */
17414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject_GenericGetAttr,            /* tp_getattro */
17424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_setattro */
17434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_as_buffer */
17444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
17454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        | Py_TPFLAGS_BASETYPE,          /* tp_flags */
17464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_doc */
17474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    (traverseproc)mbstreamwriter_traverse,      /* tp_traverse */
17484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_clear */
17494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_richcompare */
17504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_weaklistoffset */
17514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_iter */
17524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_iterext */
17534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    mbstreamwriter_methods,             /* tp_methods */
17544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    mbstreamwriter_members,             /* tp_members */
17554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    codecctx_getsets,                   /* tp_getset */
17564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_base */
17574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_dict */
17584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_descr_get */
17594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_descr_set */
17604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_dictoffset */
17614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    mbstreamwriter_init,                /* tp_init */
17624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                  /* tp_alloc */
17634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    mbstreamwriter_new,                 /* tp_new */
17644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
17654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/**
17684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * Exposed factory function
17694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */
17704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
17724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm__create_codec(PyObject *ignore, PyObject *arg)
17734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
17744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    MultibyteCodecObject *self;
17754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    MultibyteCodec *codec;
17764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyCapsule_IsValid(arg, PyMultibyteCodec_CAPSULE_NAME)) {
17784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_ValueError, "argument type invalid");
17794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
17804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
17814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    codec = PyCapsule_GetPointer(arg, PyMultibyteCodec_CAPSULE_NAME);
17834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (codec->codecinit != NULL && codec->codecinit(codec->config) != 0)
17844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
17854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self = PyObject_New(MultibyteCodecObject, &MultibyteCodec_Type);
17874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self == NULL)
17884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
17894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->codec = codec;
17904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return (PyObject *)self;
17924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
17934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic struct PyMethodDef __methods[] = {
17954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"__create_codec", (PyCFunction)__create_codec, METH_O},
17964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {NULL, NULL},
17974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
17984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyMODINIT_FUNC
18004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylminit_multibytecodec(void)
18014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
18024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int i;
18034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *m;
18044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyTypeObject *typelist[] = {
18054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        &MultibyteIncrementalEncoder_Type,
18064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        &MultibyteIncrementalDecoder_Type,
18074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        &MultibyteStreamReader_Type,
18084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        &MultibyteStreamWriter_Type,
18094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        NULL
18104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    };
18114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (PyType_Ready(&MultibyteCodec_Type) < 0)
18134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return;
18144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    m = Py_InitModule("_multibytecodec", __methods);
18164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (m == NULL)
18174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return;
18184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    for (i = 0; typelist[i] != NULL; i++) {
18204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (PyType_Ready(typelist[i]) < 0)
18214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return;
18224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_INCREF(typelist[i]);
18234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyModule_AddObject(m, typelist[i]->tp_name,
18244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                           (PyObject *)typelist[i]);
18254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
18264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (PyErr_Occurred())
18284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_FatalError("can't initialize the _multibytecodec module");
18294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
1830