Make rpmhash a generic datatype using macros and includes
authorFlorian Festi <ffesti@redhat.com>
Fri, 17 Oct 2008 14:18:45 +0000 (16:18 +0200)
committerFlorian Festi <ffesti@redhat.com>
Fri, 24 Oct 2008 08:34:25 +0000 (10:34 +0200)
lib/fprint.h
lib/rpmhash.C [new file with mode: 0644]
lib/rpmhash.H [new file with mode: 0644]
lib/rpmhash.c
lib/rpmhash.h

index 30bcb4b..ff4dbfe 100644 (file)
@@ -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 (file)
index 0000000..2d7cfde
--- /dev/null
@@ -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 (file)
index 0000000..324cbc8
--- /dev/null
@@ -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);
index 3836975..5d5d6a7 100644 (file)
@@ -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;
-}
index a95d373..57cc290 100644 (file)
@@ -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.
 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
 }