LCOV - code coverage report
Current view: top level - Modules - _json.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit 5e6661bce9] Lines: 14 887 1.6 %
Date: 2023-03-20 08:15:36 Functions: 2 35 5.7 %
Branches: 4 821 0.5 %

           Branch data     Line data    Source code
       1                 :            : /* JSON accelerator C extensor: _json module.
       2                 :            :  *
       3                 :            :  * It is built as a built-in module (Py_BUILD_CORE_BUILTIN define) on Windows
       4                 :            :  * and as an extension module (Py_BUILD_CORE_MODULE define) on other
       5                 :            :  * platforms. */
       6                 :            : 
       7                 :            : #ifndef Py_BUILD_CORE_BUILTIN
       8                 :            : #  define Py_BUILD_CORE_MODULE 1
       9                 :            : #endif
      10                 :            : 
      11                 :            : #include "Python.h"
      12                 :            : #include "pycore_ceval.h"           // _Py_EnterRecursiveCall()
      13                 :            : #include "pycore_runtime.h"         // _PyRuntime
      14                 :            : #include "structmember.h"           // PyMemberDef
      15                 :            : #include "pycore_global_objects.h"  // _Py_ID()
      16                 :            : #include <stdbool.h>                // bool
      17                 :            : 
      18                 :            : 
      19                 :            : typedef struct _PyScannerObject {
      20                 :            :     PyObject_HEAD
      21                 :            :     signed char strict;
      22                 :            :     PyObject *object_hook;
      23                 :            :     PyObject *object_pairs_hook;
      24                 :            :     PyObject *parse_float;
      25                 :            :     PyObject *parse_int;
      26                 :            :     PyObject *parse_constant;
      27                 :            :     PyObject *memo;
      28                 :            : } PyScannerObject;
      29                 :            : 
      30                 :            : static PyMemberDef scanner_members[] = {
      31                 :            :     {"strict", T_BOOL, offsetof(PyScannerObject, strict), READONLY, "strict"},
      32                 :            :     {"object_hook", T_OBJECT, offsetof(PyScannerObject, object_hook), READONLY, "object_hook"},
      33                 :            :     {"object_pairs_hook", T_OBJECT, offsetof(PyScannerObject, object_pairs_hook), READONLY},
      34                 :            :     {"parse_float", T_OBJECT, offsetof(PyScannerObject, parse_float), READONLY, "parse_float"},
      35                 :            :     {"parse_int", T_OBJECT, offsetof(PyScannerObject, parse_int), READONLY, "parse_int"},
      36                 :            :     {"parse_constant", T_OBJECT, offsetof(PyScannerObject, parse_constant), READONLY, "parse_constant"},
      37                 :            :     {NULL}
      38                 :            : };
      39                 :            : 
      40                 :            : typedef struct _PyEncoderObject {
      41                 :            :     PyObject_HEAD
      42                 :            :     PyObject *markers;
      43                 :            :     PyObject *defaultfn;
      44                 :            :     PyObject *encoder;
      45                 :            :     PyObject *indent;
      46                 :            :     PyObject *key_separator;
      47                 :            :     PyObject *item_separator;
      48                 :            :     char sort_keys;
      49                 :            :     char skipkeys;
      50                 :            :     int allow_nan;
      51                 :            :     PyCFunction fast_encode;
      52                 :            : } PyEncoderObject;
      53                 :            : 
      54                 :            : static PyMemberDef encoder_members[] = {
      55                 :            :     {"markers", T_OBJECT, offsetof(PyEncoderObject, markers), READONLY, "markers"},
      56                 :            :     {"default", T_OBJECT, offsetof(PyEncoderObject, defaultfn), READONLY, "default"},
      57                 :            :     {"encoder", T_OBJECT, offsetof(PyEncoderObject, encoder), READONLY, "encoder"},
      58                 :            :     {"indent", T_OBJECT, offsetof(PyEncoderObject, indent), READONLY, "indent"},
      59                 :            :     {"key_separator", T_OBJECT, offsetof(PyEncoderObject, key_separator), READONLY, "key_separator"},
      60                 :            :     {"item_separator", T_OBJECT, offsetof(PyEncoderObject, item_separator), READONLY, "item_separator"},
      61                 :            :     {"sort_keys", T_BOOL, offsetof(PyEncoderObject, sort_keys), READONLY, "sort_keys"},
      62                 :            :     {"skipkeys", T_BOOL, offsetof(PyEncoderObject, skipkeys), READONLY, "skipkeys"},
      63                 :            :     {NULL}
      64                 :            : };
      65                 :            : 
      66                 :            : /* Forward decls */
      67                 :            : 
      68                 :            : static PyObject *
      69                 :            : ascii_escape_unicode(PyObject *pystr);
      70                 :            : static PyObject *
      71                 :            : py_encode_basestring_ascii(PyObject* Py_UNUSED(self), PyObject *pystr);
      72                 :            : static PyObject *
      73                 :            : scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr);
      74                 :            : static PyObject *
      75                 :            : _build_rval_index_tuple(PyObject *rval, Py_ssize_t idx);
      76                 :            : static PyObject *
      77                 :            : scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
      78                 :            : static void
      79                 :            : scanner_dealloc(PyObject *self);
      80                 :            : static int
      81                 :            : scanner_clear(PyScannerObject *self);
      82                 :            : static PyObject *
      83                 :            : encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
      84                 :            : static void
      85                 :            : encoder_dealloc(PyObject *self);
      86                 :            : static int
      87                 :            : encoder_clear(PyEncoderObject *self);
      88                 :            : static int
      89                 :            : encoder_listencode_list(PyEncoderObject *s, _PyUnicodeWriter *writer, PyObject *seq, Py_ssize_t indent_level);
      90                 :            : static int
      91                 :            : encoder_listencode_obj(PyEncoderObject *s, _PyUnicodeWriter *writer, PyObject *obj, Py_ssize_t indent_level);
      92                 :            : static int
      93                 :            : encoder_listencode_dict(PyEncoderObject *s, _PyUnicodeWriter *writer, PyObject *dct, Py_ssize_t indent_level);
      94                 :            : static PyObject *
      95                 :            : _encoded_const(PyObject *obj);
      96                 :            : static void
      97                 :            : raise_errmsg(const char *msg, PyObject *s, Py_ssize_t end);
      98                 :            : static PyObject *
      99                 :            : encoder_encode_string(PyEncoderObject *s, PyObject *obj);
     100                 :            : static PyObject *
     101                 :            : encoder_encode_float(PyEncoderObject *s, PyObject *obj);
     102                 :            : 
     103                 :            : #define S_CHAR(c) (c >= ' ' && c <= '~' && c != '\\' && c != '"')
     104                 :            : #define IS_WHITESPACE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\n') || ((c) == '\r'))
     105                 :            : 
     106                 :            : static Py_ssize_t
     107                 :          0 : ascii_escape_unichar(Py_UCS4 c, unsigned char *output, Py_ssize_t chars)
     108                 :            : {
     109                 :            :     /* Escape unicode code point c to ASCII escape sequences
     110                 :            :     in char *output. output must have at least 12 bytes unused to
     111                 :            :     accommodate an escaped surrogate pair "\uXXXX\uXXXX" */
     112                 :          0 :     output[chars++] = '\\';
     113   [ #  #  #  #  :          0 :     switch (c) {
             #  #  #  # ]
     114                 :          0 :         case '\\': output[chars++] = c; break;
     115                 :          0 :         case '"': output[chars++] = c; break;
     116                 :          0 :         case '\b': output[chars++] = 'b'; break;
     117                 :          0 :         case '\f': output[chars++] = 'f'; break;
     118                 :          0 :         case '\n': output[chars++] = 'n'; break;
     119                 :          0 :         case '\r': output[chars++] = 'r'; break;
     120                 :          0 :         case '\t': output[chars++] = 't'; break;
     121                 :          0 :         default:
     122         [ #  # ]:          0 :             if (c >= 0x10000) {
     123                 :            :                 /* UTF-16 surrogate pair */
     124                 :          0 :                 Py_UCS4 v = Py_UNICODE_HIGH_SURROGATE(c);
     125                 :          0 :                 output[chars++] = 'u';
     126                 :          0 :                 output[chars++] = Py_hexdigits[(v >> 12) & 0xf];
     127                 :          0 :                 output[chars++] = Py_hexdigits[(v >>  8) & 0xf];
     128                 :          0 :                 output[chars++] = Py_hexdigits[(v >>  4) & 0xf];
     129                 :          0 :                 output[chars++] = Py_hexdigits[(v      ) & 0xf];
     130                 :          0 :                 c = Py_UNICODE_LOW_SURROGATE(c);
     131                 :          0 :                 output[chars++] = '\\';
     132                 :            :             }
     133                 :          0 :             output[chars++] = 'u';
     134                 :          0 :             output[chars++] = Py_hexdigits[(c >> 12) & 0xf];
     135                 :          0 :             output[chars++] = Py_hexdigits[(c >>  8) & 0xf];
     136                 :          0 :             output[chars++] = Py_hexdigits[(c >>  4) & 0xf];
     137                 :          0 :             output[chars++] = Py_hexdigits[(c      ) & 0xf];
     138                 :            :     }
     139                 :          0 :     return chars;
     140                 :            : }
     141                 :            : 
     142                 :            : static PyObject *
     143                 :          0 : ascii_escape_unicode(PyObject *pystr)
     144                 :            : {
     145                 :            :     /* Take a PyUnicode pystr and return a new ASCII-only escaped PyUnicode */
     146                 :            :     Py_ssize_t i;
     147                 :            :     Py_ssize_t input_chars;
     148                 :            :     Py_ssize_t output_size;
     149                 :            :     Py_ssize_t chars;
     150                 :            :     PyObject *rval;
     151                 :            :     const void *input;
     152                 :            :     Py_UCS1 *output;
     153                 :            :     int kind;
     154                 :            : 
     155         [ #  # ]:          0 :     if (PyUnicode_READY(pystr) == -1)
     156                 :          0 :         return NULL;
     157                 :            : 
     158                 :          0 :     input_chars = PyUnicode_GET_LENGTH(pystr);
     159                 :          0 :     input = PyUnicode_DATA(pystr);
     160                 :          0 :     kind = PyUnicode_KIND(pystr);
     161                 :            : 
     162                 :            :     /* Compute the output size */
     163         [ #  # ]:          0 :     for (i = 0, output_size = 2; i < input_chars; i++) {
     164                 :          0 :         Py_UCS4 c = PyUnicode_READ(kind, input, i);
     165                 :            :         Py_ssize_t d;
     166   [ #  #  #  #  :          0 :         if (S_CHAR(c)) {
             #  #  #  # ]
     167                 :          0 :             d = 1;
     168                 :            :         }
     169                 :            :         else {
     170         [ #  # ]:          0 :             switch(c) {
     171                 :          0 :             case '\\': case '"': case '\b': case '\f':
     172                 :            :             case '\n': case '\r': case '\t':
     173                 :          0 :                 d = 2; break;
     174                 :          0 :             default:
     175         [ #  # ]:          0 :                 d = c >= 0x10000 ? 12 : 6;
     176                 :            :             }
     177                 :            :         }
     178         [ #  # ]:          0 :         if (output_size > PY_SSIZE_T_MAX - d) {
     179                 :          0 :             PyErr_SetString(PyExc_OverflowError, "string is too long to escape");
     180                 :          0 :             return NULL;
     181                 :            :         }
     182                 :          0 :         output_size += d;
     183                 :            :     }
     184                 :            : 
     185                 :          0 :     rval = PyUnicode_New(output_size, 127);
     186         [ #  # ]:          0 :     if (rval == NULL) {
     187                 :          0 :         return NULL;
     188                 :            :     }
     189                 :          0 :     output = PyUnicode_1BYTE_DATA(rval);
     190                 :          0 :     chars = 0;
     191                 :          0 :     output[chars++] = '"';
     192         [ #  # ]:          0 :     for (i = 0; i < input_chars; i++) {
     193                 :          0 :         Py_UCS4 c = PyUnicode_READ(kind, input, i);
     194   [ #  #  #  #  :          0 :         if (S_CHAR(c)) {
             #  #  #  # ]
     195                 :          0 :             output[chars++] = c;
     196                 :            :         }
     197                 :            :         else {
     198                 :          0 :             chars = ascii_escape_unichar(c, output, chars);
     199                 :            :         }
     200                 :            :     }
     201                 :          0 :     output[chars++] = '"';
     202                 :            : #ifdef Py_DEBUG
     203                 :            :     assert(_PyUnicode_CheckConsistency(rval, 1));
     204                 :            : #endif
     205                 :          0 :     return rval;
     206                 :            : }
     207                 :            : 
     208                 :            : static PyObject *
     209                 :          0 : escape_unicode(PyObject *pystr)
     210                 :            : {
     211                 :            :     /* Take a PyUnicode pystr and return a new escaped PyUnicode */
     212                 :            :     Py_ssize_t i;
     213                 :            :     Py_ssize_t input_chars;
     214                 :            :     Py_ssize_t output_size;
     215                 :            :     Py_ssize_t chars;
     216                 :            :     PyObject *rval;
     217                 :            :     const void *input;
     218                 :            :     int kind;
     219                 :            :     Py_UCS4 maxchar;
     220                 :            : 
     221         [ #  # ]:          0 :     if (PyUnicode_READY(pystr) == -1)
     222                 :          0 :         return NULL;
     223                 :            : 
     224                 :          0 :     maxchar = PyUnicode_MAX_CHAR_VALUE(pystr);
     225                 :          0 :     input_chars = PyUnicode_GET_LENGTH(pystr);
     226                 :          0 :     input = PyUnicode_DATA(pystr);
     227                 :          0 :     kind = PyUnicode_KIND(pystr);
     228                 :            : 
     229                 :            :     /* Compute the output size */
     230         [ #  # ]:          0 :     for (i = 0, output_size = 2; i < input_chars; i++) {
     231                 :          0 :         Py_UCS4 c = PyUnicode_READ(kind, input, i);
     232                 :            :         Py_ssize_t d;
     233         [ #  # ]:          0 :         switch (c) {
     234                 :          0 :         case '\\': case '"': case '\b': case '\f':
     235                 :            :         case '\n': case '\r': case '\t':
     236                 :          0 :             d = 2;
     237                 :          0 :             break;
     238                 :          0 :         default:
     239         [ #  # ]:          0 :             if (c <= 0x1f)
     240                 :          0 :                 d = 6;
     241                 :            :             else
     242                 :          0 :                 d = 1;
     243                 :            :         }
     244         [ #  # ]:          0 :         if (output_size > PY_SSIZE_T_MAX - d) {
     245                 :          0 :             PyErr_SetString(PyExc_OverflowError, "string is too long to escape");
     246                 :          0 :             return NULL;
     247                 :            :         }
     248                 :          0 :         output_size += d;
     249                 :            :     }
     250                 :            : 
     251                 :          0 :     rval = PyUnicode_New(output_size, maxchar);
     252         [ #  # ]:          0 :     if (rval == NULL)
     253                 :          0 :         return NULL;
     254                 :            : 
     255                 :          0 :     kind = PyUnicode_KIND(rval);
     256                 :            : 
     257                 :            : #define ENCODE_OUTPUT do { \
     258                 :            :         chars = 0; \
     259                 :            :         output[chars++] = '"'; \
     260                 :            :         for (i = 0; i < input_chars; i++) { \
     261                 :            :             Py_UCS4 c = PyUnicode_READ(kind, input, i); \
     262                 :            :             switch (c) { \
     263                 :            :             case '\\': output[chars++] = '\\'; output[chars++] = c; break; \
     264                 :            :             case '"':  output[chars++] = '\\'; output[chars++] = c; break; \
     265                 :            :             case '\b': output[chars++] = '\\'; output[chars++] = 'b'; break; \
     266                 :            :             case '\f': output[chars++] = '\\'; output[chars++] = 'f'; break; \
     267                 :            :             case '\n': output[chars++] = '\\'; output[chars++] = 'n'; break; \
     268                 :            :             case '\r': output[chars++] = '\\'; output[chars++] = 'r'; break; \
     269                 :            :             case '\t': output[chars++] = '\\'; output[chars++] = 't'; break; \
     270                 :            :             default: \
     271                 :            :                 if (c <= 0x1f) { \
     272                 :            :                     output[chars++] = '\\'; \
     273                 :            :                     output[chars++] = 'u'; \
     274                 :            :                     output[chars++] = '0'; \
     275                 :            :                     output[chars++] = '0'; \
     276                 :            :                     output[chars++] = Py_hexdigits[(c >> 4) & 0xf]; \
     277                 :            :                     output[chars++] = Py_hexdigits[(c     ) & 0xf]; \
     278                 :            :                 } else { \
     279                 :            :                     output[chars++] = c; \
     280                 :            :                 } \
     281                 :            :             } \
     282                 :            :         } \
     283                 :            :         output[chars++] = '"'; \
     284                 :            :     } while (0)
     285                 :            : 
     286         [ #  # ]:          0 :     if (kind == PyUnicode_1BYTE_KIND) {
     287                 :          0 :         Py_UCS1 *output = PyUnicode_1BYTE_DATA(rval);
     288   [ #  #  #  #  :          0 :         ENCODE_OUTPUT;
          #  #  #  #  #  
                #  #  # ]
     289         [ #  # ]:          0 :     } else if (kind == PyUnicode_2BYTE_KIND) {
     290                 :          0 :         Py_UCS2 *output = PyUnicode_2BYTE_DATA(rval);
     291   [ #  #  #  #  :          0 :         ENCODE_OUTPUT;
          #  #  #  #  #  
                #  #  # ]
     292                 :            :     } else {
     293                 :          0 :         Py_UCS4 *output = PyUnicode_4BYTE_DATA(rval);
     294                 :            :         assert(kind == PyUnicode_4BYTE_KIND);
     295   [ #  #  #  #  :          0 :         ENCODE_OUTPUT;
          #  #  #  #  #  
                #  #  # ]
     296                 :            :     }
     297                 :            : #undef ENCODE_OUTPUT
     298                 :            : 
     299                 :            : #ifdef Py_DEBUG
     300                 :            :     assert(_PyUnicode_CheckConsistency(rval, 1));
     301                 :            : #endif
     302                 :          0 :     return rval;
     303                 :            : }
     304                 :            : 
     305                 :            : static void
     306                 :          0 : raise_errmsg(const char *msg, PyObject *s, Py_ssize_t end)
     307                 :            : {
     308                 :            :     /* Use JSONDecodeError exception to raise a nice looking ValueError subclass */
     309                 :            :     _Py_DECLARE_STR(json_decoder, "json.decoder");
     310                 :            :     PyObject *JSONDecodeError =
     311                 :          0 :          _PyImport_GetModuleAttr(&_Py_STR(json_decoder), &_Py_ID(JSONDecodeError));
     312         [ #  # ]:          0 :     if (JSONDecodeError == NULL) {
     313                 :          0 :         return;
     314                 :            :     }
     315                 :            : 
     316                 :            :     PyObject *exc;
     317                 :          0 :     exc = PyObject_CallFunction(JSONDecodeError, "zOn", msg, s, end);
     318                 :          0 :     Py_DECREF(JSONDecodeError);
     319         [ #  # ]:          0 :     if (exc) {
     320                 :          0 :         PyErr_SetObject(JSONDecodeError, exc);
     321                 :          0 :         Py_DECREF(exc);
     322                 :            :     }
     323                 :            : }
     324                 :            : 
     325                 :            : static void
     326                 :          0 : raise_stop_iteration(Py_ssize_t idx)
     327                 :            : {
     328                 :          0 :     PyObject *value = PyLong_FromSsize_t(idx);
     329         [ #  # ]:          0 :     if (value != NULL) {
     330                 :          0 :         PyErr_SetObject(PyExc_StopIteration, value);
     331                 :          0 :         Py_DECREF(value);
     332                 :            :     }
     333                 :          0 : }
     334                 :            : 
     335                 :            : static PyObject *
     336                 :          0 : _build_rval_index_tuple(PyObject *rval, Py_ssize_t idx) {
     337                 :            :     /* return (rval, idx) tuple, stealing reference to rval */
     338                 :            :     PyObject *tpl;
     339                 :            :     PyObject *pyidx;
     340                 :            :     /*
     341                 :            :     steal a reference to rval, returns (rval, idx)
     342                 :            :     */
     343         [ #  # ]:          0 :     if (rval == NULL) {
     344                 :          0 :         return NULL;
     345                 :            :     }
     346                 :          0 :     pyidx = PyLong_FromSsize_t(idx);
     347         [ #  # ]:          0 :     if (pyidx == NULL) {
     348                 :          0 :         Py_DECREF(rval);
     349                 :          0 :         return NULL;
     350                 :            :     }
     351                 :          0 :     tpl = PyTuple_New(2);
     352         [ #  # ]:          0 :     if (tpl == NULL) {
     353                 :          0 :         Py_DECREF(pyidx);
     354                 :          0 :         Py_DECREF(rval);
     355                 :          0 :         return NULL;
     356                 :            :     }
     357                 :          0 :     PyTuple_SET_ITEM(tpl, 0, rval);
     358                 :          0 :     PyTuple_SET_ITEM(tpl, 1, pyidx);
     359                 :          0 :     return tpl;
     360                 :            : }
     361                 :            : 
     362                 :            : static PyObject *
     363                 :          0 : scanstring_unicode(PyObject *pystr, Py_ssize_t end, int strict, Py_ssize_t *next_end_ptr)
     364                 :            : {
     365                 :            :     /* Read the JSON string from PyUnicode pystr.
     366                 :            :     end is the index of the first character after the quote.
     367                 :            :     if strict is zero then literal control characters are allowed
     368                 :            :     *next_end_ptr is a return-by-reference index of the character
     369                 :            :         after the end quote
     370                 :            : 
     371                 :            :     Return value is a new PyUnicode
     372                 :            :     */
     373                 :          0 :     PyObject *rval = NULL;
     374                 :            :     Py_ssize_t len;
     375                 :          0 :     Py_ssize_t begin = end - 1;
     376                 :            :     Py_ssize_t next /* = begin */;
     377                 :            :     const void *buf;
     378                 :            :     int kind;
     379                 :            : 
     380         [ #  # ]:          0 :     if (PyUnicode_READY(pystr) == -1)
     381                 :          0 :         return 0;
     382                 :            : 
     383                 :            :     _PyUnicodeWriter writer;
     384                 :          0 :     _PyUnicodeWriter_Init(&writer);
     385                 :          0 :     writer.overallocate = 1;
     386                 :            : 
     387                 :          0 :     len = PyUnicode_GET_LENGTH(pystr);
     388                 :          0 :     buf = PyUnicode_DATA(pystr);
     389                 :          0 :     kind = PyUnicode_KIND(pystr);
     390                 :            : 
     391   [ #  #  #  # ]:          0 :     if (end < 0 || len < end) {
     392                 :          0 :         PyErr_SetString(PyExc_ValueError, "end is out of bounds");
     393                 :          0 :         goto bail;
     394                 :            :     }
     395                 :          0 :     while (1) {
     396                 :            :         /* Find the end of the string or the next escape */
     397                 :            :         Py_UCS4 c;
     398                 :            :         {
     399                 :            :             // Use tight scope variable to help register allocation.
     400                 :          0 :             Py_UCS4 d = 0;
     401         [ #  # ]:          0 :             for (next = end; next < len; next++) {
     402                 :          0 :                 d = PyUnicode_READ(kind, buf, next);
     403   [ #  #  #  # ]:          0 :                 if (d == '"' || d == '\\') {
     404                 :            :                     break;
     405                 :            :                 }
     406   [ #  #  #  # ]:          0 :                 if (d <= 0x1f && strict) {
     407                 :          0 :                     raise_errmsg("Invalid control character at", pystr, next);
     408                 :          0 :                     goto bail;
     409                 :            :                 }
     410                 :            :             }
     411                 :          0 :             c = d;
     412                 :            :         }
     413                 :            : 
     414         [ #  # ]:          0 :         if (c == '"') {
     415                 :            :             // Fast path for simple case.
     416         [ #  # ]:          0 :             if (writer.buffer == NULL) {
     417                 :          0 :                 PyObject *ret = PyUnicode_Substring(pystr, end, next);
     418         [ #  # ]:          0 :                 if (ret == NULL) {
     419                 :          0 :                     goto bail;
     420                 :            :                 }
     421                 :          0 :                 *next_end_ptr = next + 1;;
     422                 :          0 :                 return ret;
     423                 :            :             }
     424                 :            :         }
     425         [ #  # ]:          0 :         else if (c != '\\') {
     426                 :          0 :             raise_errmsg("Unterminated string starting at", pystr, begin);
     427                 :          0 :             goto bail;
     428                 :            :         }
     429                 :            : 
     430                 :            :         /* Pick up this chunk if it's not zero length */
     431         [ #  # ]:          0 :         if (next != end) {
     432         [ #  # ]:          0 :             if (_PyUnicodeWriter_WriteSubstring(&writer, pystr, end, next) < 0) {
     433                 :          0 :                 goto bail;
     434                 :            :             }
     435                 :            :         }
     436                 :          0 :         next++;
     437         [ #  # ]:          0 :         if (c == '"') {
     438                 :          0 :             end = next;
     439                 :          0 :             break;
     440                 :            :         }
     441         [ #  # ]:          0 :         if (next == len) {
     442                 :          0 :             raise_errmsg("Unterminated string starting at", pystr, begin);
     443                 :          0 :             goto bail;
     444                 :            :         }
     445                 :          0 :         c = PyUnicode_READ(kind, buf, next);
     446         [ #  # ]:          0 :         if (c != 'u') {
     447                 :            :             /* Non-unicode backslash escapes */
     448                 :          0 :             end = next + 1;
     449   [ #  #  #  #  :          0 :             switch (c) {
             #  #  #  #  
                      # ]
     450                 :          0 :                 case '"': break;
     451                 :          0 :                 case '\\': break;
     452                 :          0 :                 case '/': break;
     453                 :          0 :                 case 'b': c = '\b'; break;
     454                 :          0 :                 case 'f': c = '\f'; break;
     455                 :          0 :                 case 'n': c = '\n'; break;
     456                 :          0 :                 case 'r': c = '\r'; break;
     457                 :          0 :                 case 't': c = '\t'; break;
     458                 :          0 :                 default: c = 0;
     459                 :            :             }
     460         [ #  # ]:          0 :             if (c == 0) {
     461                 :          0 :                 raise_errmsg("Invalid \\escape", pystr, end - 2);
     462                 :          0 :                 goto bail;
     463                 :            :             }
     464                 :            :         }
     465                 :            :         else {
     466                 :          0 :             c = 0;
     467                 :          0 :             next++;
     468                 :          0 :             end = next + 4;
     469         [ #  # ]:          0 :             if (end >= len) {
     470                 :          0 :                 raise_errmsg("Invalid \\uXXXX escape", pystr, next - 1);
     471                 :          0 :                 goto bail;
     472                 :            :             }
     473                 :            :             /* Decode 4 hex digits */
     474         [ #  # ]:          0 :             for (; next < end; next++) {
     475                 :          0 :                 Py_UCS4 digit = PyUnicode_READ(kind, buf, next);
     476                 :          0 :                 c <<= 4;
     477   [ #  #  #  # ]:          0 :                 switch (digit) {
     478                 :          0 :                     case '0': case '1': case '2': case '3': case '4':
     479                 :            :                     case '5': case '6': case '7': case '8': case '9':
     480                 :          0 :                         c |= (digit - '0'); break;
     481                 :          0 :                     case 'a': case 'b': case 'c': case 'd': case 'e':
     482                 :            :                     case 'f':
     483                 :          0 :                         c |= (digit - 'a' + 10); break;
     484                 :          0 :                     case 'A': case 'B': case 'C': case 'D': case 'E':
     485                 :            :                     case 'F':
     486                 :          0 :                         c |= (digit - 'A' + 10); break;
     487                 :          0 :                     default:
     488                 :          0 :                         raise_errmsg("Invalid \\uXXXX escape", pystr, end - 5);
     489                 :          0 :                         goto bail;
     490                 :            :                 }
     491                 :            :             }
     492                 :            :             /* Surrogate pair */
     493   [ #  #  #  #  :          0 :             if (Py_UNICODE_IS_HIGH_SURROGATE(c) && end + 6 < len &&
                   #  # ]
     494         [ #  # ]:          0 :                 PyUnicode_READ(kind, buf, next++) == '\\' &&
     495                 :          0 :                 PyUnicode_READ(kind, buf, next++) == 'u') {
     496                 :          0 :                 Py_UCS4 c2 = 0;
     497                 :          0 :                 end += 6;
     498                 :            :                 /* Decode 4 hex digits */
     499         [ #  # ]:          0 :                 for (; next < end; next++) {
     500                 :          0 :                     Py_UCS4 digit = PyUnicode_READ(kind, buf, next);
     501                 :          0 :                     c2 <<= 4;
     502   [ #  #  #  # ]:          0 :                     switch (digit) {
     503                 :          0 :                         case '0': case '1': case '2': case '3': case '4':
     504                 :            :                         case '5': case '6': case '7': case '8': case '9':
     505                 :          0 :                             c2 |= (digit - '0'); break;
     506                 :          0 :                         case 'a': case 'b': case 'c': case 'd': case 'e':
     507                 :            :                         case 'f':
     508                 :          0 :                             c2 |= (digit - 'a' + 10); break;
     509                 :          0 :                         case 'A': case 'B': case 'C': case 'D': case 'E':
     510                 :            :                         case 'F':
     511                 :          0 :                             c2 |= (digit - 'A' + 10); break;
     512                 :          0 :                         default:
     513                 :          0 :                             raise_errmsg("Invalid \\uXXXX escape", pystr, end - 5);
     514                 :          0 :                             goto bail;
     515                 :            :                     }
     516                 :            :                 }
     517         [ #  # ]:          0 :                 if (Py_UNICODE_IS_LOW_SURROGATE(c2))
     518                 :          0 :                     c = Py_UNICODE_JOIN_SURROGATES(c, c2);
     519                 :            :                 else
     520                 :          0 :                     end -= 6;
     521                 :            :             }
     522                 :            :         }
     523         [ #  # ]:          0 :         if (_PyUnicodeWriter_WriteChar(&writer, c) < 0) {
     524                 :          0 :             goto bail;
     525                 :            :         }
     526                 :            :     }
     527                 :            : 
     528                 :          0 :     rval = _PyUnicodeWriter_Finish(&writer);
     529                 :          0 :     *next_end_ptr = end;
     530                 :          0 :     return rval;
     531                 :            : 
     532                 :          0 : bail:
     533                 :          0 :     *next_end_ptr = -1;
     534                 :          0 :     _PyUnicodeWriter_Dealloc(&writer);
     535                 :          0 :     return NULL;
     536                 :            : }
     537                 :            : 
     538                 :            : PyDoc_STRVAR(pydoc_scanstring,
     539                 :            :     "scanstring(string, end, strict=True) -> (string, end)\n"
     540                 :            :     "\n"
     541                 :            :     "Scan the string s for a JSON string. End is the index of the\n"
     542                 :            :     "character in s after the quote that started the JSON string.\n"
     543                 :            :     "Unescapes all valid JSON string escape sequences and raises ValueError\n"
     544                 :            :     "on attempt to decode an invalid string. If strict is False then literal\n"
     545                 :            :     "control characters are allowed in the string.\n"
     546                 :            :     "\n"
     547                 :            :     "Returns a tuple of the decoded string and the index of the character in s\n"
     548                 :            :     "after the end quote."
     549                 :            : );
     550                 :            : 
     551                 :            : static PyObject *
     552                 :          0 : py_scanstring(PyObject* Py_UNUSED(self), PyObject *args)
     553                 :            : {
     554                 :            :     PyObject *pystr;
     555                 :            :     PyObject *rval;
     556                 :            :     Py_ssize_t end;
     557                 :          0 :     Py_ssize_t next_end = -1;
     558                 :          0 :     int strict = 1;
     559         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args, "On|p:scanstring", &pystr, &end, &strict)) {
     560                 :          0 :         return NULL;
     561                 :            :     }
     562         [ #  # ]:          0 :     if (PyUnicode_Check(pystr)) {
     563                 :          0 :         rval = scanstring_unicode(pystr, end, strict, &next_end);
     564                 :            :     }
     565                 :            :     else {
     566                 :          0 :         PyErr_Format(PyExc_TypeError,
     567                 :            :                      "first argument must be a string, not %.80s",
     568                 :          0 :                      Py_TYPE(pystr)->tp_name);
     569                 :          0 :         return NULL;
     570                 :            :     }
     571                 :          0 :     return _build_rval_index_tuple(rval, next_end);
     572                 :            : }
     573                 :            : 
     574                 :            : PyDoc_STRVAR(pydoc_encode_basestring_ascii,
     575                 :            :     "encode_basestring_ascii(string) -> string\n"
     576                 :            :     "\n"
     577                 :            :     "Return an ASCII-only JSON representation of a Python string"
     578                 :            : );
     579                 :            : 
     580                 :            : static PyObject *
     581                 :          0 : py_encode_basestring_ascii(PyObject* Py_UNUSED(self), PyObject *pystr)
     582                 :            : {
     583                 :            :     PyObject *rval;
     584                 :            :     /* Return an ASCII-only JSON representation of a Python string */
     585                 :            :     /* METH_O */
     586         [ #  # ]:          0 :     if (PyUnicode_Check(pystr)) {
     587                 :          0 :         rval = ascii_escape_unicode(pystr);
     588                 :            :     }
     589                 :            :     else {
     590                 :          0 :         PyErr_Format(PyExc_TypeError,
     591                 :            :                      "first argument must be a string, not %.80s",
     592                 :          0 :                      Py_TYPE(pystr)->tp_name);
     593                 :          0 :         return NULL;
     594                 :            :     }
     595                 :          0 :     return rval;
     596                 :            : }
     597                 :            : 
     598                 :            : 
     599                 :            : PyDoc_STRVAR(pydoc_encode_basestring,
     600                 :            :     "encode_basestring(string) -> string\n"
     601                 :            :     "\n"
     602                 :            :     "Return a JSON representation of a Python string"
     603                 :            : );
     604                 :            : 
     605                 :            : static PyObject *
     606                 :          0 : py_encode_basestring(PyObject* Py_UNUSED(self), PyObject *pystr)
     607                 :            : {
     608                 :            :     PyObject *rval;
     609                 :            :     /* Return a JSON representation of a Python string */
     610                 :            :     /* METH_O */
     611         [ #  # ]:          0 :     if (PyUnicode_Check(pystr)) {
     612                 :          0 :         rval = escape_unicode(pystr);
     613                 :            :     }
     614                 :            :     else {
     615                 :          0 :         PyErr_Format(PyExc_TypeError,
     616                 :            :                      "first argument must be a string, not %.80s",
     617                 :          0 :                      Py_TYPE(pystr)->tp_name);
     618                 :          0 :         return NULL;
     619                 :            :     }
     620                 :          0 :     return rval;
     621                 :            : }
     622                 :            : 
     623                 :            : static void
     624                 :          0 : scanner_dealloc(PyObject *self)
     625                 :            : {
     626                 :          0 :     PyTypeObject *tp = Py_TYPE(self);
     627                 :            :     /* bpo-31095: UnTrack is needed before calling any callbacks */
     628                 :          0 :     PyObject_GC_UnTrack(self);
     629                 :          0 :     scanner_clear((PyScannerObject *)self);
     630                 :          0 :     tp->tp_free(self);
     631                 :          0 :     Py_DECREF(tp);
     632                 :          0 : }
     633                 :            : 
     634                 :            : static int
     635                 :          0 : scanner_traverse(PyScannerObject *self, visitproc visit, void *arg)
     636                 :            : {
     637   [ #  #  #  # ]:          0 :     Py_VISIT(Py_TYPE(self));
     638   [ #  #  #  # ]:          0 :     Py_VISIT(self->object_hook);
     639   [ #  #  #  # ]:          0 :     Py_VISIT(self->object_pairs_hook);
     640   [ #  #  #  # ]:          0 :     Py_VISIT(self->parse_float);
     641   [ #  #  #  # ]:          0 :     Py_VISIT(self->parse_int);
     642   [ #  #  #  # ]:          0 :     Py_VISIT(self->parse_constant);
     643   [ #  #  #  # ]:          0 :     Py_VISIT(self->memo);
     644                 :          0 :     return 0;
     645                 :            : }
     646                 :            : 
     647                 :            : static int
     648                 :          0 : scanner_clear(PyScannerObject *self)
     649                 :            : {
     650         [ #  # ]:          0 :     Py_CLEAR(self->object_hook);
     651         [ #  # ]:          0 :     Py_CLEAR(self->object_pairs_hook);
     652         [ #  # ]:          0 :     Py_CLEAR(self->parse_float);
     653         [ #  # ]:          0 :     Py_CLEAR(self->parse_int);
     654         [ #  # ]:          0 :     Py_CLEAR(self->parse_constant);
     655         [ #  # ]:          0 :     Py_CLEAR(self->memo);
     656                 :          0 :     return 0;
     657                 :            : }
     658                 :            : 
     659                 :            : static PyObject *
     660                 :          0 : _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr)
     661                 :            : {
     662                 :            :     /* Read a JSON object from PyUnicode pystr.
     663                 :            :     idx is the index of the first character after the opening curly brace.
     664                 :            :     *next_idx_ptr is a return-by-reference index to the first character after
     665                 :            :         the closing curly brace.
     666                 :            : 
     667                 :            :     Returns a new PyObject (usually a dict, but object_hook can change that)
     668                 :            :     */
     669                 :            :     const void *str;
     670                 :            :     int kind;
     671                 :            :     Py_ssize_t end_idx;
     672                 :          0 :     PyObject *val = NULL;
     673                 :          0 :     PyObject *rval = NULL;
     674                 :          0 :     PyObject *key = NULL;
     675                 :          0 :     int has_pairs_hook = (s->object_pairs_hook != Py_None);
     676                 :            :     Py_ssize_t next_idx;
     677                 :            : 
     678         [ #  # ]:          0 :     if (PyUnicode_READY(pystr) == -1)
     679                 :          0 :         return NULL;
     680                 :            : 
     681                 :          0 :     str = PyUnicode_DATA(pystr);
     682                 :          0 :     kind = PyUnicode_KIND(pystr);
     683                 :          0 :     end_idx = PyUnicode_GET_LENGTH(pystr) - 1;
     684                 :            : 
     685         [ #  # ]:          0 :     if (has_pairs_hook)
     686                 :          0 :         rval = PyList_New(0);
     687                 :            :     else
     688                 :          0 :         rval = PyDict_New();
     689         [ #  # ]:          0 :     if (rval == NULL)
     690                 :          0 :         return NULL;
     691                 :            : 
     692                 :            :     /* skip whitespace after { */
     693   [ #  #  #  #  :          0 :     while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind,str, idx))) idx++;
          #  #  #  #  #  
                      # ]
     694                 :            : 
     695                 :            :     /* only loop if the object is non-empty */
     696   [ #  #  #  # ]:          0 :     if (idx > end_idx || PyUnicode_READ(kind, str, idx) != '}') {
     697                 :          0 :         while (1) {
     698                 :            :             PyObject *memokey;
     699                 :            : 
     700                 :            :             /* read key */
     701   [ #  #  #  # ]:          0 :             if (idx > end_idx || PyUnicode_READ(kind, str, idx) != '"') {
     702                 :          0 :                 raise_errmsg("Expecting property name enclosed in double quotes", pystr, idx);
     703                 :          0 :                 goto bail;
     704                 :            :             }
     705                 :          0 :             key = scanstring_unicode(pystr, idx + 1, s->strict, &next_idx);
     706         [ #  # ]:          0 :             if (key == NULL)
     707                 :          0 :                 goto bail;
     708                 :          0 :             memokey = PyDict_SetDefault(s->memo, key, key);
     709         [ #  # ]:          0 :             if (memokey == NULL) {
     710                 :          0 :                 goto bail;
     711                 :            :             }
     712                 :          0 :             Py_SETREF(key, Py_NewRef(memokey));
     713                 :          0 :             idx = next_idx;
     714                 :            : 
     715                 :            :             /* skip whitespace between key and : delimiter, read :, skip whitespace */
     716   [ #  #  #  #  :          0 :             while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++;
          #  #  #  #  #  
                      # ]
     717   [ #  #  #  # ]:          0 :             if (idx > end_idx || PyUnicode_READ(kind, str, idx) != ':') {
     718                 :          0 :                 raise_errmsg("Expecting ':' delimiter", pystr, idx);
     719                 :          0 :                 goto bail;
     720                 :            :             }
     721                 :          0 :             idx++;
     722   [ #  #  #  #  :          0 :             while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++;
          #  #  #  #  #  
                      # ]
     723                 :            : 
     724                 :            :             /* read any JSON term */
     725                 :          0 :             val = scan_once_unicode(s, pystr, idx, &next_idx);
     726         [ #  # ]:          0 :             if (val == NULL)
     727                 :          0 :                 goto bail;
     728                 :            : 
     729         [ #  # ]:          0 :             if (has_pairs_hook) {
     730                 :          0 :                 PyObject *item = PyTuple_Pack(2, key, val);
     731         [ #  # ]:          0 :                 if (item == NULL)
     732                 :          0 :                     goto bail;
     733         [ #  # ]:          0 :                 Py_CLEAR(key);
     734         [ #  # ]:          0 :                 Py_CLEAR(val);
     735         [ #  # ]:          0 :                 if (PyList_Append(rval, item) == -1) {
     736                 :          0 :                     Py_DECREF(item);
     737                 :          0 :                     goto bail;
     738                 :            :                 }
     739                 :          0 :                 Py_DECREF(item);
     740                 :            :             }
     741                 :            :             else {
     742         [ #  # ]:          0 :                 if (PyDict_SetItem(rval, key, val) < 0)
     743                 :          0 :                     goto bail;
     744         [ #  # ]:          0 :                 Py_CLEAR(key);
     745         [ #  # ]:          0 :                 Py_CLEAR(val);
     746                 :            :             }
     747                 :          0 :             idx = next_idx;
     748                 :            : 
     749                 :            :             /* skip whitespace before } or , */
     750   [ #  #  #  #  :          0 :             while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++;
          #  #  #  #  #  
                      # ]
     751                 :            : 
     752                 :            :             /* bail if the object is closed or we didn't get the , delimiter */
     753   [ #  #  #  # ]:          0 :             if (idx <= end_idx && PyUnicode_READ(kind, str, idx) == '}')
     754                 :          0 :                 break;
     755   [ #  #  #  # ]:          0 :             if (idx > end_idx || PyUnicode_READ(kind, str, idx) != ',') {
     756                 :          0 :                 raise_errmsg("Expecting ',' delimiter", pystr, idx);
     757                 :          0 :                 goto bail;
     758                 :            :             }
     759                 :          0 :             idx++;
     760                 :            : 
     761                 :            :             /* skip whitespace after , delimiter */
     762   [ #  #  #  #  :          0 :             while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++;
          #  #  #  #  #  
                      # ]
     763                 :            :         }
     764                 :            :     }
     765                 :            : 
     766                 :          0 :     *next_idx_ptr = idx + 1;
     767                 :            : 
     768         [ #  # ]:          0 :     if (has_pairs_hook) {
     769                 :          0 :         val = PyObject_CallOneArg(s->object_pairs_hook, rval);
     770                 :          0 :         Py_DECREF(rval);
     771                 :          0 :         return val;
     772                 :            :     }
     773                 :            : 
     774                 :            :     /* if object_hook is not None: rval = object_hook(rval) */
     775         [ #  # ]:          0 :     if (s->object_hook != Py_None) {
     776                 :          0 :         val = PyObject_CallOneArg(s->object_hook, rval);
     777                 :          0 :         Py_DECREF(rval);
     778                 :          0 :         return val;
     779                 :            :     }
     780                 :          0 :     return rval;
     781                 :          0 : bail:
     782                 :          0 :     Py_XDECREF(key);
     783                 :          0 :     Py_XDECREF(val);
     784                 :          0 :     Py_XDECREF(rval);
     785                 :          0 :     return NULL;
     786                 :            : }
     787                 :            : 
     788                 :            : static PyObject *
     789                 :          0 : _parse_array_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
     790                 :            :     /* Read a JSON array from PyUnicode pystr.
     791                 :            :     idx is the index of the first character after the opening brace.
     792                 :            :     *next_idx_ptr is a return-by-reference index to the first character after
     793                 :            :         the closing brace.
     794                 :            : 
     795                 :            :     Returns a new PyList
     796                 :            :     */
     797                 :            :     const void *str;
     798                 :            :     int kind;
     799                 :            :     Py_ssize_t end_idx;
     800                 :          0 :     PyObject *val = NULL;
     801                 :            :     PyObject *rval;
     802                 :            :     Py_ssize_t next_idx;
     803                 :            : 
     804         [ #  # ]:          0 :     if (PyUnicode_READY(pystr) == -1)
     805                 :          0 :         return NULL;
     806                 :            : 
     807                 :          0 :     rval = PyList_New(0);
     808         [ #  # ]:          0 :     if (rval == NULL)
     809                 :          0 :         return NULL;
     810                 :            : 
     811                 :          0 :     str = PyUnicode_DATA(pystr);
     812                 :          0 :     kind = PyUnicode_KIND(pystr);
     813                 :          0 :     end_idx = PyUnicode_GET_LENGTH(pystr) - 1;
     814                 :            : 
     815                 :            :     /* skip whitespace after [ */
     816   [ #  #  #  #  :          0 :     while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++;
          #  #  #  #  #  
                      # ]
     817                 :            : 
     818                 :            :     /* only loop if the array is non-empty */
     819   [ #  #  #  # ]:          0 :     if (idx > end_idx || PyUnicode_READ(kind, str, idx) != ']') {
     820                 :            :         while (1) {
     821                 :            : 
     822                 :            :             /* read any JSON term  */
     823                 :          0 :             val = scan_once_unicode(s, pystr, idx, &next_idx);
     824         [ #  # ]:          0 :             if (val == NULL)
     825                 :          0 :                 goto bail;
     826                 :            : 
     827         [ #  # ]:          0 :             if (PyList_Append(rval, val) == -1)
     828                 :          0 :                 goto bail;
     829                 :            : 
     830         [ #  # ]:          0 :             Py_CLEAR(val);
     831                 :          0 :             idx = next_idx;
     832                 :            : 
     833                 :            :             /* skip whitespace between term and , */
     834   [ #  #  #  #  :          0 :             while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++;
          #  #  #  #  #  
                      # ]
     835                 :            : 
     836                 :            :             /* bail if the array is closed or we didn't get the , delimiter */
     837   [ #  #  #  # ]:          0 :             if (idx <= end_idx && PyUnicode_READ(kind, str, idx) == ']')
     838                 :          0 :                 break;
     839   [ #  #  #  # ]:          0 :             if (idx > end_idx || PyUnicode_READ(kind, str, idx) != ',') {
     840                 :          0 :                 raise_errmsg("Expecting ',' delimiter", pystr, idx);
     841                 :          0 :                 goto bail;
     842                 :            :             }
     843                 :          0 :             idx++;
     844                 :            : 
     845                 :            :             /* skip whitespace after , */
     846   [ #  #  #  #  :          0 :             while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++;
          #  #  #  #  #  
                      # ]
     847                 :            :         }
     848                 :            :     }
     849                 :            : 
     850                 :            :     /* verify that idx < end_idx, PyUnicode_READ(kind, str, idx) should be ']' */
     851   [ #  #  #  # ]:          0 :     if (idx > end_idx || PyUnicode_READ(kind, str, idx) != ']') {
     852                 :          0 :         raise_errmsg("Expecting value", pystr, end_idx);
     853                 :          0 :         goto bail;
     854                 :            :     }
     855                 :          0 :     *next_idx_ptr = idx + 1;
     856                 :          0 :     return rval;
     857                 :          0 : bail:
     858                 :          0 :     Py_XDECREF(val);
     859                 :          0 :     Py_DECREF(rval);
     860                 :          0 :     return NULL;
     861                 :            : }
     862                 :            : 
     863                 :            : static PyObject *
     864                 :          0 : _parse_constant(PyScannerObject *s, const char *constant, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
     865                 :            :     /* Read a JSON constant.
     866                 :            :     constant is the constant string that was found
     867                 :            :         ("NaN", "Infinity", "-Infinity").
     868                 :            :     idx is the index of the first character of the constant
     869                 :            :     *next_idx_ptr is a return-by-reference index to the first character after
     870                 :            :         the constant.
     871                 :            : 
     872                 :            :     Returns the result of parse_constant
     873                 :            :     */
     874                 :            :     PyObject *cstr;
     875                 :            :     PyObject *rval;
     876                 :            :     /* constant is "NaN", "Infinity", or "-Infinity" */
     877                 :          0 :     cstr = PyUnicode_InternFromString(constant);
     878         [ #  # ]:          0 :     if (cstr == NULL)
     879                 :          0 :         return NULL;
     880                 :            : 
     881                 :            :     /* rval = parse_constant(constant) */
     882                 :          0 :     rval = PyObject_CallOneArg(s->parse_constant, cstr);
     883                 :          0 :     idx += PyUnicode_GET_LENGTH(cstr);
     884                 :          0 :     Py_DECREF(cstr);
     885                 :          0 :     *next_idx_ptr = idx;
     886                 :          0 :     return rval;
     887                 :            : }
     888                 :            : 
     889                 :            : static PyObject *
     890                 :          0 : _match_number_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t start, Py_ssize_t *next_idx_ptr) {
     891                 :            :     /* Read a JSON number from PyUnicode pystr.
     892                 :            :     idx is the index of the first character of the number
     893                 :            :     *next_idx_ptr is a return-by-reference index to the first character after
     894                 :            :         the number.
     895                 :            : 
     896                 :            :     Returns a new PyObject representation of that number:
     897                 :            :         PyLong, or PyFloat.
     898                 :            :         May return other types if parse_int or parse_float are set
     899                 :            :     */
     900                 :            :     const void *str;
     901                 :            :     int kind;
     902                 :            :     Py_ssize_t end_idx;
     903                 :          0 :     Py_ssize_t idx = start;
     904                 :          0 :     int is_float = 0;
     905                 :            :     PyObject *rval;
     906                 :          0 :     PyObject *numstr = NULL;
     907                 :            :     PyObject *custom_func;
     908                 :            : 
     909         [ #  # ]:          0 :     if (PyUnicode_READY(pystr) == -1)
     910                 :          0 :         return NULL;
     911                 :            : 
     912                 :          0 :     str = PyUnicode_DATA(pystr);
     913                 :          0 :     kind = PyUnicode_KIND(pystr);
     914                 :          0 :     end_idx = PyUnicode_GET_LENGTH(pystr) - 1;
     915                 :            : 
     916                 :            :     /* read a sign if it's there, make sure it's not the end of the string */
     917         [ #  # ]:          0 :     if (PyUnicode_READ(kind, str, idx) == '-') {
     918                 :          0 :         idx++;
     919         [ #  # ]:          0 :         if (idx > end_idx) {
     920                 :          0 :             raise_stop_iteration(start);
     921                 :          0 :             return NULL;
     922                 :            :         }
     923                 :            :     }
     924                 :            : 
     925                 :            :     /* read as many integer digits as we find as long as it doesn't start with 0 */
     926   [ #  #  #  # ]:          0 :     if (PyUnicode_READ(kind, str, idx) >= '1' && PyUnicode_READ(kind, str, idx) <= '9') {
     927                 :          0 :         idx++;
     928   [ #  #  #  #  :          0 :         while (idx <= end_idx && PyUnicode_READ(kind, str, idx) >= '0' && PyUnicode_READ(kind, str, idx) <= '9') idx++;
                   #  # ]
     929                 :            :     }
     930                 :            :     /* if it starts with 0 we only expect one integer digit */
     931         [ #  # ]:          0 :     else if (PyUnicode_READ(kind, str, idx) == '0') {
     932                 :          0 :         idx++;
     933                 :            :     }
     934                 :            :     /* no integer digits, error */
     935                 :            :     else {
     936                 :          0 :         raise_stop_iteration(start);
     937                 :          0 :         return NULL;
     938                 :            :     }
     939                 :            : 
     940                 :            :     /* if the next char is '.' followed by a digit then read all float digits */
     941   [ #  #  #  #  :          0 :     if (idx < end_idx && PyUnicode_READ(kind, str, idx) == '.' && PyUnicode_READ(kind, str, idx + 1) >= '0' && PyUnicode_READ(kind, str, idx + 1) <= '9') {
             #  #  #  # ]
     942                 :          0 :         is_float = 1;
     943                 :          0 :         idx += 2;
     944   [ #  #  #  #  :          0 :         while (idx <= end_idx && PyUnicode_READ(kind, str, idx) >= '0' && PyUnicode_READ(kind, str, idx) <= '9') idx++;
                   #  # ]
     945                 :            :     }
     946                 :            : 
     947                 :            :     /* if the next char is 'e' or 'E' then maybe read the exponent (or backtrack) */
     948   [ #  #  #  #  :          0 :     if (idx < end_idx && (PyUnicode_READ(kind, str, idx) == 'e' || PyUnicode_READ(kind, str, idx) == 'E')) {
                   #  # ]
     949                 :          0 :         Py_ssize_t e_start = idx;
     950                 :          0 :         idx++;
     951                 :            : 
     952                 :            :         /* read an exponent sign if present */
     953   [ #  #  #  #  :          0 :         if (idx < end_idx && (PyUnicode_READ(kind, str, idx) == '-' || PyUnicode_READ(kind, str, idx) == '+')) idx++;
                   #  # ]
     954                 :            : 
     955                 :            :         /* read all digits */
     956   [ #  #  #  #  :          0 :         while (idx <= end_idx && PyUnicode_READ(kind, str, idx) >= '0' && PyUnicode_READ(kind, str, idx) <= '9') idx++;
                   #  # ]
     957                 :            : 
     958                 :            :         /* if we got a digit, then parse as float. if not, backtrack */
     959   [ #  #  #  # ]:          0 :         if (PyUnicode_READ(kind, str, idx - 1) >= '0' && PyUnicode_READ(kind, str, idx - 1) <= '9') {
     960                 :          0 :             is_float = 1;
     961                 :            :         }
     962                 :            :         else {
     963                 :          0 :             idx = e_start;
     964                 :            :         }
     965                 :            :     }
     966                 :            : 
     967   [ #  #  #  # ]:          0 :     if (is_float && s->parse_float != (PyObject *)&PyFloat_Type)
     968                 :          0 :         custom_func = s->parse_float;
     969   [ #  #  #  # ]:          0 :     else if (!is_float && s->parse_int != (PyObject *) &PyLong_Type)
     970                 :          0 :         custom_func = s->parse_int;
     971                 :            :     else
     972                 :          0 :         custom_func = NULL;
     973                 :            : 
     974         [ #  # ]:          0 :     if (custom_func) {
     975                 :            :         /* copy the section we determined to be a number */
     976                 :          0 :         numstr = PyUnicode_FromKindAndData(kind,
     977                 :          0 :                                            (char*)str + kind * start,
     978                 :            :                                            idx - start);
     979         [ #  # ]:          0 :         if (numstr == NULL)
     980                 :          0 :             return NULL;
     981                 :          0 :         rval = PyObject_CallOneArg(custom_func, numstr);
     982                 :            :     }
     983                 :            :     else {
     984                 :            :         Py_ssize_t i, n;
     985                 :            :         char *buf;
     986                 :            :         /* Straight conversion to ASCII, to avoid costly conversion of
     987                 :            :            decimal unicode digits (which cannot appear here) */
     988                 :          0 :         n = idx - start;
     989                 :          0 :         numstr = PyBytes_FromStringAndSize(NULL, n);
     990         [ #  # ]:          0 :         if (numstr == NULL)
     991                 :          0 :             return NULL;
     992                 :          0 :         buf = PyBytes_AS_STRING(numstr);
     993         [ #  # ]:          0 :         for (i = 0; i < n; i++) {
     994                 :          0 :             buf[i] = (char) PyUnicode_READ(kind, str, i + start);
     995                 :            :         }
     996         [ #  # ]:          0 :         if (is_float)
     997                 :          0 :             rval = PyFloat_FromString(numstr);
     998                 :            :         else
     999                 :          0 :             rval = PyLong_FromString(buf, NULL, 10);
    1000                 :            :     }
    1001                 :          0 :     Py_DECREF(numstr);
    1002                 :          0 :     *next_idx_ptr = idx;
    1003                 :          0 :     return rval;
    1004                 :            : }
    1005                 :            : 
    1006                 :            : static PyObject *
    1007                 :          0 : scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr)
    1008                 :            : {
    1009                 :            :     /* Read one JSON term (of any kind) from PyUnicode pystr.
    1010                 :            :     idx is the index of the first character of the term
    1011                 :            :     *next_idx_ptr is a return-by-reference index to the first character after
    1012                 :            :         the number.
    1013                 :            : 
    1014                 :            :     Returns a new PyObject representation of the term.
    1015                 :            :     */
    1016                 :            :     PyObject *res;
    1017                 :            :     const void *str;
    1018                 :            :     int kind;
    1019                 :            :     Py_ssize_t length;
    1020                 :            : 
    1021         [ #  # ]:          0 :     if (PyUnicode_READY(pystr) == -1)
    1022                 :          0 :         return NULL;
    1023                 :            : 
    1024                 :          0 :     str = PyUnicode_DATA(pystr);
    1025                 :          0 :     kind = PyUnicode_KIND(pystr);
    1026                 :          0 :     length = PyUnicode_GET_LENGTH(pystr);
    1027                 :            : 
    1028         [ #  # ]:          0 :     if (idx < 0) {
    1029                 :          0 :         PyErr_SetString(PyExc_ValueError, "idx cannot be negative");
    1030                 :          0 :         return NULL;
    1031                 :            :     }
    1032         [ #  # ]:          0 :     if (idx >= length) {
    1033                 :          0 :         raise_stop_iteration(idx);
    1034                 :          0 :         return NULL;
    1035                 :            :     }
    1036                 :            : 
    1037   [ #  #  #  #  :          0 :     switch (PyUnicode_READ(kind, str, idx)) {
          #  #  #  #  #  
                      # ]
    1038                 :          0 :         case '"':
    1039                 :            :             /* string */
    1040                 :          0 :             return scanstring_unicode(pystr, idx + 1, s->strict, next_idx_ptr);
    1041                 :          0 :         case '{':
    1042                 :            :             /* object */
    1043         [ #  # ]:          0 :             if (_Py_EnterRecursiveCall(" while decoding a JSON object "
    1044                 :            :                                        "from a unicode string"))
    1045                 :          0 :                 return NULL;
    1046                 :          0 :             res = _parse_object_unicode(s, pystr, idx + 1, next_idx_ptr);
    1047                 :          0 :             _Py_LeaveRecursiveCall();
    1048                 :          0 :             return res;
    1049                 :          0 :         case '[':
    1050                 :            :             /* array */
    1051         [ #  # ]:          0 :             if (_Py_EnterRecursiveCall(" while decoding a JSON array "
    1052                 :            :                                        "from a unicode string"))
    1053                 :          0 :                 return NULL;
    1054                 :          0 :             res = _parse_array_unicode(s, pystr, idx + 1, next_idx_ptr);
    1055                 :          0 :             _Py_LeaveRecursiveCall();
    1056                 :          0 :             return res;
    1057                 :          0 :         case 'n':
    1058                 :            :             /* null */
    1059   [ #  #  #  #  :          0 :             if ((idx + 3 < length) && PyUnicode_READ(kind, str, idx + 1) == 'u' && PyUnicode_READ(kind, str, idx + 2) == 'l' && PyUnicode_READ(kind, str, idx + 3) == 'l') {
             #  #  #  # ]
    1060                 :          0 :                 *next_idx_ptr = idx + 4;
    1061                 :          0 :                 Py_RETURN_NONE;
    1062                 :            :             }
    1063                 :          0 :             break;
    1064                 :          0 :         case 't':
    1065                 :            :             /* true */
    1066   [ #  #  #  #  :          0 :             if ((idx + 3 < length) && PyUnicode_READ(kind, str, idx + 1) == 'r' && PyUnicode_READ(kind, str, idx + 2) == 'u' && PyUnicode_READ(kind, str, idx + 3) == 'e') {
             #  #  #  # ]
    1067                 :          0 :                 *next_idx_ptr = idx + 4;
    1068                 :          0 :                 Py_RETURN_TRUE;
    1069                 :            :             }
    1070                 :          0 :             break;
    1071                 :          0 :         case 'f':
    1072                 :            :             /* false */
    1073   [ #  #  #  #  :          0 :             if ((idx + 4 < length) && PyUnicode_READ(kind, str, idx + 1) == 'a' &&
                   #  # ]
    1074         [ #  # ]:          0 :                 PyUnicode_READ(kind, str, idx + 2) == 'l' &&
    1075         [ #  # ]:          0 :                 PyUnicode_READ(kind, str, idx + 3) == 's' &&
    1076                 :          0 :                 PyUnicode_READ(kind, str, idx + 4) == 'e') {
    1077                 :          0 :                 *next_idx_ptr = idx + 5;
    1078                 :          0 :                 Py_RETURN_FALSE;
    1079                 :            :             }
    1080                 :          0 :             break;
    1081                 :          0 :         case 'N':
    1082                 :            :             /* NaN */
    1083   [ #  #  #  #  :          0 :             if ((idx + 2 < length) && PyUnicode_READ(kind, str, idx + 1) == 'a' &&
                   #  # ]
    1084                 :          0 :                 PyUnicode_READ(kind, str, idx + 2) == 'N') {
    1085                 :          0 :                 return _parse_constant(s, "NaN", idx, next_idx_ptr);
    1086                 :            :             }
    1087                 :          0 :             break;
    1088                 :          0 :         case 'I':
    1089                 :            :             /* Infinity */
    1090   [ #  #  #  #  :          0 :             if ((idx + 7 < length) && PyUnicode_READ(kind, str, idx + 1) == 'n' &&
                   #  # ]
    1091         [ #  # ]:          0 :                 PyUnicode_READ(kind, str, idx + 2) == 'f' &&
    1092         [ #  # ]:          0 :                 PyUnicode_READ(kind, str, idx + 3) == 'i' &&
    1093         [ #  # ]:          0 :                 PyUnicode_READ(kind, str, idx + 4) == 'n' &&
    1094         [ #  # ]:          0 :                 PyUnicode_READ(kind, str, idx + 5) == 'i' &&
    1095         [ #  # ]:          0 :                 PyUnicode_READ(kind, str, idx + 6) == 't' &&
    1096                 :          0 :                 PyUnicode_READ(kind, str, idx + 7) == 'y') {
    1097                 :          0 :                 return _parse_constant(s, "Infinity", idx, next_idx_ptr);
    1098                 :            :             }
    1099                 :          0 :             break;
    1100                 :          0 :         case '-':
    1101                 :            :             /* -Infinity */
    1102   [ #  #  #  #  :          0 :             if ((idx + 8 < length) && PyUnicode_READ(kind, str, idx + 1) == 'I' &&
                   #  # ]
    1103         [ #  # ]:          0 :                 PyUnicode_READ(kind, str, idx + 2) == 'n' &&
    1104         [ #  # ]:          0 :                 PyUnicode_READ(kind, str, idx + 3) == 'f' &&
    1105         [ #  # ]:          0 :                 PyUnicode_READ(kind, str, idx + 4) == 'i' &&
    1106         [ #  # ]:          0 :                 PyUnicode_READ(kind, str, idx + 5) == 'n' &&
    1107         [ #  # ]:          0 :                 PyUnicode_READ(kind, str, idx + 6) == 'i' &&
    1108         [ #  # ]:          0 :                 PyUnicode_READ(kind, str, idx + 7) == 't' &&
    1109                 :          0 :                 PyUnicode_READ(kind, str, idx + 8) == 'y') {
    1110                 :          0 :                 return _parse_constant(s, "-Infinity", idx, next_idx_ptr);
    1111                 :            :             }
    1112                 :          0 :             break;
    1113                 :            :     }
    1114                 :            :     /* Didn't find a string, object, array, or named constant. Look for a number. */
    1115                 :          0 :     return _match_number_unicode(s, pystr, idx, next_idx_ptr);
    1116                 :            : }
    1117                 :            : 
    1118                 :            : static PyObject *
    1119                 :          0 : scanner_call(PyScannerObject *self, PyObject *args, PyObject *kwds)
    1120                 :            : {
    1121                 :            :     /* Python callable interface to scan_once_{str,unicode} */
    1122                 :            :     PyObject *pystr;
    1123                 :            :     PyObject *rval;
    1124                 :            :     Py_ssize_t idx;
    1125                 :          0 :     Py_ssize_t next_idx = -1;
    1126                 :            :     static char *kwlist[] = {"string", "idx", NULL};
    1127         [ #  # ]:          0 :     if (!PyArg_ParseTupleAndKeywords(args, kwds, "On:scan_once", kwlist, &pystr, &idx))
    1128                 :          0 :         return NULL;
    1129                 :            : 
    1130         [ #  # ]:          0 :     if (PyUnicode_Check(pystr)) {
    1131                 :          0 :         rval = scan_once_unicode(self, pystr, idx, &next_idx);
    1132                 :            :     }
    1133                 :            :     else {
    1134                 :          0 :         PyErr_Format(PyExc_TypeError,
    1135                 :            :                  "first argument must be a string, not %.80s",
    1136                 :          0 :                  Py_TYPE(pystr)->tp_name);
    1137                 :          0 :         return NULL;
    1138                 :            :     }
    1139                 :          0 :     PyDict_Clear(self->memo);
    1140         [ #  # ]:          0 :     if (rval == NULL)
    1141                 :          0 :         return NULL;
    1142                 :          0 :     return _build_rval_index_tuple(rval, next_idx);
    1143                 :            : }
    1144                 :            : 
    1145                 :            : static PyObject *
    1146                 :          0 : scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
    1147                 :            : {
    1148                 :            :     PyScannerObject *s;
    1149                 :            :     PyObject *ctx;
    1150                 :            :     PyObject *strict;
    1151                 :            :     static char *kwlist[] = {"context", NULL};
    1152                 :            : 
    1153         [ #  # ]:          0 :     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:make_scanner", kwlist, &ctx))
    1154                 :          0 :         return NULL;
    1155                 :            : 
    1156                 :          0 :     s = (PyScannerObject *)type->tp_alloc(type, 0);
    1157         [ #  # ]:          0 :     if (s == NULL) {
    1158                 :          0 :         return NULL;
    1159                 :            :     }
    1160                 :            : 
    1161                 :          0 :     s->memo = PyDict_New();
    1162         [ #  # ]:          0 :     if (s->memo == NULL)
    1163                 :          0 :         goto bail;
    1164                 :            : 
    1165                 :            :     /* All of these will fail "gracefully" so we don't need to verify them */
    1166                 :          0 :     strict = PyObject_GetAttrString(ctx, "strict");
    1167         [ #  # ]:          0 :     if (strict == NULL)
    1168                 :          0 :         goto bail;
    1169                 :          0 :     s->strict = PyObject_IsTrue(strict);
    1170                 :          0 :     Py_DECREF(strict);
    1171         [ #  # ]:          0 :     if (s->strict < 0)
    1172                 :          0 :         goto bail;
    1173                 :          0 :     s->object_hook = PyObject_GetAttrString(ctx, "object_hook");
    1174         [ #  # ]:          0 :     if (s->object_hook == NULL)
    1175                 :          0 :         goto bail;
    1176                 :          0 :     s->object_pairs_hook = PyObject_GetAttrString(ctx, "object_pairs_hook");
    1177         [ #  # ]:          0 :     if (s->object_pairs_hook == NULL)
    1178                 :          0 :         goto bail;
    1179                 :          0 :     s->parse_float = PyObject_GetAttrString(ctx, "parse_float");
    1180         [ #  # ]:          0 :     if (s->parse_float == NULL)
    1181                 :          0 :         goto bail;
    1182                 :          0 :     s->parse_int = PyObject_GetAttrString(ctx, "parse_int");
    1183         [ #  # ]:          0 :     if (s->parse_int == NULL)
    1184                 :          0 :         goto bail;
    1185                 :          0 :     s->parse_constant = PyObject_GetAttrString(ctx, "parse_constant");
    1186         [ #  # ]:          0 :     if (s->parse_constant == NULL)
    1187                 :          0 :         goto bail;
    1188                 :            : 
    1189                 :          0 :     return (PyObject *)s;
    1190                 :            : 
    1191                 :          0 : bail:
    1192                 :          0 :     Py_DECREF(s);
    1193                 :          0 :     return NULL;
    1194                 :            : }
    1195                 :            : 
    1196                 :            : PyDoc_STRVAR(scanner_doc, "JSON scanner object");
    1197                 :            : 
    1198                 :            : static PyType_Slot PyScannerType_slots[] = {
    1199                 :            :     {Py_tp_doc, (void *)scanner_doc},
    1200                 :            :     {Py_tp_dealloc, scanner_dealloc},
    1201                 :            :     {Py_tp_call, scanner_call},
    1202                 :            :     {Py_tp_traverse, scanner_traverse},
    1203                 :            :     {Py_tp_clear, scanner_clear},
    1204                 :            :     {Py_tp_members, scanner_members},
    1205                 :            :     {Py_tp_new, scanner_new},
    1206                 :            :     {0, 0}
    1207                 :            : };
    1208                 :            : 
    1209                 :            : static PyType_Spec PyScannerType_spec = {
    1210                 :            :     .name = "_json.Scanner",
    1211                 :            :     .basicsize = sizeof(PyScannerObject),
    1212                 :            :     .itemsize = 0,
    1213                 :            :     .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
    1214                 :            :     .slots = PyScannerType_slots,
    1215                 :            : };
    1216                 :            : 
    1217                 :            : static PyObject *
    1218                 :          0 : encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
    1219                 :            : {
    1220                 :            :     static char *kwlist[] = {"markers", "default", "encoder", "indent", "key_separator", "item_separator", "sort_keys", "skipkeys", "allow_nan", NULL};
    1221                 :            : 
    1222                 :            :     PyEncoderObject *s;
    1223                 :            :     PyObject *markers, *defaultfn, *encoder, *indent, *key_separator;
    1224                 :            :     PyObject *item_separator;
    1225                 :            :     int sort_keys, skipkeys, allow_nan;
    1226                 :            : 
    1227         [ #  # ]:          0 :     if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOUUppp:make_encoder", kwlist,
    1228                 :            :         &markers, &defaultfn, &encoder, &indent,
    1229                 :            :         &key_separator, &item_separator,
    1230                 :            :         &sort_keys, &skipkeys, &allow_nan))
    1231                 :          0 :         return NULL;
    1232                 :            : 
    1233   [ #  #  #  # ]:          0 :     if (markers != Py_None && !PyDict_Check(markers)) {
    1234                 :          0 :         PyErr_Format(PyExc_TypeError,
    1235                 :            :                      "make_encoder() argument 1 must be dict or None, "
    1236                 :          0 :                      "not %.200s", Py_TYPE(markers)->tp_name);
    1237                 :          0 :         return NULL;
    1238                 :            :     }
    1239                 :            : 
    1240                 :          0 :     s = (PyEncoderObject *)type->tp_alloc(type, 0);
    1241         [ #  # ]:          0 :     if (s == NULL)
    1242                 :          0 :         return NULL;
    1243                 :            : 
    1244                 :          0 :     s->markers = Py_NewRef(markers);
    1245                 :          0 :     s->defaultfn = Py_NewRef(defaultfn);
    1246                 :          0 :     s->encoder = Py_NewRef(encoder);
    1247                 :          0 :     s->indent = Py_NewRef(indent);
    1248                 :          0 :     s->key_separator = Py_NewRef(key_separator);
    1249                 :          0 :     s->item_separator = Py_NewRef(item_separator);
    1250                 :          0 :     s->sort_keys = sort_keys;
    1251                 :          0 :     s->skipkeys = skipkeys;
    1252                 :          0 :     s->allow_nan = allow_nan;
    1253                 :          0 :     s->fast_encode = NULL;
    1254                 :            : 
    1255         [ #  # ]:          0 :     if (PyCFunction_Check(s->encoder)) {
    1256                 :          0 :         PyCFunction f = PyCFunction_GetFunction(s->encoder);
    1257   [ #  #  #  # ]:          0 :         if (f == (PyCFunction)py_encode_basestring_ascii ||
    1258                 :            :                 f == (PyCFunction)py_encode_basestring) {
    1259                 :          0 :             s->fast_encode = f;
    1260                 :            :         }
    1261                 :            :     }
    1262                 :            : 
    1263                 :          0 :     return (PyObject *)s;
    1264                 :            : }
    1265                 :            : 
    1266                 :            : static PyObject *
    1267                 :          0 : encoder_call(PyEncoderObject *self, PyObject *args, PyObject *kwds)
    1268                 :            : {
    1269                 :            :     /* Python callable interface to encode_listencode_obj */
    1270                 :            :     static char *kwlist[] = {"obj", "_current_indent_level", NULL};
    1271                 :            :     PyObject *obj, *result;
    1272                 :            :     Py_ssize_t indent_level;
    1273                 :            :     _PyUnicodeWriter writer;
    1274                 :            : 
    1275         [ #  # ]:          0 :     if (!PyArg_ParseTupleAndKeywords(args, kwds, "On:_iterencode", kwlist,
    1276                 :            :         &obj, &indent_level))
    1277                 :          0 :         return NULL;
    1278                 :            : 
    1279                 :          0 :     _PyUnicodeWriter_Init(&writer);
    1280                 :          0 :     writer.overallocate = 1;
    1281                 :            : 
    1282         [ #  # ]:          0 :     if (encoder_listencode_obj(self, &writer, obj, indent_level)) {
    1283                 :          0 :         _PyUnicodeWriter_Dealloc(&writer);
    1284                 :          0 :         return NULL;
    1285                 :            :     }
    1286                 :            : 
    1287                 :          0 :     result = PyTuple_New(1);
    1288   [ #  #  #  # ]:          0 :     if (result == NULL ||
    1289                 :          0 :             PyTuple_SetItem(result, 0, _PyUnicodeWriter_Finish(&writer)) < 0) {
    1290                 :          0 :         Py_XDECREF(result);
    1291                 :          0 :         return NULL;
    1292                 :            :     }
    1293                 :          0 :     return result;
    1294                 :            : }
    1295                 :            : 
    1296                 :            : static PyObject *
    1297                 :          0 : _encoded_const(PyObject *obj)
    1298                 :            : {
    1299                 :            :     /* Return the JSON string representation of None, True, False */
    1300         [ #  # ]:          0 :     if (obj == Py_None) {
    1301                 :          0 :         return Py_NewRef(&_Py_ID(null));
    1302                 :            :     }
    1303         [ #  # ]:          0 :     else if (obj == Py_True) {
    1304                 :          0 :         return Py_NewRef(&_Py_ID(true));
    1305                 :            :     }
    1306         [ #  # ]:          0 :     else if (obj == Py_False) {
    1307                 :          0 :         return Py_NewRef(&_Py_ID(false));
    1308                 :            :     }
    1309                 :            :     else {
    1310                 :          0 :         PyErr_SetString(PyExc_ValueError, "not a const");
    1311                 :          0 :         return NULL;
    1312                 :            :     }
    1313                 :            : }
    1314                 :            : 
    1315                 :            : static PyObject *
    1316                 :          0 : encoder_encode_float(PyEncoderObject *s, PyObject *obj)
    1317                 :            : {
    1318                 :            :     /* Return the JSON representation of a PyFloat. */
    1319                 :          0 :     double i = PyFloat_AS_DOUBLE(obj);
    1320         [ #  # ]:          0 :     if (!Py_IS_FINITE(i)) {
    1321         [ #  # ]:          0 :         if (!s->allow_nan) {
    1322                 :          0 :             PyErr_Format(
    1323                 :            :                     PyExc_ValueError,
    1324                 :            :                     "Out of range float values are not JSON compliant: %R",
    1325                 :            :                     obj
    1326                 :            :                     );
    1327                 :          0 :             return NULL;
    1328                 :            :         }
    1329         [ #  # ]:          0 :         if (i > 0) {
    1330                 :          0 :             return PyUnicode_FromString("Infinity");
    1331                 :            :         }
    1332         [ #  # ]:          0 :         else if (i < 0) {
    1333                 :          0 :             return PyUnicode_FromString("-Infinity");
    1334                 :            :         }
    1335                 :            :         else {
    1336                 :          0 :             return PyUnicode_FromString("NaN");
    1337                 :            :         }
    1338                 :            :     }
    1339                 :          0 :     return PyFloat_Type.tp_repr(obj);
    1340                 :            : }
    1341                 :            : 
    1342                 :            : static PyObject *
    1343                 :          0 : encoder_encode_string(PyEncoderObject *s, PyObject *obj)
    1344                 :            : {
    1345                 :            :     /* Return the JSON representation of a string */
    1346                 :            :     PyObject *encoded;
    1347                 :            : 
    1348         [ #  # ]:          0 :     if (s->fast_encode) {
    1349                 :          0 :         return s->fast_encode(NULL, obj);
    1350                 :            :     }
    1351                 :          0 :     encoded = PyObject_CallOneArg(s->encoder, obj);
    1352   [ #  #  #  # ]:          0 :     if (encoded != NULL && !PyUnicode_Check(encoded)) {
    1353                 :          0 :         PyErr_Format(PyExc_TypeError,
    1354                 :            :                      "encoder() must return a string, not %.80s",
    1355                 :          0 :                      Py_TYPE(encoded)->tp_name);
    1356                 :          0 :         Py_DECREF(encoded);
    1357                 :          0 :         return NULL;
    1358                 :            :     }
    1359                 :          0 :     return encoded;
    1360                 :            : }
    1361                 :            : 
    1362                 :            : static int
    1363                 :          0 : _steal_accumulate(_PyUnicodeWriter *writer, PyObject *stolen)
    1364                 :            : {
    1365                 :            :     /* Append stolen and then decrement its reference count */
    1366                 :          0 :     int rval = _PyUnicodeWriter_WriteStr(writer, stolen);
    1367                 :          0 :     Py_DECREF(stolen);
    1368                 :          0 :     return rval;
    1369                 :            : }
    1370                 :            : 
    1371                 :            : static int
    1372                 :          0 : encoder_listencode_obj(PyEncoderObject *s, _PyUnicodeWriter *writer,
    1373                 :            :                        PyObject *obj, Py_ssize_t indent_level)
    1374                 :            : {
    1375                 :            :     /* Encode Python object obj to a JSON term */
    1376                 :            :     PyObject *newobj;
    1377                 :            :     int rv;
    1378                 :            : 
    1379         [ #  # ]:          0 :     if (obj == Py_None) {
    1380                 :          0 :       return _PyUnicodeWriter_WriteASCIIString(writer, "null", 4);
    1381                 :            :     }
    1382         [ #  # ]:          0 :     else if (obj == Py_True) {
    1383                 :          0 :       return _PyUnicodeWriter_WriteASCIIString(writer, "true", 4);
    1384                 :            :     }
    1385         [ #  # ]:          0 :     else if (obj == Py_False) {
    1386                 :          0 :       return _PyUnicodeWriter_WriteASCIIString(writer, "false", 5);
    1387                 :            :     }
    1388         [ #  # ]:          0 :     else if (PyUnicode_Check(obj)) {
    1389                 :          0 :         PyObject *encoded = encoder_encode_string(s, obj);
    1390         [ #  # ]:          0 :         if (encoded == NULL)
    1391                 :          0 :             return -1;
    1392                 :          0 :         return _steal_accumulate(writer, encoded);
    1393                 :            :     }
    1394         [ #  # ]:          0 :     else if (PyLong_Check(obj)) {
    1395                 :          0 :         PyObject *encoded = PyLong_Type.tp_repr(obj);
    1396         [ #  # ]:          0 :         if (encoded == NULL)
    1397                 :          0 :             return -1;
    1398                 :          0 :         return _steal_accumulate(writer, encoded);
    1399                 :            :     }
    1400         [ #  # ]:          0 :     else if (PyFloat_Check(obj)) {
    1401                 :          0 :         PyObject *encoded = encoder_encode_float(s, obj);
    1402         [ #  # ]:          0 :         if (encoded == NULL)
    1403                 :          0 :             return -1;
    1404                 :          0 :         return _steal_accumulate(writer, encoded);
    1405                 :            :     }
    1406   [ #  #  #  # ]:          0 :     else if (PyList_Check(obj) || PyTuple_Check(obj)) {
    1407         [ #  # ]:          0 :         if (_Py_EnterRecursiveCall(" while encoding a JSON object"))
    1408                 :          0 :             return -1;
    1409                 :          0 :         rv = encoder_listencode_list(s, writer, obj, indent_level);
    1410                 :          0 :         _Py_LeaveRecursiveCall();
    1411                 :          0 :         return rv;
    1412                 :            :     }
    1413         [ #  # ]:          0 :     else if (PyDict_Check(obj)) {
    1414         [ #  # ]:          0 :         if (_Py_EnterRecursiveCall(" while encoding a JSON object"))
    1415                 :          0 :             return -1;
    1416                 :          0 :         rv = encoder_listencode_dict(s, writer, obj, indent_level);
    1417                 :          0 :         _Py_LeaveRecursiveCall();
    1418                 :          0 :         return rv;
    1419                 :            :     }
    1420                 :            :     else {
    1421                 :          0 :         PyObject *ident = NULL;
    1422         [ #  # ]:          0 :         if (s->markers != Py_None) {
    1423                 :            :             int has_key;
    1424                 :          0 :             ident = PyLong_FromVoidPtr(obj);
    1425         [ #  # ]:          0 :             if (ident == NULL)
    1426                 :          0 :                 return -1;
    1427                 :          0 :             has_key = PyDict_Contains(s->markers, ident);
    1428         [ #  # ]:          0 :             if (has_key) {
    1429         [ #  # ]:          0 :                 if (has_key != -1)
    1430                 :          0 :                     PyErr_SetString(PyExc_ValueError, "Circular reference detected");
    1431                 :          0 :                 Py_DECREF(ident);
    1432                 :          0 :                 return -1;
    1433                 :            :             }
    1434         [ #  # ]:          0 :             if (PyDict_SetItem(s->markers, ident, obj)) {
    1435                 :          0 :                 Py_DECREF(ident);
    1436                 :          0 :                 return -1;
    1437                 :            :             }
    1438                 :            :         }
    1439                 :          0 :         newobj = PyObject_CallOneArg(s->defaultfn, obj);
    1440         [ #  # ]:          0 :         if (newobj == NULL) {
    1441                 :          0 :             Py_XDECREF(ident);
    1442                 :          0 :             return -1;
    1443                 :            :         }
    1444                 :            : 
    1445         [ #  # ]:          0 :         if (_Py_EnterRecursiveCall(" while encoding a JSON object")) {
    1446                 :          0 :             Py_DECREF(newobj);
    1447                 :          0 :             Py_XDECREF(ident);
    1448                 :          0 :             return -1;
    1449                 :            :         }
    1450                 :          0 :         rv = encoder_listencode_obj(s, writer, newobj, indent_level);
    1451                 :          0 :         _Py_LeaveRecursiveCall();
    1452                 :            : 
    1453                 :          0 :         Py_DECREF(newobj);
    1454         [ #  # ]:          0 :         if (rv) {
    1455                 :          0 :             Py_XDECREF(ident);
    1456                 :          0 :             return -1;
    1457                 :            :         }
    1458         [ #  # ]:          0 :         if (ident != NULL) {
    1459         [ #  # ]:          0 :             if (PyDict_DelItem(s->markers, ident)) {
    1460                 :          0 :                 Py_XDECREF(ident);
    1461                 :          0 :                 return -1;
    1462                 :            :             }
    1463                 :          0 :             Py_XDECREF(ident);
    1464                 :            :         }
    1465                 :          0 :         return rv;
    1466                 :            :     }
    1467                 :            : }
    1468                 :            : 
    1469                 :            : static int
    1470                 :          0 : encoder_encode_key_value(PyEncoderObject *s, _PyUnicodeWriter *writer, bool *first,
    1471                 :            :                          PyObject *key, PyObject *value, Py_ssize_t indent_level)
    1472                 :            : {
    1473                 :          0 :     PyObject *keystr = NULL;
    1474                 :            :     PyObject *encoded;
    1475                 :            : 
    1476         [ #  # ]:          0 :     if (PyUnicode_Check(key)) {
    1477                 :          0 :         keystr = Py_NewRef(key);
    1478                 :            :     }
    1479         [ #  # ]:          0 :     else if (PyFloat_Check(key)) {
    1480                 :          0 :         keystr = encoder_encode_float(s, key);
    1481                 :            :     }
    1482   [ #  #  #  #  :          0 :     else if (key == Py_True || key == Py_False || key == Py_None) {
                   #  # ]
    1483                 :            :                     /* This must come before the PyLong_Check because
    1484                 :            :                        True and False are also 1 and 0.*/
    1485                 :          0 :         keystr = _encoded_const(key);
    1486                 :            :     }
    1487         [ #  # ]:          0 :     else if (PyLong_Check(key)) {
    1488                 :          0 :         keystr = PyLong_Type.tp_repr(key);
    1489                 :            :     }
    1490         [ #  # ]:          0 :     else if (s->skipkeys) {
    1491                 :          0 :         return 0;
    1492                 :            :     }
    1493                 :            :     else {
    1494                 :          0 :         PyErr_Format(PyExc_TypeError,
    1495                 :            :                      "keys must be str, int, float, bool or None, "
    1496                 :          0 :                      "not %.100s", Py_TYPE(key)->tp_name);
    1497                 :          0 :         return -1;
    1498                 :            :     }
    1499                 :            : 
    1500         [ #  # ]:          0 :     if (keystr == NULL) {
    1501                 :          0 :         return -1;
    1502                 :            :     }
    1503                 :            : 
    1504         [ #  # ]:          0 :     if (*first) {
    1505                 :          0 :         *first = false;
    1506                 :            :     }
    1507                 :            :     else {
    1508         [ #  # ]:          0 :         if (_PyUnicodeWriter_WriteStr(writer, s->item_separator) < 0) {
    1509                 :          0 :             Py_DECREF(keystr);
    1510                 :          0 :             return -1;
    1511                 :            :         }
    1512                 :            :     }
    1513                 :            : 
    1514                 :          0 :     encoded = encoder_encode_string(s, keystr);
    1515                 :          0 :     Py_DECREF(keystr);
    1516         [ #  # ]:          0 :     if (encoded == NULL) {
    1517                 :          0 :         return -1;
    1518                 :            :     }
    1519                 :            : 
    1520         [ #  # ]:          0 :     if (_steal_accumulate(writer, encoded) < 0) {
    1521                 :          0 :         return -1;
    1522                 :            :     }
    1523         [ #  # ]:          0 :     if (_PyUnicodeWriter_WriteStr(writer, s->key_separator) < 0) {
    1524                 :          0 :         return -1;
    1525                 :            :     }
    1526         [ #  # ]:          0 :     if (encoder_listencode_obj(s, writer, value, indent_level) < 0) {
    1527                 :          0 :         return -1;
    1528                 :            :     }
    1529                 :          0 :     return 0;
    1530                 :            : }
    1531                 :            : 
    1532                 :            : static int
    1533                 :          0 : encoder_listencode_dict(PyEncoderObject *s, _PyUnicodeWriter *writer,
    1534                 :            :                         PyObject *dct, Py_ssize_t indent_level)
    1535                 :            : {
    1536                 :            :     /* Encode Python dict dct a JSON term */
    1537                 :          0 :     PyObject *ident = NULL;
    1538                 :          0 :     PyObject *items = NULL;
    1539                 :            :     PyObject *key, *value;
    1540                 :          0 :     bool first = true;
    1541                 :            : 
    1542         [ #  # ]:          0 :     if (PyDict_GET_SIZE(dct) == 0)  /* Fast path */
    1543                 :          0 :         return _PyUnicodeWriter_WriteASCIIString(writer, "{}", 2);
    1544                 :            : 
    1545         [ #  # ]:          0 :     if (s->markers != Py_None) {
    1546                 :            :         int has_key;
    1547                 :          0 :         ident = PyLong_FromVoidPtr(dct);
    1548         [ #  # ]:          0 :         if (ident == NULL)
    1549                 :          0 :             goto bail;
    1550                 :          0 :         has_key = PyDict_Contains(s->markers, ident);
    1551         [ #  # ]:          0 :         if (has_key) {
    1552         [ #  # ]:          0 :             if (has_key != -1)
    1553                 :          0 :                 PyErr_SetString(PyExc_ValueError, "Circular reference detected");
    1554                 :          0 :             goto bail;
    1555                 :            :         }
    1556         [ #  # ]:          0 :         if (PyDict_SetItem(s->markers, ident, dct)) {
    1557                 :          0 :             goto bail;
    1558                 :            :         }
    1559                 :            :     }
    1560                 :            : 
    1561         [ #  # ]:          0 :     if (_PyUnicodeWriter_WriteChar(writer, '{'))
    1562                 :          0 :         goto bail;
    1563                 :            : 
    1564         [ #  # ]:          0 :     if (s->indent != Py_None) {
    1565                 :            :         /* TODO: DOES NOT RUN */
    1566                 :          0 :         indent_level += 1;
    1567                 :            :         /*
    1568                 :            :             newline_indent = '\n' + (' ' * (_indent * _current_indent_level))
    1569                 :            :             separator = _item_separator + newline_indent
    1570                 :            :             buf += newline_indent
    1571                 :            :         */
    1572                 :            :     }
    1573                 :            : 
    1574   [ #  #  #  # ]:          0 :     if (s->sort_keys || !PyDict_CheckExact(dct)) {
    1575                 :          0 :         items = PyMapping_Items(dct);
    1576   [ #  #  #  #  :          0 :         if (items == NULL || (s->sort_keys && PyList_Sort(items) < 0))
                   #  # ]
    1577                 :          0 :             goto bail;
    1578                 :            : 
    1579         [ #  # ]:          0 :         for (Py_ssize_t  i = 0; i < PyList_GET_SIZE(items); i++) {
    1580                 :          0 :             PyObject *item = PyList_GET_ITEM(items, i);
    1581                 :            : 
    1582   [ #  #  #  # ]:          0 :             if (!PyTuple_Check(item) || PyTuple_GET_SIZE(item) != 2) {
    1583                 :          0 :                 PyErr_SetString(PyExc_ValueError, "items must return 2-tuples");
    1584                 :          0 :                 goto bail;
    1585                 :            :             }
    1586                 :            : 
    1587                 :          0 :             key = PyTuple_GET_ITEM(item, 0);
    1588                 :          0 :             value = PyTuple_GET_ITEM(item, 1);
    1589         [ #  # ]:          0 :             if (encoder_encode_key_value(s, writer, &first, key, value, indent_level) < 0)
    1590                 :          0 :                 goto bail;
    1591                 :            :         }
    1592         [ #  # ]:          0 :         Py_CLEAR(items);
    1593                 :            : 
    1594                 :            :     } else {
    1595                 :          0 :         Py_ssize_t pos = 0;
    1596         [ #  # ]:          0 :         while (PyDict_Next(dct, &pos, &key, &value)) {
    1597         [ #  # ]:          0 :             if (encoder_encode_key_value(s, writer, &first, key, value, indent_level) < 0)
    1598                 :          0 :                 goto bail;
    1599                 :            :         }
    1600                 :            :     }
    1601                 :            : 
    1602         [ #  # ]:          0 :     if (ident != NULL) {
    1603         [ #  # ]:          0 :         if (PyDict_DelItem(s->markers, ident))
    1604                 :          0 :             goto bail;
    1605         [ #  # ]:          0 :         Py_CLEAR(ident);
    1606                 :            :     }
    1607                 :            :     /* TODO DOES NOT RUN; dead code
    1608                 :            :     if (s->indent != Py_None) {
    1609                 :            :         indent_level -= 1;
    1610                 :            : 
    1611                 :            :         yield '\n' + (' ' * (_indent * _current_indent_level))
    1612                 :            :     }*/
    1613         [ #  # ]:          0 :     if (_PyUnicodeWriter_WriteChar(writer, '}'))
    1614                 :          0 :         goto bail;
    1615                 :          0 :     return 0;
    1616                 :            : 
    1617                 :          0 : bail:
    1618                 :          0 :     Py_XDECREF(items);
    1619                 :          0 :     Py_XDECREF(ident);
    1620                 :          0 :     return -1;
    1621                 :            : }
    1622                 :            : 
    1623                 :            : static int
    1624                 :          0 : encoder_listencode_list(PyEncoderObject *s, _PyUnicodeWriter *writer,
    1625                 :            :                         PyObject *seq, Py_ssize_t indent_level)
    1626                 :            : {
    1627                 :          0 :     PyObject *ident = NULL;
    1628                 :          0 :     PyObject *s_fast = NULL;
    1629                 :            :     Py_ssize_t i;
    1630                 :            : 
    1631                 :          0 :     ident = NULL;
    1632                 :          0 :     s_fast = PySequence_Fast(seq, "_iterencode_list needs a sequence");
    1633         [ #  # ]:          0 :     if (s_fast == NULL)
    1634                 :          0 :         return -1;
    1635   [ #  #  #  # ]:          0 :     if (PySequence_Fast_GET_SIZE(s_fast) == 0) {
    1636                 :          0 :         Py_DECREF(s_fast);
    1637                 :          0 :         return _PyUnicodeWriter_WriteASCIIString(writer, "[]", 2);
    1638                 :            :     }
    1639                 :            : 
    1640         [ #  # ]:          0 :     if (s->markers != Py_None) {
    1641                 :            :         int has_key;
    1642                 :          0 :         ident = PyLong_FromVoidPtr(seq);
    1643         [ #  # ]:          0 :         if (ident == NULL)
    1644                 :          0 :             goto bail;
    1645                 :          0 :         has_key = PyDict_Contains(s->markers, ident);
    1646         [ #  # ]:          0 :         if (has_key) {
    1647         [ #  # ]:          0 :             if (has_key != -1)
    1648                 :          0 :                 PyErr_SetString(PyExc_ValueError, "Circular reference detected");
    1649                 :          0 :             goto bail;
    1650                 :            :         }
    1651         [ #  # ]:          0 :         if (PyDict_SetItem(s->markers, ident, seq)) {
    1652                 :          0 :             goto bail;
    1653                 :            :         }
    1654                 :            :     }
    1655                 :            : 
    1656         [ #  # ]:          0 :     if (_PyUnicodeWriter_WriteChar(writer, '['))
    1657                 :          0 :         goto bail;
    1658         [ #  # ]:          0 :     if (s->indent != Py_None) {
    1659                 :            :         /* TODO: DOES NOT RUN */
    1660                 :          0 :         indent_level += 1;
    1661                 :            :         /*
    1662                 :            :             newline_indent = '\n' + (' ' * (_indent * _current_indent_level))
    1663                 :            :             separator = _item_separator + newline_indent
    1664                 :            :             buf += newline_indent
    1665                 :            :         */
    1666                 :            :     }
    1667   [ #  #  #  # ]:          0 :     for (i = 0; i < PySequence_Fast_GET_SIZE(s_fast); i++) {
    1668         [ #  # ]:          0 :         PyObject *obj = PySequence_Fast_GET_ITEM(s_fast, i);
    1669         [ #  # ]:          0 :         if (i) {
    1670         [ #  # ]:          0 :             if (_PyUnicodeWriter_WriteStr(writer, s->item_separator))
    1671                 :          0 :                 goto bail;
    1672                 :            :         }
    1673         [ #  # ]:          0 :         if (encoder_listencode_obj(s, writer, obj, indent_level))
    1674                 :          0 :             goto bail;
    1675                 :            :     }
    1676         [ #  # ]:          0 :     if (ident != NULL) {
    1677         [ #  # ]:          0 :         if (PyDict_DelItem(s->markers, ident))
    1678                 :          0 :             goto bail;
    1679         [ #  # ]:          0 :         Py_CLEAR(ident);
    1680                 :            :     }
    1681                 :            : 
    1682                 :            :     /* TODO: DOES NOT RUN
    1683                 :            :     if (s->indent != Py_None) {
    1684                 :            :         indent_level -= 1;
    1685                 :            : 
    1686                 :            :         yield '\n' + (' ' * (_indent * _current_indent_level))
    1687                 :            :     }*/
    1688         [ #  # ]:          0 :     if (_PyUnicodeWriter_WriteChar(writer, ']'))
    1689                 :          0 :         goto bail;
    1690                 :          0 :     Py_DECREF(s_fast);
    1691                 :          0 :     return 0;
    1692                 :            : 
    1693                 :          0 : bail:
    1694                 :          0 :     Py_XDECREF(ident);
    1695                 :          0 :     Py_DECREF(s_fast);
    1696                 :          0 :     return -1;
    1697                 :            : }
    1698                 :            : 
    1699                 :            : static void
    1700                 :          0 : encoder_dealloc(PyObject *self)
    1701                 :            : {
    1702                 :          0 :     PyTypeObject *tp = Py_TYPE(self);
    1703                 :            :     /* bpo-31095: UnTrack is needed before calling any callbacks */
    1704                 :          0 :     PyObject_GC_UnTrack(self);
    1705                 :          0 :     encoder_clear((PyEncoderObject *)self);
    1706                 :          0 :     tp->tp_free(self);
    1707                 :          0 :     Py_DECREF(tp);
    1708                 :          0 : }
    1709                 :            : 
    1710                 :            : static int
    1711                 :          0 : encoder_traverse(PyEncoderObject *self, visitproc visit, void *arg)
    1712                 :            : {
    1713   [ #  #  #  # ]:          0 :     Py_VISIT(Py_TYPE(self));
    1714   [ #  #  #  # ]:          0 :     Py_VISIT(self->markers);
    1715   [ #  #  #  # ]:          0 :     Py_VISIT(self->defaultfn);
    1716   [ #  #  #  # ]:          0 :     Py_VISIT(self->encoder);
    1717   [ #  #  #  # ]:          0 :     Py_VISIT(self->indent);
    1718   [ #  #  #  # ]:          0 :     Py_VISIT(self->key_separator);
    1719   [ #  #  #  # ]:          0 :     Py_VISIT(self->item_separator);
    1720                 :          0 :     return 0;
    1721                 :            : }
    1722                 :            : 
    1723                 :            : static int
    1724                 :          0 : encoder_clear(PyEncoderObject *self)
    1725                 :            : {
    1726                 :            :     /* Deallocate Encoder */
    1727         [ #  # ]:          0 :     Py_CLEAR(self->markers);
    1728         [ #  # ]:          0 :     Py_CLEAR(self->defaultfn);
    1729         [ #  # ]:          0 :     Py_CLEAR(self->encoder);
    1730         [ #  # ]:          0 :     Py_CLEAR(self->indent);
    1731         [ #  # ]:          0 :     Py_CLEAR(self->key_separator);
    1732         [ #  # ]:          0 :     Py_CLEAR(self->item_separator);
    1733                 :          0 :     return 0;
    1734                 :            : }
    1735                 :            : 
    1736                 :            : PyDoc_STRVAR(encoder_doc, "_iterencode(obj, _current_indent_level) -> iterable");
    1737                 :            : 
    1738                 :            : static PyType_Slot PyEncoderType_slots[] = {
    1739                 :            :     {Py_tp_doc, (void *)encoder_doc},
    1740                 :            :     {Py_tp_dealloc, encoder_dealloc},
    1741                 :            :     {Py_tp_call, encoder_call},
    1742                 :            :     {Py_tp_traverse, encoder_traverse},
    1743                 :            :     {Py_tp_clear, encoder_clear},
    1744                 :            :     {Py_tp_members, encoder_members},
    1745                 :            :     {Py_tp_new, encoder_new},
    1746                 :            :     {0, 0}
    1747                 :            : };
    1748                 :            : 
    1749                 :            : static PyType_Spec PyEncoderType_spec = {
    1750                 :            :     .name = "_json.Encoder",
    1751                 :            :     .basicsize = sizeof(PyEncoderObject),
    1752                 :            :     .itemsize = 0,
    1753                 :            :     .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
    1754                 :            :     .slots = PyEncoderType_slots
    1755                 :            : };
    1756                 :            : 
    1757                 :            : static PyMethodDef speedups_methods[] = {
    1758                 :            :     {"encode_basestring_ascii",
    1759                 :            :         (PyCFunction)py_encode_basestring_ascii,
    1760                 :            :         METH_O,
    1761                 :            :         pydoc_encode_basestring_ascii},
    1762                 :            :     {"encode_basestring",
    1763                 :            :         (PyCFunction)py_encode_basestring,
    1764                 :            :         METH_O,
    1765                 :            :         pydoc_encode_basestring},
    1766                 :            :     {"scanstring",
    1767                 :            :         (PyCFunction)py_scanstring,
    1768                 :            :         METH_VARARGS,
    1769                 :            :         pydoc_scanstring},
    1770                 :            :     {NULL, NULL, 0, NULL}
    1771                 :            : };
    1772                 :            : 
    1773                 :            : PyDoc_STRVAR(module_doc,
    1774                 :            : "json speedups\n");
    1775                 :            : 
    1776                 :            : static int
    1777                 :          1 : _json_exec(PyObject *module)
    1778                 :            : {
    1779                 :          1 :     PyObject *PyScannerType = PyType_FromSpec(&PyScannerType_spec);
    1780         [ -  + ]:          1 :     if (PyScannerType == NULL) {
    1781                 :          0 :         return -1;
    1782                 :            :     }
    1783                 :          1 :     int rc = PyModule_AddObjectRef(module, "make_scanner", PyScannerType);
    1784                 :          1 :     Py_DECREF(PyScannerType);
    1785         [ -  + ]:          1 :     if (rc < 0) {
    1786                 :          0 :         return -1;
    1787                 :            :     }
    1788                 :            : 
    1789                 :          1 :     PyObject *PyEncoderType = PyType_FromSpec(&PyEncoderType_spec);
    1790         [ -  + ]:          1 :     if (PyEncoderType == NULL) {
    1791                 :          0 :         return -1;
    1792                 :            :     }
    1793                 :          1 :     rc = PyModule_AddObjectRef(module, "make_encoder", PyEncoderType);
    1794                 :          1 :     Py_DECREF(PyEncoderType);
    1795         [ -  + ]:          1 :     if (rc < 0) {
    1796                 :          0 :         return -1;
    1797                 :            :     }
    1798                 :            : 
    1799                 :          1 :     return 0;
    1800                 :            : }
    1801                 :            : 
    1802                 :            : static PyModuleDef_Slot _json_slots[] = {
    1803                 :            :     {Py_mod_exec, _json_exec},
    1804                 :            :     {0, NULL}
    1805                 :            : };
    1806                 :            : 
    1807                 :            : static struct PyModuleDef jsonmodule = {
    1808                 :            :     .m_base = PyModuleDef_HEAD_INIT,
    1809                 :            :     .m_name = "_json",
    1810                 :            :     .m_doc = module_doc,
    1811                 :            :     .m_methods = speedups_methods,
    1812                 :            :     .m_slots = _json_slots,
    1813                 :            : };
    1814                 :            : 
    1815                 :            : PyMODINIT_FUNC
    1816                 :          1 : PyInit__json(void)
    1817                 :            : {
    1818                 :          1 :     return PyModuleDef_Init(&jsonmodule);
    1819                 :            : }

Generated by: LCOV version 1.14