diff options
Diffstat (limited to 'Objects/dictobject.c')
-rw-r--r-- | Objects/dictobject.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 6c3fc62..8e74962 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1437,6 +1437,71 @@ PyDict_GetItem(PyObject *op, PyObject *key) return value; } +Py_ssize_t +_PyDict_GetItemHint(PyDictObject *mp, PyObject *key, + Py_ssize_t hint, PyObject **value) +{ + Py_hash_t hash; + PyThreadState *tstate; + + assert(*value == NULL); + assert(PyDict_CheckExact((PyObject*)mp)); + assert(PyUnicode_CheckExact(key)); + + if (hint >= 0 && hint < _PyDict_KeysSize(mp->ma_keys)) { + PyObject *res = NULL; + + PyDictKeyEntry *ep = DK_ENTRIES(mp->ma_keys) + (size_t)hint; + if (ep->me_key == key) { + if (mp->ma_keys->dk_lookup == lookdict_split) { + assert(mp->ma_values != NULL); + res = mp->ma_values[(size_t)hint]; + } + else { + res = ep->me_value; + } + if (res != NULL) { + *value = res; + return hint; + } + } + } + + if ((hash = ((PyASCIIObject *) key)->hash) == -1) + { + hash = PyObject_Hash(key); + if (hash == -1) { + PyErr_Clear(); + return -1; + } + } + + // We can arrive here with a NULL tstate during initialization: try + // running "python -Wi" for an example related to string interning + tstate = _PyThreadState_UncheckedGet(); + Py_ssize_t ix = 0; + if (tstate != NULL && tstate->curexc_type != NULL) { + /* preserve the existing exception */ + PyObject *err_type, *err_value, *err_tb; + PyErr_Fetch(&err_type, &err_value, &err_tb); + ix = (mp->ma_keys->dk_lookup)(mp, key, hash, value); + /* ignore errors */ + PyErr_Restore(err_type, err_value, err_tb); + if (ix < 0) { + return -1; + } + } + else { + ix = (mp->ma_keys->dk_lookup)(mp, key, hash, value); + if (ix < 0) { + PyErr_Clear(); + return -1; + } + } + + return ix; +} + /* Same as PyDict_GetItemWithError() but with hash supplied by caller. This returns NULL *with* an exception set if an exception occurred. It returns NULL *without* an exception set if the key wasn't present. |