1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
commit ac4637fbc4e72bd59f221d9bba19127820d21023
Author: Joakim Hamren <joakim.hamren@gmail.com>
Date: Sat Feb 4 16:36:14 2017 +0100
Following std json handling of None dict key
Previously a None dict item key would be outputted in JSON as "None".
To better align with the standard json module this was changed to output
"null". There's no proper representation of null object keys in JSON so
this is implementation specific but it seems more natural to follow
suit when it can be done without a significant performance hit.
Added and used branch prediction macros (LIKELY/UNLIKELY) as well.
diff --git a/lib/ultrajson.h b/lib/ultrajson.h
index 6c1dbc1..ca82a29 100644
--- a/lib/ultrajson.h
+++ b/lib/ultrajson.h
@@ -117,6 +117,14 @@ typedef uint32_t JSUINT32;
#define INLINE_PREFIX inline
+#ifdef __GNUC__
+#define LIKELY(x) __builtin_expect(!!(x), 1)
+#define UNLIKELY(x) __builtin_expect(!!(x), 0)
+#else
+#define LIKELY(x) (x)
+#define UNLIKELY(x) (x)
+#endif
+
typedef uint8_t JSUINT8;
typedef uint16_t JSUTF16;
typedef uint32_t JSUTF32;
diff --git a/python/objToJSON.c b/python/objToJSON.c
index adea2f6..41d4289 100644
--- a/python/objToJSON.c
+++ b/python/objToJSON.c
@@ -488,6 +488,12 @@ static int Dict_iterNext(JSOBJ obj, JSONTypeContext *tc)
else
if (!PyString_Check(GET_TC(tc)->itemName))
{
+ if (UNLIKELY(GET_TC(tc)->itemName == Py_None))
+ {
+ GET_TC(tc)->itemName = PyString_FromString("null");
+ return 1;
+ }
+
GET_TC(tc)->itemName = PyObject_Str(GET_TC(tc)->itemName);
#if PY_MAJOR_VERSION >= 3
itemNameTmp = GET_TC(tc)->itemName;
@@ -743,7 +749,7 @@ static void Object_beginTypeContext (JSOBJ _obj, JSONTypeContext *tc, JSONObject
return;
}
else
- if (PyString_Check(obj) && !PyHasAttrStringPreserveErr(obj, "__json__"))
+ if (PyString_Check(obj) && LIKELY(!PyHasAttrStringPreserveErr(obj, "__json__")))
{
PRINTMARK();
pc->PyTypeToJSON = PyStringToUTF8; tc->type = JT_UTF8;
@@ -837,7 +843,7 @@ ISITERABLE:
}
*/
- if (PyObject_HasAttrString(obj, "toDict"))
+ if (UNLIKELY(PyObject_HasAttrString(obj, "toDict")))
{
PyObject* toDictFunc = PyObject_GetAttrString(obj, "toDict");
PyObject* tuple = PyTuple_New(0);
@@ -863,7 +869,7 @@ ISITERABLE:
return;
}
else
- if (PyObject_HasAttrString(obj, "__json__"))
+ if (UNLIKELY(PyObject_HasAttrString(obj, "__json__")))
{
PyObject* toJSONFunc = PyObject_GetAttrString(obj, "__json__");
PyObject* tuple = PyTuple_New(0);
|