1 /* hash.c - hash tables for opkg
3 Steven M. Ayer, Jamey Hicks
5 Copyright (C) 2002 Compaq Computer Corporation
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2, or (at
10 your option) any later version.
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
22 #include "hash_table.h"
23 #include "opkg_message.h"
24 #include "libbb/libbb.h"
27 static int hash_index(hash_table_t *hash, const char *pkg_name);
28 static int rotating(const char *key, int len, int prime);
30 static int hash_index(hash_table_t *hash, const char *pkg_name)
32 return rotating(pkg_name, strlen(pkg_name), hash->n_entries);
35 static int rotating(const char *key, int len, int prime)
38 for (hash=len, i=0; i<len; ++i)
39 hash = (hash<<4)^(hash>>28)^key[i];
40 return (hash % prime);
45 * this is an open table keyed by strings
47 int hash_table_init(const char *name, hash_table_t *hash, int len)
49 static int primes_table[] = {
50 379, 761, 983, 1423, 2711, 3361, 3931, 4679, 5519, 6701, 9587,
51 19471, 23143, 33961, 46499, 49727, 99529, 0
55 if (hash->entries != NULL) {
56 /* we have been here already */
63 hash->hash_entry_key = NULL;
65 picker = primes_table;
66 while(*picker && (*picker++ < len));
68 fprintf(stderr, "%s: primes table might not be big enough (! << %d)\n", __FUNCTION__, len);
71 hash->n_entries = *picker;
72 hash->entries = (hash_entry_t *)calloc(hash->n_entries, sizeof(hash_entry_t));
73 if (hash->entries == NULL) {
74 fprintf(stderr, "%s: Out of memory.\n", __FUNCTION__);
80 void hash_table_deinit(hash_table_t *hash)
86 /* free the reminaing entries */
87 for (i = 0; i < hash->n_entries; i++) {
88 hash_entry_t *hash_entry = (hash->entries + i);
89 free (hash_entry->key);
90 /* skip the first entry as this is part of the array */
91 hash_entry = hash_entry->next;
94 hash_entry_t *old = hash_entry;
95 hash_entry = hash_entry->next;
101 free (hash->entries);
103 hash->entries = NULL;
107 void *hash_table_get(hash_table_t *hash, const char *key)
109 int ndx= hash_index(hash, key);
110 hash_entry_t *hash_entry = hash->entries + ndx;
115 if (strcmp(key, hash_entry->key) == 0) {
116 // opkg_message(NULL, OPKG_DEBUG, "Function: %s. Key found for '%s' \n", __FUNCTION__, key);
117 return hash_entry->data;
120 hash_entry = hash_entry->next;
125 int hash_table_insert(hash_table_t *hash, const char *key, void *value)
127 int ndx= hash_index(hash, key);
128 hash_entry_t *hash_entry = hash->entries + ndx;
129 if (0) opkg_message(NULL, OPKG_DEBUG2, "Function: %s. Inserting in hash for '%s' \n", __FUNCTION__, key);
130 if (hash_entry->key) {
131 if (strcmp(hash_entry->key, key) == 0) {
132 /* alread in table, update the value */
133 if (0) opkg_message(NULL, OPKG_DEBUG2, "Function: %s. Value already in hash for '%s' \n", __FUNCTION__, key);
134 hash_entry->data = value;
138 * if this is a collision, we have to go to the end of the ll,
139 * then add a new entry
140 * before we can hook up the value
142 if (0) opkg_message(NULL, OPKG_DEBUG2, "Function: %s. Value already in hash by collision for '%s' \n", __FUNCTION__, key);
143 while (hash_entry->next) {
144 hash_entry = hash_entry->next;
145 if (strcmp(hash_entry->key, key) == 0) {
146 hash_entry->data = value;
150 hash_entry->next = (hash_entry_t *)calloc(1, sizeof(hash_entry_t));
151 if (!hash_entry->next) {
154 hash_entry = hash_entry->next;
155 hash_entry->next = NULL;
159 hash_entry->key = xstrdup(key);
160 hash_entry->data = value;
165 int hash_table_remove(hash_table_t *hash, const char *key)
167 int ndx= hash_index(hash, key);
168 hash_entry_t *hash_entry = hash->entries + ndx;
169 hash_entry_t *next_entry=NULL, *last_entry=NULL;
174 if (strcmp(key, hash_entry->key) == 0) {
175 free(hash_entry->key);
177 last_entry->next = hash_entry->next;
180 next_entry = hash_entry->next;
182 memmove(hash_entry, next_entry, sizeof(hash_entry_t));
185 memset(hash_entry, 0 , sizeof(hash_entry_t));
191 last_entry = hash_entry;
192 hash_entry = hash_entry->next;
197 void hash_table_foreach(hash_table_t *hash, void (*f)(const char *key, void *entry, void *data), void *data)
203 for (i = 0; i < hash->n_entries; i++) {
204 hash_entry_t *hash_entry = (hash->entries + i);
206 if(hash_entry->key) {
207 f(hash_entry->key, hash_entry->data, data);
209 } while((hash_entry = hash_entry->next));