2002-03-25 23:16:26 +03:00
/**
* \ file rpmdb / rpmhash . c
* Hash table implemenation
*/
# include "system.h"
2002-03-26 01:02:39 +03:00
# include "rpmlib.h"
2002-03-25 23:16:26 +03:00
# include "rpmhash.h"
# include "debug.h"
2009-03-25 10:52:02 +03:00
# include "jhash.h"
2002-03-25 23:16:26 +03:00
typedef struct hashBucket_s * hashBucket ;
/**
*/
struct hashBucket_s {
2009-03-26 10:39:08 +03:00
hashBucket next ; /*!< pointer to next item in bucket */
const void * key ; /*!< hash key */
unsigned int dataCount ; /*!< data entries */
const void * data [ 1 ] ; /*!< data - grows by resizing whole bucket */
2002-03-25 23:16:26 +03:00
} ;
/**
*/
struct hashTable_s {
hashFunctionType fn ; /*!< generate hash value for key */
hashEqualityType eq ; /*!< compare hash keys for equality */
2009-03-26 10:21:02 +03:00
unsigned int numBuckets ; /*!< number of hash buckets */
hashBucket buckets [ 1 ] ; /*!< hash bucket array */
2002-03-25 23:16:26 +03:00
} ;
/**
* 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 )
*/
2009-03-26 10:27:35 +03:00
static inline /*@shared@*/ /*@null@*/
hashBucket findBucket ( hashTable ht , const void * key )
2002-03-25 23:16:26 +03:00
/*@*/
{
2009-03-26 10:27:35 +03:00
unsigned int hash = ht - > fn ( key ) & ( ht - > numBuckets - 1 ) ;
hashBucket b = ht - > buckets [ hash ] ;
2002-03-25 23:16:26 +03:00
while ( b & & b - > key & & ht - > eq ( b - > key , key ) )
b = b - > next ;
return b ;
}
int hashEqualityString ( const void * key1 , const void * key2 )
{
2009-03-26 10:41:33 +03:00
return strcmp ( key1 , key2 ) ;
2002-03-25 23:16:26 +03:00
}
2009-03-25 10:52:02 +03:00
unsigned int hashFunctionString ( const void * str )
2002-03-25 23:16:26 +03:00
{
2009-03-25 10:52:02 +03:00
return jhashString ( str ) ;
2002-03-25 23:16:26 +03:00
}
2009-03-25 10:52:02 +03:00
hashTable htCreate ( unsigned int size , hashFunctionType fn , hashEqualityType eq )
2002-03-25 23:16:26 +03:00
{
hashTable ht ;
2009-03-26 10:21:02 +03:00
unsigned int numBuckets = jhashSize ( size ) ;
size_t numBytes = sizeof ( * ht ) + sizeof ( ht - > buckets [ 1 ] ) * ( numBuckets - 1 ) ;
ht = xcalloc ( numBytes , 1 ) ;
ht - > numBuckets = numBuckets ;
2002-03-25 23:16:26 +03:00
/*@-assignexpose@*/
ht - > fn = fn ;
ht - > eq = eq ;
/*@=assignexpose@*/
return ht ;
}
void htAddEntry ( hashTable ht , const void * key , const void * data )
{
2009-03-25 10:52:02 +03:00
unsigned int hash = ht - > fn ( key ) & ( ht - > numBuckets - 1 ) ;
2009-03-14 20:26:24 +03:00
hashBucket b = ht - > buckets [ hash ] ;
hashBucket * b_addr = ht - > buckets + hash ;
2002-03-25 23:16:26 +03:00
2009-03-14 20:26:24 +03:00
while ( b & & b - > key & & ht - > eq ( b - > key , key ) ) {
b_addr = & ( b - > next ) ;
2002-03-25 23:16:26 +03:00
b = b - > next ;
2009-03-14 20:26:24 +03:00
}
2002-03-25 23:16:26 +03:00
if ( b = = NULL ) {
b = xmalloc ( sizeof ( * b ) ) ;
2009-03-14 18:38:36 +03:00
b - > key = key ;
2009-03-14 20:26:24 +03:00
b - > dataCount = 1 ;
b - > data [ 0 ] = data ;
2002-03-25 23:16:26 +03:00
b - > next = ht - > buckets [ hash ] ;
ht - > buckets [ hash ] = b ;
}
2009-03-14 20:26:24 +03:00
else {
// Bucket_s already contains space for one dataset
b = * b_addr = xrealloc ( b , sizeof ( * b ) + sizeof ( b - > data [ 0 ] ) * b - > dataCount ) ;
// though increasing dataCount after the resize
b - > data [ b - > dataCount + + ] = data ;
}
2002-03-25 23:16:26 +03:00
}
2009-03-25 10:12:06 +03:00
hashTable htFree ( hashTable ht , hashFreeKeyType freeKey , hashFreeDataType freeData )
2002-03-25 23:16:26 +03:00
{
hashBucket b , n ;
2009-03-26 10:39:08 +03:00
unsigned int i , j ;
2002-03-25 23:16:26 +03:00
for ( i = 0 ; i < ht - > numBuckets ; i + + ) {
b = ht - > buckets [ i ] ;
if ( b = = NULL )
continue ;
ht - > buckets [ i ] = NULL ;
do {
n = b - > next ;
2009-03-25 10:12:06 +03:00
if ( freeKey )
b - > key = freeKey ( b - > key ) ;
if ( freeData )
2009-03-14 20:26:24 +03:00
for ( j = 0 ; j < b - > dataCount ; j + + )
2009-03-25 10:12:06 +03:00
b - > data [ j ] = freeData ( b - > data [ j ] ) ;
2002-03-25 23:16:26 +03:00
b = _free ( b ) ;
} while ( ( b = n ) ! = NULL ) ;
}
ht = _free ( ht ) ;
2009-03-25 10:12:06 +03:00
return NULL ;
2002-03-25 23:16:26 +03:00
}
int htHasEntry ( hashTable ht , const void * key )
{
2009-03-26 10:27:35 +03:00
hashBucket b = findBucket ( ht , key ) ;
if ( b = = NULL )
return 0 ;
return 1 ;
2002-03-25 23:16:26 +03:00
}
int htGetEntry ( hashTable ht , const void * key , const void * * * data ,
int * dataCount , const void * * tableKey )
{
2009-03-26 10:27:35 +03:00
hashBucket b = findBucket ( ht , key ) ;
if ( b = = NULL )
2002-03-25 23:16:26 +03:00
return 1 ;
if ( data )
2009-03-26 10:39:08 +03:00
* data = b - > data ;
2002-03-25 23:16:26 +03:00
if ( dataCount )
* dataCount = b - > dataCount ;
if ( tableKey )
* tableKey = b - > key ;
return 0 ;
}