librazor/types.c
author J. Ali Harlow <ali@juiblex.co.uk>
Wed Apr 29 17:00:01 2009 +0100 (2009-04-29)
changeset 361 2523d03a840e
parent 300 455eaa569767
permissions -rw-r--r--
Add support for preloading lua modules. This is useful both when
providing lua bindings to applications based on librazor and when
producing static binaries using librazor (where otherwise the lua
POSIX library would need to be included as an additional dynamic
object).
     1 /*
     2  * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
     3  * Copyright (C) 2008  Red Hat, Inc
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation; either version 2 of the License, or
     8  * (at your option) any later version.
     9  *
    10  * This program is distributed in the hope that it will be useful,
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  * GNU General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU General Public License along
    16  * with this program; if not, write to the Free Software Foundation, Inc.,
    17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    18  */
    19 
    20 #include <stdlib.h>
    21 #include <string.h>
    22 
    23 #include "razor-internal.h"
    24 
    25 void
    26 array_init(struct array *array)
    27 {
    28 	memset(array, 0, sizeof *array);
    29 }
    30 
    31 void
    32 array_release(struct array *array)
    33 {
    34 	free(array->data);
    35 }
    36 
    37 void *
    38 array_add(struct array *array, int size)
    39 {
    40 	int alloc;
    41 	void *data, *p;
    42 
    43 	if (array->alloc > 0)
    44 		alloc = array->alloc;
    45 	else
    46 		alloc = 16;
    47 
    48 	while (alloc < array->size + size)
    49 		alloc *= 2;
    50 
    51 	if (array->alloc < alloc) {
    52 		data = realloc(array->data, alloc);
    53 		if (data == NULL)
    54 			return 0;
    55 		array->data = data;
    56 		array->alloc = alloc;
    57 	}
    58 
    59 	p = array->data + array->size;
    60 	array->size += size;
    61 
    62 	return p;
    63 }
    64 
    65 /* RAZOR_IMMEDIATE and RAZOR_ENTRY_LAST must have the same value */
    66 #define RAZOR_ENTRY_LAST 0x80
    67 #define RAZOR_IMMEDIATE  0x80
    68 #define RAZOR_EMPTY_LIST 0xff
    69 
    70 void
    71 list_set_empty(struct list_head *head)
    72 {
    73 	head->list_ptr = ~0;
    74 	head->flags = RAZOR_EMPTY_LIST;
    75 }
    76 
    77 void
    78 list_set_ptr(struct list_head *head, uint32_t ptr)
    79 {
    80 	head->list_ptr = ptr;
    81 	head->flags = 0;
    82 }
    83 
    84 void
    85 list_set_array(struct list_head *head, struct array *pool,
    86 	       struct array *items, int force_indirect)
    87 {
    88 	struct list *p;
    89 
    90 	if (!force_indirect) {
    91 		if (items->size == 0) {
    92 			list_set_empty(head);
    93 			return;
    94 		} else if (items->size == sizeof (uint32_t)) {
    95 			head->list_ptr = *(uint32_t *) items->data;
    96 			head->flags = RAZOR_IMMEDIATE;
    97 			return;
    98 		}
    99 	}
   100 
   101 	p = array_add(pool, items->size);
   102 	memcpy(p, items->data, items->size);
   103 	p[items->size / sizeof *p - 1].flags = RAZOR_ENTRY_LAST;
   104 	list_set_ptr(head, p - (struct list *) pool->data);
   105 }
   106 
   107 struct list *
   108 list_first(struct list_head *head, struct array *pool)
   109 {
   110 	if (head->flags == RAZOR_EMPTY_LIST)
   111 		return NULL;
   112 	else if (head->flags == RAZOR_IMMEDIATE)
   113 		return (struct list *) head;
   114 	else
   115 		return (struct list *) pool->data + head->list_ptr;
   116 }
   117 
   118 struct list *
   119 list_next(struct list *list)
   120 {
   121 	if (list->flags)
   122 		return NULL;
   123 	return ++list;
   124 }
   125 
   126 void
   127 list_remap_pool(struct array *pool, uint32_t *map)
   128 {
   129 	struct list *p, *end;
   130 
   131 	end = pool->data + pool->size;
   132 	for (p = pool->data; p < end; p++)
   133 		p->data = map[p->data];
   134 }
   135 
   136 void
   137 list_remap_head(struct list_head *head, uint32_t *map)
   138 {
   139 	if (head->flags == RAZOR_IMMEDIATE)
   140 		head->list_ptr = map[head->list_ptr];
   141 }
   142 
   143 
   144 void
   145 hashtable_init(struct hashtable *table, struct array *pool)
   146 {
   147 	array_init(&table->buckets);
   148 	table->pool = pool;
   149 }
   150 
   151 void
   152 hashtable_release(struct hashtable *table)
   153 {
   154 	array_release(&table->buckets);
   155 }
   156 
   157 static unsigned int
   158 hash_string(const char *key)
   159 {
   160 	const char *p;
   161 	unsigned int hash = 0;
   162 
   163 	for (p = key; *p; p++)
   164 		hash = (hash * 617) ^ *p;
   165 
   166 	return hash;
   167 }
   168 
   169 uint32_t
   170 hashtable_lookup(struct hashtable *table, const char *key)
   171 {
   172 	unsigned int mask, start, i;
   173 	uint32_t *b;
   174 	char *pool;
   175 
   176 	pool = table->pool->data;
   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 
   183 		if (*b == 0xFFFFFFFF)
   184 			return 0xFFFFFFFF;
   185 
   186 		if (strcmp(key, &pool[*b]) == 0)
   187 			return *b;
   188 	}
   189 
   190 	return 0xFFFFFFFF;
   191 }
   192 
   193 static void
   194 do_insert(struct hashtable *table, uint32_t value)
   195 {
   196 	unsigned int mask, start, i;
   197 	uint32_t *b;
   198 	const char *key;
   199 
   200 	key = (char *) table->pool->data + value;
   201 	mask = table->buckets.alloc - 1;
   202 	start = hash_string(key) * sizeof(uint32_t);
   203 
   204 	for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
   205 		b = table->buckets.data + ((start + i) & mask);
   206 		if (*b == 0xFFFFFFFF) {
   207 			*b = value;
   208 			break;
   209 		}
   210 	}
   211 }
   212 
   213 static uint32_t
   214 add_to_string_pool(struct hashtable *table, const char *key)
   215 {
   216 	int len;
   217 	char *p;
   218 
   219 	len = strlen(key) + 1;
   220 	p = array_add(table->pool, len);
   221 	memcpy(p, key, len);
   222 
   223 	return p - (char *) table->pool->data;
   224 }
   225 
   226 uint32_t
   227 hashtable_insert(struct hashtable *table, const char *key)
   228 {
   229 	uint32_t value, *buckets, *b, *end;
   230 	int alloc;
   231 
   232 	alloc = table->buckets.alloc;
   233 	array_add(&table->buckets, 4 * sizeof *buckets);
   234 	if (alloc != table->buckets.alloc) {
   235 		end = table->buckets.data + alloc;
   236 		memset(end, 0xFF, table->buckets.alloc - alloc);
   237 		for (b = table->buckets.data; b < end; b++) {
   238 			value = *b;
   239 			if (value != 0xFFFFFFFF) {
   240 				*b = 0xFFFFFFFF;
   241 				do_insert(table, value);
   242 			}
   243 		}
   244 	}
   245 
   246 	value = add_to_string_pool(table, key);
   247 	do_insert (table, value);
   248 
   249 	return value;
   250 }
   251 
   252 uint32_t
   253 hashtable_tokenize(struct hashtable *table, const char *string)
   254 {
   255 	uint32_t token;
   256 
   257 	if (string == NULL)
   258 		string = "";
   259 
   260 	token = hashtable_lookup(table, string);
   261 	if (token != 0xFFFFFFFF)
   262 		return token;
   263 
   264 	return hashtable_insert(table, string);
   265 }