#include <stdlib.h>
#include <string.h>
#include <sys/types.h>

/**
 * This file implements a "cache" of "known" domains together with
 * their verdicts.
 */

/**
 * This is the CacheEntry type of a malloc-ed cstring domain and a
 * verdict.
 */
typedef struct _CacheEntry {
    unsigned char *domain;
    unsigned int ix;
} CacheEntry;

/**
 * This is the cache root structure as apointer to the CacheEntry
 * array and its size.
 */
struct {
    CacheEntry *table;
    int size;
} cache;

/**
 * This computes a hash code for a domain which is its cache index.
 * This hashing simply adds the domain characters modulo cache table
 * size.
 */
int hash_code(unsigned char *domain) {
    int i = 0;
    for ( ; *domain; domain++ ) {
	i += *domain;
    }
    return i % cache.size;
}

/**
 * Look up a domain in the cache and return its cached verdict, or -1
 * of not present.
 */
int lookup_cache(unsigned char *domain) {
    if ( cache.table ) {
	int i = hash_code( domain );
	if ( cache.table[i].domain &&
	     strcmp( (char*)  domain, (char*) cache.table[i].domain ) == 0 ) {
	    return cache.table[i].ix;
	}
    }
    return -1;
}

/**
 * Add a domain and verdict into the cache. The domain hash code is
 * used as index into the table, to replace any prior CacheEntry
 * setting. The domain is a NUL terminated string that is copied into
 * the cache.
 */
void add_cache(unsigned char *domain,unsigned int ix) {
    if ( cache.table == 0 ) {
	cache.size = 1024;
	cache.table = (CacheEntry*) calloc( cache.size, sizeof( CacheEntry ) );
    }
    int i = hash_code( domain );
    if ( cache.table[i].domain ) {
	free( cache.table[i].domain );
    }
    cache.table[i].domain =  (unsigned char*) strdup( (char*) domain );
    cache.table[i].ix = ix;
}
