11cb0ef41Sopenharmony_ci/* insert_string.h
21cb0ef41Sopenharmony_ci *
31cb0ef41Sopenharmony_ci * Copyright 2019 The Chromium Authors
41cb0ef41Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
51cb0ef41Sopenharmony_ci * found in the Chromium source repository LICENSE file.
61cb0ef41Sopenharmony_ci */
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#ifndef INSERT_STRING_H
91cb0ef41Sopenharmony_ci#define INSERT_STRING_H
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ci#ifndef INLINE
121cb0ef41Sopenharmony_ci#if defined(_MSC_VER) && !defined(__clang__)
131cb0ef41Sopenharmony_ci#define INLINE __inline
141cb0ef41Sopenharmony_ci#else
151cb0ef41Sopenharmony_ci#define INLINE inline
161cb0ef41Sopenharmony_ci#endif
171cb0ef41Sopenharmony_ci#endif
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ci#include <stdint.h>
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci/**
221cb0ef41Sopenharmony_ci * Some applications need to match zlib DEFLATE output exactly [3]. Use the
231cb0ef41Sopenharmony_ci * canonical zlib Rabin-Karp rolling hash [1,2] in that case.
241cb0ef41Sopenharmony_ci *
251cb0ef41Sopenharmony_ci *  [1] For a description of the Rabin and Karp algorithm, see "Algorithms"
261cb0ef41Sopenharmony_ci *      book by R. Sedgewick, Addison-Wesley, p252.
271cb0ef41Sopenharmony_ci *  [2] https://www.euccas.me/zlib/#zlib_rabin_karp and also "rolling hash"
281cb0ef41Sopenharmony_ci *      https://en.wikipedia.org/wiki/Rolling_hash
291cb0ef41Sopenharmony_ci *  [3] crbug.com/1316541 AOSP incremental client APK package OTA upgrades.
301cb0ef41Sopenharmony_ci */
311cb0ef41Sopenharmony_ci#ifdef CHROMIUM_ZLIB_NO_CASTAGNOLI
321cb0ef41Sopenharmony_ci#define USE_ZLIB_RABIN_KARP_ROLLING_HASH
331cb0ef41Sopenharmony_ci#endif
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci/* ===========================================================================
361cb0ef41Sopenharmony_ci * Update a hash value with the given input byte (Rabin-Karp rolling hash).
371cb0ef41Sopenharmony_ci * IN  assertion: all calls to UPDATE_HASH are made with consecutive input
381cb0ef41Sopenharmony_ci *    characters, so that a running hash key can be computed from the previous
391cb0ef41Sopenharmony_ci *    key instead of complete recalculation each time.
401cb0ef41Sopenharmony_ci */
411cb0ef41Sopenharmony_ci#define UPDATE_HASH(s, h, c) (h = (((h) << s->hash_shift) ^ (c)) & s->hash_mask)
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci/* ===========================================================================
441cb0ef41Sopenharmony_ci * Insert string str in the dictionary and set match_head to the previous head
451cb0ef41Sopenharmony_ci * of the hash chain (the most recent string with same hash key). Return
461cb0ef41Sopenharmony_ci * the previous length of the hash chain.
471cb0ef41Sopenharmony_ci * If this file is compiled with -DFASTEST, the compression level is forced
481cb0ef41Sopenharmony_ci * to 1, and no hash chains are maintained.
491cb0ef41Sopenharmony_ci * IN  assertion: all calls to INSERT_STRING are made with consecutive input
501cb0ef41Sopenharmony_ci *    characters and the first MIN_MATCH bytes of str are valid (except for
511cb0ef41Sopenharmony_ci *    the last MIN_MATCH-1 bytes of the input file).
521cb0ef41Sopenharmony_ci */
531cb0ef41Sopenharmony_cilocal INLINE Pos insert_string(deflate_state* const s, const Pos str) {
541cb0ef41Sopenharmony_ci  Pos ret;
551cb0ef41Sopenharmony_ci/* insert_string dictionary insertion: ANZAC++ hasher
561cb0ef41Sopenharmony_ci * significantly improves data compression speed.
571cb0ef41Sopenharmony_ci *
581cb0ef41Sopenharmony_ci * Note: the generated compressed output is a valid DEFLATE stream, but will
591cb0ef41Sopenharmony_ci * differ from canonical zlib output.
601cb0ef41Sopenharmony_ci */
611cb0ef41Sopenharmony_ci#if defined(USE_ZLIB_RABIN_KARP_ROLLING_HASH)
621cb0ef41Sopenharmony_ci  UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH - 1)]);
631cb0ef41Sopenharmony_ci#else
641cb0ef41Sopenharmony_ci  uint32_t value;
651cb0ef41Sopenharmony_ci  // Validated for little endian archs (i.e. x86, Arm). YMMV for big endian.
661cb0ef41Sopenharmony_ci  zmemcpy(&value, &s->window[str], sizeof(value));
671cb0ef41Sopenharmony_ci  s->ins_h = ((value * 66521 + 66521) >> 16) & s->hash_mask;
681cb0ef41Sopenharmony_ci#endif
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci#ifdef FASTEST
711cb0ef41Sopenharmony_ci  ret = s->head[s->ins_h];
721cb0ef41Sopenharmony_ci#else
731cb0ef41Sopenharmony_ci  ret = s->prev[str & s->w_mask] = s->head[s->ins_h];
741cb0ef41Sopenharmony_ci#endif
751cb0ef41Sopenharmony_ci  s->head[s->ins_h] = str;
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci  return ret;
781cb0ef41Sopenharmony_ci}
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci#endif /* INSERT_STRING_H */
81