Adding upstream version 1.7~pre1.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e79cdc32de
commit
115e463032
27 changed files with 1157 additions and 1534 deletions
|
@ -1,3 +1,10 @@
|
|||
2015-02-24 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
||||
* Version 1.7-pre1 released.
|
||||
* Ported fast encoder and option '-0' from lzip.
|
||||
* If open-->write-->finish, produce same dictionary size as lzip.
|
||||
* Makefile.in: Added new targets 'install*-compress'.
|
||||
|
||||
2014-08-27 Antonio Diaz Diaz <antonio@gnu.org>
|
||||
|
||||
* Version 1.6 released.
|
||||
|
@ -146,7 +153,7 @@
|
|||
* Version 0.1 released.
|
||||
|
||||
|
||||
Copyright (C) 2009-2014 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2015 Antonio Diaz Diaz.
|
||||
|
||||
This file is a collection of facts, and thus it is not copyrightable,
|
||||
but just in case, you have unlimited permission to copy, distribute and
|
||||
|
|
6
INSTALL
6
INSTALL
|
@ -32,6 +32,10 @@ the main archive.
|
|||
5. Type 'make install' to install the library and any data files and
|
||||
documentation. (You might have to run ldconfig also).
|
||||
|
||||
Or type 'make install-compress', which additionally compresses the
|
||||
info manual and the man page after installation. (Installing
|
||||
compressed docs may become the default in the future).
|
||||
|
||||
You can install only the library, the info manual or the man page by
|
||||
typing 'make install-bin', 'make install-info' or 'make install-man'
|
||||
respectively.
|
||||
|
@ -58,7 +62,7 @@ After running 'configure', you can run 'make' and 'make install' as
|
|||
explained above.
|
||||
|
||||
|
||||
Copyright (C) 2009-2014 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2015 Antonio Diaz Diaz.
|
||||
|
||||
This file is free documentation: you have unlimited permission to copy,
|
||||
distribute and modify it.
|
||||
|
|
33
Makefile.in
33
Makefile.in
|
@ -11,7 +11,9 @@ SHELL = /bin/sh
|
|||
objs = carg_parser.o main.o
|
||||
|
||||
|
||||
.PHONY : all install install-bin install-info install-man install-strip \
|
||||
.PHONY : all install install-bin install-info install-man \
|
||||
install-strip install-compress install-strip-compress \
|
||||
install-bin-strip install-info-compress install-man-compress \
|
||||
install-as-lzip uninstall uninstall-bin uninstall-info uninstall-man \
|
||||
doc info man check dist clean distclean
|
||||
|
||||
|
@ -29,9 +31,6 @@ $(progname) : $(objs) lib$(libname).a
|
|||
$(progname)_shared : $(objs) lib$(libname).so.$(pkgversion)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(objs) lib$(libname).so.$(pkgversion)
|
||||
|
||||
$(progname)_profiled : $(objs) lib$(libname).a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -pg -o $@ $(objs) lib$(libname).a
|
||||
|
||||
bbexample : bbexample.o lib$(libname).a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ bbexample.o lib$(libname).a
|
||||
|
||||
|
@ -47,7 +46,8 @@ lzlib_sh.o : lzlib.c
|
|||
%.o : %.c
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
|
||||
|
||||
lzdeps = lzlib.h lzip.h cbuffer.c decoder.h decoder.c encoder.h encoder.c
|
||||
lzdeps = lzlib.h lzip.h cbuffer.c decoder.h decoder.c encoder_base.h \
|
||||
encoder_base.c encoder.h encoder.c fast_encoder.h fast_encoder.c
|
||||
|
||||
$(objs) : Makefile
|
||||
carg_parser.o : carg_parser.h
|
||||
|
@ -77,6 +77,9 @@ check : $(progname) bbexample lzcheck
|
|||
@$(VPATH)/testsuite/check.sh $(VPATH)/testsuite $(pkgversion)
|
||||
|
||||
install : install-bin install-info
|
||||
install-strip : install-bin-strip install-info
|
||||
install-compress : install-bin install-info-compress
|
||||
install-strip-compress : install-bin-strip install-info-compress
|
||||
|
||||
install-bin : all
|
||||
if [ ! -d "$(DESTDIR)$(includedir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(includedir)" ; fi
|
||||
|
@ -99,17 +102,25 @@ install-bin : all
|
|||
[ -x "$(LDCONFIG)" ] ; then "$(LDCONFIG)" -n "$(DESTDIR)$(libdir)" || true ; fi ; \
|
||||
fi
|
||||
|
||||
install-bin-strip : all
|
||||
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install-bin
|
||||
|
||||
install-info :
|
||||
if [ ! -d "$(DESTDIR)$(infodir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(infodir)" ; fi
|
||||
-rm -f "$(DESTDIR)$(infodir)/$(pkgname).info"*
|
||||
$(INSTALL_DATA) $(VPATH)/doc/$(pkgname).info "$(DESTDIR)$(infodir)/$(pkgname).info"
|
||||
-install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$(pkgname).info"
|
||||
|
||||
install-info-compress : install-info
|
||||
lzip -v -9 "$(DESTDIR)$(infodir)/$(pkgname).info"
|
||||
|
||||
install-man :
|
||||
if [ ! -d "$(DESTDIR)$(mandir)/man1" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1" ; fi
|
||||
-rm -f "$(DESTDIR)$(mandir)/man1/$(progname).1"*
|
||||
$(INSTALL_DATA) $(VPATH)/doc/$(progname).1 "$(DESTDIR)$(mandir)/man1/$(progname).1"
|
||||
|
||||
install-strip : all
|
||||
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install
|
||||
install-man-compress : install-man
|
||||
lzip -v -9 "$(DESTDIR)$(mandir)/man1/$(progname).1"
|
||||
|
||||
install-as-lzip : install install-man
|
||||
if [ ! -d "$(DESTDIR)$(bindir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(bindir)" ; fi
|
||||
|
@ -117,7 +128,7 @@ install-as-lzip : install install-man
|
|||
-rm -f "$(DESTDIR)$(bindir)/lzip"
|
||||
cd "$(DESTDIR)$(bindir)" && ln -s $(progname) lzip
|
||||
|
||||
uninstall : uninstall-bin uninstall-info uninstall-man
|
||||
uninstall : uninstall-man uninstall-info uninstall-bin
|
||||
|
||||
uninstall-bin :
|
||||
-rm -f "$(DESTDIR)$(bindir)/$(progname)"
|
||||
|
@ -129,10 +140,10 @@ uninstall-bin :
|
|||
|
||||
uninstall-info :
|
||||
-install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$(pkgname).info"
|
||||
-rm -f "$(DESTDIR)$(infodir)/$(pkgname).info"
|
||||
-rm -f "$(DESTDIR)$(infodir)/$(pkgname).info"*
|
||||
|
||||
uninstall-man :
|
||||
-rm -f "$(DESTDIR)$(mandir)/man1/$(progname).1"
|
||||
-rm -f "$(DESTDIR)$(mandir)/man1/$(progname).1"*
|
||||
|
||||
dist : doc
|
||||
ln -sf $(VPATH) $(DISTNAME)
|
||||
|
@ -158,7 +169,7 @@ dist : doc
|
|||
lzip -v -9 $(DISTNAME).tar
|
||||
|
||||
clean :
|
||||
-rm -f $(progname) $(progname)_profiled $(objs)
|
||||
-rm -f $(progname) $(objs)
|
||||
-rm -f $(progname)_shared lzlib_sh.o *.so.$(pkgversion)
|
||||
-rm -f bbexample bbexample.o lzcheck lzcheck.o lzlib.o *.a
|
||||
|
||||
|
|
49
NEWS
49
NEWS
|
@ -1,41 +1,16 @@
|
|||
Changes in version 1.6:
|
||||
Changes in version 1.7:
|
||||
|
||||
Compression ratio of option -9 has been slightly increased.
|
||||
The fast encoder, which produces a compression speed and ratio
|
||||
comparable to those of gzip, has been ported from lzip.
|
||||
|
||||
The configure script now accepts the option "--disable-static".
|
||||
The option "-0" has been ported from lzip to minilzip.
|
||||
|
||||
Improved portability to BSD systems:
|
||||
If all the data to be compressed are written in advance, lzlib will
|
||||
automatically adjust the header of the compressed data to use the
|
||||
smallest possible dictionary size. This feature reduces the amount of
|
||||
memory needed for decompression and allows minilzip to produce identical
|
||||
compressed output as lzip.
|
||||
|
||||
The configure script now accepts the option "--disable-ldconfig".
|
||||
|
||||
"make install" now ignores any errors from ldconfig.
|
||||
|
||||
Minilzip now copies file dates, permissions, and ownership like "cp -p".
|
||||
(If the user ID or the group ID can't be duplicated, the file permission
|
||||
bits S_ISUID and S_ISGID are cleared).
|
||||
|
||||
"lzlib.texinfo" has been renamed to "lzlib.texi".
|
||||
|
||||
The license has been changed to "GPL version 2 or later with link
|
||||
exception".
|
||||
|
||||
-----
|
||||
|
||||
Rationale for the license change.
|
||||
|
||||
I have recently been shocked to know that it is apparently not legal to
|
||||
use lzlib in GPLv2 programs. Linking those programs with lzlib violates
|
||||
the GPLv2. But linking proprietary programs with lzlib is fine and legal!
|
||||
|
||||
This problem is not caused by any fault in lzlib's link exception; the
|
||||
LGPLv3 has the same problem. See for example
|
||||
http://nmav.gnutls.org/2013/03/the-perils-of-lgplv3.html
|
||||
|
||||
Of course it was never my intention to prevent GPLv2 programs from using
|
||||
lzlib. I'm sorry for any inconveniences my oversight may have caused to
|
||||
distributions, GPLv2 software projects, and users in general.
|
||||
|
||||
I am also ashamed of having participated in this schism of the GPL
|
||||
community. The mere proliferation of different free software licenses is
|
||||
a burden in and of itself. From now on I'll license all my projects and
|
||||
contributions in a way compatible with the GPLv2.
|
||||
The targets "install-compress", "install-strip-compress",
|
||||
"install-info-compress" and "install-man-compress" have been added to
|
||||
the Makefile.
|
||||
|
|
23
README
23
README
|
@ -5,8 +5,9 @@ and decompression functions, including integrity checking of the
|
|||
decompressed data. The compressed data format used by the library is the
|
||||
lzip format. Lzlib is written in C.
|
||||
|
||||
The lzip file format is designed for long-term data archiving, taking
|
||||
into account both data integrity and decoder availability:
|
||||
The lzip file format is designed for data sharing and long-term
|
||||
archiving, taking into account both data integrity and decoder
|
||||
availability:
|
||||
|
||||
* The lzip format provides very safe integrity checking and some data
|
||||
recovery means. The lziprecover program can repair bit-flip errors
|
||||
|
@ -21,8 +22,8 @@ into account both data integrity and decoder availability:
|
|||
extract the data from a lzip file long after quantum computers
|
||||
eventually render LZMA obsolete.
|
||||
|
||||
* Additionally lzip is copylefted, which guarantees that it will
|
||||
remain free forever.
|
||||
* Additionally the lzip reference implementation is copylefted, which
|
||||
guarantees that it will remain free forever.
|
||||
|
||||
A nice feature of the lzip format is that a corrupt byte is easier to
|
||||
repair the nearer it is from the beginning of the file. Therefore, with
|
||||
|
@ -45,6 +46,12 @@ until some data is read, even if you write a lot of data. If you want
|
|||
the data to be compressed in advance, just call the read function with a
|
||||
size equal to 0.
|
||||
|
||||
If all the data to be compressed are written in advance, lzlib will
|
||||
automatically adjust the header of the compressed data to use the
|
||||
smallest possible dictionary size. This feature reduces the amount of
|
||||
memory needed for decompression and allows minilzip to produce identical
|
||||
compressed output as lzip.
|
||||
|
||||
Lzlib will correctly decompress a data stream which is the concatenation
|
||||
of two or more compressed data streams. The result is the concatenation
|
||||
of the corresponding decompressed data streams. Integrity testing of
|
||||
|
@ -62,9 +69,9 @@ elaborated way of finding coding sequences of minimum price than the one
|
|||
currently used by lzip could be developed, and the resulting sequence
|
||||
could also be coded using the LZMA coding scheme.
|
||||
|
||||
Lzip currently implements two variants of the LZMA algorithm; fast (used
|
||||
by option -0) and normal (used by all other compression levels). Lzlib
|
||||
just implements the "normal" variant.
|
||||
Lzlib currently implements two variants of the LZMA algorithm; fast
|
||||
(used by option -0 of minilzip) and normal (used by all other
|
||||
compression levels).
|
||||
|
||||
The high compression of LZMA comes from combining two basic, well-proven
|
||||
compression ideas: sliding dictionaries (LZ77/78) and markov models (the
|
||||
|
@ -79,7 +86,7 @@ range encoding), Igor Pavlov (for putting all the above together in
|
|||
LZMA), and Julian Seward (for bzip2's CLI).
|
||||
|
||||
|
||||
Copyright (C) 2009-2014 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2015 Antonio Diaz Diaz.
|
||||
|
||||
This file is free documentation: you have unlimited permission to copy,
|
||||
distribute and modify it.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Buff to buff example - Test program for the lzlib library
|
||||
Copyright (C) 2010-2014 Antonio Diaz Diaz.
|
||||
Copyright (C) 2010-2015 Antonio Diaz Diaz.
|
||||
|
||||
This program is free software: you have unlimited permission
|
||||
to copy, distribute and modify it.
|
||||
|
@ -164,7 +164,7 @@ int main( const int argc, const char * const argv[] )
|
|||
file = fopen( argv[1], "rb" );
|
||||
if( !file )
|
||||
{
|
||||
fprintf( stderr, "bbexample: Can't open file '%s' for reading\n", argv[1] );
|
||||
fprintf( stderr, "bbexample: Can't open file '%s' for reading.\n", argv[1] );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Arg_parser - POSIX/GNU command line argument parser. (C version)
|
||||
Copyright (C) 2006-2014 Antonio Diaz Diaz.
|
||||
Copyright (C) 2006-2015 Antonio Diaz Diaz.
|
||||
|
||||
This library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Arg_parser - POSIX/GNU command line argument parser. (C version)
|
||||
Copyright (C) 2006-2014 Antonio Diaz Diaz.
|
||||
Copyright (C) 2006-2015 Antonio Diaz Diaz.
|
||||
|
||||
This library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Lzlib - Compression library for the lzip format
|
||||
Copyright (C) 2009-2014 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2015 Antonio Diaz Diaz.
|
||||
|
||||
This library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -77,7 +77,7 @@ static int Cb_read_data( struct Circular_buffer * const cb,
|
|||
uint8_t * const out_buffer, const int out_size )
|
||||
{
|
||||
int size = 0;
|
||||
if( out_size < 0 ) return 0;
|
||||
if( out_size <= 0 ) return 0;
|
||||
if( cb->get > cb->put )
|
||||
{
|
||||
size = min( cb->buffer_size - cb->get, out_size );
|
||||
|
|
6
configure
vendored
6
configure
vendored
|
@ -1,12 +1,12 @@
|
|||
#! /bin/sh
|
||||
# configure script for Lzlib - Compression library for the lzip format
|
||||
# Copyright (C) 2009-2014 Antonio Diaz Diaz.
|
||||
# Copyright (C) 2009-2015 Antonio Diaz Diaz.
|
||||
#
|
||||
# This configure script is free software: you have unlimited permission
|
||||
# to copy, distribute and modify it.
|
||||
|
||||
pkgname=lzlib
|
||||
pkgversion=1.6
|
||||
pkgversion=1.7-pre1
|
||||
soversion=1
|
||||
progname=minilzip
|
||||
progname_static=${progname}
|
||||
|
@ -191,7 +191,7 @@ echo "LDFLAGS = ${LDFLAGS}"
|
|||
rm -f Makefile
|
||||
cat > Makefile << EOF
|
||||
# Makefile for Lzlib - Compression library for the lzip format
|
||||
# Copyright (C) 2009-2014 Antonio Diaz Diaz.
|
||||
# Copyright (C) 2009-2015 Antonio Diaz Diaz.
|
||||
# This file was generated automatically by configure. Do not edit.
|
||||
#
|
||||
# This Makefile is free software: you have unlimited permission
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Lzlib - Compression library for the lzip format
|
||||
Copyright (C) 2009-2014 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2015 Antonio Diaz Diaz.
|
||||
|
||||
This library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -129,7 +129,7 @@ static int LZd_decode_member( struct LZ_decoder * const d )
|
|||
{
|
||||
d->rep0 += Rd_decode( rdec, direct_bits - dis_align_bits ) << dis_align_bits;
|
||||
d->rep0 += Rd_decode_tree_reversed4( rdec, d->bm_align );
|
||||
if( d->rep0 == 0xFFFFFFFFU ) /* Marker found */
|
||||
if( d->rep0 == 0xFFFFFFFFU ) /* marker found */
|
||||
{
|
||||
d->rep0 = rep0_saved;
|
||||
Rd_normalize( rdec );
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Lzlib - Compression library for the lzip format
|
||||
Copyright (C) 2009-2014 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2015 Antonio Diaz Diaz.
|
||||
|
||||
This library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -407,7 +407,6 @@ static inline bool LZd_init( struct LZ_decoder * const d,
|
|||
Bm_array_init( d->bm_dis_slot[0], len_states * (1 << dis_slot_bits) );
|
||||
Bm_array_init( d->bm_dis, modeled_distances - end_dis_model );
|
||||
Bm_array_init( d->bm_align, dis_align_size );
|
||||
|
||||
Lm_init( &d->match_len_model );
|
||||
Lm_init( &d->rep_len_model );
|
||||
d->cb.buffer[d->cb.buffer_size-1] = 0; /* prev_byte of first byte */
|
||||
|
|
|
@ -11,7 +11,7 @@ File: lzlib.info, Node: Top, Next: Introduction, Up: (dir)
|
|||
Lzlib Manual
|
||||
************
|
||||
|
||||
This manual is for Lzlib (version 1.6, 27 August 2014).
|
||||
This manual is for Lzlib (version 1.7-pre1, 24 February 2015).
|
||||
|
||||
* Menu:
|
||||
|
||||
|
@ -29,7 +29,7 @@ This manual is for Lzlib (version 1.6, 27 August 2014).
|
|||
* Concept index:: Index of concepts
|
||||
|
||||
|
||||
Copyright (C) 2009-2014 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2015 Antonio Diaz Diaz.
|
||||
|
||||
This manual is free documentation: you have unlimited permission to
|
||||
copy, distribute and modify it.
|
||||
|
@ -45,8 +45,9 @@ and decompression functions, including integrity checking of the
|
|||
decompressed data. The compressed data format used by the library is the
|
||||
lzip format. Lzlib is written in C.
|
||||
|
||||
The lzip file format is designed for long-term data archiving, taking
|
||||
into account both data integrity and decoder availability:
|
||||
The lzip file format is designed for data sharing and long-term
|
||||
archiving, taking into account both data integrity and decoder
|
||||
availability:
|
||||
|
||||
* The lzip format provides very safe integrity checking and some data
|
||||
recovery means. The lziprecover program can repair bit-flip errors
|
||||
|
@ -61,8 +62,8 @@ into account both data integrity and decoder availability:
|
|||
archaeologist to extract the data from a lzip file long after
|
||||
quantum computers eventually render LZMA obsolete.
|
||||
|
||||
* Additionally lzip is copylefted, which guarantees that it will
|
||||
remain free forever.
|
||||
* Additionally the lzip reference implementation is copylefted, which
|
||||
guarantees that it will remain free forever.
|
||||
|
||||
A nice feature of the lzip format is that a corrupt byte is easier to
|
||||
repair the nearer it is from the beginning of the file. Therefore, with
|
||||
|
@ -75,15 +76,21 @@ library are given in the files 'main.c' and 'bbexample.c' from the
|
|||
source distribution.
|
||||
|
||||
Compression/decompression is done by repeatedly calling a couple of
|
||||
read/write functions until all the data has been processed by the
|
||||
read/write functions until all the data have been processed by the
|
||||
library. This interface is safer and less error prone than the
|
||||
traditional zlib interface.
|
||||
|
||||
Compression/decompression is done when the read function is called.
|
||||
This means the value returned by the position functions will not be
|
||||
updated until some data is read, even if you write a lot of data. If
|
||||
you want the data to be compressed in advance, just call the read
|
||||
function with a SIZE equal to 0.
|
||||
updated until a read call, even if a lot of data is written. If you
|
||||
want the data to be compressed in advance, just call the read function
|
||||
with a SIZE equal to 0.
|
||||
|
||||
If all the data to be compressed are written in advance, lzlib will
|
||||
automatically adjust the header of the compressed data to use the
|
||||
smallest possible dictionary size. This feature reduces the amount of
|
||||
memory needed for decompression and allows minilzip to produce identical
|
||||
compressed output as lzip.
|
||||
|
||||
Lzlib will correctly decompress a data stream which is the
|
||||
concatenation of two or more compressed data streams. The result is the
|
||||
|
@ -103,9 +110,9 @@ elaborated way of finding coding sequences of minimum price than the one
|
|||
currently used by lzip could be developed, and the resulting sequence
|
||||
could also be coded using the LZMA coding scheme.
|
||||
|
||||
Lzip currently implements two variants of the LZMA algorithm; fast
|
||||
(used by option -0) and normal (used by all other compression levels).
|
||||
Lzlib just implements the "normal" variant.
|
||||
Lzlib currently implements two variants of the LZMA algorithm; fast
|
||||
(used by option -0 of minilzip) and normal (used by all other
|
||||
compression levels).
|
||||
|
||||
The high compression of LZMA comes from combining two basic,
|
||||
well-proven compression ideas: sliding dictionaries (LZ77/78) and
|
||||
|
@ -147,15 +154,18 @@ File: lzlib.info, Node: Buffering, Next: Parameter limits, Prev: Library vers
|
|||
|
||||
Lzlib internal functions need access to a memory chunk at least as large
|
||||
as the dictionary size (sliding window). For efficiency reasons, the
|
||||
input buffer for compression is twice as large as the dictionary size.
|
||||
input buffer for compression is twice or sixteen times as large as the
|
||||
dictionary size.
|
||||
|
||||
Finally, for safety reasons, lzlib uses two more internal buffers.
|
||||
|
||||
These are the four buffers used by lzlib, and their guaranteed
|
||||
minimum sizes:
|
||||
|
||||
* Input compression buffer. Written to by the 'LZ_compress_write'
|
||||
function. Its size is two times the dictionary size set with the
|
||||
'LZ_compress_open' function or 64 KiB, whichever is larger.
|
||||
function. For the normal variant of LZMA, its size is two times
|
||||
the dictionary size set with the 'LZ_compress_open' function or 64
|
||||
KiB, whichever is larger. For the fast variant, its size is 1 MiB.
|
||||
|
||||
* Output compression buffer. Read from by the 'LZ_compress_read'
|
||||
function. Its size is 64 KiB.
|
||||
|
@ -230,6 +240,11 @@ calling 'LZ_compress_errno' before using it.
|
|||
range from 5 to 273. Larger values usually give better compression
|
||||
ratios but longer compression times.
|
||||
|
||||
If DICTIONARY_SIZE is 65535 and MATCH_LEN_LIMIT is 16, the fast
|
||||
variant of LZMA is chosen, which produces identical compressed
|
||||
output as 'lzip -0'. (The DICTIONARY_SIZE used will be rounded
|
||||
upwards to 64 KiB).
|
||||
|
||||
MEMBER_SIZE sets the member size limit in bytes. Minimum member
|
||||
size limit is 100 kB. Small member size may degrade compression
|
||||
ratio, so use it only when needed. To produce a single-member data
|
||||
|
@ -246,8 +261,8 @@ calling 'LZ_compress_errno' before using it.
|
|||
-- Function: int LZ_compress_finish ( struct LZ_Encoder * const
|
||||
ENCODER )
|
||||
Use this function to tell 'lzlib' that all the data for this member
|
||||
has already been written (with the 'LZ_compress_write' function).
|
||||
After all the produced compressed data has been read with
|
||||
have already been written (with the 'LZ_compress_write' function).
|
||||
After all the produced compressed data have been read with
|
||||
'LZ_compress_read' and 'LZ_compress_member_finished' returns 1, a
|
||||
new member can be started with 'LZ_compress_restart_member'.
|
||||
|
||||
|
@ -262,9 +277,8 @@ calling 'LZ_compress_errno' before using it.
|
|||
ENCODER )
|
||||
Use this function to make available to 'LZ_compress_read' all the
|
||||
data already written with the 'LZ_compress_write' function. First
|
||||
call 'LZ_compress_read' until it returns 0. Then call
|
||||
'LZ_compress_sync_flush'. Finally, call 'LZ_compress_read' again
|
||||
to read the remaining data.
|
||||
call 'LZ_compress_sync_flush'. Then call 'LZ_compress_read' until
|
||||
it returns 0.
|
||||
|
||||
Repeated use of 'LZ_compress_sync_flush' may degrade compression
|
||||
ratio, so use it only when needed.
|
||||
|
@ -304,8 +318,8 @@ calling 'LZ_compress_errno' before using it.
|
|||
|
||||
-- Function: int LZ_compress_finished ( struct LZ_Encoder * const
|
||||
ENCODER )
|
||||
Returns 1 if all the data has been read and 'LZ_compress_close' can
|
||||
be safely called. Otherwise it returns 0.
|
||||
Returns 1 if all the data have been read and 'LZ_compress_close'
|
||||
can be safely called. Otherwise it returns 0.
|
||||
|
||||
-- Function: int LZ_compress_member_finished ( struct LZ_Encoder *
|
||||
const ENCODER )
|
||||
|
@ -364,7 +378,8 @@ verified by calling 'LZ_decompress_errno' before using it.
|
|||
-- Function: int LZ_decompress_finish ( struct LZ_Decoder * const
|
||||
DECODER )
|
||||
Use this function to tell 'lzlib' that all the data for this stream
|
||||
has already been written (with the 'LZ_decompress_write' function).
|
||||
have already been written (with the 'LZ_decompress_write'
|
||||
function).
|
||||
|
||||
-- Function: int LZ_decompress_reset ( struct LZ_Decoder * const
|
||||
DECODER )
|
||||
|
@ -420,7 +435,7 @@ verified by calling 'LZ_decompress_errno' before using it.
|
|||
|
||||
-- Function: int LZ_decompress_finished ( struct LZ_Decoder * const
|
||||
DECODER )
|
||||
Returns 1 if all the data has been read and 'LZ_decompress_close'
|
||||
Returns 1 if all the data have been read and 'LZ_decompress_close'
|
||||
can be safely called. Otherwise it returns 0.
|
||||
|
||||
-- Function: int LZ_decompress_member_finished ( struct LZ_Decoder *
|
||||
|
@ -589,8 +604,8 @@ with no additional information before, between, or after them.
|
|||
|
||||
'Lzma stream'
|
||||
The lzma stream, finished by an end of stream marker. Uses default
|
||||
values for encoder properties. See the lzip manual for a full
|
||||
description.
|
||||
values for encoder properties. *Note Stream format: (lzip)Stream
|
||||
format, for a complete description.
|
||||
Lzip only uses the LZMA marker '2' ("End Of Stream" marker). Lzlib
|
||||
also uses the LZMA marker '3' ("Sync Flush" marker).
|
||||
|
||||
|
@ -630,7 +645,7 @@ Example 1: Normal compression (MEMBER_SIZE > total output).
|
|||
1) LZ_compress_open
|
||||
2) LZ_compress_write
|
||||
3) LZ_compress_read
|
||||
4) go back to step 2 until all input data has been written
|
||||
4) go back to step 2 until all input data have been written
|
||||
5) LZ_compress_finish
|
||||
6) LZ_compress_read
|
||||
7) go back to step 6 until LZ_compress_finished returns 1
|
||||
|
@ -653,7 +668,7 @@ Example 3: Decompression.
|
|||
1) LZ_decompress_open
|
||||
2) LZ_decompress_write
|
||||
3) LZ_decompress_read
|
||||
4) go back to step 2 until all input data has been written
|
||||
4) go back to step 2 until all input data have been written
|
||||
5) LZ_decompress_finish
|
||||
6) LZ_decompress_read
|
||||
7) go back to step 6 until LZ_decompress_finished returns 1
|
||||
|
@ -697,7 +712,7 @@ Example 6: Multi-member compression (user-restarted members).
|
|||
6) LZ_compress_read
|
||||
7) go back to step 6 until LZ_compress_member_finished returns 1
|
||||
8) verify that LZ_compress_finished returns 1
|
||||
9) go to step 12 if all input data has been written
|
||||
9) go to step 12 if all input data have been written
|
||||
10) LZ_compress_restart_member
|
||||
11) go back to step 2
|
||||
12) LZ_compress_close
|
||||
|
@ -770,18 +785,18 @@ Concept index
|
|||
|
||||
Tag Table:
|
||||
Node: Top220
|
||||
Node: Introduction1304
|
||||
Node: Library version5487
|
||||
Node: Buffering6132
|
||||
Node: Parameter limits7253
|
||||
Node: Compression functions8212
|
||||
Node: Decompression functions14594
|
||||
Node: Error codes20755
|
||||
Node: Error messages22694
|
||||
Node: Data format23273
|
||||
Node: Examples25922
|
||||
Node: Problems30005
|
||||
Node: Concept index30577
|
||||
Node: Introduction1311
|
||||
Node: Library version5808
|
||||
Node: Buffering6453
|
||||
Node: Parameter limits7673
|
||||
Node: Compression functions8632
|
||||
Node: Decompression functions15176
|
||||
Node: Error codes21344
|
||||
Node: Error messages23283
|
||||
Node: Data format23862
|
||||
Node: Examples26538
|
||||
Node: Problems30624
|
||||
Node: Concept index31196
|
||||
|
||||
End Tag Table
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
@finalout
|
||||
@c %**end of header
|
||||
|
||||
@set UPDATED 27 August 2014
|
||||
@set VERSION 1.6
|
||||
@set UPDATED 24 February 2015
|
||||
@set VERSION 1.7-pre1
|
||||
|
||||
@dircategory Data Compression
|
||||
@direntry
|
||||
|
@ -50,7 +50,7 @@ This manual is for Lzlib (version @value{VERSION}, @value{UPDATED}).
|
|||
@end menu
|
||||
|
||||
@sp 1
|
||||
Copyright @copyright{} 2009-2014 Antonio Diaz Diaz.
|
||||
Copyright @copyright{} 2009-2015 Antonio Diaz Diaz.
|
||||
|
||||
This manual is free documentation: you have unlimited permission
|
||||
to copy, distribute and modify it.
|
||||
|
@ -65,8 +65,9 @@ and decompression functions, including integrity checking of the
|
|||
decompressed data. The compressed data format used by the library is the
|
||||
lzip format. Lzlib is written in C.
|
||||
|
||||
The lzip file format is designed for long-term data archiving, taking
|
||||
into account both data integrity and decoder availability:
|
||||
The lzip file format is designed for data sharing and long-term
|
||||
archiving, taking into account both data integrity and decoder
|
||||
availability:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
|
@ -85,8 +86,8 @@ data from a lzip file long after quantum computers eventually render
|
|||
LZMA obsolete.
|
||||
|
||||
@item
|
||||
Additionally lzip is copylefted, which guarantees that it will remain
|
||||
free forever.
|
||||
Additionally the lzip reference implementation is copylefted, which
|
||||
guarantees that it will remain free forever.
|
||||
@end itemize
|
||||
|
||||
A nice feature of the lzip format is that a corrupt byte is easier to
|
||||
|
@ -100,16 +101,22 @@ library are given in the files @samp{main.c} and @samp{bbexample.c} from
|
|||
the source distribution.
|
||||
|
||||
Compression/decompression is done by repeatedly calling a couple of
|
||||
read/write functions until all the data has been processed by the
|
||||
read/write functions until all the data have been processed by the
|
||||
library. This interface is safer and less error prone than the
|
||||
traditional zlib interface.
|
||||
|
||||
Compression/decompression is done when the read function is called. This
|
||||
means the value returned by the position functions will not be updated
|
||||
until some data is read, even if you write a lot of data. If you want
|
||||
the data to be compressed in advance, just call the read function with a
|
||||
until a read call, even if a lot of data is written. If you want the
|
||||
data to be compressed in advance, just call the read function with a
|
||||
@var{size} equal to 0.
|
||||
|
||||
If all the data to be compressed are written in advance, lzlib will
|
||||
automatically adjust the header of the compressed data to use the
|
||||
smallest possible dictionary size. This feature reduces the amount of
|
||||
memory needed for decompression and allows minilzip to produce identical
|
||||
compressed output as lzip.
|
||||
|
||||
Lzlib will correctly decompress a data stream which is the concatenation
|
||||
of two or more compressed data streams. The result is the concatenation
|
||||
of the corresponding decompressed data streams. Integrity testing of
|
||||
|
@ -127,9 +134,9 @@ elaborated way of finding coding sequences of minimum price than the one
|
|||
currently used by lzip could be developed, and the resulting sequence
|
||||
could also be coded using the LZMA coding scheme.
|
||||
|
||||
Lzip currently implements two variants of the LZMA algorithm; fast (used
|
||||
by option -0) and normal (used by all other compression levels). Lzlib
|
||||
just implements the "normal" variant.
|
||||
Lzlib currently implements two variants of the LZMA algorithm; fast
|
||||
(used by option -0 of minilzip) and normal (used by all other
|
||||
compression levels).
|
||||
|
||||
The high compression of LZMA comes from combining two basic, well-proven
|
||||
compression ideas: sliding dictionaries (LZ77/78) and markov models (the
|
||||
|
@ -173,7 +180,9 @@ if( LZ_version()[0] != LZ_version_string[0] )
|
|||
|
||||
Lzlib internal functions need access to a memory chunk at least as large
|
||||
as the dictionary size (sliding window). For efficiency reasons, the
|
||||
input buffer for compression is twice as large as the dictionary size.
|
||||
input buffer for compression is twice or sixteen times as large as the
|
||||
dictionary size.
|
||||
|
||||
Finally, for safety reasons, lzlib uses two more internal buffers.
|
||||
|
||||
These are the four buffers used by lzlib, and their guaranteed minimum
|
||||
|
@ -181,9 +190,10 @@ sizes:
|
|||
|
||||
@itemize @bullet
|
||||
@item Input compression buffer. Written to by the
|
||||
@samp{LZ_compress_write} function. Its size is two times the dictionary
|
||||
size set with the @samp{LZ_compress_open} function or 64 KiB, whichever
|
||||
is larger.
|
||||
@samp{LZ_compress_write} function. For the normal variant of LZMA, its
|
||||
size is two times the dictionary size set with the
|
||||
@samp{LZ_compress_open} function or 64 KiB, whichever is larger. For the
|
||||
fast variant, its size is 1 MiB.
|
||||
|
||||
@item Output compression buffer. Read from by the
|
||||
@samp{LZ_compress_read} function. Its size is 64 KiB.
|
||||
|
@ -261,6 +271,11 @@ to it.
|
|||
range from 5 to 273. Larger values usually give better compression
|
||||
ratios but longer compression times.
|
||||
|
||||
If @var{dictionary_size} is 65535 and @var{match_len_limit} is 16, the
|
||||
fast variant of LZMA is chosen, which produces identical compressed
|
||||
output as @code{lzip -0}. (The @var{dictionary_size} used will be
|
||||
rounded upwards to 64 KiB).
|
||||
|
||||
@var{member_size} sets the member size limit in bytes. Minimum member
|
||||
size limit is 100 kB. Small member size may degrade compression ratio, so
|
||||
use it only when needed. To produce a single-member data stream, give
|
||||
|
@ -279,8 +294,8 @@ more be used as an argument to any LZ_compress function.
|
|||
|
||||
@deftypefun int LZ_compress_finish ( struct LZ_Encoder * const @var{encoder} )
|
||||
Use this function to tell @samp{lzlib} that all the data for this member
|
||||
has already been written (with the @samp{LZ_compress_write} function).
|
||||
After all the produced compressed data has been read with
|
||||
have already been written (with the @samp{LZ_compress_write} function).
|
||||
After all the produced compressed data have been read with
|
||||
@samp{LZ_compress_read} and @samp{LZ_compress_member_finished} returns
|
||||
1, a new member can be started with @samp{LZ_compress_restart_member}.
|
||||
@end deftypefun
|
||||
|
@ -297,9 +312,8 @@ indicates that the current member has been fully read (with the
|
|||
@deftypefun int LZ_compress_sync_flush ( struct LZ_Encoder * const @var{encoder} )
|
||||
Use this function to make available to @samp{LZ_compress_read} all the
|
||||
data already written with the @samp{LZ_compress_write} function. First
|
||||
call @samp{LZ_compress_read} until it returns 0. Then call
|
||||
@samp{LZ_compress_sync_flush}. Finally, call @samp{LZ_compress_read}
|
||||
again to read the remaining data.
|
||||
call @samp{LZ_compress_sync_flush}. Then call @samp{LZ_compress_read}
|
||||
until it returns 0.
|
||||
|
||||
Repeated use of @samp{LZ_compress_sync_flush} may degrade compression
|
||||
ratio, so use it only when needed.
|
||||
|
@ -345,8 +359,8 @@ Returns the current error code for @var{encoder} (@pxref{Error codes}).
|
|||
|
||||
|
||||
@deftypefun int LZ_compress_finished ( struct LZ_Encoder * const @var{encoder} )
|
||||
Returns 1 if all the data has been read and @samp{LZ_compress_close} can
|
||||
be safely called. Otherwise it returns 0.
|
||||
Returns 1 if all the data have been read and @samp{LZ_compress_close}
|
||||
can be safely called. Otherwise it returns 0.
|
||||
@end deftypefun
|
||||
|
||||
|
||||
|
@ -414,7 +428,7 @@ more be used as an argument to any LZ_decompress function.
|
|||
|
||||
@deftypefun int LZ_decompress_finish ( struct LZ_Decoder * const @var{decoder} )
|
||||
Use this function to tell @samp{lzlib} that all the data for this stream
|
||||
has already been written (with the @samp{LZ_decompress_write} function).
|
||||
have already been written (with the @samp{LZ_decompress_write} function).
|
||||
@end deftypefun
|
||||
|
||||
|
||||
|
@ -478,7 +492,7 @@ Returns the current error code for @var{decoder} (@pxref{Error codes}).
|
|||
|
||||
|
||||
@deftypefun int LZ_decompress_finished ( struct LZ_Decoder * const @var{decoder} )
|
||||
Returns 1 if all the data has been read and @samp{LZ_decompress_close}
|
||||
Returns 1 if all the data have been read and @samp{LZ_decompress_close}
|
||||
can be safely called. Otherwise it returns 0.
|
||||
@end deftypefun
|
||||
|
||||
|
@ -665,8 +679,15 @@ Valid values for dictionary size range from 4 KiB to 512 MiB.
|
|||
|
||||
@item Lzma stream
|
||||
The lzma stream, finished by an end of stream marker. Uses default
|
||||
values for encoder properties. See the lzip manual for a full
|
||||
description.@*
|
||||
values for encoder properties.
|
||||
@ifnothtml
|
||||
@xref{Stream format,,,lzip},
|
||||
@end ifnothtml
|
||||
@ifhtml
|
||||
See
|
||||
@uref{http://www.nongnu.org/lzip/manual/lzip_manual.html#Stream-format,,Stream format}
|
||||
@end ifhtml
|
||||
for a complete description.@*
|
||||
Lzip only uses the LZMA marker @samp{2} ("End Of Stream" marker). Lzlib
|
||||
also uses the LZMA marker @samp{3} ("Sync Flush" marker).
|
||||
|
||||
|
@ -706,7 +727,7 @@ Example 1: Normal compression (@var{member_size} > total output).
|
|||
1) LZ_compress_open
|
||||
2) LZ_compress_write
|
||||
3) LZ_compress_read
|
||||
4) go back to step 2 until all input data has been written
|
||||
4) go back to step 2 until all input data have been written
|
||||
5) LZ_compress_finish
|
||||
6) LZ_compress_read
|
||||
7) go back to step 6 until LZ_compress_finished returns 1
|
||||
|
@ -735,7 +756,7 @@ Example 3: Decompression.
|
|||
1) LZ_decompress_open
|
||||
2) LZ_decompress_write
|
||||
3) LZ_decompress_read
|
||||
4) go back to step 2 until all input data has been written
|
||||
4) go back to step 2 until all input data have been written
|
||||
5) LZ_decompress_finish
|
||||
6) LZ_decompress_read
|
||||
7) go back to step 6 until LZ_decompress_finished returns 1
|
||||
|
@ -788,7 +809,7 @@ Example 6: Multi-member compression (user-restarted members).
|
|||
6) LZ_compress_read
|
||||
7) go back to step 6 until LZ_compress_member_finished returns 1
|
||||
8) verify that LZ_compress_finished returns 1
|
||||
9) go to step 12 if all input data has been written
|
||||
9) go to step 12 if all input data have been written
|
||||
10) LZ_compress_restart_member
|
||||
11) go back to step 2
|
||||
12) LZ_compress_close
|
||||
|
@ -838,7 +859,7 @@ for all eternity, if not longer.
|
|||
|
||||
If you find a bug in Lzlib, please send electronic mail to
|
||||
@email{lzip-bug@@nongnu.org}. Include the version number, which you can
|
||||
find by running @w{@samp{minilzip --version}} or in
|
||||
find by running @w{@code{minilzip --version}} or in
|
||||
@samp{LZ_version_string} from @samp{lzlib.h}.
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1.
|
||||
.TH MINILZIP "1" "August 2014" "minilzip 1.6" "User Commands"
|
||||
.TH MINILZIP "1" "February 2015" "minilzip 1.7-pre1" "User Commands"
|
||||
.SH NAME
|
||||
minilzip \- reduces the size of files
|
||||
.SH SYNOPSIS
|
||||
|
@ -54,11 +54,11 @@ test compressed file integrity
|
|||
\fB\-v\fR, \fB\-\-verbose\fR
|
||||
be verbose (a 2nd \fB\-v\fR gives more)
|
||||
.TP
|
||||
\fB\-1\fR .. \fB\-9\fR
|
||||
\fB\-0\fR .. \fB\-9\fR
|
||||
set compression level [default 6]
|
||||
.TP
|
||||
\fB\-\-fast\fR
|
||||
alias for \fB\-1\fR
|
||||
alias for \fB\-0\fR
|
||||
.TP
|
||||
\fB\-\-best\fR
|
||||
alias for \fB\-9\fR
|
||||
|
@ -70,8 +70,7 @@ Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...
|
|||
The bidimensional parameter space of LZMA can't be mapped to a linear
|
||||
scale optimal for all files. If your files are large, very repetitive,
|
||||
etc, you may need to use the \fB\-\-match\-length\fR and \fB\-\-dictionary\-size\fR
|
||||
options directly to achieve optimal performance. For example, \fB\-9m64\fR
|
||||
usually compresses executables more (and faster) than \fB\-9\fR.
|
||||
options directly to achieve optimal performance.
|
||||
.PP
|
||||
Exit status: 0 for a normal exit, 1 for environmental problems (file
|
||||
not found, invalid flags, I/O errors, etc), 2 to indicate a corrupt or
|
||||
|
@ -82,8 +81,8 @@ Report bugs to lzip\-bug@nongnu.org
|
|||
.br
|
||||
Lzlib home page: http://www.nongnu.org/lzip/lzlib.html
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co 2014 Antonio Diaz Diaz.
|
||||
Using lzlib 1.6
|
||||
Copyright \(co 2015 Antonio Diaz Diaz.
|
||||
Using lzlib 1.7\-pre1
|
||||
License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>
|
||||
.br
|
||||
This is free software: you are free to change and redistribute it.
|
||||
|
|
436
encoder.c
436
encoder.c
|
@ -1,5 +1,5 @@
|
|||
/* Lzlib - Compression library for the lzip format
|
||||
Copyright (C) 2009-2014 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2015 Antonio Diaz Diaz.
|
||||
|
||||
This library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -25,125 +25,26 @@
|
|||
Public License.
|
||||
*/
|
||||
|
||||
static bool Mf_normalize_pos( struct Matchfinder * const mf )
|
||||
static int LZe_get_match_pairs( struct LZ_encoder * const e, struct Pair * pairs )
|
||||
{
|
||||
if( mf->pos > mf->stream_pos )
|
||||
{ mf->pos = mf->stream_pos; return false; }
|
||||
if( !mf->at_stream_end )
|
||||
{
|
||||
int i;
|
||||
const int offset = mf->pos - mf->dictionary_size - before_size;
|
||||
const int size = mf->stream_pos - offset;
|
||||
memmove( mf->buffer, mf->buffer + offset, size );
|
||||
mf->partial_data_pos += offset;
|
||||
mf->pos -= offset;
|
||||
mf->stream_pos -= offset;
|
||||
for( i = 0; i < mf->num_prev_positions; ++i )
|
||||
mf->prev_positions[i] -= min( mf->prev_positions[i], offset );
|
||||
for( i = 0; i < 2 * ( mf->dictionary_size + 1 ); ++i )
|
||||
mf->prev_pos_tree[i] -= min( mf->prev_pos_tree[i], offset );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool Mf_init( struct Matchfinder * const mf, const int dict_size,
|
||||
const int match_len_limit )
|
||||
{
|
||||
const int buffer_size_limit = ( 2 * dict_size ) + before_size + after_size;
|
||||
unsigned size;
|
||||
int i;
|
||||
|
||||
mf->partial_data_pos = 0;
|
||||
mf->match_len_limit = match_len_limit;
|
||||
mf->pos = 0;
|
||||
mf->cyclic_pos = 0;
|
||||
mf->stream_pos = 0;
|
||||
mf->cycles = ( match_len_limit < max_match_len ) ?
|
||||
16 + ( match_len_limit / 2 ) : 256;
|
||||
mf->at_stream_end = false;
|
||||
mf->been_flushed = false;
|
||||
mf->flushing = false;
|
||||
|
||||
mf->buffer_size = max( 65536, buffer_size_limit );
|
||||
mf->buffer = (uint8_t *)malloc( mf->buffer_size );
|
||||
if( !mf->buffer ) return false;
|
||||
mf->dictionary_size = dict_size;
|
||||
mf->pos_limit = mf->buffer_size - after_size;
|
||||
size = 1 << max( 16, real_bits( mf->dictionary_size - 1 ) - 2 );
|
||||
if( mf->dictionary_size > 1 << 26 ) /* 64 MiB */
|
||||
size >>= 1;
|
||||
mf->key4_mask = size - 1;
|
||||
size += num_prev_positions2;
|
||||
size += num_prev_positions3;
|
||||
|
||||
mf->num_prev_positions = size;
|
||||
size += ( 2 * ( mf->dictionary_size + 1 ) );
|
||||
if( size * sizeof (int32_t) <= size ) mf->prev_positions = 0;
|
||||
else mf->prev_positions = (int32_t *)malloc( size * sizeof (int32_t) );
|
||||
if( !mf->prev_positions ) { free( mf->buffer ); return false; }
|
||||
mf->prev_pos_tree = mf->prev_positions + mf->num_prev_positions;
|
||||
for( i = 0; i < mf->num_prev_positions; ++i ) mf->prev_positions[i] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void Mf_adjust_distionary_size( struct Matchfinder * const mf )
|
||||
{
|
||||
if( mf->stream_pos < mf->dictionary_size )
|
||||
{
|
||||
int size;
|
||||
mf->buffer_size =
|
||||
mf->dictionary_size =
|
||||
mf->pos_limit = max( min_dictionary_size, mf->stream_pos );
|
||||
size = 1 << max( 16, real_bits( mf->dictionary_size - 1 ) - 2 );
|
||||
if( mf->dictionary_size > 1 << 26 )
|
||||
size >>= 1;
|
||||
mf->key4_mask = size - 1;
|
||||
size += num_prev_positions2;
|
||||
size += num_prev_positions3;
|
||||
mf->num_prev_positions = size;
|
||||
mf->prev_pos_tree = mf->prev_positions + mf->num_prev_positions;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void Mf_reset( struct Matchfinder * const mf )
|
||||
{
|
||||
int i;
|
||||
if( mf->stream_pos > mf->pos )
|
||||
memmove( mf->buffer, mf->buffer + mf->pos, mf->stream_pos - mf->pos );
|
||||
mf->partial_data_pos = 0;
|
||||
mf->stream_pos -= mf->pos;
|
||||
mf->pos = 0;
|
||||
mf->cyclic_pos = 0;
|
||||
mf->at_stream_end = false;
|
||||
mf->been_flushed = false;
|
||||
mf->flushing = false;
|
||||
for( i = 0; i < mf->num_prev_positions; ++i ) mf->prev_positions[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
static int Mf_get_match_pairs( struct Matchfinder * const mf, struct Pair * pairs )
|
||||
{
|
||||
int32_t * ptr0 = mf->prev_pos_tree + ( mf->cyclic_pos << 1 );
|
||||
int32_t * ptr0 = e->eb.mb.pos_array + ( e->eb.mb.cyclic_pos << 1 );
|
||||
int32_t * ptr1 = ptr0 + 1;
|
||||
int32_t * newptr;
|
||||
int len = 0, len0 = 0, len1 = 0;
|
||||
int maxlen = 0;
|
||||
int num_pairs = 0;
|
||||
const int pos1 = mf->pos + 1;
|
||||
const int min_pos =
|
||||
( mf->pos > mf->dictionary_size ) ? mf->pos - mf->dictionary_size : 0;
|
||||
const uint8_t * const data = mf->buffer + mf->pos;
|
||||
const int pos1 = e->eb.mb.pos + 1;
|
||||
const int min_pos = ( e->eb.mb.pos > e->eb.mb.dictionary_size ) ?
|
||||
e->eb.mb.pos - e->eb.mb.dictionary_size : 0;
|
||||
const uint8_t * const data = Mb_ptr_to_current_pos( &e->eb.mb );
|
||||
int count, delta, key2, key3, key4, newpos;
|
||||
unsigned tmp;
|
||||
int len_limit = mf->match_len_limit;
|
||||
int len_limit = e->match_len_limit;
|
||||
|
||||
if( len_limit > Mf_available_bytes( mf ) )
|
||||
if( len_limit > Mb_available_bytes( &e->eb.mb ) )
|
||||
{
|
||||
mf->been_flushed = true;
|
||||
len_limit = Mf_available_bytes( mf );
|
||||
e->been_flushed = true;
|
||||
len_limit = Mb_available_bytes( &e->eb.mb );
|
||||
if( len_limit < 4 ) { *ptr0 = *ptr1 = 0; return 0; }
|
||||
}
|
||||
|
||||
|
@ -152,23 +53,23 @@ static int Mf_get_match_pairs( struct Matchfinder * const mf, struct Pair * pair
|
|||
tmp ^= (unsigned)data[2] << 8;
|
||||
key3 = num_prev_positions2 + ( tmp & ( num_prev_positions3 - 1 ) );
|
||||
key4 = num_prev_positions2 + num_prev_positions3 +
|
||||
( ( tmp ^ ( crc32[data[3]] << 5 ) ) & mf->key4_mask );
|
||||
( ( tmp ^ ( crc32[data[3]] << 5 ) ) & e->eb.mb.key4_mask );
|
||||
|
||||
if( pairs )
|
||||
{
|
||||
int np2 = mf->prev_positions[key2];
|
||||
int np3 = mf->prev_positions[key3];
|
||||
if( np2 > min_pos && mf->buffer[np2-1] == data[0] )
|
||||
int np2 = e->eb.mb.prev_positions[key2];
|
||||
int np3 = e->eb.mb.prev_positions[key3];
|
||||
if( np2 > min_pos && e->eb.mb.buffer[np2-1] == data[0] )
|
||||
{
|
||||
pairs[0].dis = mf->pos - np2;
|
||||
pairs[0].dis = e->eb.mb.pos - np2;
|
||||
pairs[0].len = maxlen = 2;
|
||||
num_pairs = 1;
|
||||
}
|
||||
if( np2 != np3 && np3 > min_pos && mf->buffer[np3-1] == data[0] )
|
||||
if( np2 != np3 && np3 > min_pos && e->eb.mb.buffer[np3-1] == data[0] )
|
||||
{
|
||||
maxlen = 3;
|
||||
np2 = np3;
|
||||
pairs[num_pairs].dis = mf->pos - np2;
|
||||
pairs[num_pairs].dis = e->eb.mb.pos - np2;
|
||||
++num_pairs;
|
||||
}
|
||||
if( num_pairs > 0 )
|
||||
|
@ -182,20 +83,20 @@ static int Mf_get_match_pairs( struct Matchfinder * const mf, struct Pair * pair
|
|||
if( maxlen < 3 ) maxlen = 3;
|
||||
}
|
||||
|
||||
mf->prev_positions[key2] = pos1;
|
||||
mf->prev_positions[key3] = pos1;
|
||||
newpos = mf->prev_positions[key4];
|
||||
mf->prev_positions[key4] = pos1;
|
||||
e->eb.mb.prev_positions[key2] = pos1;
|
||||
e->eb.mb.prev_positions[key3] = pos1;
|
||||
newpos = e->eb.mb.prev_positions[key4];
|
||||
e->eb.mb.prev_positions[key4] = pos1;
|
||||
|
||||
for( count = mf->cycles; ; )
|
||||
for( count = e->cycles; ; )
|
||||
{
|
||||
if( newpos <= min_pos || --count < 0 ) { *ptr0 = *ptr1 = 0; break; }
|
||||
|
||||
if( mf->been_flushed ) len = 0;
|
||||
if( e->been_flushed ) len = 0;
|
||||
delta = pos1 - newpos;
|
||||
newptr = mf->prev_pos_tree +
|
||||
( ( mf->cyclic_pos - delta +
|
||||
( (mf->cyclic_pos >= delta) ? 0 : mf->dictionary_size + 1 ) ) << 1 );
|
||||
newptr = e->eb.mb.pos_array +
|
||||
( ( e->eb.mb.cyclic_pos - delta +
|
||||
( (e->eb.mb.cyclic_pos >= delta) ? 0 : e->eb.mb.dictionary_size + 1 ) ) << 1 );
|
||||
if( data[len-delta] == data[len] )
|
||||
{
|
||||
while( ++len < len_limit && data[len-delta] == data[len] ) {}
|
||||
|
@ -231,43 +132,6 @@ static int Mf_get_match_pairs( struct Matchfinder * const mf, struct Pair * pair
|
|||
}
|
||||
|
||||
|
||||
/* End Of Stream mark => (dis == 0xFFFFFFFFU, len == min_match_len) */
|
||||
static bool LZe_full_flush( struct LZ_encoder * const e, const State state )
|
||||
{
|
||||
int i;
|
||||
const int pos_state = Mf_data_position( e->matchfinder ) & pos_state_mask;
|
||||
File_trailer trailer;
|
||||
if( e->member_finished ||
|
||||
Cb_free_bytes( &e->renc.cb ) < max_marker_size + Ft_size )
|
||||
return false;
|
||||
Re_encode_bit( &e->renc, &e->bm_match[state][pos_state], 1 );
|
||||
Re_encode_bit( &e->renc, &e->bm_rep[state], 0 );
|
||||
LZe_encode_pair( e, 0xFFFFFFFFU, min_match_len, pos_state );
|
||||
Re_flush( &e->renc );
|
||||
Ft_set_data_crc( trailer, LZe_crc( e ) );
|
||||
Ft_set_data_size( trailer, Mf_data_position( e->matchfinder ) );
|
||||
Ft_set_member_size( trailer, Re_member_position( &e->renc ) + Ft_size );
|
||||
for( i = 0; i < Ft_size; ++i )
|
||||
Cb_put_byte( &e->renc.cb, trailer[i] );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Sync Flush mark => (dis == 0xFFFFFFFFU, len == min_match_len + 1) */
|
||||
static bool LZe_sync_flush( struct LZ_encoder * const e )
|
||||
{
|
||||
const int pos_state = Mf_data_position( e->matchfinder ) & pos_state_mask;
|
||||
const State state = e->state;
|
||||
if( e->member_finished || Cb_free_bytes( &e->renc.cb ) < max_marker_size )
|
||||
return false;
|
||||
Re_encode_bit( &e->renc, &e->bm_match[state][pos_state], 1 );
|
||||
Re_encode_bit( &e->renc, &e->bm_rep[state], 0 );
|
||||
LZe_encode_pair( e, 0xFFFFFFFFU, min_match_len + 1, pos_state );
|
||||
Re_flush( &e->renc );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void LZe_update_distance_prices( struct LZ_encoder * const e )
|
||||
{
|
||||
int dis, len_state;
|
||||
|
@ -276,7 +140,7 @@ static void LZe_update_distance_prices( struct LZ_encoder * const e )
|
|||
const int dis_slot = dis_slots[dis];
|
||||
const int direct_bits = ( dis_slot >> 1 ) - 1;
|
||||
const int base = ( 2 | ( dis_slot & 1 ) ) << direct_bits;
|
||||
const int price = price_symbol_reversed( e->bm_dis + base - dis_slot - 1,
|
||||
const int price = price_symbol_reversed( e->eb.bm_dis + base - dis_slot - 1,
|
||||
dis - base, direct_bits );
|
||||
for( len_state = 0; len_state < len_states; ++len_state )
|
||||
e->dis_prices[len_state][dis] = price;
|
||||
|
@ -286,7 +150,7 @@ static void LZe_update_distance_prices( struct LZ_encoder * const e )
|
|||
{
|
||||
int * const dsp = e->dis_slot_prices[len_state];
|
||||
int * const dp = e->dis_prices[len_state];
|
||||
const Bit_model * const bmds = e->bm_dis_slot[len_state];
|
||||
const Bit_model * const bmds = e->eb.bm_dis_slot[len_state];
|
||||
int slot = 0;
|
||||
for( ; slot < end_dis_model; ++slot )
|
||||
dsp[slot] = price_symbol( bmds, slot, dis_slot_bits );
|
||||
|
@ -302,48 +166,7 @@ static void LZe_update_distance_prices( struct LZ_encoder * const e )
|
|||
}
|
||||
|
||||
|
||||
static bool LZe_init( struct LZ_encoder * const e,
|
||||
struct Matchfinder * const mf,
|
||||
const File_header header,
|
||||
const unsigned long long member_size )
|
||||
{
|
||||
int i;
|
||||
e->member_size_limit = member_size - Ft_size - max_marker_size;
|
||||
e->pending_num_pairs = 0;
|
||||
e->crc = 0xFFFFFFFFU;
|
||||
|
||||
Bm_array_init( e->bm_literal[0], (1 << literal_context_bits) * 0x300 );
|
||||
Bm_array_init( e->bm_match[0], states * pos_states );
|
||||
Bm_array_init( e->bm_rep, states );
|
||||
Bm_array_init( e->bm_rep0, states );
|
||||
Bm_array_init( e->bm_rep1, states );
|
||||
Bm_array_init( e->bm_rep2, states );
|
||||
Bm_array_init( e->bm_len[0], states * pos_states );
|
||||
Bm_array_init( e->bm_dis_slot[0], len_states * (1 << dis_slot_bits) );
|
||||
Bm_array_init( e->bm_dis, modeled_distances - end_dis_model );
|
||||
Bm_array_init( e->bm_align, dis_align_size );
|
||||
|
||||
e->matchfinder = mf;
|
||||
if( !Re_init( &e->renc ) ) return false;
|
||||
Lm_init( &e->match_len_model );
|
||||
Lm_init( &e->rep_len_model );
|
||||
Lp_init( &e->match_len_prices, &e->match_len_model, mf->match_len_limit );
|
||||
Lp_init( &e->rep_len_prices, &e->rep_len_model, mf->match_len_limit );
|
||||
for( i = 0; i < num_rep_distances; ++i ) e->reps[i] = 0;
|
||||
e->num_dis_slots = 2 * real_bits( mf->dictionary_size - 1 );
|
||||
e->price_counter = 0;
|
||||
e->dis_price_counter = 0;
|
||||
e->align_price_counter = 0;
|
||||
e->state = 0;
|
||||
e->member_finished = false;
|
||||
|
||||
for( i = 0; i < Fh_size; ++i )
|
||||
Cb_put_byte( &e->renc.cb, header[i] );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Return value == number of bytes advanced (ahead).
|
||||
/* Returns the number of bytes advanced (ahead).
|
||||
trials[0]..trials[ahead-1] contain the steps to encode.
|
||||
( trials[0].dis == -1 ) means literal.
|
||||
A match/rep longer or equal than match_len_limit finishes the sequence.
|
||||
|
@ -367,45 +190,44 @@ static int LZe_sequence_optimizer( struct LZ_encoder * const e,
|
|||
|
||||
for( i = 0; i < num_rep_distances; ++i )
|
||||
{
|
||||
replens[i] =
|
||||
Mf_true_match_len( e->matchfinder, 0, reps[i] + 1, max_match_len );
|
||||
replens[i] = Mb_true_match_len( &e->eb.mb, 0, reps[i] + 1, max_match_len );
|
||||
if( replens[i] > replens[rep_index] ) rep_index = i;
|
||||
}
|
||||
if( replens[rep_index] >= e->matchfinder->match_len_limit )
|
||||
if( replens[rep_index] >= e->match_len_limit )
|
||||
{
|
||||
e->trials[0].dis = rep_index;
|
||||
e->trials[0].price = replens[rep_index];
|
||||
if( !LZe_move_pos( e, replens[rep_index] ) ) return 0;
|
||||
if( !LZe_move_and_update( e, replens[rep_index] ) ) return 0;
|
||||
return replens[rep_index];
|
||||
}
|
||||
|
||||
if( main_len >= e->matchfinder->match_len_limit )
|
||||
if( main_len >= e->match_len_limit )
|
||||
{
|
||||
e->trials[0].dis = e->pairs[num_pairs-1].dis + num_rep_distances;
|
||||
e->trials[0].price = main_len;
|
||||
if( !LZe_move_pos( e, main_len ) ) return 0;
|
||||
if( !LZe_move_and_update( e, main_len ) ) return 0;
|
||||
return main_len;
|
||||
}
|
||||
|
||||
{
|
||||
const int pos_state = Mf_data_position( e->matchfinder ) & pos_state_mask;
|
||||
const int match_price = price1( e->bm_match[state][pos_state] );
|
||||
const int rep_match_price = match_price + price1( e->bm_rep[state] );
|
||||
const uint8_t prev_byte = Mf_peek( e->matchfinder, 1 );
|
||||
const uint8_t cur_byte = Mf_peek( e->matchfinder, 0 );
|
||||
const uint8_t match_byte = Mf_peek( e->matchfinder, reps[0] + 1 );
|
||||
const int pos_state = Mb_data_position( &e->eb.mb ) & pos_state_mask;
|
||||
const int match_price = price1( e->eb.bm_match[state][pos_state] );
|
||||
const int rep_match_price = match_price + price1( e->eb.bm_rep[state] );
|
||||
const uint8_t prev_byte = Mb_peek( &e->eb.mb, 1 );
|
||||
const uint8_t cur_byte = Mb_peek( &e->eb.mb, 0 );
|
||||
const uint8_t match_byte = Mb_peek( &e->eb.mb, reps[0] + 1 );
|
||||
|
||||
e->trials[0].state = state;
|
||||
e->trials[1].dis = -1; /* literal */
|
||||
e->trials[1].price = price0( e->bm_match[state][pos_state] );
|
||||
e->trials[1].price = price0( e->eb.bm_match[state][pos_state] );
|
||||
if( St_is_char( state ) )
|
||||
e->trials[1].price += LZe_price_literal( e, prev_byte, cur_byte );
|
||||
e->trials[1].price += LZeb_price_literal( &e->eb, prev_byte, cur_byte );
|
||||
else
|
||||
e->trials[1].price += LZe_price_matched( e, prev_byte, cur_byte, match_byte );
|
||||
e->trials[1].price += LZeb_price_matched( &e->eb, prev_byte, cur_byte, match_byte );
|
||||
|
||||
if( match_byte == cur_byte )
|
||||
Tr_update( &e->trials[1], rep_match_price +
|
||||
LZe_price_shortrep( e, state, pos_state ), 0, 0 );
|
||||
LZeb_price_shortrep( &e->eb, state, pos_state ), 0, 0 );
|
||||
|
||||
num_trials = max( main_len, replens[rep_index] );
|
||||
|
||||
|
@ -413,7 +235,7 @@ static int LZe_sequence_optimizer( struct LZ_encoder * const e,
|
|||
{
|
||||
e->trials[0].dis = e->trials[1].dis;
|
||||
e->trials[0].price = 1;
|
||||
if( !Mf_move_pos( e->matchfinder ) ) return 0;
|
||||
if( !Mb_move_pos( &e->eb.mb ) ) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -429,8 +251,7 @@ static int LZe_sequence_optimizer( struct LZ_encoder * const e,
|
|||
{
|
||||
int price;
|
||||
if( replens[rep] < min_match_len ) continue;
|
||||
price = rep_match_price + LZe_price_rep( e, rep, state, pos_state );
|
||||
|
||||
price = rep_match_price + LZeb_price_rep( &e->eb, rep, state, pos_state );
|
||||
for( len = min_match_len; len <= replens[rep]; ++len )
|
||||
Tr_update( &e->trials[len], price +
|
||||
Lp_price( &e->rep_len_prices, len, pos_state ), rep, 0 );
|
||||
|
@ -438,7 +259,7 @@ static int LZe_sequence_optimizer( struct LZ_encoder * const e,
|
|||
|
||||
if( main_len > replens[0] )
|
||||
{
|
||||
const int normal_match_price = match_price + price0( e->bm_rep[state] );
|
||||
const int normal_match_price = match_price + price0( e->eb.bm_rep[state] );
|
||||
i = 0, len = max( replens[0] + 1, min_match_len );
|
||||
while( len > e->pairs[i].len ) ++i;
|
||||
while( true )
|
||||
|
@ -455,13 +276,13 @@ static int LZe_sequence_optimizer( struct LZ_encoder * const e,
|
|||
while( true ) /* price optimization loop */
|
||||
{
|
||||
struct Trial *cur_trial, *next_trial;
|
||||
int newlen, pos_state, available_bytes, len_limit;
|
||||
int newlen, pos_state, triable_bytes, len_limit;
|
||||
int start_len = min_match_len;
|
||||
int next_price, match_price, rep_match_price;
|
||||
State cur_state;
|
||||
uint8_t prev_byte, cur_byte, match_byte;
|
||||
|
||||
if( !Mf_move_pos( e->matchfinder ) ) return 0;
|
||||
if( !Mb_move_pos( &e->eb.mb ) ) return 0;
|
||||
if( ++cur >= num_trials ) /* no more initialized trials */
|
||||
{
|
||||
LZe_backward( e, cur );
|
||||
|
@ -470,7 +291,7 @@ static int LZe_sequence_optimizer( struct LZ_encoder * const e,
|
|||
|
||||
num_pairs = LZe_read_match_distances( e );
|
||||
newlen = ( num_pairs > 0 ) ? e->pairs[num_pairs-1].len : 0;
|
||||
if( newlen >= e->matchfinder->match_len_limit )
|
||||
if( newlen >= e->match_len_limit )
|
||||
{
|
||||
e->pending_num_pairs = num_pairs;
|
||||
LZe_backward( e, cur );
|
||||
|
@ -517,31 +338,31 @@ static int LZe_sequence_optimizer( struct LZ_encoder * const e,
|
|||
mtf_reps( dis, cur_trial->reps );
|
||||
}
|
||||
|
||||
pos_state = Mf_data_position( e->matchfinder ) & pos_state_mask;
|
||||
prev_byte = Mf_peek( e->matchfinder, 1 );
|
||||
cur_byte = Mf_peek( e->matchfinder, 0 );
|
||||
match_byte = Mf_peek( e->matchfinder, cur_trial->reps[0] + 1 );
|
||||
pos_state = Mb_data_position( &e->eb.mb ) & pos_state_mask;
|
||||
prev_byte = Mb_peek( &e->eb.mb, 1 );
|
||||
cur_byte = Mb_peek( &e->eb.mb, 0 );
|
||||
match_byte = Mb_peek( &e->eb.mb, cur_trial->reps[0] + 1 );
|
||||
|
||||
next_price = cur_trial->price +
|
||||
price0( e->bm_match[cur_state][pos_state] );
|
||||
price0( e->eb.bm_match[cur_state][pos_state] );
|
||||
if( St_is_char( cur_state ) )
|
||||
next_price += LZe_price_literal( e, prev_byte, cur_byte );
|
||||
next_price += LZeb_price_literal( &e->eb, prev_byte, cur_byte );
|
||||
else
|
||||
next_price += LZe_price_matched( e, prev_byte, cur_byte, match_byte );
|
||||
next_price += LZeb_price_matched( &e->eb, prev_byte, cur_byte, match_byte );
|
||||
|
||||
/* try last updates to next trial */
|
||||
next_trial = &e->trials[cur+1];
|
||||
|
||||
Tr_update( next_trial, next_price, -1, cur ); /* literal */
|
||||
|
||||
match_price = cur_trial->price + price1( e->bm_match[cur_state][pos_state] );
|
||||
rep_match_price = match_price + price1( e->bm_rep[cur_state] );
|
||||
match_price = cur_trial->price + price1( e->eb.bm_match[cur_state][pos_state] );
|
||||
rep_match_price = match_price + price1( e->eb.bm_rep[cur_state] );
|
||||
|
||||
if( match_byte == cur_byte && next_trial->dis != 0 &&
|
||||
next_trial->prev_index2 == single_step_trial )
|
||||
{
|
||||
const int price = rep_match_price +
|
||||
LZe_price_shortrep( e, cur_state, pos_state );
|
||||
LZeb_price_shortrep( &e->eb, cur_state, pos_state );
|
||||
if( price <= next_trial->price )
|
||||
{
|
||||
next_trial->price = price;
|
||||
|
@ -550,19 +371,18 @@ static int LZe_sequence_optimizer( struct LZ_encoder * const e,
|
|||
}
|
||||
}
|
||||
|
||||
available_bytes = min( Mf_available_bytes( e->matchfinder ),
|
||||
max_num_trials - 1 - cur );
|
||||
if( available_bytes < min_match_len ) continue;
|
||||
triable_bytes =
|
||||
min( Mb_available_bytes( &e->eb.mb ), max_num_trials - 1 - cur );
|
||||
if( triable_bytes < min_match_len ) continue;
|
||||
|
||||
len_limit = min( e->matchfinder->match_len_limit, available_bytes );
|
||||
len_limit = min( e->match_len_limit, triable_bytes );
|
||||
|
||||
/* try literal + rep0 */
|
||||
if( match_byte != cur_byte && next_trial->prev_index != cur )
|
||||
{
|
||||
const uint8_t * const data = Mf_ptr_to_current_pos( e->matchfinder );
|
||||
const uint8_t * const data = Mb_ptr_to_current_pos( &e->eb.mb );
|
||||
const int dis = cur_trial->reps[0] + 1;
|
||||
const int limit = min( e->matchfinder->match_len_limit + 1,
|
||||
available_bytes );
|
||||
const int limit = min( e->match_len_limit + 1, triable_bytes );
|
||||
len = 1;
|
||||
while( len < limit && data[len-dis] == data[len] ) ++len;
|
||||
if( --len >= min_match_len )
|
||||
|
@ -570,8 +390,8 @@ static int LZe_sequence_optimizer( struct LZ_encoder * const e,
|
|||
const int pos_state2 = ( pos_state + 1 ) & pos_state_mask;
|
||||
const State state2 = St_set_char( cur_state );
|
||||
const int price = next_price +
|
||||
price1( e->bm_match[state2][pos_state2] ) +
|
||||
price1( e->bm_rep[state2] ) +
|
||||
price1( e->eb.bm_match[state2][pos_state2] ) +
|
||||
price1( e->eb.bm_rep[state2] ) +
|
||||
LZe_price_rep0_len( e, len, state2, pos_state2 );
|
||||
while( num_trials < cur + 1 + len )
|
||||
e->trials[++num_trials].price = infinite_price;
|
||||
|
@ -582,7 +402,7 @@ static int LZe_sequence_optimizer( struct LZ_encoder * const e,
|
|||
/* try rep distances */
|
||||
for( rep = 0; rep < num_rep_distances; ++rep )
|
||||
{
|
||||
const uint8_t * const data = Mf_ptr_to_current_pos( e->matchfinder );
|
||||
const uint8_t * const data = Mb_ptr_to_current_pos( &e->eb.mb );
|
||||
int price;
|
||||
const int dis = cur_trial->reps[rep] + 1;
|
||||
|
||||
|
@ -591,7 +411,7 @@ static int LZe_sequence_optimizer( struct LZ_encoder * const e,
|
|||
if( data[len-dis] != data[len] ) break;
|
||||
while( num_trials < cur + len )
|
||||
e->trials[++num_trials].price = infinite_price;
|
||||
price = rep_match_price + LZe_price_rep( e, rep, cur_state, pos_state );
|
||||
price = rep_match_price + LZeb_price_rep( &e->eb, rep, cur_state, pos_state );
|
||||
for( i = min_match_len; i <= len; ++i )
|
||||
Tr_update( &e->trials[cur+i], price +
|
||||
Lp_price( &e->rep_len_prices, i, pos_state ), rep, cur );
|
||||
|
@ -600,9 +420,9 @@ static int LZe_sequence_optimizer( struct LZ_encoder * const e,
|
|||
|
||||
/* try rep + literal + rep0 */
|
||||
{
|
||||
int len2 = len + 1, pos_state2;
|
||||
const int limit = min( e->matchfinder->match_len_limit + len2,
|
||||
available_bytes );
|
||||
int len2 = len + 1;
|
||||
const int limit = min( e->match_len_limit + len2, triable_bytes );
|
||||
int pos_state2;
|
||||
State state2;
|
||||
while( len2 < limit && data[len2-dis] == data[len2] ) ++len2;
|
||||
len2 -= len + 1;
|
||||
|
@ -611,12 +431,12 @@ static int LZe_sequence_optimizer( struct LZ_encoder * const e,
|
|||
pos_state2 = ( pos_state + len ) & pos_state_mask;
|
||||
state2 = St_set_rep( cur_state );
|
||||
price += Lp_price( &e->rep_len_prices, len, pos_state ) +
|
||||
price0( e->bm_match[state2][pos_state2] ) +
|
||||
LZe_price_matched( e, data[len-1], data[len], data[len-dis] );
|
||||
price0( e->eb.bm_match[state2][pos_state2] ) +
|
||||
LZeb_price_matched( &e->eb, data[len-1], data[len], data[len-dis] );
|
||||
pos_state2 = ( pos_state2 + 1 ) & pos_state_mask;
|
||||
state2 = St_set_char( state2 );
|
||||
price += price1( e->bm_match[state2][pos_state2] ) +
|
||||
price1( e->bm_rep[state2] ) +
|
||||
price += price1( e->eb.bm_match[state2][pos_state2] ) +
|
||||
price1( e->eb.bm_rep[state2] ) +
|
||||
LZe_price_rep0_len( e, len2, state2, pos_state2 );
|
||||
while( num_trials < cur + len + 1 + len2 )
|
||||
e->trials[++num_trials].price = infinite_price;
|
||||
|
@ -629,7 +449,7 @@ static int LZe_sequence_optimizer( struct LZ_encoder * const e,
|
|||
{
|
||||
int dis;
|
||||
const int normal_match_price = match_price +
|
||||
price0( e->bm_rep[cur_state] );
|
||||
price0( e->eb.bm_rep[cur_state] );
|
||||
|
||||
while( num_trials < cur + newlen )
|
||||
e->trials[++num_trials].price = infinite_price;
|
||||
|
@ -646,23 +466,22 @@ static int LZe_sequence_optimizer( struct LZ_encoder * const e,
|
|||
/* try match + literal + rep0 */
|
||||
if( len == e->pairs[i].len )
|
||||
{
|
||||
const uint8_t * const data = Mf_ptr_to_current_pos( e->matchfinder );
|
||||
const uint8_t * const data = Mb_ptr_to_current_pos( &e->eb.mb );
|
||||
const int dis2 = dis + 1;
|
||||
int len2 = len + 1;
|
||||
const int limit = min( e->matchfinder->match_len_limit + len2,
|
||||
available_bytes );
|
||||
const int limit = min( e->match_len_limit + len2, triable_bytes );
|
||||
while( len2 < limit && data[len2-dis2] == data[len2] ) ++len2;
|
||||
len2 -= len + 1;
|
||||
if( len2 >= min_match_len )
|
||||
{
|
||||
int pos_state2 = ( pos_state + len ) & pos_state_mask;
|
||||
State state2 = St_set_match( cur_state );
|
||||
price += price0( e->bm_match[state2][pos_state2] ) +
|
||||
LZe_price_matched( e, data[len-1], data[len], data[len-dis2] );
|
||||
price += price0( e->eb.bm_match[state2][pos_state2] ) +
|
||||
LZeb_price_matched( &e->eb, data[len-1], data[len], data[len-dis2] );
|
||||
pos_state2 = ( pos_state2 + 1 ) & pos_state_mask;
|
||||
state2 = St_set_char( state2 );
|
||||
price += price1( e->bm_match[state2][pos_state2] ) +
|
||||
price1( e->bm_rep[state2] ) +
|
||||
price += price1( e->eb.bm_match[state2][pos_state2] ) +
|
||||
price1( e->eb.bm_rep[state2] ) +
|
||||
LZe_price_rep0_len( e, len2, state2, pos_state2 );
|
||||
|
||||
while( num_trials < cur + len + 1 + len2 )
|
||||
|
@ -681,39 +500,39 @@ static int LZe_sequence_optimizer( struct LZ_encoder * const e,
|
|||
|
||||
static bool LZe_encode_member( struct LZ_encoder * const e )
|
||||
{
|
||||
const bool best = ( e->matchfinder->match_len_limit > 12 );
|
||||
const bool best = ( e->match_len_limit > 12 );
|
||||
const int dis_price_count = best ? 1 : 512;
|
||||
const int align_price_count = best ? 1 : dis_align_size;
|
||||
const int price_count = ( e->matchfinder->match_len_limit > 36 ) ? 1013 : 4093;
|
||||
const int price_count = ( e->match_len_limit > 36 ) ? 1013 : 4093;
|
||||
int ahead, i;
|
||||
State * const state = &e->state;
|
||||
State * const state = &e->eb.state;
|
||||
|
||||
if( e->member_finished ) return true;
|
||||
if( Re_member_position( &e->renc ) >= e->member_size_limit )
|
||||
if( e->eb.member_finished ) return true;
|
||||
if( Re_member_position( &e->eb.renc ) >= e->eb.member_size_limit )
|
||||
{
|
||||
if( LZe_full_flush( e, *state ) ) e->member_finished = true;
|
||||
if( LZeb_full_flush( &e->eb ) ) e->eb.member_finished = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if( Mf_data_position( e->matchfinder ) == 0 &&
|
||||
!Mf_finished( e->matchfinder ) ) /* encode first byte */
|
||||
if( Mb_data_position( &e->eb.mb ) == 0 &&
|
||||
!Mb_data_finished( &e->eb.mb ) ) /* encode first byte */
|
||||
{
|
||||
const uint8_t prev_byte = 0;
|
||||
uint8_t cur_byte;
|
||||
if( !Mf_enough_available_bytes( e->matchfinder ) ||
|
||||
!Re_enough_free_bytes( &e->renc ) ) return true;
|
||||
cur_byte = Mf_peek( e->matchfinder, 0 );
|
||||
Re_encode_bit( &e->renc, &e->bm_match[*state][0], 0 );
|
||||
LZe_encode_literal( e, prev_byte, cur_byte );
|
||||
CRC32_update_byte( &e->crc, cur_byte );
|
||||
Mf_get_match_pairs( e->matchfinder, 0 );
|
||||
if( !Mf_move_pos( e->matchfinder ) ) return false;
|
||||
if( !Mb_enough_available_bytes( &e->eb.mb ) ||
|
||||
!Re_enough_free_bytes( &e->eb.renc ) ) return true;
|
||||
cur_byte = Mb_peek( &e->eb.mb, 0 );
|
||||
Re_encode_bit( &e->eb.renc, &e->eb.bm_match[*state][0], 0 );
|
||||
LZeb_encode_literal( &e->eb, prev_byte, cur_byte );
|
||||
CRC32_update_byte( &e->eb.crc, cur_byte );
|
||||
LZe_get_match_pairs( e, 0 );
|
||||
if( !Mb_move_pos( &e->eb.mb ) ) return false;
|
||||
}
|
||||
|
||||
while( !Mf_finished( e->matchfinder ) )
|
||||
while( !Mb_data_finished( &e->eb.mb ) )
|
||||
{
|
||||
if( !Mf_enough_available_bytes( e->matchfinder ) ||
|
||||
!Re_enough_free_bytes( &e->renc ) ) return true;
|
||||
if( !Mb_enough_available_bytes( &e->eb.mb ) ||
|
||||
!Re_enough_free_bytes( &e->eb.renc ) ) return true;
|
||||
if( e->price_counter <= 0 && e->pending_num_pairs == 0 )
|
||||
{
|
||||
e->price_counter = price_count; /* recalculate prices every these bytes */
|
||||
|
@ -723,69 +542,68 @@ static bool LZe_encode_member( struct LZ_encoder * const e )
|
|||
{
|
||||
e->align_price_counter = align_price_count;
|
||||
for( i = 0; i < dis_align_size; ++i )
|
||||
e->align_prices[i] = price_symbol_reversed( e->bm_align, i, dis_align_bits );
|
||||
e->align_prices[i] = price_symbol_reversed( e->eb.bm_align, i, dis_align_bits );
|
||||
}
|
||||
Lp_update_prices( &e->match_len_prices );
|
||||
Lp_update_prices( &e->rep_len_prices );
|
||||
}
|
||||
|
||||
ahead = LZe_sequence_optimizer( e, e->reps, *state );
|
||||
ahead = LZe_sequence_optimizer( e, e->eb.reps, *state );
|
||||
if( ahead <= 0 ) return false; /* can't happen */
|
||||
e->price_counter -= ahead;
|
||||
|
||||
for( i = 0; ahead > 0; )
|
||||
{
|
||||
const int pos_state =
|
||||
( Mf_data_position( e->matchfinder ) - ahead ) & pos_state_mask;
|
||||
( Mb_data_position( &e->eb.mb ) - ahead ) & pos_state_mask;
|
||||
const int dis = e->trials[i].dis;
|
||||
const int len = e->trials[i].price;
|
||||
|
||||
bool bit = ( dis < 0 );
|
||||
Re_encode_bit( &e->renc, &e->bm_match[*state][pos_state], !bit );
|
||||
Re_encode_bit( &e->eb.renc, &e->eb.bm_match[*state][pos_state], !bit );
|
||||
if( bit ) /* literal byte */
|
||||
{
|
||||
const uint8_t prev_byte = Mf_peek( e->matchfinder, ahead + 1 );
|
||||
const uint8_t cur_byte = Mf_peek( e->matchfinder, ahead );
|
||||
CRC32_update_byte( &e->crc, cur_byte );
|
||||
const uint8_t prev_byte = Mb_peek( &e->eb.mb, ahead + 1 );
|
||||
const uint8_t cur_byte = Mb_peek( &e->eb.mb, ahead );
|
||||
CRC32_update_byte( &e->eb.crc, cur_byte );
|
||||
if( St_is_char( *state ) )
|
||||
LZe_encode_literal( e, prev_byte, cur_byte );
|
||||
LZeb_encode_literal( &e->eb, prev_byte, cur_byte );
|
||||
else
|
||||
{
|
||||
const uint8_t match_byte =
|
||||
Mf_peek( e->matchfinder, ahead + e->reps[0] + 1 );
|
||||
LZe_encode_matched( e, prev_byte, cur_byte, match_byte );
|
||||
const uint8_t match_byte = Mb_peek( &e->eb.mb, ahead + e->eb.reps[0] + 1 );
|
||||
LZeb_encode_matched( &e->eb, prev_byte, cur_byte, match_byte );
|
||||
}
|
||||
*state = St_set_char( *state );
|
||||
}
|
||||
else /* match or repeated match */
|
||||
{
|
||||
CRC32_update_buf( &e->crc, Mf_ptr_to_current_pos( e->matchfinder ) - ahead, len );
|
||||
mtf_reps( dis, e->reps );
|
||||
CRC32_update_buf( &e->eb.crc, Mb_ptr_to_current_pos( &e->eb.mb ) - ahead, len );
|
||||
mtf_reps( dis, e->eb.reps );
|
||||
bit = ( dis < num_rep_distances );
|
||||
Re_encode_bit( &e->renc, &e->bm_rep[*state], bit );
|
||||
Re_encode_bit( &e->eb.renc, &e->eb.bm_rep[*state], bit );
|
||||
if( bit ) /* repeated match */
|
||||
{
|
||||
bit = ( dis == 0 );
|
||||
Re_encode_bit( &e->renc, &e->bm_rep0[*state], !bit );
|
||||
Re_encode_bit( &e->eb.renc, &e->eb.bm_rep0[*state], !bit );
|
||||
if( bit )
|
||||
Re_encode_bit( &e->renc, &e->bm_len[*state][pos_state], len > 1 );
|
||||
Re_encode_bit( &e->eb.renc, &e->eb.bm_len[*state][pos_state], len > 1 );
|
||||
else
|
||||
{
|
||||
Re_encode_bit( &e->renc, &e->bm_rep1[*state], dis > 1 );
|
||||
Re_encode_bit( &e->eb.renc, &e->eb.bm_rep1[*state], dis > 1 );
|
||||
if( dis > 1 )
|
||||
Re_encode_bit( &e->renc, &e->bm_rep2[*state], dis > 2 );
|
||||
Re_encode_bit( &e->eb.renc, &e->eb.bm_rep2[*state], dis > 2 );
|
||||
}
|
||||
if( len == 1 ) *state = St_set_short_rep( *state );
|
||||
else
|
||||
{
|
||||
Re_encode_len( &e->renc, &e->rep_len_model, len, pos_state );
|
||||
Re_encode_len( &e->eb.renc, &e->eb.rep_len_model, len, pos_state );
|
||||
Lp_decrement_counter( &e->rep_len_prices, pos_state );
|
||||
*state = St_set_rep( *state );
|
||||
}
|
||||
}
|
||||
else /* match */
|
||||
{
|
||||
LZe_encode_pair( e, dis - num_rep_distances, len, pos_state );
|
||||
LZeb_encode_pair( &e->eb, dis - num_rep_distances, len, pos_state );
|
||||
if( get_slot( dis - num_rep_distances ) >= end_dis_model )
|
||||
--e->align_price_counter;
|
||||
--e->dis_price_counter;
|
||||
|
@ -794,14 +612,14 @@ static bool LZe_encode_member( struct LZ_encoder * const e )
|
|||
}
|
||||
}
|
||||
ahead -= len; i += len;
|
||||
if( Re_member_position( &e->renc ) >= e->member_size_limit )
|
||||
if( Re_member_position( &e->eb.renc ) >= e->eb.member_size_limit )
|
||||
{
|
||||
if( !Mf_dec_pos( e->matchfinder, ahead ) ) return false;
|
||||
if( LZe_full_flush( e, *state ) ) e->member_finished = true;
|
||||
if( !Mb_dec_pos( &e->eb.mb, ahead ) ) return false;
|
||||
if( LZeb_full_flush( &e->eb ) ) e->eb.member_finished = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( LZe_full_flush( e, *state ) ) e->member_finished = true;
|
||||
if( LZeb_full_flush( &e->eb ) ) e->eb.member_finished = true;
|
||||
return true;
|
||||
}
|
||||
|
|
656
encoder.h
656
encoder.h
|
@ -1,5 +1,5 @@
|
|||
/* Lzlib - Compression library for the lzip format
|
||||
Copyright (C) 2009-2014 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2015 Antonio Diaz Diaz.
|
||||
|
||||
This library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -25,475 +25,6 @@
|
|||
Public License.
|
||||
*/
|
||||
|
||||
enum { max_num_trials = 1 << 13,
|
||||
price_shift_bits = 6,
|
||||
price_step_bits = 2 };
|
||||
|
||||
static const uint8_t dis_slots[1<<10] =
|
||||
{
|
||||
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
|
||||
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
|
||||
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
|
||||
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19 };
|
||||
|
||||
static inline uint8_t get_slot( const unsigned dis )
|
||||
{
|
||||
if( dis < (1 << 10) ) return dis_slots[dis];
|
||||
if( dis < (1 << 19) ) return dis_slots[dis>> 9] + 18;
|
||||
if( dis < (1 << 28) ) return dis_slots[dis>>18] + 36;
|
||||
return dis_slots[dis>>27] + 54;
|
||||
}
|
||||
|
||||
|
||||
static const short prob_prices[bit_model_total >> price_step_bits] =
|
||||
{
|
||||
640, 539, 492, 461, 438, 419, 404, 390, 379, 369, 359, 351, 343, 336, 330, 323,
|
||||
318, 312, 307, 302, 298, 293, 289, 285, 281, 277, 274, 270, 267, 264, 261, 258,
|
||||
255, 252, 250, 247, 244, 242, 239, 237, 235, 232, 230, 228, 226, 224, 222, 220,
|
||||
218, 216, 214, 213, 211, 209, 207, 206, 204, 202, 201, 199, 198, 196, 195, 193,
|
||||
192, 190, 189, 188, 186, 185, 184, 182, 181, 180, 178, 177, 176, 175, 174, 172,
|
||||
171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 159, 158, 157, 157, 156,
|
||||
155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 145, 144, 143, 142, 141,
|
||||
140, 140, 139, 138, 137, 136, 136, 135, 134, 133, 133, 132, 131, 130, 130, 129,
|
||||
128, 127, 127, 126, 125, 125, 124, 123, 123, 122, 121, 121, 120, 119, 119, 118,
|
||||
117, 117, 116, 115, 115, 114, 114, 113, 112, 112, 111, 111, 110, 109, 109, 108,
|
||||
108, 107, 106, 106, 105, 105, 104, 104, 103, 103, 102, 101, 101, 100, 100, 99,
|
||||
99, 98, 98, 97, 97, 96, 96, 95, 95, 94, 94, 93, 93, 92, 92, 91,
|
||||
91, 90, 90, 89, 89, 88, 88, 88, 87, 87, 86, 86, 85, 85, 84, 84,
|
||||
83, 83, 83, 82, 82, 81, 81, 80, 80, 80, 79, 79, 78, 78, 77, 77,
|
||||
77, 76, 76, 75, 75, 75, 74, 74, 73, 73, 73, 72, 72, 71, 71, 71,
|
||||
70, 70, 70, 69, 69, 68, 68, 68, 67, 67, 67, 66, 66, 65, 65, 65,
|
||||
64, 64, 64, 63, 63, 63, 62, 62, 61, 61, 61, 60, 60, 60, 59, 59,
|
||||
59, 58, 58, 58, 57, 57, 57, 56, 56, 56, 55, 55, 55, 54, 54, 54,
|
||||
53, 53, 53, 53, 52, 52, 52, 51, 51, 51, 50, 50, 50, 49, 49, 49,
|
||||
48, 48, 48, 48, 47, 47, 47, 46, 46, 46, 45, 45, 45, 45, 44, 44,
|
||||
44, 43, 43, 43, 43, 42, 42, 42, 41, 41, 41, 41, 40, 40, 40, 40,
|
||||
39, 39, 39, 38, 38, 38, 38, 37, 37, 37, 37, 36, 36, 36, 35, 35,
|
||||
35, 35, 34, 34, 34, 34, 33, 33, 33, 33, 32, 32, 32, 32, 31, 31,
|
||||
31, 31, 30, 30, 30, 30, 29, 29, 29, 29, 28, 28, 28, 28, 27, 27,
|
||||
27, 27, 26, 26, 26, 26, 26, 25, 25, 25, 25, 24, 24, 24, 24, 23,
|
||||
23, 23, 23, 22, 22, 22, 22, 22, 21, 21, 21, 21, 20, 20, 20, 20,
|
||||
20, 19, 19, 19, 19, 18, 18, 18, 18, 18, 17, 17, 17, 17, 17, 16,
|
||||
16, 16, 16, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
|
||||
13, 13, 12, 12, 12, 12, 12, 11, 11, 11, 11, 10, 10, 10, 10, 10,
|
||||
9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7,
|
||||
6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4,
|
||||
3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1 };
|
||||
|
||||
static inline int get_price( const int probability )
|
||||
{ return prob_prices[probability >> price_step_bits]; }
|
||||
|
||||
|
||||
static inline int price0( const Bit_model probability )
|
||||
{ return get_price( probability ); }
|
||||
|
||||
static inline int price1( const Bit_model probability )
|
||||
{ return get_price( bit_model_total - probability ); }
|
||||
|
||||
static inline int price_bit( const Bit_model bm, const int bit )
|
||||
{ if( bit ) return price1( bm ); else return price0( bm ); }
|
||||
|
||||
|
||||
static inline int price_symbol( const Bit_model bm[], int symbol,
|
||||
const int num_bits )
|
||||
{
|
||||
int price = 0;
|
||||
symbol |= ( 1 << num_bits );
|
||||
while( symbol > 1 )
|
||||
{
|
||||
const int bit = symbol & 1;
|
||||
symbol >>= 1;
|
||||
price += price_bit( bm[symbol], bit );
|
||||
}
|
||||
return price;
|
||||
}
|
||||
|
||||
|
||||
static inline int price_symbol_reversed( const Bit_model bm[], int symbol,
|
||||
const int num_bits )
|
||||
{
|
||||
int price = 0;
|
||||
int model = 1;
|
||||
int i;
|
||||
for( i = num_bits; i > 0; --i )
|
||||
{
|
||||
const int bit = symbol & 1;
|
||||
price += price_bit( bm[model], bit );
|
||||
model = ( model << 1 ) | bit;
|
||||
symbol >>= 1;
|
||||
}
|
||||
return price;
|
||||
}
|
||||
|
||||
|
||||
static inline int price_matched( const Bit_model bm[], int symbol,
|
||||
int match_byte )
|
||||
{
|
||||
int price = 0;
|
||||
int mask = 0x100;
|
||||
symbol |= mask;
|
||||
|
||||
do {
|
||||
int match_bit, bit;
|
||||
match_byte <<= 1;
|
||||
match_bit = match_byte & mask;
|
||||
symbol <<= 1;
|
||||
bit = symbol & 0x100;
|
||||
price += price_bit( bm[match_bit+(symbol>>9)+mask], bit );
|
||||
mask &= ~(match_byte ^ symbol); /* if( match_bit != bit ) mask = 0; */
|
||||
}
|
||||
while( symbol < 0x10000 );
|
||||
return price;
|
||||
}
|
||||
|
||||
|
||||
struct Pair /* distance-length pair */
|
||||
{
|
||||
int dis;
|
||||
int len;
|
||||
};
|
||||
|
||||
|
||||
enum { /* bytes to keep in buffer before dictionary */
|
||||
before_size = max_num_trials + 1,
|
||||
/* bytes to keep in buffer after pos */
|
||||
after_size = max_num_trials + ( 2 * max_match_len ) + 1,
|
||||
num_prev_positions3 = 1 << 16,
|
||||
num_prev_positions2 = 1 << 10 };
|
||||
|
||||
struct Matchfinder
|
||||
{
|
||||
unsigned long long partial_data_pos;
|
||||
uint8_t * buffer; /* input buffer */
|
||||
int32_t * prev_positions; /* 1 + last seen position of key. else 0 */
|
||||
int32_t * prev_pos_tree; /* previous positions of key */
|
||||
int match_len_limit;
|
||||
int buffer_size;
|
||||
int dictionary_size; /* bytes to keep in buffer before pos */
|
||||
int pos; /* current pos in buffer */
|
||||
int cyclic_pos; /* cycles through [0, dictionary_size] */
|
||||
int stream_pos; /* first byte not yet read from file */
|
||||
int pos_limit; /* when reached, a new block must be read */
|
||||
int cycles;
|
||||
int key4_mask;
|
||||
int num_prev_positions; /* size of prev_positions */
|
||||
bool at_stream_end; /* stream_pos shows real end of file */
|
||||
bool been_flushed;
|
||||
bool flushing;
|
||||
};
|
||||
|
||||
static int Mf_write_data( struct Matchfinder * const mf,
|
||||
const uint8_t * const inbuf, const int size )
|
||||
{
|
||||
const int sz = min( mf->buffer_size - mf->stream_pos, size );
|
||||
if( !mf->at_stream_end && sz > 0 )
|
||||
{
|
||||
memcpy( mf->buffer + mf->stream_pos, inbuf, sz );
|
||||
mf->stream_pos += sz;
|
||||
}
|
||||
return sz;
|
||||
}
|
||||
|
||||
static bool Mf_normalize_pos( struct Matchfinder * const mf );
|
||||
|
||||
static inline void Mf_free( struct Matchfinder * const mf )
|
||||
{
|
||||
free( mf->prev_positions );
|
||||
free( mf->buffer );
|
||||
}
|
||||
|
||||
static inline uint8_t Mf_peek( const struct Matchfinder * const mf,
|
||||
const int distance )
|
||||
{ return mf->buffer[mf->pos-distance]; }
|
||||
|
||||
static inline int Mf_available_bytes( const struct Matchfinder * const mf )
|
||||
{ return mf->stream_pos - mf->pos; }
|
||||
|
||||
static inline unsigned long long
|
||||
Mf_data_position( const struct Matchfinder * const mf )
|
||||
{ return mf->partial_data_pos + mf->pos; }
|
||||
|
||||
static inline void Mf_finish( struct Matchfinder * const mf )
|
||||
{ mf->at_stream_end = true; mf->flushing = false; }
|
||||
|
||||
static inline bool Mf_finished( const struct Matchfinder * const mf )
|
||||
{ return mf->at_stream_end && mf->pos >= mf->stream_pos; }
|
||||
|
||||
static inline bool Mf_flushing_or_end( const struct Matchfinder * const mf )
|
||||
{ return mf->at_stream_end || mf->flushing; }
|
||||
|
||||
static inline int Mf_free_bytes( const struct Matchfinder * const mf )
|
||||
{ if( mf->at_stream_end ) return 0; return mf->buffer_size - mf->stream_pos; }
|
||||
|
||||
static inline bool Mf_enough_available_bytes( const struct Matchfinder * const mf )
|
||||
{
|
||||
return ( mf->pos + after_size <= mf->stream_pos ||
|
||||
( Mf_flushing_or_end( mf ) && mf->pos < mf->stream_pos ) );
|
||||
}
|
||||
|
||||
static inline const uint8_t *
|
||||
Mf_ptr_to_current_pos( const struct Matchfinder * const mf )
|
||||
{ return mf->buffer + mf->pos; }
|
||||
|
||||
static inline bool Mf_dec_pos( struct Matchfinder * const mf,
|
||||
const int ahead )
|
||||
{
|
||||
if( ahead < 0 || mf->pos < ahead ) return false;
|
||||
mf->pos -= ahead;
|
||||
mf->cyclic_pos -= ahead;
|
||||
if( mf->cyclic_pos < 0 ) mf->cyclic_pos += mf->dictionary_size + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline int Mf_true_match_len( const struct Matchfinder * const mf,
|
||||
const int index, const int distance,
|
||||
int len_limit )
|
||||
{
|
||||
const uint8_t * const data = mf->buffer + mf->pos + index;
|
||||
int i = 0;
|
||||
|
||||
if( index + len_limit > Mf_available_bytes( mf ) )
|
||||
len_limit = Mf_available_bytes( mf ) - index;
|
||||
while( i < len_limit && data[i-distance] == data[i] ) ++i;
|
||||
return i;
|
||||
}
|
||||
|
||||
static inline bool Mf_move_pos( struct Matchfinder * const mf )
|
||||
{
|
||||
if( ++mf->cyclic_pos > mf->dictionary_size ) mf->cyclic_pos = 0;
|
||||
if( ++mf->pos >= mf->pos_limit ) return Mf_normalize_pos( mf );
|
||||
return true;
|
||||
}
|
||||
|
||||
static int Mf_get_match_pairs( struct Matchfinder * const mf, struct Pair * pairs );
|
||||
|
||||
|
||||
enum { re_min_free_bytes = 2 * max_num_trials };
|
||||
|
||||
struct Range_encoder
|
||||
{
|
||||
struct Circular_buffer cb;
|
||||
uint64_t low;
|
||||
unsigned long long partial_member_pos;
|
||||
uint32_t range;
|
||||
unsigned ff_count;
|
||||
uint8_t cache;
|
||||
};
|
||||
|
||||
static inline void Re_shift_low( struct Range_encoder * const renc )
|
||||
{
|
||||
const bool carry = ( renc->low > 0xFFFFFFFFU );
|
||||
if( carry || renc->low < 0xFF000000U )
|
||||
{
|
||||
Cb_put_byte( &renc->cb, renc->cache + carry );
|
||||
for( ; renc->ff_count > 0; --renc->ff_count )
|
||||
Cb_put_byte( &renc->cb, 0xFF + carry );
|
||||
renc->cache = renc->low >> 24;
|
||||
}
|
||||
else ++renc->ff_count;
|
||||
renc->low = ( renc->low & 0x00FFFFFFU ) << 8;
|
||||
}
|
||||
|
||||
static inline bool Re_init( struct Range_encoder * const renc )
|
||||
{
|
||||
if( !Cb_init( &renc->cb, 65536 + re_min_free_bytes ) ) return false;
|
||||
renc->low = 0;
|
||||
renc->partial_member_pos = 0;
|
||||
renc->range = 0xFFFFFFFFU;
|
||||
renc->ff_count = 0;
|
||||
renc->cache = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void Re_free( struct Range_encoder * const renc )
|
||||
{ Cb_free( &renc->cb ); }
|
||||
|
||||
static inline unsigned long long
|
||||
Re_member_position( const struct Range_encoder * const renc )
|
||||
{ return renc->partial_member_pos + Cb_used_bytes( &renc->cb ) + renc->ff_count; }
|
||||
|
||||
static inline bool Re_enough_free_bytes( const struct Range_encoder * const renc )
|
||||
{ return Cb_free_bytes( &renc->cb ) >= re_min_free_bytes; }
|
||||
|
||||
static inline int Re_read_data( struct Range_encoder * const renc,
|
||||
uint8_t * const out_buffer, const int out_size )
|
||||
{
|
||||
const int size = Cb_read_data( &renc->cb, out_buffer, out_size );
|
||||
if( size > 0 ) renc->partial_member_pos += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
static inline void Re_flush( struct Range_encoder * const renc )
|
||||
{
|
||||
int i; for( i = 0; i < 5; ++i ) Re_shift_low( renc );
|
||||
renc->low = 0;
|
||||
renc->range = 0xFFFFFFFFU;
|
||||
renc->ff_count = 0;
|
||||
renc->cache = 0;
|
||||
}
|
||||
|
||||
static inline void Re_encode( struct Range_encoder * const renc,
|
||||
const int symbol, const int num_bits )
|
||||
{
|
||||
int i;
|
||||
for( i = num_bits - 1; i >= 0; --i )
|
||||
{
|
||||
renc->range >>= 1;
|
||||
if( (symbol >> i) & 1 ) renc->low += renc->range;
|
||||
if( renc->range <= 0x00FFFFFFU )
|
||||
{ renc->range <<= 8; Re_shift_low( renc ); }
|
||||
}
|
||||
}
|
||||
|
||||
static inline void Re_encode_bit( struct Range_encoder * const renc,
|
||||
Bit_model * const probability, const int bit )
|
||||
{
|
||||
const uint32_t bound = ( renc->range >> bit_model_total_bits ) * *probability;
|
||||
if( !bit )
|
||||
{
|
||||
renc->range = bound;
|
||||
*probability += (bit_model_total - *probability) >> bit_model_move_bits;
|
||||
}
|
||||
else
|
||||
{
|
||||
renc->low += bound;
|
||||
renc->range -= bound;
|
||||
*probability -= *probability >> bit_model_move_bits;
|
||||
}
|
||||
if( renc->range <= 0x00FFFFFFU )
|
||||
{ renc->range <<= 8; Re_shift_low( renc ); }
|
||||
}
|
||||
|
||||
static inline void Re_encode_tree( struct Range_encoder * const renc,
|
||||
Bit_model bm[], const int symbol, const int num_bits )
|
||||
{
|
||||
int mask = ( 1 << ( num_bits - 1 ) );
|
||||
int model = 1;
|
||||
int i;
|
||||
for( i = num_bits; i > 0; --i, mask >>= 1 )
|
||||
{
|
||||
const int bit = ( symbol & mask );
|
||||
Re_encode_bit( renc, &bm[model], bit );
|
||||
model <<= 1;
|
||||
if( bit ) model |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void Re_encode_tree_reversed( struct Range_encoder * const renc,
|
||||
Bit_model bm[], int symbol, const int num_bits )
|
||||
{
|
||||
int model = 1;
|
||||
int i;
|
||||
for( i = num_bits; i > 0; --i )
|
||||
{
|
||||
const int bit = symbol & 1;
|
||||
Re_encode_bit( renc, &bm[model], bit );
|
||||
model = ( model << 1 ) | bit;
|
||||
symbol >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void Re_encode_matched( struct Range_encoder * const renc,
|
||||
Bit_model bm[], int symbol,
|
||||
int match_byte )
|
||||
{
|
||||
int mask = 0x100;
|
||||
symbol |= mask;
|
||||
|
||||
do {
|
||||
int match_bit, bit;
|
||||
match_byte <<= 1;
|
||||
match_bit = match_byte & mask;
|
||||
symbol <<= 1;
|
||||
bit = symbol & 0x100;
|
||||
Re_encode_bit( renc, &bm[match_bit+(symbol>>9)+mask], bit );
|
||||
mask &= ~(match_byte ^ symbol); /* if( match_bit != bit ) mask = 0; */
|
||||
}
|
||||
while( symbol < 0x10000 );
|
||||
}
|
||||
|
||||
static inline void Re_encode_len( struct Range_encoder * const renc,
|
||||
struct Len_model * const lm,
|
||||
int symbol, const int pos_state )
|
||||
{
|
||||
bool bit = ( ( symbol -= min_match_len ) >= len_low_symbols );
|
||||
Re_encode_bit( renc, &lm->choice1, bit );
|
||||
if( !bit )
|
||||
Re_encode_tree( renc, lm->bm_low[pos_state], symbol, len_low_bits );
|
||||
else
|
||||
{
|
||||
bit = ( symbol >= len_low_symbols + len_mid_symbols );
|
||||
Re_encode_bit( renc, &lm->choice2, bit );
|
||||
if( !bit )
|
||||
Re_encode_tree( renc, lm->bm_mid[pos_state],
|
||||
symbol - len_low_symbols, len_mid_bits );
|
||||
else
|
||||
Re_encode_tree( renc, lm->bm_high,
|
||||
symbol - len_low_symbols - len_mid_symbols, len_high_bits );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct Len_prices
|
||||
{
|
||||
const struct Len_model * lm;
|
||||
|
@ -530,15 +61,17 @@ static inline void Lp_update_high_prices( struct Len_prices * const lp )
|
|||
price_symbol( lp->lm->bm_high, len - len_low_symbols - len_mid_symbols, len_high_bits );
|
||||
}
|
||||
|
||||
static inline void Lp_reset( struct Len_prices * const lp )
|
||||
{ int i; for( i = 0; i < pos_states; ++i ) lp->counters[i] = 0; }
|
||||
|
||||
static inline void Lp_init( struct Len_prices * const lp,
|
||||
const struct Len_model * const lm,
|
||||
const int match_len_limit )
|
||||
{
|
||||
int i;
|
||||
lp->lm = lm;
|
||||
lp->len_symbols = match_len_limit + 1 - min_match_len;
|
||||
lp->count = ( match_len_limit > 12 ) ? 1 : lp->len_symbols;
|
||||
for( i = 0; i < pos_states; ++i ) lp->counters[i] = 0;
|
||||
Lp_reset( lp );
|
||||
}
|
||||
|
||||
static inline void Lp_decrement_counter( struct Len_prices * const lp,
|
||||
|
@ -561,9 +94,14 @@ static inline int Lp_price( const struct Len_prices * const lp,
|
|||
{ return lp->prices[pos_state][symbol - min_match_len]; }
|
||||
|
||||
|
||||
struct Pair /* distance-length pair */
|
||||
{
|
||||
int dis;
|
||||
int len;
|
||||
};
|
||||
|
||||
enum { infinite_price = 0x0FFFFFFF,
|
||||
max_marker_size = 16,
|
||||
num_rep_distances = 4, /* must be 4 */
|
||||
max_num_trials = 1 << 13,
|
||||
single_step_trial = -2,
|
||||
dual_step_trial = -1 };
|
||||
|
||||
|
@ -613,31 +151,14 @@ static inline void Tr_update3( struct Trial * const trial, const int pr,
|
|||
|
||||
struct LZ_encoder
|
||||
{
|
||||
unsigned long long member_size_limit;
|
||||
int pending_num_pairs;
|
||||
uint32_t crc;
|
||||
|
||||
Bit_model bm_literal[1<<literal_context_bits][0x300];
|
||||
Bit_model bm_match[states][pos_states];
|
||||
Bit_model bm_rep[states];
|
||||
Bit_model bm_rep0[states];
|
||||
Bit_model bm_rep1[states];
|
||||
Bit_model bm_rep2[states];
|
||||
Bit_model bm_len[states][pos_states];
|
||||
Bit_model bm_dis_slot[len_states][1<<dis_slot_bits];
|
||||
Bit_model bm_dis[modeled_distances-end_dis_model];
|
||||
Bit_model bm_align[dis_align_size];
|
||||
|
||||
struct Matchfinder * matchfinder;
|
||||
struct Range_encoder renc;
|
||||
struct Len_model match_len_model;
|
||||
struct Len_model rep_len_model;
|
||||
struct LZ_encoder_base eb;
|
||||
int cycles;
|
||||
int match_len_limit;
|
||||
struct Len_prices match_len_prices;
|
||||
struct Len_prices rep_len_prices;
|
||||
|
||||
int pending_num_pairs;
|
||||
struct Pair pairs[max_match_len+1];
|
||||
struct Trial trials[max_num_trials];
|
||||
int reps[num_rep_distances];
|
||||
|
||||
int dis_slot_prices[len_states][2*max_dictionary_bits];
|
||||
int dis_prices[len_states][modeled_distances];
|
||||
|
@ -646,18 +167,20 @@ struct LZ_encoder
|
|||
int price_counter;
|
||||
int dis_price_counter;
|
||||
int align_price_counter;
|
||||
State state;
|
||||
bool member_finished;
|
||||
bool been_flushed;
|
||||
};
|
||||
|
||||
static inline bool LZe_member_finished( const struct LZ_encoder * const e )
|
||||
{ return ( e->member_finished && !Cb_used_bytes( &e->renc.cb ) ); }
|
||||
static inline bool Mb_dec_pos( struct Matchfinder_base * const mb,
|
||||
const int ahead )
|
||||
{
|
||||
if( ahead < 0 || mb->pos < ahead ) return false;
|
||||
mb->pos -= ahead;
|
||||
mb->cyclic_pos -= ahead;
|
||||
if( mb->cyclic_pos < 0 ) mb->cyclic_pos += mb->dictionary_size + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void LZe_free( struct LZ_encoder * const e )
|
||||
{ Re_free( &e->renc ); }
|
||||
|
||||
static inline unsigned LZe_crc( const struct LZ_encoder * const e )
|
||||
{ return e->crc ^ 0xFFFFFFFFU; }
|
||||
static int LZe_get_match_pairs( struct LZ_encoder * const e, struct Pair * pairs );
|
||||
|
||||
/* move-to-front dis in/into reps if( dis > 0 ) */
|
||||
static inline void mtf_reps( const int dis, int reps[num_rep_distances] )
|
||||
|
@ -676,26 +199,26 @@ static inline void mtf_reps( const int dis, int reps[num_rep_distances] )
|
|||
}
|
||||
}
|
||||
|
||||
static inline int LZe_price_shortrep( const struct LZ_encoder * const e,
|
||||
static inline int LZeb_price_shortrep( const struct LZ_encoder_base * const eb,
|
||||
const State state, const int pos_state )
|
||||
{
|
||||
return price0( e->bm_rep0[state] ) + price0( e->bm_len[state][pos_state] );
|
||||
return price0( eb->bm_rep0[state] ) + price0( eb->bm_len[state][pos_state] );
|
||||
}
|
||||
|
||||
static inline int LZe_price_rep( const struct LZ_encoder * const e,
|
||||
static inline int LZeb_price_rep( const struct LZ_encoder_base * const eb,
|
||||
const int rep,
|
||||
const State state, const int pos_state )
|
||||
{
|
||||
int price;
|
||||
if( rep == 0 ) return price0( e->bm_rep0[state] ) +
|
||||
price1( e->bm_len[state][pos_state] );
|
||||
price = price1( e->bm_rep0[state] );
|
||||
if( rep == 0 ) return price0( eb->bm_rep0[state] ) +
|
||||
price1( eb->bm_len[state][pos_state] );
|
||||
price = price1( eb->bm_rep0[state] );
|
||||
if( rep == 1 )
|
||||
price += price0( e->bm_rep1[state] );
|
||||
price += price0( eb->bm_rep1[state] );
|
||||
else
|
||||
{
|
||||
price += price1( e->bm_rep1[state] );
|
||||
price += price_bit( e->bm_rep2[state], rep - 2 );
|
||||
price += price1( eb->bm_rep1[state] );
|
||||
price += price_bit( eb->bm_rep2[state], rep - 2 );
|
||||
}
|
||||
return price;
|
||||
}
|
||||
|
@ -704,7 +227,7 @@ static inline int LZe_price_rep0_len( const struct LZ_encoder * const e,
|
|||
const int len,
|
||||
const State state, const int pos_state )
|
||||
{
|
||||
return LZe_price_rep( e, 0, state, pos_state ) +
|
||||
return LZeb_price_rep( &e->eb, 0, state, pos_state ) +
|
||||
Lp_price( &e->rep_len_prices, len, pos_state );
|
||||
}
|
||||
|
||||
|
@ -721,64 +244,15 @@ static inline int LZe_price_pair( const struct LZ_encoder * const e,
|
|||
e->align_prices[dis & (dis_align_size - 1)];
|
||||
}
|
||||
|
||||
static inline int LZe_price_literal( const struct LZ_encoder * const e,
|
||||
uint8_t prev_byte, uint8_t symbol )
|
||||
{ return price_symbol( e->bm_literal[get_lit_state(prev_byte)], symbol, 8 ); }
|
||||
|
||||
static inline int LZe_price_matched( const struct LZ_encoder * const e,
|
||||
uint8_t prev_byte, uint8_t symbol,
|
||||
uint8_t match_byte )
|
||||
{ return price_matched( e->bm_literal[get_lit_state(prev_byte)], symbol,
|
||||
match_byte ); }
|
||||
|
||||
static inline void LZe_encode_literal( struct LZ_encoder * const e,
|
||||
uint8_t prev_byte, uint8_t symbol )
|
||||
{ Re_encode_tree( &e->renc,
|
||||
e->bm_literal[get_lit_state(prev_byte)], symbol, 8 ); }
|
||||
|
||||
static inline void LZe_encode_matched( struct LZ_encoder * const e,
|
||||
uint8_t prev_byte, uint8_t symbol,
|
||||
uint8_t match_byte )
|
||||
{ Re_encode_matched( &e->renc, e->bm_literal[get_lit_state(prev_byte)],
|
||||
symbol, match_byte ); }
|
||||
|
||||
static inline void LZe_encode_pair( struct LZ_encoder * const e,
|
||||
const unsigned dis, const int len,
|
||||
const int pos_state )
|
||||
{
|
||||
const int dis_slot = get_slot( dis );
|
||||
Re_encode_len( &e->renc, &e->match_len_model, len, pos_state );
|
||||
Re_encode_tree( &e->renc, e->bm_dis_slot[get_len_state(len)], dis_slot,
|
||||
dis_slot_bits );
|
||||
|
||||
if( dis_slot >= start_dis_model )
|
||||
{
|
||||
const int direct_bits = ( dis_slot >> 1 ) - 1;
|
||||
const unsigned base = ( 2 | ( dis_slot & 1 ) ) << direct_bits;
|
||||
const unsigned direct_dis = dis - base;
|
||||
|
||||
if( dis_slot < end_dis_model )
|
||||
Re_encode_tree_reversed( &e->renc, e->bm_dis + base - dis_slot - 1,
|
||||
direct_dis, direct_bits );
|
||||
else
|
||||
{
|
||||
Re_encode( &e->renc, direct_dis >> dis_align_bits,
|
||||
direct_bits - dis_align_bits );
|
||||
Re_encode_tree_reversed( &e->renc, e->bm_align, direct_dis, dis_align_bits );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline int LZe_read_match_distances( struct LZ_encoder * const e )
|
||||
{
|
||||
const int num_pairs = Mf_get_match_pairs( e->matchfinder, e->pairs );
|
||||
const int num_pairs = LZe_get_match_pairs( e, e->pairs );
|
||||
if( num_pairs > 0 )
|
||||
{
|
||||
int len = e->pairs[num_pairs-1].len;
|
||||
if( len == e->matchfinder->match_len_limit && len < max_match_len )
|
||||
if( len == e->match_len_limit && len < max_match_len )
|
||||
{
|
||||
len += Mf_true_match_len( e->matchfinder, len,
|
||||
e->pairs[num_pairs-1].dis + 1,
|
||||
len += Mb_true_match_len( &e->eb.mb, len, e->pairs[num_pairs-1].dis + 1,
|
||||
max_match_len - len );
|
||||
e->pairs[num_pairs-1].len = len;
|
||||
}
|
||||
|
@ -786,13 +260,13 @@ static inline int LZe_read_match_distances( struct LZ_encoder * const e )
|
|||
return num_pairs;
|
||||
}
|
||||
|
||||
static inline bool LZe_move_pos( struct LZ_encoder * const e, int n )
|
||||
static inline bool LZe_move_and_update( struct LZ_encoder * const e, int n )
|
||||
{
|
||||
while( true )
|
||||
{
|
||||
if( !Mf_move_pos( e->matchfinder ) ) return false;
|
||||
if( !Mb_move_pos( &e->eb.mb ) ) return false;
|
||||
if( --n <= 0 ) break;
|
||||
Mf_get_match_pairs( e->matchfinder, 0 );
|
||||
LZe_get_match_pairs( e, 0 );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -823,3 +297,47 @@ static inline void LZe_backward( struct LZ_encoder * const e, int cur )
|
|||
cur = prev_index;
|
||||
}
|
||||
}
|
||||
|
||||
enum { num_prev_positions3 = 1 << 16,
|
||||
num_prev_positions2 = 1 << 10 };
|
||||
|
||||
static inline bool LZe_init( struct LZ_encoder * const e,
|
||||
const int dict_size, const int len_limit,
|
||||
const unsigned long long member_size )
|
||||
{
|
||||
enum { before = max_num_trials + 1,
|
||||
/* bytes to keep in buffer after pos */
|
||||
after_size = max_num_trials + ( 2 * max_match_len ) + 1,
|
||||
dict_factor = 2,
|
||||
num_prev_positions23 = num_prev_positions2 + num_prev_positions3,
|
||||
pos_array_factor = 2,
|
||||
min_free_bytes = 2 * max_num_trials };
|
||||
|
||||
if( !LZeb_init( &e->eb, before, dict_size, after_size, dict_factor,
|
||||
num_prev_positions23, pos_array_factor, min_free_bytes,
|
||||
member_size ) ) return false;
|
||||
e->cycles = ( len_limit < max_match_len ) ? 16 + ( len_limit / 2 ) : 256;
|
||||
e->match_len_limit = len_limit;
|
||||
Lp_init( &e->match_len_prices, &e->eb.match_len_model, e->match_len_limit );
|
||||
Lp_init( &e->rep_len_prices, &e->eb.rep_len_model, e->match_len_limit );
|
||||
e->pending_num_pairs = 0;
|
||||
e->num_dis_slots = 2 * real_bits( e->eb.mb.dictionary_size - 1 );
|
||||
e->price_counter = 0;
|
||||
e->dis_price_counter = 0;
|
||||
e->align_price_counter = 0;
|
||||
e->been_flushed = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void LZe_reset( struct LZ_encoder * const e,
|
||||
const unsigned long long member_size )
|
||||
{
|
||||
LZeb_reset( &e->eb, member_size );
|
||||
Lp_reset( &e->match_len_prices );
|
||||
Lp_reset( &e->rep_len_prices );
|
||||
e->pending_num_pairs = 0;
|
||||
e->price_counter = 0;
|
||||
e->dis_price_counter = 0;
|
||||
e->align_price_counter = 0;
|
||||
e->been_flushed = false;
|
||||
}
|
||||
|
|
192
encoder_base.c
Normal file
192
encoder_base.c
Normal file
|
@ -0,0 +1,192 @@
|
|||
/* Lzlib - Compression library for the lzip format
|
||||
Copyright (C) 2009-2015 Antonio Diaz Diaz.
|
||||
|
||||
This library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
As a special exception, you may use this file as part of a free
|
||||
software library without restriction. Specifically, if other files
|
||||
instantiate templates or use macros or inline functions from this
|
||||
file, or you compile this file and link it with other files to
|
||||
produce an executable, this file does not by itself cause the
|
||||
resulting executable to be covered by the GNU General Public
|
||||
License. This exception does not however invalidate any other
|
||||
reasons why the executable file might be covered by the GNU General
|
||||
Public License.
|
||||
*/
|
||||
|
||||
static bool Mb_normalize_pos( struct Matchfinder_base * const mb )
|
||||
{
|
||||
if( mb->pos > mb->stream_pos )
|
||||
{ mb->pos = mb->stream_pos; return false; }
|
||||
if( !mb->at_stream_end )
|
||||
{
|
||||
int i;
|
||||
const int offset = mb->pos - mb->dictionary_size - mb->before_size;
|
||||
const int size = mb->stream_pos - offset;
|
||||
memmove( mb->buffer, mb->buffer + offset, size );
|
||||
mb->partial_data_pos += offset;
|
||||
mb->pos -= offset;
|
||||
mb->stream_pos -= offset;
|
||||
for( i = 0; i < mb->num_prev_positions; ++i )
|
||||
mb->prev_positions[i] -= min( mb->prev_positions[i], offset );
|
||||
for( i = 0; i < mb->pos_array_size; ++i )
|
||||
mb->pos_array[i] -= min( mb->pos_array[i], offset );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool Mb_init( struct Matchfinder_base * const mb,
|
||||
const int before, const int dict_size,
|
||||
const int after_size, const int dict_factor,
|
||||
const int num_prev_positions23,
|
||||
const int pos_array_factor )
|
||||
{
|
||||
const int buffer_size_limit = ( dict_factor * dict_size ) + before + after_size;
|
||||
unsigned size;
|
||||
int i;
|
||||
|
||||
mb->partial_data_pos = 0;
|
||||
mb->before_size = before;
|
||||
mb->after_size = after_size;
|
||||
mb->pos = 0;
|
||||
mb->cyclic_pos = 0;
|
||||
mb->stream_pos = 0;
|
||||
mb->at_stream_end = false;
|
||||
mb->flushing = false;
|
||||
|
||||
mb->buffer_size = max( 65536, buffer_size_limit );
|
||||
mb->buffer = (uint8_t *)malloc( mb->buffer_size );
|
||||
if( !mb->buffer ) return false;
|
||||
mb->dictionary_size = dict_size;
|
||||
mb->pos_limit = mb->buffer_size - after_size;
|
||||
size = 1 << max( 16, real_bits( mb->dictionary_size - 1 ) - 2 );
|
||||
if( mb->dictionary_size > 1 << 26 ) /* 64 MiB */
|
||||
size >>= 1;
|
||||
mb->key4_mask = size - 1;
|
||||
mb->num_prev_positions23 = num_prev_positions23;
|
||||
size += num_prev_positions23;
|
||||
|
||||
mb->num_prev_positions = size;
|
||||
mb->pos_array_size = pos_array_factor * ( mb->dictionary_size + 1 );
|
||||
size += mb->pos_array_size;
|
||||
if( size * sizeof (int32_t) <= size ) mb->prev_positions = 0;
|
||||
else mb->prev_positions = (int32_t *)malloc( size * sizeof (int32_t) );
|
||||
if( !mb->prev_positions ) { free( mb->buffer ); return false; }
|
||||
mb->pos_array = mb->prev_positions + mb->num_prev_positions;
|
||||
for( i = 0; i < mb->num_prev_positions; ++i ) mb->prev_positions[i] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void Mb_adjust_distionary_size( struct Matchfinder_base * const mb )
|
||||
{
|
||||
if( mb->stream_pos < mb->dictionary_size )
|
||||
{
|
||||
int size;
|
||||
mb->buffer_size =
|
||||
mb->dictionary_size =
|
||||
mb->pos_limit = max( min_dictionary_size, mb->stream_pos );
|
||||
size = 1 << max( 16, real_bits( mb->dictionary_size - 1 ) - 2 );
|
||||
if( mb->dictionary_size > 1 << 26 )
|
||||
size >>= 1;
|
||||
mb->key4_mask = size - 1;
|
||||
size += mb->num_prev_positions23;
|
||||
mb->num_prev_positions = size;
|
||||
mb->pos_array = mb->prev_positions + mb->num_prev_positions;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void Mb_reset( struct Matchfinder_base * const mb )
|
||||
{
|
||||
int i;
|
||||
if( mb->stream_pos > mb->pos )
|
||||
memmove( mb->buffer, mb->buffer + mb->pos, mb->stream_pos - mb->pos );
|
||||
mb->partial_data_pos = 0;
|
||||
mb->stream_pos -= mb->pos;
|
||||
mb->pos = 0;
|
||||
mb->cyclic_pos = 0;
|
||||
mb->at_stream_end = false;
|
||||
mb->flushing = false;
|
||||
for( i = 0; i < mb->num_prev_positions; ++i ) mb->prev_positions[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
/* End Of Stream mark => (dis == 0xFFFFFFFFU, len == min_match_len) */
|
||||
static bool LZeb_full_flush( struct LZ_encoder_base * const eb )
|
||||
{
|
||||
int i;
|
||||
const int pos_state = Mb_data_position( &eb->mb ) & pos_state_mask;
|
||||
const State state = eb->state;
|
||||
File_trailer trailer;
|
||||
if( eb->member_finished ||
|
||||
Cb_free_bytes( &eb->renc.cb ) < max_marker_size + Ft_size )
|
||||
return false;
|
||||
Re_encode_bit( &eb->renc, &eb->bm_match[state][pos_state], 1 );
|
||||
Re_encode_bit( &eb->renc, &eb->bm_rep[state], 0 );
|
||||
LZeb_encode_pair( eb, 0xFFFFFFFFU, min_match_len, pos_state );
|
||||
Re_flush( &eb->renc );
|
||||
Ft_set_data_crc( trailer, LZeb_crc( eb ) );
|
||||
Ft_set_data_size( trailer, Mb_data_position( &eb->mb ) );
|
||||
Ft_set_member_size( trailer, Re_member_position( &eb->renc ) + Ft_size );
|
||||
for( i = 0; i < Ft_size; ++i )
|
||||
Cb_put_byte( &eb->renc.cb, trailer[i] );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Sync Flush mark => (dis == 0xFFFFFFFFU, len == min_match_len + 1) */
|
||||
static bool LZeb_sync_flush( struct LZ_encoder_base * const eb )
|
||||
{
|
||||
int i;
|
||||
const int pos_state = Mb_data_position( &eb->mb ) & pos_state_mask;
|
||||
const State state = eb->state;
|
||||
if( eb->member_finished || Cb_free_bytes( &eb->renc.cb ) < 2 * max_marker_size )
|
||||
return false;
|
||||
for( i = 0; i < 2; ++i ) /* 2 consecutive markers guarantee decoding */
|
||||
{
|
||||
Re_encode_bit( &eb->renc, &eb->bm_match[state][pos_state], 1 );
|
||||
Re_encode_bit( &eb->renc, &eb->bm_rep[state], 0 );
|
||||
LZeb_encode_pair( eb, 0xFFFFFFFFU, min_match_len + 1, pos_state );
|
||||
Re_flush( &eb->renc );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void LZeb_reset( struct LZ_encoder_base * const eb,
|
||||
const unsigned long long member_size )
|
||||
{
|
||||
int i;
|
||||
Mb_reset( &eb->mb );
|
||||
eb->member_size_limit = member_size - Ft_size - max_marker_size;
|
||||
eb->crc = 0xFFFFFFFFU;
|
||||
Bm_array_init( eb->bm_literal[0], (1 << literal_context_bits) * 0x300 );
|
||||
Bm_array_init( eb->bm_match[0], states * pos_states );
|
||||
Bm_array_init( eb->bm_rep, states );
|
||||
Bm_array_init( eb->bm_rep0, states );
|
||||
Bm_array_init( eb->bm_rep1, states );
|
||||
Bm_array_init( eb->bm_rep2, states );
|
||||
Bm_array_init( eb->bm_len[0], states * pos_states );
|
||||
Bm_array_init( eb->bm_dis_slot[0], len_states * (1 << dis_slot_bits) );
|
||||
Bm_array_init( eb->bm_dis, modeled_distances - end_dis_model );
|
||||
Bm_array_init( eb->bm_align, dis_align_size );
|
||||
Lm_init( &eb->match_len_model );
|
||||
Lm_init( &eb->rep_len_model );
|
||||
Re_reset( &eb->renc );
|
||||
for( i = 0; i < num_rep_distances; ++i ) eb->reps[i] = 0;
|
||||
eb->state = 0;
|
||||
eb->member_finished = false;
|
||||
}
|
587
encoder_base.h
Normal file
587
encoder_base.h
Normal file
|
@ -0,0 +1,587 @@
|
|||
/* Lzlib - Compression library for the lzip format
|
||||
Copyright (C) 2009-2015 Antonio Diaz Diaz.
|
||||
|
||||
This library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
As a special exception, you may use this file as part of a free
|
||||
software library without restriction. Specifically, if other files
|
||||
instantiate templates or use macros or inline functions from this
|
||||
file, or you compile this file and link it with other files to
|
||||
produce an executable, this file does not by itself cause the
|
||||
resulting executable to be covered by the GNU General Public
|
||||
License. This exception does not however invalidate any other
|
||||
reasons why the executable file might be covered by the GNU General
|
||||
Public License.
|
||||
*/
|
||||
|
||||
enum { price_shift_bits = 6,
|
||||
price_step_bits = 2 };
|
||||
|
||||
static const uint8_t dis_slots[1<<10] =
|
||||
{
|
||||
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
|
||||
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
|
||||
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
|
||||
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19 };
|
||||
|
||||
static inline uint8_t get_slot( const unsigned dis )
|
||||
{
|
||||
if( dis < (1 << 10) ) return dis_slots[dis];
|
||||
if( dis < (1 << 19) ) return dis_slots[dis>> 9] + 18;
|
||||
if( dis < (1 << 28) ) return dis_slots[dis>>18] + 36;
|
||||
return dis_slots[dis>>27] + 54;
|
||||
}
|
||||
|
||||
|
||||
static const short prob_prices[bit_model_total >> price_step_bits] =
|
||||
{
|
||||
640, 539, 492, 461, 438, 419, 404, 390, 379, 369, 359, 351, 343, 336, 330, 323,
|
||||
318, 312, 307, 302, 298, 293, 289, 285, 281, 277, 274, 270, 267, 264, 261, 258,
|
||||
255, 252, 250, 247, 244, 242, 239, 237, 235, 232, 230, 228, 226, 224, 222, 220,
|
||||
218, 216, 214, 213, 211, 209, 207, 206, 204, 202, 201, 199, 198, 196, 195, 193,
|
||||
192, 190, 189, 188, 186, 185, 184, 182, 181, 180, 178, 177, 176, 175, 174, 172,
|
||||
171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 159, 158, 157, 157, 156,
|
||||
155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 145, 144, 143, 142, 141,
|
||||
140, 140, 139, 138, 137, 136, 136, 135, 134, 133, 133, 132, 131, 130, 130, 129,
|
||||
128, 127, 127, 126, 125, 125, 124, 123, 123, 122, 121, 121, 120, 119, 119, 118,
|
||||
117, 117, 116, 115, 115, 114, 114, 113, 112, 112, 111, 111, 110, 109, 109, 108,
|
||||
108, 107, 106, 106, 105, 105, 104, 104, 103, 103, 102, 101, 101, 100, 100, 99,
|
||||
99, 98, 98, 97, 97, 96, 96, 95, 95, 94, 94, 93, 93, 92, 92, 91,
|
||||
91, 90, 90, 89, 89, 88, 88, 88, 87, 87, 86, 86, 85, 85, 84, 84,
|
||||
83, 83, 83, 82, 82, 81, 81, 80, 80, 80, 79, 79, 78, 78, 77, 77,
|
||||
77, 76, 76, 75, 75, 75, 74, 74, 73, 73, 73, 72, 72, 71, 71, 71,
|
||||
70, 70, 70, 69, 69, 68, 68, 68, 67, 67, 67, 66, 66, 65, 65, 65,
|
||||
64, 64, 64, 63, 63, 63, 62, 62, 61, 61, 61, 60, 60, 60, 59, 59,
|
||||
59, 58, 58, 58, 57, 57, 57, 56, 56, 56, 55, 55, 55, 54, 54, 54,
|
||||
53, 53, 53, 53, 52, 52, 52, 51, 51, 51, 50, 50, 50, 49, 49, 49,
|
||||
48, 48, 48, 48, 47, 47, 47, 46, 46, 46, 45, 45, 45, 45, 44, 44,
|
||||
44, 43, 43, 43, 43, 42, 42, 42, 41, 41, 41, 41, 40, 40, 40, 40,
|
||||
39, 39, 39, 38, 38, 38, 38, 37, 37, 37, 37, 36, 36, 36, 35, 35,
|
||||
35, 35, 34, 34, 34, 34, 33, 33, 33, 33, 32, 32, 32, 32, 31, 31,
|
||||
31, 31, 30, 30, 30, 30, 29, 29, 29, 29, 28, 28, 28, 28, 27, 27,
|
||||
27, 27, 26, 26, 26, 26, 26, 25, 25, 25, 25, 24, 24, 24, 24, 23,
|
||||
23, 23, 23, 22, 22, 22, 22, 22, 21, 21, 21, 21, 20, 20, 20, 20,
|
||||
20, 19, 19, 19, 19, 18, 18, 18, 18, 18, 17, 17, 17, 17, 17, 16,
|
||||
16, 16, 16, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
|
||||
13, 13, 12, 12, 12, 12, 12, 11, 11, 11, 11, 10, 10, 10, 10, 10,
|
||||
9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7,
|
||||
6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4,
|
||||
3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1 };
|
||||
|
||||
static inline int get_price( const int probability )
|
||||
{ return prob_prices[probability >> price_step_bits]; }
|
||||
|
||||
|
||||
static inline int price0( const Bit_model probability )
|
||||
{ return get_price( probability ); }
|
||||
|
||||
static inline int price1( const Bit_model probability )
|
||||
{ return get_price( bit_model_total - probability ); }
|
||||
|
||||
static inline int price_bit( const Bit_model bm, const int bit )
|
||||
{ if( bit ) return price1( bm ); else return price0( bm ); }
|
||||
|
||||
|
||||
static inline int price_symbol( const Bit_model bm[], int symbol,
|
||||
const int num_bits )
|
||||
{
|
||||
int price = 0;
|
||||
symbol |= ( 1 << num_bits );
|
||||
while( symbol > 1 )
|
||||
{
|
||||
const int bit = symbol & 1;
|
||||
symbol >>= 1;
|
||||
price += price_bit( bm[symbol], bit );
|
||||
}
|
||||
return price;
|
||||
}
|
||||
|
||||
|
||||
static inline int price_symbol_reversed( const Bit_model bm[], int symbol,
|
||||
const int num_bits )
|
||||
{
|
||||
int price = 0;
|
||||
int model = 1;
|
||||
int i;
|
||||
for( i = num_bits; i > 0; --i )
|
||||
{
|
||||
const int bit = symbol & 1;
|
||||
price += price_bit( bm[model], bit );
|
||||
model = ( model << 1 ) | bit;
|
||||
symbol >>= 1;
|
||||
}
|
||||
return price;
|
||||
}
|
||||
|
||||
|
||||
static inline int price_matched( const Bit_model bm[], int symbol,
|
||||
int match_byte )
|
||||
{
|
||||
int price = 0;
|
||||
int mask = 0x100;
|
||||
symbol |= mask;
|
||||
|
||||
do {
|
||||
int match_bit, bit;
|
||||
match_byte <<= 1;
|
||||
match_bit = match_byte & mask;
|
||||
symbol <<= 1;
|
||||
bit = symbol & 0x100;
|
||||
price += price_bit( bm[match_bit+(symbol>>9)+mask], bit );
|
||||
mask &= ~(match_byte ^ symbol); /* if( match_bit != bit ) mask = 0; */
|
||||
}
|
||||
while( symbol < 0x10000 );
|
||||
return price;
|
||||
}
|
||||
|
||||
|
||||
struct Matchfinder_base
|
||||
{
|
||||
unsigned long long partial_data_pos;
|
||||
uint8_t * buffer; /* input buffer */
|
||||
int32_t * prev_positions; /* 1 + last seen position of key. else 0 */
|
||||
int32_t * pos_array; /* may be tree or chain */
|
||||
int before_size; /* bytes to keep in buffer before dictionary */
|
||||
int after_size; /* bytes to keep in buffer after pos */
|
||||
int buffer_size;
|
||||
int dictionary_size; /* bytes to keep in buffer before pos */
|
||||
int pos; /* current pos in buffer */
|
||||
int cyclic_pos; /* cycles through [0, dictionary_size] */
|
||||
int stream_pos; /* first byte not yet read from file */
|
||||
int pos_limit; /* when reached, a new block must be read */
|
||||
int key4_mask;
|
||||
int num_prev_positions23;
|
||||
int num_prev_positions; /* size of prev_positions */
|
||||
int pos_array_size;
|
||||
bool at_stream_end; /* stream_pos shows real end of file */
|
||||
bool flushing;
|
||||
};
|
||||
|
||||
static bool Mb_normalize_pos( struct Matchfinder_base * const mb );
|
||||
|
||||
static bool Mb_init( struct Matchfinder_base * const mb,
|
||||
const int before, const int dict_size,
|
||||
const int after_size, const int dict_factor,
|
||||
const int num_prev_positions23,
|
||||
const int pos_array_factor );
|
||||
|
||||
static inline void Mb_free( struct Matchfinder_base * const mb )
|
||||
{ free( mb->prev_positions ); free( mb->buffer ); }
|
||||
|
||||
static inline uint8_t Mb_peek( const struct Matchfinder_base * const mb,
|
||||
const int distance )
|
||||
{ return mb->buffer[mb->pos-distance]; }
|
||||
|
||||
static inline int Mb_available_bytes( const struct Matchfinder_base * const mb )
|
||||
{ return mb->stream_pos - mb->pos; }
|
||||
|
||||
static inline unsigned long long
|
||||
Mb_data_position( const struct Matchfinder_base * const mb )
|
||||
{ return mb->partial_data_pos + mb->pos; }
|
||||
|
||||
static inline void Mb_finish( struct Matchfinder_base * const mb )
|
||||
{ mb->at_stream_end = true; mb->flushing = false; }
|
||||
|
||||
static inline bool Mb_data_finished( const struct Matchfinder_base * const mb )
|
||||
{ return mb->at_stream_end && !mb->flushing && mb->pos >= mb->stream_pos; }
|
||||
|
||||
static inline bool Mb_flushing_or_end( const struct Matchfinder_base * const mb )
|
||||
{ return mb->at_stream_end || mb->flushing; }
|
||||
|
||||
static inline int Mb_free_bytes( const struct Matchfinder_base * const mb )
|
||||
{ if( Mb_flushing_or_end( mb ) ) return 0;
|
||||
return mb->buffer_size - mb->stream_pos; }
|
||||
|
||||
static inline bool Mb_enough_available_bytes( const struct Matchfinder_base * const mb )
|
||||
{
|
||||
return ( mb->pos + mb->after_size <= mb->stream_pos ||
|
||||
( Mb_flushing_or_end( mb ) && mb->pos < mb->stream_pos ) );
|
||||
}
|
||||
|
||||
static inline const uint8_t *
|
||||
Mb_ptr_to_current_pos( const struct Matchfinder_base * const mb )
|
||||
{ return mb->buffer + mb->pos; }
|
||||
|
||||
static int Mb_write_data( struct Matchfinder_base * const mb,
|
||||
const uint8_t * const inbuf, const int size )
|
||||
{
|
||||
const int sz = min( mb->buffer_size - mb->stream_pos, size );
|
||||
if( Mb_flushing_or_end( mb ) || sz <= 0 ) return 0;
|
||||
memcpy( mb->buffer + mb->stream_pos, inbuf, sz );
|
||||
mb->stream_pos += sz;
|
||||
return sz;
|
||||
}
|
||||
|
||||
static inline int Mb_true_match_len( const struct Matchfinder_base * const mb,
|
||||
const int index, const int distance,
|
||||
int len_limit )
|
||||
{
|
||||
const uint8_t * const data = mb->buffer + mb->pos + index;
|
||||
int i = 0;
|
||||
if( index + len_limit > Mb_available_bytes( mb ) )
|
||||
len_limit = Mb_available_bytes( mb ) - index;
|
||||
while( i < len_limit && data[i-distance] == data[i] ) ++i;
|
||||
return i;
|
||||
}
|
||||
|
||||
static inline bool Mb_move_pos( struct Matchfinder_base * const mb )
|
||||
{
|
||||
if( ++mb->cyclic_pos > mb->dictionary_size ) mb->cyclic_pos = 0;
|
||||
if( ++mb->pos >= mb->pos_limit ) return Mb_normalize_pos( mb );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
struct Range_encoder
|
||||
{
|
||||
struct Circular_buffer cb;
|
||||
int min_free_bytes;
|
||||
uint64_t low;
|
||||
unsigned long long partial_member_pos;
|
||||
uint32_t range;
|
||||
unsigned ff_count;
|
||||
uint8_t cache;
|
||||
File_header header;
|
||||
};
|
||||
|
||||
static inline void Re_shift_low( struct Range_encoder * const renc )
|
||||
{
|
||||
const bool carry = ( renc->low > 0xFFFFFFFFU );
|
||||
if( carry || renc->low < 0xFF000000U )
|
||||
{
|
||||
Cb_put_byte( &renc->cb, renc->cache + carry );
|
||||
for( ; renc->ff_count > 0; --renc->ff_count )
|
||||
Cb_put_byte( &renc->cb, 0xFF + carry );
|
||||
renc->cache = renc->low >> 24;
|
||||
}
|
||||
else ++renc->ff_count;
|
||||
renc->low = ( renc->low & 0x00FFFFFFU ) << 8;
|
||||
}
|
||||
|
||||
static inline void Re_reset( struct Range_encoder * const renc )
|
||||
{
|
||||
int i;
|
||||
Cb_reset( &renc->cb );
|
||||
renc->low = 0;
|
||||
renc->partial_member_pos = 0;
|
||||
renc->range = 0xFFFFFFFFU;
|
||||
renc->ff_count = 0;
|
||||
renc->cache = 0;
|
||||
for( i = 0; i < Fh_size; ++i )
|
||||
Cb_put_byte( &renc->cb, renc->header[i] );
|
||||
}
|
||||
|
||||
static inline bool Re_init( struct Range_encoder * const renc,
|
||||
const unsigned dictionary_size,
|
||||
const int min_free_bytes )
|
||||
{
|
||||
if( !Cb_init( &renc->cb, 65536 + min_free_bytes ) ) return false;
|
||||
renc->min_free_bytes = min_free_bytes;
|
||||
Fh_set_magic( renc->header );
|
||||
Fh_set_dictionary_size( renc->header, dictionary_size );
|
||||
Re_reset( renc );
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void Re_free( struct Range_encoder * const renc )
|
||||
{ Cb_free( &renc->cb ); }
|
||||
|
||||
static inline unsigned long long
|
||||
Re_member_position( const struct Range_encoder * const renc )
|
||||
{ return renc->partial_member_pos + Cb_used_bytes( &renc->cb ) + renc->ff_count; }
|
||||
|
||||
static inline bool Re_enough_free_bytes( const struct Range_encoder * const renc )
|
||||
{ return Cb_free_bytes( &renc->cb ) >= renc->min_free_bytes; }
|
||||
|
||||
static inline int Re_read_data( struct Range_encoder * const renc,
|
||||
uint8_t * const out_buffer, const int out_size )
|
||||
{
|
||||
const int size = Cb_read_data( &renc->cb, out_buffer, out_size );
|
||||
if( size > 0 ) renc->partial_member_pos += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
static inline void Re_flush( struct Range_encoder * const renc )
|
||||
{
|
||||
int i; for( i = 0; i < 5; ++i ) Re_shift_low( renc );
|
||||
renc->low = 0;
|
||||
renc->range = 0xFFFFFFFFU;
|
||||
renc->ff_count = 0;
|
||||
renc->cache = 0;
|
||||
}
|
||||
|
||||
static inline void Re_encode( struct Range_encoder * const renc,
|
||||
const int symbol, const int num_bits )
|
||||
{
|
||||
int i;
|
||||
for( i = num_bits - 1; i >= 0; --i )
|
||||
{
|
||||
renc->range >>= 1;
|
||||
if( (symbol >> i) & 1 ) renc->low += renc->range;
|
||||
if( renc->range <= 0x00FFFFFFU )
|
||||
{ renc->range <<= 8; Re_shift_low( renc ); }
|
||||
}
|
||||
}
|
||||
|
||||
static inline void Re_encode_bit( struct Range_encoder * const renc,
|
||||
Bit_model * const probability, const int bit )
|
||||
{
|
||||
const uint32_t bound = ( renc->range >> bit_model_total_bits ) * *probability;
|
||||
if( !bit )
|
||||
{
|
||||
renc->range = bound;
|
||||
*probability += (bit_model_total - *probability) >> bit_model_move_bits;
|
||||
}
|
||||
else
|
||||
{
|
||||
renc->low += bound;
|
||||
renc->range -= bound;
|
||||
*probability -= *probability >> bit_model_move_bits;
|
||||
}
|
||||
if( renc->range <= 0x00FFFFFFU )
|
||||
{ renc->range <<= 8; Re_shift_low( renc ); }
|
||||
}
|
||||
|
||||
static inline void Re_encode_tree( struct Range_encoder * const renc,
|
||||
Bit_model bm[], const int symbol, const int num_bits )
|
||||
{
|
||||
int mask = ( 1 << ( num_bits - 1 ) );
|
||||
int model = 1;
|
||||
int i;
|
||||
for( i = num_bits; i > 0; --i, mask >>= 1 )
|
||||
{
|
||||
const int bit = ( symbol & mask );
|
||||
Re_encode_bit( renc, &bm[model], bit );
|
||||
model <<= 1;
|
||||
if( bit ) model |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void Re_encode_tree_reversed( struct Range_encoder * const renc,
|
||||
Bit_model bm[], int symbol, const int num_bits )
|
||||
{
|
||||
int model = 1;
|
||||
int i;
|
||||
for( i = num_bits; i > 0; --i )
|
||||
{
|
||||
const int bit = symbol & 1;
|
||||
Re_encode_bit( renc, &bm[model], bit );
|
||||
model = ( model << 1 ) | bit;
|
||||
symbol >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void Re_encode_matched( struct Range_encoder * const renc,
|
||||
Bit_model bm[], int symbol,
|
||||
int match_byte )
|
||||
{
|
||||
int mask = 0x100;
|
||||
symbol |= mask;
|
||||
|
||||
do {
|
||||
int match_bit, bit;
|
||||
match_byte <<= 1;
|
||||
match_bit = match_byte & mask;
|
||||
symbol <<= 1;
|
||||
bit = symbol & 0x100;
|
||||
Re_encode_bit( renc, &bm[match_bit+(symbol>>9)+mask], bit );
|
||||
mask &= ~(match_byte ^ symbol); /* if( match_bit != bit ) mask = 0; */
|
||||
}
|
||||
while( symbol < 0x10000 );
|
||||
}
|
||||
|
||||
static inline void Re_encode_len( struct Range_encoder * const renc,
|
||||
struct Len_model * const lm,
|
||||
int symbol, const int pos_state )
|
||||
{
|
||||
bool bit = ( ( symbol -= min_match_len ) >= len_low_symbols );
|
||||
Re_encode_bit( renc, &lm->choice1, bit );
|
||||
if( !bit )
|
||||
Re_encode_tree( renc, lm->bm_low[pos_state], symbol, len_low_bits );
|
||||
else
|
||||
{
|
||||
bit = ( symbol >= len_low_symbols + len_mid_symbols );
|
||||
Re_encode_bit( renc, &lm->choice2, bit );
|
||||
if( !bit )
|
||||
Re_encode_tree( renc, lm->bm_mid[pos_state],
|
||||
symbol - len_low_symbols, len_mid_bits );
|
||||
else
|
||||
Re_encode_tree( renc, lm->bm_high,
|
||||
symbol - len_low_symbols - len_mid_symbols, len_high_bits );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum { max_marker_size = 16,
|
||||
num_rep_distances = 4 }; /* must be 4 */
|
||||
|
||||
struct LZ_encoder_base
|
||||
{
|
||||
struct Matchfinder_base mb;
|
||||
unsigned long long member_size_limit;
|
||||
uint32_t crc;
|
||||
|
||||
Bit_model bm_literal[1<<literal_context_bits][0x300];
|
||||
Bit_model bm_match[states][pos_states];
|
||||
Bit_model bm_rep[states];
|
||||
Bit_model bm_rep0[states];
|
||||
Bit_model bm_rep1[states];
|
||||
Bit_model bm_rep2[states];
|
||||
Bit_model bm_len[states][pos_states];
|
||||
Bit_model bm_dis_slot[len_states][1<<dis_slot_bits];
|
||||
Bit_model bm_dis[modeled_distances-end_dis_model];
|
||||
Bit_model bm_align[dis_align_size];
|
||||
struct Len_model match_len_model;
|
||||
struct Len_model rep_len_model;
|
||||
struct Range_encoder renc;
|
||||
int reps[num_rep_distances];
|
||||
State state;
|
||||
bool member_finished;
|
||||
};
|
||||
|
||||
static void LZeb_reset( struct LZ_encoder_base * const eb,
|
||||
const unsigned long long member_size );
|
||||
|
||||
static inline bool LZeb_init( struct LZ_encoder_base * const eb,
|
||||
const int before, const int dict_size,
|
||||
const int after_size, const int dict_factor,
|
||||
const int num_prev_positions23,
|
||||
const int pos_array_factor,
|
||||
const int min_free_bytes,
|
||||
const unsigned long long member_size )
|
||||
{
|
||||
if( !Mb_init( &eb->mb, before, dict_size, after_size, dict_factor,
|
||||
num_prev_positions23, pos_array_factor ) ) return false;
|
||||
if( !Re_init( &eb->renc, eb->mb.dictionary_size, min_free_bytes ) )
|
||||
return false;
|
||||
LZeb_reset( eb, member_size );
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool LZeb_member_finished( const struct LZ_encoder_base * const eb )
|
||||
{ return ( eb->member_finished && !Cb_used_bytes( &eb->renc.cb ) ); }
|
||||
|
||||
static inline void LZeb_free( struct LZ_encoder_base * const eb )
|
||||
{ Re_free( &eb->renc ); Mb_free( &eb->mb ); }
|
||||
|
||||
static inline unsigned LZeb_crc( const struct LZ_encoder_base * const eb )
|
||||
{ return eb->crc ^ 0xFFFFFFFFU; }
|
||||
|
||||
static inline int LZeb_price_literal( const struct LZ_encoder_base * const eb,
|
||||
uint8_t prev_byte, uint8_t symbol )
|
||||
{ return price_symbol( eb->bm_literal[get_lit_state(prev_byte)], symbol, 8 ); }
|
||||
|
||||
static inline int LZeb_price_matched( const struct LZ_encoder_base * const eb,
|
||||
uint8_t prev_byte, uint8_t symbol,
|
||||
uint8_t match_byte )
|
||||
{ return price_matched( eb->bm_literal[get_lit_state(prev_byte)], symbol,
|
||||
match_byte ); }
|
||||
|
||||
static inline void LZeb_encode_literal( struct LZ_encoder_base * const eb,
|
||||
uint8_t prev_byte, uint8_t symbol )
|
||||
{ Re_encode_tree( &eb->renc,
|
||||
eb->bm_literal[get_lit_state(prev_byte)], symbol, 8 ); }
|
||||
|
||||
static inline void LZeb_encode_matched( struct LZ_encoder_base * const eb,
|
||||
uint8_t prev_byte, uint8_t symbol,
|
||||
uint8_t match_byte )
|
||||
{ Re_encode_matched( &eb->renc, eb->bm_literal[get_lit_state(prev_byte)],
|
||||
symbol, match_byte ); }
|
||||
|
||||
static inline void LZeb_encode_pair( struct LZ_encoder_base * const eb,
|
||||
const unsigned dis, const int len,
|
||||
const int pos_state )
|
||||
{
|
||||
const int dis_slot = get_slot( dis );
|
||||
Re_encode_len( &eb->renc, &eb->match_len_model, len, pos_state );
|
||||
Re_encode_tree( &eb->renc, eb->bm_dis_slot[get_len_state(len)], dis_slot,
|
||||
dis_slot_bits );
|
||||
|
||||
if( dis_slot >= start_dis_model )
|
||||
{
|
||||
const int direct_bits = ( dis_slot >> 1 ) - 1;
|
||||
const unsigned base = ( 2 | ( dis_slot & 1 ) ) << direct_bits;
|
||||
const unsigned direct_dis = dis - base;
|
||||
|
||||
if( dis_slot < end_dis_model )
|
||||
Re_encode_tree_reversed( &eb->renc, eb->bm_dis + base - dis_slot - 1,
|
||||
direct_dis, direct_bits );
|
||||
else
|
||||
{
|
||||
Re_encode( &eb->renc, direct_dis >> dis_align_bits,
|
||||
direct_bits - dis_align_bits );
|
||||
Re_encode_tree_reversed( &eb->renc, eb->bm_align, direct_dis, dis_align_bits );
|
||||
}
|
||||
}
|
||||
}
|
203
fast_encoder.c
Normal file
203
fast_encoder.c
Normal file
|
@ -0,0 +1,203 @@
|
|||
/* Lzlib - Compression library for the lzip format
|
||||
Copyright (C) 2009-2015 Antonio Diaz Diaz.
|
||||
|
||||
This library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
As a special exception, you may use this file as part of a free
|
||||
software library without restriction. Specifically, if other files
|
||||
instantiate templates or use macros or inline functions from this
|
||||
file, or you compile this file and link it with other files to
|
||||
produce an executable, this file does not by itself cause the
|
||||
resulting executable to be covered by the GNU General Public
|
||||
License. This exception does not however invalidate any other
|
||||
reasons why the executable file might be covered by the GNU General
|
||||
Public License.
|
||||
*/
|
||||
|
||||
int FLZe_longest_match_len( struct FLZ_encoder * const fe, int * const distance )
|
||||
{
|
||||
enum { len_limit = 16 };
|
||||
const uint8_t * const data = Mb_ptr_to_current_pos( &fe->eb.mb );
|
||||
int32_t * ptr0 = fe->eb.mb.pos_array + fe->eb.mb.cyclic_pos;
|
||||
int32_t * newptr;
|
||||
const int pos1 = fe->eb.mb.pos + 1;
|
||||
int maxlen = 0;
|
||||
int count, delta, newpos;
|
||||
if( len_limit > Mb_available_bytes( &fe->eb.mb ) ) { *ptr0 = 0; return 0; }
|
||||
|
||||
fe->key4 = ( ( fe->key4 << 4 ) ^ data[3] ) & fe->eb.mb.key4_mask;
|
||||
newpos = fe->eb.mb.prev_positions[fe->key4];
|
||||
fe->eb.mb.prev_positions[fe->key4] = pos1;
|
||||
|
||||
|
||||
for( count = 4; ; )
|
||||
{
|
||||
if( --count < 0 || newpos <= 0 ) { *ptr0 = 0; break; }
|
||||
delta = pos1 - newpos;
|
||||
if( delta > fe->eb.mb.dictionary_size ) { *ptr0 = 0; break; }
|
||||
newptr = fe->eb.mb.pos_array +
|
||||
( fe->eb.mb.cyclic_pos - delta +
|
||||
( ( fe->eb.mb.cyclic_pos >= delta ) ? 0 : fe->eb.mb.dictionary_size + 1 ) );
|
||||
|
||||
if( data[maxlen-delta] == data[maxlen] )
|
||||
{
|
||||
int len = 0;
|
||||
while( len < len_limit && data[len-delta] == data[len] ) ++len;
|
||||
if( maxlen < len ) { maxlen = len; *distance = delta - 1; }
|
||||
}
|
||||
|
||||
if( maxlen < len_limit )
|
||||
{
|
||||
*ptr0 = newpos;
|
||||
ptr0 = newptr;
|
||||
newpos = *ptr0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr0 = *newptr;
|
||||
maxlen += Mb_true_match_len( &fe->eb.mb, maxlen, *distance + 1,
|
||||
max_match_len - maxlen );
|
||||
break;
|
||||
}
|
||||
}
|
||||
return maxlen;
|
||||
}
|
||||
|
||||
|
||||
bool FLZe_encode_member( struct FLZ_encoder * const fe )
|
||||
{
|
||||
int rep = 0, i;
|
||||
State * const state = &fe->eb.state;
|
||||
|
||||
if( fe->eb.member_finished ) return true;
|
||||
if( Re_member_position( &fe->eb.renc ) >= fe->eb.member_size_limit )
|
||||
{
|
||||
if( LZeb_full_flush( &fe->eb ) ) fe->eb.member_finished = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if( Mb_data_position( &fe->eb.mb ) == 0 &&
|
||||
!Mb_data_finished( &fe->eb.mb ) ) /* encode first byte */
|
||||
{
|
||||
const uint8_t prev_byte = 0;
|
||||
uint8_t cur_byte;
|
||||
if( !Mb_enough_available_bytes( &fe->eb.mb ) ||
|
||||
!Re_enough_free_bytes( &fe->eb.renc ) ) return true;
|
||||
cur_byte = Mb_peek( &fe->eb.mb, 0 );
|
||||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_match[*state][0], 0 );
|
||||
LZeb_encode_literal( &fe->eb, prev_byte, cur_byte );
|
||||
CRC32_update_byte( &fe->eb.crc, cur_byte );
|
||||
FLZe_reset_key4( fe );
|
||||
if( !FLZe_update_and_move( fe, 1 ) ) return false;
|
||||
}
|
||||
|
||||
while( !Mb_data_finished( &fe->eb.mb ) &&
|
||||
Re_member_position( &fe->eb.renc ) < fe->eb.member_size_limit )
|
||||
{
|
||||
int match_distance;
|
||||
int main_len, pos_state, len;
|
||||
if( !Mb_enough_available_bytes( &fe->eb.mb ) ||
|
||||
!Re_enough_free_bytes( &fe->eb.renc ) ) return true;
|
||||
main_len = FLZe_longest_match_len( fe, &match_distance );
|
||||
pos_state = Mb_data_position( &fe->eb.mb ) & pos_state_mask;
|
||||
len = 0;
|
||||
|
||||
for( i = 0; i < num_rep_distances; ++i )
|
||||
{
|
||||
const int tlen = Mb_true_match_len( &fe->eb.mb, 0,
|
||||
fe->eb.reps[i] + 1, max_match_len );
|
||||
if( tlen > len ) { len = tlen; rep = i; }
|
||||
}
|
||||
if( len > min_match_len && len + 3 > main_len )
|
||||
{
|
||||
CRC32_update_buf( &fe->eb.crc, Mb_ptr_to_current_pos( &fe->eb.mb ), len );
|
||||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_match[*state][pos_state], 1 );
|
||||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep[*state], 1 );
|
||||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep0[*state], rep != 0 );
|
||||
if( rep == 0 )
|
||||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_len[*state][pos_state], 1 );
|
||||
else
|
||||
{
|
||||
int distance;
|
||||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep1[*state], rep > 1 );
|
||||
if( rep > 1 )
|
||||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep2[*state], rep > 2 );
|
||||
distance = fe->eb.reps[rep];
|
||||
for( i = rep; i > 0; --i ) fe->eb.reps[i] = fe->eb.reps[i-1];
|
||||
fe->eb.reps[0] = distance;
|
||||
}
|
||||
*state = St_set_rep( *state );
|
||||
Re_encode_len( &fe->eb.renc, &fe->eb.rep_len_model, len, pos_state );
|
||||
if( !Mb_move_pos( &fe->eb.mb ) ) return false;
|
||||
if( !FLZe_update_and_move( fe, len - 1 ) ) return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( main_len > min_match_len )
|
||||
{
|
||||
CRC32_update_buf( &fe->eb.crc, Mb_ptr_to_current_pos( &fe->eb.mb ), main_len );
|
||||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_match[*state][pos_state], 1 );
|
||||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep[*state], 0 );
|
||||
*state = St_set_match( *state );
|
||||
for( i = num_rep_distances - 1; i > 0; --i ) fe->eb.reps[i] = fe->eb.reps[i-1];
|
||||
fe->eb.reps[0] = match_distance;
|
||||
LZeb_encode_pair( &fe->eb, match_distance, main_len, pos_state );
|
||||
if( !Mb_move_pos( &fe->eb.mb ) ) return false;
|
||||
if( !FLZe_update_and_move( fe, main_len - 1 ) ) return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
const uint8_t prev_byte = Mb_peek( &fe->eb.mb, 1 );
|
||||
const uint8_t cur_byte = Mb_peek( &fe->eb.mb, 0 );
|
||||
const uint8_t match_byte = Mb_peek( &fe->eb.mb, fe->eb.reps[0] + 1 );
|
||||
if( !Mb_move_pos( &fe->eb.mb ) ) return false;
|
||||
CRC32_update_byte( &fe->eb.crc, cur_byte );
|
||||
|
||||
if( match_byte == cur_byte )
|
||||
{
|
||||
int price = price0( fe->eb.bm_match[*state][pos_state] );
|
||||
int short_rep_price;
|
||||
if( St_is_char( *state ) )
|
||||
price += LZeb_price_literal( &fe->eb, prev_byte, cur_byte );
|
||||
else
|
||||
price += LZeb_price_matched( &fe->eb, prev_byte, cur_byte, match_byte );
|
||||
short_rep_price = price1( fe->eb.bm_match[*state][pos_state] ) +
|
||||
price1( fe->eb.bm_rep[*state] ) +
|
||||
price0( fe->eb.bm_rep0[*state] ) +
|
||||
price0( fe->eb.bm_len[*state][pos_state] );
|
||||
if( short_rep_price < price )
|
||||
{
|
||||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_match[*state][pos_state], 1 );
|
||||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep[*state], 1 );
|
||||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep0[*state], 0 );
|
||||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_len[*state][pos_state], 0 );
|
||||
*state = St_set_short_rep( *state );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* literal byte */
|
||||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_match[*state][pos_state], 0 );
|
||||
if( St_is_char( *state ) )
|
||||
LZeb_encode_literal( &fe->eb, prev_byte, cur_byte );
|
||||
else
|
||||
LZeb_encode_matched( &fe->eb, prev_byte, cur_byte, match_byte );
|
||||
*state = St_set_char( *state );
|
||||
}
|
||||
}
|
||||
|
||||
if( LZeb_full_flush( &fe->eb ) ) fe->eb.member_finished = true;
|
||||
return true;
|
||||
}
|
82
fast_encoder.h
Normal file
82
fast_encoder.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
/* Lzlib - Compression library for the lzip format
|
||||
Copyright (C) 2009-2015 Antonio Diaz Diaz.
|
||||
|
||||
This library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
As a special exception, you may use this file as part of a free
|
||||
software library without restriction. Specifically, if other files
|
||||
instantiate templates or use macros or inline functions from this
|
||||
file, or you compile this file and link it with other files to
|
||||
produce an executable, this file does not by itself cause the
|
||||
resulting executable to be covered by the GNU General Public
|
||||
License. This exception does not however invalidate any other
|
||||
reasons why the executable file might be covered by the GNU General
|
||||
Public License.
|
||||
*/
|
||||
|
||||
struct FLZ_encoder
|
||||
{
|
||||
struct LZ_encoder_base eb;
|
||||
int key4; /* key made from latest 4 bytes */
|
||||
};
|
||||
|
||||
static inline void FLZe_reset_key4( struct FLZ_encoder * const fe )
|
||||
{
|
||||
int i;
|
||||
fe->key4 = 0;
|
||||
for( i = 0; i < 3 && i < Mb_available_bytes( &fe->eb.mb ); ++i )
|
||||
fe->key4 = ( fe->key4 << 4 ) ^ fe->eb.mb.buffer[i];
|
||||
}
|
||||
|
||||
int FLZe_longest_match_len( struct FLZ_encoder * const fe, int * const distance );
|
||||
|
||||
static inline bool FLZe_update_and_move( struct FLZ_encoder * const fe, int n )
|
||||
{
|
||||
while( --n >= 0 )
|
||||
{
|
||||
if( Mb_available_bytes( &fe->eb.mb ) >= 4 )
|
||||
{
|
||||
int newpos;
|
||||
fe->key4 = ( ( fe->key4 << 4 ) ^ fe->eb.mb.buffer[fe->eb.mb.pos+3] ) &
|
||||
fe->eb.mb.key4_mask;
|
||||
newpos = fe->eb.mb.prev_positions[fe->key4];
|
||||
fe->eb.mb.prev_positions[fe->key4] = fe->eb.mb.pos + 1;
|
||||
fe->eb.mb.pos_array[fe->eb.mb.cyclic_pos] = newpos;
|
||||
}
|
||||
else fe->eb.mb.pos_array[fe->eb.mb.cyclic_pos] = 0;
|
||||
if( !Mb_move_pos( &fe->eb.mb ) ) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool FLZe_init( struct FLZ_encoder * const fe,
|
||||
const unsigned long long member_size )
|
||||
{
|
||||
enum { before = 0,
|
||||
dict_size = 65536,
|
||||
/* bytes to keep in buffer after pos */
|
||||
after_size = max_match_len,
|
||||
dict_factor = 16,
|
||||
num_prev_positions23 = 0,
|
||||
pos_array_factor = 1,
|
||||
min_free_bytes = max_marker_size };
|
||||
|
||||
return LZeb_init( &fe->eb, before, dict_size, after_size, dict_factor,
|
||||
num_prev_positions23, pos_array_factor, min_free_bytes,
|
||||
member_size );
|
||||
}
|
||||
|
||||
static inline void FLZe_reset( struct FLZ_encoder * const fe,
|
||||
const unsigned long long member_size )
|
||||
{ LZeb_reset( &fe->eb, member_size ); }
|
46
lzcheck.c
46
lzcheck.c
|
@ -1,5 +1,5 @@
|
|||
/* Lzcheck - Test program for the lzlib library
|
||||
Copyright (C) 2009-2014 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2015 Antonio Diaz Diaz.
|
||||
|
||||
This program is free software: you have unlimited permission
|
||||
to copy, distribute and modify it.
|
||||
|
@ -34,30 +34,14 @@ uint8_t mid_buffer[buffer_size];
|
|||
uint8_t out_buffer[buffer_size];
|
||||
|
||||
|
||||
int main( const int argc, const char * const argv[] )
|
||||
int lzcheck( FILE * const file, const int dictionary_size )
|
||||
{
|
||||
const int dictionary_size = 1 << 20;
|
||||
const int match_len_limit = 16;
|
||||
const unsigned long long member_size = 0x7FFFFFFFFFFFFFFFULL; /* INT64_MAX */
|
||||
struct LZ_Encoder * encoder;
|
||||
struct LZ_Decoder * decoder;
|
||||
FILE * file;
|
||||
int retval = 0;
|
||||
|
||||
if( argc < 2 )
|
||||
{
|
||||
fprintf( stderr, "Usage: lzcheck filename.txt\n" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
file = fopen( argv[1], "rb" );
|
||||
if( !file )
|
||||
{
|
||||
fprintf( stderr, "lzcheck: Can't open file '%s' for reading\n", argv[1] );
|
||||
return 1;
|
||||
}
|
||||
/* fprintf( stderr, "lzcheck: Testing file '%s'\n", argv[1] ); */
|
||||
|
||||
encoder = LZ_compress_open( dictionary_size, match_len_limit, member_size );
|
||||
if( !encoder || LZ_compress_errno( encoder ) != LZ_ok )
|
||||
{
|
||||
|
@ -224,6 +208,32 @@ int main( const int argc, const char * const argv[] )
|
|||
|
||||
LZ_decompress_close( decoder );
|
||||
LZ_compress_close( encoder );
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
int main( const int argc, const char * const argv[] )
|
||||
{
|
||||
FILE * file;
|
||||
int retval;
|
||||
|
||||
if( argc < 2 )
|
||||
{
|
||||
fprintf( stderr, "Usage: lzcheck filename.txt\n" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
file = fopen( argv[1], "rb" );
|
||||
if( !file )
|
||||
{
|
||||
fprintf( stderr, "lzcheck: Can't open file '%s' for reading.\n", argv[1] );
|
||||
return 1;
|
||||
}
|
||||
/* fprintf( stderr, "lzcheck: Testing file '%s'\n", argv[1] ); */
|
||||
|
||||
retval = lzcheck( file, 65535 );
|
||||
if( retval == 0 )
|
||||
{ rewind( file ); retval = lzcheck( file, 1 << 20 ); }
|
||||
fclose( file );
|
||||
return retval;
|
||||
}
|
||||
|
|
2
lzip.h
2
lzip.h
|
@ -1,5 +1,5 @@
|
|||
/* Lzlib - Compression library for the lzip format
|
||||
Copyright (C) 2009-2014 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2015 Antonio Diaz Diaz.
|
||||
|
||||
This library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
148
lzlib.c
148
lzlib.c
|
@ -1,5 +1,5 @@
|
|||
/* Lzlib - Compression library for the lzip format
|
||||
Copyright (C) 2009-2014 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2015 Antonio Diaz Diaz.
|
||||
|
||||
This library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -35,33 +35,33 @@
|
|||
#include "cbuffer.c"
|
||||
#include "decoder.h"
|
||||
#include "decoder.c"
|
||||
#include "encoder_base.h"
|
||||
#include "encoder_base.c"
|
||||
#include "encoder.h"
|
||||
#include "encoder.c"
|
||||
#include "fast_encoder.h"
|
||||
#include "fast_encoder.c"
|
||||
|
||||
|
||||
struct LZ_Encoder
|
||||
{
|
||||
unsigned long long partial_in_size;
|
||||
unsigned long long partial_out_size;
|
||||
struct Matchfinder * matchfinder;
|
||||
struct LZ_encoder * lz_encoder;
|
||||
struct LZ_encoder_base * lz_encoder_base; /* these 3 pointers make a */
|
||||
struct LZ_encoder * lz_encoder; /* polymorphic encoder */
|
||||
struct FLZ_encoder * flz_encoder;
|
||||
enum LZ_Errno lz_errno;
|
||||
int flush_pending;
|
||||
File_header member_header;
|
||||
bool fatal;
|
||||
};
|
||||
|
||||
static void LZ_Encoder_init( struct LZ_Encoder * const e,
|
||||
const File_header header )
|
||||
static void LZ_Encoder_init( struct LZ_Encoder * const e )
|
||||
{
|
||||
int i;
|
||||
e->partial_in_size = 0;
|
||||
e->partial_out_size = 0;
|
||||
e->matchfinder = 0;
|
||||
e->lz_encoder_base = 0;
|
||||
e->lz_encoder = 0;
|
||||
e->flz_encoder = 0;
|
||||
e->lz_errno = LZ_ok;
|
||||
e->flush_pending = 0;
|
||||
for( i = 0; i < Fh_size; ++i ) e->member_header[i] = header[i];
|
||||
e->fatal = false;
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,8 @@ static void LZ_Decoder_init( struct LZ_Decoder * const d )
|
|||
static bool verify_encoder( struct LZ_Encoder * const e )
|
||||
{
|
||||
if( !e ) return false;
|
||||
if( !e->matchfinder || !e->lz_encoder )
|
||||
if( !e->lz_encoder_base || ( !e->lz_encoder && !e->flz_encoder ) ||
|
||||
( e->lz_encoder && e->flz_encoder ) )
|
||||
{ e->lz_errno = LZ_bad_argument; return false; }
|
||||
return true;
|
||||
}
|
||||
|
@ -147,36 +148,32 @@ struct LZ_Encoder * LZ_compress_open( const int dictionary_size,
|
|||
const unsigned long long member_size )
|
||||
{
|
||||
File_header header;
|
||||
const bool error = ( !Fh_set_dictionary_size( header, dictionary_size ) ||
|
||||
match_len_limit < min_match_len_limit ||
|
||||
match_len_limit > max_match_len ||
|
||||
member_size < min_dictionary_size );
|
||||
|
||||
struct LZ_Encoder * const e =
|
||||
(struct LZ_Encoder *)malloc( sizeof (struct LZ_Encoder) );
|
||||
if( !e ) return 0;
|
||||
Fh_set_magic( header );
|
||||
LZ_Encoder_init( e, header );
|
||||
if( error ) e->lz_errno = LZ_bad_argument;
|
||||
LZ_Encoder_init( e );
|
||||
if( !Fh_set_dictionary_size( header, dictionary_size ) ||
|
||||
match_len_limit < min_match_len_limit ||
|
||||
match_len_limit > max_match_len ||
|
||||
member_size < min_dictionary_size )
|
||||
e->lz_errno = LZ_bad_argument;
|
||||
else
|
||||
{
|
||||
e->matchfinder = (struct Matchfinder *)malloc( sizeof (struct Matchfinder) );
|
||||
if( e->matchfinder )
|
||||
if( dictionary_size == 65535 && match_len_limit == 16 )
|
||||
{
|
||||
e->flz_encoder = (struct FLZ_encoder *)malloc( sizeof (struct FLZ_encoder) );
|
||||
if( e->flz_encoder && FLZe_init( e->flz_encoder, member_size ) )
|
||||
{ e->lz_encoder_base = &e->flz_encoder->eb; return e; }
|
||||
free( e->flz_encoder ); e->flz_encoder = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
e->lz_encoder = (struct LZ_encoder *)malloc( sizeof (struct LZ_encoder) );
|
||||
if( e->lz_encoder )
|
||||
{
|
||||
if( Mf_init( e->matchfinder,
|
||||
Fh_get_dictionary_size( header ), match_len_limit ) )
|
||||
{
|
||||
if( LZe_init( e->lz_encoder, e->matchfinder, header, member_size ) )
|
||||
return e;
|
||||
Mf_free( e->matchfinder );
|
||||
}
|
||||
if( e->lz_encoder && LZe_init( e->lz_encoder, Fh_get_dictionary_size( header ),
|
||||
match_len_limit, member_size ) )
|
||||
{ e->lz_encoder_base = &e->lz_encoder->eb; return e; }
|
||||
free( e->lz_encoder ); e->lz_encoder = 0;
|
||||
}
|
||||
free( e->matchfinder ); e->matchfinder = 0;
|
||||
}
|
||||
e->lz_errno = LZ_mem_error;
|
||||
}
|
||||
e->fatal = true;
|
||||
|
@ -187,10 +184,9 @@ struct LZ_Encoder * LZ_compress_open( const int dictionary_size,
|
|||
int LZ_compress_close( struct LZ_Encoder * const e )
|
||||
{
|
||||
if( !e ) return -1;
|
||||
if( e->lz_encoder )
|
||||
{ LZe_free( e->lz_encoder ); free( e->lz_encoder ); }
|
||||
if( e->matchfinder )
|
||||
{ Mf_free( e->matchfinder ); free( e->matchfinder ); }
|
||||
if( e->lz_encoder_base )
|
||||
{ LZeb_free( e->lz_encoder_base );
|
||||
free( e->lz_encoder ); free( e->flz_encoder ); }
|
||||
free( e );
|
||||
return 0;
|
||||
}
|
||||
|
@ -199,13 +195,17 @@ int LZ_compress_close( struct LZ_Encoder * const e )
|
|||
int LZ_compress_finish( struct LZ_Encoder * const e )
|
||||
{
|
||||
if( !verify_encoder( e ) || e->fatal ) return -1;
|
||||
Mf_finish( e->matchfinder );
|
||||
e->flush_pending = 0;
|
||||
Mb_finish( &e->lz_encoder_base->mb );
|
||||
/* if (open --> write --> finish) use same dictionary size as lzip. */
|
||||
/* this does not save any memory. */
|
||||
if( Mf_data_position( e->matchfinder ) == 0 &&
|
||||
if( Mb_data_position( &e->lz_encoder_base->mb ) == 0 &&
|
||||
LZ_compress_total_out_size( e ) == Fh_size )
|
||||
Mf_adjust_distionary_size( e->matchfinder );
|
||||
{
|
||||
Mb_adjust_distionary_size( &e->lz_encoder_base->mb );
|
||||
Fh_set_dictionary_size( e->lz_encoder_base->renc.header,
|
||||
e->lz_encoder_base->mb.dictionary_size );
|
||||
e->lz_encoder_base->renc.cb.buffer[5] = e->lz_encoder_base->renc.header[5];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -214,22 +214,16 @@ int LZ_compress_restart_member( struct LZ_Encoder * const e,
|
|||
const unsigned long long member_size )
|
||||
{
|
||||
if( !verify_encoder( e ) || e->fatal ) return -1;
|
||||
if( !LZe_member_finished( e->lz_encoder ) )
|
||||
if( !LZeb_member_finished( e->lz_encoder_base ) )
|
||||
{ e->lz_errno = LZ_sequence_error; return -1; }
|
||||
if( member_size < min_dictionary_size )
|
||||
{ e->lz_errno = LZ_bad_argument; return -1; }
|
||||
|
||||
e->partial_in_size += Mf_data_position( e->matchfinder );
|
||||
e->partial_out_size += Re_member_position( &e->lz_encoder->renc );
|
||||
Mf_reset( e->matchfinder );
|
||||
e->partial_in_size += Mb_data_position( &e->lz_encoder_base->mb );
|
||||
e->partial_out_size += Re_member_position( &e->lz_encoder_base->renc );
|
||||
|
||||
LZe_free( e->lz_encoder );
|
||||
if( !LZe_init( e->lz_encoder, e->matchfinder, e->member_header, member_size ) )
|
||||
{
|
||||
LZe_free( e->lz_encoder ); free( e->lz_encoder ); e->lz_encoder = 0;
|
||||
e->lz_errno = LZ_mem_error; e->fatal = true;
|
||||
return -1;
|
||||
}
|
||||
if( e->lz_encoder ) LZe_reset( e->lz_encoder, member_size );
|
||||
else FLZe_reset( e->flz_encoder, member_size );
|
||||
e->lz_errno = LZ_ok;
|
||||
return 0;
|
||||
}
|
||||
|
@ -238,15 +232,8 @@ int LZ_compress_restart_member( struct LZ_Encoder * const e,
|
|||
int LZ_compress_sync_flush( struct LZ_Encoder * const e )
|
||||
{
|
||||
if( !verify_encoder( e ) || e->fatal ) return -1;
|
||||
if( e->flush_pending <= 0 && !Mf_flushing_or_end( e->matchfinder ) )
|
||||
{
|
||||
e->flush_pending = 2; /* 2 consecutive markers guarantee decoding */
|
||||
e->matchfinder->flushing = true;
|
||||
if( !LZe_encode_member( e->lz_encoder ) )
|
||||
{ e->lz_errno = LZ_library_error; e->fatal = true; return -1; }
|
||||
while( e->flush_pending > 0 && LZe_sync_flush( e->lz_encoder ) )
|
||||
{ if( --e->flush_pending <= 0 ) e->matchfinder->flushing = false; }
|
||||
}
|
||||
if( !Mb_flushing_or_end( &e->lz_encoder_base->mb ) )
|
||||
e->lz_encoder_base->mb.flushing = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -254,12 +241,23 @@ int LZ_compress_sync_flush( struct LZ_Encoder * const e )
|
|||
int LZ_compress_read( struct LZ_Encoder * const e,
|
||||
uint8_t * const buffer, const int size )
|
||||
{
|
||||
int out_size = 0;
|
||||
if( !verify_encoder( e ) || e->fatal ) return -1;
|
||||
if( !LZe_encode_member( e->lz_encoder ) )
|
||||
do {
|
||||
if( ( e->flz_encoder && !FLZe_encode_member( e->flz_encoder ) ) ||
|
||||
( e->lz_encoder && !LZe_encode_member( e->lz_encoder ) ) )
|
||||
{ e->lz_errno = LZ_library_error; e->fatal = true; return -1; }
|
||||
while( e->flush_pending > 0 && LZe_sync_flush( e->lz_encoder ) )
|
||||
{ if( --e->flush_pending <= 0 ) e->matchfinder->flushing = false; }
|
||||
return Re_read_data( &e->lz_encoder->renc, buffer, size );
|
||||
if( e->lz_encoder_base->mb.flushing &&
|
||||
Mb_available_bytes( &e->lz_encoder_base->mb ) <= 0 &&
|
||||
LZeb_sync_flush( e->lz_encoder_base ) )
|
||||
e->lz_encoder_base->mb.flushing = false;
|
||||
out_size += Re_read_data( &e->lz_encoder_base->renc,
|
||||
buffer + out_size, size - out_size );
|
||||
}
|
||||
while( e->lz_encoder_base->mb.flushing && out_size < size &&
|
||||
Mb_enough_available_bytes( &e->lz_encoder_base->mb ) &&
|
||||
Re_enough_free_bytes( &e->lz_encoder_base->renc ) );
|
||||
return out_size;
|
||||
}
|
||||
|
||||
|
||||
|
@ -267,16 +265,14 @@ int LZ_compress_write( struct LZ_Encoder * const e,
|
|||
const uint8_t * const buffer, const int size )
|
||||
{
|
||||
if( !verify_encoder( e ) || e->fatal ) return -1;
|
||||
if( e->flush_pending > 0 || size < 0 ) return 0;
|
||||
return Mf_write_data( e->matchfinder, buffer, size );
|
||||
return Mb_write_data( &e->lz_encoder_base->mb, buffer, size );
|
||||
}
|
||||
|
||||
|
||||
int LZ_compress_write_size( struct LZ_Encoder * const e )
|
||||
{
|
||||
if( !verify_encoder( e ) || e->fatal ) return -1;
|
||||
if( e->flush_pending > 0 ) return 0;
|
||||
return Mf_free_bytes( e->matchfinder );
|
||||
return Mb_free_bytes( &e->lz_encoder_base->mb );
|
||||
}
|
||||
|
||||
|
||||
|
@ -290,43 +286,43 @@ enum LZ_Errno LZ_compress_errno( struct LZ_Encoder * const e )
|
|||
int LZ_compress_finished( struct LZ_Encoder * const e )
|
||||
{
|
||||
if( !verify_encoder( e ) ) return -1;
|
||||
return ( e->flush_pending <= 0 && Mf_finished( e->matchfinder ) &&
|
||||
LZe_member_finished( e->lz_encoder ) );
|
||||
return ( Mb_data_finished( &e->lz_encoder_base->mb ) &&
|
||||
LZeb_member_finished( e->lz_encoder_base ) );
|
||||
}
|
||||
|
||||
|
||||
int LZ_compress_member_finished( struct LZ_Encoder * const e )
|
||||
{
|
||||
if( !verify_encoder( e ) ) return -1;
|
||||
return LZe_member_finished( e->lz_encoder );
|
||||
return LZeb_member_finished( e->lz_encoder_base );
|
||||
}
|
||||
|
||||
|
||||
unsigned long long LZ_compress_data_position( struct LZ_Encoder * const e )
|
||||
{
|
||||
if( !verify_encoder( e ) ) return 0;
|
||||
return Mf_data_position( e->matchfinder );
|
||||
return Mb_data_position( &e->lz_encoder_base->mb );
|
||||
}
|
||||
|
||||
|
||||
unsigned long long LZ_compress_member_position( struct LZ_Encoder * const e )
|
||||
{
|
||||
if( !verify_encoder( e ) ) return 0;
|
||||
return Re_member_position( &e->lz_encoder->renc );
|
||||
return Re_member_position( &e->lz_encoder_base->renc );
|
||||
}
|
||||
|
||||
|
||||
unsigned long long LZ_compress_total_in_size( struct LZ_Encoder * const e )
|
||||
{
|
||||
if( !verify_encoder( e ) ) return 0;
|
||||
return e->partial_in_size + Mf_data_position( e->matchfinder );
|
||||
return e->partial_in_size + Mb_data_position( &e->lz_encoder_base->mb );
|
||||
}
|
||||
|
||||
|
||||
unsigned long long LZ_compress_total_out_size( struct LZ_Encoder * const e )
|
||||
{
|
||||
if( !verify_encoder( e ) ) return 0;
|
||||
return e->partial_out_size + Re_member_position( &e->lz_encoder->renc );
|
||||
return e->partial_out_size + Re_member_position( &e->lz_encoder_base->renc );
|
||||
}
|
||||
|
||||
|
||||
|
|
4
lzlib.h
4
lzlib.h
|
@ -1,5 +1,5 @@
|
|||
/* Lzlib - Compression library for the lzip format
|
||||
Copyright (C) 2009-2014 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2015 Antonio Diaz Diaz.
|
||||
|
||||
This library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -29,7 +29,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
static const char * const LZ_version_string = "1.6";
|
||||
static const char * const LZ_version_string = "1.7-pre1";
|
||||
|
||||
enum LZ_Errno { LZ_ok = 0, LZ_bad_argument, LZ_mem_error,
|
||||
LZ_sequence_error, LZ_header_error, LZ_unexpected_eof,
|
||||
|
|
58
main.c
58
main.c
|
@ -1,5 +1,5 @@
|
|||
/* Minilzip - Test program for the lzlib library
|
||||
Copyright (C) 2009-2014 Antonio Diaz Diaz.
|
||||
Copyright (C) 2009-2015 Antonio Diaz Diaz.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -76,7 +76,7 @@ void internal_error( const char * const msg );
|
|||
|
||||
const char * const Program_name = "Minilzip";
|
||||
const char * const program_name = "minilzip";
|
||||
const char * const program_year = "2014";
|
||||
const char * const program_year = "2015";
|
||||
const char * invocation_name = 0;
|
||||
|
||||
struct { const char * from; const char * to; } const known_extensions[] = {
|
||||
|
@ -179,8 +179,8 @@ static void show_help( void )
|
|||
" -S, --volume-size=<bytes> set volume size limit in bytes\n"
|
||||
" -t, --test test compressed file integrity\n"
|
||||
" -v, --verbose be verbose (a 2nd -v gives more)\n"
|
||||
" -1 .. -9 set compression level [default 6]\n"
|
||||
" --fast alias for -1\n"
|
||||
" -0 .. -9 set compression level [default 6]\n"
|
||||
" --fast alias for -0\n"
|
||||
" --best alias for -9\n"
|
||||
"If no file names are given, minilzip compresses or decompresses\n"
|
||||
"from standard input to standard output.\n"
|
||||
|
@ -189,8 +189,7 @@ static void show_help( void )
|
|||
"The bidimensional parameter space of LZMA can't be mapped to a linear\n"
|
||||
"scale optimal for all files. If your files are large, very repetitive,\n"
|
||||
"etc, you may need to use the --match-length and --dictionary-size\n"
|
||||
"options directly to achieve optimal performance. For example, -9m64\n"
|
||||
"usually compresses executables more (and faster) than -9.\n"
|
||||
"options directly to achieve optimal performance.\n"
|
||||
"\nExit status: 0 for a normal exit, 1 for environmental problems (file\n"
|
||||
"not found, invalid flags, I/O errors, etc), 2 to indicate a corrupt or\n"
|
||||
"invalid input file, 3 for an internal consistency error (eg, bug) which\n"
|
||||
|
@ -212,6 +211,8 @@ static void show_version( void )
|
|||
|
||||
|
||||
static void show_header( const unsigned dictionary_size )
|
||||
{
|
||||
if( verbosity >= 3 )
|
||||
{
|
||||
const char * const prefix[8] =
|
||||
{ "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" };
|
||||
|
@ -226,6 +227,7 @@ static void show_header( const unsigned dictionary_size )
|
|||
p = prefix[i]; np = ""; }
|
||||
fprintf( stderr, "dictionary size %s%4u %sB. ", np, num, p );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static unsigned long long getnum( const char * const ptr,
|
||||
|
@ -301,8 +303,10 @@ static int extension_index( const char * const name )
|
|||
for( i = 0; known_extensions[i].from; ++i )
|
||||
{
|
||||
const char * const ext = known_extensions[i].from;
|
||||
if( strlen( name ) > strlen( ext ) &&
|
||||
strncmp( name + strlen( name ) - strlen( ext ), ext, strlen( ext ) ) == 0 )
|
||||
const unsigned name_len = strlen( name );
|
||||
const unsigned ext_len = strlen( ext );
|
||||
if( name_len > ext_len &&
|
||||
strncmp( name + name_len - ext_len, ext, ext_len ) == 0 )
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
|
@ -379,20 +383,21 @@ static void set_c_outname( const char * const name, const bool multifile )
|
|||
|
||||
static void set_d_outname( const char * const name, const int i )
|
||||
{
|
||||
const unsigned name_len = strlen( name );
|
||||
if( i >= 0 )
|
||||
{
|
||||
const char * const from = known_extensions[i].from;
|
||||
if( strlen( name ) > strlen( from ) )
|
||||
const unsigned from_len = strlen( from );
|
||||
if( name_len > from_len )
|
||||
{
|
||||
output_filename = resize_buffer( output_filename, strlen( name ) +
|
||||
output_filename = resize_buffer( output_filename, name_len +
|
||||
strlen( known_extensions[0].to ) + 1 );
|
||||
strcpy( output_filename, name );
|
||||
strcpy( output_filename + strlen( name ) - strlen( from ),
|
||||
known_extensions[i].to );
|
||||
strcpy( output_filename + name_len - from_len, known_extensions[i].to );
|
||||
return;
|
||||
}
|
||||
}
|
||||
output_filename = resize_buffer( output_filename, strlen( name ) + 4 + 1 );
|
||||
output_filename = resize_buffer( output_filename, name_len + 4 + 1 );
|
||||
strcpy( output_filename, name );
|
||||
strcat( output_filename, ".out" );
|
||||
if( verbosity >= 1 )
|
||||
|
@ -422,7 +427,7 @@ static bool open_outstream( const bool force )
|
|||
|
||||
static bool check_tty( const int infd, const enum Mode program_mode )
|
||||
{
|
||||
if( program_mode == m_compress && outfd >= 0 && isatty( outfd ) )
|
||||
if( program_mode == m_compress && isatty( outfd ) )
|
||||
{
|
||||
show_error( "I won't write compressed data to a terminal.", 0, true );
|
||||
return false;
|
||||
|
@ -522,11 +527,11 @@ static int writeblock( const int fd, const uint8_t * const buf, const int size )
|
|||
|
||||
static bool next_filename( void )
|
||||
{
|
||||
const unsigned len = strlen( known_extensions[0].from );
|
||||
const unsigned name_len = strlen( output_filename );
|
||||
const unsigned ext_len = strlen( known_extensions[0].from );
|
||||
int i, j;
|
||||
|
||||
if( strlen( output_filename ) >= len + 5 ) /* "*00001.lz" */
|
||||
for( i = strlen( output_filename ) - len - 1, j = 0; j < 5; --i, ++j )
|
||||
if( name_len >= ext_len + 5 ) /* "*00001.lz" */
|
||||
for( i = name_len - ext_len - 1, j = 0; j < 5; --i, ++j )
|
||||
{
|
||||
if( output_filename[i] < '9' ) { ++output_filename[i]; return true; }
|
||||
else output_filename[i] = '0';
|
||||
|
@ -635,10 +640,10 @@ static int do_compress( struct LZ_Encoder * const encoder,
|
|||
}
|
||||
|
||||
|
||||
int compress( const unsigned long long member_size,
|
||||
const unsigned long long volume_size,
|
||||
static int compress( const unsigned long long member_size,
|
||||
const unsigned long long volume_size, const int infd,
|
||||
const struct Lzma_options * const encoder_options,
|
||||
const int infd, struct Pretty_print * const pp,
|
||||
struct Pretty_print * const pp,
|
||||
const struct stat * const in_statsp )
|
||||
{
|
||||
struct LZ_Encoder * const encoder =
|
||||
|
@ -662,7 +667,7 @@ int compress( const unsigned long long member_size,
|
|||
}
|
||||
|
||||
|
||||
int do_decompress( struct LZ_Decoder * const decoder, const int infd,
|
||||
static int do_decompress( struct LZ_Decoder * const decoder, const int infd,
|
||||
struct Pretty_print * const pp, const bool testing )
|
||||
{
|
||||
enum { buffer_size = 65536 };
|
||||
|
@ -710,7 +715,6 @@ int do_decompress( struct LZ_Decoder * const decoder, const int infd,
|
|||
const unsigned long long data_position = LZ_decompress_data_position( decoder );
|
||||
const unsigned long long member_size = LZ_decompress_member_position( decoder );
|
||||
Pp_show_msg( pp, 0 );
|
||||
if( verbosity >= 3 )
|
||||
show_header( LZ_decompress_dictionary_size( decoder ) );
|
||||
if( verbosity >= 2 && data_position > 0 && member_size > 0 )
|
||||
fprintf( stderr, "%6.3f:1, %6.3f bits/byte, %5.2f%% saved. ",
|
||||
|
@ -759,7 +763,7 @@ int do_decompress( struct LZ_Decoder * const decoder, const int infd,
|
|||
}
|
||||
|
||||
|
||||
int decompress( const int infd, struct Pretty_print * const pp,
|
||||
static int decompress( const int infd, struct Pretty_print * const pp,
|
||||
const bool testing )
|
||||
{
|
||||
struct LZ_Decoder * const decoder = LZ_decompress_open();
|
||||
|
@ -821,7 +825,7 @@ int main( const int argc, const char * const argv[] )
|
|||
to the corresponding LZMA compression modes. */
|
||||
const struct Lzma_options option_mapping[] =
|
||||
{
|
||||
{ 1 << 20, 5 }, /* -0 */
|
||||
{ 65535, 16 }, /* -0 */
|
||||
{ 1 << 20, 5 }, /* -1 */
|
||||
{ 3 << 19, 6 }, /* -2 */
|
||||
{ 1 << 21, 8 }, /* -3 */
|
||||
|
@ -1022,8 +1026,8 @@ int main( const int argc, const char * const argv[] )
|
|||
in_statsp = input_filename[0] ? &in_stats : 0;
|
||||
Pp_set_name( &pp, input_filename );
|
||||
if( program_mode == m_compress )
|
||||
tmp = compress( member_size, volume_size, &encoder_options, infd,
|
||||
&pp, in_statsp );
|
||||
tmp = compress( member_size, volume_size, infd, &encoder_options, &pp,
|
||||
in_statsp );
|
||||
else
|
||||
tmp = decompress( infd, &pp, program_mode == m_test );
|
||||
if( tmp > retval ) retval = tmp;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#! /bin/sh
|
||||
# check script for Lzlib - A compression library for lzip files
|
||||
# Copyright (C) 2009-2014 Antonio Diaz Diaz.
|
||||
# Copyright (C) 2009-2015 Antonio Diaz Diaz.
|
||||
#
|
||||
# This script is free software: you have unlimited permission
|
||||
# to copy, distribute and modify it.
|
||||
|
|
Loading…
Add table
Reference in a new issue