librazor/types.c
author James Bowes <jbowes@redhat.com>
Wed Jul 09 10:11:13 2008 -0400 (2008-07-09)
changeset 318 829d6711b316
parent 248 057933050c42
child 358 13beaca8b75f
permissions -rw-r--r--
Use strings to identify section types in the on-disk repo format.

Previously, a given razor file type had a fixed number of sections in a
fixed order, identified by an integer type. Now, sections are identified
by a named string (stored in a string pool after the section lists).

This will allow for razor files to contain arbitrary sections.

For bonus points, also drop the 4k section alignment and change the
magic byte string to "RZDB".

committer: Kristian H?gsberg <krh@redhat.com>
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
}