[glib] Use glibc qsort_r() for g_qsort_with_data()



commit 4cda703d8e925fc34f9fc3303f96ed20765a816d
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed Feb 16 01:28:27 2011 -0500

    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(-)
---
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 <stdlib.h>
+
+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 <limits.h>
 #include <stdlib.h>
 #include <string.h>
@@ -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 <glib.h>
+
+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 ();
+}
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]