New doc system done for core
[io.git] / libs / basekit / source / List.c
blob2837f358f094f72672056b8eb52dca061f5d296c
1 //metadoc List copyright Steve Dekorte 2002
2 //metadoc List license BSD revised
4 #define LIST_C
5 #include "List.h"
6 #undef LIST_C
7 #include <stdlib.h>
9 List *List_new(void)
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;
18 List *List_clone(const List *self)
20 List *child = List_new();
21 List_copy_(child, self);
23 List *child = cpalloc(self, sizeof(List));
24 child->items = cpalloc(self->items, self->memSize);
26 return child;
29 static size_t indexWrap(long index, size_t size)
31 if (index < 0)
33 index = size - index;
35 if (index < 0)
37 index = 0;
41 if (index > (int)size)
43 index = size;
46 return (size_t)index;
49 void List_sliceInPlace(List* self, long startIndex, long endIndex)
51 size_t i, size = List_size(self);
52 List *tmp = List_new();
53 size_t start = indexWrap(startIndex, size);
54 size_t end = indexWrap(endIndex, size);
56 for (i = start; i < size && i < end + 1; i ++)
58 List_append_(tmp, List_at_(self, i));
61 List_copy_(self, tmp);
62 List_free(tmp);
65 List *List_cloneSlice(const List *self, long startIndex, long endIndex)
67 List *child = List_clone(self);
68 List_sliceInPlace(child, startIndex, endIndex);
69 return child;
72 void List_free(List *self)
74 //printf("List_free(%p)\n", (void *)self);
75 io_free(self->items);
76 io_free(self);
79 UArray List_asStackAllocatedUArray(List *self)
81 UArray a = UArray_stackAllocedEmptyUArray();
82 a.itemType = CTYPE_uintptr_t;
83 a.itemSize = sizeof(uintptr_t);
84 a.size = self->size;
85 a.data = (uint8_t *)(self->items);
86 return a;
89 size_t List_memorySize(const List *self)
91 return sizeof(List) + (self->size * sizeof(void *));
94 void List_removeAll(List *self)
96 self->size = 0;
97 List_compactIfNeeded(self);
100 void List_copy_(List *self, const List *otherList)
102 if (self == otherList || (!otherList->size && !self->size))
104 return;
107 List_preallocateToSize_(self, otherList->size);
108 memmove(self->items, otherList->items, sizeof(void *) * (otherList->size));
109 self->size = otherList->size;
112 int List_equals_(const List *self, const List *otherList)
114 return (self->size == otherList->size &&
115 memcmp(self->items, otherList->items, sizeof(void *) * self->size) == 0);
118 /* --- sizing ------------------------------------------------ */
120 void List_setSize_(List *self, size_t index)
122 List_ifNeededSizeTo_(self, index);
123 self->size = index;
126 void List_preallocateToSize_(List *self, size_t index)
128 size_t s = index * sizeof(void *);
130 if (s >= self->memSize)
132 size_t newSize = self->memSize * LIST_RESIZE_FACTOR;
134 if (s > newSize)
136 newSize = s;
139 self->items = (void **)io_realloc(self->items, newSize);
140 memset(self->items + self->size, 0, (newSize - (self->size*sizeof(void *))));
141 self->memSize = newSize;
145 void List_compact(List *self)
147 self->memSize = self->size * sizeof(void *);
148 self->items = (void **)io_realloc(self->items, self->memSize);
151 // -----------------------------------------------------------
153 void List_print(const List *self)
155 size_t i;
157 printf("List <%p> [%i bytes]\n", (void *)self, (int)self->memSize);
159 for (i = 0; i < self->size; i ++)
161 printf("%i: %p\n", i, (void *)self->items[i]);
164 printf("\n");
167 // enumeration -----------------------------------------
169 void List_do_(List *self, ListDoCallback *callback)
171 LIST_FOREACH(self, i, v, if (v) (*callback)(v));
174 void List_do_with_(List *self, ListDoWithCallback *callback, void *arg)
176 LIST_FOREACH(self, i, v, if (v) (*callback)(v, arg));
179 void List_mapInPlace_(List *self, ListCollectCallback *callback)
181 void **items = self->items;
182 LIST_FOREACH(self, i, v, items[i] = (*callback)(v));
185 List *List_map_(List *self, ListCollectCallback *callback)
187 List *r = List_new();
188 LIST_FOREACH(self, i, v, List_append_(r, (*callback)(v)););
189 return r;
192 List *List_select_(List *self, ListSelectCallback *callback)
194 List *r = List_new();
195 LIST_FOREACH(self, i, v, if ((*callback)(v)) List_append_(r, v));
196 return r;
199 void *List_detect_(List *self, ListDetectCallback *callback)
201 LIST_FOREACH(self, i, v, if (v && (*callback)(v)) return v; );
202 return NULL;
205 void *List_anyOne(const List *self)
207 size_t i;
209 if (self->size == 0)
211 return (void *)NULL;
214 if (self->size == 1)
216 return LIST_AT_(self, 0);
219 i = (rand() >> 4) % (self->size); // without the shift, just get a sequence!
221 return LIST_AT_(self, i);
224 void List_shuffle(List *self)
226 size_t i, j;
228 for (i = 0; i < self->size - 1; i ++)
230 j = i + rand() % (self->size - i);
231 List_swap_with_(self, i, j);
235 void *List_removeLast(List *self)
237 void *item = List_at_(self, self->size - 1);
239 if (item)
241 self->size --;
242 List_compactIfNeeded(self);
245 return item;