mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Integrated LZX compression code.
This commit is contained in:
parent
6e24dcddff
commit
4a0a5711b1
4
setup.py
4
setup.py
@ -374,7 +374,9 @@ if __name__ == '__main__':
|
|||||||
ext_modules = [
|
ext_modules = [
|
||||||
Extension('calibre.plugins.lzx',
|
Extension('calibre.plugins.lzx',
|
||||||
sources=['src/calibre/utils/lzx/lzxmodule.c',
|
sources=['src/calibre/utils/lzx/lzxmodule.c',
|
||||||
'src/calibre/utils/lzx/lzxd.c'],
|
'src/calibre/utils/lzx/lzxd.c',
|
||||||
|
'src/calibre/utils/lzx/lzc.c',
|
||||||
|
'src/calibre/utils/lzx/lzxc.c'],
|
||||||
include_dirs=['src/calibre/utils/lzx']),
|
include_dirs=['src/calibre/utils/lzx']),
|
||||||
|
|
||||||
Extension('calibre.plugins.msdes',
|
Extension('calibre.plugins.msdes',
|
||||||
|
@ -3,11 +3,11 @@ import sys
|
|||||||
import os
|
import os
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
from ctypes import *
|
from ctypes import *
|
||||||
|
from calibre import plugins
|
||||||
|
_lzx, LzxError = plugins['lzx']
|
||||||
|
|
||||||
__all__ = ['Compressor']
|
__all__ = ['Compressor']
|
||||||
|
|
||||||
liblzxcomp = cdll.LoadLibrary('liblzxcomp.so')
|
|
||||||
|
|
||||||
class lzx_data(Structure):
|
class lzx_data(Structure):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -25,32 +25,22 @@ class lzx_results(Structure):
|
|||||||
# lzx_at_eof_t at_eof,
|
# lzx_at_eof_t at_eof,
|
||||||
# lzx_put_bytes_t put_bytes, void *put_bytes_arg,
|
# lzx_put_bytes_t put_bytes, void *put_bytes_arg,
|
||||||
# lzx_mark_frame_t mark_frame, void *mark_frame_arg);
|
# lzx_mark_frame_t mark_frame, void *mark_frame_arg);
|
||||||
lzx_init = liblzxcomp.lzx_init
|
lzx_init_t = CFUNCTYPE(
|
||||||
lzx_init.restype = c_int
|
c_int, POINTER(POINTER(lzx_data)), c_int, lzx_get_bytes_t, c_voidp,
|
||||||
lzx_init.argtypes = [POINTER(POINTER(lzx_data)), c_int,
|
lzx_at_eof_t, lzx_put_bytes_t, c_voidp, lzx_mark_frame_t, c_voidp)
|
||||||
lzx_get_bytes_t, c_voidp,
|
lzx_init = lzx_init_t(_lzx._lzxc_init)
|
||||||
lzx_at_eof_t,
|
|
||||||
lzx_put_bytes_t, c_voidp,
|
|
||||||
lzx_mark_frame_t, c_voidp]
|
|
||||||
|
|
||||||
# void lzx_reset(lzx_data *lzxd);
|
# void lzx_reset(lzx_data *lzxd);
|
||||||
lzx_reset = liblzxcomp.lzx_reset
|
lzx_reset_t = CFUNCTYPE(None, POINTER(lzx_data))
|
||||||
lzx_reset.restype = None
|
lzx_reset = lzx_reset_t(_lzx._lzxc_reset)
|
||||||
lzx_reset.argtypes = [POINTER(lzx_data)]
|
|
||||||
|
|
||||||
# int lzx_compress_block(lzx_data *lzxd, int block_size, int subdivide);
|
# int lzx_compress_block(lzx_data *lzxd, int block_size, int subdivide);
|
||||||
lzx_compress_block = liblzxcomp.lzx_compress_block
|
lzx_compress_block_t = CFUNCTYPE(c_int, POINTER(lzx_data), c_int, c_int)
|
||||||
lzx_compress_block.restype = c_int
|
lzx_compress_block = lzx_compress_block_t(_lzx._lzxc_compress_block)
|
||||||
lzx_compress_block.argtypes = [POINTER(lzx_data), c_int, c_int]
|
|
||||||
|
|
||||||
# int lzx_finish(struct lzx_data *lzxd, struct lzx_results *lzxr);
|
# int lzx_finish(struct lzx_data *lzxd, struct lzx_results *lzxr);
|
||||||
lzx_finish = liblzxcomp.lzx_finish
|
lzx_finish_t = CFUNCTYPE(c_int, POINTER(lzx_data), POINTER(lzx_results))
|
||||||
lzx_finish.restype = c_int
|
lzx_finish = lzx_finish_t(_lzx._lzxc_finish)
|
||||||
lzx_finish.argtypes = [POINTER(lzx_data), POINTER(lzx_results)]
|
|
||||||
|
|
||||||
|
|
||||||
class LzxError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Compressor(object):
|
class Compressor(object):
|
||||||
|
389
src/calibre/utils/lzx/lzc.c
Normal file
389
src/calibre/utils/lzx/lzc.c
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
/*
|
||||||
|
File lz_nonslide.c, part of lzxcomp library
|
||||||
|
Copyright (C) 2002 Matthew T. Russotto
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; version 2.1 only
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Document here
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <string.h>
|
||||||
|
#ifdef DEBUG_PERF
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#endif
|
||||||
|
#include <lzc.h>
|
||||||
|
|
||||||
|
#define MAX_MATCH 253
|
||||||
|
#define MIN_MATCH 2
|
||||||
|
|
||||||
|
void lz_init(lz_info *lzi, int wsize, int max_dist,
|
||||||
|
int max_match, int min_match,
|
||||||
|
int frame_size,
|
||||||
|
get_chars_t get_chars,
|
||||||
|
output_match_t output_match,
|
||||||
|
output_literal_t output_literal, void *user_data)
|
||||||
|
{
|
||||||
|
/* the reason for the separate max_dist value is LZX can't reach the
|
||||||
|
first three characters in its nominal window. But using a smaller
|
||||||
|
window results in inefficiency when dealing with reset intervals
|
||||||
|
which are the length of the nominal window */
|
||||||
|
|
||||||
|
lzi->wsize = wsize;
|
||||||
|
if (max_match > wsize)
|
||||||
|
lzi->max_match = wsize;
|
||||||
|
else
|
||||||
|
lzi->max_match = max_match;
|
||||||
|
|
||||||
|
lzi->min_match = min_match;
|
||||||
|
if (lzi->min_match < 3) lzi->min_match = 3;
|
||||||
|
|
||||||
|
lzi->max_dist = max_dist;
|
||||||
|
lzi->block_buf_size = wsize + lzi->max_dist;
|
||||||
|
lzi->block_buf = malloc(lzi->block_buf_size);
|
||||||
|
lzi->block_bufe = lzi->block_buf + lzi->block_buf_size;
|
||||||
|
assert(lzi->block_buf != NULL);
|
||||||
|
|
||||||
|
lzi->cur_loc = 0;
|
||||||
|
lzi->block_loc = 0;
|
||||||
|
lzi->chars_in_buf = 0;
|
||||||
|
lzi->eofcount = 0;
|
||||||
|
lzi->get_chars = get_chars;
|
||||||
|
lzi->output_match = output_match;
|
||||||
|
lzi->output_literal = output_literal;
|
||||||
|
lzi->user_data = user_data;
|
||||||
|
lzi->frame_size = frame_size;
|
||||||
|
lzi->lentab = calloc(lzi->block_buf_size + 1, sizeof(int));
|
||||||
|
lzi->prevtab = calloc(lzi->block_buf_size + 1, sizeof(u_char *));
|
||||||
|
lzi->analysis_valid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lz_release(lz_info *lzi)
|
||||||
|
{
|
||||||
|
free(lzi->block_buf);
|
||||||
|
free(lzi->lentab);
|
||||||
|
free(lzi->prevtab);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lz_reset(lz_info *lzi)
|
||||||
|
{
|
||||||
|
int residual = lzi->chars_in_buf - lzi->block_loc;
|
||||||
|
memmove(lzi->block_buf, lzi->block_buf + lzi->block_loc, residual);
|
||||||
|
lzi->chars_in_buf = residual;
|
||||||
|
lzi->block_loc = 0;
|
||||||
|
lzi->analysis_valid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef LZNONSLIDE_MAIN
|
||||||
|
typedef struct lz_user_data
|
||||||
|
{
|
||||||
|
FILE *infile;
|
||||||
|
FILE *outfile;
|
||||||
|
int R0, R1, R2;
|
||||||
|
} lz_user_data;
|
||||||
|
|
||||||
|
int tmp_get_chars(lz_info *lzi, int n, u_char *buf)
|
||||||
|
{
|
||||||
|
lz_user_data *lzud = (lz_user_data *)lzi->user_data;
|
||||||
|
return fread(buf, 1, n, lzud->infile);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tmp_output_match(lz_info *lzi, int match_pos, int match_len)
|
||||||
|
{
|
||||||
|
lz_user_data *lzud = (lz_user_data *)lzi->user_data;
|
||||||
|
int mod_match_loc;
|
||||||
|
|
||||||
|
mod_match_loc = match_pos;
|
||||||
|
|
||||||
|
fprintf(lzud->outfile, "(%d, %d)(%d)\n", match_pos, match_len, mod_match_loc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tmp_output_literal(lz_info *lzi, u_char ch)
|
||||||
|
{
|
||||||
|
lz_user_data *lzud = (lz_user_data *)lzi->user_data;
|
||||||
|
fprintf(lzud->outfile, "'%c'", ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int wsize = atoi(argv[1]);
|
||||||
|
lz_info lzi;
|
||||||
|
lz_user_data lzu = {stdin, stdout, 1, 1, 1};
|
||||||
|
|
||||||
|
lz_init(&lzi, wsize, wsize, MAX_MATCH, MIN_MATCH, 8192, tmp_get_chars, tmp_output_match, tmp_output_literal,&lzu);
|
||||||
|
lz_compress(&lzi);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__inline__ int lz_left_to_process(lz_info *lzi)
|
||||||
|
{
|
||||||
|
return lzi->chars_in_buf - lzi->block_loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fill_blockbuf(lz_info *lzi, int maxchars)
|
||||||
|
{
|
||||||
|
int toread;
|
||||||
|
u_char *readhere;
|
||||||
|
int nread;
|
||||||
|
|
||||||
|
if (lzi->eofcount) return;
|
||||||
|
maxchars -= lz_left_to_process(lzi);
|
||||||
|
toread = lzi->block_buf_size - lzi->chars_in_buf;
|
||||||
|
if (toread > maxchars) toread = maxchars;
|
||||||
|
readhere = lzi->block_buf + lzi->chars_in_buf;
|
||||||
|
nread = lzi->get_chars(lzi, toread, readhere);
|
||||||
|
lzi->chars_in_buf += nread;
|
||||||
|
if (nread != toread)
|
||||||
|
lzi->eofcount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lz_analyze_block(lz_info *lzi)
|
||||||
|
{
|
||||||
|
int *lentab, *lenp;
|
||||||
|
u_char **prevtab, **prevp;
|
||||||
|
u_char *bbp, *bbe;
|
||||||
|
u_char *chartab[256];
|
||||||
|
u_char *cursor;
|
||||||
|
int prevlen;
|
||||||
|
int ch;
|
||||||
|
int maxlen;
|
||||||
|
long wasinc;
|
||||||
|
int max_dist = lzi->max_dist;
|
||||||
|
#ifdef DEBUG_ANALYZE_BLOCK
|
||||||
|
static short n = 0;
|
||||||
|
#endif
|
||||||
|
#ifdef DEBUG_PERF
|
||||||
|
struct rusage innerloop;
|
||||||
|
struct timeval innertime, tmptime;
|
||||||
|
struct rusage outerloop;
|
||||||
|
struct timeval outertime;
|
||||||
|
struct rusage initialloop;
|
||||||
|
struct timeval initialtime;
|
||||||
|
struct rusage totalloop;
|
||||||
|
struct timeval totaltime;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG_ANALYZE_BLOCK
|
||||||
|
fprintf(stderr, "Analyzing block %d, cur_loc = %06x\n", n, lzi->cur_loc);
|
||||||
|
#endif
|
||||||
|
memset(chartab, 0, sizeof(chartab));
|
||||||
|
prevtab = prevp = lzi->prevtab;
|
||||||
|
lentab = lenp = lzi->lentab;
|
||||||
|
memset(prevtab, 0, sizeof(*prevtab) * lzi->chars_in_buf);
|
||||||
|
memset(lentab, 0, sizeof(*lentab) * lzi->chars_in_buf);
|
||||||
|
#ifdef DEBUG_PERF
|
||||||
|
memset(&innertime, 0, sizeof(innertime));
|
||||||
|
memset(&outertime, 0, sizeof(outertime));
|
||||||
|
getrusage(RUSAGE_SELF, &initialloop);
|
||||||
|
totalloop = initialloop;
|
||||||
|
#endif
|
||||||
|
bbp = lzi->block_buf;
|
||||||
|
bbe = bbp + lzi->chars_in_buf;
|
||||||
|
while (bbp < bbe) {
|
||||||
|
if (chartab[ch = *bbp]) {
|
||||||
|
*prevp = chartab[ch];
|
||||||
|
*lenp = 1;
|
||||||
|
}
|
||||||
|
chartab[ch] = bbp;
|
||||||
|
bbp++;
|
||||||
|
prevp++;
|
||||||
|
lenp++;
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_PERF
|
||||||
|
initialtime = initialloop.ru_utime;
|
||||||
|
getrusage(RUSAGE_SELF, &initialloop);
|
||||||
|
timersub(&initialloop.ru_utime, &initialtime, &initialtime);
|
||||||
|
#endif
|
||||||
|
wasinc = 1;
|
||||||
|
for (maxlen = 1; wasinc && (maxlen < lzi->max_match); maxlen++) {
|
||||||
|
#ifdef DEBUG_PERF
|
||||||
|
getrusage(RUSAGE_SELF, &outerloop);
|
||||||
|
#endif
|
||||||
|
bbp = bbe - maxlen - 1;
|
||||||
|
lenp = lentab + lzi->chars_in_buf - maxlen - 1;
|
||||||
|
prevp = prevtab + lzi->chars_in_buf - maxlen - 1;
|
||||||
|
wasinc = 0;
|
||||||
|
while (bbp > lzi->block_buf) {
|
||||||
|
if (*lenp == maxlen) {
|
||||||
|
#ifdef DEBUG_PERF
|
||||||
|
getrusage(RUSAGE_SELF, &innerloop);
|
||||||
|
#endif
|
||||||
|
ch = bbp[maxlen];
|
||||||
|
cursor = *prevp;
|
||||||
|
while(cursor && ((bbp - cursor) <= max_dist)) {
|
||||||
|
prevlen = *(cursor - lzi->block_buf + lentab);
|
||||||
|
if (cursor[maxlen] == ch) {
|
||||||
|
*prevp = cursor;
|
||||||
|
(*lenp)++;
|
||||||
|
wasinc++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (prevlen != maxlen) break;
|
||||||
|
cursor = *(cursor - lzi->block_buf + prevtab);
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_PERF
|
||||||
|
tmptime = innerloop.ru_utime;
|
||||||
|
getrusage(RUSAGE_SELF, &innerloop);
|
||||||
|
timersub(&innerloop.ru_utime, &tmptime, &tmptime);
|
||||||
|
timeradd(&tmptime, &innertime, &innertime);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
bbp--;
|
||||||
|
prevp--;
|
||||||
|
lenp--;
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_PERF
|
||||||
|
tmptime = outerloop.ru_utime;
|
||||||
|
getrusage(RUSAGE_SELF, &outerloop);
|
||||||
|
timersub(&outerloop.ru_utime, &tmptime, &tmptime);
|
||||||
|
timeradd(&tmptime, &outertime, &outertime);
|
||||||
|
#endif
|
||||||
|
// fprintf(stderr, "maxlen = %d, wasinc = %ld\n", maxlen, wasinc);
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_PERF
|
||||||
|
totaltime = totalloop.ru_utime;
|
||||||
|
getrusage(RUSAGE_SELF, &totalloop);
|
||||||
|
timersub(&totalloop.ru_utime, &totaltime, &totaltime);
|
||||||
|
fprintf(stderr, "Time spend in initial loop = %f\n", initialtime.tv_sec + initialtime.tv_usec/(double)1E6);
|
||||||
|
fprintf(stderr, "Time spend in outer loop = %f\n", outertime.tv_sec + outertime.tv_usec/(double)1E6);
|
||||||
|
fprintf(stderr, "Time spend in inner loop = %f\n", innertime.tv_sec + innertime.tv_usec/(double)1E6);
|
||||||
|
fprintf(stderr, "Time spend in all loops = %f\n", totaltime.tv_sec + totaltime.tv_usec/(double)1E6);
|
||||||
|
#endif
|
||||||
|
lzi->analysis_valid = 1;
|
||||||
|
#ifdef DEBUG_ANALYZE_BLOCK
|
||||||
|
fprintf(stderr, "Done analyzing block %d, cur_loc = %06x\n", n++, lzi->cur_loc);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void lz_stop_compressing(lz_info *lzi)
|
||||||
|
{
|
||||||
|
lzi->stop = 1;
|
||||||
|
/* fprintf(stderr, "Stopping...\n");*/
|
||||||
|
}
|
||||||
|
|
||||||
|
int lz_compress(lz_info *lzi, int nchars)
|
||||||
|
{
|
||||||
|
|
||||||
|
u_char *bbp, *bbe;
|
||||||
|
int *lentab, *lenp;
|
||||||
|
u_char **prevtab, **prevp;
|
||||||
|
int len;
|
||||||
|
int holdback;
|
||||||
|
short trimmed;
|
||||||
|
|
||||||
|
lzi->stop = 0;
|
||||||
|
while ((lz_left_to_process(lzi) || !lzi->eofcount) && !lzi->stop && nchars > 0) {
|
||||||
|
#if 1
|
||||||
|
if (!lzi->analysis_valid ||
|
||||||
|
(!lzi->eofcount &&
|
||||||
|
((lzi->chars_in_buf- lzi->block_loc) < nchars))) {
|
||||||
|
int residual = lzi->chars_in_buf - lzi->block_loc;
|
||||||
|
int bytes_to_move = lzi->max_dist + residual;
|
||||||
|
if (bytes_to_move > lzi->chars_in_buf)
|
||||||
|
bytes_to_move = lzi->chars_in_buf;
|
||||||
|
#ifdef DEBUG_ANALYZE_BLOCK
|
||||||
|
fprintf(stderr, "Moving %06x, chars_in_buf %06x, residual = %06x, nchars= %06x block_loc = %06x\n", bytes_to_move, lzi->chars_in_buf, residual, nchars, lzi->block_loc);
|
||||||
|
#endif
|
||||||
|
memmove(lzi->block_buf, lzi->block_buf + lzi->chars_in_buf - bytes_to_move,
|
||||||
|
bytes_to_move);
|
||||||
|
|
||||||
|
lzi->block_loc = bytes_to_move - residual;
|
||||||
|
lzi->chars_in_buf = bytes_to_move;
|
||||||
|
#ifdef DEBUG_ANALYZE_BLOCK
|
||||||
|
fprintf(stderr, "New chars_in_buf %06x, new block_loc = %06x, eof = %1d\n", lzi->chars_in_buf, lzi->block_loc, lzi->eofcount);
|
||||||
|
#endif
|
||||||
|
fill_blockbuf(lzi, nchars);
|
||||||
|
#ifdef DEBUG_ANALYZE_BLOCK
|
||||||
|
fprintf(stderr, "Really new chars_in_buf %06x, new block_loc = %06x, eof = %1d\n", lzi->chars_in_buf, lzi->block_loc, lzi->eofcount);
|
||||||
|
#endif
|
||||||
|
lz_analyze_block(lzi);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (!lzi->analysis_valid ||
|
||||||
|
(lzi->block_loc - lzi->chars_in_buf) == 0) {
|
||||||
|
lzi->block_loc = 0;
|
||||||
|
lzi->chars_in_buf = 0;
|
||||||
|
fill_blockbuf(lzi, nchars);
|
||||||
|
lz_analyze_block(lzi);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
prevtab = prevp = lzi->prevtab + lzi->block_loc;
|
||||||
|
lentab = lenp = lzi->lentab + lzi->block_loc;
|
||||||
|
bbp = lzi->block_buf + lzi->block_loc;
|
||||||
|
holdback = lzi->max_match;
|
||||||
|
if (lzi->eofcount) holdback = 0;
|
||||||
|
if (lzi->chars_in_buf < (nchars + lzi->block_loc))
|
||||||
|
bbe = lzi->block_buf + lzi->chars_in_buf - holdback;
|
||||||
|
else
|
||||||
|
bbe = bbp + nchars;
|
||||||
|
while ((bbp < bbe) && (!lzi->stop)) {
|
||||||
|
trimmed = 0;
|
||||||
|
len = *lenp;
|
||||||
|
if (lzi->frame_size && (len > (lzi->frame_size - lzi->cur_loc % lzi->frame_size))) {
|
||||||
|
#ifdef DEBUG_TRIMMING
|
||||||
|
fprintf(stderr, "Trim for framing: %06x %d %d\n", lzi->cur_loc,len, (lzi->frame_size - lzi->cur_loc % lzi->frame_size));
|
||||||
|
#endif
|
||||||
|
trimmed = 1;
|
||||||
|
len = (lzi->frame_size - lzi->cur_loc % lzi->frame_size);
|
||||||
|
}
|
||||||
|
if (len > nchars) {
|
||||||
|
#ifdef DEBUG_TRIMMING
|
||||||
|
fprintf(stderr, "Trim for blocking: %06x %d %d\n", lzi->cur_loc,len, nchars);
|
||||||
|
#endif
|
||||||
|
trimmed = 1;
|
||||||
|
len = nchars;
|
||||||
|
}
|
||||||
|
if (len >= lzi->min_match) {
|
||||||
|
#ifdef LAZY
|
||||||
|
if ((bbp < bbe -1) && !trimmed &&
|
||||||
|
((lenp[1] > (len + 1)) /* || ((lenp[1] == len) && (prevp[1] > prevp[0])) */)) {
|
||||||
|
len = 1;
|
||||||
|
/* this is the lazy eval case */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if (lzi->output_match(lzi, (*prevp - lzi->block_buf) - lzi->block_loc,
|
||||||
|
len) < 0) {
|
||||||
|
// fprintf(stderr, "Match rejected: %06x %d\n", lzi->cur_loc, len);
|
||||||
|
len = 1; /* match rejected */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
len = 1;
|
||||||
|
|
||||||
|
if (len < lzi->min_match) {
|
||||||
|
assert(len == 1);
|
||||||
|
lzi->output_literal(lzi, *bbp);
|
||||||
|
}
|
||||||
|
// fprintf(stderr, "len = %3d, *lenp = %3d, cur_loc = %06x, block_loc = %06x\n", len, *lenp, lzi->cur_loc, lzi->block_loc);
|
||||||
|
bbp += len;
|
||||||
|
prevp += len;
|
||||||
|
lenp += len;
|
||||||
|
lzi->cur_loc += len;
|
||||||
|
lzi->block_loc += len;
|
||||||
|
assert(nchars >= len);
|
||||||
|
nchars -= len;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
60
src/calibre/utils/lzx/lzc.h
Normal file
60
src/calibre/utils/lzx/lzc.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
File lz_nonslide.h, part of lzxcomp library
|
||||||
|
Copyright (C) 2002 Matthew T. Russotto
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; version 2.1 only
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
typedef struct lz_info lz_info;
|
||||||
|
typedef int (*get_chars_t)(lz_info *lzi, int n, u_char *buf);
|
||||||
|
typedef int (*output_match_t)(lz_info *lzi, int match_pos, int match_len);
|
||||||
|
typedef void (*output_literal_t)(lz_info *lzi, u_char ch);
|
||||||
|
|
||||||
|
struct lz_info
|
||||||
|
{
|
||||||
|
int wsize; /* window size in bytes */
|
||||||
|
int max_match; /* size of longest match in bytes */
|
||||||
|
int min_match;
|
||||||
|
u_char *block_buf;
|
||||||
|
u_char *block_bufe;
|
||||||
|
int block_buf_size;
|
||||||
|
int chars_in_buf;
|
||||||
|
int cur_loc; /* location within stream */
|
||||||
|
int block_loc;
|
||||||
|
int frame_size;
|
||||||
|
int max_dist;
|
||||||
|
u_char **prevtab;
|
||||||
|
int *lentab;
|
||||||
|
short eofcount;
|
||||||
|
short stop;
|
||||||
|
short analysis_valid;
|
||||||
|
|
||||||
|
get_chars_t get_chars;
|
||||||
|
output_match_t output_match;
|
||||||
|
output_literal_t output_literal;
|
||||||
|
void *user_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
void lz_init(lz_info *lzi, int wsize, int max_dist,
|
||||||
|
int max_match, int min_match,
|
||||||
|
int frame_size,
|
||||||
|
get_chars_t get_chars,
|
||||||
|
output_match_t output_match,
|
||||||
|
output_literal_t output_literal, void *user_data);
|
||||||
|
|
||||||
|
void lz_release(lz_info *lzi);
|
||||||
|
|
||||||
|
void lz_reset(lz_info *lzi);
|
||||||
|
void lz_stop_compressing(lz_info *lzi);
|
||||||
|
int lz_left_to_process(lz_info *lzi); /* returns # chars read in but unprocessed */
|
||||||
|
int lz_compress(lz_info *lzi, int nchars);
|
1259
src/calibre/utils/lzx/lzxc.c
Normal file
1259
src/calibre/utils/lzx/lzxc.c
Normal file
File diff suppressed because it is too large
Load Diff
57
src/calibre/utils/lzx/lzxc.h
Normal file
57
src/calibre/utils/lzx/lzxc.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
File lzx_compress.h, part of lzxcomp library
|
||||||
|
Copyright (C) 2002 Matthew T. Russotto
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; version 2.1 only
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if BYTE_ORDER == BIG_ENDIAN
|
||||||
|
# define LZX_BIG_ENDIAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* the names of these constants are specific to this library */
|
||||||
|
#define LZX_MAX_CODE_LENGTH 16
|
||||||
|
#define LZX_FRAME_SIZE 32768
|
||||||
|
#define LZX_PRETREE_SIZE 20
|
||||||
|
#define LZX_ALIGNED_BITS 3
|
||||||
|
#define LZX_ALIGNED_SIZE 8
|
||||||
|
|
||||||
|
#define LZX_VERBATIM_BLOCK 1
|
||||||
|
#define LZX_ALIGNED_OFFSET_BLOCK 2
|
||||||
|
|
||||||
|
typedef struct lzx_data lzx_data;
|
||||||
|
typedef int (*lzx_get_bytes_t)(void *arg, int n, void *buf);
|
||||||
|
typedef int (*lzx_put_bytes_t)(void *arg, int n, void *buf);
|
||||||
|
typedef void (*lzx_mark_frame_t)(void *arg, uint32_t uncomp, uint32_t comp);
|
||||||
|
typedef int (*lzx_at_eof_t)(void *arg);
|
||||||
|
|
||||||
|
typedef struct lzx_results
|
||||||
|
{
|
||||||
|
/* add more here? Error codes, # blocks, # frames, etc? */
|
||||||
|
long len_compressed_output;
|
||||||
|
long len_uncompressed_input;
|
||||||
|
} lzx_results;
|
||||||
|
|
||||||
|
int lzx_init(struct lzx_data **lzxdp, int wsize_code,
|
||||||
|
lzx_get_bytes_t get_bytes, void *get_bytes_arg,
|
||||||
|
lzx_at_eof_t at_eof,
|
||||||
|
lzx_put_bytes_t put_bytes, void *put_bytes_arg,
|
||||||
|
lzx_mark_frame_t mark_frame, void *mark_frame_arg);
|
||||||
|
|
||||||
|
void lzx_reset(lzx_data *lzxd);
|
||||||
|
|
||||||
|
int lzx_compress_block(lzx_data *lzxd, int block_size, int subdivide);
|
||||||
|
|
||||||
|
int lzx_finish(struct lzx_data *lzxd, struct lzx_results *lzxr);
|
||||||
|
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
#include <mspack.h>
|
#include <mspack.h>
|
||||||
#include <system.h>
|
#include <system.h>
|
||||||
#include <lzx.h>
|
#include <lzxd.h>
|
||||||
|
|
||||||
/* Microsoft's LZX document and their implementation of the
|
/* Microsoft's LZX document and their implementation of the
|
||||||
* com.ms.util.cab Java package do not concur.
|
* com.ms.util.cab Java package do not concur.
|
||||||
|
@ -4,14 +4,15 @@
|
|||||||
* Python module C glue code.
|
* Python module C glue code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
|
|
||||||
#include <mspack.h>
|
#include <mspack.h>
|
||||||
#include <lzx.h>
|
#include <lzxd.h>
|
||||||
|
#include <lzxc.h>
|
||||||
|
|
||||||
static char lzx_doc[] =
|
static char lzx_doc[] =
|
||||||
"Provide basic LZX decompression using the code from libmspack.";
|
"Provide basic LZX compression and decompression using the code from\n"
|
||||||
|
"liblzxcomp and libmspack respectively.";
|
||||||
|
|
||||||
static PyObject *LzxError = NULL;
|
static PyObject *LzxError = NULL;
|
||||||
|
|
||||||
@ -214,6 +215,15 @@ initlzx(void)
|
|||||||
LzxError = PyErr_NewException("lzx.LzxError", NULL, NULL);
|
LzxError = PyErr_NewException("lzx.LzxError", NULL, NULL);
|
||||||
Py_INCREF(LzxError);
|
Py_INCREF(LzxError);
|
||||||
PyModule_AddObject(m, "LzxError", LzxError);
|
PyModule_AddObject(m, "LzxError", LzxError);
|
||||||
|
|
||||||
|
PyModule_AddObject(m, "_lzxc_init",
|
||||||
|
Py_BuildValue("k", (unsigned long)lzx_init));
|
||||||
|
PyModule_AddObject(m, "_lzxc_reset",
|
||||||
|
Py_BuildValue("k", (unsigned long)lzx_reset));
|
||||||
|
PyModule_AddObject(m, "_lzxc_compress_block",
|
||||||
|
Py_BuildValue("k", (unsigned long)lzx_compress_block));
|
||||||
|
PyModule_AddObject(m, "_lzxc_finish",
|
||||||
|
Py_BuildValue("k", (unsigned long)lzx_finish));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user