Ejemplo n.º 1
0
/* Return:
   NULL for exception;
   some object not equal to NotImplemented if it is implemented
     (this latter object may not be a Boolean).
*/
PyObject *
PyObject_RichCompare(PyObject *v, PyObject *w, int op)
{
	PyObject *res;

	assert(Py_LT <= op && op <= Py_GE);
	if (Py_EnterRecursiveCall(" in cmp"))
		return NULL;

	/* If the types are equal, and not old-style instances, try to
	   get out cheap (don't bother with coercions etc.). */
	if (v->ob_type == w->ob_type && !PyInstance_Check(v)) {
		cmpfunc fcmp;
		richcmpfunc frich = RICHCOMPARE(v->ob_type);
		/* If the type has richcmp, try it first.  try_rich_compare
		   tries it two-sided, which is not needed since we've a
		   single type only. */
		if (frich != NULL) {
			res = (*frich)(v, w, op);
			if (res != Py_NotImplemented)
				goto Done;
			Py_DECREF(res);
		}
		/* No richcmp, or this particular richmp not implemented.
		   Try 3-way cmp. */
		fcmp = v->ob_type->tp_compare;
		if (fcmp != NULL) {
			int c = (*fcmp)(v, w);
			c = adjust_tp_compare(c);
			if (c == -2) {
				res = NULL;
				goto Done;
			}
			res = convert_3way_to_object(op, c);
			goto Done;
		}
	}

	/* Fast path not taken, or couldn't deliver a useful result. */
	res = do_richcmp(v, w, op);
Done:
	Py_LeaveRecursiveCall();
	return res;
}
Ejemplo n.º 2
0
/* Return:
   NULL for exception;
   some object not equal to NotImplemented if it is implemented
     (this latter object may not be a Boolean).
*/
PyObject *
PyObject_RichCompare(PyObject *v, PyObject *w, int op)
{
	PyObject *res;

	assert(Py_LT <= op && op <= Py_GE);

	compare_nesting++;
	if (compare_nesting > NESTING_LIMIT &&
		(v->ob_type->tp_as_mapping
		 || (v->ob_type->tp_as_sequence
		     && !PyString_Check(v)
		     && !PyTuple_Check(v)))) {

		/* try to detect circular data structures */
		PyObject *token = check_recursion(v, w, op);
		if (token == NULL) {
			res = NULL;
			goto Done;
		}
		else if (token == Py_None) {
			/* already comparing these objects with this operator.
			   assume they're equal until shown otherwise */
			if (op == Py_EQ)
				res = Py_True;
			else if (op == Py_NE)
				res = Py_False;
			else {
				PyErr_SetString(PyExc_ValueError,
					"can't order recursive values");
				res = NULL;
			}
			Py_XINCREF(res);
		}
		else {
			res = do_richcmp(v, w, op);
			delete_token(token);
		}
		goto Done;
	}

	/* No nesting extremism.
	   If the types are equal, and not old-style instances, try to
	   get out cheap (don't bother with coercions etc.). */
	if (v->ob_type == w->ob_type && !PyInstance_Check(v)) {
		cmpfunc fcmp;
		richcmpfunc frich = RICHCOMPARE(v->ob_type);
		/* If the type has richcmp, try it first.  try_rich_compare
		   tries it two-sided, which is not needed since we've a
		   single type only. */
		if (frich != NULL) {
			res = (*frich)(v, w, op);
			if (res != Py_NotImplemented)
				goto Done;
			Py_DECREF(res);
		}
		/* No richcmp, or this particular richmp not implemented.
		   Try 3-way cmp. */
		fcmp = v->ob_type->tp_compare;
		if (fcmp != NULL) {
			int c = (*fcmp)(v, w);
			if (c < 0 && PyErr_Occurred()) {
				res = NULL;
				goto Done;
			}
			res = convert_3way_to_object(op, c);
			goto Done;
		}
	}

	/* Fast path not taken, or couldn't deliver a useful result. */
	res = do_richcmp(v, w, op);
Done:
	compare_nesting--;
	return res;
}