Home | History | Annotate | Line # | Download | only in zopfli
      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