summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorFlorian Festi <ffesti@redhat.com>2008-10-17 16:18:45 +0200
committerFlorian Festi <ffesti@redhat.com>2008-10-24 10:34:25 +0200
commit832909b4a7f093f6ab223850dad892223a71ff80 (patch)
tree93db7c0fd8d9d7d752d1196c1b21a8053f23e520 /lib
parent6a8c221ce6a890d6b23daed92669eb90e80ec2af (diff)
downloadrpm-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.h2
-rw-r--r--lib/rpmhash.C175
-rw-r--r--lib/rpmhash.H90
-rw-r--r--lib/rpmhash.c155
-rw-r--r--lib/rpmhash.h88
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
}