/* An implementation of hash tables:
 * Copyright(C) 2000-2001 Salvatore Sanfilippo <antirez@invece.org>
 *
 * TODO:
 * o ht_copy() to copy an element between hash tables
 * o ht_dup() to duplicate an entire hash table
 * o ht_merge() to add the content of one hash table to another
 * o disk operations, the ability to save an hashtable from the
 *   memory to the disk and the reverse operation.
 *
 * LICENSE
 * -------
 *
 * Copyright (c) 2000-2001 Salvatore Sanfilippo <antirez@invece.org>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * Products derived from the Software may not be called with the original
 * name of the Software, the name of the Software and the name of the authors
 * may not be used to endorse or promote products derived from the Software
 * without prior written permission from all the authors of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "aht.h"

/* The special ht_free_element pointer is used to mark
 * a freed element in the hash table (note that the elements
 * neven used are just NULL pointers) */
static struct ht_ele *ht_free_element = (void*) -1;

static const unsigned int small_primes[] =
{   /* 2 is eliminated by trying only odd numbers. */
  3, 5, 7, 11, 13, 17, 19,
  23, 29, 31, 37, 41, 43, 47, 53,
  59, 61, 67, 71, 73, 79, 83, 89,
  97, 101, 103, 107, 109, 113, 127, 131,
  137, 139, 149, 151, 157, 163, 167, 173,
  179, 181, 191, 193, 197, 199, 211, 223,
  227, 229, 233, 239, 241, 251, 257, 263,
  269, 271, 277, 281, 283, 293, 307, 311,
  313, 317, 331, 337, 347, 349, 353, 359,
  367, 373, 379, 383, 389, 397, 401, 409,
  419, 421, 431, 433, 439, 443, 449, 457,
  461, 463, 467, 479, 487, 491, 499, 503,
  509, 521, 523, 541, 547, 557, 563, 569,
  571, 577, 587, 593, 599, 601, 607, 613,
  617, 619, 631, 641, 643, 647, 653, 659,
  661, 673, 677, 683, 691, 701, 709, 719,
  727, 733, 739, 743, 751, 757, 761, 769,
  773, 787, 797, 809, 811, 821, 823, 827,
  829, 839, 853, 857, 859, 863, 877, 881,
  883, 887, 907, 911, 919, 929, 937, 941,
  947, 953, 967, 971, 977, 983, 991, 997,
  1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049,
  1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097,
  1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163,
  1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223,
  1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283,
  1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321,
  1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423,
  1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459,
  1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511,
  1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571,
  1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619,
  1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693,
  1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747,
  1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811,
  1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877,
  1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949,
  1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003,
  2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069,
  2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129,
  2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203,
  2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267,
  2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311,
  2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377,
  2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423,
  2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503,
  2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579,
  2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657,
  2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693,
  2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741,
  2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801,
  2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861,
  2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939,
  2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011,
  3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079,
  3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167,
  3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221,
  3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301,
  3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347,
  3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413,
  3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491,
  3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541,
  3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607,
  3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671,
  3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727,
  3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797,
  3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863,
  3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923,
  3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003,
  4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057,
  4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129,
  4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211,
  4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259,
  4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337,
  4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409,
  4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481,
  4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547,
  4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621,
  4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673,
  4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751,
  4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813,
  4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909,
  4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967,
  4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011,
  5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087,
  5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167,
  5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233,
  5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309,
  5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399,
  5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443,
  5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507,
  5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573,
  5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653,
  5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711,
  5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791,
  5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849,
  5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897,
  5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007,
  6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073,
  6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133,
  6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211,
  6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271,
  6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329,
  6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379,
  6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473,
  6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563,
  6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637,
  6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701,
  6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779,
  6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833,
  6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907,
  6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971,
  6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027,
  7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121,
  7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207,
  7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253,
  7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349,
  7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457,
  7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517,
  7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561,
  7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621,
  7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691,
  7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757,
  7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853,
  7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919,
  7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009,
  8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087,
  8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161,
  8167, 8171, 8179, 8191,
  0};

