diff --git a/c/word-count/GNUmakefile b/c/word-count/GNUmakefile index ec085d0..ac0efa6 100644 --- a/c/word-count/GNUmakefile +++ b/c/word-count/GNUmakefile @@ -41,7 +41,7 @@ mem: clean memcheck unit: CFLAGS+=-DUNIT_TEST unit: clean std -debug: CFLAGS+=-DUNIT_TEST -DDEBUG +debug: CFLAGS+=-DUNIT_TEST -DDEBUG -DDEBUG_HASH debug: clean std debugtest: CFLAGS+=-DDEBUG diff --git a/c/word-count/src/hash.c b/c/word-count/src/hash.c index 792722c..aacb408 100644 --- a/c/word-count/src/hash.c +++ b/c/word-count/src/hash.c @@ -3,28 +3,18 @@ #include "hash.h" -#define HASH_SIZE 50 +/* TODO: + * - multiple linked pools + * - free pools ? + * - do a kernel-like list management, + add counter for pool elements + * so that they get freed when counter becomes zero (to allow an element + * to be in multiple lists) + */ -//static hash_t *hash_table[HASH_SIZE]; static h_entry_t *pool_free, *alloc_entries; static int n_entries; -void h_init(hash_t *hash) -{ - memset(hash->entries, 0, sizeof(h_entry_t)*hash->size); -} - -hash_t *h_create(int size) -{ - hash_t *hash; - - if ( !(hash=calloc(sizeof(hash_t) + size*(sizeof (h_entry_t *)), 1)) ) - return NULL; - hash->size=size; - return hash; -} - -void h_destroy(hash_t *h) +void h_free_all(hash_t *h) { h_entry_t *tmp; @@ -35,6 +25,32 @@ void h_destroy(hash_t *h) h->entries[i]=tmp; } } +} + +/* Should be used only when using unknown memory state, which is unlickely. + * Instead prefer: + * h_free_all: removes all entries from hash table + * h_destroy: cleans entries, and free hash memory + * TODO: add size parameter, to totally create a hash in known available memory + */ +void h_init(hash_t *h) +{ + memset(h->entries, 0, sizeof(h_entry_t)*h->size); +} + +hash_t *h_create(int size) +{ + hash_t *hash; + + if ( !(hash=calloc(1, sizeof(hash_t) + size*(sizeof (h_entry_t *)))) ) + return NULL; + hash->size=size; + return hash; +} + +void h_destroy(hash_t *h) +{ + h_free_all(h); free(h); } @@ -60,7 +76,7 @@ h_entry_t *h_entry_find(hash_t *h, const unsigned char *s, const int l) h_entry_t *entry; int found=0; -# ifdef DEBUG +# ifdef DEBUG_HASH printf("h_entry_find([%.*s]): hash=%#lx (%lu) - ", l, s, hash, hash%h->size); # endif hash%=h->size; @@ -70,7 +86,7 @@ h_entry_t *h_entry_find(hash_t *h, const unsigned char *s, const int l) break; } } -# ifdef DEBUG +# ifdef DEBUG_HASH printf("ret=%p\n", found? (void *)entry: (void *)-1); # endif return found? entry: NULL; @@ -86,17 +102,15 @@ h_entry_t *h_entry_add(hash_t *h, const unsigned char *s, const int l, int *inse if (!pool_free) { register int i=n_entries; - n_entries+=ENTRY_ALLOC_SIZE; -# ifdef DEBUG + n_entries+=POOL_ALLOC_SIZE; +# ifdef DEBUG_HASH printf("get_hash: allocating %d new entries - total entries=%d\n", - ENTRY_ALLOC_SIZE, n_entries); + POOL_ALLOC_SIZE, n_entries); # endif alloc_entries=reallocarray(alloc_entries, n_entries, sizeof(h_entry_t)); - for (; inext=pool_free; - pool_free=alloc_entries+i; - } + for (; idata=(unsigned char *)s; entry->key_len=l; - //assert(entry!=freenodes); -# ifdef DEBUG +# ifdef DEBUG_HASH printf("h_entry_add: %p\n", (void *)entry); # endif return entry; diff --git a/c/word-count/src/hash.h b/c/word-count/src/hash.h index 98ac2b0..b8fe752 100644 --- a/c/word-count/src/hash.h +++ b/c/word-count/src/hash.h @@ -30,23 +30,25 @@ typedef struct { h_entry_t *entries[1024]; } hash_1024_t; -#define ENTRY_ALLOC_SIZE 20 +#define POOL_ALLOC_SIZE 1024 /* hash map functions */ +// TODO: hash function parameter hash_t *h_create(int size); void h_init(hash_t *); void h_destroy(hash_t *); +void h_free_all(hash_t *); -/* static free_nodes */ -void set_pool_free_static(h_entry_t *p); +/* TODO: static free_nodes */ +// void set_pool_free_static(h_entry_t *p); /* hash entries functions */ -h_entry_t *h_entry_add(hash_t *, const unsigned char *, const int, int *); h_entry_t *h_entry_find(hash_t *, const unsigned char *, const int); +h_entry_t *h_entry_add(hash_t *, const unsigned char *, const int, int *); void h_entry_free(h_entry_t *); +// TODO: delete entry - -/* hash function */ +/* hash functions */ unsigned long hash_djb2(const unsigned char *str, const int len); #endif diff --git a/c/word-count/src/word_count.c b/c/word-count/src/word_count.c index b2a0f06..f30e99b 100644 --- a/c/word-count/src/word_count.c +++ b/c/word-count/src/word_count.c @@ -33,9 +33,6 @@ static word_t next_word(const char **p) static char tmp[1024]; int pos=0; -# ifdef DEBUG - printf("next_word(%s)\n", *p); -# endif for (; *p1 && !isalpha(*p1) && !isdigit(*p1); ++p1) ; @@ -70,18 +67,11 @@ static word_t next_word(const char **p) *p=q; } end: -# ifdef DEBUG - printf("next_word: [%s], %d\n", res.word? res.word: "NULL", res.len); -# endif return res; } static int insert_word(word_count_word_t *words, word_t w, int pos) { -#ifdef DEBUG - printf("insert words(len=%d word=[%.*s])\n", w.len, w.len, w.word); -#endif - memcpy(words[pos].text, w.word, w.len); words[pos].text[w.len]=0; words[pos].count=0; @@ -94,14 +84,8 @@ int count_words(const char *sentence, word_count_word_t *words) int current=0, new, index; hash_t *hash; h_entry_t *e; -# ifdef DEBUG - const char *s=sentence; -# endif hash=h_create(16); -# ifdef DEBUG - printf("count_words([%s], %p)\n", sentence, (void *)words); -# endif for (; *sentence;) { w=next_word(&sentence); if (!w.word) @@ -117,12 +101,6 @@ int count_words(const char *sentence, word_count_word_t *words) } index=(word_count_word_t *)e->data-&words[0]; words[index].count++; - //sentence=w.word+w.len; - //sentence+=w.len; -# ifdef DEBUG - printf("count_words: index=%d\n", index); - printf("offset=%d\n", (int)(sentence-s)); -# endif } h_destroy(hash); return current; @@ -139,7 +117,6 @@ static void print_wtable(int n) { for (int i=0; i