ucx/list.c

changeset 5
88625853ae74
parent 1
1bcaac272cdf
child 70
88092b88ec00
--- a/ucx/list.c	Sat Dec 01 20:34:55 2012 +0100
+++ b/ucx/list.c	Mon Aug 12 14:40:19 2013 +0200
@@ -1,13 +1,45 @@
+/*
+ * 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 "list.h"
 
-UcxList *restrict ucx_list_clone(UcxList *restrict l,
+UcxList *ucx_list_clone(UcxList *l, copy_func fnc, void *data) {
+    return ucx_list_clone_a(ucx_default_allocator(), l, fnc, data);
+}
+
+UcxList *ucx_list_clone_a(UcxAllocator *alloc, UcxList *l,
         copy_func fnc, void *data) {
     UcxList *ret = NULL;
-    while (l != NULL) {
-        if (fnc != NULL) {
-            ret = ucx_list_append(ret, fnc(l->data, data));
+    while (l) {
+        if (fnc) {
+            ret = ucx_list_append_a(alloc, ret, fnc(l->data, data));
         } else {
-            ret = ucx_list_append(ret, l->data);
+            ret = ucx_list_append_a(alloc, ret, l->data);
         }
         l = l->next;
     }
@@ -32,46 +64,67 @@
 }
 
 void ucx_list_free(UcxList *l) {
+    ucx_list_free_a(ucx_default_allocator(), l);
+}
+
+void ucx_list_free_a(UcxAllocator *alloc, UcxList *l) {
     UcxList *e = l, *f;
     while (e != NULL) {
         f = e;
         e = e->next;
-        free(f);
+        alloc->free(alloc->pool, f);
     }
 }
 
 UcxList *ucx_list_append(UcxList *l, void *data)  {
-    UcxList *nl = (UcxList*) malloc(sizeof(UcxList));
-    if (nl == NULL) return NULL;
+    return ucx_list_append_a(ucx_default_allocator(), l, data);
+}
+
+UcxList *ucx_list_append_a(UcxAllocator *alloc, UcxList *l, void *data)  {
+    UcxList *nl = (UcxList*) alloc->malloc(alloc->pool, sizeof(UcxList));
+    if (!nl) {
+        return NULL;
+    }
     
     nl->data = data;
     nl->next = NULL;
-    if (l == NULL) {
-        return nl;
-    } else {
+    if (l) {
         UcxList *t = ucx_list_last(l);
         t->next = nl;
+        nl->prev = t;
         return l;
+    } else {
+        nl->prev = NULL;
+        return nl;
     }
 }
 
 UcxList *ucx_list_prepend(UcxList *l, void *data) {
-    UcxList *nl = ucx_list_append(NULL, data);
-    if (nl == NULL) return NULL;
+    return ucx_list_prepend_a(ucx_default_allocator(), l, data);
+}
+
+UcxList *ucx_list_prepend_a(UcxAllocator *alloc, UcxList *l, void *data) {
+    UcxList *nl = ucx_list_append_a(alloc, NULL, data);
+    if (!nl) {
+        return NULL;
+    }
+    l = ucx_list_first(l);
     
-    if (l != NULL) {
+    if (l) {
         nl->next = l;
+        l->prev = nl;
     }
     return nl;
 }
 
-UcxList *ucx_list_concat(UcxList *restrict l1, UcxList *restrict l2) {
-    if (l1 == NULL) {
-        return l2;
-    } else {
+UcxList *ucx_list_concat(UcxList *l1, UcxList *l2) {
+    if (l1) {
         UcxList *last = ucx_list_last(l1);
         last->next = l2;
+        l2->prev = last;
         return l1;
+    } else {
+        return l2;
     }
 }
 
@@ -85,11 +138,23 @@
     return (UcxList*)e;
 }
 
+ssize_t ucx_list_indexof(const UcxList *list, const UcxList *elem) {
+    ssize_t index = 0;
+    while (list) {
+        if (list == elem) {
+            return index;
+        }
+        list = list->next;
+        index++;
+    }
+    return -1;
+}
+
 UcxList *ucx_list_get(const UcxList *l, int index) {
     if (l == NULL) return NULL;
 
     const UcxList *e = l;
-    while (e->next != NULL && index > 0) {
+    while (e->next && index > 0) {
         e = e->next;
         index--;
     }
@@ -97,6 +162,27 @@
     return (UcxList*)(index == 0 ? e : NULL);
 }
 
+ssize_t ucx_list_find(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) {
+    ssize_t index = 0;
+    UCX_FOREACH(e, l) {
+        if (fnc) {
+            if (fnc(elem, e->data, cmpdata) == 0) {
+                return index;
+            }
+        } else {
+            if (elem == e->data) {
+                return index;
+            }
+        }
+        index++;
+    }
+    return -1;
+}
+
+int ucx_list_contains(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) {
+    return ucx_list_find(l, elem, fnc, cmpdata) > -1;
+}
+
 size_t ucx_list_size(const UcxList *l) {
     if (l == NULL) return 0;
     
@@ -141,8 +227,10 @@
     }
 
     // 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;
 
@@ -199,21 +287,35 @@
     }
 }
 
-/* list specific functions */
+UcxList *ucx_list_first(const UcxList *l) {
+    if (!l) {
+        return NULL;
+    }
+    
+    const UcxList *e = l;
+    while (e->prev) {
+        e = e->prev;
+    }
+    return (UcxList *)e;
+}
+
 UcxList *ucx_list_remove(UcxList *l, UcxList *e) {
-    if (e == l) {
-        l = e->next;
-        free(e);
+    return ucx_list_remove_a(ucx_default_allocator(), l, e);
+}
+    
+UcxList *ucx_list_remove_a(UcxAllocator *alloc, UcxList *l, UcxList *e) {
+    if (e->prev == NULL) {
+        if(e->next != NULL) {
+            e->next->prev = NULL;
+            l = e->next;
+        } else {
+            l = NULL;
+        }
+        
     } else {
-        UcxList *f = l;
-        while (f->next != NULL && f->next != e) {
-            f = f->next;
-        }
-        /* perform remove if this element is found in this list */
-        if (f->next == e) {
-            f->next = e->next;
-            free(e);
-        }
+        e->prev->next = e->next;
+        e->next->prev = e->prev;
     }
+    alloc->free(alloc->pool, e);
     return l;
 }

mercurial