├── .doxygen ├── .gitignore ├── Makefile ├── README.md ├── TODO.md ├── UNLICENSE ├── doc ├── doc.pdf └── examples │ ├── Makefile │ ├── README.md │ ├── dict0.c │ ├── dict1.c │ ├── g_assert0.c │ ├── g_assert1.c │ ├── graph0.c │ ├── map0.c │ ├── map1.c │ ├── pqueue0.c │ ├── pqueue1.c │ ├── pqueue2.c │ ├── queue0.c │ ├── queue1.c │ ├── queue2.c │ ├── queue3.c │ ├── rbtree0.c │ ├── rbtree1.c │ ├── rbtree2.c │ ├── rbtree3.c │ ├── rbtree4.c │ ├── stack0.c │ ├── stack1.c │ ├── trie0.c │ ├── trie1.c │ ├── vector0.c │ ├── vector1.c │ ├── vector2.c │ └── vector3.c ├── include └── generics │ ├── dict.h │ ├── gerror.h │ ├── graph.h │ ├── map.h │ ├── priority_queue.h │ ├── queue.h │ ├── red_black_tree.h │ ├── stack.h │ ├── trie.h │ └── vector.h └── src ├── dict.c ├── gerror.c ├── graph.c ├── map.c ├── priority_queue.c ├── queue.c ├── red_black_tree.c ├── stack.c ├── trie.c └── vector.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Libraries 15 | *.lib 16 | *.a 17 | *.la 18 | *.lo 19 | 20 | # Shared objects (inc. Windows DLLs) 21 | *.dll 22 | *.so 23 | *.so.* 24 | *.dylib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | *.i*86 31 | *.x86_64 32 | *.hex 33 | 34 | # Debug files 35 | *.dSYM/ 36 | *.su 37 | 38 | # object path 39 | bin/ 40 | build/ 41 | .ycm_extra_conf.py* 42 | 43 | #doxygen 44 | doc/doxygen 45 | *~ 46 | *.swp 47 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # --VARIABLES---------------------------------------------- 2 | # gcc 3 | GCC=gcc 4 | GCC_FLAGS=-ansi -Wall -Wextra -O3 5 | 6 | # paths and files 7 | BUILD_PATH=build 8 | LIB_PATH=$(BUILD_PATH)/lib 9 | INCLUDE=include/generics 10 | SRC_PATH=src 11 | SRC=$(wildcard $(SRC_PATH)/*.c) 12 | HEADER=$(wildcard $(INCLUDE)/*.h) 13 | 14 | LIB_STATIC_PATH=$(LIB_PATH)/static 15 | LIB_SHARED_PATH=$(LIB_PATH)/shared 16 | STATIC_OBJECT=$(patsubst $(SRC_PATH)/%.c,$(LIB_STATIC_PATH)/%.o,$(SRC)) 17 | SHARED_OBJECT=$(patsubst $(SRC_PATH)/%.c,$(LIB_SHARED_PATH)/%.o,$(SRC)) 18 | 19 | # libs 20 | LIB_STATIC=$(LIB_STATIC_PATH)/libgenerics.a 21 | LIB_SHARED=$(LIB_SHARED_PATH)/libgenerics.so 22 | 23 | # installation 24 | LIB_STATIC_INSTALL=/usr/lib/libgenerics.a 25 | LIB_SHARED_INSTALL=/usr/lib/libgenerics.so 26 | HEADER_INSTALL=/usr/include 27 | 28 | # example 29 | EXAMPLE_PATH=doc/examples 30 | EXAMPLE=$(wildcard $(EXAMPLE_PATH)/*.c) 31 | 32 | # --RULES-DEFINITION--------------------------------------- 33 | # objects (*.o) rule 34 | define static_object_rule 35 | $(1): $(patsubst $(LIB_STATIC_PATH)/%.o,$(SRC_PATH)/%.c,$(1)) $(patsubst $(LIB_STATIC_PATH)/%.o,$(INCLUDE)/%.h,$(1)) 36 | @mkdir -p $(LIB_STATIC_PATH) 37 | $(GCC) $(GCC_FLAGS) -c -o $(1) $(patsubst $(LIB_STATIC_PATH)/%.o,$(SRC_PATH)/%.c,$(1)) -I $(INCLUDE) 38 | endef 39 | 40 | define shared_object_rule 41 | $(1): $(patsubst $(LIB_SHARED_PATH)/%.o,$(SRC_PATH)/%.c,$(1)) $(patsubst $(LIB_SHARED_PATH)/%.o,$(INCLUDE)/%.h,$(1)) 42 | @mkdir -p $(LIB_SHARED_PATH) 43 | $(GCC) $(GCC_FLAGS) -fPIC -c -o $(1) $(patsubst $(LIB_SHARED_PATH)/%.o,$(SRC_PATH)/%.c,$(1)) -I $(INCLUDE) 44 | endef 45 | 46 | # --RULES-------------------------------------------------- 47 | all: $(LIB_STATIC) $(LIB_SHARED) 48 | 49 | $(foreach obj, $(STATIC_OBJECT), $(eval $(call static_object_rule, $(obj)))) 50 | $(foreach obj, $(SHARED_OBJECT), $(eval $(call shared_object_rule, $(obj)))) 51 | 52 | $(LIB_STATIC): $(STATIC_OBJECT) 53 | ar -cvq $(LIB_STATIC) $(STATIC_OBJECT) 54 | 55 | $(LIB_SHARED): $(SHARED_OBJECT) 56 | $(GCC) -shared -Wl,-soname,libgenerics.so -o $(LIB_SHARED) $(SHARED_OBJECT) 57 | 58 | # --INSTALATION-------------------------------------------- 59 | install: $(LIB_STATIC) $(LIB_SHARED) 60 | mkdir -p $(HEADER_INSTALL) 61 | cp -vr $(HEADER) $(HEADER_INSTALL) 62 | cp $(LIB_STATIC) $(LIB_STATIC_INSTALL) 63 | cp $(LIB_SHARED) $(LIB_SHARED_INSTALL) 64 | 65 | uninstall: 66 | rm $(patsubst $(INCLUDE)/%,$(HEADER_INSTALL)/%,$(HEADER)) 67 | rmdir $(HEADER_INSTALL) 68 | rm $(LIB_STATIC_INSTALL) 69 | rm $(LIB_SHARED_INSTALL) 70 | 71 | # --EXAMPLE------------------------------------------------ 72 | examples: $(EXAMPLE) 73 | make -C $(EXAMPLE_PATH) BUILD_PATH=../../build/examples 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | libgenerics 2 | ----------- 3 | 4 | libgenerics is a minimalistic and generic library for C basic data structures. 5 | 6 | The entire implementation was aimed at providing reusable, generic and easy-to-read code like this: 7 | 8 | ```c 9 | #include 10 | #include 11 | 12 | #define N 10 13 | 14 | int main() 15 | { 16 | int i; 17 | queue_t q; 18 | queue_create(&q, sizeof(int)); 19 | 20 | for( i=0; i](http://unlicense.org/) 83 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # TODO 2 | 3 | - [ ] queue 4 | - [x] enqueue 5 | - [x] dequeue 6 | - [x] create 7 | - [x] destroy 8 | - [x] remove 9 | - [ ] head\_value 10 | - [ ] tail\_value 11 | - [ ] stack 12 | - [x] push 13 | - [x] pop 14 | - [x] create 15 | - [x] destroy 16 | - [ ] remove 17 | - [ ] top\_value 18 | - [ ] bottom\_value 19 | - [x] trie 20 | - [x] create 21 | - [x] destroy 22 | - [x] add element 23 | - [x] remove element 24 | - [x] get element 25 | - [x] set element 26 | - [x] red-black tree 27 | - [x] create 28 | - [x] destroy 29 | - [x] add element 30 | - [x] set compare_function 31 | - [x] remove element 32 | - [x] find element 33 | - [x] find max, min 34 | - [x] map 35 | - [x] create 36 | - [x] destroy 37 | - [x] insert 38 | - [x] remove 39 | - [x] at 40 | - [x] set compare function 41 | - [x] dict 42 | - [x] create 43 | - [x] destroy 44 | - [x] insert 45 | - [x] remove 46 | - [x] at 47 | - [ ] graph 48 | - [x] create 49 | - [x] destroy 50 | - [x] add edge by index 51 | - [ ] add edge by labels 52 | - [x] add label 53 | - [x] set label 54 | - [ ] add vertex 55 | - [ ] remove edge 56 | - [ ] remove vertex 57 | - [ ] algorithms 58 | - [ ] depth first search 59 | - [ ] breadth first search 60 | - [ ] euclidean path 61 | - [ ] dijkstra algorithm 62 | - [x] vector 63 | - [x] create 64 | - [x] destroy 65 | - [x] resize 66 | - [x] add 67 | - [x] at 68 | - [x] set_elem_at 69 | - [x] priority queue 70 | - [x] create 71 | - [x] destroy 72 | - [x] add 73 | - [x] extract 74 | - [x] max\_priority 75 | -------------------------------------------------------------------------------- /UNLICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /doc/doc.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yudi-matsuzake/libgenerics/e957ce809c0788c1ee53a5eb19bc2f7a07dd59b0/doc/doc.pdf -------------------------------------------------------------------------------- /doc/examples/Makefile: -------------------------------------------------------------------------------- 1 | # --VARIABLES---------------------------------------------- 2 | # gcc 3 | GCC=gcc 4 | GCC_FLAGS=-Wall -Wextra -O3 -I../../include 5 | 6 | # paths and files 7 | BUILD_PATH=build/example 8 | EXAMPLE_PATH=. 9 | EXAMPLE=$(wildcard $(EXAMPLE_PATH)/*.c) 10 | STATIC_LIB=../../build/lib/static/libgenerics.a 11 | 12 | 13 | # --RULES-DEFINITION--------------------------------------- 14 | define build_example 15 | $(patsubst $(EXAMPLE_PATH)/%.c,$(BUILD_PATH)/%.out,$(1)): $(1) ${STATIC_LIB} 16 | @mkdir -p $(BUILD_PATH) 17 | $(GCC) $(GCC_FLAGS) -o $(patsubst $(EXAMPLE_PATH)/%.c,$(BUILD_PATH)/%.out,$(1)) $(1) ${STATIC_LIB} 18 | endef 19 | 20 | # --RULES-------------------------------------------------- 21 | all: $(patsubst $(EXAMPLE_PATH)/%.c,$(BUILD_PATH)/%.out,$(EXAMPLE)) 22 | 23 | $(foreach ex, $(EXAMPLE), $(eval $(call build_example, $(ex)))) 24 | -------------------------------------------------------------------------------- /doc/examples/README.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | > Everybody loves examples 4 | 5 | **queue0.c** simple example of simple use of the queue\_t struct and your functions: 6 | 7 | **queue1.c** example of using multiple queues and multiples types, including a example with a struc; 8 | 9 | **queue2.c** example of useful uses of queue\_remove; 10 | 11 | **queue3.c** error handling for queue; 12 | 13 | **stack0.c** simple example of pop and push; 14 | 15 | **stack1.c** example with pop and push with null values and null member\_size 16 | 17 | **graph0.c** simple example of graph and a print function; 18 | 19 | **trie0.c** simple example of using the trie structure; 20 | 21 | **trie1.c** simple example of using the trie structure, remove function and a lexicographic print; 22 | 23 | **vector0.c** simple example of using the vector structure; 24 | 25 | **vector1.c** simple example of using the vector structure and resize buffer; 26 | 27 | **pqueue0.c** simple example of using priority queue structure; 28 | 29 | **pqueue1.c** simple example of using priority queue structure and using a custom compare function; 30 | 31 | **pqueue1.c** simple example of using priority queue structure and using a custom function compare string; 32 | 33 | **rbtree0.c** simple example of using rbtree and the add function; there is an in-order print example function; 34 | 35 | **rbtree1.c** simple example of using rbtree and add/remove functions; 36 | 37 | **rbtree2.c** example using rbtree function with a custom compare function; 38 | 39 | **rbtree3.c** example using rbtree with manually creation; It's useful for debug purpose; 40 | 41 | **rbtree4.c** example using rbtree changing the internal flags; 42 | 43 | **g_assert0.c** example using g_assert for debuging errors and receive a more descriptive error message; 44 | 45 | **g_assert1.c** example using g_assert for debuging errors and receive a more descriptive error message; 46 | 47 | **map0.c** simple example of using map; 48 | 49 | **map1.c** example of using map with a custom compare function. 50 | 51 | **dict0.c** simple example of dict_t usage; 52 | 53 | **dict0.c** simple example of dict_t usage; 54 | 55 | **dict1.c** example of dict_t usage with case insensitive; 56 | -------------------------------------------------------------------------------- /doc/examples/dict0.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "generics/dict.h" 3 | 4 | int main() 5 | { 6 | 7 | dict_t d; 8 | dict_create(&d, sizeof(long), G_DICT_CASE_SENSITIVE); 9 | 10 | long i; 11 | i = rand(); 12 | printf("barbara -> %ld\n", i); 13 | dict_insert(&d, "barbara", &i); 14 | 15 | i = rand(); 16 | printf("boris -> %ld\n", i); 17 | dict_insert(&d, "boris", &i); 18 | 19 | i = rand(); 20 | printf("linux -> %ld\n", i); 21 | dict_insert(&d, "linux", &i); 22 | 23 | dict_at(&d, "barbara", &i); 24 | printf("barbara = %ld\n", i); 25 | 26 | dict_at(&d, "boris", &i); 27 | printf("boris = %ld\n", i); 28 | 29 | dict_at(&d, "linux", &i); 30 | printf("linux = %ld\n", i); 31 | 32 | dict_destroy(&d); 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /doc/examples/dict1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | 7 | dict_t d; 8 | dict_create(&d, sizeof(long), G_DICT_CASE_INSENSITIVE); 9 | 10 | long i; 11 | i = rand(); 12 | printf("barbara -> %ld\n", i); 13 | dict_insert(&d, "barbara", &i); 14 | 15 | i = rand(); 16 | printf("Barbara -> %ld\n", i); 17 | dict_insert(&d, "Barbara", &i); 18 | 19 | i = rand(); 20 | printf("BoriS -> %ld\n", i); 21 | dict_insert(&d, "BoriS", &i); 22 | 23 | i = rand(); 24 | printf("boris -> %ld\n", i); 25 | dict_insert(&d, "boris", &i); 26 | 27 | i = rand(); 28 | printf("linux -> %ld\n", i); 29 | dict_insert(&d, "linux", &i); 30 | 31 | i = rand(); 32 | printf("LINUX -> %ld\n", i); 33 | dict_insert(&d, "LINUX", &i); 34 | 35 | dict_at(&d, "barbara", &i); 36 | printf("barbara = %ld\n", i); 37 | 38 | dict_at(&d, "boris", &i); 39 | printf("boris = %ld\n", i); 40 | 41 | dict_at(&d, "linux", &i); 42 | printf("linux = %ld\n", i); 43 | 44 | dict_destroy(&d); 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /doc/examples/g_assert0.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | 7 | vector_t v; 8 | g_assert(vector_create(&v, 0, sizeof(int))); 9 | 10 | int n; 11 | g_assert(vector_at(&v, 666, &n)); 12 | 13 | g_assert(vector_destroy(&v)); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /doc/examples/g_assert1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | 7 | g_assert(queue_create(NULL, 1)); 8 | 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /doc/examples/graph0.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define N 4 5 | 6 | void printf_graph(graph_t* g) 7 | { 8 | 9 | size_t i; 10 | 11 | for(i=0; iV; i++) 12 | { 13 | int label; 14 | graph_get_label_at(g, i, &label); 15 | 16 | printf("[%d]->", label); 17 | qnode_t* j; 18 | 19 | for(j=g->adj[i].head; j!=NULL; j = j->next){ 20 | int adj_index = *(int*)j->data; 21 | graph_get_label_at(g, adj_index, &label); 22 | 23 | printf("%d%s", label, (j->next)?", ":""); 24 | } 25 | printf("\n"); 26 | } 27 | 28 | } 29 | 30 | int main() 31 | { 32 | 33 | graph_t g; 34 | graph_create(&g, N, sizeof(int)); 35 | 36 | graph_add_edge(&g, 0, 1); 37 | graph_add_edge(&g, 2, 1); 38 | graph_add_edge(&g, 3, 0); 39 | graph_add_edge(&g, 3, 1); 40 | graph_add_edge(&g, 3, 2); 41 | 42 | int i; 43 | for(i=1; i<=N; i++) 44 | graph_set_label_at(&g, i-1, &i); 45 | 46 | printf_graph(&g); 47 | 48 | graph_destroy(&g); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /doc/examples/map0.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define N 10 6 | 7 | void swap(long* a, long* b) 8 | { 9 | long cup = *a; 10 | *a = *b; 11 | *b = cup; 12 | } 13 | 14 | void randomize(long r[N]) 15 | { 16 | long i; 17 | for(i = 0; i %ld\n", r[i], i); 37 | map_insert(&m, &r[i], &i); 38 | } 39 | 40 | randomize(r); 41 | for(i=0; i %ld\n", r[i], i); 43 | map_insert(&m, &r[i], &i); 44 | } 45 | 46 | randomize(r); 47 | for(i = 0; i ", r[i]); 57 | if(map_at(&m, &r[i], &e) == GERROR_OK) 58 | printf("%ld\n", e); 59 | else 60 | printf("removed\n"); 61 | } 62 | 63 | map_destroy(&m); 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /doc/examples/map1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define UNUSED(X) ((void)X) 6 | 7 | double dzrand() 8 | { 9 | return (double) rand() / (double) RAND_MAX; 10 | } 11 | 12 | double drand() 13 | { 14 | return ((double) rand() / (double) RAND_MAX) 15 | *(double) rand(); 16 | } 17 | 18 | int compare_string_function(void* a, void* b, void* arg) 19 | { 20 | UNUSED(arg); 21 | 22 | char* a_str = *(char**)a; 23 | char* b_str = *(char**)b; 24 | 25 | int r = strcmp(a_str, b_str); 26 | rbcomp_t result; 27 | 28 | if(r < 0) 29 | result = G_RB_FIRST_IS_SMALLER; 30 | else if(r == 0) 31 | result = G_RB_EQUAL; 32 | else 33 | result = G_RB_FIRST_IS_GREATER; 34 | 35 | return result; 36 | } 37 | 38 | int main() 39 | { 40 | 41 | map_t m; 42 | map_create(&m, sizeof(char*), sizeof(double)); 43 | map_set_compare_function(&m, compare_string_function, NULL); 44 | 45 | char* keys[] = { "hi", "bye", "barbara", "boris" }; 46 | size_t keys_len = sizeof(keys)/sizeof(char*); 47 | 48 | size_t i; 49 | for(i = 0; i %lf\n", keys[i], d); 53 | } 54 | 55 | for(i = 0; i %lf\n", keys[i], d); 59 | } 60 | 61 | map_destroy(&m); 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /doc/examples/pqueue0.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define N 15 7 | 8 | void print(pqueue_t* p) 9 | { 10 | size_t i; 11 | printf("(tam: %lu)", p->size); 12 | for ( i = 0; isize ; i++ ){ 13 | int temp; 14 | vector_at(&p->queue, i, &temp); 15 | printf("[%d]", temp); 16 | } 17 | printf("\n"); 18 | } 19 | 20 | int main() 21 | { 22 | srand(time(NULL)); 23 | pqueue_t p; 24 | pqueue_create(&p, sizeof(int)); 25 | 26 | int i; 27 | for ( i = 0; i 2 | #include 3 | #include 4 | #include 5 | 6 | #define N 10 7 | 8 | double drand(){ 9 | return (double)(rand()%N) + ((double)rand())/(double)RAND_MAX; 10 | } 11 | 12 | int double_compare(void* a, void* b, void* arg) 13 | { 14 | (void)arg; 15 | double double_a = *(double*)a; 16 | double double_b = *(double*)b; 17 | 18 | if( double_a > double_b ) return G_PQUEUE_FIRST_PRIORITY; 19 | else if( double_a < double_b ) return G_PQUEUE_SECOND_PRIORITY; 20 | else return G_PQUEUE_EQUAL_PRIORITY; 21 | } 22 | 23 | int main() 24 | { 25 | srand(time(NULL)); 26 | pqueue_t p; 27 | pqueue_create(&p, sizeof(double)); 28 | pqueue_set_compare_function(&p, double_compare, NULL); 29 | 30 | int i; 31 | for ( i = 0; i 2 | #include 3 | #include 4 | 5 | int priority_string(void* a, void* b, void* arg) 6 | { 7 | (void)arg; 8 | char* str_a = *(char**)a; 9 | char* str_b = *(char**)b; 10 | 11 | int res = strcmp(str_a, str_b); 12 | if(res == 0) 13 | return G_PQUEUE_EQUAL_PRIORITY; 14 | else if(res < 0) 15 | return G_PQUEUE_FIRST_PRIORITY; 16 | else 17 | return G_PQUEUE_SECOND_PRIORITY; 18 | 19 | } 20 | 21 | int main() 22 | { 23 | 24 | char* str[] = { "yudi", "barbara", "boris", "raul", "tiago", "tutu", "pedrita"}; 25 | size_t len = sizeof(str)/sizeof(char*); 26 | 27 | priority_queue_t p; 28 | 29 | pqueue_create(&p, sizeof(char*)); 30 | pqueue_set_compare_function(&p, priority_string, NULL); 31 | 32 | size_t i; 33 | for ( i = 0; i 2 | #include 3 | #include 4 | #include 5 | 6 | #define N 10 7 | 8 | int main() 9 | { 10 | srand(time(NULL)); 11 | 12 | int i; 13 | queue_t q; 14 | queue_create(&q, sizeof(int)); 15 | 16 | for( i=0; i 2 | #include 3 | #include 4 | #include 5 | 6 | #define N 10 7 | 8 | typedef struct cord{ 9 | int x, y; 10 | }cord; 11 | 12 | int main() 13 | { 14 | srand(time(NULL)); 15 | 16 | int i; 17 | queue_t q, d, c; 18 | queue_create(&q, sizeof(int)); 19 | queue_create(&d, sizeof(double)); 20 | queue_create(&c, sizeof(struct cord)); 21 | 22 | for( i=0; i 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | srand(time(NULL)); 9 | 10 | int i; 11 | queue_t q; 12 | queue_create(&q, sizeof(int)); 13 | 14 | i = 1; 15 | queue_enqueue(&q, &i); 16 | i = 2; 17 | queue_enqueue(&q, &i); 18 | i = 3; 19 | queue_enqueue(&q, &i); 20 | i = 4; 21 | queue_enqueue(&q, &i); 22 | 23 | int n; 24 | if(queue_remove(&q, q.head->next, &n) == GERROR_OK) 25 | printf("removed %d\n", n); 26 | if(queue_remove(&q, q.head, &n) == GERROR_OK) 27 | printf("removed %d\n", n); 28 | if(queue_remove(&q, q.tail, &n) == GERROR_OK) 29 | printf("removed %d\n", n); 30 | if(queue_remove(&q, q.head, &n) == GERROR_OK) 31 | printf("removed %d\n", n); 32 | 33 | queue_destroy(&q); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /doc/examples/queue3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define N 10 7 | 8 | int main() 9 | { 10 | srand(time(NULL)); 11 | 12 | int i; 13 | queue_t q; 14 | queue_create(&q, sizeof(int)); 15 | 16 | for( i=0; i 2 | #include 3 | #include 4 | 5 | #define N 10 6 | 7 | void print_rbt (rbnode_t* node, int t) 8 | { 9 | if(node != NULL){ 10 | int i; 11 | for( i = 0; idata), (node->color == G_RB_BLACK)?"black":"red"); 15 | 16 | print_rbt(node->left, t+1); 17 | print_rbt(node->right, t+1); 18 | }else{ 19 | int i; 20 | for( i = 0; icolor == G_RB_BLACK; 32 | n += im_black; 33 | 34 | if(!is_a_valid_rbtree(node->left, n, count)) 35 | return 0; 36 | 37 | if(!is_a_valid_rbtree(node->right, n, count)) 38 | return 0; 39 | 40 | return 1; 41 | } 42 | 43 | n++; 44 | if(*count == 0){ 45 | *count = n; 46 | } 47 | 48 | return n == *count; 49 | } 50 | 51 | void swap(int* a, int* b) 52 | { 53 | int cup = *a; 54 | *a = *b; 55 | *b = cup; 56 | } 57 | 58 | int main() 59 | { 60 | 61 | srand(time(NULL)); 62 | 63 | rbtree_t rbt; 64 | 65 | rbtree_create(&rbt, sizeof(int)); 66 | 67 | int i; 68 | 69 | /* 70 | * insert 71 | */ 72 | int to_insert[N]; 73 | for( i = 0; icolor == G_RB_RED)? 98 | "red":"black"); 99 | if(node->parent) printf("father: %d\n", *(int*)node->parent->data); 100 | else printf("father: null\n"); 101 | }else{ 102 | printf("%s\n", gerror_to_str(g)); 103 | } 104 | 105 | printf("min value: "); 106 | if(( g = rbtree_min_value(&rbt, &n) ) == GERROR_OK) 107 | printf("%d\n", n); 108 | else 109 | printf("%s\n", gerror_to_str(g)); 110 | 111 | printf("max value: "); 112 | if(( g = rbtree_max_value(&rbt, &n) ) == GERROR_OK) 113 | printf("%d\n", n); 114 | else 115 | printf("%s\n", gerror_to_str(g)); 116 | 117 | /* 118 | * verify tree 119 | */ 120 | n = 0; 121 | printf("It %s a valid red-black tree\n", (is_a_valid_rbtree(rbt.root, 0, &n))?"is":"is not"); 122 | 123 | rbtree_destroy( &rbt ); 124 | 125 | return 0; 126 | } 127 | -------------------------------------------------------------------------------- /doc/examples/rbtree1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define N 10 6 | 7 | void print_rbt (rbnode_t* node, int t) 8 | { 9 | if(node != NULL){ 10 | int i; 11 | for( i = 0; idata), (node->color == G_RB_BLACK)?"black":"red"); 15 | 16 | print_rbt(node->left, t+1); 17 | print_rbt(node->right, t+1); 18 | }else{ 19 | int i; 20 | for( i = 0; icolor == G_RB_BLACK; 32 | n += im_black; 33 | 34 | if(!is_a_valid_rbtree(node->left, n, count)) 35 | return 0; 36 | 37 | if(!is_a_valid_rbtree(node->right, n, count)) 38 | return 0; 39 | 40 | return 1; 41 | } 42 | 43 | n++; 44 | if(*count == 0){ 45 | *count = n; 46 | } 47 | 48 | return n == *count; 49 | } 50 | 51 | void find_int(rbtree_t* rbt, int elem) 52 | { 53 | rbnode_t* node; 54 | gerror_t g = rbtree_find_node(rbt, &elem, &node); 55 | 56 | if(g == GERROR_OK){ 57 | printf("%d found in node addr [%p]\n", elem, node); 58 | printf("color: %s\n", (node->color == G_RB_RED)? 59 | "red":"black"); 60 | if(node->parent) printf("father: %d\n", *(int*)node->parent->data); 61 | else printf("father: null\n"); 62 | }else{ 63 | printf("%s\n", gerror_to_str(g)); 64 | } 65 | } 66 | 67 | void swap(int* a, int* b) 68 | { 69 | int cup = *a; 70 | *a = *b; 71 | *b = cup; 72 | } 73 | 74 | void inicialize(int* v, int n) 75 | { 76 | int i; 77 | for( i = 0; iroot, 0, &n)){ 103 | printf("It is a valid red-black tree\n"); 104 | } 105 | else{ 106 | printf("It is not a valid red-black tree\n"); 107 | exit(EXIT_FAILURE); 108 | } 109 | } 110 | 111 | int main() 112 | { 113 | 114 | srand(time(NULL)); 115 | 116 | rbtree_t rbt; 117 | rbtree_create(&rbt, sizeof(int)); 118 | int i; 119 | 120 | /* 121 | * insert 122 | */ 123 | int to_insert[N]; 124 | 125 | inicialize(to_insert, N); 126 | randomize(to_insert, N); 127 | vprint(to_insert, N); 128 | 129 | for( i = 0; i 2 | #include 3 | #include 4 | 5 | #define N 10 6 | #define UNUSED(X) ((void)X) 7 | 8 | 9 | void print_rbt (rbnode_t* node, int t) 10 | { 11 | if(node != NULL){ 12 | int i; 13 | for( i = 0; idata), (node->color == G_RB_BLACK)?"black":"red"); 17 | 18 | print_rbt(node->left, t+1); 19 | print_rbt(node->right, t+1); 20 | }else{ 21 | int i; 22 | for( i = 0; icolor == G_RB_BLACK; 34 | n += im_black; 35 | 36 | if(!is_a_valid_rbtree(node->left, n, count)) 37 | return 0; 38 | 39 | if(!is_a_valid_rbtree(node->right, n, count)) 40 | return 0; 41 | 42 | return 1; 43 | } 44 | 45 | n++; 46 | if(*count == 0){ 47 | *count = n; 48 | } 49 | 50 | return n == *count; 51 | } 52 | 53 | 54 | void swap(char** a, char** b) 55 | { 56 | char* cup = *a; 57 | *a = *b; 58 | *b = cup; 59 | } 60 | 61 | void inicialize(int* v, int n) 62 | { 63 | int i; 64 | for( i = 0; iroot, 0, &n)){ 90 | printf("It is a valid red-black tree\n"); 91 | } 92 | else{ 93 | printf("It is not a valid red-black tree\n"); 94 | exit(EXIT_FAILURE); 95 | } 96 | } 97 | 98 | int compare_string_function(void* a, void* b, void* arg) 99 | { 100 | UNUSED(arg); 101 | 102 | char* a_str = *(char**)a; 103 | char* b_str = *(char**)b; 104 | 105 | int r = strcmp(a_str, b_str); 106 | rbcomp_t result; 107 | 108 | if(r < 0) 109 | result = G_RB_FIRST_IS_SMALLER; 110 | else if(r == 0) 111 | result = G_RB_EQUAL; 112 | else 113 | result = G_RB_FIRST_IS_GREATER; 114 | 115 | return result; 116 | } 117 | 118 | 119 | int main() 120 | { 121 | 122 | srand(time(NULL)); 123 | 124 | rbtree_t rbt; 125 | rbtree_create(&rbt, sizeof(char*)); 126 | rbtree_set_compare_function(&rbt, compare_string_function, NULL); 127 | 128 | int i; 129 | 130 | /* 131 | * insert 132 | */ 133 | char* to_insert[N] = { 134 | "yudi", 135 | "boris", 136 | "barbara", 137 | "pedrita", 138 | "brazil", 139 | "english", 140 | "wilson", 141 | "root", 142 | "linux", 143 | "zoeira" 144 | }; 145 | 146 | randomize(to_insert, N); 147 | vprint(to_insert, N); 148 | 149 | for( i = 0; i 2 | #include 3 | 4 | void print_rbt (rbnode_t* node, int t) 5 | { 6 | if(node != NULL){ 7 | int i; 8 | for( i = 0; idata), (node->color == G_RB_BLACK)?"black":"red"); 12 | 13 | print_rbt(node->left, t+1); 14 | print_rbt(node->right, t+1); 15 | }else{ 16 | int i; 17 | for( i = 0; icolor = c; 29 | node->parent = NULL; 30 | node->data = (void*) malloc(sizeof(int)); 31 | memcpy(node->data, &v, sizeof(int)); 32 | 33 | if(l){ 34 | l->parent = node; 35 | node->left = l; 36 | } 37 | 38 | if(r){ 39 | r->parent = node; 40 | node->right = r; 41 | } 42 | 43 | return node; 44 | } 45 | 46 | int main() 47 | { 48 | 49 | rbtree_t rbt; 50 | rbtree_create(&rbt, sizeof(int)); 51 | 52 | rbt.root = create_node(4, G_RB_BLACK, 53 | create_node(1, G_RB_RED, 54 | create_node(0, G_RB_BLACK, 55 | NULL, 56 | NULL), 57 | create_node(2, G_RB_BLACK, 58 | NULL, 59 | create_node(3, G_RB_RED, 60 | NULL, 61 | NULL))), 62 | create_node(7, G_RB_RED, 63 | create_node(6, G_RB_BLACK, 64 | NULL, 65 | NULL), 66 | create_node(9, G_RB_BLACK, 67 | create_node(8, G_RB_RED, 68 | NULL, 69 | NULL), 70 | NULL))); 71 | 72 | rbt.size = 9; 73 | 74 | print_rbt(rbt.root, 0); 75 | 76 | int n = 6; 77 | 78 | gerror_t g = rbtree_remove_item(&rbt, &n); 79 | 80 | printf("%s\n", gerror_to_str(g)); 81 | 82 | print_rbt(rbt.root, 0); 83 | 84 | rbtree_destroy(&rbt); 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /doc/examples/rbtree4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define N 10 6 | 7 | void print_rbt (rbnode_t* node, int t) 8 | { 9 | if(node != NULL){ 10 | int i; 11 | for( i = 0; idata), (node->color == G_RB_BLACK)?"black":"red"); 15 | 16 | print_rbt(node->left, t+1); 17 | print_rbt(node->right, t+1); 18 | }else{ 19 | int i; 20 | for( i = 0; i 2 | #include 3 | #include 4 | #include 5 | 6 | #define N 10 7 | 8 | int main() 9 | { 10 | srand(time(NULL)); 11 | stack_t s; 12 | stack_create(&s, sizeof(int)); 13 | 14 | int i; 15 | 16 | for(i=0; i 2 | #include 3 | #include 4 | #include 5 | 6 | #define N 10 7 | 8 | int main() 9 | { 10 | srand(time(NULL)); 11 | stack_t s; 12 | stack_create(&s, 0); 13 | 14 | printf("push\n"); 15 | stack_push(&s, NULL); 16 | 17 | while( (stack_pop(&s, NULL) == GERROR_OK) ){ 18 | printf("pop\n"); 19 | 20 | if( rand()%10 < 6 ) { 21 | printf("push\n"); 22 | stack_push(&s, NULL); 23 | } 24 | } 25 | 26 | stack_destroy(&s); 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /doc/examples/trie0.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | trie_t t; 8 | trie_create(&t, sizeof(int)); 9 | 10 | char* nome = "yudi"; 11 | int i = 50; 12 | trie_add_element(&t, nome, strlen(nome), &i); 13 | 14 | nome = "bárbara"; 15 | i = 100; 16 | trie_add_element(&t, nome, strlen(nome), &i); 17 | 18 | nome = "raul"; 19 | i = 10; 20 | trie_add_element(&t, nome, strlen(nome), &i); 21 | 22 | nome = "tutu"; 23 | i = 1; 24 | trie_add_element(&t, nome, strlen(nome), &i); 25 | 26 | nome = "boris"; 27 | i = 100000; 28 | trie_add_element(&t, nome, strlen(nome), &i); 29 | 30 | nome = "yudi"; 31 | trie_get_element(&t, nome, strlen(nome), &i); 32 | printf("[%s] = %d\n", nome, i); 33 | 34 | nome = "bárbara"; 35 | trie_get_element(&t, nome, strlen(nome), &i); 36 | printf("[%s] = %d\n", nome, i); 37 | 38 | nome = "raul"; 39 | trie_get_element(&t, nome, strlen(nome), &i); 40 | printf("[%s] = %d\n", nome, i); 41 | 42 | nome = "tutu"; 43 | trie_get_element(&t, nome, strlen(nome), &i); 44 | printf("[%s] = %d\n", nome, i); 45 | 46 | nome = "boris"; 47 | trie_get_element(&t, nome, strlen(nome), &i); 48 | printf("[%s] = %d\n", nome, i); 49 | 50 | trie_destroy(&t); 51 | } 52 | -------------------------------------------------------------------------------- /doc/examples/trie1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void print_lexicography_node(struct tnode_t *node, struct queue_t* q) 7 | { 8 | if(node && q){ 9 | 10 | if(node->value){ 11 | 12 | struct qnode_t* qnode; 13 | printf("["); 14 | for(qnode=q->head; qnode!=NULL; qnode=qnode->next){ 15 | printf("%c", *(char*)qnode->data); 16 | } 17 | printf("]"); 18 | printf(" -> %d\n", *(int*)node->value); 19 | } 20 | 21 | int i; 22 | for ( i = 0; ichildren[i], q); 26 | queue_remove(q, q->tail, NULL); 27 | } 28 | 29 | } 30 | } 31 | 32 | void print_lexicography(struct trie_t* t) 33 | { 34 | queue_t q; 35 | queue_create(&q, sizeof(char)); 36 | print_lexicography_node(&t->root, &q); 37 | queue_destroy(&q); 38 | } 39 | 40 | int main() 41 | { 42 | trie_t t; 43 | trie_create(&t, sizeof(int)); 44 | 45 | char* nome = "yudi"; 46 | int i = 50; 47 | trie_add_element(&t, nome, strlen(nome), &i); 48 | 49 | nome = ""; 50 | i = -1; 51 | trie_add_element(&t, nome, strlen(nome), &i); 52 | 53 | nome = "barbara"; 54 | i = 100; 55 | trie_add_element(&t, nome, strlen(nome), &i); 56 | 57 | nome = "raul"; 58 | i = 10; 59 | trie_add_element(&t, nome, strlen(nome), &i); 60 | 61 | nome = "tutu"; 62 | i = 1; 63 | trie_add_element(&t, nome, strlen(nome), &i); 64 | 65 | nome = "boris"; 66 | i = 100000; 67 | trie_add_element(&t, nome, strlen(nome), &i); 68 | 69 | print_lexicography(&t); 70 | printf("remove: %s\n", nome); 71 | trie_remove_element(&t, nome, strlen(nome)); 72 | print_lexicography(&t); 73 | 74 | trie_destroy(&t); 75 | 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /doc/examples/vector0.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define N 50 5 | 6 | int main() 7 | { 8 | 9 | vector_t v; 10 | 11 | vector_create(&v, 0, sizeof(int)); 12 | 13 | int i; 14 | for ( i = 0; i 2 | #include 3 | 4 | #define N 20 5 | 6 | void print_v(vector_t* v){ 7 | size_t i; 8 | printf("v(%.2zu)-> ", v->buffer_size/v->member_size); 9 | 10 | for(i=0; isize; i++){ 11 | int tmp = ((int*)v->data)[i]; 12 | printf( "[%.2d]", tmp); 13 | } 14 | 15 | printf("\n"); 16 | } 17 | 18 | int main() 19 | { 20 | 21 | vector_t v; 22 | 23 | vector_create(&v, N, sizeof(int)); 24 | 25 | int i; 26 | for(i=0; i 2 | #include 3 | 4 | #define N 50 5 | 6 | int main() 7 | { 8 | 9 | vector_t v; 10 | size_t new_buf_siz = 32; 11 | printf("Set the min_buf_siz from %lu to %lu\n", 12 | vector_get_min_buf_siz(), new_buf_siz); 13 | vector_set_min_buf_siz(new_buf_siz); 14 | 15 | vector_create(&v, 0, sizeof(int)); 16 | 17 | int i; 18 | for ( i = 0; i 2 | #include 3 | 4 | int main() 5 | { 6 | 7 | vector_t buffer; 8 | gerror_t result; 9 | if((result = vector_create(&buffer, 0, sizeof(char))) != GERROR_OK){ 10 | fprintf(stderr, "Cannot create vector\n"); 11 | fprintf(stderr, "Error: %s\n", gerror_to_str(result)); 12 | return 1; 13 | } 14 | 15 | char buffer_temp[BUFSIZ]; 16 | size_t n_data; 17 | 18 | while( (n_data = fread(buffer_temp, sizeof(char), BUFSIZ, stdin)) ) 19 | vector_append_buffer(&buffer, buffer_temp, n_data); 20 | 21 | vector_append( &buffer, &buffer ); 22 | 23 | fprintf(stdout, "output duplicated (%lu bytes):\n", buffer.size); 24 | fwrite(buffer.data, buffer.member_size, buffer.size, stdout); 25 | 26 | vector_destroy( &buffer ); 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /include/generics/dict.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * For more information, please refer to 18 | */ 19 | 20 | #ifndef __DICT_H__ 21 | #define __DICT_H__ 22 | 23 | #include 24 | #include 25 | 26 | #include "gerror.h" 27 | #include "vector.h" 28 | #include "map.h" 29 | 30 | typedef struct dict_t { 31 | size_t member_size; 32 | map_t map; 33 | 34 | int (*strcomprfunction)(const char*, const char*); 35 | } dict_t; 36 | 37 | typedef enum dict_flags_t { 38 | G_DICT_CASE_SENSITIVE = 0, 39 | G_DICT_CASE_INSENSITIVE = 1 40 | } dict_flags_t; 41 | 42 | gerror_t dict_create(struct dict_t* d, size_t member_size, int flags); 43 | gerror_t dict_destroy(struct dict_t* d); 44 | gerror_t dict_insert(struct dict_t* d, const char* key, void* elem); 45 | gerror_t dict_remove(struct dict_t* d, const char* key, void* elem); 46 | gerror_t dict_at(struct dict_t* d, const char* key, void* elem); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /include/generics/gerror.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * For more information, please refer to 18 | */ 19 | #ifndef __GERROR_H__ 20 | #define __GERROR_H__ 21 | #include 22 | #include 23 | 24 | typedef enum gerror_t{ 25 | GERROR_OK, 26 | GERROR_NULL_STRUCTURE, 27 | GERROR_NULL_HEAD, 28 | GERROR_NULL_NODE, 29 | GERROR_NULL_POINTER_TO_BUFFER, 30 | GERROR_TRY_REMOVE_EMPTY_STRUCTURE, 31 | GERROR_TRY_ADD_EDGE_NO_VERTEX, 32 | GERROR_ACCESS_OUT_OF_BOUND, 33 | GERROR_INCOMPATIBLE_VECTOR_APPEND_SIZE, 34 | GERROR_NULL_RETURN_POINTER, 35 | GERROR_EMPTY_STRUCTURE, 36 | GERROR_NULL_ELEMENT_POINTER, 37 | GERROR_REMOVE_ELEMENT_NOT_FOUNDED, 38 | GERROR_ELEMENT_NOT_FOUNDED, 39 | GERROR_NULL_KEY, 40 | GERROR_COMPARE_FUNCTION_WRONG_RETURN, 41 | GERROR_N_ERROR 42 | } gerror_t; 43 | 44 | char* gerror_to_str (gerror_t g); 45 | 46 | void gerror_abort_message ( 47 | gerror_t g, 48 | const char* call, 49 | const char* file, 50 | int line_number); 51 | 52 | #define _g_assert(X, F, LINE) \ 53 | { \ 54 | gerror_t __gerror__; \ 55 | if((__gerror__ = X) != GERROR_OK){ \ 56 | gerror_abort_message( \ 57 | __gerror__, \ 58 | #X, \ 59 | F, \ 60 | LINE); \ 61 | } \ 62 | } 63 | 64 | #define g_assert(X) _g_assert(X, __FILE__, __LINE__) 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /include/generics/graph.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * For more information, please refer to 18 | */ 19 | #ifndef __GRAPH_T_H__ 20 | #define __GRAPH_T_H__ 21 | #include 22 | #include "gerror.h" 23 | #include "queue.h" 24 | 25 | /** Graph structure and elements. 26 | */ 27 | typedef struct graph_t{ 28 | size_t V; 29 | size_t E; 30 | size_t member_size; 31 | struct queue_t* adj; 32 | void* label; 33 | }graph_t; 34 | 35 | gerror_t graph_create(graph_t* g, size_t size, size_t member_size); 36 | gerror_t graph_add_edge(graph_t* g, size_t from, size_t to); 37 | gerror_t graph_get_label_at(graph_t* g, size_t index, void* label); 38 | gerror_t graph_set_label_at(graph_t* g, size_t index, void* label); 39 | gerror_t graph_destroy(graph_t* g); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /include/generics/map.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * For more information, please refer to 18 | */ 19 | 20 | #ifndef __MAP_H__ 21 | #define __MAP_H__ 22 | 23 | #include "red_black_tree.h" 24 | #include "gerror.h" 25 | 26 | typedef struct map_t { 27 | size_t key_size; 28 | size_t member_size; 29 | 30 | redblacktree_t map; 31 | } map_t; 32 | 33 | gerror_t map_create(struct map_t* m, size_t key_size, size_t member_size); 34 | gerror_t map_destroy(struct map_t* m); 35 | gerror_t map_insert(struct map_t* m, void* key, void* elem); 36 | gerror_t map_remove(struct map_t* m, void* key, void* elem); 37 | gerror_t map_at(struct map_t* m, void* key, void* elem); 38 | gerror_t map_get_pair( 39 | struct map_t* m, 40 | void* key, 41 | void* rkey, 42 | void* relem); 43 | 44 | gerror_t map_set_compare_function( 45 | struct map_t* m, 46 | rbtree_compare_function compare_function, 47 | void* arg); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /include/generics/priority_queue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * For more information, please refer to 18 | */ 19 | 20 | #ifndef __PRIORITY_QUEUE_T_H__ 21 | #define __PRIORITY_QUEUE_T_H__ 22 | #include 23 | #include "gerror.h" 24 | #include "vector.h" 25 | 26 | typedef enum{ 27 | G_PQUEUE_FIRST_PRIORITY = -1, /* a > b */ 28 | G_PQUEUE_EQUAL_PRIORITY, /* a == b */ 29 | G_PQUEUE_SECOND_PRIORITY /* a < b */ 30 | }queue_priority_t; 31 | 32 | typedef int (*pqueue_compare_function)(void* a, void* b, void* arg); 33 | 34 | typedef struct priority_queue_t{ 35 | size_t size; 36 | size_t member_size; 37 | 38 | pqueue_compare_function compare; 39 | void* compare_argument; 40 | struct vector_t queue; 41 | } priority_queue_t; 42 | 43 | typedef struct priority_queue_t pqueue_t; 44 | 45 | gerror_t pqueue_create(pqueue_t* p, size_t member_size); 46 | gerror_t pqueue_destroy(pqueue_t* p); 47 | gerror_t pqueue_set_compare_function(pqueue_t* p, pqueue_compare_function function, void* argument); 48 | gerror_t pqueue_add(pqueue_t* p, void* e); 49 | gerror_t pqueue_max_priority(pqueue_t* p, void* e); 50 | gerror_t pqueue_extract(pqueue_t* p, void* e); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /include/generics/queue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * For more information, please refer to 18 | */ 19 | #ifndef __QUEUE_T_H__ 20 | #define __QUEUE_T_H__ 21 | #include 22 | #include 23 | #include "gerror.h" 24 | 25 | /** queue node. 26 | * 27 | */ 28 | typedef struct qnode_t{ 29 | struct qnode_t* next; 30 | struct qnode_t* prev; 31 | 32 | void* data; 33 | }qnode_t; 34 | 35 | /** Represents a queue structure. 36 | */ 37 | typedef struct queue_t{ 38 | size_t size; 39 | size_t member_size; 40 | struct qnode_t* head; 41 | struct qnode_t* tail; 42 | }queue_t; 43 | 44 | gerror_t queue_create(struct queue_t* q, size_t member_size); 45 | gerror_t queue_enqueue(struct queue_t* q, void* e); 46 | gerror_t queue_dequeue(struct queue_t* q, void* e); 47 | gerror_t queue_destroy(struct queue_t* q); 48 | gerror_t queue_remove(struct queue_t* q, struct qnode_t* node, void* e); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /include/generics/red_black_tree.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * For more information, please refer to 18 | */ 19 | #ifndef __RED_BLACK_TREE_H__ 20 | #define __RED_BLACK_TREE_H__ 21 | 22 | #include 23 | #include 24 | #include "gerror.h" 25 | 26 | /** 27 | * return of the redblacktree compare function 28 | * of type rbtree_compare_function 29 | */ 30 | typedef enum { 31 | G_RB_FIRST_IS_SMALLER = -1, 32 | G_RB_EQUAL, 33 | G_RB_FIRST_IS_GREATER 34 | } rbcomp_t; 35 | 36 | /** Flags for rbtree. 37 | */ 38 | typedef enum { 39 | /** rbtree left leaning, if this flag is not on, 40 | * the rbtree will be right leaning 41 | */ 42 | G_RB_LEFT_LEANING = 1, 43 | 44 | /** if this flag is set, when a node is equal, 45 | * the value will be override and the tree will not leaning 46 | * if this flag is set 47 | */ 48 | G_RB_EQUAL_OVERRIDE = 1<<1 49 | } rbflag_t; 50 | 51 | typedef int (*rbtree_compare_function)(void* a, void *b, void* arg); 52 | 53 | typedef enum { 54 | G_RB_RED, 55 | G_RB_BLACK, 56 | G_RB_DOUBLE_BLACK, 57 | } rbcolor_t; 58 | 59 | typedef struct redblacknode_t { 60 | struct redblacknode_t* left; 61 | struct redblacknode_t* right; 62 | struct redblacknode_t* parent; 63 | 64 | rbcolor_t color; 65 | void* data; 66 | } redblacknode_t; 67 | 68 | typedef struct redblacktree_t { 69 | size_t size; 70 | size_t member_size; 71 | 72 | rbtree_compare_function compare; 73 | void* compare_argument; 74 | long flags; 75 | struct redblacknode_t* root; 76 | } redblacktree_t; 77 | 78 | typedef struct redblacktree_t rbtree_t; 79 | typedef struct redblacknode_t rbnode_t; 80 | 81 | gerror_t rbtree_create(rbtree_t* rbt, size_t member_size); 82 | gerror_t rbtree_destroy(rbtree_t* rbt); 83 | 84 | gerror_t rbtree_set_compare_function( rbtree_t* rbt, 85 | rbtree_compare_function function, 86 | void* argument); 87 | gerror_t rbtree_add(rbtree_t* rbt, void* elem); 88 | gerror_t rbtree_remove_item(rbtree_t* rbt, void* elem); 89 | gerror_t rbtree_remove_node(rbtree_t* rbt, rbnode_t* node); 90 | 91 | gerror_t rbtree_set_flags(rbtree_t* rbt, long flags); 92 | 93 | gerror_t rbtree_min_node(rbtree_t* rbt, rbnode_t** node); 94 | gerror_t rbtree_min_value(rbtree_t* rbt, void* elem); 95 | gerror_t rbtree_max_node(rbtree_t* rbt, rbnode_t** node); 96 | gerror_t rbtree_max_value(rbtree_t* rbt, void* elem); 97 | gerror_t rbtree_find_node(rbtree_t* rbt, void* elem, rbnode_t** node); 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /include/generics/stack.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * For more information, please refer to 18 | */ 19 | #ifndef __STACK_T_H__ 20 | #define __STACK_T_H__ 21 | #include 22 | #include 23 | #include "gerror.h" 24 | 25 | /** node of a stack 26 | */ 27 | typedef struct snode_t{ 28 | struct snode_t* next; 29 | struct snode_t* prev; 30 | 31 | void* data; 32 | }snode_t; 33 | 34 | /** represents the stack structure. 35 | */ 36 | typedef struct stack_t{ 37 | size_t size; 38 | size_t member_size; 39 | struct snode_t* head; 40 | }stack_t; 41 | 42 | gerror_t stack_create(struct stack_t* q, size_t member_size); 43 | gerror_t stack_push(struct stack_t* q, void* e); 44 | gerror_t stack_pop(struct stack_t* q, void* e); 45 | gerror_t stack_destroy(struct stack_t* q); 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /include/generics/trie.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * For more information, please refer to 18 | */ 19 | #ifndef __TRIE_H__ 20 | #define __TRIE_H__ 21 | #include 22 | #include 23 | #include 24 | 25 | #include "gerror.h" 26 | 27 | #define NBYTE (0x100) 28 | 29 | /** node of a trie_t element. 30 | */ 31 | typedef struct tnode_t { 32 | void* value; 33 | struct tnode_t* children[NBYTE]; 34 | } tnode_t; 35 | 36 | /** Represents the trie structure. 37 | */ 38 | typedef struct trie_t { 39 | size_t size; 40 | size_t member_size; 41 | struct tnode_t root; 42 | } trie_t; 43 | 44 | gerror_t trie_create(struct trie_t* t, size_t member_size); 45 | gerror_t trie_destroy(struct trie_t* t); 46 | gerror_t trie_add_element(struct trie_t* t, void* string, size_t size, void* elem); 47 | gerror_t trie_remove_element(struct trie_t* t, void* string, size_t size); 48 | gerror_t trie_get_element(struct trie_t* t, void* string, size_t size, void* elem); 49 | gerror_t trie_set_element(struct trie_t* t, void* string, size_t size, void* elem); 50 | tnode_t* trie_get_node_or_allocate ( struct trie_t* t, void* string, size_t size); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /include/generics/vector.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * For more information, please refer to 18 | */ 19 | #ifndef __VECTOR_T_H__ 20 | #define __VECTOR_T_H__ 21 | #include 22 | #include 23 | #include 24 | 25 | #include "gerror.h" 26 | 27 | typedef struct vector_t { 28 | void* data; 29 | size_t size; 30 | size_t buffer_size; 31 | size_t member_size; 32 | } vector_t; 33 | 34 | gerror_t vector_create (vector_t* v, size_t initial_size, size_t member_size); 35 | gerror_t vector_destroy (vector_t* v); 36 | gerror_t vector_resize_buffer (vector_t* v, size_t new_size); 37 | gerror_t vector_at (vector_t* v, size_t index, void* elem); 38 | gerror_t vector_append (vector_t* v0, vector_t* v1); 39 | gerror_t vector_append_buffer (vector_t* v, void* buffer, size_t size); 40 | void* vector_ptr_at (vector_t* v, size_t index); 41 | gerror_t vector_set_elem_at (vector_t* v, size_t index, void* elem); 42 | gerror_t vector_add (vector_t* v, void* elem); 43 | void vector_set_min_buf_siz(size_t new_min_buf_size); 44 | size_t vector_get_min_buf_siz(void); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/dict.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * For more information, please refer to 18 | */ 19 | 20 | #include "dict.h" 21 | 22 | #define UNUSED(X) ((void)X) 23 | 24 | int compare_string_function(void* a, void* b, void* arg); 25 | void dict_free_node(redblacknode_t* node); 26 | 27 | /** Creates a dict and populates the structure `d`. 28 | * TODO: A more datailed description of dict_create. 29 | * 30 | * @param d previous allocated `dict_t` structure 31 | * @param member_size size of the member 32 | * 33 | * @see map_create 34 | * @see map_set_compare_function 35 | * 36 | * @return GERROR_OK in case of success; 37 | * GERROR_NULL_STRUCTURE in case the structure `d` 38 | * is pointed to null 39 | */ 40 | gerror_t dict_create (struct dict_t* d, size_t member_size, int flags) 41 | { 42 | if(!d) return GERROR_NULL_STRUCTURE; 43 | 44 | d->member_size = member_size; 45 | map_create(&d->map, sizeof(char*), d->member_size); 46 | 47 | if(flags & G_DICT_CASE_INSENSITIVE) 48 | d->strcomprfunction = strcasecmp; 49 | else 50 | d->strcomprfunction = strcmp; 51 | 52 | map_set_compare_function( 53 | &d->map, 54 | compare_string_function, 55 | d->strcomprfunction); 56 | 57 | return GERROR_OK; 58 | } 59 | 60 | /** Deallocates and cleanup the `dict_t` structure. 61 | * TODO: A more datailed description of dict_destroy. 62 | * 63 | * @param d TODO 64 | * 65 | * @see map_destroy 66 | * 67 | * @return GERROR_OK in case of success; 68 | * GERROR_NULL_STRUCTURE in case the structure `d` 69 | * is pointed to null 70 | */ 71 | gerror_t dict_destroy (struct dict_t* d) 72 | { 73 | if(!d) return GERROR_NULL_STRUCTURE; 74 | 75 | struct redblacknode_t* node = d->map.map.root; 76 | 77 | dict_free_node(node); 78 | 79 | return map_destroy(&d->map); 80 | } 81 | 82 | /** Inserts the element `elem` and mapped it with `key` in `d`. 83 | * TODO: A more datailed description of dict_insert. 84 | * 85 | * @param d previous allocated `dict_t` structure 86 | * @param key the string with '\0' terminator to map `elem` 87 | * @param elem the element to be mapped 88 | * 89 | * @see map_insert 90 | * 91 | * @return GERROR_OK in case of success; 92 | * GERROR_NULL_STRUCTURE in case the structure `d` 93 | * is pointed to null 94 | */ 95 | gerror_t dict_insert (struct dict_t* d, const char* key, void* elem) 96 | { 97 | if(!d) return GERROR_NULL_STRUCTURE; 98 | if(!key) return GERROR_NULL_KEY; 99 | 100 | size_t keylen = strlen(key); 101 | size_t alloc_key_siz = keylen+1; 102 | char* alloc_key = (char*) malloc(sizeof(char)*alloc_key_siz); 103 | 104 | strncpy(alloc_key, key, alloc_key_siz); 105 | return map_insert(&d->map, &alloc_key, elem); 106 | } 107 | 108 | /** Removes the elem mapped by `key` and write in the memory location 109 | * pointed by `elem` if is different of null. 110 | * TODO: A more datailed description of dict_remove. 111 | * 112 | * @param d previous allocated `dict_t` structure 113 | * @param key pointer to the key 114 | * @param elem pointer to a local in memory to write 115 | * the removed element 116 | * 117 | * @return GERROR_OK in case of success; 118 | * GERROR_NULL_STRUCTURE in case the structure `d` 119 | * GERROR_NULL_KEY in case that `key` is null 120 | */ 121 | gerror_t dict_remove (struct dict_t* d, const char* key, void* elem) 122 | { 123 | if(!d) return GERROR_NULL_STRUCTURE; 124 | if(!key) return GERROR_NULL_KEY; 125 | 126 | char* rkey; 127 | gerror_t g = map_get_pair(&d->map, &key, &rkey, elem); 128 | 129 | if(g != GERROR_OK) 130 | return g; 131 | 132 | free(rkey); 133 | 134 | return GERROR_OK; 135 | } 136 | 137 | /** Find the element pointed by `key` and writes in the memory location 138 | * pointed by `elem`. 139 | * TODO: A more datailed description of dict_at. 140 | * 141 | * @param d previous allocated `dict_t` structure 142 | * @param key pointer to the key 143 | * @param elem pointer to a local in memory to write the returning element 144 | * 145 | * @see map_at 146 | * 147 | * @return GERROR_OK in case of success; 148 | * GERROR_NULL_STRUCTURE in case the structure `d` 149 | * GERROR_NULL_KEY in case that `key` is null 150 | */ 151 | gerror_t dict_at (struct dict_t* d, const char* key, void* elem) 152 | { 153 | if(!d) return GERROR_NULL_STRUCTURE; 154 | if(!key) return GERROR_NULL_KEY; 155 | 156 | return map_at(&d->map, &key, elem); 157 | } 158 | 159 | 160 | /* 161 | * recursively frees the node data `node` 162 | */ 163 | void dict_free_node(redblacknode_t* node) 164 | { 165 | if(node != NULL){ 166 | dict_free_node(node->left); 167 | dict_free_node(node->right); 168 | char* str; 169 | 170 | memcpy(&str, node->data, sizeof(char*)); 171 | 172 | if(str) 173 | free(str); 174 | } 175 | } 176 | 177 | /* 178 | * compare function dict 179 | */ 180 | int compare_string_function(void* a, void* b, void* arg) 181 | { 182 | 183 | int (*strcompare)(const char*, const char*) = arg; 184 | 185 | char* a_str = *(char**)a; 186 | char* b_str = *(char**)b; 187 | 188 | int r = strcompare(a_str, b_str); 189 | rbcomp_t result; 190 | 191 | if(r < 0) 192 | result = G_RB_FIRST_IS_SMALLER; 193 | else if(r == 0) 194 | result = G_RB_EQUAL; 195 | else 196 | result = G_RB_FIRST_IS_GREATER; 197 | 198 | return result; 199 | } 200 | -------------------------------------------------------------------------------- /src/gerror.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * For more information, please refer to 18 | */ 19 | #include "gerror.h" 20 | 21 | char* gerror_to_string[GERROR_N_ERROR] = { 22 | "Success", 23 | "Null pointer to structure", 24 | "Null pointer to the head of structure", 25 | "Null pointer to the node", 26 | "Null pointer to the buffer", 27 | "Attempt to remove an element but the structure is empty", 28 | "Attempt to add a edge with inexistent vertex", 29 | "Attempt to access a position out of the container or buffer", 30 | "Attempt to append two vectors with different member_size" 31 | "Null pointer passed to write the return data", 32 | "Attempt to pass a empty structure", 33 | "Attempt to operate a function with a prohibitive null pointer element", 34 | "Attempt to remove an element that is not in the structure", 35 | "The pointer to the key cannot be null", 36 | "Compare function return an unknown value", 37 | "Element not found" 38 | }; 39 | 40 | char* gerror_to_str (gerror_t g) 41 | { 42 | if( g < GERROR_N_ERROR ) 43 | return gerror_to_string[g]; 44 | 45 | return NULL; 46 | } 47 | 48 | void gerror_abort_message( 49 | gerror_t g, 50 | const char* call, 51 | const char* file, 52 | int line_number) 53 | { 54 | fprintf(stderr, "\ng_assert error in %s:%d\n" 55 | "%s: %s\n", 56 | file, 57 | line_number, 58 | call, 59 | gerror_to_str(g)); 60 | 61 | exit(EXIT_FAILURE); 62 | } 63 | -------------------------------------------------------------------------------- /src/graph.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * For more information, please refer to 18 | */ 19 | #include "graph.h" 20 | 21 | /** Creates a graph and populates the previous 22 | * allocated structure pointed by `g`; 23 | * 24 | * @param g pointer to a graph structure; 25 | * @param member_size size of the elements that will be 26 | * indexed by `g` 27 | * @return GERROR_OK in case of success operation; 28 | * GERROR_NULL_STRUCURE in case `g` is a NULL 29 | */ 30 | gerror_t graph_create(graph_t* g, size_t size, size_t member_size) 31 | { 32 | if(!g) return GERROR_NULL_STRUCTURE; 33 | g->V = size; 34 | g->E = 0; 35 | g->member_size = member_size; 36 | 37 | g->adj = (queue_t*) malloc(sizeof(queue_t)*size); 38 | size_t i; 39 | for(i=0; iadj[i], sizeof(int)); 41 | 42 | if( g->member_size ){ 43 | g->label = malloc(g->member_size*size); 44 | memset(g->label, 0, size*g->member_size); 45 | }else{ 46 | g->label = NULL; 47 | } 48 | 49 | return GERROR_OK; 50 | } 51 | 52 | /** Adds an edge on the graph `g` from the vertex `from` 53 | * to the vertex `to`. Where `from` and `to` are indexes 54 | * of these vertex. 55 | * 56 | * @param g pointer to a graph structure; 57 | * @param from index of the first vertex; 58 | * @param to index of the incident vertex. 59 | * 60 | * @return GERROR_OK in case of success operation; 61 | * GERROR_TRY_ADD_EDGE_NO_VERTEX in case that 62 | * `from` or `to` not exists in the graph 63 | * 64 | */ 65 | gerror_t graph_add_edge(graph_t* g, size_t from, size_t to) 66 | { 67 | if(!g) return GERROR_NULL_STRUCTURE; 68 | if(from > g->V || to > g->V) return GERROR_TRY_ADD_EDGE_NO_VERTEX; 69 | queue_enqueue(&g->adj[from], &to); 70 | g->E++; 71 | 72 | return GERROR_OK; 73 | } 74 | 75 | /** Gets the label of the vertex in the `index` position 76 | * of the graph `g`. 77 | * 78 | * @param g pointer to a graph structure; 79 | * @param index index of the vertex; 80 | * @param label pointer to the memory allocated that 81 | * will be write with the label in `index` 82 | * 83 | * @return GERROR_OK in case of success operation; 84 | * GERROR_NULL_STRUCURE in case `g` is a NULL 85 | * 86 | */ 87 | gerror_t graph_get_label_at(graph_t* g, size_t index, void* label) 88 | { 89 | if(!g) return GERROR_NULL_STRUCTURE; 90 | if (index >= g->V) return GERROR_ACCESS_OUT_OF_BOUND; 91 | 92 | if(g->label && g->member_size && label){ 93 | void* ptr = g->label + (index * g->member_size); 94 | memcpy(label, ptr, g->member_size); 95 | } 96 | 97 | return GERROR_OK; 98 | } 99 | 100 | /** Sets the label at the `index` to `label`. 101 | * 102 | * @param g pointer to a graph structure; 103 | * @param index index of the vertex; 104 | * @param label the new label of the vertex positioned 105 | * in `index` 106 | * @return GERROR_OK in case of success operation; 107 | * GERROR_ACCESS_OUT_OF_BOUND in case that `index` 108 | * is out of bound 109 | */ 110 | gerror_t graph_set_label_at(graph_t* g, size_t index, void* label) 111 | { 112 | if(!g) return GERROR_NULL_STRUCTURE; 113 | if(index >= g->V) return GERROR_ACCESS_OUT_OF_BOUND; 114 | 115 | if(g->member_size){ 116 | void* at = g->label + (index * g->member_size); 117 | memcpy(at, label, g->member_size); 118 | } 119 | 120 | return GERROR_OK; 121 | } 122 | 123 | /** Deallocates the structures in `g`. 124 | * This function WILL NOT deallocate the pointer `g`. 125 | * 126 | * @param g pointer to a graph structure; 127 | * 128 | * @return GERROR_OK in case of success operation; 129 | * GERROR_NULL_STRUCURE in case `g` is a NULL 130 | * 131 | */ 132 | gerror_t graph_destroy(graph_t* g) 133 | { 134 | if(!g) return GERROR_NULL_STRUCTURE; 135 | g->member_size = 0; 136 | 137 | size_t i; 138 | for(i=0; iV; i++){ 139 | queue_destroy(&g->adj[i]); 140 | } 141 | 142 | free(g->adj); 143 | if(g->label) 144 | free(g->label); 145 | g->V = g->E = 0; 146 | 147 | return GERROR_OK; 148 | } 149 | -------------------------------------------------------------------------------- /src/map.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * For more information, please refer to 18 | */ 19 | 20 | #include "map.h" 21 | 22 | /** Default compare function for map. 23 | * This functions only looks to the key. 24 | * 25 | * @see rbtree_compare_function 26 | */ 27 | int map_default_compare_function (void* a, void* b, void* arg); 28 | 29 | /** Creates a map of key size `key_size` and mapped member with size `member_size` 30 | * and populates the previous allocated structure `m`. 31 | * TODO: A more datailed description of map_create. 32 | * 33 | * @param m pointer to a previous allocated `map_t` structure; 34 | * @param key_size size of the key in bytes 35 | * @param member_size size of the members in bytes 36 | * 37 | * @see rbtree_create 38 | * 39 | * @return GERROR_OK in case of success 40 | */ 41 | gerror_t map_create (struct map_t* m, size_t key_size, size_t member_size) 42 | { 43 | if(!m) return GERROR_NULL_STRUCTURE; 44 | 45 | m->key_size = key_size; 46 | m->member_size = member_size; 47 | 48 | gerror_t g = rbtree_create(&m->map, key_size + member_size); 49 | if(g != GERROR_OK) 50 | return g; 51 | 52 | g = rbtree_set_flags(&m->map, G_RB_EQUAL_OVERRIDE); 53 | 54 | return rbtree_set_compare_function(&m->map, map_default_compare_function, m); 55 | } 56 | 57 | /** Destroys and deallocates inner attributes of `m`. 58 | * TODO: A more datailed description of map_destroy. 59 | * 60 | * @param m pointer to a previous allocated `map_t` structure; 61 | * 62 | * @see rbtree_destroy 63 | * 64 | * @return GERROR_OK in case of success 65 | */ 66 | gerror_t map_destroy (struct map_t* m) 67 | { 68 | if(!m) return GERROR_NULL_STRUCTURE; 69 | 70 | m->key_size = 0; 71 | m->member_size = 0; 72 | 73 | return rbtree_destroy(&m->map); 74 | } 75 | 76 | /** Inserts a element `elem` in the key `key` in the map `m`. 77 | * TODO: A more datailed description of map_insert. 78 | * 79 | * @param m pointer to a previous allocated `map_t` structure; 80 | * @param key pointer to the key used to map the `elem` 81 | * @param elem pointer to the element to be inserted 82 | * 83 | * @see rbtree_add 84 | * 85 | * @return GERROR_OK in case of success 86 | */ 87 | gerror_t map_insert (struct map_t* m, void* key, void* elem) 88 | { 89 | if(!m) return GERROR_NULL_STRUCTURE; 90 | if(!key) return GERROR_NULL_KEY; 91 | if(!elem) return GERROR_NULL_ELEMENT_POINTER; 92 | 93 | void* pair = (void*) malloc(m->key_size + m->member_size); 94 | memcpy(pair, key, m->key_size); 95 | memcpy(pair + m->key_size, elem, m->member_size); 96 | 97 | gerror_t g = rbtree_add(&m->map, pair); 98 | 99 | free(pair); 100 | return g; 101 | } 102 | 103 | /** Removes the element mapped by `key`. 104 | * TODO: A more datailed description of map_remove. 105 | * 106 | * @param m pointer to a previous allocated `map_t` structure; 107 | * @param key pointer to the key 108 | * @param elem pointer to a location of memory where the `elem` 109 | * will be returned 110 | * 111 | * @see rbtree_find_node 112 | * @see rbree_remove_node 113 | * 114 | * @return GERROR_OK in case of success 115 | */ 116 | gerror_t map_remove (struct map_t* m, void* key, void* elem) 117 | { 118 | if(!m) return GERROR_NULL_STRUCTURE; 119 | if(!key) return GERROR_NULL_KEY; 120 | 121 | rbnode_t* node; 122 | gerror_t g = rbtree_find_node(&m->map, key, &node); 123 | if(g != GERROR_OK) 124 | return g; 125 | 126 | if(elem) 127 | memcpy(elem, node->data + m->key_size, m->member_size); 128 | 129 | return rbtree_remove_node(&m->map, node); 130 | } 131 | 132 | /** Writes the elem mapped by `key` in the memory pointed by `elem`. 133 | * TODO: A more datailed description of map_at. 134 | * 135 | * @param m pointer to a previous allocated `map_t` structure; 136 | * @param key pointer to the key 137 | * @param elem pointer to a local in memory to write 138 | * the element at `key` 139 | * 140 | * @see 141 | * 142 | * @return GERROR_OK in case of success 143 | * GERROR_NULL_KEY in case that `key` is null 144 | */ 145 | gerror_t map_at (struct map_t* m, void* key, void* elem) 146 | { 147 | if(!m) return GERROR_NULL_STRUCTURE; 148 | if(!key) return GERROR_NULL_KEY; 149 | 150 | rbnode_t* node; 151 | 152 | gerror_t g = rbtree_find_node(&m->map, key, &node); 153 | if(g != GERROR_OK) 154 | return g; 155 | 156 | if(elem && node && node->data) 157 | memcpy(elem, node->data + m->key_size, m->member_size); 158 | 159 | return GERROR_OK; 160 | } 161 | 162 | /** Set the default compare function of `m` keys. 163 | * TODO: A more datailed description of map_set_compare_function. 164 | * 165 | * @param m pointer to a previous allocated `map_t` structure; 166 | * @param compare_function compare function to use in rbtree 167 | * @param arg argument to use in comparison function 168 | * 169 | * @see rbtree_set_compare_function 170 | * 171 | * @return GERROR_OK in case of success 172 | */ 173 | gerror_t map_set_compare_function ( 174 | struct map_t* m, 175 | rbtree_compare_function compare_function, 176 | void* arg) 177 | { 178 | if(!m) return GERROR_NULL_STRUCTURE; 179 | 180 | return rbtree_set_compare_function(&m->map, compare_function, arg); 181 | } 182 | 183 | /** Get the pair key:value and write in memory pointed by 184 | * `rkey` and `relem`. 185 | * TODO: A more datailed description of map_get_pair. 186 | * 187 | * @param m pointer to a previous allocated `map_t` structure; 188 | * @param key pointer to the key 189 | * @param rkey pointer to the memory location to write the key 190 | * @param relem pointer to the memory location to write the elem 191 | * 192 | * @return GERROR_OK in case of success 193 | * GERROR_NULL_KEY in case that `key` is null 194 | */ 195 | gerror_t map_get_pair ( 196 | struct map_t* m, 197 | void* key, 198 | void* rkey, 199 | void* relem) 200 | { 201 | if(!m) return GERROR_NULL_STRUCTURE; 202 | if(!key) return GERROR_NULL_KEY; 203 | 204 | rbnode_t* node; 205 | 206 | gerror_t g = rbtree_find_node(&m->map, key, &node); 207 | if(g != GERROR_OK) 208 | return g; 209 | 210 | if(rkey && node && node->data) 211 | memcpy(rkey, node->data, m->key_size); 212 | 213 | if(relem && node && node->data) 214 | memcpy(relem, node->data + m->key_size, m->member_size); 215 | 216 | return GERROR_OK; 217 | } 218 | 219 | /* 220 | * default compare function of map 221 | * only work for ints, only look the keys 222 | */ 223 | int map_default_compare_function (void* a, void* b, void* arg) 224 | { 225 | struct map_t* m = (struct map_t*) arg; 226 | size_t size = m->key_size; 227 | 228 | long la = 0; 229 | long lb = 0; 230 | 231 | switch(size){ 232 | case sizeof(int): 233 | la = *(int*)a; 234 | lb = *(int*)b; 235 | break; 236 | case sizeof(char): 237 | la = *(char*)a; 238 | lb = *(char*)b; 239 | break; 240 | case sizeof(long): 241 | la = *(long*)a; 242 | lb = *(long*)b; 243 | break; 244 | } 245 | return (la > lb) - (la < lb); 246 | } 247 | -------------------------------------------------------------------------------- /src/priority_queue.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * For more information, please refer to 18 | */ 19 | 20 | #include "priority_queue.h" 21 | 22 | #define PARENT(i) ((i-1)/2) 23 | #define LEFT(i) (((i+1)*2)-1) 24 | #define RIGHT(i) (LEFT(i)+1) 25 | 26 | void nswap (void* a, void* b, size_t n); 27 | int pqueue_default_compare_function(void* a, void* b, void* arg); 28 | void max_heapify(pqueue_t* p, size_t i); 29 | 30 | /** Populates the `p` structure and inicialize it. 31 | * A priority queue needs a pqueue_compare_function. The default function 32 | * will only work for char, int and long. If you need a double or float 33 | * you need to implement the compare function and set with the 34 | * function `pqueue_set_compare_function` 35 | * 36 | * @param p previous allocated pqueue_t struct 37 | * @param member_size size in bytes of the indexed elements 38 | * 39 | * @return GERROR_OK in case of success operation; 40 | * GERROR_NULL_STRUCURE in case `p` is a NULL 41 | */ 42 | gerror_t pqueue_create (pqueue_t* p, size_t member_size) 43 | { 44 | if(!p) return GERROR_NULL_STRUCTURE; 45 | p->member_size = member_size; 46 | p->compare = pqueue_default_compare_function; 47 | p->compare_argument = &p->member_size; 48 | vector_create(&p->queue, 0, member_size); 49 | return GERROR_OK; 50 | } 51 | 52 | /** Destroy (i.e. deallocates) the `p` structure fields. 53 | * TODO: A more detailed description of pqueue_destroy. 54 | * 55 | * @param p previous allocated pqueue_t struct 56 | * 57 | * @return TODO 58 | */ 59 | gerror_t pqueue_destroy (pqueue_t* p) 60 | { 61 | if(!p) return GERROR_NULL_STRUCTURE; 62 | p->size = 0; 63 | p->member_size = 0; 64 | p->compare = NULL; 65 | p->compare_argument = NULL; 66 | vector_destroy(&p->queue); 67 | return GERROR_OK; 68 | } 69 | 70 | /** Change the default comparison function of the priority queue `p` by 71 | * `function` with the argument `argument`. 72 | * 73 | * @param p previous allocated pqueue_t struct 74 | * @param function comparison function callback that has 75 | * the following prototype: 76 | * int compare(void* a, void* b) 77 | * the a and b are the arguments 78 | * returns -1 if `a` has priority BIG than `b` 79 | * returns 0 if `a` has priority EQUAL than `b` 80 | * return 1 if `a` has priority LESS than `b` 81 | * @param argument pointer to the argument to the comparison function 82 | * 83 | * @return GERROR_OK in case of success operation; 84 | * GERROR_NULL_STRUCURE in case `t` is a NULL 85 | */ 86 | gerror_t pqueue_set_compare_function (pqueue_t* p, pqueue_compare_function function, void* argument) 87 | { 88 | if(!p) return GERROR_NULL_STRUCTURE; 89 | p->compare = function; 90 | p->compare_argument = argument; 91 | return GERROR_OK; 92 | } 93 | 94 | /** Adds an element in the queue and max heap the queue. 95 | * TODO: A more datailed description of pqueue_add. 96 | * 97 | * @param p previous allocated pqueue_t struct 98 | * @param e the element to be added 99 | * 100 | * @return GERROR_OK in case of success operation; 101 | * GERROR_NULL_STRUCURE in case `t` is a NULL 102 | */ 103 | gerror_t pqueue_add (pqueue_t* p, void* e) 104 | { 105 | if(!p) return GERROR_NULL_STRUCTURE; 106 | 107 | vector_add( &p->queue, e ); 108 | p->size = p->queue.size; 109 | size_t i = p->size - 1; 110 | 111 | if(i>0){ 112 | void* child, *parent; 113 | do{ 114 | child = vector_ptr_at(&p->queue, i), 115 | parent = vector_ptr_at(&p->queue, PARENT(i)); 116 | queue_priority_t priority; 117 | priority = p->compare(child, parent, p->compare_argument); 118 | 119 | if (i>0 && priority == G_PQUEUE_FIRST_PRIORITY) 120 | nswap(child, parent, p->member_size); 121 | i = PARENT(i); 122 | }while ( i > 0 && i < p->size ); 123 | } 124 | 125 | return GERROR_OK; 126 | } 127 | 128 | /** Returns and does not remove the highest priority of the queue. 129 | * TODO: A more datailed description of pqueue_max_priority. 130 | * 131 | * @param p previous allocated pqueue_t struct 132 | * @param e pointer to previous allocated variable 133 | * with `member_size` size that will receive 134 | * a copy of the highest priority element of the queue. 135 | * 136 | * @return GERROR_OK in case of success operation; 137 | * GERROR_ACESS_OUT_OF_BOUND in case the queue is empty 138 | * GERROR_NULL_STRUCURE in case `t` is a NULL 139 | */ 140 | gerror_t pqueue_max_priority (pqueue_t* p, void* e) 141 | { 142 | if(!p) return GERROR_NULL_STRUCTURE; 143 | if(p->size == 0) return GERROR_ACCESS_OUT_OF_BOUND; 144 | vector_at( &p->queue, 0, e ); 145 | return GERROR_OK; 146 | } 147 | 148 | /** Extracts the highest priority element in the queue and 149 | * writes in `e` pointer. 150 | * 151 | * @param p previous allocated pqueue_t struct 152 | * @param e pointer to previous allocated variable 153 | * 154 | * @return GERROR_OK in case of success operation; 155 | * GERROR_ACESS_OUT_OF_BOUND in case the queue is empty 156 | * GERROR_NULL_STRUCURE in case `t` is a NULL 157 | */ 158 | gerror_t pqueue_extract (pqueue_t* p, void* e) 159 | { 160 | if(!p) return GERROR_NULL_STRUCTURE; 161 | if(p->size == 0) return GERROR_ACCESS_OUT_OF_BOUND; 162 | 163 | vector_at( &p->queue, 0, e ); 164 | void* ptr = vector_ptr_at( &p->queue, p->size-1 ); 165 | vector_set_elem_at( &p->queue, 0, ptr ); 166 | 167 | vector_resize_buffer( &p->queue, p->size-1 ); 168 | p->size = p->queue.size; 169 | 170 | max_heapify( p, 0 ); 171 | 172 | return GERROR_OK; 173 | } 174 | 175 | /* 176 | * auxiliar function to swap n bytes in 177 | * a to b 178 | */ 179 | void nswap (void* a, void* b, size_t n) 180 | { 181 | void* cup = malloc(n); 182 | memcpy(cup, a, n); 183 | memcpy(a, b, n); 184 | memcpy(b, cup, n); 185 | free(cup); 186 | } 187 | 188 | /* 189 | * the default comparison function. Just compare 190 | * like to long 191 | */ 192 | int pqueue_default_compare_function(void* a, void* b, void* arg) 193 | { 194 | size_t size = *(size_t*)arg; 195 | 196 | long la = 0; 197 | long lb = 0; 198 | 199 | switch(size){ 200 | case sizeof(int): 201 | la = *(int*)a; 202 | lb = *(int*)b; 203 | break; 204 | case sizeof(char): 205 | la = *(char*)a; 206 | lb = *(char*)b; 207 | break; 208 | case sizeof(long): 209 | la = *(long*)a; 210 | lb = *(long*)b; 211 | break; 212 | } 213 | return (la > lb) - (la < lb); 214 | } 215 | 216 | /* 217 | * classical heapify algorithm 218 | */ 219 | void max_heapify(pqueue_t* p, size_t i) 220 | { 221 | size_t left = LEFT(i); 222 | size_t right = RIGHT(i); 223 | size_t largest; 224 | 225 | void* ptr_i = vector_ptr_at(&p->queue, i); 226 | void* pleft = vector_ptr_at(&p->queue, left); 227 | void* pright = vector_ptr_at(&p->queue, right); 228 | void* plargest; 229 | 230 | if( left < p->size && 231 | p->compare(pleft, ptr_i, p->compare_argument) == G_PQUEUE_FIRST_PRIORITY ) { 232 | largest = left; 233 | plargest = pleft; 234 | }else{ 235 | largest = i; 236 | plargest = ptr_i; 237 | } 238 | 239 | if( right < p->size && 240 | p->compare(pright, plargest, p->compare_argument) == G_PQUEUE_FIRST_PRIORITY){ 241 | largest = right; 242 | plargest = pright; 243 | } 244 | 245 | if( largest != i ){ 246 | nswap(ptr_i, plargest, p->member_size); 247 | max_heapify(p, largest); 248 | } 249 | } 250 | -------------------------------------------------------------------------------- /src/queue.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * For more information, please refer to 18 | */ 19 | #include "queue.h" 20 | 21 | /** Creates a queue and populates the previous 22 | * allocated structure pointed by `q`; 23 | * 24 | * @param q pointer to a queue structure; 25 | * @param member_size size of the elements that will be 26 | * indexed by `q` 27 | * 28 | * @return GERROR_OK in case of success operation; 29 | * GERROR_NULL_STRUCURE in case `q` is a NULL 30 | * pointer 31 | */ 32 | gerror_t queue_create(struct queue_t* q, size_t member_size) 33 | { 34 | if(!q) return GERROR_NULL_STRUCTURE; 35 | 36 | q->member_size = member_size; 37 | q->size = 0; 38 | q->head = NULL; 39 | q->tail = NULL; 40 | 41 | return GERROR_OK; 42 | } 43 | 44 | /** Enqueues the element pointed by `e` in the 45 | * queue `q`. 46 | * 47 | * @param q pointer to a queue structure; 48 | * @param e pointer to the element that will be indexed 49 | * by q. 50 | * 51 | * @return GERROR_OK in case of success operation; 52 | * GERROR_NULL_STRUCURE in case `q` is a NULL 53 | * pointer 54 | * 55 | */ 56 | gerror_t queue_enqueue(struct queue_t* q, void* e) 57 | { 58 | if(!q) return GERROR_NULL_STRUCTURE; 59 | 60 | struct qnode_t* new_node = (qnode_t*) malloc(sizeof(qnode_t)); 61 | 62 | if(q->member_size) 63 | new_node->data = malloc(q->member_size); 64 | else 65 | new_node->data = NULL; 66 | 67 | new_node->next = new_node->prev = NULL; 68 | 69 | if(q->member_size && e) 70 | memcpy(new_node->data, e, q->member_size); 71 | 72 | if(q->tail){ 73 | q->tail->next = new_node; 74 | new_node->prev = q->tail; 75 | q->tail = new_node; 76 | }else{ 77 | q->head = new_node; 78 | q->tail = new_node; 79 | } 80 | 81 | q->size++; 82 | 83 | return GERROR_OK; 84 | } 85 | 86 | /** Dequeues the first element of the queue `q` 87 | * 88 | * @param q pointer to a queue structure; 89 | * @param e pointer to the previous allocated element 90 | * memory that will be write with de dequeued 91 | * element. 92 | * 93 | * @return GERROR_OK in case of success operation; 94 | * GERROR_NULL_HEAD in case that the head `q->head` 95 | * is a null pointer. 96 | * GERROR_NULL_STRUCURE in case `q` is a NULL 97 | * pointer 98 | * GERROR_TRY_REMOVE_EMPTY_STRUCTURE in case 99 | * that `q` has no element. 100 | */ 101 | gerror_t queue_dequeue(struct queue_t* q, void* e) 102 | { 103 | if(!q) return GERROR_NULL_STRUCTURE; 104 | if(!q->head) return GERROR_NULL_HEAD; 105 | if(!q->size) return GERROR_TRY_REMOVE_EMPTY_STRUCTURE; 106 | 107 | void* ptr = q->head->data; 108 | struct qnode_t* old_node = q->head; 109 | 110 | q->head = q->head->next; 111 | 112 | if( q->head ) 113 | q->head->prev = NULL; 114 | else 115 | q->tail = NULL; 116 | 117 | q->size--; 118 | free(old_node); 119 | if(q->member_size && e) 120 | memcpy(e, ptr, q->member_size); 121 | if(ptr) 122 | free(ptr); 123 | return GERROR_OK; 124 | } 125 | 126 | /** Removes the element `node` of the queue `q`. 127 | * 128 | * @param q pointer to a queue structure; 129 | * @param node element to be removed from the queue 130 | * @param e pointer to the memory that will be 131 | * write with the removed element 132 | * 133 | * @return GERROR_OK in case of success operation; 134 | * GERROR_NULL_STRUCURE in case `q` is a NULL 135 | * pointer 136 | * GERROR_NULL_NODE in case `node` is NULL; 137 | * GERROR_TRY_REMOVE_EMPTY_STRUCTURE in case 138 | * that `q` has no element. 139 | * 140 | */ 141 | gerror_t queue_remove(struct queue_t* q, struct qnode_t* node, void* e) 142 | { 143 | if(!q) return GERROR_NULL_STRUCTURE; 144 | if(!node) return GERROR_NULL_NODE; 145 | if(!q->size) return GERROR_TRY_REMOVE_EMPTY_STRUCTURE; 146 | 147 | if(node->prev) 148 | node->prev->next = node->next; 149 | else 150 | q->head = node->next; 151 | 152 | if(node->next) 153 | node->next->prev = node->prev; 154 | else 155 | q->tail = node->prev; 156 | 157 | q->size--; 158 | node->next = node->prev = NULL; 159 | void* ptr = node->data; 160 | free(node); 161 | 162 | if(q->member_size && e) 163 | memcpy(e, ptr, q->member_size); 164 | if(ptr) 165 | free(ptr); 166 | return GERROR_OK; 167 | } 168 | 169 | /** Deallocate the nodes of the queue q. 170 | * This function WILL NOT deallocate the pointer q. 171 | * 172 | * @param q pointer to a queue structure; 173 | * 174 | * @return GERROR_OK in case of success operation; 175 | * GERROR_NULL_STRUCURE in case `q` is a NULL 176 | * pointer 177 | */ 178 | gerror_t queue_destroy(struct queue_t* q) 179 | { 180 | if(!q) return GERROR_NULL_STRUCTURE; 181 | 182 | struct qnode_t* i, *j; 183 | 184 | for( i=q->head; i!=NULL; i=j ){ 185 | j = i->next; 186 | if(i->data) 187 | free(i->data); 188 | free(i); 189 | } 190 | 191 | return GERROR_OK; 192 | } 193 | -------------------------------------------------------------------------------- /src/red_black_tree.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * For more information, please refer to 18 | */ 19 | 20 | #include "red_black_tree.h" 21 | 22 | typedef enum{ 23 | RB_LEFT, 24 | RB_RIGHT 25 | } rbc_t ; 26 | 27 | rbnode_t* rbnode_destroy(rbnode_t* node); 28 | 29 | /* 30 | * auxiliar function prototypes to insert 31 | */ 32 | static void rbtree_insert_fixup(rbtree_t* rbt, rbnode_t* node); 33 | static void fix_insert_case(rbtree_t* rbt, rbnode_t** node, rbnode_t* uncle, int c, int l); 34 | static rbnode_t* create_node(rbtree_t* rbt, void* elem); 35 | static void left_rotate(rbtree_t* rbt, rbnode_t* node); 36 | static void right_rotate(rbtree_t* rbt, rbnode_t* node); 37 | 38 | /* 39 | * auxiliar function prototypes to delete 40 | */ 41 | void rbtree_transplant(rbtree_t* rbt, rbnode_t* u, rbnode_t* v); 42 | void rbtree_delete_fixup(rbtree_t* rbt, rbnode_t* node); 43 | int rbtree_identify_case(rbnode_t* node, rbc_t* side); 44 | rbnode_t* rbtree_create_double_black(); 45 | rbnode_t* rbtree_find_minimal_node(rbnode_t* node); 46 | void rbtree_remove_double_black(rbtree_t* rbt, rbnode_t* db); 47 | int rbnode_is_red(rbnode_t* node); 48 | int rbnode_is_black(rbnode_t* node); 49 | 50 | 51 | /* 52 | * default compare function prototype 53 | */ 54 | int rbtree_default_compare_function(void* a, void* b, void* arg); 55 | 56 | /** Populates the `rbt` structure and inicialize it. 57 | * A red n black tree needs a rbtree_compare_function. The default function 58 | * will only work for char, int and long. If you need a double or float 59 | * you need to implement the compare function and set with the 60 | * function `rbtree_set_compare_function` 61 | * 62 | * @param rbt previous allocated rbtree_t struct 63 | * @param member_size size in bytes of the indexed elements 64 | * 65 | * @return GERROR_OK in case of success operation; 66 | * GERROR_NULL_STRUCURE in case `rbt` is a NULL 67 | */ 68 | gerror_t rbtree_create(rbtree_t* rbt, size_t member_size) 69 | { 70 | if(!rbt) return GERROR_NULL_STRUCTURE; 71 | 72 | rbt->member_size = member_size; 73 | rbt->size = 0; 74 | rbt->compare = rbtree_default_compare_function; 75 | rbt->compare_argument = &(rbt->member_size); 76 | rbt->root = NULL; 77 | 78 | rbt->flags = G_RB_LEFT_LEANING; 79 | 80 | return GERROR_OK; 81 | } 82 | 83 | 84 | /** Destroy (i.e. deallocates) the `rbt` structure fields. 85 | * 86 | * @param p previous allocated pqueue_t struct 87 | * 88 | * @return GERROR_OK in case of success operation; 89 | * GERROR_NULL_STRUCURE in case `rbt` is a NULL 90 | */ 91 | gerror_t rbtree_destroy (rbtree_t* rbt) 92 | { 93 | if(!rbt) return GERROR_NULL_STRUCTURE; 94 | 95 | rbt->member_size = 0; 96 | rbt->compare = NULL; 97 | rbt->compare_argument = NULL; 98 | rbt->size = 0; 99 | rbt->root = rbnode_destroy(rbt->root); 100 | 101 | return GERROR_OK; 102 | } 103 | 104 | 105 | /** Change the default comparison function of the red n black tree `rbt` 106 | * for `function` with the argument `argument`. 107 | * 108 | * @param rbt pointer to a previous allocated `rbtree_t` structure 109 | * @param function comparison function callback that has 110 | * the following prototype: 111 | * int compare(void* a, void* b) 112 | * the a and b are the arguments 113 | * returns -1 if `a` is smaller than b 114 | * returns 0 if `a` is equal than `b` 115 | * return 1 if `a` is bigger than `b` 116 | * @param argument pointer to the argument to the comparison function 117 | * 118 | * @see rbcomp_t 119 | * 120 | * @return GERROR_OK in case of success operation; 121 | * GERROR_NULL_STRUCURE in case `t` is a NULL 122 | */ 123 | gerror_t rbtree_set_compare_function( 124 | rbtree_t* rbt, 125 | rbtree_compare_function function, 126 | void* argument) 127 | { 128 | if(!rbt) return GERROR_NULL_STRUCTURE; 129 | 130 | rbt->compare = function; 131 | rbt->compare_argument = argument; 132 | 133 | return GERROR_OK; 134 | } 135 | 136 | /** Add an element pointed by `elem` with size `rbt->member_size` 137 | * in the rbtree. 138 | * 139 | * @param rbt previous allocated rbtree_t structure 140 | * @param elem pointer to the elem to be copied to the structure 141 | * 142 | * @return GERROR_OK in case of sucess operation; 143 | * GERROR_NULL_STRUCTURE in case `rbt` is null 144 | */ 145 | gerror_t rbtree_add(rbtree_t* rbt, void* elem) 146 | { 147 | if(!rbt) return GERROR_NULL_STRUCTURE; 148 | 149 | /* 150 | * find the node parent of `elem` 151 | */ 152 | rbnode_t* parent_node = NULL; 153 | rbnode_t* node = rbt->root; 154 | rbc_t c = RB_LEFT; 155 | 156 | while( node != NULL ){ 157 | parent_node = node; 158 | 159 | rbcomp_t result = rbt->compare(elem, node->data, rbt->compare_argument); 160 | 161 | switch(result){ 162 | case G_RB_FIRST_IS_GREATER: 163 | node = node->right; 164 | c = RB_RIGHT; 165 | break; 166 | case G_RB_FIRST_IS_SMALLER: 167 | node = node->left; 168 | c = RB_LEFT; 169 | break; 170 | case G_RB_EQUAL: 171 | if(rbt->flags & G_RB_EQUAL_OVERRIDE){ 172 | if(elem) 173 | memcpy(node->data, elem, rbt->member_size); 174 | return GERROR_OK; 175 | }else if(rbt->flags & G_RB_LEFT_LEANING){ 176 | node = node->left; 177 | c = RB_LEFT; 178 | }else{ 179 | node = node->right; 180 | c = RB_RIGHT; 181 | } 182 | break; 183 | default: 184 | return GERROR_COMPARE_FUNCTION_WRONG_RETURN; 185 | } 186 | 187 | } 188 | 189 | /* 190 | * insert the node 191 | */ 192 | node = create_node(rbt, elem); 193 | 194 | if(parent_node == NULL) 195 | rbt->root = node; 196 | else if(c == RB_LEFT) 197 | parent_node->left = node; 198 | else 199 | parent_node->right = node; 200 | 201 | node->parent = parent_node; 202 | 203 | /* 204 | * fixup 205 | */ 206 | rbtree_insert_fixup(rbt, node); 207 | 208 | rbt->size++; 209 | 210 | return GERROR_OK; 211 | } 212 | 213 | /** Finds and remove the first element that match with `elem`. 214 | * 215 | * @param rbt previous allocated rbtree_t structure 216 | * @param elem pointer element to be removed 217 | * 218 | * @return GERROR_OK in case of sucess operation; 219 | * GERROR_NULL_STRUCTURE in case `rbt` is null; 220 | * GERROR_NULL_ELEMENT_POINTER in case `elem` is 221 | * pointing to null; 222 | * GERROR_TRY_REMOVE_EMPTY_STRUCTURE in case the 223 | * `rbt` structure is empty 224 | * 225 | */ 226 | gerror_t rbtree_remove_item (rbtree_t* rbt, void* elem) 227 | { 228 | if(!rbt) return GERROR_NULL_STRUCTURE; 229 | if(!elem) return GERROR_NULL_ELEMENT_POINTER; 230 | if(!rbt->size) return GERROR_TRY_REMOVE_EMPTY_STRUCTURE; 231 | 232 | rbnode_t* node = NULL; 233 | 234 | if(rbtree_find_node(rbt, elem, &node) == GERROR_OK) 235 | return rbtree_remove_node(rbt, node); 236 | 237 | return GERROR_REMOVE_ELEMENT_NOT_FOUNDED; 238 | } 239 | 240 | /** Removes the node `node` of the `rbt` tree. 241 | * 242 | * @param rbt previous allocated rbtree_t structure 243 | * @param node pointer to a `rbnode_t` structure. 244 | * 245 | * @return GERROR_OK in case of sucess operation; 246 | * GERROR_NULL_STRUCURE in case `rbt` is a NULL; 247 | * GERROR_NULL_ELEMENT_POINTER in case `elem` is 248 | * pointing to null; 249 | * GERROR_TRY_REMOVE_EMPTY_STRUCTURE in case the 250 | * `rbt` structure is empty 251 | */ 252 | gerror_t rbtree_remove_node (rbtree_t* rbt, rbnode_t* node) 253 | { 254 | if(!rbt) return GERROR_NULL_STRUCTURE; 255 | if(!node) return GERROR_NULL_ELEMENT_POINTER; 256 | if(!rbt->size) return GERROR_TRY_REMOVE_EMPTY_STRUCTURE; 257 | 258 | rbnode_t* to_delete = node; 259 | rbnode_t* to_fix = NULL; 260 | rbcolor_t original_color = node->color; 261 | 262 | /* 263 | * if the node has no children 264 | */ 265 | if(node->right == NULL && node->left == NULL){ 266 | to_fix = rbtree_create_double_black(); 267 | rbtree_transplant(rbt, node, to_fix); 268 | 269 | /* 270 | * if the node does not have the right child 271 | */ 272 | }else if(node->left == NULL){ 273 | to_fix = node->right; 274 | rbtree_transplant(rbt, node, node->right); 275 | 276 | /* 277 | * if the node does not have the left child 278 | */ 279 | }else if(node->right == NULL){ 280 | to_fix = node->left; 281 | rbtree_transplant(rbt, node, node->left); 282 | 283 | /* 284 | * if the node has both children 285 | */ 286 | }else{ 287 | 288 | /* 289 | * find the minimal node in the right subtree 290 | */ 291 | to_delete = rbtree_find_minimal_node(node->right); 292 | original_color = to_delete->color; 293 | 294 | /* 295 | * create double black node if 296 | * the minimal node has no children 297 | * and point `to_fix` to the right 298 | * child of `to_delete` 299 | * 300 | * this is because `to_fix` needs 301 | * to points where the node was removed 302 | * for the fixup function 303 | */ 304 | if(to_delete->right == NULL){ 305 | to_fix = rbtree_create_double_black(); 306 | to_delete->right = to_fix; 307 | to_fix->parent = to_delete; 308 | }else{ 309 | to_fix = to_delete->right; 310 | } 311 | 312 | /* 313 | * linking 314 | */ 315 | if(to_delete->parent == node){ 316 | to_fix->parent = to_delete; 317 | }else{ 318 | rbtree_transplant(rbt, to_delete, to_delete->right); 319 | to_delete->right = node->right; 320 | to_delete->right->parent = to_delete; 321 | } 322 | 323 | rbtree_transplant(rbt, node, to_delete); 324 | to_delete->left = node->left; 325 | to_delete->left->parent = to_delete; 326 | to_delete->color = node->color; 327 | 328 | 329 | } 330 | 331 | if(original_color == G_RB_BLACK) 332 | rbtree_delete_fixup(rbt, to_fix); 333 | 334 | /* 335 | * delete the double black node 336 | */ 337 | if(to_fix != NULL && to_fix->color == G_RB_DOUBLE_BLACK) 338 | rbtree_remove_double_black(rbt, to_fix); 339 | 340 | free(node->data); 341 | free(node); 342 | 343 | rbt->size--; 344 | 345 | return GERROR_OK; 346 | } 347 | 348 | /** Set the flags of the rbtree. 349 | * TODO: A more datailed description of rbtree_set_flags. 350 | * 351 | * @param rbt previous allocated rbtree_t structure 352 | * @param flags flags to set the 353 | * 354 | * @see rbflag_t 355 | * 356 | * @return GERROR_OK in case of sucess operation; 357 | * GERROR_NULL_STRUCURE in case `rbt` is a NULL 358 | */ 359 | gerror_t rbtree_set_flags (redblacktree_t* rbt, long flags) 360 | { 361 | if(!rbt) return GERROR_NULL_STRUCTURE; 362 | 363 | rbt->flags = flags; 364 | 365 | return GERROR_OK; 366 | } 367 | 368 | /** Find a node with the value pointed by `elem` and write the pointer to 369 | * `node`. 370 | * 371 | * @param rbt previous allocated rbtree_t struct 372 | * @param elem pointer element to find 373 | * @param node pointer to the return node pointer; 374 | * this pointer could be null 375 | * 376 | * @return GERROR_OK in case of success operation; 377 | * GERROR_NULL_ELEMENT_POINTER in case `elem` is 378 | * null; 379 | * GERROR_NULL_STRUCURE in case `rbt` is a NULL; 380 | * By the end of the function, the `*node` will point 381 | * to the found element or NULL otherwise 382 | */ 383 | gerror_t rbtree_find_node (rbtree_t* rbt, void* elem, rbnode_t** node) 384 | { 385 | if(!rbt) return GERROR_NULL_STRUCTURE; 386 | if(!elem) return GERROR_NULL_ELEMENT_POINTER; 387 | 388 | rbnode_t* n = rbt->root; 389 | *node = NULL; 390 | 391 | while(n != NULL){ 392 | rbcomp_t result = rbt->compare(elem, n->data, rbt->compare_argument); 393 | 394 | switch(result){ 395 | case G_RB_FIRST_IS_SMALLER: 396 | n = n->left; 397 | break; 398 | case G_RB_FIRST_IS_GREATER: 399 | n = n->right; 400 | break; 401 | case G_RB_EQUAL: 402 | *node = n; 403 | return GERROR_OK; 404 | break; 405 | default: 406 | return GERROR_COMPARE_FUNCTION_WRONG_RETURN; 407 | } 408 | } 409 | 410 | return GERROR_ELEMENT_NOT_FOUNDED; 411 | } 412 | 413 | /** Find the minimal value in rbt and write the pointer to 414 | * `node`. 415 | * 416 | * @param rbt previous allocated rbtree_t struct 417 | * @param node pointer to the return node pointer; 418 | * 419 | * @return GERROR_OK in case of success operation; 420 | * GERROR_EMPTY_STRUCTURE in case the 421 | * `rbt` structure is empty 422 | * GERROR_NULL_STRUCURE in case `rbt` is a NULL; 423 | * GERROR_NULL_RETURN_POINTER in case that `node` 424 | * By the end of the function, the `*node` will point 425 | * to the found element or NULL otherwise 426 | */ 427 | gerror_t rbtree_min_node (rbtree_t* rbt, rbnode_t** node) 428 | { 429 | if(!rbt) return GERROR_NULL_STRUCTURE; 430 | if(!rbt->size) return GERROR_EMPTY_STRUCTURE; 431 | if(!node) return GERROR_NULL_RETURN_POINTER; 432 | 433 | rbnode_t* n = rbt->root; 434 | rbnode_t* temp_node = rbt->root; 435 | 436 | while(n != NULL){ 437 | temp_node = n; 438 | n = n->left; 439 | } 440 | 441 | *node = temp_node; 442 | 443 | return GERROR_OK; 444 | } 445 | 446 | /** Find the maximal value in rbt and write the pointer to 447 | * `node`. 448 | * 449 | * @param rbt previous allocated rbtree_t struct 450 | * @param node pointer to the return node pointer; 451 | * 452 | * @return GERROR_OK in case of success operation; 453 | * GERROR_EMPTY_STRUCTURE in case the 454 | * `rbt` structure is empty 455 | * GERROR_NULL_STRUCURE in case `rbt` is a NULL; 456 | * GERROR_NULL_RETURN_POINTER in case that `node` 457 | * By the end of the function, the `*node` will point 458 | * to the found element or NULL otherwise 459 | */ 460 | gerror_t rbtree_max_node (rbtree_t* rbt, rbnode_t** node) 461 | { 462 | if(!rbt) return GERROR_NULL_STRUCTURE; 463 | if(!rbt->size) return GERROR_EMPTY_STRUCTURE; 464 | if(!node) return GERROR_NULL_RETURN_POINTER; 465 | 466 | rbnode_t* n = rbt->root; 467 | rbnode_t* temp_node = rbt->root; 468 | 469 | while(n != NULL){ 470 | temp_node = n; 471 | n = n->right; 472 | } 473 | 474 | *node = temp_node; 475 | 476 | return GERROR_OK; 477 | } 478 | 479 | /* 480 | * destroy a node and it's children's 481 | * recursively 482 | */ 483 | rbnode_t* rbnode_destroy(rbnode_t* node) 484 | { 485 | if(node){ 486 | rbnode_destroy(node->left); 487 | rbnode_destroy(node->right); 488 | free(node->data); 489 | free(node); 490 | } 491 | return NULL; 492 | } 493 | 494 | /** Find the minimal value in rbt and write the value to 495 | * `elem`. 496 | * 497 | * @param rbt previous allocated rbtree_t struct 498 | * @param elem pointer to a local in memory to write 499 | * the minimal value 500 | * 501 | * @return GERROR_OK in case of success operation; 502 | * GERROR_EMPTY_STRUCTURE in case the 503 | * `rbt` structure is empty 504 | * GERROR_NULL_STRUCURE in case `rbt` is a NULL; 505 | * GERROR_NULL_RETURN_POINTER in case that `node` 506 | * By the end of the function, the `*node` will point 507 | * to the found element or NULL otherwise 508 | */ 509 | gerror_t rbtree_min_value (rbtree_t* rbt, void* elem) 510 | { 511 | if(!elem) return GERROR_NULL_RETURN_POINTER; 512 | 513 | rbnode_t* node; 514 | gerror_t result = rbtree_min_node(rbt, &node); 515 | 516 | if( result != GERROR_OK ) 517 | return result; 518 | 519 | memcpy(elem, node->data, rbt->member_size); 520 | 521 | return GERROR_OK; 522 | } 523 | 524 | /** Find the maximal value in rbt and write the value to 525 | * `elem`. 526 | * 527 | * @param rbt previous allocated rbtree_t struct 528 | * @param elem pointer to a local in memory to write 529 | * the maximal value 530 | * 531 | * @return GERROR_OK in case of success operation; 532 | * GERROR_EMPTY_STRUCTURE in case the 533 | * `rbt` structure is empty 534 | * GERROR_NULL_STRUCURE in case `rbt` is a NULL; 535 | * GERROR_NULL_RETURN_POINTER in case that `node` 536 | * By the end of the function, the `*node` will point 537 | * to the found element or NULL otherwise 538 | */ 539 | gerror_t rbtree_max_value (rbtree_t* rbt, void* elem) 540 | { 541 | if(!elem) return GERROR_NULL_RETURN_POINTER; 542 | 543 | rbnode_t* node; 544 | gerror_t result = rbtree_max_node(rbt, &node); 545 | 546 | if( result != GERROR_OK ) 547 | return result; 548 | 549 | memcpy(elem, node->data, rbt->member_size); 550 | 551 | return GERROR_OK; 552 | } 553 | 554 | /* 555 | * Classic red n black insert fixup function 556 | */ 557 | static void rbtree_insert_fixup(rbtree_t* rbt, rbnode_t* node) 558 | { 559 | while( node->parent != NULL && node->parent->color == G_RB_RED ){ 560 | 561 | /* 562 | * the parent of the node is the left child 563 | */ 564 | if( node->parent == node->parent->parent->left ){ 565 | 566 | /* 567 | * so the uncle is the right child 568 | */ 569 | rbnode_t* uncle = node->parent->parent->right; 570 | 571 | if( uncle != NULL && uncle->color == G_RB_RED ) 572 | fix_insert_case(rbt, &node, uncle, 0, 1); 573 | else if(node == node->parent->right) 574 | fix_insert_case(rbt, &node, uncle, 1, 1); 575 | else if(node == node->parent->left) 576 | fix_insert_case(rbt, &node, uncle, 2, 1); 577 | }else{ 578 | /* 579 | * so the uncle is the left child 580 | */ 581 | rbnode_t* uncle = node->parent->parent->left; 582 | if( uncle != NULL && uncle->color == G_RB_RED ) 583 | fix_insert_case(rbt, &node, uncle, 0, 0); 584 | else if(node == node->parent->left) 585 | fix_insert_case(rbt, &node, uncle, 1, 0); 586 | else if(node == node->parent->right) 587 | fix_insert_case(rbt, &node, uncle, 2, 0); 588 | } 589 | } 590 | 591 | rbt->root->color = G_RB_BLACK; 592 | } 593 | 594 | /* 595 | * receives a rbtree, a node and a case `c` and fix 596 | * the case `c`. `l` is whether the father is the left child 597 | */ 598 | static void fix_insert_case(rbtree_t* rbt, rbnode_t** node, rbnode_t* uncle, int c, int l) 599 | { 600 | switch(c){ 601 | /* 602 | * case 0 603 | * recoloring because uncle and parent are 604 | * red 605 | */ 606 | case 0: 607 | (*node)->parent->color = G_RB_BLACK; 608 | if(uncle) uncle->color = G_RB_BLACK; 609 | (*node)->parent->parent->color = G_RB_RED; 610 | *node = (*node)->parent->parent; 611 | break; 612 | /* 613 | * case 1 614 | * left rotate 615 | * because the uncle is black, the parent 616 | * is red and the node is the right child 617 | * note: the case 1 will end up in case 2, 618 | * so the break statement is no used in 619 | * this case 620 | */ 621 | case 1: 622 | *node = (*node)->parent; 623 | if(l) 624 | left_rotate(rbt, *node); 625 | else 626 | right_rotate(rbt, *node); 627 | /* 628 | * case 2 629 | * recoloring and right rotate 630 | * because the uncle is black, the parent 631 | * is red and the node is the left child 632 | */ 633 | case 2: 634 | (*node)->parent->color = G_RB_BLACK; 635 | (*node)->parent->parent->color = G_RB_RED; 636 | if(l) 637 | right_rotate(rbt, (*node)->parent->parent); 638 | else 639 | left_rotate(rbt, (*node)->parent->parent); 640 | break; 641 | } 642 | } 643 | 644 | /* 645 | * allocates and create a node 646 | */ 647 | static rbnode_t* create_node(rbtree_t* rbt, void* elem) 648 | { 649 | rbnode_t* node = (rbnode_t*) malloc( sizeof(rbnode_t) ); 650 | 651 | node->left = NULL; 652 | node->right = NULL; 653 | node->parent = NULL; 654 | node->color = G_RB_RED; 655 | node->data = NULL; 656 | 657 | if( rbt->member_size && elem ){ 658 | node->data = (void*) malloc(rbt->member_size); 659 | memcpy(node->data, elem, rbt->member_size); 660 | } 661 | 662 | 663 | return node; 664 | } 665 | 666 | /* 667 | * performs the left rotation. This is the classical binary 668 | * search tree left rotation function. 669 | */ 670 | static void left_rotate(rbtree_t* rbt, rbnode_t* node) 671 | { 672 | 673 | rbnode_t* temp_node = node->right; 674 | node->right = temp_node->left; 675 | 676 | if(temp_node->left != NULL) 677 | temp_node->left->parent = node; 678 | 679 | temp_node->parent = node->parent; 680 | 681 | /* 682 | * checks if the `node` was the root of rbtree and 683 | * update the new root to `temp_node` or link to 684 | * the correct children side; 685 | */ 686 | if(node->parent == NULL) 687 | rbt->root = temp_node; 688 | else if(node->parent->left == node) 689 | node->parent->left = temp_node; 690 | else 691 | node->parent->right = temp_node; 692 | 693 | temp_node->left = node; 694 | node->parent = temp_node; 695 | } 696 | 697 | /* 698 | * performs the right rotation. This is the classical binary 699 | * search tree right rotation function. 700 | */ 701 | static void right_rotate(rbtree_t* rbt, rbnode_t* node) 702 | { 703 | 704 | rbnode_t* temp_node = node->left; 705 | node->left = temp_node->right; 706 | 707 | if(temp_node->right != NULL) 708 | temp_node->right->parent = node; 709 | 710 | temp_node->parent = node->parent; 711 | 712 | /* 713 | * checks if the `node` was the root of rbtree and 714 | * update the new root to `temp_node` or link to 715 | * the correct children side; 716 | */ 717 | if(node->parent == NULL) 718 | rbt->root = temp_node; 719 | else if(node->parent->left == node) 720 | node->parent->left = temp_node; 721 | else 722 | node->parent->right = temp_node; 723 | 724 | temp_node->right = node; 725 | node->parent = temp_node; 726 | } 727 | 728 | /* 729 | * the default comparison function. Just compare 730 | * like to long 731 | */ 732 | int rbtree_default_compare_function(void* a, void* b, void* arg) 733 | { 734 | size_t size = *(size_t*)arg; 735 | 736 | long la = 0; 737 | long lb = 0; 738 | 739 | switch(size){ 740 | case sizeof(int): 741 | la = *(int*)a; 742 | lb = *(int*)b; 743 | break; 744 | case sizeof(char): 745 | la = *(char*)a; 746 | lb = *(char*)b; 747 | break; 748 | case sizeof(long): 749 | la = *(long*)a; 750 | lb = *(long*)b; 751 | break; 752 | } 753 | return (la > lb) - (la < lb); 754 | } 755 | 756 | /* 757 | * transplant function, transplants node u by node v in the tree 758 | */ 759 | void rbtree_transplant(rbtree_t* rbt, rbnode_t* u, rbnode_t* v) 760 | { 761 | if(u->parent == NULL) 762 | rbt->root = v; 763 | else if(u == u->parent->left) 764 | u->parent->left = v; 765 | else 766 | u->parent->right = v; 767 | 768 | if(v) v->parent = u->parent; 769 | } 770 | 771 | 772 | /* 773 | * returns 1 if the node is red and 0 otherwise 774 | */ 775 | int rbnode_is_red(rbnode_t* node) 776 | { 777 | return !rbnode_is_black(node); 778 | } 779 | 780 | /* 781 | * returns 1 if the node is black and 0 otherwise 782 | */ 783 | int rbnode_is_black(rbnode_t* node) 784 | { 785 | return node == NULL || node->color != G_RB_RED; 786 | } 787 | 788 | /* 789 | * Classic red n black delete fixup function 790 | */ 791 | void rbtree_delete_fixup(rbtree_t* rbt, rbnode_t* node) 792 | { 793 | 794 | while(node != rbt->root && rbnode_is_black(node)){ 795 | 796 | rbc_t side; 797 | 798 | int c; 799 | switch( c = rbtree_identify_case(node, &side) ){ 800 | case 2: 801 | /* 802 | * parent becomes red 803 | * sibling becomes black 804 | * left rotate the parent 805 | * "no" push the problem up 806 | * "no" between quotes because 807 | * the problem is pushed up only for 808 | * a non-double-black node 809 | */ 810 | if(side == RB_LEFT){ 811 | node->parent->color = G_RB_RED; 812 | node->parent->right->color = G_RB_BLACK; 813 | left_rotate(rbt, node->parent); 814 | 815 | if(node->parent->right == NULL) 816 | node = node->parent; 817 | 818 | }else{ 819 | node->parent->color = G_RB_RED; 820 | node->parent->left->color = G_RB_BLACK; 821 | right_rotate(rbt, node->parent); 822 | 823 | if(node->parent->left == NULL) 824 | node = node->parent; 825 | } 826 | 827 | break; 828 | 829 | case 3: 830 | 831 | /* 832 | * sibling becomes red 833 | * push the problem upwards 834 | */ 835 | if(side == RB_LEFT) 836 | node->parent->right->color = G_RB_RED; 837 | else 838 | node->parent->left->color = G_RB_RED; 839 | 840 | node = node->parent; 841 | break; 842 | case 4: 843 | /* 844 | * parent becomes black 845 | * sibling becomes red 846 | */ 847 | node->parent->color = G_RB_BLACK; 848 | 849 | if(side == RB_LEFT){ 850 | if(node->parent->right != NULL) 851 | node->parent->right->color = G_RB_RED; 852 | } 853 | else{ 854 | if(node->parent->left != NULL) 855 | node->parent->left->color = G_RB_RED; 856 | } 857 | 858 | /*this is a terminal case*/ 859 | node = rbt->root; 860 | break; 861 | case 5: 862 | /* 863 | * sibling becomes black 864 | * siblings's left child becomes red 865 | * push the problem upwards 866 | * right-rotation on the sibling 867 | */ 868 | if(side == RB_LEFT){ 869 | node->parent->right->color = G_RB_RED; 870 | node->parent->right->left->color = G_RB_BLACK; 871 | right_rotate(rbt, node->parent->right); 872 | }else{ 873 | node->parent->left->color = G_RB_RED; 874 | node->parent->left->right->color = G_RB_BLACK; 875 | left_rotate(rbt, node->parent->left); 876 | } 877 | 878 | break; 879 | case 6: 880 | /* 881 | * sibling take the color of the parent 882 | * parent becomes black 883 | * right child of the sibling becomes black 884 | * left-rotate in the parent 885 | */ 886 | if(side == RB_LEFT){ 887 | node->parent->right->color = node->parent->color; 888 | node->parent->color = G_RB_BLACK; 889 | node->parent->right->right->color = G_RB_BLACK; 890 | left_rotate(rbt, node->parent); 891 | }else{ 892 | node->parent->left->color = node->parent->color; 893 | node->parent->color = G_RB_BLACK; 894 | node->parent->left->left->color = G_RB_BLACK; 895 | right_rotate(rbt, node->parent); 896 | } 897 | 898 | /*this is a terminal case*/ 899 | node = rbt->root; 900 | break; 901 | case 0: 902 | node = rbt->root; 903 | break; 904 | } 905 | 906 | } 907 | 908 | if(node->color != G_RB_DOUBLE_BLACK) 909 | node->color = G_RB_BLACK; 910 | 911 | } 912 | 913 | 914 | /* 915 | * allocates and populate a double black node based 916 | * by `node` and return the pointer 917 | */ 918 | rbnode_t* rbtree_create_double_black() 919 | { 920 | rbnode_t* db = (rbnode_t*) malloc(sizeof(rbnode_t)); 921 | 922 | db->parent = NULL; 923 | db->right = NULL; 924 | db->left = NULL; 925 | db->data = NULL; 926 | db->color = G_RB_DOUBLE_BLACK; 927 | 928 | return db; 929 | } 930 | 931 | /* 932 | * remove and deallocates the double_black node 933 | */ 934 | void rbtree_remove_double_black(rbtree_t* rbt, rbnode_t* db) 935 | { 936 | if(db == rbt->root){ 937 | rbt->root = NULL; 938 | }else{ 939 | if(db->parent->left == db){ 940 | db->parent->left = NULL; 941 | }else{ 942 | db->parent->right = NULL; 943 | } 944 | } 945 | 946 | free(db); 947 | } 948 | 949 | /* 950 | * give a node, find a minimal of the subtree 951 | */ 952 | rbnode_t* rbtree_find_minimal_node(rbnode_t* node) 953 | { 954 | rbnode_t* minimal = NULL; 955 | while(node != NULL){ 956 | minimal = node; 957 | node = node->left; 958 | } 959 | 960 | return minimal; 961 | } 962 | 963 | /* 964 | * identify the case to fix 965 | */ 966 | int rbtree_identify_case (rbnode_t* node, rbc_t* side) 967 | { 968 | if(node == node->parent->left){ 969 | *side = RB_LEFT; 970 | rbnode_t* sibling = node->parent->right; 971 | 972 | if(rbnode_is_black(node->parent)){ 973 | 974 | if(rbnode_is_red(sibling)){ 975 | return 2; 976 | }else{ 977 | if(rbnode_is_black(sibling->right)){ 978 | if(rbnode_is_black(sibling->left)) 979 | return 3; 980 | else 981 | return 5; 982 | } 983 | 984 | if(rbnode_is_red(sibling->right)) 985 | return 6; 986 | } 987 | 988 | }else{ 989 | if(rbnode_is_black(sibling)){ 990 | if( sibling == NULL || 991 | (rbnode_is_black(sibling->right) && 992 | rbnode_is_black(sibling->left))){ 993 | return 4; 994 | }else if(rbnode_is_red(sibling->left) && 995 | rbnode_is_black(sibling->right)){ 996 | return 5; 997 | }else if(rbnode_is_red(sibling->right)){ 998 | return 6; 999 | } 1000 | } 1001 | } 1002 | 1003 | }else{ 1004 | *side = RB_RIGHT; 1005 | 1006 | rbnode_t* sibling = node->parent->left; 1007 | 1008 | if(rbnode_is_black(node->parent)){ 1009 | 1010 | if(rbnode_is_red(sibling)){ 1011 | return 2; 1012 | }else{ 1013 | if(rbnode_is_black(sibling->left)){ 1014 | if(rbnode_is_black(sibling->right)) 1015 | return 3; 1016 | else 1017 | return 5; 1018 | } 1019 | 1020 | if(rbnode_is_red(sibling->left)) 1021 | return 6; 1022 | } 1023 | 1024 | }else{ 1025 | if(rbnode_is_black(sibling)){ 1026 | if( sibling == NULL || 1027 | (rbnode_is_black(sibling->right) && 1028 | rbnode_is_black(sibling->left))){ 1029 | return 4; 1030 | }else if(rbnode_is_red(sibling->right) && 1031 | rbnode_is_black(sibling->left)){ 1032 | return 5; 1033 | }else if(rbnode_is_red(sibling->left)){ 1034 | return 6; 1035 | } 1036 | } 1037 | } 1038 | 1039 | } 1040 | 1041 | return 0; 1042 | } 1043 | -------------------------------------------------------------------------------- /src/stack.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * For more information, please refer to 18 | */ 19 | #include "stack.h" 20 | 21 | /** Creates a stack and populates the previous 22 | * allocated structure pointed by `s`; 23 | * 24 | * @param s pointer to a stack structure; 25 | * @param member_size size of the elements that will be 26 | * indexed by `s` 27 | * 28 | * @return GERROR_OK in case of success operation; 29 | * GERROR_NULL_ELEMENT in case that `e` is empty. 30 | */ 31 | gerror_t stack_create(struct stack_t* s, size_t member_size) 32 | { 33 | if(!s) return GERROR_NULL_STRUCTURE; 34 | 35 | s->member_size = member_size; 36 | s->size = 0; 37 | s->head = NULL; 38 | return GERROR_OK; 39 | } 40 | 41 | /** Add the element `e` in the beginning of the stack `s`. 42 | * 43 | * @param s pointer to a stack structure; 44 | * @param e pointer to the element that will be indexed 45 | * by s. 46 | * 47 | * @return GERROR_OK in case of success operation; 48 | * GERROR_NULL_STRUCURE in case `s` is a NULL 49 | */ 50 | gerror_t stack_push(struct stack_t* s, void* e) 51 | { 52 | if(!s) return GERROR_NULL_STRUCTURE; 53 | 54 | struct snode_t* new_node = (snode_t*) malloc(sizeof(snode_t)); 55 | if( s->member_size ) 56 | new_node->data = malloc(s->member_size); 57 | else 58 | new_node->data = NULL; 59 | new_node->prev = NULL; 60 | new_node->next = s->head; 61 | 62 | if(s->member_size && e) 63 | memcpy(new_node->data, e, s->member_size); 64 | 65 | s->head = new_node; 66 | 67 | s->size++; 68 | 69 | return GERROR_OK; 70 | } 71 | 72 | /** Pops the first element of the stack `s`. 73 | * 74 | * @param s pointer to a stack structure; 75 | * @param e pointer to the previous allocated element 76 | * 77 | * @return GERROR_OK in case of success operation; 78 | * GERROR_NULL_STRUCURE in case `s` is a NULL 79 | * GERROR_NULL_HEAD in case that the head `s->head` 80 | * GERROR_TRY_REMOVE_EMPTY_STRUCTURE in case that `s` 81 | * is empty 82 | */ 83 | gerror_t stack_pop (struct stack_t* s, void* e) 84 | { 85 | if(!s) return GERROR_NULL_STRUCTURE; 86 | if(!s->head) return GERROR_NULL_HEAD; 87 | if(!s->size) return GERROR_TRY_REMOVE_EMPTY_STRUCTURE; 88 | 89 | void* ptr = s->head->data; 90 | struct snode_t* old_node = s->head; 91 | 92 | s->head = s->head->next; 93 | 94 | if( s->head ) 95 | s->head->prev = NULL; 96 | 97 | s->size--; 98 | free(old_node); 99 | 100 | if(s->member_size && e) 101 | memcpy(e, ptr, s->member_size); 102 | if(ptr) 103 | free(ptr); 104 | return GERROR_OK; 105 | } 106 | 107 | 108 | /** Deallocates the nodes of the structure pointed 109 | * by `s`. This function WILL NOT deallocate the 110 | * pointer `q`. 111 | * 112 | * @param s pointer to a stack structure; 113 | * 114 | * @return GERROR_OK in case of success operation; 115 | * GERROR_NULL_STRUCURE in case `s` is a NULL 116 | */ 117 | gerror_t stack_destroy(struct stack_t* s) 118 | { 119 | if(!s) return GERROR_NULL_STRUCTURE; 120 | 121 | struct snode_t* i, *j; 122 | 123 | for( i=s->head; i!=NULL; i=j ){ 124 | j = i->next; 125 | if(i->data) 126 | free(i->data); 127 | free(i); 128 | } 129 | 130 | return GERROR_OK; 131 | } 132 | -------------------------------------------------------------------------------- /src/trie.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * For more information, please refer to 18 | */ 19 | #include "trie.h" 20 | 21 | /* 22 | * Auxiliar function; 23 | * find the node mapped by `string`, if necessary, allocates 24 | * 25 | * @return the node mapped with string and allocate 26 | */ 27 | tnode_t* trie_get_node_or_allocate ( 28 | struct trie_t* t, 29 | void* string, 30 | size_t size) 31 | { 32 | if(!t || !string) return NULL; 33 | struct tnode_t* node = &t->root; 34 | size_t i; 35 | char *ptr = string; 36 | 37 | for(i=0; ichildren[byte] == NULL ){ 40 | node->children[byte] = (tnode_t*)malloc(sizeof(tnode_t)); 41 | node->children[byte]->value = NULL; 42 | 43 | int j; 44 | for(j=0; jchildren[byte]->children[i] = NULL; 46 | 47 | } 48 | 49 | node = node->children[byte]; 50 | } 51 | return node; 52 | } 53 | 54 | /* 55 | * Auxiliar function; 56 | * find the node mapped by `string` 57 | * 58 | * @return the node mapped with `string` or null case the mapped 59 | * does not exists. 60 | */ 61 | tnode_t* node_at ( struct trie_t* t, void* string, size_t size) 62 | { 63 | if(!t || !string) return NULL; 64 | struct tnode_t* node = &t->root; 65 | size_t i; 66 | char *ptr = string; 67 | 68 | for(i=0; ichildren[byte] == NULL ) 72 | return NULL; 73 | 74 | node = node->children[byte]; 75 | } 76 | return node; 77 | } 78 | 79 | /** Inicialize structure `t` with `member_size` size. 80 | * The t has to be allocated. 81 | * 82 | * @param t pointer to the allocated struct trie_t; 83 | * @param member_size size in bytes of the indexed elements 84 | * by the trie. 85 | */ 86 | gerror_t trie_create (struct trie_t* t, size_t member_size) 87 | { 88 | if(!t) return GERROR_NULL_STRUCTURE; 89 | 90 | t->size = 0; 91 | t->member_size = member_size; 92 | t->root.value = NULL; 93 | 94 | int i; 95 | for(i=0; iroot.children[i] = NULL; 97 | 98 | return GERROR_OK; 99 | } 100 | 101 | /* 102 | * auxiliar function. 103 | * destroy a node recursively. 104 | */ 105 | void trie_destroy_tnode (struct tnode_t* node) 106 | { 107 | if( node ){ 108 | int i; 109 | for(i=0; ichildren[i]); 111 | 112 | if( node->value ) 113 | free(node->value); 114 | 115 | free(node); 116 | } 117 | } 118 | 119 | /** Destroy the members pointed by `t`. 120 | * The structure is not freed. 121 | * 122 | * @return GERROR_OK in case of success operation; 123 | * GERROR_NULL_STRUCURE in case `t` is a NULL 124 | */ 125 | gerror_t trie_destroy (struct trie_t* t) 126 | { 127 | if(!t) return GERROR_NULL_STRUCTURE; 128 | 129 | int i; 130 | 131 | if(t->root.value) 132 | free(t->root.value); 133 | 134 | for(i=0; iroot.children[i]); 136 | t->root.children[i] = NULL; 137 | } 138 | t->size = 0; 139 | t->member_size = 0; 140 | 141 | return GERROR_OK; 142 | } 143 | 144 | /** Adds the `elem` and maps it with the `string` with size `size`. 145 | * This function overwrite any data left in the trie mapped with string. 146 | * 147 | * @param t pointer to the trie structure; 148 | * @param string pointer to the string of bytes to map elem; 149 | * @param size size of the string of bytes 150 | * @param elem pointer to the element to add 151 | */ 152 | gerror_t trie_add_element (struct trie_t* t, void* string, size_t size, void* elem) 153 | { 154 | if(!t) return GERROR_NULL_STRUCTURE; 155 | struct tnode_t* node = trie_get_node_or_allocate(t, string, size); 156 | 157 | if(node->value == NULL) 158 | node->value = malloc(t->member_size); 159 | 160 | if(t->member_size && string) 161 | memcpy(node->value, elem, t->member_size); 162 | t->size++; 163 | 164 | return GERROR_OK; 165 | } 166 | 167 | /** Removes the element mapped by `string`. 168 | * 169 | * @param t pointer to the structure trie_t; 170 | * @param string pointer to the string of bytes to map elem; 171 | * @param size size of the string of bytes. 172 | * 173 | * @return GERROR_OK in case of success operation; 174 | * GERROR_NULL_STRUCURE in case `t` is a NULL 175 | * GERROR_OUT_OF_BOUND the `elem` does not exist 176 | * in `string map` 177 | */ 178 | gerror_t trie_remove_element (struct trie_t* t, void* string, size_t size) 179 | { 180 | if(!t) return GERROR_NULL_STRUCTURE; 181 | 182 | struct tnode_t* node = node_at(t, string, size); 183 | if(!node) return GERROR_ACCESS_OUT_OF_BOUND; 184 | 185 | void* removed_value = node->value; 186 | 187 | node->value = NULL; 188 | 189 | t->size--; 190 | void* ptr = removed_value; 191 | if(ptr) 192 | free(ptr); 193 | return GERROR_OK; 194 | } 195 | 196 | /** Returns the element mapped by `string`. If the map does not 197 | * exist, returns NULL. 198 | * 199 | * @param t pointer to the structure; 200 | * @param string pointer to the string of bytes to map elem; 201 | * @param size size of the string of bytes. 202 | * @param elem pointer to the memory allocated that 203 | * will be write with the elem mapped by `string` 204 | * 205 | * @return GERROR_OK in case of success operation; 206 | * GERROR_NULL_STRUCURE in case `t` is a NULL 207 | */ 208 | gerror_t trie_get_element (struct trie_t* t, void* string, size_t size, void* elem) 209 | { 210 | if(!t) return GERROR_NULL_STRUCTURE; 211 | 212 | struct tnode_t* node = node_at(t, string, size); 213 | 214 | if(node == NULL) 215 | return GERROR_ACCESS_OUT_OF_BOUND; 216 | 217 | if(t->member_size) 218 | memcpy(elem, node->value, t->member_size); 219 | 220 | return GERROR_OK; 221 | } 222 | 223 | /** Sets the value mapped by `string`. 224 | * Encapsulates the remove and add functions. 225 | * 226 | * @param t pointer to the structure; 227 | * @param string pointer to the string of bytes to map elem; 228 | * @param size size of the string of bytes. 229 | * @param elem pointer to the element to add 230 | */ 231 | gerror_t trie_set_element (struct trie_t* t, void* string, size_t size, void* elem) 232 | { 233 | 234 | if(!t) return GERROR_NULL_STRUCTURE; 235 | 236 | struct tnode_t* node = node_at(t, string, size); 237 | if(node){ 238 | if(t->member_size) 239 | memcpy(node->value, elem, t->member_size); 240 | 241 | } 242 | 243 | return GERROR_OK; 244 | } 245 | -------------------------------------------------------------------------------- /src/vector.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * For more information, please refer to 18 | */ 19 | #include "vector.h" 20 | 21 | #define VECTOR_MIN_SIZ 8 22 | size_t vector_min_siz = VECTOR_MIN_SIZ; 23 | 24 | /** Populate the `vetor_t` structure pointed by `v` 25 | * and allocates `member_size`*`initial_size` for initial buffer_size. 26 | * 27 | * @param v a pointer to `vector_t` structure 28 | * already allocated; 29 | * @param inicial_buf_size number of the members of the initial 30 | * allocated buffer; 31 | * @param member_size size of every member indexed by `v`. 32 | * 33 | * @return GERROR_OK in case of success operation; 34 | * GERROR_NULL_STRUCURE in case `v` is a NULL 35 | * pointer 36 | * 37 | */ 38 | gerror_t vector_create (vector_t* v, size_t initial_buf_siz, size_t member_size) 39 | { 40 | if(!v) return GERROR_NULL_STRUCTURE; 41 | 42 | v->size = 0; 43 | v->member_size = member_size; 44 | if ( initial_buf_siz < vector_min_siz ) 45 | v->buffer_size = vector_min_siz*member_size; 46 | else 47 | v->buffer_size = initial_buf_siz*member_size; 48 | 49 | v->data = malloc(v->buffer_size); 50 | return GERROR_OK; 51 | } 52 | 53 | /** Destroy the structure `vector_t` pointed by `v`. 54 | * 55 | * @param v a pointer to `vector_t` structure 56 | * 57 | * @return GERROR_OK in case of success operation; 58 | * GERROR_NULL_STRUCURE in case `v` is a NULL 59 | * pointer 60 | */ 61 | gerror_t vector_destroy (vector_t* v) 62 | { 63 | 64 | if( !v ) return GERROR_NULL_STRUCTURE; 65 | 66 | free(v->data); 67 | v->buffer_size = 0; 68 | v->member_size = 0; 69 | v->data = NULL; 70 | 71 | return GERROR_NULL_STRUCTURE; 72 | 73 | } 74 | 75 | /** Returns the `vector_min_siz`: a private variable that holds 76 | * the minimal number of elements that `vector_t` will index. 77 | * This variable is important for avoid multiple small resizes 78 | * in the `vector_t` container. 79 | * 80 | * @return vector_min_siz 81 | */ 82 | size_t vector_get_min_buf_siz (void) 83 | { 84 | return vector_min_siz; 85 | } 86 | 87 | /** Set the `vector_min_siz`: a private variable that holds 88 | * the minimal number of elements that `vector_t` will index. 89 | * This variable is important for avoid multiple small resizes 90 | * in the `vector_t` container. 91 | * 92 | * @param new_min_buf_siz the new size of `vector_min_siz` 93 | */ 94 | void vector_set_min_buf_siz (size_t new_min_buf_siz) 95 | { 96 | vector_min_siz = new_min_buf_siz; 97 | } 98 | 99 | /** Resize the buffer in the `vector_t` strucuture 100 | * pointed by `v`. 101 | * 102 | * @param v a pointer to `vector_t` 103 | * structure. 104 | * @param new_size the new size of the `v` 105 | */ 106 | gerror_t vector_resize_buffer (vector_t* v, size_t n_elements) 107 | { 108 | if(!v) return GERROR_NULL_STRUCTURE; 109 | 110 | size_t new_proposed_size = n_elements*v->member_size; 111 | size_t new_actual_size; 112 | 113 | /* 114 | * update the size if need 115 | */ 116 | if( n_elements < v->size ) 117 | v->size = n_elements; 118 | 119 | /* 120 | * resize the buffer if the size proposed is bigger. 121 | * if the size proposed is not much bigger than member 122 | * size so a bigger resize value is set. This is to 123 | * prevent multiple small resizes. 124 | * 125 | * if the size proposed is less than buffer the buffer 126 | * is resized if the less is bigger than vector_min_siz 127 | * else vector_min_siz will be the newsize. 128 | */ 129 | size_t min_resize = vector_min_siz*v->member_size; 130 | if( new_proposed_size >= v->buffer_size ){ 131 | size_t buffer_size_diff = new_proposed_size - v->buffer_size; 132 | if( buffer_size_diff < min_resize ) 133 | new_actual_size = v->buffer_size + min_resize; 134 | else 135 | new_actual_size = new_proposed_size; 136 | }else{ 137 | if(new_proposed_size < min_resize ) 138 | new_actual_size = min_resize; 139 | else 140 | new_actual_size = new_proposed_size; 141 | } 142 | if( new_actual_size != v->buffer_size ){ 143 | v->data = realloc(v->data, new_actual_size); 144 | v->buffer_size = new_actual_size; 145 | } 146 | 147 | return GERROR_OK; 148 | } 149 | 150 | /** Get the element in the `index` position indexed by 151 | * the `vector_t` structure pointed by `v`. 152 | * 153 | * @param v a pointer to `vector_t` 154 | * @param index index of the position 155 | * @param elem pointer to a previous allocated 156 | * memory that will receive the element 157 | * 158 | * @return GERROR_OK in case of success operation; 159 | * GERROR_NULL_STRUCURE in case `v` is a NULL 160 | * pointer 161 | */ 162 | gerror_t vector_at (vector_t* v, size_t index, void* elem) 163 | { 164 | size_t at = index*v->member_size; 165 | if( !v ) return GERROR_NULL_STRUCTURE; 166 | if( !v->buffer_size || at >= v->buffer_size ) return GERROR_ACCESS_OUT_OF_BOUND; 167 | 168 | if(elem) memcpy(elem, (v->data + at), v->member_size); 169 | 170 | return GERROR_OK; 171 | } 172 | 173 | /** set the element at `index` pointed by `v` with the 174 | * element pointed by `elem`. 175 | * 176 | * @param v a pointer to `vector_t` 177 | * @param index index of the position 178 | * @param elem the element to be set in `v` 179 | * 180 | * @return GERROR_OK in case of success operation; 181 | * GERROR_NULL_STRUCURE in case `v` is a NULL 182 | * pointer 183 | */ 184 | gerror_t vector_set_elem_at (vector_t* v, size_t index, void* elem) 185 | { 186 | if(!v) return GERROR_NULL_STRUCTURE; 187 | 188 | size_t at = index*v->member_size; 189 | if( at >= v->buffer_size ) return GERROR_ACCESS_OUT_OF_BOUND; 190 | 191 | void* ptr = (v->data + at); 192 | if( ptr && elem) memcpy(ptr, elem, v->member_size); 193 | 194 | return GERROR_OK; 195 | } 196 | 197 | /** adds the `elem` in the structure `vector_t` pointed 198 | * by `v`. 199 | * 200 | * @param v a pointer to `vector_t` 201 | * @param elem the element to be add in `v` 202 | * 203 | * @return GERROR_OK in case of success operation; 204 | * GERROR_NULL_STRUCTURE in case `v` is a NULL 205 | * pointer 206 | */ 207 | gerror_t vector_add (vector_t* v, void* elem) 208 | { 209 | if( !v ) return GERROR_NULL_STRUCTURE; 210 | size_t room_size = v->buffer_size/v->member_size; 211 | 212 | if( room_size < (v->size+1) ) 213 | vector_resize_buffer(v, v->size+1); 214 | 215 | gerror_t s = vector_set_elem_at(v, v->size, elem); 216 | v->size++; 217 | 218 | if(s != GERROR_OK) return s; 219 | return GERROR_OK; 220 | } 221 | 222 | /** Calculate the pointer at `index` position. 223 | * 224 | * @param v a pointer to `vector_t` 225 | * @param index index of the pointer 226 | * 227 | * @return a pointer to the `index` element 228 | * NULL in case of out of bound 229 | */ 230 | void* vector_ptr_at (vector_t* v, size_t index) 231 | { 232 | if(index >= v->size || index >= v->buffer_size) 233 | return NULL; 234 | return v->data + (index*v->member_size); 235 | } 236 | 237 | /** Appends the vector `v1` to the vector `v0`. 238 | * 239 | * @param v0 vector structure 240 | * @param v1 vector structure to be appended 241 | * 242 | * @return GERROR_OK in case of success operation; 243 | * GERROR_NULL_STRUCTURE in case `v` is a NULL 244 | */ 245 | gerror_t vector_append (vector_t* v0, vector_t* v1) 246 | { 247 | if(!v0 || !v1) return GERROR_NULL_STRUCTURE; 248 | if(v0->member_size != v1->member_size) return GERROR_INCOMPATIBLE_VECTOR_APPEND_SIZE; 249 | 250 | vector_append_buffer(v0, v1->data, v1->size); 251 | 252 | return GERROR_OK; 253 | } 254 | 255 | /** Appends `size` members pointed by `buffer` in `v`. 256 | * 257 | * @param v a pointer to `vector_t` structure 258 | * @param buffer pointer to the elements with the same size to `v->member_size` 259 | * to be appended 260 | * @param size number of elements pointed by the `buffer` 261 | * 262 | * @return GERROR_OK in case of success operation; 263 | * GERROR_NULL_STRUCTURE in case `v` is a NULL 264 | */ 265 | gerror_t vector_append_buffer (vector_t* v, void* buffer, size_t size) 266 | { 267 | if(!v) return GERROR_NULL_STRUCTURE; 268 | if(!buffer) return GERROR_NULL_POINTER_TO_BUFFER; 269 | 270 | vector_resize_buffer (v, v->size + size); 271 | memcpy(v->data + (v->size*v->member_size), buffer, size*v->member_size); 272 | v->size += size; 273 | 274 | return GERROR_OK; 275 | } 276 | --------------------------------------------------------------------------------