xref: /inferno-os/include/freetype/internal/fthash.h (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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