summaryrefslogtreecommitdiffstats
path: root/Objects/dictobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/dictobject.c')
-rw-r--r--Objects/dictobject.c65
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.