| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 6a69450 commit 67962ab
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -13,6 +13,10 @@ There are three kinds of slots in the table: | |||
| 13 | 13 | 1. Unused: key == NULL | |
| 14 | 14 | 2. Active: key != NULL and key != dummy | |
| 15 | 15 | 3. Dummy: key == dummy | |
| 16 | + | ||
| 17 | + Note: .pop() abuses the hash field of an Unused or Dummy slot to | ||
| 18 | + hold a search finger. The hash field of Unused or Dummy slots has | ||
| 19 | + no meaning otherwise. | ||
| 16 | 20 | */ | |
| 17 | 21 | ||
| 18 | 22 | #define PySet_MINSIZE 8 | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1508,24 +1508,42 @@ static PyObject * | |||
| 1508 | 1508 | set_pop(PySetObject *so) | |
| 1509 | 1509 | { | |
| 1510 | 1510 | PyObject *key; | |
| 1511 | - int pos = 0; | ||
| 1512 | - int rv; | ||
| 1511 | + register setentry *entry; | ||
| 1512 | + register int i = 0; | ||
| 1513 | 1513 | ||
| 1514 | - if (!set_next_internal(so, &pos, &key)) { | ||
| 1514 | + assert (PyAnySet_Check(so)); | ||
| 1515 | + if (so->used == 0) { | ||
| 1515 | 1516 | PyErr_SetString(PyExc_KeyError, "pop from an empty set"); | |
| 1516 | 1517 | return NULL; | |
| 1517 | 1518 | } | |
| 1518 | - Py_INCREF(key); | ||
| 1519 | 1519 | ||
| 1520 | - rv = set_discard_internal(so, key); | ||
| 1521 | - if (rv == -1) { | ||
| 1522 | - Py_DECREF(key); | ||
| 1523 | - return NULL; | ||
| 1524 | - } else if (rv == DISCARD_NOTFOUND) { | ||
| 1525 | - Py_DECREF(key); | ||
| 1526 | - PyErr_SetObject(PyExc_KeyError, key); | ||
| 1527 | - return NULL; | ||
| 1520 | + /* Set entry to "the first" unused or dummy set entry. We abuse | ||
| 1521 | + * the hash field of slot 0 to hold a search finger: | ||
| 1522 | + * If slot 0 has a value, use slot 0. | ||
| 1523 | + * Else slot 0 is being used to hold a search finger, | ||
| 1524 | + * and we use its hash value as the first index to look. | ||
| 1525 | + */ | ||
| 1526 | + entry = &so->table[0]; | ||
| 1527 | + if (entry->key == NULL || entry->key == dummy) { | ||
| 1528 | + i = (int)entry->hash; | ||
| 1529 | + /* The hash field may be a real hash value, or it may be a | ||
| 1530 | + * legit search finger, or it may be a once-legit search | ||
| 1531 | + * finger that's out of bounds now because it wrapped around | ||
| 1532 | + * or the table shrunk -- simply make sure it's in bounds now. | ||
| 1533 | + */ | ||
| 1534 | + if (i > so->mask || i < 1) | ||
| 1535 | + i = 1; /* skip slot 0 */ | ||
| 1536 | + while ((entry = &so->table[i])->key == NULL || entry->key==dummy) { | ||
| 1537 | + i++; | ||
| 1538 | + if (i > so->mask) | ||
| 1539 | + i = 1; | ||
| 1540 | + } | ||
| 1528 | 1541 | } | |
| 1542 | + key = entry->key; | ||
| 1543 | + Py_INCREF(dummy); | ||
| 1544 | + entry->key = dummy; | ||
| 1545 | + so->used--; | ||
| 1546 | + so->table[0].hash = i + 1; /* next place to start */ | ||
| 1529 | 1547 | return key; | |
| 1530 | 1548 | } | |
| 1531 | 1549 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments