summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2000-12-12 22:02:18 (GMT)
committerGuido van Rossum <guido@python.org>2000-12-12 22:02:18 (GMT)
commitba6ab84e73bd5808cc9a4ed1ab58c752af6eef04 (patch)
tree85c7a556c62c8ce2a401b8c3d643920f502cdef2
parent968c36d81b840a01f8e0fe92283dc9126f29c16c (diff)
downloadcpython-ba6ab84e73bd5808cc9a4ed1ab58c752af6eef04.zip
cpython-ba6ab84e73bd5808cc9a4ed1ab58c752af6eef04.tar.gz
cpython-ba6ab84e73bd5808cc9a4ed1ab58c752af6eef04.tar.bz2
Add popitem() -- SF patch #102733.
-rw-r--r--Objects/dictobject.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 7be1c67..924928f 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -1132,6 +1132,58 @@ dict_clear(register dictobject *mp, PyObject *args)
return Py_None;
}
+static PyObject *
+dict_popitem(dictobject *mp, PyObject *args)
+{
+ int i = 0;
+ dictentry *ep;
+ PyObject *res;
+
+ if (!PyArg_NoArgs(args))
+ return NULL;
+ if (mp->ma_used == 0) {
+ PyErr_SetString(PyExc_KeyError,
+ "popitem(): dictionary is empty");
+ return NULL;
+ }
+ /* Set ep to "the first" dict entry with a value. We abuse the hash
+ * field of slot 0 to hold a search finger:
+ * If slot 0 has a value, use slot 0.
+ * Else slot 0 is being used to hold a search finger,
+ * and we use its hash value as the first index to look.
+ */
+ ep = &mp->ma_table[0];
+ if (ep->me_value == NULL) {
+ i = (int)ep->me_hash;
+ /* The hash field may be uninitialized trash, or it
+ * may be a real hash value, or it may be a legit
+ * search finger, or it may be a once-legit search
+ * finger that's out of bounds now because it
+ * wrapped around or the table shrunk -- simply
+ * make sure it's in bounds now.
+ */
+ if (i >= mp->ma_size || i < 1)
+ i = 1; /* skip slot 0 */
+ while ((ep = &mp->ma_table[i])->me_value == NULL) {
+ i++;
+ if (i >= mp->ma_size)
+ i = 1;
+ }
+ }
+ res = PyTuple_New(2);
+ if (res != NULL) {
+ PyTuple_SET_ITEM(res, 0, ep->me_key);
+ PyTuple_SET_ITEM(res, 1, ep->me_value);
+ Py_INCREF(dummy);
+ ep->me_key = dummy;
+ ep->me_value = NULL;
+ mp->ma_used--;
+ assert(mp->ma_table[0].me_value == NULL);
+ mp->ma_table[0].me_hash = i + 1; /* next place to start */
+ }
+ return res;
+}
+
static int
dict_traverse(PyObject *op, visitproc visit, void *arg)
{
@@ -1167,6 +1219,7 @@ static PyMethodDef mapp_methods[] = {
{"copy", (PyCFunction)dict_copy},
{"get", (PyCFunction)dict_get, METH_VARARGS},
{"setdefault", (PyCFunction)dict_setdefault, METH_VARARGS},
+ {"popitem", (PyCFunction)dict_popitem},
{NULL, NULL} /* sentinel */
};