From: Benjamin Auder Date: Wed, 3 Feb 2021 21:42:55 +0000 (+0100) Subject: Implement HashTable + fix some extra blank spaces, remove Bool type (using bool ... X-Git-Url: https://git.auder.net/doc/html/css/current/gitweb.css?a=commitdiff_plain;h=1ff641f9960fa6c6081817a5641afb22fad91dcd;p=cgds.git Implement HashTable + fix some extra blank spaces, remove Bool type (using bool / C99) --- diff --git a/.gitignore b/.gitignore index b9d261d..941f4fb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *.o /src/obj/*.so /test/test +/test/vgcore.* /doc/html/ /doc/latex/ diff --git a/Makefile b/Makefile index de9dd81..640ed2e 100644 --- a/Makefile +++ b/Makefile @@ -22,9 +22,11 @@ install: cp src/obj/$(LIBRARY) $(INSTALL_PREFIX)/lib/ mkdir -p $(INSTALL_PREFIX)/include/cgds cp src/*.h $(INSTALL_PREFIX)/include/cgds/ + mv $(INSTALL_PREFIX)/include/cgds/cgds.h $(INSTALL_PREFIX)/include/ uninstall: rm -f ${INSTALL_PREFIX}/lib/${LIBRARY} + rm -f ${INSTALL_PREFIX}/include/cgds.h [[ -d ${INSTALL_PREFIX}/include/cgds ]] && rm -rf ${INSTALL_PREFIX}/include/cgds .PHONY: src test doc clean install uninstall diff --git a/src/BufferTop.c b/src/BufferTop.c index db66476..1ead6b8 100644 --- a/src/BufferTop.c +++ b/src/BufferTop.c @@ -43,7 +43,7 @@ List* buffertop_2list(BufferTop* bufferTop) return bufferInList; } -Bool buffertop_empty(BufferTop* bufferTop) +bool buffertop_empty(BufferTop* bufferTop) { return (heap_size(bufferTop->heap) == 0); } diff --git a/src/BufferTop.h b/src/BufferTop.h index 1f7d9a9..96af769 100644 --- a/src/BufferTop.h +++ b/src/BufferTop.h @@ -17,7 +17,7 @@ */ typedef struct BufferTop { UInt capacity; ///< Buffer capacity (in items count). - OrderType bType; ///< Type of buffer: keep max items (MAX_T) or min items (MIN_T). + OrderType bType; ///< Type of buffer: keep max or min items (MAX_T or MIN_T). Heap* heap; ///< Item-ValueS are internally organized into a heap. } BufferTop; @@ -27,7 +27,7 @@ typedef struct BufferTop { BufferTop* _buffertop_new( size_t dataSize, ///< Size in bytes of a buffer element. UInt capacity, ///< Maximum number of elements that the buffer can contain. - OrderType bType, ///< Type of buffer: keep max items (bType==MAX_T) or min items (bType==MIN_T). + OrderType bType, ///< Type of buffer: keep max or min items (MAX_T or MIN_T). UInt arity ///< Arity of the wrapped heap: any integer >=2. ); @@ -35,16 +35,17 @@ BufferTop* _buffertop_new( * @brief Return an allocated and initialized buffer. * @param type Type of a buffer item (int, char*, ...). * @param capacity Maximum number of elements that the buffer can contain. - * @param bType type of buffer top: max items (bType==MAX_T) or min items (bType==MIN_T). + * @param bType type of buffer: keep max or min items (MAX_T or MIN_T). * @param arity Arity of the wrapped heap: any integer >=2. - * - * Usage: BufferTop* buffertop_new( type, UInt capacity, OrderTypebType, UInt arity) + * + * Usage: BufferTop* buffertop_new(\ + * type, UInt capacity, OrderTypebType, UInt arity) */ #define buffertop_new(type, capacity, bType, arity) \ _buffertop_new(sizeof(type), capacity, bType, arity) /** - * @brief Copy constructor (works well if items do not have allocated sub-pointers). + * @brief Copy constructor (shallow copy, ok for basic types). */ BufferTop* buffertop_copy( BufferTop* bufferTop ///< "this" pointer. @@ -60,7 +61,7 @@ List* buffertop_2list( /** * @brief Check if the buffer is empty. */ -Bool buffertop_empty( +bool buffertop_empty( BufferTop* bufferTop ///< "this" pointer. ); @@ -85,7 +86,7 @@ void _buffertop_tryadd( * @param bufferTop "this" pointer. * @param item Item of type as defined in the constructor. * @param value Value associated with the item. - * + * * Usage: void buffertop_tryadd(BufferTop* bufferTop, void item, Real value) */ #define buffertop_tryadd(bufferTop, item, value) \ @@ -105,7 +106,7 @@ ItemValue* buffertop_first_raw( * @brief Set item_ to the top ("worst among best") item inside current buffer. * @param bufferTop "this" pointer. * @param item_ Variable to be assigned. - * + * * Usage: void buffertop_first(BufferTop* bufferTop, void item) */ #define buffertop_first(bufferTop, item_) \ diff --git a/src/HashTable.c b/src/HashTable.c new file mode 100644 index 0000000..7bd310c --- /dev/null +++ b/src/HashTable.c @@ -0,0 +1,163 @@ +/** + * @file HashTable.c + */ + +#include "cgds/HashTable.h" + +void _hashtable_init(HashTable* hashTable, size_t dataSize, size_t hashSize) +{ + hashTable->hashSize = hashSize; + hashTable->dataSize = dataSize; + hashTable->head = safe_malloc(hashSize * sizeof(HashCell*)); + for (UInt i = 0; i < hashSize; i++) + hashTable->head[i] = NULL; + hashTable->size = 0; +} + +HashTable* _hashtable_new(size_t dataSize, size_t hashSize) +{ + HashTable* hashTable = (HashTable*) safe_malloc(sizeof (HashTable)); + _hashtable_init(hashTable, dataSize, hashSize); + return hashTable; +} + +HashTable* hashtable_copy(HashTable* hashTable) +{ + HashTable* hashTableCopy = + _hashtable_new(hashTable->dataSize, hashTable->hashSize); + hashTableCopy->size = hashTable->size; + for (UInt i = 0; i < hashTable->hashSize; i++) + { + HashCell *cell = hashTable->head[i], + *cellCopy = hashTableCopy->head[i], + *prev = NULL; + while (cell != NULL) + { + // cellCopy == NULL (from empty list) + cellCopy = (HashCell*) safe_malloc(sizeof(HashCell*)); + cellCopy->key = (char*) safe_malloc(strlen(cell->key) + 1); + strcpy(cellCopy->key, cell->key); + cellCopy->data = safe_malloc(hashTable->dataSize); + memcpy(cellCopy->data, cell->data, hashTable->dataSize); + if (prev == NULL) hashTableCopy->head[i] = cellCopy; + else prev->next = cellCopy; + prev = cellCopy; + cell = cell->next; + } + if (cellCopy != NULL) cellCopy->next = NULL; + } + return hashTableCopy; +} + +bool hashtable_empty(HashTable* hashTable) +{ + return (hashTable->size == 0); +} + +UInt hashtable_size(HashTable* hashTable) +{ + return hashTable->size; +} + +// Function (string) key --> (integer) hash [internal usage] +UInt _compute_hash(char* key, size_t hashSize) +{ + UInt res = 0; + for (unsigned char* s = key; *s != '\0'; s++) + // NOTE: '31' from here https://stackoverflow.com/a/4384446 + res += *s + 31 * res; + return res % hashSize; +} + +void* _hashtable_get(HashTable* hashTable, char* key) +{ + UInt hashIdx = _compute_hash(key, hashTable->hashSize); + HashCell* cell = hashTable->head[hashIdx]; + while (cell != NULL) + { + if (strcmp(cell->key, key) == 0) return cell->data; + cell = cell->next; + } + return NULL; +} + +void _hashtable_set(HashTable* hashTable, char* key, void* data) +{ + UInt hashIdx = _compute_hash(key, hashTable->hashSize); + HashCell + *cell = hashTable->head[hashIdx], + *prev = NULL; + while (cell != NULL) + { + if (strcmp(cell->key, key) == 0) + { + // Modify: + memcpy(cell->data, data, hashTable->dataSize); + return; + } + prev = cell; + cell = cell->next; + } + // New element: insert after prev (which may be NULL) + HashCell* newCell = (HashCell*) safe_malloc(sizeof(HashCell)); + newCell->key = (char*) safe_malloc(strlen(key) + 1); + strcpy(newCell->key, key); + newCell->data = safe_malloc(hashTable->dataSize); + memcpy(newCell->data, data, hashTable->dataSize); + newCell->next = NULL; + if (prev == NULL) + hashTable->head[hashIdx] = newCell; + else + prev->next = newCell; + hashTable->size++; +} + +void hashtable_delete(HashTable* hashTable, char* key) +{ + UInt hashIdx = _compute_hash(key, hashTable->hashSize); + HashCell + *cell = hashTable->head[hashIdx], + *prev = NULL; + while (cell != NULL) + { + if (strcmp(cell->key, key) == 0) + { + if (prev == NULL) + hashTable->head[hashIdx] = cell->next; + else + prev->next = cell->next; + safe_free(cell->key); + safe_free(cell->data); + safe_free(cell); + hashTable->size--; + break; + } + prev = cell; + cell = cell->next; + } +} + +void hashtable_clear(HashTable* hashTable) +{ + for (UInt i = 0; i < hashTable->hashSize; i++) + { + HashCell* cell = hashTable->head[i]; + while (cell != NULL) + { + HashCell* next = cell->next; + safe_free(cell->key); + safe_free(cell->data); + safe_free(cell); + cell = next; + } + hashTable->head[i] = NULL; + } + hashTable->size = 0; +} + +void hashtable_destroy(HashTable* hashTable) +{ + hashtable_clear(hashTable); + safe_free(hashTable->head); + safe_free(hashTable); +} diff --git a/src/HashTable.h b/src/HashTable.h new file mode 100644 index 0000000..7014de3 --- /dev/null +++ b/src/HashTable.h @@ -0,0 +1,147 @@ +/** + * @file HashTable.h + */ + +#ifndef CGDS_HASH_TABLE_H +#define CGDS_HASH_TABLE_H + +#include +#include +#include "cgds/safe_alloc.h" +#include "cgds/types.h" +#include "cgds/Vector.h" + +/** + * @brief Cell of a dictionary. + */ +typedef struct HashCell { + char* key; ///< Key (as a string). + void* data; ///< Generic data contained in this cell. + struct HashCell* next; ///< Pointer to next cell in the list. +} HashCell; + +/** + * @brief Generic dictionary string --> any data. + */ +typedef struct HashTable { + UInt size; ///< Count elements in the dictionary. + size_t dataSize; ///< Size of a dict cell element in bytes. + size_t hashSize; ///< (Maximum) Number of stored hash keys. + HashCell** head; ///< Pointers to the first cell in a list. +} HashTable; + +/** + * @brief Initialize an empty dictionary. + */ +void _hashtable_init( + HashTable* hashTable, ///< "this" pointer. + size_t dataSize, ///< Size in bytes of a dictionary element. + size_t hashSize ///< (Maximum) Number of stored hash keys. +); + +/** + * @brief Return an allocated and initialized dictionary. + */ +HashTable* _hashtable_new( + size_t dataSize, ///< Size in bytes of a dictionary element. + size_t hashSize ///< (Maximum) Number of stored hash keys. +); + +/** + * @brief Return an allocated and initialized vector. + * @param type Type of a vector element (int, char*, ...). + * + * Usage: HashTable* hashtable_new( type, UInt hash_size) + */ +#define hashtable_new(type, hsize) \ + _hashtable_new(sizeof(type), hsize) + +/** + * @brief Copy constructor (shallow copy, ok for basic types). + */ +HashTable* hashtable_copy( + HashTable* hashTable ///< "this" pointer. +); + +/** + * @brief Check if the dictionary is empty. + */ +bool hashtable_empty( + HashTable* hastTable ///< "this" pointer. +); + +/** + * @brief Return current size. + */ +UInt hashtable_size( + HashTable* hastTable ///< "this" pointer. +); + +/** + * @brief Lookup element of given key. + */ +void* _hashtable_get( + HashTable* hashTable, ///< "this" pointer. + char* key ///< Key of the element to retrieve. +); + +/** + * @brief Lookup element of given key. + * @param hashTable "this" pointer. + * @param key Key of the element to retrieve.. + * @param data 'out' variable to contain the result. + * + * Usage: void hashtable_get(HashTable* hashTable, char* key, void data) + */ +#define hashtable_get(hashTable, key, data) \ +{ \ + void* pData = _hashtable_get(hashTable, key); \ + data = *((typeof(&data))pData); \ +} + +/** + * @brief Add the entry (key, value) to dictionary. + */ +void _hashtable_set( + HashTable* hashTable, ///< "this" pointer. + char* key, ///< Key of the element to add or modify. + void* data ///< Pointer to new data at given key. +); + +/** + * @brief Add the entry (key, value) to dictionary. + * @param hashTable "this" pointer. + * @param key Key of the element to add or modify. + * @param data New data at given key. + * + * Usage: void hashtable_set(HashTable* hashTable, char* key, void data) + */ +#define hashtable_set(hashTable, key, data) \ +{ \ + typeof((data)) tmp = data; \ + _hashtable_set(hashTable, key, &tmp); \ +} + +/** + * @brief Remove the given key (+ associated value). + */ +void hashtable_delete( + HashTable* hashTable, ///< "this" pointer. + char* key ///< Key of the element to delete. +); + +/** + * @brief Clear the entire dictionary. + */ +void hashtable_clear( + HashTable* hashTable ///< "this" pointer. +); + +/** + * @brief Destroy the dictionary: clear it, and free hashes array. + */ +void hashtable_destroy( + HashTable* hashTable ///< "this" pointer. +); + +#endif diff --git a/src/Heap.c b/src/Heap.c index 659e539..fd41a09 100644 --- a/src/Heap.c +++ b/src/Heap.c @@ -19,23 +19,28 @@ Heap* _heap_new(size_t dataSize, OrderType hType, UInt arity) Heap* heap_copy(Heap* heap) { Heap* heapCopy = _heap_new(heap->dataSize, heap->hType, heap->arity); - // HACK: vector_copy is not enough, since we also have to allocate ItemValue(->item) + // HACK: vector_copy is not enough, + // since we also have to allocate ItemValue(->item) heapCopy->array->size = heap->array->size; heapCopy->array->capacity = heap->array->capacity; - heapCopy->array->datas = (void**)safe_malloc(heap->array->capacity*sizeof(void*)); + heapCopy->array->datas = + (void**)safe_malloc(heap->array->capacity*sizeof(void*)); for (UInt i=0; iarray->size; i++) { heapCopy->array->datas[i] = safe_malloc(sizeof(ItemValue)); ItemValue itemValueCopy = (ItemValue){ - .item=safe_malloc(heap->dataSize), + .item=safe_malloc(heap->dataSize), .value=((ItemValue*)(heap->array->datas[i]))->value}; - memcpy(itemValueCopy.item, ((ItemValue*)(heap->array->datas[i]))->item, heap->dataSize); + memcpy( + itemValueCopy.item, + ((ItemValue*)(heap->array->datas[i]))->item, + heap->dataSize); memcpy(heapCopy->array->datas[i], &itemValueCopy, sizeof(ItemValue)); } return heapCopy; } -Bool heap_empty(Heap* heap) +bool heap_empty(Heap* heap) { return vector_empty(heap->array); } @@ -45,22 +50,22 @@ UInt heap_size(Heap* heap) return vector_size(heap->array); } -// NOTE: [perf] in two following methods, full heap[k] exchanges are not needed; -// we keep track of the moving element without assigning it at every step, -// thus saving array accesses and affectations + 'aux' temp. memory. +// NOTE: [perf] in two following methods, full heap[k] exchanges are +// not needed; we keep track of the moving element without assigning it at +// every step, thus saving array accesses and affectations + 'aux' tmp memory. // --> this is not the most natural way of writing these functions. void _heap_bubble_up(Heap* heap, UInt startIndex) { UInt currentIndex = startIndex; ItemValue* startItemValue = heap->array->datas[startIndex]; - while (C_TRUE) + while (true) { // get parent UInt nextIndex = currentIndex / heap->arity; Real nextValue = ((ItemValue*)(heap->array->datas[nextIndex]))->value; // compare to parent (if applicable) - if (currentIndex == 0 || + if (currentIndex == 0 || (heap->hType == MIN_T && startItemValue->value >= nextValue) || (heap->hType == MAX_T && startItemValue->value <= nextValue)) { @@ -78,7 +83,7 @@ void _heap_bubble_down(Heap* heap, UInt startIndex) { UInt currentIndex = startIndex; ItemValue* startItemValue = heap->array->datas[startIndex]; - while (C_TRUE) + while (true) { if (currentIndex * heap->arity >= heap->array->size) { @@ -121,7 +126,8 @@ void _heap_bubble_down(Heap* heap, UInt startIndex) void _heap_insert(Heap* heap, void* item, Real value) { - ItemValue itemValue = (ItemValue){.item=safe_malloc(heap->dataSize), .value=value}; + ItemValue itemValue = + (ItemValue){.item=safe_malloc(heap->dataSize), .value=value}; memcpy(itemValue.item, item, heap->dataSize); _vector_push(heap->array, &itemValue); _heap_bubble_up(heap, heap->array->size-1); @@ -136,7 +142,7 @@ void _heap_modify(Heap* heap, UInt index, Real newValue) { _heap_bubble_down(heap, index); } - else + else _heap_bubble_up(heap, index); } @@ -147,7 +153,7 @@ void _heap_remove(Heap* heap, UInt index) heap->array->datas[index] = heap->array->datas[heap_size(heap)-1]; heap->array->datas[heap_size(heap)-1] = tmp; vector_pop(heap->array); - if (heap->array->size > 0) + if (heap->array->size > 0) _heap_bubble_down(heap, index); } diff --git a/src/Heap.h b/src/Heap.h index 895eb32..c17cb73 100644 --- a/src/Heap.h +++ b/src/Heap.h @@ -36,14 +36,14 @@ Heap* _heap_new( * @param type Type of a buffer item (int, char*, ...). * @param hType Type of heap: max first (MAX_T) or min first (MIN_T). * @param arity Arity of the underlying tree. - * + * * Usage: Heap* heap_new( type, OrderType hType, UInt arity) */ #define heap_new(type, hType, arity) \ _heap_new(sizeof(type), hType, arity) /** - * @brief Copy constructor (works well if items do not have allocated sub-pointers). + * @brief Copy constructor (shallow copy, ok for basic types). */ Heap* heap_copy( Heap* heap ///< "this" pointer. @@ -52,7 +52,7 @@ Heap* heap_copy( /** * @brief Check if the heap is empty. */ -Bool heap_empty( +bool heap_empty( Heap* heap ///< "this" pointer. ); @@ -64,7 +64,8 @@ UInt heap_size( ); /** - * @brief "Bubble up" an item-value inserted somewhere in the tree in O(log(n)) operations. + * @brief "Bubble up" an item-value inserted somewhere in the tree + * in O(log(n)) operations. */ void _heap_bubble_up( Heap* heap, ///< "this" pointer. @@ -72,7 +73,8 @@ void _heap_bubble_up( ); /** - * @brief "Bubble down" an item-value inserted somewhere in the tree in O(log(n)) operations. + * @brief "Bubble down" an item-value inserted somewhere in the tree + * in O(log(n)) operations. */ void _heap_bubble_down( Heap* heap, ///< "this" pointer. @@ -93,7 +95,7 @@ void _heap_insert( * @param heap "this" pointer. * @param item Item of type as defined in the constructor. * @param value Value associated with the item. - * + * * Usage: void heap_insert(Heap* heap, void item, Real value) */ #define heap_insert(heap, item, value) \ @@ -117,7 +119,7 @@ void _heap_modify( * @param item_ Item to modify. * @param newValue New value for the item. * @note If several similar items are present, only the first is affected. - * + * * Usage: void heap_modify(Heap* heap, void item_, Real newValue) * WARNING: does not work if items are not basic type nor pointers. */ @@ -146,7 +148,7 @@ void _heap_remove( * @param heap "this" pointer. * @param item_ Item to remove. * @note If several similar items are present, only the first is deleted. - * + * * Usage: void heap_remove(Heap* heap, void item_) * WARNING: does not work if items are not basic type nor pointers. */ @@ -173,7 +175,7 @@ ItemValue* heap_top_raw( * @brief Return what is at the beginning of the heap. * @param heap "this" pointer. * @param item_ Item to be assigned. - * + * * Usage: void heap_top(Heap* heap, void item_) */ #define heap_top(heap, item_) \ diff --git a/src/List.c b/src/List.c index d34fc92..0d4c113 100644 --- a/src/List.c +++ b/src/List.c @@ -35,7 +35,7 @@ List* list_copy(List* list) return listCopy; } -Bool list_empty(List* list) +bool list_empty(List* list) { return (list->size == 0); } @@ -115,13 +115,13 @@ void _list_insert_back(List* list, void* data) void list_remove(List* list, ListCell* listCell) { - if (listCell->prev != NULL) + if (listCell->prev != NULL) listCell->prev->next = listCell->next; - else + else list->head = listCell->next; - if (listCell->next != NULL) + if (listCell->next != NULL) listCell->next->prev = listCell->prev; - else + else list->tail = listCell->prev; safe_free(listCell->data); safe_free(listCell); @@ -180,7 +180,7 @@ void listI_reset_tail(ListIterator* listI) listI->current = listI->list->tail; } -Bool listI_has_data(ListIterator* listI) +bool listI_has_data(ListIterator* listI) { return (listI->current != NULL); } diff --git a/src/List.h b/src/List.h index 3e1c4ad..0a36ea0 100644 --- a/src/List.h +++ b/src/List.h @@ -28,7 +28,7 @@ typedef struct ListCell { */ typedef struct List { UInt size; ///< Count elements in the list. - size_t dataSize; ///< Size of a list cell elements in bytes. + size_t dataSize; ///< Size of a list cell element in bytes. ListCell* head; ///< Pointer to the first cell in the list. ListCell* tail; ///< Pointer to the last cell in the list. } List; @@ -52,14 +52,14 @@ List* _list_new( /** * @brief Return an allocated and initialized list. * @param type Type of a list element (int, char*, ...). - * + * * Usage: List* list_new( type) */ #define list_new(type) \ _list_new(sizeof(type)) /** - * @brief Copy constructor (works well if items do not have allocated sub-pointers). + * @brief Copy constructor (shallow copy, ok for basic types). */ List* list_copy( List* list ///< "this" pointer. @@ -68,7 +68,7 @@ List* list_copy( /** * @brief Check if the list is empty. */ -Bool list_empty( +bool list_empty( List* list ///< "this" pointer. ); @@ -90,7 +90,7 @@ void* _list_get( * @brief Get data at the given list cell argument. * @param listCell Pointer to a cell inside "this" list. * @param data Data to be assigned. - * + * * Usage: void list_get(ListCell* listCell, void data) */ #define list_get(listCell, data) \ @@ -113,7 +113,7 @@ void _list_set( * @param list "this" pointer. * @param listCell Pointer to a cell inside "this" list. * @param data Data to be set. - * + * * Usage: void list_set(List* list, ListCell* listCell, void data); */ #define list_set(list, listCell, data) \ @@ -144,7 +144,7 @@ void _list_insert_before( * @param list "this" pointer. * @param listCell Pointer to a cell inside "this" list. * @param data Data to be inserted. - * + * * Usage: void list_insert_before(List* list, ListCell* listCell, void data) */ #define list_insert_before(list, listCell, data) \ @@ -167,7 +167,7 @@ void _list_insert_after( * @param list "this" pointer. * @param listCell Pointer to a cell inside "this" list. * @param data Data to be inserted. - * + * * Usage: void list_insert_after(List* list, ListCell* listCell, void data) */ #define list_insert_after(list, listCell, data) \ @@ -188,7 +188,7 @@ void _list_insert_front( * @brief Add data at the beginning of the list. * @param list "this" pointer. * @param data Data to be inserted. - * + * * Usage: void list_insert_front(List* list, void data) */ #define list_insert_front(list, data) \ @@ -209,7 +209,7 @@ void _list_insert_back( * @brief Add data at the end of the list. * @param list "this" pointer. * @param data Data to be inserted. - * + * * Usage: void list_insert_back(List* list, void data) */ #define list_insert_back(list, data) \ @@ -218,7 +218,7 @@ void _list_insert_back( _list_insert_back(list, &tmp); \ } -/** +/** * @brief Remove data at position given by 'listCell'. */ void list_remove( @@ -290,7 +290,7 @@ void listI_reset_tail( /** * @brief Tell if there is some data at the current index. */ -Bool listI_has_data( +bool listI_has_data( ListIterator* listI ///< "this" pointer. ); @@ -298,7 +298,7 @@ Bool listI_has_data( * @brief Return data contained in the current list cell. * @param listI "this" pointer. * @param data Data to be assigned. - * + * * Usage: void listI_get(ListIterator* listI, void data) */ #define listI_get(listI, data) \ @@ -308,8 +308,8 @@ Bool listI_has_data( * @brief Set data at the current iterator position. * @param listI "this" pointer * @param data Data to assign. - * - * Usage: void listI_set(ListIterator* listI, void data); + * + * Usage: void listI_set(ListIterator* listI, void data); */ #define listI_set(listI, data) \ list_set(listI->list, listI->current, data) @@ -318,7 +318,7 @@ Bool listI_has_data( * @brief Add data before current list cell. * @param listI "this" pointer * @param data Data to be inserted. - * + * * Usage: void listI_insert_before(ListIteratorI* listI, void data) */ #define listI_insert_before(listI, data) \ @@ -328,7 +328,7 @@ Bool listI_has_data( * @brief Add data after current list cell. * @param listI "this" pointer * @param data Data to be inserted. - * + * * Usage: void listI_insert_after(ListIteratorI* listI, void data) */ #define listI_insert_after(listI, data) \ diff --git a/src/PriorityQueue.c b/src/PriorityQueue.c index 5606db3..f0b71e4 100644 --- a/src/PriorityQueue.c +++ b/src/PriorityQueue.c @@ -4,11 +4,13 @@ #include "cgds/PriorityQueue.h" -// NOTE: no _init() method here, since PriorityQueue has no specific initialization +// NOTE: no _init() method here, +// since PriorityQueue has no specific initialization PriorityQueue* _priorityqueue_new(size_t dataSize, OrderType pType, UInt arity) { - PriorityQueue* priorityQueue = (PriorityQueue*) safe_malloc(sizeof (PriorityQueue)); + PriorityQueue* priorityQueue = + (PriorityQueue*) safe_malloc(sizeof (PriorityQueue)); Heap* heap = _heap_new(dataSize, pType, arity); priorityQueue->heap = heap; return priorityQueue; @@ -24,7 +26,7 @@ PriorityQueue* priorityqueue_copy(PriorityQueue* priorityQueue) return priorityQueueCopy; } -Bool priorityqueue_empty(PriorityQueue* priorityQueue) +bool priorityqueue_empty(PriorityQueue* priorityQueue) { return heap_empty(priorityQueue->heap); } diff --git a/src/PriorityQueue.h b/src/PriorityQueue.h index a543dd8..59fe511 100644 --- a/src/PriorityQueue.h +++ b/src/PriorityQueue.h @@ -23,23 +23,24 @@ typedef struct PriorityQueue { */ PriorityQueue* _priorityqueue_new( size_t dataSize, ///< Size in bytes of a priority queue element. - OrderType pType, ///< Type of priority queue: max first (hType==MAX_T) or min first (hType==MIN_T). + OrderType pType, ///< Type of priority queue: max or min first (MAX_T or MIN_T). UInt arity ///< Arity of the wrapped heap: any integer >=2. ); /** * @brief Return an allocated and initialized Queue. * @param type Type of a priority queue item (int, char*, ...). - * @param pType type of priority queue: max first (hType==MAX_T) or min first (hType==MIN_T). + * @param pType type of priority queue: max or min first (MAX_T or MIN_T). * @param arity Arity of the wrapped heap: any integer >=2. - * - * Usage: PriorityQueue* priorityqueue_new( type, OrderType pType, UInt arity) + * + * Usage: PriorityQueue* priorityqueue_new(\ + * type, OrderType pType, UInt arity) */ #define priorityqueue_new(type, pType, arity) \ _priorityqueue_new(sizeof(type), pType, arity) /** - * @brief Copy constructor (works well if items do not have allocated sub-pointers). + * @brief Copy constructor (shallow copy, ok for basic types). */ PriorityQueue* priorityqueue_copy( PriorityQueue* priorityQueue ///< "this" pointer. @@ -48,7 +49,7 @@ PriorityQueue* priorityqueue_copy( /** * @brief Check if the priority queue is empty. */ -Bool priorityqueue_empty( +bool priorityqueue_empty( PriorityQueue* priorityQueue ///< "this" pointer. ); @@ -64,8 +65,9 @@ UInt priorityqueue_size( * @param priorityQueue "this" pointer. * @param item Item to be added. * @param priority Priority of the added item. - * - * Usage: void priorityqueue_insert(PriorityQueue* priorityQueue, void item, Real priority) + * + * Usage: void priorityqueue_insert(\ + * PriorityQueue* priorityQueue, void item, Real priority) */ #define priorityqueue_insert(priorityQueue, item, priority) \ heap_insert(priorityQueue->heap, item, priority) @@ -76,8 +78,9 @@ UInt priorityqueue_size( * @param item Item to be modified. * @param newPriority New priority of the modified item. * @note If several similar items are present, only the first is affected. - * - * Usage: void priorityqueue_set_priority(PriorityQueue* priorityQueue, void item, Real newPriority) + * + * Usage: void priorityqueue_set_priority(\ + * PriorityQueue* priorityQueue, void item, Real newPriority) */ #define priorityqueue_set(priorityQueue, item, newPriority) \ heap_modify(priorityQueue->heap, item, newPriority) @@ -87,7 +90,7 @@ UInt priorityqueue_size( * @param priorityQueue "this" pointer. * @param item Item to be removed. * @note If several similar items are present, only the first is deleted. - * + * * Usage: void priorityqueue_remove(PriorityQueue* priorityQueue, void item) */ #define priorityqueue_remove(priorityQueue, item) \ @@ -95,7 +98,7 @@ UInt priorityqueue_size( /** * @brief Return what is at the beginning of the queue. - * @return An ItemValue* 'iv' with iv->item is the data, and iv->value its priority. + * @return An ItemValue* 'iv' with iv->item = data, and iv->value its priority. */ ItemValue* priorityqueue_peek_raw( PriorityQueue* priorityQueue ///< "this" pointer. @@ -105,7 +108,7 @@ ItemValue* priorityqueue_peek_raw( * @brief Peek the item at the beginning of the queue. * @param priorityQueue "this" pointer. * @param item Item to be assigned. - * + * * Usage: void priorityqueue_peek(PriorityQueue* priorityQueue, void item) */ #define priorityqueue_peek(priorityQueue, item) \ @@ -118,7 +121,7 @@ void priorityqueue_pop( PriorityQueue* priorityQueue ///< "this" pointer. ); -/** +/** * @brief Clear the entire queue. */ void priorityqueue_clear( diff --git a/src/Queue.c b/src/Queue.c index 3e61381..0303505 100644 --- a/src/Queue.c +++ b/src/Queue.c @@ -27,7 +27,7 @@ Queue* queue_copy(Queue* queue) return queueCopy; } -Bool queue_empty(Queue* queue) +bool queue_empty(Queue* queue) { return list_empty(queue->list); } diff --git a/src/Queue.h b/src/Queue.h index 0cd9766..9aae379 100644 --- a/src/Queue.h +++ b/src/Queue.h @@ -30,24 +30,24 @@ void _queue_init( size_t dataSize ///< Size in bytes of a queue element. ); -/** +/** * @brief Return an allocated and initialized queue. */ Queue* _queue_new( size_t dataSize ///< Size in bytes of a queue element. ); -/** +/** * @brief Return an allocated and initialized queue. * @param type Type of a queue element (int, char*, ...). - * + * * Usage: Queue* queue_new( type) */ #define queue_new(type) \ _queue_new(sizeof(type)) /** - * @brief Copy constructor (works well if items do not have allocated sub-pointers). + * @brief Copy constructor (shallow copy, ok for basic types). */ Queue* queue_copy( Queue* queue ///< "this" pointer. @@ -56,7 +56,7 @@ Queue* queue_copy( /** * @brief Check if the queue is empty. */ -Bool queue_empty( +bool queue_empty( Queue* queue ///< "this" pointer. ); @@ -79,7 +79,7 @@ void _queue_push( * @brief Add something at the end of the queue. * @param queue "this" pointer * @param data Data to be pushed. - * + * * Usage: void queue_push(Queue* queue, void data) */ #define queue_push(queue, data) \ @@ -99,7 +99,7 @@ void* _queue_peek( * @brief Return what is at the beginning of the queue. * @param queue "this" pointer. * @param data Data to be assigned. - * + * * Usage: void queue_peek(Queue* queue, void data) */ #define queue_peek(queue, data) \ diff --git a/src/Stack.c b/src/Stack.c index 8aa7800..92457c0 100644 --- a/src/Stack.c +++ b/src/Stack.c @@ -27,7 +27,7 @@ Stack* stack_copy(Stack* stack) return stackCopy; } -Bool stack_empty(Stack* stack) +bool stack_empty(Stack* stack) { return vector_empty(stack->array); } diff --git a/src/Stack.h b/src/Stack.h index c314c28..24ad176 100644 --- a/src/Stack.h +++ b/src/Stack.h @@ -27,24 +27,24 @@ void _stack_init( size_t dataSize ///< Size in bytes of a stack element. ); -/** +/** * @brief Return an allocated and initialized stack. */ Stack* _stack_new( size_t dataSize ///< Size in bytes of a stack element. ); -/** +/** * @brief Return an allocated and initialized stack. * @param type Type of a stack element (int, char*, ...). - * + * * Usage: Stack* stack_new( type) */ #define stack_new(type) \ _stack_new(sizeof(type)) /** - * @brief Copy constructor (works well if items do not have allocated sub-pointers). + * @brief Copy constructor (shallow copy, ok for basic types). */ Stack* stack_copy( Stack* stack ///< "this" pointer. @@ -53,7 +53,7 @@ Stack* stack_copy( /** * @brief Check if the stack is empty. */ -Bool stack_empty( +bool stack_empty( Stack* stack ///< "this" pointer. ); @@ -76,7 +76,7 @@ void _stack_push( * @brief Add something on top of the stack. * @param stack "this" pointer. * @param data Data to be added. - * + * * Usage: void stack_push(Stack* stack, void data) */ #define stack_push(stack, data) \ @@ -96,7 +96,7 @@ void* _stack_top( * @brief Return what is on top of the stack. * @param stack "this" pointer. * @param data Data to be assigned. - * + * * Usage: void stack_top(Stack* stack, void data) */ #define stack_top(stack, data) \ diff --git a/src/Tree.c b/src/Tree.c index fe21a6b..1ee3b51 100644 --- a/src/Tree.c +++ b/src/Tree.c @@ -25,7 +25,7 @@ Tree* _tree_new(size_t dataSize) Tree* tree_copy(Tree* tree) { Tree* treeCopy = _tree_new(tree->dataSize); - if (tree->root == NULL) + if (tree->root == NULL) return treeCopy; _tree_set_root(treeCopy, tree->root->data); @@ -88,7 +88,7 @@ Tree* tree_copy(Tree* tree) return treeCopy; } -Bool tree_empty(Tree* tree) +bool tree_empty(Tree* tree) { return (tree->root == NULL); } @@ -100,14 +100,14 @@ UInt tree_size(Tree* tree) UInt _tree_height_rekursiv(TreeNode* treeNode) { - if (tree_is_leaf(treeNode)) + if (tree_is_leaf(treeNode)) return 1; TreeNode* child = treeNode->firstChild; UInt maxHeightChild = 0; while (child != NULL) { UInt heightChild = _tree_height_rekursiv(child); - if (heightChild > maxHeightChild) + if (heightChild > maxHeightChild) maxHeightChild = heightChild; child = child->next; } @@ -116,12 +116,12 @@ UInt _tree_height_rekursiv(TreeNode* treeNode) UInt tree_height(Tree* tree) { - if (tree_empty(tree)) + if (tree_empty(tree)) return 0; return _tree_height_rekursiv(tree->root); } -Bool tree_is_leaf(TreeNode* treeNode) +bool tree_is_leaf(TreeNode* treeNode) { return (treeNode->firstChild == NULL); } @@ -155,11 +155,11 @@ void _tree_add_child(Tree* tree, TreeNode* treeNode, void* data) newChildNode->data = safe_malloc(tree->dataSize); memcpy(newChildNode->data, data, tree->dataSize); newChildNode->next = NULL; - if (treeNode->lastChild != NULL) + if (treeNode->lastChild != NULL) treeNode->lastChild->next = newChildNode; newChildNode->prev = treeNode->lastChild; treeNode->lastChild = newChildNode; - if (treeNode->firstChild == NULL) + if (treeNode->firstChild == NULL) treeNode->firstChild = newChildNode; newChildNode->parent = treeNode; newChildNode->firstChild = NULL; @@ -173,7 +173,7 @@ void _tree_add_sibling(Tree* tree, TreeNode* treeNode, void* data) newSiblingNode->data = safe_malloc(tree->dataSize); memcpy(newSiblingNode->data, data, tree->dataSize); newSiblingNode->next = treeNode->next; - if (treeNode->next != NULL) + if (treeNode->next != NULL) treeNode->next->prev = newSiblingNode; newSiblingNode->prev = treeNode; treeNode->next = newSiblingNode; @@ -201,14 +201,14 @@ void tree_remove(Tree* tree, TreeNode* treeNode) { if (treeNode->parent != NULL) { - if (treeNode->prev == NULL) + if (treeNode->prev == NULL) treeNode->parent->firstChild = treeNode->next; - if (treeNode->next == NULL) + if (treeNode->next == NULL) treeNode->parent->lastChild = treeNode->prev; } - if (treeNode->next != NULL) + if (treeNode->next != NULL) treeNode->next->prev = treeNode->prev; - if (treeNode->prev != NULL) + if (treeNode->prev != NULL) treeNode->prev->next = treeNode->next; _tree_remove_rekursiv(tree, treeNode); } @@ -228,14 +228,14 @@ void tree_rm_childs(Tree* tree, TreeNode* treeNode) void tree_clear(Tree* tree) { - if (tree->root != NULL) + if (tree->root != NULL) _tree_remove_rekursiv(tree, tree->root); _tree_init(tree, tree->dataSize); } void tree_destroy(Tree* tree) { - if (tree->root != NULL) + if (tree->root != NULL) tree_clear(tree); safe_free(tree); } @@ -258,7 +258,7 @@ void treeI_reset(TreeIterator* treeI) treeI->current = treeI->tree->root; } -Bool treeI_has_data(TreeIterator* treeI) +bool treeI_has_data(TreeIterator* treeI) { return (treeI->current != NULL); } diff --git a/src/Tree.h b/src/Tree.h index 3fa66fc..617ea15 100644 --- a/src/Tree.h +++ b/src/Tree.h @@ -53,14 +53,14 @@ Tree* _tree_new( /** * @brief Return an allocated and initialized tree. * @param type Type at a tree node (int, char*, ...). - * + * * Usage: Tree* tree_new( type) */ #define tree_new(type) \ _tree_new(sizeof(type)) /** - * @brief Copy constructor (works well if items do not have allocated sub-pointers). + * @brief Copy constructor (shallow copy, ok for basic types). */ Tree* tree_copy( Tree* tree ///< "this" pointer. @@ -69,7 +69,7 @@ Tree* tree_copy( /** * @brief Check if the tree is empty. */ -Bool tree_empty( +bool tree_empty( Tree* tree ///< "this" pointer. ); @@ -97,7 +97,7 @@ UInt tree_height( /** * @brief Check if a sub-tree is a leaf (without children). */ -Bool tree_is_leaf( +bool tree_is_leaf( TreeNode* treeNode ///< Pointer to a node in the "this" tree. ); @@ -113,7 +113,7 @@ void _tree_set_root( * @brief Initialize tree root when the tree is empty. * @param tree "this" pointer. * @param data Data to be assigned. - * + * * Usage: void tree_set_root(Tree* tree, void data) */ #define tree_set_root(tree, data) \ @@ -133,7 +133,7 @@ void* _tree_get( * @brief Retrieve data contained in a given tree node. * @param treeNode Pointer to a node in the "this" tree. * @param data Data to be assigned. - * + * * Usage: void tree_get(TreeNode* treeNode, void data) */ #define tree_get(treeNode, data) \ @@ -156,7 +156,7 @@ void _tree_set( * @param tree "this" pointer. * @param treeNode Pointer to a node in the "this" tree. * @param data Data to be assigned. - * + * * Usage: void tree_set(Tree* tree, TreeNode* treeNode, void data) */ #define tree_set(tree, treeNode, data) \ @@ -179,7 +179,7 @@ void _tree_add_child( * @param tree "this" pointer. * @param treeNode Pointer to a node in the "this" tree. * @param data Data to be added. - * + * * Usage: void tree_add_child(Tree* tree, TreeNode* treeNode, void data) */ #define tree_add_child(tree,treeNode,data) \ @@ -202,7 +202,7 @@ void _tree_add_sibling( * @param tree "this" pointer. * @param treeNode Pointer to a node in the "this" tree. * @param data Data to be added. - * + * * Usage: void tree_add_sibling(Tree* tree, TreeNode* treeNode, void data) */ #define tree_add_sibling(tree, treeNode, data) \ @@ -288,7 +288,7 @@ void treeI_reset( /** * @brief Tell if there is some data at the current index. */ -Bool treeI_has_data( +bool treeI_has_data( TreeIterator* treeI ///< "this" pointer. ); @@ -303,7 +303,7 @@ TreeNode* treeI_get_raw( * @brief Get data at current tree node. * @param treeI "this" pointer. * @param data Data to be assigned. - * + * * Usage: void treeI_get(TreeIterator* treeI, void data) */ #define treeI_get(treeI, data) \ @@ -313,7 +313,7 @@ TreeNode* treeI_get_raw( * @brief Set (alter) data at current tree node. * @param treeI "this" pointer. * @param data Data to be assigned. - * + * * Usage: void treeI_set(TreeIterator* treeI, void data) */ #define treeI_set(treeI, data) \ diff --git a/src/Vector.c b/src/Vector.c index 2d00985..042e75c 100644 --- a/src/Vector.c +++ b/src/Vector.c @@ -1,5 +1,5 @@ /** - * @file Vector.cpp + * @file Vector.c */ #include "cgds/Vector.h" @@ -37,7 +37,7 @@ Vector* vector_copy(Vector* vector) return vectorCopy; } -Bool vector_empty(Vector* vector) +bool vector_empty(Vector* vector) { return (vector->size == 0); } @@ -112,7 +112,8 @@ void vector_destroy(Vector* vector) VectorIterator* vector_get_iterator(Vector* vector) { - VectorIterator* vectorI = (VectorIterator*) safe_malloc(sizeof (VectorIterator)); + VectorIterator* vectorI = + (VectorIterator*) safe_malloc(sizeof (VectorIterator)); vectorI->vector = vector; vectorI_reset_begin(vectorI); return vectorI; @@ -128,7 +129,7 @@ void vectorI_reset_end(VectorIterator* vectorI) vectorI->current = vectorI->vector->datas + vectorI->vector->size - 1; } -Bool vectorI_has_data(VectorIterator* vectorI) +bool vectorI_has_data(VectorIterator* vectorI) { return (vectorI->current >= vectorI->vector->datas && vectorI->current < vectorI->vector->datas + vectorI->vector->size); diff --git a/src/Vector.h b/src/Vector.h index d3fe04c..f6060f8 100644 --- a/src/Vector.h +++ b/src/Vector.h @@ -42,14 +42,14 @@ Vector* _vector_new( /** * @brief Return an allocated and initialized vector. * @param type Type of a vector element (int, char*, ...). - * + * * Usage: Vector* vector_new( type) */ #define vector_new(type) \ _vector_new(sizeof(type)) /** - * @brief Copy constructor (works well if items do not have allocated sub-pointers). + * @brief Copy constructor (shallow copy, ok for basic types). */ Vector* vector_copy( Vector* vector ///< "this" pointer. @@ -58,7 +58,7 @@ Vector* vector_copy( /** * @brief Check if the vector is empty. */ -Bool vector_empty( +bool vector_empty( Vector* vector ///< "this" pointer. ); @@ -89,7 +89,7 @@ void _vector_push( * @brief Add data at the end. * @param vector "this" pointer. * @param data Data to be added. - * + * * Usage: void vector_push(Vector* vector, void data) */ #define vector_push(vector, data) \ @@ -118,7 +118,7 @@ void* _vector_get( * @param vector "this" pointer. * @param index Index of the element to retrieve. * @param data 'out' variable to contain the result. - * + * * Usage: void vector_get(Vector* vector, size_t index, void data) */ #define vector_get(vector, index, data) \ @@ -141,7 +141,7 @@ void _vector_set( * @param vector "this" pointer. * @param index Index of the element to be modified. * @param data New data at given index. - * + * * Usage: void vector_set(Vector* vector, size_t index, void data) */ #define vector_set(vector, index, data) \ @@ -200,7 +200,7 @@ void vectorI_reset_end( /** * @brief Tell if there is some data at the current index. */ -Bool vectorI_has_data( +bool vectorI_has_data( VectorIterator* vectorI ///< "this" pointer. ); @@ -215,7 +215,7 @@ void* _vectorI_get( * @brief Get data contained at the current index. * @param vectorI "this" pointer. * @param data 'out' variable to contain the result. - * + * * Usage: void vectorI_get(VectorIterator* vectorI, void data); */ #define vectorI_get(vectorI, data) \ @@ -236,7 +236,7 @@ void _vectorI_set( * @brief Set the element at current index. * @param vectorI "this" pointer. * @param data Data to be assigned. - * + * * Usage: void vectorI_set(VectorIterator* vectorI, void data) */ #define vectorI_set(vectorI, data) \ diff --git a/src/cds.h b/src/cgds.h similarity index 82% rename from src/cds.h rename to src/cgds.h index 89e6e79..6533a7e 100644 --- a/src/cds.h +++ b/src/cgds.h @@ -1,7 +1,9 @@ #ifndef LIBCGDS_H #define LIBCGDS_H +// To include everything: #include +#include #include #include #include diff --git a/src/safe_alloc.c b/src/safe_alloc.c index 9d1de7e..dcb8c33 100644 --- a/src/safe_alloc.c +++ b/src/safe_alloc.c @@ -39,6 +39,6 @@ void* safe_realloc(void* ptr, size_t size) void safe_free(void* ptr) { - if (ptr != NULL) + if (ptr != NULL) free(ptr); } diff --git a/src/types.h b/src/types.h index 99b6d2c..f202b26 100644 --- a/src/types.h +++ b/src/types.h @@ -8,6 +8,7 @@ #include #include +#include /** * @brief Signed integer type. @@ -24,14 +25,6 @@ typedef uint64_t UInt; */ typedef double Real; -/** - * @brief Boolean type (prefixed with C_ to avoid some conflicts). - */ -typedef enum { - C_FALSE = 0, ///< False is mapped to 0 - C_TRUE = 1 ///< True is mapped to 1 -} Bool; - /** * @brief Enumeration for the type of buffer or heap. */ diff --git a/test/lut.h b/test/lut.h index 821feb3..e41e9c9 100644 --- a/test/lut.h +++ b/test/lut.h @@ -13,10 +13,12 @@ #define _lu_assert_int(X, OP, Y) do { \ int _lu_x = (X); \ int _lu_y = (Y); \ - lu_assert_msg(_lu_x OP _lu_y, "Assertion '"#X#OP#Y"' failed: "#X"==%i, "#Y"==%i\n", _lu_x, _lu_y); \ + lu_assert_msg(_lu_x OP _lu_y, \ + "Assertion '"#X#OP#Y"' failed: "#X"==%i, "#Y"==%i\n", \ + _lu_x, _lu_y); \ } while (0) -#define lu_assert_int_eq(X, Y) _lu_assert_int(X, ==, Y) -#define lu_assert_int_ne(X, Y) _lu_assert_int(X, !=, Y) +#define lu_assert_int_eq(X, Y) _lu_assert_int(X, ==, Y) +#define lu_assert_int_ne(X, Y) _lu_assert_int(X, !=, Y) #define lu_assert_int_lt(X, Y) _lu_assert_int(X, <, Y) #define lu_assert_int_le(X, Y) _lu_assert_int(X, <=, Y) #define lu_assert_int_gt(X, Y) _lu_assert_int(X, >, Y) @@ -25,10 +27,12 @@ #define _lu_assert_dbl(X, OP, Y) do { \ double _lu_x = (X); \ double _lu_y = (Y); \ - lu_assert_msg(_lu_x OP _lu_y, "Assertion '"#X#OP#Y"' failed: "#X"==%g, "#Y"==%g", _lu_x, _lu_y); \ + lu_assert_msg(_lu_x OP _lu_y, \ + "Assertion '"#X#OP#Y"' failed: "#X"==%g, "#Y"==%g", \ + _lu_x, _lu_y); \ } while (0) -#define lu_assert_dbl_eq(X, Y) _lu_assert_dbl(X, ==, Y) -#define lu_assert_dbl_ne(X, Y) _lu_assert_dbl(X, !=, Y) +#define lu_assert_dbl_eq(X, Y) _lu_assert_dbl(X, ==, Y) +#define lu_assert_dbl_ne(X, Y) _lu_assert_dbl(X, !=, Y) #define lu_assert_dbl_lt(X, Y) _lu_assert_dbl(X, <, Y) #define lu_assert_dbl_le(X, Y) _lu_assert_dbl(X, <=, Y) #define lu_assert_dbl_gt(X, Y) _lu_assert_dbl(X, >, Y) diff --git a/test/main.c b/test/main.c index 3c2cf04..c5683f8 100644 --- a/test/main.c +++ b/test/main.c @@ -2,20 +2,6 @@ int main(int argc, char** argv) { - //file ./t.Stack.c : - t_stack_clear(); - t_stack_size(); - t_stack_push_pop_basic(); - t_stack_push_pop_evolved(); - t_stack_copy(); - - //file ./t.List.c : - t_list_clear(); - t_list_size(); - t_list_push_pop_basic(); - t_list_push_pop_evolved(); - t_list_copy(); - //file ./t.Tree.c : t_tree_clear(); t_tree_size(); @@ -23,19 +9,12 @@ int main(int argc, char** argv) t_tree_iterate(); t_tree_copy(); - //file ./t.Vector.c : - t_vector_clear(); - t_vector_size(); - t_vector_push_pop_basic(); - t_vector_push_pop_evolved(); - t_vector_copy(); - - //file ./t.Queue.c : - t_queue_clear(); - t_queue_size(); - t_queue_push_pop_basic(); - t_queue_push_pop_evolved(); - t_queue_copy(); + //file ./t.PriorityQueue.c : + t_priorityqueue_clear(); + t_priorityqueue_size(); + t_priorityqueue_push_pop_basic(); + t_priorityqueue_push_pop_evolved(); + t_priorityqueue_copy(); //file ./t.Heap.c : t_heap_clear(); @@ -44,6 +23,13 @@ int main(int argc, char** argv) t_heap_push_pop_evolved(); t_heap_copy(); + //file ./t.List.c : + t_list_clear(); + t_list_size(); + t_list_push_pop_basic(); + t_list_push_pop_evolved(); + t_list_copy(); + //file ./t.BufferTop.c : t_buffertop_clear(); t_buffertop_size(); @@ -51,12 +37,33 @@ int main(int argc, char** argv) t_buffertop_push_pop_evolved(); t_buffertop_copy(); - //file ./t.PriorityQueue.c : - t_priorityqueue_clear(); - t_priorityqueue_size(); - t_priorityqueue_push_pop_basic(); - t_priorityqueue_push_pop_evolved(); - t_priorityqueue_copy(); + //file ./t.HashTable.c : + //t_hashtable_clear(); + //t_hashtable_size(); + t_hashtable_set_remove_basic(); + //t_hashtable_getnull_modify(); + //t_hashtable_copy(); + + //file ./t.Stack.c : + t_stack_clear(); + t_stack_size(); + t_stack_push_pop_basic(); + t_stack_push_pop_evolved(); + t_stack_copy(); + + //file ./t.Queue.c : + t_queue_clear(); + t_queue_size(); + t_queue_push_pop_basic(); + t_queue_push_pop_evolved(); + t_queue_copy(); + + //file ./t.Vector.c : + t_vector_clear(); + t_vector_size(); + t_vector_push_pop_basic(); + t_vector_push_pop_evolved(); + t_vector_copy(); return 0; } diff --git a/test/t.BufferTop.c b/test/t.BufferTop.c index 42b31c9..53899c4 100644 --- a/test/t.BufferTop.c +++ b/test/t.BufferTop.c @@ -7,7 +7,7 @@ void t_buffertop_clear() { BufferTop* bt = buffertop_new(int, 10, MIN_T, 2); - // NOTE: items with same values are supported; + // NOTE: items with same values are supported; // since it is unused in this test, we arbitrarily choose 0.0 buffertop_tryadd(bt, 0, 0.0); buffertop_tryadd(bt, 0, 0.0); diff --git a/test/t.HashTable.c b/test/t.HashTable.c new file mode 100644 index 0000000..5c23cb7 --- /dev/null +++ b/test/t.HashTable.c @@ -0,0 +1,159 @@ +#include +#include "cgds/HashTable.h" +#include "helpers.h" +#include "lut.h" + +void t_hashtable_clear() +{ + HashTable* h = hashtable_new(int, 16); + lu_assert(hashtable_empty(h)); + + hashtable_set(h, "key1", 0); + hashtable_set(h, "key2", 1); + hashtable_set(h, "key3", 2); + + hashtable_destroy(h); + h = hashtable_new(int, 8); + + hashtable_set(h, "key1", 1); + hashtable_set(h, "key2", 2); + hashtable_set(h, "key3", 3); + + hashtable_clear(h); + lu_assert(hashtable_empty(h)); + + hashtable_destroy(h); +} + +void t_hashtable_size() +{ + HashTable* h = hashtable_new(int, 16); + lu_assert(hashtable_empty(h)); + + hashtable_set(h, "key1", 0); + hashtable_set(h, "key2", 1); + hashtable_set(h, "key3", 2); + lu_assert_int_eq(hashtable_size(h), 3); + + hashtable_set(h, "key4", 3); + hashtable_set(h, "key5", 4); + lu_assert_int_eq(hashtable_size(h), 5); + + hashtable_set(h, "key6", 5); + hashtable_set(h, "key7", 6); + hashtable_set(h, "key8", 7); + lu_assert_int_eq(hashtable_size(h), 8); + + hashtable_destroy(h); +} + +void t_hashtable_set_remove_basic() +{ + int n = 10; + + HashTable* h = hashtable_new(double, 4); + char key[] = "key_"; + for (int i = 0; i < n; i++) + { + key[3] = (char)(48 + i); + hashtable_set(h, key, (double)i); + } + lu_assert_int_eq(hashtable_size(h), n); + + // Check values + double ckValue = 0.0; + for (int i = 0; i < n; i++) + { + double d; + key[3] = (char)(48 + i); + hashtable_get(h, key, d); + lu_assert_dbl_eq(d, ckValue); + ckValue += 1.0; + } + + //Remove keys / values + for (int i = 0; i < n; i++) + { + double d; + key[3] = (char)(48 + i); + hashtable_delete(h, key); + } + lu_assert_int_eq(hashtable_size(h), 0); + + hashtable_destroy(h); +} + +void t_hashtable_getnull_modify() +{ + int n = 10; + + HashTable* h = hashtable_new(StructTest1, 4); + StructTest1* st1 = (StructTest1*) malloc(n * sizeof (StructTest1)); + char* key = "key_"; + for (int i = 0; i < n; i++) + { + key[3] = (char)(48 + i); + st1[i].a = random() % 42; + st1[i].b = (double) random() / RAND_MAX; + hashtable_set(h, key, *(st1 + i)); + } + for (int i = 0; i < n; i++) + { + //another way to access elements + key[3] = (char)(48 + i); + StructTest1 st1Cell; + hashtable_get(h, key, st1Cell); + lu_assert_int_eq(st1Cell.a, st1[i].a); + lu_assert_dbl_eq(st1Cell.b, st1[i].b); + } + + // Get null: + StructTest1* stmp; + hashtable_get(h, "key12", stmp); + lu_assert(stmp == NULL); + hashtable_get(h, "key32", stmp); + lu_assert(stmp == NULL); + // Modify: + StructTest1* stMod; + stMod->a = -17; + stMod->b = 3.0; + hashtable_set(h, "key1", stMod); + hashtable_get(h, "key1", stmp); + lu_assert_int_eq(stmp->a, stMod->a); + lu_assert_dbl_eq(stmp->b, stMod->b); + stMod->a = -7; + stMod->b = 3.5; + hashtable_set(h, "key5", stMod); + hashtable_get(h, "key5", stmp); + lu_assert_int_eq(stmp->a, stMod->a); + lu_assert_dbl_eq(stmp->b, stMod->b); + + safe_free(st1); + hashtable_destroy(h); +} + +void t_hashtable_copy() +{ + int n = 10; + + HashTable* h = hashtable_new(int, 8); + char* key = "key_"; + for (int i = 0; i < n; i++) + { + key[3] = (char)(48 + i); + hashtable_set(h, key, random() % 42); + } + HashTable* hc = hashtable_copy(h); + + lu_assert_int_eq(h->size, hc->size); + int a, b; + for (int i = 0; i < n; i++) + { + key[3] = (char)(48 + i); + hashtable_get(h, key, a); + hashtable_get(hc, key, b); + lu_assert_int_eq(a, b); + } + hashtable_destroy(h); + hashtable_destroy(hc); +} diff --git a/test/t.Heap.c b/test/t.Heap.c index b01f835..733f104 100644 --- a/test/t.Heap.c +++ b/test/t.Heap.c @@ -7,7 +7,7 @@ void t_heap_clear() { Heap* h = heap_new(int, MIN_T, 2); - // NOTE: items with same priorities are supported; + // NOTE: items with same priorities are supported; // since it is unused in this test, we arbitrarily choose 0.0 heap_insert(h, 0, 0.0); heap_insert(h, 0, 0.0); diff --git a/test/t.PriorityQueue.c b/test/t.PriorityQueue.c index e5c3bae..8cabc1e 100644 --- a/test/t.PriorityQueue.c +++ b/test/t.PriorityQueue.c @@ -7,7 +7,7 @@ void t_priorityqueue_clear() { PriorityQueue* pq = priorityqueue_new(int, MIN_T, 2); - // NOTE: items with same priorities are supported; + // NOTE: items with same priorities are supported; // since it is unused in this test, we arbitrarily choose 0.0 priorityqueue_insert(pq, 0, 0.0); priorityqueue_insert(pq, 0, 0.0); diff --git a/test/t.Queue.c b/test/t.Queue.c index a393da2..9dd1986 100644 --- a/test/t.Queue.c +++ b/test/t.Queue.c @@ -43,7 +43,7 @@ void t_queue_push_pop_basic() int n = 10; Queue* q = queue_new(double); - for (int i = 0; i < n; i++) + for (int i = 0; i < n; i++) queue_push(q, (double) i); // iterate and check values double ckValue = 0.0; diff --git a/test/t.Stack.c b/test/t.Stack.c index ba53e9f..3cbaef6 100644 --- a/test/t.Stack.c +++ b/test/t.Stack.c @@ -44,7 +44,7 @@ void t_stack_push_pop_basic() int n = 10; Stack* s = stack_new(double); - for (int i = 0; i < n; i++) + for (int i = 0; i < n; i++) stack_push(s, (double) i); // iterate and check values double ckValue = n - 1; diff --git a/test/t.Vector.c b/test/t.Vector.c index 6cae626..7fde1e9 100644 --- a/test/t.Vector.c +++ b/test/t.Vector.c @@ -88,8 +88,8 @@ void t_vector_push_pop_evolved() StructTest1* st1 = (StructTest1*) malloc(n * sizeof (StructTest1)); for (int i = 0; i < n; i++) { - st1[i].a = rand() % 42; - st1[i].b = (double) rand() / RAND_MAX; + st1[i].a = random() % 42; + st1[i].b = (double) random() / RAND_MAX; vector_push(v, *(st1 + i)); } for (int i = 0; i < n; i++) @@ -107,10 +107,10 @@ void t_vector_push_pop_evolved() StructTest2* st2 = (StructTest2*) malloc(n * sizeof (StructTest2)); for (int i = 0; i < n; i++) { - st2[i].a = (float) rand() / RAND_MAX; + st2[i].a = (float) random() / RAND_MAX; st2[i].b = (StructTest1*) malloc(sizeof (StructTest1)); - st2[i].b->a = rand() % 42; - st2[i].b->b = (double) rand() / RAND_MAX; + st2[i].b->a = random() % 42; + st2[i].b->b = (double) random() / RAND_MAX; vector_push(v, st2 + i); } for (int i = 0; i < n; i++) @@ -132,7 +132,7 @@ void t_vector_copy() Vector* v = vector_new(int); for (int i = 0; i < n; i++) - vector_push(v, rand() % 42); + vector_push(v, random() % 42); Vector* vc = vector_copy(v); lu_assert_int_eq(v->size, vc->size);