Blame hash.c

Packit 9c3e7e
/**
Packit 9c3e7e
 * @file hash.c
Packit 9c3e7e
 * @brief Implements a simple hash table.
Packit 9c3e7e
 * @note Copyright (C) 2015 Richard Cochran <richardcochran@gmail.com>
Packit 9c3e7e
 *
Packit 9c3e7e
 * This program is free software; you can redistribute it and/or modify
Packit 9c3e7e
 * it under the terms of the GNU General Public License as published by
Packit 9c3e7e
 * the Free Software Foundation; either version 2 of the License, or
Packit 9c3e7e
 * (at your option) any later version.
Packit 9c3e7e
 *
Packit 9c3e7e
 * This program is distributed in the hope that it will be useful,
Packit 9c3e7e
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 9c3e7e
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 9c3e7e
 * GNU General Public License for more details.
Packit 9c3e7e
 *
Packit 9c3e7e
 * You should have received a copy of the GNU General Public License along
Packit 9c3e7e
 * with this program; if not, write to the Free Software Foundation, Inc.,
Packit 9c3e7e
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Packit 9c3e7e
 */
Packit 9c3e7e
#include <stdlib.h>
Packit 9c3e7e
#include <string.h>
Packit 9c3e7e
Packit 9c3e7e
#include "hash.h"
Packit 9c3e7e
Packit 9c3e7e
#define HASH_TABLE_SIZE 200
Packit 9c3e7e
Packit 9c3e7e
struct node {
Packit 9c3e7e
	char *key;
Packit 9c3e7e
	void *data;
Packit 9c3e7e
	struct node *next;
Packit 9c3e7e
};
Packit 9c3e7e
Packit 9c3e7e
struct hash {
Packit 9c3e7e
	struct node *table[HASH_TABLE_SIZE];
Packit 9c3e7e
};
Packit 9c3e7e
Packit 9c3e7e
static unsigned int hash_function(const char* s)
Packit 9c3e7e
{
Packit 9c3e7e
	unsigned int i;
Packit 9c3e7e
Packit 9c3e7e
	for (i = 0; *s; s++) {
Packit 9c3e7e
		i = 131 * i + *s;
Packit 9c3e7e
	}
Packit 9c3e7e
	return i % HASH_TABLE_SIZE;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
struct hash *hash_create(void)
Packit 9c3e7e
{
Packit 9c3e7e
	struct hash *ht = calloc(1, sizeof(*ht));
Packit 9c3e7e
	return ht;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
void hash_destroy(struct hash *ht, void (*func)(void *))
Packit 9c3e7e
{
Packit 9c3e7e
	unsigned int i;
Packit 9c3e7e
	struct node *n, *next, **table = ht->table;
Packit 9c3e7e
Packit 9c3e7e
	for (i = 0; i < HASH_TABLE_SIZE; i++) {
Packit 9c3e7e
		for (n = table[i] ; n; n = next) {
Packit 9c3e7e
			next = n->next;
Packit 9c3e7e
			if (func) {
Packit 9c3e7e
				func(n->data);
Packit 9c3e7e
			}
Packit 9c3e7e
			free(n->key);
Packit 9c3e7e
			free(n);
Packit 9c3e7e
		}
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	free(ht);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int hash_insert(struct hash *ht, const char* key, void *data)
Packit 9c3e7e
{
Packit 9c3e7e
	unsigned int h;
Packit 9c3e7e
	struct node *n, **table = ht->table;
Packit 9c3e7e
Packit 9c3e7e
	h = hash_function(key);
Packit 9c3e7e
Packit 9c3e7e
	for (n = table[h] ; n; n = n->next) {
Packit 9c3e7e
		if (!strcmp(n->key, key)) {
Packit 9c3e7e
			/* reject duplicate keys */
Packit 9c3e7e
			return -1;
Packit 9c3e7e
		}
Packit 9c3e7e
	}
Packit 9c3e7e
	n = calloc(1, sizeof(*n));
Packit 9c3e7e
	if (!n) {
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
	n->key = strdup(key);
Packit 9c3e7e
	if (!n->key) {
Packit 9c3e7e
		free(n);
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
	n->data = data;
Packit 9c3e7e
	n->next = table[h];
Packit 9c3e7e
	table[h] = n;
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
void *hash_lookup(struct hash *ht, const char* key)
Packit 9c3e7e
{
Packit 9c3e7e
	unsigned int h;
Packit 9c3e7e
	struct node *n, **table = ht->table;
Packit 9c3e7e
Packit 9c3e7e
	h = hash_function(key);
Packit 9c3e7e
Packit 9c3e7e
	for (n = table[h] ; n; n = n->next) {
Packit 9c3e7e
		if (!strcmp(n->key, key)) {
Packit 9c3e7e
			return n->data;
Packit 9c3e7e
		}
Packit 9c3e7e
	}
Packit 9c3e7e
	return NULL;
Packit 9c3e7e
}