/* All the numbers congruent to 1, 7, 11, 13, 17,
 * 19, 23, and 29 modulo 30 are a superset of
 * all the prime numbers:
 * More info at:
 * http://www.utm.edu/research/primes/glossary/WheelFactorization.html
 *
 * Starting from 8191 that's the last prime in the
 * small_primes list we must add:
 */
static unsigned add[] = {6, 4, 2, 4, 2, 4, 6, 2};

/* The djb hash function, that's under public domain */
u_int32_t djb_hash(unsigned char *buf, size_t len)
{
	int i;
	u_int32_t h = 5381;
	for (i = 0; i < len; i++)
		h = (h + (h << 5)) ^ buf[i];
	return h;
}

/* My own hash function. It shows a good distribution
 * with strings, but it's quite slower due to the presence
 * of the multiplication. You may use it as a second hash
 * function in double hashing if the key is a string
 * (otherwise it sucks). It's based on the concept of
 * mixing different algebrical groups */
u_int32_t alt_hashf(unsigned char *buf, size_t len)
{
	int i;
	u_int32_t h = 5381;
	for (i = 0; i < len; i++) {
		if (i & 1)
			h *= buf[i];
		else
			h += buf[i];
	}
	return h;
}

/* This functions are used to generate prime numbers: to
 * make the hash table the nearest prime number to a power of 2
 * can avoid some problem related to bad distribution of the hash
 * functions.
 * 
 * The following function try to divide the number to the small_primes
 * list, then try to use the 'wheel factorization'.
 * We should stop to try at the square root of the number
 * but I want not link against the math lib, so the function
 * stops when the divisor reaches n/2 */
int isprime(int n)
{
	int i = 0;
	int p, limit = n/2;

	if ((n & 1) == 0)
		return 0;
	while ((p = small_primes[i++]) != 0 && p < n) {
		if ((n % p) == 0)
			return 0;
	}

	i = 0;
	p = 8191; /* the last prime in the small_primes table */
	p += add[i++];
	while (p < limit) {
		if ((n % p) == 0)
			return 0;
		p += add[i];
		i = (i+1)%8;
	}
	return 1;
}

/* Return the littlest prime number major or equal to n */
int next_prime(int n)
{
	while (isprime(n) == 0)
		n++;
	return n;
}

/* Initialize the hash table */
void ht_init(struct hashtable *t)
{
	t->table = NULL;
	t->size = 0;
	t->used = 0;
	t->collisions = 0;
	t->hashf[0] = djb_hash; /* Our default hash function */
	t->hashf[1] = t->hashf[2] = NULL;
}

/* Expand the hash table if needed */
int ht_expand_if_needed(struct hashtable *t)
{
	int ret;

	/* If the hash table is empty expand it to the intial size,
	 * if the table is half-full redobule its size. */
	if (t->size == 0) {
		ret = ht_expand(t, HT_INITIAL_SIZE);
		if (ret != HT_OK)
			return ret;
	} else if (t->size <= (t->used << 1)) {
		ret = ht_expand(t, t->size << 1);
		if (ret != HT_OK)
			return ret;
	}
	return HT_OK;
}

/* Resize the table to the minimal size that contains all the elements */
int ht_resize(struct hashtable *t)
{
	int minimal = (t->used * 2)+1;

	if (minimal < HT_INITIAL_SIZE)
		minimal = HT_INITIAL_SIZE;
	return ht_expand(t, minimal);
}

/* Move an element accross hash tables */
int ht_move(struct hashtable *orig, struct hashtable *dest, unsigned int index)
{
	int ret;
	unsigned int new_index;

	/* If the element isn't in the table ht_search will store
	 * the index of the free ht_ele in the integer pointer by *index */
	ret = ht_search(dest, orig->table[index]->key,
			      orig->table[index]->keysize, &new_index, NULL);
	if (ret == HT_FOUND)
		return HT_BUSY;
	else if (ret != HT_NOTFOUND) /* then report the error */
		return ret;

	/* Move the element */
	dest->table[new_index] = orig->table[index];
	orig->table[index] = ht_free_element;
	orig->used--;
	dest->used++;
	return HT_OK;
}

