LCOV - code coverage report
Current view: top level - Modules - _json.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 58 1201 4.8 %
Date: 2017-04-19 Functions: 5 41 12.2 %

          Line data    Source code
       1             : #include "Python.h"
       2             : #include "structmember.h"
       3             : #if PY_VERSION_HEX < 0x02060000 && !defined(Py_TYPE)
       4             : #define Py_TYPE(ob)     (((PyObject*)(ob))->ob_type)
       5             : #endif
       6             : #if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
       7             : typedef int Py_ssize_t;
       8             : #define PY_SSIZE_T_MAX INT_MAX
       9             : #define PY_SSIZE_T_MIN INT_MIN
      10             : #define PyInt_FromSsize_t PyInt_FromLong
      11             : #define PyInt_AsSsize_t PyInt_AsLong
      12             : #endif
      13             : #ifndef Py_IS_FINITE
      14             : #define Py_IS_FINITE(X) (!Py_IS_INFINITY(X) && !Py_IS_NAN(X))
      15             : #endif
      16             : 
      17             : #ifdef __GNUC__
      18             : #define UNUSED __attribute__((__unused__))
      19             : #else
      20             : #define UNUSED
      21             : #endif
      22             : 
      23             : #define DEFAULT_ENCODING "utf-8"
      24             : 
      25             : #define PyScanner_Check(op) PyObject_TypeCheck(op, &PyScannerType)
      26             : #define PyScanner_CheckExact(op) (Py_TYPE(op) == &PyScannerType)
      27             : #define PyEncoder_Check(op) PyObject_TypeCheck(op, &PyEncoderType)
      28             : #define PyEncoder_CheckExact(op) (Py_TYPE(op) == &PyEncoderType)
      29             : 
      30             : static PyTypeObject PyScannerType;
      31             : static PyTypeObject PyEncoderType;
      32             : 
      33             : typedef struct _PyScannerObject {
      34             :     PyObject_HEAD
      35             :     PyObject *encoding;
      36             :     PyObject *strict;
      37             :     PyObject *object_hook;
      38             :     PyObject *pairs_hook;
      39             :     PyObject *parse_float;
      40             :     PyObject *parse_int;
      41             :     PyObject *parse_constant;
      42             : } PyScannerObject;
      43             : 
      44             : static PyMemberDef scanner_members[] = {
      45             :     {"encoding", T_OBJECT, offsetof(PyScannerObject, encoding), READONLY, "encoding"},
      46             :     {"strict", T_OBJECT, offsetof(PyScannerObject, strict), READONLY, "strict"},
      47             :     {"object_hook", T_OBJECT, offsetof(PyScannerObject, object_hook), READONLY, "object_hook"},
      48             :     {"object_pairs_hook", T_OBJECT, offsetof(PyScannerObject, pairs_hook), READONLY, "object_pairs_hook"},
      49             :     {"parse_float", T_OBJECT, offsetof(PyScannerObject, parse_float), READONLY, "parse_float"},
      50             :     {"parse_int", T_OBJECT, offsetof(PyScannerObject, parse_int), READONLY, "parse_int"},
      51             :     {"parse_constant", T_OBJECT, offsetof(PyScannerObject, parse_constant), READONLY, "parse_constant"},
      52             :     {NULL}
      53             : };
      54             : 
      55             : typedef struct _PyEncoderObject {
      56             :     PyObject_HEAD
      57             :     PyObject *markers;
      58             :     PyObject *defaultfn;
      59             :     PyObject *encoder;
      60             :     PyObject *indent;
      61             :     PyObject *key_separator;
      62             :     PyObject *item_separator;
      63             :     PyObject *sort_keys;
      64             :     PyObject *skipkeys;
      65             :     int fast_encode;
      66             :     int allow_nan;
      67             : } PyEncoderObject;
      68             : 
      69             : static PyMemberDef encoder_members[] = {
      70             :     {"markers", T_OBJECT, offsetof(PyEncoderObject, markers), READONLY, "markers"},
      71             :     {"default", T_OBJECT, offsetof(PyEncoderObject, defaultfn), READONLY, "default"},
      72             :     {"encoder", T_OBJECT, offsetof(PyEncoderObject, encoder), READONLY, "encoder"},
      73             :     {"indent", T_OBJECT, offsetof(PyEncoderObject, indent), READONLY, "indent"},
      74             :     {"key_separator", T_OBJECT, offsetof(PyEncoderObject, key_separator), READONLY, "key_separator"},
      75             :     {"item_separator", T_OBJECT, offsetof(PyEncoderObject, item_separator), READONLY, "item_separator"},
      76             :     {"sort_keys", T_OBJECT, offsetof(PyEncoderObject, sort_keys), READONLY, "sort_keys"},
      77             :     {"skipkeys", T_OBJECT, offsetof(PyEncoderObject, skipkeys), READONLY, "skipkeys"},
      78             :     {NULL}
      79             : };
      80             : 
      81             : static Py_ssize_t
      82             : ascii_escape_char(Py_UNICODE c, char *output, Py_ssize_t chars);
      83             : static PyObject *
      84             : ascii_escape_unicode(PyObject *pystr);
      85             : static PyObject *
      86             : ascii_escape_str(PyObject *pystr);
      87             : static PyObject *
      88             : py_encode_basestring_ascii(PyObject* self UNUSED, PyObject *pystr);
      89             : void init_json(void);
      90             : static PyObject *
      91             : scan_once_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr);
      92             : static PyObject *
      93             : scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr);
      94             : static PyObject *
      95             : _build_rval_index_tuple(PyObject *rval, Py_ssize_t idx);
      96             : static PyObject *
      97             : scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
      98             : static int
      99             : scanner_init(PyObject *self, PyObject *args, PyObject *kwds);
     100             : static void
     101             : scanner_dealloc(PyObject *self);
     102             : static int
     103             : scanner_clear(PyObject *self);
     104             : static PyObject *
     105             : encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
     106             : static int
     107             : encoder_init(PyObject *self, PyObject *args, PyObject *kwds);
     108             : static void
     109             : encoder_dealloc(PyObject *self);
     110             : static int
     111             : encoder_clear(PyObject *self);
     112             : static int
     113             : encoder_listencode_list(PyEncoderObject *s, PyObject *rval, PyObject *seq, Py_ssize_t indent_level);
     114             : static int
     115             : encoder_listencode_obj(PyEncoderObject *s, PyObject *rval, PyObject *obj, Py_ssize_t indent_level);
     116             : static int
     117             : encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ssize_t indent_level);
     118             : static PyObject *
     119             : _encoded_const(PyObject *obj);
     120             : static void
     121             : raise_errmsg(char *msg, PyObject *s, Py_ssize_t end);
     122             : static PyObject *
     123             : encoder_encode_string(PyEncoderObject *s, PyObject *obj);
     124             : static int
     125             : _convertPyInt_AsSsize_t(PyObject *o, Py_ssize_t *size_ptr);
     126             : static PyObject *
     127             : _convertPyInt_FromSsize_t(Py_ssize_t *size_ptr);
     128             : static PyObject *
     129             : encoder_encode_float(PyEncoderObject *s, PyObject *obj);
     130             : 
     131             : #define S_CHAR(c) (c >= ' ' && c <= '~' && c != '\\' && c != '"')
     132             : #define IS_WHITESPACE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\n') || ((c) == '\r'))
     133             : 
     134             : #define MIN_EXPANSION 6
     135             : #ifdef Py_UNICODE_WIDE
     136             : #define MAX_EXPANSION (2 * MIN_EXPANSION)
     137             : #else
     138             : #define MAX_EXPANSION MIN_EXPANSION
     139             : #endif
     140             : 
     141             : static int
     142           0 : _convertPyInt_AsSsize_t(PyObject *o, Py_ssize_t *size_ptr)
     143             : {
     144             :     /* PyObject to Py_ssize_t converter */
     145           0 :     *size_ptr = PyInt_AsSsize_t(o);
     146           0 :     if (*size_ptr == -1 && PyErr_Occurred())
     147           0 :         return 0;
     148           0 :     return 1;
     149             : }
     150             : 
     151             : static PyObject *
     152           0 : _convertPyInt_FromSsize_t(Py_ssize_t *size_ptr)
     153             : {
     154             :     /* Py_ssize_t to PyObject converter */
     155           0 :     return PyInt_FromSsize_t(*size_ptr);
     156             : }
     157             : 
     158             : static Py_ssize_t
     159           0 : ascii_escape_char(Py_UNICODE c, char *output, Py_ssize_t chars)
     160             : {
     161             :     /* Escape unicode code point c to ASCII escape sequences
     162             :     in char *output. output must have at least 12 bytes unused to
     163             :     accommodate an escaped surrogate pair "\uXXXX\uXXXX" */
     164           0 :     output[chars++] = '\\';
     165           0 :     switch (c) {
     166           0 :         case '\\': output[chars++] = (char)c; break;
     167           0 :         case '"': output[chars++] = (char)c; break;
     168           0 :         case '\b': output[chars++] = 'b'; break;
     169           0 :         case '\f': output[chars++] = 'f'; break;
     170           0 :         case '\n': output[chars++] = 'n'; break;
     171           0 :         case '\r': output[chars++] = 'r'; break;
     172           0 :         case '\t': output[chars++] = 't'; break;
     173             :         default:
     174             : #ifdef Py_UNICODE_WIDE
     175             :             if (c >= 0x10000) {
     176             :                 /* UTF-16 surrogate pair */
     177             :                 Py_UNICODE v = c - 0x10000;
     178             :                 c = 0xd800 | ((v >> 10) & 0x3ff);
     179             :                 output[chars++] = 'u';
     180             :                 output[chars++] = "0123456789abcdef"[(c >> 12) & 0xf];
     181             :                 output[chars++] = "0123456789abcdef"[(c >>  8) & 0xf];
     182             :                 output[chars++] = "0123456789abcdef"[(c >>  4) & 0xf];
     183             :                 output[chars++] = "0123456789abcdef"[(c      ) & 0xf];
     184             :                 c = 0xdc00 | (v & 0x3ff);
     185             :                 output[chars++] = '\\';
     186             :             }
     187             : #endif
     188           0 :             output[chars++] = 'u';
     189           0 :             output[chars++] = "0123456789abcdef"[(c >> 12) & 0xf];
     190           0 :             output[chars++] = "0123456789abcdef"[(c >>  8) & 0xf];
     191           0 :             output[chars++] = "0123456789abcdef"[(c >>  4) & 0xf];
     192           0 :             output[chars++] = "0123456789abcdef"[(c      ) & 0xf];
     193             :     }
     194           0 :     return chars;
     195             : }
     196             : 
     197             : static PyObject *
     198           0 : ascii_escape_unicode(PyObject *pystr)
     199             : {
     200             :     /* Take a PyUnicode pystr and return a new ASCII-only escaped PyString */
     201             :     Py_ssize_t i;
     202             :     Py_ssize_t input_chars;
     203             :     Py_ssize_t output_size;
     204             :     Py_ssize_t max_output_size;
     205             :     Py_ssize_t chars;
     206             :     Py_ssize_t incr;
     207             :     PyObject *rval;
     208             :     char *output;
     209             :     Py_UNICODE *input_unicode;
     210             : 
     211           0 :     input_chars = PyUnicode_GET_SIZE(pystr);
     212           0 :     input_unicode = PyUnicode_AS_UNICODE(pystr);
     213             : 
     214           0 :     output_size = input_chars;
     215           0 :     incr = 2; /* for quotes */
     216             :     /* One char input can be up to 6 chars output, estimate 4 of these */
     217           0 :     incr += MIN_EXPANSION * 4;
     218           0 :     if (PY_SSIZE_T_MAX - incr < output_size) {
     219           0 :         PyErr_NoMemory();
     220           0 :         return NULL;
     221             :     }
     222           0 :     output_size += incr;
     223           0 :     if (PY_SSIZE_T_MAX / MAX_EXPANSION < input_chars ||
     224           0 :         PY_SSIZE_T_MAX - 2 < input_chars * MAX_EXPANSION)
     225           0 :         max_output_size = PY_SSIZE_T_MAX;
     226             :     else
     227           0 :         max_output_size = 2 + (input_chars * MAX_EXPANSION);
     228           0 :     rval = PyString_FromStringAndSize(NULL, output_size);
     229           0 :     if (rval == NULL) {
     230           0 :         return NULL;
     231             :     }
     232           0 :     output = PyString_AS_STRING(rval);
     233           0 :     chars = 0;
     234           0 :     output[chars++] = '"';
     235           0 :     for (i = 0; i < input_chars; i++) {
     236           0 :         Py_UNICODE c = input_unicode[i];
     237           0 :         if (S_CHAR(c)) {
     238           0 :             output[chars++] = (char)c;
     239             :         }
     240             :         else {
     241           0 :             chars = ascii_escape_char(c, output, chars);
     242             :         }
     243           0 :         if (output_size - chars < (1 + MAX_EXPANSION)) {
     244           0 :             if (output_size == PY_SSIZE_T_MAX) {
     245           0 :                 Py_DECREF(rval);
     246           0 :                 PyErr_NoMemory();
     247           0 :                 return NULL;
     248             :             }
     249             :             /* There's more than four, so let's resize by a lot */
     250           0 :             if (PY_SSIZE_T_MAX / 2 >= output_size && output_size * 2 < max_output_size)
     251           0 :                 output_size *= 2;
     252             :             else
     253           0 :                 output_size = max_output_size;
     254           0 :             if (_PyString_Resize(&rval, output_size) == -1) {
     255           0 :                 return NULL;
     256             :             }
     257           0 :             output = PyString_AS_STRING(rval);
     258             :         }
     259             :     }
     260           0 :     output[chars++] = '"';
     261           0 :     if (_PyString_Resize(&rval, chars) == -1) {
     262           0 :         return NULL;
     263             :     }
     264           0 :     return rval;
     265             : }
     266             : 
     267             : static PyObject *
     268           0 : ascii_escape_str(PyObject *pystr)
     269             : {
     270             :     /* Take a PyString pystr and return a new ASCII-only escaped PyString */
     271             :     Py_ssize_t i;
     272             :     Py_ssize_t input_chars;
     273             :     Py_ssize_t output_size;
     274             :     Py_ssize_t max_output_size;
     275             :     Py_ssize_t chars;
     276             :     Py_ssize_t incr;
     277             :     PyObject *rval;
     278             :     char *output;
     279             :     char *input_str;
     280             : 
     281           0 :     input_chars = PyString_GET_SIZE(pystr);
     282           0 :     input_str = PyString_AS_STRING(pystr);
     283             : 
     284             :     /* Fast path for a string that's already ASCII */
     285           0 :     for (i = 0; i < input_chars; i++) {
     286           0 :         Py_UNICODE c = (Py_UNICODE)(unsigned char)input_str[i];
     287           0 :         if (!S_CHAR(c)) {
     288             :             /* If we have to escape something, scan the string for unicode */
     289             :             Py_ssize_t j;
     290           0 :             for (j = i; j < input_chars; j++) {
     291           0 :                 c = (Py_UNICODE)(unsigned char)input_str[j];
     292           0 :                 if (c > 0x7f) {
     293             :                     /* We hit a non-ASCII character, bail to unicode mode */
     294             :                     PyObject *uni;
     295           0 :                     uni = PyUnicode_DecodeUTF8(input_str, input_chars, "strict");
     296           0 :                     if (uni == NULL) {
     297           0 :                         return NULL;
     298             :                     }
     299           0 :                     rval = ascii_escape_unicode(uni);
     300           0 :                     Py_DECREF(uni);
     301           0 :                     return rval;
     302             :                 }
     303             :             }
     304           0 :             break;
     305             :         }
     306             :     }
     307             : 
     308           0 :     output_size = input_chars;
     309           0 :     incr = 2; /* for quotes */
     310           0 :     if (i != input_chars) {
     311             :         /* One char input can be up to 6 chars output, estimate 4 of these */
     312           0 :         incr += MIN_EXPANSION * 4;
     313             :     }
     314           0 :     if (PY_SSIZE_T_MAX - incr < output_size) {
     315           0 :         PyErr_NoMemory();
     316           0 :         return NULL;
     317             :     }
     318           0 :     output_size += incr;
     319           0 :     if (PY_SSIZE_T_MAX / MIN_EXPANSION < input_chars ||
     320           0 :         PY_SSIZE_T_MAX - 2 < input_chars * MIN_EXPANSION)
     321           0 :         max_output_size = PY_SSIZE_T_MAX;
     322             :     else
     323           0 :         max_output_size = 2 + (input_chars * MIN_EXPANSION);
     324           0 :     rval = PyString_FromStringAndSize(NULL, output_size);
     325           0 :     if (rval == NULL) {
     326           0 :         return NULL;
     327             :     }
     328           0 :     output = PyString_AS_STRING(rval);
     329           0 :     output[0] = '"';
     330             : 
     331             :     /* We know that everything up to i is ASCII already */
     332           0 :     chars = i + 1;
     333           0 :     memcpy(&output[1], input_str, i);
     334             : 
     335           0 :     for (; i < input_chars; i++) {
     336           0 :         Py_UNICODE c = (Py_UNICODE)(unsigned char)input_str[i];
     337           0 :         if (S_CHAR(c)) {
     338           0 :             output[chars++] = (char)c;
     339             :         }
     340             :         else {
     341           0 :             chars = ascii_escape_char(c, output, chars);
     342             :         }
     343             :         /* An ASCII char can't possibly expand to a surrogate! */
     344           0 :         if (output_size - chars < (1 + MIN_EXPANSION)) {
     345           0 :             if (output_size == PY_SSIZE_T_MAX) {
     346           0 :                 Py_DECREF(rval);
     347           0 :                 PyErr_NoMemory();
     348           0 :                 return NULL;
     349             :             }
     350             :             /* There's more than four, so let's resize by a lot */
     351           0 :             if (PY_SSIZE_T_MAX / 2 >= output_size && output_size * 2 < max_output_size)
     352           0 :                 output_size *= 2;
     353             :             else
     354           0 :                 output_size = max_output_size;
     355           0 :             if (_PyString_Resize(&rval, output_size) == -1) {
     356           0 :                 return NULL;
     357             :             }
     358           0 :             output = PyString_AS_STRING(rval);
     359             :         }
     360             :     }
     361           0 :     output[chars++] = '"';
     362           0 :     if (_PyString_Resize(&rval, chars) == -1) {
     363           0 :         return NULL;
     364             :     }
     365           0 :     return rval;
     366             : }
     367             : 
     368             : static void
     369           0 : raise_errmsg(char *msg, PyObject *s, Py_ssize_t end)
     370             : {
     371             :     /* Use the Python function json.decoder.errmsg to raise a nice
     372             :     looking ValueError exception */
     373             :     static PyObject *errmsg_fn = NULL;
     374             :     PyObject *pymsg;
     375           0 :     if (errmsg_fn == NULL) {
     376           0 :         PyObject *decoder = PyImport_ImportModule("json.decoder");
     377           0 :         if (decoder == NULL)
     378           0 :             return;
     379           0 :         errmsg_fn = PyObject_GetAttrString(decoder, "errmsg");
     380           0 :         Py_DECREF(decoder);
     381           0 :         if (errmsg_fn == NULL)
     382           0 :             return;
     383             :     }
     384           0 :     pymsg = PyObject_CallFunction(errmsg_fn, "(zOO&)", msg, s, _convertPyInt_FromSsize_t, &end);
     385           0 :     if (pymsg) {
     386           0 :         PyErr_SetObject(PyExc_ValueError, pymsg);
     387           0 :         Py_DECREF(pymsg);
     388             :     }
     389             : }
     390             : 
     391             : static PyObject *
     392           0 : join_list_unicode(PyObject *lst)
     393             : {
     394             :     /* return u''.join(lst) */
     395             :     static PyObject *joinfn = NULL;
     396           0 :     if (joinfn == NULL) {
     397           0 :         PyObject *ustr = PyUnicode_FromUnicode(NULL, 0);
     398           0 :         if (ustr == NULL)
     399           0 :             return NULL;
     400             : 
     401           0 :         joinfn = PyObject_GetAttrString(ustr, "join");
     402           0 :         Py_DECREF(ustr);
     403           0 :         if (joinfn == NULL)
     404           0 :             return NULL;
     405             :     }
     406           0 :     return PyObject_CallFunctionObjArgs(joinfn, lst, NULL);
     407             : }
     408             : 
     409             : static PyObject *
     410           0 : _build_rval_index_tuple(PyObject *rval, Py_ssize_t idx) {
     411             :     /* return (rval, idx) tuple, stealing reference to rval */
     412             :     PyObject *tpl;
     413             :     PyObject *pyidx;
     414             :     /*
     415             :     steal a reference to rval, returns (rval, idx)
     416             :     */
     417           0 :     if (rval == NULL) {
     418           0 :         return NULL;
     419             :     }
     420           0 :     pyidx = PyInt_FromSsize_t(idx);
     421           0 :     if (pyidx == NULL) {
     422           0 :         Py_DECREF(rval);
     423           0 :         return NULL;
     424             :     }
     425           0 :     tpl = PyTuple_New(2);
     426           0 :     if (tpl == NULL) {
     427           0 :         Py_DECREF(pyidx);
     428           0 :         Py_DECREF(rval);
     429           0 :         return NULL;
     430             :     }
     431           0 :     PyTuple_SET_ITEM(tpl, 0, rval);
     432           0 :     PyTuple_SET_ITEM(tpl, 1, pyidx);
     433           0 :     return tpl;
     434             : }
     435             : 
     436             : static PyObject *
     437           0 : scanstring_str(PyObject *pystr, Py_ssize_t end, char *encoding, int strict, Py_ssize_t *next_end_ptr)
     438             : {
     439             :     /* Read the JSON string from PyString pystr.
     440             :     end is the index of the first character after the quote.
     441             :     encoding is the encoding of pystr (must be an ASCII superset)
     442             :     if strict is zero then literal control characters are allowed
     443             :     *next_end_ptr is a return-by-reference index of the character
     444             :         after the end quote
     445             : 
     446             :     Return value is a new PyString (if ASCII-only) or PyUnicode
     447             :     */
     448             :     PyObject *rval;
     449           0 :     Py_ssize_t len = PyString_GET_SIZE(pystr);
     450           0 :     Py_ssize_t begin = end - 1;
     451             :     Py_ssize_t next;
     452           0 :     char *buf = PyString_AS_STRING(pystr);
     453           0 :     PyObject *chunks = PyList_New(0);
     454           0 :     if (chunks == NULL) {
     455           0 :         goto bail;
     456             :     }
     457           0 :     if (end < 0 || len <= end) {
     458           0 :         PyErr_SetString(PyExc_ValueError, "end is out of bounds");
     459           0 :         goto bail;
     460             :     }
     461             :     while (1) {
     462             :         /* Find the end of the string or the next escape */
     463           0 :         Py_UNICODE c = 0;
     464           0 :         PyObject *chunk = NULL;
     465           0 :         for (next = end; next < len; next++) {
     466           0 :             c = (unsigned char)buf[next];
     467           0 :             if (c == '"' || c == '\\') {
     468             :                 break;
     469             :             }
     470           0 :             else if (strict && c <= 0x1f) {
     471           0 :                 raise_errmsg("Invalid control character at", pystr, next);
     472           0 :                 goto bail;
     473             :             }
     474             :         }
     475           0 :         if (!(c == '"' || c == '\\')) {
     476           0 :             raise_errmsg("Unterminated string starting at", pystr, begin);
     477           0 :             goto bail;
     478             :         }
     479             :         /* Pick up this chunk if it's not zero length */
     480           0 :         if (next != end) {
     481           0 :             PyObject *strchunk = PyString_FromStringAndSize(&buf[end], next - end);
     482           0 :             if (strchunk == NULL) {
     483           0 :                 goto bail;
     484             :             }
     485           0 :             chunk = PyUnicode_FromEncodedObject(strchunk, encoding, NULL);
     486           0 :             Py_DECREF(strchunk);
     487           0 :             if (chunk == NULL) {
     488           0 :                 goto bail;
     489             :             }
     490           0 :             if (PyList_Append(chunks, chunk)) {
     491           0 :                 Py_DECREF(chunk);
     492           0 :                 goto bail;
     493             :             }
     494           0 :             Py_DECREF(chunk);
     495             :         }
     496           0 :         next++;
     497           0 :         if (c == '"') {
     498           0 :             end = next;
     499           0 :             break;
     500             :         }
     501           0 :         if (next == len) {
     502           0 :             raise_errmsg("Unterminated string starting at", pystr, begin);
     503           0 :             goto bail;
     504             :         }
     505           0 :         c = buf[next];
     506           0 :         if (c != 'u') {
     507             :             /* Non-unicode backslash escapes */
     508           0 :             end = next + 1;
     509           0 :             switch (c) {
     510           0 :                 case '"': break;
     511           0 :                 case '\\': break;
     512           0 :                 case '/': break;
     513           0 :                 case 'b': c = '\b'; break;
     514           0 :                 case 'f': c = '\f'; break;
     515           0 :                 case 'n': c = '\n'; break;
     516           0 :                 case 'r': c = '\r'; break;
     517           0 :                 case 't': c = '\t'; break;
     518           0 :                 default: c = 0;
     519             :             }
     520           0 :             if (c == 0) {
     521           0 :                 raise_errmsg("Invalid \\escape", pystr, end - 2);
     522           0 :                 goto bail;
     523             :             }
     524             :         }
     525             :         else {
     526           0 :             c = 0;
     527           0 :             next++;
     528           0 :             end = next + 4;
     529           0 :             if (end >= len) {
     530           0 :                 raise_errmsg("Invalid \\uXXXX escape", pystr, next - 1);
     531           0 :                 goto bail;
     532             :             }
     533             :             /* Decode 4 hex digits */
     534           0 :             for (; next < end; next++) {
     535           0 :                 Py_UNICODE digit = buf[next];
     536           0 :                 c <<= 4;
     537           0 :                 switch (digit) {
     538             :                     case '0': case '1': case '2': case '3': case '4':
     539             :                     case '5': case '6': case '7': case '8': case '9':
     540           0 :                         c |= (digit - '0'); break;
     541             :                     case 'a': case 'b': case 'c': case 'd': case 'e':
     542             :                     case 'f':
     543           0 :                         c |= (digit - 'a' + 10); break;
     544             :                     case 'A': case 'B': case 'C': case 'D': case 'E':
     545             :                     case 'F':
     546           0 :                         c |= (digit - 'A' + 10); break;
     547             :                     default:
     548           0 :                         raise_errmsg("Invalid \\uXXXX escape", pystr, end - 5);
     549           0 :                         goto bail;
     550             :                 }
     551             :             }
     552             : #ifdef Py_UNICODE_WIDE
     553             :             /* Surrogate pair */
     554             :             if ((c & 0xfc00) == 0xd800 && end + 6 < len &&
     555             :                 buf[next++] == '\\' &&
     556             :                 buf[next++] == 'u') {
     557             :                 Py_UNICODE c2 = 0;
     558             :                 end += 6;
     559             :                 /* Decode 4 hex digits */
     560             :                 for (; next < end; next++) {
     561             :                     Py_UNICODE digit = buf[next];
     562             :                     c2 <<= 4;
     563             :                     switch (digit) {
     564             :                         case '0': case '1': case '2': case '3': case '4':
     565             :                         case '5': case '6': case '7': case '8': case '9':
     566             :                             c2 |= (digit - '0'); break;
     567             :                         case 'a': case 'b': case 'c': case 'd': case 'e':
     568             :                         case 'f':
     569             :                             c2 |= (digit - 'a' + 10); break;
     570             :                         case 'A': case 'B': case 'C': case 'D': case 'E':
     571             :                         case 'F':
     572             :                             c2 |= (digit - 'A' + 10); break;
     573             :                         default:
     574             :                             raise_errmsg("Invalid \\uXXXX escape", pystr, end - 5);
     575             :                             goto bail;
     576             :                     }
     577             :                 }
     578             :                 if ((c2 & 0xfc00) == 0xdc00)
     579             :                     c = 0x10000 + (((c - 0xd800) << 10) | (c2 - 0xdc00));
     580             :                 else
     581             :                     end -= 6;
     582             :             }
     583             : #endif
     584             :         }
     585           0 :         chunk = PyUnicode_FromUnicode(&c, 1);
     586           0 :         if (chunk == NULL) {
     587           0 :             goto bail;
     588             :         }
     589           0 :         if (PyList_Append(chunks, chunk)) {
     590           0 :             Py_DECREF(chunk);
     591           0 :             goto bail;
     592             :         }
     593           0 :         Py_DECREF(chunk);
     594           0 :     }
     595             : 
     596           0 :     rval = join_list_unicode(chunks);
     597           0 :     if (rval == NULL) {
     598           0 :         goto bail;
     599             :     }
     600           0 :     Py_CLEAR(chunks);
     601           0 :     *next_end_ptr = end;
     602           0 :     return rval;
     603             : bail:
     604           0 :     *next_end_ptr = -1;
     605           0 :     Py_XDECREF(chunks);
     606           0 :     return NULL;
     607             : }
     608             : 
     609             : 
     610             : static PyObject *
     611           0 : scanstring_unicode(PyObject *pystr, Py_ssize_t end, int strict, Py_ssize_t *next_end_ptr)
     612             : {
     613             :     /* Read the JSON string from PyUnicode pystr.
     614             :     end is the index of the first character after the quote.
     615             :     if strict is zero then literal control characters are allowed
     616             :     *next_end_ptr is a return-by-reference index of the character
     617             :         after the end quote
     618             : 
     619             :     Return value is a new PyUnicode
     620             :     */
     621             :     PyObject *rval;
     622           0 :     Py_ssize_t len = PyUnicode_GET_SIZE(pystr);
     623           0 :     Py_ssize_t begin = end - 1;
     624             :     Py_ssize_t next;
     625           0 :     const Py_UNICODE *buf = PyUnicode_AS_UNICODE(pystr);
     626           0 :     PyObject *chunks = PyList_New(0);
     627           0 :     if (chunks == NULL) {
     628           0 :         goto bail;
     629             :     }
     630           0 :     if (end < 0 || len <= end) {
     631           0 :         PyErr_SetString(PyExc_ValueError, "end is out of bounds");
     632           0 :         goto bail;
     633             :     }
     634             :     while (1) {
     635             :         /* Find the end of the string or the next escape */
     636           0 :         Py_UNICODE c = 0;
     637           0 :         PyObject *chunk = NULL;
     638           0 :         for (next = end; next < len; next++) {
     639           0 :             c = buf[next];
     640           0 :             if (c == '"' || c == '\\') {
     641             :                 break;
     642             :             }
     643           0 :             else if (strict && c <= 0x1f) {
     644           0 :                 raise_errmsg("Invalid control character at", pystr, next);
     645           0 :                 goto bail;
     646             :             }
     647             :         }
     648           0 :         if (!(c == '"' || c == '\\')) {
     649           0 :             raise_errmsg("Unterminated string starting at", pystr, begin);
     650           0 :             goto bail;
     651             :         }
     652             :         /* Pick up this chunk if it's not zero length */
     653           0 :         if (next != end) {
     654           0 :             chunk = PyUnicode_FromUnicode(&buf[end], next - end);
     655           0 :             if (chunk == NULL) {
     656           0 :                 goto bail;
     657             :             }
     658           0 :             if (PyList_Append(chunks, chunk)) {
     659           0 :                 Py_DECREF(chunk);
     660           0 :                 goto bail;
     661             :             }
     662           0 :             Py_DECREF(chunk);
     663             :         }
     664           0 :         next++;
     665           0 :         if (c == '"') {
     666           0 :             end = next;
     667           0 :             break;
     668             :         }
     669           0 :         if (next == len) {
     670           0 :             raise_errmsg("Unterminated string starting at", pystr, begin);
     671           0 :             goto bail;
     672             :         }
     673           0 :         c = buf[next];
     674           0 :         if (c != 'u') {
     675             :             /* Non-unicode backslash escapes */
     676           0 :             end = next + 1;
     677           0 :             switch (c) {
     678           0 :                 case '"': break;
     679           0 :                 case '\\': break;
     680           0 :                 case '/': break;
     681           0 :                 case 'b': c = '\b'; break;
     682           0 :                 case 'f': c = '\f'; break;
     683           0 :                 case 'n': c = '\n'; break;
     684           0 :                 case 'r': c = '\r'; break;
     685           0 :                 case 't': c = '\t'; break;
     686           0 :                 default: c = 0;
     687             :             }
     688           0 :             if (c == 0) {
     689           0 :                 raise_errmsg("Invalid \\escape", pystr, end - 2);
     690           0 :                 goto bail;
     691             :             }
     692             :         }
     693             :         else {
     694           0 :             c = 0;
     695           0 :             next++;
     696           0 :             end = next + 4;
     697           0 :             if (end >= len) {
     698           0 :                 raise_errmsg("Invalid \\uXXXX escape", pystr, next - 1);
     699           0 :                 goto bail;
     700             :             }
     701             :             /* Decode 4 hex digits */
     702           0 :             for (; next < end; next++) {
     703           0 :                 Py_UNICODE digit = buf[next];
     704           0 :                 c <<= 4;
     705           0 :                 switch (digit) {
     706             :                     case '0': case '1': case '2': case '3': case '4':
     707             :                     case '5': case '6': case '7': case '8': case '9':
     708           0 :                         c |= (digit - '0'); break;
     709             :                     case 'a': case 'b': case 'c': case 'd': case 'e':
     710             :                     case 'f':
     711           0 :                         c |= (digit - 'a' + 10); break;
     712             :                     case 'A': case 'B': case 'C': case 'D': case 'E':
     713             :                     case 'F':
     714           0 :                         c |= (digit - 'A' + 10); break;
     715             :                     default:
     716           0 :                         raise_errmsg("Invalid \\uXXXX escape", pystr, end - 5);
     717           0 :                         goto bail;
     718             :                 }
     719             :             }
     720             : #ifdef Py_UNICODE_WIDE
     721             :             /* Surrogate pair */
     722             :             if ((c & 0xfc00) == 0xd800 && end + 6 < len &&
     723             :                 buf[next++] == '\\' && buf[next++] == 'u') {
     724             :                 Py_UNICODE c2 = 0;
     725             :                 end += 6;
     726             :                 /* Decode 4 hex digits */
     727             :                 for (; next < end; next++) {
     728             :                     Py_UNICODE digit = buf[next];
     729             :                     c2 <<= 4;
     730             :                     switch (digit) {
     731             :                         case '0': case '1': case '2': case '3': case '4':
     732             :                         case '5': case '6': case '7': case '8': case '9':
     733             :                             c2 |= (digit - '0'); break;
     734             :                         case 'a': case 'b': case 'c': case 'd': case 'e':
     735             :                         case 'f':
     736             :                             c2 |= (digit - 'a' + 10); break;
     737             :                         case 'A': case 'B': case 'C': case 'D': case 'E':
     738             :                         case 'F':
     739             :                             c2 |= (digit - 'A' + 10); break;
     740             :                         default:
     741             :                             raise_errmsg("Invalid \\uXXXX escape", pystr, end - 5);
     742             :                             goto bail;
     743             :                     }
     744             :                 }
     745             :                 if ((c2 & 0xfc00) == 0xdc00)
     746             :                     c = 0x10000 + (((c - 0xd800) << 10) | (c2 - 0xdc00));
     747             :                 else
     748             :                     end -= 6;
     749             :             }
     750             : #endif
     751             :         }
     752           0 :         chunk = PyUnicode_FromUnicode(&c, 1);
     753           0 :         if (chunk == NULL) {
     754           0 :             goto bail;
     755             :         }
     756           0 :         if (PyList_Append(chunks, chunk)) {
     757           0 :             Py_DECREF(chunk);
     758           0 :             goto bail;
     759             :         }
     760           0 :         Py_DECREF(chunk);
     761           0 :     }
     762             : 
     763           0 :     rval = join_list_unicode(chunks);
     764           0 :     if (rval == NULL) {
     765           0 :         goto bail;
     766             :     }
     767           0 :     Py_DECREF(chunks);
     768           0 :     *next_end_ptr = end;
     769           0 :     return rval;
     770             : bail:
     771           0 :     *next_end_ptr = -1;
     772           0 :     Py_XDECREF(chunks);
     773           0 :     return NULL;
     774             : }
     775             : 
     776             : PyDoc_STRVAR(pydoc_scanstring,
     777             :     "scanstring(basestring, end, encoding, strict=True) -> (str, end)\n"
     778             :     "\n"
     779             :     "Scan the string s for a JSON string. End is the index of the\n"
     780             :     "character in s after the quote that started the JSON string.\n"
     781             :     "Unescapes all valid JSON string escape sequences and raises ValueError\n"
     782             :     "on attempt to decode an invalid string. If strict is False then literal\n"
     783             :     "control characters are allowed in the string.\n"
     784             :     "\n"
     785             :     "Returns a tuple of the decoded string and the index of the character in s\n"
     786             :     "after the end quote."
     787             : );
     788             : 
     789             : static PyObject *
     790           0 : py_scanstring(PyObject* self UNUSED, PyObject *args)
     791             : {
     792             :     PyObject *pystr;
     793             :     PyObject *rval;
     794             :     Py_ssize_t end;
     795           0 :     Py_ssize_t next_end = -1;
     796           0 :     char *encoding = NULL;
     797           0 :     int strict = 1;
     798           0 :     if (!PyArg_ParseTuple(args, "OO&|zi:scanstring", &pystr, _convertPyInt_AsSsize_t, &end, &encoding, &strict)) {
     799           0 :         return NULL;
     800             :     }
     801           0 :     if (encoding == NULL) {
     802           0 :         encoding = DEFAULT_ENCODING;
     803             :     }
     804           0 :     if (PyString_Check(pystr)) {
     805           0 :         rval = scanstring_str(pystr, end, encoding, strict, &next_end);
     806             :     }
     807           0 :     else if (PyUnicode_Check(pystr)) {
     808           0 :         rval = scanstring_unicode(pystr, end, strict, &next_end);
     809             :     }
     810             :     else {
     811           0 :         PyErr_Format(PyExc_TypeError,
     812             :                      "first argument must be a string, not %.80s",
     813           0 :                      Py_TYPE(pystr)->tp_name);
     814           0 :         return NULL;
     815             :     }
     816           0 :     return _build_rval_index_tuple(rval, next_end);
     817             : }
     818             : 
     819             : PyDoc_STRVAR(pydoc_encode_basestring_ascii,
     820             :     "encode_basestring_ascii(basestring) -> str\n"
     821             :     "\n"
     822             :     "Return an ASCII-only JSON representation of a Python string"
     823             : );
     824             : 
     825             : static PyObject *
     826           0 : py_encode_basestring_ascii(PyObject* self UNUSED, PyObject *pystr)
     827             : {
     828             :     /* Return an ASCII-only JSON representation of a Python string */
     829             :     /* METH_O */
     830           0 :     if (PyString_Check(pystr)) {
     831           0 :         return ascii_escape_str(pystr);
     832             :     }
     833           0 :     else if (PyUnicode_Check(pystr)) {
     834           0 :         return ascii_escape_unicode(pystr);
     835             :     }
     836             :     else {
     837           0 :         PyErr_Format(PyExc_TypeError,
     838             :                      "first argument must be a string, not %.80s",
     839           0 :                      Py_TYPE(pystr)->tp_name);
     840           0 :         return NULL;
     841             :     }
     842             : }
     843             : 
     844             : static void
     845           3 : scanner_dealloc(PyObject *self)
     846             : {
     847             :     /* Deallocate scanner object */
     848           3 :     scanner_clear(self);
     849           3 :     Py_TYPE(self)->tp_free(self);
     850           3 : }
     851             : 
     852             : static int
     853          18 : scanner_traverse(PyObject *self, visitproc visit, void *arg)
     854             : {
     855             :     PyScannerObject *s;
     856             :     assert(PyScanner_Check(self));
     857          18 :     s = (PyScannerObject *)self;
     858          18 :     Py_VISIT(s->encoding);
     859          18 :     Py_VISIT(s->strict);
     860          18 :     Py_VISIT(s->object_hook);
     861          18 :     Py_VISIT(s->pairs_hook);
     862          18 :     Py_VISIT(s->parse_float);
     863          18 :     Py_VISIT(s->parse_int);
     864          18 :     Py_VISIT(s->parse_constant);
     865          18 :     return 0;
     866             : }
     867             : 
     868             : static int
     869           3 : scanner_clear(PyObject *self)
     870             : {
     871             :     PyScannerObject *s;
     872             :     assert(PyScanner_Check(self));
     873           3 :     s = (PyScannerObject *)self;
     874           3 :     Py_CLEAR(s->encoding);
     875           3 :     Py_CLEAR(s->strict);
     876           3 :     Py_CLEAR(s->object_hook);
     877           3 :     Py_CLEAR(s->pairs_hook);
     878           3 :     Py_CLEAR(s->parse_float);
     879           3 :     Py_CLEAR(s->parse_int);
     880           3 :     Py_CLEAR(s->parse_constant);
     881           3 :     return 0;
     882             : }
     883             : 
     884             : static PyObject *
     885           0 : _parse_object_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
     886             :     /* Read a JSON object from PyString pystr.
     887             :     idx is the index of the first character after the opening curly brace.
     888             :     *next_idx_ptr is a return-by-reference index to the first character after
     889             :         the closing curly brace.
     890             : 
     891             :     Returns a new PyObject (usually a dict, but object_hook can change that)
     892             :     */
     893           0 :     char *str = PyString_AS_STRING(pystr);
     894           0 :     Py_ssize_t end_idx = PyString_GET_SIZE(pystr) - 1;
     895             :     PyObject *rval;
     896             :     PyObject *pairs;
     897             :     PyObject *item;
     898           0 :     PyObject *key = NULL;
     899           0 :     PyObject *val = NULL;
     900           0 :     char *encoding = PyString_AS_STRING(s->encoding);
     901           0 :     int strict = PyObject_IsTrue(s->strict);
     902             :     Py_ssize_t next_idx;
     903             : 
     904           0 :     if (strict < 0)
     905           0 :         return NULL;
     906             : 
     907           0 :     pairs = PyList_New(0);
     908           0 :     if (pairs == NULL)
     909           0 :         return NULL;
     910             : 
     911             :     /* skip whitespace after { */
     912           0 :     while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
     913             : 
     914             :     /* only loop if the object is non-empty */
     915           0 :     if (idx <= end_idx && str[idx] != '}') {
     916           0 :         while (idx <= end_idx) {
     917             :             /* read key */
     918           0 :             if (str[idx] != '"') {
     919           0 :                 raise_errmsg("Expecting property name", pystr, idx);
     920           0 :                 goto bail;
     921             :             }
     922           0 :             key = scanstring_str(pystr, idx + 1, encoding, strict, &next_idx);
     923           0 :             if (key == NULL)
     924           0 :                 goto bail;
     925           0 :             idx = next_idx;
     926             : 
     927             :             /* skip whitespace between key and : delimiter, read :, skip whitespace */
     928           0 :             while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
     929           0 :             if (idx > end_idx || str[idx] != ':') {
     930           0 :                 raise_errmsg("Expecting : delimiter", pystr, idx);
     931           0 :                 goto bail;
     932             :             }
     933           0 :             idx++;
     934           0 :             while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
     935             : 
     936             :             /* read any JSON data type */
     937           0 :             val = scan_once_str(s, pystr, idx, &next_idx);
     938           0 :             if (val == NULL)
     939           0 :                 goto bail;
     940             : 
     941           0 :             item = PyTuple_Pack(2, key, val);
     942           0 :             if (item == NULL)
     943           0 :                 goto bail;
     944           0 :             Py_CLEAR(key);
     945           0 :             Py_CLEAR(val);
     946           0 :             if (PyList_Append(pairs, item) == -1) {
     947           0 :                 Py_DECREF(item);
     948           0 :                 goto bail;
     949             :             }
     950           0 :             Py_DECREF(item);
     951           0 :             idx = next_idx;
     952             : 
     953             :             /* skip whitespace before } or , */
     954           0 :             while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
     955             : 
     956             :             /* bail if the object is closed or we didn't get the , delimiter */
     957           0 :             if (idx > end_idx) break;
     958           0 :             if (str[idx] == '}') {
     959           0 :                 break;
     960             :             }
     961           0 :             else if (str[idx] != ',') {
     962           0 :                 raise_errmsg("Expecting , delimiter", pystr, idx);
     963           0 :                 goto bail;
     964             :             }
     965           0 :             idx++;
     966             : 
     967             :             /* skip whitespace after , delimiter */
     968           0 :             while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
     969             :         }
     970             :     }
     971             :     /* verify that idx < end_idx, str[idx] should be '}' */
     972           0 :     if (idx > end_idx || str[idx] != '}') {
     973           0 :         raise_errmsg("Expecting object", pystr, end_idx);
     974           0 :         goto bail;
     975             :     }
     976             : 
     977             :     /* if pairs_hook is not None: rval = object_pairs_hook(pairs) */
     978           0 :     if (s->pairs_hook != Py_None) {
     979           0 :         val = PyObject_CallFunctionObjArgs(s->pairs_hook, pairs, NULL);
     980           0 :         if (val == NULL)
     981           0 :             goto bail;
     982           0 :         Py_DECREF(pairs);
     983           0 :         *next_idx_ptr = idx + 1;
     984           0 :         return val;
     985             :     }
     986             : 
     987           0 :     rval = PyObject_CallFunctionObjArgs((PyObject *)(&PyDict_Type), 
     988             :                                          pairs, NULL);
     989           0 :     if (rval == NULL)
     990           0 :         goto bail;
     991           0 :     Py_CLEAR(pairs);
     992             : 
     993             :     /* if object_hook is not None: rval = object_hook(rval) */
     994           0 :     if (s->object_hook != Py_None) {
     995           0 :         val = PyObject_CallFunctionObjArgs(s->object_hook, rval, NULL);
     996           0 :         if (val == NULL)
     997           0 :             goto bail;
     998           0 :         Py_DECREF(rval);
     999           0 :         rval = val;
    1000           0 :         val = NULL;
    1001             :     }
    1002           0 :     *next_idx_ptr = idx + 1;
    1003           0 :     return rval;
    1004             : bail:
    1005           0 :     Py_XDECREF(key);
    1006           0 :     Py_XDECREF(val);
    1007           0 :     Py_XDECREF(pairs);
    1008           0 :     return NULL;
    1009             : }
    1010             : 
    1011             : static PyObject *
    1012           0 : _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
    1013             :     /* Read a JSON object from PyUnicode pystr.
    1014             :     idx is the index of the first character after the opening curly brace.
    1015             :     *next_idx_ptr is a return-by-reference index to the first character after
    1016             :         the closing curly brace.
    1017             : 
    1018             :     Returns a new PyObject (usually a dict, but object_hook can change that)
    1019             :     */
    1020           0 :     Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr);
    1021           0 :     Py_ssize_t end_idx = PyUnicode_GET_SIZE(pystr) - 1;
    1022             :     PyObject *rval;
    1023             :     PyObject *pairs;
    1024             :     PyObject *item;
    1025           0 :     PyObject *key = NULL;
    1026           0 :     PyObject *val = NULL;
    1027           0 :     int strict = PyObject_IsTrue(s->strict);
    1028             :     Py_ssize_t next_idx;
    1029             : 
    1030           0 :     if (strict < 0)
    1031           0 :         return NULL;
    1032             : 
    1033           0 :     pairs = PyList_New(0);
    1034           0 :     if (pairs == NULL)
    1035           0 :         return NULL;
    1036             : 
    1037             :     /* skip whitespace after { */
    1038           0 :     while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
    1039             : 
    1040             :     /* only loop if the object is non-empty */
    1041           0 :     if (idx <= end_idx && str[idx] != '}') {
    1042           0 :         while (idx <= end_idx) {
    1043             :             /* read key */
    1044           0 :             if (str[idx] != '"') {
    1045           0 :                 raise_errmsg("Expecting property name enclosed in double quotes", pystr, idx);
    1046           0 :                 goto bail;
    1047             :             }
    1048           0 :             key = scanstring_unicode(pystr, idx + 1, strict, &next_idx);
    1049           0 :             if (key == NULL)
    1050           0 :                 goto bail;
    1051           0 :             idx = next_idx;
    1052             : 
    1053             :             /* skip whitespace between key and : delimiter, read :, skip whitespace */
    1054           0 :             while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
    1055           0 :             if (idx > end_idx || str[idx] != ':') {
    1056           0 :                 raise_errmsg("Expecting ':' delimiter", pystr, idx);
    1057           0 :                 goto bail;
    1058             :             }
    1059           0 :             idx++;
    1060           0 :             while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
    1061             : 
    1062             :             /* read any JSON term */
    1063           0 :             val = scan_once_unicode(s, pystr, idx, &next_idx);
    1064           0 :             if (val == NULL)
    1065           0 :                 goto bail;
    1066             : 
    1067           0 :             item = PyTuple_Pack(2, key, val);
    1068           0 :             if (item == NULL)
    1069           0 :                 goto bail;
    1070           0 :             Py_CLEAR(key);
    1071           0 :             Py_CLEAR(val);
    1072           0 :             if (PyList_Append(pairs, item) == -1) {
    1073           0 :                 Py_DECREF(item);
    1074           0 :                 goto bail;
    1075             :             }
    1076           0 :             Py_DECREF(item);
    1077           0 :             idx = next_idx;
    1078             : 
    1079             :             /* skip whitespace before } or , */
    1080           0 :             while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
    1081             : 
    1082             :             /* bail if the object is closed or we didn't get the , delimiter */
    1083           0 :             if (idx > end_idx) break;
    1084           0 :             if (str[idx] == '}') {
    1085           0 :                 break;
    1086             :             }
    1087           0 :             else if (str[idx] != ',') {
    1088           0 :                 raise_errmsg("Expecting ',' delimiter", pystr, idx);
    1089           0 :                 goto bail;
    1090             :             }
    1091           0 :             idx++;
    1092             : 
    1093             :             /* skip whitespace after , delimiter */
    1094           0 :             while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
    1095             :         }
    1096             :     }
    1097             : 
    1098             :     /* verify that idx < end_idx, str[idx] should be '}' */
    1099           0 :     if (idx > end_idx || str[idx] != '}') {
    1100           0 :         raise_errmsg("Expecting object", pystr, end_idx);
    1101           0 :         goto bail;
    1102             :     }
    1103             : 
    1104             :     /* if pairs_hook is not None: rval = object_pairs_hook(pairs) */
    1105           0 :     if (s->pairs_hook != Py_None) {
    1106           0 :         val = PyObject_CallFunctionObjArgs(s->pairs_hook, pairs, NULL);
    1107           0 :         if (val == NULL)
    1108           0 :             goto bail;
    1109           0 :         Py_DECREF(pairs);
    1110           0 :         *next_idx_ptr = idx + 1;
    1111           0 :         return val;
    1112             :     }
    1113             : 
    1114           0 :     rval = PyObject_CallFunctionObjArgs((PyObject *)(&PyDict_Type), 
    1115             :                                          pairs, NULL);
    1116           0 :     if (rval == NULL)
    1117           0 :         goto bail;
    1118           0 :     Py_CLEAR(pairs);
    1119             : 
    1120             :     /* if object_hook is not None: rval = object_hook(rval) */
    1121           0 :     if (s->object_hook != Py_None) {
    1122           0 :         val = PyObject_CallFunctionObjArgs(s->object_hook, rval, NULL);
    1123           0 :         if (val == NULL)
    1124           0 :             goto bail;
    1125           0 :         Py_DECREF(rval);
    1126           0 :         rval = val;
    1127           0 :         val = NULL;
    1128             :     }
    1129           0 :     *next_idx_ptr = idx + 1;
    1130           0 :     return rval;
    1131             : bail:
    1132           0 :     Py_XDECREF(key);
    1133           0 :     Py_XDECREF(val);
    1134           0 :     Py_XDECREF(pairs);
    1135           0 :     return NULL;
    1136             : }
    1137             : 
    1138             : static PyObject *
    1139           0 : _parse_array_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
    1140             :     /* Read a JSON array from PyString pystr.
    1141             :     idx is the index of the first character after the opening brace.
    1142             :     *next_idx_ptr is a return-by-reference index to the first character after
    1143             :         the closing brace.
    1144             : 
    1145             :     Returns a new PyList
    1146             :     */
    1147           0 :     char *str = PyString_AS_STRING(pystr);
    1148           0 :     Py_ssize_t end_idx = PyString_GET_SIZE(pystr) - 1;
    1149           0 :     PyObject *val = NULL;
    1150           0 :     PyObject *rval = PyList_New(0);
    1151             :     Py_ssize_t next_idx;
    1152           0 :     if (rval == NULL)
    1153           0 :         return NULL;
    1154             : 
    1155             :     /* skip whitespace after [ */
    1156           0 :     while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
    1157             : 
    1158             :     /* only loop if the array is non-empty */
    1159           0 :     if (idx <= end_idx && str[idx] != ']') {
    1160           0 :         while (idx <= end_idx) {
    1161             : 
    1162             :             /* read any JSON term and de-tuplefy the (rval, idx) */
    1163           0 :             val = scan_once_str(s, pystr, idx, &next_idx);
    1164           0 :             if (val == NULL)
    1165           0 :                 goto bail;
    1166             : 
    1167           0 :             if (PyList_Append(rval, val) == -1)
    1168           0 :                 goto bail;
    1169             : 
    1170           0 :             Py_CLEAR(val);
    1171           0 :             idx = next_idx;
    1172             : 
    1173             :             /* skip whitespace between term and , */
    1174           0 :             while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
    1175             : 
    1176             :             /* bail if the array is closed or we didn't get the , delimiter */
    1177           0 :             if (idx > end_idx) break;
    1178           0 :             if (str[idx] == ']') {
    1179           0 :                 break;
    1180             :             }
    1181           0 :             else if (str[idx] != ',') {
    1182           0 :                 raise_errmsg("Expecting , delimiter", pystr, idx);
    1183           0 :                 goto bail;
    1184             :             }
    1185           0 :             idx++;
    1186             : 
    1187             :             /* skip whitespace after , */
    1188           0 :             while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
    1189             :         }
    1190             :     }
    1191             : 
    1192             :     /* verify that idx < end_idx, str[idx] should be ']' */
    1193           0 :     if (idx > end_idx || str[idx] != ']') {
    1194           0 :         raise_errmsg("Expecting object", pystr, end_idx);
    1195           0 :         goto bail;
    1196             :     }
    1197           0 :     *next_idx_ptr = idx + 1;
    1198           0 :     return rval;
    1199             : bail:
    1200           0 :     Py_XDECREF(val);
    1201           0 :     Py_DECREF(rval);
    1202           0 :     return NULL;
    1203             : }
    1204             : 
    1205             : static PyObject *
    1206           0 : _parse_array_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
    1207             :     /* Read a JSON array from PyString pystr.
    1208             :     idx is the index of the first character after the opening brace.
    1209             :     *next_idx_ptr is a return-by-reference index to the first character after
    1210             :         the closing brace.
    1211             : 
    1212             :     Returns a new PyList
    1213             :     */
    1214           0 :     Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr);
    1215           0 :     Py_ssize_t end_idx = PyUnicode_GET_SIZE(pystr) - 1;
    1216           0 :     PyObject *val = NULL;
    1217           0 :     PyObject *rval = PyList_New(0);
    1218             :     Py_ssize_t next_idx;
    1219           0 :     if (rval == NULL)
    1220           0 :         return NULL;
    1221             : 
    1222             :     /* skip whitespace after [ */
    1223           0 :     while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
    1224             : 
    1225             :     /* only loop if the array is non-empty */
    1226           0 :     if (idx <= end_idx && str[idx] != ']') {
    1227           0 :         while (idx <= end_idx) {
    1228             : 
    1229             :             /* read any JSON term  */
    1230           0 :             val = scan_once_unicode(s, pystr, idx, &next_idx);
    1231           0 :             if (val == NULL)
    1232           0 :                 goto bail;
    1233             : 
    1234           0 :             if (PyList_Append(rval, val) == -1)
    1235           0 :                 goto bail;
    1236             : 
    1237           0 :             Py_CLEAR(val);
    1238           0 :             idx = next_idx;
    1239             : 
    1240             :             /* skip whitespace between term and , */
    1241           0 :             while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
    1242             : 
    1243             :             /* bail if the array is closed or we didn't get the , delimiter */
    1244           0 :             if (idx > end_idx) break;
    1245           0 :             if (str[idx] == ']') {
    1246           0 :                 break;
    1247             :             }
    1248           0 :             else if (str[idx] != ',') {
    1249           0 :                 raise_errmsg("Expecting ',' delimiter", pystr, idx);
    1250           0 :                 goto bail;
    1251             :             }
    1252           0 :             idx++;
    1253             : 
    1254             :             /* skip whitespace after , */
    1255           0 :             while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++;
    1256             :         }
    1257             :     }
    1258             : 
    1259             :     /* verify that idx < end_idx, str[idx] should be ']' */
    1260           0 :     if (idx > end_idx || str[idx] != ']') {
    1261           0 :         raise_errmsg("Expecting object", pystr, end_idx);
    1262           0 :         goto bail;
    1263             :     }
    1264           0 :     *next_idx_ptr = idx + 1;
    1265           0 :     return rval;
    1266             : bail:
    1267           0 :     Py_XDECREF(val);
    1268           0 :     Py_DECREF(rval);
    1269           0 :     return NULL;
    1270             : }
    1271             : 
    1272             : static PyObject *
    1273           0 : _parse_constant(PyScannerObject *s, char *constant, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
    1274             :     /* Read a JSON constant from PyString pystr.
    1275             :     constant is the constant string that was found
    1276             :         ("NaN", "Infinity", "-Infinity").
    1277             :     idx is the index of the first character of the constant
    1278             :     *next_idx_ptr is a return-by-reference index to the first character after
    1279             :         the constant.
    1280             : 
    1281             :     Returns the result of parse_constant
    1282             :     */
    1283             :     PyObject *cstr;
    1284             :     PyObject *rval;
    1285             :     /* constant is "NaN", "Infinity", or "-Infinity" */
    1286           0 :     cstr = PyString_InternFromString(constant);
    1287           0 :     if (cstr == NULL)
    1288           0 :         return NULL;
    1289             : 
    1290             :     /* rval = parse_constant(constant) */
    1291           0 :     rval = PyObject_CallFunctionObjArgs(s->parse_constant, cstr, NULL);
    1292           0 :     idx += PyString_GET_SIZE(cstr);
    1293           0 :     Py_DECREF(cstr);
    1294           0 :     *next_idx_ptr = idx;
    1295           0 :     return rval;
    1296             : }
    1297             : 
    1298             : static PyObject *
    1299           0 : _match_number_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t start, Py_ssize_t *next_idx_ptr) {
    1300             :     /* Read a JSON number from PyString pystr.
    1301             :     idx is the index of the first character of the number
    1302             :     *next_idx_ptr is a return-by-reference index to the first character after
    1303             :         the number.
    1304             : 
    1305             :     Returns a new PyObject representation of that number:
    1306             :         PyInt, PyLong, or PyFloat.
    1307             :         May return other types if parse_int or parse_float are set
    1308             :     */
    1309           0 :     char *str = PyString_AS_STRING(pystr);
    1310           0 :     Py_ssize_t end_idx = PyString_GET_SIZE(pystr) - 1;
    1311           0 :     Py_ssize_t idx = start;
    1312           0 :     int is_float = 0;
    1313             :     PyObject *rval;
    1314             :     PyObject *numstr;
    1315             : 
    1316             :     /* read a sign if it's there, make sure it's not the end of the string */
    1317           0 :     if (str[idx] == '-') {
    1318           0 :         idx++;
    1319           0 :         if (idx > end_idx) {
    1320           0 :             PyErr_SetNone(PyExc_StopIteration);
    1321           0 :             return NULL;
    1322             :         }
    1323             :     }
    1324             : 
    1325             :     /* read as many integer digits as we find as long as it doesn't start with 0 */
    1326           0 :     if (str[idx] >= '1' && str[idx] <= '9') {
    1327           0 :         idx++;
    1328           0 :         while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
    1329             :     }
    1330             :     /* if it starts with 0 we only expect one integer digit */
    1331           0 :     else if (str[idx] == '0') {
    1332           0 :         idx++;
    1333             :     }
    1334             :     /* no integer digits, error */
    1335             :     else {
    1336           0 :         PyErr_SetNone(PyExc_StopIteration);
    1337           0 :         return NULL;
    1338             :     }
    1339             : 
    1340             :     /* if the next char is '.' followed by a digit then read all float digits */
    1341           0 :     if (idx < end_idx && str[idx] == '.' && str[idx + 1] >= '0' && str[idx + 1] <= '9') {
    1342           0 :         is_float = 1;
    1343           0 :         idx += 2;
    1344           0 :         while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
    1345             :     }
    1346             : 
    1347             :     /* if the next char is 'e' or 'E' then maybe read the exponent (or backtrack) */
    1348           0 :     if (idx < end_idx && (str[idx] == 'e' || str[idx] == 'E')) {
    1349             : 
    1350             :         /* save the index of the 'e' or 'E' just in case we need to backtrack */
    1351           0 :         Py_ssize_t e_start = idx;
    1352           0 :         idx++;
    1353             : 
    1354             :         /* read an exponent sign if present */
    1355           0 :         if (idx < end_idx && (str[idx] == '-' || str[idx] == '+')) idx++;
    1356             : 
    1357             :         /* read all digits */
    1358           0 :         while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
    1359             : 
    1360             :         /* if we got a digit, then parse as float. if not, backtrack */
    1361           0 :         if (str[idx - 1] >= '0' && str[idx - 1] <= '9') {
    1362           0 :             is_float = 1;
    1363             :         }
    1364             :         else {
    1365           0 :             idx = e_start;
    1366             :         }
    1367             :     }
    1368             : 
    1369             :     /* copy the section we determined to be a number */
    1370           0 :     numstr = PyString_FromStringAndSize(&str[start], idx - start);
    1371           0 :     if (numstr == NULL)
    1372           0 :         return NULL;
    1373           0 :     if (is_float) {
    1374             :         /* parse as a float using a fast path if available, otherwise call user defined method */
    1375           0 :         if (s->parse_float != (PyObject *)&PyFloat_Type) {
    1376           0 :             rval = PyObject_CallFunctionObjArgs(s->parse_float, numstr, NULL);
    1377             :         }
    1378             :         else {
    1379           0 :             double d = PyOS_string_to_double(PyString_AS_STRING(numstr),
    1380             :                                              NULL, NULL);
    1381           0 :             if (d == -1.0 && PyErr_Occurred())
    1382           0 :                 return NULL;
    1383           0 :             rval = PyFloat_FromDouble(d);
    1384             :         }
    1385             :     }
    1386             :     else {
    1387             :         /* parse as an int using a fast path if available, otherwise call user defined method */
    1388           0 :         if (s->parse_int != (PyObject *)&PyInt_Type) {
    1389           0 :             rval = PyObject_CallFunctionObjArgs(s->parse_int, numstr, NULL);
    1390             :         }
    1391             :         else {
    1392           0 :             rval = PyInt_FromString(PyString_AS_STRING(numstr), NULL, 10);
    1393             :         }
    1394             :     }
    1395           0 :     Py_DECREF(numstr);
    1396           0 :     *next_idx_ptr = idx;
    1397           0 :     return rval;
    1398             : }
    1399             : 
    1400             : static PyObject *
    1401           0 : _match_number_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t start, Py_ssize_t *next_idx_ptr) {
    1402             :     /* Read a JSON number from PyUnicode pystr.
    1403             :     idx is the index of the first character of the number
    1404             :     *next_idx_ptr is a return-by-reference index to the first character after
    1405             :         the number.
    1406             : 
    1407             :     Returns a new PyObject representation of that number:
    1408             :         PyInt, PyLong, or PyFloat.
    1409             :         May return other types if parse_int or parse_float are set
    1410             :     */
    1411           0 :     Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr);
    1412           0 :     Py_ssize_t end_idx = PyUnicode_GET_SIZE(pystr) - 1;
    1413           0 :     Py_ssize_t idx = start;
    1414           0 :     int is_float = 0;
    1415             :     PyObject *rval;
    1416             :     PyObject *numstr;
    1417             : 
    1418             :     /* read a sign if it's there, make sure it's not the end of the string */
    1419           0 :     if (str[idx] == '-') {
    1420           0 :         idx++;
    1421           0 :         if (idx > end_idx) {
    1422           0 :             PyErr_SetNone(PyExc_StopIteration);
    1423           0 :             return NULL;
    1424             :         }
    1425             :     }
    1426             : 
    1427             :     /* read as many integer digits as we find as long as it doesn't start with 0 */
    1428           0 :     if (str[idx] >= '1' && str[idx] <= '9') {
    1429           0 :         idx++;
    1430           0 :         while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
    1431             :     }
    1432             :     /* if it starts with 0 we only expect one integer digit */
    1433           0 :     else if (str[idx] == '0') {
    1434           0 :         idx++;
    1435             :     }
    1436             :     /* no integer digits, error */
    1437             :     else {
    1438           0 :         PyErr_SetNone(PyExc_StopIteration);
    1439           0 :         return NULL;
    1440             :     }
    1441             : 
    1442             :     /* if the next char is '.' followed by a digit then read all float digits */
    1443           0 :     if (idx < end_idx && str[idx] == '.' && str[idx + 1] >= '0' && str[idx + 1] <= '9') {
    1444           0 :         is_float = 1;
    1445           0 :         idx += 2;
    1446           0 :         while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
    1447             :     }
    1448             : 
    1449             :     /* if the next char is 'e' or 'E' then maybe read the exponent (or backtrack) */
    1450           0 :     if (idx < end_idx && (str[idx] == 'e' || str[idx] == 'E')) {
    1451           0 :         Py_ssize_t e_start = idx;
    1452           0 :         idx++;
    1453             : 
    1454             :         /* read an exponent sign if present */
    1455           0 :         if (idx < end_idx && (str[idx] == '-' || str[idx] == '+')) idx++;
    1456             : 
    1457             :         /* read all digits */
    1458           0 :         while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++;
    1459             : 
    1460             :         /* if we got a digit, then parse as float. if not, backtrack */
    1461           0 :         if (str[idx - 1] >= '0' && str[idx - 1] <= '9') {
    1462           0 :             is_float = 1;
    1463             :         }
    1464             :         else {
    1465           0 :             idx = e_start;
    1466             :         }
    1467             :     }
    1468             : 
    1469             :     /* copy the section we determined to be a number */
    1470           0 :     numstr = PyUnicode_FromUnicode(&str[start], idx - start);
    1471           0 :     if (numstr == NULL)
    1472           0 :         return NULL;
    1473           0 :     if (is_float) {
    1474             :         /* parse as a float using a fast path if available, otherwise call user defined method */
    1475           0 :         if (s->parse_float != (PyObject *)&PyFloat_Type) {
    1476           0 :             rval = PyObject_CallFunctionObjArgs(s->parse_float, numstr, NULL);
    1477             :         }
    1478             :         else {
    1479           0 :             rval = PyFloat_FromString(numstr, NULL);
    1480             :         }
    1481             :     }
    1482             :     else {
    1483             :         /* no fast path for unicode -> int, just call */
    1484           0 :         rval = PyObject_CallFunctionObjArgs(s->parse_int, numstr, NULL);
    1485             :     }
    1486           0 :     Py_DECREF(numstr);
    1487           0 :     *next_idx_ptr = idx;
    1488           0 :     return rval;
    1489             : }
    1490             : 
    1491             : static PyObject *
    1492           0 : scan_once_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr)
    1493             : {
    1494             :     /* Read one JSON term (of any kind) from PyString pystr.
    1495             :     idx is the index of the first character of the term
    1496             :     *next_idx_ptr is a return-by-reference index to the first character after
    1497             :         the number.
    1498             : 
    1499             :     Returns a new PyObject representation of the term.
    1500             :     */
    1501             :     PyObject *res;
    1502             :     int strict;
    1503           0 :     char *str = PyString_AS_STRING(pystr);
    1504           0 :     Py_ssize_t length = PyString_GET_SIZE(pystr);
    1505           0 :     if (idx < 0) {
    1506           0 :         PyErr_SetString(PyExc_ValueError, "idx cannot be negative");
    1507           0 :         return NULL;
    1508             :     }
    1509           0 :     if (idx >= length) {
    1510           0 :         PyErr_SetNone(PyExc_StopIteration);
    1511           0 :         return NULL;
    1512             :     }
    1513           0 :     switch (str[idx]) {
    1514             :         case '"':
    1515             :             /* string */
    1516           0 :             strict = PyObject_IsTrue(s->strict);
    1517           0 :             if (strict < 0)
    1518           0 :                 return NULL;
    1519           0 :             return scanstring_str(pystr, idx + 1,
    1520           0 :                 PyString_AS_STRING(s->encoding), strict, next_idx_ptr);
    1521             :         case '{':
    1522             :             /* object */
    1523           0 :             if (Py_EnterRecursiveCall(" while decoding a JSON object "
    1524             :                                       "from a byte string"))
    1525           0 :                 return NULL;
    1526           0 :             res = _parse_object_str(s, pystr, idx + 1, next_idx_ptr);
    1527           0 :             Py_LeaveRecursiveCall();
    1528           0 :             return res;
    1529             :         case '[':
    1530             :             /* array */
    1531           0 :             if (Py_EnterRecursiveCall(" while decoding a JSON array "
    1532             :                                       "from a byte string"))
    1533           0 :                 return NULL;
    1534           0 :             res = _parse_array_str(s, pystr, idx + 1, next_idx_ptr);
    1535           0 :             Py_LeaveRecursiveCall();
    1536           0 :             return res;
    1537             :         case 'n':
    1538             :             /* null */
    1539           0 :             if ((idx + 3 < length) && str[idx + 1] == 'u' && str[idx + 2] == 'l' && str[idx + 3] == 'l') {
    1540           0 :                 Py_INCREF(Py_None);
    1541           0 :                 *next_idx_ptr = idx + 4;
    1542           0 :                 return Py_None;
    1543             :             }
    1544           0 :             break;
    1545             :         case 't':
    1546             :             /* true */
    1547           0 :             if ((idx + 3 < length) && str[idx + 1] == 'r' && str[idx + 2] == 'u' && str[idx + 3] == 'e') {
    1548           0 :                 Py_INCREF(Py_True);
    1549           0 :                 *next_idx_ptr = idx + 4;
    1550           0 :                 return Py_True;
    1551             :             }
    1552           0 :             break;
    1553             :         case 'f':
    1554             :             /* false */
    1555           0 :             if ((idx + 4 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'l' && str[idx + 3] == 's' && str[idx + 4] == 'e') {
    1556           0 :                 Py_INCREF(Py_False);
    1557           0 :                 *next_idx_ptr = idx + 5;
    1558           0 :                 return Py_False;
    1559             :             }
    1560           0 :             break;
    1561             :         case 'N':
    1562             :             /* NaN */
    1563           0 :             if ((idx + 2 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'N') {
    1564           0 :                 return _parse_constant(s, "NaN", idx, next_idx_ptr);
    1565             :             }
    1566           0 :             break;
    1567             :         case 'I':
    1568             :             /* Infinity */
    1569           0 :             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') {
    1570           0 :                 return _parse_constant(s, "Infinity", idx, next_idx_ptr);
    1571             :             }
    1572           0 :             break;
    1573             :         case '-':
    1574             :             /* -Infinity */
    1575           0 :             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') {
    1576           0 :                 return _parse_constant(s, "-Infinity", idx, next_idx_ptr);
    1577             :             }
    1578           0 :             break;
    1579             :     }
    1580             :     /* Didn't find a string, object, array, or named constant. Look for a number. */
    1581           0 :     return _match_number_str(s, pystr, idx, next_idx_ptr);
    1582             : }
    1583             : 
    1584             : static PyObject *
    1585           0 : scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr)
    1586             : {
    1587             :     /* Read one JSON term (of any kind) from PyUnicode pystr.
    1588             :     idx is the index of the first character of the term
    1589             :     *next_idx_ptr is a return-by-reference index to the first character after
    1590             :         the number.
    1591             : 
    1592             :     Returns a new PyObject representation of the term.
    1593             :     */
    1594             :     PyObject *res;
    1595             :     int strict;
    1596           0 :     Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr);
    1597           0 :     Py_ssize_t length = PyUnicode_GET_SIZE(pystr);
    1598           0 :     if (idx < 0) {
    1599           0 :         PyErr_SetString(PyExc_ValueError, "idx cannot be negative");
    1600           0 :         return NULL;
    1601             :     }
    1602           0 :     if (idx >= length) {
    1603           0 :         PyErr_SetNone(PyExc_StopIteration);
    1604           0 :         return NULL;
    1605             :     }
    1606           0 :     switch (str[idx]) {
    1607             :         case '"':
    1608             :             /* string */
    1609           0 :             strict = PyObject_IsTrue(s->strict);
    1610           0 :             if (strict < 0)
    1611           0 :                 return NULL;
    1612           0 :             return scanstring_unicode(pystr, idx + 1, strict, next_idx_ptr);
    1613             :         case '{':
    1614             :             /* object */
    1615           0 :             if (Py_EnterRecursiveCall(" while decoding a JSON object "
    1616             :                                       "from a unicode string"))
    1617           0 :                 return NULL;
    1618           0 :             res = _parse_object_unicode(s, pystr, idx + 1, next_idx_ptr);
    1619           0 :             Py_LeaveRecursiveCall();
    1620           0 :             return res;
    1621             :         case '[':
    1622             :             /* array */
    1623           0 :             if (Py_EnterRecursiveCall(" while decoding a JSON array "
    1624             :                                       "from a unicode string"))
    1625           0 :                 return NULL;
    1626           0 :             res = _parse_array_unicode(s, pystr, idx + 1, next_idx_ptr);
    1627           0 :             Py_LeaveRecursiveCall();
    1628           0 :             return res;
    1629             :         case 'n':
    1630             :             /* null */
    1631           0 :             if ((idx + 3 < length) && str[idx + 1] == 'u' && str[idx + 2] == 'l' && str[idx + 3] == 'l') {
    1632           0 :                 Py_INCREF(Py_None);
    1633           0 :                 *next_idx_ptr = idx + 4;
    1634           0 :                 return Py_None;
    1635             :             }
    1636           0 :             break;
    1637             :         case 't':
    1638             :             /* true */
    1639           0 :             if ((idx + 3 < length) && str[idx + 1] == 'r' && str[idx + 2] == 'u' && str[idx + 3] == 'e') {
    1640           0 :                 Py_INCREF(Py_True);
    1641           0 :                 *next_idx_ptr = idx + 4;
    1642           0 :                 return Py_True;
    1643             :             }
    1644           0 :             break;
    1645             :         case 'f':
    1646             :             /* false */
    1647           0 :             if ((idx + 4 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'l' && str[idx + 3] == 's' && str[idx + 4] == 'e') {
    1648           0 :                 Py_INCREF(Py_False);
    1649           0 :                 *next_idx_ptr = idx + 5;
    1650           0 :                 return Py_False;
    1651             :             }
    1652           0 :             break;
    1653             :         case 'N':
    1654             :             /* NaN */
    1655           0 :             if ((idx + 2 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'N') {
    1656           0 :                 return _parse_constant(s, "NaN", idx, next_idx_ptr);
    1657             :             }
    1658           0 :             break;
    1659             :         case 'I':
    1660             :             /* Infinity */
    1661           0 :             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') {
    1662           0 :                 return _parse_constant(s, "Infinity", idx, next_idx_ptr);
    1663             :             }
    1664           0 :             break;
    1665             :         case '-':
    1666             :             /* -Infinity */
    1667           0 :             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') {
    1668           0 :                 return _parse_constant(s, "-Infinity", idx, next_idx_ptr);
    1669             :             }
    1670           0 :             break;
    1671             :     }
    1672             :     /* Didn't find a string, object, array, or named constant. Look for a number. */
    1673           0 :     return _match_number_unicode(s, pystr, idx, next_idx_ptr);
    1674             : }
    1675             : 
    1676             : static PyObject *
    1677           0 : scanner_call(PyObject *self, PyObject *args, PyObject *kwds)
    1678             : {
    1679             :     /* Python callable interface to scan_once_{str,unicode} */
    1680             :     PyObject *pystr;
    1681             :     PyObject *rval;
    1682             :     Py_ssize_t idx;
    1683           0 :     Py_ssize_t next_idx = -1;
    1684             :     static char *kwlist[] = {"string", "idx", NULL};
    1685             :     PyScannerObject *s;
    1686             :     assert(PyScanner_Check(self));
    1687           0 :     s = (PyScannerObject *)self;
    1688           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&:scan_once", kwlist, &pystr, _convertPyInt_AsSsize_t, &idx))
    1689           0 :         return NULL;
    1690             : 
    1691           0 :     if (PyString_Check(pystr)) {
    1692           0 :         rval = scan_once_str(s, pystr, idx, &next_idx);
    1693             :     }
    1694           0 :     else if (PyUnicode_Check(pystr)) {
    1695           0 :         rval = scan_once_unicode(s, pystr, idx, &next_idx);
    1696             :     }
    1697             :     else {
    1698           0 :         PyErr_Format(PyExc_TypeError,
    1699             :                  "first argument must be a string, not %.80s",
    1700           0 :                  Py_TYPE(pystr)->tp_name);
    1701           0 :         return NULL;
    1702             :     }
    1703           0 :     return _build_rval_index_tuple(rval, next_idx);
    1704             : }
    1705             : 
    1706             : static PyObject *
    1707           0 : scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
    1708             : {
    1709             :     PyScannerObject *s;
    1710           0 :     s = (PyScannerObject *)type->tp_alloc(type, 0);
    1711           0 :     if (s != NULL) {
    1712           0 :         s->encoding = NULL;
    1713           0 :         s->strict = NULL;
    1714           0 :         s->object_hook = NULL;
    1715           0 :         s->pairs_hook = NULL;
    1716           0 :         s->parse_float = NULL;
    1717           0 :         s->parse_int = NULL;
    1718           0 :         s->parse_constant = NULL;
    1719             :     }
    1720           0 :     return (PyObject *)s;
    1721             : }
    1722             : 
    1723             : static int
    1724           3 : scanner_init(PyObject *self, PyObject *args, PyObject *kwds)
    1725             : {
    1726             :     /* Initialize Scanner object */
    1727             :     PyObject *ctx;
    1728             :     static char *kwlist[] = {"context", NULL};
    1729             :     PyScannerObject *s;
    1730             : 
    1731             :     assert(PyScanner_Check(self));
    1732           3 :     s = (PyScannerObject *)self;
    1733             : 
    1734           3 :     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:make_scanner", kwlist, &ctx))
    1735           0 :         return -1;
    1736             : 
    1737             :     /* PyString_AS_STRING is used on encoding */
    1738           3 :     s->encoding = PyObject_GetAttrString(ctx, "encoding");
    1739           3 :     if (s->encoding == NULL)
    1740           0 :         goto bail;
    1741           3 :     if (s->encoding == Py_None) {
    1742           3 :         Py_DECREF(Py_None);
    1743           3 :         s->encoding = PyString_InternFromString(DEFAULT_ENCODING);
    1744             :     }
    1745           0 :     else if (PyUnicode_Check(s->encoding)) {
    1746           0 :         PyObject *tmp = PyUnicode_AsEncodedString(s->encoding, NULL, NULL);
    1747           0 :         Py_SETREF(s->encoding, tmp);
    1748             :     }
    1749           3 :     if (s->encoding == NULL)
    1750           0 :         goto bail;
    1751           3 :     if (!PyString_Check(s->encoding)) {
    1752           0 :         PyErr_Format(PyExc_TypeError,
    1753             :                      "encoding must be a string, not %.80s",
    1754           0 :                      Py_TYPE(s->encoding)->tp_name);
    1755           0 :         goto bail;
    1756             :     }
    1757             :        
    1758             : 
    1759             :     /* All of these will fail "gracefully" so we don't need to verify them */
    1760           3 :     s->strict = PyObject_GetAttrString(ctx, "strict");
    1761           3 :     if (s->strict == NULL)
    1762           0 :         goto bail;
    1763           3 :     s->object_hook = PyObject_GetAttrString(ctx, "object_hook");
    1764           3 :     if (s->object_hook == NULL)
    1765           0 :         goto bail;
    1766           3 :     s->pairs_hook = PyObject_GetAttrString(ctx, "object_pairs_hook");
    1767           3 :     if (s->pairs_hook == NULL)
    1768           0 :         goto bail;
    1769           3 :     s->parse_float = PyObject_GetAttrString(ctx, "parse_float");
    1770           3 :     if (s->parse_float == NULL)
    1771           0 :         goto bail;
    1772           3 :     s->parse_int = PyObject_GetAttrString(ctx, "parse_int");
    1773           3 :     if (s->parse_int == NULL)
    1774           0 :         goto bail;
    1775           3 :     s->parse_constant = PyObject_GetAttrString(ctx, "parse_constant");
    1776           3 :     if (s->parse_constant == NULL)
    1777           0 :         goto bail;
    1778             : 
    1779           3 :     return 0;
    1780             : 
    1781             : bail:
    1782           0 :     Py_CLEAR(s->encoding);
    1783           0 :     Py_CLEAR(s->strict);
    1784           0 :     Py_CLEAR(s->object_hook);
    1785           0 :     Py_CLEAR(s->pairs_hook);
    1786           0 :     Py_CLEAR(s->parse_float);
    1787           0 :     Py_CLEAR(s->parse_int);
    1788           0 :     Py_CLEAR(s->parse_constant);
    1789           0 :     return -1;
    1790             : }
    1791             : 
    1792             : PyDoc_STRVAR(scanner_doc, "JSON scanner object");
    1793             : 
    1794             : static
    1795             : PyTypeObject PyScannerType = {
    1796             :     PyObject_HEAD_INIT(NULL)
    1797             :     0,                    /* tp_internal */
    1798             :     "_json.Scanner",       /* tp_name */
    1799             :     sizeof(PyScannerObject), /* tp_basicsize */
    1800             :     0,                    /* tp_itemsize */
    1801             :     scanner_dealloc, /* tp_dealloc */
    1802             :     0,                    /* tp_print */
    1803             :     0,                    /* tp_getattr */
    1804             :     0,                    /* tp_setattr */
    1805             :     0,                    /* tp_compare */
    1806             :     0,                    /* tp_repr */
    1807             :     0,                    /* tp_as_number */
    1808             :     0,                    /* tp_as_sequence */
    1809             :     0,                    /* tp_as_mapping */
    1810             :     0,                    /* tp_hash */
    1811             :     scanner_call,         /* tp_call */
    1812             :     0,                    /* tp_str */
    1813             :     0,/* PyObject_GenericGetAttr, */                    /* tp_getattro */
    1814             :     0,/* PyObject_GenericSetAttr, */                    /* tp_setattro */
    1815             :     0,                    /* tp_as_buffer */
    1816             :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,   /* tp_flags */
    1817             :     scanner_doc,          /* tp_doc */
    1818             :     scanner_traverse,                    /* tp_traverse */
    1819             :     scanner_clear,                    /* tp_clear */
    1820             :     0,                    /* tp_richcompare */
    1821             :     0,                    /* tp_weaklistoffset */
    1822             :     0,                    /* tp_iter */
    1823             :     0,                    /* tp_iternext */
    1824             :     0,                    /* tp_methods */
    1825             :     scanner_members,                    /* tp_members */
    1826             :     0,                    /* tp_getset */
    1827             :     0,                    /* tp_base */
    1828             :     0,                    /* tp_dict */
    1829             :     0,                    /* tp_descr_get */
    1830             :     0,                    /* tp_descr_set */
    1831             :     0,                    /* tp_dictoffset */
    1832             :     scanner_init,                    /* tp_init */
    1833             :     0,/* PyType_GenericAlloc, */        /* tp_alloc */
    1834             :     scanner_new,          /* tp_new */
    1835             :     0,/* PyObject_GC_Del, */              /* tp_free */
    1836             : };
    1837             : 
    1838             : static PyObject *
    1839           0 : encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
    1840             : {
    1841             :     PyEncoderObject *s;
    1842           0 :     s = (PyEncoderObject *)type->tp_alloc(type, 0);
    1843           0 :     if (s != NULL) {
    1844           0 :         s->markers = NULL;
    1845           0 :         s->defaultfn = NULL;
    1846           0 :         s->encoder = NULL;
    1847           0 :         s->indent = NULL;
    1848           0 :         s->key_separator = NULL;
    1849           0 :         s->item_separator = NULL;
    1850           0 :         s->sort_keys = NULL;
    1851           0 :         s->skipkeys = NULL;
    1852             :     }
    1853           0 :     return (PyObject *)s;
    1854             : }
    1855             : 
    1856             : static int
    1857           0 : encoder_init(PyObject *self, PyObject *args, PyObject *kwds)
    1858             : {
    1859             :     /* initialize Encoder object */
    1860             :     static char *kwlist[] = {"markers", "default", "encoder", "indent", "key_separator", "item_separator", "sort_keys", "skipkeys", "allow_nan", NULL};
    1861             : 
    1862             :     PyEncoderObject *s;
    1863             :     PyObject *markers, *defaultfn, *encoder, *indent, *key_separator;
    1864             :     PyObject *item_separator, *sort_keys, *skipkeys, *allow_nan_obj;
    1865             :     int allow_nan;
    1866             : 
    1867             :     assert(PyEncoder_Check(self));
    1868           0 :     s = (PyEncoderObject *)self;
    1869             : 
    1870           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOOOO:make_encoder", kwlist,
    1871             :         &markers, &defaultfn, &encoder, &indent, &key_separator, &item_separator,
    1872             :         &sort_keys, &skipkeys, &allow_nan_obj))
    1873           0 :         return -1;
    1874             : 
    1875           0 :     allow_nan = PyObject_IsTrue(allow_nan_obj);
    1876           0 :     if (allow_nan < 0)
    1877           0 :         return -1;
    1878             : 
    1879           0 :     if (markers != Py_None && !PyDict_Check(markers)) {
    1880           0 :         PyErr_Format(PyExc_TypeError,
    1881             :                      "make_encoder() argument 1 must be dict or None, "
    1882           0 :                      "not %.200s", Py_TYPE(markers)->tp_name);
    1883           0 :         return -1;
    1884             :     }
    1885             : 
    1886           0 :     s->markers = markers;
    1887           0 :     s->defaultfn = defaultfn;
    1888           0 :     s->encoder = encoder;
    1889           0 :     s->indent = indent;
    1890           0 :     s->key_separator = key_separator;
    1891           0 :     s->item_separator = item_separator;
    1892           0 :     s->sort_keys = sort_keys;
    1893           0 :     s->skipkeys = skipkeys;
    1894           0 :     s->fast_encode = (PyCFunction_Check(s->encoder) && PyCFunction_GetFunction(s->encoder) == (PyCFunction)py_encode_basestring_ascii);
    1895           0 :     s->allow_nan = allow_nan;
    1896             : 
    1897           0 :     Py_INCREF(s->markers);
    1898           0 :     Py_INCREF(s->defaultfn);
    1899           0 :     Py_INCREF(s->encoder);
    1900           0 :     Py_INCREF(s->indent);
    1901           0 :     Py_INCREF(s->key_separator);
    1902           0 :     Py_INCREF(s->item_separator);
    1903           0 :     Py_INCREF(s->sort_keys);
    1904           0 :     Py_INCREF(s->skipkeys);
    1905           0 :     return 0;
    1906             : }
    1907             : 
    1908             : static PyObject *
    1909           0 : encoder_call(PyObject *self, PyObject *args, PyObject *kwds)
    1910             : {
    1911             :     /* Python callable interface to encode_listencode_obj */
    1912             :     static char *kwlist[] = {"obj", "_current_indent_level", NULL};
    1913             :     PyObject *obj;
    1914             :     PyObject *rval;
    1915             :     Py_ssize_t indent_level;
    1916             :     PyEncoderObject *s;
    1917             :     assert(PyEncoder_Check(self));
    1918           0 :     s = (PyEncoderObject *)self;
    1919           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&:_iterencode", kwlist,
    1920             :         &obj, _convertPyInt_AsSsize_t, &indent_level))
    1921           0 :         return NULL;
    1922           0 :     rval = PyList_New(0);
    1923           0 :     if (rval == NULL)
    1924           0 :         return NULL;
    1925           0 :     if (encoder_listencode_obj(s, rval, obj, indent_level)) {
    1926           0 :         Py_DECREF(rval);
    1927           0 :         return NULL;
    1928             :     }
    1929           0 :     return rval;
    1930             : }
    1931             : 
    1932             : static PyObject *
    1933           0 : _encoded_const(PyObject *obj)
    1934             : {
    1935             :     /* Return the JSON string representation of None, True, False */
    1936           0 :     if (obj == Py_None) {
    1937             :         static PyObject *s_null = NULL;
    1938           0 :         if (s_null == NULL) {
    1939           0 :             s_null = PyString_InternFromString("null");
    1940             :         }
    1941           0 :         Py_INCREF(s_null);
    1942           0 :         return s_null;
    1943             :     }
    1944           0 :     else if (obj == Py_True) {
    1945             :         static PyObject *s_true = NULL;
    1946           0 :         if (s_true == NULL) {
    1947           0 :             s_true = PyString_InternFromString("true");
    1948             :         }
    1949           0 :         Py_INCREF(s_true);
    1950           0 :         return s_true;
    1951             :     }
    1952           0 :     else if (obj == Py_False) {
    1953             :         static PyObject *s_false = NULL;
    1954           0 :         if (s_false == NULL) {
    1955           0 :             s_false = PyString_InternFromString("false");
    1956             :         }
    1957           0 :         Py_INCREF(s_false);
    1958           0 :         return s_false;
    1959             :     }
    1960             :     else {
    1961           0 :         PyErr_SetString(PyExc_ValueError, "not a const");
    1962           0 :         return NULL;
    1963             :     }
    1964             : }
    1965             : 
    1966             : static PyObject *
    1967           0 : encoder_encode_float(PyEncoderObject *s, PyObject *obj)
    1968             : {
    1969             :     /* Return the JSON representation of a PyFloat */
    1970           0 :     double i = PyFloat_AS_DOUBLE(obj);
    1971           0 :     if (!Py_IS_FINITE(i)) {
    1972           0 :         if (!s->allow_nan) {
    1973           0 :             PyErr_SetString(PyExc_ValueError, "Out of range float values are not JSON compliant");
    1974           0 :             return NULL;
    1975             :         }
    1976           0 :         if (i > 0) {
    1977           0 :             return PyString_FromString("Infinity");
    1978             :         }
    1979           0 :         else if (i < 0) {
    1980           0 :             return PyString_FromString("-Infinity");
    1981             :         }
    1982             :         else {
    1983           0 :             return PyString_FromString("NaN");
    1984             :         }
    1985             :     }
    1986             :     /* Make sure to use the base float class repr method */
    1987           0 :     return PyFloat_Type.tp_repr(obj);
    1988             : }
    1989             : 
    1990             : static PyObject *
    1991           0 : encoder_encode_string(PyEncoderObject *s, PyObject *obj)
    1992             : {
    1993             :     /* Return the JSON representation of a string */
    1994           0 :     if (s->fast_encode)
    1995           0 :         return py_encode_basestring_ascii(NULL, obj);
    1996             :     else
    1997           0 :         return PyObject_CallFunctionObjArgs(s->encoder, obj, NULL);
    1998             : }
    1999             : 
    2000             : static int
    2001           0 : _steal_list_append(PyObject *lst, PyObject *stolen)
    2002             : {
    2003             :     /* Append stolen and then decrement its reference count */
    2004           0 :     int rval = PyList_Append(lst, stolen);
    2005           0 :     Py_DECREF(stolen);
    2006           0 :     return rval;
    2007             : }
    2008             : 
    2009             : static int
    2010           0 : encoder_listencode_obj(PyEncoderObject *s, PyObject *rval, PyObject *obj, Py_ssize_t indent_level)
    2011             : {
    2012             :     /* Encode Python object obj to a JSON term, rval is a PyList */
    2013             :     PyObject *newobj;
    2014             :     int rv;
    2015             : 
    2016           0 :     if (obj == Py_None || obj == Py_True || obj == Py_False) {
    2017           0 :         PyObject *cstr = _encoded_const(obj);
    2018           0 :         if (cstr == NULL)
    2019           0 :             return -1;
    2020           0 :         return _steal_list_append(rval, cstr);
    2021             :     }
    2022           0 :     else if (PyString_Check(obj) || PyUnicode_Check(obj))
    2023             :     {
    2024           0 :         PyObject *encoded = encoder_encode_string(s, obj);
    2025           0 :         if (encoded == NULL)
    2026           0 :             return -1;
    2027           0 :         return _steal_list_append(rval, encoded);
    2028             :     }
    2029           0 :     else if (PyInt_Check(obj) || PyLong_Check(obj)) {
    2030           0 :         PyObject *encoded = PyObject_Str(obj);
    2031           0 :         if (encoded == NULL)
    2032           0 :             return -1;
    2033           0 :         return _steal_list_append(rval, encoded);
    2034             :     }
    2035           0 :     else if (PyFloat_Check(obj)) {
    2036           0 :         PyObject *encoded = encoder_encode_float(s, obj);
    2037           0 :         if (encoded == NULL)
    2038           0 :             return -1;
    2039           0 :         return _steal_list_append(rval, encoded);
    2040             :     }
    2041           0 :     else if (PyList_Check(obj) || PyTuple_Check(obj)) {
    2042           0 :         if (Py_EnterRecursiveCall(" while encoding a JSON object"))
    2043           0 :             return -1;
    2044           0 :         rv = encoder_listencode_list(s, rval, obj, indent_level);
    2045           0 :         Py_LeaveRecursiveCall();
    2046           0 :         return rv;
    2047             :     }
    2048           0 :     else if (PyDict_Check(obj)) {
    2049           0 :         if (Py_EnterRecursiveCall(" while encoding a JSON object"))
    2050           0 :             return -1;
    2051           0 :         rv = encoder_listencode_dict(s, rval, obj, indent_level);
    2052           0 :         Py_LeaveRecursiveCall();
    2053           0 :         return rv;
    2054             :     }
    2055             :     else {
    2056           0 :         PyObject *ident = NULL;
    2057           0 :         if (s->markers != Py_None) {
    2058             :             int has_key;
    2059           0 :             ident = PyLong_FromVoidPtr(obj);
    2060           0 :             if (ident == NULL)
    2061           0 :                 return -1;
    2062           0 :             has_key = PyDict_Contains(s->markers, ident);
    2063           0 :             if (has_key) {
    2064           0 :                 if (has_key != -1)
    2065           0 :                     PyErr_SetString(PyExc_ValueError, "Circular reference detected");
    2066           0 :                 Py_DECREF(ident);
    2067           0 :                 return -1;
    2068             :             }
    2069           0 :             if (PyDict_SetItem(s->markers, ident, obj)) {
    2070           0 :                 Py_DECREF(ident);
    2071           0 :                 return -1;
    2072             :             }
    2073             :         }
    2074           0 :         newobj = PyObject_CallFunctionObjArgs(s->defaultfn, obj, NULL);
    2075           0 :         if (newobj == NULL) {
    2076           0 :             Py_XDECREF(ident);
    2077           0 :             return -1;
    2078             :         }
    2079             : 
    2080           0 :         if (Py_EnterRecursiveCall(" while encoding a JSON object"))
    2081           0 :             return -1;
    2082           0 :         rv = encoder_listencode_obj(s, rval, newobj, indent_level);
    2083           0 :         Py_LeaveRecursiveCall();
    2084             : 
    2085           0 :         Py_DECREF(newobj);
    2086           0 :         if (rv) {
    2087           0 :             Py_XDECREF(ident);
    2088           0 :             return -1;
    2089             :         }
    2090           0 :         if (ident != NULL) {
    2091           0 :             if (PyDict_DelItem(s->markers, ident)) {
    2092           0 :                 Py_XDECREF(ident);
    2093           0 :                 return -1;
    2094             :             }
    2095           0 :             Py_XDECREF(ident);
    2096             :         }
    2097           0 :         return rv;
    2098             :     }
    2099             : }
    2100             : 
    2101             : static int
    2102           0 : encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ssize_t indent_level)
    2103             : {
    2104             :     /* Encode Python dict dct a JSON term, rval is a PyList */
    2105             :     static PyObject *open_dict = NULL;
    2106             :     static PyObject *close_dict = NULL;
    2107             :     static PyObject *empty_dict = NULL;
    2108           0 :     PyObject *kstr = NULL;
    2109           0 :     PyObject *ident = NULL;
    2110           0 :     PyObject *key = NULL;
    2111           0 :     PyObject *value = NULL;
    2112           0 :     PyObject *it = NULL;
    2113             :     int skipkeys;
    2114             :     Py_ssize_t idx;
    2115             : 
    2116           0 :     if (open_dict == NULL || close_dict == NULL || empty_dict == NULL) {
    2117           0 :         open_dict = PyString_InternFromString("{");
    2118           0 :         close_dict = PyString_InternFromString("}");
    2119           0 :         empty_dict = PyString_InternFromString("{}");
    2120           0 :         if (open_dict == NULL || close_dict == NULL || empty_dict == NULL)
    2121           0 :             return -1;
    2122             :     }
    2123           0 :     if (Py_SIZE(dct) == 0)
    2124           0 :         return PyList_Append(rval, empty_dict);
    2125             : 
    2126           0 :     if (s->markers != Py_None) {
    2127             :         int has_key;
    2128           0 :         ident = PyLong_FromVoidPtr(dct);
    2129           0 :         if (ident == NULL)
    2130           0 :             goto bail;
    2131           0 :         has_key = PyDict_Contains(s->markers, ident);
    2132           0 :         if (has_key) {
    2133           0 :             if (has_key != -1)
    2134           0 :                 PyErr_SetString(PyExc_ValueError, "Circular reference detected");
    2135           0 :             goto bail;
    2136             :         }
    2137           0 :         if (PyDict_SetItem(s->markers, ident, dct)) {
    2138           0 :             goto bail;
    2139             :         }
    2140             :     }
    2141             : 
    2142           0 :     if (PyList_Append(rval, open_dict))
    2143           0 :         goto bail;
    2144             : 
    2145           0 :     if (s->indent != Py_None) {
    2146             :         /* TODO: DOES NOT RUN */
    2147           0 :         indent_level += 1;
    2148             :         /*
    2149             :             newline_indent = '\n' + (' ' * (_indent * _current_indent_level))
    2150             :             separator = _item_separator + newline_indent
    2151             :             buf += newline_indent
    2152             :         */
    2153             :     }
    2154             : 
    2155             :     /* TODO: C speedup not implemented for sort_keys */
    2156             : 
    2157           0 :     it = PyObject_GetIter(dct);
    2158           0 :     if (it == NULL)
    2159           0 :         goto bail;
    2160           0 :     skipkeys = PyObject_IsTrue(s->skipkeys);
    2161           0 :     if (skipkeys < 0)
    2162           0 :         goto bail;
    2163           0 :     idx = 0;
    2164           0 :     while ((key = PyIter_Next(it)) != NULL) {
    2165             :         PyObject *encoded;
    2166             : 
    2167           0 :         if (PyString_Check(key) || PyUnicode_Check(key)) {
    2168           0 :             Py_INCREF(key);
    2169           0 :             kstr = key;
    2170             :         }
    2171           0 :         else if (PyFloat_Check(key)) {
    2172           0 :             kstr = encoder_encode_float(s, key);
    2173           0 :             if (kstr == NULL)
    2174           0 :                 goto bail;
    2175             :         }
    2176           0 :         else if (PyInt_Check(key) || PyLong_Check(key)) {
    2177           0 :             kstr = PyObject_Str(key);
    2178           0 :             if (kstr == NULL)
    2179           0 :                 goto bail;
    2180             :         }
    2181           0 :         else if (key == Py_True || key == Py_False || key == Py_None) {
    2182           0 :             kstr = _encoded_const(key);
    2183           0 :             if (kstr == NULL)
    2184           0 :                 goto bail;
    2185             :         }
    2186           0 :         else if (skipkeys) {
    2187           0 :             Py_DECREF(key);
    2188           0 :             continue;
    2189             :         }
    2190             :         else {
    2191             :             /* TODO: include repr of key */
    2192           0 :             PyErr_SetString(PyExc_TypeError, "keys must be a string");
    2193           0 :             goto bail;
    2194             :         }
    2195             : 
    2196           0 :         if (idx) {
    2197           0 :             if (PyList_Append(rval, s->item_separator))
    2198           0 :                 goto bail;
    2199             :         }
    2200             : 
    2201           0 :         value = PyObject_GetItem(dct, key);
    2202           0 :         if (value == NULL)
    2203           0 :             goto bail;
    2204             : 
    2205           0 :         encoded = encoder_encode_string(s, kstr);
    2206           0 :         Py_CLEAR(kstr);
    2207           0 :         if (encoded == NULL)
    2208           0 :             goto bail;
    2209           0 :         if (PyList_Append(rval, encoded)) {
    2210           0 :             Py_DECREF(encoded);
    2211           0 :             goto bail;
    2212             :         }
    2213           0 :         Py_DECREF(encoded);
    2214           0 :         if (PyList_Append(rval, s->key_separator))
    2215           0 :             goto bail;
    2216           0 :         if (encoder_listencode_obj(s, rval, value, indent_level))
    2217           0 :             goto bail;
    2218           0 :         idx += 1;
    2219           0 :         Py_CLEAR(value);
    2220           0 :         Py_DECREF(key);
    2221             :     }
    2222           0 :     if (PyErr_Occurred())
    2223           0 :         goto bail;
    2224           0 :     Py_CLEAR(it);
    2225             : 
    2226           0 :     if (ident != NULL) {
    2227           0 :         if (PyDict_DelItem(s->markers, ident))
    2228           0 :             goto bail;
    2229           0 :         Py_CLEAR(ident);
    2230             :     }
    2231           0 :     if (s->indent != Py_None) {
    2232             :         /* TODO: DOES NOT RUN */
    2233             :         /*
    2234             :             indent_level -= 1;
    2235             : 
    2236             :             yield '\n' + (' ' * (_indent * _current_indent_level))
    2237             :         */
    2238             :     }
    2239           0 :     if (PyList_Append(rval, close_dict))
    2240           0 :         goto bail;
    2241           0 :     return 0;
    2242             : 
    2243             : bail:
    2244           0 :     Py_XDECREF(it);
    2245           0 :     Py_XDECREF(key);
    2246           0 :     Py_XDECREF(value);
    2247           0 :     Py_XDECREF(kstr);
    2248           0 :     Py_XDECREF(ident);
    2249           0 :     return -1;
    2250             : }
    2251             : 
    2252             : 
    2253             : static int
    2254           0 : encoder_listencode_list(PyEncoderObject *s, PyObject *rval, PyObject *seq, Py_ssize_t indent_level)
    2255             : {
    2256             :     /* Encode Python list seq to a JSON term, rval is a PyList */
    2257             :     static PyObject *open_array = NULL;
    2258             :     static PyObject *close_array = NULL;
    2259             :     static PyObject *empty_array = NULL;
    2260           0 :     PyObject *ident = NULL;
    2261           0 :     PyObject *s_fast = NULL;
    2262             :     Py_ssize_t i;
    2263             : 
    2264           0 :     if (open_array == NULL || close_array == NULL || empty_array == NULL) {
    2265           0 :         open_array = PyString_InternFromString("[");
    2266           0 :         close_array = PyString_InternFromString("]");
    2267           0 :         empty_array = PyString_InternFromString("[]");
    2268           0 :         if (open_array == NULL || close_array == NULL || empty_array == NULL)
    2269           0 :             return -1;
    2270             :     }
    2271           0 :     ident = NULL;
    2272           0 :     s_fast = PySequence_Fast(seq, "_iterencode_list needs a sequence");
    2273           0 :     if (s_fast == NULL)
    2274           0 :         return -1;
    2275           0 :     if (PySequence_Fast_GET_SIZE(s_fast) == 0) {
    2276           0 :         Py_DECREF(s_fast);
    2277           0 :         return PyList_Append(rval, empty_array);
    2278             :     }
    2279             : 
    2280           0 :     if (s->markers != Py_None) {
    2281             :         int has_key;
    2282           0 :         ident = PyLong_FromVoidPtr(seq);
    2283           0 :         if (ident == NULL)
    2284           0 :             goto bail;
    2285           0 :         has_key = PyDict_Contains(s->markers, ident);
    2286           0 :         if (has_key) {
    2287           0 :             if (has_key != -1)
    2288           0 :                 PyErr_SetString(PyExc_ValueError, "Circular reference detected");
    2289           0 :             goto bail;
    2290             :         }
    2291           0 :         if (PyDict_SetItem(s->markers, ident, seq)) {
    2292           0 :             goto bail;
    2293             :         }
    2294             :     }
    2295             : 
    2296           0 :     if (PyList_Append(rval, open_array))
    2297           0 :         goto bail;
    2298           0 :     if (s->indent != Py_None) {
    2299             :         /* TODO: DOES NOT RUN */
    2300           0 :         indent_level += 1;
    2301             :         /*
    2302             :             newline_indent = '\n' + (' ' * (_indent * _current_indent_level))
    2303             :             separator = _item_separator + newline_indent
    2304             :             buf += newline_indent
    2305             :         */
    2306             :     }
    2307           0 :     for (i = 0; i < PySequence_Fast_GET_SIZE(s_fast); i++) {
    2308           0 :         PyObject *obj = PySequence_Fast_GET_ITEM(s_fast, i);
    2309           0 :         if (i) {
    2310           0 :             if (PyList_Append(rval, s->item_separator))
    2311           0 :                 goto bail;
    2312             :         }
    2313           0 :         if (encoder_listencode_obj(s, rval, obj, indent_level))
    2314           0 :             goto bail;
    2315             :     }
    2316           0 :     if (ident != NULL) {
    2317           0 :         if (PyDict_DelItem(s->markers, ident))
    2318           0 :             goto bail;
    2319           0 :         Py_CLEAR(ident);
    2320             :     }
    2321           0 :     if (s->indent != Py_None) {
    2322             :         /* TODO: DOES NOT RUN */
    2323             :         /*
    2324             :             indent_level -= 1;
    2325             : 
    2326             :             yield '\n' + (' ' * (_indent * _current_indent_level))
    2327             :         */
    2328             :     }
    2329           0 :     if (PyList_Append(rval, close_array))
    2330           0 :         goto bail;
    2331           0 :     Py_DECREF(s_fast);
    2332           0 :     return 0;
    2333             : 
    2334             : bail:
    2335           0 :     Py_XDECREF(ident);
    2336           0 :     Py_DECREF(s_fast);
    2337           0 :     return -1;
    2338             : }
    2339             : 
    2340             : static void
    2341           0 : encoder_dealloc(PyObject *self)
    2342             : {
    2343             :     /* Deallocate Encoder */
    2344           0 :     encoder_clear(self);
    2345           0 :     Py_TYPE(self)->tp_free(self);
    2346           0 : }
    2347             : 
    2348             : static int
    2349           0 : encoder_traverse(PyObject *self, visitproc visit, void *arg)
    2350             : {
    2351             :     PyEncoderObject *s;
    2352             :     assert(PyEncoder_Check(self));
    2353           0 :     s = (PyEncoderObject *)self;
    2354           0 :     Py_VISIT(s->markers);
    2355           0 :     Py_VISIT(s->defaultfn);
    2356           0 :     Py_VISIT(s->encoder);
    2357           0 :     Py_VISIT(s->indent);
    2358           0 :     Py_VISIT(s->key_separator);
    2359           0 :     Py_VISIT(s->item_separator);
    2360           0 :     Py_VISIT(s->sort_keys);
    2361           0 :     Py_VISIT(s->skipkeys);
    2362           0 :     return 0;
    2363             : }
    2364             : 
    2365             : static int
    2366           0 : encoder_clear(PyObject *self)
    2367             : {
    2368             :     /* Deallocate Encoder */
    2369             :     PyEncoderObject *s;
    2370             :     assert(PyEncoder_Check(self));
    2371           0 :     s = (PyEncoderObject *)self;
    2372           0 :     Py_CLEAR(s->markers);
    2373           0 :     Py_CLEAR(s->defaultfn);
    2374           0 :     Py_CLEAR(s->encoder);
    2375           0 :     Py_CLEAR(s->indent);
    2376           0 :     Py_CLEAR(s->key_separator);
    2377           0 :     Py_CLEAR(s->item_separator);
    2378           0 :     Py_CLEAR(s->sort_keys);
    2379           0 :     Py_CLEAR(s->skipkeys);
    2380           0 :     return 0;
    2381             : }
    2382             : 
    2383             : PyDoc_STRVAR(encoder_doc, "_iterencode(obj, _current_indent_level) -> iterable");
    2384             : 
    2385             : static
    2386             : PyTypeObject PyEncoderType = {
    2387             :     PyObject_HEAD_INIT(NULL)
    2388             :     0,                    /* tp_internal */
    2389             :     "_json.Encoder",       /* tp_name */
    2390             :     sizeof(PyEncoderObject), /* tp_basicsize */
    2391             :     0,                    /* tp_itemsize */
    2392             :     encoder_dealloc, /* tp_dealloc */
    2393             :     0,                    /* tp_print */
    2394             :     0,                    /* tp_getattr */
    2395             :     0,                    /* tp_setattr */
    2396             :     0,                    /* tp_compare */
    2397             :     0,                    /* tp_repr */
    2398             :     0,                    /* tp_as_number */
    2399             :     0,                    /* tp_as_sequence */
    2400             :     0,                    /* tp_as_mapping */
    2401             :     0,                    /* tp_hash */
    2402             :     encoder_call,         /* tp_call */
    2403             :     0,                    /* tp_str */
    2404             :     0,                    /* tp_getattro */
    2405             :     0,                    /* tp_setattro */
    2406             :     0,                    /* tp_as_buffer */
    2407             :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,   /* tp_flags */
    2408             :     encoder_doc,          /* tp_doc */
    2409             :     encoder_traverse,     /* tp_traverse */
    2410             :     encoder_clear,        /* tp_clear */
    2411             :     0,                    /* tp_richcompare */
    2412             :     0,                    /* tp_weaklistoffset */
    2413             :     0,                    /* tp_iter */
    2414             :     0,                    /* tp_iternext */
    2415             :     0,                    /* tp_methods */
    2416             :     encoder_members,      /* tp_members */
    2417             :     0,                    /* tp_getset */
    2418             :     0,                    /* tp_base */
    2419             :     0,                    /* tp_dict */
    2420             :     0,                    /* tp_descr_get */
    2421             :     0,                    /* tp_descr_set */
    2422             :     0,                    /* tp_dictoffset */
    2423             :     encoder_init,         /* tp_init */
    2424             :     0,                    /* tp_alloc */
    2425             :     encoder_new,          /* tp_new */
    2426             :     0,                    /* tp_free */
    2427             : };
    2428             : 
    2429             : static PyMethodDef speedups_methods[] = {
    2430             :     {"encode_basestring_ascii",
    2431             :         (PyCFunction)py_encode_basestring_ascii,
    2432             :         METH_O,
    2433             :         pydoc_encode_basestring_ascii},
    2434             :     {"scanstring",
    2435             :         (PyCFunction)py_scanstring,
    2436             :         METH_VARARGS,
    2437             :         pydoc_scanstring},
    2438             :     {NULL, NULL, 0, NULL}
    2439             : };
    2440             : 
    2441             : PyDoc_STRVAR(module_doc,
    2442             : "json speedups\n");
    2443             : 
    2444             : void
    2445           3 : init_json(void)
    2446             : {
    2447             :     PyObject *m;
    2448           3 :     PyScannerType.tp_new = PyType_GenericNew;
    2449           3 :     if (PyType_Ready(&PyScannerType) < 0)
    2450           0 :         return;
    2451           3 :     PyEncoderType.tp_new = PyType_GenericNew;
    2452           3 :     if (PyType_Ready(&PyEncoderType) < 0)
    2453           0 :         return;
    2454           3 :     m = Py_InitModule3("_json", speedups_methods, module_doc);
    2455           3 :     if (m == NULL)
    2456           0 :         return;
    2457           3 :     Py_INCREF((PyObject*)&PyScannerType);
    2458           3 :     PyModule_AddObject(m, "make_scanner", (PyObject*)&PyScannerType);
    2459           3 :     Py_INCREF((PyObject*)&PyEncoderType);
    2460           3 :     PyModule_AddObject(m, "make_encoder", (PyObject*)&PyEncoderType);
    2461             : }

Generated by: LCOV version 1.10