1*37da2899SCharles.Forsyth /****************************************************************** 2*37da2899SCharles.Forsyth * 3*37da2899SCharles.Forsyth * fthash.h - fast dynamic hash tables 4*37da2899SCharles.Forsyth * 5*37da2899SCharles.Forsyth * Copyright 2002 by 6*37da2899SCharles.Forsyth * David Turner, Robert Wilhelm, and Werner Lemberg 7*37da2899SCharles.Forsyth * 8*37da2899SCharles.Forsyth * This file is part of the FreeType project, and may only be used, 9*37da2899SCharles.Forsyth * modified, and distributed under the terms of the FreeType project 10*37da2899SCharles.Forsyth * license, LICENSE.TXT. By continuing to use, modify, or distribute 11*37da2899SCharles.Forsyth * this file you indicate that you have read the license and 12*37da2899SCharles.Forsyth * understand and accept it fully. 13*37da2899SCharles.Forsyth * 14*37da2899SCharles.Forsyth * 15*37da2899SCharles.Forsyth * This header is used to define dynamic hash tables as described 16*37da2899SCharles.Forsyth * by the article "Main-Memory Linear Hashing - Some Enhancements 17*37da2899SCharles.Forsyth * of Larson's Algorithm" by Mikael Petterson. 18*37da2899SCharles.Forsyth * 19*37da2899SCharles.Forsyth * Basically, linear hashing prevents big "stalls" during 20*37da2899SCharles.Forsyth * resizes of the buckets array by only splitting one bucket 21*37da2899SCharles.Forsyth * at a time. This ensures excellent response time even when 22*37da2899SCharles.Forsyth * the table is frequently resized.. 23*37da2899SCharles.Forsyth * 24*37da2899SCharles.Forsyth * 25*37da2899SCharles.Forsyth * Note that the use of the FT_Hash type is rather unusual in order 26*37da2899SCharles.Forsyth * to be as generic and efficient as possible. See the comments in the 27*37da2899SCharles.Forsyth * following definitions for more details. 28*37da2899SCharles.Forsyth */ 29*37da2899SCharles.Forsyth 30*37da2899SCharles.Forsyth #ifndef __FT_HASH_H__ 31*37da2899SCharles.Forsyth #define __FT_HASH_H__ 32*37da2899SCharles.Forsyth 33*37da2899SCharles.Forsyth #include <ft2build.h> 34*37da2899SCharles.Forsyth #include FT_TYPES_H 35*37da2899SCharles.Forsyth 36*37da2899SCharles.Forsyth FT_BEGIN_HEADER 37*37da2899SCharles.Forsyth 38*37da2899SCharles.Forsyth /*********************************************************** 39*37da2899SCharles.Forsyth * 40*37da2899SCharles.Forsyth * @type: FT_Hash 41*37da2899SCharles.Forsyth * 42*37da2899SCharles.Forsyth * @description: 43*37da2899SCharles.Forsyth * handle to a @FT_HashRec structure used to model a 44*37da2899SCharles.Forsyth * dynamic hash table 45*37da2899SCharles.Forsyth */ 46*37da2899SCharles.Forsyth typedef struct FT_HashRec_* FT_Hash; 47*37da2899SCharles.Forsyth 48*37da2899SCharles.Forsyth 49*37da2899SCharles.Forsyth /*********************************************************** 50*37da2899SCharles.Forsyth * 51*37da2899SCharles.Forsyth * @type: FT_HashNode 52*37da2899SCharles.Forsyth * 53*37da2899SCharles.Forsyth * @description: 54*37da2899SCharles.Forsyth * handle to a @FT_HashNodeRec structure used to model a 55*37da2899SCharles.Forsyth * single node of a hash table 56*37da2899SCharles.Forsyth */ 57*37da2899SCharles.Forsyth typedef struct FT_HashNodeRec_* FT_HashNode; 58*37da2899SCharles.Forsyth 59*37da2899SCharles.Forsyth 60*37da2899SCharles.Forsyth /*********************************************************** 61*37da2899SCharles.Forsyth * 62*37da2899SCharles.Forsyth * @type: FT_HashLookup 63*37da2899SCharles.Forsyth * 64*37da2899SCharles.Forsyth * @description: 65*37da2899SCharles.Forsyth * handle to a @FT_HashNode pointer. This is returned by 66*37da2899SCharles.Forsyth * the @ft_hash_lookup function and can later be used by 67*37da2899SCharles.Forsyth * @ft_hash_add or @ft_hash_remove 68*37da2899SCharles.Forsyth */ 69*37da2899SCharles.Forsyth typedef FT_HashNode* FT_HashLookup; 70*37da2899SCharles.Forsyth 71*37da2899SCharles.Forsyth 72*37da2899SCharles.Forsyth /*********************************************************** 73*37da2899SCharles.Forsyth * 74*37da2899SCharles.Forsyth * @type: FT_Hash_EqualFunc 75*37da2899SCharles.Forsyth * 76*37da2899SCharles.Forsyth * @description: 77*37da2899SCharles.Forsyth * a function used to compare two nodes of the hash table 78*37da2899SCharles.Forsyth * 79*37da2899SCharles.Forsyth * @input: 80*37da2899SCharles.Forsyth * node1 :: handle to first node 81*37da2899SCharles.Forsyth * node2 :: handle to second node 82*37da2899SCharles.Forsyth * 83*37da2899SCharles.Forsyth * @return: 84*37da2899SCharles.Forsyth * 1 iff the 'keys' in 'node1' and 'node2' are identical. 85*37da2899SCharles.Forsyth * 0 otherwise. 86*37da2899SCharles.Forsyth */ 87*37da2899SCharles.Forsyth typedef FT_Int (*FT_Hash_EqualFunc)( FT_HashNode node1, 88*37da2899SCharles.Forsyth FT_HashNode node2 ); 89*37da2899SCharles.Forsyth 90*37da2899SCharles.Forsyth 91*37da2899SCharles.Forsyth /*********************************************************** 92*37da2899SCharles.Forsyth * 93*37da2899SCharles.Forsyth * @struct: FT_HashRec 94*37da2899SCharles.Forsyth * 95*37da2899SCharles.Forsyth * @description: 96*37da2899SCharles.Forsyth * a structure used to model a dynamic hash table. 97*37da2899SCharles.Forsyth * 98*37da2899SCharles.Forsyth * @fields: 99*37da2899SCharles.Forsyth * memory :: memory manager used to allocate 100*37da2899SCharles.Forsyth * the buckets array and the hash nodes 101*37da2899SCharles.Forsyth * 102*37da2899SCharles.Forsyth * buckets :: array of hash buckets 103*37da2899SCharles.Forsyth * 104*37da2899SCharles.Forsyth * node_size :: size of node in bytes 105*37da2899SCharles.Forsyth * node_compare :: a function used to compare two nodes 106*37da2899SCharles.Forsyth * node_hash :: a function used to compute the hash 107*37da2899SCharles.Forsyth * value of a given node 108*37da2899SCharles.Forsyth * p :: 109*37da2899SCharles.Forsyth * mask :: 110*37da2899SCharles.Forsyth * slack :: 111*37da2899SCharles.Forsyth * 112*37da2899SCharles.Forsyth * @note: 113*37da2899SCharles.Forsyth * 'p', 'mask' and 'slack' are control values managed by 114*37da2899SCharles.Forsyth * the hash table. Do not try to interpret them directly. 115*37da2899SCharles.Forsyth * 116*37da2899SCharles.Forsyth * You can grab the hash table size by calling 117*37da2899SCharles.Forsyth * '@ft_hash_get_size'. 118*37da2899SCharles.Forsyth */ 119*37da2899SCharles.Forsyth typedef struct FT_HashRec_ 120*37da2899SCharles.Forsyth { 121*37da2899SCharles.Forsyth FT_HashNode* buckets; 122*37da2899SCharles.Forsyth FT_UInt p; 123*37da2899SCharles.Forsyth FT_UInt mask; /* really maxp-1 */ 124*37da2899SCharles.Forsyth FT_Long slack; 125*37da2899SCharles.Forsyth FT_Hash_EqualFunc node_equal; 126*37da2899SCharles.Forsyth FT_Memory memory; 127*37da2899SCharles.Forsyth 128*37da2899SCharles.Forsyth } FT_HashRec; 129*37da2899SCharles.Forsyth 130*37da2899SCharles.Forsyth 131*37da2899SCharles.Forsyth /*********************************************************** 132*37da2899SCharles.Forsyth * 133*37da2899SCharles.Forsyth * @struct: FT_HashNodeRec 134*37da2899SCharles.Forsyth * 135*37da2899SCharles.Forsyth * @description: 136*37da2899SCharles.Forsyth * a structure used to model the root fields of a dynamic 137*37da2899SCharles.Forsyth * hash table node. 138*37da2899SCharles.Forsyth * 139*37da2899SCharles.Forsyth * it's up to client applications to "sub-class" this 140*37da2899SCharles.Forsyth * structure to add relevant (key,value) definitions 141*37da2899SCharles.Forsyth * 142*37da2899SCharles.Forsyth * @fields: 143*37da2899SCharles.Forsyth * link :: pointer to next node in bucket's collision list 144*37da2899SCharles.Forsyth * hash :: 32-bit hash value for this node 145*37da2899SCharles.Forsyth * 146*37da2899SCharles.Forsyth * @note: 147*37da2899SCharles.Forsyth * it's up to client applications to "sub-class" this structure 148*37da2899SCharles.Forsyth * to add relevant (key,value) type definitions. For example, 149*37da2899SCharles.Forsyth * if we want to build a "string -> int" mapping, we could use 150*37da2899SCharles.Forsyth * something like: 151*37da2899SCharles.Forsyth * 152*37da2899SCharles.Forsyth * { 153*37da2899SCharles.Forsyth * typedef struct MyNodeRec_ 154*37da2899SCharles.Forsyth * { 155*37da2899SCharles.Forsyth * FT_HashNodeRec hnode; 156*37da2899SCharles.Forsyth * const char* key; 157*37da2899SCharles.Forsyth * int value; 158*37da2899SCharles.Forsyth * 159*37da2899SCharles.Forsyth * } MyNodeRec, *MyNode; 160*37da2899SCharles.Forsyth * } 161*37da2899SCharles.Forsyth * 162*37da2899SCharles.Forsyth */ 163*37da2899SCharles.Forsyth typedef struct FT_HashNodeRec_ 164*37da2899SCharles.Forsyth { 165*37da2899SCharles.Forsyth FT_HashNode link; 166*37da2899SCharles.Forsyth FT_UInt32 hash; 167*37da2899SCharles.Forsyth 168*37da2899SCharles.Forsyth } FT_HashNodeRec; 169*37da2899SCharles.Forsyth 170*37da2899SCharles.Forsyth 171*37da2899SCharles.Forsyth /**************************************************************** 172*37da2899SCharles.Forsyth * 173*37da2899SCharles.Forsyth * @function: ft_hash_init 174*37da2899SCharles.Forsyth * 175*37da2899SCharles.Forsyth * @description: 176*37da2899SCharles.Forsyth * initialize a dynamic hash table 177*37da2899SCharles.Forsyth * 178*37da2899SCharles.Forsyth * @input: 179*37da2899SCharles.Forsyth * table :: handle to target hash table structure 180*37da2899SCharles.Forsyth * node_equal :: node comparison function 181*37da2899SCharles.Forsyth * memory :: memory manager handle used to allocate the 182*37da2899SCharles.Forsyth * buckets array within the hash table 183*37da2899SCharles.Forsyth * 184*37da2899SCharles.Forsyth * @return: 185*37da2899SCharles.Forsyth * error code. 0 means success 186*37da2899SCharles.Forsyth * 187*37da2899SCharles.Forsyth * @note: 188*37da2899SCharles.Forsyth * the node comparison function should only compare node _keys_ 189*37da2899SCharles.Forsyth * and ignore values !! with good hashing computation (which the 190*37da2899SCharles.Forsyth * user must perform itself), the comparison function should be 191*37da2899SCharles.Forsyth * pretty seldom called. 192*37da2899SCharles.Forsyth * 193*37da2899SCharles.Forsyth * here is a simple example: 194*37da2899SCharles.Forsyth * 195*37da2899SCharles.Forsyth * { 196*37da2899SCharles.Forsyth * static int my_equal( MyNode node1, 197*37da2899SCharles.Forsyth * MyNode node2 ) 198*37da2899SCharles.Forsyth * { 199*37da2899SCharles.Forsyth * // compare keys of 'node1' and 'node2' 200*37da2899SCharles.Forsyth * return (strcmp( node1->key, node2->key ) == 0); 201*37da2899SCharles.Forsyth * } 202*37da2899SCharles.Forsyth * 203*37da2899SCharles.Forsyth * .... 204*37da2899SCharles.Forsyth * 205*37da2899SCharles.Forsyth * ft_hash_init( &hash, (FT_Hash_EqualFunc) my_compare, memory ); 206*37da2899SCharles.Forsyth * .... 207*37da2899SCharles.Forsyth * } 208*37da2899SCharles.Forsyth */ 209*37da2899SCharles.Forsyth FT_BASE( FT_Error ) 210*37da2899SCharles.Forsyth ft_hash_init( FT_Hash table, 211*37da2899SCharles.Forsyth FT_Hash_EqualFunc compare, 212*37da2899SCharles.Forsyth FT_Memory memory ); 213*37da2899SCharles.Forsyth 214*37da2899SCharles.Forsyth 215*37da2899SCharles.Forsyth /**************************************************************** 216*37da2899SCharles.Forsyth * 217*37da2899SCharles.Forsyth * @function: ft_hash_lookup 218*37da2899SCharles.Forsyth * 219*37da2899SCharles.Forsyth * @description: 220*37da2899SCharles.Forsyth * search a hash table to find a node corresponding to a given 221*37da2899SCharles.Forsyth * key. 222*37da2899SCharles.Forsyth * 223*37da2899SCharles.Forsyth * @input: 224*37da2899SCharles.Forsyth * table :: handle to target hash table structure 225*37da2899SCharles.Forsyth * keynode :: handle to a reference hash node that will be 226*37da2899SCharles.Forsyth * only used for key comparisons with the table's 227*37da2899SCharles.Forsyth * elements 228*37da2899SCharles.Forsyth * 229*37da2899SCharles.Forsyth * @return: 230*37da2899SCharles.Forsyth * a pointer-to-hash-node value, which must be used as followed: 231*37da2899SCharles.Forsyth * 232*37da2899SCharles.Forsyth * - if '*result' is NULL, the key wasn't found in the hash 233*37da2899SCharles.Forsyth * table. The value of 'result' can be used to add new elements 234*37da2899SCharles.Forsyth * through @ft_hash_add however.. 235*37da2899SCharles.Forsyth * 236*37da2899SCharles.Forsyth * - if '*result' is not NULL, it's a handle to the first table 237*37da2899SCharles.Forsyth * node that corresponds to the search key. The value of 'result' 238*37da2899SCharles.Forsyth * can be used to remove this element through @ft_hash_remove 239*37da2899SCharles.Forsyth * 240*37da2899SCharles.Forsyth * @note: 241*37da2899SCharles.Forsyth * here is an example: 242*37da2899SCharles.Forsyth * 243*37da2899SCharles.Forsyth * { 244*37da2899SCharles.Forsyth * // maps a string to an integer with a hash table 245*37da2899SCharles.Forsyth * // returns -1 in case of failure 246*37da2899SCharles.Forsyth * // 247*37da2899SCharles.Forsyth * int my_lookup( FT_Hash table, 248*37da2899SCharles.Forsyth * const char* key ) 249*37da2899SCharles.Forsyth * { 250*37da2899SCharles.Forsyth * MyNode* pnode; 251*37da2899SCharles.Forsyth * MyNodeRec noderec; 252*37da2899SCharles.Forsyth * 253*37da2899SCharles.Forsyth * // set-up key node. It's 'hash' and 'key' fields must 254*37da2899SCharles.Forsyth * // be set correctly.. we ignore 'link' and 'value' 255*37da2899SCharles.Forsyth * // 256*37da2899SCharles.Forsyth * noderec.hnode.hash = strhash( key ); 257*37da2899SCharles.Forsyth * noderec.key = key; 258*37da2899SCharles.Forsyth * 259*37da2899SCharles.Forsyth * // perform search - return value 260*37da2899SCharles.Forsyth * // 261*37da2899SCharles.Forsyth * pnode = (MyNode) ft_hash_lookup( table, &noderec ); 262*37da2899SCharles.Forsyth * if ( *pnode ) 263*37da2899SCharles.Forsyth * { 264*37da2899SCharles.Forsyth * // we found it 265*37da2899SCharles.Forsyth * return (*pnode)->value; 266*37da2899SCharles.Forsyth * } 267*37da2899SCharles.Forsyth * return -1; 268*37da2899SCharles.Forsyth * } 269*37da2899SCharles.Forsyth * } 270*37da2899SCharles.Forsyth */ 271*37da2899SCharles.Forsyth FT_BASE_DEF( FT_HashLookup ) 272*37da2899SCharles.Forsyth ft_hash_lookup( FT_Hash table, 273*37da2899SCharles.Forsyth FT_HashNode keynode ); 274*37da2899SCharles.Forsyth 275*37da2899SCharles.Forsyth 276*37da2899SCharles.Forsyth /**************************************************************** 277*37da2899SCharles.Forsyth * 278*37da2899SCharles.Forsyth * @function: ft_hash_add 279*37da2899SCharles.Forsyth * 280*37da2899SCharles.Forsyth * @description: 281*37da2899SCharles.Forsyth * add a new node to a dynamic hash table. the user must 282*37da2899SCharles.Forsyth * call @ft_hash_lookup and allocate a new node before calling 283*37da2899SCharles.Forsyth * this function. 284*37da2899SCharles.Forsyth * 285*37da2899SCharles.Forsyth * @input: 286*37da2899SCharles.Forsyth * table :: hash table handle 287*37da2899SCharles.Forsyth * lookup :: pointer-to-hash-node value returned by @ft_hash_lookup 288*37da2899SCharles.Forsyth * new_node :: handle to new hash node. All its fields must be correctly 289*37da2899SCharles.Forsyth * set, including 'hash'. 290*37da2899SCharles.Forsyth * 291*37da2899SCharles.Forsyth * @return: 292*37da2899SCharles.Forsyth * error code. 0 means success 293*37da2899SCharles.Forsyth * 294*37da2899SCharles.Forsyth * @note: 295*37da2899SCharles.Forsyth * this function should always be used _after_ a call to @ft_hash_lookup 296*37da2899SCharles.Forsyth * that returns a pointer to a NULL handle. Here's an example: 297*37da2899SCharles.Forsyth * 298*37da2899SCharles.Forsyth * { 299*37da2899SCharles.Forsyth * // sets the value corresponding to a given string key 300*37da2899SCharles.Forsyth * // 301*37da2899SCharles.Forsyth * void my_set( FT_Hash table, 302*37da2899SCharles.Forsyth * const char* key, 303*37da2899SCharles.Forsyth * int value ) 304*37da2899SCharles.Forsyth * { 305*37da2899SCharles.Forsyth * MyNode* pnode; 306*37da2899SCharles.Forsyth * MyNodeRec noderec; 307*37da2899SCharles.Forsyth * MyNode node; 308*37da2899SCharles.Forsyth * 309*37da2899SCharles.Forsyth * // set-up key node. It's 'hash' and 'key' fields must 310*37da2899SCharles.Forsyth * // be set correctly.. 311*37da2899SCharles.Forsyth * noderec.hnode.hash = strhash( key ); 312*37da2899SCharles.Forsyth * noderec.key = key; 313*37da2899SCharles.Forsyth * 314*37da2899SCharles.Forsyth * // perform search - return value 315*37da2899SCharles.Forsyth * pnode = (MyNode) ft_hash_lookup( table, &noderec ); 316*37da2899SCharles.Forsyth * if ( *pnode ) 317*37da2899SCharles.Forsyth * { 318*37da2899SCharles.Forsyth * // we found it, simply replace the value in the node 319*37da2899SCharles.Forsyth * (*pnode)->value = value; 320*37da2899SCharles.Forsyth * return; 321*37da2899SCharles.Forsyth * } 322*37da2899SCharles.Forsyth * 323*37da2899SCharles.Forsyth * // allocate a new node - and set it up 324*37da2899SCharles.Forsyth * node = (MyNode) malloc( sizeof(*node) ); 325*37da2899SCharles.Forsyth * if ( node == NULL ) ..... 326*37da2899SCharles.Forsyth * 327*37da2899SCharles.Forsyth * node->hnode.hash = noderec.hnode.hash; 328*37da2899SCharles.Forsyth * node->key = key; 329*37da2899SCharles.Forsyth * node->value = value; 330*37da2899SCharles.Forsyth * 331*37da2899SCharles.Forsyth * // add it to the hash table 332*37da2899SCharles.Forsyth * error = ft_hash_add( table, pnode, node ); 333*37da2899SCharles.Forsyth * if (error) .... 334*37da2899SCharles.Forsyth * } 335*37da2899SCharles.Forsyth */ 336*37da2899SCharles.Forsyth FT_BASE( FT_Error ) 337*37da2899SCharles.Forsyth ft_hash_add( FT_Hash table, 338*37da2899SCharles.Forsyth FT_HashLookup lookup, 339*37da2899SCharles.Forsyth FT_HashNode new_node ); 340*37da2899SCharles.Forsyth 341*37da2899SCharles.Forsyth 342*37da2899SCharles.Forsyth /**************************************************************** 343*37da2899SCharles.Forsyth * 344*37da2899SCharles.Forsyth * @function: ft_hash_remove 345*37da2899SCharles.Forsyth * 346*37da2899SCharles.Forsyth * @description: 347*37da2899SCharles.Forsyth * try to remove the node corresponding to a given key from 348*37da2899SCharles.Forsyth * a hash table. This must be called after @ft_hash_lookup 349*37da2899SCharles.Forsyth * 350*37da2899SCharles.Forsyth * @input: 351*37da2899SCharles.Forsyth * table :: hash table handle 352*37da2899SCharles.Forsyth * lookup :: pointer-to-hash-node value returned by @ft_hash_lookup 353*37da2899SCharles.Forsyth * 354*37da2899SCharles.Forsyth * @note: 355*37da2899SCharles.Forsyth * this function doesn't free the node itself !! Here's an example: 356*37da2899SCharles.Forsyth * 357*37da2899SCharles.Forsyth * { 358*37da2899SCharles.Forsyth * // sets the value corresponding to a given string key 359*37da2899SCharles.Forsyth * // 360*37da2899SCharles.Forsyth * void my_remove( FT_Hash table, 361*37da2899SCharles.Forsyth * const char* key ) 362*37da2899SCharles.Forsyth * { 363*37da2899SCharles.Forsyth * MyNodeRec noderec; 364*37da2899SCharles.Forsyth * MyNode node; 365*37da2899SCharles.Forsyth * 366*37da2899SCharles.Forsyth * noderec.hnode.hash = strhash(key); 367*37da2899SCharles.Forsyth * noderec.key = key; 368*37da2899SCharles.Forsyth * node = &noderec; 369*37da2899SCharles.Forsyth * 370*37da2899SCharles.Forsyth * pnode = ft_hash_lookup( table, &noderec ); 371*37da2899SCharles.Forsyth * node = *pnode; 372*37da2899SCharles.Forsyth * if ( node != NULL ) 373*37da2899SCharles.Forsyth * { 374*37da2899SCharles.Forsyth * error = ft_hash_remove( table, pnode ); 375*37da2899SCharles.Forsyth * if ( !error ) 376*37da2899SCharles.Forsyth * free( node ); 377*37da2899SCharles.Forsyth * } 378*37da2899SCharles.Forsyth * } 379*37da2899SCharles.Forsyth * } 380*37da2899SCharles.Forsyth */ 381*37da2899SCharles.Forsyth FT_BASE( FT_Error ) 382*37da2899SCharles.Forsyth ft_hash_remove( FT_Hash table, 383*37da2899SCharles.Forsyth FT_HashLookup lookup ); 384*37da2899SCharles.Forsyth 385*37da2899SCharles.Forsyth 386*37da2899SCharles.Forsyth 387*37da2899SCharles.Forsyth /**************************************************************** 388*37da2899SCharles.Forsyth * 389*37da2899SCharles.Forsyth * @function: ft_hash_get_size 390*37da2899SCharles.Forsyth * 391*37da2899SCharles.Forsyth * @description: 392*37da2899SCharles.Forsyth * return the number of elements in a given hash table 393*37da2899SCharles.Forsyth * 394*37da2899SCharles.Forsyth * @input: 395*37da2899SCharles.Forsyth * table :: handle to target hash table structure 396*37da2899SCharles.Forsyth * 397*37da2899SCharles.Forsyth * @return: 398*37da2899SCharles.Forsyth * number of elements. 0 if empty 399*37da2899SCharles.Forsyth */ 400*37da2899SCharles.Forsyth FT_BASE( FT_UInt ) 401*37da2899SCharles.Forsyth ft_hash_get_size( FT_Hash table ); 402*37da2899SCharles.Forsyth 403*37da2899SCharles.Forsyth 404*37da2899SCharles.Forsyth 405*37da2899SCharles.Forsyth /**************************************************************** 406*37da2899SCharles.Forsyth * 407*37da2899SCharles.Forsyth * @functype: FT_Hash_ForeachFunc 408*37da2899SCharles.Forsyth * 409*37da2899SCharles.Forsyth * @description: 410*37da2899SCharles.Forsyth * a function used to iterate over all elements of a given 411*37da2899SCharles.Forsyth * hash table 412*37da2899SCharles.Forsyth * 413*37da2899SCharles.Forsyth * @input: 414*37da2899SCharles.Forsyth * node :: handle to target @FT_HashNodeRec node structure 415*37da2899SCharles.Forsyth * data :: optional argument to iteration routine 416*37da2899SCharles.Forsyth * 417*37da2899SCharles.Forsyth * @also: @ft_hash_foreach 418*37da2899SCharles.Forsyth */ 419*37da2899SCharles.Forsyth typedef void (*FT_Hash_ForeachFunc)( const FT_HashNode node, 420*37da2899SCharles.Forsyth const FT_Pointer data ); 421*37da2899SCharles.Forsyth 422*37da2899SCharles.Forsyth 423*37da2899SCharles.Forsyth /**************************************************************** 424*37da2899SCharles.Forsyth * 425*37da2899SCharles.Forsyth * @function: ft_hash_foreach 426*37da2899SCharles.Forsyth * 427*37da2899SCharles.Forsyth * @description: 428*37da2899SCharles.Forsyth * parse over all elements in a hash table 429*37da2899SCharles.Forsyth * 430*37da2899SCharles.Forsyth * @input: 431*37da2899SCharles.Forsyth * table :: handle to target hash table structure 432*37da2899SCharles.Forsyth * foreach_func :: iteration routine called for each element 433*37da2899SCharles.Forsyth * foreach_data :: optional argument to the iteration routine 434*37da2899SCharles.Forsyth * 435*37da2899SCharles.Forsyth * @note: 436*37da2899SCharles.Forsyth * this function is often used to release all elements from a 437*37da2899SCharles.Forsyth * hash table. See the example given for @ft_hash_done 438*37da2899SCharles.Forsyth */ 439*37da2899SCharles.Forsyth FT_BASE( void ) 440*37da2899SCharles.Forsyth ft_hash_foreach( FT_Hash table, 441*37da2899SCharles.Forsyth FT_Hash_ForeachFunc foreach_func, 442*37da2899SCharles.Forsyth const FT_Pointer foreach_data ); 443*37da2899SCharles.Forsyth 444*37da2899SCharles.Forsyth 445*37da2899SCharles.Forsyth 446*37da2899SCharles.Forsyth /**************************************************************** 447*37da2899SCharles.Forsyth * 448*37da2899SCharles.Forsyth * @function: ft_hash_done 449*37da2899SCharles.Forsyth * 450*37da2899SCharles.Forsyth * @description: 451*37da2899SCharles.Forsyth * finalize a given hash table 452*37da2899SCharles.Forsyth * 453*37da2899SCharles.Forsyth * @input: 454*37da2899SCharles.Forsyth * table :: handle to target hash table structure 455*37da2899SCharles.Forsyth * node_func :: optional iteration function pointer. this 456*37da2899SCharles.Forsyth * can be used to destroy all nodes explicitely 457*37da2899SCharles.Forsyth * node_data :: optional argument to the node iterator 458*37da2899SCharles.Forsyth * 459*37da2899SCharles.Forsyth * @note: 460*37da2899SCharles.Forsyth * this function simply frees the hash table's buckets. 461*37da2899SCharles.Forsyth * you probably will need to call @ft_hash_foreach to 462*37da2899SCharles.Forsyth * destroy all its elements before @ft_hash_done, as in 463*37da2899SCharles.Forsyth * the following example: 464*37da2899SCharles.Forsyth * 465*37da2899SCharles.Forsyth * { 466*37da2899SCharles.Forsyth * static void my_node_clear( const MyNode node ) 467*37da2899SCharles.Forsyth * { 468*37da2899SCharles.Forsyth * free( node ); 469*37da2899SCharles.Forsyth * } 470*37da2899SCharles.Forsyth * 471*37da2899SCharles.Forsyth * static void my_done( FT_Hash table ) 472*37da2899SCharles.Forsyth * { 473*37da2899SCharles.Forsyth * ft_hash_done( table, (FT_Hash_ForeachFunc) my_node_clear, NULL ); 474*37da2899SCharles.Forsyth * } 475*37da2899SCharles.Forsyth * } 476*37da2899SCharles.Forsyth */ 477*37da2899SCharles.Forsyth FT_BASE( void ) 478*37da2899SCharles.Forsyth ft_hash_done( FT_Hash table, 479*37da2899SCharles.Forsyth FT_Hash_ForeachFunc item_func, 480*37da2899SCharles.Forsyth const FT_Pointer item_data ); 481*37da2899SCharles.Forsyth 482*37da2899SCharles.Forsyth /* */ 483*37da2899SCharles.Forsyth 484*37da2899SCharles.Forsyth /* compute bucket index from hash value in a dynamic hash table */ 485*37da2899SCharles.Forsyth /* this is only used to break encapsulation to speed lookups in */ 486*37da2899SCharles.Forsyth /* the FreeType cache manager !! */ 487*37da2899SCharles.Forsyth /* */ 488*37da2899SCharles.Forsyth 489*37da2899SCharles.Forsyth #define FT_HASH_COMPUTE_INDEX(_table,_hash,_index) \ 490*37da2899SCharles.Forsyth { \ 491*37da2899SCharles.Forsyth FT_UInt _mask = (_table)->mask; \ 492*37da2899SCharles.Forsyth FT_UInt _hash0 = (_hash); \ 493*37da2899SCharles.Forsyth \ 494*37da2899SCharles.Forsyth (_index) = (FT_UInt)( (_hash0) & _mask ) ); \ 495*37da2899SCharles.Forsyth if ( (_index) < (_table)->p ) \ 496*37da2899SCharles.Forsyth (_index) = (FT_uInt)( (_hash0) & ( 2*_mask+1 ) ); \ 497*37da2899SCharles.Forsyth } 498*37da2899SCharles.Forsyth 499*37da2899SCharles.Forsyth 500*37da2899SCharles.Forsyth FT_END_HEADER 501*37da2899SCharles.Forsyth 502*37da2899SCharles.Forsyth #endif /* __FT_HASH_H__ */ 503