summaryrefslogtreecommitdiff
path: root/minilib/hash.c
blob: ad26732cbff21e93c614f0633fc4d48bcde32f2a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include "hash.h"
#include "arena.h"
#include "string.h"
#include "stddef.h"
#include "io.h"

void inthash_init( intHashTable *ht, int size )
{
	ht->table = (intHashEntry **)allocate( size * sizeof( intHashEntry ) );
	memset( ht->table, 0, size * sizeof( intHashEntry ) );
	ht->capacity = size;
	ht->size = 0;
}

void inthash_done( intHashTable *ht )
{
	deallocate( (void **)&ht->table );
}

static int hash_string( char *s )
{
	int h = 0;
	int c;

	while( ( c = *s++ ) ) {
		h += c;
	}

	return h;
}

void inthash_set( intHashTable *ht, char *key, int value )
{
	int h;
	intHashEntry *entry;
	intHashEntry *new;
	
	h = hash_string( key ) % ht->capacity;
	entry = ht->table[h];
	
	while( entry != NULL && strcmp( key, entry->key ) != 0 ) {
		entry = entry->next;
	}
	
	if( entry != NULL && strcmp( key, entry->key ) == 0 ) {
		entry->value = value;
	} else {
		new = (intHashEntry *)allocate( sizeof( intHashEntry ) );
		new->key = key;
		new->value = value;
		new->next = ht->table[h];		
		ht->table[h] = new;
	}
	
	ht->size++;
}

int inthash_get( intHashTable *ht, char *key)
{
	int h;
	intHashEntry *entry;
	
	h = hash_string( key ) % ht->capacity;
	entry = ht->table[h];
	
	while( entry != NULL && strcmp( key, entry->key ) != 0 ) {
		entry = entry->next;
	}
	
	if( entry != NULL && strcmp( key, entry->key ) == 0 ) {
		return entry->value;
	}
	
	return -1;
}

intHashEntry *inthash_getfirst( intHashTable *ht, intHashIterator *it )
{
	it->pos = 0;
	it->entry = ht->table[0];
	it->ht = ht;

	while( it->entry == NULL ) {
		it->pos++;
		if( it->pos > ht->capacity ) {
			return NULL;
		}
		it->entry = ht->table[it->pos];
	}

	return it->entry;
}

intHashEntry *inthash_getnext( intHashIterator *it )
{
	if( it->entry != NULL ) {
		it->entry = it->entry->next;
		if( it->entry != NULL ) {
			return it->entry;
		}
	}
	
	do {
		it->pos++;
		if( it->pos > it->ht->capacity ) {
			return NULL;
		}
		it->entry = it->ht->table[it->pos];
	} while( it->entry == NULL );
	
	return it->entry;	
}