Tue, 25 Jun 2013 15:45:13 +0200
some fixes
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2013 Olaf Wintermann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "dlist.h" UcxDlist *ucx_dlist_clone(UcxDlist *l, copy_func fnc, void *data) { UcxDlist *ret = NULL; while (l != NULL) { if (fnc != NULL) { ret = ucx_dlist_append(ret, fnc(l->data, data)); } else { ret = ucx_dlist_append(ret, l->data); } l = l->next; } return ret; } int ucx_dlist_equals(const UcxDlist *l1, const UcxDlist *l2, cmp_func fnc, void* data) { if (l1 == l2) return 1; while (l1 != NULL && l2 != NULL) { if (fnc == NULL) { if (l1->data != l2->data) return 0; } else { if (fnc(l1->data, l2->data, data) != 0) return 0; } l1 = l1->next; l2 = l2->next; } return (l1 == NULL && l2 == NULL); } void ucx_dlist_free(UcxDlist *l) { UcxDlist *e = l, *f; while (e != NULL) { f = e; e = e->next; free(f); } } UcxDlist *ucx_dlist_append(UcxDlist *l, void *data) { UcxDlist *nl = (UcxDlist*) malloc(sizeof(UcxDlist)); if (nl == NULL) return NULL; nl->data = data; nl->next = NULL; if (l == NULL) { nl->prev = NULL; return nl; } else { UcxDlist *t = ucx_dlist_last(l); t->next = nl; nl->prev = t; return l; } } UcxDlist *ucx_dlist_prepend(UcxDlist *l, void *data) { UcxDlist *nl = ucx_dlist_append(NULL, data); if (nl == NULL) return NULL; if (l != NULL) { nl->next = l; l->prev = nl; } return nl; } UcxDlist *ucx_dlist_concat(UcxDlist *l1, UcxDlist *l2) { if (l1 == NULL) { return l2; } else { UcxDlist *last = ucx_dlist_last(l1); last->next = l2; l2->prev = last; return l1; } } UcxDlist *ucx_dlist_last(const UcxDlist *l) { if (l == NULL) return NULL; const UcxDlist *e = l; while (e->next != NULL) { e = e->next; } return (UcxDlist*)e; } UcxDlist *ucx_dlist_get(const UcxDlist *l, int index) { if (l == NULL) return NULL; const UcxDlist *e = l; while (e->next != NULL && index > 0) { e = e->next; index--; } return (UcxDlist*)(index == 0 ? e : NULL); } int ucx_dlist_contains(UcxDlist *l, void *elem, cmp_func fnc, void *cmpdata) { UCX_FOREACH(UcxDlist*, l, e) { if (!fnc(elem, e->data, cmpdata)) { return 1; } } return 0; } size_t ucx_dlist_size(const UcxDlist *l) { if (l == NULL) return 0; const UcxDlist *e = l; size_t s = 1; while (e->next != NULL) { e = e->next; s++; } return s; } UcxDlist *ucx_dlist_sort_merge(int length, UcxDlist* restrict ls, UcxDlist* restrict le, UcxDlist* restrict re, cmp_func fnc, void* data) { UcxDlist** sorted = (UcxDlist**) malloc(sizeof(UcxDlist*)*length); UcxDlist *rc, *lc; lc = ls; rc = le; int n = 0; while (lc && lc != le && rc != re) { if (fnc(lc->data, rc->data, data) <= 0) { sorted[n] = lc; lc = lc->next; } else { sorted[n] = rc; rc = rc->next; } n++; } while (lc && lc != le) { sorted[n] = lc; lc = lc->next; n++; } while (rc && rc != re) { sorted[n] = rc; rc = rc->next; n++; } // Update pointer sorted[0]->prev = NULL; for (int i = 0 ; i < length-1 ; i++) { sorted[i]->next = sorted[i+1]; sorted[i+1]->prev = sorted[i]; } sorted[length-1]->next = NULL; UcxDlist *ret = sorted[0]; free(sorted); return ret; } UcxDlist *ucx_dlist_sort(UcxDlist *l, cmp_func fnc, void *data) { if (l == NULL) { return NULL; } UcxDlist *lc; int ln = 1; UcxDlist *restrict ls = l, *restrict le, *restrict re; lc = ls; while (lc->next != NULL && fnc(lc->next->data, lc->data, data) > 0) { lc = lc->next; ln++; } le = lc->next; if (le == NULL) { return l; // this list is already sorted :) } else { UcxDlist *rc; int rn = 1; rc = le; while (rc->next != NULL && fnc(rc->next->data, rc->data, data) > 0) { rc = rc->next; rn++; } re = rc->next; // Something left? Sort it! UcxDlist *remainder = re; size_t remainder_length = ucx_dlist_size(remainder); if (remainder != NULL) { remainder = ucx_dlist_sort(remainder, fnc, data); } // {ls,...,le->prev} and {rs,...,re->prev} are sorted - merge them UcxDlist *sorted = ucx_dlist_sort_merge(ln+rn, ls, le, re, fnc, data); // merge sorted list with (also sorted) remainder l = ucx_dlist_sort_merge(ln+rn+remainder_length, sorted, remainder, NULL, fnc, data); return l; } } /* dlist specific functions */ UcxDlist *ucx_dlist_first(const UcxDlist *l) { if (l == NULL) return NULL; const UcxDlist *e = l; while (e->prev != NULL) { e = e->prev; } return (UcxDlist *)e; } UcxDlist *ucx_dlist_remove(UcxDlist *l, UcxDlist *e) { if (e->prev == NULL) { if(e->next != NULL) { e->next->prev = NULL; l = e->next; } else { l = NULL; } } else { e->prev->next = e->next; e->next->prev = e->prev; } free(e); return l; }