src/ucx/list.c

Tue, 23 Aug 2016 13:49:38 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 23 Aug 2016 13:49:38 +0200
changeset 39
ac35daceb24c
permissions
-rw-r--r--

adds UCX + changes how the input file is read (uses an consecutive memory area now)

universe@39 1 /*
universe@39 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
universe@39 3 *
universe@39 4 * Copyright 2015 Olaf Wintermann. All rights reserved.
universe@39 5 *
universe@39 6 * Redistribution and use in source and binary forms, with or without
universe@39 7 * modification, are permitted provided that the following conditions are met:
universe@39 8 *
universe@39 9 * 1. Redistributions of source code must retain the above copyright
universe@39 10 * notice, this list of conditions and the following disclaimer.
universe@39 11 *
universe@39 12 * 2. Redistributions in binary form must reproduce the above copyright
universe@39 13 * notice, this list of conditions and the following disclaimer in the
universe@39 14 * documentation and/or other materials provided with the distribution.
universe@39 15 *
universe@39 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
universe@39 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
universe@39 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
universe@39 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
universe@39 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
universe@39 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
universe@39 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
universe@39 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
universe@39 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
universe@39 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
universe@39 26 * POSSIBILITY OF SUCH DAMAGE.
universe@39 27 */
universe@39 28
universe@39 29 #include "list.h"
universe@39 30
universe@39 31 UcxList *ucx_list_clone(UcxList *l, copy_func fnc, void *data) {
universe@39 32 return ucx_list_clone_a(ucx_default_allocator(), l, fnc, data);
universe@39 33 }
universe@39 34
universe@39 35 UcxList *ucx_list_clone_a(UcxAllocator *alloc, UcxList *l,
universe@39 36 copy_func fnc, void *data) {
universe@39 37 UcxList *ret = NULL;
universe@39 38 while (l) {
universe@39 39 if (fnc) {
universe@39 40 ret = ucx_list_append_a(alloc, ret, fnc(l->data, data));
universe@39 41 } else {
universe@39 42 ret = ucx_list_append_a(alloc, ret, l->data);
universe@39 43 }
universe@39 44 l = l->next;
universe@39 45 }
universe@39 46 return ret;
universe@39 47 }
universe@39 48
universe@39 49 int ucx_list_equals(const UcxList *l1, const UcxList *l2,
universe@39 50 cmp_func fnc, void* data) {
universe@39 51 if (l1 == l2) return 1;
universe@39 52
universe@39 53 while (l1 != NULL && l2 != NULL) {
universe@39 54 if (fnc == NULL) {
universe@39 55 if (l1->data != l2->data) return 0;
universe@39 56 } else {
universe@39 57 if (fnc(l1->data, l2->data, data) != 0) return 0;
universe@39 58 }
universe@39 59 l1 = l1->next;
universe@39 60 l2 = l2->next;
universe@39 61 }
universe@39 62
universe@39 63 return (l1 == NULL && l2 == NULL);
universe@39 64 }
universe@39 65
universe@39 66 void ucx_list_free(UcxList *l) {
universe@39 67 ucx_list_free_a(ucx_default_allocator(), l);
universe@39 68 }
universe@39 69
universe@39 70 void ucx_list_free_a(UcxAllocator *alloc, UcxList *l) {
universe@39 71 UcxList *e = l, *f;
universe@39 72 while (e != NULL) {
universe@39 73 f = e;
universe@39 74 e = e->next;
universe@39 75 alfree(alloc, f);
universe@39 76 }
universe@39 77 }
universe@39 78
universe@39 79 void ucx_list_free_content(UcxList* list, ucx_destructor destr) {
universe@39 80 while (list != NULL) {
universe@39 81 destr(list->data);
universe@39 82 list = list->next;
universe@39 83 }
universe@39 84 }
universe@39 85
universe@39 86 UcxList *ucx_list_append(UcxList *l, void *data) {
universe@39 87 return ucx_list_append_a(ucx_default_allocator(), l, data);
universe@39 88 }
universe@39 89
universe@39 90 UcxList *ucx_list_append_a(UcxAllocator *alloc, UcxList *l, void *data) {
universe@39 91 UcxList *nl = (UcxList*) almalloc(alloc, sizeof(UcxList));
universe@39 92 if (!nl) {
universe@39 93 return NULL;
universe@39 94 }
universe@39 95
universe@39 96 nl->data = data;
universe@39 97 nl->next = NULL;
universe@39 98 if (l) {
universe@39 99 UcxList *t = ucx_list_last(l);
universe@39 100 t->next = nl;
universe@39 101 nl->prev = t;
universe@39 102 return l;
universe@39 103 } else {
universe@39 104 nl->prev = NULL;
universe@39 105 return nl;
universe@39 106 }
universe@39 107 }
universe@39 108
universe@39 109 UcxList *ucx_list_prepend(UcxList *l, void *data) {
universe@39 110 return ucx_list_prepend_a(ucx_default_allocator(), l, data);
universe@39 111 }
universe@39 112
universe@39 113 UcxList *ucx_list_prepend_a(UcxAllocator *alloc, UcxList *l, void *data) {
universe@39 114 UcxList *nl = ucx_list_append_a(alloc, NULL, data);
universe@39 115 if (!nl) {
universe@39 116 return NULL;
universe@39 117 }
universe@39 118 l = ucx_list_first(l);
universe@39 119
universe@39 120 if (l) {
universe@39 121 nl->next = l;
universe@39 122 l->prev = nl;
universe@39 123 }
universe@39 124 return nl;
universe@39 125 }
universe@39 126
universe@39 127 UcxList *ucx_list_concat(UcxList *l1, UcxList *l2) {
universe@39 128 if (l1) {
universe@39 129 UcxList *last = ucx_list_last(l1);
universe@39 130 last->next = l2;
universe@39 131 if (l2) {
universe@39 132 l2->prev = last;
universe@39 133 }
universe@39 134 return l1;
universe@39 135 } else {
universe@39 136 return l2;
universe@39 137 }
universe@39 138 }
universe@39 139
universe@39 140 UcxList *ucx_list_last(const UcxList *l) {
universe@39 141 if (l == NULL) return NULL;
universe@39 142
universe@39 143 const UcxList *e = l;
universe@39 144 while (e->next != NULL) {
universe@39 145 e = e->next;
universe@39 146 }
universe@39 147 return (UcxList*)e;
universe@39 148 }
universe@39 149
universe@39 150 ssize_t ucx_list_indexof(const UcxList *list, const UcxList *elem) {
universe@39 151 ssize_t index = 0;
universe@39 152 while (list) {
universe@39 153 if (list == elem) {
universe@39 154 return index;
universe@39 155 }
universe@39 156 list = list->next;
universe@39 157 index++;
universe@39 158 }
universe@39 159 return -1;
universe@39 160 }
universe@39 161
universe@39 162 UcxList *ucx_list_get(const UcxList *l, size_t index) {
universe@39 163 if (l == NULL) return NULL;
universe@39 164
universe@39 165 const UcxList *e = l;
universe@39 166 while (e->next && index > 0) {
universe@39 167 e = e->next;
universe@39 168 index--;
universe@39 169 }
universe@39 170
universe@39 171 return (UcxList*)(index == 0 ? e : NULL);
universe@39 172 }
universe@39 173
universe@39 174 ssize_t ucx_list_find(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) {
universe@39 175 ssize_t index = 0;
universe@39 176 UCX_FOREACH(e, l) {
universe@39 177 if (fnc) {
universe@39 178 if (fnc(elem, e->data, cmpdata) == 0) {
universe@39 179 return index;
universe@39 180 }
universe@39 181 } else {
universe@39 182 if (elem == e->data) {
universe@39 183 return index;
universe@39 184 }
universe@39 185 }
universe@39 186 index++;
universe@39 187 }
universe@39 188 return -1;
universe@39 189 }
universe@39 190
universe@39 191 int ucx_list_contains(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) {
universe@39 192 return ucx_list_find(l, elem, fnc, cmpdata) > -1;
universe@39 193 }
universe@39 194
universe@39 195 size_t ucx_list_size(const UcxList *l) {
universe@39 196 if (l == NULL) return 0;
universe@39 197
universe@39 198 const UcxList *e = l;
universe@39 199 size_t s = 1;
universe@39 200 while (e->next != NULL) {
universe@39 201 e = e->next;
universe@39 202 s++;
universe@39 203 }
universe@39 204
universe@39 205 return s;
universe@39 206 }
universe@39 207
universe@39 208 static UcxList *ucx_list_sort_merge(int length,
universe@39 209 UcxList* restrict ls, UcxList* restrict le, UcxList* restrict re,
universe@39 210 cmp_func fnc, void* data) {
universe@39 211
universe@39 212 UcxList** sorted = (UcxList**) malloc(sizeof(UcxList*)*length);
universe@39 213 UcxList *rc, *lc;
universe@39 214
universe@39 215 lc = ls; rc = le;
universe@39 216 int n = 0;
universe@39 217 while (lc && lc != le && rc != re) {
universe@39 218 if (fnc(lc->data, rc->data, data) <= 0) {
universe@39 219 sorted[n] = lc;
universe@39 220 lc = lc->next;
universe@39 221 } else {
universe@39 222 sorted[n] = rc;
universe@39 223 rc = rc->next;
universe@39 224 }
universe@39 225 n++;
universe@39 226 }
universe@39 227 while (lc && lc != le) {
universe@39 228 sorted[n] = lc;
universe@39 229 lc = lc->next;
universe@39 230 n++;
universe@39 231 }
universe@39 232 while (rc && rc != re) {
universe@39 233 sorted[n] = rc;
universe@39 234 rc = rc->next;
universe@39 235 n++;
universe@39 236 }
universe@39 237
universe@39 238 // Update pointer
universe@39 239 sorted[0]->prev = NULL;
universe@39 240 for (int i = 0 ; i < length-1 ; i++) {
universe@39 241 sorted[i]->next = sorted[i+1];
universe@39 242 sorted[i+1]->prev = sorted[i];
universe@39 243 }
universe@39 244 sorted[length-1]->next = NULL;
universe@39 245
universe@39 246 UcxList *ret = sorted[0];
universe@39 247 free(sorted);
universe@39 248 return ret;
universe@39 249 }
universe@39 250
universe@39 251 UcxList *ucx_list_sort(UcxList *l, cmp_func fnc, void *data) {
universe@39 252 if (l == NULL) {
universe@39 253 return NULL;
universe@39 254 }
universe@39 255
universe@39 256 UcxList *lc;
universe@39 257 int ln = 1;
universe@39 258
universe@39 259 UcxList *restrict ls = l, *restrict le, *restrict re;
universe@39 260
universe@39 261 // check how many elements are already sorted
universe@39 262 lc = ls;
universe@39 263 while (lc->next != NULL && fnc(lc->next->data, lc->data, data) > 0) {
universe@39 264 lc = lc->next;
universe@39 265 ln++;
universe@39 266 }
universe@39 267 le = lc->next;
universe@39 268
universe@39 269 if (le == NULL) {
universe@39 270 return l; // this list is already sorted :)
universe@39 271 } else {
universe@39 272 UcxList *rc;
universe@39 273 int rn = 1;
universe@39 274 rc = le;
universe@39 275 // skip already sorted elements
universe@39 276 while (rc->next != NULL && fnc(rc->next->data, rc->data, data) > 0) {
universe@39 277 rc = rc->next;
universe@39 278 rn++;
universe@39 279 }
universe@39 280 re = rc->next;
universe@39 281
universe@39 282 // {ls,...,le->prev} and {rs,...,re->prev} are sorted - merge them
universe@39 283 UcxList *sorted = ucx_list_sort_merge(ln+rn,
universe@39 284 ls, le, re,
universe@39 285 fnc, data);
universe@39 286
universe@39 287 // Something left? Sort it!
universe@39 288 size_t remainder_length = ucx_list_size(re);
universe@39 289 if (remainder_length > 0) {
universe@39 290 UcxList *remainder = ucx_list_sort(re, fnc, data);
universe@39 291
universe@39 292 // merge sorted list with (also sorted) remainder
universe@39 293 l = ucx_list_sort_merge(ln+rn+remainder_length,
universe@39 294 sorted, remainder, NULL, fnc, data);
universe@39 295 } else {
universe@39 296 // no remainder - we've got our sorted list
universe@39 297 l = sorted;
universe@39 298 }
universe@39 299
universe@39 300 return l;
universe@39 301 }
universe@39 302 }
universe@39 303
universe@39 304 UcxList *ucx_list_first(const UcxList *l) {
universe@39 305 if (!l) {
universe@39 306 return NULL;
universe@39 307 }
universe@39 308
universe@39 309 const UcxList *e = l;
universe@39 310 while (e->prev) {
universe@39 311 e = e->prev;
universe@39 312 }
universe@39 313 return (UcxList *)e;
universe@39 314 }
universe@39 315
universe@39 316 UcxList *ucx_list_remove(UcxList *l, UcxList *e) {
universe@39 317 return ucx_list_remove_a(ucx_default_allocator(), l, e);
universe@39 318 }
universe@39 319
universe@39 320 UcxList *ucx_list_remove_a(UcxAllocator *alloc, UcxList *l, UcxList *e) {
universe@39 321 if (l == e) {
universe@39 322 l = e->next;
universe@39 323 }
universe@39 324
universe@39 325 if (e->next) {
universe@39 326 e->next->prev = e->prev;
universe@39 327 }
universe@39 328
universe@39 329 if (e->prev) {
universe@39 330 e->prev->next = e->next;
universe@39 331 }
universe@39 332
universe@39 333 alfree(alloc, e);
universe@39 334 return l;
universe@39 335 }

mercurial