src/list.c

Tue, 14 Mar 2023 20:25:24 +0100

author
Mike Becker <universe@uap-core.de>
date
Tue, 14 Mar 2023 20:25:24 +0100
changeset 664
af5bf4603a5d
parent 655
7340c4255f1f
child 666
b5dd654deb3b
permissions
-rw-r--r--

add cxListClear and fix missing destructor invocations - #241 #246

     1 /*
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 2021 Mike Becker, 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 "cx/list.h"
    31 #include <string.h>
    33 // <editor-fold desc="Store Pointers Functionality">
    35 static _Thread_local CxListComparator cx_pl_cmpfunc_impl;
    37 static int cx_pl_cmpfunc(
    38         void const *l,
    39         void const *r
    40 ) {
    41     void *const *lptr = l;
    42     void *const *rptr = r;
    43     void const *left = lptr == NULL ? NULL : *lptr;
    44     void const *right = rptr == NULL ? NULL : *rptr;
    45     return cx_pl_cmpfunc_impl(left, right);
    46 }
    48 static void cx_pl_hack_cmpfunc(struct cx_list_s const *list) {
    49     // cast away const - this is the hacky thing
    50     struct cx_list_s *l = (struct cx_list_s *) list;
    51     cx_pl_cmpfunc_impl = l->cmpfunc;
    52     l->cmpfunc = cx_pl_cmpfunc;
    53 }
    55 static void cx_pl_unhack_cmpfunc(struct cx_list_s const *list) {
    56     // cast away const - this is the hacky thing
    57     struct cx_list_s *l = (struct cx_list_s *) list;
    58     l->cmpfunc = cx_pl_cmpfunc_impl;
    59 }
    61 static void cx_pl_destructor(struct cx_list_s *list) {
    62     list->climpl->destructor(list);
    63 }
    65 static int cx_pl_insert_element(
    66         struct cx_list_s *list,
    67         size_t index,
    68         void const *element
    69 ) {
    70     return list->climpl->insert_element(list, index, &element);
    71 }
    73 static size_t cx_pl_insert_array(
    74         struct cx_list_s *list,
    75         size_t index,
    76         void const *array,
    77         size_t n
    78 ) {
    79     return list->climpl->insert_array(list, index, array, n);
    80 }
    82 static int cx_pl_insert_iter(
    83         struct cx_mut_iterator_s *iter,
    84         void const *elem,
    85         int prepend
    86 ) {
    87     struct cx_list_s *list = iter->src_handle;
    88     return list->climpl->insert_iter(iter, &elem, prepend);
    89 }
    91 static int cx_pl_remove(
    92         struct cx_list_s *list,
    93         size_t index
    94 ) {
    95     return list->climpl->remove(list, index);
    96 }
    98 static void cx_pl_clear(struct cx_list_s *list) {
    99     list->climpl->clear(list);
   100 }
   102 static int cx_pl_swap(
   103         struct cx_list_s *list,
   104         size_t i,
   105         size_t j
   106 ) {
   107     return list->climpl->swap(list, i, j);
   108 }
   110 static void *cx_pl_at(
   111         struct cx_list_s const *list,
   112         size_t index
   113 ) {
   114     void **ptr = list->climpl->at(list, index);
   115     return ptr == NULL ? NULL : *ptr;
   116 }
   118 static size_t cx_pl_find(
   119         struct cx_list_s const *list,
   120         void const *elem
   121 ) {
   122     cx_pl_hack_cmpfunc(list);
   123     size_t ret = list->climpl->find(list, &elem);
   124     cx_pl_unhack_cmpfunc(list);
   125     return ret;
   126 }
   128 static void cx_pl_sort(struct cx_list_s *list) {
   129     cx_pl_hack_cmpfunc(list);
   130     list->climpl->sort(list);
   131     cx_pl_unhack_cmpfunc(list);
   132 }
   134 static int cx_pl_compare(
   135         struct cx_list_s const *list,
   136         struct cx_list_s const *other
   137 ) {
   138     cx_pl_hack_cmpfunc(list);
   139     int ret = list->climpl->compare(list, other);
   140     cx_pl_unhack_cmpfunc(list);
   141     return ret;
   142 }
   144 static void cx_pl_reverse(struct cx_list_s *list) {
   145     list->climpl->reverse(list);
   146 }
   148 static void *cx_pl_iter_current(void const *it) {
   149     struct cx_iterator_s const *iter = it;
   150     void **ptr = iter->base.current_impl(it);
   151     return ptr == NULL ? NULL : *ptr;
   152 }
   154 static struct cx_iterator_s cx_pl_iterator(
   155         struct cx_list_s const *list,
   156         size_t index,
   157         bool backwards
   158 ) {
   159     struct cx_iterator_s iter = list->climpl->iterator(list, index, backwards);
   160     iter.base.current_impl = iter.base.current;
   161     iter.base.current = cx_pl_iter_current;
   162     return iter;
   163 }
   165 static cx_list_class cx_pointer_list_class = {
   166         cx_pl_destructor,
   167         cx_pl_insert_element,
   168         cx_pl_insert_array,
   169         cx_pl_insert_iter,
   170         cx_pl_remove,
   171         cx_pl_clear,
   172         cx_pl_swap,
   173         cx_pl_at,
   174         cx_pl_find,
   175         cx_pl_sort,
   176         cx_pl_compare,
   177         cx_pl_reverse,
   178         cx_pl_iterator,
   179 };
   181 void cxListStoreObjects(CxList *list) {
   182     if (list->climpl != NULL) {
   183         list->cl = list->climpl;
   184         list->climpl = NULL;
   185     }
   186 }
   188 void cxListStorePointers(CxList *list) {
   189     list->itemsize = sizeof(void *);
   190     list->climpl = list->cl;
   191     list->cl = &cx_pointer_list_class;
   192 }
   194 bool cxListIsStoringPointers(CxList *list) {
   195     return list->climpl != NULL;
   196 }
   198 // </editor-fold>
   200 void cx_list_invoke_destructor(
   201         CxList const *list,
   202         void *elem
   203 ) {
   204     switch (list->content_destructor_type) {
   205         case CX_DESTRUCTOR_SIMPLE: {
   206             list->simple_destructor(elem);
   207             break;
   208         }
   209         case CX_DESTRUCTOR_ADVANCED: {
   210             list->advanced_destructor.func(list->advanced_destructor.data, elem);
   211             break;
   212         }
   213         case CX_DESTRUCTOR_NONE:
   214             break; // nothing
   215     }
   216 }
   218 void cxListDestroy(CxList *list) {
   219     switch (list->content_destructor_type) {
   220         case CX_DESTRUCTOR_SIMPLE: {
   221             CxIterator iter = cxListIterator(list);
   222             cx_foreach(void*, elem, iter) {
   223                 list->simple_destructor(elem);
   224             }
   225             break;
   226         }
   227         case CX_DESTRUCTOR_ADVANCED: {
   228             CxIterator iter = cxListIterator(list);
   229             cx_foreach(void*, elem, iter) {
   230                 list->advanced_destructor.func(list->advanced_destructor.data, elem);
   231             }
   232             break;
   233         }
   234         case CX_DESTRUCTOR_NONE:
   235             break; // nothing
   236     }
   238     list->cl->destructor(list);
   239     cxFree(list->allocator, list);
   240 }
   242 int cxListCompare(
   243         CxList const *list,
   244         CxList const *other
   245 ) {
   246     if (list->cl->compare == other->cl->compare) {
   247         // same compare function, lists are compatible
   248         return list->cl->compare(list, other);
   249     } else {
   250         // different compare functions, use iterator
   251         if (list->size == other->size) {
   252             CxIterator left = cxListIterator(list);
   253             CxIterator right = cxListIterator(other);
   254             for (size_t i = 0; i < list->size; i++) {
   255                 void *leftValue = cxIteratorCurrent(left);
   256                 void *rightValue = cxIteratorCurrent(right);
   257                 int d = list->cmpfunc(leftValue, rightValue);
   258                 if (d != 0) {
   259                     return d;
   260                 }
   261                 cxIteratorNext(left);
   262                 cxIteratorNext(right);
   263             }
   264             return 0;
   265         } else {
   266             return list->size < other->size ? -1 : 1;
   267         }
   268     }
   269 }
   271 CxMutIterator cxListMutIteratorAt(
   272         CxList *list,
   273         size_t index
   274 ) {
   275     CxIterator it = list->cl->iterator(list, index, false);
   276     it.base.mutating = true;
   278     // we know the iterators share the same memory layout
   279     CxMutIterator iter;
   280     memcpy(&iter, &it, sizeof(CxMutIterator));
   281     return iter;
   282 }
   284 CxMutIterator cxListMutBackwardsIteratorAt(
   285         CxList *list,
   286         size_t index
   287 ) {
   288     CxIterator it = list->cl->iterator(list, index, true);
   289     it.base.mutating = true;
   291     // we know the iterators share the same memory layout
   292     CxMutIterator iter;
   293     memcpy(&iter, &it, sizeof(CxMutIterator));
   294     return iter;
   295 }

mercurial