blob: 7a2f862dd86e5f037f5d1daeeb65ba7e60b1d624 [file] [edit]
/* insert_string_p.h -- static insert_string and insert_string_roll functions
*
* Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#ifndef INSERT_STRING_P_H_
#define INSERT_STRING_P_H_
#define UPDATE_HASH_INT(h,val) h = (((val) * 2654435761U) >> 16) & HASH_MASK
#define UPDATE_HASH_ROLL(h,val) h = ((h << 5) ^ ((uint8_t)(val))) & (32768u - 1u)
/* ===========================================================================
* Update a hash value with the given input byte
* IN assertion: all calls to UPDATE_HASH are made with consecutive
* input characters, so that a running hash key can be computed from the
* previous key instead of complete recalculation each time.
*/
Z_FORCEINLINE static uint32_t update_hash_roll(uint32_t h, uint32_t val) {
h = ((h << 5) ^ ((uint8_t)val));
return h & (32768u - 1u);
}
/* ===========================================================================
* Quick insert string str in the dictionary using a pre-read value and set match_head
* to the previous head of the hash chain (the most recent string with same hash key).
* Return the previous length of the hash chain.
*/
Z_FORCEINLINE static uint32_t quick_insert_value(deflate_state *const s, uint32_t str, uint32_t val) {
uint32_t h, head;
UPDATE_HASH_INT(h, val);
head = s->head[h];
if (LIKELY(head != str)) {
s->prev[str & W_MASK(s)] = (Pos)head;
s->head[h] = (Pos)str;
}
return head;
}
/* ===========================================================================
* Quick insert string str in the dictionary and set match_head to the previous head
* of the hash chain (the most recent string with same hash key). Return
* the previous length of the hash chain.
*/
Z_FORCEINLINE static uint32_t quick_insert_string(deflate_state *const s, unsigned char *window, uint32_t str) {
uint8_t *strstart = window + str;
uint32_t val, h, head;
val = Z_U32_FROM_LE(zng_memread_4(strstart));
UPDATE_HASH_INT(h, val);
head = s->head[h];
if (LIKELY(head != str)) {
s->prev[str & W_MASK(s)] = (Pos)head;
s->head[h] = (Pos)str;
}
return head;
}
Z_FORCEINLINE static uint32_t quick_insert_string_roll(deflate_state *const s, unsigned char *window, uint32_t str) {
uint8_t *strstart = window + str + (STD_MIN_MATCH-1);
uint32_t h, head;
h = s->ins_h;
UPDATE_HASH_ROLL(h, strstart[0]);
s->ins_h = h;
head = s->head[h];
if (LIKELY(head != str)) {
s->prev[str & W_MASK(s)] = (Pos)head;
s->head[h] = (Pos)str;
}
return head;
}
/* ===========================================================================
* Insert string str in the dictionary and set match_head to the previous head
* of the hash chain (the most recent string with same hash key). Return
* the previous length of the hash chain.
* IN assertion: all calls to INSERT_STRING are made with consecutive
* input characters and the first STD_MIN_MATCH bytes of str are valid
* (except for the last STD_MIN_MATCH-1 bytes of the input file).
*/
Z_FORCEINLINE static void insert_string_static(deflate_state *const s, unsigned char *window, uint32_t str, uint32_t count) {
uint8_t *strstart = window + str;
uint8_t *strend = strstart + count;
/* Local pointers to avoid indirection */
Pos *headp = s->head;
Pos *prevp = s->prev;
const unsigned int w_mask = W_MASK(s);
for (uint32_t idx = str; strstart < strend; idx++, strstart++) {
uint32_t val, h, head;
val = Z_U32_FROM_LE(zng_memread_4(strstart));
UPDATE_HASH_INT(h, val);
head = headp[h];
if (LIKELY(head != idx)) {
prevp[idx & w_mask] = (Pos)head;
headp[h] = (Pos)idx;
}
}
}
Z_FORCEINLINE static void insert_string_roll_static(deflate_state *const s, unsigned char *window, uint32_t str, uint32_t count) {
uint8_t *strstart = window + str + (STD_MIN_MATCH-1);
uint8_t *strend = strstart + count;
/* Local pointers to avoid indirection */
Pos *headp = s->head;
Pos *prevp = s->prev;
uint32_t h = s->ins_h;
const unsigned int w_mask = W_MASK(s);
for (uint32_t idx = str; strstart < strend; idx++, strstart++) {
uint32_t head;
UPDATE_HASH_ROLL(h, strstart[0]);
head = headp[h];
if (LIKELY(head != idx)) {
prevp[idx & w_mask] = (Pos)head;
headp[h] = (Pos)idx;
}
}
s->ins_h = h;
}
#endif