LCOV - code coverage report
Current view: top level - Modules - _json.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 799 922 86.7 %
Date: 2022-07-20 13:12:14 Functions: 34 34 100.0 %
Branches: 621 841 73.8 %

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

Generated by: LCOV version 1.14