[Python-checkins] CVS: python/dist/src/Objects dictobject.c,2.72,2.73

Guido van Rossum gvanrossum@users.sourceforge.net
Wed, 17 Jan 2001 16:39:04 -0800


Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv2822

Modified Files:
	dictobject.c 
Log Message:
Rich comparisons:

- Use PyObject_RichCompareBool() when comparing keys; this makes the
  error handling cleaner.

- There were two implementations for dictionary comparison, an old one
  (#ifdef'ed out) and a new one.  Got rid of the old one, which was
  abandoned years ago.

- In the characterize() function, part of dictionary comparison, use
  PyObject_RichCompareBool() to compare keys and values instead.  But
  continue to use PyObject_Compare() for comparing the final
  (deciding) elements.

- Align the comments in the type struct initializer.

Note: I don't implement rich comparison for dictionaries -- there
doesn't seem to be much to be gained.  (The existing comparison
already decides that shorter dicts are always smaller than longer
dicts.)


Index: dictobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v
retrieving revision 2.72
retrieving revision 2.73
diff -C2 -r2.72 -r2.73
*** dictobject.c	2001/01/03 22:34:59	2.72
--- dictobject.c	2001/01/18 00:39:02	2.73
***************
*** 208,215 ****
  				PyErr_Fetch(&err_type, &err_value, &err_tb);
  			}
! 			cmp = PyObject_Compare(ep->me_key, key);
! 			if (PyErr_Occurred())
! 				PyErr_Clear();
! 			else if (cmp == 0) {
  				if (restore_error)
  					PyErr_Restore(err_type, err_value,
--- 208,213 ----
  				PyErr_Fetch(&err_type, &err_value, &err_tb);
  			}
! 			cmp = PyObject_RichCompareBool(ep->me_key, key, Py_EQ);
! 			if (cmp > 0) {
  				if (restore_error)
  					PyErr_Restore(err_type, err_value,
***************
*** 217,220 ****
--- 215,220 ----
  				return ep;
  			}
+ 			else if (cmp < 0)
+ 				PyErr_Clear();
  		}
  		freeslot = NULL;
***************
*** 253,260 ****
  				}
  			}
! 			cmp = PyObject_Compare(ep->me_key, key);
! 			if (PyErr_Occurred())
! 				PyErr_Clear();
! 			else if (cmp == 0) {
  				if (restore_error)
  					PyErr_Restore(err_type, err_value,
--- 253,258 ----
  				}
  			}
! 			cmp = PyObject_RichCompareBool(ep->me_key, key, Py_EQ);
! 			if (cmp > 0) {
  				if (restore_error)
  					PyErr_Restore(err_type, err_value,
***************
*** 262,265 ****
--- 260,265 ----
  				return ep;
  			}
+ 			else if (cmp < 0)
+ 				PyErr_Clear();
  		}
  		/* Cycle through GF(2^n)-{0} */
***************
*** 913,920 ****
  }
  
- #define NEWCMP
- 
- #ifdef NEWCMP
- 
  /* Subroutine which returns the smallest key in a for which b's value
     is different or absent.  The value is returned too, through the
--- 913,916 ----
***************
*** 925,929 ****
  {
  	PyObject *diff = NULL;
! 	int i;
  
  	*pval = NULL;
--- 921,925 ----
  {
  	PyObject *diff = NULL;
! 	int i, cmp;
  
  	*pval = NULL;
***************
*** 932,942 ****
  			PyObject *key = a->ma_table[i].me_key;
  			PyObject *aval, *bval;
! 			/* XXX What if PyObject_Compare raises an exception? */
! 			if (diff != NULL && PyObject_Compare(key, diff) > 0)
  				continue;
  			aval = a->ma_table[i].me_value;
  			bval = PyDict_GetItem((PyObject *)b, key);
