17eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#include "Python.h"
27eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#include "structmember.h"
37eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#if PY_VERSION_HEX < 0x02060000 && !defined(Py_TYPE)
47eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#define Py_TYPE(ob)     (((PyObject*)(ob))->ob_type)
57eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#endif
67eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
77eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanieltypedef int Py_ssize_t;
87eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#define PY_SSIZE_T_MAX INT_MAX
97eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#define PY_SSIZE_T_MIN INT_MIN
107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#define PyInt_FromSsize_t PyInt_FromLong
117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#define PyInt_AsSsize_t PyInt_AsLong
127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#endif
137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#ifndef Py_IS_FINITE
147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#define Py_IS_FINITE(X) (!Py_IS_INFINITY(X) && !Py_IS_NAN(X))
157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#endif
167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#ifdef __GNUC__
187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#define UNUSED __attribute__((__unused__))
197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#else
207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#define UNUSED
217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#endif
227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#define DEFAULT_ENCODING "utf-8"
247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#define PyScanner_Check(op) PyObject_TypeCheck(op, &PyScannerType)
267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#define PyScanner_CheckExact(op) (Py_TYPE(op) == &PyScannerType)
277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#define PyEncoder_Check(op) PyObject_TypeCheck(op, &PyEncoderType)
287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#define PyEncoder_CheckExact(op) (Py_TYPE(op) == &PyEncoderType)
297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyTypeObject PyScannerType;
317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyTypeObject PyEncoderType;
327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanieltypedef struct _PyScannerObject {
347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject_HEAD
357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *encoding;
367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *strict;
377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *object_hook;
387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *pairs_hook;
397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *parse_float;
407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *parse_int;
417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *parse_constant;
427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel} PyScannerObject;
437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyMemberDef scanner_members[] = {
457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"encoding", T_OBJECT, offsetof(PyScannerObject, encoding), READONLY, "encoding"},
467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"strict", T_OBJECT, offsetof(PyScannerObject, strict), READONLY, "strict"},
477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"object_hook", T_OBJECT, offsetof(PyScannerObject, object_hook), READONLY, "object_hook"},
487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"object_pairs_hook", T_OBJECT, offsetof(PyScannerObject, pairs_hook), READONLY, "object_pairs_hook"},
497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"parse_float", T_OBJECT, offsetof(PyScannerObject, parse_float), READONLY, "parse_float"},
507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"parse_int", T_OBJECT, offsetof(PyScannerObject, parse_int), READONLY, "parse_int"},
517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"parse_constant", T_OBJECT, offsetof(PyScannerObject, parse_constant), READONLY, "parse_constant"},
527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {NULL}
537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel};
547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanieltypedef struct _PyEncoderObject {
567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject_HEAD
577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *markers;
587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *defaultfn;
597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *encoder;
607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *indent;
617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *key_separator;
627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *item_separator;
637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *sort_keys;
647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *skipkeys;
657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    int fast_encode;
667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    int allow_nan;
677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel} PyEncoderObject;
687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyMemberDef encoder_members[] = {
707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"markers", T_OBJECT, offsetof(PyEncoderObject, markers), READONLY, "markers"},
717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"default", T_OBJECT, offsetof(PyEncoderObject, defaultfn), READONLY, "default"},
727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"encoder", T_OBJECT, offsetof(PyEncoderObject, encoder), READONLY, "encoder"},
737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"indent", T_OBJECT, offsetof(PyEncoderObject, indent), READONLY, "indent"},
747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"key_separator", T_OBJECT, offsetof(PyEncoderObject, key_separator), READONLY, "key_separator"},
757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"item_separator", T_OBJECT, offsetof(PyEncoderObject, item_separator), READONLY, "item_separator"},
767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"sort_keys", T_OBJECT, offsetof(PyEncoderObject, sort_keys), READONLY, "sort_keys"},
777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"skipkeys", T_OBJECT, offsetof(PyEncoderObject, skipkeys), READONLY, "skipkeys"},
787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {NULL}
797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel};
807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic Py_ssize_t
827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielascii_escape_char(Py_UNICODE c, char *output, Py_ssize_t chars);
837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielascii_escape_unicode(PyObject *pystr);
857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielascii_escape_str(PyObject *pystr);
877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielpy_encode_basestring_ascii(PyObject* self UNUSED, PyObject *pystr);
897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielvoid init_json(void);
907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielscan_once_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr);
927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielscan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr);
947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel_build_rval_index_tuple(PyObject *rval, Py_ssize_t idx);
967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielscanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielscanner_init(PyObject *self, PyObject *args, PyObject *kwds);
1007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic void
1017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielscanner_dealloc(PyObject *self);
1027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
1037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielscanner_clear(PyObject *self);
1047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
1057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielencoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
1067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
1077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielencoder_init(PyObject *self, PyObject *args, PyObject *kwds);
1087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic void
1097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielencoder_dealloc(PyObject *self);
1107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
1117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielencoder_clear(PyObject *self);
1127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
1137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielencoder_listencode_list(PyEncoderObject *s, PyObject *rval, PyObject *seq, Py_ssize_t indent_level);
1147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
1157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielencoder_listencode_obj(PyEncoderObject *s, PyObject *rval, PyObject *obj, Py_ssize_t indent_level);
1167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
1177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielencoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ssize_t indent_level);
1187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
1197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel_encoded_const(PyObject *obj);
1207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic void
1217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielraise_errmsg(char *msg, PyObject *s, Py_ssize_t end);
1227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
1237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielencoder_encode_string(PyEncoderObject *s, PyObject *obj);
1247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
1257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel_convertPyInt_AsSsize_t(PyObject *o, Py_ssize_t *size_ptr);
1267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
1277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel_convertPyInt_FromSsize_t(Py_ssize_t *size_ptr);
1287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
1297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielencoder_encode_float(PyEncoderObject *s, PyObject *obj);
1307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#define S_CHAR(c) (c >= ' ' && c <= '~' && c != '\\' && c != '"')
1327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#define IS_WHITESPACE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\n') || ((c) == '\r'))
1337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#define MIN_EXPANSION 6
1357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#ifdef Py_UNICODE_WIDE
1367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#define MAX_EXPANSION (2 * MIN_EXPANSION)
1377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#else
1387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#define MAX_EXPANSION MIN_EXPANSION
1397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#endif
1407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
1427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel_convertPyInt_AsSsize_t(PyObject *o, Py_ssize_t *size_ptr)
1437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
1447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* PyObject to Py_ssize_t converter */
1457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *size_ptr = PyInt_AsSsize_t(o);
1467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (*size_ptr == -1 && PyErr_Occurred())
1477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return 0;
1487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return 1;
1497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
1507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
1527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel_convertPyInt_FromSsize_t(Py_ssize_t *size_ptr)
1537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
1547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Py_ssize_t to PyObject converter */
1557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return PyInt_FromSsize_t(*size_ptr);
1567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
1577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic Py_ssize_t
1597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielascii_escape_char(Py_UNICODE c, char *output, Py_ssize_t chars)
1607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
1617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Escape unicode code point c to ASCII escape sequences
1627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    in char *output. output must have at least 12 bytes unused to
1637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    accommodate an escaped surrogate pair "\uXXXX\uXXXX" */
1647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    output[chars++] = '\\';
1657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    switch (c) {
1667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case '\\': output[chars++] = (char)c; break;
1677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case '"': output[chars++] = (char)c; break;
1687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case '\b': output[chars++] = 'b'; break;
1697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case '\f': output[chars++] = 'f'; break;
1707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case '\n': output[chars++] = 'n'; break;
1717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case '\r': output[chars++] = 'r'; break;
1727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case '\t': output[chars++] = 't'; break;
1737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        default:
1747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#ifdef Py_UNICODE_WIDE
1757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (c >= 0x10000) {
1767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                /* UTF-16 surrogate pair */
1777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                Py_UNICODE v = c - 0x10000;
1787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                c = 0xd800 | ((v >> 10) & 0x3ff);
1797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                output[chars++] = 'u';
1807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                output[chars++] = "0123456789abcdef"[(c >> 12) & 0xf];
1817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                output[chars++] = "0123456789abcdef"[(c >>  8) & 0xf];
1827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                output[chars++] = "0123456789abcdef"[(c >>  4) & 0xf];
1837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                output[chars++] = "0123456789abcdef"[(c      ) & 0xf];
1847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                c = 0xdc00 | (v & 0x3ff);
1857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                output[chars++] = '\\';
1867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
1877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#endif
1887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            output[chars++] = 'u';
1897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            output[chars++] = "0123456789abcdef"[(c >> 12) & 0xf];
1907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            output[chars++] = "0123456789abcdef"[(c >>  8) & 0xf];
1917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            output[chars++] = "0123456789abcdef"[(c >>  4) & 0xf];
1927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            output[chars++] = "0123456789abcdef"[(c      ) & 0xf];
1937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
1947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return chars;
1957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
1967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
1977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
1987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielascii_escape_unicode(PyObject *pystr)
1997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
2007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Take a PyUnicode pystr and return a new ASCII-only escaped PyString */
2017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t i;
2027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t input_chars;
2037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t output_size;
2047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t max_output_size;
2057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t chars;
2067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *rval;
2077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    char *output;
2087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_UNICODE *input_unicode;
2097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
2107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    input_chars = PyUnicode_GET_SIZE(pystr);
2117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    input_unicode = PyUnicode_AS_UNICODE(pystr);
2127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
2137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* One char input can be up to 6 chars output, estimate 4 of these */
2147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    output_size = 2 + (MIN_EXPANSION * 4) + input_chars;
2157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    max_output_size = 2 + (input_chars * MAX_EXPANSION);
2167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    rval = PyString_FromStringAndSize(NULL, output_size);
2177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (rval == NULL) {
2187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
2197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
2207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    output = PyString_AS_STRING(rval);
2217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    chars = 0;
2227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    output[chars++] = '"';
2237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    for (i = 0; i < input_chars; i++) {
2247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_UNICODE c = input_unicode[i];
2257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (S_CHAR(c)) {
2267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            output[chars++] = (char)c;
2277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
2287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        else {
2297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            chars = ascii_escape_char(c, output, chars);
2307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
2317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (output_size - chars < (1 + MAX_EXPANSION)) {
2327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* There's more than four, so let's resize by a lot */
2337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_ssize_t new_output_size = output_size * 2;
2347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* This is an upper bound */
2357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (new_output_size > max_output_size) {
2367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                new_output_size = max_output_size;
2377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
2387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* Make sure that the output size changed before resizing */
2397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (new_output_size != output_size) {
2407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                output_size = new_output_size;
2417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                if (_PyString_Resize(&rval, output_size) == -1) {
2427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    return NULL;
2437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                }
2447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                output = PyString_AS_STRING(rval);
2457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
2467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
2477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
2487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    output[chars++] = '"';
2497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (_PyString_Resize(&rval, chars) == -1) {
2507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
2517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
2527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return rval;
2537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
2547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
2557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
2567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielascii_escape_str(PyObject *pystr)
2577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
2587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Take a PyString pystr and return a new ASCII-only escaped PyString */
2597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t i;
2607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t input_chars;
2617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t output_size;
2627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t chars;
2637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *rval;
2647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    char *output;
2657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    char *input_str;
2667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
2677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    input_chars = PyString_GET_SIZE(pystr);
2687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    input_str = PyString_AS_STRING(pystr);
2697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
2707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Fast path for a string that's already ASCII */
2717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    for (i = 0; i < input_chars; i++) {
2727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_UNICODE c = (Py_UNICODE)(unsigned char)input_str[i];
2737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (!S_CHAR(c)) {
2747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* If we have to escape something, scan the string for unicode */
2757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_ssize_t j;
2767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            for (j = i; j < input_chars; j++) {
2777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                c = (Py_UNICODE)(unsigned char)input_str[j];
2787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                if (c > 0x7f) {
2797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    /* We hit a non-ASCII character, bail to unicode mode */
2807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    PyObject *uni;
2817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    uni = PyUnicode_DecodeUTF8(input_str, input_chars, "strict");
2827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    if (uni == NULL) {
2837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        return NULL;
2847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    }
2857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    rval = ascii_escape_unicode(uni);
2867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    Py_DECREF(uni);
2877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    return rval;
2887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                }
2897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
2907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            break;
2917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
2927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
2937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
2947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (i == input_chars) {
2957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* Input is already ASCII */
2967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        output_size = 2 + input_chars;
2977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
2987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else {
2997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* One char input can be up to 6 chars output, estimate 4 of these */
3007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        output_size = 2 + (MIN_EXPANSION * 4) + input_chars;
3017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
3027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    rval = PyString_FromStringAndSize(NULL, output_size);
3037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (rval == NULL) {
3047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
3057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
3067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    output = PyString_AS_STRING(rval);
3077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    output[0] = '"';
3087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
3097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* We know that everything up to i is ASCII already */
3107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    chars = i + 1;
3117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    memcpy(&output[1], input_str, i);
3127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
3137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    for (; i < input_chars; i++) {
3147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_UNICODE c = (Py_UNICODE)(unsigned char)input_str[i];
3157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (S_CHAR(c)) {
3167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            output[chars++] = (char)c;
3177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
3187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        else {
3197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            chars = ascii_escape_char(c, output, chars);
3207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
3217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* An ASCII char can't possibly expand to a surrogate! */
3227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (output_size - chars < (1 + MIN_EXPANSION)) {
3237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* There's more than four, so let's resize by a lot */
3247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            output_size *= 2;
3257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (output_size > 2 + (input_chars * MIN_EXPANSION)) {
3267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                output_size = 2 + (input_chars * MIN_EXPANSION);
3277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
3287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (_PyString_Resize(&rval, output_size) == -1) {
3297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return NULL;
3307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
3317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            output = PyString_AS_STRING(rval);
3327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
3337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
3347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    output[chars++] = '"';
3357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (_PyString_Resize(&rval, chars) == -1) {
3367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
3377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
3387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return rval;
3397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
3407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
3417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic void
3427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielraise_errmsg(char *msg, PyObject *s, Py_ssize_t end)
3437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
3447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Use the Python function json.decoder.errmsg to raise a nice
3457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    looking ValueError exception */
3467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    static PyObject *errmsg_fn = NULL;
3477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *pymsg;
3487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (errmsg_fn == NULL) {
3497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyObject *decoder = PyImport_ImportModule("json.decoder");
3507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (decoder == NULL)
3517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return;
3527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        errmsg_fn = PyObject_GetAttrString(decoder, "errmsg");
3537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(decoder);
3547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (errmsg_fn == NULL)
3557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return;
3567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
3577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    pymsg = PyObject_CallFunction(errmsg_fn, "(zOO&)", msg, s, _convertPyInt_FromSsize_t, &end);
3587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (pymsg) {
3597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_SetObject(PyExc_ValueError, pymsg);
3607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(pymsg);
3617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
3627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
3637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
3647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
3657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanieljoin_list_unicode(PyObject *lst)
3667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
3677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* return u''.join(lst) */
3687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    static PyObject *joinfn = NULL;
3697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (joinfn == NULL) {
3707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyObject *ustr = PyUnicode_FromUnicode(NULL, 0);
3717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (ustr == NULL)
3727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return NULL;
3737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
3747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        joinfn = PyObject_GetAttrString(ustr, "join");
3757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(ustr);
3767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (joinfn == NULL)
3777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return NULL;
3787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
3797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return PyObject_CallFunctionObjArgs(joinfn, lst, NULL);
3807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
3817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
3827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
3837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel_build_rval_index_tuple(PyObject *rval, Py_ssize_t idx) {
3847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* return (rval, idx) tuple, stealing reference to rval */
3857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *tpl;
3867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *pyidx;
3877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /*
3887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    steal a reference to rval, returns (rval, idx)
3897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    */
3907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (rval == NULL) {
3917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
3927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
3937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    pyidx = PyInt_FromSsize_t(idx);
3947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (pyidx == NULL) {
3957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(rval);
3967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
3977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
3987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    tpl = PyTuple_New(2);
3997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (tpl == NULL) {
4007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(pyidx);
4017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(rval);
4027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
4037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
4047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyTuple_SET_ITEM(tpl, 0, rval);
4057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyTuple_SET_ITEM(tpl, 1, pyidx);
4067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return tpl;
4077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
4087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
4097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
4107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielscanstring_str(PyObject *pystr, Py_ssize_t end, char *encoding, int strict, Py_ssize_t *next_end_ptr)
4117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
4127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Read the JSON string from PyString pystr.
4137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    end is the index of the first character after the quote.
4147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    encoding is the encoding of pystr (must be an ASCII superset)
4157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if strict is zero then literal control characters are allowed
4167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *next_end_ptr is a return-by-reference index of the character
4177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        after the end quote
4187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
4197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Return value is a new PyString (if ASCII-only) or PyUnicode
4207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    */
4217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *rval;
4227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t len = PyString_GET_SIZE(pystr);
4237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t begin = end - 1;
4247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t next;
4257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    char *buf = PyString_AS_STRING(pystr);
4267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *chunks = PyList_New(0);
4277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (chunks == NULL) {
4287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
4297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
4307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (end < 0 || len <= end) {
4317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_SetString(PyExc_ValueError, "end is out of bounds");
4327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
4337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
4347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    while (1) {
4357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* Find the end of the string or the next escape */
4367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_UNICODE c = 0;
4377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyObject *chunk = NULL;
4387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        for (next = end; next < len; next++) {
4397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            c = (unsigned char)buf[next];
4407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (c == '"' || c == '\\') {
4417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                break;
4427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
4437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            else if (strict && c <= 0x1f) {
4447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                raise_errmsg("Invalid control character at", pystr, next);
4457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
4467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
4477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
4487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (!(c == '"' || c == '\\')) {
4497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            raise_errmsg("Unterminated string starting at", pystr, begin);
4507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
4517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
4527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* Pick up this chunk if it's not zero length */
4537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (next != end) {
4547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            PyObject *strchunk = PyString_FromStringAndSize(&buf[end], next - end);
4557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (strchunk == NULL) {
4567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
4577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
4587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            chunk = PyUnicode_FromEncodedObject(strchunk, encoding, NULL);
4597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_DECREF(strchunk);
4607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (chunk == NULL) {
4617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
4627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
4637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (PyList_Append(chunks, chunk)) {
4647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                Py_DECREF(chunk);
4657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
4667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
4677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_DECREF(chunk);
4687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
4697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        next++;
4707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (c == '"') {
4717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            end = next;
4727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            break;
4737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
4747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (next == len) {
4757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            raise_errmsg("Unterminated string starting at", pystr, begin);
4767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
4777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
4787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        c = buf[next];
4797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (c != 'u') {
4807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* Non-unicode backslash escapes */
4817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            end = next + 1;
4827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            switch (c) {
4837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                case '"': break;
4847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                case '\\': break;
4857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                case '/': break;
4867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                case 'b': c = '\b'; break;
4877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                case 'f': c = '\f'; break;
4887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                case 'n': c = '\n'; break;
4897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                case 'r': c = '\r'; break;
4907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                case 't': c = '\t'; break;
4917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                default: c = 0;
4927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
4937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (c == 0) {
4947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                raise_errmsg("Invalid \\escape", pystr, end - 2);
4957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
4967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
4977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
4987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        else {
4997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            c = 0;
5007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            next++;
5017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            end = next + 4;
5027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (end >= len) {
5037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                raise_errmsg("Invalid \\uXXXX escape", pystr, next - 1);
5047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
5057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
5067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* Decode 4 hex digits */
5077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            for (; next < end; next++) {
5087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                Py_UNICODE digit = buf[next];
5097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                c <<= 4;
5107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                switch (digit) {
5117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    case '0': case '1': case '2': case '3': case '4':
5127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    case '5': case '6': case '7': case '8': case '9':
5137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        c |= (digit - '0'); break;
5147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    case 'a': case 'b': case 'c': case 'd': case 'e':
5157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    case 'f':
5167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        c |= (digit - 'a' + 10); break;
5177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    case 'A': case 'B': case 'C': case 'D': case 'E':
5187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    case 'F':
5197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        c |= (digit - 'A' + 10); break;
5207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    default:
5217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        raise_errmsg("Invalid \\uXXXX escape", pystr, end - 5);
5227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        goto bail;
5237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                }
5247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
5257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#ifdef Py_UNICODE_WIDE
5267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* Surrogate pair */
5277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if ((c & 0xfc00) == 0xd800 && end + 6 < len &&
5287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                buf[next++] == '\\' &&
5297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                buf[next++] == 'u') {
5307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                Py_UNICODE c2 = 0;
5317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                end += 6;
5327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                /* Decode 4 hex digits */
5337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                for (; next < end; next++) {
5347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    Py_UNICODE digit = buf[next];
5357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    c2 <<= 4;
5367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    switch (digit) {
5377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        case '0': case '1': case '2': case '3': case '4':
5387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        case '5': case '6': case '7': case '8': case '9':
5397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                            c2 |= (digit - '0'); break;
5407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        case 'a': case 'b': case 'c': case 'd': case 'e':
5417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        case 'f':
5427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                            c2 |= (digit - 'a' + 10); break;
5437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        case 'A': case 'B': case 'C': case 'D': case 'E':
5447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        case 'F':
5457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                            c2 |= (digit - 'A' + 10); break;
5467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        default:
5477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                            raise_errmsg("Invalid \\uXXXX escape", pystr, end - 5);
5487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                            goto bail;
5497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    }
5507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                }
5517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                if ((c2 & 0xfc00) == 0xdc00)
5527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    c = 0x10000 + (((c - 0xd800) << 10) | (c2 - 0xdc00));
5537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                else
5547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    end -= 6;
5557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
5567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#endif
5577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
5587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        chunk = PyUnicode_FromUnicode(&c, 1);
5597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (chunk == NULL) {
5607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
5617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
5627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (PyList_Append(chunks, chunk)) {
5637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_DECREF(chunk);
5647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
5657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
5667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(chunk);
5677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
5687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
5697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    rval = join_list_unicode(chunks);
5707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (rval == NULL) {
5717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
5727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
5737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(chunks);
5747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *next_end_ptr = end;
5757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return rval;
5767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielbail:
5777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *next_end_ptr = -1;
5787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_XDECREF(chunks);
5797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return NULL;
5807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
5817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
5827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
5837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
5847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielscanstring_unicode(PyObject *pystr, Py_ssize_t end, int strict, Py_ssize_t *next_end_ptr)
5857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
5867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Read the JSON string from PyUnicode pystr.
5877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    end is the index of the first character after the quote.
5887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if strict is zero then literal control characters are allowed
5897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *next_end_ptr is a return-by-reference index of the character
5907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        after the end quote
5917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
5927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Return value is a new PyUnicode
5937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    */
5947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *rval;
5957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t len = PyUnicode_GET_SIZE(pystr);
5967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t begin = end - 1;
5977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t next;
5987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    const Py_UNICODE *buf = PyUnicode_AS_UNICODE(pystr);
5997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *chunks = PyList_New(0);
6007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (chunks == NULL) {
6017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
6027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
6037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (end < 0 || len <= end) {
6047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_SetString(PyExc_ValueError, "end is out of bounds");
6057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
6067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
6077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    while (1) {
6087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* Find the end of the string or the next escape */
6097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_UNICODE c = 0;
6107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyObject *chunk = NULL;
6117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        for (next = end; next < len; next++) {
6127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            c = buf[next];
6137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (c == '"' || c == '\\') {
6147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                break;
6157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
6167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            else if (strict && c <= 0x1f) {
6177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                raise_errmsg("Invalid control character at", pystr, next);
6187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
6197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
6207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
6217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (!(c == '"' || c == '\\')) {
6227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            raise_errmsg("Unterminated string starting at", pystr, begin);
6237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
6247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
6257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* Pick up this chunk if it's not zero length */
6267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (next != end) {
6277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            chunk = PyUnicode_FromUnicode(&buf[end], next - end);
6287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (chunk == NULL) {
6297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
6307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
6317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (PyList_Append(chunks, chunk)) {
6327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                Py_DECREF(chunk);
6337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
6347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
6357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_DECREF(chunk);
6367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
6377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        next++;
6387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (c == '"') {
6397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            end = next;
6407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            break;
6417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
6427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (next == len) {
6437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            raise_errmsg("Unterminated string starting at", pystr, begin);
6447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
6457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
6467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        c = buf[next];
6477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (c != 'u') {
6487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* Non-unicode backslash escapes */
6497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            end = next + 1;
6507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            switch (c) {
6517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                case '"': break;
6527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                case '\\': break;
6537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                case '/': break;
6547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                case 'b': c = '\b'; break;
6557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                case 'f': c = '\f'; break;
6567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                case 'n': c = '\n'; break;
6577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                case 'r': c = '\r'; break;
6587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                case 't': c = '\t'; break;
6597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                default: c = 0;
6607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
6617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (c == 0) {
6627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                raise_errmsg("Invalid \\escape", pystr, end - 2);
6637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
6647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
6657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
6667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        else {
6677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            c = 0;
6687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            next++;
6697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            end = next + 4;
6707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (end >= len) {
6717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                raise_errmsg("Invalid \\uXXXX escape", pystr, next - 1);
6727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
6737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
6747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* Decode 4 hex digits */
6757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            for (; next < end; next++) {
6767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                Py_UNICODE digit = buf[next];
6777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                c <<= 4;
6787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                switch (digit) {
6797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    case '0': case '1': case '2': case '3': case '4':
6807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    case '5': case '6': case '7': case '8': case '9':
6817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        c |= (digit - '0'); break;
6827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    case 'a': case 'b': case 'c': case 'd': case 'e':
6837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    case 'f':
6847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        c |= (digit - 'a' + 10); break;
6857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    case 'A': case 'B': case 'C': case 'D': case 'E':
6867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    case 'F':
6877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        c |= (digit - 'A' + 10); break;
6887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    default:
6897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        raise_errmsg("Invalid \\uXXXX escape", pystr, end - 5);
6907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        goto bail;
6917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                }
6927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
6937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#ifdef Py_UNICODE_WIDE
6947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* Surrogate pair */
6957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if ((c & 0xfc00) == 0xd800 && end + 6 < len &&
6967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                buf[next++] == '\\' && buf[next++] == 'u') {
6977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                Py_UNICODE c2 = 0;
6987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                end += 6;
6997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                /* Decode 4 hex digits */
7007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                for (; next < end; next++) {
7017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    Py_UNICODE digit = buf[next];
7027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    c2 <<= 4;
7037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    switch (digit) {
7047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        case '0': case '1': case '2': case '3': case '4':
7057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        case '5': case '6': case '7': case '8': case '9':
7067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                            c2 |= (digit - '0'); break;
7077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        case 'a': case 'b': case 'c': case 'd': case 'e':
7087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        case 'f':
7097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                            c2 |= (digit - 'a' + 10); break;
7107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        case 'A': case 'B': case 'C': case 'D': case 'E':
7117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        case 'F':
7127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                            c2 |= (digit - 'A' + 10); break;
7137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                        default:
7147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                            raise_errmsg("Invalid \\uXXXX escape", pystr, end - 5);
7157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                            goto bail;
7167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    }
7177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                }
7187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                if ((c2 & 0xfc00) == 0xdc00)
7197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    c = 0x10000 + (((c - 0xd800) << 10) | (c2 - 0xdc00));
7207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                else
7217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    end -= 6;
7227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
7237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel#endif
7247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
7257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        chunk = PyUnicode_FromUnicode(&c, 1);
7267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (chunk == NULL) {
7277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
7287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
7297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (PyList_Append(chunks, chunk)) {
7307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_DECREF(chunk);
7317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
7327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
7337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(chunk);
7347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
7357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
7367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    rval = join_list_unicode(chunks);
7377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (rval == NULL) {
7387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
7397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
7407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_DECREF(chunks);
7417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *next_end_ptr = end;
7427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return rval;
7437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielbail:
7447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *next_end_ptr = -1;
7457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_XDECREF(chunks);
7467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return NULL;
7477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
7487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
7497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielPyDoc_STRVAR(pydoc_scanstring,
7507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "scanstring(basestring, end, encoding, strict=True) -> (str, end)\n"
7517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "\n"
7527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "Scan the string s for a JSON string. End is the index of the\n"
7537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "character in s after the quote that started the JSON string.\n"
7547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "Unescapes all valid JSON string escape sequences and raises ValueError\n"
7557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "on attempt to decode an invalid string. If strict is False then literal\n"
7567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "control characters are allowed in the string.\n"
7577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "\n"
7587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "Returns a tuple of the decoded string and the index of the character in s\n"
7597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "after the end quote."
7607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel);
7617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
7627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
7637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielpy_scanstring(PyObject* self UNUSED, PyObject *args)
7647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
7657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *pystr;
7667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *rval;
7677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t end;
7687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t next_end = -1;
7697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    char *encoding = NULL;
7707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    int strict = 1;
7717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (!PyArg_ParseTuple(args, "OO&|zi:scanstring", &pystr, _convertPyInt_AsSsize_t, &end, &encoding, &strict)) {
7727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
7737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
7747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (encoding == NULL) {
7757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        encoding = DEFAULT_ENCODING;
7767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
7777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (PyString_Check(pystr)) {
7787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        rval = scanstring_str(pystr, end, encoding, strict, &next_end);
7797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
7807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else if (PyUnicode_Check(pystr)) {
7817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        rval = scanstring_unicode(pystr, end, strict, &next_end);
7827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
7837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else {
7847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_Format(PyExc_TypeError,
7857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                     "first argument must be a string, not %.80s",
7867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                     Py_TYPE(pystr)->tp_name);
7877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
7887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
7897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return _build_rval_index_tuple(rval, next_end);
7907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
7917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
7927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielPyDoc_STRVAR(pydoc_encode_basestring_ascii,
7937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "encode_basestring_ascii(basestring) -> str\n"
7947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "\n"
7957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "Return an ASCII-only JSON representation of a Python string"
7967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel);
7977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
7987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
7997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielpy_encode_basestring_ascii(PyObject* self UNUSED, PyObject *pystr)
8007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
8017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Return an ASCII-only JSON representation of a Python string */
8027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* METH_O */
8037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (PyString_Check(pystr)) {
8047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return ascii_escape_str(pystr);
8057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
8067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else if (PyUnicode_Check(pystr)) {
8077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return ascii_escape_unicode(pystr);
8087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
8097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else {
8107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_Format(PyExc_TypeError,
8117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                     "first argument must be a string, not %.80s",
8127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                     Py_TYPE(pystr)->tp_name);
8137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
8147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
8157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
8167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
8177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic void
8187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielscanner_dealloc(PyObject *self)
8197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
8207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Deallocate scanner object */
8217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    scanner_clear(self);
8227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_TYPE(self)->tp_free(self);
8237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
8247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
8257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
8267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielscanner_traverse(PyObject *self, visitproc visit, void *arg)
8277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
8287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyScannerObject *s;
8297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    assert(PyScanner_Check(self));
8307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s = (PyScannerObject *)self;
8317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_VISIT(s->encoding);
8327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_VISIT(s->strict);
8337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_VISIT(s->object_hook);
8347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_VISIT(s->pairs_hook);
8357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_VISIT(s->parse_float);
8367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_VISIT(s->parse_int);
8377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_VISIT(s->parse_constant);
8387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return 0;
8397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
8407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
8417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
8427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielscanner_clear(PyObject *self)
8437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
8447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyScannerObject *s;
8457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    assert(PyScanner_Check(self));
8467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s = (PyScannerObject *)self;
8477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(s->encoding);
8487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(s->strict);
8497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(s->object_hook);
8507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(s->pairs_hook);
8517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(s->parse_float);
8527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(s->parse_int);
8537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(s->parse_constant);
8547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return 0;
8557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
8567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
8577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
8587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel_parse_object_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
8597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Read a JSON object from PyString pystr.
8607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    idx is the index of the first character after the opening curly brace.
8617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *next_idx_ptr is a return-by-reference index to the first character after
8627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        the closing curly brace.
8637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
8647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Returns a new PyObject (usually a dict, but object_hook can change that)
8657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    */
8667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    char *str = PyString_AS_STRING(pystr);
8677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t end_idx = PyString_GET_SIZE(pystr) - 1;
8687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *rval;
8697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *pairs;
8707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *item;
8717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *key = NULL;
8727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *val = NULL;
8737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    char *encoding = PyString_AS_STRING(s->encoding);
8747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    int strict = PyObject_IsTrue(s->strict);
8757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t next_idx;
8767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
8777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    pairs = PyList_New(0);
8787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (pairs == NULL)
8797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
8807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
8817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* skip whitespace after { */
8827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
8837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
8847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* only loop if the object is non-empty */
8857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (idx <= end_idx && str[idx] != '}') {
8867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        while (idx <= end_idx) {
8877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* read key */
8887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (str[idx] != '"') {
8897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                raise_errmsg("Expecting property name", pystr, idx);
8907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
8917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
8927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            key = scanstring_str(pystr, idx + 1, encoding, strict, &next_idx);
8937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (key == NULL)
8947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
8957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            idx = next_idx;
8967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
8977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* skip whitespace between key and : delimiter, read :, skip whitespace */
8987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
8997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (idx > end_idx || str[idx] != ':') {
9007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                raise_errmsg("Expecting : delimiter", pystr, idx);
9017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
9027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
9037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            idx++;
9047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
9057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
9067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* read any JSON data type */
9077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            val = scan_once_str(s, pystr, idx, &next_idx);
9087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (val == NULL)
9097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
9107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
9117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            item = PyTuple_Pack(2, key, val);
9127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (item == NULL)
9137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
9147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_CLEAR(key);
9157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_CLEAR(val);
9167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (PyList_Append(pairs, item) == -1) {
9177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                Py_DECREF(item);
9187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
9197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
9207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_DECREF(item);
9217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            idx = next_idx;
9227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
9237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* skip whitespace before } or , */
9247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
9257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
9267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* bail if the object is closed or we didn't get the , delimiter */
9277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (idx > end_idx) break;
9287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (str[idx] == '}') {
9297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                break;
9307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
9317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            else if (str[idx] != ',') {
9327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                raise_errmsg("Expecting , delimiter", pystr, idx);
9337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
9347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
9357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            idx++;
9367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
9377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* skip whitespace after , delimiter */
9387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
9397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
9407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
9417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* verify that idx < end_idx, str[idx] should be '}' */
9427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (idx > end_idx || str[idx] != '}') {
9437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        raise_errmsg("Expecting object", pystr, end_idx);
9447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
9457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
9467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
9477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* if pairs_hook is not None: rval = object_pairs_hook(pairs) */
9487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s->pairs_hook != Py_None) {
9497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        val = PyObject_CallFunctionObjArgs(s->pairs_hook, pairs, NULL);
9507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (val == NULL)
9517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
9527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(pairs);
9537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        *next_idx_ptr = idx + 1;
9547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return val;
9557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
9567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
9577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    rval = PyObject_CallFunctionObjArgs((PyObject *)(&PyDict_Type),
9587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                                         pairs, NULL);
9597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (rval == NULL)
9607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
9617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(pairs);
9627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
9637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* if object_hook is not None: rval = object_hook(rval) */
9647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s->object_hook != Py_None) {
9657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        val = PyObject_CallFunctionObjArgs(s->object_hook, rval, NULL);
9667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (val == NULL)
9677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
9687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(rval);
9697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        rval = val;
9707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        val = NULL;
9717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
9727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *next_idx_ptr = idx + 1;
9737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return rval;
9747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielbail:
9757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_XDECREF(key);
9767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_XDECREF(val);
9777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_XDECREF(pairs);
9787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return NULL;
9797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
9807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
9817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
9827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel_parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
9837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Read a JSON object from PyUnicode pystr.
9847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    idx is the index of the first character after the opening curly brace.
9857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *next_idx_ptr is a return-by-reference index to the first character after
9867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        the closing curly brace.
9877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
9887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Returns a new PyObject (usually a dict, but object_hook can change that)
9897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    */
9907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr);
9917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t end_idx = PyUnicode_GET_SIZE(pystr) - 1;
9927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *rval;
9937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *pairs;
9947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *item;
9957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *key = NULL;
9967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *val = NULL;
9977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    int strict = PyObject_IsTrue(s->strict);
9987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t next_idx;
9997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
10007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    pairs = PyList_New(0);
10017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (pairs == NULL)
10027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
10037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
10047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* skip whitespace after { */
10057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
10067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
10077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* only loop if the object is non-empty */
10087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (idx <= end_idx && str[idx] != '}') {
10097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        while (idx <= end_idx) {
10107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* read key */
10117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (str[idx] != '"') {
10127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                raise_errmsg("Expecting property name enclosed in double quotes", pystr, idx);
10137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
10147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
10157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            key = scanstring_unicode(pystr, idx + 1, strict, &next_idx);
10167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (key == NULL)
10177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
10187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            idx = next_idx;
10197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
10207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* skip whitespace between key and : delimiter, read :, skip whitespace */
10217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
10227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (idx > end_idx || str[idx] != ':') {
10237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                raise_errmsg("Expecting ':' delimiter", pystr, idx);
10247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
10257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
10267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            idx++;
10277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
10287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
10297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* read any JSON term */
10307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            val = scan_once_unicode(s, pystr, idx, &next_idx);
10317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (val == NULL)
10327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
10337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
10347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            item = PyTuple_Pack(2, key, val);
10357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (item == NULL)
10367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
10377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_CLEAR(key);
10387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_CLEAR(val);
10397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (PyList_Append(pairs, item) == -1) {
10407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                Py_DECREF(item);
10417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
10427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
10437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_DECREF(item);
10447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            idx = next_idx;
10457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
10467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* skip whitespace before } or , */
10477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
10487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
10497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* bail if the object is closed or we didn't get the , delimiter */
10507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (idx > end_idx) break;
10517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (str[idx] == '}') {
10527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                break;
10537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
10547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            else if (str[idx] != ',') {
10557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                raise_errmsg("Expecting ',' delimiter", pystr, idx);
10567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
10577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
10587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            idx++;
10597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
10607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* skip whitespace after , delimiter */
10617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
10627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
10637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
10647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
10657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* verify that idx < end_idx, str[idx] should be '}' */
10667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (idx > end_idx || str[idx] != '}') {
10677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        raise_errmsg("Expecting object", pystr, end_idx);
10687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
10697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
10707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
10717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* if pairs_hook is not None: rval = object_pairs_hook(pairs) */
10727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s->pairs_hook != Py_None) {
10737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        val = PyObject_CallFunctionObjArgs(s->pairs_hook, pairs, NULL);
10747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (val == NULL)
10757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
10767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(pairs);
10777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        *next_idx_ptr = idx + 1;
10787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return val;
10797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
10807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
10817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    rval = PyObject_CallFunctionObjArgs((PyObject *)(&PyDict_Type),
10827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                                         pairs, NULL);
10837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (rval == NULL)
10847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
10857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(pairs);
10867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
10877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* if object_hook is not None: rval = object_hook(rval) */
10887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s->object_hook != Py_None) {
10897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        val = PyObject_CallFunctionObjArgs(s->object_hook, rval, NULL);
10907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (val == NULL)
10917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
10927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(rval);
10937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        rval = val;
10947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        val = NULL;
10957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
10967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *next_idx_ptr = idx + 1;
10977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return rval;
10987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielbail:
10997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_XDECREF(key);
11007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_XDECREF(val);
11017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_XDECREF(pairs);
11027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return NULL;
11037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
11047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
11057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
11067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel_parse_array_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
11077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Read a JSON array from PyString pystr.
11087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    idx is the index of the first character after the opening brace.
11097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *next_idx_ptr is a return-by-reference index to the first character after
11107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        the closing brace.
11117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
11127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Returns a new PyList
11137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    */
11147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    char *str = PyString_AS_STRING(pystr);
11157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t end_idx = PyString_GET_SIZE(pystr) - 1;
11167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *val = NULL;
11177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *rval = PyList_New(0);
11187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t next_idx;
11197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (rval == NULL)
11207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
11217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
11227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* skip whitespace after [ */
11237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
11247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
11257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* only loop if the array is non-empty */
11267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (idx <= end_idx && str[idx] != ']') {
11277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        while (idx <= end_idx) {
11287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
11297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* read any JSON term and de-tuplefy the (rval, idx) */
11307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            val = scan_once_str(s, pystr, idx, &next_idx);
11317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (val == NULL)
11327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
11337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
11347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (PyList_Append(rval, val) == -1)
11357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
11367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
11377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_CLEAR(val);
11387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            idx = next_idx;
11397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
11407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* skip whitespace between term and , */
11417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
11427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
11437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* bail if the array is closed or we didn't get the , delimiter */
11447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (idx > end_idx) break;
11457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (str[idx] == ']') {
11467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                break;
11477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
11487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            else if (str[idx] != ',') {
11497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                raise_errmsg("Expecting , delimiter", pystr, idx);
11507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
11517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
11527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            idx++;
11537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
11547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* skip whitespace after , */
11557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
11567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
11577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
11587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
11597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* verify that idx < end_idx, str[idx] should be ']' */
11607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (idx > end_idx || str[idx] != ']') {
11617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        raise_errmsg("Expecting object", pystr, end_idx);
11627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
11637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
11647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *next_idx_ptr = idx + 1;
11657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return rval;
11667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielbail:
11677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_XDECREF(val);
11687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_DECREF(rval);
11697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return NULL;
11707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
11717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
11727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
11737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel_parse_array_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
11747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Read a JSON array from PyString pystr.
11757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    idx is the index of the first character after the opening brace.
11767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *next_idx_ptr is a return-by-reference index to the first character after
11777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        the closing brace.
11787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
11797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Returns a new PyList
11807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    */
11817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr);
11827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t end_idx = PyUnicode_GET_SIZE(pystr) - 1;
11837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *val = NULL;
11847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *rval = PyList_New(0);
11857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t next_idx;
11867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (rval == NULL)
11877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
11887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
11897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* skip whitespace after [ */
11907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
11917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
11927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* only loop if the array is non-empty */
11937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (idx <= end_idx && str[idx] != ']') {
11947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        while (idx <= end_idx) {
11957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
11967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* read any JSON term  */
11977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            val = scan_once_unicode(s, pystr, idx, &next_idx);
11987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (val == NULL)
11997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
12007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
12017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (PyList_Append(rval, val) == -1)
12027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
12037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
12047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_CLEAR(val);
12057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            idx = next_idx;
12067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
12077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* skip whitespace between term and , */
12087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
12097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
12107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* bail if the array is closed or we didn't get the , delimiter */
12117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (idx > end_idx) break;
12127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (str[idx] == ']') {
12137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                break;
12147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
12157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            else if (str[idx] != ',') {
12167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                raise_errmsg("Expecting ',' delimiter", pystr, idx);
12177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
12187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
12197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            idx++;
12207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
12217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* skip whitespace after , */
12227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
12237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
12247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
12257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
12267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* verify that idx < end_idx, str[idx] should be ']' */
12277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (idx > end_idx || str[idx] != ']') {
12287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        raise_errmsg("Expecting object", pystr, end_idx);
12297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
12307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
12317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *next_idx_ptr = idx + 1;
12327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return rval;
12337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielbail:
12347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_XDECREF(val);
12357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_DECREF(rval);
12367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return NULL;
12377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
12387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
12397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
12407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel_parse_constant(PyScannerObject *s, char *constant, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
12417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Read a JSON constant from PyString pystr.
12427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    constant is the constant string that was found
12437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        ("NaN", "Infinity", "-Infinity").
12447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    idx is the index of the first character of the constant
12457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *next_idx_ptr is a return-by-reference index to the first character after
12467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        the constant.
12477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
12487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Returns the result of parse_constant
12497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    */
12507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *cstr;
12517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *rval;
12527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* constant is "NaN", "Infinity", or "-Infinity" */
12537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    cstr = PyString_InternFromString(constant);
12547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (cstr == NULL)
12557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
12567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
12577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* rval = parse_constant(constant) */
12587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    rval = PyObject_CallFunctionObjArgs(s->parse_constant, cstr, NULL);
12597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    idx += PyString_GET_SIZE(cstr);
12607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_DECREF(cstr);
12617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *next_idx_ptr = idx;
12627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return rval;
12637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
12647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
12657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
12667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel_match_number_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t start, Py_ssize_t *next_idx_ptr) {
12677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Read a JSON number from PyString pystr.
12687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    idx is the index of the first character of the number
12697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *next_idx_ptr is a return-by-reference index to the first character after
12707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        the number.
12717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
12727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Returns a new PyObject representation of that number:
12737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyInt, PyLong, or PyFloat.
12747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        May return other types if parse_int or parse_float are set
12757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    */
12767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    char *str = PyString_AS_STRING(pystr);
12777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t end_idx = PyString_GET_SIZE(pystr) - 1;
12787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t idx = start;
12797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    int is_float = 0;
12807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *rval;
12817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *numstr;
12827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
12837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* read a sign if it's there, make sure it's not the end of the string */
12847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (str[idx] == '-') {
12857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        idx++;
12867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (idx > end_idx) {
12877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            PyErr_SetNone(PyExc_StopIteration);
12887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return NULL;
12897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
12907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
12917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
12927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* read as many integer digits as we find as long as it doesn't start with 0 */
12937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (str[idx] >= '1' && str[idx] <= '9') {
12947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        idx++;
12957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
12967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
12977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* if it starts with 0 we only expect one integer digit */
12987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else if (str[idx] == '0') {
12997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        idx++;
13007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
13017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* no integer digits, error */
13027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else {
13037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_SetNone(PyExc_StopIteration);
13047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
13057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
13067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
13077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* if the next char is '.' followed by a digit then read all float digits */
13087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (idx < end_idx && str[idx] == '.' && str[idx + 1] >= '0' && str[idx + 1] <= '9') {
13097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        is_float = 1;
13107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        idx += 2;
13117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
13127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
13137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
13147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* if the next char is 'e' or 'E' then maybe read the exponent (or backtrack) */
13157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (idx < end_idx && (str[idx] == 'e' || str[idx] == 'E')) {
13167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
13177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* save the index of the 'e' or 'E' just in case we need to backtrack */
13187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_ssize_t e_start = idx;
13197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        idx++;
13207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
13217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* read an exponent sign if present */
13227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (idx < end_idx && (str[idx] == '-' || str[idx] == '+')) idx++;
13237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
13247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* read all digits */
13257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
13267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
13277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* if we got a digit, then parse as float. if not, backtrack */
13287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (str[idx - 1] >= '0' && str[idx - 1] <= '9') {
13297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            is_float = 1;
13307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
13317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        else {
13327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            idx = e_start;
13337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
13347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
13357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
13367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* copy the section we determined to be a number */
13377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    numstr = PyString_FromStringAndSize(&str[start], idx - start);
13387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (numstr == NULL)
13397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
13407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (is_float) {
13417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* parse as a float using a fast path if available, otherwise call user defined method */
13427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (s->parse_float != (PyObject *)&PyFloat_Type) {
13437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            rval = PyObject_CallFunctionObjArgs(s->parse_float, numstr, NULL);
13447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
13457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        else {
13467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            double d = PyOS_string_to_double(PyString_AS_STRING(numstr),
13477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                                             NULL, NULL);
13487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (d == -1.0 && PyErr_Occurred())
13497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return NULL;
13507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            rval = PyFloat_FromDouble(d);
13517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
13527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
13537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else {
13547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* parse as an int using a fast path if available, otherwise call user defined method */
13557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (s->parse_int != (PyObject *)&PyInt_Type) {
13567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            rval = PyObject_CallFunctionObjArgs(s->parse_int, numstr, NULL);
13577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
13587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        else {
13597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            rval = PyInt_FromString(PyString_AS_STRING(numstr), NULL, 10);
13607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
13617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
13627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_DECREF(numstr);
13637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *next_idx_ptr = idx;
13647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return rval;
13657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
13667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
13677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
13687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel_match_number_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t start, Py_ssize_t *next_idx_ptr) {
13697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Read a JSON number from PyUnicode pystr.
13707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    idx is the index of the first character of the number
13717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *next_idx_ptr is a return-by-reference index to the first character after
13727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        the number.
13737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
13747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Returns a new PyObject representation of that number:
13757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyInt, PyLong, or PyFloat.
13767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        May return other types if parse_int or parse_float are set
13777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    */
13787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr);
13797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t end_idx = PyUnicode_GET_SIZE(pystr) - 1;
13807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t idx = start;
13817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    int is_float = 0;
13827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *rval;
13837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *numstr;
13847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
13857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* read a sign if it's there, make sure it's not the end of the string */
13867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (str[idx] == '-') {
13877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        idx++;
13887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (idx > end_idx) {
13897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            PyErr_SetNone(PyExc_StopIteration);
13907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return NULL;
13917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
13927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
13937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
13947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* read as many integer digits as we find as long as it doesn't start with 0 */
13957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (str[idx] >= '1' && str[idx] <= '9') {
13967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        idx++;
13977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
13987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
13997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* if it starts with 0 we only expect one integer digit */
14007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else if (str[idx] == '0') {
14017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        idx++;
14027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
14037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* no integer digits, error */
14047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else {
14057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_SetNone(PyExc_StopIteration);
14067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
14077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
14087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
14097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* if the next char is '.' followed by a digit then read all float digits */
14107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (idx < end_idx && str[idx] == '.' && str[idx + 1] >= '0' && str[idx + 1] <= '9') {
14117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        is_float = 1;
14127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        idx += 2;
14137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
14147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
14157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
14167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* if the next char is 'e' or 'E' then maybe read the exponent (or backtrack) */
14177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (idx < end_idx && (str[idx] == 'e' || str[idx] == 'E')) {
14187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_ssize_t e_start = idx;
14197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        idx++;
14207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
14217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* read an exponent sign if present */
14227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (idx < end_idx && (str[idx] == '-' || str[idx] == '+')) idx++;
14237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
14247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* read all digits */
14257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
14267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
14277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* if we got a digit, then parse as float. if not, backtrack */
14287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (str[idx - 1] >= '0' && str[idx - 1] <= '9') {
14297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            is_float = 1;
14307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
14317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        else {
14327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            idx = e_start;
14337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
14347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
14357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
14367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* copy the section we determined to be a number */
14377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    numstr = PyUnicode_FromUnicode(&str[start], idx - start);
14387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (numstr == NULL)
14397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
14407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (is_float) {
14417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* parse as a float using a fast path if available, otherwise call user defined method */
14427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (s->parse_float != (PyObject *)&PyFloat_Type) {
14437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            rval = PyObject_CallFunctionObjArgs(s->parse_float, numstr, NULL);
14447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
14457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        else {
14467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            rval = PyFloat_FromString(numstr, NULL);
14477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
14487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
14497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else {
14507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* no fast path for unicode -> int, just call */
14517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        rval = PyObject_CallFunctionObjArgs(s->parse_int, numstr, NULL);
14527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
14537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_DECREF(numstr);
14547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *next_idx_ptr = idx;
14557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return rval;
14567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
14577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
14587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
14597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielscan_once_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr)
14607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
14617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Read one JSON term (of any kind) from PyString pystr.
14627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    idx is the index of the first character of the term
14637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *next_idx_ptr is a return-by-reference index to the first character after
14647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        the number.
14657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
14667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Returns a new PyObject representation of the term.
14677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    */
14687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *res;
14697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    char *str = PyString_AS_STRING(pystr);
14707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t length = PyString_GET_SIZE(pystr);
14717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (idx < 0) {
14727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_SetString(PyExc_ValueError, "idx cannot be negative");
14737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
14747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
14757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (idx >= length) {
14767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_SetNone(PyExc_StopIteration);
14777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
14787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
14797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    switch (str[idx]) {
14807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case '"':
14817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* string */
14827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return scanstring_str(pystr, idx + 1,
14837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                PyString_AS_STRING(s->encoding),
14847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                PyObject_IsTrue(s->strict),
14857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                next_idx_ptr);
14867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case '{':
14877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* object */
14887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (Py_EnterRecursiveCall(" while decoding a JSON object "
14897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                                      "from a byte string"))
14907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return NULL;
14917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            res = _parse_object_str(s, pystr, idx + 1, next_idx_ptr);
14927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_LeaveRecursiveCall();
14937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return res;
14947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case '[':
14957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* array */
14967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (Py_EnterRecursiveCall(" while decoding a JSON array "
14977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                                      "from a byte string"))
14987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return NULL;
14997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            res = _parse_array_str(s, pystr, idx + 1, next_idx_ptr);
15007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_LeaveRecursiveCall();
15017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return res;
15027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case 'n':
15037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* null */
15047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if ((idx + 3 < length) && str[idx + 1] == 'u' && str[idx + 2] == 'l' && str[idx + 3] == 'l') {
15057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                Py_INCREF(Py_None);
15067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                *next_idx_ptr = idx + 4;
15077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return Py_None;
15087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
15097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            break;
15107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case 't':
15117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* true */
15127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if ((idx + 3 < length) && str[idx + 1] == 'r' && str[idx + 2] == 'u' && str[idx + 3] == 'e') {
15137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                Py_INCREF(Py_True);
15147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                *next_idx_ptr = idx + 4;
15157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return Py_True;
15167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
15177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            break;
15187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case 'f':
15197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* false */
15207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if ((idx + 4 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'l' && str[idx + 3] == 's' && str[idx + 4] == 'e') {
15217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                Py_INCREF(Py_False);
15227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                *next_idx_ptr = idx + 5;
15237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return Py_False;
15247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
15257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            break;
15267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case 'N':
15277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* NaN */
15287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if ((idx + 2 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'N') {
15297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return _parse_constant(s, "NaN", idx, next_idx_ptr);
15307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
15317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            break;
15327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case 'I':
15337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* Infinity */
15347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if ((idx + 7 < length) && str[idx + 1] == 'n' && str[idx + 2] == 'f' && str[idx + 3] == 'i' && str[idx + 4] == 'n' && str[idx + 5] == 'i' && str[idx + 6] == 't' && str[idx + 7] == 'y') {
15357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return _parse_constant(s, "Infinity", idx, next_idx_ptr);
15367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
15377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            break;
15387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case '-':
15397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* -Infinity */
15407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if ((idx + 8 < length) && str[idx + 1] == 'I' && str[idx + 2] == 'n' && str[idx + 3] == 'f' && str[idx + 4] == 'i' && str[idx + 5] == 'n' && str[idx + 6] == 'i' && str[idx + 7] == 't' && str[idx + 8] == 'y') {
15417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return _parse_constant(s, "-Infinity", idx, next_idx_ptr);
15427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
15437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            break;
15447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
15457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Didn't find a string, object, array, or named constant. Look for a number. */
15467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return _match_number_str(s, pystr, idx, next_idx_ptr);
15477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
15487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
15497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
15507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielscan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr)
15517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
15527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Read one JSON term (of any kind) from PyUnicode pystr.
15537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    idx is the index of the first character of the term
15547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    *next_idx_ptr is a return-by-reference index to the first character after
15557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        the number.
15567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
15577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Returns a new PyObject representation of the term.
15587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    */
15597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *res;
15607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr);
15617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t length = PyUnicode_GET_SIZE(pystr);
15627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (idx < 0) {
15637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_SetString(PyExc_ValueError, "idx cannot be negative");
15647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
15657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
15667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (idx >= length) {
15677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_SetNone(PyExc_StopIteration);
15687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
15697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
15707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    switch (str[idx]) {
15717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case '"':
15727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* string */
15737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return scanstring_unicode(pystr, idx + 1,
15747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                PyObject_IsTrue(s->strict),
15757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                next_idx_ptr);
15767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case '{':
15777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* object */
15787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (Py_EnterRecursiveCall(" while decoding a JSON object "
15797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                                      "from a unicode string"))
15807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return NULL;
15817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            res = _parse_object_unicode(s, pystr, idx + 1, next_idx_ptr);
15827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_LeaveRecursiveCall();
15837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return res;
15847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case '[':
15857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* array */
15867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (Py_EnterRecursiveCall(" while decoding a JSON array "
15877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                                      "from a unicode string"))
15887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return NULL;
15897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            res = _parse_array_unicode(s, pystr, idx + 1, next_idx_ptr);
15907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_LeaveRecursiveCall();
15917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return res;
15927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case 'n':
15937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* null */
15947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if ((idx + 3 < length) && str[idx + 1] == 'u' && str[idx + 2] == 'l' && str[idx + 3] == 'l') {
15957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                Py_INCREF(Py_None);
15967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                *next_idx_ptr = idx + 4;
15977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return Py_None;
15987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
15997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            break;
16007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case 't':
16017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* true */
16027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if ((idx + 3 < length) && str[idx + 1] == 'r' && str[idx + 2] == 'u' && str[idx + 3] == 'e') {
16037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                Py_INCREF(Py_True);
16047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                *next_idx_ptr = idx + 4;
16057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return Py_True;
16067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
16077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            break;
16087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case 'f':
16097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* false */
16107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if ((idx + 4 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'l' && str[idx + 3] == 's' && str[idx + 4] == 'e') {
16117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                Py_INCREF(Py_False);
16127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                *next_idx_ptr = idx + 5;
16137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return Py_False;
16147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
16157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            break;
16167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case 'N':
16177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* NaN */
16187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if ((idx + 2 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'N') {
16197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return _parse_constant(s, "NaN", idx, next_idx_ptr);
16207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
16217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            break;
16227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case 'I':
16237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* Infinity */
16247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if ((idx + 7 < length) && str[idx + 1] == 'n' && str[idx + 2] == 'f' && str[idx + 3] == 'i' && str[idx + 4] == 'n' && str[idx + 5] == 'i' && str[idx + 6] == 't' && str[idx + 7] == 'y') {
16257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return _parse_constant(s, "Infinity", idx, next_idx_ptr);
16267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
16277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            break;
16287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        case '-':
16297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* -Infinity */
16307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if ((idx + 8 < length) && str[idx + 1] == 'I' && str[idx + 2] == 'n' && str[idx + 3] == 'f' && str[idx + 4] == 'i' && str[idx + 5] == 'n' && str[idx + 6] == 'i' && str[idx + 7] == 't' && str[idx + 8] == 'y') {
16317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return _parse_constant(s, "-Infinity", idx, next_idx_ptr);
16327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
16337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            break;
16347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
16357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Didn't find a string, object, array, or named constant. Look for a number. */
16367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return _match_number_unicode(s, pystr, idx, next_idx_ptr);
16377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
16387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
16397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
16407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielscanner_call(PyObject *self, PyObject *args, PyObject *kwds)
16417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
16427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Python callable interface to scan_once_{str,unicode} */
16437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *pystr;
16447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *rval;
16457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t idx;
16467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t next_idx = -1;
16477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    static char *kwlist[] = {"string", "idx", NULL};
16487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyScannerObject *s;
16497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    assert(PyScanner_Check(self));
16507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s = (PyScannerObject *)self;
16517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&:scan_once", kwlist, &pystr, _convertPyInt_AsSsize_t, &idx))
16527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
16537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
16547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (PyString_Check(pystr)) {
16557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        rval = scan_once_str(s, pystr, idx, &next_idx);
16567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
16577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else if (PyUnicode_Check(pystr)) {
16587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        rval = scan_once_unicode(s, pystr, idx, &next_idx);
16597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
16607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else {
16617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_Format(PyExc_TypeError,
16627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                 "first argument must be a string, not %.80s",
16637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                 Py_TYPE(pystr)->tp_name);
16647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
16657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
16667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return _build_rval_index_tuple(rval, next_idx);
16677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
16687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
16697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
16707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielscanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
16717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
16727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyScannerObject *s;
16737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s = (PyScannerObject *)type->tp_alloc(type, 0);
16747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s != NULL) {
16757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        s->encoding = NULL;
16767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        s->strict = NULL;
16777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        s->object_hook = NULL;
16787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        s->pairs_hook = NULL;
16797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        s->parse_float = NULL;
16807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        s->parse_int = NULL;
16817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        s->parse_constant = NULL;
16827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
16837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return (PyObject *)s;
16847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
16857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
16867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
16877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielscanner_init(PyObject *self, PyObject *args, PyObject *kwds)
16887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
16897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Initialize Scanner object */
16907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *ctx;
16917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    static char *kwlist[] = {"context", NULL};
16927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyScannerObject *s;
16937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
16947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    assert(PyScanner_Check(self));
16957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s = (PyScannerObject *)self;
16967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
16977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:make_scanner", kwlist, &ctx))
16987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return -1;
16997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
17007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* PyString_AS_STRING is used on encoding */
17017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s->encoding = PyObject_GetAttrString(ctx, "encoding");
17027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s->encoding == NULL)
17037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
17047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s->encoding == Py_None) {
17057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(Py_None);
17067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        s->encoding = PyString_InternFromString(DEFAULT_ENCODING);
17077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
17087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else if (PyUnicode_Check(s->encoding)) {
17097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyObject *tmp = PyUnicode_AsEncodedString(s->encoding, NULL, NULL);
17107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(s->encoding);
17117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        s->encoding = tmp;
17127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
17137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s->encoding == NULL)
17147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
17157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (!PyString_Check(s->encoding)) {
17167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel	PyErr_Format(PyExc_TypeError,
17177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel		     "encoding must be a string, not %.80s",
17187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel		     Py_TYPE(s->encoding)->tp_name);
17197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel	goto bail;
17207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
17217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
17227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
17237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* All of these will fail "gracefully" so we don't need to verify them */
17247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s->strict = PyObject_GetAttrString(ctx, "strict");
17257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s->strict == NULL)
17267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
17277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s->object_hook = PyObject_GetAttrString(ctx, "object_hook");
17287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s->object_hook == NULL)
17297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
17307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s->pairs_hook = PyObject_GetAttrString(ctx, "object_pairs_hook");
17317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s->pairs_hook == NULL)
17327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
17337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s->parse_float = PyObject_GetAttrString(ctx, "parse_float");
17347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s->parse_float == NULL)
17357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
17367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s->parse_int = PyObject_GetAttrString(ctx, "parse_int");
17377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s->parse_int == NULL)
17387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
17397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s->parse_constant = PyObject_GetAttrString(ctx, "parse_constant");
17407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s->parse_constant == NULL)
17417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
17427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
17437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return 0;
17447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
17457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielbail:
17467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(s->encoding);
17477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(s->strict);
17487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(s->object_hook);
17497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(s->pairs_hook);
17507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(s->parse_float);
17517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(s->parse_int);
17527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(s->parse_constant);
17537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return -1;
17547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
17557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
17567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielPyDoc_STRVAR(scanner_doc, "JSON scanner object");
17577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
17587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic
17597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielPyTypeObject PyScannerType = {
17607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject_HEAD_INIT(NULL)
17617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_internal */
17627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "_json.Scanner",       /* tp_name */
17637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    sizeof(PyScannerObject), /* tp_basicsize */
17647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_itemsize */
17657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    scanner_dealloc, /* tp_dealloc */
17667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_print */
17677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_getattr */
17687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_setattr */
17697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_compare */
17707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_repr */
17717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_as_number */
17727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_as_sequence */
17737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_as_mapping */
17747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_hash */
17757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    scanner_call,         /* tp_call */
17767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_str */
17777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,/* PyObject_GenericGetAttr, */                    /* tp_getattro */
17787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,/* PyObject_GenericSetAttr, */                    /* tp_setattro */
17797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_as_buffer */
17807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,   /* tp_flags */
17817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    scanner_doc,          /* tp_doc */
17827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    scanner_traverse,                    /* tp_traverse */
17837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    scanner_clear,                    /* tp_clear */
17847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_richcompare */
17857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_weaklistoffset */
17867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_iter */
17877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_iternext */
17887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_methods */
17897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    scanner_members,                    /* tp_members */
17907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_getset */
17917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_base */
17927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_dict */
17937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_descr_get */
17947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_descr_set */
17957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_dictoffset */
17967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    scanner_init,                    /* tp_init */
17977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,/* PyType_GenericAlloc, */        /* tp_alloc */
17987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    scanner_new,          /* tp_new */
17997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,/* PyObject_GC_Del, */              /* tp_free */
18007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel};
18017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
18027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
18037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielencoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
18047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
18057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyEncoderObject *s;
18067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s = (PyEncoderObject *)type->tp_alloc(type, 0);
18077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s != NULL) {
18087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        s->markers = NULL;
18097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        s->defaultfn = NULL;
18107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        s->encoder = NULL;
18117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        s->indent = NULL;
18127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        s->key_separator = NULL;
18137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        s->item_separator = NULL;
18147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        s->sort_keys = NULL;
18157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        s->skipkeys = NULL;
18167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
18177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return (PyObject *)s;
18187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
18197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
18207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
18217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielencoder_init(PyObject *self, PyObject *args, PyObject *kwds)
18227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
18237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* initialize Encoder object */
18247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    static char *kwlist[] = {"markers", "default", "encoder", "indent", "key_separator", "item_separator", "sort_keys", "skipkeys", "allow_nan", NULL};
18257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
18267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyEncoderObject *s;
18277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *markers, *defaultfn, *encoder, *indent, *key_separator;
18287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *item_separator, *sort_keys, *skipkeys, *allow_nan;
18297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
18307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    assert(PyEncoder_Check(self));
18317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s = (PyEncoderObject *)self;
18327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
18337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOOOO:make_encoder", kwlist,
18347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        &markers, &defaultfn, &encoder, &indent, &key_separator, &item_separator,
18357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        &sort_keys, &skipkeys, &allow_nan))
18367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return -1;
18377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
18387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s->markers = markers;
18397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s->defaultfn = defaultfn;
18407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s->encoder = encoder;
18417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s->indent = indent;
18427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s->key_separator = key_separator;
18437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s->item_separator = item_separator;
18447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s->sort_keys = sort_keys;
18457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s->skipkeys = skipkeys;
18467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s->fast_encode = (PyCFunction_Check(s->encoder) && PyCFunction_GetFunction(s->encoder) == (PyCFunction)py_encode_basestring_ascii);
18477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s->allow_nan = PyObject_IsTrue(allow_nan);
18487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
18497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_INCREF(s->markers);
18507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_INCREF(s->defaultfn);
18517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_INCREF(s->encoder);
18527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_INCREF(s->indent);
18537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_INCREF(s->key_separator);
18547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_INCREF(s->item_separator);
18557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_INCREF(s->sort_keys);
18567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_INCREF(s->skipkeys);
18577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return 0;
18587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
18597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
18607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
18617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielencoder_call(PyObject *self, PyObject *args, PyObject *kwds)
18627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
18637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Python callable interface to encode_listencode_obj */
18647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    static char *kwlist[] = {"obj", "_current_indent_level", NULL};
18657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *obj;
18667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *rval;
18677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t indent_level;
18687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyEncoderObject *s;
18697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    assert(PyEncoder_Check(self));
18707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s = (PyEncoderObject *)self;
18717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&:_iterencode", kwlist,
18727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        &obj, _convertPyInt_AsSsize_t, &indent_level))
18737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
18747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    rval = PyList_New(0);
18757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (rval == NULL)
18767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
18777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (encoder_listencode_obj(s, rval, obj, indent_level)) {
18787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(rval);
18797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
18807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
18817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return rval;
18827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
18837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
18847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
18857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel_encoded_const(PyObject *obj)
18867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
18877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Return the JSON string representation of None, True, False */
18887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (obj == Py_None) {
18897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        static PyObject *s_null = NULL;
18907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (s_null == NULL) {
18917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            s_null = PyString_InternFromString("null");
18927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
18937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_INCREF(s_null);
18947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return s_null;
18957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
18967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else if (obj == Py_True) {
18977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        static PyObject *s_true = NULL;
18987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (s_true == NULL) {
18997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            s_true = PyString_InternFromString("true");
19007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
19017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_INCREF(s_true);
19027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return s_true;
19037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
19047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else if (obj == Py_False) {
19057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        static PyObject *s_false = NULL;
19067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (s_false == NULL) {
19077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            s_false = PyString_InternFromString("false");
19087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
19097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_INCREF(s_false);
19107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return s_false;
19117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
19127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else {
19137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyErr_SetString(PyExc_ValueError, "not a const");
19147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return NULL;
19157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
19167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
19177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
19187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
19197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielencoder_encode_float(PyEncoderObject *s, PyObject *obj)
19207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
19217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Return the JSON representation of a PyFloat */
19227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    double i = PyFloat_AS_DOUBLE(obj);
19237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (!Py_IS_FINITE(i)) {
19247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (!s->allow_nan) {
19257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            PyErr_SetString(PyExc_ValueError, "Out of range float values are not JSON compliant");
19267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return NULL;
19277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
19287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (i > 0) {
19297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return PyString_FromString("Infinity");
19307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
19317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        else if (i < 0) {
19327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return PyString_FromString("-Infinity");
19337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
19347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        else {
19357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return PyString_FromString("NaN");
19367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
19377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
19387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Use a better float format here? */
19397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return PyObject_Repr(obj);
19407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
19417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
19427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyObject *
19437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielencoder_encode_string(PyEncoderObject *s, PyObject *obj)
19447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
19457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Return the JSON representation of a string */
19467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s->fast_encode)
19477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return py_encode_basestring_ascii(NULL, obj);
19487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else
19497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return PyObject_CallFunctionObjArgs(s->encoder, obj, NULL);
19507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
19517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
19527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
19537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel_steal_list_append(PyObject *lst, PyObject *stolen)
19547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
19557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Append stolen and then decrement its reference count */
19567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    int rval = PyList_Append(lst, stolen);
19577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_DECREF(stolen);
19587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return rval;
19597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
19607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
19617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
19627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielencoder_listencode_obj(PyEncoderObject *s, PyObject *rval, PyObject *obj, Py_ssize_t indent_level)
19637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
19647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Encode Python object obj to a JSON term, rval is a PyList */
19657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *newobj;
19667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    int rv;
19677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
19687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (obj == Py_None || obj == Py_True || obj == Py_False) {
19697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyObject *cstr = _encoded_const(obj);
19707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (cstr == NULL)
19717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return -1;
19727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return _steal_list_append(rval, cstr);
19737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
19747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else if (PyString_Check(obj) || PyUnicode_Check(obj))
19757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {
19767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyObject *encoded = encoder_encode_string(s, obj);
19777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (encoded == NULL)
19787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return -1;
19797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return _steal_list_append(rval, encoded);
19807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
19817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else if (PyInt_Check(obj) || PyLong_Check(obj)) {
19827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyObject *encoded = PyObject_Str(obj);
19837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (encoded == NULL)
19847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return -1;
19857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return _steal_list_append(rval, encoded);
19867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
19877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else if (PyFloat_Check(obj)) {
19887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyObject *encoded = encoder_encode_float(s, obj);
19897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (encoded == NULL)
19907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return -1;
19917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return _steal_list_append(rval, encoded);
19927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
19937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else if (PyList_Check(obj) || PyTuple_Check(obj)) {
19947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (Py_EnterRecursiveCall(" while encoding a JSON object"))
19957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return -1;
19967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        rv = encoder_listencode_list(s, rval, obj, indent_level);
19977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_LeaveRecursiveCall();
19987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return rv;
19997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
20007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else if (PyDict_Check(obj)) {
20017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (Py_EnterRecursiveCall(" while encoding a JSON object"))
20027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return -1;
20037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        rv = encoder_listencode_dict(s, rval, obj, indent_level);
20047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_LeaveRecursiveCall();
20057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return rv;
20067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
20077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    else {
20087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyObject *ident = NULL;
20097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (s->markers != Py_None) {
20107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            int has_key;
20117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            ident = PyLong_FromVoidPtr(obj);
20127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (ident == NULL)
20137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return -1;
20147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            has_key = PyDict_Contains(s->markers, ident);
20157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (has_key) {
20167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                if (has_key != -1)
20177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                    PyErr_SetString(PyExc_ValueError, "Circular reference detected");
20187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                Py_DECREF(ident);
20197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return -1;
20207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
20217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (PyDict_SetItem(s->markers, ident, obj)) {
20227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                Py_DECREF(ident);
20237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return -1;
20247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
20257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
20267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        newobj = PyObject_CallFunctionObjArgs(s->defaultfn, obj, NULL);
20277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (newobj == NULL) {
20287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_XDECREF(ident);
20297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return -1;
20307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
20317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
20327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (Py_EnterRecursiveCall(" while encoding a JSON object"))
20337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return -1;
20347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        rv = encoder_listencode_obj(s, rval, newobj, indent_level);
20357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_LeaveRecursiveCall();
20367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
20377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(newobj);
20387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (rv) {
20397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_XDECREF(ident);
20407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return -1;
20417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
20427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (ident != NULL) {
20437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (PyDict_DelItem(s->markers, ident)) {
20447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                Py_XDECREF(ident);
20457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                return -1;
20467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            }
20477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_XDECREF(ident);
20487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
20497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return rv;
20507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
20517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
20527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
20537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
20547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielencoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ssize_t indent_level)
20557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
20567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Encode Python dict dct a JSON term, rval is a PyList */
20577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    static PyObject *open_dict = NULL;
20587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    static PyObject *close_dict = NULL;
20597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    static PyObject *empty_dict = NULL;
20607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *kstr = NULL;
20617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *ident = NULL;
20627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *key = NULL;
20637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *value = NULL;
20647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *it = NULL;
20657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    int skipkeys;
20667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t idx;
20677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
20687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (open_dict == NULL || close_dict == NULL || empty_dict == NULL) {
20697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        open_dict = PyString_InternFromString("{");
20707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        close_dict = PyString_InternFromString("}");
20717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        empty_dict = PyString_InternFromString("{}");
20727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (open_dict == NULL || close_dict == NULL || empty_dict == NULL)
20737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return -1;
20747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
20757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (Py_SIZE(dct) == 0)
20767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return PyList_Append(rval, empty_dict);
20777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
20787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s->markers != Py_None) {
20797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        int has_key;
20807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        ident = PyLong_FromVoidPtr(dct);
20817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (ident == NULL)
20827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
20837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        has_key = PyDict_Contains(s->markers, ident);
20847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (has_key) {
20857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (has_key != -1)
20867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                PyErr_SetString(PyExc_ValueError, "Circular reference detected");
20877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
20887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
20897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (PyDict_SetItem(s->markers, ident, dct)) {
20907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
20917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
20927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
20937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
20947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (PyList_Append(rval, open_dict))
20957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
20967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
20977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s->indent != Py_None) {
20987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* TODO: DOES NOT RUN */
20997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        indent_level += 1;
21007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /*
21017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            newline_indent = '\n' + (' ' * (_indent * _current_indent_level))
21027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            separator = _item_separator + newline_indent
21037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            buf += newline_indent
21047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        */
21057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
21067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
21077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* TODO: C speedup not implemented for sort_keys */
21087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
21097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    it = PyObject_GetIter(dct);
21107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (it == NULL)
21117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
21127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    skipkeys = PyObject_IsTrue(s->skipkeys);
21137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    idx = 0;
21147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    while ((key = PyIter_Next(it)) != NULL) {
21157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyObject *encoded;
21167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
21177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (PyString_Check(key) || PyUnicode_Check(key)) {
21187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_INCREF(key);
21197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            kstr = key;
21207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
21217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        else if (PyFloat_Check(key)) {
21227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            kstr = encoder_encode_float(s, key);
21237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (kstr == NULL)
21247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
21257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
21267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        else if (PyInt_Check(key) || PyLong_Check(key)) {
21277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            kstr = PyObject_Str(key);
21287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (kstr == NULL)
21297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
21307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
21317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        else if (key == Py_True || key == Py_False || key == Py_None) {
21327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            kstr = _encoded_const(key);
21337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (kstr == NULL)
21347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
21357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
21367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        else if (skipkeys) {
21377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_DECREF(key);
21387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            continue;
21397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
21407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        else {
21417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            /* TODO: include repr of key */
21427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            PyErr_SetString(PyExc_TypeError, "keys must be a string");
21437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
21447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
21457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
21467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (idx) {
21477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (PyList_Append(rval, s->item_separator))
21487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
21497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
21507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
21517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        value = PyObject_GetItem(dct, key);
21527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (value == NULL)
21537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
21547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
21557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        encoded = encoder_encode_string(s, kstr);
21567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_CLEAR(kstr);
21577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (encoded == NULL)
21587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
21597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (PyList_Append(rval, encoded)) {
21607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            Py_DECREF(encoded);
21617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
21627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
21637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(encoded);
21647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (PyList_Append(rval, s->key_separator))
21657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
21667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (encoder_listencode_obj(s, rval, value, indent_level))
21677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
21687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        idx += 1;
21697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_CLEAR(value);
21707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(key);
21717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
21727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (PyErr_Occurred())
21737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
21747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(it);
21757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
21767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (ident != NULL) {
21777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (PyDict_DelItem(s->markers, ident))
21787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
21797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_CLEAR(ident);
21807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
21817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s->indent != Py_None) {
21827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* TODO: DOES NOT RUN */
21837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /*
21847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            indent_level -= 1;
21857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
21867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            yield '\n' + (' ' * (_indent * _current_indent_level))
21877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        */
21887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
21897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (PyList_Append(rval, close_dict))
21907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
21917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return 0;
21927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
21937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielbail:
21947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_XDECREF(it);
21957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_XDECREF(key);
21967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_XDECREF(value);
21977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_XDECREF(kstr);
21987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_XDECREF(ident);
21997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return -1;
22007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
22017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
22027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
22037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
22047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielencoder_listencode_list(PyEncoderObject *s, PyObject *rval, PyObject *seq, Py_ssize_t indent_level)
22057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
22067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Encode Python list seq to a JSON term, rval is a PyList */
22077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    static PyObject *open_array = NULL;
22087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    static PyObject *close_array = NULL;
22097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    static PyObject *empty_array = NULL;
22107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *ident = NULL;
22117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *s_fast = NULL;
22127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_ssize_t i;
22137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
22147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (open_array == NULL || close_array == NULL || empty_array == NULL) {
22157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        open_array = PyString_InternFromString("[");
22167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        close_array = PyString_InternFromString("]");
22177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        empty_array = PyString_InternFromString("[]");
22187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (open_array == NULL || close_array == NULL || empty_array == NULL)
22197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            return -1;
22207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
22217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    ident = NULL;
22227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s_fast = PySequence_Fast(seq, "_iterencode_list needs a sequence");
22237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s_fast == NULL)
22247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return -1;
22257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (PySequence_Fast_GET_SIZE(s_fast) == 0) {
22267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_DECREF(s_fast);
22277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return PyList_Append(rval, empty_array);
22287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
22297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
22307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s->markers != Py_None) {
22317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        int has_key;
22327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        ident = PyLong_FromVoidPtr(seq);
22337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (ident == NULL)
22347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
22357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        has_key = PyDict_Contains(s->markers, ident);
22367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (has_key) {
22377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (has_key != -1)
22387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                PyErr_SetString(PyExc_ValueError, "Circular reference detected");
22397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
22407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
22417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (PyDict_SetItem(s->markers, ident, seq)) {
22427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
22437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
22447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
22457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
22467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (PyList_Append(rval, open_array))
22477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
22487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s->indent != Py_None) {
22497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* TODO: DOES NOT RUN */
22507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        indent_level += 1;
22517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /*
22527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            newline_indent = '\n' + (' ' * (_indent * _current_indent_level))
22537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            separator = _item_separator + newline_indent
22547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            buf += newline_indent
22557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        */
22567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
22577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    for (i = 0; i < PySequence_Fast_GET_SIZE(s_fast); i++) {
22587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        PyObject *obj = PySequence_Fast_GET_ITEM(s_fast, i);
22597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (i) {
22607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            if (PyList_Append(rval, s->item_separator))
22617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel                goto bail;
22627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        }
22637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (encoder_listencode_obj(s, rval, obj, indent_level))
22647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
22657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
22667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (ident != NULL) {
22677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        if (PyDict_DelItem(s->markers, ident))
22687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            goto bail;
22697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        Py_CLEAR(ident);
22707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
22717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (s->indent != Py_None) {
22727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /* TODO: DOES NOT RUN */
22737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        /*
22747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            indent_level -= 1;
22757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
22767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel            yield '\n' + (' ' * (_indent * _current_indent_level))
22777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        */
22787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    }
22797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (PyList_Append(rval, close_array))
22807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        goto bail;
22817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_DECREF(s_fast);
22827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return 0;
22837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
22847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielbail:
22857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_XDECREF(ident);
22867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_DECREF(s_fast);
22877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return -1;
22887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
22897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
22907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic void
22917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielencoder_dealloc(PyObject *self)
22927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
22937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Deallocate Encoder */
22947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    encoder_clear(self);
22957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_TYPE(self)->tp_free(self);
22967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
22977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
22987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
22997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielencoder_traverse(PyObject *self, visitproc visit, void *arg)
23007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
23017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyEncoderObject *s;
23027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    assert(PyEncoder_Check(self));
23037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s = (PyEncoderObject *)self;
23047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_VISIT(s->markers);
23057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_VISIT(s->defaultfn);
23067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_VISIT(s->encoder);
23077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_VISIT(s->indent);
23087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_VISIT(s->key_separator);
23097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_VISIT(s->item_separator);
23107eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_VISIT(s->sort_keys);
23117eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_VISIT(s->skipkeys);
23127eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return 0;
23137eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
23147eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
23157eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic int
23167eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielencoder_clear(PyObject *self)
23177eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
23187eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    /* Deallocate Encoder */
23197eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyEncoderObject *s;
23207eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    assert(PyEncoder_Check(self));
23217eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    s = (PyEncoderObject *)self;
23227eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(s->markers);
23237eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(s->defaultfn);
23247eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(s->encoder);
23257eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(s->indent);
23267eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(s->key_separator);
23277eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(s->item_separator);
23287eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(s->sort_keys);
23297eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_CLEAR(s->skipkeys);
23307eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    return 0;
23317eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
23327eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
23337eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielPyDoc_STRVAR(encoder_doc, "_iterencode(obj, _current_indent_level) -> iterable");
23347eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
23357eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic
23367eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielPyTypeObject PyEncoderType = {
23377eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject_HEAD_INIT(NULL)
23387eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_internal */
23397eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    "_json.Encoder",       /* tp_name */
23407eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    sizeof(PyEncoderObject), /* tp_basicsize */
23417eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_itemsize */
23427eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    encoder_dealloc, /* tp_dealloc */
23437eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_print */
23447eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_getattr */
23457eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_setattr */
23467eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_compare */
23477eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_repr */
23487eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_as_number */
23497eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_as_sequence */
23507eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_as_mapping */
23517eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_hash */
23527eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    encoder_call,         /* tp_call */
23537eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_str */
23547eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_getattro */
23557eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_setattro */
23567eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_as_buffer */
23577eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,   /* tp_flags */
23587eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    encoder_doc,          /* tp_doc */
23597eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    encoder_traverse,     /* tp_traverse */
23607eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    encoder_clear,        /* tp_clear */
23617eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_richcompare */
23627eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_weaklistoffset */
23637eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_iter */
23647eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_iternext */
23657eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_methods */
23667eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    encoder_members,      /* tp_members */
23677eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_getset */
23687eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_base */
23697eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_dict */
23707eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_descr_get */
23717eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_descr_set */
23727eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_dictoffset */
23737eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    encoder_init,         /* tp_init */
23747eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_alloc */
23757eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    encoder_new,          /* tp_new */
23767eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    0,                    /* tp_free */
23777eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel};
23787eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
23797eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielstatic PyMethodDef speedups_methods[] = {
23807eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"encode_basestring_ascii",
23817eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        (PyCFunction)py_encode_basestring_ascii,
23827eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        METH_O,
23837eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        pydoc_encode_basestring_ascii},
23847eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {"scanstring",
23857eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        (PyCFunction)py_scanstring,
23867eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        METH_VARARGS,
23877eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        pydoc_scanstring},
23887eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    {NULL, NULL, 0, NULL}
23897eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel};
23907eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
23917eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielPyDoc_STRVAR(module_doc,
23927eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel"json speedups\n");
23937eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel
23947eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielvoid
23957eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDanielinit_json(void)
23967eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel{
23977eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyObject *m;
23987eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyScannerType.tp_new = PyType_GenericNew;
23997eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (PyType_Ready(&PyScannerType) < 0)
24007eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return;
24017eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyEncoderType.tp_new = PyType_GenericNew;
24027eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    if (PyType_Ready(&PyEncoderType) < 0)
24037eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel        return;
24047eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    m = Py_InitModule3("_json", speedups_methods, module_doc);
24057eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_INCREF((PyObject*)&PyScannerType);
24067eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyModule_AddObject(m, "make_scanner", (PyObject*)&PyScannerType);
24077eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    Py_INCREF((PyObject*)&PyEncoderType);
24087eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel    PyModule_AddObject(m, "make_encoder", (PyObject*)&PyEncoderType);
24097eb75bccb5dacb658c63db1a9a980950c3d54d42Daryl McDaniel}
2410