- add ecore_list_sort() a wrapper for ecore_list_mergesort and ecore_list_heapsort
authorPeter Wehrfritz <peter.wehrfritz@web.de>
Thu, 1 Feb 2007 19:22:35 +0000 (19:22 +0000)
committerPeter Wehrfritz <peter.wehrfritz@web.de>
Thu, 1 Feb 2007 19:22:35 +0000 (19:22 +0000)
- change the API for the sort functions to return an int on success
- change ECORE_SHEAP_MIN/MAX to ECORE_SORT_MIN/MAX (*API break*)
- use ecore_list_sort() in ecore_file_ls()

SVN revision: 28188

legacy/ecore/src/lib/ecore/Ecore_Data.h
legacy/ecore/src/lib/ecore/ecore_list.c
legacy/ecore/src/lib/ecore/ecore_sheap.c
legacy/ecore/src/lib/ecore_file/ecore_file.c

index dc3b892..7225b0e 100644 (file)
@@ -40,6 +40,9 @@ extern "C" {
    
    EAPI extern const unsigned int ecore_prime_table[];
    
+# define ECORE_SORT_MIN 0
+# define ECORE_SORT_MAX 1
+
    typedef void (*Ecore_For_Each) (void *value, void *user_data);
 # define ECORE_FOR_EACH(function) ((Ecore_For_Each)function)
    
@@ -119,9 +122,11 @@ extern "C" {
         const void *user_data);
 
    /* Sorting the list */
-   EAPI void ecore_list_mergesort(Ecore_List *list, Ecore_Compare_Cb compare,
+   EAPI int ecore_list_sort(Ecore_List *list, Ecore_Compare_Cb compare,
+                                  char order);
+   EAPI int ecore_list_mergesort(Ecore_List *list, Ecore_Compare_Cb compare,
                                   char order);
-   EAPI void ecore_list_heapsort(Ecore_List *list, Ecore_Compare_Cb compare,
+   EAPI int ecore_list_heapsort(Ecore_List *list, Ecore_Compare_Cb compare,
                                   char order);
    
    /* Check to see if there is any data in the list */
@@ -327,9 +332,6 @@ extern "C" {
    EAPI Ecore_List *ecore_plugin_get_available(int group_id);
 
 
-# define ECORE_SHEAP_MIN 0
-# define ECORE_SHEAP_MAX 1
-
    typedef struct _ecore_heap Ecore_Sheap;
 # define ECORE_HEAP(heap) ((Ecore_Sheap *)heap)
    
index 4c43550..cf825aa 100644 (file)
@@ -2,6 +2,11 @@
 #include "Ecore.h"
 #include "Ecore_Data.h"
 
+/* Some tests showed that beyond that value heap sort is faster than merge sort
+ * (in this implementation). This value has to be changed or at least review
+ * if someone is changing the implementation. */
+#define ECORE_MERGESORT_LIMIT 40000
+
 /* Return information about the list */
 static void *_ecore_list_current(Ecore_List * list);
 
@@ -1121,24 +1126,51 @@ _ecore_list_find(Ecore_List *list, Ecore_Compare_Cb function, const void *user_d
 }
 
 /**
- * Sort data in @p list using the compare function @p func
+ * Sort data in @p list using the compare function @p compare
+ * @param list      The list.
+ * @param compare   The function to compare the data of @p list
+ * @param order     The sort direction
+ *
+ * @return          true on success
+ *
+ * This is a wrapper function for mergesort and heapsort. It
+ * tries to choose the fastest algorithm depending on the
+ * number of notes. Note: The sort may be unstable.
+ */
+EAPI int
+ecore_list_sort(Ecore_List *list, Ecore_Compare_Cb compare, char order)
+{
+   CHECK_PARAM_POINTER_RETURN("list", list, 0);
+   
+   if (list->nodes < 2)
+     return 1;
+   if (list->nodes < ECORE_MERGESORT_LIMIT)
+     return ecore_list_mergesort(list, compare, order);
+   if (!ecore_list_heapsort(list, compare, order))
+     return ecore_list_mergesort(list, compare, order);
+  
+   return 1;
+}
+/**
+ * Sort data in @p list using the compare function @p compare
  * @param list      The list.
  * @param compare   The function to compare the data of @p list
  * @param order     The sort direction
  *
+ * @return          true on success
+ *
  * Mergesort is a stable, in-place sorting algorithm 
  */
-EAPI void
+EAPI int
 ecore_list_mergesort(Ecore_List *list, Ecore_Compare_Cb compare, char order)
 {
    Ecore_List_Node *node;
 
-   CHECK_PARAM_POINTER("list", list);
-   if (!list || list->nodes < 2)
-     {
-       return;
-     }
-   if (order == ECORE_SHEAP_MIN)
+   CHECK_PARAM_POINTER_RETURN("list", list, 0);
+   if (list->nodes < 2)
+     return 1;
+
+   if (order == ECORE_SORT_MIN)
      order = 1;
    else
      order = -1;
@@ -1152,6 +1184,8 @@ ecore_list_mergesort(Ecore_List *list, Ecore_Compare_Cb compare, char order)
    list->last = node;
 
    _ecore_list_goto_first(list);
+
+   return 1;
 }
 
 /* this is the internal recrusive function for the merge sort */
@@ -1170,7 +1204,7 @@ _ecore_list_node_mergesort(Ecore_List_Node *first, int n,
      return first;
    else if (n == 2)
      {
-       if (compare(first->data, first->next->data) == order)
+       if (compare(first->data, first->next->data) * order > 0)
           {
                /* swap the data */
                void *data;
@@ -1206,7 +1240,7 @@ _ecore_list_node_merge(Ecore_List_Node *first, Ecore_List_Node *second,
 
    /* select the first node outside the loop, because we need to keep
     * a pointer to it */
-   if (compare(first->data, second->data) == order)
+   if (compare(first->data, second->data) * order > 0)
      {
        list = l = second;
        second = second->next;
@@ -1220,7 +1254,7 @@ _ecore_list_node_merge(Ecore_List_Node *first, Ecore_List_Node *second,
    /* and now start the merging */
    while (first && second)
      {
-       if (compare(first->data, second->data) == order)
+       if (compare(first->data, second->data) * order > 0)
          {
                l = l->next = second;
                second = second->next;
@@ -1244,26 +1278,31 @@ _ecore_list_node_merge(Ecore_List_Node *first, Ecore_List_Node *second,
 }
 
 /**
- * Sort data in @p list using the compare function @p func
+ * Sort data in @p list using the compare function @p compare
  * @param list      The list.
  * @param compare   The function to compare the data of @p list
  * @param order     The sort direction 
  *
+ * @return          true on success
+ *
  * Heapsort is a unstable sorting algorithm, it needs to allocate extra memomry,
  * but there for it is for a great number of nodes faster than mergesort
  */
-EAPI void
+EAPI int
 ecore_list_heapsort(Ecore_List *list, Ecore_Compare_Cb compare, char order)
 {
    Ecore_Sheap *heap;
    Ecore_List_Node *node;
    void *data;
 
-   CHECK_PARAM_POINTER("list", list);
+   CHECK_PARAM_POINTER_RETURN("list", list, 0);
    /*
     * Push the data into a heap.
     */
    heap = ecore_sheap_new(compare, list->nodes);
+   if (!heap)
+     return 0;
+
    ecore_sheap_set_order(heap, order);
    _ecore_list_goto_first(list);
    while ((data = _ecore_list_next(list)))
@@ -1284,6 +1323,7 @@ ecore_list_heapsort(Ecore_List *list, Ecore_Compare_Cb compare, char order)
    ecore_sheap_destroy(heap);
 
    _ecore_list_goto_first(list);
+   return 1;
 }
 
 /* Initialize a node to starting values */
index f6241b2..7e7d10d 100644 (file)
@@ -54,7 +54,7 @@ ecore_sheap_init(Ecore_Sheap *heap, Ecore_Compare_Cb compare, int size)
      heap->compare = ecore_direct_compare;
    else
      heap->compare = compare;
-   heap->order = ECORE_SHEAP_MIN;
+   heap->order = ECORE_SORT_MIN;
 
    heap->data = (void **)malloc(heap->space * sizeof(void *));
    if (!heap->data)
@@ -149,7 +149,7 @@ ecore_sheap_insert(Ecore_Sheap *heap, void *data)
     * data. The loop is placed inside the if statement to reduce the
     * number of branching decisions that must be predicted.
     */
-   if (heap->order == ECORE_SHEAP_MIN)
+   if (heap->order == ECORE_SORT_MIN)
      {
        while ((position > 0) && heap->compare(heap->data[parent],
                                               heap->data[position]) > 0)
@@ -383,7 +383,7 @@ _ecore_sheap_heapify(Ecore_Sheap *heap, int i)
    int left = LEFT(i);
    int right = RIGHT(i);
 
-   if (heap->order == ECORE_SHEAP_MIN)
+   if (heap->order == ECORE_SORT_MIN)
      {
        if (left <= heap->size && heap->compare(heap->data[left - 1],
                                                heap->data[i - 1]) < 0)
index 64c7099..b139fd7 100644 (file)
@@ -298,7 +298,6 @@ ecore_file_ls(const char *dir)
    DIR                *dirp;
    struct dirent      *dp;
    Ecore_List         *list;
-   Ecore_Sheap        *heap;
 
    dirp = opendir(dir);
    if (!dirp) return NULL;
@@ -315,25 +314,8 @@ ecore_file_ls(const char *dir)
          }
      }
    closedir(dirp);
-
-   /*
-    * Push the data into a heap.
-    */
-   heap = ecore_sheap_new(ECORE_COMPARE_CB(strcasecmp), ecore_list_nodes(list));
-   while ((f = ecore_list_remove_first(list)))
-     {
-       ecore_sheap_insert(heap, f);
-     }
-
-   /*
-    * Extract in sorted order.
-    */
-   while ((f = ecore_sheap_extract(heap)))
-     {
-       ecore_list_append(list, f);
-     }
-
-   ecore_sheap_destroy(heap);
+   
+   ecore_list_sort(list, ECORE_COMPARE_CB(strcasecmp), ECORE_SORT_MIN);
 
    ecore_list_goto_first(list);
    return list;