/* Try a 3-way comparison, returning an int. Return: -2 for an exception; -1 if v < w; 0 if v == w; 1 if v > w; 2 if this particular 3-way comparison is not implemented or undefined. */ static int try_3way_compare(PyObject *v, PyObject *w) { int c; cmpfunc f; /* Comparisons involving instances are given to instance_compare, which has the same return conventions as this function. */ f = v->ob_type->tp_compare; if (PyInstance_Check(v)) return (*f)(v, w); if (PyInstance_Check(w)) return (*w->ob_type->tp_compare)(v, w); /* If both have the same (non-NULL) tp_compare, use it. */ if (f != NULL && f == w->ob_type->tp_compare) { c = (*f)(v, w); if (c < 0 && PyErr_Occurred()) return -1; return c < 0 ? -1 : c > 0 ? 1 : 0; } /* If either tp_compare is _PyObject_SlotCompare, that's safe. */ if (f == _PyObject_SlotCompare || w->ob_type->tp_compare == _PyObject_SlotCompare) return _PyObject_SlotCompare(v, w); /* Try coercion; if it fails, give up */ c = PyNumber_CoerceEx(&v, &w); if (c < 0) return -2; if (c > 0) return 2; /* Try v's comparison, if defined */ if ((f = v->ob_type->tp_compare) != NULL) { c = (*f)(v, w); Py_DECREF(v); Py_DECREF(w); if (c < 0 && PyErr_Occurred()) return -2; return c < 0 ? -1 : c > 0 ? 1 : 0; } /* Try w's comparison, if defined */ if ((f = w->ob_type->tp_compare) != NULL) { c = (*f)(w, v); /* swapped! */ Py_DECREF(v); Py_DECREF(w); if (c < 0 && PyErr_Occurred()) return -2; return c < 0 ? 1 : c > 0 ? -1 : 0; /* negated! */ } /* No comparison defined */ Py_DECREF(v); Py_DECREF(w); return 2; }
/* Try a 3-way comparison, returning an int. Return: -2 for an exception; -1 if v < w; 0 if v == w; 1 if v > w; 2 if this particular 3-way comparison is not implemented or undefined. */ static int try_3way_compare(PyObject *v, PyObject *w) { int c; cmpfunc f; /* Comparisons involving instances are given to instance_compare, which has the same return conventions as this function. */ f = v->ob_type->tp_compare; if (PyInstance_Check(v)) return (*f)(v, w); if (PyInstance_Check(w)) return (*w->ob_type->tp_compare)(v, w); /* If both have the same (non-NULL) tp_compare, use it. */ if (f != NULL && f == w->ob_type->tp_compare) { c = (*f)(v, w); return adjust_tp_compare(c); } /* If either tp_compare is _PyObject_SlotCompare, that's safe. */ if (f == _PyObject_SlotCompare || w->ob_type->tp_compare == _PyObject_SlotCompare) return _PyObject_SlotCompare(v, w); /* If we're here, v and w, a) are not instances; b) have different types or a type without tp_compare; and c) don't have a user-defined tp_compare. tp_compare implementations in C assume that both arguments have their type, so we give up if the coercion fails or if it yields types which are still incompatible (which can happen with a user-defined nb_coerce). */ c = PyNumber_CoerceEx(&v, &w); if (c < 0) return -2; if (c > 0) return 2; f = v->ob_type->tp_compare; if (f != NULL && f == w->ob_type->tp_compare) { c = (*f)(v, w); Py_DECREF(v); Py_DECREF(w); return adjust_tp_compare(c); } /* No comparison defined */ Py_DECREF(v); Py_DECREF(w); return 2; }