diff options
Diffstat (limited to 'include/freetype/internal/fthash.h')
| -rw-r--r-- | include/freetype/internal/fthash.h | 595 |
1 files changed, 114 insertions, 481 deletions
diff --git a/include/freetype/internal/fthash.h b/include/freetype/internal/fthash.h index b95b6c92..622ec76b 100644 --- a/include/freetype/internal/fthash.h +++ b/include/freetype/internal/fthash.h @@ -1,502 +1,135 @@ -/****************************************************************** +/**************************************************************************** * - * fthash.h - fast dynamic hash tables + * fthash.h * - * Copyright 2002 by - * David Turner, Robert Wilhelm, and Werner Lemberg + * Hashing functions (specification). * - * This file is part of the FreeType project, and may only be used, - * modified, and distributed under the terms of the FreeType project - * license, LICENSE.TXT. By continuing to use, modify, or distribute - * this file you indicate that you have read the license and - * understand and accept it fully. - * - * - * This header is used to define dynamic hash tables as described - * by the article "Main-Memory Linear Hashing - Some Enhancements - * of Larson's Algorithm" by Mikael Petterson. + */ + +/* + * Copyright 2000 Computing Research Labs, New Mexico State University + * Copyright 2001-2015 + * Francesco Zappa Nardelli * - * Basically, linear hashing prevents big "stalls" during - * resizes of the buckets array by only splitting one bucket - * at a time. This ensures excellent response time even when - * the table is frequently resized.. + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * - * Note that the use of the FT_Hash type is rather unusual in order - * to be as generic and efficient as possible. See the comments in the - * following definitions for more details. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT + * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef __FT_HASH_H__ -#define __FT_HASH_H__ + /************************************************************************** + * + * This file is based on code from bdf.c,v 1.22 2000/03/16 20:08:50 + * + * taken from Mark Leisher's xmbdfed package + * + */ + + +#ifndef FTHASH_H_ +#define FTHASH_H_ + + +#include <freetype/freetype.h> -#include <ft2build.h> -#include FT_TYPES_H FT_BEGIN_HEADER - /*********************************************************** - * - * @type: FT_Hash - * - * @description: - * handle to a @FT_HashRec structure used to model a - * dynamic hash table - */ - typedef struct FT_HashRec_* FT_Hash; - - - /*********************************************************** - * - * @type: FT_HashNode - * - * @description: - * handle to a @FT_HashNodeRec structure used to model a - * single node of a hash table - */ - typedef struct FT_HashNodeRec_* FT_HashNode; - - - /*********************************************************** - * - * @type: FT_HashLookup - * - * @description: - * handle to a @FT_HashNode pointer. This is returned by - * the @ft_hash_lookup function and can later be used by - * @ft_hash_add or @ft_hash_remove - */ - typedef FT_HashNode* FT_HashLookup; - - - /*********************************************************** - * - * @type: FT_Hash_EqualFunc - * - * @description: - * a function used to compare two nodes of the hash table - * - * @input: - * node1 :: handle to first node - * node2 :: handle to second node - * - * @return: - * 1 iff the 'keys' in 'node1' and 'node2' are identical. - * 0 otherwise. - */ - typedef FT_Int (*FT_Hash_EqualFunc)( FT_HashNode node1, - FT_HashNode node2 ); - - - /*********************************************************** - * - * @struct: FT_HashRec - * - * @description: - * a structure used to model a dynamic hash table. - * - * @fields: - * memory :: memory manager used to allocate - * the buckets array and the hash nodes - * - * buckets :: array of hash buckets - * - * node_size :: size of node in bytes - * node_compare :: a function used to compare two nodes - * node_hash :: a function used to compute the hash - * value of a given node - * p :: - * mask :: - * slack :: - * - * @note: - * 'p', 'mask' and 'slack' are control values managed by - * the hash table. Do not try to interpret them directly. - * - * You can grab the hash table size by calling - * '@ft_hash_get_size'. - */ - typedef struct FT_HashRec_ + + typedef union FT_Hashkey_ { - FT_HashNode* buckets; - FT_UInt p; - FT_UInt mask; /* really maxp-1 */ - FT_Long slack; - FT_Hash_EqualFunc node_equal; - FT_Memory memory; + FT_Int num; + const char* str; - } FT_HashRec; + } FT_Hashkey; + + + typedef struct FT_HashnodeRec_ + { + FT_Hashkey key; + size_t data; + + } FT_HashnodeRec; + + typedef struct FT_HashnodeRec_ *FT_Hashnode; + + + typedef FT_ULong + (*FT_Hash_LookupFunc)( FT_Hashkey* key ); + + typedef FT_Bool + (*FT_Hash_CompareFunc)( FT_Hashkey* a, + FT_Hashkey* b ); - /*********************************************************** - * - * @struct: FT_HashNodeRec - * - * @description: - * a structure used to model the root fields of a dynamic - * hash table node. - * - * it's up to client applications to "sub-class" this - * structure to add relevant (key,value) definitions - * - * @fields: - * link :: pointer to next node in bucket's collision list - * hash :: 32-bit hash value for this node - * - * @note: - * it's up to client applications to "sub-class" this structure - * to add relevant (key,value) type definitions. For example, - * if we want to build a "string -> int" mapping, we could use - * something like: - * - * { - * typedef struct MyNodeRec_ - * { - * FT_HashNodeRec hnode; - * const char* key; - * int value; - * - * } MyNodeRec, *MyNode; - * } - * - */ - typedef struct FT_HashNodeRec_ + typedef struct FT_HashRec_ { - FT_HashNode link; - FT_UInt32 hash; - - } FT_HashNodeRec; - - - /**************************************************************** - * - * @function: ft_hash_init - * - * @description: - * initialize a dynamic hash table - * - * @input: - * table :: handle to target hash table structure - * node_equal :: node comparison function - * memory :: memory manager handle used to allocate the - * buckets array within the hash table - * - * @return: - * error code. 0 means success - * - * @note: - * the node comparison function should only compare node _keys_ - * and ignore values !! with good hashing computation (which the - * user must perform itself), the comparison function should be - * pretty seldom called. - * - * here is a simple example: - * - * { - * static int my_equal( MyNode node1, - * MyNode node2 ) - * { - * // compare keys of 'node1' and 'node2' - * return (strcmp( node1->key, node2->key ) == 0); - * } - * - * .... - * - * ft_hash_init( &hash, (FT_Hash_EqualFunc) my_compare, memory ); - * .... - * } - */ - FT_BASE( FT_Error ) - ft_hash_init( FT_Hash table, - FT_Hash_EqualFunc compare, - FT_Memory memory ); - - - /**************************************************************** - * - * @function: ft_hash_lookup - * - * @description: - * search a hash table to find a node corresponding to a given - * key. - * - * @input: - * table :: handle to target hash table structure - * keynode :: handle to a reference hash node that will be - * only used for key comparisons with the table's - * elements - * - * @return: - * a pointer-to-hash-node value, which must be used as followed: - * - * - if '*result' is NULL, the key wasn't found in the hash - * table. The value of 'result' can be used to add new elements - * through @ft_hash_add however.. - * - * - if '*result' is not NULL, it's a handle to the first table - * node that corresponds to the search key. The value of 'result' - * can be used to remove this element through @ft_hash_remove - * - * @note: - * here is an example: - * - * { - * // maps a string to an integer with a hash table - * // returns -1 in case of failure - * // - * int my_lookup( FT_Hash table, - * const char* key ) - * { - * MyNode* pnode; - * MyNodeRec noderec; - * - * // set-up key node. It's 'hash' and 'key' fields must - * // be set correctly.. we ignore 'link' and 'value' - * // - * noderec.hnode.hash = strhash( key ); - * noderec.key = key; - * - * // perform search - return value - * // - * pnode = (MyNode) ft_hash_lookup( table, &noderec ); - * if ( *pnode ) - * { - * // we found it - * return (*pnode)->value; - * } - * return -1; - * } - * } - */ - FT_BASE_DEF( FT_HashLookup ) - ft_hash_lookup( FT_Hash table, - FT_HashNode keynode ); - - - /**************************************************************** - * - * @function: ft_hash_add - * - * @description: - * add a new node to a dynamic hash table. the user must - * call @ft_hash_lookup and allocate a new node before calling - * this function. - * - * @input: - * table :: hash table handle - * lookup :: pointer-to-hash-node value returned by @ft_hash_lookup - * new_node :: handle to new hash node. All its fields must be correctly - * set, including 'hash'. - * - * @return: - * error code. 0 means success - * - * @note: - * this function should always be used _after_ a call to @ft_hash_lookup - * that returns a pointer to a NULL handle. Here's an example: - * - * { - * // sets the value corresponding to a given string key - * // - * void my_set( FT_Hash table, - * const char* key, - * int value ) - * { - * MyNode* pnode; - * MyNodeRec noderec; - * MyNode node; - * - * // set-up key node. It's 'hash' and 'key' fields must - * // be set correctly.. - * noderec.hnode.hash = strhash( key ); - * noderec.key = key; - * - * // perform search - return value - * pnode = (MyNode) ft_hash_lookup( table, &noderec ); - * if ( *pnode ) - * { - * // we found it, simply replace the value in the node - * (*pnode)->value = value; - * return; - * } - * - * // allocate a new node - and set it up - * node = (MyNode) malloc( sizeof(*node) ); - * if ( node == NULL ) ..... - * - * node->hnode.hash = noderec.hnode.hash; - * node->key = key; - * node->value = value; - * - * // add it to the hash table - * error = ft_hash_add( table, pnode, node ); - * if (error) .... - * } - */ - FT_BASE( FT_Error ) - ft_hash_add( FT_Hash table, - FT_HashLookup lookup, - FT_HashNode new_node ); - - - /**************************************************************** - * - * @function: ft_hash_remove - * - * @description: - * try to remove the node corresponding to a given key from - * a hash table. This must be called after @ft_hash_lookup - * - * @input: - * table :: hash table handle - * lookup :: pointer-to-hash-node value returned by @ft_hash_lookup - * - * @note: - * this function doesn't free the node itself !! Here's an example: - * - * { - * // sets the value corresponding to a given string key - * // - * void my_remove( FT_Hash table, - * const char* key ) - * { - * MyNodeRec noderec; - * MyNode node; - * - * noderec.hnode.hash = strhash(key); - * noderec.key = key; - * node = &noderec; - * - * pnode = ft_hash_lookup( table, &noderec ); - * node = *pnode; - * if ( node != NULL ) - * { - * error = ft_hash_remove( table, pnode ); - * if ( !error ) - * free( node ); - * } - * } - * } - */ - FT_BASE( FT_Error ) - ft_hash_remove( FT_Hash table, - FT_HashLookup lookup ); - - - - /**************************************************************** - * - * @function: ft_hash_get_size - * - * @description: - * return the number of elements in a given hash table - * - * @input: - * table :: handle to target hash table structure - * - * @return: - * number of elements. 0 if empty - */ - FT_BASE( FT_UInt ) - ft_hash_get_size( FT_Hash table ); - - - - /**************************************************************** - * - * @functype: FT_Hash_ForeachFunc - * - * @description: - * a function used to iterate over all elements of a given - * hash table - * - * @input: - * node :: handle to target @FT_HashNodeRec node structure - * data :: optional argument to iteration routine - * - * @also: @ft_hash_foreach - */ - typedef void (*FT_Hash_ForeachFunc)( const FT_HashNode node, - const FT_Pointer data ); - - - /**************************************************************** - * - * @function: ft_hash_foreach - * - * @description: - * parse over all elements in a hash table - * - * @input: - * table :: handle to target hash table structure - * foreach_func :: iteration routine called for each element - * foreach_data :: optional argument to the iteration routine - * - * @note: - * this function is often used to release all elements from a - * hash table. See the example given for @ft_hash_done - */ - FT_BASE( void ) - ft_hash_foreach( FT_Hash table, - FT_Hash_ForeachFunc foreach_func, - const FT_Pointer foreach_data ); - - - - /**************************************************************** - * - * @function: ft_hash_done - * - * @description: - * finalize a given hash table - * - * @input: - * table :: handle to target hash table structure - * node_func :: optional iteration function pointer. this - * can be used to destroy all nodes explicitely - * node_data :: optional argument to the node iterator - * - * @note: - * this function simply frees the hash table's buckets. - * you probably will need to call @ft_hash_foreach to - * destroy all its elements before @ft_hash_done, as in - * the following example: - * - * { - * static void my_node_clear( const MyNode node ) - * { - * free( node ); - * } - * - * static void my_done( FT_Hash table ) - * { - * ft_hash_done( table, (FT_Hash_ForeachFunc) my_node_clear, NULL ); - * } - * } - */ - FT_BASE( void ) - ft_hash_done( FT_Hash table, - FT_Hash_ForeachFunc item_func, - const FT_Pointer item_data ); - - /* */ - - /* compute bucket index from hash value in a dynamic hash table */ - /* this is only used to break encapsulation to speed lookups in */ - /* the FreeType cache manager !! */ - /* */ - -#define FT_HASH_COMPUTE_INDEX(_table,_hash,_index) \ - { \ - FT_UInt _mask = (_table)->mask; \ - FT_UInt _hash0 = (_hash); \ - \ - (_index) = (FT_UInt)( (_hash0) & _mask ) ); \ - if ( (_index) < (_table)->p ) \ - (_index) = (FT_uInt)( (_hash0) & ( 2*_mask+1 ) ); \ - } + FT_UInt limit; + FT_UInt size; + FT_UInt used; + + FT_Hash_LookupFunc lookup; + FT_Hash_CompareFunc compare; + + FT_Hashnode* table; + + } FT_HashRec; + + typedef struct FT_HashRec_ *FT_Hash; + + + FT_Error + ft_hash_str_init( FT_Hash hash, + FT_Memory memory ); + + FT_Error + ft_hash_num_init( FT_Hash hash, + FT_Memory memory ); + + void + ft_hash_str_free( FT_Hash hash, + FT_Memory memory ); + +#define ft_hash_num_free ft_hash_str_free + + FT_Error + ft_hash_str_insert( const char* key, + size_t data, + FT_Hash hash, + FT_Memory memory ); + + FT_Error + ft_hash_num_insert( FT_Int num, + size_t data, + FT_Hash hash, + FT_Memory memory ); + + size_t* + ft_hash_str_lookup( const char* key, + FT_Hash hash ); + + size_t* + ft_hash_num_lookup( FT_Int num, + FT_Hash hash ); FT_END_HEADER -#endif /* __FT_HASH_H__ */ + +#endif /* FTHASH_H_ */ + + +/* END */ |
