src/array_list.c

Wed, 16 Nov 2022 22:27:46 +0100

author
Mike Becker <universe@uap-core.de>
date
Wed, 16 Nov 2022 22:27:46 +0100
changeset 610
de5d3ee6435f
parent 607
2d99e978dc34
child 611
77efa5163ae5
permissions
-rw-r--r--

#219 array list: implement add and at

Add uses the low level cx_array_copy function which is
now also implemented, but not tested by individual unit
tests.

universe@606 1 /*
universe@606 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
universe@606 3 *
universe@606 4 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
universe@606 5 *
universe@606 6 * Redistribution and use in source and binary forms, with or without
universe@606 7 * modification, are permitted provided that the following conditions are met:
universe@606 8 *
universe@606 9 * 1. Redistributions of source code must retain the above copyright
universe@606 10 * notice, this list of conditions and the following disclaimer.
universe@606 11 *
universe@606 12 * 2. Redistributions in binary form must reproduce the above copyright
universe@606 13 * notice, this list of conditions and the following disclaimer in the
universe@606 14 * documentation and/or other materials provided with the distribution.
universe@606 15 *
universe@606 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
universe@606 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
universe@606 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
universe@606 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
universe@606 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
universe@606 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
universe@606 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
universe@606 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
universe@606 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
universe@606 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
universe@606 26 * POSSIBILITY OF SUCH DAMAGE.
universe@606 27 */
universe@606 28
universe@606 29 #include "cx/array_list.h"
universe@610 30 #include <assert.h>
universe@610 31 #include <string.h>
universe@606 32
universe@607 33 /* LOW LEVEL ARRAY LIST FUNCTIONS */
universe@607 34
universe@610 35 enum cx_array_coppy_result cx_array_copy(
universe@610 36 void **target,
universe@610 37 size_t *size,
universe@610 38 size_t *capacity,
universe@610 39 size_t index,
universe@610 40 void const *src,
universe@610 41 size_t elem_size,
universe@610 42 size_t elem_count,
universe@610 43 struct cx_array_reallocator_s *reallocator
universe@610 44 ) {
universe@610 45 /* assert pointers */
universe@610 46 assert(target != NULL);
universe@610 47 assert(size != NULL);
universe@610 48 assert(src != NULL);
universe@607 49
universe@610 50 /* determine capacity */
universe@610 51 size_t cap = capacity == NULL ? *size : *capacity;
universe@610 52
universe@610 53 /* check if resize is required */
universe@610 54 size_t newsize = index + elem_count;
universe@610 55 bool needrealloc = newsize > cap;
universe@610 56
universe@610 57 /* reallocate if possible */
universe@610 58 if (needrealloc) {
universe@610 59 /* a reallocator and a capacity variable must be available */
universe@610 60 if (reallocator == NULL || capacity == NULL) {
universe@610 61 return CX_ARRAY_COPY_REALLOC_NOT_SUPPORTED;
universe@610 62 }
universe@610 63
universe@610 64 /* increase capacity linearly */
universe@610 65 cap += 16;
universe@610 66
universe@610 67 /* perform reallocation */
universe@610 68 void *newmem = reallocator->realloc(
universe@610 69 *target, cap, elem_size, reallocator
universe@610 70 );
universe@610 71 if (newmem == NULL) {
universe@610 72 return CX_ARRAY_COPY_REALLOC_FAILED;
universe@610 73 }
universe@610 74
universe@610 75 /* store new pointer and capacity */
universe@610 76 *target = newmem;
universe@610 77 *capacity = cap;
universe@610 78 }
universe@610 79
universe@610 80 /* determine target pointer */
universe@610 81 char *start = *target;
universe@610 82 start += index * elem_size;
universe@610 83
universe@610 84 /* copy elements and set new size */
universe@610 85 memcpy(start, src, elem_count * elem_size);
universe@610 86 *size = newsize;
universe@610 87
universe@610 88 /* return successfully */
universe@610 89 return CX_ARRAY_COPY_SUCCESS;
universe@610 90 }
universe@607 91
universe@607 92 /* HIGH LEVEL ARRAY LIST FUNCTIONS */
universe@607 93
universe@607 94 typedef struct {
universe@607 95 struct cx_list_s base;
universe@607 96 void *data;
universe@610 97 struct cx_array_reallocator_s reallocator;
universe@607 98 } cx_array_list;
universe@607 99
universe@610 100 static void *cx_arl_realloc(
universe@610 101 void *array,
universe@610 102 size_t capacity,
universe@610 103 size_t elem_size,
universe@610 104 struct cx_array_reallocator_s *alloc
universe@610 105 ) {
universe@610 106 /* retrieve the pointer to the list allocator */
universe@610 107 CxAllocator const *al = alloc->ptr1;
universe@610 108
universe@610 109 /* use the list allocator to reallocate the memory */
universe@610 110 return cxRealloc(al, array, capacity * elem_size);
universe@610 111 }
universe@610 112
universe@607 113 static void cx_arl_destructor(struct cx_list_s *list) {
universe@610 114 cx_array_list *arl = (cx_array_list *) list;
universe@607 115 cxFree(list->allocator, arl->data);
universe@607 116 }
universe@607 117
universe@607 118 static int cx_arl_add(
universe@607 119 struct cx_list_s *list,
universe@607 120 void const *elem
universe@607 121 ) {
universe@610 122 cx_array_list *arl = (cx_array_list *) list;
universe@610 123 return cx_array_copy(
universe@610 124 &arl->data,
universe@610 125 &list->size,
universe@610 126 &list->capacity,
universe@610 127 list->size,
universe@610 128 elem,
universe@610 129 list->itemsize,
universe@610 130 1,
universe@610 131 &arl->reallocator
universe@610 132 );
universe@607 133 }
universe@607 134
universe@607 135 static int cx_arl_insert(
universe@607 136 struct cx_list_s *list,
universe@607 137 size_t index,
universe@607 138 void const *elem
universe@607 139 ) {
universe@607 140 return 1;
universe@607 141 }
universe@607 142
universe@607 143 static int cx_arl_insert_iter(
universe@607 144 struct cx_iterator_s *iter,
universe@607 145 void const *elem,
universe@607 146 int prepend
universe@607 147 ) {
universe@607 148 return 1;
universe@607 149 }
universe@607 150
universe@607 151 static int cx_arl_remove(
universe@607 152 struct cx_list_s *list,
universe@607 153 size_t index
universe@607 154 ) {
universe@607 155 return 1;
universe@607 156 }
universe@607 157
universe@610 158 static void *cx_arl_at(
universe@607 159 struct cx_list_s const *list,
universe@607 160 size_t index
universe@607 161 ) {
universe@610 162 if (index < list->size) {
universe@610 163 cx_array_list const *arl = (cx_array_list const *) list;
universe@610 164 char *space = arl->data;
universe@610 165 return space + index * list->itemsize;
universe@610 166 } else {
universe@610 167 return NULL;
universe@610 168 }
universe@607 169 }
universe@607 170
universe@607 171 static size_t cx_arl_find(
universe@607 172 struct cx_list_s const *list,
universe@607 173 void const *elem
universe@607 174 ) {
universe@607 175 return 0;
universe@607 176 }
universe@607 177
universe@607 178 static void cx_arl_sort(struct cx_list_s *list) {
universe@607 179
universe@607 180 }
universe@607 181
universe@607 182 static int cx_arl_compare(
universe@607 183 struct cx_list_s const *list,
universe@607 184 struct cx_list_s const *other
universe@607 185 ) {
universe@607 186
universe@607 187 }
universe@607 188
universe@607 189 static void cx_arl_reverse(struct cx_list_s *list) {
universe@607 190
universe@607 191 }
universe@607 192
universe@607 193 static struct cx_iterator_s cx_arl_iterator(
universe@607 194 struct cx_list_s *list,
universe@607 195 size_t index
universe@607 196 ) {
universe@607 197 struct cx_iterator_s iter;
universe@607 198
universe@607 199 return iter;
universe@607 200 }
universe@607 201
universe@607 202 static cx_list_class cx_array_list_class = {
universe@607 203 cx_arl_destructor,
universe@607 204 cx_arl_add,
universe@607 205 cx_arl_insert,
universe@607 206 cx_arl_insert_iter,
universe@607 207 cx_arl_remove,
universe@607 208 cx_arl_at,
universe@607 209 cx_arl_find,
universe@607 210 cx_arl_sort,
universe@607 211 cx_arl_compare,
universe@607 212 cx_arl_reverse,
universe@607 213 cx_arl_iterator,
universe@607 214 };
universe@607 215
universe@606 216 CxList *cxArrayListCreate(
universe@606 217 CxAllocator const *allocator,
universe@606 218 CxListComparator comparator,
universe@606 219 size_t item_size,
universe@606 220 size_t initial_capacity
universe@606 221 ) {
universe@607 222 cx_array_list *list = cxCalloc(allocator, 1, sizeof(cx_array_list));
universe@607 223 if (list == NULL) return NULL;
universe@607 224
universe@607 225 list->data = cxCalloc(allocator, initial_capacity, item_size);
universe@607 226 if (list->data == NULL) {
universe@607 227 cxFree(allocator, list);
universe@607 228 return NULL;
universe@607 229 }
universe@607 230
universe@607 231 list->base.cl = &cx_array_list_class;
universe@607 232 list->base.allocator = allocator;
universe@607 233 list->base.cmpfunc = comparator;
universe@607 234 list->base.itemsize = item_size;
universe@607 235 list->base.capacity = initial_capacity;
universe@607 236
universe@610 237 /* configure the reallocator */
universe@610 238 list->reallocator.realloc = cx_arl_realloc;
universe@610 239 list->reallocator.ptr1 = (void *) allocator;
universe@610 240
universe@607 241 return (CxList *) list;
universe@606 242 }

mercurial