ucx/list.c

Mon, 22 Jul 2013 11:53:39 +0200

author
Mike Becker <universe@uap-core.de>
date
Mon, 22 Jul 2013 11:53:39 +0200
changeset 122
540d99722f1f
parent 121
ucx/dlist.c@311cac04d079
child 123
7fb0f74517c5
permissions
-rw-r--r--

removal of single linked list implemenation - step 2: renamed UcxDlist to UcxList (new single implementation)

     1 /*
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 2013 Olaf Wintermann. All rights reserved.
     5  *
     6  * Redistribution and use in source and binary forms, with or without
     7  * modification, are permitted provided that the following conditions are met:
     8  *
     9  *   1. Redistributions of source code must retain the above copyright
    10  *      notice, this list of conditions and the following disclaimer.
    11  *
    12  *   2. Redistributions in binary form must reproduce the above copyright
    13  *      notice, this list of conditions and the following disclaimer in the
    14  *      documentation and/or other materials provided with the distribution.
    15  *
    16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    26  * POSSIBILITY OF SUCH DAMAGE.
    27  */
    29 #include "list.h"
    31 UcxList *ucx_list_clone(UcxList *l, copy_func fnc, void *data) {
    32     UcxList *ret = NULL;
    33     while (l != NULL) {
    34         if (fnc != NULL) {
    35             ret = ucx_list_append(ret, fnc(l->data, data));
    36         } else {
    37             ret = ucx_list_append(ret, l->data);
    38         }
    39         l = l->next;
    40     }
    41     return ret;
    42 }
    44 int ucx_list_equals(const UcxList *l1, const UcxList *l2,
    45         cmp_func fnc, void* data) {
    46     if (l1 == l2) return 1;
    48     while (l1 != NULL && l2 != NULL) {
    49         if (fnc == NULL) {
    50             if (l1->data != l2->data) return 0;
    51         } else {
    52             if (fnc(l1->data, l2->data, data) != 0) return 0;
    53         }
    54         l1 = l1->next;
    55         l2 = l2->next;
    56     }
    58     return (l1 == NULL && l2 == NULL);
    59 }
    61 void ucx_list_free(UcxList *l) {
    62     UcxList *e = l, *f;
    63     while (e != NULL) {
    64         f = e;
    65         e = e->next;
    66         free(f);
    67     }
    68 }
    70 UcxList *ucx_list_append(UcxList *l, void *data)  {
    71     UcxList *nl = (UcxList*) malloc(sizeof(UcxList));
    72     if (nl == NULL) return NULL;
    74     nl->data = data;
    75     nl->next = NULL;
    76     if (l == NULL) {
    77         nl->prev = NULL;
    78         return nl;
    79     } else {
    80         UcxList *t = ucx_list_last(l);
    81         t->next = nl;
    82         nl->prev = t;
    83         return l;
    84     }
    85 }
    87 UcxList *ucx_list_prepend(UcxList *l, void *data) {
    88     UcxList *nl = ucx_list_append(NULL, data);
    89     if (nl == NULL) return NULL;
    91     if (l != NULL) {
    92         nl->next = l;
    93         l->prev = nl;
    94     }
    95     return nl;
    96 }
    98 UcxList *ucx_list_concat(UcxList *l1, UcxList *l2) {
    99     if (l1 == NULL) {
   100         return l2;
   101     } else {
   102         UcxList *last = ucx_list_last(l1);
   103         last->next = l2;
   104         l2->prev = last;
   105         return l1;
   106     }
   107 }
   109 UcxList *ucx_list_last(const UcxList *l) {
   110     if (l == NULL) return NULL;
   112     const UcxList *e = l;
   113     while (e->next != NULL) {
   114         e = e->next;
   115     }
   116     return (UcxList*)e;
   117 }
   119 UcxList *ucx_list_get(const UcxList *l, int index) {
   120     if (l == NULL) return NULL;
   122     const UcxList *e = l;
   123     while (e->next != NULL && index > 0) {
   124         e = e->next;
   125         index--;
   126     }
   128     return (UcxList*)(index == 0 ? e : NULL);
   129 }
   131 int ucx_list_contains(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) {
   132     UCX_FOREACH(e, l) {
   133         if (!fnc(elem, e->data, cmpdata)) {
   134             return 1;
   135         }
   136     }
   137     return 0;
   138 }
   140 size_t ucx_list_size(const UcxList *l) {
   141     if (l == NULL) return 0;
   143     const UcxList *e = l;
   144     size_t s = 1;
   145     while (e->next != NULL) {
   146         e = e->next;
   147         s++;
   148     }
   150     return s;
   151 }
   153 UcxList *ucx_list_sort_merge(int length,
   154         UcxList* restrict ls, UcxList* restrict le, UcxList* restrict re,
   155         cmp_func fnc, void* data) {
   157     UcxList** sorted = (UcxList**) malloc(sizeof(UcxList*)*length);
   158     UcxList *rc, *lc;
   160     lc = ls; rc = le;
   161     int n = 0;
   162     while (lc && lc != le && rc != re) {
   163         if (fnc(lc->data, rc->data, data) <= 0) {
   164             sorted[n] = lc;
   165             lc = lc->next;
   166         } else {
   167             sorted[n] = rc;
   168             rc = rc->next;
   169         }
   170         n++;
   171     }
   172     while (lc && lc != le) {
   173         sorted[n] = lc;
   174         lc = lc->next;
   175         n++;
   176     }
   177     while (rc && rc != re) {
   178         sorted[n] = rc;
   179         rc = rc->next;
   180         n++;
   181     }
   183     // Update pointer
   184     sorted[0]->prev = NULL;
   185     for (int i = 0 ; i < length-1 ; i++) {
   186         sorted[i]->next = sorted[i+1];
   187         sorted[i+1]->prev = sorted[i];
   188     }
   189     sorted[length-1]->next = NULL;
   191     UcxList *ret = sorted[0];
   192     free(sorted);
   193     return ret;
   194 }
   196 UcxList *ucx_list_sort(UcxList *l, cmp_func fnc, void *data) {
   197     if (l == NULL) {
   198         return NULL;
   199     }
   201     UcxList *lc;
   202     int ln = 1;
   204     UcxList *restrict ls = l, *restrict le, *restrict re;
   205     lc = ls;
   206     while (lc->next != NULL && fnc(lc->next->data, lc->data, data) > 0) {
   207         lc = lc->next;
   208         ln++;
   209     }
   210     le = lc->next;
   212     if (le == NULL) {
   213         return l; // this list is already sorted :)
   214     } else {
   215         UcxList *rc;
   216         int rn = 1;
   217         rc = le;
   218         while (rc->next != NULL && fnc(rc->next->data, rc->data, data) > 0) {
   219             rc = rc->next;
   220             rn++;
   221         }
   222         re = rc->next;
   224         // Something left? Sort it!
   225         UcxList *remainder = re;
   226         size_t remainder_length = ucx_list_size(remainder);
   227         if (remainder != NULL) {
   228             remainder = ucx_list_sort(remainder, fnc, data);
   229         }
   231         // {ls,...,le->prev} and {rs,...,re->prev} are sorted - merge them
   232         UcxList *sorted = ucx_list_sort_merge(ln+rn,
   233                 ls, le, re,
   234                 fnc, data);
   236         // merge sorted list with (also sorted) remainder
   237         l = ucx_list_sort_merge(ln+rn+remainder_length,
   238                 sorted, remainder, NULL, fnc, data);
   240         return l;
   241     }
   242 }
   244 UcxList *ucx_list_first(const UcxList *l) {
   245     if (l == NULL) return NULL;
   247     const UcxList *e = l;
   248     while (e->prev != NULL) {
   249         e = e->prev;
   250     }
   251     return (UcxList *)e;
   252 }
   254 UcxList *ucx_list_remove(UcxList *l, UcxList *e) {
   255     if (e->prev == NULL) {
   256         if(e->next != NULL) {
   257             e->next->prev = NULL;
   258             l = e->next;
   259         } else {
   260             l = NULL;
   261         }
   263     } else {
   264         e->prev->next = e->next;
   265         e->next->prev = e->prev;
   266     }
   267     free(e);
   268     return l;
   269 }

mercurial