types.c
author Dan Winship <danw@gnome.org>
Mon Feb 11 11:21:54 2008 -0500 (2008-02-11)
changeset 119 66998d6a1765
parent 117 1c213cbf9da9
child 124 feef7736a439
permissions -rw-r--r--
split razor_property.name into name, flags, and type bitfields
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@117
    46
/* RAZOR_IMMEDIATE and RAZOR_ENTRY_LAST must have the same value */
danw@118
    47
#define RAZOR_ENTRY_LAST 0x80
danw@118
    48
#define RAZOR_IMMEDIATE  0x80
danw@118
    49
#define RAZOR_EMPTY_LIST 0xff
danw@116
    50
danw@116
    51
void
danw@117
    52
list_set_empty(struct list_head *head)
danw@116
    53
{
danw@117
    54
	head->list_ptr = ~0;
danw@117
    55
	head->flags = RAZOR_EMPTY_LIST;
danw@116
    56
}
danw@116
    57
danw@116
    58
void
danw@117
    59
list_set_ptr(struct list_head *head, uint32_t ptr)
danw@116
    60
{
danw@117
    61
	head->list_ptr = ptr;
danw@117
    62
	head->flags = 0;
danw@117
    63
}
danw@117
    64
danw@117
    65
void
danw@117
    66
list_set_array(struct list_head *head, struct array *pool, struct array *items)
danw@117
    67
{
danw@117
    68
	struct list *p;
danw@116
    69
danw@116
    70
	if (items->size == 0) {
danw@117
    71
		list_set_empty(head);
danw@116
    72
	} else if (items->size == sizeof (uint32_t)) {
danw@117
    73
		head->list_ptr = *(uint32_t *) items->data;
danw@117
    74
		head->flags = RAZOR_IMMEDIATE;
danw@116
    75
	} else {
danw@116
    76
		p = array_add(pool, items->size);
danw@116
    77
		memcpy(p, items->data, items->size);
danw@117
    78
		p[items->size / sizeof *p - 1].flags = RAZOR_ENTRY_LAST;
danw@117
    79
		list_set_ptr(head, p - (struct list *) pool->data);
danw@116
    80
	}
danw@116
    81
}
danw@116
    82
danw@117
    83
struct list *
danw@117
    84
list_first(struct list_head *head, struct array *pool)
danw@116
    85
{
danw@117
    86
	if (head->flags == RAZOR_EMPTY_LIST)
danw@116
    87
		return NULL;
danw@117
    88
	else if (head->flags == RAZOR_IMMEDIATE)
danw@117
    89
		return (struct list *) head;
danw@116
    90
	else
danw@117
    91
		return (struct list *) pool->data + head->list_ptr;
danw@116
    92
}
danw@116
    93
danw@117
    94
struct list *
danw@117
    95
list_next(struct list *list)
danw@116
    96
{
danw@117
    97
	if (list->flags)
danw@116
    98
		return NULL;
danw@116
    99
	return ++list;
danw@116
   100
}
danw@116
   101
danw@116
   102
void
danw@116
   103
list_remap_pool(struct array *pool, uint32_t *map)
danw@116
   104
{
danw@117
   105
	struct list *p, *end;
danw@116
   106
danw@116
   107
	end = pool->data + pool->size;
danw@116
   108
	for (p = pool->data; p < end; p++)
danw@117
   109
		p->data = map[p->data];
danw@116
   110
}
danw@116
   111
danw@116
   112
void
danw@117
   113
list_remap_head(struct list_head *head, uint32_t *map)
danw@116
   114
{
danw@117
   115
	if (head->flags == RAZOR_IMMEDIATE)
danw@117
   116
		head->list_ptr = map[head->list_ptr];
danw@116
   117
}
danw@116
   118
danw@115
   119
danw@115
   120
void
danw@115
   121
hashtable_init(struct hashtable *table, struct array *pool)
danw@115
   122
{
danw@115
   123
	array_init(&table->buckets);
danw@115
   124
	table->pool = pool;
danw@115
   125
}
danw@115
   126
danw@115
   127
void
danw@115
   128
hashtable_release(struct hashtable *table)
danw@115
   129
{
danw@115
   130
	array_release(&table->buckets);
danw@115
   131
}
danw@115
   132
danw@115
   133
static unsigned int
danw@115
   134
