diff options
Diffstat (limited to 'Objects/setobject.c')
-rw-r--r-- | Objects/setobject.c | 3606 |
1 files changed, 1803 insertions, 1803 deletions
diff --git a/Objects/setobject.c b/Objects/setobject.c index aaa4838..b35fef5 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -1,5 +1,5 @@ -/* set object implementation +/* set object implementation Written and maintained by Raymond D. Hettinger <python@rcn.com> Derived from Lib/sets.py and Objects/dictobject.c. @@ -17,12 +17,12 @@ static void set_key_error(PyObject *arg) { - PyObject *tup; - tup = PyTuple_Pack(1, arg); - if (!tup) - return; /* caller will expect error to be set anyway */ - PyErr_SetObject(PyExc_KeyError, tup); - Py_DECREF(tup); + PyObject *tup; + tup = PyTuple_Pack(1, arg); + if (!tup) + return; /* caller will expect error to be set anyway */ + PyErr_SetObject(PyExc_KeyError, tup); + Py_DECREF(tup); } /* This must be >= 1. */ @@ -35,20 +35,20 @@ static PyObject *dummy = NULL; /* Initialized by first call to make_new_set() */ PyObject * _PySet_Dummy(void) { - return dummy; + return dummy; } #endif -#define INIT_NONZERO_SET_SLOTS(so) do { \ - (so)->table = (so)->smalltable; \ - (so)->mask = PySet_MINSIZE - 1; \ - (so)->hash = -1; \ +#define INIT_NONZERO_SET_SLOTS(so) do { \ + (so)->table = (so)->smalltable; \ + (so)->mask = PySet_MINSIZE - 1; \ + (so)->hash = -1; \ } while(0) -#define EMPTY_TO_MINSIZE(so) do { \ - memset((so)->smalltable, 0, sizeof((so)->smalltable)); \ - (so)->used = (so)->fill = 0; \ - INIT_NONZERO_SET_SLOTS(so); \ +#define EMPTY_TO_MINSIZE(so) do { \ + memset((so)->smalltable, 0, sizeof((so)->smalltable)); \ + (so)->used = (so)->fill = 0; \ + INIT_NONZERO_SET_SLOTS(so); \ } while(0) /* Reuse scheme to save calls to malloc, free, and memset */ @@ -77,78 +77,78 @@ NULL if the rich comparison returns an error. static setentry * set_lookkey(PySetObject *so, PyObject *key, register long hash) { - register Py_ssize_t i; - register size_t perturb; - register setentry *freeslot; - register size_t mask = so->mask; - setentry *table = so->table; - register setentry *entry; - register int cmp; - PyObject *startkey; - - i = hash & mask; - entry = &table[i]; - if (entry->key == NULL || entry->key == key) - return entry; - - if (entry->key == dummy) - freeslot = entry; - else { - if (entry->hash == hash) { - startkey = entry->key; - Py_INCREF(startkey); - cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); - Py_DECREF(startkey); - if (cmp < 0) - return NULL; - if (table == so->table && entry->key == startkey) { - if (cmp > 0) - return entry; - } - else { - /* The compare did major nasty stuff to the - * set: start over. - */ - return set_lookkey(so, key, hash); - } - } - freeslot = NULL; - } - - /* In the loop, key == dummy is by far (factor of 100s) the - least likely outcome, so test for that last. */ - for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { - i = (i << 2) + i + perturb + 1; - entry = &table[i & mask]; - if (entry->key == NULL) { - if (freeslot != NULL) - entry = freeslot; - break; - } - if (entry->key == key) - break; - if (entry->hash == hash && entry->key != dummy) { - startkey = entry->key; - Py_INCREF(startkey); - cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); - Py_DECREF(startkey); - if (cmp < 0) - return NULL; - if (table == so->table && entry->key == startkey) { - if (cmp > 0) - break; - } - else { - /* The compare did major nasty stuff to the - * set: start over. - */ - return set_lookkey(so, key, hash); - } - } - else if (entry->key == dummy && freeslot == NULL) - freeslot = entry; - } - return entry; + register Py_ssize_t i; + register size_t perturb; + register setentry *freeslot; + register size_t mask = so->mask; + setentry *table = so->table; + register setentry *entry; + register int cmp; + PyObject *startkey; + + i = hash & mask; + entry = &table[i]; + if (entry->key == NULL || entry->key == key) + return entry; + + if (entry->key == dummy) + freeslot = entry; + else { + if (entry->hash == hash) { + startkey = entry->key; + Py_INCREF(startkey); + cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); + Py_DECREF(startkey); + if (cmp < 0) + return NULL; + if (table == so->table && entry->key == startkey) { + if (cmp > 0) + return entry; + } + else { + /* The compare did major nasty stuff to the + * set: start over. + */ + return set_lookkey(so, key, hash); + } + } + freeslot = NULL; + } + + /* In the loop, key == dummy is by far (factor of 100s) the + least likely outcome, so test for that last. */ + for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { + i = (i << 2) + i + perturb + 1; + entry = &table[i & mask]; + if (entry->key == NULL) { + if (freeslot != NULL) + entry = freeslot; + break; + } + if (entry->key == key) + break; + if (entry->hash == hash && entry->key != dummy) { + startkey = entry->key; + Py_INCREF(startkey); + cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); + Py_DECREF(startkey); + if (cmp < 0) + return NULL; + if (table == so->table && entry->key == startkey) { + if (cmp > 0) + break; + } + else { + /* The compare did major nasty stuff to the + * set: start over. + */ + return set_lookkey(so, key, hash); + } + } + else if (entry->key == dummy && freeslot == NULL) + freeslot = entry; + } + return entry; } /* @@ -159,50 +159,50 @@ set_lookkey(PySetObject *so, PyObject *key, register long hash) static setentry * set_lookkey_unicode(PySetObject *so, PyObject *key, register long hash) { - register Py_ssize_t i; - register size_t perturb; - register setentry *freeslot; - register size_t mask = so->mask; - setentry *table = so->table; - register setentry *entry; - - /* Make sure this function doesn't have to handle non-unicode keys, - including subclasses of str; e.g., one reason to subclass - strings is to override __eq__, and for speed we don't cater to - that here. */ - if (!PyUnicode_CheckExact(key)) { - so->lookup = set_lookkey; - return set_lookkey(so, key, hash); - } - i = hash & mask; - entry = &table[i]; - if (entry->key == NULL || entry->key == key) - return entry; - if (entry->key == dummy) - freeslot = entry; - else { - if (entry->hash == hash && unicode_eq(entry->key, key)) - return entry; - freeslot = NULL; - } - - /* In the loop, key == dummy is by far (factor of 100s) the - least likely outcome, so test for that last. */ - for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { - i = (i << 2) + i + perturb + 1; - entry = &table[i & mask]; - if (entry->key == NULL) - return freeslot == NULL ? entry : freeslot; - if (entry->key == key - || (entry->hash == hash - && entry->key != dummy - && unicode_eq(entry->key, key))) - return entry; - if (entry->key == dummy && freeslot == NULL) - freeslot = entry; - } - assert(0); /* NOT REACHED */ - return 0; + register Py_ssize_t i; + register size_t perturb; + register setentry *freeslot; + register size_t mask = so->mask; + setentry *table = so->table; + register setentry *entry; + + /* Make sure this function doesn't have to handle non-unicode keys, + including subclasses of str; e.g., one reason to subclass + strings is to override __eq__, and for speed we don't cater to + that here. */ + if (!PyUnicode_CheckExact(key)) { + so->lookup = set_lookkey; + return set_lookkey(so, key, hash); + } + i = hash & mask; + entry = &table[i]; + if (entry->key == NULL || entry->key == key) + return entry; + if (entry->key == dummy) + freeslot = entry; + else { + if (entry->hash == hash && unicode_eq(entry->key, key)) + return entry; + freeslot = NULL; + } + + /* In the loop, key == dummy is by far (factor of 100s) the + least likely outcome, so test for that last. */ + for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { + i = (i << 2) + i + perturb + 1; + entry = &table[i & mask]; + if (entry->key == NULL) + return freeslot == NULL ? entry : freeslot; + if (entry->key == key + || (entry->hash == hash + && entry->key != dummy + && unicode_eq(entry->key, key))) + return entry; + if (entry->key == dummy && freeslot == NULL) + freeslot = entry; + } + assert(0); /* NOT REACHED */ + return 0; } /* @@ -213,30 +213,30 @@ Eats a reference to key. static int set_insert_key(register PySetObject *so, PyObject *key, long hash) { - register setentry *entry; - typedef setentry *(*lookupfunc)(PySetObject *, PyObject *, long); - - assert(so->lookup != NULL); - entry = so->lookup(so, key, hash); - if (entry == NULL) - return -1; - if (entry->key == NULL) { - /* UNUSED */ - so->fill++; - entry->key = key; - entry->hash = hash; - so->used++; - } else if (entry->key == dummy) { - /* DUMMY */ - entry->key = key; - entry->hash = hash; - so->used++; - Py_DECREF(dummy); - } else { - /* ACTIVE */ - Py_DECREF(key); - } - return 0; + register setentry *entry; + typedef setentry *(*lookupfunc)(PySetObject *, PyObject *, long); + + assert(so->lookup != NULL); + entry = so->lookup(so, key, hash); + if (entry == NULL) + return -1; + if (entry->key == NULL) { + /* UNUSED */ + so->fill++; + entry->key = key; + entry->hash = hash; + so->used++; + } else if (entry->key == dummy) { + /* DUMMY */ + entry->key = key; + entry->hash = hash; + so->used++; + Py_DECREF(dummy); + } else { + /* ACTIVE */ + Py_DECREF(key); + } + return 0; } /* @@ -250,22 +250,22 @@ is responsible for incref'ing `key`. static void set_insert_clean(register PySetObject *so, PyObject *key, long hash) { - register size_t i; - register size_t perturb; - register size_t mask = (size_t)so->mask; - setentry *table = so->table; - register setentry *entry; + register size_t i; + register size_t perturb; + register size_t mask = (size_t)so->mask; + setentry *table = so->table; + register setentry *entry; - i = hash & mask; - entry = &table[i]; - for (perturb = hash; entry->key != NULL; perturb >>= PERTURB_SHIFT) { - i = (i << 2) + i + perturb + 1; - entry = &table[i & mask]; - } - so->fill++; - entry->key = key; - entry->hash = hash; - so->used++; + i = hash & mask; + entry = &table[i]; + for (perturb = hash; entry->key != NULL; perturb >>= PERTURB_SHIFT) { + i = (i << 2) + i + perturb + 1; + entry = &table[i & mask]; + } + so->fill++; + entry->key = key; + entry->hash = hash; + so->used++; } /* @@ -276,86 +276,86 @@ actually be smaller than the old one. static int set_table_resize(PySetObject *so, Py_ssize_t minused) { - Py_ssize_t newsize; - setentry *oldtable, *newtable, *entry; - Py_ssize_t i; - int is_oldtable_malloced; - setentry small_copy[PySet_MINSIZE]; - - assert(minused >= 0); - - /* Find the smallest table size > minused. */ - for (newsize = PySet_MINSIZE; - newsize <= minused && newsize > 0; - newsize <<= 1) - ; - if (newsize <= 0) { - PyErr_NoMemory(); - return -1; - } - - /* Get space for a new table. */ - oldtable = so->table; - assert(oldtable != NULL); - is_oldtable_malloced = oldtable != so->smalltable; - - if (newsize == PySet_MINSIZE) { - /* A large table is shrinking, or we can't get any smaller. */ - newtable = so->smalltable; - if (newtable == oldtable) { - if (so->fill == so->used) { - /* No dummies, so no point doing anything. */ - return 0; - } - /* We're not going to resize it, but rebuild the - table anyway to purge old dummy entries. - Subtle: This is *necessary* if fill==size, - as set_lookkey needs at least one virgin slot to - terminate failing searches. If fill < size, it's - merely desirable, as dummies slow searches. */ - assert(so->fill > so->used); - memcpy(small_copy, oldtable, sizeof(small_copy)); - oldtable = small_copy; - } - } - else { - newtable = PyMem_NEW(setentry, newsize); - if (newtable == NULL) { - PyErr_NoMemory(); - return -1; - } - } - - /* Make the set empty, using the new table. */ - assert(newtable != oldtable); - so->table = newtable; - so->mask = newsize - 1; - memset(newtable, 0, sizeof(setentry) * newsize); - so->used = 0; - i = so->fill; - so->fill = 0; - - /* Copy the data over; this is refcount-neutral for active entries; - dummy entries aren't copied over, of course */ - for (entry = oldtable; i > 0; entry++) { - if (entry->key == NULL) { - /* UNUSED */ - ; - } else if (entry->key == dummy) { - /* DUMMY */ - --i; - assert(entry->key == dummy); - Py_DECREF(entry->key); - } else { - /* ACTIVE */ - --i; - set_insert_clean(so, entry->key, entry->hash); - } - } - - if (is_oldtable_malloced) - PyMem_DEL(oldtable); - return 0; + Py_ssize_t newsize; + setentry *oldtable, *newtable, *entry; + Py_ssize_t i; + int is_oldtable_malloced; + setentry small_copy[PySet_MINSIZE]; + + assert(minused >= 0); + + /* Find the smallest table size > minused. */ + for (newsize = PySet_MINSIZE; + newsize <= minused && newsize > 0; + newsize <<= 1) + ; + if (newsize <= 0) { + PyErr_NoMemory(); + return -1; + } + + /* Get space for a new table. */ + oldtable = so->table; + assert(oldtable != NULL); + is_oldtable_malloced = oldtable != so->smalltable; + + if (newsize == PySet_MINSIZE) { + /* A large table is shrinking, or we can't get any smaller. */ + newtable = so->smalltable; + if (newtable == oldtable) { + if (so->fill == so->used) { + /* No dummies, so no point doing anything. */ + return 0; + } + /* We're not going to resize it, but rebuild the + table anyway to purge old dummy entries. + Subtle: This is *necessary* if fill==size, + as set_lookkey needs at least one virgin slot to + terminate failing searches. If fill < size, it's + merely desirable, as dummies slow searches. */ + assert(so->fill > so->used); + memcpy(small_copy, oldtable, sizeof(small_copy)); + oldtable = small_copy; + } + } + else { + newtable = PyMem_NEW(setentry, newsize); + if (newtable == NULL) { + PyErr_NoMemory(); + return -1; + } + } + + /* Make the set empty, using the new table. */ + assert(newtable != oldtable); + so->table = newtable; + so->mask = newsize - 1; + memset(newtable, 0, sizeof(setentry) * newsize); + so->used = 0; + i = so->fill; + so->fill = 0; + + /* Copy the data over; this is refcount-neutral for active entries; + dummy entries aren't copied over, of course */ + for (entry = oldtable; i > 0; entry++) { + if (entry->key == NULL) { + /* UNUSED */ + ; + } else if (entry->key == dummy) { + /* DUMMY */ + --i; + assert(entry->key == dummy); + Py_DECREF(entry->key); + } else { + /* ACTIVE */ + --i; + set_insert_clean(so, entry->key, entry->hash); + } + } + + if (is_oldtable_malloced) + PyMem_DEL(oldtable); + return 0; } /* CAUTION: set_add_key/entry() must guarantee it won't resize the table */ @@ -363,42 +363,42 @@ set_table_resize(PySetObject *so, Py_ssize_t minused) static int set_add_entry(register PySetObject *so, setentry *entry) { - register Py_ssize_t n_used; + register Py_ssize_t n_used; - assert(so->fill <= so->mask); /* at least one empty slot */ - n_used = so->used; - Py_INCREF(entry->key); - if (set_insert_key(so, entry->key, entry->hash) == -1) { - Py_DECREF(entry->key); - return -1; - } - if (!(so->used > n_used && so->fill*3 >= (so->mask+1)*2)) - return 0; - return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4); + assert(so->fill <= so->mask); /* at least one empty slot */ + n_used = so->used; + Py_INCREF(entry->key); + if (set_insert_key(so, entry->key, entry->hash) == -1) { + Py_DECREF(entry->key); + return -1; + } + if (!(so->used > n_used && so->fill*3 >= (so->mask+1)*2)) + return 0; + return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4); } static int set_add_key(register PySetObject *so, PyObject *key) { - register long hash; - register Py_ssize_t n_used; - - if (!PyUnicode_CheckExact(key) || - (hash = ((PyUnicodeObject *) key)->hash) == -1) { - hash = PyObject_Hash(key); - if (hash == -1) - return -1; - } - assert(so->fill <= so->mask); /* at least one empty slot */ - n_used = so->used; - Py_INCREF(key); - if (set_insert_key(so, key, hash) == -1) { - Py_DECREF(key); - return -1; - } - if (!(so->used > n_used && so->fill*3 >= (so->mask+1)*2)) - return 0; - return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4); + register long hash; + register Py_ssize_t n_used; + + if (!PyUnicode_CheckExact(key) || + (hash = ((PyUnicodeObject *) key)->hash) == -1) { + hash = PyObject_Hash(key); + if (hash == -1) + return -1; + } + assert(so->fill <= so->mask); /* at least one empty slot */ + n_used = so->used; + Py_INCREF(key); + if (set_insert_key(so, key, hash) == -1) { + Py_DECREF(key); + return -1; + } + if (!(so->used > n_used && so->fill*3 >= (so->mask+1)*2)) + return 0; + return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4); } #define DISCARD_NOTFOUND 0 @@ -406,112 +406,112 @@ set_add_key(register PySetObject *so, PyObject *key) static int set_discard_entry(PySetObject *so, setentry *oldentry) -{ register setentry *entry; - PyObject *old_key; - - entry = (so->lookup)(so, oldentry->key, oldentry->hash); - if (entry == NULL) - return -1; - if (entry->key == NULL || entry->key == dummy) - return DISCARD_NOTFOUND; - old_key = entry->key; - Py_INCREF(dummy); - entry->key = dummy; - so->used--; - Py_DECREF(old_key); - return DISCARD_FOUND; +{ register setentry *entry; + PyObject *old_key; + + entry = (so->lookup)(so, oldentry->key, oldentry->hash); + if (entry == NULL) + return -1; + if (entry->key == NULL || entry->key == dummy) + return DISCARD_NOTFOUND; + old_key = entry->key; + Py_INCREF(dummy); + entry->key = dummy; + so->used--; + Py_DECREF(old_key); + return DISCARD_FOUND; } static int set_discard_key(PySetObject *so, PyObject *key) { - register long hash; - register setentry *entry; - PyObject *old_key; - - assert (PyAnySet_Check(so)); - - if (!PyUnicode_CheckExact(key) || - (hash = ((PyUnicodeObject *) key)->hash) == -1) { - hash = PyObject_Hash(key); - if (hash == -1) - return -1; - } - entry = (so->lookup)(so, key, hash); - if (entry == NULL) - return -1; - if (entry->key == NULL || entry->key == dummy) - return DISCARD_NOTFOUND; - old_key = entry->key; - Py_INCREF(dummy); - entry->key = dummy; - so->used--; - Py_DECREF(old_key); - return DISCARD_FOUND; + register long hash; + register setentry *entry; + PyObject *old_key; + + assert (PyAnySet_Check(so)); + + if (!PyUnicode_CheckExact(key) || + (hash = ((PyUnicodeObject *) key)->hash) == -1) { + hash = PyObject_Hash(key); + if (hash == -1) + return -1; + } + entry = (so->lookup)(so, key, hash); + if (entry == NULL) + return -1; + if (entry->key == NULL || entry->key == dummy) + return DISCARD_NOTFOUND; + old_key = entry->key; + Py_INCREF(dummy); + entry->key = dummy; + so->used--; + Py_DECREF(old_key); + return DISCARD_FOUND; } static int set_clear_internal(PySetObject *so) { - setentry *entry, *table; - int table_is_malloced; - Py_ssize_t fill; - setentry small_copy[PySet_MINSIZE]; + setentry *entry, *table; + int table_is_malloced; + Py_ssize_t fill; + setentry small_copy[PySet_MINSIZE]; #ifdef Py_DEBUG - Py_ssize_t i, n; - assert (PyAnySet_Check(so)); + Py_ssize_t i, n; + assert (PyAnySet_Check(so)); - n = so->mask + 1; - i = 0; + n = so->mask + 1; + i = 0; #endif - table = so->table; - assert(table != NULL); - table_is_malloced = table != so->smalltable; - - /* This is delicate. During the process of clearing the set, - * decrefs can cause the set to mutate. To avoid fatal confusion - * (voice of experience), we have to make the set empty before - * clearing the slots, and never refer to anything via so->ref while - * clearing. - */ - fill = so->fill; - if (table_is_malloced) - EMPTY_TO_MINSIZE(so); - - else if (fill > 0) { - /* It's a small table with something that needs to be cleared. - * Afraid the only safe way is to copy the set entries into - * another small table first. - */ - memcpy(small_copy, table, sizeof(small_copy)); - table = small_copy; - EMPTY_TO_MINSIZE(so); - } - /* else it's a small table that's already empty */ - - /* Now we can finally clear things. If C had refcounts, we could - * assert that the refcount on table is 1 now, i.e. that this function - * has unique access to it, so decref side-effects can't alter it. - */ - for (entry = table; fill > 0; ++entry) { + table = so->table; + assert(table != NULL); + table_is_malloced = table != so->smalltable; + + /* This is delicate. During the process of clearing the set, + * decrefs can cause the set to mutate. To avoid fatal confusion + * (voice of experience), we have to make the set empty before + * clearing the slots, and never refer to anything via so->ref while + * clearing. + */ + fill = so->fill; + if (table_is_malloced) + EMPTY_TO_MINSIZE(so); + + else if (fill > 0) { + /* It's a small table with something that needs to be cleared. + * Afraid the only safe way is to copy the set entries into + * another small table first. + */ + memcpy(small_copy, table, sizeof(small_copy)); + table = small_copy; + EMPTY_TO_MINSIZE(so); + } + /* else it's a small table that's already empty */ + + /* Now we can finally clear things. If C had refcounts, we could + * assert that the refcount on table is 1 now, i.e. that this function + * has unique access to it, so decref side-effects can't alter it. + */ + for (entry = table; fill > 0; ++entry) { #ifdef Py_DEBUG - assert(i < n); - ++i; + assert(i < n); + ++i; #endif - if (entry->key) { - --fill; - Py_DECREF(entry->key); - } + if (entry->key) { + --fill; + Py_DECREF(entry->key); + } #ifdef Py_DEBUG - else - assert(entry->key == NULL); + else + assert(entry->key == NULL); #endif - } + } - if (table_is_malloced) - PyMem_DEL(table); - return 0; + if (table_is_malloced) + PyMem_DEL(table); + return 0; } /* @@ -525,223 +525,223 @@ set_clear_internal(PySetObject *so) * } * * CAUTION: In general, it isn't safe to use set_next in a loop that - * mutates the table. + * mutates the table. */ static int set_next(PySetObject *so, Py_ssize_t *pos_ptr, setentry **entry_ptr) { - Py_ssize_t i; - Py_ssize_t mask; - register setentry *table; - - assert (PyAnySet_Check(so)); - i = *pos_ptr; - assert(i >= 0); - table = so->table; - mask = so->mask; - while (i <= mask && (table[i].key == NULL || table[i].key == dummy)) - i++; - *pos_ptr = i+1; - if (i > mask) - return 0; - assert(table[i].key != NULL); - *entry_ptr = &table[i]; - return 1; + Py_ssize_t i; + Py_ssize_t mask; + register setentry *table; + + assert (PyAnySet_Check(so)); + i = *pos_ptr; + assert(i >= 0); + table = so->table; + mask = so->mask; + while (i <= mask && (table[i].key == NULL || table[i].key == dummy)) + i++; + *pos_ptr = i+1; + if (i > mask) + return 0; + assert(table[i].key != NULL); + *entry_ptr = &table[i]; + return 1; } static void set_dealloc(PySetObject *so) { - register setentry *entry; - Py_ssize_t fill = so->fill; - PyObject_GC_UnTrack(so); - Py_TRASHCAN_SAFE_BEGIN(so) - if (so->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *) so); - - for (entry = so->table; fill > 0; entry++) { - if (entry->key) { - --fill; - Py_DECREF(entry->key); - } - } - if (so->table != so->smalltable) - PyMem_DEL(so->table); - if (numfree < PySet_MAXFREELIST && PyAnySet_CheckExact(so)) - free_list[numfree++] = so; - else - Py_TYPE(so)->tp_free(so); - Py_TRASHCAN_SAFE_END(so) + register setentry *entry; + Py_ssize_t fill = so->fill; + PyObject_GC_UnTrack(so); + Py_TRASHCAN_SAFE_BEGIN(so) + if (so->weakreflist != NULL) + PyObject_ClearWeakRefs((PyObject *) so); + + for (entry = so->table; fill > 0; entry++) { + if (entry->key) { + --fill; + Py_DECREF(entry->key); + } + } + if (so->table != so->smalltable) + PyMem_DEL(so->table); + if (numfree < PySet_MAXFREELIST && PyAnySet_CheckExact(so)) + free_list[numfree++] = so; + else + Py_TYPE(so)->tp_free(so); + Py_TRASHCAN_SAFE_END(so) } static PyObject * set_repr(PySetObject *so) { - PyObject *keys, *result=NULL; - Py_UNICODE *u; - int status = Py_ReprEnter((PyObject*)so); - PyObject *listrepr; - Py_ssize_t newsize; - - if (status != 0) { - if (status < 0) - return NULL; - return PyUnicode_FromFormat("%s(...)", Py_TYPE(so)->tp_name); - } - - /* shortcut for the empty set */ - if (!so->used) { - Py_ReprLeave((PyObject*)so); - return PyUnicode_FromFormat("%s()", Py_TYPE(so)->tp_name); - } - - keys = PySequence_List((PyObject *)so); - if (keys == NULL) - goto done; - - listrepr = PyObject_Repr(keys); - Py_DECREF(keys); - if (listrepr == NULL) - goto done; - newsize = PyUnicode_GET_SIZE(listrepr); - result = PyUnicode_FromUnicode(NULL, newsize); - if (result) { - u = PyUnicode_AS_UNICODE(result); - *u++ = '{'; - /* Omit the brackets from the listrepr */ - Py_UNICODE_COPY(u, PyUnicode_AS_UNICODE(listrepr)+1, - PyUnicode_GET_SIZE(listrepr)-2); - u += newsize-2; - *u++ = '}'; - } - Py_DECREF(listrepr); - if (Py_TYPE(so) != &PySet_Type) { - PyObject *tmp = PyUnicode_FromFormat("%s(%U)", - Py_TYPE(so)->tp_name, - result); - Py_DECREF(result); - result = tmp; - } + PyObject *keys, *result=NULL; + Py_UNICODE *u; + int status = Py_ReprEnter((PyObject*)so); + PyObject *listrepr; + Py_ssize_t newsize; + + if (status != 0) { + if (status < 0) + return NULL; + return PyUnicode_FromFormat("%s(...)", Py_TYPE(so)->tp_name); + } + + /* shortcut for the empty set */ + if (!so->used) { + Py_ReprLeave((PyObject*)so); + return PyUnicode_FromFormat("%s()", Py_TYPE(so)->tp_name); + } + + keys = PySequence_List((PyObject *)so); + if (keys == NULL) + goto done; + + listrepr = PyObject_Repr(keys); + Py_DECREF(keys); + if (listrepr == NULL) + goto done; + newsize = PyUnicode_GET_SIZE(listrepr); + result = PyUnicode_FromUnicode(NULL, newsize); + if (result) { + u = PyUnicode_AS_UNICODE(result); + *u++ = '{'; + /* Omit the brackets from the listrepr */ + Py_UNICODE_COPY(u, PyUnicode_AS_UNICODE(listrepr)+1, + PyUnicode_GET_SIZE(listrepr)-2); + u += newsize-2; + *u++ = '}'; + } + Py_DECREF(listrepr); + if (Py_TYPE(so) != &PySet_Type) { + PyObject *tmp = PyUnicode_FromFormat("%s(%U)", + Py_TYPE(so)->tp_name, + result); + Py_DECREF(result); + result = tmp; + } done: - Py_ReprLeave((PyObject*)so); - return result; + Py_ReprLeave((PyObject*)so); + return result; } static Py_ssize_t set_len(PyObject *so) { - return ((PySetObject *)so)->used; + return ((PySetObject *)so)->used; } static int set_merge(PySetObject *so, PyObject *otherset) { - PySetObject *other; - register Py_ssize_t i; - register setentry *entry; - - assert (PyAnySet_Check(so)); - assert (PyAnySet_Check(otherset)); - - other = (PySetObject*)otherset; - if (other == so || other->used == 0) - /* a.update(a) or a.update({}); nothing to do */ - return 0; - /* Do one big resize at the start, rather than - * incrementally resizing as we insert new keys. Expect - * that there will be no (or few) overlapping keys. - */ - if ((so->fill + other->used)*3 >= (so->mask+1)*2) { - if (set_table_resize(so, (so->used + other->used)*2) != 0) - return -1; - } - for (i = 0; i <= other->mask; i++) { - entry = &other->table[i]; - if (entry->key != NULL && - entry->key != dummy) { - Py_INCREF(entry->key); - if (set_insert_key(so, entry->key, entry->hash) == -1) { - Py_DECREF(entry->key); - return -1; - } - } - } - return 0; + PySetObject *other; + register Py_ssize_t i; + register setentry *entry; + + assert (PyAnySet_Check(so)); + assert (PyAnySet_Check(otherset)); + + other = (PySetObject*)otherset; + if (other == so || other->used == 0) + /* a.update(a) or a.update({}); nothing to do */ + return 0; + /* Do one big resize at the start, rather than + * incrementally resizing as we insert new keys. Expect + * that there will be no (or few) overlapping keys. + */ + if ((so->fill + other->used)*3 >= (so->mask+1)*2) { + if (set_table_resize(so, (so->used + other->used)*2) != 0) + return -1; + } + for (i = 0; i <= other->mask; i++) { + entry = &other->table[i]; + if (entry->key != NULL && + entry->key != dummy) { + Py_INCREF(entry->key); + if (set_insert_key(so, entry->key, entry->hash) == -1) { + Py_DECREF(entry->key); + return -1; + } + } + } + return 0; } static int set_contains_key(PySetObject *so, PyObject *key) { - long hash; - setentry *entry; + long hash; + setentry *entry; - if (!PyUnicode_CheckExact(key) || - (hash = ((PyUnicodeObject *) key)->hash) == -1) { - hash = PyObject_Hash(key); - if (hash == -1) - return -1; - } - entry = (so->lookup)(so, key, hash); - if (entry == NULL) - return -1; - key = entry->key; - return key != NULL && key != dummy; + if (!PyUnicode_CheckExact(key) || + (hash = ((PyUnicodeObject *) key)->hash) == -1) { + hash = PyObject_Hash(key); + if (hash == -1) + return -1; + } + entry = (so->lookup)(so, key, hash); + if (entry == NULL) + return -1; + key = entry->key; + return key != NULL && key != dummy; } static int set_contains_entry(PySetObject *so, setentry *entry) { - PyObject *key; - setentry *lu_entry; + PyObject *key; + setentry *lu_entry; - lu_entry = (so->lookup)(so, entry->key, entry->hash); - if (lu_entry == NULL) - return -1; - key = lu_entry->key; - return key != NULL && key != dummy; + lu_entry = (so->lookup)(so, entry->key, entry->hash); + if (lu_entry == NULL) + return -1; + key = lu_entry->key; + return key != NULL && key != dummy; } static PyObject * set_pop(PySetObject *so) { - register Py_ssize_t i = 0; - register setentry *entry; - PyObject *key; - - assert (PyAnySet_Check(so)); - if (so->used == 0) { - PyErr_SetString(PyExc_KeyError, "pop from an empty set"); - return NULL; - } - - /* Set entry to "the first" unused or dummy set entry. 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. - */ - entry = &so->table[0]; - if (entry->key == NULL || entry->key == dummy) { - i = 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; + register Py_ssize_t i = 0; + register setentry *entry; + PyObject *key; + + assert (PyAnySet_Check(so)); + if (so->used == 0) { + PyErr_SetString(PyExc_KeyError, "pop from an empty set"); + return NULL; + } + + /* Set entry to "the first" unused or dummy set entry. 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. + */ + entry = &so->table[0]; + if (entry->key == NULL || entry->key == dummy) { + i = 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; } PyDoc_STRVAR(pop_doc, "Remove and return an arbitrary set element.\n\ @@ -750,289 +750,289 @@ Raises KeyError if the set is empty."); static int set_traverse(PySetObject *so, visitproc visit, void *arg) { - Py_ssize_t pos = 0; - setentry *entry; + Py_ssize_t pos = 0; + setentry *entry; - while (set_next(so, &pos, &entry)) - Py_VISIT(entry->key); - return 0; + while (set_next(so, &pos, &entry)) + Py_VISIT(entry->key); + return 0; } static long frozenset_hash(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 - values. The is important because some use cases have many - combinations of a small number of elements with nearby - hashes so that many distinct combinations collapse to only - a handful of distinct hash values. */ - h = entry->hash; - hash ^= (h ^ (h << 16) ^ 89869747L) * 3644798167u; - } - hash = hash * 69069L + 907133923L; - if (hash == -1) - hash = 590923713L; - so->hash = hash; - return hash; + 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 + values. The is important because some use cases have many + combinations of a small number of elements with nearby + hashes so that many distinct combinations collapse to only + a handful of distinct hash values. */ + h = entry->hash; + hash ^= (h ^ (h << 16) ^ 89869747L) * 3644798167u; + } + hash = hash * 69069L + 907133923L; + if (hash == -1) + hash = 590923713L; + so->hash = hash; + return hash; } /***** Set iterator type ***********************************************/ typedef struct { - PyObject_HEAD - PySetObject *si_set; /* Set to NULL when iterator is exhausted */ - Py_ssize_t si_used; - Py_ssize_t si_pos; - Py_ssize_t len; + PyObject_HEAD + PySetObject *si_set; /* Set to NULL when iterator is exhausted */ + Py_ssize_t si_used; + Py_ssize_t si_pos; + Py_ssize_t len; } setiterobject; static void setiter_dealloc(setiterobject *si) { - Py_XDECREF(si->si_set); - PyObject_GC_Del(si); + Py_XDECREF(si->si_set); + PyObject_GC_Del(si); } static int setiter_traverse(setiterobject *si, visitproc visit, void *arg) { - Py_VISIT(si->si_set); - return 0; + Py_VISIT(si->si_set); + return 0; } static PyObject * setiter_len(setiterobject *si) { - Py_ssize_t len = 0; - if (si->si_set != NULL && si->si_used == si->si_set->used) - len = si->len; - return PyLong_FromLong(len); + Py_ssize_t len = 0; + if (si->si_set != NULL && si->si_used == si->si_set->used) + len = si->len; + return PyLong_FromLong(len); } PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); static PyMethodDef setiter_methods[] = { - {"__length_hint__", (PyCFunction)setiter_len, METH_NOARGS, length_hint_doc}, - {NULL, NULL} /* sentinel */ + {"__length_hint__", (PyCFunction)setiter_len, METH_NOARGS, length_hint_doc}, + {NULL, NULL} /* sentinel */ }; static PyObject *setiter_iternext(setiterobject *si) { - PyObject *key; - register Py_ssize_t i, mask; - register setentry *entry; - PySetObject *so = si->si_set; - - if (so == NULL) - return NULL; - assert (PyAnySet_Check(so)); - - if (si->si_used != so->used) { - PyErr_SetString(PyExc_RuntimeError, - "Set changed size during iteration"); - si->si_used = -1; /* Make this state sticky */ - return NULL; - } - - i = si->si_pos; - assert(i>=0); - entry = so->table; - mask = so->mask; - while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy)) - i++; - si->si_pos = i+1; - if (i > mask) - goto fail; - si->len--; - key = entry[i].key; - Py_INCREF(key); - return key; + PyObject *key; + register Py_ssize_t i, mask; + register setentry *entry; + PySetObject *so = si->si_set; + + if (so == NULL) + return NULL; + assert (PyAnySet_Check(so)); + + if (si->si_used != so->used) { + PyErr_SetString(PyExc_RuntimeError, + "Set changed size during iteration"); + si->si_used = -1; /* Make this state sticky */ + return NULL; + } + + i = si->si_pos; + assert(i>=0); + entry = so->table; + mask = so->mask; + while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy)) + i++; + si->si_pos = i+1; + if (i > mask) + goto fail; + si->len--; + key = entry[i].key; + Py_INCREF(key); + return key; fail: - Py_DECREF(so); - si->si_set = NULL; - return NULL; + Py_DECREF(so); + si->si_set = NULL; + return NULL; } PyTypeObject PySetIter_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "set_iterator", /* tp_name */ - sizeof(setiterobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)setiter_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ - 0, /* tp_doc */ - (traverseproc)setiter_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)setiter_iternext, /* tp_iternext */ - setiter_methods, /* tp_methods */ - 0, + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "set_iterator", /* tp_name */ + sizeof(setiterobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)setiter_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ + 0, /* tp_doc */ + (traverseproc)setiter_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)setiter_iternext, /* tp_iternext */ + setiter_methods, /* tp_methods */ + 0, }; static PyObject * set_iter(PySetObject *so) { - setiterobject *si = PyObject_GC_New(setiterobject, &PySetIter_Type); - if (si == NULL) - return NULL; - Py_INCREF(so); - si->si_set = so; - si->si_used = so->used; - si->si_pos = 0; - si->len = so->used; - _PyObject_GC_TRACK(si); - return (PyObject *)si; + setiterobject *si = PyObject_GC_New(setiterobject, &PySetIter_Type); + if (si == NULL) + return NULL; + Py_INCREF(so); + si->si_set = so; + si->si_used = so->used; + si->si_pos = 0; + si->len = so->used; + _PyObject_GC_TRACK(si); + return (PyObject *)si; } static int set_update_internal(PySetObject *so, PyObject *other) { - PyObject *key, *it; - - if (PyAnySet_Check(other)) - return set_merge(so, other); - - if (PyDict_CheckExact(other)) { - PyObject *value; - Py_ssize_t pos = 0; - long hash; - Py_ssize_t dictsize = PyDict_Size(other); - - /* Do one big resize at the start, rather than - * incrementally resizing as we insert new keys. Expect - * that there will be no (or few) overlapping keys. - */ - if (dictsize == -1) - return -1; - if ((so->fill + dictsize)*3 >= (so->mask+1)*2) { - if (set_table_resize(so, (so->used + dictsize)*2) != 0) - return -1; - } - while (_PyDict_Next(other, &pos, &key, &value, &hash)) { - setentry an_entry; - - an_entry.hash = hash; - an_entry.key = key; - if (set_add_entry(so, &an_entry) == -1) - return -1; - } - return 0; - } - - it = PyObject_GetIter(other); - if (it == NULL) - return -1; - - while ((key = PyIter_Next(it)) != NULL) { - if (set_add_key(so, key) == -1) { - Py_DECREF(it); - Py_DECREF(key); - return -1; - } - Py_DECREF(key); - } - Py_DECREF(it); - if (PyErr_Occurred()) - return -1; - return 0; + PyObject *key, *it; + + if (PyAnySet_Check(other)) + return set_merge(so, other); + + if (PyDict_CheckExact(other)) { + PyObject *value; + Py_ssize_t pos = 0; + long hash; + Py_ssize_t dictsize = PyDict_Size(other); + + /* Do one big resize at the start, rather than + * incrementally resizing as we insert new keys. Expect + * that there will be no (or few) overlapping keys. + */ + if (dictsize == -1) + return -1; + if ((so->fill + dictsize)*3 >= (so->mask+1)*2) { + if (set_table_resize(so, (so->used + dictsize)*2) != 0) + return -1; + } + while (_PyDict_Next(other, &pos, &key, &value, &hash)) { + setentry an_entry; + + an_entry.hash = hash; + an_entry.key = key; + if (set_add_entry(so, &an_entry) == -1) + return -1; + } + return 0; + } + + it = PyObject_GetIter(other); + if (it == NULL) + return -1; + + while ((key = PyIter_Next(it)) != NULL) { + if (set_add_key(so, key) == -1) { + Py_DECREF(it); + Py_DECREF(key); + return -1; + } + Py_DECREF(key); + } + Py_DECREF(it); + if (PyErr_Occurred()) + return -1; + return 0; } static PyObject * set_update(PySetObject *so, PyObject *args) { - Py_ssize_t i; + Py_ssize_t i; - for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) { - PyObject *other = PyTuple_GET_ITEM(args, i); - if (set_update_internal(so, other) == -1) - return NULL; - } - Py_RETURN_NONE; + for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) { + PyObject *other = PyTuple_GET_ITEM(args, i); + if (set_update_internal(so, other) == -1) + return NULL; + } + Py_RETURN_NONE; } -PyDoc_STRVAR(update_doc, +PyDoc_STRVAR(update_doc, "Update a set with the union of itself and others."); static PyObject * make_new_set(PyTypeObject *type, PyObject *iterable) { - register PySetObject *so = NULL; - - if (dummy == NULL) { /* Auto-initialize dummy */ - dummy = PyUnicode_FromString("<dummy key>"); - if (dummy == NULL) - return NULL; - } - - /* create PySetObject structure */ - if (numfree && - (type == &PySet_Type || type == &PyFrozenSet_Type)) { - so = free_list[--numfree]; - assert (so != NULL && PyAnySet_CheckExact(so)); - Py_TYPE(so) = type; - _Py_NewReference((PyObject *)so); - EMPTY_TO_MINSIZE(so); - PyObject_GC_Track(so); - } else { - so = (PySetObject *)type->tp_alloc(type, 0); - if (so == NULL) - return NULL; - /* tp_alloc has already zeroed the structure */ - assert(so->table == NULL && so->fill == 0 && so->used == 0); - INIT_NONZERO_SET_SLOTS(so); - } - - so->lookup = set_lookkey_unicode; - so->weakreflist = NULL; - - if (iterable != NULL) { - if (set_update_internal(so, iterable) == -1) { - Py_DECREF(so); - return NULL; - } - } - - return (PyObject *)so; + register PySetObject *so = NULL; + + if (dummy == NULL) { /* Auto-initialize dummy */ + dummy = PyUnicode_FromString("<dummy key>"); + if (dummy == NULL) + return NULL; + } + + /* create PySetObject structure */ + if (numfree && + (type == &PySet_Type || type == &PyFrozenSet_Type)) { + so = free_list[--numfree]; + assert (so != NULL && PyAnySet_CheckExact(so)); + Py_TYPE(so) = type; + _Py_NewReference((PyObject *)so); + EMPTY_TO_MINSIZE(so); + PyObject_GC_Track(so); + } else { + so = (PySetObject *)type->tp_alloc(type, 0); + if (so == NULL) + return NULL; + /* tp_alloc has already zeroed the structure */ + assert(so->table == NULL && so->fill == 0 && so->used == 0); + INIT_NONZERO_SET_SLOTS(so); + } + + so->lookup = set_lookkey_unicode; + so->weakreflist = NULL; + + if (iterable != NULL) { + if (set_update_internal(so, iterable) == -1) { + Py_DECREF(so); + return NULL; + } + } + + return (PyObject *)so; } static PyObject * make_new_set_basetype(PyTypeObject *type, PyObject *iterable) { - if (type != &PySet_Type && type != &PyFrozenSet_Type) { - if (PyType_IsSubtype(type, &PySet_Type)) - type = &PySet_Type; - else - type = &PyFrozenSet_Type; - } - return make_new_set(type, iterable); + if (type != &PySet_Type && type != &PyFrozenSet_Type) { + if (PyType_IsSubtype(type, &PySet_Type)) + type = &PySet_Type; + else + type = &PyFrozenSet_Type; + } + return make_new_set(type, iterable); } /* The empty frozenset is a singleton */ @@ -1041,56 +1041,56 @@ static PyObject *emptyfrozenset = NULL; static PyObject * frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - PyObject *iterable = NULL, *result; + PyObject *iterable = NULL, *result; - if (type == &PyFrozenSet_Type && !_PyArg_NoKeywords("frozenset()", kwds)) - return NULL; + if (type == &PyFrozenSet_Type && !_PyArg_NoKeywords("frozenset()", kwds)) + return NULL; - if (!PyArg_UnpackTuple(args, type->tp_name, 0, 1, &iterable)) - return NULL; + if (!PyArg_UnpackTuple(args, type->tp_name, 0, 1, &iterable)) + return NULL; - if (type != &PyFrozenSet_Type) - return make_new_set(type, iterable); + if (type != &PyFrozenSet_Type) + return make_new_set(type, iterable); - if (iterable != NULL) { - /* frozenset(f) is idempotent */ - if (PyFrozenSet_CheckExact(iterable)) { - Py_INCREF(iterable); - return iterable; - } - result = make_new_set(type, iterable); - if (result == NULL || PySet_GET_SIZE(result)) - return result; - Py_DECREF(result); - } - /* The empty frozenset is a singleton */ - if (emptyfrozenset == NULL) - emptyfrozenset = make_new_set(type, NULL); - Py_XINCREF(emptyfrozenset); - return emptyfrozenset; + if (iterable != NULL) { + /* frozenset(f) is idempotent */ + if (PyFrozenSet_CheckExact(iterable)) { + Py_INCREF(iterable); + return iterable; + } + result = make_new_set(type, iterable); + if (result == NULL || PySet_GET_SIZE(result)) + return result; + Py_DECREF(result); + } + /* The empty frozenset is a singleton */ + if (emptyfrozenset == NULL) + emptyfrozenset = make_new_set(type, NULL); + Py_XINCREF(emptyfrozenset); + return emptyfrozenset; } void PySet_Fini(void) { - PySetObject *so; + PySetObject *so; - while (numfree) { - numfree--; - so = free_list[numfree]; - PyObject_GC_Del(so); - } - Py_CLEAR(dummy); - Py_CLEAR(emptyfrozenset); + while (numfree) { + numfree--; + so = free_list[numfree]; + PyObject_GC_Del(so); + } + Py_CLEAR(dummy); + Py_CLEAR(emptyfrozenset); } static PyObject * set_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - if (type == &PySet_Type && !_PyArg_NoKeywords("set()", kwds)) - return NULL; - - return make_new_set(type, NULL); + if (type == &PySet_Type && !_PyArg_NoKeywords("set()", kwds)) + return NULL; + + return make_new_set(type, NULL); } /* set_swap_bodies() switches the contents of any two sets by moving their @@ -1100,64 +1100,64 @@ set_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 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 + 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 + that update in-place (by allowing an intermediate result to be swapped into one of the original inputs). */ static void set_swap_bodies(PySetObject *a, PySetObject *b) { - Py_ssize_t t; - 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; - t = a->mask; a->mask = b->mask; b->mask = t; - - u = a->table; - if (a->table == a->smalltable) - u = b->smalltable; - a->table = b->table; - if (b->table == b->smalltable) - a->table = a->smalltable; - b->table = u; - - f = a->lookup; a->lookup = b->lookup; b->lookup = f; - - if (a->table == a->smalltable || b->table == b->smalltable) { - memcpy(tab, a->smalltable, sizeof(tab)); - memcpy(a->smalltable, b->smalltable, sizeof(tab)); - 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; - } + Py_ssize_t t; + 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; + t = a->mask; a->mask = b->mask; b->mask = t; + + u = a->table; + if (a->table == a->smalltable) + u = b->smalltable; + a->table = b->table; + if (b->table == b->smalltable) + a->table = a->smalltable; + b->table = u; + + f = a->lookup; a->lookup = b->lookup; b->lookup = f; + + if (a->table == a->smalltable || b->table == b->smalltable) { + memcpy(tab, a->smalltable, sizeof(tab)); + memcpy(a->smalltable, b->smalltable, sizeof(tab)); + 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; + } } static PyObject * set_copy(PySetObject *so) { - return make_new_set_basetype(Py_TYPE(so), (PyObject *)so); + return make_new_set_basetype(Py_TYPE(so), (PyObject *)so); } static PyObject * frozenset_copy(PySetObject *so) { - if (PyFrozenSet_CheckExact(so)) { - Py_INCREF(so); - return (PyObject *)so; - } - return set_copy(so); + if (PyFrozenSet_CheckExact(so)) { + Py_INCREF(so); + return (PyObject *)so; + } + return set_copy(so); } PyDoc_STRVAR(copy_doc, "Return a shallow copy of a set."); @@ -1165,8 +1165,8 @@ PyDoc_STRVAR(copy_doc, "Return a shallow copy of a set."); static PyObject * set_clear(PySetObject *so) { - set_clear_internal(so); - Py_RETURN_NONE; + set_clear_internal(so); + Py_RETURN_NONE; } PyDoc_STRVAR(clear_doc, "Remove all elements from this set."); @@ -1174,24 +1174,24 @@ PyDoc_STRVAR(clear_doc, "Remove all elements from this set."); static PyObject * set_union(PySetObject *so, PyObject *args) { - PySetObject *result; - PyObject *other; - Py_ssize_t i; + PySetObject *result; + PyObject *other; + Py_ssize_t i; - result = (PySetObject *)set_copy(so); - if (result == NULL) - return NULL; + result = (PySetObject *)set_copy(so); + if (result == NULL) + return NULL; - for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) { - other = PyTuple_GET_ITEM(args, i); - if ((PyObject *)so == other) - continue; - if (set_update_internal(result, other) == -1) { - Py_DECREF(result); - return NULL; - } - } - return (PyObject *)result; + for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) { + other = PyTuple_GET_ITEM(args, i); + if ((PyObject *)so == other) + continue; + if (set_update_internal(result, other) == -1) { + Py_DECREF(result); + return NULL; + } + } + return (PyObject *)result; } PyDoc_STRVAR(union_doc, @@ -1202,142 +1202,142 @@ PyDoc_STRVAR(union_doc, static PyObject * set_or(PySetObject *so, PyObject *other) { - PySetObject *result; + PySetObject *result; - if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } + if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } - result = (PySetObject *)set_copy(so); - if (result == NULL) - return NULL; - if ((PyObject *)so == other) - return (PyObject *)result; - if (set_update_internal(result, other) == -1) { - Py_DECREF(result); - return NULL; - } - return (PyObject *)result; + result = (PySetObject *)set_copy(so); + if (result == NULL) + return NULL; + if ((PyObject *)so == other) + return (PyObject *)result; + if (set_update_internal(result, other) == -1) { + Py_DECREF(result); + return NULL; + } + return (PyObject *)result; } static PyObject * set_ior(PySetObject *so, PyObject *other) { - if (!PyAnySet_Check(other)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - if (set_update_internal(so, other) == -1) - return NULL; - Py_INCREF(so); - return (PyObject *)so; + if (!PyAnySet_Check(other)) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + if (set_update_internal(so, other) == -1) + return NULL; + Py_INCREF(so); + return (PyObject *)so; } static PyObject * set_intersection(PySetObject *so, PyObject *other) { - PySetObject *result; - PyObject *key, *it, *tmp; - - if ((PyObject *)so == other) - return set_copy(so); - - result = (PySetObject *)make_new_set_basetype(Py_TYPE(so), NULL); - if (result == NULL) - return NULL; - - if (PyAnySet_Check(other)) { - Py_ssize_t pos = 0; - setentry *entry; - - if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) { - tmp = (PyObject *)so; - so = (PySetObject *)other; - other = tmp; - } - - while (set_next((PySetObject *)other, &pos, &entry)) { - int rv = set_contains_entry(so, entry); - if (rv == -1) { - Py_DECREF(result); - return NULL; - } - if (rv) { - if (set_add_entry(result, entry) == -1) { - Py_DECREF(result); - return NULL; - } - } - } - return (PyObject *)result; - } - - it = PyObject_GetIter(other); - if (it == NULL) { - Py_DECREF(result); - return NULL; - } - - while ((key = PyIter_Next(it)) != NULL) { - int rv; - setentry entry; - long hash = PyObject_Hash(key); - - if (hash == -1) { - Py_DECREF(it); - Py_DECREF(result); - Py_DECREF(key); - return NULL; - } - entry.hash = hash; - entry.key = key; - rv = set_contains_entry(so, &entry); - if (rv == -1) { - Py_DECREF(it); - Py_DECREF(result); - Py_DECREF(key); - return NULL; - } - if (rv) { - if (set_add_entry(result, &entry) == -1) { - Py_DECREF(it); - Py_DECREF(result); - Py_DECREF(key); - return NULL; - } - } - Py_DECREF(key); - } - Py_DECREF(it); - if (PyErr_Occurred()) { - Py_DECREF(result); - return NULL; - } - return (PyObject *)result; + PySetObject *result; + PyObject *key, *it, *tmp; + + if ((PyObject *)so == other) + return set_copy(so); + + result = (PySetObject *)make_new_set_basetype(Py_TYPE(so), NULL); + if (result == NULL) + return NULL; + + if (PyAnySet_Check(other)) { + Py_ssize_t pos = 0; + setentry *entry; + + if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) { + tmp = (PyObject *)so; + so = (PySetObject *)other; + other = tmp; + } + + while (set_next((PySetObject *)other, &pos, &entry)) { + int rv = set_contains_entry(so, entry); + if (rv == -1) { + Py_DECREF(result); + return NULL; + } + if (rv) { + if (set_add_entry(result, entry) == -1) { + Py_DECREF(result); + return NULL; + } + } + } + return (PyObject *)result; + } + + it = PyObject_GetIter(other); + if (it == NULL) { + Py_DECREF(result); + return NULL; + } + + while ((key = PyIter_Next(it)) != NULL) { + int rv; + setentry entry; + long hash = PyObject_Hash(key); + + if (hash == -1) { + Py_DECREF(it); + Py_DECREF(result); + Py_DECREF(key); + return NULL; + } + entry.hash = hash; + entry.key = key; + rv = set_contains_entry(so, &entry); + if (rv == -1) { + Py_DECREF(it); + Py_DECREF(result); + Py_DECREF(key); + return NULL; + } + if (rv) { + if (set_add_entry(result, &entry) == -1) { + Py_DECREF(it); + Py_DECREF(result); + Py_DECREF(key); + return NULL; + } + } + Py_DECREF(key); + } + Py_DECREF(it); + if (PyErr_Occurred()) { + Py_DECREF(result); + return NULL; + } + return (PyObject *)result; } static PyObject * set_intersection_multi(PySetObject *so, PyObject *args) { - Py_ssize_t i; - PyObject *result = (PyObject *)so; + Py_ssize_t i; + PyObject *result = (PyObject *)so; - if (PyTuple_GET_SIZE(args) == 0) - return set_copy(so); + if (PyTuple_GET_SIZE(args) == 0) + return set_copy(so); - Py_INCREF(so); - for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) { - PyObject *other = PyTuple_GET_ITEM(args, i); - PyObject *newresult = set_intersection((PySetObject *)result, other); - if (newresult == NULL) { - Py_DECREF(result); - return NULL; - } - Py_DECREF(result); - result = newresult; - } - return result; + Py_INCREF(so); + for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) { + PyObject *other = PyTuple_GET_ITEM(args, i); + PyObject *newresult = set_intersection((PySetObject *)result, other); + if (newresult == NULL) { + Py_DECREF(result); + return NULL; + } + Py_DECREF(result); + result = newresult; + } + return result; } PyDoc_STRVAR(intersection_doc, @@ -1348,27 +1348,27 @@ PyDoc_STRVAR(intersection_doc, static PyObject * set_intersection_update(PySetObject *so, PyObject *other) { - PyObject *tmp; + PyObject *tmp; - tmp = set_intersection(so, other); - if (tmp == NULL) - return NULL; - set_swap_bodies(so, (PySetObject *)tmp); - Py_DECREF(tmp); - Py_RETURN_NONE; + tmp = set_intersection(so, other); + if (tmp == NULL) + return NULL; + set_swap_bodies(so, (PySetObject *)tmp); + Py_DECREF(tmp); + Py_RETURN_NONE; } static PyObject * set_intersection_update_multi(PySetObject *so, PyObject *args) { - PyObject *tmp; + PyObject *tmp; - tmp = set_intersection_multi(so, args); - if (tmp == NULL) - return NULL; - set_swap_bodies(so, (PySetObject *)tmp); - Py_DECREF(tmp); - Py_RETURN_NONE; + tmp = set_intersection_multi(so, args); + if (tmp == NULL) + return NULL; + set_swap_bodies(so, (PySetObject *)tmp); + Py_DECREF(tmp); + Py_RETURN_NONE; } PyDoc_STRVAR(intersection_update_doc, @@ -1377,92 +1377,92 @@ PyDoc_STRVAR(intersection_update_doc, static PyObject * set_and(PySetObject *so, PyObject *other) { - if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - return set_intersection(so, other); + if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + return set_intersection(so, other); } static PyObject * set_iand(PySetObject *so, PyObject *other) { - PyObject *result; + PyObject *result; - if (!PyAnySet_Check(other)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - result = set_intersection_update(so, other); - if (result == NULL) - return NULL; - Py_DECREF(result); - Py_INCREF(so); - return (PyObject *)so; + if (!PyAnySet_Check(other)) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + result = set_intersection_update(so, other); + if (result == NULL) + return NULL; + Py_DECREF(result); + Py_INCREF(so); + return (PyObject *)so; } static PyObject * set_isdisjoint(PySetObject *so, PyObject *other) { - PyObject *key, *it, *tmp; - - if ((PyObject *)so == other) { - if (PySet_GET_SIZE(so) == 0) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; - } - - if (PyAnySet_CheckExact(other)) { - Py_ssize_t pos = 0; - setentry *entry; - - if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) { - tmp = (PyObject *)so; - so = (PySetObject *)other; - other = tmp; - } - while (set_next((PySetObject *)other, &pos, &entry)) { - int rv = set_contains_entry(so, entry); - if (rv == -1) - return NULL; - if (rv) - Py_RETURN_FALSE; - } - Py_RETURN_TRUE; - } - - it = PyObject_GetIter(other); - if (it == NULL) - return NULL; - - while ((key = PyIter_Next(it)) != NULL) { - int rv; - setentry entry; - long hash = PyObject_Hash(key);; - - if (hash == -1) { - Py_DECREF(key); - Py_DECREF(it); - return NULL; - } - entry.hash = hash; - entry.key = key; - rv = set_contains_entry(so, &entry); - Py_DECREF(key); - if (rv == -1) { - Py_DECREF(it); - return NULL; - } - if (rv) { - Py_DECREF(it); - Py_RETURN_FALSE; - } - } - Py_DECREF(it); - if (PyErr_Occurred()) - return NULL; - Py_RETURN_TRUE; + PyObject *key, *it, *tmp; + + if ((PyObject *)so == other) { + if (PySet_GET_SIZE(so) == 0) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; + } + + if (PyAnySet_CheckExact(other)) { + Py_ssize_t pos = 0; + setentry *entry; + + if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) { + tmp = (PyObject *)so; + so = (PySetObject *)other; + other = tmp; + } + while (set_next((PySetObject *)other, &pos, &entry)) { + int rv = set_contains_entry(so, entry); + if (rv == -1) + return NULL; + if (rv) + Py_RETURN_FALSE; + } + Py_RETURN_TRUE; + } + + it = PyObject_GetIter(other); + if (it == NULL) + return NULL; + + while ((key = PyIter_Next(it)) != NULL) { + int rv; + setentry entry; + long hash = PyObject_Hash(key);; + + if (hash == -1) { + Py_DECREF(key); + Py_DECREF(it); + return NULL; + } + entry.hash = hash; + entry.key = key; + rv = set_contains_entry(so, &entry); + Py_DECREF(key); + if (rv == -1) { + Py_DECREF(it); + return NULL; + } + if (rv) { + Py_DECREF(it); + Py_RETURN_FALSE; + } + } + Py_DECREF(it); + if (PyErr_Occurred()) + return NULL; + Py_RETURN_TRUE; } PyDoc_STRVAR(isdisjoint_doc, @@ -1471,51 +1471,51 @@ PyDoc_STRVAR(isdisjoint_doc, static int set_difference_update_internal(PySetObject *so, PyObject *other) { - if ((PyObject *)so == other) - return set_clear_internal(so); - - if (PyAnySet_Check(other)) { - setentry *entry; - Py_ssize_t pos = 0; - - while (set_next((PySetObject *)other, &pos, &entry)) - if (set_discard_entry(so, entry) == -1) - return -1; - } else { - PyObject *key, *it; - it = PyObject_GetIter(other); - if (it == NULL) - return -1; - - while ((key = PyIter_Next(it)) != NULL) { - if (set_discard_key(so, key) == -1) { - Py_DECREF(it); - Py_DECREF(key); - return -1; - } - Py_DECREF(key); - } - Py_DECREF(it); - if (PyErr_Occurred()) - return -1; - } - /* If more than 1/5 are dummies, then resize them away. */ - if ((so->fill - so->used) * 5 < so->mask) - return 0; - return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4); + if ((PyObject *)so == other) + return set_clear_internal(so); + + if (PyAnySet_Check(other)) { + setentry *entry; + Py_ssize_t pos = 0; + + while (set_next((PySetObject *)other, &pos, &entry)) + if (set_discard_entry(so, entry) == -1) + return -1; + } else { + PyObject *key, *it; + it = PyObject_GetIter(other); + if (it == NULL) + return -1; + + while ((key = PyIter_Next(it)) != NULL) { + if (set_discard_key(so, key) == -1) { + Py_DECREF(it); + Py_DECREF(key); + return -1; + } + Py_DECREF(key); + } + Py_DECREF(it); + if (PyErr_Occurred()) + return -1; + } + /* If more than 1/5 are dummies, then resize them away. */ + if ((so->fill - so->used) * 5 < so->mask) + return 0; + return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4); } static PyObject * set_difference_update(PySetObject *so, PyObject *args) { - Py_ssize_t i; + Py_ssize_t i; - for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) { - PyObject *other = PyTuple_GET_ITEM(args, i); - if (set_difference_update_internal(so, other) == -1) - return NULL; - } - Py_RETURN_NONE; + for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) { + PyObject *other = PyTuple_GET_ITEM(args, i); + if (set_difference_update_internal(so, other) == -1) + return NULL; + } + Py_RETURN_NONE; } PyDoc_STRVAR(difference_update_doc, @@ -1524,77 +1524,77 @@ PyDoc_STRVAR(difference_update_doc, static PyObject * set_difference(PySetObject *so, PyObject *other) { - PyObject *result; - setentry *entry; - Py_ssize_t pos = 0; - - if (!PyAnySet_Check(other) && !PyDict_CheckExact(other)) { - result = set_copy(so); - if (result == NULL) - return NULL; - if (set_difference_update_internal((PySetObject *)result, other) != -1) - return result; - Py_DECREF(result); - return NULL; - } - - result = make_new_set_basetype(Py_TYPE(so), NULL); - if (result == NULL) - return NULL; - - if (PyDict_CheckExact(other)) { - while (set_next(so, &pos, &entry)) { - setentry entrycopy; - entrycopy.hash = entry->hash; - entrycopy.key = entry->key; - if (!_PyDict_Contains(other, entry->key, entry->hash)) { - if (set_add_entry((PySetObject *)result, &entrycopy) == -1) { - Py_DECREF(result); - return NULL; - } - } - } - return result; - } - - while (set_next(so, &pos, &entry)) { - int rv = set_contains_entry((PySetObject *)other, entry); - if (rv == -1) { - Py_DECREF(result); - return NULL; - } - if (!rv) { - if (set_add_entry((PySetObject *)result, entry) == -1) { - Py_DECREF(result); - return NULL; - } - } - } - return result; + PyObject *result; + setentry *entry; + Py_ssize_t pos = 0; + + if (!PyAnySet_Check(other) && !PyDict_CheckExact(other)) { + result = set_copy(so); + if (result == NULL) + return NULL; + if (set_difference_update_internal((PySetObject *)result, other) != -1) + return result; + Py_DECREF(result); + return NULL; + } + + result = make_new_set_basetype(Py_TYPE(so), NULL); + if (result == NULL) + return NULL; + + if (PyDict_CheckExact(other)) { + while (set_next(so, &pos, &entry)) { + setentry entrycopy; + entrycopy.hash = entry->hash; + entrycopy.key = entry->key; + if (!_PyDict_Contains(other, entry->key, entry->hash)) { + if (set_add_entry((PySetObject *)result, &entrycopy) == -1) { + Py_DECREF(result); + return NULL; + } + } + } + return result; + } + + while (set_next(so, &pos, &entry)) { + int rv = set_contains_entry((PySetObject *)other, entry); + if (rv == -1) { + Py_DECREF(result); + return NULL; + } + if (!rv) { + if (set_add_entry((PySetObject *)result, entry) == -1) { + Py_DECREF(result); + return NULL; + } + } + } + return result; } static PyObject * set_difference_multi(PySetObject *so, PyObject *args) { - Py_ssize_t i; - PyObject *result, *other; + Py_ssize_t i; + PyObject *result, *other; - if (PyTuple_GET_SIZE(args) == 0) - return set_copy(so); + if (PyTuple_GET_SIZE(args) == 0) + return set_copy(so); - other = PyTuple_GET_ITEM(args, 0); - result = set_difference(so, other); - if (result == NULL) - return NULL; + other = PyTuple_GET_ITEM(args, 0); + result = set_difference(so, other); + if (result == NULL) + return NULL; - for (i=1 ; i<PyTuple_GET_SIZE(args) ; i++) { - other = PyTuple_GET_ITEM(args, i); - if (set_difference_update_internal((PySetObject *)result, other) == -1) { - Py_DECREF(result); - return NULL; - } - } - return result; + for (i=1 ; i<PyTuple_GET_SIZE(args) ; i++) { + other = PyTuple_GET_ITEM(args, i); + if (set_difference_update_internal((PySetObject *)result, other) == -1) { + Py_DECREF(result); + return NULL; + } + } + return result; } PyDoc_STRVAR(difference_doc, @@ -1604,81 +1604,81 @@ PyDoc_STRVAR(difference_doc, static PyObject * set_sub(PySetObject *so, PyObject *other) { - if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - return set_difference(so, other); + if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + return set_difference(so, other); } static PyObject * set_isub(PySetObject *so, PyObject *other) { - if (!PyAnySet_Check(other)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - if (set_difference_update_internal(so, other) == -1) - return NULL; - Py_INCREF(so); - return (PyObject *)so; + if (!PyAnySet_Check(other)) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + if (set_difference_update_internal(so, other) == -1) + return NULL; + Py_INCREF(so); + return (PyObject *)so; } static PyObject * set_symmetric_difference_update(PySetObject *so, PyObject *other) { - PySetObject *otherset; - PyObject *key; - Py_ssize_t pos = 0; - setentry *entry; - - if ((PyObject *)so == other) - return set_clear(so); - - if (PyDict_CheckExact(other)) { - PyObject *value; - int rv; - long hash; - while (_PyDict_Next(other, &pos, &key, &value, &hash)) { - setentry an_entry; - - an_entry.hash = hash; - an_entry.key = key; - rv = set_discard_entry(so, &an_entry); - if (rv == -1) - return NULL; - if (rv == DISCARD_NOTFOUND) { - if (set_add_entry(so, &an_entry) == -1) - return NULL; - } - } - Py_RETURN_NONE; - } - - if (PyAnySet_Check(other)) { - Py_INCREF(other); - otherset = (PySetObject *)other; - } else { - otherset = (PySetObject *)make_new_set_basetype(Py_TYPE(so), other); - if (otherset == NULL) - return NULL; - } - - while (set_next(otherset, &pos, &entry)) { - int rv = set_discard_entry(so, entry); - if (rv == -1) { - Py_DECREF(otherset); - return NULL; - } - if (rv == DISCARD_NOTFOUND) { - if (set_add_entry(so, entry) == -1) { - Py_DECREF(otherset); - return NULL; - } - } - } - Py_DECREF(otherset); - Py_RETURN_NONE; + PySetObject *otherset; + PyObject *key; + Py_ssize_t pos = 0; + setentry *entry; + + if ((PyObject *)so == other) + return set_clear(so); + + if (PyDict_CheckExact(other)) { + PyObject *value; + int rv; + long hash; + while (_PyDict_Next(other, &pos, &key, &value, &hash)) { + setentry an_entry; + + an_entry.hash = hash; + an_entry.key = key; + rv = set_discard_entry(so, &an_entry); + if (rv == -1) + return NULL; + if (rv == DISCARD_NOTFOUND) { + if (set_add_entry(so, &an_entry) == -1) + return NULL; + } + } + Py_RETURN_NONE; + } + + if (PyAnySet_Check(other)) { + Py_INCREF(other); + otherset = (PySetObject *)other; + } else { + otherset = (PySetObject *)make_new_set_basetype(Py_TYPE(so), other); + if (otherset == NULL) + return NULL; + } + + while (set_next(otherset, &pos, &entry)) { + int rv = set_discard_entry(so, entry); + if (rv == -1) { + Py_DECREF(otherset); + return NULL; + } + if (rv == DISCARD_NOTFOUND) { + if (set_add_entry(so, entry) == -1) { + Py_DECREF(otherset); + return NULL; + } + } + } + Py_DECREF(otherset); + Py_RETURN_NONE; } PyDoc_STRVAR(symmetric_difference_update_doc, @@ -1687,17 +1687,17 @@ PyDoc_STRVAR(symmetric_difference_update_doc, static PyObject * set_symmetric_difference(PySetObject *so, PyObject *other) { - PyObject *rv; - PySetObject *otherset; + PyObject *rv; + PySetObject *otherset; - otherset = (PySetObject *)make_new_set_basetype(Py_TYPE(so), other); - if (otherset == NULL) - return NULL; - rv = set_symmetric_difference_update(otherset, (PyObject *)so); - if (rv == NULL) - return NULL; - Py_DECREF(rv); - return (PyObject *)otherset; + otherset = (PySetObject *)make_new_set_basetype(Py_TYPE(so), other); + if (otherset == NULL) + return NULL; + rv = set_symmetric_difference_update(otherset, (PyObject *)so); + if (rv == NULL) + return NULL; + Py_DECREF(rv); + return (PyObject *)otherset; } PyDoc_STRVAR(symmetric_difference_doc, @@ -1708,56 +1708,56 @@ PyDoc_STRVAR(symmetric_difference_doc, static PyObject * set_xor(PySetObject *so, PyObject *other) { - if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - return set_symmetric_difference(so, other); + if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + return set_symmetric_difference(so, other); } static PyObject * set_ixor(PySetObject *so, PyObject *other) { - PyObject *result; + PyObject *result; - if (!PyAnySet_Check(other)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - result = set_symmetric_difference_update(so, other); - if (result == NULL) - return NULL; - Py_DECREF(result); - Py_INCREF(so); - return (PyObject *)so; + if (!PyAnySet_Check(other)) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + result = set_symmetric_difference_update(so, other); + if (result == NULL) + return NULL; + Py_DECREF(result); + Py_INCREF(so); + return (PyObject *)so; } static PyObject * set_issubset(PySetObject *so, PyObject *other) { - setentry *entry; - Py_ssize_t pos = 0; - - if (!PyAnySet_Check(other)) { - PyObject *tmp, *result; - tmp = make_new_set(&PySet_Type, other); - if (tmp == NULL) - return NULL; - result = set_issubset(so, tmp); - Py_DECREF(tmp); - return result; - } - if (PySet_GET_SIZE(so) > PySet_GET_SIZE(other)) - Py_RETURN_FALSE; - - while (set_next(so, &pos, &entry)) { - int rv = set_contains_entry((PySetObject *)other, entry); - if (rv == -1) - return NULL; - if (!rv) - Py_RETURN_FALSE; - } - Py_RETURN_TRUE; + setentry *entry; + Py_ssize_t pos = 0; + + if (!PyAnySet_Check(other)) { + PyObject *tmp, *result; + tmp = make_new_set(&PySet_Type, other); + if (tmp == NULL) + return NULL; + result = set_issubset(so, tmp); + Py_DECREF(tmp); + return result; + } + if (PySet_GET_SIZE(so) > PySet_GET_SIZE(other)) + Py_RETURN_FALSE; + + while (set_next(so, &pos, &entry)) { + int rv = set_contains_entry((PySetObject *)other, entry); + if (rv == -1) + return NULL; + if (!rv) + Py_RETURN_FALSE; + } + Py_RETURN_TRUE; } PyDoc_STRVAR(issubset_doc, "Report whether another set contains this set."); @@ -1765,17 +1765,17 @@ PyDoc_STRVAR(issubset_doc, "Report whether another set contains this set."); static PyObject * set_issuperset(PySetObject *so, PyObject *other) { - PyObject *tmp, *result; + PyObject *tmp, *result; - if (!PyAnySet_Check(other)) { - tmp = make_new_set(&PySet_Type, other); - if (tmp == NULL) - return NULL; - result = set_issuperset(so, tmp); - Py_DECREF(tmp); - return result; - } - return set_issubset((PySetObject *)other, (PyObject *)so); + if (!PyAnySet_Check(other)) { + tmp = make_new_set(&PySet_Type, other); + if (tmp == NULL) + return NULL; + result = set_issuperset(so, tmp); + Py_DECREF(tmp); + return result; + } + return set_issubset((PySetObject *)other, (PyObject *)so); } PyDoc_STRVAR(issuperset_doc, "Report whether this set contains another set."); @@ -1783,54 +1783,54 @@ PyDoc_STRVAR(issuperset_doc, "Report whether this set contains another set."); static PyObject * set_richcompare(PySetObject *v, PyObject *w, int op) { - PyObject *r1, *r2; - - if(!PyAnySet_Check(w)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - switch (op) { - case Py_EQ: - if (PySet_GET_SIZE(v) != PySet_GET_SIZE(w)) - Py_RETURN_FALSE; - if (v->hash != -1 && - ((PySetObject *)w)->hash != -1 && - v->hash != ((PySetObject *)w)->hash) - Py_RETURN_FALSE; - return set_issubset(v, w); - case Py_NE: - r1 = set_richcompare(v, w, Py_EQ); - if (r1 == NULL) - return NULL; - r2 = PyBool_FromLong(PyObject_Not(r1)); - Py_DECREF(r1); - return r2; - case Py_LE: - return set_issubset(v, w); - case Py_GE: - return set_issuperset(v, w); - case Py_LT: - if (PySet_GET_SIZE(v) >= PySet_GET_SIZE(w)) - Py_RETURN_FALSE; - return set_issubset(v, w); - case Py_GT: - if (PySet_GET_SIZE(v) <= PySet_GET_SIZE(w)) - Py_RETURN_FALSE; - return set_issuperset(v, w); - } - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; + PyObject *r1, *r2; + + if(!PyAnySet_Check(w)) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + switch (op) { + case Py_EQ: + if (PySet_GET_SIZE(v) != PySet_GET_SIZE(w)) + Py_RETURN_FALSE; + if (v->hash != -1 && + ((PySetObject *)w)->hash != -1 && + v->hash != ((PySetObject *)w)->hash) + Py_RETURN_FALSE; + return set_issubset(v, w); + case Py_NE: + r1 = set_richcompare(v, w, Py_EQ); + if (r1 == NULL) + return NULL; + r2 = PyBool_FromLong(PyObject_Not(r1)); + Py_DECREF(r1); + return r2; + case Py_LE: + return set_issubset(v, w); + case Py_GE: + return set_issuperset(v, w); + case Py_LT: + if (PySet_GET_SIZE(v) >= PySet_GET_SIZE(w)) + Py_RETURN_FALSE; + return set_issubset(v, w); + case Py_GT: + if (PySet_GET_SIZE(v) <= PySet_GET_SIZE(w)) + Py_RETURN_FALSE; + return set_issuperset(v, w); + } + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; } static PyObject * set_add(PySetObject *so, PyObject *key) { - if (set_add_key(so, key) == -1) - return NULL; - Py_RETURN_NONE; + if (set_add_key(so, key) == -1) + return NULL; + Py_RETURN_NONE; } -PyDoc_STRVAR(add_doc, +PyDoc_STRVAR(add_doc, "Add an element to a set.\n\ \n\ This has no effect if the element is already present."); @@ -1838,34 +1838,34 @@ This has no effect if the element is already present."); static int set_contains(PySetObject *so, PyObject *key) { - PyObject *tmpkey; - int rv; - - rv = set_contains_key(so, key); - if (rv == -1) { - if (!PySet_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; + PyObject *tmpkey; + int rv; + + rv = set_contains_key(so, key); + if (rv == -1) { + if (!PySet_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; } static PyObject * set_direct_contains(PySetObject *so, PyObject *key) { - long result; + long result; - result = set_contains(so, key); - if (result == -1) - return NULL; - return PyBool_FromLong(result); + result = set_contains(so, key); + if (result == -1) + return NULL; + return PyBool_FromLong(result); } PyDoc_STRVAR(contains_doc, "x.__contains__(y) <==> y in x."); @@ -1873,30 +1873,30 @@ PyDoc_STRVAR(contains_doc, "x.__contains__(y) <==> y in x."); static PyObject * set_remove(PySetObject *so, PyObject *key) { - PyObject *tmpkey; - int rv; - - rv = set_discard_key(so, key); - if (rv == -1) { - if (!PySet_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); - rv = set_discard_key(so, tmpkey); - set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key); - Py_DECREF(tmpkey); - if (rv == -1) - return NULL; - } - - if (rv == DISCARD_NOTFOUND) { - set_key_error(key); - return NULL; - } - Py_RETURN_NONE; + PyObject *tmpkey; + int rv; + + rv = set_discard_key(so, key); + if (rv == -1) { + if (!PySet_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); + rv = set_discard_key(so, tmpkey); + set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key); + Py_DECREF(tmpkey); + if (rv == -1) + return NULL; + } + + if (rv == DISCARD_NOTFOUND) { + set_key_error(key); + return NULL; + } + Py_RETURN_NONE; } PyDoc_STRVAR(remove_doc, @@ -1907,54 +1907,54 @@ If the element is not a member, raise a KeyError."); static PyObject * set_discard(PySetObject *so, PyObject *key) { - PyObject *tmpkey, *result; - int rv; - - rv = set_discard_key(so, key); - if (rv == -1) { - if (!PySet_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; - } - Py_RETURN_NONE; + PyObject *tmpkey, *result; + int rv; + + rv = set_discard_key(so, key); + if (rv == -1) { + if (!PySet_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; + } + Py_RETURN_NONE; } PyDoc_STRVAR(discard_doc, "Remove an element from a set if it is a member.\n\ \n\ -If the element is not a member, do nothing."); +If the element is not a member, do nothing."); static PyObject * set_reduce(PySetObject *so) { - PyObject *keys=NULL, *args=NULL, *result=NULL, *dict=NULL; - - keys = PySequence_List((PyObject *)so); - if (keys == NULL) - goto done; - args = PyTuple_Pack(1, keys); - if (args == NULL) - goto done; - dict = PyObject_GetAttrString((PyObject *)so, "__dict__"); - if (dict == NULL) { - PyErr_Clear(); - dict = Py_None; - Py_INCREF(dict); - } - result = PyTuple_Pack(3, Py_TYPE(so), args, dict); + PyObject *keys=NULL, *args=NULL, *result=NULL, *dict=NULL; + + keys = PySequence_List((PyObject *)so); + if (keys == NULL) + goto done; + args = PyTuple_Pack(1, keys); + if (args == NULL) + goto done; + dict = PyObject_GetAttrString((PyObject *)so, "__dict__"); + if (dict == NULL) { + PyErr_Clear(); + dict = Py_None; + Py_INCREF(dict); + } + result = PyTuple_Pack(3, Py_TYPE(so), args, dict); done: - Py_XDECREF(args); - Py_XDECREF(keys); - Py_XDECREF(dict); - return result; + Py_XDECREF(args); + Py_XDECREF(keys); + Py_XDECREF(dict); + return result; } PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); @@ -1962,42 +1962,42 @@ PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); static PyObject * set_sizeof(PySetObject *so) { - Py_ssize_t res; + Py_ssize_t res; - res = sizeof(PySetObject); - if (so->table != so->smalltable) - res = res + (so->mask + 1) * sizeof(setentry); - return PyLong_FromSsize_t(res); + res = sizeof(PySetObject); + if (so->table != so->smalltable) + res = res + (so->mask + 1) * sizeof(setentry); + return PyLong_FromSsize_t(res); } PyDoc_STRVAR(sizeof_doc, "S.__sizeof__() -> size of S in memory, in bytes"); static int set_init(PySetObject *self, PyObject *args, PyObject *kwds) { - PyObject *iterable = NULL; + PyObject *iterable = NULL; - if (!PyAnySet_Check(self)) - return -1; - if (PySet_Check(self) && !_PyArg_NoKeywords("set()", kwds)) - return -1; - if (!PyArg_UnpackTuple(args, Py_TYPE(self)->tp_name, 0, 1, &iterable)) - return -1; - set_clear_internal(self); - self->hash = -1; - if (iterable == NULL) - return 0; - return set_update_internal(self, iterable); + if (!PyAnySet_Check(self)) + return -1; + if (PySet_Check(self) && !_PyArg_NoKeywords("set()", kwds)) + return -1; + if (!PyArg_UnpackTuple(args, Py_TYPE(self)->tp_name, 0, 1, &iterable)) + return -1; + set_clear_internal(self); + self->hash = -1; + if (iterable == NULL) + return 0; + return set_update_internal(self, iterable); } static PySequenceMethods set_as_sequence = { - set_len, /* sq_length */ - 0, /* sq_concat */ - 0, /* sq_repeat */ - 0, /* sq_item */ - 0, /* sq_slice */ - 0, /* sq_ass_item */ - 0, /* sq_ass_slice */ - (objobjproc)set_contains, /* sq_contains */ + set_len, /* sq_length */ + 0, /* sq_concat */ + 0, /* sq_repeat */ + 0, /* sq_item */ + 0, /* sq_slice */ + 0, /* sq_ass_item */ + 0, /* sq_ass_slice */ + (objobjproc)set_contains, /* sq_contains */ }; /* set object ********************************************************/ @@ -2010,83 +2010,83 @@ All is well if assertions don't fail."); #endif static PyMethodDef set_methods[] = { - {"add", (PyCFunction)set_add, METH_O, - add_doc}, - {"clear", (PyCFunction)set_clear, METH_NOARGS, - clear_doc}, - {"__contains__",(PyCFunction)set_direct_contains, METH_O | METH_COEXIST, - contains_doc}, - {"copy", (PyCFunction)set_copy, METH_NOARGS, - copy_doc}, - {"discard", (PyCFunction)set_discard, METH_O, - discard_doc}, - {"difference", (PyCFunction)set_difference_multi, METH_VARARGS, - difference_doc}, - {"difference_update", (PyCFunction)set_difference_update, METH_VARARGS, - difference_update_doc}, - {"intersection",(PyCFunction)set_intersection_multi, METH_VARARGS, - intersection_doc}, - {"intersection_update",(PyCFunction)set_intersection_update_multi, METH_VARARGS, - intersection_update_doc}, - {"isdisjoint", (PyCFunction)set_isdisjoint, METH_O, - isdisjoint_doc}, - {"issubset", (PyCFunction)set_issubset, METH_O, - issubset_doc}, - {"issuperset", (PyCFunction)set_issuperset, METH_O, - issuperset_doc}, - {"pop", (PyCFunction)set_pop, METH_NOARGS, - pop_doc}, - {"__reduce__", (PyCFunction)set_reduce, METH_NOARGS, - reduce_doc}, - {"remove", (PyCFunction)set_remove, METH_O, - remove_doc}, - {"__sizeof__", (PyCFunction)set_sizeof, METH_NOARGS, - sizeof_doc}, - {"symmetric_difference",(PyCFunction)set_symmetric_difference, METH_O, - symmetric_difference_doc}, - {"symmetric_difference_update",(PyCFunction)set_symmetric_difference_update, METH_O, - symmetric_difference_update_doc}, + {"add", (PyCFunction)set_add, METH_O, + add_doc}, + {"clear", (PyCFunction)set_clear, METH_NOARGS, + clear_doc}, + {"__contains__",(PyCFunction)set_direct_contains, METH_O | METH_COEXIST, + contains_doc}, + {"copy", (PyCFunction)set_copy, METH_NOARGS, + copy_doc}, + {"discard", (PyCFunction)set_discard, METH_O, + discard_doc}, + {"difference", (PyCFunction)set_difference_multi, METH_VARARGS, + difference_doc}, + {"difference_update", (PyCFunction)set_difference_update, METH_VARARGS, + difference_update_doc}, + {"intersection",(PyCFunction)set_intersection_multi, METH_VARARGS, + intersection_doc}, + {"intersection_update",(PyCFunction)set_intersection_update_multi, METH_VARARGS, + intersection_update_doc}, + {"isdisjoint", (PyCFunction)set_isdisjoint, METH_O, + isdisjoint_doc}, + {"issubset", (PyCFunction)set_issubset, METH_O, + issubset_doc}, + {"issuperset", (PyCFunction)set_issuperset, METH_O, + issuperset_doc}, + {"pop", (PyCFunction)set_pop, METH_NOARGS, + pop_doc}, + {"__reduce__", (PyCFunction)set_reduce, METH_NOARGS, + reduce_doc}, + {"remove", (PyCFunction)set_remove, METH_O, + remove_doc}, + {"__sizeof__", (PyCFunction)set_sizeof, METH_NOARGS, + sizeof_doc}, + {"symmetric_difference",(PyCFunction)set_symmetric_difference, METH_O, + symmetric_difference_doc}, + {"symmetric_difference_update",(PyCFunction)set_symmetric_difference_update, METH_O, + symmetric_difference_update_doc}, #ifdef Py_DEBUG - {"test_c_api", (PyCFunction)test_c_api, METH_NOARGS, - test_c_api_doc}, + {"test_c_api", (PyCFunction)test_c_api, METH_NOARGS, + test_c_api_doc}, #endif - {"union", (PyCFunction)set_union, METH_VARARGS, - union_doc}, - {"update", (PyCFunction)set_update, METH_VARARGS, - update_doc}, - {NULL, NULL} /* sentinel */ + {"union", (PyCFunction)set_union, METH_VARARGS, + union_doc}, + {"update", (PyCFunction)set_update, METH_VARARGS, + update_doc}, + {NULL, NULL} /* sentinel */ }; static PyNumberMethods set_as_number = { - 0, /*nb_add*/ - (binaryfunc)set_sub, /*nb_subtract*/ - 0, /*nb_multiply*/ - 0, /*nb_remainder*/ - 0, /*nb_divmod*/ - 0, /*nb_power*/ - 0, /*nb_negative*/ - 0, /*nb_positive*/ - 0, /*nb_absolute*/ - 0, /*nb_bool*/ - 0, /*nb_invert*/ - 0, /*nb_lshift*/ - 0, /*nb_rshift*/ - (binaryfunc)set_and, /*nb_and*/ - (binaryfunc)set_xor, /*nb_xor*/ - (binaryfunc)set_or, /*nb_or*/ - 0, /*nb_int*/ - 0, /*nb_reserved*/ - 0, /*nb_float*/ - 0, /*nb_inplace_add*/ - (binaryfunc)set_isub, /*nb_inplace_subtract*/ - 0, /*nb_inplace_multiply*/ - 0, /*nb_inplace_remainder*/ - 0, /*nb_inplace_power*/ - 0, /*nb_inplace_lshift*/ - 0, /*nb_inplace_rshift*/ - (binaryfunc)set_iand, /*nb_inplace_and*/ - (binaryfunc)set_ixor, /*nb_inplace_xor*/ - (binaryfunc)set_ior, /*nb_inplace_or*/ + 0, /*nb_add*/ + (binaryfunc)set_sub, /*nb_subtract*/ + 0, /*nb_multiply*/ + 0, /*nb_remainder*/ + 0, /*nb_divmod*/ + 0, /*nb_power*/ + 0, /*nb_negative*/ + 0, /*nb_positive*/ + 0, /*nb_absolute*/ + 0, /*nb_bool*/ + 0, /*nb_invert*/ + 0, /*nb_lshift*/ + 0, /*nb_rshift*/ + (binaryfunc)set_and, /*nb_and*/ + (binaryfunc)set_xor, /*nb_xor*/ + (binaryfunc)set_or, /*nb_or*/ + 0, /*nb_int*/ + 0, /*nb_reserved*/ + 0, /*nb_float*/ + 0, /*nb_inplace_add*/ + (binaryfunc)set_isub, /*nb_inplace_subtract*/ + 0, /*nb_inplace_multiply*/ + 0, /*nb_inplace_remainder*/ + 0, /*nb_inplace_power*/ + 0, /*nb_inplace_lshift*/ + 0, /*nb_inplace_rshift*/ + (binaryfunc)set_iand, /*nb_inplace_and*/ + (binaryfunc)set_ixor, /*nb_inplace_xor*/ + (binaryfunc)set_ior, /*nb_inplace_or*/ }; PyDoc_STRVAR(set_doc, @@ -2096,95 +2096,95 @@ set(iterable) -> new set object\n\ Build an unordered collection of unique elements."); PyTypeObject PySet_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "set", /* tp_name */ - sizeof(PySetObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)set_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)set_repr, /* tp_repr */ - &set_as_number, /* tp_as_number */ - &set_as_sequence, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)PyObject_HashNotImplemented, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - set_doc, /* tp_doc */ - (traverseproc)set_traverse, /* tp_traverse */ - (inquiry)set_clear_internal, /* tp_clear */ - (richcmpfunc)set_richcompare, /* tp_richcompare */ - offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */ - (getiterfunc)set_iter, /* tp_iter */ - 0, /* tp_iternext */ - set_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)set_init, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - set_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "set", /* tp_name */ + sizeof(PySetObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)set_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)set_repr, /* tp_repr */ + &set_as_number, /* tp_as_number */ + &set_as_sequence, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + (hashfunc)PyObject_HashNotImplemented, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_BASETYPE, /* tp_flags */ + set_doc, /* tp_doc */ + (traverseproc)set_traverse, /* tp_traverse */ + (inquiry)set_clear_internal, /* tp_clear */ + (richcmpfunc)set_richcompare, /* tp_richcompare */ + offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */ + (getiterfunc)set_iter, /* tp_iter */ + 0, /* tp_iternext */ + set_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)set_init, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + set_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ }; /* frozenset object ********************************************************/ static PyMethodDef frozenset_methods[] = { - {"__contains__",(PyCFunction)set_direct_contains, METH_O | METH_COEXIST, - contains_doc}, - {"copy", (PyCFunction)frozenset_copy, METH_NOARGS, - copy_doc}, - {"difference", (PyCFunction)set_difference_multi, METH_VARARGS, - difference_doc}, - {"intersection",(PyCFunction)set_intersection_multi, METH_VARARGS, - intersection_doc}, - {"isdisjoint", (PyCFunction)set_isdisjoint, METH_O, - isdisjoint_doc}, - {"issubset", (PyCFunction)set_issubset, METH_O, - issubset_doc}, - {"issuperset", (PyCFunction)set_issuperset, METH_O, - issuperset_doc}, - {"__reduce__", (PyCFunction)set_reduce, METH_NOARGS, - reduce_doc}, - {"__sizeof__", (PyCFunction)set_sizeof, METH_NOARGS, - sizeof_doc}, - {"symmetric_difference",(PyCFunction)set_symmetric_difference, METH_O, - symmetric_difference_doc}, - {"union", (PyCFunction)set_union, METH_VARARGS, - union_doc}, - {NULL, NULL} /* sentinel */ + {"__contains__",(PyCFunction)set_direct_contains, METH_O | METH_COEXIST, + contains_doc}, + {"copy", (PyCFunction)frozenset_copy, METH_NOARGS, + copy_doc}, + {"difference", (PyCFunction)set_difference_multi, METH_VARARGS, + difference_doc}, + {"intersection",(PyCFunction)set_intersection_multi, METH_VARARGS, + intersection_doc}, + {"isdisjoint", (PyCFunction)set_isdisjoint, METH_O, + isdisjoint_doc}, + {"issubset", (PyCFunction)set_issubset, METH_O, + issubset_doc}, + {"issuperset", (PyCFunction)set_issuperset, METH_O, + issuperset_doc}, + {"__reduce__", (PyCFunction)set_reduce, METH_NOARGS, + reduce_doc}, + {"__sizeof__", (PyCFunction)set_sizeof, METH_NOARGS, + sizeof_doc}, + {"symmetric_difference",(PyCFunction)set_symmetric_difference, METH_O, + symmetric_difference_doc}, + {"union", (PyCFunction)set_union, METH_VARARGS, + union_doc}, + {NULL, NULL} /* sentinel */ }; static PyNumberMethods frozenset_as_number = { - 0, /*nb_add*/ - (binaryfunc)set_sub, /*nb_subtract*/ - 0, /*nb_multiply*/ - 0, /*nb_remainder*/ - 0, /*nb_divmod*/ - 0, /*nb_power*/ - 0, /*nb_negative*/ - 0, /*nb_positive*/ - 0, /*nb_absolute*/ - 0, /*nb_bool*/ - 0, /*nb_invert*/ - 0, /*nb_lshift*/ - 0, /*nb_rshift*/ - (binaryfunc)set_and, /*nb_and*/ - (binaryfunc)set_xor, /*nb_xor*/ - (binaryfunc)set_or, /*nb_or*/ + 0, /*nb_add*/ + (binaryfunc)set_sub, /*nb_subtract*/ + 0, /*nb_multiply*/ + 0, /*nb_remainder*/ + 0, /*nb_divmod*/ + 0, /*nb_power*/ + 0, /*nb_negative*/ + 0, /*nb_positive*/ + 0, /*nb_absolute*/ + 0, /*nb_bool*/ + 0, /*nb_invert*/ + 0, /*nb_lshift*/ + 0, /*nb_rshift*/ + (binaryfunc)set_and, /*nb_and*/ + (binaryfunc)set_xor, /*nb_xor*/ + (binaryfunc)set_or, /*nb_or*/ }; PyDoc_STRVAR(frozenset_doc, @@ -2194,47 +2194,47 @@ frozenset(iterable) -> frozenset object\n\ Build an immutable unordered collection of unique elements."); PyTypeObject PyFrozenSet_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "frozenset", /* tp_name */ - sizeof(PySetObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)set_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)set_repr, /* tp_repr */ - &frozenset_as_number, /* tp_as_number */ - &set_as_sequence, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - frozenset_hash, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - frozenset_doc, /* tp_doc */ - (traverseproc)set_traverse, /* tp_traverse */ - (inquiry)set_clear_internal, /* tp_clear */ - (richcmpfunc)set_richcompare, /* tp_richcompare */ - offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */ - (getiterfunc)set_iter, /* tp_iter */ - 0, /* tp_iternext */ - frozenset_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - frozenset_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "frozenset", /* tp_name */ + sizeof(PySetObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)set_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)set_repr, /* tp_repr */ + &frozenset_as_number, /* tp_as_number */ + &set_as_sequence, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + frozenset_hash, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_BASETYPE, /* tp_flags */ + frozenset_doc, /* tp_doc */ + (traverseproc)set_traverse, /* tp_traverse */ + (inquiry)set_clear_internal, /* tp_clear */ + (richcmpfunc)set_richcompare, /* tp_richcompare */ + offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */ + (getiterfunc)set_iter, /* tp_iter */ + 0, /* tp_iternext */ + frozenset_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + frozenset_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ }; @@ -2243,238 +2243,238 @@ PyTypeObject PyFrozenSet_Type = { PyObject * PySet_New(PyObject *iterable) { - return make_new_set(&PySet_Type, iterable); + return make_new_set(&PySet_Type, iterable); } PyObject * PyFrozenSet_New(PyObject *iterable) { - return make_new_set(&PyFrozenSet_Type, iterable); + return make_new_set(&PyFrozenSet_Type, iterable); } Py_ssize_t PySet_Size(PyObject *anyset) { - if (!PyAnySet_Check(anyset)) { - PyErr_BadInternalCall(); - return -1; - } - return PySet_GET_SIZE(anyset); + if (!PyAnySet_Check(anyset)) { + PyErr_BadInternalCall(); + return -1; + } + return PySet_GET_SIZE(anyset); } int PySet_Clear(PyObject *set) { - if (!PySet_Check(set)) { - PyErr_BadInternalCall(); - return -1; - } - return set_clear_internal((PySetObject *)set); + if (!PySet_Check(set)) { + PyErr_BadInternalCall(); + return -1; + } + return set_clear_internal((PySetObject *)set); } int PySet_Contains(PyObject *anyset, PyObject *key) { - if (!PyAnySet_Check(anyset)) { - PyErr_BadInternalCall(); - return -1; - } - return set_contains_key((PySetObject *)anyset, key); + if (!PyAnySet_Check(anyset)) { + PyErr_BadInternalCall(); + return -1; + } + return set_contains_key((PySetObject *)anyset, key); } int PySet_Discard(PyObject *set, PyObject *key) { - if (!PySet_Check(set)) { - PyErr_BadInternalCall(); - return -1; - } - return set_discard_key((PySetObject *)set, key); + if (!PySet_Check(set)) { + PyErr_BadInternalCall(); + return -1; + } + return set_discard_key((PySetObject *)set, key); } int PySet_Add(PyObject *anyset, PyObject *key) { - if (!PySet_Check(anyset) && - (!PyFrozenSet_Check(anyset) || Py_REFCNT(anyset) != 1)) { - PyErr_BadInternalCall(); - return -1; - } - return set_add_key((PySetObject *)anyset, key); + if (!PySet_Check(anyset) && + (!PyFrozenSet_Check(anyset) || Py_REFCNT(anyset) != 1)) { + PyErr_BadInternalCall(); + return -1; + } + return set_add_key((PySetObject *)anyset, key); } int _PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, long *hash) { - setentry *entry; + setentry *entry; - if (!PyAnySet_Check(set)) { - PyErr_BadInternalCall(); - return -1; - } - if (set_next((PySetObject *)set, pos, &entry) == 0) - return 0; - *key = entry->key; - *hash = entry->hash; - return 1; + if (!PyAnySet_Check(set)) { + PyErr_BadInternalCall(); + return -1; + } + if (set_next((PySetObject *)set, pos, &entry) == 0) + return 0; + *key = entry->key; + *hash = entry->hash; + return 1; } PyObject * PySet_Pop(PyObject *set) { - if (!PySet_Check(set)) { - PyErr_BadInternalCall(); - return NULL; - } - return set_pop((PySetObject *)set); + if (!PySet_Check(set)) { + PyErr_BadInternalCall(); + return NULL; + } + return set_pop((PySetObject *)set); } int _PySet_Update(PyObject *set, PyObject *iterable) { - if (!PySet_Check(set)) { - PyErr_BadInternalCall(); - return -1; - } - return set_update_internal((PySetObject *)set, iterable); + if (!PySet_Check(set)) { + PyErr_BadInternalCall(); + return -1; + } + return set_update_internal((PySetObject *)set, iterable); } #ifdef Py_DEBUG -/* Test code to be called with any three element set. +/* Test code to be called with any three element set. Returns True and original set is restored. */ -#define assertRaises(call_return_value, exception) \ - do { \ - assert(call_return_value); \ - assert(PyErr_ExceptionMatches(exception)); \ - PyErr_Clear(); \ - } while(0) +#define assertRaises(call_return_value, exception) \ + do { \ + assert(call_return_value); \ + assert(PyErr_ExceptionMatches(exception)); \ + PyErr_Clear(); \ + } while(0) static PyObject * test_c_api(PySetObject *so) { - Py_ssize_t count; - char *s; - Py_ssize_t i; - PyObject *elem=NULL, *dup=NULL, *t, *f, *dup2, *x; - PyObject *ob = (PyObject *)so; - long hash; - PyObject *str; - - /* Verify preconditions */ - assert(PyAnySet_Check(ob)); - assert(PyAnySet_CheckExact(ob)); - assert(!PyFrozenSet_CheckExact(ob)); - - /* so.clear(); so |= set("abc"); */ - str = PyUnicode_FromString("abc"); - if (str == NULL) - return NULL; - set_clear_internal(so); - if (set_update_internal(so, str) == -1) { - Py_DECREF(str); - return NULL; - } - Py_DECREF(str); - - /* Exercise type/size checks */ - assert(PySet_Size(ob) == 3); - assert(PySet_GET_SIZE(ob) == 3); - - /* Raise TypeError for non-iterable constructor arguments */ - assertRaises(PySet_New(Py_None) == NULL, PyExc_TypeError); - assertRaises(PyFrozenSet_New(Py_None) == NULL, PyExc_TypeError); - - /* Raise TypeError for unhashable key */ - dup = PySet_New(ob); - assertRaises(PySet_Discard(ob, dup) == -1, PyExc_TypeError); - assertRaises(PySet_Contains(ob, dup) == -1, PyExc_TypeError); - assertRaises(PySet_Add(ob, dup) == -1, PyExc_TypeError); - - /* Exercise successful pop, contains, add, and discard */ - elem = PySet_Pop(ob); - assert(PySet_Contains(ob, elem) == 0); - assert(PySet_GET_SIZE(ob) == 2); - assert(PySet_Add(ob, elem) == 0); - assert(PySet_Contains(ob, elem) == 1); - assert(PySet_GET_SIZE(ob) == 3); - assert(PySet_Discard(ob, elem) == 1); - assert(PySet_GET_SIZE(ob) == 2); - assert(PySet_Discard(ob, elem) == 0); - assert(PySet_GET_SIZE(ob) == 2); - - /* Exercise clear */ - dup2 = PySet_New(dup); - assert(PySet_Clear(dup2) == 0); - assert(PySet_Size(dup2) == 0); - Py_DECREF(dup2); - - /* Raise SystemError on clear or update of frozen set */ - f = PyFrozenSet_New(dup); - assertRaises(PySet_Clear(f) == -1, PyExc_SystemError); - assertRaises(_PySet_Update(f, dup) == -1, PyExc_SystemError); - assert(PySet_Add(f, elem) == 0); - Py_INCREF(f); - assertRaises(PySet_Add(f, elem) == -1, PyExc_SystemError); - Py_DECREF(f); - Py_DECREF(f); - - /* Exercise direct iteration */ - i = 0, count = 0; - while (_PySet_NextEntry((PyObject *)dup, &i, &x, &hash)) { - s = _PyUnicode_AsString(x); - assert(s && (s[0] == 'a' || s[0] == 'b' || s[0] == 'c')); - count++; - } - assert(count == 3); - - /* Exercise updates */ - dup2 = PySet_New(NULL); - assert(_PySet_Update(dup2, dup) == 0); - assert(PySet_Size(dup2) == 3); - assert(_PySet_Update(dup2, dup) == 0); - assert(PySet_Size(dup2) == 3); - Py_DECREF(dup2); - - /* Raise SystemError when self argument is not a set or frozenset. */ - t = PyTuple_New(0); - assertRaises(PySet_Size(t) == -1, PyExc_SystemError); - assertRaises(PySet_Contains(t, elem) == -1, PyExc_SystemError); - Py_DECREF(t); - - /* Raise SystemError when self argument is not a set. */ - f = PyFrozenSet_New(dup); - assert(PySet_Size(f) == 3); - assert(PyFrozenSet_CheckExact(f)); - assertRaises(PySet_Discard(f, elem) == -1, PyExc_SystemError); - assertRaises(PySet_Pop(f) == NULL, PyExc_SystemError); - Py_DECREF(f); - - /* Raise KeyError when popping from an empty set */ - assert(PyNumber_InPlaceSubtract(ob, ob) == ob); - Py_DECREF(ob); - assert(PySet_GET_SIZE(ob) == 0); - assertRaises(PySet_Pop(ob) == NULL, PyExc_KeyError); - - /* Restore the set from the copy using the PyNumber API */ - assert(PyNumber_InPlaceOr(ob, dup) == ob); - Py_DECREF(ob); - - /* Verify constructors accept NULL arguments */ - f = PySet_New(NULL); - assert(f != NULL); - assert(PySet_GET_SIZE(f) == 0); - Py_DECREF(f); - f = PyFrozenSet_New(NULL); - assert(f != NULL); - assert(PyFrozenSet_CheckExact(f)); - assert(PySet_GET_SIZE(f) == 0); - Py_DECREF(f); - - Py_DECREF(elem); - Py_DECREF(dup); - Py_RETURN_TRUE; + Py_ssize_t count; + char *s; + Py_ssize_t i; + PyObject *elem=NULL, *dup=NULL, *t, *f, *dup2, *x; + PyObject *ob = (PyObject *)so; + long hash; + PyObject *str; + + /* Verify preconditions */ + assert(PyAnySet_Check(ob)); + assert(PyAnySet_CheckExact(ob)); + assert(!PyFrozenSet_CheckExact(ob)); + + /* so.clear(); so |= set("abc"); */ + str = PyUnicode_FromString("abc"); + if (str == NULL) + return NULL; + set_clear_internal(so); + if (set_update_internal(so, str) == -1) { + Py_DECREF(str); + return NULL; + } + Py_DECREF(str); + + /* Exercise type/size checks */ + assert(PySet_Size(ob) == 3); + assert(PySet_GET_SIZE(ob) == 3); + + /* Raise TypeError for non-iterable constructor arguments */ + assertRaises(PySet_New(Py_None) == NULL, PyExc_TypeError); + assertRaises(PyFrozenSet_New(Py_None) == NULL, PyExc_TypeError); + + /* Raise TypeError for unhashable key */ + dup = PySet_New(ob); + assertRaises(PySet_Discard(ob, dup) == -1, PyExc_TypeError); + assertRaises(PySet_Contains(ob, dup) == -1, PyExc_TypeError); + assertRaises(PySet_Add(ob, dup) == -1, PyExc_TypeError); + + /* Exercise successful pop, contains, add, and discard */ + elem = PySet_Pop(ob); + assert(PySet_Contains(ob, elem) == 0); + assert(PySet_GET_SIZE(ob) == 2); + assert(PySet_Add(ob, elem) == 0); + assert(PySet_Contains(ob, elem) == 1); + assert(PySet_GET_SIZE(ob) == 3); + assert(PySet_Discard(ob, elem) == 1); + assert(PySet_GET_SIZE(ob) == 2); + assert(PySet_Discard(ob, elem) == 0); + assert(PySet_GET_SIZE(ob) == 2); + + /* Exercise clear */ + dup2 = PySet_New(dup); + assert(PySet_Clear(dup2) == 0); + assert(PySet_Size(dup2) == 0); + Py_DECREF(dup2); + + /* Raise SystemError on clear or update of frozen set */ + f = PyFrozenSet_New(dup); + assertRaises(PySet_Clear(f) == -1, PyExc_SystemError); + assertRaises(_PySet_Update(f, dup) == -1, PyExc_SystemError); + assert(PySet_Add(f, elem) == 0); + Py_INCREF(f); + assertRaises(PySet_Add(f, elem) == -1, PyExc_SystemError); + Py_DECREF(f); + Py_DECREF(f); + + /* Exercise direct iteration */ + i = 0, count = 0; + while (_PySet_NextEntry((PyObject *)dup, &i, &x, &hash)) { + s = _PyUnicode_AsString(x); + assert(s && (s[0] == 'a' || s[0] == 'b' || s[0] == 'c')); + count++; + } + assert(count == 3); + + /* Exercise updates */ + dup2 = PySet_New(NULL); + assert(_PySet_Update(dup2, dup) == 0); + assert(PySet_Size(dup2) == 3); + assert(_PySet_Update(dup2, dup) == 0); + assert(PySet_Size(dup2) == 3); + Py_DECREF(dup2); + + /* Raise SystemError when self argument is not a set or frozenset. */ + t = PyTuple_New(0); + assertRaises(PySet_Size(t) == -1, PyExc_SystemError); + assertRaises(PySet_Contains(t, elem) == -1, PyExc_SystemError); + Py_DECREF(t); + + /* Raise SystemError when self argument is not a set. */ + f = PyFrozenSet_New(dup); + assert(PySet_Size(f) == 3); + assert(PyFrozenSet_CheckExact(f)); + assertRaises(PySet_Discard(f, elem) == -1, PyExc_SystemError); + assertRaises(PySet_Pop(f) == NULL, PyExc_SystemError); + Py_DECREF(f); + + /* Raise KeyError when popping from an empty set */ + assert(PyNumber_InPlaceSubtract(ob, ob) == ob); + Py_DECREF(ob); + assert(PySet_GET_SIZE(ob) == 0); + assertRaises(PySet_Pop(ob) == NULL, PyExc_KeyError); + + /* Restore the set from the copy using the PyNumber API */ + assert(PyNumber_InPlaceOr(ob, dup) == ob); + Py_DECREF(ob); + + /* Verify constructors accept NULL arguments */ + f = PySet_New(NULL); + assert(f != NULL); + assert(PySet_GET_SIZE(f) == 0); + Py_DECREF(f); + f = PyFrozenSet_New(NULL); + assert(f != NULL); + assert(PyFrozenSet_CheckExact(f)); + assert(PySet_GET_SIZE(f) == 0); + Py_DECREF(f); + + Py_DECREF(elem); + Py_DECREF(dup); + Py_RETURN_TRUE; } #undef assertRaises |