bpo-30248: Convert boolean arguments only once in _json. (#1423)
Rather than saving the Python object and calling PyObject_IsTrue() every time when the boolean argument is used, call it only once and save C boolean value.
This commit is contained in:
parent
4a8bcdf79c
commit
ac5bbd43bc
|
@ -18,7 +18,7 @@ static PyTypeObject PyEncoderType;
|
|||
|
||||
typedef struct _PyScannerObject {
|
||||
PyObject_HEAD
|
||||
PyObject *strict;
|
||||
char strict;
|
||||
PyObject *object_hook;
|
||||
PyObject *object_pairs_hook;
|
||||
PyObject *parse_float;
|
||||
|
@ -28,7 +28,7 @@ typedef struct _PyScannerObject {
|
|||
} PyScannerObject;
|
||||
|
||||
static PyMemberDef scanner_members[] = {
|
||||
{"strict", T_OBJECT, offsetof(PyScannerObject, strict), READONLY, "strict"},
|
||||
{"strict", T_BOOL, offsetof(PyScannerObject, strict), READONLY, "strict"},
|
||||
{"object_hook", T_OBJECT, offsetof(PyScannerObject, object_hook), READONLY, "object_hook"},
|
||||
{"object_pairs_hook", T_OBJECT, offsetof(PyScannerObject, object_pairs_hook), READONLY},
|
||||
{"parse_float", T_OBJECT, offsetof(PyScannerObject, parse_float), READONLY, "parse_float"},
|
||||
|
@ -45,10 +45,10 @@ typedef struct _PyEncoderObject {
|
|||
PyObject *indent;
|
||||
PyObject *key_separator;
|
||||
PyObject *item_separator;
|
||||
PyObject *sort_keys;
|
||||
PyObject *skipkeys;
|
||||
PyCFunction fast_encode;
|
||||
char sort_keys;
|
||||
char skipkeys;
|
||||
int allow_nan;
|
||||
PyCFunction fast_encode;
|
||||
} PyEncoderObject;
|
||||
|
||||
static PyMemberDef encoder_members[] = {
|
||||
|
@ -58,8 +58,8 @@ static PyMemberDef encoder_members[] = {
|
|||
{"indent", T_OBJECT, offsetof(PyEncoderObject, indent), READONLY, "indent"},
|
||||
{"key_separator", T_OBJECT, offsetof(PyEncoderObject, key_separator), READONLY, "key_separator"},
|
||||
{"item_separator", T_OBJECT, offsetof(PyEncoderObject, item_separator), READONLY, "item_separator"},
|
||||
{"sort_keys", T_OBJECT, offsetof(PyEncoderObject, sort_keys), READONLY, "sort_keys"},
|
||||
{"skipkeys", T_OBJECT, offsetof(PyEncoderObject, skipkeys), READONLY, "skipkeys"},
|
||||
{"sort_keys", T_BOOL, offsetof(PyEncoderObject, sort_keys), READONLY, "sort_keys"},
|
||||
{"skipkeys", T_BOOL, offsetof(PyEncoderObject, skipkeys), READONLY, "skipkeys"},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
|
@ -666,7 +666,6 @@ scanner_traverse(PyObject *self, visitproc visit, void *arg)
|
|||
PyScannerObject *s;
|
||||
assert(PyScanner_Check(self));
|
||||
s = (PyScannerObject *)self;
|
||||
Py_VISIT(s->strict);
|
||||
Py_VISIT(s->object_hook);
|
||||
Py_VISIT(s->object_pairs_hook);
|
||||
Py_VISIT(s->parse_float);
|
||||
|
@ -681,7 +680,6 @@ scanner_clear(PyObject *self)
|
|||
PyScannerObject *s;
|
||||
assert(PyScanner_Check(self));
|
||||
s = (PyScannerObject *)self;
|
||||
Py_CLEAR(s->strict);
|
||||
Py_CLEAR(s->object_hook);
|
||||
Py_CLEAR(s->object_pairs_hook);
|
||||
Py_CLEAR(s->parse_float);
|
||||
|
@ -692,7 +690,8 @@ scanner_clear(PyObject *self)
|
|||
}
|
||||
|
||||
static PyObject *
|
||||
_parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
|
||||
_parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr)
|
||||
{
|
||||
/* Read a JSON object from PyUnicode pystr.
|
||||
idx is the index of the first character after the opening curly brace.
|
||||
*next_idx_ptr is a return-by-reference index to the first character after
|
||||
|
@ -706,13 +705,9 @@ _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ss
|
|||
PyObject *val = NULL;
|
||||
PyObject *rval = NULL;
|
||||
PyObject *key = NULL;
|
||||
int strict = PyObject_IsTrue(s->strict);
|
||||
int has_pairs_hook = (s->object_pairs_hook != Py_None);
|
||||
Py_ssize_t next_idx;
|
||||
|
||||
if (strict < 0)
|
||||
return NULL;
|
||||
|
||||
if (PyUnicode_READY(pystr) == -1)
|
||||
return NULL;
|
||||
|
||||
|
@ -740,7 +735,7 @@ _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ss
|
|||
raise_errmsg("Expecting property name enclosed in double quotes", pystr, idx);
|
||||
goto bail;
|
||||
}
|
||||
key = scanstring_unicode(pystr, idx + 1, strict, &next_idx);
|
||||
key = scanstring_unicode(pystr, idx + 1, s->strict, &next_idx);
|
||||
if (key == NULL)
|
||||
goto bail;
|
||||
memokey = PyDict_GetItem(s->memo, key);
|
||||
|
@ -1060,7 +1055,6 @@ scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_
|
|||
void *str;
|
||||
int kind;
|
||||
Py_ssize_t length;
|
||||
int strict;
|
||||
|
||||
if (PyUnicode_READY(pystr) == -1)
|
||||
return NULL;
|
||||
|
@ -1081,10 +1075,7 @@ scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_
|
|||
switch (PyUnicode_READ(kind, str, idx)) {
|
||||
case '"':
|
||||
/* string */
|
||||
strict = PyObject_IsTrue(s->strict);
|
||||
if (strict < 0)
|
||||
return NULL;
|
||||
return scanstring_unicode(pystr, idx + 1, strict, next_idx_ptr);
|
||||
return scanstring_unicode(pystr, idx + 1, s->strict, next_idx_ptr);
|
||||
case '{':
|
||||
/* object */
|
||||
if (Py_EnterRecursiveCall(" while decoding a JSON object "
|
||||
|
@ -1197,6 +1188,7 @@ scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
{
|
||||
PyScannerObject *s;
|
||||
PyObject *ctx;
|
||||
PyObject *strict;
|
||||
static char *kwlist[] = {"context", NULL};
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:make_scanner", kwlist, &ctx))
|
||||
|
@ -1212,8 +1204,12 @@ scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
goto bail;
|
||||
|
||||
/* All of these will fail "gracefully" so we don't need to verify them */
|
||||
s->strict = PyObject_GetAttrString(ctx, "strict");
|
||||
if (s->strict == NULL)
|
||||
strict = PyObject_GetAttrString(ctx, "strict");
|
||||
if (strict == NULL)
|
||||
goto bail;
|
||||
s->strict = PyObject_IsTrue(strict);
|
||||
Py_DECREF(strict);
|
||||
if (s->strict < 0)
|
||||
goto bail;
|
||||
s->object_hook = PyObject_GetAttrString(ctx, "object_hook");
|
||||
if (s->object_hook == NULL)
|
||||
|
@ -1290,10 +1286,10 @@ encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
|
||||
PyEncoderObject *s;
|
||||
PyObject *markers, *defaultfn, *encoder, *indent, *key_separator;
|
||||
PyObject *item_separator, *sort_keys, *skipkeys;
|
||||
int allow_nan;
|
||||
PyObject *item_separator;
|
||||
int sort_keys, skipkeys, allow_nan;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOUUOOp:make_encoder", kwlist,
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOUUppp:make_encoder", kwlist,
|
||||
&markers, &defaultfn, &encoder, &indent,
|
||||
&key_separator, &item_separator,
|
||||
&sort_keys, &skipkeys, &allow_nan))
|
||||
|
@ -1318,6 +1314,7 @@ encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
s->item_separator = item_separator;
|
||||
s->sort_keys = sort_keys;
|
||||
s->skipkeys = skipkeys;
|
||||
s->allow_nan = allow_nan;
|
||||
s->fast_encode = NULL;
|
||||
if (PyCFunction_Check(s->encoder)) {
|
||||
PyCFunction f = PyCFunction_GetFunction(s->encoder);
|
||||
|
@ -1326,7 +1323,6 @@ encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
s->fast_encode = f;
|
||||
}
|
||||
}
|
||||
s->allow_nan = allow_nan;
|
||||
|
||||
Py_INCREF(s->markers);
|
||||
Py_INCREF(s->defaultfn);
|
||||
|
@ -1334,8 +1330,6 @@ encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
Py_INCREF(s->indent);
|
||||
Py_INCREF(s->key_separator);
|
||||
Py_INCREF(s->item_separator);
|
||||
Py_INCREF(s->sort_keys);
|
||||
Py_INCREF(s->skipkeys);
|
||||
return (PyObject *)s;
|
||||
}
|
||||
|
||||
|
@ -1551,8 +1545,6 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc,
|
|||
PyObject *it = NULL;
|
||||
PyObject *items;
|
||||
PyObject *item = NULL;
|
||||
int skipkeys;
|
||||
int sortkeys;
|
||||
Py_ssize_t idx;
|
||||
|
||||
if (open_dict == NULL || close_dict == NULL || empty_dict == NULL) {
|
||||
|
@ -1597,16 +1589,12 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc,
|
|||
items = PyMapping_Items(dct);
|
||||
if (items == NULL)
|
||||
goto bail;
|
||||
sortkeys = PyObject_IsTrue(s->sort_keys);
|
||||
if (sortkeys < 0 || (sortkeys && PyList_Sort(items) < 0))
|
||||
if (s->sort_keys && PyList_Sort(items) < 0)
|
||||
goto bail;
|
||||
it = PyObject_GetIter(items);
|
||||
Py_DECREF(items);
|
||||
if (it == NULL)
|
||||
goto bail;
|
||||
skipkeys = PyObject_IsTrue(s->skipkeys);
|
||||
if (skipkeys < 0)
|
||||
goto bail;
|
||||
idx = 0;
|
||||
while ((item = PyIter_Next(it)) != NULL) {
|
||||
PyObject *encoded, *key, *value;
|
||||
|
@ -1637,7 +1625,7 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc,
|
|||
goto bail;
|
||||
}
|
||||
}
|
||||
else if (skipkeys) {
|
||||
else if (s->skipkeys) {
|
||||
Py_DECREF(item);
|
||||
continue;
|
||||
}
|
||||
|
@ -1805,8 +1793,6 @@ encoder_traverse(PyObject *self, visitproc visit, void *arg)
|
|||
Py_VISIT(s->indent);
|
||||
Py_VISIT(s->key_separator);
|
||||
Py_VISIT(s->item_separator);
|
||||
Py_VISIT(s->sort_keys);
|
||||
Py_VISIT(s->skipkeys);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1823,8 +1809,6 @@ encoder_clear(PyObject *self)
|
|||
Py_CLEAR(s->indent);
|
||||
Py_CLEAR(s->key_separator);
|
||||
Py_CLEAR(s->item_separator);
|
||||
Py_CLEAR(s->sort_keys);
|
||||
Py_CLEAR(s->skipkeys);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue