diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..67807a3 --- /dev/null +++ b/Makefile @@ -0,0 +1,29 @@ +SRC:=src/*.c +INCLUDE:=include/ +CFLAGS:=-g -Wall -pedantic +LFLAGS:= +BUILD:=build +OBJ:=obj + +TEST_SRC:=src/test/main.c + +ifeq ($(shell uname), Linux) +TARGET_TEST_EXT = +else +TARGET_TEST_EXT = .exe +endif + +all: clean test + +clean: + rm -f $(BUILD)/* + rm -f $(OBJ)/* + +liblist: + gcc -c $(CFLAGS) -I$(INCLUDE) $(SRC) + mv *.o $(OBJ)/ + ar rcs $(BUILD)/$@.a $(OBJ)/*.o + +test: liblist + gcc $(TEST_SRC) $(CFLAGS) -I$(INCLUDE) -o $(BUILD)/$@$(TARGET_TEST_EXT) $(LFLAGS) $(BUILD)/liblist.a + $(BUILD)/$@$(TARGET_TEST_EXT) \ No newline at end of file diff --git a/build/liblist.a b/build/liblist.a new file mode 100644 index 0000000..8a1068f Binary files /dev/null and b/build/liblist.a differ diff --git a/build/test.exe b/build/test.exe new file mode 100644 index 0000000..592cb41 Binary files /dev/null and b/build/test.exe differ diff --git a/include/list.h b/include/list.h new file mode 100644 index 0000000..3b69948 --- /dev/null +++ b/include/list.h @@ -0,0 +1,101 @@ +#ifndef _LIST_H +#define _LIST_H +#include +#include +#include +#include + +#define L_DEFAULT_BLOCKSIZE 16 + +/* Functional Macros */ + +#define l_create_d(type) l_create(type, L_DEFAULT_BLOCKSIZE) +#define l_create_from_d(from, length, type) l_create_from(from,length, type, L_DEFAULT_BLOCKSIZE) +#define l_get_v(list,index, type) *(type*)l_get(list,index) + +/** Returns 1 if is a valid index for **/ +#define l_bcheck(t, index) (index>=0&&indexlength) + +/* Enums */ + +typedef enum { + QUICKSORT +} _l_sort_alg; + +/* Structures */ + +struct l_block { + struct l_block* next; + unsigned char data[]; +}; + +typedef struct { + int length; + size_t type; + int blocksize; + struct l_block* block0; +} list_t; + +typedef struct { + list_t *list; + void* element; + int index; +} l_iterator; + +/* Function Pointers */ + +#define L_P_FUNCTION(name) int lp_ ## name(const list_t *list, int index) +#define L_A_FUNCTION(name) void la_ ## name(const list_t *list, int index) +#define L_C_FUNCTION(name) int lc_ ## name(const list_t *list, int i1, int i2) +typedef int (*_l_predicate)(const list_t *, int); /** Takes (list), (index). Returns non-zero if true **/ +typedef int (*_l_comparator)(const list_t*, int,int); /** Takes (list), (i1), (i2). Returns 0 if equal, -1 if goes before , +1 if goes after **/ +typedef void (*_l_action)(const list_t*, int); /** Takes (list), (index) **/ + +/* Functions */ +#ifdef __cplusplus +extern "C" { +#endif + +list_t* l_create(size_t type,int blocksize); /** Allocates new list_t aligned to size (e.g. "sizeof(int)"), and first block with (use l_create_d(size_t) to use default blocksize) **/ +list_t* l_create_from(void* from, int items, size_t type, int bs); /** Allocates new list_t and copies elements from into it **/ +void l_destroy(list_t *t); /** Frees all memory alocated to and then frees **/ +void l_add(list_t *t, const void* o); /** Adds new element at end of array with copy of data at , then updates ->length pointer **/ +void* l_get(const list_t *t, int index); /** Returns pointer to element at **/ +void l_nullify(list_t *t, int index); /** Writes over element at with 0s (bytes) **/ +void l_copy(const list_t* src,int so,list_t* de, int o,int len); /** Copies elements from (offset by ) to (offset by ) **/ +void l_copy_ar(const list_t* src, int so, void* dest, int len); /** Copies elements from (offset by ) to **/ +void* l_toarray_n(const list_t *t, int* size, _l_predicate p); /** Creates a new array and copies each element that satisfies

