diff options
author | Dennis Sweeney <36520290+sweeneyde@users.noreply.github.com> | 2020-06-10 05:56:56 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-10 05:56:56 (GMT) |
commit | 07d81128124f2b574808e33267c38b104b42ae2a (patch) | |
tree | f099a32436e70dcab4083a302fbc2b6cb604cdfd /Objects/dictobject.c | |
parent | bae872f1fe9b3a0d3e3b8800a2ac8d6b440d6e4d (diff) | |
download | cpython-07d81128124f2b574808e33267c38b104b42ae2a.zip cpython-07d81128124f2b574808e33267c38b104b42ae2a.tar.gz cpython-07d81128124f2b574808e33267c38b104b42ae2a.tar.bz2 |
bpo-40889: Optimize dict.items() ^ dict.items() (GH-20718)
Diffstat (limited to 'Objects/dictobject.c')
-rw-r--r-- | Objects/dictobject.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c index c4d5da5..1bb8cfd 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -4409,9 +4409,99 @@ dictviews_or(PyObject* self, PyObject *other) return result; } +static PyObject * +dictitems_xor(PyObject *self, PyObject *other) +{ + assert(PyDictItems_Check(self)); + assert(PyDictItems_Check(other)); + PyObject *d1 = (PyObject *)((_PyDictViewObject *)self)->dv_dict; + PyObject *d2 = (PyObject *)((_PyDictViewObject *)other)->dv_dict; + + PyObject *temp_dict = PyDict_Copy(d1); + if (temp_dict == NULL) { + return NULL; + } + PyObject *result_set = PySet_New(NULL); + if (result_set == NULL) { + Py_CLEAR(temp_dict); + return NULL; + } + + PyObject *key = NULL, *val1 = NULL, *val2 = NULL; + Py_ssize_t pos = 0; + Py_hash_t hash; + + while (_PyDict_Next(d2, &pos, &key, &val2, &hash)) { + Py_INCREF(key); + Py_INCREF(val2); + val1 = _PyDict_GetItem_KnownHash(temp_dict, key, hash); + + int to_delete; + if (val1 == NULL) { + if (PyErr_Occurred()) { + goto error; + } + to_delete = 0; + } + else { + Py_INCREF(val1); + to_delete = PyObject_RichCompareBool(val1, val2, Py_EQ); + if (to_delete < 0) { + goto error; + } + } + + if (to_delete) { + if (_PyDict_DelItem_KnownHash(temp_dict, key, hash) < 0) { + goto error; + } + } + else { + PyObject *pair = PyTuple_Pack(2, key, val2); + if (pair == NULL) { + goto error; + } + if (PySet_Add(result_set, pair) < 0) { + Py_DECREF(pair); + goto error; + } + Py_DECREF(pair); + } + Py_DECREF(key); + Py_XDECREF(val1); + Py_DECREF(val2); + } + key = val1 = val2 = NULL; + + _Py_IDENTIFIER(items); + PyObject *remaining_pairs = _PyObject_CallMethodIdNoArgs(temp_dict, + &PyId_items); + if (remaining_pairs == NULL) { + goto error; + } + if (_PySet_Update(result_set, remaining_pairs) < 0) { + Py_DECREF(remaining_pairs); + goto error; + } + Py_DECREF(temp_dict); + Py_DECREF(remaining_pairs); + return result_set; + +error: + Py_XDECREF(temp_dict); + Py_XDECREF(result_set); + Py_XDECREF(key); + Py_XDECREF(val1); + Py_XDECREF(val2); + return NULL; +} + static PyObject* dictviews_xor(PyObject* self, PyObject *other) { + if (PyDictItems_Check(self) && PyDictItems_Check(other)) { + return dictitems_xor(self, other); + } PyObject *result = dictviews_to_set(self); if (result == NULL) { return NULL; |