ucx/list.c

Mon, 22 Jul 2013 13:45:49 +0200

author
Mike Becker <universe@uap-core.de>
date
Mon, 22 Jul 2013 13:45:49 +0200
changeset 123
7fb0f74517c5
parent 122
540d99722f1f
child 125
fca8efb122de
permissions
-rw-r--r--

changed signature of sstrncat + some documentation for UcxList + new features for UcxList

     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 ssize_t ucx_list_indexof(const UcxList *list, const UcxList *elem) {
   120     ssize_t index = 0;
   121     while (list) {
   122         if (list == elem) {
   123             return index;
   124         }
   125         list = list->next;
   126         index++;
   127     }
   128     return -1;
   129 }
   131 UcxList *ucx_list_get(const UcxList *l, int index) {
   132     if (l == NULL) return NULL;
   134     const UcxList *e = l;
   135     while (e->next != NULL && index > 0) {
   136         e = e->next;
   137         index--;
   138     }
   140     return (UcxList*)(index == 0 ? e : NULL);
   141 }
   143 ssize_t ucx_list_find(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) {
   144     ssize_t index = 0;
   145     UCX_FOREACH(e, l) {
   146         if (fnc(elem, e->data, cmpdata) == 0) {
   147             return index;
   148         }
   149         index++;
   150     }
   151     return -1;
   152 }
   154 int ucx_list_contains(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) {
   155     return ucx_list_find(l, elem, fnc, cmpdata) > -1;
   156 }
   158 size_t ucx_list_size(const UcxList *l) {
   159     if (l == NULL) return 0;
   161     const UcxList *e = l;
   162     size_t s = 1;
   163     while (e->next != NULL) {
   164         e = e->next;
   165         s++;
   166     }
   168     return s;
   169 }
   171 UcxList *ucx_list_sort_merge(int length,
   172         UcxList* restrict ls, UcxList* restrict le, UcxList* restrict re,
   173         cmp_func fnc, void* data) {
   175     UcxList** sorted = (UcxList**) malloc(sizeof(UcxList*)*length);
   176     UcxList *rc, *lc;
   178     lc = ls; rc = le;
   179     int n = 0;
   180     while (lc && lc != le && rc != re) {
   181         if (fnc(lc->data, rc->data, data) <= 0) {
   182             sorted[n] = lc;
   183             lc = lc->next;
   184         } else {
   185             sorted[n] = rc;
   186             rc = rc->next;
   187         }
   188         n++;
   189     }
   190     while (lc && lc != le) {
   191         sorted[n] = lc;
   192         lc = lc->next;
   193         n++;
   194     }
   195     while (rc && rc != re) {
   196         sorted[n] = rc;
   197         rc = rc->next;
   198         n++;
   199     }
   201     // Update pointer
   202     sorted[0]->prev = NULL;
   203     for (int i = 0 ; i < length-1 ; i++) {
   204         sorted[i]->next = sorted[i+1];
   205         sorted[i+1]->prev = sorted[i];
   206     }
   207     sorted[length-1]->next = NULL;
   209     UcxList *ret = sorted[0];
   210     free(sorted);
   211     return ret;
   212 }
   214 UcxList *ucx_list_sort(UcxList *l, cmp_func fnc, void *data) {
   215     if (l == NULL) {
   216         return NULL;
   217     }
   219     UcxList *lc;
   220     int ln = 1;
   222     UcxList *restrict ls = l, *restrict le, *restrict re;
   223     lc = ls;
   224     while (lc->next != NULL && fnc(lc->next->data, lc->data, data) > 0) {
   225         lc = lc->next;
   226         ln++;
   227     }
   228     le = lc->next;
   230     if (le == NULL) {
   231         return l; // this list is already sorted :)
   232     } else {
   233         UcxList *rc;
   234         int rn = 1;
   235         rc = le;
   236         while (rc->next != NULL && fnc(rc->next->data, rc->data, data) > 0) {
   237             rc = rc->next;
   238             rn++;
   239         }
   240         re = rc->next;
   242         // Something left? Sort it!
   243         UcxList *remainder = re;
   244         size_t remainder_length = ucx_list_size(remainder);
   245         if (remainder != NULL) {
   246             remainder = ucx_list_sort(remainder, fnc, data);
   247         }
   249         // {ls,...,le->prev} and {rs,...,re->prev} are sorted - merge them
   250         UcxList *sorted = ucx_list_sort_merge(ln+rn,
   251                 ls, le, re,
   252                 fnc, data);
   254         // merge sorted list with (also sorted) remainder
   255         l = ucx_list_sort_merge(ln+rn+remainder_length,
   256                 sorted, remainder, NULL, fnc, data);
   258         return l;
   259     }
   260 }
   262 UcxList *ucx_list_first(const UcxList *l) {
   263     if (l == NULL) return NULL;
   265     const UcxList *e = l;
   266     while (e->prev != NULL) {
   267         e = e->prev;
   268     }
   269     return (UcxList *)e;
   270 }
   272 UcxList *ucx_list_remove(UcxList *l, UcxList *e) {
   273     if (e->prev == NULL) {
   274         if(e->next != NULL) {
   275             e->next->prev = NULL;
   276             l = e->next;
   277         } else {
   278             l = NULL;
   279         }
   281     } else {
   282         e->prev->next = e->next;
   283         e->next->prev = e->prev;
   284     }
   285     free(e);
   286     return l;
   287 }

mercurial