[eglib] Implement g_ptr_array_sort_with_data()
authorGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Thu, 31 Mar 2011 18:04:44 +0000 (14:04 -0400)
committerGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Thu, 31 Mar 2011 18:05:08 +0000 (14:05 -0400)
eglib/src/gptrarray.c
eglib/test/ptrarray.c

index bfde715225590fdc0477c19ca86cf2792924cb63..1fbdd6fefb14ff185c31095b026c7ff9ff2b54db 100644 (file)
@@ -3,8 +3,9 @@
  *
  * Author:
  *   Aaron Bockover (abockover@novell.com)
+ *   Gonzalo Paniagua Javier (gonzalo@novell.com)
  *
- * (C) 2006 Novell, Inc.
+ * (C) 2006,2011 Novell, Inc.
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
@@ -215,11 +216,45 @@ g_ptr_array_sort(GPtrArray *array, GCompareFunc compare_func)
        qsort(array->pdata, array->len, sizeof(gpointer), compare_func);
 }
 
-void
-g_ptr_array_sort_with_data(GPtrArray *array, GCompareDataFunc compare_func, 
-       gpointer user_data)
+#define PTR_ADDR(n) (&g_ptr_array_index (array, n))
+#define SWAP_PTR(l,r) do { \
+               gpointer ptr; \
+               if (l != r) { \
+                       ptr = array->pdata [l]; \
+                       array->pdata [l] = array->pdata [r]; \
+                       array->pdata [r] = ptr; \
+               } \
+       } while (0)
+
+static void
+qsort_with_data (GPtrArray *array, gint left, gint right, GCompareDataFunc compare_func, gpointer user_data)
 {
-}
+       gint l = left + 1;
+       gint r = right;
+       if (right <= left + 1)
+               return;
 
+       while (l < r) {
+               if (compare_func (PTR_ADDR (l), PTR_ADDR (left), user_data) <= 0) {
+                       l++;
+               } else {
+                       r--;
+                       SWAP_PTR (l, r);
+               }
+       }
+       l--;
+       SWAP_PTR (l, left);
+       qsort_with_data (array, left, l, compare_func, user_data);
+       qsort_with_data (array, r, right, compare_func, user_data);
+}
+#undef PTR_ADDR
+#undef SWAP_PTR
 
+void
+g_ptr_array_sort_with_data(GPtrArray *array, GCompareDataFunc compare_func, gpointer user_data)
+{
+       g_return_if_fail (array != NULL);
+       g_return_if_fail (compare_func != NULL);
+       qsort_with_data (array, 0, array->len, compare_func, user_data);
+}
 
index a823dd7655517d64f1ff115631f1bf62acbb674c..34d78b0235604a56bf0cb1521b668f3d14109edc 100644 (file)
@@ -243,8 +243,8 @@ RESULT ptrarray_sort()
 
        for(i = 0; i < array->len; i++) {
                if(array->pdata[i] != letters[i]) {
-                       return FAILED("Array out of order, expected %s got %s", 
-                               (gchar *)array->pdata[i], letters[i]);
+                       return FAILED("Array out of order, expected %s got %s at position %d",
+                               letters [i], (gchar *) array->pdata [i], i);
                }
        }
 
@@ -253,6 +253,43 @@ RESULT ptrarray_sort()
        return OK;
 }
 
+static gint ptrarray_sort_compare_with_data (gconstpointer a, gconstpointer b, gpointer user_data)
+{
+       gchar *stra = *(gchar **) a;
+       gchar *strb = *(gchar **) b;
+
+       if (strcmp (user_data, "this is the data for qsort") != 0)
+               fprintf (stderr, "oops at compare with_data\n");
+
+       return strcmp(stra, strb);
+}
+
+RESULT ptrarray_sort_with_data ()
+{
+       GPtrArray *array = g_ptr_array_new();
+       guint i;
+       gchar *letters [] = { "A", "B", "C", "D", "E" };
+
+       g_ptr_array_add(array, letters[4]);
+       g_ptr_array_add(array, letters[1]);
+       g_ptr_array_add(array, letters[2]);
+       g_ptr_array_add(array, letters[0]);
+       g_ptr_array_add(array, letters[3]);
+
+       g_ptr_array_sort_with_data(array, ptrarray_sort_compare_with_data, "this is the data for qsort");
+
+       for(i = 0; i < array->len; i++) {
+               if(array->pdata[i] != letters[i]) {
+                       return FAILED("Array out of order, expected %s got %s at position %d",
+                               letters [i], (gchar *) array->pdata [i], i);
+               }
+       }
+
+       g_ptr_array_free(array, TRUE);
+
+       return OK;
+}
+
 RESULT ptrarray_remove_fast()
 {
        GPtrArray *array = g_ptr_array_new();
@@ -303,6 +340,7 @@ static Test ptrarray_tests [] = {
        {"remove", ptrarray_remove},
        {"sort", ptrarray_sort},
        {"remove_fast", ptrarray_remove_fast},
+       {"sort_with_data", ptrarray_sort_with_data},
        {NULL, NULL}
 };