rpm/lib/hash.c

137 lines
2.7 KiB
C

#include "system.h"
#include "rpmlib.h"
#include "hash.h"
struct hashBucket {
void * key;
void ** data;
int dataCount;
struct hashBucket * next;
};
struct hashTable_s {
int numBuckets;
int keySize;
struct hashBucket ** buckets;
hashFunctionType fn;
hashEqualityType eq;
};
static struct hashBucket * findEntry(hashTable ht, const void * key);
int hashEqualityString(const void * key1, const void * key2) {
char *k1 = (char *)key1;
char *k2 = (char *)key2;
return strcmp(k1, k2);
}
unsigned int hashFunctionString(const void * string) {
char xorValue = 0;
char sum = 0;
short len;
int i;
const char * chp = string;
len = strlen(string);
for (i = 0; i < len; i++, chp++) {
xorValue ^= *chp;
sum += *chp;
}
return ((len << 16) + (sum << 8) + xorValue);
};
hashTable htCreate(int numBuckets, int keySize, hashFunctionType fn,
hashEqualityType eq) {
hashTable ht;
ht = malloc(sizeof(*ht));
ht->numBuckets = numBuckets;
ht->buckets = calloc(sizeof(*ht->buckets), numBuckets);
ht->keySize = keySize;
ht->fn = fn;
ht->eq = eq;
return ht;
}
void htAddEntry(hashTable ht, const void * key, void * data) {
unsigned int hash;
struct hashBucket * b, * ob;
hash = ht->fn(key) % ht->numBuckets;
b = ob = ht->buckets[hash];
while (b && b->key && !ht->eq(b->key, key))
b = b->next;
if (!b) {
b = malloc(sizeof(*b));
if (ht->keySize) {
b->key = malloc(ht->keySize);
memcpy(b->key, key, ht->keySize);
} else {
b->key = (void *) key;
}
b->dataCount = 0;
b->next = ht->buckets[hash];
b->data = NULL;
ht->buckets[hash] = b;
}
b->data = realloc(b->data, sizeof(*b->data) * (b->dataCount + 1));
b->data[b->dataCount++] = data;
}
void htFree(hashTable ht) {
int i;
struct hashBucket * b, * n;
for (i = 0; i < ht->numBuckets; i++) {
b = ht->buckets[i];
if (ht->keySize && b) free(b->key);
while (b) {
n = b->next;
free(b);
b = n;
}
}
free(ht->buckets);
free(ht);
}
static struct hashBucket * findEntry(hashTable ht, const void * key) {
unsigned int hash;
struct hashBucket * b;
hash = ht->fn(key) % ht->numBuckets;
b = ht->buckets[hash];
while (b && b->key && !ht->eq(b->key, key))
b = b->next;
return b;
}
int htHasEntry(hashTable ht, const void * key) {
struct hashBucket * b;
if (!(b = findEntry(ht, key))) return 0; else return 1;
}
int htGetEntry(hashTable ht, const void * key, void *** data,
int * dataCount, void ** tableKey) {
struct hashBucket * b;
if (!(b = findEntry(ht, key))) return 1;
*data = b->data;
*dataCount = b->dataCount;
if (tableKey) *tableKey = b->key;
return 0;
}