diff options
author | Bob Ippolito <bob@redivi.com> | 2010-11-05 02:40:53 +0000 |
---|---|---|
committer | Bob Ippolito <bob@redivi.com> | 2010-11-05 02:40:53 +0000 |
commit | db980b6827239e264cf9626e2c4a7947d4f746f2 (patch) | |
tree | 992fc6e1f52bade043cb013afd1b86b49d53635d | |
parent | 887d575bef8aea50d81d51c7c9c9eb9d1b98403e (diff) | |
download | simplejson-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.txt | 5 | ||||
-rw-r--r-- | simplejson/_speedups.c | 69 | ||||
-rw-r--r-- | simplejson/encoder.py | 2 | ||||
-rw-r--r-- | simplejson/tests/test_encode_basestring_ascii.py | 5 |
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}') |