src/array_list.c

changeset 611
77efa5163ae5
parent 610
de5d3ee6435f
child 612
820ee59121b4
equal deleted inserted replaced
610:de5d3ee6435f 611:77efa5163ae5
27 */ 27 */
28 28
29 #include "cx/array_list.h" 29 #include "cx/array_list.h"
30 #include <assert.h> 30 #include <assert.h>
31 #include <string.h> 31 #include <string.h>
32 #include <stdint.h>
32 33
33 /* LOW LEVEL ARRAY LIST FUNCTIONS */ 34 /* LOW LEVEL ARRAY LIST FUNCTIONS */
34 35
35 enum cx_array_coppy_result cx_array_copy( 36 enum cx_array_coppy_result cx_array_copy(
36 void **target, 37 void **target,
59 /* a reallocator and a capacity variable must be available */ 60 /* a reallocator and a capacity variable must be available */
60 if (reallocator == NULL || capacity == NULL) { 61 if (reallocator == NULL || capacity == NULL) {
61 return CX_ARRAY_COPY_REALLOC_NOT_SUPPORTED; 62 return CX_ARRAY_COPY_REALLOC_NOT_SUPPORTED;
62 } 63 }
63 64
65 /* check, if we need to repair the src pointer */
66 uintptr_t targetaddr = (uintptr_t) *target;
67 uintptr_t srcaddr = (uintptr_t) src;
68 bool repairsrc = targetaddr <= srcaddr
69 && srcaddr < targetaddr + cap * elem_size;
70
64 /* increase capacity linearly */ 71 /* increase capacity linearly */
65 cap += 16; 72 cap += 16;
66 73
67 /* perform reallocation */ 74 /* perform reallocation */
68 void *newmem = reallocator->realloc( 75 void *newmem = reallocator->realloc(
70 ); 77 );
71 if (newmem == NULL) { 78 if (newmem == NULL) {
72 return CX_ARRAY_COPY_REALLOC_FAILED; 79 return CX_ARRAY_COPY_REALLOC_FAILED;
73 } 80 }
74 81
82 /* repair src pointer, if necessary */
83 if (repairsrc) {
84 src = ((char *) newmem) + (srcaddr - targetaddr);
85 }
86
75 /* store new pointer and capacity */ 87 /* store new pointer and capacity */
76 *target = newmem; 88 *target = newmem;
77 *capacity = cap; 89 *capacity = cap;
78 } 90 }
79 91
80 /* determine target pointer */ 92 /* determine target pointer */
81 char *start = *target; 93 char *start = *target;
82 start += index * elem_size; 94 start += index * elem_size;
83 95
84 /* copy elements and set new size */ 96 /* copy elements and set new size */
85 memcpy(start, src, elem_count * elem_size); 97 memmove(start, src, elem_count * elem_size);
86 *size = newsize; 98 *size = newsize;
87 99
88 /* return successfully */ 100 /* return successfully */
89 return CX_ARRAY_COPY_SUCCESS; 101 return CX_ARRAY_COPY_SUCCESS;
90 } 102 }
135 static int cx_arl_insert( 147 static int cx_arl_insert(
136 struct cx_list_s *list, 148 struct cx_list_s *list,
137 size_t index, 149 size_t index,
138 void const *elem 150 void const *elem
139 ) { 151 ) {
140 return 1; 152 if (index > list->size) {
153 return 1;
154 } else if (index == list->size) {
155 return cx_arl_add(list, elem);
156 } else {
157 cx_array_list *arl = (cx_array_list *) list;
158
159 /* move elements starting at index to the right */
160 if (cx_array_copy(
161 &arl->data,
162 &list->size,
163 &list->capacity,
164 index + 1,
165 ((char *) arl->data) + index * list->itemsize,
166 list->itemsize,
167 list->size - index,
168 &arl->reallocator
169 )) {
170 return 1;
171 }
172
173 /* place the element */
174 memcpy(((char *) arl->data) + index * list->itemsize,
175 elem, list->itemsize);
176
177 return 0;
178 }
141 } 179 }
142 180
143 static int cx_arl_insert_iter( 181 static int cx_arl_insert_iter(
144 struct cx_iterator_s *iter, 182 struct cx_iterator_s *iter,
145 void const *elem, 183 void const *elem,

mercurial