/* Expand or create the hashtable structures */
int ht_expand(struct hashtable *t, size_t size)
{
	struct hashtable n; /* the new hashtable */
	unsigned int realsize = next_prime(size), i;
	int ret, j;

	ht_init(&n);
	n.size = realsize;
	n.table = malloc(realsize*sizeof(struct ht_ele*));
	if (n.table == NULL)
		return HT_NOMEM;
	/* Copy the hash functions pointers */
	for (j = 0; j < HT_FUNCTIONS; j++)
		n.hashf[j] = t->hashf[j];

	/* Initialize all the pointers to NULL */
	memset(n.table, 0, realsize*sizeof(struct ht_ele*));

	/* Copy all the elements from the old to the new table:
	 * note that if the old hash table is empty t->size is zero,
	 * so ht_expand() acts like an ht_create() */
	for (i = 0; i < t->size && t->used > 0; i++) {
		if (t->table[i] != NULL && t->table[i] != ht_free_element) {
			/* ht_move is faster than ht_add() + ht_free() */
			ret = ht_move(t, &n, i);
			/* If there aren't bugs ht_move() must return
			 * only HT_OK or HT_NOMEM */
			if (ret != HT_OK) {
				assert(ret == HT_NOMEM);
				ht_destroy(&n);
				return ret;
			}
		}
	}
	assert(t->used == 0);
	ht_destroy(t);

	/* Remap the new hashtable in the old */
	*t = n;
	return HT_OK;
}

/* Add an element, discarding the old if the key exist */
int ht_replace(struct hashtable *t, void *key, size_t keysize,
				    void *data, size_t datasize)
{
	int ret;
	unsigned int index;

	/* Try to add the element */
	ret = ht_add(t, key, keysize, data, datasize);
	if (ret == HT_OK || ret != HT_BUSY)
		return ret;
	/* It already exist, get the index */
	ret = ht_search(t, key, keysize, NULL, &index);
	assert(ret == HT_FOUND);
	/* Remove the old */
	ret = ht_free(t, index);
	assert(ret == HT_OK);
	/* And add the new */
	return ht_add(t, key, keysize, data, datasize);
}

/* Add an element to the target hash table
 * allocating automatically dynamic memory */
int ht_add(struct hashtable *t, void *key, size_t keysize,
				void *data, size_t datasize)
{
	int ret;
	char *mem;

	/* Copy the element in the dynamically allocated memory */
	if (datasize > 0) {
		mem = malloc(datasize);
		if (mem == NULL)
			return HT_NOMEM;
		memcpy(mem, data, datasize);
	} else {
		mem = NULL;
	}

	ret = ht_add_generic(t, key, keysize, mem, datasize, ht_destructor_free);
	if (ret != HT_OK)
		free(mem);
	return ret;
}

/* Add an element to the target hash table */
int ht_add_generic(struct hashtable *t, void *key, size_t keysize,
			void *data, size_t datasize,
			void (*destructor) (void *obj, unsigned int size))
{
	int ret;
	unsigned int index;

	/* The key can't be zero length */
	if (keysize == 0)
		return HT_INVALID;

	/* If the element isn't in the table ht_search() will store
	 * the index of the free ht_ele in the integer pointer by *index */
	ret = ht_search(t, key, keysize, &index, NULL);
	if (ret == HT_FOUND)
		return HT_BUSY;
	else if (ret != HT_NOTFOUND) /* then report the error */
		return ret;

	/* Allocates the memory and stores key */
	if ((t->table[index] = malloc(sizeof(struct ht_ele))) == NULL)
		return HT_NOMEM;
	if ((t->table[index]->key = malloc(keysize)) == NULL) {
		free(t->table[index]);
		return HT_NOMEM;
	}
	memcpy(t->table[index]->key, key, keysize);
	t->table[index]->keysize = keysize;

	/* Store the data pointer */
	t->table[index]->data = data;
	t->table[index]->datasize = datasize;
	if (destructor != NULL)
		t->table[index]->destructor = destructor;
	else
		t->table[index]->destructor = ht_no_destructor;
	t->used++;
	return HT_OK;
}

