diff options
author | Guido van Rossum <guido@python.org> | 1992-08-03 19:05:37 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1992-08-03 19:05:37 (GMT) |
commit | e10a19ea6d710ee495160682e60e37240562e92c (patch) | |
tree | 49072154d9e28eeec4e6bfeba2bcfe874b1175b4 | |
parent | 7b2c03f39b651410566b881707e7be7ee4bbb64f (diff) | |
download | cpython-e10a19ea6d710ee495160682e60e37240562e92c.zip cpython-e10a19ea6d710ee495160682e60e37240562e92c.tar.gz cpython-e10a19ea6d710ee495160682e60e37240562e92c.tar.bz2 |
listobject.c: added optional cmp function to list.sort().
-rw-r--r-- | Objects/listobject.c | 61 |
1 files changed, 54 insertions, 7 deletions
diff --git a/Objects/listobject.c b/Objects/listobject.c index 6992a0f..996c289 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -26,6 +26,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "allobjects.h" #include "modsupport.h" +#include "compile.h" /* Needed by ceval.h */ +#include "ceval.h" /* For call_object() */ object * newlistobject(size) @@ -471,11 +473,46 @@ listappend(self, args) return ins(self, (int) self->ob_size, args); } +static object *cmpfunc; + static int cmp(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 * @@ -483,14 +520,24 @@ listsort(self, args) listobject *self; object *args; { - if (args != NULL) { - err_badarg(); - return NULL; + object *save_cmpfunc; + if (self->ob_size <= 1) { + 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(); - if (self->ob_size > 1) - qsort((char *)self->ob_item, + qsort((char *)self->ob_item, (int) self->ob_size, sizeof(object *), cmp); + cmpfunc = save_cmpfunc; if (err_occurred()) return NULL; INCREF(None); |