/*#io
docCopyright("Steve Dekorte", 2002)
docLicense("BSD revised")
docDescription("List is an array of void pointers.
The List is not responsible for freeing it's elements.
")
*/
#ifdef LIST_C
#define IO_IN_C_FILE
#endif
#include "Common_inline.h"
#ifdef IO_DECLARE_INLINES
#define LIST_FOREACH(list, index, value, code) \
{ \
List *foreachList = list; \
size_t index, foreachMax = List_size(foreachList); \
\
for (index = 0; index < foreachMax; index ++) \
{ \
void *value = List_at_(foreachList, index); \
code; \
} \
}
#define LIST_SAFEFOREACH(list, index, value, code) \
{ \
List *foreachList = list; \
size_t index; \
\
for (index = 0; index < List_size(foreachList); index ++) \
{ \
void *value = List_at_(foreachList, index); \
code; \
} \
}
#define LIST_REVERSEFOREACH(list, index, value, code) \
{ \
List *foreachList = list; \
size_t index = List_size(foreachList); \
\
while (index) \
{ \
void *value = List_at_(foreachList, (index --)); \
code; \
} \
}
#define LIST_SAFEREVERSEFOREACH(list, index, value, code) \
{ \
List *foreachList = list; \
size_t index = List_size(foreachList); \
\
for (index = List_size(foreachList) - 1; index > 0; index --) \
{ \
void *value = List_at_(foreachList, index); \
code; \
if (index > List_size(foreachList) - 1) { index = List_size(foreachList) - 1; } \
} \
}
#define LIST_DO_(list, func) \
{ \
List *foreachList = list; \
size_t index, foreachMax = List_size(foreachList); \
\
for (index = 0; index < foreachMax; index ++) \
{ \
func(List_at_(foreachList, index)); \
} \
}
IOINLINE int List_size(List *self)
{
return self->size;
}
IOINLINE void List_ifNeededSizeTo_(List *self, int newSize)
{
if (newSize * sizeof(void *) >= self->memSize)
{
List_preallocateToSize_(self, newSize);
}
}
IOINLINE void *List_rawAt_(List *self, unsigned int index)
{
return self->items[index];
}
IOINLINE void *List_at_(List *self, int index)
{
if (index < self->size && index > -1 )
{
return self->items[index];
}
return (void *)NULL;
}
// --------------------------------
IOINLINE ListCursor List_cursor(List *self)
{
ListCursor lc;
lc.list = self;
lc.index = 0;
return lc;
}
IOINLINE void *ListCursor_next(ListCursor *self)
{
if (self->index == (size_t)List_size(self->list))
{
return NULL;
}
self->index ++;
return List_at_(self->list, self->index);
}
IOINLINE size_t ListCursor_index(ListCursor *self)
{
return self->index;
}
IOINLINE void *ListCursor_value(ListCursor *self)
{
return List_at_(self->list, self->index);
}
// --------------------------------------------
IOINLINE int List_indexOf_(List *self, void *item)
{
int index = 0;
while (index < self->size)
{
if (self->items[index] == item)
{
return index;
}
index ++;
}
return -1;
}
IOINLINE int List_contains_(List *self, void *item)
{
int index = 0;
while (index < self->size)
{
if (self->items[index] == item)
{
return 1;
}
index ++;
}
return 0;
}
IOINLINE void *List_append_(List *self, void *item)
{
List_ifNeededSizeTo_(self, self->size + 1);
self->items[self->size] = item;
self->size ++;
return item;
}
IOINLINE void List_appendSeq_(List *self, List *otherList)
{
LIST_FOREACH(otherList, i, v, List_append_(self, v); );
/*
List_setSize_(self, self->size + otherList->size);
memcpy(self->items + self->size, otherList->items, otherList->size * sizeof(void *));
*/
}
IOINLINE void List_compactIfNeeded(List *self)
{
if(self->memSize > 1024 && self->size * sizeof(void *) * 4 < self->memSize)
{
List_compact(self);
}
}
IOINLINE void List_removeIndex_(List *self, int index)
{
if (index >= 0 && index < self->size)
{
if ( index != self->size - 1)
{
memmove(&self->items[index], &self->items[index + 1],
(self->size - 1 - index) * sizeof(void *));
}
self->size --;
List_compactIfNeeded(self);
}
}
IOINLINE void List_removeIndex_toIndex_(List *self, int index1, int index2)
{
int length;
if (index1 < 0)
{
index1 = 0;
}
if (index1 > self->size - 1)
{
index1 = self->size - 1;
}
if (index2 < 0)
{
index2 = 0;
}
if (index2 > self->size - 1)
{
index2 = self->size - 1;
}
length = index2 - index1;
if (length <= 0)
{
return;
}
memmove(&self->items[index1], &self->items[index2],
(self->size - index2) * sizeof(void *));
self->size -= length;
List_compactIfNeeded(self);
}
IOINLINE void List_remove_(List *self, void *item)
{
int index;
for (index = 0; index < self->size; index ++)
{
if (self->items[index] == item)
{
List_removeIndex_(self, index);
}
}
}
IOINLINE int List_removeFirst_(List *self, void *item)
{
int i, max = self->size;
for (i = 0; i < max; i ++)
{
if (self->items[i] == item)
{
List_removeIndex_(self, i);
return 1;
}
}
return 0;
}
IOINLINE void List_removeLast_(List *self, void *item)
{
int index = self->size - 1;
for (index = self->size - 1; index > -1; index --)
{
if (self->items[index] == item)
{
List_removeIndex_(self, index);
break;
}
}
}
IOINLINE void List_removeItems_(List *self, List *other)
{
int i;
int count = other->size;
void **items = other->items;
for (i = 0; i < count; i ++)
{
List_remove_(self, items[i]);
}
}
IOINLINE void List_at_insert_(List *self, int index, void *item)
{
if (index < 0)
{
return;
}
if (index > self->size - 1)
{
List_preallocateToSize_(self, index + 1);
}
else
{
List_ifNeededSizeTo_(self, self->size + 1);
}
memmove(&self->items[index + 1], &self->items[index],
(self->size - index) * sizeof(void *));
self->items[index] = item;
self->size ++;
}
IOINLINE void List_at_put_(List *self, int index, void *item)
{
if (index < 0)
{
return;
}
List_ifNeededSizeTo_(self, index);
self->items[index] = item;
if (index + 1 > self->size)
{
self->size = index + 1;
}
}
IOINLINE void List_swap_with_(List *self, int index1, int index2)
{
if (index1 < 0 || index2 < 0)
{
return;
}
if (index1 != index2)
{
void **items = self->items;
void *v1 = items[index1];
items[index1] = items[index2];
items[index2] = v1;
}
}
IOINLINE void List_reverse(List *self)
{
register void **i = self->items;
register void **j = i + (self->size - 1);
register void *iv;
while (j > i)
{
iv = *i;
*i = *j;
*j = iv;
j --;
i ++;
}
}
/* --- stack -------------------------------------------------- */
IOINLINE void List_push_(List *self, void *item)
{
List_ifNeededSizeTo_(self, self->size + 1);
self->items[self->size] = item;
self->size ++;
}
IOINLINE void *List_pop(List *self)
{
void *item;
if (!self->size)
{
return (void *)NULL;
}
self->size --;
item = self->items[self->size];
List_compactIfNeeded(self);
return item;
}
IOINLINE void *List_top(List *self)
{
if (!self->size)
{
return (void *)NULL;
}
return self->items[self->size - 1];
}
/* --- perform -------------------------------------------------- */
IOINLINE int List_removeTrueFor_(List *self, ListCollectCallback* callback)
{
int getIndex = 0;
int putIndex = 0;
int count = self->size;
void **items = self->items;
while (getIndex < count)
{
void *item = items[getIndex];
if (item && !((*callback)(item)))
{
if (getIndex!=putIndex)
{
items[putIndex] = item;
}
putIndex ++;
}
getIndex ++;
}
self->size = putIndex;
return getIndex - putIndex;
}
IOINLINE void List_qsort(List *self, ListSortCallback *callback)
{
qsort(self->items, self->size, sizeof(void *), *callback);
}
IOINLINE void *List_bsearch(List *self, const void *key, ListSortCallback *callback)
{
return bsearch(key, self->items, self->size, sizeof(void *), callback);
}
IOINLINE void *List_first(List *self)
{
return List_at_(self, 0);
}
IOINLINE void *List_last(List *self)
{
return List_at_(self, List_size(self) - 1);
}
#undef IO_IN_C_FILE
#endif
syntax highlighted by Code2HTML, v. 0.9.1