From 4cda703d8e925fc34f9fc3303f96ed20765a816d Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 16 Feb 2011 01:28:27 -0500 Subject: [PATCH] Use glibc qsort_r() for g_qsort_with_data() No point in using an outdated copy that claims to 'work best on a Sun 4/260' when we can just wrap qsort_r... --- configure.ac | 40 +++++++++++++++++++++++++++++++++ glib/gqsort.c | 40 +++++++++++++++++++++++---------- glib/tests/Makefile.am | 3 +++ glib/tests/sort.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+), 12 deletions(-) create mode 100644 glib/tests/sort.c diff --git a/configure.ac b/configure.ac index 47331cf..7636ead 100644 --- a/configure.ac +++ b/configure.ac @@ -573,6 +573,46 @@ AC_FUNC_VPRINTF AC_FUNC_ALLOCA AC_CHECK_FUNCS(mmap posix_memalign memalign valloc fsync pipe2) AC_CHECK_FUNCS(atexit on_exit timegm gmtime_r) +# BSD has a qsort_r with wrong argument order +AC_MSG_CHECKING([for qsort_r]) +AC_RUN_IFELSE([[ +#define _GNU_SOURCE +#include + +static int +cmp (const void *a, const void *b, void *c) +{ + const int *ia = a; + const int *ib = b; + + if (*ia < *ib) + return -1; + else if (*ia > *ib) + return 1; + else + return 0; +} + +int +main (int argc, char **argv) +{ + int arr[3] = { 1, 2, 0 }; + int d = 3; + + qsort_r (arr, 3, sizeof (int), cmp, &d); + + if (arr[0] == 0 && arr[1] == 1 && arr[2] == 2) + return 0; + else + return 1; +}]],[have_qsort_r=yes],[have_qsort_r=no]) + +if test $have_qsort_r = yes ; then + AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_QSORT_R, 1, [Define to 1 if you have the 'qsort_r' function]) +else + AC_MSG_RESULT([no]) +fi AC_CHECK_SIZEOF(char) AC_CHECK_SIZEOF(short) diff --git a/glib/gqsort.c b/glib/gqsort.c index f0acecf..e2a5a2e 100644 --- a/glib/gqsort.c +++ b/glib/gqsort.c @@ -34,6 +34,7 @@ #include "config.h" +#define _GNU_SOURCE #include #include #include @@ -42,6 +43,31 @@ #include "gtestutils.h" +#ifdef HAVE_QSORT_R + +/** + * g_qsort_with_data: + * @pbase: start of array to sort + * @total_elems: elements in the array + * @size: size of each element + * @compare_func: function to compare elements + * @user_data: data to pass to @compare_func + * + * This is just like the standard C qsort() function, but + * the comparison routine accepts a user data argument. + */ +void +g_qsort_with_data (gconstpointer pbase, + gint total_elems, + gsize size, + GCompareDataFunc compare_func, + gpointer user_data) +{ + qsort_r (pbase, total_elems, size, compare_func, user_data); +} + +#else + /* Byte-wise swap two items of size SIZE. */ #define SWAP(a, b, size) \ do \ @@ -102,18 +128,6 @@ typedef struct smaller partition. This *guarantees* no more than log (total_elems) stack size is needed (actually O(1) in this case)! */ -/** - * g_qsort_with_data: - * @pbase: start of array to sort - * @total_elems: elements in the array - * @size: size of each element - * @compare_func: function to compare elements - * @user_data: data to pass to @compare_func - * - * This is just like the standard C qsort() function, but - * the comparison routine accepts a user data argument. - * - **/ void g_qsort_with_data (gconstpointer pbase, gint total_elems, @@ -283,3 +297,5 @@ g_qsort_with_data (gconstpointer pbase, } } } + +#endif /* HAVE_QSORT_R */ diff --git a/glib/tests/Makefile.am b/glib/tests/Makefile.am index 6cd51ae..f2dfa49 100644 --- a/glib/tests/Makefile.am +++ b/glib/tests/Makefile.am @@ -161,6 +161,9 @@ mappedfile_LDADD = $(progs_ldadd) TEST_PROGS += dataset dataset_LDADD = $(progs_ldadd) +TEST_PROGS += sort +sort_LDADD = $(progs_ldadd) + if OS_UNIX # some testing of gtester funcitonality diff --git a/glib/tests/sort.c b/glib/tests/sort.c new file mode 100644 index 0000000..7fec42b --- /dev/null +++ b/glib/tests/sort.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2011 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +static int +int_compare_data (gconstpointer p1, gconstpointer p2, gpointer data) +{ + const gint *i1 = p1; + const gint *i2 = p2; + + return *i1 - *i2; +} + +static void +test_sort_basic (void) +{ + gint *data; + gint i; + + data = g_malloc (10000 * sizeof (int)); + for (i = 0; i < 10000; i++) + { + data[i] = g_random_int_range (0, 10000); + } + + g_qsort_with_data (data, 10000, sizeof (int), int_compare_data, NULL); + + for (i = 1; i < 10000; i++) + g_assert_cmpint (data[i -1], <=, data[i]); + + g_free (data); +} + +int +main (int argc, char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/sort/basic", test_sort_basic); + + return g_test_run (); +} + -- 2.7.4