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