1 //metadoc List copyright Steve Dekorte 2002
2 //metadoc List license BSD revised
3
4 #define LIST_C
5 #include "List.h"
6 #undef LIST_C
7 #include <stdlib.h>
8
List_new(void)9 List *List_new(void)
10 {
11 List *self = (List *)io_calloc(1, sizeof(List));
12 self->size = 0;
13 self->memSize = sizeof(void *)*LIST_START_SIZE;
14 self->items = (void **)io_calloc(1, self->memSize);
15 return self;
16 }
17
List_clone(const List * self)18 List *List_clone(const List *self)
19 {
20 List *child = List_new();
21 List_copy_(child, self);
22 /*
23 List *child = cpalloc(self, sizeof(List));
24 child->items = cpalloc(self->items, self->memSize);
25 */
26 return child;
27 }
28
List_sliceInPlace(List * self,long startIndex,long endIndex,long step)29 void List_sliceInPlace(List* self, long startIndex, long endIndex, long step)
30 {
31 List *tmp = List_new();
32 ssize_t cur;
33 size_t i; //, size = List_size(self);
34 /* Calculating new list's size. */
35 size_t slicesize = abs((int)((step < 0)
36 ? (endIndex - startIndex + 1) / step + 1
37 : (endIndex - startIndex - 1) / step + 1));
38 for(cur = startIndex, i = 0; i < slicesize; cur += step, i++)
39 {
40 List_append_(tmp, List_at_(self, cur));
41 }
42
43 List_copy_(self, tmp);
44 List_free(tmp);
45 }
46
List_cloneSlice(const List * self,long startIndex,long endIndex,long step)47 List *List_cloneSlice(const List *self, long startIndex, long endIndex, long step)
48 {
49 List *child = List_clone(self);
50 List_sliceInPlace(child, startIndex, endIndex, step);
51 return child;
52 }
53
List_free(List * self)54 void List_free(List *self)
55 {
56 //printf("List_free(%p)\n", (void *)self);
57 io_free(self->items);
58 io_free(self);
59 }
60
List_asStackAllocatedUArray(List * self)61 UArray List_asStackAllocatedUArray(List *self)
62 {
63 UArray a = UArray_stackAllocedEmptyUArray();
64 a.itemType = CTYPE_uintptr_t;
65 a.itemSize = sizeof(uintptr_t);
66 a.size = self->size;
67 a.data = (uint8_t *)(self->items);
68 return a;
69 }
70
List_memorySize(const List * self)71 size_t List_memorySize(const List *self)
72 {
73 return sizeof(List) + (self->size * sizeof(void *));
74 }
75
List_removeAll(List * self)76 void List_removeAll(List *self)
77 {
78 self->size = 0;
79 List_compactIfNeeded(self);
80 }
81
List_copy_(List * self,const List * otherList)82 void List_copy_(List *self, const List *otherList)
83 {
84 if (self == otherList || (!otherList->size && !self->size))
85 {
86 return;
87 }
88
89 List_preallocateToSize_(self, otherList->size);
90 memmove(self->items, otherList->items, sizeof(void *) * (otherList->size));
91 self->size = otherList->size;
92 }
93
List_equals_(const List * self,const List * otherList)94 int List_equals_(const List *self, const List *otherList)
95 {
96 return (self->size == otherList->size &&
97 memcmp(self->items, otherList->items, sizeof(void *) * self->size) == 0);
98 }
99
100 /* --- sizing ------------------------------------------------ */
101
List_setSize_(List * self,size_t index)102 void List_setSize_(List *self, size_t index)
103 {
104 List_ifNeededSizeTo_(self, index);
105 self->size = index;
106 }
107
List_preallocateToSize_(List * self,size_t index)108 void List_preallocateToSize_(List *self, size_t index)
109 {
110 size_t s = index * sizeof(void *);
111
112 if (s >= self->memSize)
113 {
114 size_t newSize = self->memSize * LIST_RESIZE_FACTOR;
115
116 if (s > newSize)
117 {
118 newSize = s;
119 }
120
121 self->items = (void **)io_realloc(self->items, newSize);
122 memset(self->items + self->size, 0, (newSize - (self->size*sizeof(void *))));
123 self->memSize = newSize;
124 }
125 }
126
List_compact(List * self)127 void List_compact(List *self)
128 {
129 self->memSize = self->size * sizeof(void *);
130 self->items = (void **)io_realloc(self->items, self->memSize);
131 }
132
133 // -----------------------------------------------------------
134
List_print(const List * self)135 void List_print(const List *self)
136 {
137 size_t i;
138
139 printf("List <%p> [%i bytes]\n", (void *)self, (int)self->memSize);
140
141 for (i = 0; i < self->size; i ++)
142 {
143 printf("%i: %p\n", (int)i, (void *)self->items[i]);
144 }
145
146 printf("\n");
147 }
148
149 // enumeration -----------------------------------------
150
List_do_(List * self,ListDoCallback * callback)151 void List_do_(List *self, ListDoCallback *callback)
152 {
153 LIST_FOREACH(self, i, v, if (v) (*callback)(v));
154 }
155
List_do_with_(List * self,ListDoWithCallback * callback,void * arg)156 void List_do_with_(List *self, ListDoWithCallback *callback, void *arg)
157 {
158 LIST_FOREACH(self, i, v, if (v) (*callback)(v, arg));
159 }
160
List_mapInPlace_(List * self,ListCollectCallback * callback)161 void List_mapInPlace_(List *self, ListCollectCallback *callback)
162 {
163 void **items = self->items;
164 LIST_FOREACH(self, i, v, items[i] = (*callback)(v));
165 }
166
List_map_(List * self,ListCollectCallback * callback)167 List *List_map_(List *self, ListCollectCallback *callback)
168 {
169 List *r = List_new();
170 LIST_FOREACH(self, i, v, List_append_(r, (*callback)(v)););
171 return r;
172 }
173
List_select_(List * self,ListSelectCallback * callback)174 List *List_select_(List *self, ListSelectCallback *callback)
175 {
176 List *r = List_new();
177 LIST_FOREACH(self, i, v, if ((*callback)(v)) List_append_(r, v));
178 return r;
179 }
180
List_detect_(List * self,ListDetectCallback * callback)181 void *List_detect_(List *self, ListDetectCallback *callback)
182 {
183 LIST_FOREACH(self, i, v, if (v && (*callback)(v)) return v; );
184 return NULL;
185 }
186
List_anyOne(const List * self)187 void *List_anyOne(const List *self)
188 {
189 size_t i;
190
191 if (self->size == 0)
192 {
193 return (void *)NULL;
194 }
195
196 if (self->size == 1)
197 {
198 return LIST_AT_(self, 0);
199 }
200
201 i = (rand() >> 4) % (self->size); // without the shift, just get a sequence!
202
203 return LIST_AT_(self, i);
204 }
205
List_shuffle(List * self)206 void List_shuffle(List *self)
207 {
208 size_t i, j;
209
210 for (i = 0; i < self->size - 1; i ++)
211 {
212 j = i + rand() % (self->size - i);
213 List_swap_with_(self, i, j);
214 }
215 }
216
List_removeLast(List * self)217 void *List_removeLast(List *self)
218 {
219 void *item = List_at_(self, self->size - 1);
220
221 if (item)
222 {
223 self->size --;
224 List_compactIfNeeded(self);
225 }
226
227 return item;
228 }
229
230