#include "hash.hpp"
#include <arpa/inet.h> // htonl


/** http://www.isthe.com/chongo/tech/comp/fnv/#FNV-1a **/
cachekey_t hash(const char* buf) {
    cachekey_t h = 2166136261u;
    while (*buf) {
        h ^= *buf;
        h *= 16777619;
        ++buf;
    }
    return h;
}


/** http://www.isthe.com/chongo/tech/comp/fnv/#FNV-1a **/
cachekey_t hash(const char* buf, size_t len) {
    return hash(buf, len, 2166136261u);
}


/** http://www.isthe.com/chongo/tech/comp/fnv/#FNV-1a **/
cachekey_t hash(const char* buf, size_t len, cachekey_t h) {
    while (len--) {
        h ^= *buf;
        h *= 16777619;
        ++buf;
    }
    return h;
}


void hash2str(cachekey_t key, char* buf) {
    (void)sprintf(buf, "%02x%02x%02x%02x", ((unsigned char*)&key)[0], ((unsigned char*)&key)[1], ((unsigned char*)&key)[2], ((unsigned char*)&key)[3]);
}


TEST(hash) {
    const char foo[] = "fo0b4r";
    cachekey_t h = hash(foo);
    TEST_ASSERT(h == hash(foo, sizeof(foo)-1));

    char buf[CACHEKEY_HEX_LEN+1];
    buf[CACHEKEY_HEX_LEN] = '\0';
    hash2str(h, buf);

    unsigned hh;
    TEST_ASSERT(sscanf(buf, "%x", &hh) == 1);
    TEST_ASSERT(htonl(hh) == h);

    return true;
}