/* Destroy an entire hash table */
int ht_destroy(struct hashtable *t)
{
	unsigned int i;
	int ret;

	/* Free all the elements */
	for (i = 0; i < t->size && t->used > 0; i++) {
		if (t->table[i] != NULL && t->table[i] != ht_free_element) {
			ret = ht_free(t, i);
			assert(ret == HT_OK);
		}
	}
	assert(t->used == 0);
	/* Free the table itself */
	free(t->table);
	/* Re-initialize the table */
	ht_init(t);
	return HT_OK; /* Actually ht_destroy never fails */
}

#include <unistd.h>
/* Free an element in the hash table */
int ht_free(struct hashtable *t, unsigned int index)
{
	if (index >= t->size)
		return HT_IOVERFLOW; /* Index overflow */
	/* ht_free() calls against non-existent elements are ignored */
	if (t->table[index] != NULL && t->table[index] != ht_free_element) {
		/* free the key data */
		free(t->table[index]->key);
		/* call the destructor */
		t->table[index]->destructor(t->table[index]->data,
					   t->table[index]->datasize);
		/* free the element structure */
		free(t->table[index]);
		/* mark the element as freed */
		t->table[index] = ht_free_element;
		t->used--;
	}
	return HT_OK;
}

/* Return 1 if two keys matches */
int ht_key_match(void *key1, unsigned int size1, void *key2, unsigned int size2)
{
	assert(size1 != 0 && size2 != 0);
	if (size1 != size2)
		return 0;
	if (memcmp(key1, key2, size1) == 0)
		return 1;
	return 0;
}

/* Search an element in the hash table: if the element does not exist
 * store the available index for the given key in *index */
int ht_search(struct hashtable *t, void *key, unsigned int keysize,
					      unsigned int *avail_index,
					      unsigned int *found_index)
{
	int ret;
	u_int32_t h = 0; /* Just in the crazy case of NO hash functions */
	unsigned int i;

	/* The user must leave at least one index pointer to NULL */
	assert(!(avail_index != NULL && found_index != NULL));

	/* Expand the hashtable if needed */
	if (avail_index != NULL || t->size == 0)
		if ((ret = ht_expand_if_needed(t)) != HT_OK)
			return ret;

	/* Try using the hash functions */
	for (i = 0; i < HT_FUNCTIONS && t->hashf[i] != NULL; i++) {
		h = t->hashf[i]((unsigned char *) key, keysize) % t->size;
		/* this handles the removed elements */
		if (t->table[h] == ht_free_element) {
			if (avail_index)
				goto notfound;
			else
				continue;
		}
		if (t->table[h] == NULL)
			goto notfound;
		else if (ht_key_match(key, keysize, t->table[h]->key,
							t->table[h]->keysize))
			goto found;
		t->collisions++;
	}

	/* Linear search */
	for (i = 0; i < t->size; i++) {
		h = (h+1) % t->size;
		/* this handles the removed elements */
		if (t->table[h] == ht_free_element) {
			if (avail_index)
				goto notfound;
			else
				continue;
		}
		if (t->table[h] == NULL)
			goto notfound;
		else if (ht_key_match(key, keysize, t->table[h]->key,
							t->table[h]->keysize))
			goto found;
		t->collisions++;
	}
	/* The hash table can't be full in this implemenation,
	 * it this happen there is a bug. We can reach this point
	 * _only_ if we are searching for an element, not for an
	 * empty slot in the table. So avail_index must be NULL */
	assert(avail_index == NULL);
	return HT_NOTFOUND;

found:
	if (found_index != NULL)
		*found_index = h;
	return HT_FOUND;

notfound:
	if (avail_index != NULL)
		*avail_index = h;
	return HT_NOTFOUND;
}

/* The default destructor */
void ht_destructor_free(void *obj, unsigned int size)
{
	free(obj);
}

/* the NULL destructor */
void ht_no_destructor(void *obj, unsigned int size) { }

/* This function is used to run all the hash table,
 * it returns:
 * 1  if the element with the given index is valid
 * 0  if the element with the given index is empty or marked free
 * -1 if the element if out of the range */
int ht_get_byindex(struct hashtable *t, unsigned int index, struct ht_ele **e)
{
	if (index >= t->size)
		return -1;
	if (t->table[index] == NULL || t->table[index] == ht_free_element)
		return 0;
	*e = t->table[index];
	return 1;
}
