summaryrefslogtreecommitdiffstats
path: root/Objects/dictobject.c
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2023-11-14 12:51:00 (GMT)
committerGitHub <noreply@github.com>2023-11-14 12:51:00 (GMT)
commit4f04172c9287c507f1426e02ddfc432f1f3ade54 (patch)
tree800ac400c3776336e1f52b49a0f10b4dae9af8c1 /Objects/dictobject.c
parentf44d6ff6e0c9eeb0bb246a3dd8f99d40b7050054 (diff)
downloadcpython-4f04172c9287c507f1426e02ddfc432f1f3ade54.zip
cpython-4f04172c9287c507f1426e02ddfc432f1f3ade54.tar.gz
cpython-4f04172c9287c507f1426e02ddfc432f1f3ade54.tar.bz2
gh-111262: Add PyDict_Pop() function (#112028)
_PyDict_Pop_KnownHash(): remove the default value and the return type becomes an int. Co-authored-by: Stefan Behnel <stefan_ml@behnel.de> Co-authored-by: Antoine Pitrou <pitrou@free.fr>
Diffstat (limited to 'Objects/dictobject.c')
-rw-r--r--Objects/dictobject.c119
1 files changed, 87 insertions, 32 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 719d438..d3d16c5 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -2226,64 +2226,119 @@ PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue)
return _PyDict_Next(op, ppos, pkey, pvalue, NULL);
}
+
/* Internal version of dict.pop(). */
-PyObject *
-_PyDict_Pop_KnownHash(PyObject *dict, PyObject *key, Py_hash_t hash, PyObject *deflt)
+int
+_PyDict_Pop_KnownHash(PyDictObject *mp, PyObject *key, Py_hash_t hash,
+ PyObject **result)
{
- Py_ssize_t ix;
- PyObject *old_value;
- PyDictObject *mp;
- PyInterpreterState *interp = _PyInterpreterState_GET();
-
- assert(PyDict_Check(dict));
- mp = (PyDictObject *)dict;
+ assert(PyDict_Check(mp));
if (mp->ma_used == 0) {
- if (deflt) {
- return Py_NewRef(deflt);
+ if (result) {
+ *result = NULL;
}
- _PyErr_SetKeyError(key);
- return NULL;
+ return 0;
}
- ix = _Py_dict_lookup(mp, key, hash, &old_value);
- if (ix == DKIX_ERROR)
- return NULL;
+
+ PyObject *old_value;
+ Py_ssize_t ix = _Py_dict_lookup(mp, key, hash, &old_value);
+ if (ix == DKIX_ERROR) {
+ if (result) {
+ *result = NULL;
+ }
+ return -1;
+ }
+
if (ix == DKIX_EMPTY || old_value == NULL) {
- if (deflt) {
- return Py_NewRef(deflt);
+ if (result) {
+ *result = NULL;
}
- _PyErr_SetKeyError(key);
- return NULL;
+ return 0;
}
+
assert(old_value != NULL);
+ PyInterpreterState *interp = _PyInterpreterState_GET();
uint64_t new_version = _PyDict_NotifyEvent(
interp, PyDict_EVENT_DELETED, mp, key, NULL);
delitem_common(mp, hash, ix, Py_NewRef(old_value), new_version);
ASSERT_CONSISTENT(mp);
- return old_value;
+ if (result) {
+ *result = old_value;
+ }
+ else {
+ Py_DECREF(old_value);
+ }
+ return 1;
}
-PyObject *
-_PyDict_Pop(PyObject *dict, PyObject *key, PyObject *deflt)
+
+int
+PyDict_Pop(PyObject *op, PyObject *key, PyObject **result)
{
- Py_hash_t hash;
+ if (!PyDict_Check(op)) {
+ if (result) {
+ *result = NULL;
+ }
+ PyErr_BadInternalCall();
+ return -1;
+ }
+ PyDictObject *dict = (PyDictObject *)op;
- if (((PyDictObject *)dict)->ma_used == 0) {
- if (deflt) {
- return Py_NewRef(deflt);
+ if (dict->ma_used == 0) {
+ if (result) {
+ *result = NULL;
}
- _PyErr_SetKeyError(key);
- return NULL;
+ return 0;
}
+
+ Py_hash_t hash;
if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
hash = PyObject_Hash(key);
- if (hash == -1)
- return NULL;
+ if (hash == -1) {
+ if (result) {
+ *result = NULL;
+ }
+ return -1;
+ }
+ }
+ return _PyDict_Pop_KnownHash(dict, key, hash, result);
+}
+
+
+int
+PyDict_PopString(PyObject *op, const char *key, PyObject **result)
+{
+ PyObject *key_obj = PyUnicode_FromString(key);
+ if (key_obj == NULL) {
+ if (result != NULL) {
+ *result = NULL;
+ }
+ return -1;
}
- return _PyDict_Pop_KnownHash(dict, key, hash, deflt);
+
+ int res = PyDict_Pop(op, key_obj, result);
+ Py_DECREF(key_obj);
+ return res;
}
+
+PyObject *
+_PyDict_Pop(PyObject *dict, PyObject *key, PyObject *default_value)
+{
+ PyObject *result;
+ if (PyDict_Pop(dict, key, &result) == 0) {
+ if (default_value != NULL) {
+ return Py_NewRef(default_value);
+ }
+ _PyErr_SetKeyError(key);
+ return NULL;
+ }
+ return result;
+}
+
+
/* Internal version of dict.from_keys(). It is subclass-friendly. */
PyObject *
_PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)