Permalink
Browse files

Added some missing error handling

  • Loading branch information...
1 parent aa4229c commit 9f43ea3a47d764e1502e1c0d7a9d0c50d1e3d9a0 @noonat committed May 7, 2011
Showing with 74 additions and 18 deletions.
  1. +51 −17 table.c
  2. +15 −1 table.h
  3. +8 −0 test/test.c
View
68 table.c
@@ -3,7 +3,7 @@
#include <string.h>
#include "table.h"
-#define MAX_SIZE_BITS 24
+#define MAX_SIZE_BITS 30
static const table_node_t _dummy_node = {
0, 0, NULL, 0
@@ -17,7 +17,7 @@ static inline uint32_t _table_mod(table_t *table, int32_t i);
static table_node_t *_table_nodes_alloc(int32_t count);
static void _table_nodes_free(table_node_t *nodes);
static int32_t _table_nodes_count(table_t *table);
-static void _table_nodes_resize(table_t *table, int32_t additional);
+static table_error_t _table_nodes_resize(table_t *table, int32_t additional);
static table_node_t *_table_node_find_inactive(table_t *table);
static table_node_t *_table_node_find_key(table_t *table, hvalue_t key, table_node_t **prev);
static table_node_t *_table_node_insert_key(table_t *table, hvalue_t key);
@@ -54,10 +54,9 @@ static inline uint32_t _table_mod(table_t *table, int32_t i) {
static table_node_t *_table_nodes_alloc(int32_t count) {
size_t size = sizeof(table_node_t) * count;
table_node_t *nodes = (table_node_t *)malloc(size);
- if (nodes == NULL) {
- // FIXME: error handling
+ if (nodes != NULL) {
+ memset(nodes, 0, size);
}
- memset(nodes, 0, size);
return nodes;
}
@@ -86,7 +85,7 @@ static int32_t _table_nodes_count(table_t *table) {
* Resize the hash table. This will use round the desired size up to the next
* power of two. Existing nodes will be redistributed across the new array.
*/
-static void _table_nodes_resize(table_t *table, int32_t additional) {
+static table_error_t _table_nodes_resize(table_t *table, int32_t additional) {
table_node_t *old_nodes = table->nodes;
int32_t old_size_log = table->nodes_size_log;
int32_t old_size = 1 << old_size_log;
@@ -100,11 +99,14 @@ static void _table_nodes_resize(table_t *table, int32_t additional) {
} else {
int32_t new_size_log = _ceil_log2(new_size);
if (new_size_log > MAX_SIZE_BITS) {
- // FIXME: error handling: table overflow
+ return TABLE_ERROR_OVERFLOW;
}
new_size = 1 << new_size_log;
table->nodes_size_log = new_size_log;
table->nodes = _table_nodes_alloc(new_size);
+ if (table->nodes == NULL) {
+ return TABLE_ERROR_MEMORY;
+ }
}
table->inactive_node = &table->nodes[new_size];
@@ -118,6 +120,8 @@ static void _table_nodes_resize(table_t *table, int32_t additional) {
}
_table_nodes_free(old_nodes);
}
+
+ return TABLE_ERROR_NONE;
}
/**
@@ -215,8 +219,13 @@ static table_node_t *_table_node_insert_key(table_t *table, hvalue_t key) {
table_node_t *new_node = _table_node_find_inactive(table);
if (new_node == NULL) {
// Couldn't find a free node, resize the table and try again
- _table_nodes_resize(table, 1);
- return _table_node_insert_key(table, key);
+ table_error_t error = _table_nodes_resize(table, 1);
+ if (error == TABLE_ERROR_NONE) {
+ return _table_node_insert_key(table, key);
+ } else {
+ table->error = error;
+ return NULL;
+ }
}
assert(new_node != _dummy_node_ptr);
other_hash = table->hash_func(table->hash_type, node->key);
@@ -246,6 +255,7 @@ static table_node_t *_table_node_insert_key(table_t *table, hvalue_t key) {
}
void table_init(table_t *table, htype_t type, hash_func_t fn, hash_equal_func_t eq_fn) {
+ assert(table != NULL);
assert(type != H_NULL);
table->nodes = _dummy_node_ptr;
table->nodes_size_log = 0;
@@ -256,33 +266,57 @@ void table_init(table_t *table, htype_t type, hash_func_t fn, hash_equal_func_t
}
void table_destroy(table_t *table) {
- _table_nodes_free(table->nodes);
- table->nodes = NULL;
+ if (table != NULL) {
+ _table_nodes_free(table->nodes);
+ table->nodes = NULL;
+ }
}
hvalue_t table_get(table_t *table, hvalue_t key) {
- table_node_t *node = _table_node_find_key(table, key, NULL);
+ table_node_t *node;
+ assert(table != NULL);
+ node = _table_node_find_key(table, key, NULL);
return node != NULL ? node->value : 0;
}
table_node_t *table_set(table_t *table, hvalue_t key, hvalue_t value) {
- table_node_t *node = _table_node_find_key(table, key, NULL);
+ table_node_t *node;
+ assert(table != NULL);
+ node = _table_node_find_key(table, key, NULL);
if (node == NULL) {
node = _table_node_insert_key(table, key);
}
- node->value = value;
+ if (node != NULL) {
+ node->value = value;
+ }
return node;
}
int32_t table_contains(table_t *table, hvalue_t key) {
- table_node_t *node = _table_node_find_key(table, key, NULL);
+ table_node_t *node;
+ assert(table != NULL);
+ node = _table_node_find_key(table, key, NULL);
return node != NULL && node->active;
}
void table_delete(table_t *table, hvalue_t key) {
- table_node_t *prev;
- table_node_t *node = _table_node_find_key(table, key, &prev);
+ table_node_t *node, *prev;
+ assert(table != NULL);
+ node = _table_node_find_key(table, key, &prev);
if (node != NULL) {
_table_node_delete(table, node, prev);
}
}
+
+const char *table_error_string(table_error_t error) {
+ switch (error) {
+ case TABLE_ERROR_NONE:
+ return "none";
+ case TABLE_ERROR_MEMORY:
+ return "out of memory";
+ case TABLE_ERROR_OVERFLOW:
+ return "table size too large";
+ default:
+ return "unknown error";
+ }
+}
View
16 table.h
@@ -8,6 +8,13 @@ extern "C" {
#include <stdint.h>
#include "hash.h"
+typedef enum _table_error {
+ TABLE_ERROR_NONE = 0,
+ TABLE_ERROR_MEMORY,
+ TABLE_ERROR_OVERFLOW,
+ MAX_TABLE_ERROR
+} table_error_t;
+
typedef struct _table table_t;
typedef struct _table_node table_node_t;
@@ -18,6 +25,7 @@ struct _table {
htype_t hash_type;
hash_func_t hash_func;
hash_equal_func_t hash_equal_func;
+ table_error_t error;
};
struct _table_node {
@@ -49,7 +57,8 @@ extern hvalue_t table_get(table_t *table, hvalue_t key);
/**
* Set the table key to a value, and return the table node. The table will
-* be resized if there isn't enough space.
+* be resized if there isn't enough space. If there is an error, NULL will
+* be returned, and table->error will contain the error code.
*/
extern table_node_t *table_set(table_t *table, hvalue_t key, hvalue_t value);
@@ -63,6 +72,11 @@ int32_t table_contains(table_t *table, hvalue_t key);
*/
extern void table_delete(table_t *table, hvalue_t key);
+/**
+* Return the string version of a table error code.
+*/
+extern const char *table_error_string(table_error_t error);
+
#ifdef __cplusplus
}
#endif
View
@@ -182,6 +182,13 @@ static void test_table_delete() {
table_destroy(&t);
}
+static void test_table_error_string() {
+ mu_assert(0 == strcmp(table_error_string(TABLE_ERROR_NONE), "none"));
+ mu_assert(0 == strcmp(table_error_string(TABLE_ERROR_MEMORY), "out of memory"));
+ mu_assert(0 == strcmp(table_error_string(TABLE_ERROR_OVERFLOW), "table size too large"));
+ mu_assert(0 == strcmp(table_error_string(MAX_TABLE_ERROR), "unknown error"));
+}
+
int main(int argc, char **argv) {
mu_test(test_table_init);
mu_test(test_table_init_with_funcs);
@@ -191,6 +198,7 @@ int main(int argc, char **argv) {
mu_test(test_table_get);
mu_test(test_table_contains);
mu_test(test_table_delete);
+ mu_test(test_table_error_string);
mu_print_results();
return mu_num_failures != 0;
}

0 comments on commit 9f43ea3

Please sign in to comment.