=== modified file 'Objects/setobject.c' --- Objects/setobject.c 2008-02-12 19:05:36 +0000 +++ Objects/setobject.c 2008-05-13 05:42:22 +0000 @@ -10,6 +10,8 @@ #include "Python.h" #include "structmember.h" +static long set_hash_common(PyObject *self); + /* Set a key error with the specified argument, wrapping it in a * tuple automatically so that tuple keys are not unpacked as the * exception arguments. */ @@ -417,7 +419,7 @@ } static int -set_discard_key(PySetObject *so, PyObject *key) +set_discard_key(PySetObject *so, PyObject *key, int treat_set_key_as_frozen) { register long hash; register setentry *entry; @@ -426,7 +428,10 @@ assert (PyAnySet_Check(so)); if (!PyString_CheckExact(key) || (hash = ((PyStringObject *) key)->ob_shash) == -1) { - hash = PyObject_Hash(key); + if (treat_set_key_as_frozen && PySet_Check(key)) + hash = set_hash_common(key); + else + hash = PyObject_Hash(key); if (hash == -1) return -1; } @@ -676,14 +681,17 @@ } static int -set_contains_key(PySetObject *so, PyObject *key) +set_contains_key(PySetObject *so, PyObject *key, int treat_set_key_as_frozen) { long hash; setentry *entry; if (!PyString_CheckExact(key) || (hash = ((PyStringObject *) key)->ob_shash) == -1) { - hash = PyObject_Hash(key); + if (treat_set_key_as_frozen && PySet_Check(key)) + hash = set_hash_common(key); + else + hash = PyObject_Hash(key); if (hash == -1) return -1; } @@ -764,16 +772,13 @@ } static long -frozenset_hash(PyObject *self) +set_hash_common(PyObject *self) { PySetObject *so = (PySetObject *)self; long h, hash = 1927868237L; setentry *entry; Py_ssize_t pos = 0; - if (so->hash != -1) - return so->hash; - hash *= PySet_GET_SIZE(self) + 1; while (set_next(so, &pos, &entry)) { /* Work to increase the bit dispersion for closely spaced hash @@ -787,6 +792,20 @@ hash = hash * 69069L + 907133923L; if (hash == -1) hash = 590923713L; + return hash; +} + +static long +frozenset_hash(PyObject *self) +{ + PySetObject *so = (PySetObject *)self; + long hash; + + if (so->hash != -1) + return so->hash; + + hash = set_hash_common(self); + so->hash = hash; return hash; } @@ -1080,10 +1099,8 @@ t=set(a); a.clear(); a.update(b); b.clear(); b.update(t); del t The function always succeeds and it leaves both objects in a stable state. - Useful for creating temporary frozensets from sets for membership testing - in __contains__(), discard(), and remove(). Also useful for operations - that update in-place (by allowing an intermediate result to be swapped - into one of the original inputs). + Useful for operations that update in-place (by allowing an intermediate + result to be swapped into one of the original inputs). */ static void @@ -1093,7 +1110,6 @@ setentry *u; setentry *(*f)(PySetObject *so, PyObject *key, long hash); setentry tab[PySet_MINSIZE]; - long h; t = a->fill; a->fill = b->fill; b->fill = t; t = a->used; a->used = b->used; b->used = t; @@ -1115,13 +1131,8 @@ memcpy(b->smalltable, tab, sizeof(tab)); } - if (PyType_IsSubtype(Py_TYPE(a), &PyFrozenSet_Type) && - PyType_IsSubtype(Py_TYPE(b), &PyFrozenSet_Type)) { - h = a->hash; a->hash = b->hash; b->hash = h; - } else { - a->hash = -1; - b->hash = -1; - } + assert(!PyFrozenSet_Check(a) && !PyFrozenSet_Check(b)); + assert(a->hash == -1 && b->hash == -1); } static PyObject * @@ -1292,6 +1303,8 @@ tmp = set_intersection(so, other); if (tmp == NULL) return NULL; + /* XXX FIXME we want to consume tmp here, not swap with it. tmp + * should always end up empty. */ set_swap_bodies(so, (PySetObject *)tmp); Py_DECREF(tmp); Py_RETURN_NONE; @@ -1414,7 +1427,7 @@ return -1; while ((key = PyIter_Next(it)) != NULL) { - if (set_discard_key(so, key) == -1) { + if (set_discard_key(so, key, 0) == -1) { Py_DECREF(it); Py_DECREF(key); return -1; @@ -1750,23 +1763,7 @@ static int set_contains(PySetObject *so, PyObject *key) { - PyObject *tmpkey; - int rv; - - rv = set_contains_key(so, key); - if (rv == -1) { - if (!PyAnySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)) - return -1; - PyErr_Clear(); - tmpkey = make_new_set(&PyFrozenSet_Type, NULL); - if (tmpkey == NULL) - return -1; - set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key); - rv = set_contains(so, tmpkey); - set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key); - Py_DECREF(tmpkey); - } - return rv; + return set_contains_key(so, key, 1); } static PyObject * @@ -1785,23 +1782,12 @@ static PyObject * set_remove(PySetObject *so, PyObject *key) { - PyObject *tmpkey, *result; int rv; - rv = set_discard_key(so, key); - if (rv == -1) { - if (!PyAnySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)) - return NULL; - PyErr_Clear(); - tmpkey = make_new_set(&PyFrozenSet_Type, NULL); - if (tmpkey == NULL) - return NULL; - set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key); - result = set_remove(so, tmpkey); - set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key); - Py_DECREF(tmpkey); - return result; - } else if (rv == DISCARD_NOTFOUND) { + rv = set_discard_key(so, key, 1); + if (rv == -1) + return NULL; + else if (rv == DISCARD_NOTFOUND) { set_key_error(key); return NULL; } @@ -1816,23 +1802,11 @@ static PyObject * set_discard(PySetObject *so, PyObject *key) { - PyObject *tmpkey, *result; int rv; - rv = set_discard_key(so, key); - if (rv == -1) { - if (!PyAnySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)) - return NULL; - PyErr_Clear(); - tmpkey = make_new_set(&PyFrozenSet_Type, NULL); - if (tmpkey == NULL) - return NULL; - set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key); - result = set_discard(so, tmpkey); - set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key); - Py_DECREF(tmpkey); - return result; - } + rv = set_discard_key(so, key, 1); + if (rv == -1) + return NULL; Py_RETURN_NONE; } @@ -2174,7 +2148,7 @@ PyErr_BadInternalCall(); return -1; } - return set_contains_key((PySetObject *)anyset, key); + return set_contains_key((PySetObject *)anyset, key, 0); } int @@ -2184,7 +2158,7 @@ PyErr_BadInternalCall(); return -1; } - return set_discard_key((PySetObject *)set, key); + return set_discard_key((PySetObject *)set, key, 0); } int