Skip to content

Instantly share code, notes, and snippets.

@jeremyBanks
Created July 21, 2011 21:35
Show Gist options
  • Save jeremyBanks/1098275 to your computer and use it in GitHub Desktop.
Save jeremyBanks/1098275 to your computer and use it in GitHub Desktop.
static PyObject *
min_max(PyObject *args, PyObject *kwds, int op)
{
PyObject *v, *it, *item, *val, *maxitem, *maxval, *keyfunc=NULL;
const char *name = op == Py_LT ? "min" : "max";
if (PyTuple_Size(args) > 1)
v = args;
else if (!PyArg_UnpackTuple(args, (char *)name, 1, 1, &v))
return NULL;
if (kwds != NULL && PyDict_Check(kwds) && PyDict_Size(kwds)) {
keyfunc = PyDict_GetItemString(kwds, "key");
if (PyDict_Size(kwds)!=1 || keyfunc == NULL) {
PyErr_Format(PyExc_TypeError,
"%s() got an unexpected keyword argument", name);
return NULL;
}
Py_INCREF(keyfunc);
}
it = PyObject_GetIter(v);
if (it == NULL) {
Py_XDECREF(keyfunc);
return NULL;
}
maxitem = NULL; /* the result */
maxval = NULL; /* the value associated with the result */
while (( item = PyIter_Next(it) )) {
/* get the value from the key function */
if (keyfunc != NULL) {
val = PyObject_CallFunctionObjArgs(keyfunc, item, NULL);
if (val == NULL)
goto Fail_it_item;
}
/* no key function; the value is the item */
else {
val = item;
Py_INCREF(val);
}
/* maximum value and item are unset; set them */
if (maxval == NULL) {
maxitem = item;
maxval = val;
}
/* maximum value and item are set; update them as necessary */
else {
int cmp = PyObject_RichCompareBool(val, maxval, op);
if (cmp < 0)
goto Fail_it_item_and_val;
else if (cmp > 0) {
Py_DECREF(maxval);
Py_DECREF(maxitem);
maxval = val;
maxitem = item;
}
else {
Py_DECREF(item);
Py_DECREF(val);
}
}
}
if (PyErr_Occurred())
goto Fail_it;
if (maxval == NULL) {
PyErr_Format(PyExc_ValueError,
"%s() arg is an empty sequence", name);
assert(maxitem == NULL);
}
else
Py_DECREF(maxval);
Py_DECREF(it);
Py_XDECREF(keyfunc);
return maxitem;
Fail_it_item_and_val:
Py_DECREF(val);
Fail_it_item:
Py_DECREF(item);
Fail_it:
Py_XDECREF(maxval);
Py_XDECREF(maxitem);
Py_DECREF(it);
Py_XDECREF(keyfunc);
return NULL;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment