librazor/types.c
author J. Ali Harlow <ali@juiblex.co.uk>
Wed Jan 14 12:21:38 2009 +0000 (2009-01-14)
changeset 350 1555934cfb04
parent 248 057933050c42
child 358 13beaca8b75f
permissions -rw-r--r--
Fix bug causing "razor remove" to quietly fail.
     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 == 0)
   184 			return 0;
   185 
   186 		if (strcmp(key, &pool[*b]) == 0)
   187 			return *b;
   188 	}
   189 
   190 	return 0;
   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 == 0) {
   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, 0, table->buckets.alloc - alloc);
   237 		for (b = table->buckets.data; b < end; b++) {
   238 			value = *b;
   239 			if (value != 0) {
   240 				*b = 0;
   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 != 0)
   262 		return token;
   263 
   264 	return hashtable_insert(table, string);
   265 }