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