cdictionarycode-snippetscode-reuse

Very simple map implemention in C (for caching purpose)?


I have a program that read urls in a file and does a gethostbyname() on each URL host. This call is quite consuming. I want to cache them.

Is there a very simple map-base code snippet in C out there that I could use to do the caching? (I just don't want to reinvent the wheel).

It has to have the following points :

PS: I tagged it homework, since it could be. I'm just being very lazy and do want to avoid all the common pitfalls I could encounter while reimplementing.


Solution

  • Here's a very simple and naive one

    :

    #include <string.h>
    #include <stdlib.h>
    
    #define NR_BUCKETS 1024
    
    struct StrHashNode {
        char *key;
        void *value;
        struct StrHashNode *next;
    
    };
    
    struct StrHashTable {
        struct StrHashNode *buckets[NR_BUCKETS];
        void (*free_key)(char *);
        void (*free_value)(void*);
        unsigned int (*hash)(const char *key);
        int (*cmp)(const char *first,const char *second);
    };
    
    void *get(struct StrHashTable *table,const char *key)
    {
        unsigned int bucket = table->hash(key)%NR_BUCKETS;
        struct StrHashNode *node;
        node = table->buckets[bucket];
        while(node) {
            if(table->cmp(key,node->key) == 0)
                return node->value;
            node = node->next;
        }
        return NULL;
    }
    int insert(struct StrHashTable *table,char *key,void *value)
    {
        unsigned int bucket = table->hash(key)%NR_BUCKETS;
        struct StrHashNode **tmp;
        struct StrHashNode *node ;
    
        tmp = &table->buckets[bucket];
        while(*tmp) {
            if(table->cmp(key,(*tmp)->key) == 0)
                break;
            tmp = &(*tmp)->next;
        }
        if(*tmp) {
            if(table->free_key != NULL)
                table->free_key((*tmp)->key);
            if(table->free_value != NULL)
                table->free_value((*tmp)->value);
            node = *tmp;
        } else {
            node = malloc(sizeof *node);
            if(node == NULL)
                return -1;
            node->next = NULL;
            *tmp = node;
        }
        node->key = key;
        node->value = value;
    
        return 0;
    }
    
    unsigned int foo_strhash(const char *str)
    {
        unsigned int hash = 0;
        for(; *str; str++)
            hash = 31*hash + *str;
        return hash;
    }
    
    #include <stdio.h>
    int main(int argc,char *argv[])
    {
        struct StrHashTable tbl = {{0},NULL,NULL,foo_strhash,strcmp};
    
        insert(&tbl,"Test","TestValue");
        insert(&tbl,"Test2","TestValue2");
        puts(get(&tbl,"Test"));
        insert(&tbl,"Test","TestValueReplaced");
        puts(get(&tbl,"Test"));
    
        return 0;
    }