summaryrefslogtreecommitdiffstats
path: root/Objects/listobject.c
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1992-08-03 19:05:37 (GMT)
committerGuido van Rossum <guido@python.org>1992-08-03 19:05:37 (GMT)
commite10a19ea6d710ee495160682e60e37240562e92c (patch)
tree49072154d9e28eeec4e6bfeba2bcfe874b1175b4 /Objects/listobject.c
parent7b2c03f39b651410566b881707e7be7ee4bbb64f (diff)
downloadcpython-e10a19ea6d710ee495160682e60e37240562e92c.zip
cpython-e10a19ea6d710ee495160682e60e37240562e92c.tar.gz
cpython-e10a19ea6d710ee495160682e60e37240562e92c.tar.bz2
listobject.c: added optional cmp function to list.sort().
Diffstat (limited to 'Objects/listobject.c')
-rw-r--r--Objects/listobject.c61
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);