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