diff options
author | Florian Festi <ffesti@redhat.com> | 2008-10-17 16:18:45 +0200 |
---|---|---|
committer | Florian Festi <ffesti@redhat.com> | 2008-10-24 10:34:25 +0200 |
commit | 832909b4a7f093f6ab223850dad892223a71ff80 (patch) | |
tree | 93db7c0fd8d9d7d752d1196c1b21a8053f23e520 /lib | |
parent | 6a8c221ce6a890d6b23daed92669eb90e80ec2af (diff) | |
download | rpm-832909b4a7f093f6ab223850dad892223a71ff80.tar.gz rpm-832909b4a7f093f6ab223850dad892223a71ff80.tar.bz2 rpm-832909b4a7f093f6ab223850dad892223a71ff80.zip |
Make rpmhash a generic datatype using macros and includes
Diffstat (limited to 'lib')
-rw-r--r-- | lib/fprint.h | 2 | ||||
-rw-r--r-- | lib/rpmhash.C | 175 | ||||
-rw-r--r-- | lib/rpmhash.H | 90 | ||||
-rw-r--r-- | lib/rpmhash.c | 155 | ||||
-rw-r--r-- | lib/rpmhash.h | 88 |
5 files changed, 271 insertions, 239 deletions
diff --git a/lib/fprint.h b/lib/fprint.h index 30bcb4b2f..ff4dbfeaa 100644 --- a/lib/fprint.h +++ b/lib/fprint.h @@ -8,6 +8,8 @@ #include <rpm/header.h> #include "lib/rpmhash.h" +#include "lib/rpmdb_internal.h" +#include "lib/rpmts_internal.h" /** */ diff --git a/lib/rpmhash.C b/lib/rpmhash.C new file mode 100644 index 000000000..2d7cfde1d --- /dev/null +++ b/lib/rpmhash.C @@ -0,0 +1,175 @@ +/** + * \file lib/rpmhash.c + * Hash table implemenation + */ + +#include "system.h" +#include "debug.h" + +#define Bucket JOIN(HASHTYPE,Buket) +#define Bucket_s JOIN(HASHTYPE,Buket_s) + +typedef struct Bucket_s * Bucket; + +/** + */ +struct Bucket_s { + HTKEYTYPE key; /*!< hash key */ + HTDATATYPE * data; /*!< pointer to hashed data */ + int dataCount; /*!< length of data (0 if unknown) */ + Bucket next; /*!< pointer to next item in bucket */ +}; + +/** + */ +struct HASHSTRUCT { + int numBuckets; /*!< number of hash buckets */ + Bucket * buckets; /*!< hash bucket array */ + hashFunctionType fn; /*!< generate hash value for key */ + hashEqualityType eq; /*!< compare hash keys for equality */ + hashFreeKey freeKey; + hashFreeData freeData; +}; + +/** + * Find entry in hash table. + * @param ht pointer to hash table + * @param key pointer to key value + * @return pointer to hash bucket of key (or NULL) + */ +static +Bucket HASHPREFIX(findEntry)(HASHTYPE ht, HTKEYTYPE key) +{ + unsigned int hash; + Bucket 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; +} + +HASHTYPE HASHPREFIX(Create)(int numBuckets, + hashFunctionType fn, hashEqualityType eq, + hashFreeKey freeKey, hashFreeData freeData) +{ + HASHTYPE ht; + + ht = xmalloc(sizeof(*ht)); + ht->numBuckets = numBuckets; + ht->buckets = xcalloc(numBuckets, sizeof(*ht->buckets)); + ht->freeKey = freeKey; + ht->freeData = freeData; + ht->fn = fn; + ht->eq = eq; + return ht; +} + +void HASHPREFIX(AddEntry)(HASHTYPE ht, HTKEYTYPE key, HTDATATYPE data) +{ + unsigned int hash; + Bucket b; + + hash = ht->fn(key) % ht->numBuckets; + b = ht->buckets[hash]; + + while (b && b->key && ht->eq(b->key, key)) + b = b->next; + + if (b == NULL) { + b = xmalloc(sizeof(*b)); + b->key = key; + b->dataCount = 0; + b->next = ht->buckets[hash]; + b->data = NULL; + ht->buckets[hash] = b; + } + + b->data = xrealloc(b->data, sizeof(*b->data) * (b->dataCount + 1)); + b->data[b->dataCount++] = data; +} + +HASHTYPE HASHPREFIX(Free)(HASHTYPE ht) +{ + Bucket b, n; + int i, j; + + for (i = 0; i < ht->numBuckets; i++) { + b = ht->buckets[i]; + if (b == NULL) + continue; + ht->buckets[i] = NULL; + if (ht->freeKey) + b->key = ht->freeKey(b->key); + + do { + n = b->next; + if (b->data) { + if (ht->freeData) { + for (j=0; j < b->dataCount; j++ ) { + b->data[j] = ht->freeData(b->data[j]); + } + } + b->data = _free(b->data); + } + b = _free(b); + } while ((b = n) != NULL); + } + + ht->buckets = _free(ht->buckets); + ht = _free(ht); + + return NULL; +} + +int HASHPREFIX(HasEntry)(HASHTYPE ht, HTKEYTYPE key) +{ + Bucket b; + + if (!(b = HASHPREFIX(findEntry)(ht, key))) return 0; else return 1; +} + +int HASHPREFIX(GetEntry)(HASHTYPE ht, HTKEYTYPE key, HTDATATYPE** data, + int * dataCount, HTKEYTYPE* tableKey) +{ + Bucket b; + + if ((b = HASHPREFIX(findEntry)(ht, key)) == NULL) + return 1; + + if (data) + *data = b->data; + if (dataCount) + *dataCount = b->dataCount; + if (tableKey) + *tableKey = b->key; + + return 0; +} + +void HASHPREFIX(PrintStats)(HASHTYPE ht) { + int i; + Bucket bucket; + + int hashcnt=0, bucketcnt=0, datacnt=0; + int maxbuckets=0; + + for (i=0; i<ht->numBuckets; i++) { + int buckets = 0; + for (bucket=ht->buckets[i]; bucket; bucket=bucket->next){ + buckets++; + datacnt += bucket->dataCount; + } + if (maxbuckets < buckets) maxbuckets = buckets; + if (buckets) hashcnt++; + bucketcnt += buckets; + } + fprintf(stderr, "Hashsize: %i\n", ht->numBuckets); + fprintf(stderr, "Hashbuckets: %i\n", hashcnt); + fprintf(stderr, "Keys: %i\n", bucketcnt); + fprintf(stderr, "Values: %i\n", datacnt); + fprintf(stderr, "Max Keys/Bucket: %i\n", maxbuckets); +} diff --git a/lib/rpmhash.H b/lib/rpmhash.H new file mode 100644 index 000000000..324cbc839 --- /dev/null +++ b/lib/rpmhash.H @@ -0,0 +1,90 @@ +/** + * \file lib/rpmhash.h + * Hash table implemenation. + */ + +#include <string.h> +// Hackery to make sure that macros get expanded +#define __JOIN(a,b) a##b +#define JOIN(a,b) __JOIN(a,b) +#define HASHPREFIX(name) JOIN(HASHTYPE,name) +#define HASHSTRUCT JOIN(HASHTYPE,_s) + +typedef struct HASHSTRUCT * HASHTYPE; + +/* function pointer types to deal with the datatypes the hash works with */ + +#define hashFunctionType JOIN(HASHTYPE,HashFunctionType) +#define hashEqualityType JOIN(HASHTYPE,HashEqualityType) +#define hashFreeKey JOIN(HASHTYPE,FreeKey) +#define hashFreeData JOIN(HASHTYPE,FreeData) + +typedef unsigned int (*hashFunctionType) (HTKEYTYPE string); +typedef int (*hashEqualityType) (HTKEYTYPE key1, HTKEYTYPE key2); +typedef HTKEYTYPE (*hashFreeKey) (HTKEYTYPE); +typedef HTDATATYPE (*hashFreeData) (HTDATATYPE); + +/** + * Create hash table. + * If keySize > 0, the key is duplicated within the table (which costs + * memory, but may be useful anyway. + * @param numBuckets number of hash buckets + * @param fn function to generate hash value for key + * @param eq function to compare hash keys for equality + * @param freeKey function to free the keys or NULL + * @param freeData function to free the data or NULL + * @return pointer to initialized hash table + */ +RPM_GNUC_INTERNAL +HASHTYPE HASHPREFIX(Create)(int numBuckets, + hashFunctionType fn, hashEqualityType eq, + hashFreeKey freeKey, hashFreeData freeData); + +/** + * Destroy hash table. + * @param ht pointer to hash table + * @return NULL always + */ +RPM_GNUC_INTERNAL +HASHTYPE HASHPREFIX(Free)( HASHTYPE ht); + +/** + * Add item to hash table. + * @param ht pointer to hash table + * @param key key + * @param data data value + */ +RPM_GNUC_INTERNAL +void HASHPREFIX(AddEntry)(HASHTYPE ht, HTKEYTYPE key, HTDATATYPE data); + +/** + * Retrieve item from hash table. + * @param ht pointer to hash table + * @param key key value + * @retval data address to store data value from bucket + * @retval dataCount address to store data value size from bucket + * @retval tableKey address to store key value from bucket (may be NULL) + * @return 0 on success, 1 if the item is not found. + */ +RPM_GNUC_INTERNAL +int HASHPREFIX(GetEntry)(HASHTYPE ht, HTKEYTYPE key, + HTDATATYPE** data, + int * dataCount, + HTKEYTYPE* tableKey); + +/** + * Check for key in hash table. + * @param ht pointer to hash table + * @param key key value + * @return 1 if the key is present, 0 otherwise + */ +RPM_GNUC_INTERNAL +int HASHPREFIX(HasEntry)(HASHTYPE ht, HTKEYTYPE key); + +/** + * Print statistics about the hash to stderr + * This is for debugging only + * @param ht pointer to hash table + */ +RPM_GNUC_INTERNAL +void HASHPREFIX(PrintStats)(HASHTYPE ht); diff --git a/lib/rpmhash.c b/lib/rpmhash.c index 383697514..5d5d6a72f 100644 --- a/lib/rpmhash.c +++ b/lib/rpmhash.c @@ -3,63 +3,9 @@ * Hash table implemenation */ -#include "system.h" #include "lib/rpmhash.h" -#include "debug.h" -typedef const void * voidptr; - -typedef struct hashBucket_s * hashBucket; - -/** - */ -struct hashBucket_s { - voidptr key; /*!< hash key */ -voidptr * data; /*!< pointer to hashed data */ - int dataCount; /*!< length of data (0 if unknown) */ - hashBucket next; /*!< pointer to next item in bucket */ -}; - -/** - */ -struct hashTable_s { - int numBuckets; /*!< number of hash buckets */ - size_t keySize; /*!< size of key (0 if unknown) */ - int freeData; /*!< should data be freed when table is destroyed? */ - hashBucket * buckets; /*!< hash bucket array */ - hashFunctionType fn; /*!< generate hash value for key */ - hashEqualityType eq; /*!< compare hash keys for equality */ -}; - -/** - * Find entry in hash table. - * @param ht pointer to hash table - * @param key pointer to key value - * @return pointer to hash bucket of key (or NULL) - */ -static -hashBucket findEntry(hashTable ht, const void * key) -{ - unsigned int hash; - 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 hashEqualityString(const void * key1, const void * key2) -{ - const char *k1 = (const char *)key1; - const char *k2 = (const char *)key2; - return strcmp(k1, k2); -} - -unsigned int hashFunctionString(const void * string) +unsigned int hashFunctionString(const char * string) { char xorValue = 0; char sum = 0; @@ -75,102 +21,3 @@ unsigned int hashFunctionString(const void * string) return ((((unsigned)len) << 16) + (((unsigned)sum) << 8) + xorValue); } - -hashTable htCreate(int numBuckets, size_t keySize, int freeData, - hashFunctionType fn, hashEqualityType eq) -{ - hashTable ht; - - ht = xmalloc(sizeof(*ht)); - ht->numBuckets = numBuckets; - ht->buckets = xcalloc(numBuckets, sizeof(*ht->buckets)); - ht->keySize = keySize; - ht->freeData = freeData; - ht->fn = fn; - ht->eq = eq; - - return ht; -} - -void htAddEntry(hashTable ht, const void * key, const void * data) -{ - unsigned int hash; - hashBucket b; - - hash = ht->fn(key) % ht->numBuckets; - b = ht->buckets[hash]; - - while (b && b->key && ht->eq(b->key, key)) - b = b->next; - - if (b == NULL) { - b = xmalloc(sizeof(*b)); - if (ht->keySize) { - char *k = xmalloc(ht->keySize); - memcpy(k, key, ht->keySize); - b->key = k; - } else { - b->key = key; - } - b->dataCount = 0; - b->next = ht->buckets[hash]; - b->data = NULL; - ht->buckets[hash] = b; - } - - b->data = xrealloc(b->data, sizeof(*b->data) * (b->dataCount + 1)); - b->data[b->dataCount++] = data; -} - -hashTable htFree(hashTable ht) -{ - hashBucket b, n; - int i; - - for (i = 0; i < ht->numBuckets; i++) { - b = ht->buckets[i]; - if (b == NULL) - continue; - ht->buckets[i] = NULL; - if (ht->keySize > 0) - b->key = _constfree(b->key); - do { - n = b->next; - if (b->data) { - if (ht->freeData) - *b->data = _constfree(*b->data); - b->data = _free(b->data); - } - b = _free(b); - } while ((b = n) != NULL); - } - - ht->buckets = _free(ht->buckets); - ht = _free(ht); - return NULL; -} - -int htHasEntry(hashTable ht, const void * key) -{ - hashBucket b; - - if (!(b = findEntry(ht, key))) return 0; else return 1; -} - -int htGetEntry(hashTable ht, const void * key, const void *** data, - int * dataCount, const void ** tableKey) -{ - hashBucket b; - - if ((b = findEntry(ht, key)) == NULL) - return 1; - - if (data) - *data = (const void **) b->data; - if (dataCount) - *dataCount = b->dataCount; - if (tableKey) - *tableKey = b->key; - - return 0; -} diff --git a/lib/rpmhash.h b/lib/rpmhash.h index a95d373cc..57cc29056 100644 --- a/lib/rpmhash.h +++ b/lib/rpmhash.h @@ -1,7 +1,8 @@ #ifndef H_RPMHASH #define H_RPMHASH -#include <rpm/rpmutil.h> +#include "rpm/rpmutil.h" + /** * \file lib/rpmhash.h * Hash table implemenation. @@ -11,91 +12,8 @@ extern "C" { #endif -/** - */ -typedef struct hashTable_s * hashTable; - -/** - */ -typedef unsigned int (*hashFunctionType) (const void * string); - -/** - */ -typedef int (*hashEqualityType) (const void * key1, const void * key2); - -/** - * Return hash value of a string - * @param string string on which to calculate hash value - * @return hash value - */ -RPM_GNUC_INTERNAL -unsigned int hashFunctionString(const void * string); - -/** - * Compare two hash table entries for equality. - * @param key1 entry 1 - * @param key2 entry 2 - * @return 0 if entries are equal - */ -RPM_GNUC_INTERNAL -int hashEqualityString(const void * key1, const void * key2); - -/** - * Create hash table. - * If keySize > 0, the key is duplicated within the table (which costs - * memory, but may be useful anyway. - * @param numBuckets number of hash buckets - * @param keySize size of key (0 if unknown) - * @param freeData Should data be freed when table is destroyed? - * @param fn function to generate hash value for key - * @param eq function to compare hash keys for equality - * @return pointer to initialized hash table - */ -RPM_GNUC_INTERNAL -hashTable htCreate(int numBuckets, size_t keySize, int freeData, - hashFunctionType fn, hashEqualityType eq); - -/** - * Destroy hash table. - * @param ht pointer to hash table - * @return NULL always - */ -RPM_GNUC_INTERNAL -hashTable htFree( hashTable ht); - -/** - * Add item to hash table. - * @param ht pointer to hash table - * @param key pointer to key - * @param data pointer to data value - */ -RPM_GNUC_INTERNAL -void htAddEntry(hashTable ht, const void * key, - const void * data); - -/** - * Retrieve item from hash table. - * @param ht pointer to hash table - * @param key pointer to key value - * @retval data address to store data value from bucket - * @retval dataCount address to store data value size from bucket - * @retval tableKey address to store key value from bucket (may be NULL) - * @return 0 on success, 1 if the item is not found. - */ -RPM_GNUC_INTERNAL -int htGetEntry(hashTable ht, const void * key, - const void *** data, - int * dataCount, - const void ** tableKey); - -/** - * Check for key in hash table. - * @param ht pointer to hash table - * @param key pointer to key value - * @return 1 if the key is present, 0 otherwise - */ RPM_GNUC_INTERNAL -int htHasEntry(hashTable ht, const void * key); +unsigned int hashFunctionString(const char * string); #ifdef __cplusplus } |