types.c
author Dan Winship <danw@gnome.org>
Thu Feb 07 09:58:48 2008 -0500 (2008-02-07)
changeset 115 26edeea5c95a
child 116 4ec6e2a55c34
permissions -rw-r--r--
split array and hashtable code out into a new file
danw@115
     1
#include <stdlib.h>
danw@115
     2
#include <string.h>
danw@115
     3
danw@115
     4
#include "types.h"
danw@115
     5
danw@115
     6
void
danw@115
     7
array_init(struct array *array)
danw@115
     8
{
danw@115
     9
	memset(array, 0, sizeof *array);
danw@115
    10
}
danw@115
    11
danw@115
    12
void
danw@115
    13
array_release(struct array *array)
danw@115
    14
{
danw@115
    15
	free(array->data);
danw@115
    16
}
danw@115
    17
danw@115
    18
void *
danw@115
    19
array_add(struct array *array, int size)
danw@115
    20
{
danw@115
    21
	int alloc;
danw@115
    22
	void *data, *p;
danw@115
    23
danw@115
    24
	if (array->alloc > 0)
danw@115
    25
		alloc = array->alloc;
danw@115
    26
	else
danw@115
    27
		alloc = 16;
danw@115
    28
danw@115
    29
	while (alloc < array->size + size)
danw@115
    30
		alloc *= 2;
danw@115
    31
danw@115
    32
	if (array->alloc < alloc) {
danw@115
    33
		data = realloc(array->data, alloc);
danw@115
    34
		if (data == NULL)
danw@115
    35
			return 0;
danw@115
    36
		array->data = data;
danw@115
    37
		array->alloc = alloc;
danw@115
    38
	}
danw@115
    39
danw@115
    40
	p = array->data + array->size;
danw@115
    41
	array->size += size;
danw@115
    42
danw@115
    43
	return p;
danw@115
    44
}
danw@115
    45
danw@115
    46
danw@115
    47
void
danw@115
    48
hashtable_init(struct hashtable *table, struct array *pool)
danw@115
    49
{
danw@115
    50
	array_init(&table->buckets);
danw@115
    51
	table->pool = pool;
danw@115
    52
}
danw@115
    53
danw@115
    54
void
danw@115
    55
hashtable_release(struct hashtable *table)
danw@115
    56
{
danw@115
    57
	array_release(&table->buckets);
danw@115
    58
}
danw@115
    59
danw@115
    60
static unsigned int
danw@115
    61
hash_string(const char *key)
danw@115
    62
{
danw@115
    63
	const char *p;
danw@115
    64
	unsigned int hash = 0;
danw@115
    65
danw@115
    66
	for (p = key; *p; p++)
danw@115
    67
		hash = (hash * 617) ^ *p;
danw@115
    68
danw@115
    69
	return hash;
danw@115
    70
}
danw@115
    71
danw@115
    72
uint32_t
danw@115
    73
hashtable_lookup(struct hashtable *table, const char *key)
danw@115
    74
{
danw@115
    75
	unsigned int mask, start, i;
danw@115
    76
	uint32_t *b;
danw@115
    77
	char *pool;
danw@115
    78
danw@115
    79
	pool = table->pool->data;
danw@115
    80
	mask = table->buckets.alloc - 1;
danw@115
    81
	start = hash_string(key) * sizeof(uint32_t);
danw@115
    82
danw@115
    83
	for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
danw@115
    84
		b = table->buckets.data + ((start + i) & mask);
danw@115
    85
danw@115
    86
		if (*b == 0)
danw@115
    87
			return 0;
danw@115
    88
danw@115
    89
		if (strcmp(key, &pool[*b]) == 0)
danw@115
    90
			return *b;
danw@115
    91
	}
danw@115
    92
danw@115
    93
	return 0;
danw@115
    94
}
danw@115
    95
danw@115
    96
static void
danw@115
    97
do_insert(struct hashtable *table, uint32_t value)
danw@115
    98
{
danw@115
    99
	unsigned int mask, start, i;
danw@115
   100
	uint32_t *b;
danw@115
   101
	const char *key;
danw@115
   102
danw@115
   103
	key = (char *) table->pool->data + value;
danw@115
   104
	mask = table->buckets.alloc - 1;
danw@115
   105
	start = hash_string(key) * sizeof(uint32_t);
danw@115
   106
danw@115
   107
	for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
danw@115
   108
		b = table->buckets.data + ((start + i) & mask);
danw@115
   109
		if (*b == 0) {
danw@115
   110
			*b = value;
danw@115
   111
			break;
danw@115
   112
		}
danw@115
   113
	}
danw@115
   114
}
danw@115
   115
danw@115
   116
static uint32_t
danw@115
   117
add_to_string_pool(struct hashtable *table, const char *key)
danw@115
   118
{
danw@115
   119
	int len;
danw@115
   120
	char *p;
danw@115
   121
danw@115
   122
	len = strlen(key) + 1;
danw@115
   123
	p = array_add(table->pool, len);
danw@115
   124
	memcpy(p, key, len);
danw@115
   125
danw@115
   126
	return p - (char *) table->pool->data;
danw@115
   127
}
danw@115
   128
danw@115
   129
uint32_t
danw@115
   130
hashtable_insert(struct hashtable *table, const char *key)
danw@115
   131
{
danw@115
   132
	uint32_t value, *buckets, *b, *end;
danw@115
   133
	int alloc;
danw@115
   134
danw@115
   135
	alloc = table->buckets.alloc;
danw@115
   136
	array_add(&table->buckets, 4 * sizeof *buckets);
danw@115
   137
	if (alloc != table->buckets.alloc) {
danw@115
   138
		end = table->buckets.data + alloc;
danw@115
   139
		memset(end, 0, table->buckets.alloc - alloc);
danw@115
   140
		for (b = table->buckets.data; b < end; b++) {
danw@115
   141
			value = *b;
danw@115
   142
			if (value != 0) {
danw@115
   143
				*b = 0;
danw@115
   144
				do_insert(table, value);
danw@115
   145
			}
danw@115
   146
		}
danw@115
   147
	}
danw@115
   148
danw@115
   149
	value = add_to_string_pool(table, key);
danw@115
   150
	do_insert (table, value);
danw@115
   151
danw@115
   152
	return value;
danw@115
   153
}
danw@115
   154
danw@115
   155
uint32_t
danw@115
   156
hashtable_tokenize(struct hashtable *table, const char *string)
danw@115
   157
{
danw@115
   158
	uint32_t token;
danw@115
   159
danw@115
   160
	if (string == NULL)
danw@115
   161
		string = "";
danw@115
   162
danw@115
   163
	token = hashtable_lookup(table, string);
danw@115
   164
	if (token != 0)
danw@115
   165
		return token;
danw@115
   166
danw@115
   167
	return hashtable_insert(table, string);
danw@115
   168
}