! 			/* XXX What if PyObject_Compare raises an exception? */
! 			if (bval == NULL || PyObject_Compare(aval, bval) != 0)
  			{
  				diff = key;
--- 928,948 ----
  			PyObject *key = a->ma_table[i].me_key;
  			PyObject *aval, *bval;
! 			if (diff != NULL) {
! 			    cmp = PyObject_RichCompareBool(diff, key, Py_LT);
! 			    if (cmp < 0)
! 				return NULL;
! 			    if (cmp > 0)
  				continue;
+ 			}
  			aval = a->ma_table[i].me_value;
  			bval = PyDict_GetItem((PyObject *)b, key);
! 			if (bval == NULL)
! 				cmp = 0;
! 			else {
! 			    cmp = PyObject_RichCompareBool(aval, bval, Py_EQ);
! 			    if (cmp < 0)
! 				return NULL;
! 			}
! 			if (cmp == 0)
  			{
  				diff = key;
***************
*** 961,970 ****
  	/* Same length -- check all keys */
  	adiff = characterize(a, b, &aval);
! 	if (PyErr_Occurred())
  		return -1;
  	if (adiff == NULL)
  		return 0;	/* a is a subset with the same length */
  	bdiff = characterize(b, a, &bval);
! 	if (PyErr_Occurred())
  		return -1;
  	/* bdiff == NULL would be impossible now */
--- 967,976 ----
  	/* Same length -- check all keys */
  	adiff = characterize(a, b, &aval);
! 	if (adiff == NULL && PyErr_Occurred())
  		return -1;
  	if (adiff == NULL)
  		return 0;	/* a is a subset with the same length */
  	bdiff = characterize(b, a, &bval);
! 	if (bdiff == NULL && PyErr_Occurred())
  		return -1;
  	/* bdiff == NULL would be impossible now */
***************
*** 975,1058 ****
  }
  
- #else /* !NEWCMP */
- 
- static int
- dict_compare(dictobject *a, dictobject *b)
- {
- 	PyObject *akeys, *bkeys;
- 	int i, n, res;
- 	if (a == b)
- 		return 0;
- 	if (a->ma_used == 0) {
- 		if (b->ma_used != 0)
- 			return -1;
- 		else
- 			return 0;
- 	}
- 	else {
- 		if (b->ma_used == 0)
- 			return 1;
- 	}
- 	akeys = dict_keys(a, (PyObject *)NULL);
- 	bkeys = dict_keys(b, (PyObject *)NULL);
- 	if (akeys == NULL || bkeys == NULL) {
- 		/* Oops, out of memory -- what to do? */
- 		/* For now, sort on address! */
- 		Py_XDECREF(akeys);
- 		Py_XDECREF(bkeys);
- 		if (a < b)
- 			return -1;
- 		else
- 			return 1;
- 	}
- 	PyList_Sort(akeys);
- 	PyList_Sort(bkeys);
- 	n = a->ma_used < b->ma_used ? a->ma_used : b->ma_used; /* smallest */
- 	res = 0;
- 	for (i = 0; i < n; i++) {
- 		PyObject *akey, *bkey, *aval, *bval;
- 		long ahash, bhash;
- 		akey = PyList_GetItem(akeys, i);
- 		bkey = PyList_GetItem(bkeys, i);
- 		res = PyObject_Compare(akey, bkey);
- 		if (res != 0)
- 			break;
- #ifdef CACHE_HASH
- 		if (!PyString_Check(akey) ||
- 		    (ahash = ((PyStringObject *) akey)->ob_shash) == -1)
- #endif
- 		{
- 			ahash = PyObject_Hash(akey);
- 			if (ahash == -1)
- 				PyErr_Clear(); /* Don't want errors here */
- 		}
- #ifdef CACHE_HASH
- 		if (!PyString_Check(bkey) ||
- 		    (bhash = ((PyStringObject *) bkey)->ob_shash) == -1)
- #endif
- 		{
- 			bhash = PyObject_Hash(bkey);
- 			if (bhash == -1)
- 				PyErr_Clear(); /* Don't want errors here */
- 		}
- 		aval = (a->ma_lookup)(a, akey, ahash) -> me_value;
- 		bval = (b->ma_lookup)(b, bkey, bhash) -> me_value;
- 		res = PyObject_Compare(aval, bval);
- 		if (res != 0)
- 			break;
- 	}
- 	if (res == 0) {
- 		if (a->ma_used < b->ma_used)
- 			res = -1;
- 		else if (a->ma_used > b->ma_used)
- 			res = 1;
- 	}
- 	Py_DECREF(akeys);
- 	Py_DECREF(bkeys);
- 	return res;
- }
- 
- #endif /* !NEWCMP */
- 
  static PyObject *
  dict_has_key(register dictobject *mp, PyObject *args)
--- 981,984 ----
***************
*** 1299,1321 ****
  	sizeof(dictobject) + PyGC_HEAD_SIZE,
  	0,
! 	(destructor)dict_dealloc, /*tp_dealloc*/
! 	(printfunc)dict_print, /*tp_print*/
! 	(getattrfunc)dict_getattr, /*tp_getattr*/
! 	0,			/*tp_setattr*/
! 	(cmpfunc)dict_compare, /*tp_compare*/
! 	(reprfunc)dict_repr, /*tp_repr*/
! 	0,			/*tp_as_number*/
! 	0,			/*tp_as_sequence*/
! 	&dict_as_mapping,	/*tp_as_mapping*/
! 	0,		/* tp_hash */
! 	0,		/* tp_call */
! 	0,		/* tp_str */
! 	0,		/* tp_getattro */
! 	0,		/* tp_setattro */
! 	0,		/* tp_as_buffer */
! 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /*tp_flags*/
! 	0,		/* tp_doc */
! 	(traverseproc)dict_traverse,	/* tp_traverse */
! 	(inquiry)dict_tp_clear,		/* tp_clear */
  };
  
--- 1225,1248 ----
  	sizeof(dictobject) + PyGC_HEAD_SIZE,
  	0,
! 	(destructor)dict_dealloc,		/* tp_dealloc */
! 	(printfunc)dict_print,			/* tp_print */
! 	(getattrfunc)dict_getattr,		/* tp_getattr */
! 	0,					/* tp_setattr */
! 	(cmpfunc)dict_compare,			/* tp_compare */
! 	(reprfunc)dict_repr,			/* tp_repr */
! 	0,					/* tp_as_number */
! 	0,					/* tp_as_sequence */
! 	&dict_as_mapping,			/* tp_as_mapping */
! 	0,					/* tp_hash */
! 	0,					/* tp_call */
! 	0,					/* tp_str */
! 	0,					/* tp_getattro */
! 	0,					/* tp_setattro */
! 	0,					/* tp_as_buffer */
! 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC,	/* tp_flags */
! 	0,					/* tp_doc */
! 	(traverseproc)dict_traverse,		/* tp_traverse */
! 	(inquiry)dict_tp_clear,			/* tp_clear */
! 	0,					/* tp_richcompare */
  };