+List* hash_table_keys(Hashtable* ht) {
+ List *keys, *head;
+ keys = head = NULL;
+
+ if (ht != NULL) {
+ for (uint32_t i = 0; i < ht->size; i++) {
+ if (ht->nodes[i] != NULL) {
+ Node* node = ht->nodes[i];
+ while (node != NULL) {
+ if (head == NULL) {
+ head = calloc(sizeof(List*), 1);
+ keys = head;
+ }
+ else {
+ head->next = calloc(sizeof(List*), 1);
+ head = head->next;
+ }
+ head->data = ht->nodes[i]->key;
+ node = node->next;
+ }
+ }
+ }
+ }
+
+ return keys;
+}
+
+List* hash_table_values(Hashtable* ht) {
+ List *values, *head;
+ values = head = NULL;
+
+ if (ht != NULL) {
+ for (uint32_t i = 0; i < ht->size; i++) {
+ if (ht->nodes[i] != NULL) {
+ Node* node = ht->nodes[i];
+ while (node != NULL) {
+ if (head == NULL) {
+ head = calloc(sizeof(List*), 1);
+ values = head;
+ }
+ else {
+ head->next = calloc(sizeof(List*), 1);
+ head = head->next;
+ }
+ head->data = ht->nodes[i]->data;
+ node = node->next;
+ }
+ }
+ }
+ }
+
+ return values;
+}
+
+void hash_table_list_free(List* list) {
+ while (list != NULL) {
+ List* prev = list;
+ list = list->next;
+ free(prev);
+ }
+}
+
+void hash_table_foreach(Hashtable* ht, ForeachFunc ff, void* userdata) {
+ if (ht != NULL) {
+ for (uint32_t i = 0; i < ht->size; i++) {
+ if (ht->nodes[i] != NULL) {
+ Node* node = ht->nodes[i];
+ while (node != NULL) {
+ ff(node->key, node->data, userdata);
+ node = node->next;
+ }
+ }
+ }
+ }
+}
+
+void hash_table_iter_init (HashtableIter* iter, Hashtable* ht) {
+ RealIter* ri = (RealIter*) iter;
+
+ if (ri != NULL && ht != NULL) {
+ ri->table = ht;
+ ri->pos = -1;
+ }
+}
+
+bool hash_table_iter_next(HashtableIter* iter, void** key, void** value) {
+ RealIter* ri = (RealIter*) iter;
+ Node* node;
+ int64_t pos;
+
+ if (ri != NULL) {
+ pos = ri->pos;
+
+ do {
+ pos++;
+ if (pos >= ri->table->size) {
+ ri->pos = pos;
+ return false;
+ }
+ node = ri->table->nodes[pos];
+ } while (node == NULL);
+
+ if (key != NULL)
+ *key = node->key;
+ if (value != NULL)
+ *value = node->data;
+
+ ri->pos = pos;
+ return true;
+ }
+ return false;
+}
+
+bool hash_table_contains(Hashtable* ht, const void* key) {
+ if (ht == NULL || key == NULL) return false;
+
+ if (hash_table_lookup(ht, key) == NULL)
+ return false;
+ return true;
+}
+
+uint64_t hash_table_size(Hashtable *ht) {
+ uint64_t size = 0;
+
+ if (ht == NULL) return size;
+
+ for (uint32_t i = 0; i < ht->size; i++) {
+ if (ht->nodes[i] != NULL) {
+ Node* node = ht->nodes[i];
+ while (node != NULL) {
+ size++;
+ node = node->next;
+ }
+ }
+ }
+
+ return size;
+}
+
+bool hash_table_replace(Hashtable *ht, void* key, void* value) {
+ if (ht == NULL || key == NULL || value == NULL) return false;
+
+ uint32_t index = hash_table_index(ht, key);
+
+ Node* node = ht->nodes[index];
+ while (node != NULL && ht->compare(node->data, key) == false) {
+ node = node->next;
+ }
+
+ if (node == NULL)
+ return hash_table_insert(ht, key, value);
+ else {
+ free(node->data);
+ node->key = key;
+ node->data = value;
+ }
+
+ return true;
+}
+