mirror of
https://github.com/facebook/zstd.git
synced 2025-10-15 00:02:02 -04:00
110 lines
2.8 KiB
C
110 lines
2.8 KiB
C
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
#include "ldm.h"
|
|
#include "ldm_hashtable.h"
|
|
#include "mem.h"
|
|
|
|
#define LDM_HASHLOG ((LDM_MEMORY_USAGE) - 4)
|
|
|
|
struct LDM_hashTable {
|
|
U32 size;
|
|
LDM_hashEntry *entries;
|
|
const BYTE *offsetBase;
|
|
};
|
|
|
|
LDM_hashTable *HASH_createTable(U32 size, const BYTE *offsetBase) {
|
|
LDM_hashTable *table = malloc(sizeof(LDM_hashTable));
|
|
table->size = size;
|
|
table->entries = calloc(size, sizeof(LDM_hashEntry));
|
|
table->offsetBase = offsetBase;
|
|
return table;
|
|
}
|
|
|
|
void HASH_initializeTable(LDM_hashTable *table, U32 size) {
|
|
table->size = size;
|
|
table->entries = calloc(size, sizeof(LDM_hashEntry));
|
|
}
|
|
|
|
LDM_hashEntry *getBucket(const LDM_hashTable *table, const hash_t hash) {
|
|
return table->entries + hash;
|
|
}
|
|
|
|
LDM_hashEntry *HASH_getEntryFromHash(
|
|
const LDM_hashTable *table, const hash_t hash, const U32 checksum) {
|
|
(void)checksum;
|
|
return getBucket(table, hash);
|
|
}
|
|
|
|
static int isValidMatch(const BYTE *pIn, const BYTE *pMatch,
|
|
U32 minMatchLength, U32 maxWindowSize) {
|
|
U32 lengthLeft = minMatchLength;
|
|
const BYTE *curIn = pIn;
|
|
const BYTE *curMatch = pMatch;
|
|
|
|
if (pIn - pMatch > maxWindowSize) {
|
|
return 0;
|
|
}
|
|
|
|
for (; lengthLeft >= 4; lengthLeft -= 4) {
|
|
if (MEM_read32(curIn) != MEM_read32(curMatch)) {
|
|
return 0;
|
|
}
|
|
curIn += 4;
|
|
curMatch += 4;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
LDM_hashEntry *HASH_getValidEntry(const LDM_hashTable *table,
|
|
const hash_t hash,
|
|
const U32 checksum,
|
|
const BYTE *pIn,
|
|
const BYTE *pEnd,
|
|
U32 minMatchLength,
|
|
U32 maxWindowSize,
|
|
U32 *matchLength) {
|
|
LDM_hashEntry *entry = getBucket(table, hash);
|
|
(void)checksum;
|
|
(void)pEnd;
|
|
(void)matchLength;
|
|
// TODO: Count the entire forward match length rather than check if valid.
|
|
if (isValidMatch(pIn, entry->offset + table->offsetBase,
|
|
minMatchLength, maxWindowSize)) {
|
|
|
|
return entry;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
hash_t HASH_hashU32(U32 value) {
|
|
return ((value * 2654435761U) >> (32 - LDM_HASHLOG));
|
|
}
|
|
|
|
void HASH_insert(LDM_hashTable *table,
|
|
const hash_t hash, const LDM_hashEntry entry) {
|
|
*getBucket(table, hash) = entry;
|
|
}
|
|
|
|
U32 HASH_getSize(const LDM_hashTable *table) {
|
|
return table->size;
|
|
}
|
|
|
|
void HASH_destroyTable(LDM_hashTable *table) {
|
|
free(table->entries);
|
|
free(table);
|
|
}
|
|
|
|
void HASH_outputTableOccupancy(const LDM_hashTable *hashTable) {
|
|
U32 i = 0;
|
|
U32 ctr = 0;
|
|
for (; i < HASH_getSize(hashTable); i++) {
|
|
if (getBucket(hashTable, i)->offset == 0) {
|
|
ctr++;
|
|
}
|
|
}
|
|
printf("Hash table size, empty slots, %% empty: %u, %u, %.3f\n",
|
|
HASH_getSize(hashTable), ctr,
|
|
100.0 * (double)(ctr) / (double)HASH_getSize(hashTable));
|
|
}
|