summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Ippolito <bob@redivi.com>2010-11-05 02:40:53 +0000
committerBob Ippolito <bob@redivi.com>2010-11-05 02:40:53 +0000
commitdb980b6827239e264cf9626e2c4a7947d4f746f2 (patch)
tree992fc6e1f52bade043cb013afd1b86b49d53635d
parent887d575bef8aea50d81d51c7c9c9eb9d1b98403e (diff)
downloadsimplejson-db980b6827239e264cf9626e2c4a7947d4f746f2.tar.gz
http://code.google.com/p/simplejson/issues/detail?id=86
git-svn-id: http://simplejson.googlecode.com/svn/trunk@240 a4795897-2c25-0410-b006-0d3caba88fa1
-rw-r--r--CHANGES.txt5
-rw-r--r--simplejson/_speedups.c69
-rw-r--r--simplejson/encoder.py2
-rw-r--r--simplejson/tests/test_encode_basestring_ascii.py5
4 files changed, 66 insertions, 15 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 6c81133..10f8218 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,8 @@
+Version 2.1.3 released XXXX-XX-XX
+
+* Support the sort_keys option in C encoding speedups
+ http://code.google.com/p/simplejson/issues/detail?id=86
+
Version 2.1.2 released 2010-11-01
* Correct wrong end when object_pairs_hook is used
diff --git a/simplejson/_speedups.c b/simplejson/_speedups.c
index 3f13f10..e43ae7c 100644
--- a/simplejson/_speedups.c
+++ b/simplejson/_speedups.c
@@ -2185,9 +2185,9 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
static PyObject *iteritems = NULL;
PyObject *kstr = NULL;
PyObject *ident = NULL;
- PyObject *key, *value;
PyObject *iter = NULL;
PyObject *item = NULL;
+ PyObject *items = NULL;
PyObject *encoded = NULL;
int skipkeys;
Py_ssize_t idx;
@@ -2232,22 +2232,61 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
*/
}
- /* TODO: C speedup not implemented for sort_keys */
+ if (PyObject_IsTrue(s->sort_keys)) {
+ /* First sort the keys then replace them with (key, value) tuples. */
+ Py_ssize_t i, nitems;
+ if (PyDict_CheckExact(dct))
+ items = PyDict_Keys(dct);
+ else
+ items = PyMapping_Keys(dct);
+ if (items == NULL)
+ goto bail;
+ if (!PyList_Check(items)) {
+ PyErr_SetString(PyExc_ValueError, "keys must return list");
+ goto bail;
+ }
+ if (PyList_Sort(items) < 0)
+ goto bail;
+ nitems = PyList_GET_SIZE(items);
+ for (i = 0; i < nitems; i++) {
+ PyObject *key, *value;
+ key = PyList_GET_ITEM(items, i);
+ value = PyDict_GetItem(dct, key);
+ item = PyTuple_Pack(2, key, value);
+ if (item == NULL)
+ goto bail;
+ PyList_SET_ITEM(items, i, item);
+ Py_DECREF(key);
+ }
+ }
+ else {
+ if (PyDict_CheckExact(dct))
+ items = PyDict_Items(dct);
+ else
+ items = PyMapping_Items(dct);
+ }
+ if (items == NULL)
+ goto bail;
+ iter = PyObject_GetIter(items);
+ Py_DECREF(items);
+ if (iter == NULL)
+ goto bail;
skipkeys = PyObject_IsTrue(s->skipkeys);
idx = 0;
- iter = PyObject_CallMethodObjArgs(dct, iteritems, NULL);
- if (iter == NULL)
- goto bail;
while ((item = PyIter_Next(iter))) {
-
- key = PyTuple_GetItem(item, 0);
+ PyObject *encoded, *key, *value;
+ if (!PyTuple_Check(item) || Py_SIZE(item) != 2) {
+ PyErr_SetString(PyExc_ValueError, "items must return 2-tuples");
+ goto bail;
+ }
+ key = PyTuple_GET_ITEM(item, 0);
if (key == NULL)
goto bail;
- value = PyTuple_GetItem(item, 1);
+ value = PyTuple_GET_ITEM(item, 1);
if (value == NULL)
goto bail;
-
+
encoded = PyDict_GetItem(s->key_memo, key);
if (encoded != NULL) {
Py_INCREF(encoded);
@@ -2261,13 +2300,15 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
if (kstr == NULL)
goto bail;
}
- else if (PyInt_Check(key) || PyLong_Check(key)) {
- kstr = PyObject_Str(key);
+ else if (key == Py_True || key == Py_False || key == Py_None) {
+ /* This must come before the PyInt_Check because
+ True and False are also 1 and 0.*/
+ kstr = _encoded_const(key);
if (kstr == NULL)
goto bail;
}
- else if (key == Py_True || key == Py_False || key == Py_None) {
- kstr = _encoded_const(key);
+ else if (PyInt_Check(key) || PyLong_Check(key)) {
+ kstr = PyObject_Str(key);
if (kstr == NULL)
goto bail;
}
@@ -2326,7 +2367,7 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
bail:
Py_XDECREF(encoded);
- Py_XDECREF(item);
+ Py_XDECREF(items);
Py_XDECREF(iter);
Py_XDECREF(kstr);
Py_XDECREF(ident);
diff --git a/simplejson/encoder.py b/simplejson/encoder.py
index a7f4eea..468d1bd 100644
--- a/simplejson/encoder.py
+++ b/simplejson/encoder.py
@@ -268,7 +268,7 @@ class JSONEncoder(object):
key_memo = {}
if (_one_shot and c_make_encoder is not None
- and self.indent is None and not self.sort_keys):
+ and self.indent is None):
_iterencode = c_make_encoder(
markers, self.default, _encoder, self.indent,
self.key_separator, self.item_separator, self.sort_keys,
diff --git a/simplejson/tests/test_encode_basestring_ascii.py b/simplejson/tests/test_encode_basestring_ascii.py
index b19631a..6c40961 100644
--- a/simplejson/tests/test_encode_basestring_ascii.py
+++ b/simplejson/tests/test_encode_basestring_ascii.py
@@ -39,3 +39,8 @@ class TestEncodeBaseStringAscii(TestCase):
# result, expect, fname, input_string))
self.assertEquals(result, expect,
'%r != %r for %s(%r)' % (result, expect, fname, input_string))
+
+ def test_sorted_dict(self):
+ items = [('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)]
+ s = simplejson.dumps(dict(items), sort_keys=True)
+ self.assertEqual(s, '{"five": 5, "four": 4, "one": 1, "three": 3, "two": 2}')