universe@10: #include "list.h" olaf@2: universe@18: UcxList *ucx_list_clone(UcxList *l, copy_func fnc, void *data) { universe@18: UcxList *ret = NULL; universe@18: while (l != NULL) { universe@18: if (fnc != NULL) { universe@18: ret = ucx_list_append(ret, fnc(l->data, data)); universe@18: } else { universe@18: ret = ucx_list_append(ret, l->data); universe@18: } universe@18: l = l->next; universe@18: } universe@18: return ret; universe@18: } universe@18: universe@18: int ucx_list_equals(UcxList *l1, UcxList *l2, cmp_func fnc, void* data) { universe@18: if (l1 == l2) return 1; universe@18: universe@18: while (l1 != NULL && l2 != NULL) { universe@18: if (fnc == NULL) { universe@18: if (l1->data != l2->data) return 0; universe@18: } else { universe@18: if (fnc(l1->data, l2->data, data) != 0) return 0; universe@18: } universe@18: l1 = l1->next; universe@18: l2 = l2->next; universe@18: } universe@18: universe@18: return (l1 == NULL && l2 == NULL); universe@18: } universe@18: universe@10: void ucx_list_free(UcxList *l) { universe@10: UcxList *e = l, *f; universe@10: while (e != NULL) { universe@10: f = e; universe@10: e = e->next; universe@10: free(f); universe@10: } universe@10: } universe@10: universe@10: UcxList *ucx_list_append(UcxList *l, void *data) { universe@10: UcxList *nl = (UcxList*) malloc(sizeof(UcxList)); universe@10: if (nl == NULL) return NULL; universe@10: universe@10: nl->data = data; universe@10: nl->next = NULL; universe@10: if (l == NULL) { universe@10: return nl; universe@10: } else { universe@10: UcxList *t = ucx_list_last(l); universe@10: t->next = nl; universe@10: return l; universe@10: } universe@10: } universe@10: universe@10: UcxList *ucx_list_prepend(UcxList *l, void *data) { universe@10: UcxList *nl = ucx_list_append(NULL, data); universe@10: if (nl == NULL) return NULL; universe@10: universe@10: if (l != NULL) { universe@10: nl->next = l; universe@10: } universe@10: return nl; universe@10: } universe@10: universe@10: UcxList *ucx_list_concat(UcxList *l1, UcxList *l2) { universe@10: if (l1 == NULL) { universe@10: return l2; universe@10: } else { universe@10: UcxList *last = ucx_list_last(l1); universe@10: last->next = l2; universe@10: return l1; universe@10: } universe@10: } universe@10: universe@10: UcxList *ucx_list_last(UcxList *l) { universe@10: if (l == NULL) return NULL; universe@10: universe@10: UcxList *e = l; universe@10: while (e->next != NULL) { universe@10: e = e->next; universe@10: } universe@10: return e; universe@10: } universe@10: universe@10: UcxList *ucx_list_get(UcxList *l, int index) { universe@10: if (l == NULL) return NULL; universe@10: universe@10: UcxList *e = l; universe@10: while (e->next != NULL && index > 0) { universe@10: e = e->next; universe@10: index--; universe@10: } universe@10: universe@10: return index == 0 ? e : NULL; universe@10: } universe@10: universe@10: size_t ucx_list_size(UcxList *l) { universe@10: if (l == NULL) return 0; universe@10: universe@10: UcxList *e = l; universe@10: size_t s = 1; universe@10: while (e->next != NULL) { universe@10: e = e->next; universe@10: s++; universe@10: } universe@10: universe@10: return s; universe@10: } universe@10: universe@37: UcxList *ucx_list_sort_merge(int length, universe@37: UcxList* ls, UcxList* rs, UcxList* le, UcxList* re, universe@37: cmp_func fnc, void* data) { universe@37: UcxList *sorted[length]; universe@37: UcxList *rc, *lc; universe@35: universe@37: lc = ls; rc = rs; universe@37: int n = 0; universe@37: while (lc != le && rc != re) { universe@37: if (fnc(lc->data, rc->data, data) <= 0) { universe@37: sorted[n] = lc; universe@37: lc = lc->next; universe@37: } else { universe@37: sorted[n] = rc; universe@37: rc = rc->next; universe@35: } universe@37: n++; universe@37: } universe@37: while (lc != le) { universe@37: sorted[n] = lc; universe@37: lc = lc->next; universe@37: n++; universe@37: } universe@37: while (rc != re) { universe@37: sorted[n] = rc; universe@37: rc = rc->next; universe@37: n++; universe@35: } universe@35: universe@37: // Update pointer universe@37: for (int i = 0 ; i < length-1 ; i++) { universe@37: sorted[i]->next = sorted[i+1]; universe@37: } universe@37: sorted[length-1]->next = NULL; universe@35: universe@37: return sorted[0]; universe@35: } universe@35: universe@36: UcxList *ucx_list_sort(UcxList *l, cmp_func fnc, void *data) { universe@35: if (l == NULL) { universe@35: return NULL; universe@35: } universe@37: universe@37: UcxList *lc; universe@37: int ln = 1; universe@37: universe@37: UcxList *ls = l, *le; universe@37: lc = ls; universe@37: while (lc->next != NULL && fnc(lc->next->data, lc->data, data) > 0) { universe@37: lc = lc->next; universe@37: ln++; universe@37: } universe@37: le = lc->next; universe@37: universe@37: UcxList *rs = le, *re; universe@37: if (rs == NULL) { universe@37: return l; // this list is already sorted :) universe@37: } else { universe@37: UcxList *rc; universe@37: int rn = 1; universe@37: rc = rs; universe@37: while (rc->next != NULL && fnc(rc->next->data, rc->data, data) > 0) { universe@37: rc = rc->next; universe@37: rn++; universe@37: } universe@37: re = rc->next; universe@37: universe@37: // Something left? Sort it! universe@37: UcxList *remainder = re; universe@37: size_t remainder_length = ucx_list_size(remainder); universe@37: if (remainder != NULL) { universe@37: remainder = ucx_list_sort(remainder, fnc, data); universe@37: } universe@37: universe@37: // {ls,...,le->prev} and {rs,...,re->prev} are sorted - merge them universe@37: UcxList *sorted = ucx_list_sort_merge(ln+rn, universe@37: ls, rs, le, re, universe@37: fnc, data); universe@37: universe@37: // merge sorted list with (also sorted) remainder universe@37: l = ucx_list_sort_merge(ln+rn+remainder_length, universe@37: sorted, remainder, NULL, NULL, universe@37: fnc, data); universe@37: universe@35: return l; universe@35: } universe@35: } universe@35: universe@23: /* list specific functions */ universe@23: UcxList *ucx_list_remove(UcxList *l, UcxList *e) { universe@23: if (e == l) { universe@23: l = e->next; universe@23: free(e); universe@23: } else { universe@23: UcxList *f = l; universe@23: while (f->next != NULL && f->next != e) { universe@23: f = f->next; universe@23: } olaf@31: /* perform remove if this element is found in this list */ universe@23: if (f->next == e) { universe@23: f->next = e->next; universe@23: free(e); universe@23: } universe@23: } universe@23: return l; universe@24: }