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