Model set.pop() after dict.popitem().
This commit is contained in:
parent
6a694508ae
commit
67962ab1bb
@ -13,6 +13,10 @@ There are three kinds of slots in the table:
|
|||||||
1. Unused: key == NULL
|
1. Unused: key == NULL
|
||||||
2. Active: key != NULL and key != dummy
|
2. Active: key != NULL and key != dummy
|
||||||
3. Dummy: key == dummy
|
3. Dummy: key == dummy
|
||||||
|
|
||||||
|
Note: .pop() abuses the hash field of an Unused or Dummy slot to
|
||||||
|
hold a search finger. The hash field of Unused or Dummy slots has
|
||||||
|
no meaning otherwise.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PySet_MINSIZE 8
|
#define PySet_MINSIZE 8
|
||||||
|
@ -1508,24 +1508,42 @@ static PyObject *
|
|||||||
set_pop(PySetObject *so)
|
set_pop(PySetObject *so)
|
||||||
{
|
{
|
||||||
PyObject *key;
|
PyObject *key;
|
||||||
int pos = 0;
|
register setentry *entry;
|
||||||
int rv;
|
register int i = 0;
|
||||||
|
|
||||||
if (!set_next_internal(so, &pos, &key)) {
|
assert (PyAnySet_Check(so));
|
||||||
|
if (so->used == 0) {
|
||||||
PyErr_SetString(PyExc_KeyError, "pop from an empty set");
|
PyErr_SetString(PyExc_KeyError, "pop from an empty set");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
Py_INCREF(key);
|
|
||||||
|
|
||||||
rv = set_discard_internal(so, key);
|
/* Set entry to "the first" unused or dummy set entry. We abuse
|
||||||
if (rv == -1) {
|
* the hash field of slot 0 to hold a search finger:
|
||||||
Py_DECREF(key);
|
* If slot 0 has a value, use slot 0.
|
||||||
return NULL;
|
* Else slot 0 is being used to hold a search finger,
|
||||||
} else if (rv == DISCARD_NOTFOUND) {
|
* and we use its hash value as the first index to look.
|
||||||
Py_DECREF(key);
|
*/
|
||||||
PyErr_SetObject(PyExc_KeyError, key);
|
entry = &so->table[0];
|
||||||
return NULL;
|
if (entry->key == NULL || entry->key == dummy) {
|
||||||
|
i = (int)entry->hash;
|
||||||
|
/* The hash field 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 > so->mask || i < 1)
|
||||||
|
i = 1; /* skip slot 0 */
|
||||||
|
while ((entry = &so->table[i])->key == NULL || entry->key==dummy) {
|
||||||
|
i++;
|
||||||
|
if (i > so->mask)
|
||||||
|
i = 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
key = entry->key;
|
||||||
|
Py_INCREF(dummy);
|
||||||
|
entry->key = dummy;
|
||||||
|
so->used--;
|
||||||
|
so->table[0].hash = i + 1; /* next place to start */
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user