src/list.c

Thu, 26 Jan 2023 20:59:36 +0100

author
Mike Becker <universe@uap-core.de>
date
Thu, 26 Jan 2023 20:59:36 +0100
changeset 641
d402fead3386
parent 640
55cc3b373c5e
child 647
2e6e9d9f2159
permissions
-rw-r--r--

add new pointer list wrapper - resolves #234

since we need a thread local variable, this drops C99 support

universe@503 1 /*
universe@503 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
universe@503 3 *
universe@503 4 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
universe@503 5 *
universe@503 6 * Redistribution and use in source and binary forms, with or without
universe@503 7 * modification, are permitted provided that the following conditions are met:
universe@503 8 *
universe@503 9 * 1. Redistributions of source code must retain the above copyright
universe@503 10 * notice, this list of conditions and the following disclaimer.
universe@503 11 *
universe@503 12 * 2. Redistributions in binary form must reproduce the above copyright
universe@503 13 * notice, this list of conditions and the following disclaimer in the
universe@503 14 * documentation and/or other materials provided with the distribution.
universe@503 15 *
universe@503 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
universe@503 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
universe@503 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
universe@503 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
universe@503 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
universe@503 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
universe@503 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
universe@503 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
universe@503 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
universe@503 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
universe@503 26 * POSSIBILITY OF SUCH DAMAGE.
universe@503 27 */
universe@503 28
universe@503 29 #include "cx/list.h"
universe@503 30
universe@640 31 #include <string.h>
universe@640 32
universe@641 33 // <editor-fold desc="Store Pointers Functionality">
universe@641 34
universe@641 35 static _Thread_local CxListComparator cx_pl_cmpfunc_impl;
universe@641 36
universe@641 37 static int cx_pl_cmpfunc(
universe@641 38 void const *l,
universe@641 39 void const *r
universe@641 40 ) {
universe@641 41 void *const *lptr = l;
universe@641 42 void *const *rptr = r;
universe@641 43 void const *left = lptr == NULL ? NULL : *lptr;
universe@641 44 void const *right = rptr == NULL ? NULL : *rptr;
universe@641 45 return cx_pl_cmpfunc_impl(left, right);
universe@641 46 }
universe@641 47
universe@641 48 static void cx_pl_hack_cmpfunc(struct cx_list_s const *list) {
universe@641 49 // cast away const - this is the hacky thing
universe@641 50 struct cx_list_s *l = (struct cx_list_s *) list;
universe@641 51 cx_pl_cmpfunc_impl = l->cmpfunc;
universe@641 52 l->cmpfunc = cx_pl_cmpfunc;
universe@641 53 }
universe@641 54
universe@641 55 static void cx_pl_unhack_cmpfunc(struct cx_list_s const *list) {
universe@641 56 // cast away const - this is the hacky thing
universe@641 57 struct cx_list_s *l = (struct cx_list_s *) list;
universe@641 58 l->cmpfunc = cx_pl_cmpfunc_impl;
universe@641 59 }
universe@641 60
universe@641 61 static void cx_pl_destructor(struct cx_list_s *list) {
universe@641 62 list->climpl->destructor(list);
universe@641 63 }
universe@641 64
universe@641 65 static int cx_pl_insert_element(
universe@641 66 struct cx_list_s *list,
universe@641 67 size_t index,
universe@641 68 void const *element
universe@641 69 ) {
universe@641 70 return list->climpl->insert_element(list, index, &element);
universe@641 71 }
universe@641 72
universe@641 73 static size_t cx_pl_insert_array(
universe@641 74 struct cx_list_s *list,
universe@641 75 size_t index,
universe@641 76 void const *array,
universe@641 77 size_t n
universe@641 78 ) {
universe@641 79 return list->climpl->insert_array(list, index, array, n);
universe@641 80 }
universe@641 81
universe@641 82 static int cx_pl_insert_iter(
universe@641 83 struct cx_mut_iterator_s *iter,
universe@641 84 void const *elem,
universe@641 85 int prepend
universe@641 86 ) {
universe@641 87 struct cx_list_s *list = iter->src_handle;
universe@641 88 return list->climpl->insert_iter(iter, &elem, prepend);
universe@641 89 }
universe@641 90
universe@641 91 static int cx_pl_remove(
universe@641 92 struct cx_list_s *list,
universe@641 93 size_t index
universe@641 94 ) {
universe@641 95 return list->climpl->remove(list, index);
universe@641 96 }
universe@641 97
universe@641 98 static void *cx_pl_at(
universe@641 99 struct cx_list_s const *list,
universe@641 100 size_t index
universe@641 101 ) {
universe@641 102 void **ptr = list->climpl->at(list, index);
universe@641 103 return ptr == NULL ? NULL : *ptr;
universe@641 104 }
universe@641 105
universe@641 106 static size_t cx_pl_find(
universe@641 107 struct cx_list_s const *list,
universe@641 108 void const *elem
universe@641 109 ) {
universe@641 110 cx_pl_hack_cmpfunc(list);
universe@641 111 size_t ret = list->climpl->find(list, &elem);
universe@641 112 cx_pl_unhack_cmpfunc(list);
universe@641 113 return ret;
universe@641 114 }
universe@641 115
universe@641 116 static void cx_pl_sort(struct cx_list_s *list) {
universe@641 117 cx_pl_hack_cmpfunc(list);
universe@641 118 list->climpl->sort(list);
universe@641 119 cx_pl_unhack_cmpfunc(list);
universe@641 120 }
universe@641 121
universe@641 122 static int cx_pl_compare(
universe@641 123 struct cx_list_s const *list,
universe@641 124 struct cx_list_s const *other
universe@641 125 ) {
universe@641 126 cx_pl_hack_cmpfunc(list);
universe@641 127 int ret = list->climpl->compare(list, other);
universe@641 128 cx_pl_unhack_cmpfunc(list);
universe@641 129 return ret;
universe@641 130 }
universe@641 131
universe@641 132 static void cx_pl_reverse(struct cx_list_s *list) {
universe@641 133 list->climpl->reverse(list);
universe@641 134 }
universe@641 135
universe@641 136 static void *cx_pl_iter_current(void const *it) {
universe@641 137 struct cx_iterator_s const *iter = it;
universe@641 138 void **ptr = iter->base.current_impl(it);
universe@641 139 return ptr == NULL ? NULL : *ptr;
universe@641 140 }
universe@641 141
universe@641 142 static struct cx_iterator_s cx_pl_iterator(
universe@641 143 struct cx_list_s const *list,
universe@641 144 size_t index
universe@641 145 ) {
universe@641 146 struct cx_iterator_s iter = list->climpl->iterator(list, index);
universe@641 147 iter.base.current_impl = iter.base.current;
universe@641 148 iter.base.current = cx_pl_iter_current;
universe@641 149 return iter;
universe@641 150 }
universe@641 151
universe@641 152 static cx_list_class cx_pointer_list_class = {
universe@641 153 cx_pl_destructor,
universe@641 154 cx_pl_insert_element,
universe@641 155 cx_pl_insert_array,
universe@641 156 cx_pl_insert_iter,
universe@641 157 cx_pl_remove,
universe@641 158 cx_pl_at,
universe@641 159 cx_pl_find,
universe@641 160 cx_pl_sort,
universe@641 161 cx_pl_compare,
universe@641 162 cx_pl_reverse,
universe@641 163 cx_pl_iterator,
universe@641 164 };
universe@641 165
universe@641 166 void cxListStoreObjects(CxList *list) {
universe@641 167 if (list->climpl != NULL) {
universe@641 168 list->cl = list->climpl;
universe@641 169 list->climpl = NULL;
universe@641 170 }
universe@641 171 }
universe@641 172
universe@641 173 void cxListStorePointers(CxList *list) {
universe@641 174 list->itemsize = sizeof(void *);
universe@641 175 list->climpl = list->cl;
universe@641 176 list->cl = &cx_pointer_list_class;
universe@641 177 }
universe@641 178
universe@641 179 bool cxListIsStoringPointers(CxList *list) {
universe@641 180 return list->climpl != NULL;
universe@641 181 }
universe@641 182
universe@641 183 // </editor-fold>
universe@641 184
universe@528 185 void cxListDestroy(CxList *list) {
universe@528 186 switch (list->content_destructor_type) {
universe@528 187 case CX_DESTRUCTOR_SIMPLE: {
universe@528 188 CxIterator iter = cxListBegin(list);
universe@528 189 cx_foreach(void*, elem, iter) {
universe@528 190 list->simple_destructor(elem);
universe@528 191 }
universe@528 192 break;
universe@503 193 }
universe@528 194 case CX_DESTRUCTOR_ADVANCED: {
universe@528 195 CxIterator iter = cxListBegin(list);
universe@528 196 cx_foreach(void*, elem, iter) {
universe@528 197 list->advanced_destructor.func(list->advanced_destructor.data, elem);
universe@528 198 }
universe@528 199 break;
universe@528 200 }
universe@528 201 case CX_DESTRUCTOR_NONE:
universe@528 202 break; // nothing
universe@503 203 }
universe@528 204
universe@524 205 list->cl->destructor(list);
universe@524 206 cxFree(list->allocator, list);
universe@503 207 }
universe@618 208
universe@618 209 int cxListCompare(
universe@618 210 CxList const *list,
universe@618 211 CxList const *other
universe@618 212 ) {
universe@618 213 if (list->cl->compare == other->cl->compare) {
universe@628 214 // same compare function, lists are compatible
universe@618 215 return list->cl->compare(list, other);
universe@618 216 } else {
universe@628 217 // different compare functions, use iterator
universe@618 218 if (list->size == other->size) {
universe@618 219 CxIterator left = cxListBegin(list);
universe@618 220 CxIterator right = cxListBegin(other);
universe@618 221 for (size_t i = 0; i < list->size; i++) {
universe@630 222 void *leftValue = cxIteratorCurrent(left);
universe@630 223 void *rightValue = cxIteratorCurrent(right);
universe@618 224 int d = list->cmpfunc(leftValue, rightValue);
universe@618 225 if (d != 0) {
universe@618 226 return d;
universe@618 227 }
universe@630 228 cxIteratorNext(left);
universe@630 229 cxIteratorNext(right);
universe@618 230 }
universe@618 231 return 0;
universe@618 232 } else {
universe@618 233 return list->size < other->size ? -1 : 1;
universe@618 234 }
universe@618 235 }
universe@618 236 }
universe@640 237
universe@640 238 CxMutIterator cxListMutIterator(
universe@640 239 CxList *list,
universe@640 240 size_t index
universe@640 241 ) {
universe@640 242 CxIterator it = list->cl->iterator(list, index);
universe@640 243 it.base.mutating = true;
universe@640 244
universe@640 245 // we know the iterators share the same memory layout
universe@640 246 CxMutIterator iter;
universe@640 247 memcpy(&iter, &it, sizeof(CxMutIterator));
universe@640 248 return iter;
universe@640 249 }

mercurial