genlz77: Generic LZ77 hash compressor.
This commit is contained in:
parent
2eb3c5275d
commit
9d639d6dcc
2 changed files with 119 additions and 0 deletions
116
src/genlz77.c
Normal file
116
src/genlz77.c
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* genlz77 - Generic LZ77 compressor
|
||||
*
|
||||
* Copyright (c) 2014 by Paul Sokolovsky
|
||||
*
|
||||
* This software is provided 'as-is', without any express
|
||||
* or implied warranty. In no event will the authors be
|
||||
* held liable for any damages arising from the use of
|
||||
* this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software
|
||||
* for any purpose, including commercial applications,
|
||||
* and to alter it and redistribute it freely, subject to
|
||||
* the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be
|
||||
* misrepresented; you must not claim that you
|
||||
* wrote the original software. If you use this
|
||||
* software in a product, an acknowledgment in
|
||||
* the product documentation would be appreciated
|
||||
* but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked
|
||||
* as such, and must not be misrepresented as
|
||||
* being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from
|
||||
* any source distribution.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "defl_static.h"
|
||||
|
||||
#define HASH_BITS 12
|
||||
#define HASH_SIZE (1<<HASH_BITS)
|
||||
|
||||
/* Minimum and maximum length of matches to look for, inclusive */
|
||||
#define MIN_MATCH 3
|
||||
#define MAX_MATCH 258
|
||||
/* Max offset of the match to look for, inclusive */
|
||||
#define MAX_OFFSET 32768
|
||||
|
||||
/* Hash function can be defined as macro or as inline function */
|
||||
|
||||
/*#define HASH(p) (p[0] + p[1] + p[2])*/
|
||||
|
||||
/* This is hash function from liblzf */
|
||||
static inline int HASH(const uint8_t *p) {
|
||||
int v = (p[0] << 16) | (p[1] << 8) | p[2];
|
||||
int hash = ((v >> (3*8 - HASH_BITS)) - v) & (HASH_SIZE - 1);
|
||||
return hash;
|
||||
}
|
||||
|
||||
#ifdef DUMP_LZTXT
|
||||
|
||||
/* Counter for approximate compressed length in LZTXT mode. */
|
||||
/* Literal is counted as 1, copy as 2 bytes. */
|
||||
unsigned approx_compressed_len;
|
||||
|
||||
void literal(void *data, uint8_t val)
|
||||
{
|
||||
printf("L%02x # %c\n", val, (val >= 0x20 && val <= 0x7e) ? val : '?');
|
||||
approx_compressed_len++;
|
||||
}
|
||||
|
||||
void copy(void *data, unsigned offset, unsigned len)
|
||||
{
|
||||
printf("C-%u,%u\n", offset, len);
|
||||
approx_compressed_len += 2;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline void literal(void *data, uint8_t val)
|
||||
{
|
||||
zlib_literal(data, val);
|
||||
}
|
||||
|
||||
static inline void copy(void *data, unsigned offset, unsigned len)
|
||||
{
|
||||
zlib_match(data, offset, len);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void tinf_compress(void *data, const uint8_t *src, unsigned slen)
|
||||
{
|
||||
const uint8_t *hashtable[HASH_SIZE] = {0};
|
||||
|
||||
const uint8_t *top = src + slen - MIN_MATCH;
|
||||
while (src < top) {
|
||||
int h = HASH(src);
|
||||
const uint8_t **bucket = &hashtable[h & (HASH_SIZE - 1)];
|
||||
const uint8_t *subs = *bucket;
|
||||
*bucket = src;
|
||||
if (subs && src > subs && (src - subs) <= MAX_OFFSET && !memcmp(src, subs, MIN_MATCH)) {
|
||||
src += MIN_MATCH;
|
||||
const uint8_t *m = subs + MIN_MATCH;
|
||||
int len = MIN_MATCH;
|
||||
while (*src == *m && len < MAX_MATCH) {
|
||||
src++; m++; len++;
|
||||
}
|
||||
copy(data, src - len - subs, len);
|
||||
} else {
|
||||
literal(data, *src++);
|
||||
}
|
||||
}
|
||||
// Process buffer tail, which is less than MIN_MATCH
|
||||
// (and so it doesn't make sense to look for matches there)
|
||||
top += MIN_MATCH;
|
||||
while (src < top) {
|
||||
literal(data, *src++);
|
||||
}
|
||||
}
|
||||
3
src/genlz77.h
Normal file
3
src/genlz77.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#include <stdint.h>
|
||||
|
||||
void tinf_compress(void *data, const uint8_t *src, unsigned slen);
|
||||
Loading…
Reference in a new issue