Commit 69f4235a authored by Guido van Rossum's avatar Guido van Rossum

listobject.c: added optional cmp function to list.sort().

parent 609c3227
...@@ -26,6 +26,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ...@@ -26,6 +26,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "allobjects.h" #include "allobjects.h"
#include "modsupport.h" #include "modsupport.h"
#include "compile.h" /* Needed by ceval.h */
#include "ceval.h" /* For call_object() */
object * object *
newlistobject(size) newlistobject(size)
...@@ -471,11 +473,46 @@ listappend(self, args) ...@@ -471,11 +473,46 @@ listappend(self, args)
return ins(self, (int) self->ob_size, args); return ins(self, (int) self->ob_size, args);
} }
static object *cmpfunc;
static int static int
cmp(v, w) cmp(v, w)
char *v, *w; char *v, *w;
{ {
return cmpobject(* (object **) v, * (object **) w); object *t, *res;
long i;
if (err_occurred())
return 0;
if (cmpfunc == NULL)
return cmpobject(* (object **) v, * (object **) w);
/* Call the user-supplied comparison function */
t = newtupleobject(2);
if (t == NULL)
return 0;
INCREF(* (object **) v);
settupleitem(t, 0, * (object **) v);
INCREF(* (object **) w);
settupleitem(t, 1, * (object **) w);
res = call_object(cmpfunc, t);
DECREF(t);
if (res == NULL)
return 0;
if (!is_intobject(res)) {
err_setstr(TypeError, "comparison function should return int");
i = 0;
}
else {
i = getintvalue(res);
if (i < 0)
i = -1;
else if (i > 0)
i = 1;
}
DECREF(res);
return (int) i;
} }
static object * static object *
...@@ -483,14 +520,24 @@ listsort(self, args) ...@@ -483,14 +520,24 @@ listsort(self, args)
listobject *self; listobject *self;
object *args; object *args;
{ {
if (args != NULL) { object *save_cmpfunc;
err_badarg(); if (self->ob_size <= 1) {
return NULL; INCREF(None);
return None;
}
save_cmpfunc = cmpfunc;
cmpfunc = args;
if (cmpfunc != NULL) {
/* Test the comparison function for obvious errors */
(void) cmp(&self->ob_item[0], &self->ob_item[1]);
if (err_occurred()) {
cmpfunc = save_cmpfunc;
return NULL;
}
} }
err_clear(); qsort((char *)self->ob_item,
if (self->ob_size > 1)
qsort((char *)self->ob_item,
(int) self->ob_size, sizeof(object *), cmp); (int) self->ob_size, sizeof(object *), cmp);
cmpfunc = save_cmpfunc;
if (err_occurred()) if (err_occurred())
return NULL; return NULL;
INCREF(None); INCREF(None);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment