hash.c revision 1.1 1 1.1 tls /*
2 1.1 tls Copyright 2011 Google Inc. All Rights Reserved.
3 1.1 tls
4 1.1 tls Licensed under the Apache License, Version 2.0 (the "License");
5 1.1 tls you may not use this file except in compliance with the License.
6 1.1 tls You may obtain a copy of the License at
7 1.1 tls
8 1.1 tls http://www.apache.org/licenses/LICENSE-2.0
9 1.1 tls
10 1.1 tls Unless required by applicable law or agreed to in writing, software
11 1.1 tls distributed under the License is distributed on an "AS IS" BASIS,
12 1.1 tls WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 1.1 tls See the License for the specific language governing permissions and
14 1.1 tls limitations under the License.
15 1.1 tls
16 1.1 tls Author: lode.vandevenne (at) gmail.com (Lode Vandevenne)
17 1.1 tls Author: jyrki.alakuijala (at) gmail.com (Jyrki Alakuijala)
18 1.1 tls */
19 1.1 tls
20 1.1 tls #include "hash.h"
21 1.1 tls
22 1.1 tls #include <assert.h>
23 1.1 tls #include <stdio.h>
24 1.1 tls #include <stdlib.h>
25 1.1 tls
26 1.1 tls #define HASH_SHIFT 5
27 1.1 tls #define HASH_MASK 32767
28 1.1 tls
29 1.1 tls void ZopfliInitHash(size_t window_size, ZopfliHash* h) {
30 1.1 tls size_t i;
31 1.1 tls
32 1.1 tls h->val = 0;
33 1.1 tls h->head = (int*)malloc(sizeof(*h->head) * 65536);
34 1.1 tls h->prev = (unsigned short*)malloc(sizeof(*h->prev) * window_size);
35 1.1 tls h->hashval = (int*)malloc(sizeof(*h->hashval) * window_size);
36 1.1 tls for (i = 0; i < 65536; i++) {
37 1.1 tls h->head[i] = -1; /* -1 indicates no head so far. */
38 1.1 tls }
39 1.1 tls for (i = 0; i < window_size; i++) {
40 1.1 tls h->prev[i] = i; /* If prev[j] == j, then prev[j] is uninitialized. */
41 1.1 tls h->hashval[i] = -1;
42 1.1 tls }
43 1.1 tls
44 1.1 tls #ifdef ZOPFLI_HASH_SAME
45 1.1 tls h->same = (unsigned short*)malloc(sizeof(*h->same) * window_size);
46 1.1 tls for (i = 0; i < window_size; i++) {
47 1.1 tls h->same[i] = 0;
48 1.1 tls }
49 1.1 tls #endif
50 1.1 tls
51 1.1 tls #ifdef ZOPFLI_HASH_SAME_HASH
52 1.1 tls h->val2 = 0;
53 1.1 tls h->head2 = (int*)malloc(sizeof(*h->head2) * 65536);
54 1.1 tls h->prev2 = (unsigned short*)malloc(sizeof(*h->prev2) * window_size);
55 1.1 tls h->hashval2 = (int*)malloc(sizeof(*h->hashval2) * window_size);
56 1.1 tls for (i = 0; i < 65536; i++) {
57 1.1 tls h->head2[i] = -1;
58 1.1 tls }
59 1.1 tls for (i = 0; i < window_size; i++) {
60 1.1 tls h->prev2[i] = i;
61 1.1 tls h->hashval2[i] = -1;
62 1.1 tls }
63 1.1 tls #endif
64 1.1 tls }
65 1.1 tls
66 1.1 tls void ZopfliCleanHash(ZopfliHash* h) {
67 1.1 tls free(h->head);
68 1.1 tls free(h->prev);
69 1.1 tls free(h->hashval);
70 1.1 tls
71 1.1 tls #ifdef ZOPFLI_HASH_SAME_HASH
72 1.1 tls free(h->head2);
73 1.1 tls free(h->prev2);
74 1.1 tls free(h->hashval2);
75 1.1 tls #endif
76 1.1 tls
77 1.1 tls #ifdef ZOPFLI_HASH_SAME
78 1.1 tls free(h->same);
79 1.1 tls #endif
80 1.1 tls }
81 1.1 tls
82 1.1 tls /*
83 1.1 tls Update the sliding hash value with the given byte. All calls to this function
84 1.1 tls must be made on consecutive input characters. Since the hash value exists out
85 1.1 tls of multiple input bytes, a few warmups with this function are needed initially.
86 1.1 tls */
87 1.1 tls static void UpdateHashValue(ZopfliHash* h, unsigned char c) {
88 1.1 tls h->val = (((h->val) << HASH_SHIFT) ^ (c)) & HASH_MASK;
89 1.1 tls }
90 1.1 tls
91 1.1 tls void ZopfliUpdateHash(const unsigned char* array, size_t pos, size_t end,
92 1.1 tls ZopfliHash* h) {
93 1.1 tls unsigned short hpos = pos & ZOPFLI_WINDOW_MASK;
94 1.1 tls #ifdef ZOPFLI_HASH_SAME
95 1.1 tls size_t amount = 0;
96 1.1 tls #endif
97 1.1 tls
98 1.1 tls UpdateHashValue(h, pos + ZOPFLI_MIN_MATCH <= end ?
99 1.1 tls array[pos + ZOPFLI_MIN_MATCH - 1] : 0);
100 1.1 tls h->hashval[hpos] = h->val;
101 1.1 tls if (h->head[h->val] != -1 && h->hashval[h->head[h->val]] == h->val) {
102 1.1 tls h->prev[hpos] = h->head[h->val];
103 1.1 tls }
104 1.1 tls else h->prev[hpos] = hpos;
105 1.1 tls h->head[h->val] = hpos;
106 1.1 tls
107 1.1 tls #ifdef ZOPFLI_HASH_SAME
108 1.1 tls /* Update "same". */
109 1.1 tls if (h->same[(pos - 1) & ZOPFLI_WINDOW_MASK] > 1) {
110 1.1 tls amount = h->same[(pos - 1) & ZOPFLI_WINDOW_MASK] - 1;
111 1.1 tls }
112 1.1 tls while (pos + amount + 1 < end &&
113 1.1 tls array[pos] == array[pos + amount + 1] && amount < (unsigned short)(-1)) {
114 1.1 tls amount++;
115 1.1 tls }
116 1.1 tls h->same[hpos] = amount;
117 1.1 tls #endif
118 1.1 tls
119 1.1 tls #ifdef ZOPFLI_HASH_SAME_HASH
120 1.1 tls h->val2 = ((h->same[hpos] - ZOPFLI_MIN_MATCH) & 255) ^ h->val;
121 1.1 tls h->hashval2[hpos] = h->val2;
122 1.1 tls if (h->head2[h->val2] != -1 && h->hashval2[h->head2[h->val2]] == h->val2) {
123 1.1 tls h->prev2[hpos] = h->head2[h->val2];
124 1.1 tls }
125 1.1 tls else h->prev2[hpos] = hpos;
126 1.1 tls h->head2[h->val2] = hpos;
127 1.1 tls #endif
128 1.1 tls }
129 1.1 tls
130 1.1 tls void ZopfliWarmupHash(const unsigned char* array, size_t pos, size_t end,
131 1.1 tls ZopfliHash* h) {
132 1.1 tls (void)end;
133 1.1 tls UpdateHashValue(h, array[pos + 0]);
134 1.1 tls UpdateHashValue(h, array[pos + 1]);
135 1.1 tls }
136