ucx/list.c

Wed, 27 Feb 2013 10:35:42 +0100

author
Mike Becker <universe@uap-core.de>
date
Wed, 27 Feb 2013 10:35:42 +0100
changeset 91
91595a45fad6
parent 87
bd444539cced
child 93
a6a99e721660
permissions
-rw-r--r--

added memcmp to the comparator module

universe@10 1 #include "list.h"
olaf@2 2
universe@87 3 UcxList *ucx_list_clone(UcxList *l, copy_func fnc, void *data) {
universe@18 4 UcxList *ret = NULL;
universe@18 5 while (l != NULL) {
universe@18 6 if (fnc != NULL) {
universe@18 7 ret = ucx_list_append(ret, fnc(l->data, data));
universe@18 8 } else {
universe@18 9 ret = ucx_list_append(ret, l->data);
universe@18 10 }
universe@18 11 l = l->next;
universe@18 12 }
universe@18 13 return ret;
universe@18 14 }
universe@18 15
universe@67 16 int ucx_list_equals(const UcxList *l1, const UcxList *l2,
universe@67 17 cmp_func fnc, void* data) {
universe@18 18 if (l1 == l2) return 1;
universe@18 19
universe@18 20 while (l1 != NULL && l2 != NULL) {
universe@18 21 if (fnc == NULL) {
universe@18 22 if (l1->data != l2->data) return 0;
universe@18 23 } else {
universe@18 24 if (fnc(l1->data, l2->data, data) != 0) return 0;
universe@18 25 }
universe@18 26 l1 = l1->next;
universe@18 27 l2 = l2->next;
universe@18 28 }
universe@18 29
universe@18 30 return (l1 == NULL && l2 == NULL);
universe@18 31 }
universe@18 32
universe@10 33 void ucx_list_free(UcxList *l) {
universe@10 34 UcxList *e = l, *f;
universe@10 35 while (e != NULL) {
universe@10 36 f = e;
universe@10 37 e = e->next;
universe@10 38 free(f);
universe@10 39 }
universe@10 40 }
universe@10 41
universe@10 42 UcxList *ucx_list_append(UcxList *l, void *data) {
universe@10 43 UcxList *nl = (UcxList*) malloc(sizeof(UcxList));
universe@10 44 if (nl == NULL) return NULL;
universe@10 45
universe@10 46 nl->data = data;
universe@10 47 nl->next = NULL;
universe@10 48 if (l == NULL) {
universe@10 49 return nl;
universe@10 50 } else {
universe@10 51 UcxList *t = ucx_list_last(l);
universe@10 52 t->next = nl;
universe@10 53 return l;
universe@10 54 }
universe@10 55 }
universe@10 56
universe@10 57 UcxList *ucx_list_prepend(UcxList *l, void *data) {
universe@10 58 UcxList *nl = ucx_list_append(NULL, data);
universe@10 59 if (nl == NULL) return NULL;
universe@10 60
universe@10 61 if (l != NULL) {
universe@10 62 nl->next = l;
universe@10 63 }
universe@10 64 return nl;
universe@10 65 }
universe@10 66
universe@67 67 UcxList *ucx_list_concat(UcxList *restrict l1, UcxList *restrict l2) {
universe@10 68 if (l1 == NULL) {
universe@10 69 return l2;
universe@10 70 } else {
universe@10 71 UcxList *last = ucx_list_last(l1);
universe@10 72 last->next = l2;
universe@10 73 return l1;
universe@10 74 }
universe@10 75 }
universe@10 76
universe@67 77 UcxList *ucx_list_last(const UcxList *l) {
universe@10 78 if (l == NULL) return NULL;
universe@10 79
universe@67 80 const UcxList *e = l;
universe@10 81 while (e->next != NULL) {
universe@10 82 e = e->next;
universe@10 83 }
universe@67 84 return (UcxList*)e;
universe@10 85 }
universe@10 86
universe@67 87 UcxList *ucx_list_get(const UcxList *l, int index) {
universe@10 88 if (l == NULL) return NULL;
universe@10 89
universe@67 90 const UcxList *e = l;
universe@10 91 while (e->next != NULL && index > 0) {
universe@10 92 e = e->next;
universe@10 93 index--;
universe@10 94 }
universe@10 95
universe@67 96 return (UcxList*)(index == 0 ? e : NULL);
universe@10 97 }
universe@10 98
universe@87 99 int ucx_list_contains(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) {
universe@87 100 UCX_FOREACH(UcxList*, l, e) {
universe@87 101 if (!fnc(elem, e->data, cmpdata)) {
universe@87 102 return 1;
universe@87 103 }
universe@87 104 }
universe@87 105 return 0;
universe@87 106 }
universe@87 107
universe@67 108 size_t ucx_list_size(const UcxList *l) {
universe@10 109 if (l == NULL) return 0;
universe@10 110
universe@67 111 const UcxList *e = l;
universe@10 112 size_t s = 1;
universe@10 113 while (e->next != NULL) {
universe@10 114 e = e->next;
universe@10 115 s++;
universe@10 116 }
universe@10 117
universe@10 118 return s;
universe@10 119 }
universe@10 120
universe@37 121 UcxList *ucx_list_sort_merge(int length,
universe@67 122 UcxList* restrict ls, UcxList* restrict le, UcxList* restrict re,
universe@37 123 cmp_func fnc, void* data) {
universe@69 124
universe@73 125 UcxList** sorted = (UcxList**) malloc(sizeof(UcxList*)*length);
universe@37 126 UcxList *rc, *lc;
universe@35 127
universe@67 128 lc = ls; rc = le;
universe@37 129 int n = 0;
universe@67 130 while (lc && lc != le && rc != re) {
universe@37 131 if (fnc(lc->data, rc->data, data) <= 0) {
universe@37 132 sorted[n] = lc;
universe@37 133 lc = lc->next;
universe@37 134 } else {
universe@37 135 sorted[n] = rc;
universe@37 136 rc = rc->next;
universe@35 137 }
universe@37 138 n++;
universe@37 139 }
universe@67 140 while (lc && lc != le) {
universe@37 141 sorted[n] = lc;
universe@37 142 lc = lc->next;
universe@37 143 n++;
universe@37 144 }
universe@67 145 while (rc && rc != re) {
universe@37 146 sorted[n] = rc;
universe@37 147 rc = rc->next;
universe@37 148 n++;
universe@35 149 }
universe@35 150
universe@37 151 // Update pointer
universe@37 152 for (int i = 0 ; i < length-1 ; i++) {
universe@37 153 sorted[i]->next = sorted[i+1];
universe@37 154 }
universe@37 155 sorted[length-1]->next = NULL;
universe@35 156
universe@69 157 UcxList *ret = sorted[0];
universe@73 158 free(sorted);
universe@69 159 return ret;
universe@35 160 }
universe@35 161
universe@36 162 UcxList *ucx_list_sort(UcxList *l, cmp_func fnc, void *data) {
universe@35 163 if (l == NULL) {
universe@35 164 return NULL;
universe@35 165 }
universe@37 166
universe@37 167 UcxList *lc;
universe@37 168 int ln = 1;
universe@37 169
universe@67 170 UcxList *restrict ls = l, *restrict le, *restrict re;
universe@37 171 lc = ls;
universe@37 172 while (lc->next != NULL && fnc(lc->next->data, lc->data, data) > 0) {
universe@37 173 lc = lc->next;
universe@37 174 ln++;
universe@37 175 }
universe@37 176 le = lc->next;
universe@37 177
universe@67 178 if (le == NULL) {
universe@37 179 return l; // this list is already sorted :)
universe@37 180 } else {
universe@37 181 UcxList *rc;
universe@37 182 int rn = 1;
universe@67 183 rc = le;
universe@37 184 while (rc->next != NULL && fnc(rc->next->data, rc->data, data) > 0) {
universe@37 185 rc = rc->next;
universe@37 186 rn++;
universe@37 187 }
universe@37 188 re = rc->next;
universe@37 189
universe@37 190 // Something left? Sort it!
universe@37 191 UcxList *remainder = re;
universe@37 192 size_t remainder_length = ucx_list_size(remainder);
universe@37 193 if (remainder != NULL) {
universe@37 194 remainder = ucx_list_sort(remainder, fnc, data);
universe@37 195 }
universe@37 196
universe@37 197 // {ls,...,le->prev} and {rs,...,re->prev} are sorted - merge them
universe@37 198 UcxList *sorted = ucx_list_sort_merge(ln+rn,
universe@67 199 ls, le, re,
universe@37 200 fnc, data);
universe@37 201
universe@37 202 // merge sorted list with (also sorted) remainder
universe@37 203 l = ucx_list_sort_merge(ln+rn+remainder_length,
universe@67 204 sorted, remainder, NULL, fnc, data);
universe@37 205
universe@35 206 return l;
universe@35 207 }
universe@35 208 }
universe@35 209
universe@23 210 /* list specific functions */
universe@23 211 UcxList *ucx_list_remove(UcxList *l, UcxList *e) {
universe@23 212 if (e == l) {
universe@23 213 l = e->next;
universe@23 214 free(e);
universe@23 215 } else {
universe@23 216 UcxList *f = l;
universe@23 217 while (f->next != NULL && f->next != e) {
universe@23 218 f = f->next;
universe@23 219 }
olaf@31 220 /* perform remove if this element is found in this list */
universe@23 221 if (f->next == e) {
universe@23 222 f->next = e->next;
universe@23 223 free(e);
universe@23 224 }
universe@23 225 }
universe@23 226 return l;
universe@24 227 }

mercurial