Commit ac5bbd43 authored by Serhiy Storchaka's avatar Serhiy Storchaka Committed by GitHub

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.
parent 4a8bcdf7
...@@ -18,7 +18,7 @@ static PyTypeObject PyEncoderType; ...@@ -18,7 +18,7 @@ static PyTypeObject PyEncoderType;
typedef struct _PyScannerObject { typedef struct _PyScannerObject {
PyObject_HEAD PyObject_HEAD
PyObject *strict; char strict;
PyObject *object_hook; PyObject *object_hook;
PyObject *object_pairs_hook; PyObject *object_pairs_hook;
PyObject *parse_float; PyObject *parse_float;
...@@ -28,7 +28,7 @@ typedef struct _PyScannerObject { ...@@ -28,7 +28,7 @@ typedef struct _PyScannerObject {
} PyScannerObject; } PyScannerObject;
static PyMemberDef scanner_members[] = { 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_hook", T_OBJECT, offsetof(PyScannerObject, object_hook), READONLY, "object_hook"},
{"object_pairs_hook", T_OBJECT, offsetof(PyScannerObject, object_pairs_hook), READONLY}, {"object_pairs_hook", T_OBJECT, offsetof(PyScannerObject, object_pairs_hook), READONLY},
{"parse_float", T_OBJECT, offsetof(PyScannerObject, parse_float), READONLY, "parse_float"}, {"parse_float", T_OBJECT, offsetof(PyScannerObject, parse_float), READONLY, "parse_float"},
...@@ -45,10 +45,10 @@ typedef struct _PyEncoderObject { ...@@ -45,10 +45,10 @@ typedef struct _PyEncoderObject {
PyObject *indent; PyObject *indent;
PyObject *key_separator; PyObject *key_separator;
PyObject *item_separator; PyObject *item_separator;
PyObject *sort_keys; char sort_keys;
PyObject *skipkeys; char skipkeys;
PyCFunction fast_encode;
int allow_nan; int allow_nan;
PyCFunction fast_encode;
} PyEncoderObject; } PyEncoderObject;
static PyMemberDef encoder_members[] = { static PyMemberDef encoder_members[] = {
...@@ -58,8 +58,8 @@ static PyMemberDef encoder_members[] = { ...@@ -58,8 +58,8 @@ static PyMemberDef encoder_members[] = {
{"indent", T_OBJECT, offsetof(PyEncoderObject, indent), READONLY, "indent"}, {"indent", T_OBJECT, offsetof(PyEncoderObject, indent), READONLY, "indent"},
{"key_separator", T_OBJECT, offsetof(PyEncoderObject, key_separator), READONLY, "key_separator"}, {"key_separator", T_OBJECT, offsetof(PyEncoderObject, key_separator), READONLY, "key_separator"},
{"item_separator", T_OBJECT, offsetof(PyEncoderObject, item_separator), READONLY, "item_separator"}, {"item_separator", T_OBJECT, offsetof(PyEncoderObject, item_separator), READONLY, "item_separator"},
{"sort_keys", T_OBJECT, offsetof(PyEncoderObject, sort_keys), READONLY, "sort_keys"}, {"sort_keys", T_BOOL, offsetof(PyEncoderObject, sort_keys), READONLY, "sort_keys"},
{"skipkeys", T_OBJECT, offsetof(PyEncoderObject, skipkeys), READONLY, "skipkeys"}, {"skipkeys", T_BOOL, offsetof(PyEncoderObject, skipkeys), READONLY, "skipkeys"},
{NULL} {NULL}
}; };
...@@ -666,7 +666,6 @@ scanner_traverse(PyObject *self, visitproc visit, void *arg) ...@@ -666,7 +666,6 @@ scanner_traverse(PyObject *self, visitproc visit, void *arg)
PyScannerObject *s; PyScannerObject *s;
assert(PyScanner_Check(self)); assert(PyScanner_Check(self));
s = (PyScannerObject *)self; s = (PyScannerObject *)self;
Py_VISIT(s->strict);
Py_VISIT(s->object_hook); Py_VISIT(s->object_hook);
Py_VISIT(s->object_pairs_hook); Py_VISIT(s->object_pairs_hook);
Py_VISIT(s->parse_float); Py_VISIT(s->parse_float);
...@@ -681,7 +680,6 @@ scanner_clear(PyObject *self) ...@@ -681,7 +680,6 @@ scanner_clear(PyObject *self)
PyScannerObject *s; PyScannerObject *s;
assert(PyScanner_Check(self)); assert(PyScanner_Check(self));
s = (PyScannerObject *)self; s = (PyScannerObject *)self;
Py_CLEAR(s->strict);
Py_CLEAR(s->object_hook); Py_CLEAR(s->object_hook);
Py_CLEAR(s->object_pairs_hook); Py_CLEAR(s->object_pairs_hook);
Py_CLEAR(s->parse_float); Py_CLEAR(s->parse_float);
...@@ -692,7 +690,8 @@ scanner_clear(PyObject *self) ...@@ -692,7 +690,8 @@ scanner_clear(PyObject *self)
} }
static PyObject * 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. /* Read a JSON object from PyUnicode pystr.
idx is the index of the first character after the opening curly brace. 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 *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 ...@@ -706,13 +705,9 @@ _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ss
PyObject *val = NULL; PyObject *val = NULL;
PyObject *rval = NULL; PyObject *rval = NULL;
PyObject *key = NULL; PyObject *key = NULL;
int strict = PyObject_IsTrue(s->strict);
int has_pairs_hook = (s->object_pairs_hook != Py_None); int has_pairs_hook = (s->object_pairs_hook != Py_None);
Py_ssize_t next_idx; Py_ssize_t next_idx;
if (strict < 0)
return NULL;
if (PyUnicode_READY(pystr) == -1) if (PyUnicode_READY(pystr) == -1)
return NULL; return NULL;
...@@ -740,7 +735,7 @@ _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ss ...@@ -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); raise_errmsg("Expecting property name enclosed in double quotes", pystr, idx);
goto bail; goto bail;
} }
key = scanstring_unicode(pystr, idx + 1, strict, &next_idx); key = scanstring_unicode(pystr, idx + 1, s->strict, &next_idx);
if (key == NULL) if (key == NULL)
goto bail; goto bail;
memokey = PyDict_GetItem(s->memo, key); memokey = PyDict_GetItem(s->memo, key);
...@@ -1060,7 +1055,6 @@ scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_ ...@@ -1060,7 +1055,6 @@ scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_
void *str; void *str;
int kind; int kind;
Py_ssize_t length; Py_ssize_t length;
int strict;
if (PyUnicode_READY(pystr) == -1) if (PyUnicode_READY(pystr) == -1)
return NULL; return NULL;
...@@ -1081,10 +1075,7 @@ scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_ ...@@ -1081,10 +1075,7 @@ scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_
switch (PyUnicode_READ(kind, str, idx)) { switch (PyUnicode_READ(kind, str, idx)) {
case '"': case '"':
/* string */ /* string */
strict = PyObject_IsTrue(s->strict); return scanstring_unicode(pystr, idx + 1, s->strict, next_idx_ptr);
if (strict < 0)
return NULL;
return scanstring_unicode(pystr, idx + 1, strict, next_idx_ptr);
case '{': case '{':
/* object */ /* object */
if (Py_EnterRecursiveCall(" while decoding a JSON object " if (Py_EnterRecursiveCall(" while decoding a JSON object "
...@@ -1197,6 +1188,7 @@ scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds) ...@@ -1197,6 +1188,7 @@ scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
PyScannerObject *s; PyScannerObject *s;
PyObject *ctx; PyObject *ctx;
PyObject *strict;
static char *kwlist[] = {"context", NULL}; static char *kwlist[] = {"context", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:make_scanner", kwlist, &ctx)) if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:make_scanner", kwlist, &ctx))
...@@ -1212,8 +1204,12 @@ scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds) ...@@ -1212,8 +1204,12 @@ scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
goto bail; goto bail;
/* All of these will fail "gracefully" so we don't need to verify them */ /* All of these will fail "gracefully" so we don't need to verify them */
s->strict = PyObject_GetAttrString(ctx, "strict"); strict = PyObject_GetAttrString(ctx, "strict");
if (s->strict == NULL) if (strict == NULL)
goto bail;
s->strict = PyObject_IsTrue(strict);
Py_DECREF(strict);
if (s->strict < 0)
goto bail; goto bail;
s->object_hook = PyObject_GetAttrString(ctx, "object_hook"); s->object_hook = PyObject_GetAttrString(ctx, "object_hook");
if (s->object_hook == NULL) if (s->object_hook == NULL)
...@@ -1290,10 +1286,10 @@ encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds) ...@@ -1290,10 +1286,10 @@ encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
PyEncoderObject *s; PyEncoderObject *s;
PyObject *markers, *defaultfn, *encoder, *indent, *key_separator; PyObject *markers, *defaultfn, *encoder, *indent, *key_separator;
PyObject *item_separator, *sort_keys, *skipkeys; PyObject *item_separator;
int allow_nan; 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, &markers, &defaultfn, &encoder, &indent,
&key_separator, &item_separator, &key_separator, &item_separator,
&sort_keys, &skipkeys, &allow_nan)) &sort_keys, &skipkeys, &allow_nan))
...@@ -1318,6 +1314,7 @@ encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds) ...@@ -1318,6 +1314,7 @@ encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
s->item_separator = item_separator; s->item_separator = item_separator;
s->sort_keys = sort_keys; s->sort_keys = sort_keys;
s->skipkeys = skipkeys; s->skipkeys = skipkeys;
s->allow_nan = allow_nan;
s->fast_encode = NULL; s->fast_encode = NULL;
if (PyCFunction_Check(s->encoder)) { if (PyCFunction_Check(s->encoder)) {
PyCFunction f = PyCFunction_GetFunction(s->encoder); PyCFunction f = PyCFunction_GetFunction(s->encoder);
...@@ -1326,7 +1323,6 @@ encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds) ...@@ -1326,7 +1323,6 @@ encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
s->fast_encode = f; s->fast_encode = f;
} }
} }
s->allow_nan = allow_nan;
Py_INCREF(s->markers); Py_INCREF(s->markers);
Py_INCREF(s->defaultfn); Py_INCREF(s->defaultfn);
...@@ -1334,8 +1330,6 @@ encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds) ...@@ -1334,8 +1330,6 @@ encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Py_INCREF(s->indent); Py_INCREF(s->indent);
Py_INCREF(s->key_separator); Py_INCREF(s->key_separator);
Py_INCREF(s->item_separator); Py_INCREF(s->item_separator);
Py_INCREF(s->sort_keys);
Py_INCREF(s->skipkeys);
return (PyObject *)s; return (PyObject *)s;
} }
...@@ -1551,8 +1545,6 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc, ...@@ -1551,8 +1545,6 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc,
PyObject *it = NULL; PyObject *it = NULL;
PyObject *items; PyObject *items;
PyObject *item = NULL; PyObject *item = NULL;
int skipkeys;
int sortkeys;
Py_ssize_t idx; Py_ssize_t idx;
if (open_dict == NULL || close_dict == NULL || empty_dict == NULL) { if (open_dict == NULL || close_dict == NULL || empty_dict == NULL) {
...@@ -1597,16 +1589,12 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc, ...@@ -1597,16 +1589,12 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc,
items = PyMapping_Items(dct); items = PyMapping_Items(dct);
if (items == NULL) if (items == NULL)
goto bail; goto bail;
sortkeys = PyObject_IsTrue(s->sort_keys); if (s->sort_keys && PyList_Sort(items) < 0)
if (sortkeys < 0 || (sortkeys && PyList_Sort(items) < 0))
goto bail; goto bail;
it = PyObject_GetIter(items); it = PyObject_GetIter(items);
Py_DECREF(items); Py_DECREF(items);
if (it == NULL) if (it == NULL)
goto bail; goto bail;
skipkeys = PyObject_IsTrue(s->skipkeys);
if (skipkeys < 0)
goto bail;
idx = 0; idx = 0;
while ((item = PyIter_Next(it)) != NULL) { while ((item = PyIter_Next(it)) != NULL) {
PyObject *encoded, *key, *value; PyObject *encoded, *key, *value;
...@@ -1637,7 +1625,7 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc, ...@@ -1637,7 +1625,7 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc,
goto bail; goto bail;
} }
} }
else if (skipkeys) { else if (s->skipkeys) {
Py_DECREF(item); Py_DECREF(item);
continue; continue;
} }
...@@ -1805,8 +1793,6 @@ encoder_traverse(PyObject *self, visitproc visit, void *arg) ...@@ -1805,8 +1793,6 @@ encoder_traverse(PyObject *self, visitproc visit, void *arg)
Py_VISIT(s->indent); Py_VISIT(s->indent);
Py_VISIT(s->key_separator); Py_VISIT(s->key_separator);
Py_VISIT(s->item_separator); Py_VISIT(s->item_separator);
Py_VISIT(s->sort_keys);
Py_VISIT(s->skipkeys);
return 0; return 0;
} }
...@@ -1823,8 +1809,6 @@ encoder_clear(PyObject *self) ...@@ -1823,8 +1809,6 @@ encoder_clear(PyObject *self)
Py_CLEAR(s->indent); Py_CLEAR(s->indent);
Py_CLEAR(s->key_separator); Py_CLEAR(s->key_separator);
Py_CLEAR(s->item_separator); Py_CLEAR(s->item_separator);
Py_CLEAR(s->sort_keys);
Py_CLEAR(s->skipkeys);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment