types.c
changeset 115 26edeea5c95a
child 116 4ec6e2a55c34
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/types.c	Thu Feb 07 09:58:48 2008 -0500
     1.3 @@ -0,0 +1,168 @@
     1.4 +#include <stdlib.h>
     1.5 +#include <string.h>
     1.6 +
     1.7 +#include "types.h"
     1.8 +
     1.9 +void
    1.10 +array_init(struct array *array)
    1.11 +{
    1.12 +	memset(array, 0, sizeof *array);
    1.13 +}
    1.14 +
    1.15 +void
    1.16 +array_release(struct array *array)
    1.17 +{
    1.18 +	free(array->data);
    1.19 +}
    1.20 +
    1.21 +void *
    1.22 +array_add(struct array *array, int size)
    1.23 +{
    1.24 +	int alloc;
    1.25 +	void *data, *p;
    1.26 +
    1.27 +	if (array->alloc > 0)
    1.28 +		alloc = array->alloc;
    1.29 +	else
    1.30 +		alloc = 16;
    1.31 +
    1.32 +	while (alloc < array->size + size)
    1.33 +		alloc *= 2;
    1.34 +
    1.35 +	if (array->alloc < alloc) {
    1.36 +		data = realloc(array->data, alloc);
    1.37 +		if (data == NULL)
    1.38 +			return 0;
    1.39 +		array->data = data;
    1.40 +		array->alloc = alloc;
    1.41 +	}
    1.42 +
    1.43 +	p = array->data + array->size;
    1.44 +	array->size += size;
    1.45 +
    1.46 +	return p;
    1.47 +}
    1.48 +
    1.49 +
    1.50 +void
    1.51 +hashtable_init(struct hashtable *table, struct array *pool)
    1.52 +{
    1.53 +	array_init(&table->buckets);
    1.54 +	table->pool = pool;
    1.55 +}
    1.56 +
    1.57 +void
    1.58 +hashtable_release(struct hashtable *table)
    1.59 +{
    1.60 +	array_release(&table->buckets);
    1.61 +}
    1.62 +
    1.63 +static unsigned int
    1.64 +hash_string(const char *key)
    1.65 +{
    1.66 +	const char *p;
    1.67 +	unsigned int hash = 0;
    1.68 +
    1.69 +	for (p = key; *p; p++)
    1.70 +		hash = (hash * 617) ^ *p;
    1.71 +
    1.72 +	return hash;
    1.73 +}
    1.74 +
    1.75 +uint32_t
    1.76 +hashtable_lookup(struct hashtable *table, const char *key)
    1.77 +{
    1.78 +	unsigned int mask, start, i;
    1.79 +	uint32_t *b;
    1.80 +	char *pool;
    1.81 +
    1.82 +	pool = table->pool->data;
    1.83 +	mask = table->buckets.alloc - 1;
    1.84 +	start = hash_string(key) * sizeof(uint32_t);
    1.85 +
    1.86 +	for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
    1.87 +		b = table->buckets.data + ((start + i) & mask);
    1.88 +
    1.89 +		if (*b == 0)
    1.90 +			return 0;
    1.91 +
    1.92 +		if (strcmp(key, &pool[*b]) == 0)
    1.93 +			return *b;
    1.94 +	}
    1.95 +
    1.96 +	return 0;
    1.97 +}
    1.98 +
    1.99 +static void
   1.100 +do_insert(struct hashtable *table, uint32_t value)
   1.101 +{
   1.102 +	unsigned int mask, start, i;
   1.103 +	uint32_t *b;
   1.104 +	const char *key;
   1.105 +
   1.106 +	key = (char *) table->pool->data + value;
   1.107 +	mask = table->buckets.alloc - 1;
   1.108 +	start = hash_string(key) * sizeof(uint32_t);
   1.109 +
   1.110 +	for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
   1.111 +		b = table->buckets.data + ((start + i) & mask);
   1.112 +		if (*b == 0) {
   1.113 +			*b = value;
   1.114 +			break;
   1.115 +		}
   1.116 +	}
   1.117 +}
   1.118 +
   1.119 +static uint32_t
   1.120 +add_to_string_pool(struct hashtable *table, const char *key)
   1.121 +{
   1.122 +	int len;
   1.123 +	char *p;
   1.124 +
   1.125 +	len = strlen(key) + 1;
   1.126 +	p = array_add(table->pool, len);
   1.127 +	memcpy(p, key, len);
   1.128 +
   1.129 +	return p - (char *) table->pool->data;
   1.130 +}
   1.131 +
   1.132 +uint32_t
   1.133 +hashtable_insert(struct hashtable *table, const char *key)
   1.134 +{
   1.135 +	uint32_t value, *buckets, *b, *end;
   1.136 +	int alloc;
   1.137 +
   1.138 +	alloc = table->buckets.alloc;
   1.139 +	array_add(&table->buckets, 4 * sizeof *buckets);
   1.140 +	if (alloc != table->buckets.alloc) {
   1.141 +		end = table->buckets.data + alloc;
   1.142 +		memset(end, 0, table->buckets.alloc - alloc);
   1.143 +		for (b = table->buckets.data; b < end; b++) {
   1.144 +			value = *b;
   1.145 +			if (value != 0) {
   1.146 +				*b = 0;
   1.147 +				do_insert(table, value);
   1.148 +			}
   1.149 +		}
   1.150 +	}
   1.151 +
   1.152 +	value = add_to_string_pool(table, key);
   1.153 +	do_insert (table, value);
   1.154 +
   1.155 +	return value;
   1.156 +}
   1.157 +
   1.158 +uint32_t
   1.159 +hashtable_tokenize(struct hashtable *table, const char *string)
   1.160 +{
   1.161 +	uint32_t token;
   1.162 +
   1.163 +	if (string == NULL)
   1.164 +		string = "";
   1.165 +
   1.166 +	token = hashtable_lookup(table, string);
   1.167 +	if (token != 0)
   1.168 +		return token;
   1.169 +
   1.170 +	return hashtable_insert(table, string);
   1.171 +}