, or if

is NULL, all of them. Size of the new array is returned in unless is NULL **/ +void l_toarray(const list_t *t, void* dest, size_t len); /** Copies elements from to **/ +int l_isnull(const list_t *t, int index); /** Returns 1 if all bytes of element at are 0 **/ +void l_nullify_if(list_t *t, _l_predicate f); /** Nullifies elements that satisfy **/ +void l_do(list_t *t, _l_action act); /** Calls on all elements of **/ +void l_do_if(list_t *t, _l_action act, _l_predicate f); /** Calls on elements that satisfy **/ +void l_swap(list_t *t, int index1, int index2); /** Swap elements at and **/ +void l_sort(list_t *t, _l_sort_alg alg, _l_comparator comp); /** Sorts with algorithm using comparator **/ +list_t* l_clone(const list_t *t); /** Creates new list from **/ +list_t* l_clone_if(const list_t *t, _l_predicate f); /** Creates new list from with all elements that satisfy **/ + +l_iterator li_create(list_t *list); /** Creates iterator from and initialises at index 0 **/ +int li_next(l_iterator *it); /** Updates current element and increments pointer in and returns non-zero if index is in bounds **/ +void* li_get(l_iterator *i); /** Updates and returns current element of iterator, or NULL if not in bounds **/ +void* li_iterate(l_iterator *i); /** Updates and returns current element of iterator and increments pointer, or returns NULL if not in bounds **/ +void* li_set(l_iterator *i,int index); /** Sets current index to then updates and returns current element, or NULL if index is not in bounds **/ + + +/* Predefined Predicates */ + +L_P_FUNCTION(not_null); /** Allows all non-null elements **/ + +/* Predefined Actions */ + +L_A_FUNCTION(assert_zero); /** Call assert(0) **/ + +/* Predefined Comparators */ + +L_C_FUNCTION(int_a); /** Ascending sort for (int) type **/ + +#ifdef __cplusplus +} +#endif + +#endif /* _LIST_H */ \ No newline at end of file diff --git a/obj/list.o b/obj/list.o new file mode 100644 index 0000000..872fc3a Binary files /dev/null and b/obj/list.o differ diff --git a/obj/sorting.o b/obj/sorting.o new file mode 100644 index 0000000..5ac579b Binary files /dev/null and b/obj/sorting.o differ diff --git a/src/list.c b/src/list.c new file mode 100644 index 0000000..f8abeaf --- /dev/null +++ b/src/list.c @@ -0,0 +1,335 @@ +#include +#include +#include +#include + +#include + +#define l_block struct l_block + +void _l_quicksort(list_t *arr, int left, int right, _l_comparator comp); + +static int _mem_isnull(unsigned char* data, size_t le) +{ + unsigned char b = 0; + register int i=0; + for(;b==0&&inext; +} + +static l_block* _l_block_skip(l_block* block, int skip) +{ + l_block* c = block; + register int i=0; + for(;inext) == NULL) break; + return c; +} + +static void* _l_at(l_block* block, size_t size, int index) +{ + return (void*)(&block->data[index*size]); +} + +list_t *l_create(size_t type,int bs) +{ + list_t *list = (list_t*)malloc(sizeof(list_t)); + list->length=0; + list->blocksize = bs; + list->type = type; + list->block0 = _l_create_block(type,bs); + + return list; +} + +void l_destroy(list_t *t) +{ + l_block* next=NULL; + l_block* current = t->block0; + do + { + next = _l_next_block(current); + free(current); + current = next; + } while(next!=NULL); + free(t); +} + +void l_copy(const list_t* src,int src_offset,list_t* dest, int dest_offset,int len) +{ + register int i=0; + + for(;ilength) { + void* d_ptr = l_get(dest, dest_offset+i); + memcpy(d_ptr, s_ptr, src->type); + } else l_add(dest, s_ptr); + } +} + +void l_copy_ar(const list_t* src, int src_offset, void* dest, int len) +{ + register int i=0; + unsigned char* by = (unsigned char*) dest; + + for(;itype); + by+=src->type; + } +} + +list_t* l_create_from(void* from, int items, size_t type, int bs) +{ + list_t *l = l_create(type, bs); + register int i=0; + + for(;inext!=NULL) + { + b0 = b0->next; + } + return b0; +}*/ /** currently unused **/ + +void l_add(list_t *t,const void* o) +{ + int real_i = t->length%t->blocksize; + int block_skip = t->length/t->blocksize; + l_block *wbl; + + if(t->length>0 && ((t->length%t->blocksize)==0)) + { + l_block *prev = _l_block_skip(t->block0, block_skip-1); + wbl = prev->next = _l_create_block(t->type,t->blocksize); + } + else + wbl = _l_block_skip(t->block0, block_skip); + memcpy(_l_at(wbl, t->type, real_i), o, t->type); + t->length+=1; +} + +void l_nullify(list_t *t, int index) +{ + memset(l_get(t, index), 0, t->length); +} + +void* l_get(const list_t *t, int index) +{ + int real_i = index%t->blocksize; + int block_skip = index/t->blocksize; + l_block *wbl= _l_block_skip(t->block0, block_skip); + + return _l_at(wbl, t->type, real_i); +} + +static void* _l_ptoarray(const list_t* t,int *size, _l_predicate p) +{ + void* output0 = calloc(t->length, t->type); + void* output; + register int i=0,j=0; + + for(;ilength;i++) + { + if(p(t, i)) { + memcpy( (void*)(((unsigned char*)output0)+(j*t->type)), l_get(t, i), t->type); + j+=1; + } + } + + output = calloc(j, t->type); + memcpy(output, output0, t->type*j); + free(output0); + + if(size!=NULL) *size = j; + + return output; +} + +void* l_toarray_n(const list_t *t, int* size, _l_predicate p) +{ + if(p==NULL) + { + void* output = calloc(t->length, t->type); + register int i=0; + + for(;ilength;i++) + memcpy( (void*)(((unsigned char*)output)+(i*t->type)), l_get(t, i), t->type); + + if(size!=NULL) *size= (t->length); + return output; + } + else return _l_ptoarray(t,size,p); +} + +void l_toarray(const list_t *t, void* dest, size_t len) +{ + int real_i = len%t->blocksize; + int block_skip = len/t->blocksize; + l_block* b = t->block0; + register int i=0; + + for(;iblocksize)*t->type)), b->data, t->type*t->blocksize); + + b = b->next; + + } + + memcpy( (void*)(((unsigned char*)dest)+((block_skip*t->blocksize)*t->type)), b->data, t->type* real_i); + +} + +int l_isnull(const list_t *t, int index) +{ + void* ptr = l_get(t, index); + return _mem_isnull((unsigned char*)ptr, t->type); +} + +void l_nullify_if(list_t *t, _l_predicate f) +{ + register int i=0; + for(;ilength;i++) + if(f(t, i)) l_nullify(t, i); +} + +void l_do_if(list_t *t, _l_action act, _l_predicate f) +{ + register int i=0; + for(;ilength;i++) + if(f(t, i)) act(t, i); +} + +void l_do(list_t *t, _l_action act) +{ + register int i=0; + for(;ilength;i++) + act(t, i); +} + + +void l_swap(list_t *t, int index1, int index2) +{ + void* temp = malloc(t->type); + memcpy(temp, l_get(t, index1), t->type); + memcpy(l_get(t, index1), l_get(t,index2), t->type); + memcpy(l_get(t,index2), temp, t->type); + free(temp); +} + +void l_sort(list_t *t, _l_sort_alg algorithm, _l_comparator comp) +{ + switch(algorithm) + { + case QUICKSORT: + _l_quicksort(t, 0, t->length-1, comp); + break; + } +} + +list_t* l_clone(const list_t *t) +{ + list_t *n = l_create(t->type, t->blocksize); + l_copy(t, 0, n, 0, t->length); + return n; +} + +list_t* l_clone_if(const list_t *t , _l_predicate f) +{ + list_t *n = l_create(t->type, t->blocksize); + register int i=0; + for(;ilength;i++) + if(f(t, i)) l_add(n, l_get(t,i)); + return n; +} + +/* Iterator stuff */ + +int li_next(l_iterator *it) +{ + it->index+=1; + it->element = NULL; + return it->indexlist->length; +} + +l_iterator li_create(list_t *list) +{ + l_iterator i; + i.index = 0; + i.list = list; + i.element = NULL; + return i; +} + +void* li_set(l_iterator *i,int index) +{ + i->index = index; + return li_get(i); +} + +void* li_get(l_iterator *i) +{ + if(i->indexlist->length) { + return i->element = l_get(i->list, i->index); + } + else return i->element = NULL; +} + +void* li_iterate(l_iterator *i) +{ + if(i->indexlist->length) { + void* p = l_get(i->list, i->index); + li_next(i); + return i->element = p; + } + else return i->element = NULL; +} + +/* Predefined predicates */ + +L_P_FUNCTION(not_null) +{ + return !l_isnull(list,index); +} + +/* Predefined Actions */ + +L_A_FUNCTION(assert_zero) +{ + assert(0); +} + +/* Predefined Comparators */ + +L_C_FUNCTION(int_a) +{ + int v1 = l_get_v(list, i1, int); + int v2 = l_get_v(list, i2, int); + int comp_res = v1>v2?1:(((v1==v2)?0:-1)); + return comp_res; +} + +#undef l_block \ No newline at end of file diff --git a/src/sorting.c b/src/sorting.c new file mode 100644 index 0000000..4bf9a25 --- /dev/null +++ b/src/sorting.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include + +#include + +void _l_quicksort(list_t *arr, int left, int right, _l_comparator comp) +{ + int m = (left+right)/2; + int l = left, r = right; + while (l <= r) { + while (l_bcheck(arr, l) && (comp(arr, l, m) < 0)) l+=1; + while (l_bcheck(arr, r) && (comp(arr, r, m) > 0)) r-=1; + if (l <= r) { + l_swap(arr, l, r); + l+=1; r-=1; + } + } + if (r > left) _l_quicksort(arr, left, r, comp); + if (l < right) _l_quicksort(arr, l, right, comp); +} \ No newline at end of file diff --git a/src/test/main.c b/src/test/main.c new file mode 100644 index 0000000..ac19838 --- /dev/null +++ b/src/test/main.c @@ -0,0 +1,99 @@ +#include +#include + +#include + +void p_show(list_t *list); +void p_show_sorted(const list_t *list); + +int main() +{ + list_t *list; + int size=100; + int i; + l_iterator iter; + + /* Create list for type "int" of default blocksize */ + list = l_create_d(sizeof(int)); + + /* Add numbers */ + for(i=0;i.element */ + printf("%d ", *(int*)iter.element ); + } + printf("\r\n"); + + p_show(list); + + printf("\r\n"); + + /* Free all memory allocated */ + l_destroy(list); + + return 0; +} +/* Create function "lp_is_even" with params (list_t*)list, (int)index for predicate */ +L_P_FUNCTION(is_even) +{ + return *(int*)l_get(list,index)%2==0; +} + +L_P_FUNCTION(is_ten) +{ + return l_get_v(list,index,int)%10==0; +} + +/* Create function "la_print" with params (list_t*)list, (int)index for action */ +L_A_FUNCTION(print) +{ + printf("%d ",*(int*)l_get(list,index)); +} + +void p_show_sorted(const list_t *list) +{ + /* Create copy of list to sort */ + list_t* sorted = l_clone(list); + + /* Sort using default int ascending comparator & quicksort algorithm */ + l_sort(sorted, QUICKSORT, &lc_int_a); + + /* Print values */ + l_do(sorted, &la_print); + + printf("\r\n"); + + /* Destroy copy of list */ + l_destroy(sorted); +} + +void p_show(list_t *list) +{ + int* newdata; + int newsize; + register int i=0; + + /* Copy all elements that satisfy lp_is_even into new array */ + newdata = (int*)l_toarray_n(list, &newsize, &lp_is_even); + + for(;i