00001 /***************************************************************************** 00002 * "Gif-Lib" - Yet another gif library. * 00003 * * 00004 * Written by: Gershon Elber IBM PC Ver 0.1, Jun. 1989 * 00005 ****************************************************************************** 00006 * Module to support the following operations: * 00007 * * 00008 * 1. InitHashTable - initialize hash table. * 00009 * 2. ClearHashTable - clear the hash table to an empty state. * 00010 * 2. InsertHashTable - insert one item into data structure. * 00011 * 3. ExistsHashTable - test if item exists in data structure. * 00012 * * 00013 * This module is used to hash the GIF codes during encoding. * 00014 ****************************************************************************** 00015 * History: * 00016 * 14 Jun 89 - Version 1.0 by Gershon Elber. * 00017 *****************************************************************************/ 00018 00019 #ifdef _WIN32 00020 #include "../win32/config.h" 00021 #else 00022 #include "../config.h" 00023 #endif 00024 00025 /* Find a thirty-two bit int type */ 00026 #ifdef HAVE_SYS_TYPES_H 00027 #include <sys/types.h> 00028 #endif 00029 00030 #ifdef __MSDOS__ 00031 #include <io.h> 00032 #include <alloc.h> 00033 #include <sys\stat.h> 00034 #else 00035 #include <sys/types.h> 00036 #include <sys/stat.h> 00037 #endif /* __MSDOS__ */ 00038 00039 #ifdef HAVE_FCNTL_H 00040 #include <fcntl.h> 00041 #endif /* HAVE_FCNTL_H */ 00042 #include <stdio.h> 00043 #include <string.h> 00044 #include "gif_lib.h" 00045 #include "gif_hash.h" 00046 #include "gif_lib_private.h" 00047 00048 /* #define DEBUG_HIT_RATE Debug number of misses per hash Insert/Exists. */ 00049 00050 #ifdef DEBUG_HIT_RATE 00051 static long NumberOfTests = 0, 00052 NumberOfMisses = 0; 00053 #endif /* DEBUG_HIT_RATE */ 00054 00055 static int KeyItem(UINT32 Item); 00056 00057 /****************************************************************************** 00058 * Initialize HashTable - allocate the memory needed and clear it. * 00059 ******************************************************************************/ 00060 GifHashTableType *_InitHashTable(void) 00061 { 00062 GifHashTableType *HashTable; 00063 00064 if ((HashTable = (GifHashTableType *) malloc(sizeof(GifHashTableType))) 00065 == NULL) 00066 return NULL; 00067 00068 _ClearHashTable(HashTable); 00069 00070 return HashTable; 00071 } 00072 00073 /****************************************************************************** 00074 * Routine to clear the HashTable to an empty state. * 00075 * This part is a little machine depended. Use the commented part otherwise. * 00076 ******************************************************************************/ 00077 void _ClearHashTable(GifHashTableType *HashTable) 00078 { 00079 memset(HashTable -> HTable, 0xFF, HT_SIZE * sizeof(UINT32)); 00080 } 00081 00082 /****************************************************************************** 00083 * Routine to insert a new Item into the HashTable. The data is assumed to be * 00084 * new one. * 00085 ******************************************************************************/ 00086 void _InsertHashTable(GifHashTableType *HashTable, UINT32 Key, int Code) 00087 { 00088 int HKey = KeyItem(Key); 00089 UINT32 *HTable = HashTable -> HTable; 00090 00091 #ifdef DEBUG_HIT_RATE 00092 NumberOfTests++; 00093 NumberOfMisses++; 00094 #endif /* DEBUG_HIT_RATE */ 00095 00096 while (HT_GET_KEY(HTable[HKey]) != 0xFFFFFL) { 00097 #ifdef DEBUG_HIT_RATE 00098 NumberOfMisses++; 00099 #endif /* DEBUG_HIT_RATE */ 00100 HKey = (HKey + 1) & HT_KEY_MASK; 00101 } 00102 HTable[HKey] = HT_PUT_KEY(Key) | HT_PUT_CODE(Code); 00103 } 00104 00105 /****************************************************************************** 00106 * Routine to test if given Key exists in HashTable and if so returns its code * 00107 * Returns the Code if key was found, -1 if not. * 00108 ******************************************************************************/ 00109 int _ExistsHashTable(GifHashTableType *HashTable, UINT32 Key) 00110 { 00111 int HKey = KeyItem(Key); 00112 UINT32 *HTable = HashTable -> HTable, HTKey; 00113 00114 #ifdef DEBUG_HIT_RATE 00115 NumberOfTests++; 00116 NumberOfMisses++; 00117 #endif /* DEBUG_HIT_RATE */ 00118 00119 while ((HTKey = HT_GET_KEY(HTable[HKey])) != 0xFFFFFL) { 00120 #ifdef DEBUG_HIT_RATE 00121 NumberOfMisses++; 00122 #endif /* DEBUG_HIT_RATE */ 00123 if (Key == HTKey) return HT_GET_CODE(HTable[HKey]); 00124 HKey = (HKey + 1) & HT_KEY_MASK; 00125 } 00126 00127 return -1; 00128 } 00129 00130 /****************************************************************************** 00131 * Routine to generate an HKey for the hashtable out of the given unique key. * 00132 * The given Key is assumed to be 20 bits as follows: lower 8 bits are the * 00133 * new postfix character, while the upper 12 bits are the prefix code. * 00134 * Because the average hit ratio is only 2 (2 hash references per entry), * 00135 * evaluating more complex keys (such as twin prime keys) does not worth it! * 00136 ******************************************************************************/ 00137 static int KeyItem(UINT32 Item) 00138 { 00139 return ((Item >> 12) ^ Item) & HT_KEY_MASK; 00140 } 00141 00142 #ifdef DEBUG_HIT_RATE 00143 /****************************************************************************** 00144 * Debugging routine to print the hit ratio - number of times the hash table * 00145 * was tested per operation. This routine was used to test the KeyItem routine * 00146 ******************************************************************************/ 00147 void HashTablePrintHitRatio(void) 00148 { 00149 printf("Hash Table Hit Ratio is %ld/%ld = %ld%%.\n", 00150 NumberOfMisses, NumberOfTests, 00151 NumberOfMisses * 100 / NumberOfTests); 00152 } 00153 #endif /* DEBUG_HIT_RATE */