xref: /aosp_15_r20/external/giflib/gif_hash.c (revision 324bb76b8d05e2a05aa88511fff61cf3f9ca5892)
1*324bb76bSAndroid Build Coastguard Worker /*****************************************************************************
2*324bb76bSAndroid Build Coastguard Worker 
3*324bb76bSAndroid Build Coastguard Worker gif_hash.c -- module to support the following operations:
4*324bb76bSAndroid Build Coastguard Worker 
5*324bb76bSAndroid Build Coastguard Worker 1. InitHashTable - initialize hash table.
6*324bb76bSAndroid Build Coastguard Worker 2. ClearHashTable - clear the hash table to an empty state.
7*324bb76bSAndroid Build Coastguard Worker 2. InsertHashTable - insert one item into data structure.
8*324bb76bSAndroid Build Coastguard Worker 3. ExistsHashTable - test if item exists in data structure.
9*324bb76bSAndroid Build Coastguard Worker 
10*324bb76bSAndroid Build Coastguard Worker This module is used to hash the GIF codes during encoding.
11*324bb76bSAndroid Build Coastguard Worker 
12*324bb76bSAndroid Build Coastguard Worker SPDX-License-Identifier: MIT
13*324bb76bSAndroid Build Coastguard Worker 
14*324bb76bSAndroid Build Coastguard Worker *****************************************************************************/
15*324bb76bSAndroid Build Coastguard Worker 
16*324bb76bSAndroid Build Coastguard Worker #include <fcntl.h>
17*324bb76bSAndroid Build Coastguard Worker #include <stdint.h>
18*324bb76bSAndroid Build Coastguard Worker #include <stdio.h>
19*324bb76bSAndroid Build Coastguard Worker #include <stdlib.h>
20*324bb76bSAndroid Build Coastguard Worker #include <string.h>
21*324bb76bSAndroid Build Coastguard Worker 
22*324bb76bSAndroid Build Coastguard Worker #include "gif_hash.h"
23*324bb76bSAndroid Build Coastguard Worker #include "gif_lib.h"
24*324bb76bSAndroid Build Coastguard Worker #include "gif_lib_private.h"
25*324bb76bSAndroid Build Coastguard Worker 
26*324bb76bSAndroid Build Coastguard Worker /* #define  DEBUG_HIT_RATE    Debug number of misses per hash Insert/Exists. */
27*324bb76bSAndroid Build Coastguard Worker 
28*324bb76bSAndroid Build Coastguard Worker #ifdef DEBUG_HIT_RATE
29*324bb76bSAndroid Build Coastguard Worker static long NumberOfTests = 0, NumberOfMisses = 0;
30*324bb76bSAndroid Build Coastguard Worker #endif /* DEBUG_HIT_RATE */
31*324bb76bSAndroid Build Coastguard Worker 
32*324bb76bSAndroid Build Coastguard Worker static int KeyItem(uint32_t Item);
33*324bb76bSAndroid Build Coastguard Worker 
34*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
35*324bb76bSAndroid Build Coastguard Worker  Initialize HashTable - allocate the memory needed and clear it.	      *
36*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
_InitHashTable(void)37*324bb76bSAndroid Build Coastguard Worker GifHashTableType *_InitHashTable(void) {
38*324bb76bSAndroid Build Coastguard Worker 	GifHashTableType *HashTable;
39*324bb76bSAndroid Build Coastguard Worker 
40*324bb76bSAndroid Build Coastguard Worker 	if ((HashTable = (GifHashTableType *)malloc(
41*324bb76bSAndroid Build Coastguard Worker 	         sizeof(GifHashTableType))) == NULL) {
42*324bb76bSAndroid Build Coastguard Worker 		return NULL;
43*324bb76bSAndroid Build Coastguard Worker 	}
44*324bb76bSAndroid Build Coastguard Worker 
45*324bb76bSAndroid Build Coastguard Worker 	_ClearHashTable(HashTable);
46*324bb76bSAndroid Build Coastguard Worker 
47*324bb76bSAndroid Build Coastguard Worker 	return HashTable;
48*324bb76bSAndroid Build Coastguard Worker }
49*324bb76bSAndroid Build Coastguard Worker 
50*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
51*324bb76bSAndroid Build Coastguard Worker  Routine to clear the HashTable to an empty state.			      *
52*324bb76bSAndroid Build Coastguard Worker  This part is a little machine depended. Use the commented part otherwise.   *
53*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
_ClearHashTable(GifHashTableType * HashTable)54*324bb76bSAndroid Build Coastguard Worker void _ClearHashTable(GifHashTableType *HashTable) {
55*324bb76bSAndroid Build Coastguard Worker 	memset(HashTable->HTable, 0xFF, HT_SIZE * sizeof(uint32_t));
56*324bb76bSAndroid Build Coastguard Worker }
57*324bb76bSAndroid Build Coastguard Worker 
58*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
59*324bb76bSAndroid Build Coastguard Worker  Routine to insert a new Item into the HashTable. The data is assumed to be  *
60*324bb76bSAndroid Build Coastguard Worker  new one.								      *
61*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
_InsertHashTable(GifHashTableType * HashTable,uint32_t Key,int Code)62*324bb76bSAndroid Build Coastguard Worker void _InsertHashTable(GifHashTableType *HashTable, uint32_t Key, int Code) {
63*324bb76bSAndroid Build Coastguard Worker 	int HKey = KeyItem(Key);
64*324bb76bSAndroid Build Coastguard Worker 	uint32_t *HTable = HashTable->HTable;
65*324bb76bSAndroid Build Coastguard Worker 
66*324bb76bSAndroid Build Coastguard Worker #ifdef DEBUG_HIT_RATE
67*324bb76bSAndroid Build Coastguard Worker 	NumberOfTests++;
68*324bb76bSAndroid Build Coastguard Worker 	NumberOfMisses++;
69*324bb76bSAndroid Build Coastguard Worker #endif /* DEBUG_HIT_RATE */
70*324bb76bSAndroid Build Coastguard Worker 
71*324bb76bSAndroid Build Coastguard Worker 	while (HT_GET_KEY(HTable[HKey]) != 0xFFFFFL) {
72*324bb76bSAndroid Build Coastguard Worker #ifdef DEBUG_HIT_RATE
73*324bb76bSAndroid Build Coastguard Worker 		NumberOfMisses++;
74*324bb76bSAndroid Build Coastguard Worker #endif /* DEBUG_HIT_RATE */
75*324bb76bSAndroid Build Coastguard Worker 		HKey = (HKey + 1) & HT_KEY_MASK;
76*324bb76bSAndroid Build Coastguard Worker 	}
77*324bb76bSAndroid Build Coastguard Worker 	HTable[HKey] = HT_PUT_KEY(Key) | HT_PUT_CODE(Code);
78*324bb76bSAndroid Build Coastguard Worker }
79*324bb76bSAndroid Build Coastguard Worker 
80*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
81*324bb76bSAndroid Build Coastguard Worker  Routine to test if given Key exists in HashTable and if so returns its code *
82*324bb76bSAndroid Build Coastguard Worker  Returns the Code if key was found, -1 if not.				      *
83*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
_ExistsHashTable(GifHashTableType * HashTable,uint32_t Key)84*324bb76bSAndroid Build Coastguard Worker int _ExistsHashTable(GifHashTableType *HashTable, uint32_t Key) {
85*324bb76bSAndroid Build Coastguard Worker 	int HKey = KeyItem(Key);
86*324bb76bSAndroid Build Coastguard Worker 	uint32_t *HTable = HashTable->HTable, HTKey;
87*324bb76bSAndroid Build Coastguard Worker 
88*324bb76bSAndroid Build Coastguard Worker #ifdef DEBUG_HIT_RATE
89*324bb76bSAndroid Build Coastguard Worker 	NumberOfTests++;
90*324bb76bSAndroid Build Coastguard Worker 	NumberOfMisses++;
91*324bb76bSAndroid Build Coastguard Worker #endif /* DEBUG_HIT_RATE */
92*324bb76bSAndroid Build Coastguard Worker 
93*324bb76bSAndroid Build Coastguard Worker 	while ((HTKey = HT_GET_KEY(HTable[HKey])) != 0xFFFFFL) {
94*324bb76bSAndroid Build Coastguard Worker #ifdef DEBUG_HIT_RATE
95*324bb76bSAndroid Build Coastguard Worker 		NumberOfMisses++;
96*324bb76bSAndroid Build Coastguard Worker #endif /* DEBUG_HIT_RATE */
97*324bb76bSAndroid Build Coastguard Worker 		if (Key == HTKey) {
98*324bb76bSAndroid Build Coastguard Worker 			return HT_GET_CODE(HTable[HKey]);
99*324bb76bSAndroid Build Coastguard Worker 		}
100*324bb76bSAndroid Build Coastguard Worker 		HKey = (HKey + 1) & HT_KEY_MASK;
101*324bb76bSAndroid Build Coastguard Worker 	}
102*324bb76bSAndroid Build Coastguard Worker 
103*324bb76bSAndroid Build Coastguard Worker 	return -1;
104*324bb76bSAndroid Build Coastguard Worker }
105*324bb76bSAndroid Build Coastguard Worker 
106*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
107*324bb76bSAndroid Build Coastguard Worker  Routine to generate an HKey for the hashtable out of the given unique key.  *
108*324bb76bSAndroid Build Coastguard Worker  The given Key is assumed to be 20 bits as follows: lower 8 bits are the     *
109*324bb76bSAndroid Build Coastguard Worker  new postfix character, while the upper 12 bits are the prefix code.	      *
110*324bb76bSAndroid Build Coastguard Worker  Because the average hit ratio is only 2 (2 hash references per entry),      *
111*324bb76bSAndroid Build Coastguard Worker  evaluating more complex keys (such as twin prime keys) does not worth it!   *
112*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
KeyItem(uint32_t Item)113*324bb76bSAndroid Build Coastguard Worker static int KeyItem(uint32_t Item) {
114*324bb76bSAndroid Build Coastguard Worker 	return ((Item >> 12) ^ Item) & HT_KEY_MASK;
115*324bb76bSAndroid Build Coastguard Worker }
116*324bb76bSAndroid Build Coastguard Worker 
117*324bb76bSAndroid Build Coastguard Worker #ifdef DEBUG_HIT_RATE
118*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
119*324bb76bSAndroid Build Coastguard Worker  Debugging routine to print the hit ratio - number of times the hash table   *
120*324bb76bSAndroid Build Coastguard Worker  was tested per operation. This routine was used to test the KeyItem routine *
121*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
HashTablePrintHitRatio(void)122*324bb76bSAndroid Build Coastguard Worker void HashTablePrintHitRatio(void) {
123*324bb76bSAndroid Build Coastguard Worker 	printf("Hash Table Hit Ratio is %ld/%ld = %ld%%.\n", NumberOfMisses,
124*324bb76bSAndroid Build Coastguard Worker 	       NumberOfTests, NumberOfMisses * 100 / NumberOfTests);
125*324bb76bSAndroid Build Coastguard Worker }
126*324bb76bSAndroid Build Coastguard Worker #endif /* DEBUG_HIT_RATE */
127*324bb76bSAndroid Build Coastguard Worker 
128*324bb76bSAndroid Build Coastguard Worker /* end */
129