types.c
author Kristian H?gsberg <krh@localhost.localdomain>
Wed Apr 30 18:22:47 2008 -0400 (2008-04-30)
changeset 214 d1e9e6a80151
parent 140 017f92f7039a
child 230 c1e2aed8dd07
permissions -rw-r--r--
Add more TODO items.
     1 #include <stdlib.h>
     2 #include <string.h>
     3 
     4 #include "types.h"
     5 
     6 void
     7 array_init(struct array *array)
     8 {
     9 	memset(array, 0, sizeof *array);
    10 }
    11 
    12 void
    13 array_release(struct array *array)
    14 {
    15 	free(array->data);
    16 }
    17 
    18 void *
    19 array_add(struct array *array, int size)
    20 {
    21 	int alloc;
    22 	void *data, *p;
    23 
    24 	if (array->alloc > 0)
    25 		alloc = array->alloc;
    26 	else
    27 		alloc = 16;
    28 
    29 	while (alloc < array->size + size)
    30 		alloc *= 2;
    31 
    32 	if (array->alloc < alloc) {
    33 		data = realloc(array->data, alloc);
    34 		if (data == NULL)
    35 			return 0;
    36 		array->data = data;
    37 		array->alloc = alloc;
    38 	}
    39 
    40 	p = array->data + array->size;
    41 	array->size += size;
    42 
    43 	return p;
    44 }
    45 
    46 /* RAZOR_IMMEDIATE and RAZOR_ENTRY_LAST must have the same value */
    47 #define RAZOR_ENTRY_LAST 0x80
    48 #define RAZOR_IMMEDIATE  0x80
    49 #define RAZOR_EMPTY_LIST 0xff
    50 
    51 void
    52 list_set_empty(struct list_head *head)
    53 {
    54 	head->list_ptr = ~0;
    55 	head->flags = RAZOR_EMPTY_LIST;
    56 }
    57 
    58 void
    59 list_set_ptr(struct list_head *head, uint32_t ptr)
    60 {
    61 	head->list_ptr = ptr;
    62 	head->flags = 0;
    63 }
    64 
    65 void
    66 list_set_array(struct list_head *head, struct array *pool,
    67 	       struct array *items, int force_indirect)
    68 {
    69 	struct list *p;
    70 
    71 	if (!force_indirect) {
    72 		if (items->size == 0) {
    73 			list_set_empty(head);
    74 			return;
    75 		} else if (items->size == sizeof (uint32_t)) {
    76 			head->list_ptr = *(uint32_t *) items->data;
    77 			head->flags = RAZOR_IMMEDIATE;
    78 			return;
    79 		}
    80 	}
    81 
    82 	p = array_add(pool, items->size);
    83 	memcpy(p, items->data, items->size);
    84 	p[items->size / sizeof *p - 1].flags = RAZOR_ENTRY_LAST;
    85 	list_set_ptr(head, p - (struct list *) pool->data);
    86 }
    87 
    88 struct list *
    89 list_first(struct list_head *head, struct array *pool)
    90 {
    91 	if (head->flags == RAZOR_EMPTY_LIST)
    92 		return NULL;
    93 	else if (head->flags == RAZOR_IMMEDIATE)
    94 		return (struct list *) head;
    95 	else
    96 		return (struct list *) pool->data + head->list_ptr;
    97 }
    98 
    99 struct list *
   100 list_next(struct list *list)
   101 {
   102 	if (list->flags)
   103 		return NULL;
   104 	return ++list;
   105 }
   106 
   107 void
   108 list_remap_pool(struct array *pool, uint32_t *map)
   109 {
   110 	struct list *p, *end;
   111 
   112 	end = pool->data + pool->size;
   113 	for (p = pool->data; p < end; p++)
   114 		p->data = map[p->data];
   115 }
   116 
   117 void
   118 list_remap_head(struct list_head *head, uint32_t *map)
   119 {
   120 	if (head->flags == RAZOR_IMMEDIATE)
   121 		head->list_ptr = map[head->list_ptr];
   122 }
   123 
   124 
   125 void
   126 hashtable_init(struct hashtable *table, struct array *pool)
   127 {
   128 	array_init(&table->buckets);
   129 	table->pool = pool;
   130 }
   131 
   132 void
   133 hashtable_release(struct hashtable *table)
   134 {
   135 	array_release(&table->buckets);
   136 }
   137 
   138 static unsigned int
   139 hash_string(const char *key)
   140 {
   141 	const char *p;
   142 	unsigned int hash = 0;
   143 
   144 	for (p = key; *p; p++)
   145 		hash = (hash * 617) ^ *p;
   146 
   147 	return hash;
   148 }
   149 
   150 uint32_t
   151 hashtable_lookup(struct hashtable *table, const char *key)
   152 {
   153 	unsigned int mask, start, i;
   154 	uint32_t *b;
   155 	char *pool;
   156 
   157 	pool = table->pool->data;
   158 	mask = table->buckets.alloc - 1;
   159 	start = hash_string(key) * sizeof(uint32_t);
   160 
   161 	for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
   162 		b = table->buckets.data + ((start + i) & mask);
   163 
   164 		if (*b == 0)
   165 			return 0;
   166 
   167 		if (strcmp(key, &pool[*b]) == 0)
   168 			return *b;
   169 	}
   170 
   171 	return 0;
   172 }
   173 
   174 static void
   175 do_insert(struct hashtable *table, uint32_t value)
   176 {
   177 	unsigned int mask, start, i;
   178 	uint32_t *b;
   179 	const char *key;
   180 
   181 	key = (char *) table->pool->data + value;
   182 	mask = table->buckets.alloc - 1;
   183 	start = hash_string(key) * sizeof(uint32_t);
   184 
   185 	for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
   186 		b = table->buckets.data + ((start + i) & mask);
   187 		if (*b == 0) {
   188 			*b = value;
   189 			break;
   190 		}
   191 	}
   192 }
   193 
   194 static uint32_t
   195 add_to_string_pool(struct hashtable *table, const char *key)
   196 {
   197 	int len;
   198 	char *p;
   199 
   200 	len = strlen(key) + 1;
   201 	p = array_add(table->pool, len);
   202 	memcpy(p, key, len);
   203 
   204 	return p - (char *) table->pool->data;
   205 }
   206 
   207 uint32_t
   208 hashtable_insert(struct hashtable *table, const char *key)
   209 {
   210 	uint32_t value, *buckets, *b, *end;
   211 	int alloc;
   212 
   213 	alloc = table->buckets.alloc;
   214 	array_add(&table->buckets, 4 * sizeof *buckets);
   215 	if (alloc != table->buckets.alloc) {
   216 		end = table->buckets.data + alloc;
   217 		memset(end, 0, table->buckets.alloc - alloc);
   218 		for (b = table->buckets.data; b < end; b++) {
   219 			value = *b;
   220 			if (value != 0) {
   221 				*b = 0;
   222 				do_insert(table, value);
   223 			}
   224 		}
   225 	}
   226 
   227 	value = add_to_string_pool(table, key);
   228 	do_insert (table, value);
   229 
   230 	return value;
   231 }
   232 
   233 uint32_t
   234 hashtable_tokenize(struct hashtable *table, const char *string)
   235 {
   236 	uint32_t token;
   237 
   238 	if (string == NULL)
   239 		string = "";
   240 
   241 	token = hashtable_lookup(table, string);
   242 	if (token != 0)
   243 		return token;
   244 
   245 	return hashtable_insert(table, string);
   246 }
   247 
   248 
   249 void
   250 bitarray_init(struct bitarray *bitarray, int size, int initial_value)
   251 {
   252 	int bytes = ((size + 31) / 32) * 4;
   253 
   254 	bitarray->bits = malloc(bytes);
   255 	memset(bitarray->bits, initial_value ? 0xff : 0x00, bytes);
   256 }
   257 
   258 void
   259 bitarray_release(struct bitarray *bitarray)
   260 {
   261 	free(bitarray->bits);
   262 }
   263 
   264 void
   265 bitarray_set(struct bitarray *bitarray, int bit, int value)
   266 {
   267 	if (value)
   268 		bitarray->bits[bit >> 5] |= 1 << (bit & 31);
   269 	else
   270 		bitarray->bits[bit >> 5] &= ~(1 << (bit & 31));
   271 }
   272 
   273 int
   274 bitarray_get(struct bitarray *bitarray, int bit)
   275 {
   276 	return (bitarray->bits[bit >> 5] & (1 << (bit & 31))) != 0;
   277 }