*.o
/src/obj/*.so
/test/test
+/test/vgcore.*
/doc/html/
/doc/latex/
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
return bufferInList;
}
-Bool buffertop_empty(BufferTop* bufferTop)
+bool buffertop_empty(BufferTop* bufferTop)
{
return (heap_size(bufferTop->heap) == 0);
}
*/
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;
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.
);
* @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> type, UInt capacity, OrderTypebType, UInt arity)
+ *
+ * Usage: BufferTop* buffertop_new(\
+ * <Type> 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.
/**
* @brief Check if the buffer is empty.
*/
-Bool buffertop_empty(
+bool buffertop_empty(
BufferTop* bufferTop ///< "this" pointer.
);
* @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) \
* @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_) \
--- /dev/null
+/**
+ * @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);
+}
--- /dev/null
+/**
+ * @file HashTable.h
+ */
+
+#ifndef CGDS_HASH_TABLE_H
+#define CGDS_HASH_TABLE_H
+
+#include <stdlib.h>
+#include <string.h>
+#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> 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
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; i<heap->array->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);
}
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))
{
{
UInt currentIndex = startIndex;
ItemValue* startItemValue = heap->array->datas[startIndex];
- while (C_TRUE)
+ while (true)
{
if (currentIndex * heap->arity >= heap->array->size)
{
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);
{
_heap_bubble_down(heap, index);
}
- else
+ else
_heap_bubble_up(heap, 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);
}
* @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> 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.
/**
* @brief Check if the heap is empty.
*/
-Bool heap_empty(
+bool heap_empty(
Heap* heap ///< "this" pointer.
);
);
/**
- * @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.
);
/**
- * @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.
* @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) \
* @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.
*/
* @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.
*/
* @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_) \
return listCopy;
}
-Bool list_empty(List* list)
+bool list_empty(List* list)
{
return (list->size == 0);
}
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);
listI->current = listI->list->tail;
}
-Bool listI_has_data(ListIterator* listI)
+bool listI_has_data(ListIterator* listI)
{
return (listI->current != NULL);
}
*/
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;
/**
* @brief Return an allocated and initialized list.
* @param type Type of a list element (int, char*, ...).
- *
+ *
* Usage: List* list_new(<Type> 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.
/**
* @brief Check if the list is empty.
*/
-Bool list_empty(
+bool list_empty(
List* list ///< "this" pointer.
);
* @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) \
* @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) \
* @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) \
* @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) \
* @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) \
* @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) \
_list_insert_back(list, &tmp); \
}
-/**
+/**
* @brief Remove data at position given by 'listCell'.
*/
void list_remove(
/**
* @brief Tell if there is some data at the current index.
*/
-Bool listI_has_data(
+bool listI_has_data(
ListIterator* listI ///< "this" pointer.
);
* @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) \
* @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)
* @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) \
* @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) \
#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;
return priorityQueueCopy;
}
-Bool priorityqueue_empty(PriorityQueue* priorityQueue)
+bool priorityqueue_empty(PriorityQueue* priorityQueue)
{
return heap_empty(priorityQueue->heap);
}
*/
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> type, OrderType pType, UInt arity)
+ *
+ * Usage: PriorityQueue* priorityqueue_new(\
+ * <Type> 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.
/**
* @brief Check if the priority queue is empty.
*/
-Bool priorityqueue_empty(
+bool priorityqueue_empty(
PriorityQueue* priorityQueue ///< "this" pointer.
);
* @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)
* @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)
* @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) \
/**
* @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.
* @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) \
PriorityQueue* priorityQueue ///< "this" pointer.
);
-/**
+/**
* @brief Clear the entire queue.
*/
void priorityqueue_clear(
return queueCopy;
}
-Bool queue_empty(Queue* queue)
+bool queue_empty(Queue* queue)
{
return list_empty(queue->list);
}
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> 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.
/**
* @brief Check if the queue is empty.
*/
-Bool queue_empty(
+bool queue_empty(
Queue* queue ///< "this" pointer.
);
* @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) \
* @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) \
return stackCopy;
}
-Bool stack_empty(Stack* stack)
+bool stack_empty(Stack* stack)
{
return vector_empty(stack->array);
}
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> 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.
/**
* @brief Check if the stack is empty.
*/
-Bool stack_empty(
+bool stack_empty(
Stack* stack ///< "this" pointer.
);
* @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) \
* @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) \
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);
return treeCopy;
}
-Bool tree_empty(Tree* tree)
+bool tree_empty(Tree* tree)
{
return (tree->root == NULL);
}
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;
}
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);
}
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;
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;
{
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);
}
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);
}
treeI->current = treeI->tree->root;
}
-Bool treeI_has_data(TreeIterator* treeI)
+bool treeI_has_data(TreeIterator* treeI)
{
return (treeI->current != NULL);
}
/**
* @brief Return an allocated and initialized tree.
* @param type Type at a tree node (int, char*, ...).
- *
+ *
* Usage: Tree* tree_new(<Type> 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.
/**
* @brief Check if the tree is empty.
*/
-Bool tree_empty(
+bool tree_empty(
Tree* tree ///< "this" pointer.
);
/**
* @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.
);
* @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) \
* @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) \
* @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) \
* @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) \
* @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) \
/**
* @brief Tell if there is some data at the current index.
*/
-Bool treeI_has_data(
+bool treeI_has_data(
TreeIterator* treeI ///< "this" pointer.
);
* @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) \
* @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) \
/**
- * @file Vector.cpp
+ * @file Vector.c
*/
#include "cgds/Vector.h"
return vectorCopy;
}
-Bool vector_empty(Vector* vector)
+bool vector_empty(Vector* vector)
{
return (vector->size == 0);
}
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;
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);
/**
* @brief Return an allocated and initialized vector.
* @param type Type of a vector element (int, char*, ...).
- *
+ *
* Usage: Vector* vector_new(<Type> 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.
/**
* @brief Check if the vector is empty.
*/
-Bool vector_empty(
+bool vector_empty(
Vector* vector ///< "this" pointer.
);
* @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) \
* @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) \
* @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) \
/**
* @brief Tell if there is some data at the current index.
*/
-Bool vectorI_has_data(
+bool vectorI_has_data(
VectorIterator* vectorI ///< "this" pointer.
);
* @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) \
* @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) \
#ifndef LIBCGDS_H
#define LIBCGDS_H
+// To include everything:
#include <cgds/BufferTop.h>
+#include <cgds/HashTable.h>
#include <cgds/Heap.h>
#include <cgds/List.h>
#include <cgds/PriorityQueue.h>
void safe_free(void* ptr)
{
- if (ptr != NULL)
+ if (ptr != NULL)
free(ptr);
}
#include <stdlib.h>
#include <stdint.h>
+#include <stdbool.h>
/**
* @brief Signed integer type.
*/
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.
*/
#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)
#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)
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();
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();
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();
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;
}
{
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);
--- /dev/null
+#include <stdlib.h>
+#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);
+}
{
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);
{
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);
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;
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;
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++)
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++)
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);