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