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