X-Git-Url: http://pileus.org/git/?p=wmpus;a=blobdiff_plain;f=util.c;h=30df76c28a39d2e25320226545be0bfc8253904b;hp=aeb766eaa01f32d65234e84261b97d63d503efe3;hb=HEAD;hpb=776ac6910ee9db701c1cfe2ab234ae5fb96ce9db diff --git a/util.c b/util.c index aeb766e..30df76c 100644 --- a/util.c +++ b/util.c @@ -90,7 +90,49 @@ list_t *list_find(list_t *list, void *data) return NULL; } +list_t *list_sort(list_t *list, int rev, int (*func)(void *a, void*b)) +{ + if (list == NULL || list->next == NULL) + return list; + + /* Split list */ + list_t *sides[2] = {NULL, NULL}; + for (int i = 0; list; i=(i+1)%2) { + list_t *head = list; + list = list->next; + head->next = sides[i]; + sides[i] = head; + } + + /* Sort sides */ + sides[0] = list_sort(sides[0], !rev, func); + sides[1] = list_sort(sides[1], !rev, func); + + /* Merge sides */ + while (sides[0] || sides[1]) { + int i = sides[0] == NULL ? 1 : + sides[1] == NULL ? 0 : + func(sides[0]->data, + sides[1]->data) > 0 ? !!rev : !rev; + list_t *head = sides[i]; + sides[i] = sides[i]->next; + head->next = list; + head->prev = NULL; + if (list) + list->prev = head; + list = head; + } + return list; +} + /* Misc */ +int str2num(char *str, int def) +{ + char *end = NULL; + int num = strtol(str, &end, 10); + return end && *end == '\0' ? num : def; +} + int error(char *fmt, ...) { va_list ap;