diff options
Diffstat (limited to 'shared/nm-utils/c-list-util.c')
| -rw-r--r-- | shared/nm-utils/c-list-util.c | 88 |
1 files changed, 22 insertions, 66 deletions
diff --git a/shared/nm-utils/c-list-util.c b/shared/nm-utils/c-list-util.c index 44ca26a5..070323c6 100644 --- a/shared/nm-utils/c-list-util.c +++ b/shared/nm-utils/c-list-util.c @@ -58,35 +58,39 @@ c_list_relink (CList *lst) /*****************************************************************************/ static CList * -_c_list_srt_split (CList *ls) +_c_list_sort (CList *ls, + CListSortCmp cmp, + const void *user_data) { - CList *ls2; + CList *ls1, *ls2; + CList head; + if (!ls->next) + return ls; + + /* split list in two halfs @ls1 and @ls2. */ + ls1 = ls; ls2 = ls; ls = ls->next; - if (!ls) - return NULL; - do { + while (ls) { ls = ls->next; if (!ls) break; ls = ls->next; ls2 = ls2->next; - } while (ls); - ls = ls2->next; - ls2->next = NULL; - return ls; -} + } + ls = ls2; + ls2 = ls->next; + ls->next = NULL; -static CList * -_c_list_srt_merge (CList *ls1, - CList *ls2, - CListSortCmp cmp, - const void *user_data) -{ - CList *ls; - CList head; + /* recurse */ + ls1 = _c_list_sort (ls1, cmp, user_data); + if (!ls2) + return ls1; + + ls2 = _c_list_sort (ls2, cmp, user_data); + /* merge */ ls = &head; for (;;) { /* while invoking the @cmp function, the list @@ -111,54 +115,6 @@ _c_list_srt_merge (CList *ls1, return head.next; } -typedef struct { - CList *ls1; - CList *ls2; - char ls1_sorted; -} SortStack; - -static CList * -_c_list_sort (CList *ls, - CListSortCmp cmp, - const void *user_data) -{ - /* reserve a huge stack-size. We need roughly log2(n) entries, hence this - * is much more we will ever need. We don't guard for stack-overflow either. */ - SortStack stack_arr[70]; - SortStack *stack_head = stack_arr; - - stack_arr[0].ls1 = ls; - - /* A simple top-down, non-recursive, stable merge-sort. - * - * Maybe natural merge-sort would be better, to do better for - * partially sorted lists. */ -_split: - stack_head[0].ls2 = _c_list_srt_split (stack_head[0].ls1); - if (stack_head[0].ls2) { - stack_head[0].ls1_sorted = 0; - stack_head[1].ls1 = stack_head[0].ls1; - stack_head++; - goto _split; - } - -_backtrack: - if (stack_head == stack_arr) - return stack_arr[0].ls1; - - stack_head--; - if (!stack_head[0].ls1_sorted) { - stack_head[0].ls1 = stack_head[1].ls1; - stack_head[0].ls1_sorted = 1; - stack_head[1].ls1 = stack_head[0].ls2; - stack_head++; - goto _split; - } - - stack_head[0].ls1 = _c_list_srt_merge (stack_head[0].ls1, stack_head[1].ls1, cmp, user_data); - goto _backtrack; -} - /** * c_list_sort_headless: * @lst: the list. |