hash_string(const char *key)
danw@115
   135
{
danw@115
   136
	const char *p;
danw@115
   137
	unsigned int hash = 0;
danw@115
   138
danw@115
   139
	for (p = key; *p; p++)
danw@115
   140
		hash = (hash * 617) ^ *p;
danw@115
   141
danw@115
   142
	return hash;
danw@115
   143
}
danw@115
   144
danw@115
   145
uint32_t
danw@115
   146
hashtable_lookup(struct hashtable *table, const char *key)
danw@115
   147
{
danw@115
   148
	unsigned int mask, start, i;
danw@115
   149
	uint32_t *b;
danw@115
   150
	char *pool;
danw@115
   151
danw@115
   152
	pool = table->pool->data;
danw@115
   153
	mask = table->buckets.alloc - 1;
danw@115
   154
	start = hash_string(key) * sizeof(uint32_t);
danw@115
   155
danw@115
   156
	for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
danw@115
   157
		b = table->buckets.data + ((start + i) & mask);
danw@115
   158
danw@115
   159
		if (*b == 0)
danw@115
   160
			return 0;
danw@115
   161
danw@115
   162
		if (strcmp(key, &pool[*b]) == 0)
danw@115
   163
			return *b;
danw@115
   164
	}
danw@115
   165
danw@115
   166
	return 0;
danw@115
   167
}
danw@115
   168
danw@115
   169
static void
danw@115
   170
do_insert(struct hashtable *table, uint32_t value)
danw@115
   171
{
danw@115
   172
	unsigned int mask, start, i;
danw@115
   173
	uint32_t *b;
danw@115
   174
	const char *key;
danw@115
   175
danw@115
   176
	key = (char *) table->pool->data + value;
danw@115
   177
	mask = table->buckets.alloc - 1;
danw@115
   178
	start = hash_string(key) * sizeof(uint32_t);
danw@115
   179
danw@115
   180
	for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
danw@115
   181
		b = table->buckets.data + ((start + i) & mask);
danw@115
   182
		if (*b == 0) {
danw@115
   183
			*b = value;
danw@115
   184
			break;
danw@115
   185
		}
danw@115
   186
	}
danw@115
   187
}
danw@115
   188
danw@115
   189
static uint32_t
danw@115
   190
add_to_string_pool(struct hashtable *table, const char *key)
danw@115
   191
{
danw@115
   192
	int len;
danw@115
   193
	char *p;
danw@115
   194
danw@115
   195
	len = strlen(key) + 1;
danw@115
   196
	p = array_add(table->pool, len);
danw@115
   197
	memcpy(p, key, len);
danw@115
   198
danw@115
   199
	return p - (char *) table->pool->data;
danw@115
   200
}
danw@115
   201
danw@115
   202
uint32_t
danw@115
   203
hashtable_insert(struct hashtable *table, const char *key)
danw@115
   204
{
danw@115
   205
	uint32_t value, *buckets, *b, *end;
danw@115
   206
	int alloc;
danw@115
   207
danw@115
   208
	alloc = table->buckets.alloc;
danw@115
   209
	array_add(&table->buckets, 4 * sizeof *buckets);
danw@115
   210
	if (alloc != table->buckets.alloc) {
danw@115
   211
		end = table->buckets.data + alloc;
danw@115
   212
		memset(end, 0, table->buckets.alloc - alloc);
danw@115
   213
		for (b = table->buckets.data; b < end; b++) {
danw@115
   214
			value = *b;
danw@115
   215
			if (value != 0) {
danw@115
   216
				*b = 0;
danw@115
   217
				do_insert(table, value);
danw@115
   218
			}
danw@115
   219
		}
danw@115
   220
	}
danw@115
   221
danw@115
   222
	value = add_to_string_pool(table, key);
danw@115
   223
	do_insert (table, value);
danw@115
   224
danw@115
   225
	return value;
danw@115
   226
}
danw@115
   227
danw@115
   228
uint32_t
danw@115
   229
hashtable_tokenize(struct hashtable *table, const char *string)
danw@115
   230
{
danw@115
   231
	uint32_t token;
danw@115
   232
danw@115
   233
	if (string == NULL)
danw@115
   234
		string = "";
danw@115
   235
danw@115
   236
	token = hashtable_lookup(table, string);
danw@115
   237
	if (token != 0)
danw@115
   238
		return token;
danw@115
   239
danw@115
   240
	return hashtable_insert(table, string);
danw@115
   241
}