| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-05 00:01:15 +00:00
										 |  |  | /* set object implementation 
 | 
					
						
							|  |  |  |    Written and maintained by Raymond D. Hettinger <python@rcn.com> | 
					
						
							|  |  |  |    Derived from Lib/sets.py and Objects/dictobject.c. | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-11 09:04:12 +00:00
										 |  |  |    Copyright (c) 2003-6 Python Software Foundation. | 
					
						
							| 
									
										
										
										
											2005-08-05 00:01:15 +00:00
										 |  |  |    All rights reserved. | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | #include "Python.h"
 | 
					
						
							| 
									
										
										
										
											2005-08-05 00:01:15 +00:00
										 |  |  | #include "structmember.h"
 | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* This must be >= 1. */ | 
					
						
							|  |  |  | #define PERTURB_SHIFT 5
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Object used as dummy key to fill deleted entries */ | 
					
						
							| 
									
										
										
										
											2005-08-05 00:01:15 +00:00
										 |  |  | static PyObject *dummy = NULL; /* Initialized by first call to make_new_set() */ | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-12 17:06:05 +00:00
										 |  |  | #ifdef Py_REF_DEBUG
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | _PySet_Dummy(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return dummy; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-07 13:02:53 +00:00
										 |  |  | #define INIT_NONZERO_SET_SLOTS(so) do {				\
 | 
					
						
							|  |  |  | 	(so)->table = (so)->smalltable;				\ | 
					
						
							|  |  |  | 	(so)->mask = PySet_MINSIZE - 1;				\ | 
					
						
							|  |  |  | 	(so)->hash = -1;					\ | 
					
						
							|  |  |  |     } while(0) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | #define EMPTY_TO_MINSIZE(so) do {				\
 | 
					
						
							|  |  |  | 	memset((so)->smalltable, 0, sizeof((so)->smalltable));	\ | 
					
						
							|  |  |  | 	(so)->used = (so)->fill = 0;				\ | 
					
						
							| 
									
										
										
										
											2005-08-07 13:02:53 +00:00
										 |  |  | 	INIT_NONZERO_SET_SLOTS(so);				\ | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  |     } while(0) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-07 13:02:53 +00:00
										 |  |  | /* Reuse scheme to save calls to malloc, free, and memset */ | 
					
						
							|  |  |  | #define MAXFREESETS 80
 | 
					
						
							|  |  |  | static PySetObject *free_sets[MAXFREESETS]; | 
					
						
							|  |  |  | static int num_free_sets = 0; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  | The basic lookup function used by all operations. | 
					
						
							|  |  |  | This is based on Algorithm D from Knuth Vol. 3, Sec. 6.4. | 
					
						
							|  |  |  | Open addressing is preferred over chaining since the link overhead for | 
					
						
							|  |  |  | chaining would be substantial (100% with typical malloc overhead). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The initial probe index is computed as hash mod the table size. Subsequent | 
					
						
							| 
									
										
										
										
											2005-08-07 13:02:53 +00:00
										 |  |  | probe indices are computed as explained in Objects/dictobject.c. | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | All arithmetic on hash should ignore overflow. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-09-16 07:14:21 +00:00
										 |  |  | Unlike the dictionary implementation, the lookkey functions can return | 
					
						
							|  |  |  | NULL if the rich comparison returns an error. | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static setentry * | 
					
						
							|  |  |  | set_lookkey(PySetObject *so, PyObject *key, register long hash) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	register Py_ssize_t i; | 
					
						
							|  |  |  | 	register size_t perturb; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	register setentry *freeslot; | 
					
						
							| 
									
										
										
										
											2006-06-19 05:40:44 +00:00
										 |  |  | 	register size_t mask = so->mask; | 
					
						
							| 
									
										
										
										
											2005-08-05 17:19:54 +00:00
										 |  |  | 	setentry *table = so->table; | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	register setentry *entry; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	register int cmp; | 
					
						
							|  |  |  | 	PyObject *startkey; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	i = hash & mask; | 
					
						
							| 
									
										
										
										
											2005-08-05 17:19:54 +00:00
										 |  |  | 	entry = &table[i]; | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	if (entry->key == NULL || entry->key == key) | 
					
						
							|  |  |  | 		return entry; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	if (entry->key == dummy) | 
					
						
							|  |  |  | 		freeslot = entry; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 		if (entry->hash == hash) { | 
					
						
							|  |  |  | 			startkey = entry->key; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 			cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); | 
					
						
							|  |  |  | 			if (cmp < 0) | 
					
						
							| 
									
										
										
										
											2005-09-16 07:14:21 +00:00
										 |  |  | 				return NULL; | 
					
						
							| 
									
										
										
										
											2005-08-05 17:19:54 +00:00
										 |  |  | 			if (table == so->table && entry->key == startkey) { | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 				if (cmp > 0) | 
					
						
							| 
									
										
										
										
											2005-09-16 07:14:21 +00:00
										 |  |  | 					return entry; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				/* The compare did major nasty stuff to the
 | 
					
						
							|  |  |  | 				 * set:  start over. | 
					
						
							|  |  |  |  				 */ | 
					
						
							| 
									
										
										
										
											2005-09-16 07:14:21 +00:00
										 |  |  |  				return set_lookkey(so, key, hash); | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  |  			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		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; | 
					
						
							| 
									
										
										
										
											2005-08-05 17:19:54 +00:00
										 |  |  | 		entry = &table[i & mask]; | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 		if (entry->key == NULL) { | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 			if (freeslot != NULL) | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 				entry = freeslot; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 		if (entry->key == key) | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 		if (entry->hash == hash && entry->key != dummy) { | 
					
						
							|  |  |  | 			startkey = entry->key; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 			cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); | 
					
						
							|  |  |  | 			if (cmp < 0) | 
					
						
							| 
									
										
										
										
											2005-09-16 07:14:21 +00:00
										 |  |  | 				return NULL; | 
					
						
							| 
									
										
										
										
											2005-08-05 17:19:54 +00:00
										 |  |  | 			if (table == so->table && entry->key == startkey) { | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 				if (cmp > 0) | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				/* The compare did major nasty stuff to the
 | 
					
						
							|  |  |  | 				 * set:  start over. | 
					
						
							|  |  |  |  				 */ | 
					
						
							| 
									
										
										
										
											2005-09-16 07:14:21 +00:00
										 |  |  |  				return set_lookkey(so, key, hash); | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  |  			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 		else if (entry->key == dummy && freeslot == NULL) | 
					
						
							|  |  |  | 			freeslot = entry; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	return entry; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Hacked up version of set_lookkey which can assume keys are always strings; | 
					
						
							| 
									
										
										
										
											2005-09-16 07:14:21 +00:00
										 |  |  |  * This means we can always use _PyString_Eq directly and not have to check to | 
					
						
							|  |  |  |  * see if the comparison altered the table. | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | static setentry * | 
					
						
							|  |  |  | set_lookkey_string(PySetObject *so, PyObject *key, register long hash) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	register Py_ssize_t i; | 
					
						
							|  |  |  | 	register size_t perturb; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	register setentry *freeslot; | 
					
						
							| 
									
										
										
										
											2006-06-19 05:40:44 +00:00
										 |  |  | 	register size_t mask = so->mask; | 
					
						
							| 
									
										
										
										
											2005-08-05 17:19:54 +00:00
										 |  |  | 	setentry *table = so->table; | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	register setentry *entry; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Make sure this function doesn't have to handle non-string 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 (!PyString_CheckExact(key)) { | 
					
						
							|  |  |  | 		so->lookup = set_lookkey; | 
					
						
							|  |  |  | 		return set_lookkey(so, key, hash); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	i = hash & mask; | 
					
						
							| 
									
										
										
										
											2005-08-05 17:19:54 +00:00
										 |  |  | 	entry = &table[i]; | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	if (entry->key == NULL || entry->key == key) | 
					
						
							|  |  |  | 		return entry; | 
					
						
							| 
									
										
										
										
											2005-08-13 08:28:03 +00:00
										 |  |  | 	if (entry->key == dummy) | 
					
						
							|  |  |  | 		freeslot = entry; | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2005-08-05 17:19:54 +00:00
										 |  |  | 		if (entry->hash == hash && _PyString_Eq(entry->key, key)) | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 			return entry; | 
					
						
							| 
									
										
										
										
											2005-08-13 08:28:03 +00:00
										 |  |  | 		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 | 
					
						
							|  |  |  | 			&& _PyString_Eq(entry->key, key))) | 
					
						
							|  |  |  | 			return entry; | 
					
						
							|  |  |  | 		if (entry->key == dummy && freeslot == NULL) | 
					
						
							|  |  |  | 			freeslot = entry; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-10-28 21:16:54 +00:00
										 |  |  | 	assert(0);	/* NOT REACHED */ | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | Internal routine to insert a new key into the table. | 
					
						
							| 
									
										
										
										
											2006-12-08 04:24:33 +00:00
										 |  |  | Used by the public insert routine. | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | Eats a reference to key. | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2005-09-16 07:14:21 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | set_insert_key(register PySetObject *so, PyObject *key, long hash) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	register setentry *entry; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	typedef setentry *(*lookupfunc)(PySetObject *, PyObject *, long); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert(so->lookup != NULL); | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	entry = so->lookup(so, key, hash); | 
					
						
							| 
									
										
										
										
											2005-09-16 07:14:21 +00:00
										 |  |  | 	if (entry == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	if (entry->key == NULL) { | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		/* UNUSED */ | 
					
						
							|  |  |  | 		so->fill++;  | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 		entry->key = key; | 
					
						
							|  |  |  | 		entry->hash = hash; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		so->used++; | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	} else if (entry->key == dummy) { | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		/* DUMMY */ | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 		entry->key = key; | 
					
						
							|  |  |  | 		entry->hash = hash; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		so->used++; | 
					
						
							|  |  |  | 		Py_DECREF(dummy); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		/* ACTIVE */ | 
					
						
							|  |  |  | 		Py_DECREF(key); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-09-16 07:14:21 +00:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-08 04:24:33 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  | Internal routine used by set_table_resize() to insert an item which is | 
					
						
							|  |  |  | known to be absent from the set.  This routine also assumes that | 
					
						
							|  |  |  | the set contains no deleted entries.  Besides the performance benefit, | 
					
						
							|  |  |  | using set_insert_clean() in set_table_resize() is dangerous (SF bug #1456209). | 
					
						
							|  |  |  | Note that no refcounts are changed by this routine; if needed, the caller | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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++; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  | Restructure the table by allocating a new table and reinserting all | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | keys again.  When entries have been deleted, the new table may | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | actually be smaller than the old one. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2006-06-19 05:40:44 +00:00
										 |  |  | set_table_resize(PySetObject *so, Py_ssize_t minused) | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-06-19 05:40:44 +00:00
										 |  |  | 	Py_ssize_t newsize; | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	setentry *oldtable, *newtable, *entry; | 
					
						
							| 
									
										
										
										
											2006-06-19 05:40:44 +00:00
										 |  |  | 	Py_ssize_t i; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	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 */ | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	for (entry = oldtable; i > 0; entry++) { | 
					
						
							|  |  |  | 		if (entry->key == NULL) { | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 			/* UNUSED */ | 
					
						
							|  |  |  | 			; | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 		} else if (entry->key == dummy) { | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 			/* DUMMY */ | 
					
						
							|  |  |  | 			--i; | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 			assert(entry->key == dummy); | 
					
						
							|  |  |  | 			Py_DECREF(entry->key); | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			/* ACTIVE */ | 
					
						
							|  |  |  | 			--i; | 
					
						
							| 
									
										
										
										
											2006-12-08 04:24:33 +00:00
										 |  |  | 			set_insert_clean(so, entry->key, entry->hash); | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (is_oldtable_malloced) | 
					
						
							|  |  |  | 		PyMem_DEL(oldtable); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | /* CAUTION: set_add_key/entry() must guarantee it won't resize the table */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | set_add_entry(register PySetObject *so, setentry *entry) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-06-19 05:40:44 +00:00
										 |  |  | 	register Py_ssize_t n_used; | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	assert(so->fill <= so->mask);  /* at least one empty slot */ | 
					
						
							|  |  |  | 	n_used = so->used; | 
					
						
							|  |  |  | 	Py_INCREF(entry->key); | 
					
						
							| 
									
										
										
										
											2006-09-07 02:42:48 +00:00
										 |  |  | 	if (set_insert_key(so, entry->key, entry->hash) == -1) { | 
					
						
							|  |  |  | 		Py_DECREF(entry->key); | 
					
						
							| 
									
										
										
										
											2005-09-16 07:14:21 +00:00
										 |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2006-09-07 02:42:48 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 	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); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | set_add_key(register PySetObject *so, PyObject *key) | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	register long hash; | 
					
						
							| 
									
										
										
										
											2006-06-19 05:40:44 +00:00
										 |  |  | 	register Py_ssize_t n_used; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 	if (!PyString_CheckExact(key) || | 
					
						
							|  |  |  | 	    (hash = ((PyStringObject *) key)->ob_shash) == -1) { | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		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); | 
					
						
							| 
									
										
										
										
											2005-09-16 07:14:21 +00:00
										 |  |  | 	if (set_insert_key(so, key, hash) == -1) { | 
					
						
							|  |  |  | 		Py_DECREF(key); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	if (!(so->used > n_used && so->fill*3 >= (so->mask+1)*2)) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2005-08-07 13:02:53 +00:00
										 |  |  | 	return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4); | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define DISCARD_NOTFOUND 0
 | 
					
						
							|  |  |  | #define DISCARD_FOUND 1
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | set_discard_entry(PySetObject *so, setentry *oldentry) | 
					
						
							|  |  |  | {	register setentry *entry; | 
					
						
							|  |  |  | 	PyObject *old_key; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	entry = (so->lookup)(so, oldentry->key, oldentry->hash); | 
					
						
							| 
									
										
										
										
											2005-09-16 07:14:21 +00:00
										 |  |  | 	if (entry == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 	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) | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	register long hash; | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	register setentry *entry; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	PyObject *old_key; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert (PyAnySet_Check(so)); | 
					
						
							|  |  |  | 	if (!PyString_CheckExact(key) || | 
					
						
							|  |  |  | 	    (hash = ((PyStringObject *) key)->ob_shash) == -1) { | 
					
						
							|  |  |  | 		hash = PyObject_Hash(key); | 
					
						
							|  |  |  | 		if (hash == -1) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	entry = (so->lookup)(so, key, hash); | 
					
						
							| 
									
										
										
										
											2005-09-16 07:14:21 +00:00
										 |  |  | 	if (entry == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	if (entry->key == NULL  ||  entry->key == dummy) | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		return DISCARD_NOTFOUND; | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	old_key = entry->key; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	Py_INCREF(dummy); | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	entry->key = dummy; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	so->used--; | 
					
						
							|  |  |  | 	Py_DECREF(old_key); | 
					
						
							|  |  |  | 	return DISCARD_FOUND; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-06 05:43:39 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | set_clear_internal(PySetObject *so) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	setentry *entry, *table; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	int table_is_malloced; | 
					
						
							| 
									
										
										
										
											2006-06-19 05:40:44 +00:00
										 |  |  | 	Py_ssize_t fill; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	setentry small_copy[PySet_MINSIZE]; | 
					
						
							|  |  |  | #ifdef Py_DEBUG
 | 
					
						
							| 
									
										
										
										
											2006-06-19 05:40:44 +00:00
										 |  |  | 	Py_ssize_t i, n; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	assert (PyAnySet_Check(so)); | 
					
						
							| 
									
										
										
										
											2005-08-05 17:19:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	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 | 
					
						
							| 
									
										
										
										
											2005-08-06 05:43:39 +00:00
										 |  |  | 	 * clearing the slots, and never refer to anything via so->ref while | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	 * 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. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	for (entry = table; fill > 0; ++entry) { | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | #ifdef Py_DEBUG
 | 
					
						
							|  |  |  | 		assert(i < n); | 
					
						
							|  |  |  | 		++i; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 		if (entry->key) { | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 			--fill; | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 			Py_DECREF(entry->key); | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | #ifdef Py_DEBUG
 | 
					
						
							|  |  |  | 		else | 
					
						
							| 
									
										
										
										
											2006-03-26 03:11:29 +00:00
										 |  |  | 			assert(entry->key == NULL); | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (table_is_malloced) | 
					
						
							|  |  |  | 		PyMem_DEL(table); | 
					
						
							| 
									
										
										
										
											2005-08-06 05:43:39 +00:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Iterate over a set table.  Use like so: | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2006-06-19 05:40:44 +00:00
										 |  |  |  *     Py_ssize_t pos; | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  |  *     setentry *entry; | 
					
						
							| 
									
										
										
										
											2005-08-01 21:39:29 +00:00
										 |  |  |  *     pos = 0;   # important!  pos should not otherwise be changed by you | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  |  *     while (set_next(yourset, &pos, &entry)) { | 
					
						
							|  |  |  |  *              Refer to borrowed reference in entry->key. | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  |  *     } | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  |  * CAUTION:  In general, it isn't safe to use set_next in a loop that | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  |  * mutates the table.   | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | set_next(PySetObject *so, Py_ssize_t *pos_ptr, setentry **entry_ptr) | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i; | 
					
						
							| 
									
										
										
										
											2006-06-19 05:40:44 +00:00
										 |  |  | 	Py_ssize_t mask; | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 	register setentry *table; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	assert (PyAnySet_Check(so)); | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 	i = *pos_ptr; | 
					
						
							| 
									
										
										
										
											2005-08-17 00:27:42 +00:00
										 |  |  | 	assert(i >= 0); | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 	table = so->table; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	mask = so->mask; | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 	while (i <= mask && (table[i].key == NULL || table[i].key == dummy)) | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		i++; | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 	*pos_ptr = i+1; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	if (i > mask) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2005-08-17 00:27:42 +00:00
										 |  |  | 	assert(table[i].key != NULL); | 
					
						
							|  |  |  | 	*entry_ptr = &table[i]; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-17 00:27:42 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | set_dealloc(PySetObject *so) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	register setentry *entry; | 
					
						
							| 
									
										
										
										
											2006-06-19 05:40:44 +00:00
										 |  |  | 	Py_ssize_t fill = so->fill; | 
					
						
							| 
									
										
										
										
											2005-08-17 00:27:42 +00:00
										 |  |  | 	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 (num_free_sets < MAXFREESETS && PyAnySet_CheckExact(so)) | 
					
						
							|  |  |  | 		free_sets[num_free_sets++] = so; | 
					
						
							|  |  |  | 	else  | 
					
						
							|  |  |  | 		so->ob_type->tp_free(so); | 
					
						
							|  |  |  | 	Py_TRASHCAN_SAFE_END(so) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | set_tp_print(PySetObject *so, FILE *fp, int flags) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	setentry *entry; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t pos=0; | 
					
						
							| 
									
										
										
										
											2005-08-17 00:27:42 +00:00
										 |  |  | 	char *emit = "";	/* No separator emitted on first pass */ | 
					
						
							|  |  |  | 	char *separator = ", "; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fprintf(fp, "%s([", so->ob_type->tp_name); | 
					
						
							|  |  |  | 	while (set_next(so, &pos, &entry)) { | 
					
						
							|  |  |  | 		fputs(emit, fp); | 
					
						
							|  |  |  | 		emit = separator; | 
					
						
							|  |  |  | 		if (PyObject_Print(entry->key, fp, 0) != 0) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	fputs("])", fp); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | set_repr(PySetObject *so) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *keys, *result, *listrepr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	keys = PySequence_List((PyObject *)so); | 
					
						
							|  |  |  | 	if (keys == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	listrepr = PyObject_Repr(keys); | 
					
						
							|  |  |  | 	Py_DECREF(keys); | 
					
						
							|  |  |  | 	if (listrepr == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	result = PyString_FromFormat("%s(%s)", so->ob_type->tp_name, | 
					
						
							|  |  |  | 		PyString_AS_STRING(listrepr)); | 
					
						
							|  |  |  | 	Py_DECREF(listrepr); | 
					
						
							|  |  |  | 	return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | static Py_ssize_t | 
					
						
							| 
									
										
										
										
											2005-08-17 00:27:42 +00:00
										 |  |  | set_len(PyObject *so) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return ((PySetObject *)so)->used; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | set_merge(PySetObject *so, PyObject *otherset) | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-08-01 21:39:29 +00:00
										 |  |  | 	PySetObject *other; | 
					
						
							| 
									
										
										
										
											2006-06-19 05:40:44 +00:00
										 |  |  | 	register Py_ssize_t i; | 
					
						
							| 
									
										
										
										
											2005-08-17 00:27:42 +00:00
										 |  |  | 	register setentry *entry; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	assert (PyAnySet_Check(so)); | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	assert (PyAnySet_Check(otherset)); | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	other = (PySetObject*)otherset; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	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
 | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	 * incrementally resizing as we insert new keys.  Expect | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	 * 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; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-08-17 00:27:42 +00:00
										 |  |  | 	for (i = 0; i <= other->mask; i++) { | 
					
						
							|  |  |  | 		entry = &other->table[i]; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		if (entry->key != NULL &&  | 
					
						
							|  |  |  | 		    entry->key != dummy) { | 
					
						
							|  |  |  | 			Py_INCREF(entry->key); | 
					
						
							| 
									
										
										
										
											2005-09-16 07:14:21 +00:00
										 |  |  | 			if (set_insert_key(so, entry->key, entry->hash) == -1) { | 
					
						
							|  |  |  | 				Py_DECREF(entry->key); | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | set_contains_key(PySetObject *so, PyObject *key) | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	long hash; | 
					
						
							| 
									
										
										
										
											2005-09-16 07:14:21 +00:00
										 |  |  | 	setentry *entry; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyString_CheckExact(key) || | 
					
						
							|  |  |  | 	    (hash = ((PyStringObject *) key)->ob_shash) == -1) { | 
					
						
							|  |  |  | 		hash = PyObject_Hash(key); | 
					
						
							|  |  |  | 		if (hash == -1) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-09-16 07:14:21 +00:00
										 |  |  | 	entry = (so->lookup)(so, key, hash); | 
					
						
							|  |  |  | 	if (entry == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	key = entry->key; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	return key != NULL && key != dummy; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | set_contains_entry(PySetObject *so, setentry *entry) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *key; | 
					
						
							| 
									
										
										
										
											2005-09-16 07:14:21 +00:00
										 |  |  | 	setentry *lu_entry; | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-09-16 07:14:21 +00:00
										 |  |  | 	lu_entry = (so->lookup)(so, entry->key, entry->hash); | 
					
						
							|  |  |  | 	if (lu_entry == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	key = lu_entry->key;  | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 	return key != NULL && key != dummy; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-13 09:28:48 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | set_pop(PySetObject *so) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-06-19 05:40:44 +00:00
										 |  |  | 	register Py_ssize_t i = 0; | 
					
						
							| 
									
										
										
										
											2005-08-17 00:27:42 +00:00
										 |  |  | 	register setentry *entry; | 
					
						
							|  |  |  | 	PyObject *key; | 
					
						
							| 
									
										
										
										
											2005-08-13 09:28:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	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) { | 
					
						
							| 
									
										
										
										
											2006-06-19 05:40:44 +00:00
										 |  |  | 		i = entry->hash; | 
					
						
							| 
									
										
										
										
											2005-08-13 09:28:48 +00:00
										 |  |  | 		/* 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."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2005-08-17 00:27:42 +00:00
										 |  |  | set_traverse(PySetObject *so, visitproc visit, void *arg) | 
					
						
							| 
									
										
										
										
											2005-08-13 09:28:48 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t pos = 0; | 
					
						
							| 
									
										
										
										
											2005-08-17 00:27:42 +00:00
										 |  |  | 	setentry *entry; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t pos = 0; | 
					
						
							| 
									
										
										
										
											2005-08-17 00:27:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static long | 
					
						
							|  |  |  | set_nohash(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyErr_SetString(PyExc_TypeError, "set objects are unhashable"); | 
					
						
							|  |  |  | 	return -1; | 
					
						
							| 
									
										
										
										
											2005-08-13 09:28:48 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-05 00:01:15 +00:00
										 |  |  | /***** Set iterator type ***********************************************/ | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  | 	PyObject_HEAD | 
					
						
							|  |  |  | 	PySetObject *si_set; /* Set to NULL when iterator is exhausted */ | 
					
						
							| 
									
										
										
										
											2006-06-19 05:40:44 +00:00
										 |  |  | 	Py_ssize_t si_used; | 
					
						
							|  |  |  | 	Py_ssize_t si_pos; | 
					
						
							|  |  |  | 	Py_ssize_t len; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | } setiterobject; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | setiter_dealloc(setiterobject *si) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Py_XDECREF(si->si_set); | 
					
						
							|  |  |  | 	PyObject_Del(si); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-09-24 21:23:05 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | setiter_len(setiterobject *si) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-06-19 05:40:44 +00:00
										 |  |  | 	Py_ssize_t len = 0; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	if (si->si_set != NULL && si->si_used == si->si_set->used) | 
					
						
							| 
									
										
										
										
											2005-09-24 21:23:05 +00:00
										 |  |  | 		len = si->len; | 
					
						
							|  |  |  | 	return PyInt_FromLong(len); | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-11 21:32:43 +00:00
										 |  |  | PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); | 
					
						
							| 
									
										
										
										
											2005-09-24 21:23:05 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyMethodDef setiter_methods[] = { | 
					
						
							| 
									
										
										
										
											2006-02-11 21:32:43 +00:00
										 |  |  | 	{"__length_hint__", (PyCFunction)setiter_len, METH_NOARGS, length_hint_doc}, | 
					
						
							| 
									
										
										
										
											2005-09-24 21:23:05 +00:00
										 |  |  |  	{NULL,		NULL}		/* sentinel */ | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | static PyObject *setiter_iternext(setiterobject *si) | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PyObject *key; | 
					
						
							| 
									
										
										
										
											2006-06-19 05:40:44 +00:00
										 |  |  | 	register Py_ssize_t i, mask; | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	register setentry *entry; | 
					
						
							|  |  |  | 	PySetObject *so = si->si_set; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	if (so == NULL) | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	assert (PyAnySet_Check(so)); | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	if (si->si_used != so->used) { | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		PyErr_SetString(PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"Set changed size during iteration"); | 
					
						
							|  |  |  | 		si->si_used = -1; /* Make this state sticky */ | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	i = si->si_pos; | 
					
						
							| 
									
										
										
										
											2005-08-17 00:27:42 +00:00
										 |  |  | 	assert(i>=0); | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	entry = so->table; | 
					
						
							|  |  |  | 	mask = so->mask; | 
					
						
							|  |  |  | 	while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy)) | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		i++; | 
					
						
							|  |  |  | 	si->si_pos = i+1; | 
					
						
							|  |  |  | 	if (i > mask) | 
					
						
							|  |  |  | 		goto fail; | 
					
						
							|  |  |  | 	si->len--; | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	key = entry[i].key; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	Py_INCREF(key); | 
					
						
							|  |  |  | 	return key; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | fail: | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	Py_DECREF(so); | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	si->si_set = NULL; | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-01 05:26:41 +00:00
										 |  |  | static PyTypeObject PySetIter_Type = { | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	PyObject_HEAD_INIT(&PyType_Type) | 
					
						
							|  |  |  | 	0,					/* ob_size */ | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	"setiterator",				/* tp_name */ | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	sizeof(setiterobject),			/* tp_basicsize */ | 
					
						
							|  |  |  | 	0,					/* tp_itemsize */ | 
					
						
							|  |  |  | 	/* methods */ | 
					
						
							|  |  |  | 	(destructor)setiter_dealloc, 		/* tp_dealloc */ | 
					
						
							|  |  |  | 	0,					/* tp_print */ | 
					
						
							|  |  |  | 	0,					/* tp_getattr */ | 
					
						
							|  |  |  | 	0,					/* tp_setattr */ | 
					
						
							|  |  |  | 	0,					/* tp_compare */ | 
					
						
							|  |  |  | 	0,					/* tp_repr */ | 
					
						
							|  |  |  | 	0,					/* tp_as_number */ | 
					
						
							| 
									
										
										
										
											2005-09-24 21:23:05 +00:00
										 |  |  | 	0,					/* tp_as_sequence */ | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	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,			/* tp_flags */ | 
					
						
							|  |  |  |  	0,					/* tp_doc */ | 
					
						
							|  |  |  |  	0,					/* tp_traverse */ | 
					
						
							|  |  |  |  	0,					/* tp_clear */ | 
					
						
							|  |  |  | 	0,					/* tp_richcompare */ | 
					
						
							|  |  |  | 	0,					/* tp_weaklistoffset */ | 
					
						
							|  |  |  | 	PyObject_SelfIter,			/* tp_iter */ | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	(iternextfunc)setiter_iternext,		/* tp_iternext */ | 
					
						
							| 
									
										
										
										
											2005-09-24 21:23:05 +00:00
										 |  |  | 	setiter_methods,			/* tp_methods */ | 
					
						
							|  |  |  | 	0, | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-11 09:04:12 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | set_iter(PySetObject *so) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	setiterobject *si = PyObject_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; | 
					
						
							|  |  |  | 	return (PyObject *)si; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-01 21:39:29 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | set_update_internal(PySetObject *so, PyObject *other) | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	PyObject *key, *it; | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-01 21:39:29 +00:00
										 |  |  | 	if (PyAnySet_Check(other)) | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 		return set_merge(so, other); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	if (PyDict_Check(other)) { | 
					
						
							| 
									
										
										
										
											2006-01-08 06:13:44 +00:00
										 |  |  | 		PyObject *value; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 		Py_ssize_t pos = 0; | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 		while (PyDict_Next(other, &pos, &key, &value)) { | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 			if (set_add_key(so, key) == -1) | 
					
						
							| 
									
										
										
										
											2005-08-01 21:39:29 +00:00
										 |  |  | 				return -1; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-08-01 21:39:29 +00:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-24 22:18:49 +00:00
										 |  |  | 	it = PyObject_GetIter(other); | 
					
						
							|  |  |  | 	if (it == NULL) | 
					
						
							| 
									
										
										
										
											2005-08-01 21:39:29 +00:00
										 |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	while ((key = PyIter_Next(it)) != NULL) { | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  |                 if (set_add_key(so, key) == -1) { | 
					
						
							| 
									
										
										
										
											2003-11-24 22:18:49 +00:00
										 |  |  | 			Py_DECREF(it); | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 			Py_DECREF(key); | 
					
						
							| 
									
										
										
										
											2005-08-01 21:39:29 +00:00
										 |  |  | 			return -1; | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  |                 }  | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 		Py_DECREF(key); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2003-11-24 22:18:49 +00:00
										 |  |  | 	Py_DECREF(it); | 
					
						
							| 
									
										
										
										
											2003-11-24 02:57:33 +00:00
										 |  |  | 	if (PyErr_Occurred()) | 
					
						
							| 
									
										
										
										
											2005-08-01 21:39:29 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | set_update(PySetObject *so, PyObject *other) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (set_update_internal(so, other) == -1) | 
					
						
							| 
									
										
										
										
											2003-11-24 22:18:49 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(update_doc,  | 
					
						
							|  |  |  | "Update a set with the union of itself and another."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | make_new_set(PyTypeObject *type, PyObject *iterable) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	register PySetObject *so = NULL; | 
					
						
							| 
									
										
										
										
											2003-11-24 22:18:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	if (dummy == NULL) { /* Auto-initialize dummy */ | 
					
						
							|  |  |  | 		dummy = PyString_FromString("<dummy key>"); | 
					
						
							|  |  |  | 		if (dummy == NULL) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* create PySetObject structure */ | 
					
						
							| 
									
										
										
										
											2005-08-07 13:02:53 +00:00
										 |  |  | 	if (num_free_sets &&  | 
					
						
							|  |  |  | 	    (type == &PySet_Type  ||  type == &PyFrozenSet_Type)) { | 
					
						
							|  |  |  | 		so = free_sets[--num_free_sets]; | 
					
						
							|  |  |  | 		assert (so != NULL && PyAnySet_CheckExact(so)); | 
					
						
							|  |  |  | 		so->ob_type = 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); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	so->lookup = set_lookkey_string; | 
					
						
							| 
									
										
										
										
											2004-05-30 07:26:47 +00:00
										 |  |  | 	so->weakreflist = NULL; | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-24 22:18:49 +00:00
										 |  |  | 	if (iterable != NULL) { | 
					
						
							| 
									
										
										
										
											2005-08-01 21:39:29 +00:00
										 |  |  | 		if (set_update_internal(so, iterable) == -1) { | 
					
						
							| 
									
										
										
										
											2003-11-24 22:18:49 +00:00
										 |  |  | 			Py_DECREF(so); | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	return (PyObject *)so; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-01 21:39:29 +00:00
										 |  |  | /* The empty frozenset is a singleton */ | 
					
						
							|  |  |  | static PyObject *emptyfrozenset = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2003-11-17 16:42:33 +00:00
										 |  |  | frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-08-01 21:39:29 +00:00
										 |  |  | 	PyObject *iterable = NULL, *result; | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-26 06:42:30 +00:00
										 |  |  | 	if (!_PyArg_NoKeywords("frozenset()", kwds)) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	if (!PyArg_UnpackTuple(args, type->tp_name, 0, 1, &iterable)) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2005-08-01 21:39:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	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; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-08-01 21:39:29 +00:00
										 |  |  | 		result = make_new_set(type, iterable); | 
					
						
							| 
									
										
										
										
											2005-08-16 03:47:52 +00:00
										 |  |  | 		if (result == NULL || PySet_GET_SIZE(result)) | 
					
						
							| 
									
										
										
										
											2005-08-01 21:39:29 +00:00
										 |  |  | 			return result; | 
					
						
							|  |  |  | 		Py_DECREF(result); | 
					
						
							| 
									
										
										
										
											2003-11-23 02:49:05 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-08-01 21:39:29 +00:00
										 |  |  | 	/* The empty frozenset is a singleton */ | 
					
						
							|  |  |  | 	if (emptyfrozenset == NULL) | 
					
						
							|  |  |  | 		emptyfrozenset = make_new_set(type, NULL); | 
					
						
							|  |  |  | 	Py_XINCREF(emptyfrozenset); | 
					
						
							|  |  |  | 	return emptyfrozenset; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | PySet_Fini(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-08-07 13:02:53 +00:00
										 |  |  | 	PySetObject *so; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (num_free_sets) { | 
					
						
							|  |  |  | 		num_free_sets--; | 
					
						
							|  |  |  | 		so = free_sets[num_free_sets]; | 
					
						
							|  |  |  | 		PyObject_GC_Del(so); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-04-15 12:47:23 +00:00
										 |  |  | 	Py_CLEAR(dummy); | 
					
						
							|  |  |  | 	Py_CLEAR(emptyfrozenset); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-17 16:42:33 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | set_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-08-26 06:42:30 +00:00
										 |  |  | 	if (!_PyArg_NoKeywords("set()", kwds)) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2003-11-17 16:42:33 +00:00
										 |  |  | 	return make_new_set(type, NULL); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-31 01:33:10 +00:00
										 |  |  | /* set_swap_bodies() switches the contents of any two sets by moving their
 | 
					
						
							|  |  |  |    internal data pointers and, if needed, copying the internal smalltables. | 
					
						
							|  |  |  |    Semantically equivalent to: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      t=set(a); a.clear(); a.update(b); b.clear(); b.update(t); del t | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    The function always succeeds and it leaves both objects in a stable state. | 
					
						
							|  |  |  |    Useful for creating temporary frozensets from sets for membership testing  | 
					
						
							|  |  |  |    in __contains__(), discard(), and remove().  Also useful for operations | 
					
						
							|  |  |  |    that update in-place (by allowing an intermediate result to be swapped  | 
					
						
							| 
									
										
										
										
											2005-07-31 13:09:28 +00:00
										 |  |  |    into one of the original inputs). | 
					
						
							| 
									
										
										
										
											2005-07-31 01:33:10 +00:00
										 |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | set_swap_bodies(PySetObject *a, PySetObject *b) | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-06-19 05:40:44 +00:00
										 |  |  | 	Py_ssize_t t; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	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)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-05 17:19:54 +00:00
										 |  |  | 	if (PyType_IsSubtype(a->ob_type, &PyFrozenSet_Type)  && | 
					
						
							|  |  |  | 	    PyType_IsSubtype(b->ob_type, &PyFrozenSet_Type)) { | 
					
						
							|  |  |  | 		h = a->hash;     a->hash = b->hash;  b->hash = h; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		a->hash = -1; | 
					
						
							|  |  |  | 		b->hash = -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | set_copy(PySetObject *so) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2003-11-24 22:18:49 +00:00
										 |  |  | 	return make_new_set(so->ob_type, (PyObject *)so); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-23 02:49:05 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | frozenset_copy(PySetObject *so) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2003-11-24 02:57:33 +00:00
										 |  |  | 	if (PyFrozenSet_CheckExact(so)) { | 
					
						
							| 
									
										
										
										
											2003-11-23 02:49:05 +00:00
										 |  |  | 		Py_INCREF(so); | 
					
						
							|  |  |  | 		return (PyObject *)so; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return set_copy(so); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | PyDoc_STRVAR(copy_doc, "Return a shallow copy of a set."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | set_clear(PySetObject *so) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	set_clear_internal(so); | 
					
						
							|  |  |  | 	Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(clear_doc, "Remove all elements from this set."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-24 02:57:33 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | set_union(PySetObject *so, PyObject *other) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PySetObject *result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	result = (PySetObject *)set_copy(so); | 
					
						
							|  |  |  | 	if (result == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2005-08-17 12:27:17 +00:00
										 |  |  | 	if ((PyObject *)so == other) | 
					
						
							|  |  |  | 		return (PyObject *)result; | 
					
						
							| 
									
										
										
										
											2005-08-01 21:39:29 +00:00
										 |  |  | 	if (set_update_internal(result, other) == -1) { | 
					
						
							| 
									
										
										
										
											2003-11-24 02:57:33 +00:00
										 |  |  | 		Py_DECREF(result); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return (PyObject *)result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(union_doc, | 
					
						
							|  |  |  |  "Return the union of two sets as a new set.\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | (i.e. all elements that are in either set.)"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | set_or(PySetObject *so, PyObject *other) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2003-11-17 16:42:33 +00:00
										 |  |  | 	if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) { | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 		Py_INCREF(Py_NotImplemented); | 
					
						
							|  |  |  | 		return Py_NotImplemented; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return set_union(so, other); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | set_ior(PySetObject *so, PyObject *other) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2003-11-17 16:42:33 +00:00
										 |  |  | 	if (!PyAnySet_Check(other)) { | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 		Py_INCREF(Py_NotImplemented); | 
					
						
							|  |  |  | 		return Py_NotImplemented; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-08-01 21:39:29 +00:00
										 |  |  | 	if (set_update_internal(so, other) == -1) | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	Py_INCREF(so); | 
					
						
							|  |  |  | 	return (PyObject *)so; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | set_intersection(PySetObject *so, PyObject *other) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PySetObject *result; | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	PyObject *key, *it, *tmp; | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-17 12:27:17 +00:00
										 |  |  | 	if ((PyObject *)so == other) | 
					
						
							|  |  |  | 		return set_copy(so); | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	result = (PySetObject *)make_new_set(so->ob_type, NULL); | 
					
						
							|  |  |  | 	if (result == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2003-11-24 02:57:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 	if (PyAnySet_Check(other)) {		 | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 		Py_ssize_t pos = 0; | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 		setentry *entry; | 
					
						
							| 
									
										
										
										
											2005-08-12 20:48:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-16 03:47:52 +00:00
										 |  |  | 		if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) { | 
					
						
							| 
									
										
										
										
											2005-08-12 20:48:39 +00:00
										 |  |  | 			tmp = (PyObject *)so; | 
					
						
							|  |  |  | 			so = (PySetObject *)other; | 
					
						
							|  |  |  | 			other = tmp; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 		while (set_next((PySetObject *)other, &pos, &entry)) { | 
					
						
							| 
									
										
										
										
											2006-09-07 02:42:48 +00:00
										 |  |  | 			int rv = set_contains_entry(so, entry); | 
					
						
							|  |  |  | 			if (rv == -1) { | 
					
						
							|  |  |  | 				Py_DECREF(result); | 
					
						
							|  |  |  | 				return NULL; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (rv) { | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 				if (set_add_entry(result, entry) == -1) { | 
					
						
							| 
									
										
										
										
											2003-12-31 14:08:58 +00:00
										 |  |  | 					Py_DECREF(result); | 
					
						
							|  |  |  | 					return NULL; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return (PyObject *)result; | 
					
						
							| 
									
										
										
										
											2003-11-24 02:57:33 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	it = PyObject_GetIter(other); | 
					
						
							|  |  |  | 	if (it == NULL) { | 
					
						
							|  |  |  | 		Py_DECREF(result); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	while ((key = PyIter_Next(it)) != NULL) { | 
					
						
							| 
									
										
										
										
											2006-12-08 03:17:18 +00:00
										 |  |  | 		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); | 
					
						
							| 
									
										
										
										
											2006-09-07 02:42:48 +00:00
										 |  |  | 		if (rv == -1) { | 
					
						
							|  |  |  | 			Py_DECREF(it); | 
					
						
							|  |  |  | 			Py_DECREF(result); | 
					
						
							|  |  |  | 			Py_DECREF(key); | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (rv) { | 
					
						
							| 
									
										
										
										
											2006-12-08 03:17:18 +00:00
										 |  |  | 			if (set_add_entry(result, &entry) == -1) { | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 				Py_DECREF(it); | 
					
						
							|  |  |  | 				Py_DECREF(result); | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 				Py_DECREF(key); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 				return NULL; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 		Py_DECREF(key); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	Py_DECREF(it); | 
					
						
							|  |  |  | 	if (PyErr_Occurred()) { | 
					
						
							|  |  |  | 		Py_DECREF(result); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return (PyObject *)result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(intersection_doc, | 
					
						
							|  |  |  | "Return the intersection of two sets as a new set.\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | (i.e. all elements that are in both sets.)"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | set_intersection_update(PySetObject *so, PyObject *other) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	PyObject *tmp; | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	tmp = set_intersection(so, other); | 
					
						
							|  |  |  | 	if (tmp == NULL) | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	set_swap_bodies(so, (PySetObject *)tmp); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	Py_DECREF(tmp); | 
					
						
							|  |  |  | 	Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(intersection_update_doc, | 
					
						
							|  |  |  | "Update a set with the intersection of itself and another."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | set_and(PySetObject *so, PyObject *other) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2003-11-17 16:42:33 +00:00
										 |  |  | 	if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) { | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 		Py_INCREF(Py_NotImplemented); | 
					
						
							|  |  |  | 		return Py_NotImplemented; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return set_intersection(so, other); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | set_iand(PySetObject *so, PyObject *other) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *result; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-17 16:42:33 +00:00
										 |  |  | 	if (!PyAnySet_Check(other)) { | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 		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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-13 18:41:28 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | set_difference_update_internal(PySetObject *so, PyObject *other) | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 	if ((PyObject *)so == other) | 
					
						
							|  |  |  | 		return set_clear_internal(so); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 	if (PyAnySet_Check(other)) { | 
					
						
							|  |  |  | 		setentry *entry; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 		Py_ssize_t pos = 0; | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 		while (set_next((PySetObject *)other, &pos, &entry)) | 
					
						
							| 
									
										
										
										
											2006-09-07 02:42:48 +00:00
										 |  |  | 			if (set_discard_entry(so, entry) == -1) | 
					
						
							|  |  |  | 				return -1; | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 	} 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; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 			Py_DECREF(key); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 		Py_DECREF(it); | 
					
						
							|  |  |  | 		if (PyErr_Occurred()) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 	/* 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 *other) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (set_difference_update_internal(so, other) != -1) | 
					
						
							| 
									
										
										
										
											2005-08-07 13:02:53 +00:00
										 |  |  | 		Py_RETURN_NONE; | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 	return NULL; | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(difference_update_doc, | 
					
						
							|  |  |  | "Remove all elements of another set from this set."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-12-15 13:23:55 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | set_difference(PySetObject *so, PyObject *other) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 	PyObject *result; | 
					
						
							|  |  |  | 	setentry *entry; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t pos = 0; | 
					
						
							| 
									
										
										
										
											2003-12-15 13:23:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	if (!PyAnySet_Check(other)  && !PyDict_Check(other)) { | 
					
						
							| 
									
										
										
										
											2003-12-15 13:23:55 +00:00
										 |  |  | 		result = set_copy(so); | 
					
						
							|  |  |  | 		if (result == NULL) | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 			return NULL; | 
					
						
							|  |  |  | 		if (set_difference_update_internal((PySetObject *)result, other) != -1) | 
					
						
							| 
									
										
										
										
											2003-12-15 13:23:55 +00:00
										 |  |  | 			return result; | 
					
						
							|  |  |  | 		Py_DECREF(result); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	result = make_new_set(so->ob_type, NULL); | 
					
						
							|  |  |  | 	if (result == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	if (PyDict_Check(other)) { | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 		while (set_next(so, &pos, &entry)) { | 
					
						
							|  |  |  | 			setentry entrycopy; | 
					
						
							|  |  |  | 			entrycopy.hash = entry->hash; | 
					
						
							|  |  |  | 			entrycopy.key = entry->key; | 
					
						
							|  |  |  | 			if (!PyDict_Contains(other, entry->key)) { | 
					
						
							| 
									
										
										
										
											2006-09-07 02:42:48 +00:00
										 |  |  | 				if (set_add_entry((PySetObject *)result, &entrycopy) == -1) { | 
					
						
							|  |  |  | 					Py_DECREF(result); | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 					return NULL; | 
					
						
							| 
									
										
										
										
											2006-09-07 02:42:48 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return result; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 	while (set_next(so, &pos, &entry)) { | 
					
						
							| 
									
										
										
										
											2006-09-07 02:42:48 +00:00
										 |  |  | 		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); | 
					
						
							| 
									
										
										
										
											2003-12-15 13:23:55 +00:00
										 |  |  | 				return NULL; | 
					
						
							| 
									
										
										
										
											2006-09-07 02:42:48 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2003-12-15 13:23:55 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(difference_doc, | 
					
						
							|  |  |  | "Return the difference of two sets as a new set.\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | (i.e. all elements that are in this set but not the other.)"); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | set_sub(PySetObject *so, PyObject *other) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2003-11-17 16:42:33 +00:00
										 |  |  | 	if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) { | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 		Py_INCREF(Py_NotImplemented); | 
					
						
							|  |  |  | 		return Py_NotImplemented; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return set_difference(so, other); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | set_isub(PySetObject *so, PyObject *other) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *result; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-17 16:42:33 +00:00
										 |  |  | 	if (!PyAnySet_Check(other)) { | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 		Py_INCREF(Py_NotImplemented); | 
					
						
							|  |  |  | 		return Py_NotImplemented; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	result = set_difference_update(so, other); | 
					
						
							|  |  |  | 	if (result == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	Py_DECREF(result); | 
					
						
							|  |  |  | 	Py_INCREF(so); | 
					
						
							|  |  |  | 	return (PyObject *)so; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2003-11-24 02:57:33 +00:00
										 |  |  | set_symmetric_difference_update(PySetObject *so, PyObject *other) | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	PySetObject *otherset; | 
					
						
							|  |  |  | 	PyObject *key; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t pos = 0; | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 	setentry *entry; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ((PyObject *)so == other) | 
					
						
							|  |  |  | 		return set_clear(so); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	if (PyDict_Check(other)) { | 
					
						
							|  |  |  | 		PyObject *value; | 
					
						
							|  |  |  | 		int rv; | 
					
						
							|  |  |  | 		while (PyDict_Next(other, &pos, &key, &value)) { | 
					
						
							| 
									
										
										
										
											2006-12-08 03:17:18 +00:00
										 |  |  | 			setentry an_entry; | 
					
						
							|  |  |  | 			long hash = PyObject_Hash(key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (hash == -1) | 
					
						
							|  |  |  | 				return NULL; | 
					
						
							|  |  |  | 			an_entry.hash = hash; | 
					
						
							|  |  |  | 			an_entry.key = key; | 
					
						
							|  |  |  | 			rv = set_discard_entry(so, &an_entry); | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 			if (rv == -1) | 
					
						
							|  |  |  | 				return NULL; | 
					
						
							|  |  |  | 			if (rv == DISCARD_NOTFOUND) { | 
					
						
							| 
									
										
										
										
											2006-12-08 03:17:18 +00:00
										 |  |  | 				if (set_add_entry(so, &an_entry) == -1) | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 					return NULL; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		Py_RETURN_NONE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (PyAnySet_Check(other)) { | 
					
						
							|  |  |  | 		Py_INCREF(other); | 
					
						
							|  |  |  | 		otherset = (PySetObject *)other; | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2003-11-20 22:54:33 +00:00
										 |  |  | 		otherset = (PySetObject *)make_new_set(so->ob_type, other); | 
					
						
							| 
									
										
										
										
											2003-11-24 02:57:33 +00:00
										 |  |  | 		if (otherset == NULL) | 
					
						
							| 
									
										
										
										
											2003-11-20 22:54:33 +00:00
										 |  |  | 			return NULL; | 
					
						
							| 
									
										
										
										
											2003-11-24 02:57:33 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 	while (set_next(otherset, &pos, &entry)) { | 
					
						
							|  |  |  | 		int rv = set_discard_entry(so, entry); | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		if (rv == -1) { | 
					
						
							| 
									
										
										
										
											2006-07-17 00:57:15 +00:00
										 |  |  | 			Py_DECREF(otherset); | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (rv == DISCARD_NOTFOUND) { | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 			if (set_add_entry(so, entry) == -1) { | 
					
						
							| 
									
										
										
										
											2006-07-17 00:57:15 +00:00
										 |  |  | 				Py_DECREF(otherset); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 				return NULL; | 
					
						
							| 
									
										
										
										
											2003-11-24 02:57:33 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	Py_DECREF(otherset); | 
					
						
							| 
									
										
										
										
											2003-11-24 02:57:33 +00:00
										 |  |  | 	Py_RETURN_NONE; | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-24 02:57:33 +00:00
										 |  |  | PyDoc_STRVAR(symmetric_difference_update_doc, | 
					
						
							|  |  |  | "Update a set with the symmetric difference of itself and another."); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2003-11-24 02:57:33 +00:00
										 |  |  | set_symmetric_difference(PySetObject *so, PyObject *other) | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	PyObject *rv; | 
					
						
							|  |  |  | 	PySetObject *otherset; | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	otherset = (PySetObject *)make_new_set(so->ob_type, other); | 
					
						
							|  |  |  | 	if (otherset == NULL) | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	rv = set_symmetric_difference_update(otherset, (PyObject *)so); | 
					
						
							|  |  |  | 	if (rv == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	Py_DECREF(rv); | 
					
						
							|  |  |  | 	return (PyObject *)otherset; | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-24 02:57:33 +00:00
										 |  |  | PyDoc_STRVAR(symmetric_difference_doc, | 
					
						
							|  |  |  | "Return the symmetric difference of two sets as a new set.\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | (i.e. all elements that are in exactly one of the sets.)"); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | set_xor(PySetObject *so, PyObject *other) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2003-11-17 16:42:33 +00:00
										 |  |  | 	if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) { | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 		Py_INCREF(Py_NotImplemented); | 
					
						
							|  |  |  | 		return Py_NotImplemented; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return set_symmetric_difference(so, other); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | set_ixor(PySetObject *so, PyObject *other) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *result; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-17 16:42:33 +00:00
										 |  |  | 	if (!PyAnySet_Check(other)) { | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 		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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-08-13 08:28:03 +00:00
										 |  |  | 	setentry *entry; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t pos = 0; | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-17 16:42:33 +00:00
										 |  |  | 	if (!PyAnySet_Check(other)) { | 
					
						
							| 
									
										
										
										
											2005-08-13 08:28:03 +00:00
										 |  |  | 		PyObject *tmp, *result; | 
					
						
							| 
									
										
										
										
											2003-11-21 07:56:36 +00:00
										 |  |  | 		tmp = make_new_set(&PySet_Type, other); | 
					
						
							|  |  |  | 		if (tmp == NULL) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		result = set_issubset(so, tmp); | 
					
						
							|  |  |  | 		Py_DECREF(tmp); | 
					
						
							|  |  |  | 		return result; | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-08-16 03:47:52 +00:00
										 |  |  | 	if (PySet_GET_SIZE(so) > PySet_GET_SIZE(other))  | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 		Py_RETURN_FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-13 08:28:03 +00:00
										 |  |  | 	while (set_next(so, &pos, &entry)) { | 
					
						
							| 
									
										
										
										
											2006-09-07 02:42:48 +00:00
										 |  |  | 		int rv = set_contains_entry((PySetObject *)other, entry); | 
					
						
							|  |  |  | 		if (rv == -1) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		if (!rv) | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 			Py_RETURN_FALSE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	Py_RETURN_TRUE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(issubset_doc, "Report whether another set contains this set."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | set_issuperset(PySetObject *so, PyObject *other) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2003-11-21 07:56:36 +00:00
										 |  |  | 	PyObject *tmp, *result; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-17 16:42:33 +00:00
										 |  |  | 	if (!PyAnySet_Check(other)) { | 
					
						
							| 
									
										
										
										
											2003-11-21 07:56:36 +00:00
										 |  |  | 		tmp = make_new_set(&PySet_Type, other); | 
					
						
							|  |  |  | 		if (tmp == NULL) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		result = set_issuperset(so, tmp); | 
					
						
							|  |  |  | 		Py_DECREF(tmp); | 
					
						
							|  |  |  | 		return result; | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return set_issubset((PySetObject *)other, (PyObject *)so); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(issuperset_doc, "Report whether this set contains another set."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | set_richcompare(PySetObject *v, PyObject *w, int op) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	PyObject *r1, *r2; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-17 16:42:33 +00:00
										 |  |  | 	if(!PyAnySet_Check(w)) { | 
					
						
							|  |  |  | 		if (op == Py_EQ) | 
					
						
							|  |  |  | 			Py_RETURN_FALSE; | 
					
						
							|  |  |  | 		if (op == Py_NE) | 
					
						
							|  |  |  | 			Py_RETURN_TRUE; | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 		PyErr_SetString(PyExc_TypeError, "can only compare to a set"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	switch (op) { | 
					
						
							|  |  |  | 	case Py_EQ: | 
					
						
							| 
									
										
										
										
											2005-08-16 03:47:52 +00:00
										 |  |  | 		if (PySet_GET_SIZE(v) != PySet_GET_SIZE(w)) | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 			Py_RETURN_FALSE; | 
					
						
							| 
									
										
										
										
											2005-08-24 00:24:40 +00:00
										 |  |  | 		if (v->hash != -1  && | 
					
						
							|  |  |  | 		    ((PySetObject *)w)->hash != -1 && | 
					
						
							|  |  |  | 		    v->hash != ((PySetObject *)w)->hash) | 
					
						
							|  |  |  | 			Py_RETURN_FALSE; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		return set_issubset(v, w); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	case Py_NE: | 
					
						
							| 
									
										
										
										
											2005-08-24 00:24:40 +00:00
										 |  |  | 		r1 = set_richcompare(v, w, Py_EQ); | 
					
						
							|  |  |  | 		if (r1 == NULL) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		r2 = PyBool_FromLong(PyObject_Not(r1)); | 
					
						
							|  |  |  | 		Py_DECREF(r1); | 
					
						
							|  |  |  | 		return r2; | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	case Py_LE: | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		return set_issubset(v, w); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	case Py_GE: | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		return set_issuperset(v, w); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	case Py_LT: | 
					
						
							| 
									
										
										
										
											2005-08-16 03:47:52 +00:00
										 |  |  | 		if (PySet_GET_SIZE(v) >= PySet_GET_SIZE(w)) | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 			Py_RETURN_FALSE;		 | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		return set_issubset(v, w); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	case Py_GT: | 
					
						
							| 
									
										
										
										
											2005-08-16 03:47:52 +00:00
										 |  |  | 		if (PySet_GET_SIZE(v) <= PySet_GET_SIZE(w)) | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 			Py_RETURN_FALSE; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		return set_issuperset(v, w); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	Py_INCREF(Py_NotImplemented); | 
					
						
							|  |  |  | 	return Py_NotImplemented; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-13 08:28:03 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2006-03-30 11:57:00 +00:00
										 |  |  | set_nocmp(PyObject *self, PyObject *other) | 
					
						
							| 
									
										
										
										
											2005-08-13 08:28:03 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PyErr_SetString(PyExc_TypeError, "cannot compare sets using cmp()"); | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | set_add(PySetObject *so, PyObject *key) | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-08-11 07:58:45 +00:00
										 |  |  | 	if (set_add_key(so, key) == -1) | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2003-12-13 19:38:47 +00:00
										 |  |  | 	Py_RETURN_NONE; | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(add_doc,  | 
					
						
							|  |  |  | "Add an element to a set.\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | This has no effect if the element is already present."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-13 09:28:48 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | set_contains(PySetObject *so, PyObject *key) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *tmpkey; | 
					
						
							|  |  |  | 	int rv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rv = set_contains_key(so, key); | 
					
						
							|  |  |  | 	if (rv == -1) { | 
					
						
							|  |  |  | 		if (!PyAnySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		PyErr_Clear(); | 
					
						
							|  |  |  | 		tmpkey = make_new_set(&PyFrozenSet_Type, NULL); | 
					
						
							|  |  |  | 		if (tmpkey == NULL) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key); | 
					
						
							|  |  |  | 		rv = set_contains(so, tmpkey); | 
					
						
							|  |  |  | 		set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key); | 
					
						
							|  |  |  | 		Py_DECREF(tmpkey); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return rv; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | set_direct_contains(PySetObject *so, PyObject *key) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	long 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."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | set_remove(PySetObject *so, PyObject *key) | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	PyObject *tmpkey, *result; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	int rv; | 
					
						
							| 
									
										
										
										
											2003-11-22 03:55:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-12 20:48:39 +00:00
										 |  |  | 	rv = set_discard_key(so, key); | 
					
						
							|  |  |  | 	if (rv == -1) { | 
					
						
							|  |  |  | 		if (!PyAnySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		PyErr_Clear(); | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 		tmpkey = make_new_set(&PyFrozenSet_Type, NULL); | 
					
						
							|  |  |  | 		if (tmpkey == NULL) | 
					
						
							| 
									
										
										
										
											2003-11-22 03:55:23 +00:00
										 |  |  | 			return NULL; | 
					
						
							| 
									
										
										
										
											2005-08-12 20:48:39 +00:00
										 |  |  | 		set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key); | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 		result = set_remove(so, tmpkey); | 
					
						
							| 
									
										
										
										
											2005-08-12 20:48:39 +00:00
										 |  |  | 		set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key); | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 		Py_DECREF(tmpkey); | 
					
						
							| 
									
										
										
										
											2003-12-13 18:53:18 +00:00
										 |  |  | 		return result; | 
					
						
							| 
									
										
										
										
											2005-08-12 20:48:39 +00:00
										 |  |  | 	} else if (rv == DISCARD_NOTFOUND) { | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 		PyErr_SetObject(PyExc_KeyError, key); | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2003-12-13 19:38:47 +00:00
										 |  |  | 	Py_RETURN_NONE; | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(remove_doc, | 
					
						
							|  |  |  | "Remove an element from a set; it must be a member.\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | If the element is not a member, raise a KeyError."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | set_discard(PySetObject *so, PyObject *key) | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 	PyObject *tmpkey, *result; | 
					
						
							| 
									
										
										
										
											2005-08-12 20:48:39 +00:00
										 |  |  | 	int rv; | 
					
						
							| 
									
										
										
										
											2003-12-13 18:53:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-12 20:48:39 +00:00
										 |  |  | 	rv = set_discard_key(so, key); | 
					
						
							|  |  |  | 	if (rv == -1) { | 
					
						
							|  |  |  | 		if (!PyAnySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		PyErr_Clear(); | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 		tmpkey = make_new_set(&PyFrozenSet_Type, NULL); | 
					
						
							|  |  |  | 		if (tmpkey == NULL) | 
					
						
							| 
									
										
										
										
											2003-12-13 18:53:18 +00:00
										 |  |  | 			return NULL; | 
					
						
							| 
									
										
										
										
											2005-08-12 20:48:39 +00:00
										 |  |  | 		set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key); | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 		result = set_discard(so, tmpkey); | 
					
						
							| 
									
										
										
										
											2005-08-12 20:48:39 +00:00
										 |  |  | 		set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key); | 
					
						
							| 
									
										
										
										
											2005-07-31 15:36:06 +00:00
										 |  |  | 		Py_DECREF(tmpkey); | 
					
						
							| 
									
										
										
										
											2003-12-13 18:53:18 +00:00
										 |  |  | 		return result; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2003-12-13 19:38:47 +00:00
										 |  |  | 	Py_RETURN_NONE; | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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.");  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | set_reduce(PySetObject *so) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-11-09 07:25:31 +00:00
										 |  |  | 	PyObject *keys=NULL, *args=NULL, *result=NULL, *dict=NULL; | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	keys = PySequence_List((PyObject *)so); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	if (keys == NULL) | 
					
						
							|  |  |  | 		goto done; | 
					
						
							|  |  |  | 	args = PyTuple_Pack(1, keys); | 
					
						
							|  |  |  | 	if (args == NULL) | 
					
						
							|  |  |  | 		goto done; | 
					
						
							| 
									
										
										
										
											2004-11-09 07:25:31 +00:00
										 |  |  | 	dict = PyObject_GetAttrString((PyObject *)so, "__dict__"); | 
					
						
							|  |  |  | 	if (dict == NULL) { | 
					
						
							|  |  |  | 		PyErr_Clear(); | 
					
						
							|  |  |  | 		dict = Py_None; | 
					
						
							|  |  |  | 		Py_INCREF(dict); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	result = PyTuple_Pack(3, so->ob_type, args, dict); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | done: | 
					
						
							|  |  |  | 	Py_XDECREF(args); | 
					
						
							|  |  |  | 	Py_XDECREF(keys); | 
					
						
							| 
									
										
										
										
											2004-11-09 07:25:31 +00:00
										 |  |  | 	Py_XDECREF(dict); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-17 16:42:33 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | set_init(PySetObject *self, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *iterable = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyAnySet_Check(self)) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	if (!PyArg_UnpackTuple(args, self->ob_type->tp_name, 0, 1, &iterable)) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	set_clear_internal(self); | 
					
						
							| 
									
										
										
										
											2003-11-17 16:42:33 +00:00
										 |  |  | 	self->hash = -1; | 
					
						
							|  |  |  | 	if (iterable == NULL) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2005-08-01 21:39:29 +00:00
										 |  |  | 	return set_update_internal(self, iterable); | 
					
						
							| 
									
										
										
										
											2003-11-17 16:42:33 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | static PySequenceMethods set_as_sequence = { | 
					
						
							| 
									
										
										
										
											2006-03-30 11:57:00 +00:00
										 |  |  | 	set_len,			/* sq_length */ | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	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 ********************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-16 10:44:15 +00:00
										 |  |  | #ifdef Py_DEBUG
 | 
					
						
							|  |  |  | static PyObject *test_c_api(PySetObject *so); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(test_c_api_doc, "Exercises C API.  Returns True.\n\
 | 
					
						
							|  |  |  | All is well if assertions don't fail."); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | static PyMethodDef set_methods[] = { | 
					
						
							|  |  |  | 	{"add",		(PyCFunction)set_add,		METH_O, | 
					
						
							|  |  |  | 	 add_doc}, | 
					
						
							|  |  |  | 	{"clear",	(PyCFunction)set_clear,		METH_NOARGS, | 
					
						
							|  |  |  | 	 clear_doc}, | 
					
						
							| 
									
										
										
										
											2003-12-13 18:53:18 +00:00
										 |  |  | 	{"__contains__",(PyCFunction)set_direct_contains,	METH_O | METH_COEXIST, | 
					
						
							| 
									
										
										
										
											2003-12-13 11:26:12 +00:00
										 |  |  | 	 contains_doc}, | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	{"copy",	(PyCFunction)set_copy,		METH_NOARGS, | 
					
						
							|  |  |  | 	 copy_doc}, | 
					
						
							|  |  |  | 	{"discard",	(PyCFunction)set_discard,	METH_O, | 
					
						
							|  |  |  | 	 discard_doc}, | 
					
						
							|  |  |  | 	{"difference",	(PyCFunction)set_difference,	METH_O, | 
					
						
							|  |  |  | 	 difference_doc}, | 
					
						
							|  |  |  | 	{"difference_update",	(PyCFunction)set_difference_update,	METH_O, | 
					
						
							|  |  |  | 	 difference_update_doc}, | 
					
						
							|  |  |  | 	{"intersection",(PyCFunction)set_intersection,	METH_O, | 
					
						
							|  |  |  | 	 intersection_doc}, | 
					
						
							|  |  |  | 	{"intersection_update",(PyCFunction)set_intersection_update,	METH_O, | 
					
						
							|  |  |  | 	 intersection_update_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}, | 
					
						
							|  |  |  | 	{"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}, | 
					
						
							| 
									
										
										
										
											2005-08-16 10:44:15 +00:00
										 |  |  | #ifdef Py_DEBUG
 | 
					
						
							|  |  |  | 	{"test_c_api",	(PyCFunction)test_c_api,	METH_NOARGS, | 
					
						
							|  |  |  | 	 test_c_api_doc}, | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	{"union",	(PyCFunction)set_union,		METH_O, | 
					
						
							|  |  |  | 	 union_doc}, | 
					
						
							| 
									
										
										
										
											2003-11-24 22:18:49 +00:00
										 |  |  | 	{"update",	(PyCFunction)set_update,	METH_O, | 
					
						
							|  |  |  | 	 update_doc}, | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	{NULL,		NULL}	/* sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyNumberMethods set_as_number = { | 
					
						
							|  |  |  | 	0,				/*nb_add*/ | 
					
						
							|  |  |  | 	(binaryfunc)set_sub,		/*nb_subtract*/ | 
					
						
							|  |  |  | 	0,				/*nb_multiply*/ | 
					
						
							|  |  |  | 	0,				/*nb_divide*/ | 
					
						
							|  |  |  | 	0,				/*nb_remainder*/ | 
					
						
							|  |  |  | 	0,				/*nb_divmod*/ | 
					
						
							|  |  |  | 	0,				/*nb_power*/ | 
					
						
							|  |  |  | 	0,				/*nb_negative*/ | 
					
						
							|  |  |  | 	0,				/*nb_positive*/ | 
					
						
							|  |  |  | 	0,				/*nb_absolute*/ | 
					
						
							|  |  |  | 	0,				/*nb_nonzero*/ | 
					
						
							|  |  |  | 	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_coerce*/ | 
					
						
							|  |  |  | 	0,				/*nb_int*/ | 
					
						
							|  |  |  | 	0,				/*nb_long*/ | 
					
						
							|  |  |  | 	0,				/*nb_float*/ | 
					
						
							|  |  |  | 	0,				/*nb_oct*/ | 
					
						
							|  |  |  | 	0, 				/*nb_hex*/ | 
					
						
							|  |  |  | 	0,				/*nb_inplace_add*/ | 
					
						
							|  |  |  | 	(binaryfunc)set_isub,		/*nb_inplace_subtract*/ | 
					
						
							|  |  |  | 	0,				/*nb_inplace_multiply*/ | 
					
						
							|  |  |  | 	0,				/*nb_inplace_divide*/ | 
					
						
							|  |  |  | 	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, | 
					
						
							|  |  |  | "set(iterable) --> set object\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							| 
									
										
										
										
											2006-07-29 15:10:32 +00:00
										 |  |  | Build an unordered collection of unique elements."); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | PyTypeObject PySet_Type = { | 
					
						
							|  |  |  | 	PyObject_HEAD_INIT(&PyType_Type) | 
					
						
							|  |  |  | 	0,				/* ob_size */ | 
					
						
							|  |  |  | 	"set",				/* tp_name */ | 
					
						
							|  |  |  | 	sizeof(PySetObject),		/* tp_basicsize */ | 
					
						
							|  |  |  | 	0,				/* tp_itemsize */ | 
					
						
							|  |  |  | 	/* methods */ | 
					
						
							|  |  |  | 	(destructor)set_dealloc,	/* tp_dealloc */ | 
					
						
							|  |  |  | 	(printfunc)set_tp_print,	/* tp_print */ | 
					
						
							|  |  |  | 	0,				/* tp_getattr */ | 
					
						
							|  |  |  | 	0,				/* tp_setattr */ | 
					
						
							| 
									
										
										
										
											2006-03-30 11:57:00 +00:00
										 |  |  | 	set_nocmp,			/* tp_compare */ | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	(reprfunc)set_repr,		/* tp_repr */ | 
					
						
							|  |  |  | 	&set_as_number,			/* tp_as_number */ | 
					
						
							|  |  |  | 	&set_as_sequence,		/* tp_as_sequence */ | 
					
						
							|  |  |  | 	0,				/* tp_as_mapping */ | 
					
						
							|  |  |  | 	set_nohash,			/* tp_hash */ | 
					
						
							|  |  |  | 	0,				/* tp_call */ | 
					
						
							|  |  |  | 	0,				/* tp_str */ | 
					
						
							|  |  |  | 	PyObject_GenericGetAttr,	/* tp_getattro */ | 
					
						
							|  |  |  | 	0,				/* tp_setattro */ | 
					
						
							|  |  |  | 	0,				/* tp_as_buffer */ | 
					
						
							| 
									
										
										
										
											2005-06-18 21:00:26 +00:00
										 |  |  | 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES | | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		Py_TPFLAGS_BASETYPE,	/* tp_flags */ | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	set_doc,			/* tp_doc */ | 
					
						
							| 
									
										
										
										
											2005-06-18 21:00:26 +00:00
										 |  |  | 	(traverseproc)set_traverse,	/* tp_traverse */ | 
					
						
							| 
									
										
										
										
											2005-08-06 05:43:39 +00:00
										 |  |  | 	(inquiry)set_clear_internal,	/* tp_clear */ | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	(richcmpfunc)set_richcompare,	/* tp_richcompare */ | 
					
						
							| 
									
										
										
										
											2004-05-30 07:26:47 +00:00
										 |  |  | 	offsetof(PySetObject, weakreflist),	/* tp_weaklistoffset */ | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 	(getiterfunc)set_iter,	/* tp_iter */ | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	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 */ | 
					
						
							| 
									
										
										
										
											2003-11-17 16:42:33 +00:00
										 |  |  | 	(initproc)set_init,		/* tp_init */ | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	PyType_GenericAlloc,		/* tp_alloc */ | 
					
						
							|  |  |  | 	set_new,			/* tp_new */ | 
					
						
							| 
									
										
										
										
											2005-06-18 21:00:26 +00:00
										 |  |  | 	PyObject_GC_Del,		/* tp_free */ | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* frozenset object ********************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMethodDef frozenset_methods[] = { | 
					
						
							| 
									
										
										
										
											2003-12-13 18:53:18 +00:00
										 |  |  | 	{"__contains__",(PyCFunction)set_direct_contains,	METH_O | METH_COEXIST, | 
					
						
							| 
									
										
										
										
											2003-12-13 11:26:12 +00:00
										 |  |  | 	 contains_doc}, | 
					
						
							| 
									
										
										
										
											2003-11-23 02:49:05 +00:00
										 |  |  | 	{"copy",	(PyCFunction)frozenset_copy,	METH_NOARGS, | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	 copy_doc}, | 
					
						
							| 
									
										
										
										
											2003-11-23 02:49:05 +00:00
										 |  |  | 	{"difference",	(PyCFunction)set_difference,	METH_O, | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	 difference_doc}, | 
					
						
							|  |  |  | 	{"intersection",(PyCFunction)set_intersection,	METH_O, | 
					
						
							|  |  |  | 	 intersection_doc}, | 
					
						
							| 
									
										
										
										
											2003-11-23 02:49:05 +00:00
										 |  |  | 	{"issubset",	(PyCFunction)set_issubset,	METH_O, | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	 issubset_doc}, | 
					
						
							| 
									
										
										
										
											2003-11-23 02:49:05 +00:00
										 |  |  | 	{"issuperset",	(PyCFunction)set_issuperset,	METH_O, | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	 issuperset_doc}, | 
					
						
							|  |  |  | 	{"__reduce__",	(PyCFunction)set_reduce,	METH_NOARGS, | 
					
						
							|  |  |  | 	 reduce_doc}, | 
					
						
							|  |  |  | 	{"symmetric_difference",(PyCFunction)set_symmetric_difference,	METH_O, | 
					
						
							|  |  |  | 	 symmetric_difference_doc}, | 
					
						
							|  |  |  | 	{"union",	(PyCFunction)set_union,		METH_O, | 
					
						
							|  |  |  | 	 union_doc}, | 
					
						
							|  |  |  | 	{NULL,		NULL}	/* sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyNumberMethods frozenset_as_number = { | 
					
						
							|  |  |  | 	0,				/*nb_add*/ | 
					
						
							|  |  |  | 	(binaryfunc)set_sub,		/*nb_subtract*/ | 
					
						
							|  |  |  | 	0,				/*nb_multiply*/ | 
					
						
							|  |  |  | 	0,				/*nb_divide*/ | 
					
						
							|  |  |  | 	0,				/*nb_remainder*/ | 
					
						
							|  |  |  | 	0,				/*nb_divmod*/ | 
					
						
							|  |  |  | 	0,				/*nb_power*/ | 
					
						
							|  |  |  | 	0,				/*nb_negative*/ | 
					
						
							|  |  |  | 	0,				/*nb_positive*/ | 
					
						
							|  |  |  | 	0,				/*nb_absolute*/ | 
					
						
							|  |  |  | 	0,				/*nb_nonzero*/ | 
					
						
							|  |  |  | 	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, | 
					
						
							|  |  |  | "frozenset(iterable) --> frozenset object\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							| 
									
										
										
										
											2006-07-29 15:10:32 +00:00
										 |  |  | Build an immutable unordered collection of unique elements."); | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | PyTypeObject PyFrozenSet_Type = { | 
					
						
							|  |  |  | 	PyObject_HEAD_INIT(&PyType_Type) | 
					
						
							|  |  |  | 	0,				/* ob_size */ | 
					
						
							|  |  |  | 	"frozenset",			/* tp_name */ | 
					
						
							|  |  |  | 	sizeof(PySetObject),		/* tp_basicsize */ | 
					
						
							| 
									
										
										
										
											2003-12-31 14:08:58 +00:00
										 |  |  | 	0,				/* tp_itemsize */ | 
					
						
							|  |  |  | 	/* methods */ | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	(destructor)set_dealloc,	/* tp_dealloc */ | 
					
						
							|  |  |  | 	(printfunc)set_tp_print,	/* tp_print */ | 
					
						
							|  |  |  | 	0,				/* tp_getattr */ | 
					
						
							|  |  |  | 	0,				/* tp_setattr */ | 
					
						
							| 
									
										
										
										
											2006-03-30 11:57:00 +00:00
										 |  |  | 	set_nocmp,			/* tp_compare */ | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	(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 */ | 
					
						
							| 
									
										
										
										
											2005-06-18 21:00:26 +00:00
										 |  |  | 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES | | 
					
						
							| 
									
										
										
										
											2005-07-31 01:16:36 +00:00
										 |  |  | 		Py_TPFLAGS_BASETYPE,	/* tp_flags */ | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	frozenset_doc,			/* tp_doc */ | 
					
						
							| 
									
										
										
										
											2005-06-18 21:00:26 +00:00
										 |  |  | 	(traverseproc)set_traverse,	/* tp_traverse */ | 
					
						
							| 
									
										
										
										
											2005-08-06 05:43:39 +00:00
										 |  |  | 	(inquiry)set_clear_internal,	/* tp_clear */ | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	(richcmpfunc)set_richcompare,	/* tp_richcompare */ | 
					
						
							| 
									
										
										
										
											2004-05-30 07:26:47 +00:00
										 |  |  | 	offsetof(PySetObject, weakreflist),	/* tp_weaklistoffset */ | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | 	(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 */ | 
					
						
							| 
									
										
										
										
											2003-11-17 16:42:33 +00:00
										 |  |  | 	frozenset_new,			/* tp_new */ | 
					
						
							| 
									
										
										
										
											2005-06-18 21:00:26 +00:00
										 |  |  | 	PyObject_GC_Del,		/* tp_free */ | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2005-08-16 03:47:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /***** C API functions *************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | PySet_New(PyObject *iterable) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return make_new_set(&PySet_Type, iterable); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | PyFrozenSet_New(PyObject *iterable) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-08-16 10:44:15 +00:00
										 |  |  | 	PyObject *args, *result; | 
					
						
							| 
									
										
										
										
											2005-08-16 03:47:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-16 10:44:15 +00:00
										 |  |  | 	if (iterable == NULL) | 
					
						
							|  |  |  | 		args = PyTuple_New(0); | 
					
						
							|  |  |  | 	else | 
					
						
							| 
									
										
										
										
											2005-08-16 03:47:52 +00:00
										 |  |  | 		args = PyTuple_Pack(1, iterable); | 
					
						
							| 
									
										
										
										
											2005-08-16 10:44:15 +00:00
										 |  |  | 	if (args == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2005-08-16 03:47:52 +00:00
										 |  |  | 	result = frozenset_new(&PyFrozenSet_Type, args, NULL); | 
					
						
							| 
									
										
										
										
											2005-08-16 10:44:15 +00:00
										 |  |  | 	Py_DECREF(args); | 
					
						
							| 
									
										
										
										
											2005-08-16 03:47:52 +00:00
										 |  |  | 	return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-04 18:41:19 +00:00
										 |  |  | Py_ssize_t | 
					
						
							| 
									
										
										
										
											2005-08-16 10:44:15 +00:00
										 |  |  | PySet_Size(PyObject *anyset) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!PyAnySet_Check(anyset)) { | 
					
						
							|  |  |  | 		PyErr_BadInternalCall(); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-08-24 00:24:40 +00:00
										 |  |  | 	return PySet_GET_SIZE(anyset); | 
					
						
							| 
									
										
										
										
											2005-08-16 10:44:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-30 22:45:35 +00:00
										 |  |  | int | 
					
						
							|  |  |  | PySet_Clear(PyObject *set) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!PyType_IsSubtype(set->ob_type, &PySet_Type)) { | 
					
						
							|  |  |  | 		PyErr_BadInternalCall(); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return set_clear_internal((PySetObject *)set); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-16 03:47:52 +00:00
										 |  |  | int | 
					
						
							|  |  |  | PySet_Contains(PyObject *anyset, PyObject *key) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!PyAnySet_Check(anyset)) { | 
					
						
							|  |  |  | 		PyErr_BadInternalCall(); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return set_contains_key((PySetObject *)anyset, key); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							| 
									
										
										
										
											2005-08-16 10:44:15 +00:00
										 |  |  | PySet_Discard(PyObject *set, PyObject *key) | 
					
						
							| 
									
										
										
										
											2005-08-16 03:47:52 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-08-16 10:44:15 +00:00
										 |  |  | 	if (!PyType_IsSubtype(set->ob_type, &PySet_Type)) { | 
					
						
							| 
									
										
										
										
											2005-08-16 03:47:52 +00:00
										 |  |  | 		PyErr_BadInternalCall(); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-08-16 10:44:15 +00:00
										 |  |  | 	return set_discard_key((PySetObject *)set, key); | 
					
						
							| 
									
										
										
										
											2005-08-16 03:47:52 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | PySet_Add(PyObject *set, PyObject *key) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!PyType_IsSubtype(set->ob_type, &PySet_Type)) { | 
					
						
							|  |  |  | 		PyErr_BadInternalCall(); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return set_add_key((PySetObject *)set, key); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-30 22:45:35 +00:00
										 |  |  | int | 
					
						
							|  |  |  | _PySet_Next(PyObject *set, Py_ssize_t *pos, PyObject **entry) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	setentry *entry_ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyAnySet_Check(set)) { | 
					
						
							|  |  |  | 		PyErr_BadInternalCall(); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (set_next((PySetObject *)set, pos, &entry_ptr) == 0) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	*entry = entry_ptr->key; | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-16 03:47:52 +00:00
										 |  |  | PyObject * | 
					
						
							|  |  |  | PySet_Pop(PyObject *set) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!PyType_IsSubtype(set->ob_type, &PySet_Type)) { | 
					
						
							|  |  |  | 		PyErr_BadInternalCall(); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return set_pop((PySetObject *)set); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2005-08-16 10:44:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-30 22:45:35 +00:00
										 |  |  | int | 
					
						
							|  |  |  | _PySet_Update(PyObject *set, PyObject *iterable) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!PyType_IsSubtype(set->ob_type, &PySet_Type)) { | 
					
						
							|  |  |  | 		PyErr_BadInternalCall(); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return set_update_internal((PySetObject *)set, iterable); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2005-08-16 10:44:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef Py_DEBUG
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* 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) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | test_c_api(PySetObject *so) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-06-19 05:40:44 +00:00
										 |  |  | 	Py_ssize_t count; | 
					
						
							| 
									
										
										
										
											2006-03-30 22:45:35 +00:00
										 |  |  | 	char *s; | 
					
						
							|  |  |  | 	Py_ssize_t i; | 
					
						
							|  |  |  | 	PyObject *elem, *dup, *t, *f, *dup2; | 
					
						
							|  |  |  | 	PyObject *ob = (PyObject *)so; | 
					
						
							| 
									
										
										
										
											2005-08-16 10:44:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Verify preconditions and exercise type/size checks */ | 
					
						
							|  |  |  | 	assert(PyAnySet_Check(ob)); | 
					
						
							|  |  |  | 	assert(PyAnySet_CheckExact(ob)); | 
					
						
							|  |  |  | 	assert(!PyFrozenSet_CheckExact(ob)); | 
					
						
							|  |  |  | 	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); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-30 22:45:35 +00:00
										 |  |  | 	/* 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); | 
					
						
							|  |  |  | 	Py_DECREF(f); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Exercise direct iteration */ | 
					
						
							|  |  |  | 	i = 0, count = 0; | 
					
						
							|  |  |  | 	while (_PySet_Next((PyObject *)dup, &i, &elem)) { | 
					
						
							|  |  |  | 		s = PyString_AsString(elem); | 
					
						
							|  |  |  | 		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); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-16 10:44:15 +00:00
										 |  |  | 	/* 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_Add(f, elem) == -1, PyExc_SystemError); | 
					
						
							|  |  |  | 	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 */ | 
					
						
							| 
									
										
										
										
											2005-08-17 12:27:17 +00:00
										 |  |  | 	assert(PyNumber_InPlaceSubtract(ob, ob) == ob); | 
					
						
							|  |  |  | 	Py_DECREF(ob); | 
					
						
							| 
									
										
										
										
											2005-08-16 10:44:15 +00:00
										 |  |  | 	assert(PySet_GET_SIZE(ob) == 0); | 
					
						
							|  |  |  | 	assertRaises(PySet_Pop(ob) == NULL, PyExc_KeyError); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-17 12:27:17 +00:00
										 |  |  | 	/* Restore the set from the copy using the PyNumber API */ | 
					
						
							|  |  |  | 	assert(PyNumber_InPlaceOr(ob, dup) == ob); | 
					
						
							|  |  |  | 	Py_DECREF(ob); | 
					
						
							| 
									
										
										
										
											2005-08-16 10:44:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* 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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-09-16 07:14:21 +00:00
										 |  |  | #undef assertRaises
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-16 10:44:15 +00:00
										 |  |  | #endif
 |