mirror of
https://github.com/PCSX2/xz.git
synced 2026-02-06 12:21:18 +01:00
Compare commits
185 Commits
v4.42.2alp
...
v4.999.5al
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb072b7c84 | ||
|
|
123ab0acec | ||
|
|
9cfcd0c4f2 | ||
|
|
2ba01bfa75 | ||
|
|
07efcb5a6b | ||
|
|
32fe5fa541 | ||
|
|
0a31ed9d5e | ||
|
|
da98df5440 | ||
|
|
2496aee8a7 | ||
|
|
bea301c26d | ||
|
|
9c75b089b4 | ||
|
|
bab0590504 | ||
|
|
689602336d | ||
|
|
80c4158f19 | ||
|
|
fc68165745 | ||
|
|
ede675f9ac | ||
|
|
3b34851de1 | ||
|
|
57b9a145a5 | ||
|
|
eaafc4367c | ||
|
|
0809c46534 | ||
|
|
d25ab1b961 | ||
|
|
6368a2fa59 | ||
|
|
7d17818cec | ||
|
|
bf6348d1a3 | ||
|
|
803194ddd2 | ||
|
|
0ea98e52ba | ||
|
|
436fa5fae9 | ||
|
|
369f72fd65 | ||
|
|
e55e0e873c | ||
|
|
ed6664146f | ||
|
|
b09464bf9a | ||
|
|
11de5d5267 | ||
|
|
dc192b6343 | ||
|
|
944b62b932 | ||
|
|
8e074349e4 | ||
|
|
2f361ac19b | ||
|
|
3be21fb12f | ||
|
|
beeb810608 | ||
|
|
c324325f9f | ||
|
|
d3ba30243c | ||
|
|
8f804c29aa | ||
|
|
c99037ea10 | ||
|
|
22ba3b0b50 | ||
|
|
17c36422d4 | ||
|
|
283f939974 | ||
|
|
eb348a60b6 | ||
|
|
6c5306e312 | ||
|
|
712cfe3ebf | ||
|
|
bc04486e36 | ||
|
|
7ab493924e | ||
|
|
641998c3e1 | ||
|
|
ad999efd27 | ||
|
|
03e0e8a0d7 | ||
|
|
7521bbdc83 | ||
|
|
63b74d000e | ||
|
|
e6eb0a2675 | ||
|
|
7d516f5129 | ||
|
|
748d6e4274 | ||
|
|
bfde3b24a5 | ||
|
|
f310c50286 | ||
|
|
5ead36cf7f | ||
|
|
d4d7feb83d | ||
|
|
0541c5ea63 | ||
|
|
596fa1fac7 | ||
|
|
45e43e1695 | ||
|
|
c0e19e0662 | ||
|
|
de74858062 | ||
|
|
1a3b218598 | ||
|
|
7e796e312b | ||
|
|
7dd48578a3 | ||
|
|
b596fac963 | ||
|
|
e9f6e9c075 | ||
|
|
4c7ad179c7 | ||
|
|
288b232f54 | ||
|
|
c467b0defc | ||
|
|
f9842f7127 | ||
|
|
e988ea1d1a | ||
|
|
4441e00418 | ||
|
|
bf4200c818 | ||
|
|
7b8fc7e6b5 | ||
|
|
e0c3d0043d | ||
|
|
1fd76d4881 | ||
|
|
6e27b1098a | ||
|
|
db9df0a960 | ||
|
|
765f0b05f6 | ||
|
|
3a7cc5c3de | ||
|
|
e5fdec93e2 | ||
|
|
ed40dc5a2c | ||
|
|
ae0cd09a66 | ||
|
|
0e80ded13d | ||
|
|
8c8eb14055 | ||
|
|
980f65a9a1 | ||
|
|
99e12af4e2 | ||
|
|
58b78ab20c | ||
|
|
4d8cdbdab4 | ||
|
|
67321de963 | ||
|
|
863028cb7a | ||
|
|
cf49f42a6b | ||
|
|
1747b85a43 | ||
|
|
0ed6f1adce | ||
|
|
305afa38f6 | ||
|
|
d53e9b7705 | ||
|
|
107259e306 | ||
|
|
e141fe1895 | ||
|
|
23c227a864 | ||
|
|
61dc82f3e3 | ||
|
|
0ae3208db9 | ||
|
|
ab5feaf1fc | ||
|
|
079c4f7fc2 | ||
|
|
61d1784d8f | ||
|
|
c9cba97691 | ||
|
|
33be3c0e24 | ||
|
|
b254bd97b1 | ||
|
|
8f5794c8f1 | ||
|
|
f88590e001 | ||
|
|
bc0b945ca3 | ||
|
|
7599bb7064 | ||
|
|
0b58153931 | ||
|
|
5b5b13c7bb | ||
|
|
19389f2b82 | ||
|
|
9bc33a54cb | ||
|
|
01d71d60b7 | ||
|
|
8235e6e5b2 | ||
|
|
f10fc6a69d | ||
|
|
e5728142a2 | ||
|
|
10437b5b56 | ||
|
|
f3c88e8b8d | ||
|
|
54ec204f58 | ||
|
|
01b4b19f49 | ||
|
|
19bd7f3cf2 | ||
|
|
9f9b198301 | ||
|
|
78e85cb1a7 | ||
|
|
949d4346e2 | ||
|
|
d13d693155 | ||
|
|
362dc3843b | ||
|
|
e22b37968d | ||
|
|
b59ef39737 | ||
|
|
9547e734a0 | ||
|
|
3e09e1c058 | ||
|
|
a670fec802 | ||
|
|
3599dba957 | ||
|
|
f73c2ab607 | ||
|
|
382808514a | ||
|
|
0e70fbe403 | ||
|
|
379fbbe84d | ||
|
|
97d5fa8207 | ||
|
|
3bb9bb3109 | ||
|
|
7054c5f588 | ||
|
|
753e4d95cd | ||
|
|
faeac7b7ac | ||
|
|
a751126dbb | ||
|
|
9080267603 | ||
|
|
b4943ccf73 | ||
|
|
e2417b2b91 | ||
|
|
5d227e51c2 | ||
|
|
c7189d981a | ||
|
|
3dbbea82b7 | ||
|
|
2fd2d18154 | ||
|
|
9a71d57310 | ||
|
|
47f48fe993 | ||
|
|
3502b3e1d0 | ||
|
|
908b2ac604 | ||
|
|
ecb2a6548f | ||
|
|
eacb805043 | ||
|
|
1239649f96 | ||
|
|
88ee301ec2 | ||
|
|
c15a7abf66 | ||
|
|
4e7e54c4c5 | ||
|
|
a71864f77d | ||
|
|
072927905a | ||
|
|
d160ee3259 | ||
|
|
fc67f79f60 | ||
|
|
0029cbbabe | ||
|
|
bbfd1f6ab0 | ||
|
|
5db745cd2a | ||
|
|
44b333d461 | ||
|
|
ec1c82b2e8 | ||
|
|
2881570df6 | ||
|
|
698470b8f3 | ||
|
|
918bcb0e07 | ||
|
|
3e16d51dd6 | ||
|
|
5286723e0d | ||
|
|
ce8b036a6c | ||
|
|
7c1ad41eb6 | ||
|
|
ce64df7162 |
3
COPYING
3
COPYING
@@ -5,7 +5,8 @@ LZMA Utils Licenses
|
||||
Different licenses apply to different files in this package. Here
|
||||
is a rough summary of which license apply to which parts of this
|
||||
package (but check the individual files to be sure!):
|
||||
- Everything under src/liblzma/check is public domain.
|
||||
- Everything under src/liblzma/check and tests/files is public
|
||||
domain.
|
||||
- Everything else under the src directory is under the GNU LGPL
|
||||
2.1 or (at your opinion) any later version.
|
||||
- Outside the src directory, there are some files that are under
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
## Lesser General Public License for more details.
|
||||
##
|
||||
|
||||
DIST_SUBDIRS = lib src po tests debug
|
||||
SUBDIRS =
|
||||
|
||||
if COND_GNULIB
|
||||
@@ -20,7 +21,6 @@ endif
|
||||
|
||||
SUBDIRS += src po tests
|
||||
|
||||
|
||||
EXTRA_DIST = \
|
||||
m4 \
|
||||
config.rpath \
|
||||
@@ -32,4 +32,8 @@ EXTRA_DIST = \
|
||||
COPYING.LGPLv2.1
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
# This works with GNU tar and gives cleaner package than normal 'make dist'.
|
||||
mydist:
|
||||
TAR_OPTIONS='--owner=0 --group=0 --numeric-owner --mode=u+rw,go+r-w' \
|
||||
$(MAKE) dist-gzip
|
||||
|
||||
35
README
35
README
@@ -59,6 +59,35 @@ Supported platforms
|
||||
in C89 or C++.
|
||||
|
||||
|
||||
Version numbering
|
||||
|
||||
Starting from LZMA Utils 5, the version number of LZMA Utils has
|
||||
absolutely nothing to do with the version number of LZMA SDK or
|
||||
7-Zip. The new version number format of LZMA Utils is X.Y.ZS:
|
||||
|
||||
- X is the major version. When this is incremented, the library
|
||||
API and ABI break.
|
||||
|
||||
- Y is the minor version. It is incremented when new features are
|
||||
added without breaking existing API or ABI. Even Y indicates
|
||||
stable release and odd Y indicates unstable (alpha or beta
|
||||
version).
|
||||
|
||||
- Z is the revision. This has different meaning for stable and
|
||||
unstable releases:
|
||||
* Stable: Z is incremented when bugs get fixed without adding
|
||||
any new features.
|
||||
* Unstable: Z is just a counter. API or ABI of features added
|
||||
in earlier unstable releases having the same X.Y may break.
|
||||
|
||||
- S indicates stability of the release. It is missing from the
|
||||
stable releases where Y is an even number. When Y is odd, S
|
||||
is either "alpha" or "beta" to make it very clear that such
|
||||
versions are not stable releases. The same X.Y.Z combination is
|
||||
not used for more than one stability level i.e. after X.Y.Zalpha,
|
||||
the next version can be X.Y.(Z+1)beta but not X.Y.Zbeta.
|
||||
|
||||
|
||||
configure options
|
||||
|
||||
If you are not familiar with `configure' scripts, read the file
|
||||
@@ -113,7 +142,11 @@ configure options
|
||||
|
||||
All the assembler code in liblzma is position-independent
|
||||
code, which is suitable for use in shared libraries and
|
||||
position-independent executables.
|
||||
position-independent executables. So far only i386
|
||||
instructions are used, but the code is optimized for i686
|
||||
class CPUs. If you are compiling liblzma exclusively for
|
||||
pre-i686 systems, you may want to disable the assembler
|
||||
code.
|
||||
|
||||
--enable-small
|
||||
Omits precomputed tables. This makes liblzma a few KiB
|
||||
|
||||
4
THANKS
4
THANKS
@@ -6,17 +6,21 @@ Some people have helped more, some less, some don't even know they have
|
||||
been helpful, but nevertheless everyone's help has been important. :-)
|
||||
In alphabetical order:
|
||||
- Mark Adler
|
||||
- Nelson H. F. Beebe
|
||||
- Anders F. Björklund
|
||||
- İsmail Dönmez
|
||||
- Jean-loup Gailly
|
||||
- Per Øyvind Karlsen
|
||||
- Ville Koskinen
|
||||
- Stephan Kulow
|
||||
- Jim Meyering
|
||||
- Igor Pavlov
|
||||
- Mikko Pouru
|
||||
- Alexandre Sauvé
|
||||
- Julian Seward
|
||||
- Paul Townsend
|
||||
- Mohammed Adnène Trojette
|
||||
- Andreas Zieringer
|
||||
|
||||
Also thanks to all the people who have participated the Tukaani project
|
||||
and others who I have forgot.
|
||||
|
||||
489
configure.ac
489
configure.ac
@@ -26,7 +26,7 @@ AC_PREREQ(2.61)
|
||||
|
||||
# [LZMA] instead of [LZMA utils] since I prefer to have lzma-version.tar.gz
|
||||
# instead of lzma-utils-version.tar.gz.
|
||||
AC_INIT([LZMA], [4.42.2alpha], [lasse.collin@tukaani.org])
|
||||
AC_INIT([LZMA], [4.999.5alpha], [lasse.collin@tukaani.org])
|
||||
|
||||
AC_CONFIG_SRCDIR([src/liblzma/common/common.h])
|
||||
AC_CONFIG_HEADER([config.h])
|
||||
@@ -39,22 +39,30 @@ echo "System type:"
|
||||
# This is needed to know if assembler optimizations can be used.
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
|
||||
echo
|
||||
echo "Configure options:"
|
||||
|
||||
# Enable/disable debugging code:
|
||||
|
||||
#############
|
||||
# Debugging #
|
||||
#############
|
||||
|
||||
AC_MSG_CHECKING([if debugging code should be compiled])
|
||||
AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [Enable debugging code.]),
|
||||
[], enable_debug=no)
|
||||
if test "x$enable_debug" = xyes; then
|
||||
CFLAGS="-g $CFLAGS"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_DEFINE(NDEBUG, 1, [Define to disable debugging code.])
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
# Enable/disable the encoder components:
|
||||
|
||||
###########
|
||||
# Encoder #
|
||||
###########
|
||||
|
||||
AC_MSG_CHECKING([if encoder components should be built])
|
||||
AC_ARG_ENABLE(encoder, AC_HELP_STRING([--disable-encoder],
|
||||
[Do not build the encoder components.]),
|
||||
@@ -68,7 +76,11 @@ else
|
||||
fi
|
||||
AM_CONDITIONAL(COND_MAIN_ENCODER, test "x$enable_encoder" = xyes)
|
||||
|
||||
# Enable/disable the decoder components:
|
||||
|
||||
###########
|
||||
# Decoder #
|
||||
###########
|
||||
|
||||
AC_MSG_CHECKING([if decoder components should be built])
|
||||
AC_ARG_ENABLE(decoder, AC_HELP_STRING([--disable-decoder],
|
||||
[Do not build the decoder components.]),
|
||||
@@ -85,146 +97,146 @@ else
|
||||
fi
|
||||
AM_CONDITIONAL(COND_MAIN_DECODER, test "x$enable_decoder" = xyes)
|
||||
|
||||
# Filters
|
||||
AC_MSG_CHECKING([which filters to build])
|
||||
AC_ARG_ENABLE(filters, AC_HELP_STRING([--enable-filters=],
|
||||
[Comma-separated list of filters to build. Default=all.
|
||||
Filters used in encoding are needed also in decoding.
|
||||
Available filters: copy subblock x86 powerpc ia64
|
||||
arm armthumb sparc delta lzma]),
|
||||
[], [enable_filters=copy,subblock,x86,powerpc,ia64,arm,armthumb,sparc,delta,lzma])
|
||||
enable_filters=`echo "$enable_filters" | sed 's/,/ /g'`
|
||||
enable_filters_copy=no
|
||||
enable_filters_subblock=no
|
||||
enable_filters_x86=no
|
||||
enable_filters_powerpc=no
|
||||
enable_filters_ia64=no
|
||||
enable_filters_arm=no
|
||||
enable_filters_armthumb=no
|
||||
enable_filters_sparc=no
|
||||
enable_filters_delta=no
|
||||
enable_filters_lzma=no
|
||||
enable_simple_filters=no
|
||||
if test "x$enable_filters" = xno || test "x$enable_filters" = x; then
|
||||
AC_MSG_RESULT([])
|
||||
AC_MSG_ERROR([Please enable at least one filter.])
|
||||
|
||||
###########
|
||||
# Filters #
|
||||
###########
|
||||
|
||||
m4_define([SUPPORTED_FILTERS], [lzma,lzma2,subblock,delta,x86,powerpc,ia64,arm,armthumb,sparc])dnl
|
||||
m4_define([SIMPLE_FILTERS], [x86,powerpc,ia64,arm,armthumb,sparc])
|
||||
m4_define([LZ_FILTERS], [lzma,lzma2])
|
||||
|
||||
m4_foreach([NAME], [SUPPORTED_FILTERS],
|
||||
[enable_filter_[]NAME=no
|
||||
enable_encoder_[]NAME=no
|
||||
enable_decoder_[]NAME=no
|
||||
])dnl
|
||||
|
||||
AC_MSG_CHECKING([which encoders to build])
|
||||
AC_ARG_ENABLE([encoders], AC_HELP_STRING([--enable-encoders=LIST],
|
||||
[Comma-separated list of encoders to build. Default=all.
|
||||
Available encoders:]
|
||||
m4_translit(m4_defn([SUPPORTED_FILTERS]), [,], [ ])),
|
||||
[], [enable_encoders=SUPPORTED_FILTERS])
|
||||
enable_encoders=`echo "$enable_encoders" | sed 's/,/ /g'`
|
||||
if test "x$enable_encoders" = xno || test "x$enable_encoders" = x; then
|
||||
AC_MSG_RESULT([(none)])
|
||||
else
|
||||
for arg in $enable_filters
|
||||
for arg in $enable_encoders
|
||||
do
|
||||
case $arg in
|
||||
copy)
|
||||
enable_filters_copy=yes
|
||||
AC_DEFINE([HAVE_FILTER_COPY], 1,
|
||||
[Define to 1 if support for the
|
||||
Copy filter is enabled.])
|
||||
;;
|
||||
subblock)
|
||||
enable_filters_subblock=yes
|
||||
AC_DEFINE([HAVE_FILTER_SUBBLOCK], 1,
|
||||
[Define to 1 if support for the
|
||||
Subblock filter is enabled.])
|
||||
;;
|
||||
x86)
|
||||
enable_filters_x86=yes
|
||||
enable_simple_filters=yes
|
||||
AC_DEFINE([HAVE_FILTER_X86], 1,
|
||||
[Define to 1 if support for the
|
||||
x86 (BCJ) filter is enabled.])
|
||||
;;
|
||||
powerpc)
|
||||
enable_filters_powerpc=yes
|
||||
enable_simple_filters=yes
|
||||
AC_DEFINE([HAVE_FILTER_POWERPC], 1,
|
||||
[Define to 1 if support for the
|
||||
PowerPC filter is enabled.])
|
||||
;;
|
||||
ia64)
|
||||
enable_filters_ia64=yes
|
||||
enable_simple_filters=yes
|
||||
AC_DEFINE([HAVE_FILTER_IA64], 1,
|
||||
[Define to 1 if support for the
|
||||
IA64 filter is enabled.])
|
||||
;;
|
||||
arm)
|
||||
enable_filters_arm=yes
|
||||
enable_simple_filters=yes
|
||||
AC_DEFINE([HAVE_FILTER_ARM], 1,
|
||||
[Define to 1 if support for the
|
||||
ARM filter is enabled.])
|
||||
;;
|
||||
armthumb)
|
||||
enable_filters_armthumb=yes
|
||||
enable_simple_filters=yes
|
||||
AC_DEFINE([HAVE_FILTER_ARMTHUMB], 1,
|
||||
[Define to 1 if support for the
|
||||
ARMThumb filter is enabled.])
|
||||
;;
|
||||
sparc)
|
||||
enable_filters_sparc=yes
|
||||
enable_simple_filters=yes
|
||||
AC_DEFINE([HAVE_FILTER_SPARC], 1,
|
||||
[Define to 1 if support for the
|
||||
SPARC filter is enabled.])
|
||||
;;
|
||||
delta)
|
||||
enable_filters_delta=yes
|
||||
AC_DEFINE([HAVE_FILTER_DELTA], 1,
|
||||
[Define to 1 if support for the
|
||||
Delta filter is enabled.])
|
||||
;;
|
||||
lzma)
|
||||
enable_filters_lzma=yes
|
||||
AC_DEFINE([HAVE_FILTER_LZMA], 1,
|
||||
[Define to 1 if support for the
|
||||
LZMA filter is enabled.])
|
||||
;;
|
||||
case $arg in m4_foreach([NAME], [SUPPORTED_FILTERS], [
|
||||
NAME)
|
||||
enable_filter_[]NAME=yes
|
||||
enable_encoder_[]NAME=yes
|
||||
AC_DEFINE(HAVE_ENCODER_[]m4_toupper(NAME), [1],
|
||||
[Define to 1 if] NAME [encoder is enabled.])
|
||||
;;])
|
||||
*)
|
||||
AC_MSG_RESULT([])
|
||||
AC_MSG_ERROR([unknown filter: $arg])
|
||||
;;
|
||||
esac
|
||||
done
|
||||
AC_MSG_RESULT([$enable_filters])
|
||||
AC_MSG_RESULT([$enable_encoders])
|
||||
fi
|
||||
if test "x$enable_simple_filters" = xyes ; then
|
||||
AC_DEFINE([HAVE_FILTER_SIMPLE], 1, [Define to 1 if support for any
|
||||
of the so called simple filters is enabled.])
|
||||
fi
|
||||
AM_CONDITIONAL(COND_FILTER_COPY, test "x$enable_filters_copy" = xyes)
|
||||
AM_CONDITIONAL(COND_FILTER_SUBBLOCK, test "x$enable_filters_subblock" = xyes)
|
||||
AM_CONDITIONAL(COND_FILTER_X86, test "x$enable_filters_x86" = xyes)
|
||||
AM_CONDITIONAL(COND_FILTER_POWERPC, test "x$enable_filters_powerpc" = xyes)
|
||||
AM_CONDITIONAL(COND_FILTER_IA64, test "x$enable_filters_ia64" = xyes)
|
||||
AM_CONDITIONAL(COND_FILTER_ARM, test "x$enable_filters_arm" = xyes)
|
||||
AM_CONDITIONAL(COND_FILTER_ARMTHUMB, test "x$enable_filters_armthumb" = xyes)
|
||||
AM_CONDITIONAL(COND_FILTER_SPARC, test "x$enable_filters_sparc" = xyes)
|
||||
AM_CONDITIONAL(COND_FILTER_DELTA, test "x$enable_filters_delta" = xyes)
|
||||
AM_CONDITIONAL(COND_FILTER_LZMA, test "x$enable_filters_lzma" = xyes)
|
||||
AM_CONDITIONAL(COND_MAIN_SIMPLE, test "x$enable_simple_filters" = xyes)
|
||||
|
||||
# Which match finders should be enabled:
|
||||
AC_MSG_CHECKING([which decoders to build])
|
||||
AC_ARG_ENABLE([decoders], AC_HELP_STRING([--enable-decoders=LIST],
|
||||
[Comma-separated list of decoders to build. Default=all.
|
||||
Available decoders are the same as available encoders.]),
|
||||
[], [enable_decoders=SUPPORTED_FILTERS])
|
||||
enable_decoders=`echo "$enable_decoders" | sed 's/,/ /g'`
|
||||
if test "x$enable_decoders" = xno || test "x$enable_decoders" = x; then
|
||||
AC_MSG_RESULT([(none)])
|
||||
else
|
||||
for arg in $enable_decoders
|
||||
do
|
||||
case $arg in m4_foreach([NAME], [SUPPORTED_FILTERS], [
|
||||
NAME)
|
||||
enable_filter_[]NAME=yes
|
||||
enable_decoder_[]NAME=yes
|
||||
AC_DEFINE(HAVE_DECODER_[]m4_toupper(NAME), [1],
|
||||
[Define to 1 if] NAME [decoder is enabled.])
|
||||
;;])
|
||||
*)
|
||||
AC_MSG_RESULT([])
|
||||
AC_MSG_ERROR([unknown filter: $arg])
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# LZMA2 requires that LZMA is enabled.
|
||||
test "x$enable_encoder_lzma2" = xyes && enable_encoder_lzma=yes
|
||||
test "x$enable_decoder_lzma2" = xyes && enable_decoder_lzma=yes
|
||||
|
||||
AC_MSG_RESULT([$enable_decoders])
|
||||
fi
|
||||
|
||||
if test "x$enable_encoder_lzma2$enable_encoder_lzma" = xyesno \
|
||||
|| test "x$enable_decoder_lzma2$enable_decoder_lzma" = xyesno; then
|
||||
AC_MSG_ERROR([LZMA2 requires that LZMA is also enabled.])
|
||||
fi
|
||||
|
||||
m4_foreach([NAME], [SUPPORTED_FILTERS],
|
||||
[AM_CONDITIONAL(COND_FILTER_[]m4_toupper(NAME), test "x$enable_filter_[]NAME" = xyes)
|
||||
AM_CONDITIONAL(COND_ENCODER_[]m4_toupper(NAME), test "x$enable_encoder_[]NAME" = xyes)
|
||||
AM_CONDITIONAL(COND_DECODER_[]m4_toupper(NAME), test "x$enable_decoder_[]NAME" = xyes)
|
||||
])dnl
|
||||
|
||||
# The so called "simple filters" share common code.
|
||||
enable_filter_simple=no
|
||||
enable_encoder_simple=no
|
||||
enable_decoder_simple=no
|
||||
m4_foreach([NAME], [SIMPLE_FILTERS],
|
||||
[test "x$enable_filter_[]NAME" = xyes && enable_filter_simple=yes
|
||||
test "x$enable_encoder_[]NAME" = xyes && enable_encoder_simple=yes
|
||||
test "x$enable_decoder_[]NAME" = xyes && enable_decoder_simple=yes
|
||||
])dnl
|
||||
AM_CONDITIONAL(COND_FILTER_SIMPLE, test "x$enable_filter_simple" = xyes)
|
||||
AM_CONDITIONAL(COND_ENCODER_SIMPLE, test "x$enable_encoder_simple" = xyes)
|
||||
AM_CONDITIONAL(COND_DECODER_SIMPLE, test "x$enable_decoder_simple" = xyes)
|
||||
|
||||
# LZ-based filters share common code.
|
||||
enable_filter_lz=no
|
||||
enable_encoder_lz=no
|
||||
enable_decoder_lz=no
|
||||
m4_foreach([NAME], [LZ_FILTERS],
|
||||
[test "x$enable_filter_[]NAME" = xyes && enable_filter_lz=yes
|
||||
test "x$enable_encoder_[]NAME" = xyes && enable_encoder_lz=yes
|
||||
test "x$enable_decoder_[]NAME" = xyes && enable_decoder_lz=yes
|
||||
])dnl
|
||||
AM_CONDITIONAL(COND_FILTER_LZ, test "x$enable_filter_lz" = xyes)
|
||||
AM_CONDITIONAL(COND_ENCODER_LZ, test "x$enable_encoder_lz" = xyes)
|
||||
AM_CONDITIONAL(COND_DECODER_LZ, test "x$enable_decoder_lz" = xyes)
|
||||
|
||||
|
||||
#################
|
||||
# Match finders #
|
||||
#################
|
||||
|
||||
m4_define([SUPPORTED_MATCH_FINDERS], [hc3,hc4,bt2,bt3,bt4])
|
||||
|
||||
m4_foreach([NAME], [SUPPORTED_MATCH_FINDERS],
|
||||
[enable_match_finder_[]NAME=no
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING([which match finders to build])
|
||||
AC_ARG_ENABLE(match-finders, AC_HELP_STRING([--enable-match-finders=],
|
||||
AC_ARG_ENABLE(match-finders, AC_HELP_STRING([--enable-match-finders=LIST],
|
||||
[Comma-separated list of match finders to build. Default=all.
|
||||
At least one match finder is required for encoding with
|
||||
the LZMA filter.
|
||||
Available match finders: hc3 hc4 bt2 bt3 bt4]), [],
|
||||
[enable_match_finders=hc3,hc4,bt2,bt3,bt4])
|
||||
the LZMA filter. Available match finders:]
|
||||
m4_translit(m4_defn([SUPPORTED_MATCH_FINDERS]), [,], [ ])), [],
|
||||
[enable_match_finders=SUPPORTED_MATCH_FINDERS])
|
||||
enable_match_finders=`echo "$enable_match_finders" | sed 's/,/ /g'`
|
||||
enable_match_finders_hc3=no
|
||||
enable_match_finders_hc4=no
|
||||
enable_match_finders_bt2=no
|
||||
enable_match_finders_bt3=no
|
||||
enable_match_finders_bt4=no
|
||||
if test "x$enable_encoder" = xyes && test "x$enable_filters_lzma" = xyes ; then
|
||||
if test "x$enable_encoder" = xyes && test "x$enable_encoder_lz" = xyes ; then
|
||||
for arg in $enable_match_finders
|
||||
do
|
||||
case $arg in
|
||||
hc3) enable_match_finders_hc3=yes ;;
|
||||
hc4) enable_match_finders_hc4=yes ;;
|
||||
bt2) enable_match_finders_bt2=yes ;;
|
||||
bt3) enable_match_finders_bt3=yes ;;
|
||||
bt4) enable_match_finders_bt4=yes ;;
|
||||
case $arg in m4_foreach([NAME], [SUPPORTED_MATCH_FINDERS], [
|
||||
NAME)
|
||||
enable_match_finder_[]NAME=yes
|
||||
AC_DEFINE(HAVE_MF_[]m4_toupper(NAME), [1],
|
||||
[Define to 1 to enable] NAME [match finder.])
|
||||
;;])
|
||||
*)
|
||||
AC_MSG_RESULT([])
|
||||
AC_MSG_ERROR([unknown match finder: $arg])
|
||||
@@ -233,48 +245,39 @@ if test "x$enable_encoder" = xyes && test "x$enable_filters_lzma" = xyes ; then
|
||||
done
|
||||
AC_MSG_RESULT([$enable_match_finders])
|
||||
else
|
||||
AC_MSG_RESULT([(none because not building the LZMA encoder)])
|
||||
AC_MSG_RESULT([(none because not building any LZ-based encoder)])
|
||||
fi
|
||||
AM_CONDITIONAL(COND_MF_HC3, test "x$enable_match_finders_hc3" = xyes)
|
||||
AM_CONDITIONAL(COND_MF_HC4, test "x$enable_match_finders_hc4" = xyes)
|
||||
AM_CONDITIONAL(COND_MF_BT2, test "x$enable_match_finders_bt2" = xyes)
|
||||
AM_CONDITIONAL(COND_MF_BT3, test "x$enable_match_finders_bt3" = xyes)
|
||||
AM_CONDITIONAL(COND_MF_BT4, test "x$enable_match_finders_bt4" = xyes)
|
||||
|
||||
# Which integrity checks to build
|
||||
|
||||
####################
|
||||
# Integrity checks #
|
||||
####################
|
||||
|
||||
m4_define([SUPPORTED_CHECKS], [crc32,crc64,sha256])
|
||||
|
||||
m4_foreach([NAME], [SUPPORTED_FILTERS],
|
||||
[enable_check_[]NAME=no
|
||||
])dnl
|
||||
|
||||
AC_MSG_CHECKING([which integrity checks to build])
|
||||
AC_ARG_ENABLE(checks, AC_HELP_STRING([--enable-checks=],
|
||||
AC_ARG_ENABLE(checks, AC_HELP_STRING([--enable-checks=LIST],
|
||||
[Comma-separated list of integrity checks to build.
|
||||
Default=all. Available integrity checks: crc32 crc64 sha256]),
|
||||
[], [enable_checks=crc32,crc64,sha256])
|
||||
Default=all. Available integrity checks:]
|
||||
m4_translit(m4_defn([SUPPORTED_CHECKS]), [,], [ ])),
|
||||
[], [enable_checks=SUPPORTED_CHECKS])
|
||||
enable_checks=`echo "$enable_checks" | sed 's/,/ /g'`
|
||||
enable_checks_crc32=no
|
||||
enable_checks_crc64=no
|
||||
enable_checks_sha256=no
|
||||
if test "x$enable_checks" = xno || test "x$enable_checks" = x; then
|
||||
AC_MSG_RESULT([(none)])
|
||||
else
|
||||
for arg in $enable_checks
|
||||
do
|
||||
case $arg in
|
||||
crc32)
|
||||
enable_checks_crc32=yes
|
||||
AC_DEFINE([HAVE_CHECK_CRC32], 1,
|
||||
[Define to 1 if CRC32 support
|
||||
is enabled.])
|
||||
;;
|
||||
crc64)
|
||||
enable_checks_crc64=yes
|
||||
AC_DEFINE([HAVE_CHECK_CRC64], 1,
|
||||
[Define to 1 if CRC64 support
|
||||
is enabled.])
|
||||
;;
|
||||
sha256)
|
||||
enable_checks_sha256=yes
|
||||
AC_DEFINE([HAVE_CHECK_SHA256], 1,
|
||||
[Define to 1 if SHA256 support
|
||||
is enabled.])
|
||||
;;
|
||||
case $arg in m4_foreach([NAME], [SUPPORTED_CHECKS], [
|
||||
NAME)
|
||||
enable_check_[]NAME=yes
|
||||
AC_DEFINE(HAVE_CHECK_[]m4_toupper(NAME), [1],
|
||||
[Define to 1 if] NAME
|
||||
[integrity check is enabled.])
|
||||
;;])
|
||||
*)
|
||||
AC_MSG_RESULT([])
|
||||
AC_MSG_ERROR([unknown integrity check: $arg])
|
||||
@@ -286,39 +289,93 @@ fi
|
||||
if test "x$enable_checks_crc32" = xno ; then
|
||||
AC_MSG_ERROR([For now, the CRC32 check must always be enabled.])
|
||||
fi
|
||||
AM_CONDITIONAL(COND_CHECK_CRC32, test "x$enable_checks_crc32" = xyes)
|
||||
AM_CONDITIONAL(COND_CHECK_CRC64, test "x$enable_checks_crc64" = xyes)
|
||||
AM_CONDITIONAL(COND_CHECK_SHA256, test "x$enable_checks_sha256" = xyes)
|
||||
|
||||
# Assembler optimizations
|
||||
m4_foreach([NAME], [SUPPORTED_CHECKS],
|
||||
[AM_CONDITIONAL(COND_CHECK_[]m4_toupper(NAME), test "x$enable_check_[]NAME" = xyes)
|
||||
])dnl
|
||||
|
||||
|
||||
###########################
|
||||
# Assembler optimizations #
|
||||
###########################
|
||||
|
||||
AC_MSG_CHECKING([if assembler optimizations should be used])
|
||||
AC_ARG_ENABLE(assembler, AC_HELP_STRING([--disable-assembler],
|
||||
[Do not use assembler optimizations even if such exist
|
||||
for the architecture.]),
|
||||
[], [enable_assembler=yes])
|
||||
[], [enable_assembler=yes])
|
||||
if test "x$enable_assembler" = xyes; then
|
||||
case $host_cpu in
|
||||
i?86) enable_assembler=x86 ;;
|
||||
x86_64) enable_assembler=x86_64 ;;
|
||||
*) enable_assembler=no ;;
|
||||
esac
|
||||
# Darwin has different ABI than GNU+Linux and Solaris,
|
||||
# and the assembler code doesn't assemble.
|
||||
case $host_os in
|
||||
darwin*) enable_assembler=no ;;
|
||||
*) ;;
|
||||
esac
|
||||
fi
|
||||
case $enable_assembler in
|
||||
x86|no) ;;
|
||||
x86)
|
||||
AC_DEFINE([HAVE_ASM_X86], 1,
|
||||
[Define to 1 if using x86 assembler optimizations.])
|
||||
;;
|
||||
x86_64)
|
||||
AC_DEFINE([HAVE_ASM_X86_64], 1,
|
||||
[Define to 1 if using x86_64 assembler optimizations.])
|
||||
;;
|
||||
no)
|
||||
;;
|
||||
*)
|
||||
AC_MSG_RESULT([])
|
||||
AC_MSG_ERROR([--enable-assembler accepts only \`yes', \`no', or \`x86'.])
|
||||
AC_MSG_ERROR([--enable-assembler accepts only \`yes', \`no', \`x86', or \`x86_64'.])
|
||||
;;
|
||||
esac
|
||||
AC_MSG_RESULT([$enable_assembler])
|
||||
AM_CONDITIONAL(COND_ASM_X86, test "x$enable_assembler" = xx86)
|
||||
AM_CONDITIONAL(COND_ASM_X86_64, test "x$enable_assembler" = xx86_64)
|
||||
|
||||
|
||||
################################
|
||||
# Fast unaligned memory access #
|
||||
################################
|
||||
|
||||
AC_MSG_CHECKING([if unaligned memory access should be used])
|
||||
AC_ARG_ENABLE(unaligned-access, AC_HELP_STRING([--enable-unaligned-access],
|
||||
[Enable if the system supports *fast* unaligned memory access
|
||||
with 16-bit and 32-bit integers. By default, this is enabled
|
||||
only on x86, x86_64, and big endian PowerPC.]),
|
||||
[], [enable_unaligned_access=auto])
|
||||
if test "x$enable_unaligned_access" = xauto ; then
|
||||
case $host_cpu in
|
||||
i?86|x86_64|powerpc|powerpc64)
|
||||
enable_unaligned_access=yes
|
||||
;;
|
||||
*)
|
||||
enable_unaligned_access=no
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if test "x$enable_unaligned_access" = xyes ; then
|
||||
AC_DEFINE([HAVE_FAST_UNALIGNED_ACCESS], [1], [Define to 1 if
|
||||
the system supports fast unaligned memory access.])
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
|
||||
#####################
|
||||
# Size optimization #
|
||||
#####################
|
||||
|
||||
# Size optimization
|
||||
AC_MSG_CHECKING([if small size is preferred over speed])
|
||||
AC_ARG_ENABLE(small, AC_HELP_STRING([--enable-small],
|
||||
[Omit precomputed tables to make liblzma a few kilobytes
|
||||
smaller. This will increase startup time of applications
|
||||
slightly, because the tables need to be computed first.]),
|
||||
[], [enable_small=no])
|
||||
[Make liblzma smaller and a little slower.
|
||||
This is disabled by default to optimize for speed.]),
|
||||
[], [enable_small=no])
|
||||
if test "x$enable_small" = xyes; then
|
||||
AC_DEFINE([HAVE_SMALL], 1, [Define to 1 if optimizing for size.])
|
||||
elif test "x$enable_small" != xno; then
|
||||
@@ -328,24 +385,25 @@ fi
|
||||
AC_MSG_RESULT([$enable_small])
|
||||
AM_CONDITIONAL(COND_SMALL, test "x$enable_small" = xyes)
|
||||
|
||||
echo
|
||||
echo "Initializing Automake:"
|
||||
|
||||
# There's no C++ or Fortran in LZMA Utils:
|
||||
CXX=no
|
||||
F77=no
|
||||
|
||||
AM_INIT_AUTOMAKE
|
||||
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
|
||||
###############################################################################
|
||||
# Checks for programs.
|
||||
###############################################################################
|
||||
|
||||
echo
|
||||
echo "Initializing Automake:"
|
||||
|
||||
AM_INIT_AUTOMAKE([1.10 foreign tar-v7 filename-length-max=99])
|
||||
AC_PROG_LN_S
|
||||
|
||||
AC_PROG_CC_C99
|
||||
if test x$ac_cv_prog_cc_c99 = xno ; then
|
||||
AC_MSG_ERROR([No C99 compiler was found.])
|
||||
fi
|
||||
|
||||
AM_PROG_CC_C_O
|
||||
AM_PROG_AS
|
||||
AC_PROG_LN_S
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
|
||||
echo
|
||||
echo "Threading support:"
|
||||
@@ -354,6 +412,8 @@ CC="$PTHREAD_CC"
|
||||
|
||||
echo
|
||||
echo "Initializing Libtool:"
|
||||
CXX=no
|
||||
F77=no
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
|
||||
@@ -392,9 +452,20 @@ AC_CHECK_HEADERS([assert.h errno.h byteswap.h sys/param.h sys/sysctl.h],
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
###############################################################################
|
||||
|
||||
dnl We don't need these as long as we need a C99 compiler anyway.
|
||||
dnl AC_C_INLINE
|
||||
dnl AC_C_RESTRICT
|
||||
|
||||
AC_HEADER_STDBOOL
|
||||
AC_C_INLINE
|
||||
AC_C_RESTRICT
|
||||
|
||||
AC_TYPE_UINT8_T
|
||||
AC_TYPE_INT32_T
|
||||
AC_TYPE_UINT32_T
|
||||
AC_TYPE_INT64_T
|
||||
AC_TYPE_UINT64_T
|
||||
AC_TYPE_UINTPTR_T
|
||||
|
||||
AC_CHECK_SIZEOF([size_t])
|
||||
|
||||
# The command line tool can copy high resolution timestamps if such
|
||||
# information is availabe in struct stat. Otherwise one second accuracy
|
||||
@@ -402,11 +473,7 @@ AC_C_RESTRICT
|
||||
AC_CHECK_MEMBERS([struct stat.st_atim.tv_nsec, struct stat.st_mtim.tv_nsec,
|
||||
struct stat.st_atimespec.tv_nsec, struct stat.st_mtimespec.tv_nsec])
|
||||
|
||||
# It is very unlikely that you want to build liblzma without
|
||||
# large file support.
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
# At the moment, the only endian-dependent part should be the integrity checks.
|
||||
AC_C_BIGENDIAN
|
||||
|
||||
|
||||
@@ -419,7 +486,7 @@ gl_GETOPT
|
||||
|
||||
# Functions that are not mandatory i.e. we have alternatives for them
|
||||
# or we can just drop some functionality:
|
||||
AC_CHECK_FUNCS([memcpy memmove memset futimes futimesat])
|
||||
AC_CHECK_FUNCS([futimes futimesat])
|
||||
|
||||
# Check how to find out the amount of physical memory in the system. The
|
||||
# lzma command line tool uses this to automatically limits its memory usage.
|
||||
@@ -516,7 +583,7 @@ main()
|
||||
|
||||
Wno_uninitialized=no
|
||||
|
||||
if test -n "$GCC" ; then
|
||||
if test "x$GCC" = xyes ; then
|
||||
echo
|
||||
echo "GCC extensions:"
|
||||
gl_VISIBILITY
|
||||
@@ -545,13 +612,28 @@ if test -n "$GCC" ; then
|
||||
# * -Winline, -Wdisabled-optimization, -Wunsafe-loop-optimizations
|
||||
# don't seem so useful here; at least the last one gives some
|
||||
# warnings which are not bugs.
|
||||
for NEW_FLAG in -Wextra -Wformat=2 -Winit-self -Wstrict-aliasing=2 \
|
||||
-Wfloat-equal -Wshadow -Wpointer-arith \
|
||||
-Wbad-function-cast -Wwrite-strings \
|
||||
-Waggregate-return -Wstrict-prototypes \
|
||||
-Wold-style-definition -Wmissing-prototypes \
|
||||
-Wmissing-declarations -Wmissing-noreturn \
|
||||
-Wredundant-decls
|
||||
#
|
||||
# The flags are in reverse order below so they end up in "beautiful"
|
||||
# order on the actual command line.
|
||||
for NEW_FLAG in \
|
||||
-Wredundant-decls \
|
||||
-Wmissing-noreturn \
|
||||
-Wmissing-declarations \
|
||||
-Wmissing-prototypes \
|
||||
-Wold-style-definition \
|
||||
-Wstrict-prototypes \
|
||||
-Waggregate-return \
|
||||
-Wwrite-strings \
|
||||
-Wbad-function-cast \
|
||||
-Wpointer-arith \
|
||||
-Wshadow \
|
||||
-Wfloat-equal \
|
||||
-Wstrict-aliasing=2 \
|
||||
-Winit-self \
|
||||
-Wformat=2 \
|
||||
-Wextra \
|
||||
-Wall \
|
||||
-pedantic
|
||||
do
|
||||
AC_MSG_CHECKING([if $CC accepts $NEW_FLAG])
|
||||
OLD_CFLAGS="$CFLAGS"
|
||||
@@ -571,9 +653,6 @@ if test -n "$GCC" ; then
|
||||
if test "x$enable_werror" = "xyes"; then
|
||||
CFLAGS="-Werror $CFLAGS"
|
||||
fi
|
||||
|
||||
# IIRC these work with all GCC versions that support -std=c99:
|
||||
CFLAGS="-std=c99 -pedantic -Wall $CFLAGS"
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL([COND_WNO_UNINITIALIZED], test "x$Wno_uninitialized" = "xyes")
|
||||
@@ -600,15 +679,17 @@ AC_CONFIG_FILES([
|
||||
src/liblzma/api/Makefile
|
||||
src/liblzma/common/Makefile
|
||||
src/liblzma/check/Makefile
|
||||
src/liblzma/rangecoder/Makefile
|
||||
src/liblzma/lz/Makefile
|
||||
src/liblzma/lzma/Makefile
|
||||
src/liblzma/simple/Makefile
|
||||
src/liblzma/subblock/Makefile
|
||||
src/liblzma/rangecoder/Makefile
|
||||
src/liblzma/delta/Makefile
|
||||
src/liblzma/simple/Makefile
|
||||
src/lzma/Makefile
|
||||
src/lzmadec/Makefile
|
||||
src/scripts/Makefile
|
||||
tests/Makefile
|
||||
debug/Makefile
|
||||
])
|
||||
|
||||
AC_OUTPUT
|
||||
|
||||
36
debug/Makefile.am
Normal file
36
debug/Makefile.am
Normal file
@@ -0,0 +1,36 @@
|
||||
##
|
||||
## Copyright (C) 2008 Lasse Collin
|
||||
##
|
||||
## This library is free software; you can redistribute it and/or
|
||||
## modify it under the terms of the GNU Lesser General Public
|
||||
## License as published by the Free Software Foundation; either
|
||||
## version 2.1 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
|
||||
## Lesser General Public License for more details.
|
||||
##
|
||||
|
||||
noinst_PROGRAMS = \
|
||||
repeat \
|
||||
sync_flush \
|
||||
full_flush \
|
||||
memusage \
|
||||
crc32 \
|
||||
known_sizes \
|
||||
hex2bin
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I@top_srcdir@/src/common \
|
||||
-I@top_srcdir@/src/liblzma/api
|
||||
|
||||
AM_LDFLAGS = -static
|
||||
|
||||
LDADD = \
|
||||
@top_builddir@/src/liblzma/liblzma.la \
|
||||
@LTLIBINTL@
|
||||
|
||||
if COND_GNULIB
|
||||
LDADD += @top_builddir@/lib/libgnu.a
|
||||
endif
|
||||
17
debug/README
Normal file
17
debug/README
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
Debug tools
|
||||
-----------
|
||||
|
||||
This directory contains a few tiny programs that may be helpful when
|
||||
debugging LZMA Utils.
|
||||
|
||||
These tools are not meant to be installed. Often one needs to edit
|
||||
the source code a little to make the programs do the wanted things.
|
||||
If you don't know how these programs could help you, it is likely
|
||||
that they really are useless to you.
|
||||
|
||||
These aren't intended to be used as example programs. They take some
|
||||
shortcuts here and there, which correct programs should not do. Many
|
||||
possible errors (especially I/O errors) are ignored. Don't report
|
||||
bugs or send patches to fix this kind of bugs.
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file block_private.h
|
||||
/// \brief Common stuff for Block encoder and decoder
|
||||
/// \file crc32.c
|
||||
/// \brief Primitive CRC32 calculation tool
|
||||
//
|
||||
// Copyright (C) 2007 Lasse Collin
|
||||
// Copyright (C) 2008 Lasse Collin
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -17,30 +17,29 @@
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_BLOCK_COMMON_H
|
||||
#define LZMA_BLOCK_COMMON_H
|
||||
#include "sysdefs.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
static inline bool
|
||||
update_size(lzma_vli *size, lzma_vli add, lzma_vli limit)
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
if (limit > LZMA_VLI_VALUE_MAX)
|
||||
limit = LZMA_VLI_VALUE_MAX;
|
||||
uint32_t crc = 0;
|
||||
|
||||
if (limit < *size || limit - *size < add)
|
||||
return true;
|
||||
do {
|
||||
uint8_t buf[BUFSIZ];
|
||||
const size_t size = fread(buf, 1, sizeof(buf), stdin);
|
||||
crc = lzma_crc32(buf, size, crc);
|
||||
} while (!ferror(stdin) && !feof(stdin));
|
||||
|
||||
*size += add;
|
||||
//printf("%08" PRIX32 "\n", crc);
|
||||
|
||||
return false;
|
||||
// I want it little endian so it's easy to work with hex editor.
|
||||
printf("%02" PRIX32 " ", crc & 0xFF);
|
||||
printf("%02" PRIX32 " ", (crc >> 8) & 0xFF);
|
||||
printf("%02" PRIX32 " ", (crc >> 16) & 0xFF);
|
||||
printf("%02" PRIX32 " ", crc >> 24);
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static inline bool
|
||||
is_size_valid(lzma_vli size, lzma_vli reference)
|
||||
{
|
||||
return reference == LZMA_VLI_VALUE_UNKNOWN || reference == size;
|
||||
}
|
||||
|
||||
#endif
|
||||
105
debug/full_flush.c
Normal file
105
debug/full_flush.c
Normal file
@@ -0,0 +1,105 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file full_flush.c
|
||||
/// \brief Encode files using LZMA_FULL_FLUSH
|
||||
//
|
||||
// Copyright (C) 2008 Lasse Collin
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "sysdefs.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
static lzma_stream strm = LZMA_STREAM_INIT;
|
||||
static FILE *file_in;
|
||||
|
||||
|
||||
static void
|
||||
encode(size_t size, lzma_action action)
|
||||
{
|
||||
static const size_t CHUNK = 64;
|
||||
uint8_t in[CHUNK];
|
||||
uint8_t out[CHUNK];
|
||||
lzma_ret ret;
|
||||
|
||||
do {
|
||||
if (strm.avail_in == 0 && size > 0) {
|
||||
const size_t amount = MIN(size, CHUNK);
|
||||
strm.avail_in = fread(in, 1, amount, file_in);
|
||||
strm.next_in = in;
|
||||
size -= amount; // Intentionally not using avail_in.
|
||||
}
|
||||
|
||||
strm.next_out = out;
|
||||
strm.avail_out = CHUNK;
|
||||
|
||||
ret = lzma_code(&strm, size == 0 ? action : LZMA_RUN);
|
||||
|
||||
if (ret != LZMA_OK && ret != LZMA_STREAM_END) {
|
||||
fprintf(stderr, "%s:%u: %s: ret == %d\n",
|
||||
__FILE__, __LINE__, __func__, ret);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fwrite(out, 1, CHUNK - strm.avail_out, stdout);
|
||||
|
||||
} while (size > 0 || strm.avail_out == 0);
|
||||
|
||||
if ((action == LZMA_RUN && ret != LZMA_OK)
|
||||
|| (action != LZMA_RUN && ret != LZMA_STREAM_END)) {
|
||||
fprintf(stderr, "%s:%u: %s: ret == %d\n",
|
||||
__FILE__, __LINE__, __func__, ret);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
lzma_init_encoder();
|
||||
|
||||
file_in = argc > 1 ? fopen(argv[1], "rb") : stdin;
|
||||
|
||||
|
||||
// Config
|
||||
lzma_filter filters[LZMA_BLOCK_FILTERS_MAX + 1];
|
||||
filters[0].id = LZMA_FILTER_LZMA2;
|
||||
filters[0].options = (void *)&lzma_preset_lzma[0];
|
||||
filters[1].id = LZMA_VLI_VALUE_UNKNOWN;
|
||||
|
||||
// Init
|
||||
if (lzma_stream_encoder(&strm, filters, LZMA_CHECK_SHA256) != LZMA_OK) {
|
||||
fprintf(stderr, "init failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// if (lzma_easy_encoder(&strm, 1)) {
|
||||
// fprintf(stderr, "init failed\n");
|
||||
// exit(1);
|
||||
// }
|
||||
|
||||
// Encoding
|
||||
encode(0, LZMA_FULL_FLUSH);
|
||||
encode(6, LZMA_FULL_FLUSH);
|
||||
encode(0, LZMA_FULL_FLUSH);
|
||||
encode(7, LZMA_FULL_FLUSH);
|
||||
encode(0, LZMA_FULL_FLUSH);
|
||||
encode(0, LZMA_FINISH);
|
||||
|
||||
// Clean up
|
||||
lzma_end(&strm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
54
debug/hex2bin.c
Normal file
54
debug/hex2bin.c
Normal file
@@ -0,0 +1,54 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file hex2bin.c
|
||||
/// \brief Converts hexadecimal input strings to binary
|
||||
//
|
||||
// This code has been put into the public domain.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "sysdefs.h"
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
static int
|
||||
getbin(int x)
|
||||
{
|
||||
if (x >= '0' && x <= '9')
|
||||
return x - '0';
|
||||
|
||||
if (x >= 'A' && x <= 'F')
|
||||
return x - 'A' + 10;
|
||||
|
||||
return x - 'a' + 10;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
while (true) {
|
||||
int byte = getchar();
|
||||
if (byte == EOF)
|
||||
return 0;
|
||||
if (!isxdigit(byte))
|
||||
continue;
|
||||
|
||||
const int digit = getchar();
|
||||
if (digit == EOF || !isxdigit(digit)) {
|
||||
fprintf(stderr, "Invalid input\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
byte = (getbin(byte) << 4) | getbin(digit);
|
||||
if (putchar(byte) == EOF) {
|
||||
perror(NULL);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
135
debug/known_sizes.c
Normal file
135
debug/known_sizes.c
Normal file
@@ -0,0 +1,135 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file known_sizes.c
|
||||
/// \brief Encodes .lzma Stream with sizes known in Block Header
|
||||
///
|
||||
/// The input file is encoded in RAM, and the known Compressed Size
|
||||
/// and/or Uncompressed Size values are stored in the Block Header.
|
||||
/// As of writing there's no such Stream encoder in liblzma.
|
||||
//
|
||||
// Copyright (C) 2008 Lasse Collin
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "sysdefs.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
// Support file sizes up to 1 MiB. We use this for output space too, so files
|
||||
// close to 1 MiB had better compress at least a little or we have a buffer
|
||||
// overflow.
|
||||
#define BUFFER_SIZE (1U << 20)
|
||||
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
// Allocate the buffers.
|
||||
uint8_t *in = malloc(BUFFER_SIZE);
|
||||
uint8_t *out = malloc(BUFFER_SIZE);
|
||||
if (in == NULL || out == NULL)
|
||||
return 1;
|
||||
|
||||
// Fill the input buffer.
|
||||
const size_t in_size = fread(in, 1, BUFFER_SIZE, stdin);
|
||||
|
||||
// Filter setup
|
||||
lzma_filter filters[] = {
|
||||
{
|
||||
.id = LZMA_FILTER_LZMA2,
|
||||
.options = (void *)(&lzma_preset_lzma[0])
|
||||
},
|
||||
{
|
||||
.id = LZMA_VLI_VALUE_UNKNOWN
|
||||
}
|
||||
};
|
||||
|
||||
lzma_block block = {
|
||||
.check = LZMA_CHECK_CRC32,
|
||||
.compressed_size = BUFFER_SIZE, // Worst case reserve
|
||||
.uncompressed_size = in_size,
|
||||
.filters = filters,
|
||||
};
|
||||
|
||||
// FIXME Insane paranoia in liblzma.
|
||||
if (lzma_block_header_size(&block) != LZMA_OK)
|
||||
return 1;
|
||||
|
||||
// We don't actually know the compressed size, so don't tell it to
|
||||
// Block encoder.
|
||||
block.compressed_size = LZMA_VLI_VALUE_UNKNOWN;
|
||||
|
||||
lzma_stream strm = LZMA_STREAM_INIT;
|
||||
if (lzma_block_encoder(&strm, &block) != LZMA_OK)
|
||||
return 1;
|
||||
|
||||
// Reserve space for Stream Header and Block Header.
|
||||
size_t out_size = LZMA_STREAM_HEADER_SIZE + block.header_size;
|
||||
|
||||
strm.next_in = in;
|
||||
strm.avail_in = in_size;
|
||||
strm.next_out = out + out_size;
|
||||
strm.avail_out = BUFFER_SIZE - out_size;
|
||||
|
||||
if (lzma_code(&strm, LZMA_FINISH) != LZMA_STREAM_END)
|
||||
return 1;
|
||||
|
||||
out_size += strm.total_out;
|
||||
|
||||
if (lzma_block_header_encode(&block, out + LZMA_STREAM_HEADER_SIZE)
|
||||
!= LZMA_OK)
|
||||
return 1;
|
||||
|
||||
lzma_index *idx = lzma_index_init(NULL, NULL);
|
||||
if (idx == NULL)
|
||||
return 1;
|
||||
|
||||
if (lzma_index_append(idx, NULL, block.header_size + strm.total_out,
|
||||
strm.total_in) != LZMA_OK)
|
||||
return 1;
|
||||
|
||||
if (lzma_index_encoder(&strm, idx) != LZMA_OK)
|
||||
return 1;
|
||||
|
||||
if (lzma_code(&strm, LZMA_RUN) != LZMA_STREAM_END)
|
||||
return 1;
|
||||
|
||||
out_size += strm.total_out;
|
||||
|
||||
lzma_end(&strm);
|
||||
|
||||
lzma_index_end(idx, NULL);
|
||||
|
||||
// Encode the Stream Header and Stream Footer. backwards_size is
|
||||
// needed only for the Stream Footer.
|
||||
lzma_stream_flags sf = {
|
||||
.backward_size = strm.total_out,
|
||||
.check = block.check,
|
||||
};
|
||||
|
||||
if (lzma_stream_header_encode(&sf, out) != LZMA_OK)
|
||||
return 1;
|
||||
|
||||
if (lzma_stream_footer_encode(&sf, out + out_size) != LZMA_OK)
|
||||
return 1;
|
||||
|
||||
out_size += LZMA_STREAM_HEADER_SIZE;
|
||||
|
||||
// Write out the file.
|
||||
fwrite(out, 1, out_size, stdout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
57
debug/memusage.c
Normal file
57
debug/memusage.c
Normal file
@@ -0,0 +1,57 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file memusage.c
|
||||
/// \brief Calculates memory usage using lzma_memory_usage()
|
||||
///
|
||||
// Copyright (C) 2008 Lasse Collin
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "sysdefs.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
lzma_init();
|
||||
|
||||
lzma_options_lzma lzma = {
|
||||
.dictionary_size = (1 << 27) + (1 << 26),
|
||||
.literal_context_bits = 3,
|
||||
.literal_pos_bits = 0,
|
||||
.pos_bits = 2,
|
||||
.preset_dictionary = NULL,
|
||||
.preset_dictionary_size = 0,
|
||||
.mode = LZMA_MODE_NORMAL,
|
||||
.fast_bytes = 48,
|
||||
.match_finder = LZMA_MF_BT4,
|
||||
.match_finder_cycles = 0,
|
||||
};
|
||||
|
||||
/*
|
||||
lzma_options_filter filters[] = {
|
||||
{ LZMA_FILTER_LZMA,
|
||||
(lzma_options_lzma *)&lzma_preset_lzma[6 - 1] },
|
||||
{ UINT64_MAX, NULL }
|
||||
};
|
||||
*/
|
||||
lzma_filter filters[] = {
|
||||
{ LZMA_FILTER_LZMA, &lzma },
|
||||
{ UINT64_MAX, NULL }
|
||||
};
|
||||
|
||||
printf("Encoder: %10" PRIu64 " B\n", lzma_memusage_encoder(filters));
|
||||
printf("Decoder: %10" PRIu64 " B\n", lzma_memusage_decoder(filters));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,9 +1,13 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file raw_decoder.h
|
||||
/// \brief Raw decoder initialization API
|
||||
/// \file repeat.c
|
||||
/// \brief Repeats given string given times
|
||||
///
|
||||
/// This program can be useful when debugging run-length encoder in
|
||||
/// the Subblock filter, especially the condition when repeat count
|
||||
/// doesn't fit into 28-bit integer.
|
||||
//
|
||||
// Copyright (C) 2007 Lasse Collin
|
||||
// Copyright (C) 2008 Lasse Collin
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -17,14 +21,23 @@
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_RAW_DECODER_H
|
||||
#define LZMA_RAW_DECODER_H
|
||||
|
||||
#include "raw_common.h"
|
||||
#include "sysdefs.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
extern lzma_ret lzma_raw_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_options_filter *options,
|
||||
lzma_vli uncompressed_size, bool implicit);
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "Usage: %s COUNT STRING\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#endif
|
||||
unsigned long long count = strtoull(argv[1], NULL, 10);
|
||||
const size_t size = strlen(argv[2]);
|
||||
|
||||
while (count-- != 0)
|
||||
fwrite(argv[2], 1, size, stdout);
|
||||
|
||||
return !!(ferror(stdout) || fclose(stdout));
|
||||
}
|
||||
141
debug/sync_flush.c
Normal file
141
debug/sync_flush.c
Normal file
@@ -0,0 +1,141 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file sync_flush.c
|
||||
/// \brief Encode files using LZMA_SYNC_FLUSH
|
||||
//
|
||||
// Copyright (C) 2008 Lasse Collin
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "sysdefs.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
static lzma_stream strm = LZMA_STREAM_INIT;
|
||||
static FILE *file_in;
|
||||
|
||||
|
||||
static void
|
||||
encode(size_t size, lzma_action action)
|
||||
{
|
||||
static const size_t CHUNK = 64;
|
||||
uint8_t in[CHUNK];
|
||||
uint8_t out[CHUNK];
|
||||
lzma_ret ret;
|
||||
|
||||
do {
|
||||
if (strm.avail_in == 0 && size > 0) {
|
||||
const size_t amount = MIN(size, CHUNK);
|
||||
strm.avail_in = fread(in, 1, amount, file_in);
|
||||
strm.next_in = in;
|
||||
size -= amount; // Intentionally not using avail_in.
|
||||
}
|
||||
|
||||
strm.next_out = out;
|
||||
strm.avail_out = CHUNK;
|
||||
|
||||
ret = lzma_code(&strm, size == 0 ? action : LZMA_RUN);
|
||||
|
||||
if (ret != LZMA_OK && ret != LZMA_STREAM_END) {
|
||||
fprintf(stderr, "%s:%u: %s: ret == %d\n",
|
||||
__FILE__, __LINE__, __func__, ret);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fwrite(out, 1, CHUNK - strm.avail_out, stdout);
|
||||
|
||||
} while (size > 0 || strm.avail_out == 0);
|
||||
|
||||
if ((action == LZMA_RUN && ret != LZMA_OK)
|
||||
|| (action != LZMA_RUN && ret != LZMA_STREAM_END)) {
|
||||
fprintf(stderr, "%s:%u: %s: ret == %d\n",
|
||||
__FILE__, __LINE__, __func__, ret);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
lzma_init_encoder();
|
||||
|
||||
file_in = argc > 1 ? fopen(argv[1], "rb") : stdin;
|
||||
|
||||
// Config
|
||||
lzma_options_lzma opt_lzma = {
|
||||
.dictionary_size = 1 << 16,
|
||||
.literal_context_bits = LZMA_LITERAL_CONTEXT_BITS_DEFAULT,
|
||||
.literal_pos_bits = LZMA_LITERAL_POS_BITS_DEFAULT,
|
||||
.pos_bits = LZMA_POS_BITS_DEFAULT,
|
||||
.preset_dictionary = NULL,
|
||||
.persistent = true,
|
||||
.mode = LZMA_MODE_NORMAL,
|
||||
.fast_bytes = 32,
|
||||
.match_finder = LZMA_MF_HC3,
|
||||
.match_finder_cycles = 0,
|
||||
};
|
||||
|
||||
lzma_options_delta opt_delta = {
|
||||
.distance = 16
|
||||
};
|
||||
|
||||
lzma_options_subblock opt_subblock = {
|
||||
.allow_subfilters = true,
|
||||
.alignment = 8, // LZMA_SUBBLOCK_ALIGNMENT_DEFAULT,
|
||||
.subblock_data_size = LZMA_SUBBLOCK_DATA_SIZE_DEFAULT,
|
||||
.rle = 1, // LZMA_SUBBLOCK_RLE_OFF,
|
||||
.subfilter_mode = LZMA_SUBFILTER_SET,
|
||||
};
|
||||
opt_subblock.subfilter_options.id = LZMA_FILTER_LZMA;
|
||||
opt_subblock.subfilter_options.options = &opt_lzma;
|
||||
opt_subblock.subfilter_options.id = LZMA_FILTER_DELTA;
|
||||
opt_subblock.subfilter_options.options = &opt_delta;
|
||||
|
||||
lzma_filter filters[LZMA_BLOCK_FILTERS_MAX + 1];
|
||||
filters[0].id = LZMA_FILTER_LZMA2;
|
||||
filters[0].options = &opt_lzma;
|
||||
filters[1].id = LZMA_VLI_VALUE_UNKNOWN;
|
||||
|
||||
// Init
|
||||
if (lzma_stream_encoder(&strm, filters, LZMA_CHECK_CRC32) != LZMA_OK) {
|
||||
fprintf(stderr, "init failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Encoding
|
||||
/*
|
||||
encode(0, LZMA_SYNC_FLUSH);
|
||||
encode(6, LZMA_SYNC_FLUSH);
|
||||
encode(0, LZMA_SYNC_FLUSH);
|
||||
encode(7, LZMA_SYNC_FLUSH);
|
||||
encode(0, LZMA_SYNC_FLUSH);
|
||||
encode(0, LZMA_FINISH);
|
||||
*/
|
||||
encode(53, LZMA_SYNC_FLUSH);
|
||||
// opt_lzma.literal_context_bits = 2;
|
||||
// opt_lzma.literal_pos_bits = 1;
|
||||
// opt_lzma.pos_bits = 0;
|
||||
encode(404, LZMA_FINISH);
|
||||
|
||||
// Clean up
|
||||
lzma_end(&strm);
|
||||
|
||||
return 0;
|
||||
|
||||
// Prevent useless warnings so we don't need to have special CFLAGS
|
||||
// to disable -Werror.
|
||||
(void)opt_lzma;
|
||||
(void)opt_subblock;
|
||||
(void)opt_delta;
|
||||
}
|
||||
@@ -80,8 +80,8 @@ Q: Which file formats are supported by LZMA Utils?
|
||||
A: Even when the raw LZMA stream is always the same, it can be wrapped
|
||||
in different container formats. The preferred format is the new .lzma
|
||||
format. It has magic bytes (the first six bytes: 0xFF 'L' 'Z' 'M'
|
||||
'A' 0x00). The format supports chaining up to seven filters filters,
|
||||
splitting data to multiple blocks for easier multi-threading and rough
|
||||
'A' 0x00). The format supports chaining up to seven filters, splitting
|
||||
data to multiple blocks for easier multi-threading and rough
|
||||
random-access reading. The file integrity is verified using CRC32,
|
||||
CRC64, or SHA256, and by verifying the uncompressed size of the file.
|
||||
|
||||
|
||||
2089
doc/file-format.txt
2089
doc/file-format.txt
File diff suppressed because it is too large
Load Diff
@@ -247,7 +247,7 @@ y.x.1. Single-Block Stream
|
||||
this prevents it from producing too much output in case of (possibly
|
||||
intentionally) corrupt file.
|
||||
|
||||
Calculate the the start offset of the Stream:
|
||||
Calculate the start offset of the Stream:
|
||||
|
||||
backward_offset - backward_size - LZMA_STREAM_HEADER_SIZE
|
||||
|
||||
|
||||
@@ -5,8 +5,14 @@ Introduction to liblzma
|
||||
Writing applications to work with liblzma
|
||||
|
||||
liblzma API is split in several subheaders to improve readability and
|
||||
maintainance. The subheaders must not be #included directly; simply
|
||||
use `#include <lzma.h>' instead.
|
||||
maintainance. The subheaders must not be #included directly. lzma.h
|
||||
requires that certain integer types and macros are available when
|
||||
the header is #included. On systems that have inttypes.h that conforms
|
||||
to C99, the following will work:
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
#include <lzma.h>
|
||||
|
||||
Those who have used zlib should find liblzma's API easy to use.
|
||||
To developers who haven't used zlib before, I recommend learning
|
||||
|
||||
@@ -86,8 +86,8 @@ Using liblzma securely
|
||||
|
||||
The simplest solution is to use setrlimit() if the kernel supports
|
||||
RLIMIT_AS, which limits the memory usage of the whole process.
|
||||
For more portable and fine-grained limitting, you can use
|
||||
memory limitter functions found from <lzma/memlimit.h>.
|
||||
For more portable and fine-grained limiting, you can use
|
||||
memory limiter functions found from <lzma/memlimit.h>.
|
||||
|
||||
|
||||
1.2.1. Encoder
|
||||
@@ -118,24 +118,24 @@ Using liblzma securely
|
||||
|
||||
1.2.2. Decoder
|
||||
|
||||
A single-threaded decoder should simply use a memory limitter and
|
||||
A single-threaded decoder should simply use a memory limiter and
|
||||
indicate an error if it runs out of memory.
|
||||
|
||||
Memory-limitting with multi-threaded decoding is tricky. The simple
|
||||
Memory-limiting with multi-threaded decoding is tricky. The simple
|
||||
solution is to divide the maximum allowed memory usage with the
|
||||
maximum allowed threads, and give each Block decoder their own
|
||||
independent lzma_memory_limitter. The drawback is that if one Block
|
||||
independent lzma_memory_limiter. The drawback is that if one Block
|
||||
needs notably more RAM than any other Block, the decoder will run out
|
||||
of memory when in reality there would be plenty of free RAM.
|
||||
|
||||
An attractive alternative would be using shared lzma_memory_limitter.
|
||||
An attractive alternative would be using shared lzma_memory_limiter.
|
||||
Depending on the application and the expected type of input, this may
|
||||
either be the best solution or a source of hard-to-repeat problems.
|
||||
Consider the following requirements:
|
||||
- You use at maximum of n threads.
|
||||
- You use a maximum of n threads.
|
||||
- x(i) is the decoder memory requirements of the Block number i
|
||||
in an expected input Stream.
|
||||
- The memory limitter is set to higher value than the sum of n
|
||||
- The memory limiter is set to higher value than the sum of n
|
||||
highest values x(i).
|
||||
|
||||
(If you are better at explaining the above conditions, please
|
||||
@@ -150,7 +150,7 @@ Using liblzma securely
|
||||
Most .lzma files have all the Blocks encoded with identical settings,
|
||||
or at least the memory usage won't vary dramatically. That's why most
|
||||
multi-threaded decoders probably want to use the simple "separate
|
||||
lzma_memory_limitter for each thread" solution, possibly fallbacking
|
||||
lzma_memory_limiter for each thread" solution, possibly falling back
|
||||
to single-threaded mode in case the per-thread memory limits aren't
|
||||
enough in multi-threaded mode.
|
||||
|
||||
@@ -206,7 +206,7 @@ FIXME: Memory usage of Stream info.
|
||||
creating a denial of service like piping decoded a Data Block to
|
||||
another process would do.
|
||||
|
||||
At first it would seem that using a memory limitter would prevent
|
||||
At first it would seem that using a memory limiter would prevent
|
||||
this issue as a side effect. But it does so only if the application
|
||||
requests liblzma to allocate the Extra Records and provide them to
|
||||
the application. If Extra Records aren't requested, they aren't
|
||||
|
||||
@@ -15,19 +15,11 @@
|
||||
|
||||
## Not using gnulib-tool, at least for now. Less mess this way.
|
||||
|
||||
## We need two builds of libgnu: one with NLS and one without.
|
||||
## This is because lzma uses NLS but lzmadec doesn't, while
|
||||
## both need GNU getopt_long().
|
||||
noinst_LIBRARIES = libgnu.a libgnu_nls.a
|
||||
noinst_LIBRARIES = libgnu.a
|
||||
|
||||
libgnu_a_SOURCES =
|
||||
libgnu_a_DEPENDENCIES = $(LIBOBJS)
|
||||
libgnu_a_LIBADD = $(LIBOBJS)
|
||||
libgnu_a_CPPFLAGS = -DDISABLE_NLS=1
|
||||
|
||||
libgnu_nls_a_SOURCES =
|
||||
libgnu_nls_a_DEPENDENCIES = $(LIBOBJS)
|
||||
libgnu_nls_a_LIBADD = $(LIBOBJS)
|
||||
|
||||
EXTRA_DIST = gettext.h getopt_.h getopt.c getopt1.c getopt_int.h
|
||||
BUILT_SOURCES = $(GETOPT_H)
|
||||
|
||||
12
po/fi.po
12
po/fi.po
@@ -5,7 +5,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: fi\n"
|
||||
"Report-Msgid-Bugs-To: lasse.collin@tukaani.org\n"
|
||||
"POT-Creation-Date: 2007-12-10 14:34+0200\n"
|
||||
"POT-Creation-Date: 2008-01-07 21:30+0200\n"
|
||||
"PO-Revision-Date: 2007-08-09 22:14+0300\n"
|
||||
"Last-Translator: Lasse Collin <lasse.collin@tukaani.org>\n"
|
||||
"Language-Team: Finnish\n"
|
||||
@@ -124,14 +124,14 @@ msgstr ""
|
||||
msgid "With no FILE, or when FILE is -, read standard input.\n"
|
||||
msgstr "Jos TIEDOSTOa ei ole annettu, tai se on \"-\", luetaan vakiosyötettä.\n"
|
||||
|
||||
#: src/lzma/help.c:143
|
||||
#: src/lzma/help.c:144
|
||||
msgid "On this system and configuration, the tool will use"
|
||||
msgstr "Tässä järjestelmässä näillä asetuksilla, tämä työkalu käyttää"
|
||||
|
||||
#: src/lzma/help.c:144
|
||||
#: src/lzma/help.c:145
|
||||
#, c-format
|
||||
msgid " * roughly %zu MiB of memory at maximum; and\n"
|
||||
msgstr " * korkeintaan %zu MiB keskusmuistia (suurpiirteinen rajoitus); ja\n"
|
||||
msgid " * roughly %<PRIu64> MiB of memory at maximum; and\n"
|
||||
msgstr " * korkeintaan %<PRIu64> MiB keskusmuistia (suurpiirteinen rajoitus); ja\n"
|
||||
|
||||
#: src/lzma/help.c:147
|
||||
msgid ""
|
||||
@@ -141,7 +141,7 @@ msgstr ""
|
||||
" * korkeintaan yhtä säiettä pakkaukseen tai purkuun.\n"
|
||||
"\n"
|
||||
|
||||
#: src/lzma/help.c:151
|
||||
#: src/lzma/help.c:152
|
||||
#, c-format
|
||||
msgid "Report bugs to <%s> (in English or Finnish).\n"
|
||||
msgstr ""
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file check_byteswap.h
|
||||
/// \brief Byteswapping needed by the checks
|
||||
/// \file bswap.h
|
||||
/// \brief Byte swapping
|
||||
//
|
||||
// This code has been put into the public domain.
|
||||
//
|
||||
@@ -11,18 +11,19 @@
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_CHECK_BYTESWAP_H
|
||||
#define LZMA_CHECK_BYTESWAP_H
|
||||
#ifndef LZMA_BSWAP_H
|
||||
#define LZMA_BSWAP_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
// NOTE: We assume that config.h is already #included.
|
||||
|
||||
// byteswap.h is a GNU extension. It contains inline assembly versions
|
||||
// for byteswapping. When byteswap.h is not available, we use generic code.
|
||||
#ifdef HAVE_BYTESWAP_H
|
||||
# include <byteswap.h>
|
||||
#else
|
||||
# define bswap_16(num) \
|
||||
(((num) << 8) | ((num) >> 8))
|
||||
|
||||
# define bswap_32(num) \
|
||||
( (((num) << 24) ) \
|
||||
| (((num) << 8) & UINT32_C(0x00FF0000)) \
|
||||
167
src/common/integer.h
Normal file
167
src/common/integer.h
Normal file
@@ -0,0 +1,167 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file integer.h
|
||||
/// \brief Reading and writing integers from and to buffers
|
||||
//
|
||||
// This code has been put into the public domain.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_INTEGER_H
|
||||
#define LZMA_INTEGER_H
|
||||
|
||||
// I'm aware of AC_CHECK_ALIGNED_ACCESS_REQUIRED from Autoconf archive, but
|
||||
// it's not useful here. We don't care if unaligned access is supported,
|
||||
// we care if it is fast. Some systems can emulate unaligned access in
|
||||
// software, which is horribly slow; we want to use byte-by-byte access on
|
||||
// such systems but the Autoconf test would detect such a system as
|
||||
// supporting unaligned access.
|
||||
//
|
||||
// NOTE: HAVE_FAST_UNALIGNED_ACCESS indicates only support for 16-bit and
|
||||
// 32-bit integer loads and stores. 64-bit integers may or may not work.
|
||||
// That's why 64-bit functions are commented out.
|
||||
#ifdef HAVE_FAST_UNALIGNED_ACCESS
|
||||
|
||||
// On big endian, we need byte swapping.
|
||||
//
|
||||
// TODO: Big endian PowerPC supports byte swapping load and store instructions
|
||||
// that also allow unaligned access. Inline assembler could be OK for that.
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
# include "bswap.h"
|
||||
# define integer_le_16(n) bswap_16(n)
|
||||
# define integer_le_32(n) bswap_32(n)
|
||||
# define integer_le_64(n) bswap_64(n)
|
||||
#else
|
||||
# define integer_le_16(n) (n)
|
||||
# define integer_le_32(n) (n)
|
||||
# define integer_le_64(n) (n)
|
||||
#endif
|
||||
|
||||
|
||||
static inline uint16_t
|
||||
integer_read_16(const uint8_t buf[static 2])
|
||||
{
|
||||
uint16_t ret = *(const uint16_t *)(buf);
|
||||
return integer_le_16(ret);
|
||||
}
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
integer_read_32(const uint8_t buf[static 4])
|
||||
{
|
||||
uint32_t ret = *(const uint32_t *)(buf);
|
||||
return integer_le_32(ret);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
static inline uint64_t
|
||||
integer_read_64(const uint8_t buf[static 8])
|
||||
{
|
||||
uint64_t ret = *(const uint64_t *)(buf);
|
||||
return integer_le_64(ret);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
static inline void
|
||||
integer_write_16(uint8_t buf[static 2], uint16_t num)
|
||||
{
|
||||
*(uint16_t *)(buf) = integer_le_16(num);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
integer_write_32(uint8_t buf[static 4], uint32_t num)
|
||||
{
|
||||
*(uint32_t *)(buf) = integer_le_32(num);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
static inline void
|
||||
integer_write_64(uint8_t buf[static 8], uint64_t num)
|
||||
{
|
||||
*(uint64_t *)(buf) = integer_le_64(num);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
#else
|
||||
|
||||
static inline uint16_t
|
||||
integer_read_16(const uint8_t buf[static 2])
|
||||
{
|
||||
uint16_t ret = buf[0] | (buf[1] << 8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
integer_read_32(const uint8_t buf[static 4])
|
||||
{
|
||||
uint32_t ret = buf[0];
|
||||
ret |= (uint32_t)(buf[1]) << 8;
|
||||
ret |= (uint32_t)(buf[2]) << 16;
|
||||
ret |= (uint32_t)(buf[3]) << 24;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
static inline uint64_t
|
||||
integer_read_64(const uint8_t buf[static 8])
|
||||
{
|
||||
uint64_t ret = buf[0];
|
||||
ret |= (uint64_t)(buf[1]) << 8;
|
||||
ret |= (uint64_t)(buf[2]) << 16;
|
||||
ret |= (uint64_t)(buf[3]) << 24;
|
||||
ret |= (uint64_t)(buf[4]) << 32;
|
||||
ret |= (uint64_t)(buf[5]) << 40;
|
||||
ret |= (uint64_t)(buf[6]) << 48;
|
||||
ret |= (uint64_t)(buf[7]) << 56;
|
||||
return ret;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
static inline void
|
||||
integer_write_16(uint8_t buf[static 2], uint16_t num)
|
||||
{
|
||||
buf[0] = (uint8_t)(num);
|
||||
buf[1] = (uint8_t)(num >> 8);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
integer_write_32(uint8_t buf[static 4], uint32_t num)
|
||||
{
|
||||
buf[0] = (uint8_t)(num);
|
||||
buf[1] = (uint8_t)(num >> 8);
|
||||
buf[2] = (uint8_t)(num >> 16);
|
||||
buf[3] = (uint8_t)(num >> 24);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
static inline void
|
||||
integer_write_64(uint8_t buf[static 8], uint64_t num)
|
||||
{
|
||||
buf[0] = (uint8_t)(num);
|
||||
buf[1] = (uint8_t)(num >> 8);
|
||||
buf[2] = (uint8_t)(num >> 16);
|
||||
buf[3] = (uint8_t)(num >> 24);
|
||||
buf[4] = (uint8_t)(num >> 32);
|
||||
buf[5] = (uint8_t)(num >> 40);
|
||||
buf[6] = (uint8_t)(num >> 48);
|
||||
buf[7] = (uint8_t)(num >> 56);
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -14,17 +14,6 @@
|
||||
#ifndef PHYSMEM_H
|
||||
#define PHYSMEM_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_PHYSMEM_SYSCTL) || defined(HAVE_NCPU_SYSCTL)
|
||||
# ifdef HAVE_SYS_PARAM_H
|
||||
# include <sys/param.h>
|
||||
|
||||
@@ -31,10 +31,97 @@
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "lzma.h"
|
||||
// size_t and NULL
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
|
||||
// C99 says that inttypes.h always includes stdint.h, but some systems
|
||||
// don't do that, and require including stdint.h separately.
|
||||
#ifdef HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
// Some pre-C99 systems have SIZE_MAX in limits.h instead of stdint.h. The
|
||||
// limits are also used to figure out some macros missing from pre-C99 systems.
|
||||
#ifdef HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
// Be more compatible with systems that have non-conforming inttypes.h.
|
||||
// We assume that int is 32-bit and that long is either 32-bit or 64-bit.
|
||||
// Full Autoconf test could be more correct, but this should work well enough.
|
||||
// Note that this duplicates some code from lzma.h, but this is better since
|
||||
// we can work without inttypes.h thanks to Autoconf tests.
|
||||
#ifndef UINT32_C
|
||||
# if UINT_MAX != 4294967295U
|
||||
# error UINT32_C is not defined and unsiged int is not 32-bit.
|
||||
# endif
|
||||
# define UINT32_C(n) n ## U
|
||||
#endif
|
||||
#ifndef UINT32_MAX
|
||||
# define UINT32_MAX UINT32_C(4294967295)
|
||||
#endif
|
||||
#ifndef PRIu32
|
||||
# define PRIu32 "u"
|
||||
#endif
|
||||
#ifndef PRIX32
|
||||
# define PRIX32 "X"
|
||||
#endif
|
||||
|
||||
#if ULONG_MAX == 4294967295UL
|
||||
# ifndef UINT64_C
|
||||
# define UINT64_C(n) n ## ULL
|
||||
# endif
|
||||
# ifndef PRIu64
|
||||
# define PRIu64 "llu"
|
||||
# endif
|
||||
# ifndef PRIX64
|
||||
# define PRIX64 "llX"
|
||||
# endif
|
||||
#else
|
||||
# ifndef UINT64_C
|
||||
# define UINT64_C(n) n ## UL
|
||||
# endif
|
||||
# ifndef PRIu64
|
||||
# define PRIu64 "lu"
|
||||
# endif
|
||||
# ifndef PRIX64
|
||||
# define PRIX64 "lX"
|
||||
# endif
|
||||
#endif
|
||||
#ifndef UINT64_MAX
|
||||
# define UINT64_MAX UINT64_C(18446744073709551615)
|
||||
#endif
|
||||
|
||||
// The code currently assumes that size_t is either 32-bit or 64-bit.
|
||||
#ifndef SIZE_MAX
|
||||
# if SIZEOF_SIZE_T == 4
|
||||
# define SIZE_MAX UINT32_MAX
|
||||
# elif SIZEOF_SIZE_T == 8
|
||||
# define SIZE_MAX UINT64_MAX
|
||||
# else
|
||||
# error sizeof(size_t) is not 32-bit or 64-bit
|
||||
# endif
|
||||
#endif
|
||||
#if SIZE_MAX != UINT32_MAX && SIZE_MAX != UINT64_MAX
|
||||
# error sizeof(size_t) is not 32-bit or 64-bit
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
// Pre-C99 systems lack stdbool.h. All the code in LZMA Utils must be written
|
||||
// so that it works with fake bool type, for example:
|
||||
//
|
||||
// bool foo = (flags & 0x100) != 0;
|
||||
// bool bar = !!(flags & 0x100);
|
||||
//
|
||||
// This works with the real C99 bool but breaks with fake bool:
|
||||
//
|
||||
// bool baz = (flags & 0x100);
|
||||
//
|
||||
#ifdef HAVE_STDBOOL_H
|
||||
# include <stdbool.h>
|
||||
#else
|
||||
@@ -53,11 +140,13 @@ typedef unsigned char _Bool;
|
||||
# ifdef NDEBUG
|
||||
# define assert(x)
|
||||
# else
|
||||
// TODO: Pretty bad assert() macro.
|
||||
// TODO: Pretty bad assert macro.
|
||||
# define assert(x) (!(x) && abort())
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// string.h should be enough but let's include strings.h and memory.h too if
|
||||
// they exists, since that shouldn't do any harm, but may improve portability.
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
@@ -70,24 +159,15 @@ typedef unsigned char _Bool;
|
||||
# include <memory.h>
|
||||
#endif
|
||||
|
||||
#include "lzma.h"
|
||||
|
||||
|
||||
////////////
|
||||
// Macros //
|
||||
////////////
|
||||
|
||||
#ifndef HAVE_MEMCPY
|
||||
# define memcpy(dest, src, n) bcopy(src, dest, n)
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MEMMOVE
|
||||
# define memmove(dest, src, n) bcopy(src, dest, n)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MEMSET
|
||||
# define memzero(s, n) memset(s, 0, n)
|
||||
#else
|
||||
# define memzero(s, n) bzero(s, n)
|
||||
#endif
|
||||
#undef memzero
|
||||
#define memzero(s, n) memset(s, 0, n)
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(x, y) ((x) < (y) ? (x) : (y))
|
||||
@@ -97,4 +177,8 @@ typedef unsigned char _Bool;
|
||||
# define MAX(x, y) ((x) > (y) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
# define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,11 +22,15 @@ liblzma_la_LIBADD = \
|
||||
common/libcommon.la \
|
||||
check/libcheck.la
|
||||
|
||||
if COND_FILTER_LZ
|
||||
SUBDIRS += lz
|
||||
liblzma_la_LIBADD += lz/liblz.la
|
||||
endif
|
||||
|
||||
if COND_FILTER_LZMA
|
||||
SUBDIRS += lz lzma rangecoder
|
||||
SUBDIRS += lzma rangecoder
|
||||
liblzma_la_LIBADD += \
|
||||
lz/liblz.la \
|
||||
lzma/liblzma4.la \
|
||||
lzma/liblzma2.la \
|
||||
rangecoder/librangecoder.la
|
||||
endif
|
||||
|
||||
@@ -35,7 +39,12 @@ SUBDIRS += subblock
|
||||
liblzma_la_LIBADD += subblock/libsubblock.la
|
||||
endif
|
||||
|
||||
if COND_MAIN_SIMPLE
|
||||
if COND_FILTER_DELTA
|
||||
SUBDIRS += delta
|
||||
liblzma_la_LIBADD += delta/libdelta.la
|
||||
endif
|
||||
|
||||
if COND_FILTER_SIMPLE
|
||||
SUBDIRS += simple
|
||||
liblzma_la_LIBADD += simple/libsimple.la
|
||||
endif
|
||||
|
||||
@@ -15,24 +15,18 @@
|
||||
nobase_include_HEADERS = \
|
||||
lzma.h \
|
||||
lzma/alignment.h \
|
||||
lzma/alone.h \
|
||||
lzma/auto.h \
|
||||
lzma/base.h \
|
||||
lzma/block.h \
|
||||
lzma/check.h \
|
||||
lzma/copy.h \
|
||||
lzma/container.h \
|
||||
lzma/delta.h \
|
||||
lzma/extra.h \
|
||||
lzma/filter.h \
|
||||
lzma/index.h \
|
||||
lzma/info.h \
|
||||
lzma/index_hash.h \
|
||||
lzma/init.h \
|
||||
lzma/lzma.h \
|
||||
lzma/memlimit.h \
|
||||
lzma/metadata.h \
|
||||
lzma/raw.h \
|
||||
lzma/simple.h \
|
||||
lzma/stream.h \
|
||||
lzma/stream_flags.h \
|
||||
lzma/subblock.h \
|
||||
lzma/version.h \
|
||||
|
||||
@@ -22,18 +22,97 @@
|
||||
#ifndef LZMA_H
|
||||
#define LZMA_H
|
||||
|
||||
/********************
|
||||
* External headers *
|
||||
********************/
|
||||
/*****************************
|
||||
* Required standard headers *
|
||||
*****************************/
|
||||
|
||||
/* size_t */
|
||||
#include <sys/types.h>
|
||||
/**
|
||||
* liblzma API headers need some standard types and macros. To allow
|
||||
* including lzma.h without requiring the application to include other
|
||||
* headers first, lzma.h includes the required standard headers unless
|
||||
* they already seem to be included.
|
||||
*
|
||||
* Here's what types and macros are needed and from which headers:
|
||||
* - stddef.h: size_t, NULL
|
||||
* - stdint.h: uint8_t, uint32_t, uint64_t, UINT32_C(n), uint64_C(n),
|
||||
* UINT32_MAX, UINT64_MAX
|
||||
*
|
||||
* However, inttypes.h is a little more portable than stdint.h, although
|
||||
* inttypes.h declares some unneeded things compared to plain stdint.h.
|
||||
*
|
||||
* The hacks below aren't perfect, specifically they assume that inttypes.h
|
||||
* exists and that it typedefs at least uint8_t, uint32_t, and uint64_t,
|
||||
* and that unsigned int is 32-bit. If your application already takes care
|
||||
* of setting up all the types properly (for example by using gnulib's
|
||||
* stdint.h or inttypes.h), feel free to define LZMA_MANUAL_HEADERS before
|
||||
* including lzma.h.
|
||||
*
|
||||
* Some could argue that liblzma API should provide all the required types,
|
||||
* for example lzma_uint64, LZMA_UINT64_C(n), and LZMA_UINT64_MAX. This was
|
||||
* seen unnecessary mess, since most systems already provide all the necessary
|
||||
* types and macros in the standard headers.
|
||||
*
|
||||
* Note that liblzma API still has lzma_bool, because using stdbool.h would
|
||||
* break C89 and C++ programs on many systems.
|
||||
*/
|
||||
|
||||
/* NULL */
|
||||
/* stddef.h even in C++ so that we get size_t in global namespace. */
|
||||
#include <stddef.h>
|
||||
|
||||
/* uint8_t, uint32_t, uint64_t, UINT32_C, UINT64_C, UINT64_MAX. */
|
||||
#include <inttypes.h>
|
||||
#if !defined(UINT32_C) || !defined(UINT64_C) \
|
||||
|| !defined(UINT32_MAX) || !defined(UINT64_MAX)
|
||||
# ifdef __cplusplus
|
||||
/*
|
||||
* C99 sections 7.18.2 and 7.18.4 specify that in C++
|
||||
* implementations define the limit and constant macros only
|
||||
* if specifically requested. Note that if you want the
|
||||
* format macros too, you need to define __STDC_FORMAT_MACROS
|
||||
* before including lzma.h, since re-including inttypes.h
|
||||
* with __STDC_FORMAT_MACROS defined doesn't necessarily work.
|
||||
*/
|
||||
# ifndef __STDC_LIMIT_MACROS
|
||||
# define __STDC_LIMIT_MACROS 1
|
||||
# endif
|
||||
# ifndef __STDC_CONSTANT_MACROS
|
||||
# define __STDC_CONSTANT_MACROS 1
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# include <inttypes.h>
|
||||
|
||||
/*
|
||||
* Some old systems have only the typedefs in inttypes.h, and lack
|
||||
* all the macros. For those systems, we need a few more hacks.
|
||||
* We assume that unsigned int is 32-bit and unsigned long is either
|
||||
* 32-bit or 64-bit. If these hacks aren't enough, the application
|
||||
* has to use setup the types manually before including lzma.h.
|
||||
*/
|
||||
# ifndef UINT32_C
|
||||
# define UINT32_C(n) n # U
|
||||
# endif
|
||||
|
||||
# ifndef UINT64_C
|
||||
/* Get ULONG_MAX. */
|
||||
# ifndef __cplusplus
|
||||
# include <limits.h>
|
||||
# else
|
||||
# include <climits>
|
||||
# endif
|
||||
# if ULONG_MAX == 4294967295UL
|
||||
# define UINT64_C(n) n ## ULL
|
||||
# else
|
||||
# define UINT64_C(n) n ## UL
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef UINT32_MAX
|
||||
# define UINT32_MAX (UINT32_C(4294967295))
|
||||
# endif
|
||||
|
||||
# ifndef UINT64_MAX
|
||||
# define UINT64_MAX (UINT64_C(18446744073709551615))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/******************
|
||||
@@ -45,20 +124,50 @@
|
||||
* break anything if these are sometimes enabled and sometimes not, only
|
||||
* affects warnings and optimizations.
|
||||
*/
|
||||
#if defined(__GNUC__) && __GNUC__ >= 3
|
||||
#if __GNUC__ >= 3
|
||||
# ifndef lzma_attribute
|
||||
# define lzma_attribute(attr) __attribute__(attr)
|
||||
# endif
|
||||
|
||||
# ifndef lzma_restrict
|
||||
# define lzma_restrict __restrict__
|
||||
# endif
|
||||
|
||||
/* warn_unused_result was added in GCC 3.4. */
|
||||
# ifndef lzma_attr_warn_unused_result
|
||||
# if __GNUC__ == 3 && __GNUC_MINOR__ < 4
|
||||
# define lzma_attr_warn_unused_result
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#else
|
||||
# ifndef lzma_attribute
|
||||
# define lzma_attribute(attr)
|
||||
# endif
|
||||
|
||||
# ifndef lzma_restrict
|
||||
# define lzma_restrict
|
||||
# if __STDC_VERSION__ >= 199901L
|
||||
# define lzma_restrict restrict
|
||||
# else
|
||||
# define lzma_restrict
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# define lzma_attr_warn_unused_result
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef lzma_attr_pure
|
||||
# define lzma_attr_pure lzma_attribute((__pure__))
|
||||
#endif
|
||||
|
||||
#ifndef lzma_attr_const
|
||||
# define lzma_attr_const lzma_attribute((__const__))
|
||||
#endif
|
||||
|
||||
#ifndef lzma_attr_warn_unused_result
|
||||
# define lzma_attr_warn_unused_result \
|
||||
lzma_attribute((__warn_unused_result__))
|
||||
#endif
|
||||
|
||||
|
||||
@@ -77,38 +186,30 @@ extern "C" {
|
||||
#define LZMA_H_INTERNAL 1
|
||||
|
||||
/* Basic features */
|
||||
#include "lzma/version.h"
|
||||
#include "lzma/init.h"
|
||||
#include "lzma/base.h"
|
||||
#include "lzma/vli.h"
|
||||
#include "lzma/filter.h"
|
||||
#include "lzma/check.h"
|
||||
|
||||
/* Filters */
|
||||
#include "lzma/copy.h"
|
||||
#include "lzma/filter.h"
|
||||
#include "lzma/subblock.h"
|
||||
#include "lzma/simple.h"
|
||||
#include "lzma/delta.h"
|
||||
#include "lzma/lzma.h"
|
||||
|
||||
/* Container formats and Metadata */
|
||||
#include "lzma/block.h"
|
||||
#include "lzma/index.h"
|
||||
#include "lzma/extra.h"
|
||||
#include "lzma/metadata.h"
|
||||
#include "lzma/stream.h"
|
||||
#include "lzma/alone.h"
|
||||
#include "lzma/raw.h"
|
||||
#include "lzma/auto.h"
|
||||
/* Container formats */
|
||||
#include "lzma/container.h"
|
||||
|
||||
/* Advanced features */
|
||||
#include "lzma/info.h"
|
||||
#include "lzma/alignment.h"
|
||||
#include "lzma/alignment.h" /* FIXME */
|
||||
#include "lzma/block.h"
|
||||
#include "lzma/index.h"
|
||||
#include "lzma/index_hash.h"
|
||||
#include "lzma/stream_flags.h"
|
||||
#include "lzma/memlimit.h"
|
||||
|
||||
/* Version number */
|
||||
#include "lzma/version.h"
|
||||
|
||||
/*
|
||||
* All subheaders included. Undefine LZMA_H_INTERNAL to prevent applications
|
||||
* re-including the subheaders.
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
* FIXME desc
|
||||
*/
|
||||
extern uint32_t lzma_alignment_input(
|
||||
const lzma_options_filter *filters, uint32_t guess);
|
||||
const lzma_filter *filters, uint32_t guess);
|
||||
|
||||
|
||||
/**
|
||||
@@ -36,7 +36,7 @@ extern uint32_t lzma_alignment_input(
|
||||
* Knowing the alignment of the output data is useful e.g. in the Block
|
||||
* encoder which tries to align the Compressed Data field optimally.
|
||||
*
|
||||
* \param filters Pointer to lzma_options_filter array, whose last
|
||||
* \param filters Pointer to lzma_filter array, whose last
|
||||
* member must have .id = LZMA_VLI_VALUE_UNKNOWN.
|
||||
* \param guess The value to return if the alignment of the output
|
||||
* is the same as the alignment of the input data.
|
||||
@@ -57,4 +57,4 @@ extern uint32_t lzma_alignment_input(
|
||||
* options), UINT32_MAX is returned.
|
||||
*/
|
||||
extern uint32_t lzma_alignment_output(
|
||||
const lzma_options_filter *filters, uint32_t guess);
|
||||
const lzma_filter *filters, uint32_t guess);
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/**
|
||||
* \file lzma/alone.h
|
||||
* \brief Handling of the legacy LZMA_Alone format
|
||||
*
|
||||
* \author Copyright (C) 1999-2006 Igor Pavlov
|
||||
* \author Copyright (C) 2007 Lasse Collin
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 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
|
||||
* Lesser General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef LZMA_H_INTERNAL
|
||||
# error Never include this file directly. Use <lzma.h> instead.
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* \brief Options for files in the LZMA_Alone format
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Uncompressed Size and usage of End of Payload Marker
|
||||
*
|
||||
* In contrast to .lzma Blocks, LZMA_Alone format cannot have both
|
||||
* uncompressed size field in the header and end of payload marker.
|
||||
* If you don't know the uncompressed size beforehand, set it to
|
||||
* LZMA_VLI_VALUE_UNKNOWN and liblzma will embed end of payload
|
||||
* marker.
|
||||
*/
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
/**
|
||||
* \brief LZMA options
|
||||
*
|
||||
* The LZMA_Alone format supports only one filter: the LZMA filter.
|
||||
*
|
||||
* \note There exists also an undocumented variant of the
|
||||
* LZMA_Alone format, which uses the x86 filter in
|
||||
* addition to LZMA. This format was never supported
|
||||
* by LZMA Utils and is not supported by liblzma either.
|
||||
*/
|
||||
lzma_options_lzma lzma;
|
||||
|
||||
} lzma_options_alone;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initializes LZMA_Alone encoder
|
||||
*
|
||||
* LZMA_Alone files have the suffix .lzma like the .lzma Stream files.
|
||||
* LZMA_Alone format supports only one filter, the LZMA filter. There is
|
||||
* no support for integrity checks like CRC32.
|
||||
*
|
||||
* Use this format if and only if you need to create files readable by
|
||||
* legacy LZMA tools.
|
||||
*
|
||||
* LZMA_Alone encoder doesn't support LZMA_SYNC_FLUSH or LZMA_FULL_FLUSH.
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern lzma_ret lzma_alone_encoder(
|
||||
lzma_stream *strm, const lzma_options_alone *options);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initializes decoder for LZMA_Alone file
|
||||
*
|
||||
* The LZMA_Alone decoder supports LZMA_SYNC_FLUSH.
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_MEM_ERROR
|
||||
*/
|
||||
extern lzma_ret lzma_alone_decoder(lzma_stream *strm);
|
||||
@@ -1,41 +0,0 @@
|
||||
/**
|
||||
* \file lzma/auto.h
|
||||
* \brief Decoder with automatic file format detection
|
||||
*
|
||||
* \author Copyright (C) 1999-2006 Igor Pavlov
|
||||
* \author Copyright (C) 2007 Lasse Collin
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 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
|
||||
* Lesser General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef LZMA_H_INTERNAL
|
||||
# error Never include this file directly. Use <lzma.h> instead.
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* \brief Decode .lzma Streams and LZMA_Alone files with autodetection
|
||||
*
|
||||
* Autodetects between the .lzma Stream and LZMA_Alone formats, and
|
||||
* calls lzma_stream_decoder_init() or lzma_alone_decoder_init() once
|
||||
* the type of the file has been detected.
|
||||
*
|
||||
* \param strm Pointer to propertily prepared lzma_stream
|
||||
* \param header Pointer to hold a pointer to Extra Records read
|
||||
* from the Header Metadata Block. Use NULL if
|
||||
* you don't care about Extra Records.
|
||||
* \param footer Same as header, but for Footer Metadata Block.
|
||||
*
|
||||
* \return - LZMA_OK: Initialization was successful.
|
||||
* - LZMA_MEM_ERROR: Cannot allocate memory.
|
||||
*/
|
||||
extern lzma_ret lzma_auto_decoder(lzma_stream *strm,
|
||||
lzma_extra **header, lzma_extra **footer);
|
||||
@@ -33,28 +33,193 @@
|
||||
typedef unsigned char lzma_bool;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Type of reserved enumeration variable in structures
|
||||
*
|
||||
* To avoid breaking library ABI when new features are added, several
|
||||
* structures contain extra variables that may be used in future. Since
|
||||
* sizeof(enum) can be different than sizeof(int), and sizeof(enum) may
|
||||
* even vary depending on the range of enumeration constants, we specify
|
||||
* a separate type to be used for reserved enumeration variables. All
|
||||
* enumeration constants in liblzma API will be non-negative and less
|
||||
* than 128, which should guarantee that the ABI won't break even when
|
||||
* new constants are added to existing enumerations.
|
||||
*/
|
||||
typedef enum {
|
||||
LZMA_RESERVED_ENUM = 0
|
||||
} lzma_reserved_enum;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Return values used by several functions in liblzma
|
||||
*
|
||||
* Check the descriptions of specific functions to find out which return
|
||||
* values they can return and the exact meanings of the values in every
|
||||
* situation. The descriptions given here are only suggestive.
|
||||
* values they can return. With some functions the return values may have
|
||||
* more specific meanings than described here; those differences are
|
||||
* described per-function basis.
|
||||
*/
|
||||
typedef enum {
|
||||
LZMA_OK = 0,
|
||||
LZMA_OK = 0,
|
||||
/**<
|
||||
* \brief Operation completed successfully
|
||||
*/
|
||||
|
||||
LZMA_STREAM_END = 1,
|
||||
LZMA_STREAM_END = 1,
|
||||
/**<
|
||||
* \brief End of stream was reached
|
||||
*
|
||||
* The application should pick the last remaining output
|
||||
* bytes from strm->next_out.
|
||||
* In encoder, LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, or
|
||||
* LZMA_FINISH was finished. In decoder, this indicates
|
||||
* that all the data was successfully decoded.
|
||||
*
|
||||
* In all cases, when LZMA_STREAM_END is returned, the last
|
||||
* output bytes should be picked from strm->next_out.
|
||||
*/
|
||||
|
||||
LZMA_PROG_ERROR = -2,
|
||||
LZMA_NO_CHECK = 2,
|
||||
/**<
|
||||
* \brief Input stream has no integrity check
|
||||
*
|
||||
* This return value can be returned only if the
|
||||
* LZMA_TELL_NO_CHECK flag was used when initializing
|
||||
* the decoder. LZMA_NO_CHECK is just a warning, and
|
||||
* the decoding can be continued normally.
|
||||
*
|
||||
* It is possible to call lzma_get_check() immediatelly after
|
||||
* lzma_code has returned LZMA_NO_CHECK. The result will
|
||||
* naturally be LZMA_CHECK_NONE, but the possibility to call
|
||||
* lzma_get_check() may be convenient in some applications.
|
||||
*/
|
||||
|
||||
LZMA_UNSUPPORTED_CHECK = 3,
|
||||
/**<
|
||||
* \brief Cannot calculate the integrity check
|
||||
*
|
||||
* The usage of this return value is slightly different in
|
||||
* encoders and decoders.
|
||||
*
|
||||
* Encoders can return this value only from the initialization
|
||||
* function. If initialization fails with this value, the
|
||||
* encoding cannot be done, because there's no way to produce
|
||||
* output with the correct integrity check.
|
||||
*
|
||||
* Decoders can return this value only from the lzma_code
|
||||
* function and only if the LZMA_TELL_UNSUPPORTED_CHECK flag
|
||||
* was used when initializing the decoder. The decoding can
|
||||
* still be continued normally even if the check type is
|
||||
* unsupported, but naturally the check will not be validated,
|
||||
* and possible errors may go undetected.
|
||||
*
|
||||
* With decoder, it is possible to call lzma_get_check()
|
||||
* immediatelly after lzma_code has returned
|
||||
* LZMA_UNSUPPORTED_CHECK. This way it is possible to find
|
||||
* out what the unsupported Check ID was.
|
||||
*/
|
||||
|
||||
LZMA_GET_CHECK = 4,
|
||||
/**<
|
||||
* \brief Integrity check type is now available
|
||||
*
|
||||
* This value can be returned only by the lzma_code() function
|
||||
* and only if the decoder was initialized with the
|
||||
* LZMA_TELL_ANY_CHECK flag. LZMA_GET_CHECK tells the
|
||||
* application that it may now call lzma_get_check() to find
|
||||
* out the Check ID. This can be used, for example, to
|
||||
* implement a decoder that accepts only files that have
|
||||
* strong enough integrity check.
|
||||
*/
|
||||
|
||||
LZMA_MEM_ERROR = 5,
|
||||
/**<
|
||||
* \brief Cannot allocate memory
|
||||
*
|
||||
* Memory allocation failed, or the size of the allocation
|
||||
* would be greater than SIZE_MAX.
|
||||
*
|
||||
* Due to lazy coding, the coding cannot be continued even
|
||||
* if more memory were made available after LZMA_MEM_ERROR.
|
||||
*/
|
||||
|
||||
LZMA_MEMLIMIT_ERROR = 6,
|
||||
/**
|
||||
* \brief Memory usage limit was reached
|
||||
*
|
||||
* Decoder would need more memory than allowed by the
|
||||
* specified memory usage limit. To continue decoding,
|
||||
* the memory usage limit has to be increased. See functions
|
||||
* lzma_memlimit_get() and lzma_memlimit_set().
|
||||
*/
|
||||
|
||||
LZMA_FORMAT_ERROR = 7,
|
||||
/**<
|
||||
* \brief Unknown file format
|
||||
*
|
||||
* The decoder did not recognize the input as supported file
|
||||
* format. This error can occur, for example, when trying to
|
||||
* decode LZMA_Alone format file with lzma_stream_decoder,
|
||||
* because lzma_stream_decoder accepts only the new .lzma
|
||||
* format.
|
||||
*/
|
||||
|
||||
LZMA_HEADER_ERROR = 8,
|
||||
/**<
|
||||
* \brief Invalid or unsupported options
|
||||
*
|
||||
* Invalid or unsupported options, for example
|
||||
* - unsupported filter(s) or filter options; or
|
||||
* - reserved bits set in headers (decoder only).
|
||||
*
|
||||
* Rebuilding liblzma with more features enabled, or
|
||||
* upgrading to a newer version of liblzma may help.
|
||||
*/
|
||||
|
||||
LZMA_DATA_ERROR = 9,
|
||||
/**<
|
||||
* \brief Data is corrupt
|
||||
*
|
||||
* The usage of this return value is different in encoders
|
||||
* and decoders. In both encoder and decoder, the coding
|
||||
* cannot continue after this error.
|
||||
*
|
||||
* Encoders return this if size limits of the target file
|
||||
* format would be exceeded. These limits are huge, thus
|
||||
* getting this error from an encoder is mostly theoretical.
|
||||
* For example, the maximum compressed and uncompressed
|
||||
* size of a Stream created with lzma_stream_encoder is
|
||||
* 2^63 - 1 bytes (one byte less than 8 EiB).
|
||||
*
|
||||
* Decoders return this error if the input data is corrupt.
|
||||
* This can mean, for example, invalid CRC32 in headers
|
||||
* or invalid check of uncompressed data.
|
||||
*/
|
||||
|
||||
LZMA_BUF_ERROR = 10,
|
||||
/**<
|
||||
* \brief No progress is possible
|
||||
*
|
||||
* This error code is returned when the coder cannot consume
|
||||
* any new input and produce any new output. The most common
|
||||
* reason for this error is that the input stream being
|
||||
* decoded is truncated or corrupt.
|
||||
*
|
||||
* This error is not fatal. Coding can be continued normally
|
||||
* by providing more input and/or more output space, if
|
||||
* possible.
|
||||
*
|
||||
* Typically the first call to lzma_code() that can do no
|
||||
* progress returns LZMA_OK instead of LZMA_BUF_ERROR. Only
|
||||
* the second consecutive call doing no progress will return
|
||||
* LZMA_BUF_ERROR. This is by design.
|
||||
*
|
||||
* With zlib, Z_BUF_ERROR may be returned even if the
|
||||
* application is doing nothing wrong. The above hack
|
||||
* guarantees that liblzma never returns LZMA_BUF_ERROR
|
||||
* to properly written applications unless the input file
|
||||
* is truncated or corrupt. This should simplify the
|
||||
* applications a little.
|
||||
*/
|
||||
|
||||
LZMA_PROG_ERROR = 11,
|
||||
/**<
|
||||
* \brief Programming error
|
||||
*
|
||||
@@ -73,70 +238,24 @@ typedef enum {
|
||||
* can be a sign of a bug in liblzma. See the documentation
|
||||
* how to report bugs.
|
||||
*/
|
||||
|
||||
LZMA_DATA_ERROR = -3,
|
||||
/**<
|
||||
* \brief Data is corrupt
|
||||
*
|
||||
* - Encoder: The input size doesn't match the uncompressed
|
||||
* size given to lzma_*_encoder_init().
|
||||
* - Decoder: The input is corrupt. This includes corrupted
|
||||
* header, corrupted compressed data, and unmatching
|
||||
* integrity Check.
|
||||
*
|
||||
* \todo What can be done if encoder returns this?
|
||||
* Probably can continue by fixing the input
|
||||
* amount, but make sure.
|
||||
*/
|
||||
|
||||
LZMA_MEM_ERROR = -4,
|
||||
/**<
|
||||
* \brief Cannot allocate memory
|
||||
*
|
||||
* Memory allocation failed.
|
||||
*/
|
||||
|
||||
LZMA_BUF_ERROR = -5,
|
||||
/**<
|
||||
* \brief No progress is possible
|
||||
*
|
||||
* This may happen when avail_in or avail_out is zero.
|
||||
*
|
||||
* \note This error is not fatal. Coding can continue
|
||||
* normally once the reason for this error has
|
||||
* been fixed.
|
||||
*/
|
||||
|
||||
LZMA_HEADER_ERROR = -6,
|
||||
/**<
|
||||
* \brief Invalid or unsupported header
|
||||
*
|
||||
* Invalid or unsupported options, for example
|
||||
* - unsupported filter(s) or filter options; or
|
||||
* - reserved bits set in headers (decoder only).
|
||||
*
|
||||
* Rebuilding liblzma with more features enabled, or
|
||||
* upgrading to a newer version of liblzma may help.
|
||||
*/
|
||||
|
||||
LZMA_UNSUPPORTED_CHECK = -7,
|
||||
/**<
|
||||
* \brief Check type is unknown
|
||||
*
|
||||
* The type of Check is not supported, and thus the Check
|
||||
* cannot be calculated. In the encoder, this is an error.
|
||||
* In the decoder, this is only a warning and decoding can
|
||||
* still proceed normally (but the Check is ignored).
|
||||
*/
|
||||
} lzma_ret;
|
||||
|
||||
|
||||
/**
|
||||
* \brief The `action' argument for lzma_code()
|
||||
*
|
||||
* After the first use of LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, or LZMA_FINISH,
|
||||
* the same `action' must is used until lzma_code() returns LZMA_STREAM_END.
|
||||
* Also, the amount of input (that is, strm->avail_in) must not be modified
|
||||
* by the application until lzma_code() returns LZMA_STREAM_END. Changing the
|
||||
* `action' or modifying the amount of input will make lzma_code() return
|
||||
* LZMA_PROG_ERROR.
|
||||
*/
|
||||
typedef enum {
|
||||
LZMA_RUN = 0,
|
||||
/**<
|
||||
* \brief Continue coding
|
||||
*
|
||||
* Encoder: Encode as much input as possible. Some internal
|
||||
* buffering will probably be done (depends on the filter
|
||||
* chain in use), which causes latency: the input used won't
|
||||
@@ -152,27 +271,37 @@ typedef enum {
|
||||
|
||||
LZMA_SYNC_FLUSH = 1,
|
||||
/**<
|
||||
* Encoder: Makes all the data given to liblzma via next_in
|
||||
* available in next_out without resetting the filters. Call
|
||||
* lzma_code() with LZMA_SYNC_FLUSH until it returns
|
||||
* LZMA_STREAM_END. Then continue encoding normally.
|
||||
* \brief Make all the input available at output
|
||||
*
|
||||
* \note Synchronous flushing is supported only by
|
||||
* some filters. Some filters support it only
|
||||
* partially.
|
||||
* Normally the encoder introduces some latency.
|
||||
* LZMA_SYNC_FLUSH forces all the buffered data to be
|
||||
* available at output without resetting the internal
|
||||
* state of the encoder. This way it is possible to use
|
||||
* compressed stream for example for communication over
|
||||
* network.
|
||||
*
|
||||
* Decoder: Asks the decoder to decode only as much as is
|
||||
* needed to fill next_out. This decreases latency with some
|
||||
* filters, but is likely to decrease also throughput. It is
|
||||
* a good idea to use this flag only when it is likely that
|
||||
* you don't need more output soon.
|
||||
* Only some filters support LZMA_SYNC_FLUSH. Trying to use
|
||||
* LZMA_SYNC_FLUSH with filters that don't support it will
|
||||
* make lzma_code() return LZMA_HEADER_ERROR. For example,
|
||||
* LZMA1 doesn't support LZMA_SYNC_FLUSH but LZMA2 does.
|
||||
*
|
||||
* \note With decoder, this is not comparable to
|
||||
* zlib's Z_SYNC_FLUSH.
|
||||
* Using LZMA_SYNC_FLUSH very often can dramatically reduce
|
||||
* the compression ratio. With some filters (for example,
|
||||
* LZMA2), finetuning the compression options may help
|
||||
* mitigate this problem significantly.
|
||||
*
|
||||
* Decoders don't support LZMA_SYNC_FLUSH.
|
||||
*/
|
||||
|
||||
LZMA_FULL_FLUSH = 2,
|
||||
/**<
|
||||
* \brief Make all the input available at output
|
||||
*
|
||||
* This is like LZMA_SYNC_FLUSH except that this resets the
|
||||
* internal encoder state.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Finishes encoding of the current Data Block. All the input
|
||||
* data going to the current Data Block must have been given
|
||||
* to the encoder (the last bytes can still be pending in
|
||||
@@ -180,19 +309,30 @@ typedef enum {
|
||||
* it returns LZMA_STREAM_END. Then continue normally with
|
||||
* LZMA_RUN or finish the Stream with LZMA_FINISH.
|
||||
*
|
||||
* This action is supported only by Multi-Block Stream
|
||||
* encoder. If there is no unfinished Data Block, no empty
|
||||
* Data Block is created.
|
||||
* This action is supported only by Stream encoder and easy
|
||||
* encoder (which uses Stream encoder). If there is no
|
||||
* unfinished Block, no empty Block is created.
|
||||
*/
|
||||
|
||||
LZMA_FINISH = 3
|
||||
/**<
|
||||
* Finishes the encoding operation. All the input data must
|
||||
* \brief Finish the coding operation
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Finishes the coding operation. All the input data must
|
||||
* have been given to the encoder (the last bytes can still
|
||||
* be pending in next_in). Call lzma_code() with LZMA_FINISH
|
||||
* until it returns LZMA_STREAM_END.
|
||||
* until it returns LZMA_STREAM_END. Once LZMA_FINISH has
|
||||
* been used, the amount of input must no longer be changed
|
||||
* by the application.
|
||||
*
|
||||
* This action is not supported by decoders.
|
||||
* When decoding, using LZMA_FINISH is optional unless the
|
||||
* LZMA_CONCATENATED flag was used when the decoder was
|
||||
* initialized. When LZMA_CONCATENATED was not used, the only
|
||||
* effect of LZMA_FINISH is that the amount of input must not
|
||||
* be changed just like in the encoder.
|
||||
*/
|
||||
} lzma_action;
|
||||
|
||||
@@ -201,8 +341,10 @@ typedef enum {
|
||||
* \brief Custom functions for memory handling
|
||||
*
|
||||
* A pointer to lzma_allocator may be passed via lzma_stream structure
|
||||
* to liblzma. The library will use these functions for memory handling
|
||||
* instead of the default malloc() and free().
|
||||
* to liblzma, and some advanced function take pointer lzma_allocator as
|
||||
* a separate function argument. The library will use the functions
|
||||
* specified in lzma_allocator for memory handling instead of the default
|
||||
* malloc() and free().
|
||||
*
|
||||
* liblzma doesn't make an internal copy of lzma_allocator. Thus, it is
|
||||
* OK to change these function pointers in the middle of the coding
|
||||
@@ -214,11 +356,6 @@ typedef struct {
|
||||
/**
|
||||
* \brief Pointer to custom memory allocation function
|
||||
*
|
||||
* Set this to point to your custom memory allocation function.
|
||||
* It can be useful for example if you want to limit how much
|
||||
* memory liblzma is allowed to use: for this, you may use
|
||||
* a pointer to lzma_memory_alloc().
|
||||
*
|
||||
* If you don't want a custom allocator, but still want
|
||||
* custom free(), set this to NULL and liblzma will use
|
||||
* the standard malloc().
|
||||
@@ -235,24 +372,32 @@ typedef struct {
|
||||
* size nmemb * size, or NULL if allocation fails
|
||||
* for some reason. When allocation fails, functions
|
||||
* of liblzma return LZMA_MEM_ERROR.
|
||||
*
|
||||
* For performance reasons, the allocator should not waste time
|
||||
* zeroing the allocated buffers. This is not only about speed, but
|
||||
* also memory usage, since the operating system kernel doesn't
|
||||
* necessarily allocate the requested memory until it is actually
|
||||
* used. With small input files liblzma may actually need only a
|
||||
* fraction of the memory that it requested for allocation.
|
||||
*
|
||||
* \note LZMA_MEM_ERROR is also used when the size of the
|
||||
* allocation would be greater than SIZE_MAX. Thus,
|
||||
* don't assume that the custom allocator must have
|
||||
* returned NULL if some function from liblzma
|
||||
* returns LZMA_MEM_ERROR.
|
||||
*/
|
||||
void *(*alloc)(void *opaque, size_t nmemb, size_t size);
|
||||
|
||||
/**
|
||||
* \brief Pointer to custom memory freeing function
|
||||
*
|
||||
* Set this to point to your custom memory freeing function.
|
||||
* If lzma_memory_alloc() is used as allocator, this should
|
||||
* be set to lzma_memory_free().
|
||||
*
|
||||
* If you don't want a custom freeing function, but still
|
||||
* want a custom allocator, set this to NULL and liblzma
|
||||
* will use the standard free().
|
||||
*
|
||||
* \param opaque lzma_allocator.opaque (see below)
|
||||
* \param ptr Pointer returned by
|
||||
* lzma_allocator.alloc(), or when it
|
||||
* is set to NULL, a pointer returned
|
||||
* \param ptr Pointer returned by lzma_allocator.alloc(),
|
||||
* or when it is set to NULL, a pointer returned
|
||||
* by the standard malloc().
|
||||
*/
|
||||
void (*free)(void *opaque, void *ptr);
|
||||
@@ -264,11 +409,7 @@ typedef struct {
|
||||
* and lzma_allocator.free(). This intended to ease implementing
|
||||
* custom memory allocation functions for use with liblzma.
|
||||
*
|
||||
* When using lzma_memory_alloc() and lzma_memory_free(), opaque
|
||||
* must point to lzma_memory_limitter structure allocated and
|
||||
* initialized with lzma_memory_limitter_create().
|
||||
*
|
||||
* If you don't need this, you should set it to NULL.
|
||||
* If you don't need this, you should set this to NULL.
|
||||
*/
|
||||
void *opaque;
|
||||
|
||||
@@ -291,31 +432,33 @@ typedef struct lzma_internal_s lzma_internal;
|
||||
* - defining custom memory hander functions; and
|
||||
* - holding a pointer to coder-specific internal data structures.
|
||||
*
|
||||
* Before calling any of the lzma_*_init() functions the first time,
|
||||
* the application must reset lzma_stream to LZMA_STREAM_INIT. The
|
||||
* lzma_*_init() function will verify the options, allocate internal
|
||||
* data structures and store pointer to them into `internal'. Finally
|
||||
* total_in and total_out are reset to zero. In contrast to zlib,
|
||||
* next_in and avail_in are ignored by the initialization functions.
|
||||
* The typical usage
|
||||
*
|
||||
* The actual coding is done with the lzma_code() function. Application
|
||||
* must update next_in, avail_in, next_out, and avail_out between
|
||||
* calls to lzma_decode() just like with zlib.
|
||||
* - After allocating lzma_stream (on stack or with malloc()), it must be
|
||||
* initialized to LZMA_STREAM_INIT (see LZMA_STREAM_INIT for details).
|
||||
*
|
||||
* In contrast to zlib, even the decoder requires that there always
|
||||
* is at least one byte space in next_out; if avail_out == 0,
|
||||
* LZMA_BUF_ERROR is returned immediatelly. This shouldn't be a problem
|
||||
* for most applications that already use zlib, but it's still worth
|
||||
* checking your application.
|
||||
* - Initialize a coder to the lzma_stream, for example by using
|
||||
* lzma_easy_encoder() or lzma_auto_decoder(). In contrast to zlib,
|
||||
* strm->next_in and strm->next_out are ignored by all initialization
|
||||
* functions, thus it is safe to not initialize them yet. The
|
||||
* initialization functions always set strm->total_in and strm->total_out
|
||||
* to zero.
|
||||
*
|
||||
* - Use lzma_code() to do the actual work.
|
||||
*
|
||||
* - Once the coding has been finished, the existing lzma_stream can be
|
||||
* reused. It is OK to reuse lzma_stream with different initialization
|
||||
* function without calling lzma_end() first. Old allocations are
|
||||
* automatically freed.
|
||||
*
|
||||
* - Finally, use lzma_end() to free the allocated memory.
|
||||
*
|
||||
* Application may modify values of total_in and total_out as it wants.
|
||||
* They are updated by liblzma to match the amount of data read and
|
||||
* written, but liblzma doesn't use the values internally.
|
||||
*
|
||||
* Application must not touch the `internal' pointer.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t *next_in; /**< Pointer to the next input byte. */
|
||||
const uint8_t *next_in; /**< Pointer to the next input byte. */
|
||||
size_t avail_in; /**< Number of available input bytes in next_in. */
|
||||
uint64_t total_in; /**< Total number of bytes read by liblzma. */
|
||||
|
||||
@@ -329,9 +472,22 @@ typedef struct {
|
||||
*/
|
||||
lzma_allocator *allocator;
|
||||
|
||||
/** Internal state is not visible to outsiders. */
|
||||
/** Internal state is not visible to applications. */
|
||||
lzma_internal *internal;
|
||||
|
||||
/**
|
||||
* Reserved space to allow possible future extensions without
|
||||
* breaking the ABI. Excluding the initialization of this structure,
|
||||
* you should not touch these, because the names of these variables
|
||||
* may change.
|
||||
*/
|
||||
void *reserved_ptr1;
|
||||
void *reserved_ptr2;
|
||||
uint64_t reserved_int1;
|
||||
uint64_t reserved_int2;
|
||||
lzma_reserved_enum reserved_enum1;
|
||||
lzma_reserved_enum reserved_enum2;
|
||||
|
||||
} lzma_stream;
|
||||
|
||||
|
||||
@@ -343,58 +499,35 @@ typedef struct {
|
||||
* has been allocated yet:
|
||||
*
|
||||
* lzma_stream strm = LZMA_STREAM_INIT;
|
||||
*/
|
||||
#define LZMA_STREAM_INIT { NULL, 0, 0, NULL, 0, 0, NULL, NULL }
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initialization for lzma_stream
|
||||
*
|
||||
* This is like LZMA_STREAM_INIT, but this can be used when the lzma_stream
|
||||
* has already been allocated:
|
||||
* If you need to initialize a dynamically allocated lzma_stream, you can use
|
||||
* memset(strm_pointer, 0, sizeof(lzma_stream)). Strictly speaking, this
|
||||
* violates the C standard since NULL may have different internal
|
||||
* representation than zero, but it should be portable enough in practice.
|
||||
* Anyway, for maximum portability, you can use something like this:
|
||||
*
|
||||
* lzma_stream *strm = malloc(sizeof(lzma_stream));
|
||||
* if (strm == NULL)
|
||||
* return LZMA_MEM_ERROR;
|
||||
* *strm = LZMA_STREAM_INIT_VAR;
|
||||
* lzma_stream tmp = LZMA_STREAM_INIT;
|
||||
* *strm = tmp;
|
||||
*/
|
||||
extern const lzma_stream LZMA_STREAM_INIT_VAR;
|
||||
#define LZMA_STREAM_INIT \
|
||||
{ NULL, 0, 0, NULL, 0, 0, NULL, NULL, NULL, NULL, 0, 0, 0, 0 }
|
||||
|
||||
|
||||
/**
|
||||
* \brief Encodes or decodes data
|
||||
*
|
||||
* Once the lzma_stream has been successfully initialized (e.g. with
|
||||
* lzma_stream_encoder_single()), the actual encoding or decoding is
|
||||
* done using this function.
|
||||
* lzma_stream_encoder()), the actual encoding or decoding is done
|
||||
* using this function. The application has to update strm->next_in,
|
||||
* strm->avail_in, strm->next_out, and strm->avail_out to pass input
|
||||
* to and get output from liblzma.
|
||||
*
|
||||
* \return Some coders may have more exact meaning for different return
|
||||
* values, which are mentioned separately in the description of
|
||||
* the initialization functions. Here are the typical meanings:
|
||||
* - LZMA_OK: So far all good.
|
||||
* - LZMA_STREAM_END:
|
||||
* - Encoder: LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, or
|
||||
* LZMA_FINISH completed.
|
||||
* - Decoder: End of uncompressed data was reached.
|
||||
* - LZMA_BUF_ERROR: Unable to progress. Provide more input or
|
||||
* output space, and call this function again. This cannot
|
||||
* occur if both avail_in and avail_out were non-zero (or
|
||||
* there's a bug in liblzma).
|
||||
* - LZMA_MEM_ERROR: Unable to allocate memory. Due to lazy
|
||||
* programming, the coding cannot continue even if the
|
||||
* application could free more memory. The next call must
|
||||
* be lzma_end() or some initialization function.
|
||||
* - LZMA_DATA_ERROR:
|
||||
* - Encoder: Filter(s) cannot process the given data.
|
||||
* - Decoder: Compressed data is corrupt.
|
||||
* - LZMA_HEADER_ERROR: Unsupported options. Rebuilding liblzma
|
||||
* with more features enabled or upgrading to a newer version
|
||||
* may help, although usually this is a sign of invalid options
|
||||
* (encoder) or corrupted input data (decoder).
|
||||
* - LZMA_PROG_ERROR: Invalid arguments or the internal state
|
||||
* of the coder is corrupt.
|
||||
* See the description of the coder-specific initialization function to find
|
||||
* out what `action' values are supported by the coder. See documentation of
|
||||
* lzma_ret for the possible return values.
|
||||
*/
|
||||
extern lzma_ret lzma_code(lzma_stream *strm, lzma_action action);
|
||||
extern lzma_ret lzma_code(lzma_stream *strm, lzma_action action)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,6 +32,21 @@
|
||||
* later calls to lzma_code().
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Size of the Block Header
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_header_encode()
|
||||
* - lzma_block_header_decode()
|
||||
* - lzma_block_decoder()
|
||||
*
|
||||
* Written by:
|
||||
* - lzma_block_header_size()
|
||||
*/
|
||||
uint32_t header_size;
|
||||
# define LZMA_BLOCK_HEADER_SIZE_MIN 8
|
||||
# define LZMA_BLOCK_HEADER_SIZE_MAX 1024
|
||||
|
||||
/**
|
||||
* \brief Type of integrity Check
|
||||
*
|
||||
@@ -39,89 +54,12 @@ typedef struct {
|
||||
* Header, thus its value must be provided also when decoding.
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_header_encode()
|
||||
* - lzma_block_header_decode()
|
||||
* - lzma_block_encoder()
|
||||
* - lzma_block_decoder()
|
||||
*/
|
||||
lzma_check_type check;
|
||||
|
||||
/**
|
||||
* \brief Precense of CRC32 of the Block Header
|
||||
*
|
||||
* Set this to true if CRC32 of the Block Header should be
|
||||
* calculated and stored in the Block Header.
|
||||
*
|
||||
* There is no way to autodetect if CRC32 is present in the Block
|
||||
* Header, thus this information must be provided also when decoding.
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_header_size()
|
||||
* - lzma_block_header_encoder()
|
||||
* - lzma_block_header_decoder()
|
||||
*/
|
||||
lzma_bool has_crc32;
|
||||
|
||||
/**
|
||||
* \brief Usage of End of Payload Marker
|
||||
*
|
||||
* If this is true, End of Payload Marker is used even if
|
||||
* Uncompressed Size is known.
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_header_encoder()
|
||||
* - lzma_block_encoder()
|
||||
* - lzma_block_decoder()
|
||||
*
|
||||
* Written by:
|
||||
* - lzma_block_header_decoder()
|
||||
*/
|
||||
lzma_bool has_eopm;
|
||||
|
||||
/**
|
||||
* \brief True if the Block is a Metadata Block
|
||||
*
|
||||
* If this is true, the Metadata bit will be set in the Block Header.
|
||||
* It is up to the application to store correctly formatted data
|
||||
* into Metadata Block.
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_header_encoder()
|
||||
*
|
||||
* Written by:
|
||||
* - lzma_block_header_decoder()
|
||||
*/
|
||||
lzma_bool is_metadata;
|
||||
|
||||
/**
|
||||
* \brief True if Uncompressed Size is in Block Footer
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_encoder()
|
||||
* - lzma_block_decoder()
|
||||
*/
|
||||
lzma_bool has_uncompressed_size_in_footer;
|
||||
|
||||
/**
|
||||
* \brief True if Backward Size is in Block Footer
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_encoder()
|
||||
* - lzma_block_decoder()
|
||||
*/
|
||||
lzma_bool has_backward_size;
|
||||
|
||||
/**
|
||||
* \brief True if Block coder should take care of Padding
|
||||
*
|
||||
* In liblzma, Stream decoder sets this to true when decoding
|
||||
* Header Metadata Block or Data Blocks from Multi-Block Stream,
|
||||
* and to false when decoding Single-Block Stream or Footer
|
||||
* Metadata Block from a Multi-Block Stream.
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_encoder()
|
||||
* - lzma_block_decoder()
|
||||
*/
|
||||
lzma_bool handle_padding;
|
||||
lzma_check check;
|
||||
|
||||
/**
|
||||
* \brief Size of the Compressed Data in bytes
|
||||
@@ -134,12 +72,11 @@ typedef struct {
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_header_size()
|
||||
* - lzma_block_header_encoder()
|
||||
* - lzma_block_encoder()
|
||||
* - lzma_block_header_encode()
|
||||
* - lzma_block_decoder()
|
||||
*
|
||||
* Written by:
|
||||
* - lzma_block_header_decoder()
|
||||
* - lzma_block_header_decode()
|
||||
* - lzma_block_encoder()
|
||||
* - lzma_block_decoder()
|
||||
*/
|
||||
@@ -163,167 +100,60 @@ typedef struct {
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_header_size()
|
||||
* - lzma_block_header_encoder()
|
||||
* - lzma_block_encoder()
|
||||
* - lzma_block_header_encode()
|
||||
* - lzma_block_decoder()
|
||||
*
|
||||
* Written by:
|
||||
* - lzma_block_header_decoder()
|
||||
* - lzma_block_header_decode()
|
||||
* - lzma_block_encoder()
|
||||
* - lzma_block_decoder()
|
||||
*/
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
/**
|
||||
* \brief Number of bytes to reserve for Compressed Size
|
||||
*
|
||||
* This is useful if you want to be able to store the Compressed Size
|
||||
* to the Block Header, but you don't know it when starting to encode.
|
||||
* Setting this to non-zero value at maximum of LZMA_VLI_BYTES_MAX,
|
||||
* the Block Header encoder will force the Compressed Size field to
|
||||
* occupy specified number of bytes. You can later rewrite the Block
|
||||
* Header to contain correct information by using otherwise identical
|
||||
* lzma_options_block structure except the correct compressed_size.
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_header_size()
|
||||
* - lzma_block_header_encoder()
|
||||
*
|
||||
* Written by:
|
||||
* - lzma_block_header_decoder()
|
||||
*/
|
||||
uint32_t compressed_reserve;
|
||||
|
||||
/**
|
||||
* \brief Number of bytes to reserve for Uncompressed Size
|
||||
*
|
||||
* See the description of compressed_size above.
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_header_size()
|
||||
* - lzma_block_header_encoder()
|
||||
*
|
||||
* Written by:
|
||||
* - lzma_block_header_decoder()
|
||||
*/
|
||||
uint32_t uncompressed_reserve;
|
||||
|
||||
/**
|
||||
* \brief Total Size of the Block in bytes
|
||||
*
|
||||
* This is useful in the decoder, which can verify the Total Size
|
||||
* if it is known from Index.
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_encoder()
|
||||
* - lzma_block_decoder()
|
||||
*
|
||||
* Written by:
|
||||
* - lzma_block_encoder()
|
||||
* - lzma_block_decoder()
|
||||
*/
|
||||
lzma_vli total_size;
|
||||
|
||||
/**
|
||||
* \brief Upper limit of Total Size
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_encoder()
|
||||
* - lzma_block_decoder()
|
||||
*/
|
||||
lzma_vli total_limit;
|
||||
|
||||
/**
|
||||
* \brief Upper limit of Uncompressed Size
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_encoder()
|
||||
* - lzma_block_decoder()
|
||||
*/
|
||||
lzma_vli uncompressed_limit;
|
||||
|
||||
/**
|
||||
* \brief Array of filters
|
||||
*
|
||||
* There can be at maximum of seven filters. The end of the array
|
||||
* is marked with .id = LZMA_VLI_VALUE_UNKNOWN. Minimum number of
|
||||
* filters is zero; in that case, an implicit Copy filter is used.
|
||||
* There can be 1-4 filters. The end of the array is marked with
|
||||
* .id = LZMA_VLI_VALUE_UNKNOWN.
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_header_size()
|
||||
* - lzma_block_header_encoder()
|
||||
* - lzma_block_header_encode()
|
||||
* - lzma_block_encoder()
|
||||
* - lzma_block_decoder()
|
||||
*
|
||||
* Written by:
|
||||
* - lzma_block_header_decoder(): Note that this does NOT free()
|
||||
* the old filter options structures. If decoding fails, the
|
||||
* caller must take care of freeing the options structures
|
||||
* that may have been allocated and decoded before the error
|
||||
* occurred.
|
||||
* - lzma_block_header_decode(): Note that this does NOT free()
|
||||
* the old filter options structures. All unused filters[] will
|
||||
* have .id == LZMA_VLI_VALUE_UNKNOWN and .options == NULL. If
|
||||
* decoding fails, all filters[] are guaranteed to be
|
||||
* LZMA_VLI_VALUE_UNKNOWN and NULL.
|
||||
*
|
||||
* \note Because of the array is terminated with
|
||||
* .id = LZMA_VLI_VALUE_UNKNOWN, the actual array must
|
||||
* have LZMA_BLOCK_FILTERS_MAX + 1 members or the Block
|
||||
* Header decoder will overflow the buffer.
|
||||
*/
|
||||
lzma_options_filter filters[8];
|
||||
lzma_filter *filters;
|
||||
# define LZMA_BLOCK_FILTERS_MAX 4
|
||||
|
||||
/**
|
||||
* \brief Size of the Padding field
|
||||
*
|
||||
* The Padding field exist to allow aligning the Compressed Data field
|
||||
* optimally in the Block. See lzma_options_stream.alignment in
|
||||
* stream.h for more information.
|
||||
*
|
||||
* If you want the Block Header encoder to automatically calculate
|
||||
* optimal size for the Padding field by looking at the information
|
||||
* in filters[], set this to LZMA_BLOCK_HEADER_PADDING_AUTO. In that
|
||||
* case, you must also set the aligmnet variable to tell the the
|
||||
* encoder the aligmnet of the beginning of the Block Header.
|
||||
*
|
||||
* The decoder never sets this to LZMA_BLOCK_HEADER_PADDING_AUTO.
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_header_size()
|
||||
* - lzma_block_header_encoder(): Note that this doesn't
|
||||
* accept LZMA_BLOCK_HEADER_PADDING_AUTO.
|
||||
*
|
||||
* Written by (these never set padding to
|
||||
* LZMA_BLOCK_HEADER_PADDING_AUTO):
|
||||
* - lzma_block_header_size()
|
||||
* - lzma_block_header_decoder()
|
||||
*/
|
||||
int32_t padding;
|
||||
# define LZMA_BLOCK_HEADER_PADDING_AUTO (-1)
|
||||
# define LZMA_BLOCK_HEADER_PADDING_MIN 0
|
||||
# define LZMA_BLOCK_HEADER_PADDING_MAX 31
|
||||
|
||||
/**
|
||||
* \brief Alignment of the beginning of the Block Header
|
||||
*
|
||||
* This variable is read only if padding has been set to
|
||||
* LZMA_BLOCK_HEADER_PADDING_AUTO.
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_header_size()
|
||||
* - lzma_block_header_encoder()
|
||||
*/
|
||||
uint32_t alignment;
|
||||
|
||||
/**
|
||||
* \brief Size of the Block Header
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_encoder()
|
||||
* - lzma_block_decoder()
|
||||
*
|
||||
* Written by:
|
||||
* - lzma_block_header_size()
|
||||
* - lzma_block_header_decoder()
|
||||
*/
|
||||
uint32_t header_size;
|
||||
|
||||
} lzma_options_block;
|
||||
} lzma_block;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculates the size of Header Padding and Block Header
|
||||
* \brief Decodes the Block Header Size field
|
||||
*
|
||||
* To decode Block Header using lzma_block_header_decode(), the size of the
|
||||
* Block Header has to be known and stored into lzma_block.header_size.
|
||||
* The size can be calculated from the first byte of a Block using this macro.
|
||||
* Note that if the first byte is 0x00, it indicates beginning of Index; use
|
||||
* this macro only when the byte is not 0x00.
|
||||
*/
|
||||
#define lzma_block_header_size_decode(b) (((uint32_t)(b) + 1) * 4)
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculates the size of Block Header
|
||||
*
|
||||
* \return - LZMA_OK: Size calculated successfully and stored to
|
||||
* options->header_size.
|
||||
@@ -334,7 +164,8 @@ typedef struct {
|
||||
* may return LZMA_OK even if lzma_block_header_encode() or
|
||||
* lzma_block_encoder() would fail.
|
||||
*/
|
||||
extern lzma_ret lzma_block_header_size(lzma_options_block *options);
|
||||
extern lzma_ret lzma_block_header_size(lzma_block *options)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
@@ -353,24 +184,66 @@ extern lzma_ret lzma_block_header_size(lzma_options_block *options);
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern lzma_ret lzma_block_header_encode(
|
||||
uint8_t *out, const lzma_options_block *options);
|
||||
const lzma_block *options, uint8_t *out)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initializes Block Header decoder
|
||||
* \brief Decodes Block Header
|
||||
*
|
||||
* Because the results of this decoder are placed into *options,
|
||||
* strm->next_in, strm->avail_in, and strm->total_in are not used.
|
||||
* Decoding of the Block options is done with a single call instead of
|
||||
* first initializing and then doing the actual work with lzma_code().
|
||||
*
|
||||
* The only valid `action' with lzma_code() is LZMA_RUN.
|
||||
* \param options Destination for block options
|
||||
* \param allocator lzma_allocator for custom allocator functions.
|
||||
* Set to NULL to use malloc().
|
||||
* \param in Beginning of the input buffer. This must be
|
||||
* at least options->header_size bytes.
|
||||
*
|
||||
* \return - LZMA_OK: Encoding was successful. options->header_size
|
||||
* \return - LZMA_OK: Decoding was successful. options->header_size
|
||||
* bytes were written to output buffer.
|
||||
* - LZMA_HEADER_ERROR: Invalid or unsupported options.
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern lzma_ret lzma_block_header_decoder(
|
||||
lzma_stream *strm, lzma_options_block *options);
|
||||
extern lzma_ret lzma_block_header_decode(lzma_block *options,
|
||||
lzma_allocator *allocator, const uint8_t *in)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Sets Compressed Size according to Total Size
|
||||
*
|
||||
* Block Header stores Compressed Size, but Index has Total Size. If the
|
||||
* application has already parsed the Index and is now decoding Blocks,
|
||||
* it can calculate Compressed Size from Total Size. This function does
|
||||
* exactly that with error checking, so application doesn't need to check,
|
||||
* for example, if the value in Index is too small to contain even the
|
||||
* Block Header. Note that you need to call this function after decoding
|
||||
* the Block Header field.
|
||||
*
|
||||
* \return - LZMA_OK: options->compressed_size was set successfully.
|
||||
* - LZMA_DATA_ERROR: total_size is too small compared to
|
||||
* options->header_size and lzma_check_sizes[options->check].
|
||||
* - LZMA_PROG_ERROR: Some values are invalid. For example,
|
||||
* total_size and options->header_size must be multiples
|
||||
* of four, total_size must be at least 12, and
|
||||
* options->header_size between 8 and 1024 inclusive.
|
||||
*/
|
||||
extern lzma_ret lzma_block_total_size_set(
|
||||
lzma_block *options, lzma_vli total_size)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculates Total Size
|
||||
*
|
||||
* This function can be useful after decoding a Block to get Total Size
|
||||
* that is stored in Index.
|
||||
*
|
||||
* \return Total Size on success, or zero on error.
|
||||
*/
|
||||
extern lzma_vli lzma_block_total_size_get(const lzma_block *options)
|
||||
lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
@@ -391,8 +264,8 @@ extern lzma_ret lzma_block_header_decoder(
|
||||
*
|
||||
* lzma_code() can return FIXME
|
||||
*/
|
||||
extern lzma_ret lzma_block_encoder(
|
||||
lzma_stream *strm, lzma_options_block *options);
|
||||
extern lzma_ret lzma_block_encoder(lzma_stream *strm, lzma_block *options)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
@@ -405,5 +278,5 @@ extern lzma_ret lzma_block_encoder(
|
||||
* - LZMA_PROG_ERROR
|
||||
* - LZMA_MEM_ERROR
|
||||
*/
|
||||
extern lzma_ret lzma_block_decoder(
|
||||
lzma_stream *strm, lzma_options_block *options);
|
||||
extern lzma_ret lzma_block_decoder(lzma_stream *strm, lzma_block *options)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
@@ -43,26 +43,26 @@ typedef enum {
|
||||
* Size of the Check field: 4 bytes
|
||||
*/
|
||||
|
||||
LZMA_CHECK_CRC64 = 3,
|
||||
LZMA_CHECK_CRC64 = 4,
|
||||
/**<
|
||||
* CRC64 using the polynomial from the ECMA-182 standard
|
||||
*
|
||||
* Size of the Check field: 8 bytes
|
||||
*/
|
||||
|
||||
LZMA_CHECK_SHA256 = 5
|
||||
LZMA_CHECK_SHA256 = 10
|
||||
/**<
|
||||
* SHA-256
|
||||
*
|
||||
* Size of the Check field: 32 bytes
|
||||
*/
|
||||
} lzma_check_type;
|
||||
} lzma_check;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Maximum valid Check ID
|
||||
*
|
||||
* The .lzma file format specification specifies eight Check IDs (0-7). Some
|
||||
* The .lzma file format specification specifies eight Check IDs (0-15). Some
|
||||
* of them are only reserved i.e. no actual Check algorithm has been assigned.
|
||||
* Still liblzma accepts any of these eight IDs for future compatibility
|
||||
* when decoding files. If a valid but unsupported Check ID is detected,
|
||||
@@ -70,29 +70,38 @@ typedef enum {
|
||||
*
|
||||
* FIXME bad desc
|
||||
*/
|
||||
#define LZMA_CHECK_ID_MAX 7
|
||||
#define LZMA_CHECK_ID_MAX 15
|
||||
|
||||
|
||||
/**
|
||||
* \brief Check IDs supported by this liblzma build
|
||||
*
|
||||
* If lzma_available_checks[n] is true, the Check ID n is supported by this
|
||||
* liblzma build. You can assume that LZMA_CHECK_NONE and LZMA_CHECK_CRC32
|
||||
* are always available.
|
||||
* \brief Maximum size of a Check field
|
||||
*/
|
||||
extern const lzma_bool lzma_available_checks[LZMA_CHECK_ID_MAX + 1];
|
||||
#define LZMA_CHECK_SIZE_MAX 64
|
||||
|
||||
|
||||
/**
|
||||
* \brief Size of the Check field with different Check IDs
|
||||
* \brief Test if the given Check ID is supported
|
||||
*
|
||||
* Returns true if the given Check ID is supported by this liblzma build.
|
||||
* Otherwise false is returned. It is safe to call this with a value that
|
||||
* is not in the range [0, 15]; in that case the return value is always false.
|
||||
*/
|
||||
extern lzma_bool lzma_check_is_supported(lzma_check check)
|
||||
lzma_attr_const;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the size of the Check field with given Check ID
|
||||
*
|
||||
* Although not all Check IDs have a check algorithm associated, the size of
|
||||
* every Check is already frozen. This array contains the size (in bytes) of
|
||||
* the Check field with specified Check ID. The values are taken from the
|
||||
* section 2.2.2 of the .lzma file format specification:
|
||||
* { 0, 4, 4, 8, 16, 32, 32, 64 }
|
||||
* every Check is already frozen. This function returns the size (in bytes) of
|
||||
* the Check field with the specified Check ID. The values are taken from the
|
||||
* section 2.1.1.2 of the .lzma file format specification:
|
||||
* { 0, 4, 4, 4, 8, 8, 8, 16, 16, 16, 32, 32, 32, 64, 64, 64 }
|
||||
*
|
||||
* If the argument is not in the range [0, 15], UINT32_MAX is returned.
|
||||
*/
|
||||
extern const uint32_t lzma_check_sizes[LZMA_CHECK_ID_MAX + 1];
|
||||
extern uint32_t lzma_check_size(lzma_check check) lzma_attr_const;
|
||||
|
||||
|
||||
/**
|
||||
@@ -109,7 +118,8 @@ extern const uint32_t lzma_check_sizes[LZMA_CHECK_ID_MAX + 1];
|
||||
* \return Updated CRC value, which can be passed to this function
|
||||
* again to continue CRC calculation.
|
||||
*/
|
||||
extern uint32_t lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc);
|
||||
extern uint32_t lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc)
|
||||
lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
@@ -119,10 +129,21 @@ extern uint32_t lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc);
|
||||
*
|
||||
* This function is used similarly to lzma_crc32(). See its documentation.
|
||||
*/
|
||||
extern uint64_t lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc);
|
||||
extern uint64_t lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc)
|
||||
lzma_attr_pure;
|
||||
|
||||
|
||||
/*
|
||||
* SHA256 functions are currently not exported to public API.
|
||||
* Contact the author if you think it should be.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the type of the integrity check
|
||||
*
|
||||
* This function can be called only immediatelly after lzma_code() has
|
||||
* returned LZMA_NO_CHECK, LZMA_UNSUPPORTED_CHECK, or LZMA_GET_CHECK.
|
||||
* Calling this function in any other situation has undefined behavior.
|
||||
*/
|
||||
extern lzma_check lzma_get_check(const lzma_stream *strm);
|
||||
|
||||
266
src/liblzma/api/lzma/container.h
Normal file
266
src/liblzma/api/lzma/container.h
Normal file
@@ -0,0 +1,266 @@
|
||||
/**
|
||||
* \file lzma/container.h
|
||||
* \brief File formats
|
||||
*
|
||||
* \author Copyright (C) 1999-2008 Igor Pavlov
|
||||
* \author Copyright (C) 2007-2008 Lasse Collin
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 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
|
||||
* Lesser General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef LZMA_H_INTERNAL
|
||||
# error Never include this file directly. Use <lzma.h> instead.
|
||||
#endif
|
||||
|
||||
|
||||
/************
|
||||
* Encoding *
|
||||
************/
|
||||
|
||||
/**
|
||||
* \brief Compression level names for lzma_easy_* functions
|
||||
*
|
||||
* At the moment, all the compression levels support LZMA_SYNC_FLUSH.
|
||||
* In future there may be levels that don't support LZMA_SYNC_FLUSH.
|
||||
* However, the LZMA_SYNC_FLUSH support won't be removed from the
|
||||
* existing compression levels.
|
||||
*
|
||||
* \note If liblzma is built without encoder support, or with some
|
||||
* filters disabled, some of the compression levels may be
|
||||
* unsupported. In that case, the initialization functions
|
||||
* will return LZMA_HEADER_ERROR.
|
||||
*/
|
||||
typedef enum {
|
||||
LZMA_EASY_COPY = 0,
|
||||
/**<
|
||||
* No compression; the data is just wrapped into .lzma
|
||||
* container.
|
||||
*/
|
||||
|
||||
LZMA_EASY_LZMA2_1 = 1,
|
||||
/**<
|
||||
* LZMA2 filter with fast compression (fast in terms of LZMA2).
|
||||
* If you are interested in the exact options used, see
|
||||
* lzma_preset_lzma[0]. Note that the exact options may
|
||||
* change between liblzma versions.
|
||||
*
|
||||
* At the moment, the command line tool uses these settings
|
||||
* when `lzma -1' is used. In future, the command line tool
|
||||
* may default to some more complex way to determine the
|
||||
* settings used e.g. the type of files being compressed.
|
||||
*
|
||||
* LZMA_EASY_LZMA_2 is equivalent to lzma_preset_lzma[1]
|
||||
* and so on.
|
||||
*/
|
||||
|
||||
LZMA_EASY_LZMA_2 = 2,
|
||||
LZMA_EASY_LZMA_3 = 3,
|
||||
LZMA_EASY_LZMA_4 = 4,
|
||||
LZMA_EASY_LZMA_5 = 5,
|
||||
LZMA_EASY_LZMA_6 = 6,
|
||||
LZMA_EASY_LZMA_7 = 7,
|
||||
LZMA_EASY_LZMA_8 = 8,
|
||||
LZMA_EASY_LZMA_9 = 9,
|
||||
} lzma_easy_level;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Default compression level
|
||||
*
|
||||
* Data Blocks contain the actual compressed data. It's not straightforward
|
||||
* to recommend a default level, because in some cases keeping the resource
|
||||
* usage relatively low is more important that getting the maximum
|
||||
* compression ratio.
|
||||
*/
|
||||
#define LZMA_EASY_DEFAULT LZMA_EASY_LZMA2_7
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculates rough memory requirements of a compression level
|
||||
*
|
||||
* This function is a wrapper for lzma_memory_usage(), which is declared
|
||||
* in filter.h.
|
||||
*
|
||||
* \return Approximate memory usage of the encoder with the given
|
||||
* compression level in mebibytes (value * 1024 * 1024 bytes).
|
||||
* On error (e.g. compression level is not supported),
|
||||
* UINT32_MAX is returned.
|
||||
*/
|
||||
extern uint64_t lzma_easy_memory_usage(lzma_easy_level level)
|
||||
lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initializes .lzma Stream encoder
|
||||
*
|
||||
* This function is intended for those who just want to use the basic features
|
||||
* if liblzma (that is, most developers out there). Lots of assumptions are
|
||||
* made, which are correct or at least good enough for most situations.
|
||||
*
|
||||
* \param strm Pointer to lzma_stream that is at least initialized
|
||||
* with LZMA_STREAM_INIT.
|
||||
* \param level Compression level to use. This selects a set of
|
||||
* compression settings from a list of compression
|
||||
* presets.
|
||||
*
|
||||
* \return - LZMA_OK: Initialization succeeded. Use lzma_code() to
|
||||
* encode your data.
|
||||
* - LZMA_MEM_ERROR: Memory allocation failed. All memory
|
||||
* previously allocated for *strm is now freed.
|
||||
* - LZMA_HEADER_ERROR: The given compression level is not
|
||||
* supported by this build of liblzma.
|
||||
*
|
||||
* If initialization succeeds, use lzma_code() to do the actual encoding.
|
||||
* Valid values for `action' (the second argument of lzma_code()) are
|
||||
* LZMA_RUN, LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, and LZMA_FINISH. In future,
|
||||
* there may be compression levels that don't support LZMA_SYNC_FLUSH.
|
||||
*/
|
||||
extern lzma_ret lzma_easy_encoder(lzma_stream *strm, lzma_easy_level level)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initializes .lzma Stream encoder
|
||||
*
|
||||
* \param strm Pointer to properly prepared lzma_stream
|
||||
* \param filters Array of filters. This must be terminated with
|
||||
* filters[n].id = LZMA_VLI_VALUE_UNKNOWN. There must
|
||||
* be 1-4 filters, but there are restrictions on how
|
||||
* multiple filters can be combined. FIXME Tell where
|
||||
* to find more information.
|
||||
* \param check Type of the integrity check to calculate from
|
||||
* uncompressed data.
|
||||
*
|
||||
* \return - LZMA_OK: Initialization was successful.
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_HEADER_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern lzma_ret lzma_stream_encoder(lzma_stream *strm,
|
||||
const lzma_filter *filters, lzma_check check)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initializes LZMA_Alone (deprecated file format) encoder
|
||||
*
|
||||
* LZMA_Alone files have the suffix .lzma like the .lzma Stream files.
|
||||
* LZMA_Alone format supports only one filter, the LZMA filter. There is
|
||||
* no support for integrity checks like CRC32.
|
||||
*
|
||||
* Use this format if and only if you need to create files readable by
|
||||
* legacy LZMA tools such as LZMA Utils 4.32.x.
|
||||
*
|
||||
* LZMA_Alone encoder doesn't support LZMA_SYNC_FLUSH or LZMA_FULL_FLUSH.
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern lzma_ret lzma_alone_encoder(
|
||||
lzma_stream *strm, const lzma_options_lzma *options)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/************
|
||||
* Decoding *
|
||||
************/
|
||||
|
||||
/**
|
||||
* This flag makes lzma_code() return LZMA_NO_CHECK if the input stream
|
||||
* being decoded has no integrity check. Note that when used with
|
||||
* lzma_auto_decoder(), all LZMA_Alone files will trigger LZMA_NO_CHECK
|
||||
* if LZMA_TELL_NO_CHECK is used.
|
||||
*/
|
||||
#define LZMA_TELL_NO_CHECK UINT32_C(0x01)
|
||||
|
||||
|
||||
/**
|
||||
* This flag makes lzma_code() return LZMA_UNSUPPORTED_CHECK if the input
|
||||
* stream has an integrity check, but the type of the integrity check is not
|
||||
* supported by this liblzma version or build. Such files can still be
|
||||
* decoded, but the integrity check cannot be verified.
|
||||
*/
|
||||
#define LZMA_TELL_UNSUPPORTED_CHECK UINT32_C(0x02)
|
||||
|
||||
|
||||
/**
|
||||
* This flag makes lzma_code() return LZMA_GET_CHECK as soon as the type
|
||||
* of the integrity check is known. The type can then be got with
|
||||
* lzma_get_check().
|
||||
*/
|
||||
#define LZMA_TELL_ANY_CHECK UINT32_C(0x04)
|
||||
|
||||
|
||||
/**
|
||||
* This flag enables decoding of concatenated files with file formats that
|
||||
* allow concatenating compressed files as is. From the formats currently
|
||||
* supported by liblzma, only the new .lzma format allows concatenated files.
|
||||
* Concatenated files are not allowed with the LZMA_Alone format.
|
||||
*
|
||||
* This flag also affects the usage of the `action' argument for lzma_code().
|
||||
* When LZMA_CONCATENATED is used, lzma_code() won't return LZMA_STREAM_END
|
||||
* unless LZMA_FINISH is used as `action'. Thus, the application has to set
|
||||
* LZMA_FINISH in the same way as it does when encoding.
|
||||
*
|
||||
* If LZMA_CONCATENATED is not used, the decoders still accept LZMA_FINISH
|
||||
* as `action' for lzma_code(), but the usage of LZMA_FINISH isn't required.
|
||||
*/
|
||||
#define LZMA_CONCATENATED UINT32_C(0x08)
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initializes decoder for .lzma Stream
|
||||
*
|
||||
* \param strm Pointer to properly prepared lzma_stream
|
||||
* \param memlimit Rough memory usage limit as bytes
|
||||
*
|
||||
* \return - LZMA_OK: Initialization was successful.
|
||||
* - LZMA_MEM_ERROR: Cannot allocate memory.
|
||||
* - LZMA_HEADER_ERROR: Unsupported flags
|
||||
*/
|
||||
extern lzma_ret lzma_stream_decoder(
|
||||
lzma_stream *strm, uint64_t memlimit, uint32_t flags)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Decode .lzma Streams and LZMA_Alone files with autodetection
|
||||
*
|
||||
* Autodetects between the .lzma Stream and LZMA_Alone formats, and
|
||||
* calls lzma_stream_decoder() or lzma_alone_decoder() once the type
|
||||
* of the file has been detected.
|
||||
*
|
||||
* \param strm Pointer to propertily prepared lzma_stream
|
||||
* \param memlimit Rough memory usage limit as bytes
|
||||
* \param flags Bitwise-or of flags, or zero for no flags.
|
||||
*
|
||||
* \return - LZMA_OK: Initialization was successful.
|
||||
* - LZMA_MEM_ERROR: Cannot allocate memory.
|
||||
* - LZMA_HEADER_ERROR: Unsupported flags
|
||||
*/
|
||||
extern lzma_ret lzma_auto_decoder(
|
||||
lzma_stream *strm, uint64_t memlimit, uint32_t flags)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initializes decoder for LZMA_Alone file
|
||||
*
|
||||
* Valid `action' arguments to lzma_code() are LZMA_RUN and LZMA_FINISH.
|
||||
* There is no need to use LZMA_FINISH, but allowing it may simplify
|
||||
* certain types of applications.
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_MEM_ERROR
|
||||
*/
|
||||
extern lzma_ret lzma_alone_decoder(lzma_stream *strm, uint64_t memlimit)
|
||||
lzma_attr_warn_unused_result;
|
||||
@@ -1,29 +0,0 @@
|
||||
/**
|
||||
* \file lzma/copy.h
|
||||
* \brief Copy filter
|
||||
*
|
||||
* \author Copyright (C) 1999-2006 Igor Pavlov
|
||||
* \author Copyright (C) 2007 Lasse Collin
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 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
|
||||
* Lesser General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef LZMA_H_INTERNAL
|
||||
# error Never include this file directly. Use <lzma.h> instead.
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* \brief Filter ID
|
||||
*
|
||||
* Filter ID of the Copy filter. This is used as lzma_options_filter.id.
|
||||
*/
|
||||
#define LZMA_FILTER_COPY LZMA_VLI_C(0x00)
|
||||
@@ -24,9 +24,21 @@
|
||||
/**
|
||||
* \brief Filter ID
|
||||
*
|
||||
* Filter ID of the Delta filter. This is used as lzma_options_filter.id.
|
||||
* Filter ID of the Delta filter. This is used as lzma_filter.id.
|
||||
*/
|
||||
#define LZMA_FILTER_DELTA LZMA_VLI_C(0x20)
|
||||
#define LZMA_FILTER_DELTA LZMA_VLI_C(0x03)
|
||||
|
||||
|
||||
/**
|
||||
* \brief Type of the delta calculation
|
||||
*
|
||||
* Currently only byte-wise delta is supported. Other possible types could
|
||||
* be, for example, delta of 16/32/64-bit little/big endian integers, but
|
||||
* these are not currently planned since byte-wise delta is almost as good.
|
||||
*/
|
||||
typedef enum {
|
||||
LZMA_DELTA_TYPE_BYTE
|
||||
} lzma_delta_type;
|
||||
|
||||
|
||||
/**
|
||||
@@ -35,8 +47,14 @@
|
||||
* These options are needed by both encoder and decoder.
|
||||
*/
|
||||
typedef struct {
|
||||
/** For now, this must always be LZMA_DELTA_TYPE_BYTE. */
|
||||
lzma_delta_type type;
|
||||
|
||||
/**
|
||||
* \brief Delta distance as bytes
|
||||
* \brief Delta distance
|
||||
*
|
||||
* With the only currently supported type, LZMA_DELTA_TYPE_BYTE,
|
||||
* the distance is as bytes.
|
||||
*
|
||||
* Examples:
|
||||
* - 16-bit stereo audio: distance = 4 bytes
|
||||
@@ -46,4 +64,16 @@ typedef struct {
|
||||
# define LZMA_DELTA_DISTANCE_MIN 1
|
||||
# define LZMA_DELTA_DISTANCE_MAX 256
|
||||
|
||||
/**
|
||||
* \brief Reserved space for possible future extensions
|
||||
*
|
||||
* You should not touch these, because the names of these variables
|
||||
* may change. These are and will never be used when type is
|
||||
* LZMA_DELTA_TYPE_BYTE, so it is safe to leave these uninitialized.
|
||||
*/
|
||||
uint32_t reserved_int1;
|
||||
uint32_t reserved_int2;
|
||||
void *reserved_ptr1;
|
||||
void *reserved_ptr2;
|
||||
|
||||
} lzma_options_delta;
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
/**
|
||||
* \file lzma/extra.h
|
||||
* \brief Handling of Extra Records in Metadata
|
||||
*
|
||||
* \author Copyright (C) 1999-2006 Igor Pavlov
|
||||
* \author Copyright (C) 2007 Lasse Collin
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 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
|
||||
* Lesser General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef LZMA_H_INTERNAL
|
||||
# error Never include this file directly. Use <lzma.h> instead.
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Extra Record IDs
|
||||
*
|
||||
* See the .lzma file format specification for description what each
|
||||
* Extra Record type exactly means.
|
||||
*
|
||||
* If you ever need to update .lzma files with Extra Records, note that
|
||||
* the Record IDs are divided in two categories:
|
||||
* - Safe-to-Copy Records may be preserved as is when the
|
||||
* Stream is modified in ways that don't change the actual
|
||||
* uncompressed data. Examples of such operatings include
|
||||
* recompressing and adding, modifying, or deleting unrelated
|
||||
* Extra Records.
|
||||
* - Unsafe-to-Copy Records should be removed (and possibly
|
||||
* recreated) when any kind of changes are made to the Stream.
|
||||
*/
|
||||
|
||||
#define LZMA_EXTRA_PADDING 0x00
|
||||
#define LZMA_EXTRA_OPENPGP 0x01
|
||||
#define LZMA_EXTRA_FILTERS 0x02
|
||||
#define LZMA_EXTRA_COMMENT 0x03
|
||||
#define LZMA_EXTRA_CHECKS 0x04
|
||||
#define LZMA_EXTRA_FILENAME 0x05
|
||||
#define LZMA_EXTRA_MTIME 0x07
|
||||
#define LZMA_EXTRA_MTIME_HR 0x09
|
||||
#define LZMA_EXTRA_MIME_TYPE 0x0B
|
||||
#define LZMA_EXTRA_HOMEPAGE 0x0D
|
||||
|
||||
|
||||
/**
|
||||
* \brief Extra Records
|
||||
*
|
||||
* The .lzma format provides a way to store custom information along
|
||||
* the actual compressed content. Information about these Records
|
||||
* are passed to and from liblzma via this linked list.
|
||||
*/
|
||||
typedef struct lzma_extra_s lzma_extra;
|
||||
struct lzma_extra_s {
|
||||
/**
|
||||
* \brief Pointer to the next Extra Record
|
||||
*
|
||||
* This is NULL on the last Extra Record.
|
||||
*/
|
||||
lzma_extra *next;
|
||||
|
||||
/**
|
||||
* \brief Record ID
|
||||
*
|
||||
* Extra Record IDs are divided in three categories:
|
||||
* - Zero is a special case used for padding. It doesn't have
|
||||
* Size of Data fields.
|
||||
* - Odd IDs (1, 3, 5, ...) are Safe-to-Copy IDs.
|
||||
* These can be preserved as is if the Stream is
|
||||
* modified in a way that doesn't alter the actual
|
||||
* uncompressed content.
|
||||
* - Even IDs (2, 4, 6, ...) are Unsafe-to-Copy IDs.
|
||||
* If the .lzma Stream is modified in any way,
|
||||
* the Extra Records having a sensitive ID should
|
||||
* be removed or updated accordingly.
|
||||
*
|
||||
* Refer to the .lzma file format specification for
|
||||
* the up to date list of Extra Record IDs.
|
||||
*/
|
||||
lzma_vli id;
|
||||
|
||||
/**
|
||||
* \brief Size of the Record data
|
||||
*
|
||||
* In case of strings, this should not include the
|
||||
* trailing '\0'.
|
||||
*/
|
||||
size_t size;
|
||||
|
||||
/**
|
||||
* \brief Record data
|
||||
*
|
||||
* Record data is often a string in UTF-8 encoding,
|
||||
* but it can be arbitrary binary data. In case of
|
||||
* strings, the trailing '\0' is usually not stored
|
||||
* in the .lzma file.
|
||||
*
|
||||
* To ease working with Extra Records containing strings,
|
||||
* liblzma always adds '\0' to the end of data even when
|
||||
* it wasn't present in the .lzma file. This '\0' is not
|
||||
* counted in the size of the data.
|
||||
*/
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
|
||||
extern void lzma_extra_free(lzma_extra *extra, lzma_allocator *allocator);
|
||||
@@ -51,55 +51,171 @@ typedef struct {
|
||||
*/
|
||||
void *options;
|
||||
|
||||
} lzma_options_filter;
|
||||
} lzma_filter;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Filters available for encoding
|
||||
* \brief Test if the given Filter ID is supported for encoding
|
||||
*
|
||||
* Pointer to an array containing the list of available Filter IDs that
|
||||
* can be used for encoding. The last element is LZMA_VLI_VALUE_UNKNOWN.
|
||||
* Returns true if the give Filter ID is supported for encoding by this
|
||||
* liblzma build. Otherwise false is returned.
|
||||
*
|
||||
* If lzma_available_filter_encoders[0] == LZMA_VLI_VALUE_UNKNOWN, the
|
||||
* encoder components haven't been built at all. This means that the
|
||||
* encoding-specific functions are probably missing from the library
|
||||
* API/ABI completely.
|
||||
* There is no way to list which filters are available in this particular
|
||||
* liblzma version and build. It would be useless, because the application
|
||||
* couldn't know what kind of options the filter would need.
|
||||
*/
|
||||
extern const lzma_vli *const lzma_available_filter_encoders;
|
||||
extern lzma_bool lzma_filter_encoder_is_supported(lzma_vli id);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Filters available for decoding
|
||||
* \brief Test if the given Filter ID is supported for decoding
|
||||
*
|
||||
* Pointer to an array containing the list of available Filter IDs that
|
||||
* can be used for decoding. The last element is LZMA_VLI_VALUE_UNKNOWN.
|
||||
*
|
||||
* If lzma_available_filter_decoders[0] == LZMA_VLI_VALUE_UNKNOWN, the
|
||||
* decoder components haven't been built at all. This means that the
|
||||
* decoding-specific functions are probably missing from the library
|
||||
* API/ABI completely.
|
||||
* Returns true if the give Filter ID is supported for decoding by this
|
||||
* liblzma build. Otherwise false is returned.
|
||||
*/
|
||||
extern const lzma_vli *const lzma_available_filter_decoders;
|
||||
extern lzma_bool lzma_filter_decoder_is_supported(lzma_vli id);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculate rough memory requirements for given filter chain
|
||||
* \brief Calculate rough memory requirements for raw encoder
|
||||
*
|
||||
* \param filters Array of filters terminated with
|
||||
* .id == LZMA_VLI_VALUE_UNKNOWN.
|
||||
* \param is_encoder Set to true when calculating memory requirements
|
||||
* of an encoder; false for decoder.
|
||||
*
|
||||
* \return Number of mebibytes (MiB i.e. 2^20) required for the given
|
||||
* encoder or decoder filter chain.
|
||||
*
|
||||
* \note If calculating memory requirements of encoder, lzma_init() or
|
||||
* lzma_init_encoder() must have been called earlier. Similarly,
|
||||
* if calculating memory requirements of decoder, lzma_init() or
|
||||
* lzma_init_decoder() must have been called earlier.
|
||||
* \return Rough number of bytes required for the given filter chain
|
||||
* when encoding.
|
||||
*/
|
||||
extern uint32_t lzma_memory_usage(
|
||||
const lzma_options_filter *filters, lzma_bool is_encoder);
|
||||
extern uint64_t lzma_memusage_encoder(const lzma_filter *filters)
|
||||
lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculate rough memory requirements for raw decoder
|
||||
*
|
||||
* \param filters Array of filters terminated with
|
||||
* .id == LZMA_VLI_VALUE_UNKNOWN.
|
||||
*
|
||||
* \return Rough number of bytes required for the given filter chain
|
||||
* when decoding.
|
||||
*/
|
||||
extern uint64_t lzma_memusage_decoder(const lzma_filter *filters)
|
||||
lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initialize raw encoder
|
||||
*
|
||||
* This function may be useful when implementing custom file formats.
|
||||
*
|
||||
* \param strm Pointer to properly prepared lzma_stream
|
||||
* \param options Array of lzma_filter structures.
|
||||
* The end of the array must be marked with
|
||||
* .id = LZMA_VLI_VALUE_UNKNOWN. The minimum
|
||||
* number of filters is one and the maximum is four.
|
||||
*
|
||||
* The `action' with lzma_code() can be LZMA_RUN, LZMA_SYNC_FLUSH (if the
|
||||
* filter chain supports it), or LZMA_FINISH.
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_HEADER_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern lzma_ret lzma_raw_encoder(
|
||||
lzma_stream *strm, const lzma_filter *options)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initialize raw decoder
|
||||
*
|
||||
* The initialization of raw decoder goes similarly to raw encoder.
|
||||
*
|
||||
* The `action' with lzma_code() can be LZMA_RUN or LZMA_FINISH. Using
|
||||
* LZMA_FINISH is not required, it is supported just for convenience.
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_HEADER_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern lzma_ret lzma_raw_decoder(
|
||||
lzma_stream *strm, const lzma_filter *options)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the size of the Filter Properties field
|
||||
*
|
||||
* This function may be useful when implementing custom file formats
|
||||
* using the raw encoder and decoder.
|
||||
*
|
||||
* \param size Pointer to uint32_t to hold the size of the properties
|
||||
* \param filter Filter ID and options (the size of the propeties may
|
||||
* vary depending on the options)
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_HEADER_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*
|
||||
* \note This function validates the Filter ID, but does not
|
||||
* necessarily validate the options. Thus, it is possible
|
||||
* that this returns LZMA_OK while the following call to
|
||||
* lzma_properties_encode() returns LZMA_HEADER_ERROR.
|
||||
*/
|
||||
extern lzma_ret lzma_properties_size(
|
||||
uint32_t *size, const lzma_filter *filter);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Encode the Filter Properties field
|
||||
*
|
||||
* \param filter Filter ID and options
|
||||
* \param props Buffer to hold the encoded options. The size of
|
||||
* buffer must have been already determined with
|
||||
* lzma_properties_size().
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_HEADER_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*
|
||||
* \note Even this function won't validate more options than actually
|
||||
* necessary. Thus, it is possible that encoding the properties
|
||||
* succeeds but using the same options to initialize the encoder
|
||||
* will fail.
|
||||
*
|
||||
* \note It is OK to skip calling this function if
|
||||
* lzma_properties_size() indicated that the size
|
||||
* of the Filter Properties field is zero.
|
||||
*/
|
||||
extern lzma_ret lzma_properties_encode(
|
||||
const lzma_filter *filter, uint8_t *props);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Decode the Filter Properties field
|
||||
*
|
||||
* \param filter filter->id must have been set to the correct
|
||||
* Filter ID. filter->options doesn't need to be
|
||||
* initialized (it's not freed by this function). The
|
||||
* decoded options will be stored to filter->options.
|
||||
* filter->options is set to NULL if there are no
|
||||
* properties or if an error occurs.
|
||||
* \param allocator Custom memory allocator used to allocate the
|
||||
* options. Set to NULL to use the default malloc(),
|
||||
* and in case of an error, also free().
|
||||
* \param props Input buffer containing the properties.
|
||||
* \param props_size Size of the properties. This must be the exact
|
||||
* size; giving too much or too little input will
|
||||
* return LZMA_HEADER_ERROR.
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_HEADER_ERROR
|
||||
* - LZMA_MEM_ERROR
|
||||
*/
|
||||
extern lzma_ret lzma_properties_decode(
|
||||
lzma_filter *filter, lzma_allocator *allocator,
|
||||
const uint8_t *props, size_t props_size);
|
||||
|
||||
|
||||
/**
|
||||
@@ -119,10 +235,11 @@ extern uint32_t lzma_memory_usage(
|
||||
* - LZMA_PROG_ERROR: Invalid options
|
||||
*
|
||||
* \note If you need to calculate size of List of Filter Flags,
|
||||
* you need to loop over every lzma_options_filter entry.
|
||||
* you need to loop over every lzma_filter entry.
|
||||
*/
|
||||
extern lzma_ret lzma_filter_flags_size(
|
||||
uint32_t *size, const lzma_options_filter *options);
|
||||
uint32_t *size, const lzma_filter *options)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
@@ -143,8 +260,9 @@ extern lzma_ret lzma_filter_flags_size(
|
||||
* buffer space (you should have checked it with
|
||||
* lzma_filter_flags_size()).
|
||||
*/
|
||||
extern lzma_ret lzma_filter_flags_encode(uint8_t *out, size_t *out_pos,
|
||||
size_t out_size, const lzma_options_filter *options);
|
||||
extern lzma_ret lzma_filter_flags_encode(const lzma_filter *options,
|
||||
uint8_t *out, size_t *out_pos, size_t out_size)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
@@ -162,5 +280,7 @@ extern lzma_ret lzma_filter_flags_encode(uint8_t *out, size_t *out_pos,
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern lzma_ret lzma_filter_flags_decoder(
|
||||
lzma_stream *strm, lzma_options_filter *options);
|
||||
extern lzma_ret lzma_filter_flags_decode(
|
||||
lzma_filter *options, lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t *in_pos, size_t in_size)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
@@ -22,63 +22,221 @@
|
||||
|
||||
|
||||
/**
|
||||
* \brief
|
||||
*
|
||||
* FIXME desc
|
||||
* \brief Opaque data type to hold the Index
|
||||
*/
|
||||
typedef struct lzma_index_s lzma_index;
|
||||
struct lzma_index_s {
|
||||
|
||||
|
||||
/**
|
||||
* \brief Index Record and its location
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Total Size of the Block
|
||||
*
|
||||
* This includes Block Header, Compressed Data, and Block Footer.
|
||||
* Total Size of a Block.
|
||||
*/
|
||||
lzma_vli total_size;
|
||||
|
||||
/**
|
||||
* \brief Uncompressed Size of the Block
|
||||
* Uncompressed Size of a Block
|
||||
*/
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
/**
|
||||
* \brief Pointer to the next Index Record
|
||||
*
|
||||
* This is NULL on the last Index Record.
|
||||
* Offset of the first byte of a Block relative to the beginning
|
||||
* of the Stream, or if there are multiple Indexes combined,
|
||||
* relative to the beginning of the first Stream.
|
||||
*/
|
||||
lzma_index *next;
|
||||
};
|
||||
lzma_vli stream_offset;
|
||||
|
||||
/**
|
||||
* Uncompressed offset
|
||||
*/
|
||||
lzma_vli uncompressed_offset;
|
||||
|
||||
} lzma_index_record;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Allocate and initialize a new lzma_index structure
|
||||
*
|
||||
* If i is NULL, a new lzma_index structure is allocated, initialized,
|
||||
* and a pointer to it returned. If allocation fails, NULL is returned.
|
||||
*
|
||||
* If i is non-NULL, it is reinitialized and the same pointer returned.
|
||||
* In this case, return value cannot be NULL or a different pointer than
|
||||
* the i given as argument.
|
||||
*/
|
||||
extern lzma_index *lzma_index_init(lzma_index *i, lzma_allocator *allocator)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Deallocate the Index
|
||||
*/
|
||||
extern void lzma_index_end(lzma_index *i, lzma_allocator *allocator);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Add a new Record to an Index
|
||||
*
|
||||
* \param index Pointer to a lzma_index structure
|
||||
* \param total_size Total Size of a Block
|
||||
* \param uncompressed_size Uncompressed Size of a Block, or
|
||||
* LZMA_VLI_VALUE_UNKNOWN to indicate padding.
|
||||
*
|
||||
* Appending a new Record does not affect the read position.
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_DATA_ERROR: Compressed or uncompressed size of the
|
||||
* Stream or size of the Index field would grow too big.
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern lzma_ret lzma_index_append(lzma_index *i, lzma_allocator *allocator,
|
||||
lzma_vli total_size, lzma_vli uncompressed_size)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the number of Records
|
||||
*/
|
||||
extern lzma_vli lzma_index_count(const lzma_index *i) lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the size of the Index field as bytes
|
||||
*
|
||||
* This is needed to verify the Index Size field from the Stream Footer.
|
||||
*/
|
||||
extern lzma_vli lzma_index_size(const lzma_index *i) lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the total size of the Blocks
|
||||
*
|
||||
* This doesn't include the Stream Header, Stream Footer, Stream Padding,
|
||||
* or Index fields.
|
||||
*/
|
||||
extern lzma_vli lzma_index_total_size(const lzma_index *i) lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the total size of the Stream
|
||||
*
|
||||
* If multiple Indexes have been combined, this works as if the Blocks
|
||||
* were in a single Stream.
|
||||
*/
|
||||
extern lzma_vli lzma_index_stream_size(const lzma_index *i) lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the total size of the file
|
||||
*
|
||||
* When no Indexes have been combined with lzma_index_cat(), this function is
|
||||
* identical to lzma_index_stream_size(). If multiple Indexes have been
|
||||
* combined, this includes also the possible Stream Padding fields.
|
||||
*/
|
||||
extern lzma_vli lzma_index_file_size(const lzma_index *i) lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the uncompressed size of the Stream
|
||||
*/
|
||||
extern lzma_vli lzma_index_uncompressed_size(const lzma_index *i)
|
||||
lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the next Record from the Index
|
||||
*/
|
||||
extern lzma_bool lzma_index_read(lzma_index *i, lzma_index_record *record)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Rewind the Index
|
||||
*
|
||||
* Rewind the Index so that next call to lzma_index_read() will return the
|
||||
* first Record.
|
||||
*/
|
||||
extern void lzma_index_rewind(lzma_index *i);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Locate a Record
|
||||
*
|
||||
* When the Index is available, it is possible to do random-access reading
|
||||
* with granularity of Block size.
|
||||
*
|
||||
* \param i Pointer to lzma_index structure
|
||||
* \param record Pointer to a structure to hold the search results
|
||||
* \param target Uncompressed target offset
|
||||
*
|
||||
* If the target is smaller than the uncompressed size of the Stream (can be
|
||||
* checked with lzma_index_uncompressed_size()):
|
||||
* - Information about the Record containing the requested uncompressed
|
||||
* offset is stored into *record.
|
||||
* - Read offset will be adjusted so that calling lzma_index_read() can be
|
||||
* used to read subsequent Records.
|
||||
* - This function returns false.
|
||||
*
|
||||
* If target is greater than the uncompressed size of the Stream, *record
|
||||
* and the read position are not modified, and this function returns true.
|
||||
*/
|
||||
extern lzma_bool lzma_index_locate(
|
||||
lzma_index *i, lzma_index_record *record, lzma_vli target)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Concatenate Indexes of two Streams
|
||||
*
|
||||
*
|
||||
*
|
||||
* \param dest Destination Index after which src is appended Source
|
||||
* \param src Index. The memory allocated for this is either moved
|
||||
* to be part of *dest or freed iff the function call
|
||||
* succeeds, and src will be an invalid pointer.
|
||||
* \param allocator Custom memory allocator; can be NULL to use
|
||||
* malloc() and free().
|
||||
* \param padding Size of the Stream Padding field between Streams.
|
||||
*
|
||||
* \return - LZMA_OK: Indexes concatenated successfully.
|
||||
* - LZMA_DATA_ERROR: *dest would grow too big.
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern lzma_ret lzma_index_cat(lzma_index *lzma_restrict dest,
|
||||
lzma_index *lzma_restrict src,
|
||||
lzma_allocator *allocator, lzma_vli padding)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Duplicates an Index list
|
||||
*
|
||||
* \return A copy of the Index list, or NULL if memory allocation
|
||||
* failed or the original Index was empty.
|
||||
* \return A copy of the Index, or NULL if memory allocation failed.
|
||||
*/
|
||||
extern lzma_index *lzma_index_dup(
|
||||
const lzma_index *index, lzma_allocator *allocator);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Frees an Index list
|
||||
*
|
||||
* All Index Recors in the list are freed. This function is convenient when
|
||||
* getting rid of lzma_metadata structures containing an Index.
|
||||
*/
|
||||
extern void lzma_index_free(lzma_index *index, lzma_allocator *allocator);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculates information about the Index
|
||||
*
|
||||
* \return LZMA_OK on success, LZMA_PROG_ERROR on error. FIXME
|
||||
*/
|
||||
extern lzma_ret lzma_index_count(const lzma_index *index, size_t *count,
|
||||
lzma_vli *lzma_restrict total_size,
|
||||
lzma_vli *lzma_restrict uncompressed_size);
|
||||
const lzma_index *i, lzma_allocator *allocator)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Compares if two Index lists are identical
|
||||
*/
|
||||
extern lzma_bool lzma_index_is_equal(const lzma_index *a, const lzma_index *b);
|
||||
extern lzma_bool lzma_index_equal(const lzma_index *a, const lzma_index *b)
|
||||
lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initializes Index encoder
|
||||
*/
|
||||
extern lzma_ret lzma_index_encoder(lzma_stream *strm, lzma_index *i)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initializes Index decoder
|
||||
*/
|
||||
extern lzma_ret lzma_index_decoder(lzma_stream *strm, lzma_index **i)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
98
src/liblzma/api/lzma/index_hash.h
Normal file
98
src/liblzma/api/lzma/index_hash.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* \file lzma/index_hash.h
|
||||
* \brief Validates Index by using a hash function
|
||||
*
|
||||
* Instead of constructing complete Index while decoding Blocks, Index hash
|
||||
* calculates a hash of the Block sizes and Index, and then compares the
|
||||
* hashes. This way memory usage is constant even with large number of
|
||||
* Blocks and huge Index.
|
||||
*
|
||||
* \author Copyright (C) 2008 Lasse Collin
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 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
|
||||
* Lesser General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef LZMA_H_INTERNAL
|
||||
# error Never include this file directly. Use <lzma.h> instead.
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Opaque data type to hold the Index hash
|
||||
*/
|
||||
typedef struct lzma_index_hash_s lzma_index_hash;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Allocate and initialize a new lzma_index_hash structure
|
||||
*
|
||||
* If index_hash is NULL, a new lzma_index_hash structure is allocated,
|
||||
* initialized, and a pointer to it returned. If allocation fails, NULL
|
||||
* is returned.
|
||||
*
|
||||
* If index_hash is non-NULL, it is reinitialized and the same pointer
|
||||
* returned. In this case, return value cannot be NULL or a different
|
||||
* pointer than the index_hash given as argument.
|
||||
*/
|
||||
extern lzma_index_hash *lzma_index_hash_init(
|
||||
lzma_index_hash *index_hash, lzma_allocator *allocator)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Deallocate the Index hash
|
||||
*/
|
||||
extern void lzma_index_hash_end(
|
||||
lzma_index_hash *index_hash, lzma_allocator *allocator);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Add a new Record to an Index hash
|
||||
*
|
||||
* \param index Pointer to a lzma_index_hash structure
|
||||
* \param total_size Total Size of a Block
|
||||
* \param uncompressed_size Uncompressed Size of a Block
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_DATA_ERROR: Compressed or uncompressed size of the
|
||||
* Stream or size of the Index field would grow too big.
|
||||
* - LZMA_PROG_ERROR: Invalid arguments or this function is being
|
||||
* used when lzma_index_hash_decode() has already been used.
|
||||
*/
|
||||
extern lzma_ret lzma_index_hash_append(lzma_index_hash *index_hash,
|
||||
lzma_vli total_size, lzma_vli uncompressed_size)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Decode the Index field
|
||||
*
|
||||
* \return - LZMA_OK: So far good, but more input is needed.
|
||||
* - LZMA_STREAM_END: Index decoded successfully and it matches
|
||||
* the Records given with lzma_index_hash_append().
|
||||
* - LZMA_DATA_ERROR: Index is corrupt or doesn't match the
|
||||
* information given with lzma_index_hash_append().
|
||||
* - LZMA_PROG_ERROR
|
||||
*
|
||||
* \note Once decoding of the Index field has been started, no more
|
||||
* Records can be added using lzma_index_hash_append().
|
||||
*/
|
||||
extern lzma_ret lzma_index_hash_decode(lzma_index_hash *index_hash,
|
||||
const uint8_t *in, size_t *in_pos, size_t in_size)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the size of the Index field as bytes
|
||||
*
|
||||
* This is needed to verify the Index Size field from the Stream Footer.
|
||||
*/
|
||||
extern lzma_vli lzma_index_hash_size(const lzma_index_hash *index_hash)
|
||||
lzma_attr_pure;
|
||||
@@ -1,315 +0,0 @@
|
||||
/**
|
||||
* \file lzma/info.h
|
||||
* \brief Handling of Stream size information
|
||||
*
|
||||
* \author Copyright (C) 1999-2006 Igor Pavlov
|
||||
* \author Copyright (C) 2007 Lasse Collin
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 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
|
||||
* Lesser General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef LZMA_H_INTERNAL
|
||||
# error Never include this file directly. Use <lzma.h> instead.
|
||||
#endif
|
||||
|
||||
|
||||
/**********
|
||||
* Basics *
|
||||
**********/
|
||||
|
||||
/**
|
||||
* \brief Opaque data type to hold the size information
|
||||
*/
|
||||
typedef struct lzma_info_s lzma_info;
|
||||
|
||||
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Total Size of this Block
|
||||
*
|
||||
* This can be LZMA_VLI_VALUE_UNKNOWN.
|
||||
*/
|
||||
lzma_vli total_size;
|
||||
|
||||
/**
|
||||
* \brief Uncompressed Size of this Block
|
||||
*
|
||||
* This can be LZMA_VLI_VALUE_UNKNOWN.
|
||||
*/
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
/**
|
||||
* \brief Offset of the first byte of the Block
|
||||
*
|
||||
* In encoder, this is useful to find out the alignment of the Block.
|
||||
*
|
||||
* In decoder, this is useful when doing random-access reading
|
||||
* with help from lzma_info_data_locate().
|
||||
*/
|
||||
lzma_vli stream_offset;
|
||||
|
||||
/**
|
||||
* \brief Uncompressed offset of the Block
|
||||
*
|
||||
* Offset of the first uncompressed byte of the Block relative to
|
||||
* all uncompressed data in the Block.
|
||||
* FIXME desc
|
||||
*/
|
||||
lzma_vli uncompressed_offset;
|
||||
|
||||
/**
|
||||
* \brief Pointers to internal data structures
|
||||
*
|
||||
* Applications must not touch these.
|
||||
*/
|
||||
void *internal[4];
|
||||
|
||||
} lzma_info_iter;
|
||||
|
||||
|
||||
typedef enum {
|
||||
LZMA_INFO_STREAM_START,
|
||||
LZMA_INFO_HEADER_METADATA,
|
||||
LZMA_INFO_TOTAL,
|
||||
LZMA_INFO_UNCOMPRESSED,
|
||||
LZMA_INFO_FOOTER_METADATA
|
||||
} lzma_info_size;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Allocates and initializes a new lzma_info structure
|
||||
*
|
||||
* If info is NULL, a new lzma_info structure is allocated, initialized, and
|
||||
* a pointer to it returned. If allocation fails, NULL is returned.
|
||||
*
|
||||
* If info is non-NULL, it is reinitialized and the same pointer returned.
|
||||
* (In this case, return value cannot be NULL or a different pointer than
|
||||
* the info given as argument.)
|
||||
*/
|
||||
extern lzma_info *lzma_info_init(lzma_info *info, lzma_allocator *allocator);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Resets lzma_info
|
||||
*
|
||||
* This is like calling lzma_info_end() and lzma_info_create(), but
|
||||
* re-uses the existing base structure.
|
||||
*/
|
||||
extern void lzma_info_reset(
|
||||
lzma_info *info, lzma_allocator *allocator);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Frees memory allocated for a lzma_info structure
|
||||
*/
|
||||
extern void lzma_info_free(lzma_info *info, lzma_allocator *allocator);
|
||||
|
||||
|
||||
/************************
|
||||
* Setting known values *
|
||||
************************/
|
||||
|
||||
/**
|
||||
* \brief Set a known size value
|
||||
*
|
||||
* \param info Pointer returned by lzma_info_create()
|
||||
* \param type Any value from lzma_info_size
|
||||
* \param size Value to set or verify
|
||||
*
|
||||
* \return LZMA_OK on success, LZMA_DATA_ERROR if the size doesn't
|
||||
* match the existing information, or LZMA_PROG_ERROR
|
||||
* if type is invalid or size is not a valid VLI.
|
||||
*/
|
||||
extern lzma_ret lzma_info_size_set(
|
||||
lzma_info *info, lzma_info_size type, lzma_vli size);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Sets the Index
|
||||
*
|
||||
* The given lzma_index list is "absorbed" by this function. The application
|
||||
* must not access it after this function call, even if this function returns
|
||||
* an error.
|
||||
*
|
||||
* \note The given lzma_index will at some point get freed by the
|
||||
* lzma_info_* functions. If you use a custom lzma_allocator,
|
||||
* make sure that it can free the lzma_index.
|
||||
*/
|
||||
extern lzma_ret lzma_info_index_set(
|
||||
lzma_info *info, lzma_allocator *allocator,
|
||||
lzma_index *index, lzma_bool eat_index);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Sets information from a known Metadata Block
|
||||
*
|
||||
* This is a shortcut for calling lzma_info_size_set() with different type
|
||||
* arguments, lzma_info_index_set() with metadata->index.
|
||||
*/
|
||||
extern lzma_ret lzma_info_metadata_set(lzma_info *info,
|
||||
lzma_allocator *allocator, lzma_metadata *metadata,
|
||||
lzma_bool is_header_metadata, lzma_bool eat_index);
|
||||
|
||||
|
||||
/***************
|
||||
* Incremental *
|
||||
***************/
|
||||
|
||||
/**
|
||||
* \brief Prepares an iterator to be used with given lzma_info structure
|
||||
*
|
||||
*
|
||||
*/
|
||||
extern void lzma_info_iter_begin(lzma_info *info, lzma_info_iter *iter);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Moves to the next Index Record
|
||||
*
|
||||
*
|
||||
*/
|
||||
extern lzma_ret lzma_info_iter_next(
|
||||
lzma_info_iter *iter, lzma_allocator *allocator);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Sets or verifies the sizes in the Index Record
|
||||
*
|
||||
* \param iter Pointer to iterator to be set or verified
|
||||
* \param total_size
|
||||
* Total Size in bytes or LZMA_VLI_VALUE_UNKNOWN
|
||||
* \param uncompressed_size
|
||||
* Uncompressed Size or LZMA_VLI_VALUE_UNKNOWN
|
||||
*
|
||||
* \return - LZMA_OK: All OK.
|
||||
* - LZMA_DATA_ERROR: Given sizes don't match with the already
|
||||
* known sizes.
|
||||
* - LZMA_PROG_ERROR: Internal error, possibly integer
|
||||
* overflow (e.g. the sum of all the known sizes is too big)
|
||||
*/
|
||||
extern lzma_ret lzma_info_iter_set(lzma_info_iter *iter,
|
||||
lzma_vli total_size, lzma_vli uncompressed_size);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Locates a Data Block
|
||||
*
|
||||
* \param iter Properly initialized iterator
|
||||
* \param allocator Pointer to lzma_allocator or NULL
|
||||
* \param uncompressed_offset
|
||||
* Target offset to locate. The final offset
|
||||
* will be equal or smaller than this.
|
||||
* \param allow_alloc True if this function is allowed to call
|
||||
* lzma_info_iter_next() to allocate a new Record
|
||||
* if the requested offset reached end of Index
|
||||
* Record list. Note that if Index has been marked
|
||||
* final, lzma_info_iter_next() is never called.
|
||||
*
|
||||
* \return - LZMA_OK: All OK, *iter updated accordingly.
|
||||
* - LZMA_DATA_ERROR: Trying to search past the end of the Index
|
||||
* Record list, and allocating a new Record was not allowed
|
||||
* either because allow_alloc was false or Index was final.
|
||||
* - LZMA_PROG_ERROR: Internal error (probably integer
|
||||
* overflow causing some lzma_vli getting too big).
|
||||
*/
|
||||
extern lzma_ret lzma_info_iter_locate(lzma_info_iter *iter,
|
||||
lzma_allocator *allocator, lzma_vli uncompressed_offset,
|
||||
lzma_bool allow_alloc);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Finishes incrementally constructed Index
|
||||
*
|
||||
* This sets the known Total Size and Uncompressed of the Data Blocks
|
||||
* based on the information collected from the Index Records, and marks
|
||||
* the Index as final.
|
||||
*/
|
||||
extern lzma_ret lzma_info_index_finish(lzma_info *info);
|
||||
|
||||
|
||||
/***************************
|
||||
* Reading the information *
|
||||
***************************/
|
||||
|
||||
/**
|
||||
* \brief Gets a known size
|
||||
*
|
||||
*
|
||||
*/
|
||||
extern lzma_vli lzma_info_size_get(
|
||||
const lzma_info *info, lzma_info_size type);
|
||||
|
||||
extern lzma_vli lzma_info_metadata_locate(
|
||||
const lzma_info *info, lzma_bool is_header_metadata);
|
||||
|
||||
/**
|
||||
* \brief Gets a pointer to the beginning of the Index list
|
||||
*
|
||||
* If detach is true, the Index will be detached from the lzma_info
|
||||
* structure, and thus not be modified or freed by lzma_info_end().
|
||||
*
|
||||
* If detach is false, the application must not modify the Index in any way.
|
||||
* Also, the Index list is guaranteed to be valid only till the next call
|
||||
* to any lzma_info_* function.
|
||||
*/
|
||||
extern lzma_index *lzma_info_index_get(lzma_info *info, lzma_bool detach);
|
||||
|
||||
|
||||
extern size_t lzma_info_index_count_get(const lzma_info *info);
|
||||
|
||||
|
||||
extern uint32_t lzma_info_metadata_alignment_get(
|
||||
const lzma_info *info, lzma_bool is_header_metadata);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \brief Locate a Block containing the given uncompressed offset
|
||||
*
|
||||
* This function is useful when you need to do random-access reading in
|
||||
* a Multi-Block Stream.
|
||||
*
|
||||
* \param info Pointer to lzma_info that has at least one
|
||||
* Index Record. The Index doesn't need to be finished.
|
||||
* \param uncompressed_target
|
||||
* Uncompressed target offset which the caller would
|
||||
* like to locate from the Stream.
|
||||
* \param stream_offset
|
||||
* Starting offset (relative to the beginning the Stream)
|
||||
* of the Block containing the requested location.
|
||||
* \param uncompressed_offset
|
||||
* The actual uncompressed offset of the beginning of
|
||||
* the Block. uncompressed_offset <= uncompressed_target
|
||||
* is always true; the application needs to uncompress
|
||||
* uncompressed_target - uncompressed_offset bytes to
|
||||
* reach the requested target offset.
|
||||
* \param total_size
|
||||
* Total Size of the Block. If the Index is incomplete,
|
||||
* this may be LZMA_VLI_VALUE_UNKNOWN indicating unknown
|
||||
* size.
|
||||
* \param uncompressed_size
|
||||
* Uncompressed Size of the Block. If the Index is
|
||||
* incomplete, this may be LZMA_VLI_VALUE_UNKNOWN
|
||||
* indicating unknown size. The application must pass
|
||||
* this value to the Block decoder to verify FIXME
|
||||
*
|
||||
* \return
|
||||
*
|
||||
* \note This function is currently implemented as a linear search.
|
||||
* If there are many Index Records, this can be really slow.
|
||||
* This can be improved in newer liblzma versions if needed.
|
||||
*/
|
||||
extern lzma_bool lzma_info_data_locate(const lzma_info *info,
|
||||
lzma_vli uncompressed_target,
|
||||
lzma_vli *lzma_restrict stream_offset,
|
||||
lzma_vli *lzma_restrict uncompressed_offset,
|
||||
lzma_vli *lzma_restrict total_size,
|
||||
lzma_vli *lzma_restrict uncompressed_size);
|
||||
@@ -38,7 +38,7 @@
|
||||
* still shouldn't be done when there are multiple threads running.
|
||||
*
|
||||
* lzma_init() initializes all internal static variables by calling
|
||||
* lzma_lzma_init_encoder() and lzma_init_decoder().
|
||||
* lzma_init_encoder() and lzma_init_decoder().
|
||||
*
|
||||
* If you need only encoder, decoder, or neither-encoder-nor-decoder
|
||||
* functions, you may use other initialization functions, which initialize
|
||||
|
||||
@@ -24,43 +24,11 @@
|
||||
/**
|
||||
* \brief Filter ID
|
||||
*
|
||||
* Filter ID of the LZMA filter. This is used as lzma_options_filter.id.
|
||||
* Filter ID of the LZMA filter. This is used as lzma_filter.id.
|
||||
*/
|
||||
#define LZMA_FILTER_LZMA LZMA_VLI_C(0x40)
|
||||
#define LZMA_FILTER_LZMA LZMA_VLI_C(0x20)
|
||||
|
||||
|
||||
/**
|
||||
* \brief LZMA compression modes
|
||||
*
|
||||
* Currently there are only two modes. Earlier LZMA SDKs had also third
|
||||
* mode between fast and best.
|
||||
*/
|
||||
typedef enum {
|
||||
LZMA_MODE_INVALID = -1,
|
||||
/**<
|
||||
* \brief Invalid mode
|
||||
*
|
||||
* Used as array terminator in lzma_available_modes.
|
||||
*/
|
||||
|
||||
|
||||
LZMA_MODE_FAST = 0,
|
||||
/**<
|
||||
* \brief Fast compression
|
||||
*
|
||||
* Fast mode is usually at its best when combined with
|
||||
* a hash chain match finder.
|
||||
*/
|
||||
|
||||
LZMA_MODE_BEST = 2
|
||||
/**<
|
||||
* \brief Best compression ratio
|
||||
*
|
||||
* This is usually notably slower than fast mode. Use this
|
||||
* together with binary tree match finders to expose the
|
||||
* full potential of the LZMA encoder.
|
||||
*/
|
||||
} lzma_mode;
|
||||
#define LZMA_FILTER_LZMA2 LZMA_VLI_C(0x21)
|
||||
|
||||
|
||||
/**
|
||||
@@ -128,6 +96,72 @@ typedef enum {
|
||||
} lzma_match_finder;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Test if given match finder is supported
|
||||
*
|
||||
* Returns true if the given match finder is supported by this liblzma build.
|
||||
* Otherwise false is returned. It is safe to call this with a value that
|
||||
* isn't listed in lzma_match_finder enumeration; the return value will be
|
||||
* false.
|
||||
*
|
||||
* There is no way to list which match finders are available in this
|
||||
* particular liblzma version and build. It would be useless, because
|
||||
* a new match finder, which the application developer wasn't aware,
|
||||
* could require giving additional options to the encoder that the older
|
||||
* match finders don't need.
|
||||
*/
|
||||
extern lzma_bool lzma_mf_is_supported(lzma_match_finder match_finder)
|
||||
lzma_attr_const;
|
||||
|
||||
|
||||
/**
|
||||
* \brief LZMA compression modes
|
||||
*
|
||||
* This selects the function used to analyze the data produced by the match
|
||||
* finder.
|
||||
*/
|
||||
typedef enum {
|
||||
LZMA_MODE_INVALID = -1,
|
||||
/**<
|
||||
* \brief Invalid mode
|
||||
*
|
||||
* Used as array terminator in lzma_available_modes.
|
||||
*/
|
||||
|
||||
LZMA_MODE_FAST = 0,
|
||||
/**<
|
||||
* \brief Fast compression
|
||||
*
|
||||
* Fast mode is usually at its best when combined with
|
||||
* a hash chain match finder.
|
||||
*/
|
||||
|
||||
LZMA_MODE_NORMAL = 1
|
||||
/**<
|
||||
* \brief Normal compression
|
||||
*
|
||||
* This is usually notably slower than fast mode. Use this
|
||||
* together with binary tree match finders to expose the
|
||||
* full potential of the LZMA encoder.
|
||||
*/
|
||||
} lzma_mode;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Test if given compression mode is supported
|
||||
*
|
||||
* Returns true if the given compression mode is supported by this liblzma
|
||||
* build. Otherwise false is returned. It is safe to call this with a value
|
||||
* that isn't listed in lzma_mode enumeration; the return value will be false.
|
||||
*
|
||||
* There is no way to list which modes are available in this particular
|
||||
* liblzma version and build. It would be useless, because a new compression
|
||||
* mode, which the application developer wasn't aware, could require giving
|
||||
* additional options to the encoder that the older modes don't need.
|
||||
*/
|
||||
extern lzma_bool lzma_mode_is_available(lzma_mode mode) lzma_attr_const;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Options specific to the LZMA method handler
|
||||
*/
|
||||
@@ -152,57 +186,10 @@ typedef struct {
|
||||
* because it uses the target buffer as the dictionary.
|
||||
*/
|
||||
uint32_t dictionary_size;
|
||||
# define LZMA_DICTIONARY_SIZE_MIN 1
|
||||
# define LZMA_DICTIONARY_SIZE_MIN (UINT32_C(1) << 12)
|
||||
# define LZMA_DICTIONARY_SIZE_MAX (UINT32_C(1) << 30)
|
||||
# define LZMA_DICTIONARY_SIZE_DEFAULT (UINT32_C(1) << 23)
|
||||
|
||||
/**
|
||||
* \brief Number of literal context bits
|
||||
*
|
||||
* How many of the highest bits of the previous uncompressed
|
||||
* eight-bit byte (also known as `literal') are taken into
|
||||
* account when predicting the bits of the next literal.
|
||||
*
|
||||
* \todo Example
|
||||
*/
|
||||
uint32_t literal_context_bits;
|
||||
# define LZMA_LITERAL_CONTEXT_BITS_MIN 0
|
||||
# define LZMA_LITERAL_CONTEXT_BITS_MAX 8
|
||||
# define LZMA_LITERAL_CONTEXT_BITS_DEFAULT 3
|
||||
|
||||
/**
|
||||
* \brief Number of literal position bits
|
||||
*
|
||||
* How many of the lowest bits of the current position (number
|
||||
* of bytes from the beginning of the uncompressed data) in the
|
||||
* uncompressed data is taken into account when predicting the
|
||||
* bits of the next literal (a single eight-bit byte).
|
||||
*
|
||||
* \todo Example
|
||||
*/
|
||||
uint32_t literal_pos_bits;
|
||||
# define LZMA_LITERAL_POS_BITS_MIN 0
|
||||
# define LZMA_LITERAL_POS_BITS_MAX 4
|
||||
# define LZMA_LITERAL_POS_BITS_DEFAULT 0
|
||||
|
||||
/**
|
||||
* \brief Number of position bits
|
||||
*
|
||||
* How many of the lowest bits of the current position in the
|
||||
* uncompressed data is taken into account when estimating
|
||||
* probabilities of matches. A match is a sequence of bytes for
|
||||
* which a matching sequence is found from the dictionary and
|
||||
* thus can be stored as distance-length pair.
|
||||
*
|
||||
* Example: If most of the matches occur at byte positions
|
||||
* of 8 * n + 3, that is, 3, 11, 19, ... set pos_bits to 3,
|
||||
* because 2**3 == 8.
|
||||
*/
|
||||
uint32_t pos_bits;
|
||||
# define LZMA_POS_BITS_MIN 0
|
||||
# define LZMA_POS_BITS_MAX 4
|
||||
# define LZMA_POS_BITS_DEFAULT 2
|
||||
|
||||
/**
|
||||
* \brief Pointer to an initial dictionary
|
||||
*
|
||||
@@ -241,10 +228,70 @@ typedef struct {
|
||||
*/
|
||||
uint32_t preset_dictionary_size;
|
||||
|
||||
/**
|
||||
* \brief Number of literal context bits
|
||||
*
|
||||
* How many of the highest bits of the previous uncompressed
|
||||
* eight-bit byte (also known as `literal') are taken into
|
||||
* account when predicting the bits of the next literal.
|
||||
*
|
||||
* \todo Example
|
||||
*/
|
||||
uint32_t literal_context_bits;
|
||||
# define LZMA_LITERAL_CONTEXT_BITS_MIN 0
|
||||
# define LZMA_LITERAL_CONTEXT_BITS_MAX 4
|
||||
# define LZMA_LITERAL_CONTEXT_BITS_DEFAULT 3
|
||||
|
||||
/**
|
||||
* \brief Number of literal position bits
|
||||
*
|
||||
* How many of the lowest bits of the current position (number
|
||||
* of bytes from the beginning of the uncompressed data) in the
|
||||
* uncompressed data is taken into account when predicting the
|
||||
* bits of the next literal (a single eight-bit byte).
|
||||
*
|
||||
* \todo Example
|
||||
*/
|
||||
uint32_t literal_pos_bits;
|
||||
# define LZMA_LITERAL_POS_BITS_MIN 0
|
||||
# define LZMA_LITERAL_POS_BITS_MAX 4
|
||||
# define LZMA_LITERAL_POS_BITS_DEFAULT 0
|
||||
|
||||
/**
|
||||
* \brief Number of position bits
|
||||
*
|
||||
* How many of the lowest bits of the current position in the
|
||||
* uncompressed data is taken into account when estimating
|
||||
* probabilities of matches. A match is a sequence of bytes for
|
||||
* which a matching sequence is found from the dictionary and
|
||||
* thus can be stored as distance-length pair.
|
||||
*
|
||||
* Example: If most of the matches occur at byte positions
|
||||
* of 8 * n + 3, that is, 3, 11, 19, ... set pos_bits to 3,
|
||||
* because 2**3 == 8.
|
||||
*/
|
||||
uint32_t pos_bits;
|
||||
# define LZMA_POS_BITS_MIN 0
|
||||
# define LZMA_POS_BITS_MAX 4
|
||||
# define LZMA_POS_BITS_DEFAULT 2
|
||||
|
||||
/******************************************
|
||||
* LZMA options needed only when encoding *
|
||||
******************************************/
|
||||
|
||||
/**
|
||||
* \brief Indicate if the options structure is persistent
|
||||
*
|
||||
* If this is true, the application must keep this options structure
|
||||
* available after the LZMA2 encoder has been initialized. With
|
||||
* persistent structure it is possible to change some encoder options
|
||||
* in the middle of the encoding process without resetting the encoder.
|
||||
*
|
||||
* This option is used only by LZMA2. LZMA1 ignores this and it is
|
||||
* safeto not initialize this when encoding with LZMA1.
|
||||
*/
|
||||
lzma_bool persistent;
|
||||
|
||||
/** LZMA compression mode */
|
||||
lzma_mode mode;
|
||||
|
||||
@@ -275,34 +322,35 @@ typedef struct {
|
||||
*/
|
||||
uint32_t match_finder_cycles;
|
||||
|
||||
/**
|
||||
* \brief Reserved space for possible future extensions
|
||||
*
|
||||
* You should not touch these, because the names of these variables
|
||||
* may change. These are and will never be used with the currently
|
||||
* supported options, so it is safe to leave these uninitialized.
|
||||
*/
|
||||
uint32_t reserved_int1;
|
||||
uint32_t reserved_int2;
|
||||
uint32_t reserved_int3;
|
||||
uint32_t reserved_int4;
|
||||
void *reserved_ptr1;
|
||||
void *reserved_ptr2;
|
||||
|
||||
} lzma_options_lzma;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Available LZMA encoding modes
|
||||
* \brief Maximum sum of literal_context_bits and literal_pos_bits
|
||||
*
|
||||
* Pointer to an array containing the list of available encoding modes.
|
||||
*
|
||||
* This variable is available only if LZMA encoder has been enabled.
|
||||
* literal_context_bits + literal_pos_bits <= LZMA_LITERAL_BITS_MAX
|
||||
*/
|
||||
extern const lzma_mode *const lzma_available_modes;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Available match finders
|
||||
*
|
||||
* Pointer to an array containing the list of available match finders.
|
||||
* The last element is LZMA_MF_INVALID.
|
||||
*
|
||||
* This variable is available only if LZMA encoder has been enabled.
|
||||
*/
|
||||
extern const lzma_match_finder *const lzma_available_match_finders;
|
||||
#define LZMA_LITERAL_BITS_MAX 4
|
||||
|
||||
|
||||
/**
|
||||
* \brief Table of presets for the LZMA filter
|
||||
*
|
||||
* lzma_presets[0] is the fastest and lzma_preset_lzma[8] is the slowest.
|
||||
* lzma_preset_lzma[0] is the fastest and lzma_preset_lzma[8] is the slowest.
|
||||
* These presets match the switches -1 .. -9 of the lzma command line tool
|
||||
*
|
||||
* The preset values are subject to changes between liblzma versions.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* \file lzma/memlimit.h
|
||||
* \brief Memory usage limitter
|
||||
* \brief Memory usage limiter
|
||||
*
|
||||
* \author Copyright (C) 1999-2006 Igor Pavlov
|
||||
* \author Copyright (C) 2007 Lasse Collin
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
|
||||
/**
|
||||
* \brief Opaque data type used with the memory usage limitting functions
|
||||
* \brief Opaque data type used with the memory usage limiting functions
|
||||
*/
|
||||
typedef struct lzma_memlimit_s lzma_memlimit;
|
||||
|
||||
@@ -39,7 +39,7 @@ typedef struct lzma_memlimit_s lzma_memlimit;
|
||||
* to these functions can be used in lzma_allocator structure, which makes
|
||||
* it easy to limit memory usage with liblzma.
|
||||
*
|
||||
* The memory limitter functions are not tied to limitting memory usage
|
||||
* The memory limiter functions are not tied to limiting memory usage
|
||||
* with liblzma itself. You can use them with anything you like.
|
||||
*
|
||||
* In multi-threaded applications, only one thread at once may use the same
|
||||
@@ -58,7 +58,8 @@ typedef struct lzma_memlimit_s lzma_memlimit;
|
||||
* lzma_memlimit_ can be used even if lzma_init() hasn't been
|
||||
* called.
|
||||
*/
|
||||
extern lzma_memlimit *lzma_memlimit_create(size_t limit);
|
||||
extern lzma_memlimit *lzma_memlimit_create(size_t limit)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
@@ -79,7 +80,8 @@ extern void lzma_memlimit_set(lzma_memlimit *mem, size_t limit);
|
||||
/**
|
||||
* \brief Gets the current memory usage limit
|
||||
*/
|
||||
extern size_t lzma_memlimit_get(const lzma_memlimit *mem);
|
||||
extern size_t lzma_memlimit_get(const lzma_memlimit *mem)
|
||||
lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
@@ -89,7 +91,54 @@ extern size_t lzma_memlimit_get(const lzma_memlimit *mem);
|
||||
* thus it will always be larger than the total number of
|
||||
* bytes allocated via lzma_memlimit_alloc().
|
||||
*/
|
||||
extern size_t lzma_memlimit_used(const lzma_memlimit *mem);
|
||||
extern size_t lzma_memlimit_used(const lzma_memlimit *mem)
|
||||
lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Gets the maximum amount of memory required in total
|
||||
*
|
||||
* Returns how much memory was or would have been allocated at the same time.
|
||||
* If lzma_memlimit_alloc() was requested so much memory that the limit
|
||||
* would have been exceeded or malloc() simply ran out of memory, the
|
||||
* requested amount is still included to the value returned by
|
||||
* lzma_memlimit_max(). This may be used as a hint how much bigger memory
|
||||
* limit would have been needed.
|
||||
*
|
||||
* If the clear flag is set, the internal variable holding the maximum
|
||||
* value is set to the current memory usage (the same value as returned
|
||||
* by lzma_memlimit_used()).
|
||||
*
|
||||
* \note Usually liblzma needs to allocate many chunks of memory, and
|
||||
* displaying a message like "memory usage limit reached, at
|
||||
* least 1024 bytes would have been needed" may be confusing,
|
||||
* because the next allocation could have been e.g. 8 MiB.
|
||||
*
|
||||
* \todo The description of this function is unclear.
|
||||
*/
|
||||
extern size_t lzma_memlimit_max(lzma_memlimit *mem, lzma_bool clear);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Checks if memory limit was reached at some point
|
||||
*
|
||||
* This function is useful to find out if the reason for LZMA_MEM_ERROR
|
||||
* was running out of memory or hitting the memory usage limit imposed
|
||||
* by lzma_memlimit_alloc(). If the clear argument is true, the internal
|
||||
* flag, that indicates that limit was reached, is cleared.
|
||||
*/
|
||||
extern lzma_bool lzma_memlimit_reached(lzma_memlimit *mem, lzma_bool clear);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Gets the number of allocations owned by the memory limiter
|
||||
*
|
||||
* The count does not include the helper structures; if no memory has
|
||||
* been allocated with lzma_memlimit_alloc() or all memory allocated
|
||||
* has been freed or detached, this will return zero.
|
||||
*/
|
||||
extern size_t lzma_memlimit_count(const lzma_memlimit *mem)
|
||||
lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
@@ -112,11 +161,12 @@ extern size_t lzma_memlimit_used(const lzma_memlimit *mem);
|
||||
* invalid amount of memory being allocated.
|
||||
*/
|
||||
extern void *lzma_memlimit_alloc(
|
||||
lzma_memlimit *mem, size_t nmemb, size_t size);
|
||||
lzma_memlimit *mem, size_t nmemb, size_t size)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Removes the pointer from memory limitting list
|
||||
* \brief Removes the pointer from memory limiting list
|
||||
*
|
||||
* \param mem Pointer to a lzma_memlimit structure returned
|
||||
* earlier by lzma_memry_limit_create().
|
||||
@@ -144,9 +194,9 @@ extern void lzma_memlimit_free(lzma_memlimit *mem, void *ptr);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Frees the memory allocated for and by the memory usage limitter
|
||||
* \brief Frees the memory allocated for and by the memory usage limiter
|
||||
*
|
||||
* \param mem Pointer to memory limitter
|
||||
* \param mem Pointer to memory limiter
|
||||
* \param free_allocated If this is non-zero, all the memory allocated
|
||||
* by lzma_memlimit_alloc() using *mem is also
|
||||
* freed if it hasn't already been freed with
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
/**
|
||||
* \file lzma/metadata.h
|
||||
* \brief Metadata handling
|
||||
*
|
||||
* \author Copyright (C) 1999-2006 Igor Pavlov
|
||||
* \author Copyright (C) 2007 Lasse Collin
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 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
|
||||
* Lesser General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef LZMA_H_INTERNAL
|
||||
# error Never include this file directly. Use <lzma.h> instead.
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* \brief Information stored into a Metadata Block
|
||||
*
|
||||
* This structure holds all the information that can be stored to
|
||||
* a Metadata Block.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Size of Header Metadata Block
|
||||
*/
|
||||
lzma_vli header_metadata_size;
|
||||
|
||||
/**
|
||||
* \brief Total Size of the Stream
|
||||
*/
|
||||
lzma_vli total_size;
|
||||
|
||||
/**
|
||||
* \brief Uncompressed Size of the Stream
|
||||
*/
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
/**
|
||||
* \brief Index of the Blocks stored in the Stream
|
||||
*/
|
||||
lzma_index *index;
|
||||
|
||||
/**
|
||||
* \brief Extra information
|
||||
*/
|
||||
lzma_extra *extra;
|
||||
|
||||
} lzma_metadata;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculate the encoded size of Metadata
|
||||
*
|
||||
* \return Uncompressed size of the Metadata in encoded form. This value
|
||||
* may be passed to Block encoder as Uncompressed Size when using
|
||||
* Metadata filter. On error, zero is returned.
|
||||
*/
|
||||
extern lzma_vli lzma_metadata_size(const lzma_metadata *metadata);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initializes Metadata encoder
|
||||
*
|
||||
* \param coder Pointer to a pointer to hold Metadata encoder's
|
||||
* internal state. Original value is ignored, thus
|
||||
* you don't need to initialize the pointer.
|
||||
* \param allocator Custom memory allocator; usually NULL.
|
||||
* \param metadata Pointer to Metadata to encoded
|
||||
*
|
||||
* \return - LZMA_OK: Initialization succeeded.
|
||||
* - LZMA_MEM_ERROR: Cannot allocate memory for *coder.
|
||||
*
|
||||
* The initialization function makes internal copy of the *metadata structure.
|
||||
* However, the linked lists metadata->index and metadata->extra are NOT
|
||||
* copied. Thus, the application may destroy *metadata after initialization
|
||||
* if it likes, but not Index or Extra.
|
||||
*/
|
||||
extern lzma_ret lzma_metadata_encoder(lzma_stream *strm,
|
||||
lzma_options_block *options, const lzma_metadata *metadata);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initializes Metadata decoder
|
||||
*
|
||||
* \param want_extra If this is true, Extra Records will be stored
|
||||
* to metadata->extra. If this is false, Extra
|
||||
* Records will be parsed but not stored anywhere,
|
||||
* metadata->extra will be set to NULL.
|
||||
*/
|
||||
extern lzma_ret lzma_metadata_decoder(
|
||||
lzma_stream *strm, lzma_options_block *options,
|
||||
lzma_metadata *metadata, lzma_bool want_extra);
|
||||
@@ -1,72 +0,0 @@
|
||||
/**
|
||||
* \file lzma/raw.h
|
||||
* \brief Raw encoder and decoder
|
||||
*
|
||||
* \author Copyright (C) 1999-2006 Igor Pavlov
|
||||
* \author Copyright (C) 2007 Lasse Collin
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 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
|
||||
* Lesser General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef LZMA_H_INTERNAL
|
||||
# error Never include this file directly. Use <lzma.h> instead.
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initializes raw encoder
|
||||
*
|
||||
* This function may be useful when implementing custom file formats.
|
||||
*
|
||||
* \param strm Pointer to properly prepared lzma_stream
|
||||
* \param options Array of lzma_options_filter structures.
|
||||
* The end of the array must be marked with
|
||||
* .id = LZMA_VLI_VALUE_UNKNOWN. The minimum
|
||||
* number of filters is zero; the maximum is
|
||||
* determined by available memory.
|
||||
* \param uncompressed_size
|
||||
* Size of the uncompressed data. If it is unknown,
|
||||
* use LZMA_VLI_VALUE_UNKNOWN. You need to give the
|
||||
* same value to the raw decoder to decode the data.
|
||||
* \param allow_implicit
|
||||
* If true, an implicit Copy or Subblock filter should be
|
||||
* automatically added when needed. If this is false and
|
||||
* an implicit filter would be needed, LZMA_PROG_ERROR is
|
||||
* returned.
|
||||
*
|
||||
* The `action' with lzma_code() can be LZMA_RUN, LZMA_SYNC_FLUSH (if the
|
||||
* filter chain support it), or LZMA_FINISH.
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_HEADER_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern lzma_ret lzma_raw_encoder(
|
||||
lzma_stream *strm, const lzma_options_filter *options,
|
||||
lzma_vli uncompressed_size, lzma_bool allow_implicit);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initializes raw decoder
|
||||
*
|
||||
* The initialization of raw decoder goes similarly to raw encoder.
|
||||
*
|
||||
* The `action' with lzma_code() can be LZMA_RUN or LZMA_SYNC_FLUSH.
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_HEADER_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern lzma_ret lzma_raw_decoder(
|
||||
lzma_stream *strm, const lzma_options_filter *options,
|
||||
lzma_vli uncompressed_size, lzma_bool allow_implicit);
|
||||
@@ -21,7 +21,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* Filter IDs for lzma_options_filter.id */
|
||||
/* Filter IDs for lzma_filter.id */
|
||||
|
||||
#define LZMA_FILTER_X86 LZMA_VLI_C(0x04)
|
||||
/**<
|
||||
@@ -64,6 +64,15 @@
|
||||
*
|
||||
* If options with non-default values have been specified when encoding,
|
||||
* the same options must also be specified when decoding.
|
||||
*
|
||||
* \note At the moment, none of the simple filters support
|
||||
* LZMA_SYNC_FLUSH. If LZMA_SYNC_FLUSH is specified,
|
||||
* LZMA_HEADER_ERROR will be returned. If there is need,
|
||||
* partial support for LZMA_SYNC_FLUSH can be added in future.
|
||||
* Partial means that flushing would be possible only at
|
||||
* offsets that are multiple of 2, 4, or 16 depending on
|
||||
* the filter, except x86 which cannot be made to support
|
||||
* LZMA_SYNC_FLUSH predictably.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
/**
|
||||
* \file lzma/stream.h
|
||||
* \brief .lzma Stream handling
|
||||
*
|
||||
* \author Copyright (C) 1999-2006 Igor Pavlov
|
||||
* \author Copyright (C) 2007 Lasse Collin
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 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
|
||||
* Lesser General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef LZMA_H_INTERNAL
|
||||
# error Never include this file directly. Use <lzma.h> instead.
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* \brief Options for .lzma Stream encoder
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Type of integrity Check
|
||||
*
|
||||
* The type of the integrity Check is stored into Stream Header
|
||||
* and Stream Footer. The same Check is used for all Blocks in
|
||||
* the Stream.
|
||||
*/
|
||||
lzma_check_type check;
|
||||
|
||||
/**
|
||||
* \brief Precense of CRC32 of the Block Header
|
||||
*
|
||||
* Set this to true if CRC32 of every Block Header should be
|
||||
* calculated and stored in the Block Header. This is recommended.
|
||||
*
|
||||
* This setting is stored into Stream Header and Stream Footer.
|
||||
*/
|
||||
lzma_bool has_crc32;
|
||||
|
||||
/**
|
||||
* \brief Uncompressed Size in bytes
|
||||
*
|
||||
* This is somewhat advanced feature. Most users want to set this to
|
||||
* LZMA_VLI_VALUE_UNKNOWN to indicate unknown Uncompressed Size.
|
||||
*
|
||||
* If the Uncompressed Size of the Stream being encoded is known,
|
||||
* it can be stored to the beginning of the Stream. The details
|
||||
* differ for Single-Block and Multi-Block Streams:
|
||||
* - With Single-Block Streams, the Uncompressed Size is stored to
|
||||
* the Block Header and End of Payload Marker is omitted.
|
||||
* - With Multi-Block Streams, the Uncompressed Size is stored to
|
||||
* the Header Metadata Block. The Uncompressed Size of the Blocks
|
||||
* will be unknown, because liblzma cannot predict how the
|
||||
* application is going to split the data in Blocks.
|
||||
*/
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
/**
|
||||
* \brief Alignment of the beginning of the Stream
|
||||
*
|
||||
* Certain filters handle data in bigger chunks than single bytes.
|
||||
* This affects two things:
|
||||
* - Performance: aligned memory access is usually faster.
|
||||
* - Further compression ratio in custom file formats: if you
|
||||
* encode multiple Blocks with some non-compression filter
|
||||
* such as LZMA_FILTER_POWERPC, it is a good idea to keep
|
||||
* the inter-Block alignment correct to maximize compression
|
||||
* ratio when all these Blocks are finally compressed as a
|
||||
* single step.
|
||||
*
|
||||
* Usually the Stream is stored into its own file, thus
|
||||
* the alignment is usually zero.
|
||||
*/
|
||||
uint32_t alignment;
|
||||
|
||||
/**
|
||||
* \brief Array of filters used to encode Data Blocks
|
||||
*
|
||||
* There can be at maximum of seven filters. The end of the array is
|
||||
* marked with .id = LZMA_VLI_VALUE_UNKNOWN. (That's why the array
|
||||
* has eight members.) Minimum number of filters is zero; in that
|
||||
* case, an implicit Copy filter is used.
|
||||
*/
|
||||
lzma_options_filter filters[8];
|
||||
|
||||
/**
|
||||
* \brief Array of filters used to encode Metadata Blocks
|
||||
*
|
||||
* This is like filters[] but for Metadata Blocks. If Metadata
|
||||
* Blocks are compressed, they usually are compressed with
|
||||
* settings that require only little memory to uncompress e.g.
|
||||
* LZMA with 64 KiB dictionary.
|
||||
*
|
||||
* \todo Recommend a preset.
|
||||
*
|
||||
* When liblzma sees that the Metadata Block would be very small
|
||||
* even in uncompressed form, it is not compressed no matter
|
||||
* what filter have been set here. This is to avoid possibly
|
||||
* increasing the size of the Metadata Block with bad compression,
|
||||
* and to avoid useless overhead of filters in uncompression phase.
|
||||
*/
|
||||
lzma_options_filter metadata_filters[8];
|
||||
|
||||
/**
|
||||
* \brief Extra information in the Header Metadata Block
|
||||
*/
|
||||
lzma_extra *header;
|
||||
|
||||
/**
|
||||
* \brief Extra information in the Footer Metadata Block
|
||||
*
|
||||
* It is enough to set this pointer any time before calling
|
||||
* lzma_code() with LZMA_FINISH as the second argument.
|
||||
*/
|
||||
lzma_extra *footer;
|
||||
|
||||
} lzma_options_stream;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initializes Single-Block .lzma Stream encoder
|
||||
*
|
||||
* This is the function that most developers are looking for. :-) It
|
||||
* compresses using the specified options without storing any extra
|
||||
* information.
|
||||
*
|
||||
* \todo Describe that is_metadata is ignored, maybe something else.
|
||||
*/
|
||||
extern lzma_ret lzma_stream_encoder_single(
|
||||
lzma_stream *strm, const lzma_options_stream *options);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initializes Multi-Block .lzma Stream encoder
|
||||
*
|
||||
*/
|
||||
extern lzma_ret lzma_stream_encoder_multi(
|
||||
lzma_stream *strm, const lzma_options_stream *options);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initializes decoder for .lzma Stream
|
||||
*
|
||||
* \param strm Pointer to propertily prepared lzma_stream
|
||||
* \param header Pointer to hold a pointer to Extra Records read
|
||||
* from the Header Metadata Block. Use NULL if
|
||||
* you don't care about Extra Records.
|
||||
* \param footer Same as header, but for Footer Metadata Block.
|
||||
*
|
||||
* \return - LZMA_OK: Initialization was successful.
|
||||
* - LZMA_MEM_ERROR: Cannot allocate memory.
|
||||
*
|
||||
* If header and/or footer are not NULL, *header and/or *footer will be
|
||||
* initially set to NULL.
|
||||
*
|
||||
* The application can detect that Header Metadata Block has been completely
|
||||
* parsed when the decoder procudes some output the first time. If *header
|
||||
* is still NULL, there was no Extra field in the Header Metadata Block (or
|
||||
* the whole Header Metadata Block wasn't present at all).
|
||||
*
|
||||
* The application can detect that Footer Metadata Block has been parsed
|
||||
* completely when lzma_code() returns LZMA_STREAM_END. If *footer is still
|
||||
* NULL, there was no Extra field in the Footer Metadata Block.
|
||||
*
|
||||
* \note If you use lzma_memory_limitter, the Extra Records will be
|
||||
* allocated with it, and thus remain in the lzma_memory_limitter
|
||||
* even after they get exported to the application via *header
|
||||
* and *footer pointers.
|
||||
*/
|
||||
extern lzma_ret lzma_stream_decoder(lzma_stream *strm,
|
||||
lzma_extra **header, lzma_extra **footer);
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* \file lzma/stream_flags.h
|
||||
* \brief .lzma Stream Header and Stream tail encoder and decoder
|
||||
* \brief .lzma Stream Header and Stream Footer encoder and decoder
|
||||
*
|
||||
* \author Copyright (C) 1999-2006 Igor Pavlov
|
||||
* \author Copyright (C) 2007 Lasse Collin
|
||||
@@ -22,121 +22,118 @@
|
||||
|
||||
|
||||
/**
|
||||
* \brief Size of Stream Header
|
||||
* \brief Size of Stream Header and Stream Footer
|
||||
*
|
||||
* Magic Bytes (6) + Stream Flags (1) + CRC32 (4)
|
||||
* Stream Header and Stream Footer have the same size and they are not
|
||||
* going to change even if a newer version of the .lzma file format is
|
||||
* developed in future.
|
||||
*/
|
||||
#define LZMA_STREAM_HEADER_SIZE (6 + 1 + 4)
|
||||
#define LZMA_STREAM_HEADER_SIZE 12
|
||||
|
||||
|
||||
/**
|
||||
* \brief Size of Stream tail
|
||||
*
|
||||
* Because Stream Footer already has a defined meaning in the file format
|
||||
* specification, we use Stream tail to denote these two fields:
|
||||
* Stream Flags (1) + Magic Bytes (2)
|
||||
*/
|
||||
#define LZMA_STREAM_TAIL_SIZE (1 + 2)
|
||||
|
||||
|
||||
/**
|
||||
* Options for encoding and decoding Stream Header and Stream tail
|
||||
* Options for encoding and decoding Stream Header and Stream Footer
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* Backward Size must be a multiple of four bytes. In this Stream
|
||||
* format version Backward Size is the size of the Index field.
|
||||
*/
|
||||
lzma_vli backward_size;
|
||||
# define LZMA_BACKWARD_SIZE_MIN 4
|
||||
# define LZMA_BACKWARD_SIZE_MAX (LZMA_VLI_C(1) << 34)
|
||||
|
||||
/**
|
||||
* Type of the Check calculated from uncompressed data
|
||||
*/
|
||||
lzma_check_type check;
|
||||
|
||||
/**
|
||||
* True if Block Headers have the CRC32 field. Note that the CRC32
|
||||
* field is always present in the Stream Header.
|
||||
*/
|
||||
lzma_bool has_crc32;
|
||||
|
||||
/**
|
||||
* True if the Stream is a Multi-Block Stream.
|
||||
*/
|
||||
lzma_bool is_multi;
|
||||
lzma_check check;
|
||||
|
||||
} lzma_stream_flags;
|
||||
|
||||
|
||||
#define lzma_stream_flags_is_equal(a, b) \
|
||||
((a).check == (b).check \
|
||||
&& (a).has_crc32 == (b).has_crc32 \
|
||||
&& (a).is_multi == (b).is_multi)
|
||||
|
||||
|
||||
/**
|
||||
* \brief Encodes Stream Header
|
||||
* \brief Encode Stream Header
|
||||
*
|
||||
* Encoding of the Stream Header is done with a single call instead of
|
||||
* first initializing and then doing the actual work with lzma_code().
|
||||
*
|
||||
* \param out Beginning of the output buffer
|
||||
* \param out_pos out[*out_pos] is the next write position. This
|
||||
* is updated by the encoder.
|
||||
* \param out_size out[out_size] is the first byte to not write.
|
||||
* \param out Beginning of the output buffer of
|
||||
* LZMA_STREAM_HEADER_SIZE bytes.
|
||||
* \param options Stream Header options to be encoded.
|
||||
* options->index_size is ignored and doesn't
|
||||
* need to be initialized.
|
||||
*
|
||||
* \return - LZMA_OK: Encoding was successful.
|
||||
* - LZMA_PROG_ERROR: Invalid options.
|
||||
* - LZMA_BUF_ERROR: Not enough output buffer space.
|
||||
*/
|
||||
extern lzma_ret lzma_stream_header_encode(
|
||||
uint8_t *out, const lzma_stream_flags *options);
|
||||
const lzma_stream_flags *options, uint8_t *out)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Encodes Stream tail
|
||||
* \brief Encode Stream Footer
|
||||
*
|
||||
* \param out Beginning of the output buffer of
|
||||
* LZMA_STREAM_HEADER_SIZE bytes.
|
||||
* \param options Stream Footer options to be encoded.
|
||||
*
|
||||
* \return - LZMA_OK: Encoding was successful.
|
||||
* - LZMA_PROG_ERROR: Invalid options.
|
||||
*/
|
||||
extern lzma_ret lzma_stream_footer_encode(
|
||||
const lzma_stream_flags *options, uint8_t *out)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Decode Stream Header
|
||||
*
|
||||
* \param footer Pointer to a pointer that will hold the
|
||||
* allocated buffer. Caller must free it once
|
||||
* it isn't needed anymore.
|
||||
* \param footer_size Pointer to a variable that will the final size
|
||||
* of the footer buffer.
|
||||
* \param allocator lzma_allocator for custom allocator functions.
|
||||
* Set to NULL to use malloc().
|
||||
* \param options Stream Header options to be encoded.
|
||||
* \param in Beginning of the input buffer of
|
||||
* LZMA_STREAM_HEADER_SIZE bytes.
|
||||
*
|
||||
* \return - LZMA_OK: Success; *header and *header_size set.
|
||||
* - LZMA_PROG_ERROR: *options is invalid.
|
||||
* - LZMA_MEM_ERROR: Cannot allocate memory.
|
||||
* options->index_size is always set to LZMA_VLI_VALUE_UNKNOWN. This is to
|
||||
* help comparing Stream Flags from Stream Header and Stream Footer with
|
||||
* lzma_stream_flags_equal().
|
||||
*
|
||||
* \return - LZMA_OK: Decoding was successful.
|
||||
* - LZMA_FORMAT_ERROR: Magic bytes don't match, thus the given
|
||||
* buffer cannot be Stream Header.
|
||||
* - LZMA_DATA_ERROR: CRC32 doesn't match, thus the header
|
||||
* is corrupt.
|
||||
* - LZMA_HEADER_ERROR: Unsupported options are present
|
||||
* in the header.
|
||||
*/
|
||||
extern lzma_ret lzma_stream_tail_encode(
|
||||
uint8_t *out, const lzma_stream_flags *options);
|
||||
extern lzma_ret lzma_stream_header_decode(
|
||||
lzma_stream_flags *options, const uint8_t *in)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initializes Stream Header decoder
|
||||
* \brief Decode Stream Footer
|
||||
*
|
||||
* \param strm Pointer to lzma_stream used to pass input data
|
||||
* \param options Target structure for parsed results
|
||||
* \param options Stream Header options to be encoded.
|
||||
* \param in Beginning of the input buffer of
|
||||
* LZMA_STREAM_HEADER_SIZE bytes.
|
||||
*
|
||||
* \return - LZMA_OK: Successfully initialized
|
||||
* - LZMA_MEM_ERROR: Cannot allocate memory
|
||||
*
|
||||
* The actual decoding is done with lzma_code() and freed with lzma_end().
|
||||
* \return - LZMA_OK: Decoding was successful.
|
||||
* - LZMA_FORMAT_ERROR: Magic bytes don't match, thus the given
|
||||
* buffer cannot be Stream Footer.
|
||||
* - LZMA_DATA_ERROR: CRC32 doesn't match, thus the footer
|
||||
* is corrupt.
|
||||
* - LZMA_HEADER_ERROR: Unsupported options are present
|
||||
* in the footer.
|
||||
*/
|
||||
extern lzma_ret lzma_stream_header_decoder(
|
||||
lzma_stream *strm, lzma_stream_flags *options);
|
||||
extern lzma_ret lzma_stream_footer_decode(
|
||||
lzma_stream_flags *options, const uint8_t *in)
|
||||
lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initializes Stream tail decoder
|
||||
* \brief Compare two lzma_stream_flags structures
|
||||
*
|
||||
* \param strm Pointer to lzma_stream used to pass input data
|
||||
* \param options Target structure for parsed results.
|
||||
* \param decode_uncompressed_size
|
||||
* Set to true if the first field to decode is
|
||||
* Uncompressed Size. Set to false if the first
|
||||
* field to decode is Backward Size.
|
||||
* index_size values are compared only if both are not LZMA_VLI_VALUE_UNKNOWN.
|
||||
*
|
||||
* \return - LZMA_OK: Successfully initialized
|
||||
* - LZMA_MEM_ERROR: Cannot allocate memory
|
||||
*
|
||||
* The actual decoding is done with lzma_code() and freed with lzma_end().
|
||||
* \return true if both structures are considered equal; false otherwise.
|
||||
*/
|
||||
extern lzma_ret lzma_stream_tail_decoder(
|
||||
lzma_stream *strm, lzma_stream_flags *options);
|
||||
extern lzma_bool lzma_stream_flags_equal(
|
||||
const lzma_stream_flags *a, const lzma_stream_flags *b)
|
||||
lzma_attr_pure;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
/**
|
||||
* \brief Filter ID
|
||||
*
|
||||
* Filter ID of the Subblock filter. This is used as lzma_options_filter.id.
|
||||
* Filter ID of the Subblock filter. This is used as lzma_filter.id.
|
||||
*/
|
||||
#define LZMA_FILTER_SUBBLOCK LZMA_VLI_C(0x01)
|
||||
|
||||
@@ -95,9 +95,10 @@ typedef struct {
|
||||
* input_offset % alignment == output_offset % alignment
|
||||
*
|
||||
* The Subblock filter assumes that the first output byte will be
|
||||
* written to a position in the output stream that is properly aligned.
|
||||
*
|
||||
* FIXME desc
|
||||
* written to a position in the output stream that is properly
|
||||
* aligned. This requirement is automatically met when the start
|
||||
* offset of the Stream or Block is correctly told to Block or
|
||||
* Stream encoder.
|
||||
*/
|
||||
uint32_t alignment;
|
||||
# define LZMA_SUBBLOCK_ALIGNMENT_MIN 1
|
||||
@@ -161,16 +162,17 @@ typedef struct {
|
||||
*
|
||||
* When subfilter_mode is LZMA_SUBFILTER_NONE, the application may
|
||||
* put Subfilter options to subfilter_options structure, and then
|
||||
* set subfilter_mode to LZMA_SUBFILTER_SET. This implies setting
|
||||
* flush to true. No new input data will be read until the Subfilter
|
||||
* has been enabled. Once the Subfilter has been enabled, liblzma
|
||||
* will set subfilter_mode to LZMA_SUBFILTER_RUN.
|
||||
* set subfilter_mode to LZMA_SUBFILTER_SET. No new input data will
|
||||
* be read until the Subfilter has been enabled. Once the Subfilter
|
||||
* has been enabled, liblzma will set subfilter_mode to
|
||||
* LZMA_SUBFILTER_RUN.
|
||||
*
|
||||
* When subfilter_mode is LZMA_SUBFILTER_RUN, the application may
|
||||
* set subfilter_mode to LZMA_SUBFILTER_FINISH. No new input data
|
||||
* will be read until the Subfilter has been finished. Once the
|
||||
* Subfilter has been finished, liblzma will set subfilter_mode
|
||||
* to LZMA_SUBFILTER_NONE.
|
||||
* set subfilter_mode to LZMA_SUBFILTER_FINISH. All the input
|
||||
* currently available will be encoded before unsetting the
|
||||
* Subfilter. Application must not change the amount of available
|
||||
* input until the Subfilter has finished. Once the Subfilter has
|
||||
* finished, liblzma will set subfilter_mode to LZMA_SUBFILTER_NONE.
|
||||
*
|
||||
* If the intent is to have Subfilter enabled to the very end of
|
||||
* the data, it is not needed to separately disable Subfilter with
|
||||
@@ -178,6 +180,11 @@ typedef struct {
|
||||
* of lzma_code() will make the Subblock encoder to disable the
|
||||
* Subfilter once all the data has been ran through the Subfilter.
|
||||
*
|
||||
* After the first call with LZMA_SYNC_FLUSH or LZMA_FINISH, the
|
||||
* application must not change subfilter_mode until LZMA_STREAM_END.
|
||||
* Setting LZMA_SUBFILTER_SET/LZMA_SUBFILTER_FINISH and
|
||||
* LZMA_SYNC_FLUSH/LZMA_FINISH _at the same time_ is fine.
|
||||
*
|
||||
* \note This variable is ignored if allow_subfilters is false.
|
||||
*/
|
||||
lzma_subfilter_mode subfilter_mode;
|
||||
@@ -192,6 +199,6 @@ typedef struct {
|
||||
*
|
||||
* \note This variable is ignored if allow_subfilters is false.
|
||||
*/
|
||||
lzma_options_filter subfilter_options;
|
||||
lzma_filter subfilter_options;
|
||||
|
||||
} lzma_options_subblock;
|
||||
|
||||
@@ -24,36 +24,34 @@
|
||||
/**
|
||||
* \brief Compile-time version number
|
||||
*
|
||||
* The version number is of format xyyyuuus where
|
||||
* - x is the major LZMA SDK version
|
||||
* - yyy is the minor LZMA SDK version
|
||||
* - uuu is LZMA Utils version (reset to zero every time SDK version
|
||||
* is incremented)
|
||||
* The version number is of format xyyyzzzs where
|
||||
* - x = major
|
||||
* - yyy = minor
|
||||
* - zzz = revision
|
||||
* - s indicates stability: 0 = alpha, 1 = beta, 2 = stable
|
||||
*
|
||||
* See the README file for details about the version numbering.
|
||||
*
|
||||
* \note The version number of LZMA Utils (and thus liblzma)
|
||||
* has nothing to with the version number of LZMA SDK.
|
||||
*/
|
||||
#define LZMA_VERSION UINT32_C(40420010)
|
||||
#define LZMA_VERSION UINT32_C(49990050)
|
||||
|
||||
|
||||
/**
|
||||
* \brief liblzma version number as an integer
|
||||
*
|
||||
* This is the value of LZMA_VERSION macro at the compile time of liblzma.
|
||||
* Returns the value of LZMA_VERSION macro at the compile time of liblzma.
|
||||
* This allows the application to compare if it was built against the same,
|
||||
* older, or newer version of liblzma that is currently running.
|
||||
*/
|
||||
extern const uint32_t lzma_version_number;
|
||||
extern uint32_t lzma_version_number(void) lzma_attr_const;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Returns versions number of liblzma as a string
|
||||
* \brief Version number of liblzma as a string
|
||||
*
|
||||
* This function may be useful if you want to display which version of
|
||||
* libilzma your application is currently using.
|
||||
*
|
||||
* \return Returns a pointer to a statically allocated string constant,
|
||||
* which contains the version number of liblzma. The format of
|
||||
* the version string is usually (but not necessarily) x.y.z
|
||||
* e.g. "4.42.1". Alpha and beta versions contain a suffix
|
||||
* ("4.42.0alpha").
|
||||
* liblzma your application is currently using.
|
||||
*/
|
||||
extern const char *const lzma_version_string;
|
||||
extern const char *lzma_version_string(void) lzma_attr_const;
|
||||
|
||||
@@ -71,112 +71,55 @@ typedef uint64_t lzma_vli;
|
||||
((vli) <= LZMA_VLI_VALUE_MAX || (vli) == LZMA_VLI_VALUE_UNKNOWN)
|
||||
|
||||
|
||||
/**
|
||||
* \brief Sets VLI to given value with error checking
|
||||
*
|
||||
* \param dest Target variable which must have type of lzma_vli.
|
||||
* \param src New value to be stored to dest.
|
||||
* \param limit Maximum allowed value for src.
|
||||
*
|
||||
* \return False on success, true on error. If an error occurred,
|
||||
* dest is left in undefined state (i.e. it's possible that
|
||||
* it will be different in newer liblzma versions).
|
||||
*/
|
||||
#define lzma_vli_set_lim(dest, src, limit) \
|
||||
((src) > (limit) || ((dest) = (src)) > (limit))
|
||||
|
||||
/**
|
||||
* \brief
|
||||
*/
|
||||
#define lzma_vli_add_lim(dest, src, limit) \
|
||||
((src) > (limit) || ((dest) += (src)) > (limit))
|
||||
|
||||
#define lzma_vli_add2_lim(dest, src1, src2, limit) \
|
||||
(lzma_vli_add_lim(dest, src1, limit) \
|
||||
|| lzma_vli_add_lim(dest, src2, limit))
|
||||
|
||||
#define lzma_vli_add3_lim(dest, src1, src2, src3, limit) \
|
||||
(lzma_vli_add_lim(dest, src1, limit) \
|
||||
|| lzma_vli_add_lim(dest, src2, limit) \
|
||||
|| lzma_vli_add_lim(dest, src3, limit))
|
||||
|
||||
#define lzma_vli_add4_lim(dest, src1, src2, src3, src4, limit) \
|
||||
(lzma_vli_add_lim(dest, src1, limit) \
|
||||
|| lzma_vli_add_lim(dest, src2, limit) \
|
||||
|| lzma_vli_add_lim(dest, src3, limit) \
|
||||
|| lzma_vli_add_lim(dest, src4, limit))
|
||||
|
||||
#define lzma_vli_sum_lim(dest, src1, src2, limit) \
|
||||
(lzma_vli_set_lim(dest, src1, limit) \
|
||||
|| lzma_vli_add_lim(dest, src2, limit))
|
||||
|
||||
#define lzma_vli_sum3_lim(dest, src1, src2, src3, limit) \
|
||||
(lzma_vli_set_lim(dest, src1, limit) \
|
||||
|| lzma_vli_add_lim(dest, src2, limit) \
|
||||
|| lzma_vli_add_lim(dest, src3, limit))
|
||||
|
||||
#define lzma_vli_sum4_lim(dest, src1, src2, src3, src4, limit) \
|
||||
(lzma_vli_set_lim(dest, src1, limit) \
|
||||
|| lzma_vli_add_lim(dest, src2, limit) \
|
||||
|| lzma_vli_add_lim(dest, src3, limit) \
|
||||
|| lzma_vli_add_lim(dest, src4, limit))
|
||||
|
||||
#define lzma_vli_set(dest, src) lzma_vli_set_lim(dest, src, LZMA_VLI_VALUE_MAX)
|
||||
|
||||
#define lzma_vli_add(dest, src) lzma_vli_add_lim(dest, src, LZMA_VLI_VALUE_MAX)
|
||||
|
||||
#define lzma_vli_add2(dest, src1, src2) \
|
||||
lzma_vli_add2_lim(dest, src1, src2, LZMA_VLI_VALUE_MAX)
|
||||
|
||||
#define lzma_vli_add3(dest, src1, src2, src3) \
|
||||
lzma_vli_add3_lim(dest, src1, src2, src3, LZMA_VLI_VALUE_MAX)
|
||||
|
||||
#define lzma_vli_add4(dest, src1, src2, src3, src4) \
|
||||
lzma_vli_add4_lim(dest, src1, src2, src3, src4, LZMA_VLI_VALUE_MAX)
|
||||
|
||||
#define lzma_vli_sum(dest, src1, src2) \
|
||||
lzma_vli_sum_lim(dest, src1, src2, LZMA_VLI_VALUE_MAX)
|
||||
|
||||
#define lzma_vli_sum3(dest, src1, src2, src3) \
|
||||
lzma_vli_sum3_lim(dest, src1, src2, src3, LZMA_VLI_VALUE_MAX)
|
||||
|
||||
#define lzma_vli_sum4(dest, src1, src2, src3, src4) \
|
||||
lzma_vli_sum4_lim(dest, src1, src2, src3, src4, LZMA_VLI_VALUE_MAX)
|
||||
|
||||
|
||||
/**
|
||||
* \brief Encodes variable-length integer
|
||||
*
|
||||
* In the new .lzma format, most integers are encoded in variable-length
|
||||
* In the .lzma format, most integers are encoded in variable-length
|
||||
* representation. This saves space when smaller values are more likely
|
||||
* than bigger values.
|
||||
*
|
||||
* The encoding scheme encodes seven bits to every byte, using minimum
|
||||
* number of bytes required to represent the given value. In other words,
|
||||
* it puts 7-63 bits into 1-9 bytes. This implementation limits the number
|
||||
* of bits used to 63, thus num must be at maximum of INT64_MAX / 2. You
|
||||
* may use LZMA_VLI_VALUE_MAX for clarity.
|
||||
* number of bytes required to represent the given value. Encodings that use
|
||||
* non-minimum number of bytes are invalid, thus every integer has exactly
|
||||
* one encoded representation. The maximum number of bits in a VLI is 63,
|
||||
* thus the vli argument must be at maximum of UINT64_MAX / 2. You should
|
||||
* use LZMA_VLI_VALUE_MAX for clarity.
|
||||
*
|
||||
* This function has two modes: single-call and multi-call. Single-call mode
|
||||
* encodes the whole integer at once; it is an error if the output buffer is
|
||||
* too small. Multi-call mode saves the position in *vli_pos, and thus it is
|
||||
* possible to continue encoding if the buffer becomes full before the whole
|
||||
* integer has been encoded.
|
||||
*
|
||||
* \param vli Integer to be encoded
|
||||
* \param vli_pos How many bytes have already been written out. This
|
||||
* must be less than 9 before calling this function.
|
||||
* \param vli_size Minimum size that the variable-length representation
|
||||
* must take. This is useful if you want to use
|
||||
* variable-length integers as padding. Usually you want
|
||||
* to set this to zero. The maximum allowed value is 9.
|
||||
* \param vli_pos How many VLI-encoded bytes have already been written
|
||||
* out. When starting to encode a new integer, *vli_pos
|
||||
* must be set to zero. To use single-call encoding,
|
||||
* set vli_pos to NULL.
|
||||
* \param out Beginning of the output buffer
|
||||
* \param out_pos The next byte will be written to out[*out_pos].
|
||||
* \param out_size Size of the out buffer; the first byte into
|
||||
* which no data is written to is out[out_size].
|
||||
*
|
||||
* \return - LZMA_OK: So far all OK, but the integer is not
|
||||
* \return Slightly different return values are used in multi-call and
|
||||
* single-call modes.
|
||||
*
|
||||
* Single-call (vli_pos == NULL):
|
||||
* - LZMA_OK: Integer successfully encoded.
|
||||
* - LZMA_PROG_ERROR: Arguments are not sane. This can be due
|
||||
* to too little output space; single-call mode doesn't use
|
||||
* LZMA_BUF_ERROR, since the application should have checked
|
||||
* the encoded size with lzma_vli_size().
|
||||
*
|
||||
* Multi-call (vli_pos != NULL):
|
||||
* - LZMA_OK: So far all OK, but the integer is not
|
||||
* completely written out yet.
|
||||
* - LZMA_STREAM_END: Integer successfully encoded.
|
||||
* - LZMA_BUF_ERROR: No output space (*out_pos == out_size)
|
||||
* - LZMA_BUF_ERROR: No output space was provided.
|
||||
* - LZMA_PROG_ERROR: Arguments are not sane.
|
||||
*/
|
||||
extern lzma_ret lzma_vli_encode(
|
||||
lzma_vli vli, size_t *lzma_restrict vli_pos, size_t vli_size,
|
||||
lzma_vli vli, size_t *lzma_restrict vli_pos,
|
||||
uint8_t *lzma_restrict out, size_t *lzma_restrict out_pos,
|
||||
size_t out_size);
|
||||
|
||||
@@ -184,22 +127,36 @@ extern lzma_ret lzma_vli_encode(
|
||||
/**
|
||||
* \brief Decodes variable-length integer
|
||||
*
|
||||
* Like lzma_vli_encode(), this function has single-call and multi-call modes.
|
||||
*
|
||||
* \param vli Pointer to decoded integer. The decoder will
|
||||
* initialize it to zero when *vli_pos == 0, so
|
||||
* application isn't required to initialize *vli.
|
||||
* \param vli_pos How many bytes have already been decoded. When
|
||||
* starting to decode a new integer, *vli_pos must
|
||||
* be initialized to zero.
|
||||
* be initialized to zero. To use single-call decoding,
|
||||
* set this to NULL.
|
||||
* \param in Beginning of the input buffer
|
||||
* \param in_pos The next byte will be read from in[*in_pos].
|
||||
* \param in_size Size of the input buffer; the first byte that
|
||||
* won't be read is in[in_size].
|
||||
*
|
||||
* \return - LZMA_OK: So far all OK, but the integer is not
|
||||
* \return Slightly different return values are used in multi-call and
|
||||
* single-call modes.
|
||||
*
|
||||
* Single-call (vli_pos == NULL):
|
||||
* - LZMA_OK: Integer successfully decoded.
|
||||
* - LZMA_DATA_ERROR: Integer is corrupt. This includes hitting
|
||||
* the end of the input buffer before the whole integer was
|
||||
* decoded; providing no input at all will use LZMA_DATA_ERROR.
|
||||
* - LZMA_PROG_ERROR: Arguments are not sane.
|
||||
*
|
||||
* Multi-call (vli_pos != NULL):
|
||||
* - LZMA_OK: So far all OK, but the integer is not
|
||||
* completely decoded yet.
|
||||
* - LZMA_STREAM_END: Integer successfully decoded.
|
||||
* - LZMA_BUF_ERROR: No input data (*in_pos == in_size)
|
||||
* - LZMA_DATA_ERROR: Integer is longer than nine bytes.
|
||||
* - LZMA_DATA_ERROR: Integer is corrupt.
|
||||
* - LZMA_BUF_ERROR: No input was provided.
|
||||
* - LZMA_PROG_ERROR: Arguments are not sane.
|
||||
*/
|
||||
extern lzma_ret lzma_vli_decode(lzma_vli *lzma_restrict vli,
|
||||
@@ -208,37 +165,10 @@ extern lzma_ret lzma_vli_decode(lzma_vli *lzma_restrict vli,
|
||||
|
||||
|
||||
/**
|
||||
* \brief Decodes variable-length integer reading buffer backwards
|
||||
*
|
||||
* The variable-length integer encoding is designed so that it can be read
|
||||
* either from the beginning to the end, or from the end to the beginning.
|
||||
* This feature is needed to make the Stream parseable backwards;
|
||||
* specifically, to read the Backward Size field in Stream Footer.
|
||||
*
|
||||
* \param vli Pointer to variable to hold the decoded integer.
|
||||
* \param in Beginning of the input buffer
|
||||
* \param in_size Number of bytes available in the in[] buffer.
|
||||
* On successful decoding, this is updated to match
|
||||
* the number of bytes used. (in[*in_size - 1] is the
|
||||
* first byte to process. After successful decoding,
|
||||
* in[*in_size] will point to the first byte of the
|
||||
* variable-length integer.)
|
||||
*
|
||||
* \return - LZMA_OK: Decoding successful
|
||||
* - LZMA_DATA_ERROR: No valid variable-length integer was found.
|
||||
* - LZMA_BUF_ERROR: Not enough input. Note that in practice,
|
||||
* this tends to be a sign of broken input, because the
|
||||
* applications usually do give as much input to this function
|
||||
* as the applications have available.
|
||||
*/
|
||||
extern lzma_ret lzma_vli_reverse_decode(
|
||||
lzma_vli *vli, const uint8_t *in, size_t *in_size);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Gets the minimum number of bytes required to encode vli
|
||||
* \brief Gets the number of bytes required to encode vli
|
||||
*
|
||||
* \return Number of bytes on success (1-9). If vli isn't valid,
|
||||
* zero is returned.
|
||||
*/
|
||||
extern size_t lzma_vli_size(lzma_vli vli);
|
||||
extern uint32_t lzma_vli_size(lzma_vli vli)
|
||||
lzma_attr_pure;
|
||||
|
||||
@@ -14,7 +14,6 @@ libcheck_la_SOURCES = \
|
||||
check.c \
|
||||
check.h \
|
||||
check_init.c \
|
||||
check_byteswap.h \
|
||||
crc_macros.h
|
||||
libcheck_la_CPPFLAGS = \
|
||||
-I@top_srcdir@/src/liblzma/api \
|
||||
@@ -23,7 +22,7 @@ libcheck_la_CPPFLAGS = \
|
||||
if COND_CHECK_CRC32
|
||||
|
||||
if COND_ASM_X86
|
||||
libcheck_la_SOURCES += crc32_x86.s
|
||||
libcheck_la_SOURCES += crc32_x86.S
|
||||
else
|
||||
libcheck_la_SOURCES += crc32.c
|
||||
endif
|
||||
@@ -40,7 +39,7 @@ endif
|
||||
if COND_CHECK_CRC64
|
||||
|
||||
if COND_ASM_X86
|
||||
libcheck_la_SOURCES += crc64_x86.s
|
||||
libcheck_la_SOURCES += crc64_x86.S
|
||||
else
|
||||
libcheck_la_SOURCES += crc64.c
|
||||
endif
|
||||
|
||||
@@ -13,99 +13,127 @@
|
||||
|
||||
#include "check.h"
|
||||
|
||||
// See the .lzma header format specification section 2.2.2.
|
||||
LZMA_API const uint32_t lzma_check_sizes[8] = { 0, 4, 4, 8, 16, 32, 32, 64 };
|
||||
|
||||
extern LZMA_API lzma_bool
|
||||
lzma_check_is_supported(lzma_check type)
|
||||
{
|
||||
if ((unsigned)(type) > LZMA_CHECK_ID_MAX)
|
||||
return false;
|
||||
|
||||
LZMA_API const lzma_bool lzma_available_checks[LZMA_CHECK_ID_MAX + 1] = {
|
||||
true, // LZMA_CHECK_NONE
|
||||
static const lzma_bool available_checks[LZMA_CHECK_ID_MAX + 1] = {
|
||||
true, // LZMA_CHECK_NONE
|
||||
|
||||
#ifdef HAVE_CHECK_CRC32
|
||||
true,
|
||||
true,
|
||||
#else
|
||||
false,
|
||||
false,
|
||||
#endif
|
||||
|
||||
false, // Reserved
|
||||
false, // Reserved
|
||||
false, // Reserved
|
||||
|
||||
#ifdef HAVE_CHECK_CRC64
|
||||
true,
|
||||
true,
|
||||
#else
|
||||
false,
|
||||
false,
|
||||
#endif
|
||||
|
||||
false, // Reserved
|
||||
false, // Reserved
|
||||
false, // Reserved
|
||||
false, // Reserved
|
||||
false, // Reserved
|
||||
false, // Reserved
|
||||
|
||||
#ifdef HAVE_CHECK_SHA256
|
||||
true,
|
||||
true,
|
||||
#else
|
||||
false,
|
||||
false,
|
||||
#endif
|
||||
|
||||
false, // Reserved
|
||||
false, // Reserved
|
||||
};
|
||||
false, // Reserved
|
||||
false, // Reserved
|
||||
false, // Reserved
|
||||
false, // Reserved
|
||||
false, // Reserved
|
||||
};
|
||||
|
||||
return available_checks[(unsigned)(type)];
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_check_init(lzma_check *check, lzma_check_type type)
|
||||
extern LZMA_API uint32_t
|
||||
lzma_check_size(lzma_check type)
|
||||
{
|
||||
lzma_ret ret = LZMA_OK;
|
||||
if ((unsigned)(type) > LZMA_CHECK_ID_MAX)
|
||||
return UINT32_MAX;
|
||||
|
||||
// See file-format.txt section 2.1.1.2.
|
||||
static const uint8_t check_sizes[LZMA_CHECK_ID_MAX + 1] = {
|
||||
0,
|
||||
4, 4, 4,
|
||||
8, 8, 8,
|
||||
16, 16, 16,
|
||||
32, 32, 32,
|
||||
64, 64, 64
|
||||
};
|
||||
|
||||
return check_sizes[(unsigned)(type)];
|
||||
}
|
||||
|
||||
|
||||
extern void
|
||||
lzma_check_init(lzma_check_state *check, lzma_check type)
|
||||
{
|
||||
switch (type) {
|
||||
case LZMA_CHECK_NONE:
|
||||
break;
|
||||
|
||||
#ifdef HAVE_CHECK_CRC32
|
||||
case LZMA_CHECK_CRC32:
|
||||
check->crc32 = 0;
|
||||
check->state.crc32 = 0;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHECK_CRC64
|
||||
case LZMA_CHECK_CRC64:
|
||||
check->crc64 = 0;
|
||||
check->state.crc64 = 0;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHECK_SHA256
|
||||
case LZMA_CHECK_SHA256:
|
||||
lzma_sha256_init(&check->sha256);
|
||||
lzma_sha256_init(check);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
if (type <= LZMA_CHECK_ID_MAX)
|
||||
ret = LZMA_UNSUPPORTED_CHECK;
|
||||
else
|
||||
ret = LZMA_PROG_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
extern void
|
||||
lzma_check_update(lzma_check *check, lzma_check_type type,
|
||||
lzma_check_update(lzma_check_state *check, lzma_check type,
|
||||
const uint8_t *buf, size_t size)
|
||||
{
|
||||
switch (type) {
|
||||
#ifdef HAVE_CHECK_CRC32
|
||||
case LZMA_CHECK_CRC32:
|
||||
check->crc32 = lzma_crc32(buf, size, check->crc32);
|
||||
check->state.crc32 = lzma_crc32(buf, size, check->state.crc32);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHECK_CRC64
|
||||
case LZMA_CHECK_CRC64:
|
||||
check->crc64 = lzma_crc64(buf, size, check->crc64);
|
||||
check->state.crc64 = lzma_crc64(buf, size, check->state.crc64);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHECK_SHA256
|
||||
case LZMA_CHECK_SHA256:
|
||||
lzma_sha256_update(buf, size, &check->sha256);
|
||||
lzma_sha256_update(buf, size, check);
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -118,43 +146,30 @@ lzma_check_update(lzma_check *check, lzma_check_type type,
|
||||
|
||||
|
||||
extern void
|
||||
lzma_check_finish(lzma_check *check, lzma_check_type type)
|
||||
lzma_check_finish(lzma_check_state *check, lzma_check type)
|
||||
{
|
||||
#ifdef HAVE_CHECK_SHA256
|
||||
if (type == LZMA_CHECK_SHA256)
|
||||
lzma_sha256_finish(&check->sha256);
|
||||
switch (type) {
|
||||
#ifdef HAVE_CHECK_CRC32
|
||||
case LZMA_CHECK_CRC32:
|
||||
check->buffer.u32[0] = integer_le_32(check->state.crc32);
|
||||
break;
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
extern bool
|
||||
lzma_check_compare(
|
||||
lzma_check *check1, lzma_check *check2, lzma_check_type type)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
switch (type) {
|
||||
case LZMA_CHECK_NONE:
|
||||
break;
|
||||
|
||||
case LZMA_CHECK_CRC32:
|
||||
ret = check1->crc32 != check2->crc32;
|
||||
break;
|
||||
|
||||
#ifdef HAVE_CHECK_CRC64
|
||||
case LZMA_CHECK_CRC64:
|
||||
ret = check1->crc64 != check2->crc64;
|
||||
check->buffer.u64[0] = integer_le_64(check->state.crc64);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHECK_SHA256
|
||||
case LZMA_CHECK_SHA256:
|
||||
lzma_sha256_finish(check);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
// Unsupported check
|
||||
assert(type <= 7);
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file check.h
|
||||
/// \brief Prototypes for different check functions
|
||||
/// \brief Internal API to different integrity check functions
|
||||
//
|
||||
// This code has been put into the public domain.
|
||||
//
|
||||
@@ -17,28 +17,44 @@
|
||||
#include "common.h"
|
||||
|
||||
|
||||
// Index hashing needs the best possible hash function (preferably
|
||||
// a cryptographic hash) for maximum reliability.
|
||||
#if defined(HAVE_CHECK_SHA256)
|
||||
# define LZMA_CHECK_BEST LZMA_CHECK_SHA256
|
||||
#elif defined(HAVE_CHECK_CRC64)
|
||||
# define LZMA_CHECK_BEST LZMA_CHECK_CRC64
|
||||
#else
|
||||
# define LZMA_CHECK_BEST LZMA_CHECK_CRC32
|
||||
#endif
|
||||
|
||||
|
||||
/// \brief Structure to hold internal state of the check being calculated
|
||||
///
|
||||
/// \note This is not in the public API because this structure may
|
||||
/// change in future if new integrity check algorithms are added.
|
||||
typedef struct {
|
||||
/// Internal state
|
||||
uint32_t state[8];
|
||||
/// Buffer to hold the final result and a temporary buffer for SHA256.
|
||||
union {
|
||||
uint8_t u8[64];
|
||||
uint32_t u32[16];
|
||||
uint64_t u64[8];
|
||||
} buffer;
|
||||
|
||||
/// Temporary 8-byte aligned buffer to hold incomplete chunk.
|
||||
/// After lzma_check_finish(), the first 32 bytes will contain
|
||||
/// the final digest in big endian byte order.
|
||||
uint8_t buffer[64];
|
||||
/// Check-specific data
|
||||
union {
|
||||
uint32_t crc32;
|
||||
uint64_t crc64;
|
||||
|
||||
/// Size of the message excluding padding
|
||||
uint64_t size;
|
||||
struct {
|
||||
/// Internal state
|
||||
uint32_t state[8];
|
||||
|
||||
} lzma_sha256;
|
||||
/// Size of the message excluding padding
|
||||
uint64_t size;
|
||||
} sha256;
|
||||
} state;
|
||||
|
||||
|
||||
/// \note This is not in the public API because this structure will
|
||||
/// change in future.
|
||||
typedef union {
|
||||
uint32_t crc32;
|
||||
uint64_t crc64;
|
||||
lzma_sha256 sha256;
|
||||
} lzma_check;
|
||||
} lzma_check_state;
|
||||
|
||||
|
||||
#ifdef HAVE_SMALL
|
||||
@@ -49,7 +65,6 @@ extern const uint32_t lzma_crc32_table[8][256];
|
||||
extern const uint64_t lzma_crc64_table[4][256];
|
||||
#endif
|
||||
|
||||
// Generic
|
||||
|
||||
/// \brief Initializes *check depending on type
|
||||
///
|
||||
@@ -57,46 +72,31 @@ extern const uint64_t lzma_crc64_table[4][256];
|
||||
/// supported by the current version or build of liblzma.
|
||||
/// LZMA_PROG_ERROR if type > LZMA_CHECK_ID_MAX.
|
||||
///
|
||||
extern lzma_ret lzma_check_init(lzma_check *check, lzma_check_type type);
|
||||
extern void lzma_check_init(lzma_check_state *check, lzma_check type);
|
||||
|
||||
|
||||
/// \brief Updates *check
|
||||
///
|
||||
extern void lzma_check_update(lzma_check *check, lzma_check_type type,
|
||||
extern void lzma_check_update(lzma_check_state *check, lzma_check type,
|
||||
const uint8_t *buf, size_t size);
|
||||
|
||||
|
||||
/// \brief Finishes *check
|
||||
///
|
||||
extern void lzma_check_finish(lzma_check *check, lzma_check_type type);
|
||||
extern void lzma_check_finish(lzma_check_state *check, lzma_check type);
|
||||
|
||||
|
||||
/*
|
||||
/// \brief Compare two checks
|
||||
///
|
||||
/// \return false if the checks are identical; true if they differ.
|
||||
///
|
||||
extern bool lzma_check_compare(
|
||||
lzma_check *check1, lzma_check *check2, lzma_check_type type);
|
||||
*/
|
||||
|
||||
|
||||
// CRC32
|
||||
|
||||
extern void lzma_crc32_init(void);
|
||||
|
||||
|
||||
// CRC64
|
||||
|
||||
extern void lzma_crc64_init(void);
|
||||
|
||||
|
||||
// SHA256
|
||||
|
||||
extern void lzma_sha256_init(lzma_sha256 *sha256);
|
||||
extern void lzma_sha256_init(lzma_check_state *check);
|
||||
|
||||
extern void lzma_sha256_update(
|
||||
const uint8_t *buf, size_t size, lzma_sha256 *sha256);
|
||||
|
||||
extern void lzma_sha256_finish(lzma_sha256 *sha256);
|
||||
const uint8_t *buf, size_t size, lzma_check_state *check);
|
||||
|
||||
extern void lzma_sha256_finish(lzma_check_state *check);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,14 +13,11 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
# include "check.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
# include "check_byteswap.h"
|
||||
# include "../../common/bswap.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -11,9 +11,7 @@
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
#include "common.h"
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
# include "crc32_table_be.h"
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
/* This file has been automatically generated by crc32_tablegen.c. */
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
const uint32_t lzma_crc32_table[8][256] = {
|
||||
{
|
||||
0x00000000, 0x96300777, 0x2C610EEE, 0xBA510999,
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
/* This file has been automatically generated by crc32_tablegen.c. */
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
const uint32_t lzma_crc32_table[8][256] = {
|
||||
{
|
||||
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/// \file crc32_tablegen.c
|
||||
/// \brief Generates CRC32 crc32_table.c
|
||||
///
|
||||
/// Compiling: gcc -std=c99 -o crc32_tablegen crc32_tablegen.c crc32_init.c
|
||||
/// Compiling: gcc -std=c99 -o crc32_tablegen crc32_tablegen.c
|
||||
/// Add -DWORDS_BIGENDIAN to generate big endian table.
|
||||
//
|
||||
// This code has been put into the public domain.
|
||||
@@ -18,10 +18,7 @@
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
extern void lzma_crc32_init(void);
|
||||
|
||||
extern uint32_t lzma_crc32_table[8][256];
|
||||
#include "crc32_init.c"
|
||||
|
||||
|
||||
int
|
||||
@@ -31,7 +28,6 @@ main()
|
||||
|
||||
printf("/* This file has been automatically generated by "
|
||||
"crc32_tablegen.c. */\n\n"
|
||||
"#include <inttypes.h>\n\n"
|
||||
"const uint32_t lzma_crc32_table[8][256] = {\n\t{");
|
||||
|
||||
for (size_t s = 0; s < 8; ++s) {
|
||||
|
||||
@@ -45,7 +45,7 @@ init_table(void)
|
||||
*/
|
||||
|
||||
.text
|
||||
.global lzma_crc32
|
||||
.globl lzma_crc32
|
||||
.type lzma_crc32, @function
|
||||
|
||||
.align 16
|
||||
@@ -215,3 +215,12 @@ lzma_crc32:
|
||||
ret
|
||||
|
||||
.size lzma_crc32, .-lzma_crc32
|
||||
|
||||
/*
|
||||
* This is needed to support non-executable stack. It's ugly to
|
||||
* use __linux__ here, but I don't know a way to detect when
|
||||
* we are using GNU assembler.
|
||||
*/
|
||||
#if defined(__ELF__) && defined(__linux__)
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
@@ -13,14 +13,11 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
# include "check.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
# include "check_byteswap.h"
|
||||
# include "../../common/bswap.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -11,9 +11,7 @@
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
#include "common.h"
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
# include "crc64_table_be.h"
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
/* This file has been automatically generated by crc64_tablegen.c. */
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
const uint64_t lzma_crc64_table[4][256] = {
|
||||
{
|
||||
UINT64_C(0x0000000000000000), UINT64_C(0x6F5FA703BE4C2EB3),
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
/* This file has been automatically generated by crc64_tablegen.c. */
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
const uint64_t lzma_crc64_table[4][256] = {
|
||||
{
|
||||
UINT64_C(0x0000000000000000), UINT64_C(0xB32E4CBE03A75F6F),
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/// \file crc64_tablegen.c
|
||||
/// \brief Generates CRC64 crc64_table.c
|
||||
///
|
||||
/// Compiling: gcc -std=c99 -o crc64_tablegen crc64_tablegen.c crc64_init.c
|
||||
/// Compiling: gcc -std=c99 -o crc64_tablegen crc64_tablegen.c
|
||||
/// Add -DWORDS_BIGENDIAN to generate big endian table.
|
||||
//
|
||||
// This code has been put into the public domain.
|
||||
@@ -18,10 +18,7 @@
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
extern void lzma_crc64_init(void);
|
||||
|
||||
extern uint64_t lzma_crc64_table[4][256];
|
||||
#include "crc64_init.c"
|
||||
|
||||
|
||||
int
|
||||
@@ -31,7 +28,6 @@ main()
|
||||
|
||||
printf("/* This file has been automatically generated by "
|
||||
"crc64_tablegen.c. */\n\n"
|
||||
"#include <inttypes.h>\n\n"
|
||||
"const uint64_t lzma_crc64_table[4][256] = {\n\t{");
|
||||
|
||||
for (size_t s = 0; s < 4; ++s) {
|
||||
|
||||
@@ -38,7 +38,7 @@ init_table(void)
|
||||
*/
|
||||
|
||||
.text
|
||||
.global lzma_crc64
|
||||
.globl lzma_crc64
|
||||
.type lzma_crc64, @function
|
||||
|
||||
.align 16
|
||||
@@ -200,4 +200,13 @@ lzma_crc64:
|
||||
popl %ebx
|
||||
ret
|
||||
|
||||
.size lzma_crc32, .-lzma_crc32
|
||||
.size lzma_crc64, .-lzma_crc64
|
||||
|
||||
/*
|
||||
* This is needed to support non-executable stack. It's ugly to
|
||||
* use __linux__ here, but I don't know a way to detect when
|
||||
* we are using GNU assembler.
|
||||
*/
|
||||
#if defined(__ELF__) && defined(__linux__)
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
@@ -12,7 +12,7 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
# include "check_byteswap.h"
|
||||
# include "../../common/bswap.h"
|
||||
|
||||
# define A(x) ((x) >> 24)
|
||||
# define B(x) (((x) >> 16) & 0xFF)
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "check.h"
|
||||
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
# include "check_byteswap.h"
|
||||
# include "../../common/bswap.h"
|
||||
#endif
|
||||
|
||||
// At least on x86, GCC is able to optimize this to a rotate instruction.
|
||||
@@ -104,18 +104,18 @@ transform(uint32_t state[static 8], const uint32_t data[static 16])
|
||||
|
||||
|
||||
static void
|
||||
process(lzma_sha256 *sha256)
|
||||
process(lzma_check_state *check)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
transform(sha256->state, (uint32_t *)(sha256->buffer));
|
||||
transform(check->state.sha256.state, check->buffer.u32);
|
||||
|
||||
#else
|
||||
uint32_t data[16];
|
||||
|
||||
for (size_t i = 0; i < 16; ++i)
|
||||
data[i] = bswap_32(*((uint32_t*)(sha256->buffer) + i));
|
||||
data[i] = bswap_32(check->buffer.u32[i]);
|
||||
|
||||
transform(sha256->state, data);
|
||||
transform(check->state.sha256.state, data);
|
||||
#endif
|
||||
|
||||
return;
|
||||
@@ -123,41 +123,41 @@ process(lzma_sha256 *sha256)
|
||||
|
||||
|
||||
extern void
|
||||
lzma_sha256_init(lzma_sha256 *sha256)
|
||||
lzma_sha256_init(lzma_check_state *check)
|
||||
{
|
||||
static const uint32_t s[8] = {
|
||||
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
|
||||
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19,
|
||||
};
|
||||
|
||||
memcpy(sha256->state, s, sizeof(s));
|
||||
sha256->size = 0;
|
||||
memcpy(check->state.sha256.state, s, sizeof(s));
|
||||
check->state.sha256.size = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
extern void
|
||||
lzma_sha256_update(const uint8_t *buf, size_t size, lzma_sha256 *sha256)
|
||||
lzma_sha256_update(const uint8_t *buf, size_t size, lzma_check_state *check)
|
||||
{
|
||||
// Copy the input data into a properly aligned temporary buffer.
|
||||
// This way we can be called with arbitrarily sized buffers
|
||||
// (no need to be multiple of 64 bytes), and the code works also
|
||||
// on architectures that don't allow unaligned memory access.
|
||||
while (size > 0) {
|
||||
const size_t copy_start = sha256->size & 0x3F;
|
||||
const size_t copy_start = check->state.sha256.size & 0x3F;
|
||||
size_t copy_size = 64 - copy_start;
|
||||
if (copy_size > size)
|
||||
copy_size = size;
|
||||
|
||||
memcpy(sha256->buffer + copy_start, buf, copy_size);
|
||||
memcpy(check->buffer.u8 + copy_start, buf, copy_size);
|
||||
|
||||
buf += copy_size;
|
||||
size -= copy_size;
|
||||
sha256->size += copy_size;
|
||||
check->state.sha256.size += copy_size;
|
||||
|
||||
if ((sha256->size & 0x3F) == 0)
|
||||
process(sha256);
|
||||
if ((check->state.sha256.size & 0x3F) == 0)
|
||||
process(check);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -165,38 +165,38 @@ lzma_sha256_update(const uint8_t *buf, size_t size, lzma_sha256 *sha256)
|
||||
|
||||
|
||||
extern void
|
||||
lzma_sha256_finish(lzma_sha256 *sha256)
|
||||
lzma_sha256_finish(lzma_check_state *check)
|
||||
{
|
||||
// Add padding as described in RFC 3174 (it describes SHA-1 but
|
||||
// the same padding style is used for SHA-256 too).
|
||||
size_t pos = sha256->size & 0x3F;
|
||||
sha256->buffer[pos++] = 0x80;
|
||||
size_t pos = check->state.sha256.size & 0x3F;
|
||||
check->buffer.u8[pos++] = 0x80;
|
||||
|
||||
while (pos != 64 - 8) {
|
||||
if (pos == 64) {
|
||||
process(sha256);
|
||||
process(check);
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
sha256->buffer[pos++] = 0x00;
|
||||
check->buffer.u8[pos++] = 0x00;
|
||||
}
|
||||
|
||||
// Convert the message size from bytes to bits.
|
||||
sha256->size *= 8;
|
||||
check->state.sha256.size *= 8;
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
*(uint64_t *)(sha256->buffer + 64 - 8) = sha256->size;
|
||||
check->buffer.u64[(64 - 8) / 8] = check->state.sha256.size;
|
||||
#else
|
||||
*(uint64_t *)(sha256->buffer + 64 - 8) = bswap_64(sha256->size);
|
||||
check->buffer.u64[(64 - 8) / 8] = bswap_64(check->state.sha256.size);
|
||||
#endif
|
||||
|
||||
process(sha256);
|
||||
process(check);
|
||||
|
||||
for (size_t i = 0; i < 8; ++i)
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
((uint32_t *)(sha256->buffer))[i] = sha256->state[i];
|
||||
check->buffer.u32[i] = check->state.sha256.state[i];
|
||||
#else
|
||||
((uint32_t *)(sha256->buffer))[i] = bswap_32(sha256->state[i]);
|
||||
check->buffer.u32[i] = bswap_32(check->state.sha256.state[i]);
|
||||
#endif
|
||||
|
||||
return;
|
||||
|
||||
@@ -16,59 +16,44 @@ noinst_LTLIBRARIES = libcommon.la
|
||||
libcommon_la_CPPFLAGS = \
|
||||
-I@top_srcdir@/src/liblzma/api \
|
||||
-I@top_srcdir@/src/liblzma/check \
|
||||
-I@top_srcdir@/src/liblzma/rangecoder \
|
||||
-I@top_srcdir@/src/liblzma/lz \
|
||||
-I@top_srcdir@/src/liblzma/lzma \
|
||||
-I@top_srcdir@/src/liblzma/simple \
|
||||
-I@top_srcdir@/src/liblzma/subblock \
|
||||
-I@top_srcdir@/src/liblzma/rangecoder
|
||||
-I@top_srcdir@/src/liblzma/delta \
|
||||
-I@top_srcdir@/src/liblzma/simple
|
||||
|
||||
libcommon_la_SOURCES = \
|
||||
common.c \
|
||||
common.h \
|
||||
sysdefs.h \
|
||||
allocator.c \
|
||||
block_private.h \
|
||||
extra.c \
|
||||
features.c \
|
||||
bsr.h \
|
||||
block_util.c \
|
||||
filter_common.c \
|
||||
filter_common.h \
|
||||
index.c \
|
||||
info.c \
|
||||
index.h \
|
||||
init.c \
|
||||
memory_limitter.c \
|
||||
memory_usage.c \
|
||||
next_coder.c \
|
||||
raw_common.c \
|
||||
raw_common.h \
|
||||
code.c \
|
||||
version.c
|
||||
|
||||
if COND_FILTER_COPY
|
||||
libcommon_la_SOURCES += \
|
||||
copy_coder.c \
|
||||
copy_coder.h
|
||||
endif
|
||||
|
||||
if COND_FILTER_DELTA
|
||||
libcommon_la_SOURCES += \
|
||||
delta_coder.c \
|
||||
delta_coder.h
|
||||
endif
|
||||
memory_limiter.c \
|
||||
stream_flags_common.c \
|
||||
stream_flags_common.h \
|
||||
vli_size.c
|
||||
|
||||
if COND_MAIN_ENCODER
|
||||
libcommon_la_SOURCES += \
|
||||
alignment.c \
|
||||
auto_decoder.c \
|
||||
alone_encoder.c \
|
||||
block_encoder.c \
|
||||
block_encoder.h \
|
||||
block_header_encoder.c \
|
||||
easy.c \
|
||||
filter_encoder.c \
|
||||
filter_encoder.h \
|
||||
filter_flags_encoder.c \
|
||||
index_encoder.c \
|
||||
index_encoder.h \
|
||||
init_encoder.c \
|
||||
metadata_encoder.c \
|
||||
metadata_encoder.h \
|
||||
raw_encoder.c \
|
||||
raw_encoder.h \
|
||||
stream_common.c \
|
||||
stream_common.h \
|
||||
stream_encoder_single.c \
|
||||
stream_encoder_multi.c \
|
||||
stream_encoder.c \
|
||||
stream_encoder.h \
|
||||
stream_flags_encoder.c \
|
||||
vli_encoder.c
|
||||
endif
|
||||
@@ -77,18 +62,19 @@ if COND_MAIN_DECODER
|
||||
libcommon_la_SOURCES += \
|
||||
alone_decoder.c \
|
||||
alone_decoder.h \
|
||||
auto_decoder.c \
|
||||
block_decoder.c \
|
||||
block_decoder.h \
|
||||
block_header_decoder.c \
|
||||
filter_decoder.c \
|
||||
filter_decoder.h \
|
||||
filter_flags_decoder.c \
|
||||
index_decoder.c \
|
||||
index_hash.c \
|
||||
init_decoder.c \
|
||||
metadata_decoder.c \
|
||||
metadata_decoder.h \
|
||||
raw_decoder.c \
|
||||
raw_decoder.h \
|
||||
stream_decoder.c \
|
||||
stream_decoder.h \
|
||||
stream_flags_decoder.c \
|
||||
stream_flags_decoder.h \
|
||||
vli_decoder.c \
|
||||
vli_reverse_decoder.c
|
||||
vli_decoder.c
|
||||
endif
|
||||
|
||||
@@ -21,11 +21,10 @@
|
||||
|
||||
|
||||
extern LZMA_API uint32_t
|
||||
lzma_alignment_input(const lzma_options_filter *filters, uint32_t guess)
|
||||
lzma_alignment_input(const lzma_filter *filters, uint32_t guess)
|
||||
{
|
||||
for (size_t i = 0; filters[i].id != LZMA_VLI_VALUE_UNKNOWN; ++i) {
|
||||
switch (filters[i].id) {
|
||||
case LZMA_FILTER_COPY:
|
||||
case LZMA_FILTER_DELTA:
|
||||
// The same as the input, check the next filter.
|
||||
continue;
|
||||
@@ -67,11 +66,10 @@ lzma_alignment_input(const lzma_options_filter *filters, uint32_t guess)
|
||||
|
||||
|
||||
extern LZMA_API uint32_t
|
||||
lzma_alignment_output(const lzma_options_filter *filters, uint32_t guess)
|
||||
lzma_alignment_output(const lzma_filter *filters, uint32_t guess)
|
||||
{
|
||||
// Check if there is only an implicit Copy filter.
|
||||
if (filters[0].id == LZMA_VLI_VALUE_UNKNOWN)
|
||||
return guess;
|
||||
return UINT32_MAX;
|
||||
|
||||
// Find the last filter in the chain.
|
||||
size_t i = 0;
|
||||
@@ -80,7 +78,6 @@ lzma_alignment_output(const lzma_options_filter *filters, uint32_t guess)
|
||||
|
||||
do {
|
||||
switch (filters[i].id) {
|
||||
case LZMA_FILTER_COPY:
|
||||
case LZMA_FILTER_DELTA:
|
||||
// It's the same as the input alignment, so
|
||||
// check the next filter.
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file allocator.c
|
||||
/// \brief Allocating and freeing memory
|
||||
//
|
||||
// Copyright (C) 2007 Lasse Collin
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#undef lzma_free
|
||||
|
||||
extern void * lzma_attribute((malloc))
|
||||
lzma_alloc(size_t size, lzma_allocator *allocator)
|
||||
{
|
||||
// Some malloc() variants return NULL if called with size == 0.
|
||||
if (size == 0)
|
||||
size = 1;
|
||||
|
||||
void *ptr;
|
||||
|
||||
if (allocator != NULL && allocator->alloc != NULL)
|
||||
ptr = allocator->alloc(allocator->opaque, 1, size);
|
||||
else
|
||||
ptr = malloc(size);
|
||||
|
||||
#if !defined(NDEBUG) && defined(HAVE_MEMSET)
|
||||
// This helps to catch some stupid mistakes.
|
||||
if (ptr != NULL)
|
||||
memset(ptr, 0xFD, size);
|
||||
#endif
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
extern void
|
||||
lzma_free(void *ptr, lzma_allocator *allocator)
|
||||
{
|
||||
if (allocator != NULL && allocator->free != NULL)
|
||||
allocator->free(allocator->opaque, ptr);
|
||||
else
|
||||
free(ptr);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "alone_decoder.h"
|
||||
#include "lzma_decoder.h"
|
||||
#include "lz_decoder.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
@@ -32,9 +33,18 @@ struct lzma_coder_s {
|
||||
SEQ_CODE,
|
||||
} sequence;
|
||||
|
||||
/// Position in the header fields
|
||||
size_t pos;
|
||||
|
||||
lzma_options_alone options;
|
||||
/// Uncompressed size decoded from the header
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
/// Memory usage limit
|
||||
uint64_t memlimit;
|
||||
|
||||
/// Options decoded from the header needed to initialize
|
||||
/// the LZMA decoder
|
||||
lzma_options_lzma options;
|
||||
};
|
||||
|
||||
|
||||
@@ -50,33 +60,37 @@ alone_decode(lzma_coder *coder,
|
||||
&& (coder->sequence == SEQ_CODE || *in_pos < in_size))
|
||||
switch (coder->sequence) {
|
||||
case SEQ_PROPERTIES:
|
||||
if (lzma_lzma_decode_properties(
|
||||
&coder->options.lzma, in[*in_pos]))
|
||||
return LZMA_DATA_ERROR;
|
||||
if (lzma_lzma_lclppb_decode(&coder->options, in[*in_pos]))
|
||||
return LZMA_FORMAT_ERROR;
|
||||
|
||||
coder->sequence = SEQ_DICTIONARY_SIZE;
|
||||
++*in_pos;
|
||||
break;
|
||||
|
||||
case SEQ_DICTIONARY_SIZE:
|
||||
coder->options.lzma.dictionary_size
|
||||
coder->options.dictionary_size
|
||||
|= (size_t)(in[*in_pos]) << (coder->pos * 8);
|
||||
|
||||
if (++coder->pos == 4) {
|
||||
// A hack to ditch tons of false positives: We allow
|
||||
// only dictionary sizes that are a power of two.
|
||||
// LZMA_Alone didn't create other kinds of files,
|
||||
// although it's not impossible that files with
|
||||
// other dictionary sizes exist. Well, if someone
|
||||
// complains, this will be reconsidered.
|
||||
size_t count = 0;
|
||||
for (size_t i = 0; i < 32; ++i)
|
||||
if (coder->options.lzma.dictionary_size
|
||||
& (UINT32_C(1) << i))
|
||||
++count;
|
||||
if (coder->options.dictionary_size
|
||||
> LZMA_DICTIONARY_SIZE_MAX)
|
||||
return LZMA_FORMAT_ERROR;
|
||||
|
||||
if (count > 1)
|
||||
return LZMA_DATA_ERROR;
|
||||
// A hack to ditch tons of false positives: We allow
|
||||
// only dictionary sizes that are 2^n or 2^n + 2^(n-1).
|
||||
// LZMA_Alone created only files with 2^n, but accepts
|
||||
// any dictionary size. If someone complains, this
|
||||
// will be reconsidered.
|
||||
uint32_t d = coder->options.dictionary_size - 1;
|
||||
d |= d >> 2;
|
||||
d |= d >> 3;
|
||||
d |= d >> 4;
|
||||
d |= d >> 8;
|
||||
d |= d >> 16;
|
||||
++d;
|
||||
|
||||
if (d != coder->options.dictionary_size)
|
||||
return LZMA_FORMAT_ERROR;
|
||||
|
||||
coder->pos = 0;
|
||||
coder->sequence = SEQ_UNCOMPRESSED_SIZE;
|
||||
@@ -86,7 +100,7 @@ alone_decode(lzma_coder *coder,
|
||||
break;
|
||||
|
||||
case SEQ_UNCOMPRESSED_SIZE:
|
||||
coder->options.uncompressed_size
|
||||
coder->uncompressed_size
|
||||
|= (lzma_vli)(in[*in_pos]) << (coder->pos * 8);
|
||||
|
||||
if (++coder->pos == 8) {
|
||||
@@ -94,11 +108,10 @@ alone_decode(lzma_coder *coder,
|
||||
// if the uncompressed size is known, it must be less
|
||||
// than 256 GiB. Again, if someone complains, this
|
||||
// will be reconsidered.
|
||||
if (coder->options.uncompressed_size
|
||||
!= LZMA_VLI_VALUE_UNKNOWN
|
||||
&& coder->options.uncompressed_size
|
||||
if (coder->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN
|
||||
&& coder->uncompressed_size
|
||||
>= (LZMA_VLI_C(1) << 38))
|
||||
return LZMA_DATA_ERROR;
|
||||
return LZMA_FORMAT_ERROR;
|
||||
|
||||
coder->pos = 0;
|
||||
coder->sequence = SEQ_CODER_INIT;
|
||||
@@ -108,13 +121,24 @@ alone_decode(lzma_coder *coder,
|
||||
break;
|
||||
|
||||
case SEQ_CODER_INIT: {
|
||||
// Two is enough because there won't be implicit filters.
|
||||
// FIXME It is unfair that this doesn't add a fixed amount
|
||||
// like lzma_memusage_common() does.
|
||||
const uint64_t memusage
|
||||
= lzma_lzma_decoder_memusage(&coder->options);
|
||||
|
||||
// Use LZMA_PROG_ERROR since LZMA_Alone decoder cannot be
|
||||
// built without LZMA support.
|
||||
// FIXME TODO Make the above comment true.
|
||||
if (memusage == UINT64_MAX)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (memusage > coder->memlimit)
|
||||
return LZMA_MEMLIMIT_ERROR;
|
||||
|
||||
lzma_filter_info filters[2] = {
|
||||
{
|
||||
.init = &lzma_lzma_decoder_init,
|
||||
.options = &coder->options.lzma,
|
||||
.uncompressed_size = coder->options
|
||||
.uncompressed_size,
|
||||
.options = &coder->options,
|
||||
}, {
|
||||
.init = NULL,
|
||||
}
|
||||
@@ -125,6 +149,10 @@ alone_decode(lzma_coder *coder,
|
||||
if (ret != LZMA_OK)
|
||||
return ret;
|
||||
|
||||
// Use a hack to set the uncompressed size.
|
||||
lzma_lz_decoder_uncompressed(coder->next.coder,
|
||||
coder->uncompressed_size);
|
||||
|
||||
coder->sequence = SEQ_CODE;
|
||||
}
|
||||
|
||||
@@ -147,15 +175,18 @@ alone_decode(lzma_coder *coder,
|
||||
static void
|
||||
alone_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
{
|
||||
lzma_next_coder_end(&coder->next, allocator);
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
alone_decoder_init(lzma_next_coder *next, lzma_allocator *allocator)
|
||||
extern lzma_ret
|
||||
lzma_alone_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
uint64_t memlimit)
|
||||
{
|
||||
lzma_next_coder_init(lzma_alone_decoder_init, next, allocator);
|
||||
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
@@ -168,30 +199,21 @@ alone_decoder_init(lzma_next_coder *next, lzma_allocator *allocator)
|
||||
|
||||
next->coder->sequence = SEQ_PROPERTIES;
|
||||
next->coder->pos = 0;
|
||||
next->coder->options.lzma.dictionary_size = 0;
|
||||
next->coder->options.uncompressed_size = 0;
|
||||
next->coder->options.dictionary_size = 0;
|
||||
next->coder->uncompressed_size = 0;
|
||||
next->coder->memlimit = memlimit;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_alone_decoder_init(lzma_next_coder *next, lzma_allocator *allocator)
|
||||
{
|
||||
// We need to use _init2 because we don't pass any varadic args.
|
||||
lzma_next_coder_init2(next, allocator, alone_decoder_init,
|
||||
alone_decoder_init, allocator);
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_ret
|
||||
lzma_alone_decoder(lzma_stream *strm)
|
||||
lzma_alone_decoder(lzma_stream *strm, uint64_t memlimit)
|
||||
{
|
||||
lzma_next_strm_init2(strm, alone_decoder_init,
|
||||
alone_decoder_init, strm->allocator);
|
||||
lzma_next_strm_init(lzma_alone_decoder_init, strm, memlimit);
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = true;
|
||||
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
|
||||
strm->internal->supported_actions[LZMA_FINISH] = true;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
@@ -17,8 +17,13 @@
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_ALONE_DECODER_H
|
||||
#define LZMA_ALONE_DECODER_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
extern lzma_ret lzma_alone_decoder_init(
|
||||
lzma_next_coder *next, lzma_allocator *allocator);
|
||||
extern lzma_ret lzma_alone_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, uint64_t memlimit);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,19 +21,19 @@
|
||||
#include "lzma_encoder.h"
|
||||
|
||||
|
||||
#define ALONE_HEADER_SIZE (1 + 4 + 8)
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
lzma_next_coder next;
|
||||
|
||||
enum {
|
||||
SEQ_PROPERTIES,
|
||||
SEQ_DICTIONARY_SIZE,
|
||||
SEQ_UNCOMPRESSED_SIZE,
|
||||
SEQ_HEADER,
|
||||
SEQ_CODE,
|
||||
} sequence;
|
||||
|
||||
size_t pos;
|
||||
|
||||
lzma_options_alone options;
|
||||
size_t header_pos;
|
||||
uint8_t header[ALONE_HEADER_SIZE];
|
||||
};
|
||||
|
||||
|
||||
@@ -47,47 +47,23 @@ alone_encode(lzma_coder *coder,
|
||||
{
|
||||
while (*out_pos < out_size)
|
||||
switch (coder->sequence) {
|
||||
case SEQ_PROPERTIES:
|
||||
if (lzma_lzma_encode_properties(
|
||||
&coder->options.lzma, out + *out_pos)) {
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
case SEQ_HEADER:
|
||||
lzma_bufcpy(coder->header, &coder->header_pos,
|
||||
ALONE_HEADER_SIZE,
|
||||
out, out_pos, out_size);
|
||||
if (coder->header_pos < ALONE_HEADER_SIZE)
|
||||
return LZMA_OK;
|
||||
|
||||
coder->sequence = SEQ_DICTIONARY_SIZE;
|
||||
++*out_pos;
|
||||
coder->sequence = SEQ_CODE;
|
||||
break;
|
||||
|
||||
case SEQ_DICTIONARY_SIZE:
|
||||
out[*out_pos] = coder->options.lzma.dictionary_size
|
||||
>> (coder->pos * 8);
|
||||
|
||||
if (++coder->pos == 4) {
|
||||
coder->pos = 0;
|
||||
coder->sequence = SEQ_UNCOMPRESSED_SIZE;
|
||||
}
|
||||
|
||||
++*out_pos;
|
||||
break;
|
||||
|
||||
case SEQ_UNCOMPRESSED_SIZE:
|
||||
out[*out_pos] = coder->options.uncompressed_size
|
||||
>> (coder->pos * 8);
|
||||
|
||||
if (++coder->pos == 8) {
|
||||
coder->pos = 0;
|
||||
coder->sequence = SEQ_CODE;
|
||||
}
|
||||
|
||||
++*out_pos;
|
||||
break;
|
||||
|
||||
case SEQ_CODE: {
|
||||
case SEQ_CODE:
|
||||
return coder->next.code(coder->next.coder,
|
||||
allocator, in, in_pos, in_size,
|
||||
out, out_pos, out_size, action);
|
||||
}
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
@@ -98,7 +74,7 @@ alone_encode(lzma_coder *coder,
|
||||
static void
|
||||
alone_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
{
|
||||
lzma_next_coder_end(&coder->next, allocator);
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
}
|
||||
@@ -107,8 +83,10 @@ alone_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
// At least for now, this is not used by any internal function.
|
||||
static lzma_ret
|
||||
alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
const lzma_options_alone *options)
|
||||
const lzma_options_lzma *options)
|
||||
{
|
||||
lzma_next_coder_init(alone_encoder_init, next, allocator);
|
||||
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
@@ -119,23 +97,45 @@ alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
next->coder->next = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
// Initialize the LZMA_Alone coder variables.
|
||||
next->coder->sequence = SEQ_PROPERTIES;
|
||||
next->coder->pos = 0;
|
||||
next->coder->options = *options;
|
||||
// Basic initializations
|
||||
next->coder->sequence = SEQ_HEADER;
|
||||
next->coder->header_pos = 0;
|
||||
|
||||
// Verify uncompressed_size since the other functions assume that
|
||||
// it is valid.
|
||||
if (!lzma_vli_is_valid(next->coder->options.uncompressed_size))
|
||||
// Encode the header:
|
||||
// - Properties (1 byte)
|
||||
if (lzma_lzma_lclppb_encode(options, next->coder->header))
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// - Dictionary size (4 bytes)
|
||||
if (options->dictionary_size < LZMA_DICTIONARY_SIZE_MIN
|
||||
|| options->dictionary_size > LZMA_DICTIONARY_SIZE_MAX)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Round up to to the next 2^n or 2^n + 2^(n - 1) depending on which
|
||||
// one is the next. While the header would allow any 32-bit integer,
|
||||
// we do this to keep the decoder of liblzma accepting the resulting
|
||||
// files.
|
||||
//
|
||||
// FIXME Maybe LZMA_Alone needs some lower limit for maximum
|
||||
// dictionary size? Must check decoders from old LZMA SDK version.
|
||||
uint32_t d = options->dictionary_size - 1;
|
||||
d |= d >> 2;
|
||||
d |= d >> 3;
|
||||
d |= d >> 4;
|
||||
d |= d >> 8;
|
||||
d |= d >> 16;
|
||||
++d;
|
||||
|
||||
integer_write_32(next->coder->header + 1, d);
|
||||
|
||||
// - Uncompressed size (always unknown and using EOPM)
|
||||
memset(next->coder->header + 1 + 4, 0xFF, 8);
|
||||
|
||||
// Initialize the LZMA encoder.
|
||||
const lzma_filter_info filters[2] = {
|
||||
{
|
||||
.init = &lzma_lzma_encoder_init,
|
||||
.options = &next->coder->options.lzma,
|
||||
.uncompressed_size = next->coder->options
|
||||
.uncompressed_size,
|
||||
.options = (void *)(options),
|
||||
}, {
|
||||
.init = NULL,
|
||||
}
|
||||
@@ -156,9 +156,9 @@ lzma_alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
|
||||
|
||||
extern LZMA_API lzma_ret
|
||||
lzma_alone_encoder(lzma_stream *strm, const lzma_options_alone *options)
|
||||
lzma_alone_encoder(lzma_stream *strm, const lzma_options_lzma *options)
|
||||
{
|
||||
lzma_next_strm_init(strm, alone_encoder_init, options);
|
||||
lzma_next_strm_init(alone_encoder_init, strm, options);
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = true;
|
||||
strm->internal->supported_actions[LZMA_FINISH] = true;
|
||||
|
||||
@@ -17,16 +17,22 @@
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "common.h"
|
||||
#include "stream_decoder.h"
|
||||
#include "alone_decoder.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
/// Stream decoder or LZMA_Alone decoder
|
||||
lzma_next_coder next;
|
||||
|
||||
lzma_extra **header;
|
||||
lzma_extra **footer;
|
||||
bool initialized;
|
||||
uint64_t memlimit;
|
||||
uint32_t flags;
|
||||
|
||||
enum {
|
||||
SEQ_INIT,
|
||||
SEQ_CODE,
|
||||
SEQ_FINISH,
|
||||
} sequence;
|
||||
};
|
||||
|
||||
|
||||
@@ -36,42 +42,97 @@ auto_decode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
size_t in_size, uint8_t *restrict out,
|
||||
size_t *restrict out_pos, size_t out_size, lzma_action action)
|
||||
{
|
||||
if (!coder->initialized) {
|
||||
switch (coder->sequence) {
|
||||
case SEQ_INIT:
|
||||
if (*in_pos >= in_size)
|
||||
return LZMA_OK;
|
||||
|
||||
lzma_ret ret;
|
||||
// Update the sequence now, because we want to continue from
|
||||
// SEQ_CODE even if we return some LZMA_*_CHECK.
|
||||
coder->sequence = SEQ_CODE;
|
||||
|
||||
if (in[*in_pos] == 0xFF)
|
||||
ret = lzma_stream_decoder_init(&coder->next, allocator,
|
||||
coder->header, coder->footer);
|
||||
else
|
||||
ret = lzma_alone_decoder_init(&coder->next, allocator);
|
||||
// Detect the file format. For now this is simple, since if
|
||||
// it doesn't start with 0xFF (the first magic byte of the
|
||||
// new format), it has to be LZMA_Alone, or something that
|
||||
// we don't support at all.
|
||||
if (in[*in_pos] == 0xFF) {
|
||||
return_if_error(lzma_stream_decoder_init(
|
||||
&coder->next, allocator,
|
||||
coder->memlimit, coder->flags));
|
||||
} else {
|
||||
return_if_error(lzma_alone_decoder_init(&coder->next,
|
||||
allocator, coder->memlimit));
|
||||
|
||||
if (ret != LZMA_OK)
|
||||
// If the application wants to know about missing
|
||||
// integrity check or about the check in general, we
|
||||
// need to handle it here, because LZMA_Alone decoder
|
||||
// doesn't accept any flags.
|
||||
if (coder->flags & LZMA_TELL_NO_CHECK)
|
||||
return LZMA_NO_CHECK;
|
||||
|
||||
if (coder->flags & LZMA_TELL_ANY_CHECK)
|
||||
return LZMA_GET_CHECK;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_CODE: {
|
||||
const lzma_ret ret = coder->next.code(
|
||||
coder->next.coder, allocator,
|
||||
in, in_pos, in_size,
|
||||
out, out_pos, out_size, action);
|
||||
if (ret != LZMA_STREAM_END
|
||||
|| (coder->flags & LZMA_CONCATENATED) == 0)
|
||||
return ret;
|
||||
|
||||
coder->initialized = true;
|
||||
coder->sequence = SEQ_FINISH;
|
||||
}
|
||||
|
||||
return coder->next.code(coder->next.coder, allocator,
|
||||
in, in_pos, in_size, out, out_pos, out_size, action);
|
||||
// Fall through
|
||||
|
||||
case SEQ_FINISH:
|
||||
// When LZMA_DECODE_CONCATENATED was used and we were decoding
|
||||
// LZMA_Alone file, we need to check check that there is no
|
||||
// trailing garbage and wait for LZMA_FINISH.
|
||||
if (*in_pos < in_size)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
return action == LZMA_FINISH ? LZMA_STREAM_END : LZMA_OK;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
auto_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
{
|
||||
lzma_next_coder_end(&coder->next, allocator);
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static lzma_check
|
||||
auto_decoder_get_check(const lzma_coder *coder)
|
||||
{
|
||||
// It is LZMA_Alone if get_check is NULL.
|
||||
return coder->next.get_check == NULL ? LZMA_CHECK_NONE
|
||||
: coder->next.get_check(coder->next.coder);
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
auto_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_extra **header, lzma_extra **footer)
|
||||
uint64_t memlimit, uint32_t flags)
|
||||
{
|
||||
lzma_next_coder_init(auto_decoder_init, next, allocator);
|
||||
|
||||
if (flags & ~LZMA_SUPPORTED_FLAGS)
|
||||
return LZMA_HEADER_ERROR;
|
||||
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
@@ -79,35 +140,25 @@ auto_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
|
||||
next->code = &auto_decode;
|
||||
next->end = &auto_decoder_end;
|
||||
next->get_check = &auto_decoder_get_check;
|
||||
next->coder->next = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
next->coder->header = header;
|
||||
next->coder->footer = footer;
|
||||
next->coder->initialized = false;
|
||||
next->coder->memlimit = memlimit;
|
||||
next->coder->flags = flags;
|
||||
next->coder->sequence = SEQ_INIT;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
extern lzma_ret
|
||||
lzma_auto_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_extra **header, lzma_extra **footer)
|
||||
{
|
||||
lzma_next_coder_init(
|
||||
auto_decoder_init, next, allocator, header, footer);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
extern LZMA_API lzma_ret
|
||||
lzma_auto_decoder(lzma_stream *strm, lzma_extra **header, lzma_extra **footer)
|
||||
lzma_auto_decoder(lzma_stream *strm, uint64_t memlimit, uint32_t flags)
|
||||
{
|
||||
lzma_next_strm_init(strm, auto_decoder_init, header, footer);
|
||||
lzma_next_strm_init(auto_decoder_init, strm, memlimit, flags);
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = true;
|
||||
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
|
||||
strm->internal->supported_actions[LZMA_FINISH] = true;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
@@ -18,37 +18,23 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "block_decoder.h"
|
||||
#include "block_private.h"
|
||||
#include "raw_decoder.h"
|
||||
#include "filter_decoder.h"
|
||||
#include "check.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
enum {
|
||||
SEQ_CODE,
|
||||
SEQ_CHECK,
|
||||
SEQ_UNCOMPRESSED_SIZE,
|
||||
SEQ_BACKWARD_SIZE,
|
||||
SEQ_PADDING,
|
||||
SEQ_END,
|
||||
SEQ_CHECK,
|
||||
} sequence;
|
||||
|
||||
/// The filters in the chain; initialized with lzma_raw_decoder_init().
|
||||
lzma_next_coder next;
|
||||
|
||||
/// Decoding options; we also write Total Size, Compressed Size, and
|
||||
/// Uncompressed Size back to this structure when the encoding has
|
||||
/// been finished.
|
||||
lzma_options_block *options;
|
||||
|
||||
/// Position in variable-length integers (and in some other places).
|
||||
size_t pos;
|
||||
|
||||
/// Check of the uncompressed data
|
||||
lzma_check check;
|
||||
|
||||
/// Total Size calculated while encoding
|
||||
lzma_vli total_size;
|
||||
/// Decoding options; we also write Compressed Size and Uncompressed
|
||||
/// Size back to this structure when the encoding has been finished.
|
||||
lzma_block *options;
|
||||
|
||||
/// Compressed Size calculated while encoding
|
||||
lzma_vli compressed_size;
|
||||
@@ -56,81 +42,38 @@ struct lzma_coder_s {
|
||||
/// Uncompressed Size calculated while encoding
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
/// Maximum allowed total_size
|
||||
lzma_vli total_limit;
|
||||
/// Maximum allowed Compressed Size; this takes into account the
|
||||
/// size of the Block Header and Check fields when Compressed Size
|
||||
/// is unknown.
|
||||
lzma_vli compressed_limit;
|
||||
|
||||
/// Maximum allowed uncompressed_size
|
||||
lzma_vli uncompressed_limit;
|
||||
/// Position when reading the Check field
|
||||
size_t check_pos;
|
||||
|
||||
/// Temporary location for the Uncompressed Size and Backward Size
|
||||
/// fields in Block Footer.
|
||||
lzma_vli tmp;
|
||||
|
||||
/// Size of the Backward Size field - This is needed so that we
|
||||
/// can verify the Backward Size and still keep updating total_size.
|
||||
size_t size_of_backward_size;
|
||||
/// Check of the uncompressed data
|
||||
lzma_check_state check;
|
||||
};
|
||||
|
||||
|
||||
static lzma_ret
|
||||
update_sequence(lzma_coder *coder)
|
||||
static inline bool
|
||||
update_size(lzma_vli *size, lzma_vli add, lzma_vli limit)
|
||||
{
|
||||
switch (coder->sequence) {
|
||||
case SEQ_CODE:
|
||||
if (coder->options->check != LZMA_CHECK_NONE) {
|
||||
lzma_check_finish(&coder->check,
|
||||
coder->options->check);
|
||||
coder->sequence = SEQ_CHECK;
|
||||
break;
|
||||
}
|
||||
if (limit > LZMA_VLI_VALUE_MAX)
|
||||
limit = LZMA_VLI_VALUE_MAX;
|
||||
|
||||
// Fall through
|
||||
if (limit < *size || limit - *size < add)
|
||||
return true;
|
||||
|
||||
case SEQ_CHECK:
|
||||
if (coder->options->has_uncompressed_size_in_footer) {
|
||||
coder->sequence = SEQ_UNCOMPRESSED_SIZE;
|
||||
break;
|
||||
}
|
||||
*size += add;
|
||||
|
||||
// Fall through
|
||||
return false;
|
||||
}
|
||||
|
||||
case SEQ_UNCOMPRESSED_SIZE:
|
||||
if (coder->options->has_backward_size) {
|
||||
coder->sequence = SEQ_BACKWARD_SIZE;
|
||||
break;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_BACKWARD_SIZE:
|
||||
if (coder->options->handle_padding) {
|
||||
coder->sequence = SEQ_PADDING;
|
||||
break;
|
||||
}
|
||||
|
||||
case SEQ_PADDING:
|
||||
if (!is_size_valid(coder->total_size,
|
||||
coder->options->total_size)
|
||||
|| !is_size_valid(coder->compressed_size,
|
||||
coder->options->compressed_size)
|
||||
|| !is_size_valid(coder->uncompressed_size,
|
||||
coder->options->uncompressed_size))
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
// Copy the values into coder->options. The caller
|
||||
// may use this information to construct Index.
|
||||
coder->options->total_size = coder->total_size;
|
||||
coder->options->compressed_size = coder->compressed_size;
|
||||
coder->options->uncompressed_size = coder->uncompressed_size;
|
||||
|
||||
return LZMA_STREAM_END;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
return LZMA_OK;
|
||||
static inline bool
|
||||
is_size_valid(lzma_vli size, lzma_vli reference)
|
||||
{
|
||||
return reference == LZMA_VLI_VALUE_UNKNOWN || reference == size;
|
||||
}
|
||||
|
||||
|
||||
@@ -140,32 +83,25 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
size_t in_size, uint8_t *restrict out,
|
||||
size_t *restrict out_pos, size_t out_size, lzma_action action)
|
||||
{
|
||||
// Special case when the Block has only Block Header.
|
||||
if (coder->sequence == SEQ_END)
|
||||
return LZMA_STREAM_END;
|
||||
|
||||
// FIXME: Termination condition should work but could be cleaner.
|
||||
while (*out_pos < out_size && (*in_pos < in_size
|
||||
|| coder->sequence == SEQ_CODE))
|
||||
switch (coder->sequence) {
|
||||
case SEQ_CODE: {
|
||||
const size_t in_start = *in_pos;
|
||||
const size_t out_start = *out_pos;
|
||||
|
||||
lzma_ret ret = coder->next.code(coder->next.coder,
|
||||
const lzma_ret ret = coder->next.code(coder->next.coder,
|
||||
allocator, in, in_pos, in_size,
|
||||
out, out_pos, out_size, action);
|
||||
|
||||
const size_t in_used = *in_pos - in_start;
|
||||
const size_t out_used = *out_pos - out_start;
|
||||
|
||||
if (update_size(&coder->total_size, in_used,
|
||||
coder->total_limit)
|
||||
|| update_size(&coder->compressed_size,
|
||||
in_used,
|
||||
coder->options->compressed_size)
|
||||
// NOTE: We compare to compressed_limit here, which prevents
|
||||
// the total size of the Block growing past LZMA_VLI_VALUE_MAX.
|
||||
if (update_size(&coder->compressed_size, in_used,
|
||||
coder->compressed_limit)
|
||||
|| update_size(&coder->uncompressed_size,
|
||||
out_used, coder->uncompressed_limit))
|
||||
out_used,
|
||||
coder->options->uncompressed_size))
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
lzma_check_update(&coder->check, coder->options->check,
|
||||
@@ -174,132 +110,78 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
if (ret != LZMA_STREAM_END)
|
||||
return ret;
|
||||
|
||||
ret = update_sequence(coder);
|
||||
if (ret != LZMA_OK)
|
||||
return ret;
|
||||
|
||||
break;
|
||||
coder->sequence = SEQ_PADDING;
|
||||
}
|
||||
|
||||
case SEQ_CHECK:
|
||||
switch (coder->options->check) {
|
||||
case LZMA_CHECK_CRC32:
|
||||
if (((coder->check.crc32 >> (coder->pos * 8))
|
||||
& 0xFF) != in[*in_pos])
|
||||
return LZMA_DATA_ERROR;
|
||||
break;
|
||||
|
||||
case LZMA_CHECK_CRC64:
|
||||
if (((coder->check.crc64 >> (coder->pos * 8))
|
||||
& 0xFF) != in[*in_pos])
|
||||
return LZMA_DATA_ERROR;
|
||||
break;
|
||||
|
||||
case LZMA_CHECK_SHA256:
|
||||
if (coder->check.sha256.buffer[coder->pos]
|
||||
!= in[*in_pos])
|
||||
return LZMA_DATA_ERROR;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(coder->options->check != LZMA_CHECK_NONE);
|
||||
assert(coder->options->check <= LZMA_CHECK_ID_MAX);
|
||||
break;
|
||||
}
|
||||
|
||||
if (update_size(&coder->total_size, 1, coder->total_limit))
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
++*in_pos;
|
||||
|
||||
if (++coder->pos == lzma_check_sizes[coder->options->check]) {
|
||||
const lzma_ret ret = update_sequence(coder);
|
||||
if (ret != LZMA_OK)
|
||||
return ret;
|
||||
|
||||
coder->pos = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SEQ_UNCOMPRESSED_SIZE: {
|
||||
const size_t in_start = *in_pos;
|
||||
|
||||
lzma_ret ret = lzma_vli_decode(&coder->tmp,
|
||||
&coder->pos, in, in_pos, in_size);
|
||||
|
||||
if (update_size(&coder->total_size, *in_pos - in_start,
|
||||
coder->total_limit))
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
if (ret != LZMA_STREAM_END)
|
||||
return ret;
|
||||
|
||||
if (coder->tmp != coder->uncompressed_size)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
coder->pos = 0;
|
||||
coder->tmp = 0;
|
||||
|
||||
ret = update_sequence(coder);
|
||||
if (ret != LZMA_OK)
|
||||
return ret;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SEQ_BACKWARD_SIZE: {
|
||||
const size_t in_start = *in_pos;
|
||||
|
||||
lzma_ret ret = lzma_vli_decode(&coder->tmp,
|
||||
&coder->pos, in, in_pos, in_size);
|
||||
|
||||
const size_t in_used = *in_pos - in_start;
|
||||
|
||||
if (update_size(&coder->total_size, in_used,
|
||||
coder->total_limit))
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
coder->size_of_backward_size += in_used;
|
||||
|
||||
if (ret != LZMA_STREAM_END)
|
||||
return ret;
|
||||
|
||||
if (coder->tmp != coder->total_size
|
||||
- coder->size_of_backward_size)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
ret = update_sequence(coder);
|
||||
if (ret != LZMA_OK)
|
||||
return ret;
|
||||
|
||||
break;
|
||||
}
|
||||
// Fall through
|
||||
|
||||
case SEQ_PADDING:
|
||||
if (in[*in_pos] == 0x00) {
|
||||
if (update_size(&coder->total_size, 1,
|
||||
coder->total_limit))
|
||||
// Compressed Data is padded to a multiple of four bytes.
|
||||
while (coder->compressed_size & 3) {
|
||||
if (*in_pos >= in_size)
|
||||
return LZMA_OK;
|
||||
|
||||
if (in[(*in_pos)++] != 0x00)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
++*in_pos;
|
||||
break;
|
||||
if (update_size(&coder->compressed_size, 1,
|
||||
coder->compressed_limit))
|
||||
return LZMA_DATA_ERROR;
|
||||
}
|
||||
|
||||
return update_sequence(coder);
|
||||
// Compressed and Uncompressed Sizes are now at their final
|
||||
// values. Verify that they match the values given to us.
|
||||
if (!is_size_valid(coder->compressed_size,
|
||||
coder->options->compressed_size)
|
||||
|| !is_size_valid(coder->uncompressed_size,
|
||||
coder->options->uncompressed_size))
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
default:
|
||||
return LZMA_PROG_ERROR;
|
||||
// Copy the values into coder->options. The caller
|
||||
// may use this information to construct Index.
|
||||
coder->options->compressed_size = coder->compressed_size;
|
||||
coder->options->uncompressed_size = coder->uncompressed_size;
|
||||
|
||||
if (coder->options->check == LZMA_CHECK_NONE)
|
||||
return LZMA_STREAM_END;
|
||||
|
||||
lzma_check_finish(&coder->check, coder->options->check);
|
||||
coder->sequence = SEQ_CHECK;
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_CHECK: {
|
||||
const bool chksup = lzma_check_is_supported(
|
||||
coder->options->check);
|
||||
|
||||
while (*in_pos < in_size) {
|
||||
// coder->check.buffer[] may be uninitialized when
|
||||
// the Check ID is not supported.
|
||||
if (chksup && coder->check.buffer.u8[coder->check_pos]
|
||||
!= in[*in_pos]) {
|
||||
++*in_pos;
|
||||
return LZMA_DATA_ERROR;
|
||||
}
|
||||
|
||||
++*in_pos;
|
||||
|
||||
if (++coder->check_pos == lzma_check_size(
|
||||
coder->options->check))
|
||||
return LZMA_STREAM_END;
|
||||
}
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return LZMA_OK;
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
block_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
{
|
||||
lzma_next_coder_end(&coder->next, allocator);
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
}
|
||||
@@ -307,11 +189,21 @@ block_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
|
||||
extern lzma_ret
|
||||
lzma_block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_options_block *options)
|
||||
lzma_block *options)
|
||||
{
|
||||
// This is pretty similar to lzma_block_encoder_init().
|
||||
// See comments there.
|
||||
lzma_next_coder_init(lzma_block_decoder_init, next, allocator);
|
||||
|
||||
// While lzma_block_total_size_get() is meant to calculate the Total
|
||||
// Size, it also validates the options excluding the filters.
|
||||
if (lzma_block_total_size_get(options) == 0)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// options->check is used for array indexing so we need to know that
|
||||
// it is in the valid range.
|
||||
if ((unsigned)(options->check) > LZMA_CHECK_ID_MAX)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Allocate and initialize *next->coder if needed.
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
@@ -322,74 +214,41 @@ lzma_block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
next->coder->next = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
if (!lzma_vli_is_valid(options->total_size)
|
||||
|| !lzma_vli_is_valid(options->compressed_size)
|
||||
|| !lzma_vli_is_valid(options->uncompressed_size)
|
||||
|| !lzma_vli_is_valid(options->total_size)
|
||||
|| !lzma_vli_is_valid(options->total_limit)
|
||||
|| !lzma_vli_is_valid(options->uncompressed_limit)
|
||||
|| (options->uncompressed_size
|
||||
!= LZMA_VLI_VALUE_UNKNOWN
|
||||
&& options->uncompressed_size
|
||||
> options->uncompressed_limit)
|
||||
|| (options->total_size != LZMA_VLI_VALUE_UNKNOWN
|
||||
&& options->total_size
|
||||
> options->total_limit)
|
||||
|| (!options->has_eopm && options->uncompressed_size
|
||||
== LZMA_VLI_VALUE_UNKNOWN)
|
||||
|| options->header_size > options->total_size
|
||||
|| (options->handle_padding
|
||||
&& (options->has_uncompressed_size_in_footer
|
||||
|| options->has_backward_size)))
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
return_if_error(lzma_check_init(&next->coder->check, options->check));
|
||||
|
||||
if (!options->has_eopm && options->uncompressed_size == 0) {
|
||||
if (!is_size_valid(0, options->compressed_size))
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (options->check != LZMA_CHECK_NONE) {
|
||||
lzma_check_finish(&next->coder->check, options->check);
|
||||
next->coder->sequence = SEQ_CHECK;
|
||||
} else if (options->handle_padding) {
|
||||
next->coder->sequence = SEQ_PADDING;
|
||||
} else {
|
||||
next->coder->sequence = SEQ_END;
|
||||
}
|
||||
} else {
|
||||
next->coder->sequence = SEQ_CODE;
|
||||
}
|
||||
|
||||
return_if_error(lzma_raw_decoder_init(&next->coder->next, allocator,
|
||||
options->filters, options->has_eopm
|
||||
? LZMA_VLI_VALUE_UNKNOWN
|
||||
: options->uncompressed_size,
|
||||
true));
|
||||
|
||||
// Basic initializations
|
||||
next->coder->sequence = SEQ_CODE;
|
||||
next->coder->options = options;
|
||||
next->coder->pos = 0;
|
||||
next->coder->total_size = options->header_size;
|
||||
next->coder->compressed_size = 0;
|
||||
next->coder->uncompressed_size = 0;
|
||||
next->coder->total_limit
|
||||
= MIN(options->total_size, options->total_limit);
|
||||
next->coder->uncompressed_limit = MIN(options->uncompressed_size,
|
||||
options->uncompressed_limit);
|
||||
next->coder->tmp = 0;
|
||||
next->coder->size_of_backward_size = 0;
|
||||
|
||||
return LZMA_OK;
|
||||
// If Compressed Size is not known, we calculate the maximum allowed
|
||||
// value so that Total Size of the Block still is a valid VLI and
|
||||
// a multiple of four.
|
||||
next->coder->compressed_limit
|
||||
= options->compressed_size == LZMA_VLI_VALUE_UNKNOWN
|
||||
? (LZMA_VLI_VALUE_MAX & ~LZMA_VLI_C(3))
|
||||
- options->header_size
|
||||
- lzma_check_size(options->check)
|
||||
: options->compressed_size;
|
||||
|
||||
// Initialize the check. It's caller's problem if the Check ID is not
|
||||
// supported, and the Block decoder cannot verify the Check field.
|
||||
// Caller can test lzma_checks[options->check].
|
||||
next->coder->check_pos = 0;
|
||||
lzma_check_init(&next->coder->check, options->check);
|
||||
|
||||
// Initialize the filter chain.
|
||||
return lzma_raw_decoder_init(&next->coder->next, allocator,
|
||||
options->filters);
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_ret
|
||||
lzma_block_decoder(lzma_stream *strm, lzma_options_block *options)
|
||||
lzma_block_decoder(lzma_stream *strm, lzma_block *options)
|
||||
{
|
||||
lzma_next_strm_init(strm, lzma_block_decoder_init, options);
|
||||
lzma_next_strm_init(lzma_block_decoder_init, strm, options);
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = true;
|
||||
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
|
||||
strm->internal->supported_actions[LZMA_FINISH] = true;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
|
||||
extern lzma_ret lzma_block_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, lzma_options_block *options);
|
||||
lzma_allocator *allocator, lzma_block *options);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,11 +18,25 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "block_encoder.h"
|
||||
#include "block_private.h"
|
||||
#include "raw_encoder.h"
|
||||
#include "filter_encoder.h"
|
||||
#include "check.h"
|
||||
|
||||
|
||||
/// The maximum size of a single Block is limited by the maximum size of
|
||||
/// a Stream, which is 2^63 - 1 bytes (i.e. LZMA_VLI_VALUE_MAX). We could
|
||||
/// take into account the headers etc. to determine the exact maximum size
|
||||
/// of the Compressed Data field, but the complexity would give us nothing
|
||||
/// useful. Instead, limit the size of Compressed Data so that even with
|
||||
/// biggest possible Block Header and Check fields the total size of the
|
||||
/// Block stays as valid VLI. This way we don't produce incorrect output
|
||||
/// if someone will really try creating a Block of 8 EiB.
|
||||
///
|
||||
/// ~LZMA_VLI_C(3) is to guarantee that if we need padding at the end of
|
||||
/// the Compressed Data field, it will still stay in the proper limit.
|
||||
#define COMPRESSED_SIZE_MAX ((LZMA_VLI_VALUE_MAX - LZMA_BLOCK_HEADER_SIZE_MAX \
|
||||
- LZMA_CHECK_SIZE_MAX) & ~LZMA_VLI_C(3))
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
/// The filters in the chain; initialized with lzma_raw_decoder_init().
|
||||
lzma_next_coder next;
|
||||
@@ -30,41 +44,25 @@ struct lzma_coder_s {
|
||||
/// Encoding options; we also write Total Size, Compressed Size, and
|
||||
/// Uncompressed Size back to this structure when the encoding has
|
||||
/// been finished.
|
||||
lzma_options_block *options;
|
||||
lzma_block *options;
|
||||
|
||||
enum {
|
||||
SEQ_CODE,
|
||||
SEQ_CHECK_FINISH,
|
||||
SEQ_CHECK_COPY,
|
||||
SEQ_UNCOMPRESSED_SIZE,
|
||||
SEQ_BACKWARD_SIZE,
|
||||
SEQ_PADDING,
|
||||
SEQ_CHECK,
|
||||
} sequence;
|
||||
|
||||
/// Position in .header and .check.
|
||||
size_t pos;
|
||||
|
||||
/// Check of the uncompressed data
|
||||
lzma_check check;
|
||||
|
||||
/// Total Size calculated while encoding
|
||||
lzma_vli total_size;
|
||||
|
||||
/// Compressed Size calculated while encoding
|
||||
lzma_vli compressed_size;
|
||||
|
||||
/// Uncompressed Size calculated while encoding
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
/// Maximum allowed total_size
|
||||
lzma_vli total_limit;
|
||||
/// Position when writing out the Check field
|
||||
size_t check_pos;
|
||||
|
||||
/// Maximum allowed uncompressed_size
|
||||
lzma_vli uncompressed_limit;
|
||||
|
||||
/// Backward Size - This is a copy of total_size right before
|
||||
/// the Backward Size field.
|
||||
lzma_vli backward_size;
|
||||
/// Check of the uncompressed data
|
||||
lzma_check_state check;
|
||||
};
|
||||
|
||||
|
||||
@@ -75,26 +73,9 @@ block_encode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
size_t *restrict out_pos, size_t out_size, lzma_action action)
|
||||
{
|
||||
// Check that our amount of input stays in proper limits.
|
||||
if (coder->options->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN) {
|
||||
if (action == LZMA_FINISH) {
|
||||
if (coder->options->uncompressed_size
|
||||
- coder->uncompressed_size
|
||||
!= (lzma_vli)(in_size - *in_pos))
|
||||
return LZMA_DATA_ERROR;
|
||||
} else {
|
||||
if (coder->options->uncompressed_size
|
||||
- coder->uncompressed_size
|
||||
< (lzma_vli)(in_size - *in_pos))
|
||||
return LZMA_DATA_ERROR;
|
||||
}
|
||||
} else if (LZMA_VLI_VALUE_MAX - coder->uncompressed_size
|
||||
< (lzma_vli)(in_size - *in_pos)) {
|
||||
return LZMA_DATA_ERROR;
|
||||
}
|
||||
if (LZMA_VLI_VALUE_MAX - coder->uncompressed_size < in_size - *in_pos)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Main loop
|
||||
while (*out_pos < out_size
|
||||
&& (*in_pos < in_size || action == LZMA_FINISH))
|
||||
switch (coder->sequence) {
|
||||
case SEQ_CODE: {
|
||||
const size_t in_start = *in_pos;
|
||||
@@ -107,13 +88,11 @@ block_encode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
const size_t in_used = *in_pos - in_start;
|
||||
const size_t out_used = *out_pos - out_start;
|
||||
|
||||
if (update_size(&coder->total_size, out_used,
|
||||
coder->total_limit)
|
||||
|| update_size(&coder->compressed_size,
|
||||
out_used,
|
||||
coder->options->compressed_size))
|
||||
if (COMPRESSED_SIZE_MAX - coder->compressed_size < out_used)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
coder->compressed_size += out_used;
|
||||
|
||||
// No need to check for overflow because we have already
|
||||
// checked it at the beginning of this function.
|
||||
coder->uncompressed_size += in_used;
|
||||
@@ -121,192 +100,94 @@ block_encode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
lzma_check_update(&coder->check, coder->options->check,
|
||||
in + in_start, in_used);
|
||||
|
||||
if (ret != LZMA_STREAM_END)
|
||||
if (ret != LZMA_STREAM_END || action == LZMA_SYNC_FLUSH)
|
||||
return ret;
|
||||
|
||||
assert(*in_pos == in_size);
|
||||
assert(action == LZMA_FINISH);
|
||||
|
||||
// Compressed and Uncompressed Sizes are now at their final
|
||||
// values. Verify that they match the values give to us.
|
||||
if (!is_size_valid(coder->compressed_size,
|
||||
coder->options->compressed_size)
|
||||
|| !is_size_valid(coder->uncompressed_size,
|
||||
coder->options->uncompressed_size))
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
coder->sequence = SEQ_CHECK_FINISH;
|
||||
break;
|
||||
coder->sequence = SEQ_PADDING;
|
||||
}
|
||||
|
||||
case SEQ_CHECK_FINISH:
|
||||
if (coder->options->check == LZMA_CHECK_NONE) {
|
||||
coder->sequence = SEQ_UNCOMPRESSED_SIZE;
|
||||
break;
|
||||
}
|
||||
|
||||
lzma_check_finish(&coder->check, coder->options->check);
|
||||
coder->sequence = SEQ_CHECK_COPY;
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_CHECK_COPY:
|
||||
assert(lzma_check_sizes[coder->options->check] > 0);
|
||||
|
||||
switch (coder->options->check) {
|
||||
case LZMA_CHECK_CRC32:
|
||||
out[*out_pos] = coder->check.crc32 >> (coder->pos * 8);
|
||||
break;
|
||||
|
||||
case LZMA_CHECK_CRC64:
|
||||
out[*out_pos] = coder->check.crc64 >> (coder->pos * 8);
|
||||
break;
|
||||
|
||||
case LZMA_CHECK_SHA256:
|
||||
out[*out_pos] = coder->check.sha256.buffer[coder->pos];
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
++*out_pos;
|
||||
|
||||
if (update_size(&coder->total_size, 1, coder->total_limit))
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
if (++coder->pos == lzma_check_sizes[coder->options->check]) {
|
||||
coder->pos = 0;
|
||||
coder->sequence = SEQ_UNCOMPRESSED_SIZE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SEQ_UNCOMPRESSED_SIZE:
|
||||
if (coder->options->has_uncompressed_size_in_footer) {
|
||||
const size_t out_start = *out_pos;
|
||||
|
||||
const lzma_ret ret = lzma_vli_encode(
|
||||
coder->uncompressed_size,
|
||||
&coder->pos, 1,
|
||||
out, out_pos, out_size);
|
||||
|
||||
// Updating the size this way instead of doing in a
|
||||
// single chunk using lzma_vli_size(), because this
|
||||
// way we detect when exactly we are going out of
|
||||
// our limits.
|
||||
if (update_size(&coder->total_size,
|
||||
*out_pos - out_start,
|
||||
coder->total_limit))
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
if (ret != LZMA_STREAM_END)
|
||||
return ret;
|
||||
|
||||
coder->pos = 0;
|
||||
}
|
||||
|
||||
coder->backward_size = coder->total_size;
|
||||
coder->sequence = SEQ_BACKWARD_SIZE;
|
||||
break;
|
||||
|
||||
case SEQ_BACKWARD_SIZE:
|
||||
if (coder->options->has_backward_size) {
|
||||
const size_t out_start = *out_pos;
|
||||
|
||||
const lzma_ret ret = lzma_vli_encode(
|
||||
coder->backward_size, &coder->pos, 1,
|
||||
out, out_pos, out_size);
|
||||
|
||||
if (update_size(&coder->total_size,
|
||||
*out_pos - out_start,
|
||||
coder->total_limit))
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
if (ret != LZMA_STREAM_END)
|
||||
return ret;
|
||||
}
|
||||
|
||||
coder->sequence = SEQ_PADDING;
|
||||
break;
|
||||
|
||||
case SEQ_PADDING:
|
||||
if (coder->options->handle_padding) {
|
||||
assert(!coder->options
|
||||
->has_uncompressed_size_in_footer);
|
||||
assert(!coder->options->has_backward_size);
|
||||
assert(coder->options->total_size != LZMA_VLI_VALUE_UNKNOWN);
|
||||
// Pad Compressed Data to a multiple of four bytes.
|
||||
while (coder->compressed_size & 3) {
|
||||
if (*out_pos >= out_size)
|
||||
return LZMA_OK;
|
||||
|
||||
if (coder->total_size < coder->options->total_size) {
|
||||
out[*out_pos] = 0x00;
|
||||
++*out_pos;
|
||||
out[*out_pos] = 0x00;
|
||||
++*out_pos;
|
||||
|
||||
if (update_size(&coder->total_size, 1,
|
||||
coder->total_limit))
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
break;
|
||||
}
|
||||
// No need to use check for overflow here since we
|
||||
// have already checked in SEQ_CODE that Compressed
|
||||
// Size will stay in proper limits.
|
||||
++coder->compressed_size;
|
||||
}
|
||||
|
||||
// Now also Total Size is known. Verify it.
|
||||
if (!is_size_valid(coder->total_size,
|
||||
coder->options->total_size))
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
// Copy the values into coder->options. The caller
|
||||
// may use this information to construct Index.
|
||||
coder->options->total_size = coder->total_size;
|
||||
coder->options->compressed_size = coder->compressed_size;
|
||||
coder->options->uncompressed_size = coder->uncompressed_size;
|
||||
|
||||
return LZMA_STREAM_END;
|
||||
if (coder->options->check == LZMA_CHECK_NONE)
|
||||
return LZMA_STREAM_END;
|
||||
|
||||
default:
|
||||
return LZMA_PROG_ERROR;
|
||||
lzma_check_finish(&coder->check, coder->options->check);
|
||||
coder->sequence = SEQ_CHECK;
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_CHECK: {
|
||||
const uint32_t check_size
|
||||
= lzma_check_size(coder->options->check);
|
||||
|
||||
while (*out_pos < out_size) {
|
||||
out[*out_pos] = coder->check.buffer.u8[
|
||||
coder->check_pos];
|
||||
++*out_pos;
|
||||
|
||||
if (++coder->check_pos == check_size)
|
||||
return LZMA_STREAM_END;
|
||||
}
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return LZMA_OK;
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
block_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
{
|
||||
lzma_next_coder_end(&coder->next, allocator);
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_options_block *options)
|
||||
extern lzma_ret
|
||||
lzma_block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_block *options)
|
||||
{
|
||||
// Validate some options.
|
||||
if (options == NULL
|
||||
|| !lzma_vli_is_valid(options->total_size)
|
||||
|| !lzma_vli_is_valid(options->compressed_size)
|
||||
|| !lzma_vli_is_valid(options->uncompressed_size)
|
||||
|| !lzma_vli_is_valid(options->total_size)
|
||||
|| !lzma_vli_is_valid(options->total_limit)
|
||||
|| !lzma_vli_is_valid(options->uncompressed_limit)
|
||||
|| (options->uncompressed_size
|
||||
!= LZMA_VLI_VALUE_UNKNOWN
|
||||
&& options->uncompressed_size
|
||||
> options->uncompressed_limit)
|
||||
|| (options->total_size != LZMA_VLI_VALUE_UNKNOWN
|
||||
&& options->total_size
|
||||
> options->total_limit)
|
||||
|| (!options->has_eopm && options->uncompressed_size
|
||||
== LZMA_VLI_VALUE_UNKNOWN)
|
||||
|| (options->handle_padding && (options->total_size
|
||||
== LZMA_VLI_VALUE_UNKNOWN
|
||||
|| options->has_uncompressed_size_in_footer
|
||||
|| options->has_backward_size))
|
||||
|| options->header_size > options->total_size)
|
||||
lzma_next_coder_init(lzma_block_encoder_init, next, allocator);
|
||||
|
||||
// While lzma_block_total_size_get() is meant to calculate the Total
|
||||
// Size, it also validates the options excluding the filters.
|
||||
if (lzma_block_total_size_get(options) == 0)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// If the Check ID is not supported, we cannot calculate the check and
|
||||
// thus not create a proper Block.
|
||||
if ((unsigned)(options->check) > LZMA_CHECK_ID_MAX)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (!lzma_check_is_supported(options->check))
|
||||
return LZMA_UNSUPPORTED_CHECK;
|
||||
|
||||
// Allocate and initialize *next->coder if needed.
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
@@ -318,55 +199,26 @@ block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
next->coder->next = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
// Initialize the check.
|
||||
return_if_error(lzma_check_init(&next->coder->check, options->check));
|
||||
|
||||
// If End of Payload Marker is not used and Uncompressed Size is zero,
|
||||
// Compressed Data is empty. That is, we don't call the encoder at all.
|
||||
// We initialize it though; it allows detecting invalid options.
|
||||
if (!options->has_eopm && options->uncompressed_size == 0) {
|
||||
// Also Compressed Size must also be zero if it has been
|
||||
// given to us.
|
||||
if (!is_size_valid(options->compressed_size, 0))
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
next->coder->sequence = SEQ_CHECK_FINISH;
|
||||
} else {
|
||||
next->coder->sequence = SEQ_CODE;
|
||||
}
|
||||
|
||||
// Other initializations
|
||||
// Basic initializations
|
||||
next->coder->sequence = SEQ_CODE;
|
||||
next->coder->options = options;
|
||||
next->coder->pos = 0;
|
||||
next->coder->total_size = options->header_size;
|
||||
next->coder->compressed_size = 0;
|
||||
next->coder->uncompressed_size = 0;
|
||||
next->coder->total_limit
|
||||
= MIN(options->total_size, options->total_limit);
|
||||
next->coder->uncompressed_limit = MIN(options->uncompressed_size,
|
||||
options->uncompressed_limit);
|
||||
|
||||
// Initialize the check
|
||||
next->coder->check_pos = 0;
|
||||
lzma_check_init(&next->coder->check, options->check);
|
||||
|
||||
// Initialize the requested filters.
|
||||
return lzma_raw_encoder_init(&next->coder->next, allocator,
|
||||
options->filters, options->has_eopm
|
||||
? LZMA_VLI_VALUE_UNKNOWN
|
||||
: options->uncompressed_size,
|
||||
true);
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_options_block *options)
|
||||
{
|
||||
lzma_next_coder_init(block_encoder_init, next, allocator, options);
|
||||
options->filters);
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_ret
|
||||
lzma_block_encoder(lzma_stream *strm, lzma_options_block *options)
|
||||
lzma_block_encoder(lzma_stream *strm, lzma_block *options)
|
||||
{
|
||||
lzma_next_strm_init(strm, block_encoder_init, options);
|
||||
lzma_next_strm_init(lzma_block_encoder_init, strm, options);
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = true;
|
||||
strm->internal->supported_actions[LZMA_FINISH] = true;
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
|
||||
extern lzma_ret lzma_block_encoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, lzma_options_block *options);
|
||||
lzma_allocator *allocator, lzma_block *options);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,353 +21,111 @@
|
||||
#include "check.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
lzma_options_block *options;
|
||||
|
||||
enum {
|
||||
SEQ_FLAGS_1,
|
||||
SEQ_FLAGS_2,
|
||||
SEQ_COMPRESSED_SIZE,
|
||||
SEQ_UNCOMPRESSED_SIZE,
|
||||
SEQ_FILTER_FLAGS_INIT,
|
||||
SEQ_FILTER_FLAGS_DECODE,
|
||||
SEQ_CRC32,
|
||||
SEQ_PADDING
|
||||
} sequence;
|
||||
|
||||
/// Position in variable-length integers
|
||||
size_t pos;
|
||||
|
||||
/// CRC32 of the Block Header
|
||||
uint32_t crc32;
|
||||
|
||||
lzma_next_coder filter_flags_decoder;
|
||||
};
|
||||
|
||||
|
||||
static bool
|
||||
update_sequence(lzma_coder *coder)
|
||||
{
|
||||
switch (coder->sequence) {
|
||||
case SEQ_FLAGS_2:
|
||||
if (coder->options->compressed_size
|
||||
!= LZMA_VLI_VALUE_UNKNOWN) {
|
||||
coder->pos = 0;
|
||||
coder->sequence = SEQ_COMPRESSED_SIZE;
|
||||
break;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_COMPRESSED_SIZE:
|
||||
if (coder->options->uncompressed_size
|
||||
!= LZMA_VLI_VALUE_UNKNOWN) {
|
||||
coder->pos = 0;
|
||||
coder->sequence = SEQ_UNCOMPRESSED_SIZE;
|
||||
break;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_UNCOMPRESSED_SIZE:
|
||||
coder->pos = 0;
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_FILTER_FLAGS_DECODE:
|
||||
if (coder->options->filters[coder->pos].id
|
||||
!= LZMA_VLI_VALUE_UNKNOWN) {
|
||||
coder->sequence = SEQ_FILTER_FLAGS_INIT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (coder->options->has_crc32) {
|
||||
coder->pos = 0;
|
||||
coder->sequence = SEQ_CRC32;
|
||||
break;
|
||||
}
|
||||
|
||||
case SEQ_CRC32:
|
||||
if (coder->options->padding != 0) {
|
||||
coder->pos = 0;
|
||||
coder->sequence = SEQ_PADDING;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
block_header_decode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
size_t in_size, uint8_t *restrict out lzma_attribute((unused)),
|
||||
size_t *restrict out_pos lzma_attribute((unused)),
|
||||
size_t out_size lzma_attribute((unused)),
|
||||
lzma_action action lzma_attribute((unused)))
|
||||
{
|
||||
while (*in_pos < in_size)
|
||||
switch (coder->sequence) {
|
||||
case SEQ_FLAGS_1:
|
||||
// Check that the reserved bit is unset. Use HEADER_ERROR
|
||||
// because newer version of liblzma may support the reserved
|
||||
// bit, although it is likely that this is just a broken file.
|
||||
if (in[*in_pos] & 0x40)
|
||||
return LZMA_HEADER_ERROR;
|
||||
|
||||
// Number of filters: we prepare appropriate amount of
|
||||
// variables for variable-length integer parsing. The
|
||||
// initialization function has already reset the rest
|
||||
// of the values to LZMA_VLI_VALUE_UNKNOWN, which allows
|
||||
// us to later know how many filters there are.
|
||||
for (int i = (int)(in[*in_pos] & 0x07) - 1; i >= 0; --i)
|
||||
coder->options->filters[i].id = 0;
|
||||
|
||||
// End of Payload Marker flag
|
||||
coder->options->has_eopm = (in[*in_pos] & 0x08) != 0;
|
||||
|
||||
// Compressed Size: Prepare for variable-length integer
|
||||
// parsing if it is known.
|
||||
if (in[*in_pos] & 0x10)
|
||||
coder->options->compressed_size = 0;
|
||||
|
||||
// Uncompressed Size: the same.
|
||||
if (in[*in_pos] & 0x20)
|
||||
coder->options->uncompressed_size = 0;
|
||||
|
||||
// Is Metadata Block flag
|
||||
coder->options->is_metadata = (in[*in_pos] & 0x80) != 0;
|
||||
|
||||
// We need at least one: Uncompressed Size or EOPM.
|
||||
if (coder->options->uncompressed_size == LZMA_VLI_VALUE_UNKNOWN
|
||||
&& !coder->options->has_eopm)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
// Update header CRC32.
|
||||
coder->crc32 = lzma_crc32(in + *in_pos, 1, coder->crc32);
|
||||
|
||||
++*in_pos;
|
||||
coder->sequence = SEQ_FLAGS_2;
|
||||
break;
|
||||
|
||||
case SEQ_FLAGS_2:
|
||||
// Check that the reserved bits are unset.
|
||||
if (in[*in_pos] & 0xE0)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
// Get the size of Header Padding.
|
||||
coder->options->padding = in[*in_pos] & 0x1F;
|
||||
|
||||
coder->crc32 = lzma_crc32(in + *in_pos, 1, coder->crc32);
|
||||
|
||||
++*in_pos;
|
||||
|
||||
if (update_sequence(coder))
|
||||
return LZMA_STREAM_END;
|
||||
|
||||
break;
|
||||
|
||||
case SEQ_COMPRESSED_SIZE: {
|
||||
// Store the old input position to be used when
|
||||
// updating coder->header_crc32.
|
||||
const size_t in_start = *in_pos;
|
||||
|
||||
const lzma_ret ret = lzma_vli_decode(
|
||||
&coder->options->compressed_size,
|
||||
&coder->pos, in, in_pos, in_size);
|
||||
|
||||
const size_t in_used = *in_pos - in_start;
|
||||
|
||||
coder->options->compressed_reserve += in_used;
|
||||
assert(coder->options->compressed_reserve
|
||||
<= LZMA_VLI_BYTES_MAX);
|
||||
|
||||
coder->options->header_size += in_used;
|
||||
|
||||
coder->crc32 = lzma_crc32(in + in_start, in_used,
|
||||
coder->crc32);
|
||||
|
||||
if (ret != LZMA_STREAM_END)
|
||||
return ret;
|
||||
|
||||
if (update_sequence(coder))
|
||||
return LZMA_STREAM_END;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SEQ_UNCOMPRESSED_SIZE: {
|
||||
const size_t in_start = *in_pos;
|
||||
|
||||
const lzma_ret ret = lzma_vli_decode(
|
||||
&coder->options->uncompressed_size,
|
||||
&coder->pos, in, in_pos, in_size);
|
||||
|
||||
const size_t in_used = *in_pos - in_start;
|
||||
|
||||
coder->options->uncompressed_reserve += in_used;
|
||||
assert(coder->options->uncompressed_reserve
|
||||
<= LZMA_VLI_BYTES_MAX);
|
||||
|
||||
coder->options->header_size += in_used;
|
||||
|
||||
coder->crc32 = lzma_crc32(in + in_start, in_used,
|
||||
coder->crc32);
|
||||
|
||||
if (ret != LZMA_STREAM_END)
|
||||
return ret;
|
||||
|
||||
if (update_sequence(coder))
|
||||
return LZMA_STREAM_END;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SEQ_FILTER_FLAGS_INIT: {
|
||||
assert(coder->options->filters[coder->pos].id
|
||||
!= LZMA_VLI_VALUE_UNKNOWN);
|
||||
|
||||
const lzma_ret ret = lzma_filter_flags_decoder_init(
|
||||
&coder->filter_flags_decoder, allocator,
|
||||
&coder->options->filters[coder->pos]);
|
||||
if (ret != LZMA_OK)
|
||||
return ret;
|
||||
|
||||
coder->sequence = SEQ_FILTER_FLAGS_DECODE;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_FILTER_FLAGS_DECODE: {
|
||||
const size_t in_start = *in_pos;
|
||||
|
||||
const lzma_ret ret = coder->filter_flags_decoder.code(
|
||||
coder->filter_flags_decoder.coder,
|
||||
allocator, in, in_pos, in_size,
|
||||
NULL, NULL, 0, LZMA_RUN);
|
||||
|
||||
const size_t in_used = *in_pos - in_start;
|
||||
coder->options->header_size += in_used;
|
||||
coder->crc32 = lzma_crc32(in + in_start,
|
||||
in_used, coder->crc32);
|
||||
|
||||
if (ret != LZMA_STREAM_END)
|
||||
return ret;
|
||||
|
||||
++coder->pos;
|
||||
|
||||
if (update_sequence(coder))
|
||||
return LZMA_STREAM_END;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SEQ_CRC32:
|
||||
assert(coder->options->has_crc32);
|
||||
|
||||
if (in[*in_pos] != ((coder->crc32 >> (coder->pos * 8)) & 0xFF))
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
++*in_pos;
|
||||
++coder->pos;
|
||||
|
||||
// Check if we reached end of the CRC32 field.
|
||||
if (coder->pos == 4) {
|
||||
coder->options->header_size += 4;
|
||||
|
||||
if (update_sequence(coder))
|
||||
return LZMA_STREAM_END;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SEQ_PADDING:
|
||||
if (in[*in_pos] != 0x00)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
++*in_pos;
|
||||
++coder->options->header_size;
|
||||
++coder->pos;
|
||||
|
||||
if (coder->pos < (size_t)(coder->options->padding))
|
||||
break;
|
||||
|
||||
return LZMA_STREAM_END;
|
||||
|
||||
default:
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
block_header_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
free_properties(lzma_block *options, lzma_allocator *allocator)
|
||||
{
|
||||
lzma_next_coder_end(&coder->filter_flags_decoder, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_block_header_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, lzma_options_block *options)
|
||||
{
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->code = &block_header_decode;
|
||||
next->end = &block_header_decoder_end;
|
||||
next->coder->filter_flags_decoder = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
// Assume that Compressed Size and Uncompressed Size are unknown.
|
||||
options->compressed_size = LZMA_VLI_VALUE_UNKNOWN;
|
||||
options->uncompressed_size = LZMA_VLI_VALUE_UNKNOWN;
|
||||
|
||||
// We will calculate the sizes of these fields too so that the
|
||||
// application may rewrite the header if it wishes so.
|
||||
options->compressed_reserve = 0;
|
||||
options->uncompressed_reserve = 0;
|
||||
|
||||
// The Block Flags field is always present, so include its size here
|
||||
// and we don't need to worry about it in block_header_decode().
|
||||
options->header_size = 2;
|
||||
|
||||
// Reset filters[] to indicate empty list of filters.
|
||||
// See SEQ_FLAGS_1 in block_header_decode() for reasoning of this.
|
||||
for (size_t i = 0; i < 8; ++i) {
|
||||
// Free allocated filter options. The last array member is not
|
||||
// touched after the initialization in the beginning of
|
||||
// lzma_block_header_decode(), so we don't need to touch that here.
|
||||
for (size_t i = 0; i < LZMA_BLOCK_FILTERS_MAX; ++i) {
|
||||
lzma_free(options->filters[i].options, allocator);
|
||||
options->filters[i].id = LZMA_VLI_VALUE_UNKNOWN;
|
||||
options->filters[i].options = NULL;
|
||||
}
|
||||
|
||||
next->coder->options = options;
|
||||
next->coder->sequence = SEQ_FLAGS_1;
|
||||
next->coder->pos = 0;
|
||||
next->coder->crc32 = 0;
|
||||
|
||||
return LZMA_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_ret
|
||||
lzma_block_header_decoder(lzma_stream *strm,
|
||||
lzma_options_block *options)
|
||||
lzma_block_header_decode(lzma_block *options,
|
||||
lzma_allocator *allocator, const uint8_t *in)
|
||||
{
|
||||
lzma_next_strm_init(strm, lzma_block_header_decoder_init, options);
|
||||
// NOTE: We consider the header to be corrupt not only when the
|
||||
// CRC32 doesn't match, but also when variable-length integers
|
||||
// are invalid or over 63 bits, or if the header is too small
|
||||
// to contain the claimed information.
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = true;
|
||||
// Initialize the filter options array. This way the caller can
|
||||
// safely free() the options even if an error occurs in this function.
|
||||
for (size_t i = 0; i <= LZMA_BLOCK_FILTERS_MAX; ++i) {
|
||||
options->filters[i].id = LZMA_VLI_VALUE_UNKNOWN;
|
||||
options->filters[i].options = NULL;
|
||||
}
|
||||
|
||||
size_t in_size = options->header_size;
|
||||
|
||||
// Validate. The caller must have set options->header_size with
|
||||
// lzma_block_header_size_decode() macro, so it is a programming error
|
||||
// if these tests fail.
|
||||
if (in_size < LZMA_BLOCK_HEADER_SIZE_MIN
|
||||
|| in_size > LZMA_BLOCK_HEADER_SIZE_MAX
|
||||
|| (in_size & 3)
|
||||
|| lzma_block_header_size_decode(in[0]) != in_size)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Exclude the CRC32 field.
|
||||
in_size -= 4;
|
||||
|
||||
// Verify CRC32
|
||||
if (lzma_crc32(in, in_size, 0) != integer_read_32(in + in_size))
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
// Check for unsupported flags.
|
||||
if (in[1] & 0x3C)
|
||||
return LZMA_HEADER_ERROR;
|
||||
|
||||
// Start after the Block Header Size and Block Flags fields.
|
||||
size_t in_pos = 2;
|
||||
|
||||
// Compressed Size
|
||||
if (in[1] & 0x40) {
|
||||
return_if_error(lzma_vli_decode(&options->compressed_size,
|
||||
NULL, in, &in_pos, in_size));
|
||||
|
||||
if (options->compressed_size > LZMA_VLI_VALUE_MAX / 4 - 1)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
options->compressed_size = (options->compressed_size + 1) * 4;
|
||||
|
||||
// Check that Total Size (that is, size of
|
||||
// Block Header + Compressed Data + Check) is
|
||||
// representable as a VLI.
|
||||
if (lzma_block_total_size_get(options) == 0)
|
||||
return LZMA_DATA_ERROR;
|
||||
} else {
|
||||
options->compressed_size = LZMA_VLI_VALUE_UNKNOWN;
|
||||
}
|
||||
|
||||
// Uncompressed Size
|
||||
if (in[1] & 0x80)
|
||||
return_if_error(lzma_vli_decode(&options->uncompressed_size,
|
||||
NULL, in, &in_pos, in_size));
|
||||
else
|
||||
options->uncompressed_size = LZMA_VLI_VALUE_UNKNOWN;
|
||||
|
||||
// Filter Flags
|
||||
const size_t filter_count = (in[1] & 3) + 1;
|
||||
for (size_t i = 0; i < filter_count; ++i) {
|
||||
const lzma_ret ret = lzma_filter_flags_decode(
|
||||
&options->filters[i], allocator,
|
||||
in, &in_pos, in_size);
|
||||
if (ret != LZMA_OK) {
|
||||
free_properties(options, allocator);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
// Padding
|
||||
while (in_pos < in_size) {
|
||||
if (in[in_pos++] != 0x00) {
|
||||
free_properties(options, allocator);
|
||||
|
||||
// Possibly some new field present so use
|
||||
// LZMA_HEADER_ERROR instead of LZMA_DATA_ERROR.
|
||||
return LZMA_HEADER_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
@@ -22,190 +22,132 @@
|
||||
|
||||
|
||||
extern LZMA_API lzma_ret
|
||||
lzma_block_header_size(lzma_options_block *options)
|
||||
lzma_block_header_size(lzma_block *options)
|
||||
{
|
||||
// Block Flags take two bytes.
|
||||
size_t size = 2;
|
||||
// Block Header Size + Block Flags + CRC32.
|
||||
size_t size = 1 + 1 + 4;
|
||||
|
||||
// Compressed Size
|
||||
if (!lzma_vli_is_valid(options->compressed_size)) {
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
} else if (options->compressed_reserve != 0) {
|
||||
// Make sure that the known Compressed Size fits into the
|
||||
// reserved space. Note that lzma_vli_size() will return zero
|
||||
// if options->compressed_size is LZMA_VLI_VALUE_UNKNOWN, so
|
||||
// we don't need to handle that special case separately.
|
||||
if (options->compressed_reserve > LZMA_VLI_BYTES_MAX
|
||||
|| lzma_vli_size(options->compressed_size)
|
||||
> (size_t)(options->compressed_reserve))
|
||||
if (options->compressed_size != LZMA_VLI_VALUE_UNKNOWN) {
|
||||
if (options->compressed_size > LZMA_VLI_VALUE_MAX / 4 - 1
|
||||
|| options->compressed_size == 0
|
||||
|| (options->compressed_size & 3))
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
size += options->compressed_reserve;
|
||||
|
||||
} else if (options->compressed_size != LZMA_VLI_VALUE_UNKNOWN) {
|
||||
// Compressed Size is known. We have already checked
|
||||
// that is is a valid VLI, and since it isn't
|
||||
// LZMA_VLI_VALUE_UNKNOWN, we can be sure that
|
||||
// lzma_vli_size() will succeed.
|
||||
size += lzma_vli_size(options->compressed_size);
|
||||
size += lzma_vli_size(options->compressed_size / 4 - 1);
|
||||
}
|
||||
|
||||
// Uncompressed Size
|
||||
if (!lzma_vli_is_valid(options->uncompressed_size)) {
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
} else if (options->uncompressed_reserve != 0) {
|
||||
if (options->uncompressed_reserve > LZMA_VLI_BYTES_MAX
|
||||
|| lzma_vli_size(options->uncompressed_size)
|
||||
> (size_t)(options->uncompressed_reserve))
|
||||
if (options->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN) {
|
||||
const size_t add = lzma_vli_size(options->uncompressed_size);
|
||||
if (add == 0)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
size += options->uncompressed_reserve;
|
||||
|
||||
} else if (options->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN) {
|
||||
size += lzma_vli_size(options->uncompressed_size);
|
||||
size += add;
|
||||
}
|
||||
|
||||
// List of Filter Flags
|
||||
if (options->filters == NULL
|
||||
|| options->filters[0].id == LZMA_VLI_VALUE_UNKNOWN)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
for (size_t i = 0; options->filters[i].id != LZMA_VLI_VALUE_UNKNOWN;
|
||||
++i) {
|
||||
// Don't allow too many filters.
|
||||
if (i == 7)
|
||||
if (i == 4)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
uint32_t tmp;
|
||||
const lzma_ret ret = lzma_filter_flags_size(&tmp,
|
||||
options->filters + i);
|
||||
if (ret != LZMA_OK)
|
||||
return ret;
|
||||
uint32_t add;
|
||||
return_if_error(lzma_filter_flags_size(&add,
|
||||
options->filters + i));
|
||||
|
||||
size += tmp;
|
||||
size += add;
|
||||
}
|
||||
|
||||
// CRC32
|
||||
if (options->has_crc32)
|
||||
size += 4;
|
||||
// Pad to a multiple of four bytes.
|
||||
options->header_size = (size + 3) & ~(size_t)(3);
|
||||
|
||||
// Padding
|
||||
int32_t padding;
|
||||
if (options->padding == LZMA_BLOCK_HEADER_PADDING_AUTO) {
|
||||
const uint32_t preferred = lzma_alignment_output(
|
||||
options->filters, 1);
|
||||
const uint32_t unaligned = size + options->alignment;
|
||||
padding = (int32_t)(unaligned % preferred);
|
||||
if (padding != 0)
|
||||
padding = preferred - padding;
|
||||
} else if (options->padding >= LZMA_BLOCK_HEADER_PADDING_MIN
|
||||
&& options->padding <= LZMA_BLOCK_HEADER_PADDING_MAX) {
|
||||
padding = options->padding;
|
||||
} else {
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
// All success. Copy the calculated values to the options structure.
|
||||
options->padding = padding;
|
||||
options->header_size = size + (size_t)(padding);
|
||||
// NOTE: We don't verify that Total Size of the Block stays within
|
||||
// limits. This is because it is possible that we are called with
|
||||
// exaggerated values to reserve space for Block Header, and later
|
||||
// called again with lower, real values.
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_ret
|
||||
lzma_block_header_encode(uint8_t *out, const lzma_options_block *options)
|
||||
lzma_block_header_encode(const lzma_block *options, uint8_t *out)
|
||||
{
|
||||
// We write the Block Flags later.
|
||||
if (options->header_size < 2)
|
||||
if ((options->header_size & 3)
|
||||
|| options->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
|
||||
|| options->header_size > LZMA_BLOCK_HEADER_SIZE_MAX)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
const size_t out_size = options->header_size;
|
||||
// Indicate the size of the buffer _excluding_ the CRC32 field.
|
||||
const size_t out_size = options->header_size - 4;
|
||||
|
||||
// Store the Block Header Size.
|
||||
out[0] = out_size / 4;
|
||||
|
||||
// We write Block Flags a little later.
|
||||
size_t out_pos = 2;
|
||||
|
||||
// Compressed Size
|
||||
if (options->compressed_size != LZMA_VLI_VALUE_UNKNOWN
|
||||
|| options->compressed_reserve != 0) {
|
||||
const lzma_vli size = options->compressed_size
|
||||
!= LZMA_VLI_VALUE_UNKNOWN
|
||||
? options->compressed_size : 0;
|
||||
size_t vli_pos = 0;
|
||||
if (lzma_vli_encode(
|
||||
size, &vli_pos, options->compressed_reserve,
|
||||
out, &out_pos, out_size) != LZMA_STREAM_END)
|
||||
if (options->compressed_size != LZMA_VLI_VALUE_UNKNOWN) {
|
||||
// Compressed Size must be non-zero, fit into a 63-bit
|
||||
// integer and be a multiple of four. Also the Total Size
|
||||
// of the Block must fit into 63-bit integer.
|
||||
if (options->compressed_size == 0
|
||||
|| (options->compressed_size & 3)
|
||||
|| options->compressed_size
|
||||
> LZMA_VLI_VALUE_MAX
|
||||
|| lzma_block_total_size_get(options) == 0)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
return_if_error(lzma_vli_encode(
|
||||
options->compressed_size / 4 - 1, NULL,
|
||||
out, &out_pos, out_size));
|
||||
}
|
||||
|
||||
// Uncompressed Size
|
||||
if (options->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN
|
||||
|| options->uncompressed_reserve != 0) {
|
||||
const lzma_vli size = options->uncompressed_size
|
||||
!= LZMA_VLI_VALUE_UNKNOWN
|
||||
? options->uncompressed_size : 0;
|
||||
size_t vli_pos = 0;
|
||||
if (lzma_vli_encode(
|
||||
size, &vli_pos, options->uncompressed_reserve,
|
||||
out, &out_pos, out_size) != LZMA_STREAM_END)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
}
|
||||
if (options->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN)
|
||||
return_if_error(lzma_vli_encode(
|
||||
options->uncompressed_size, NULL,
|
||||
out, &out_pos, out_size));
|
||||
|
||||
// Filter Flags
|
||||
size_t filter_count;
|
||||
for (filter_count = 0; options->filters[filter_count].id
|
||||
!= LZMA_VLI_VALUE_UNKNOWN; ++filter_count) {
|
||||
// There can be at maximum of seven filters.
|
||||
if (filter_count == 7)
|
||||
if (options->filters == NULL
|
||||
|| options->filters[0].id == LZMA_VLI_VALUE_UNKNOWN)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
size_t filter_count = 0;
|
||||
do {
|
||||
// There can be at maximum of four filters.
|
||||
if (filter_count == 4)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
const lzma_ret ret = lzma_filter_flags_encode(out, &out_pos,
|
||||
out_size, options->filters + filter_count);
|
||||
// FIXME: Don't return LZMA_BUF_ERROR.
|
||||
if (ret != LZMA_OK)
|
||||
return ret;
|
||||
}
|
||||
return_if_error(lzma_filter_flags_encode(
|
||||
options->filters + filter_count,
|
||||
out, &out_pos, out_size));
|
||||
|
||||
// Block Flags 1
|
||||
out[0] = filter_count;
|
||||
} while (options->filters[++filter_count].id
|
||||
!= LZMA_VLI_VALUE_UNKNOWN);
|
||||
|
||||
if (options->has_eopm)
|
||||
out[0] |= 0x08;
|
||||
else if (options->uncompressed_size == LZMA_VLI_VALUE_UNKNOWN)
|
||||
return LZMA_PROG_ERROR;
|
||||
// Block Flags
|
||||
out[1] = filter_count - 1;
|
||||
|
||||
if (options->compressed_size != LZMA_VLI_VALUE_UNKNOWN
|
||||
|| options->compressed_reserve != 0)
|
||||
out[0] |= 0x10;
|
||||
if (options->compressed_size != LZMA_VLI_VALUE_UNKNOWN)
|
||||
out[1] |= 0x40;
|
||||
|
||||
if (options->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN
|
||||
|| options->uncompressed_reserve != 0)
|
||||
out[0] |= 0x20;
|
||||
if (options->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN)
|
||||
out[1] |= 0x80;
|
||||
|
||||
if (options->is_metadata)
|
||||
out[0] |= 0x80;
|
||||
|
||||
// Block Flags 2
|
||||
if (options->padding < LZMA_BLOCK_HEADER_PADDING_MIN
|
||||
|| options->padding > LZMA_BLOCK_HEADER_PADDING_MAX)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
out[1] = (uint8_t)(options->padding);
|
||||
// Padding
|
||||
memzero(out + out_pos, out_size - out_pos);
|
||||
|
||||
// CRC32
|
||||
if (options->has_crc32) {
|
||||
if (out_size - out_pos < 4)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
const uint32_t crc = lzma_crc32(out, out_pos, 0);
|
||||
for (size_t i = 0; i < 4; ++i)
|
||||
out[out_pos++] = crc >> (i * 8);
|
||||
}
|
||||
|
||||
// Padding - the amount of available space must now match with
|
||||
// the size of the Padding field.
|
||||
if (out_size - out_pos != (size_t)(options->padding))
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
memzero(out + out_pos, (size_t)(options->padding));
|
||||
integer_write_32(out + out_size, lzma_crc32(out, out_size, 0));
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
73
src/liblzma/common/block_util.c
Normal file
73
src/liblzma/common/block_util.c
Normal file
@@ -0,0 +1,73 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file block_header.c
|
||||
/// \brief Utility functions to handle lzma_block
|
||||
//
|
||||
// Copyright (C) 2008 Lasse Collin
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
extern LZMA_API lzma_ret
|
||||
lzma_block_total_size_set(lzma_block *options, lzma_vli total_size)
|
||||
{
|
||||
// Validate.
|
||||
if (options->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
|
||||
|| options->header_size > LZMA_BLOCK_HEADER_SIZE_MAX
|
||||
|| (options->header_size & 3)
|
||||
|| (unsigned)(options->check) > LZMA_CHECK_ID_MAX
|
||||
|| (total_size & 3))
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
const uint32_t container_size = options->header_size
|
||||
+ lzma_check_size(options->check);
|
||||
|
||||
// Validate that Compressed Size will be greater than zero.
|
||||
if (container_size <= total_size)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
options->compressed_size = total_size - container_size;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_vli
|
||||
lzma_block_total_size_get(const lzma_block *options)
|
||||
{
|
||||
// Validate the values that we are interested in.
|
||||
if (options->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
|
||||
|| options->header_size > LZMA_BLOCK_HEADER_SIZE_MAX
|
||||
|| (options->header_size & 3)
|
||||
|| (unsigned)(options->check) > LZMA_CHECK_ID_MAX)
|
||||
return 0;
|
||||
|
||||
// If Compressed Size is unknown, return that we cannot know
|
||||
// Total Size either.
|
||||
if (options->compressed_size == LZMA_VLI_VALUE_UNKNOWN)
|
||||
return LZMA_VLI_VALUE_UNKNOWN;
|
||||
|
||||
const lzma_vli total_size = options->compressed_size
|
||||
+ options->header_size
|
||||
+ lzma_check_size(options->check);
|
||||
|
||||
// Validate the calculated Total Size.
|
||||
if (options->compressed_size > LZMA_VLI_VALUE_MAX
|
||||
|| (options->compressed_size & 3)
|
||||
|| total_size > LZMA_VLI_VALUE_MAX)
|
||||
return 0;
|
||||
|
||||
return total_size;
|
||||
}
|
||||
61
src/liblzma/common/bsr.h
Normal file
61
src/liblzma/common/bsr.h
Normal file
@@ -0,0 +1,61 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file bsr.h
|
||||
/// \brief Bit scan reverse
|
||||
//
|
||||
// This code has been put into the public domain.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_BSR_H
|
||||
#define LZMA_BSR_H
|
||||
|
||||
// NOTE: Both input and output variables for lzma_bsr must be uint32_t.
|
||||
|
||||
#if defined(__GNUC__) && (defined (HAVE_ASM_X86) || defined(HAVE_ASM_X86_64))
|
||||
# define lzma_bsr(dest, n) \
|
||||
__asm__("bsrl %1, %0" : "=r" (dest) : "rm" (n))
|
||||
|
||||
#else
|
||||
# define lzma_bsr(dest, n) dest = lzma_bsr_helper(n)
|
||||
|
||||
static inline uint32_t
|
||||
lzma_bsr_helper(uint32_t n)
|
||||
{
|
||||
assert(n != 0);
|
||||
|
||||
uint32_t i = 31;
|
||||
|
||||
if ((n & UINT32_C(0xFFFF0000)) == 0) {
|
||||
n <<= 16;
|
||||
i = 15;
|
||||
}
|
||||
|
||||
if ((n & UINT32_C(0xFF000000)) == 0) {
|
||||
n <<= 8;
|
||||
i -= 8;
|
||||
}
|
||||
|
||||
if ((n & UINT32_C(0xF0000000)) == 0) {
|
||||
n <<= 4;
|
||||
i -= 4;
|
||||
}
|
||||
|
||||
if ((n & UINT32_C(0xC0000000)) == 0) {
|
||||
n <<= 2;
|
||||
i -= 2;
|
||||
}
|
||||
|
||||
if ((n & UINT32_C(0x80000000)) == 0)
|
||||
--i;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,9 +1,9 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file code.c
|
||||
/// \brief zlib-like API wrapper for liblzma's internal API
|
||||
/// \file common.h
|
||||
/// \brief Common functions needed in many places in liblzma
|
||||
//
|
||||
// Copyright (C) 2007 Lasse Collin
|
||||
// Copyright (C) 2007-2008 Lasse Collin
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -20,17 +20,115 @@
|
||||
#include "common.h"
|
||||
|
||||
|
||||
LZMA_API const lzma_stream LZMA_STREAM_INIT_VAR = {
|
||||
.next_in = NULL,
|
||||
.avail_in = 0,
|
||||
.total_in = 0,
|
||||
.next_out = NULL,
|
||||
.avail_out = 0,
|
||||
.total_out = 0,
|
||||
.allocator = NULL,
|
||||
.internal = NULL,
|
||||
};
|
||||
/////////////
|
||||
// Version //
|
||||
/////////////
|
||||
|
||||
extern LZMA_API uint32_t
|
||||
lzma_version_number(void)
|
||||
{
|
||||
return LZMA_VERSION;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API const char *
|
||||
lzma_version_string(void)
|
||||
{
|
||||
return PACKAGE_VERSION;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////
|
||||
// Memory allocation //
|
||||
///////////////////////
|
||||
|
||||
extern void * lzma_attribute((malloc))
|
||||
lzma_alloc(size_t size, lzma_allocator *allocator)
|
||||
{
|
||||
// Some malloc() variants return NULL if called with size == 0.
|
||||
if (size == 0)
|
||||
size = 1;
|
||||
|
||||
void *ptr;
|
||||
|
||||
if (allocator != NULL && allocator->alloc != NULL)
|
||||
ptr = allocator->alloc(allocator->opaque, 1, size);
|
||||
else
|
||||
ptr = malloc(size);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
extern void
|
||||
lzma_free(void *ptr, lzma_allocator *allocator)
|
||||
{
|
||||
if (allocator != NULL && allocator->free != NULL)
|
||||
allocator->free(allocator->opaque, ptr);
|
||||
else
|
||||
free(ptr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//////////
|
||||
// Misc //
|
||||
//////////
|
||||
|
||||
extern size_t
|
||||
lzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
size_t in_size, uint8_t *restrict out,
|
||||
size_t *restrict out_pos, size_t out_size)
|
||||
{
|
||||
const size_t in_avail = in_size - *in_pos;
|
||||
const size_t out_avail = out_size - *out_pos;
|
||||
const size_t copy_size = MIN(in_avail, out_avail);
|
||||
|
||||
memcpy(out + *out_pos, in + *in_pos, copy_size);
|
||||
|
||||
*in_pos += copy_size;
|
||||
*out_pos += copy_size;
|
||||
|
||||
return copy_size;
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_next_filter_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
lzma_next_coder_init(filters[0].init, next, allocator);
|
||||
|
||||
return filters[0].init == NULL
|
||||
? LZMA_OK : filters[0].init(next, allocator, filters);
|
||||
}
|
||||
|
||||
|
||||
extern void
|
||||
lzma_next_end(lzma_next_coder *next, lzma_allocator *allocator)
|
||||
{
|
||||
if (next->init != (uintptr_t)(NULL)) {
|
||||
// To avoid tiny end functions that simply call
|
||||
// lzma_free(coder, allocator), we allow leaving next->end
|
||||
// NULL and call lzma_free() here.
|
||||
if (next->end != NULL)
|
||||
next->end(next->coder, allocator);
|
||||
else
|
||||
lzma_free(next->coder, allocator);
|
||||
|
||||
// Reset the variables so the we don't accidentally think
|
||||
// that it is an already initialized coder.
|
||||
*next = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////
|
||||
// External to internal API wrapper //
|
||||
//////////////////////////////////////
|
||||
|
||||
extern lzma_ret
|
||||
lzma_strm_init(lzma_stream *strm)
|
||||
@@ -191,13 +289,17 @@ extern LZMA_API void
|
||||
lzma_end(lzma_stream *strm)
|
||||
{
|
||||
if (strm != NULL && strm->internal != NULL) {
|
||||
if (strm->internal->next.end != NULL)
|
||||
strm->internal->next.end(strm->internal->next.coder,
|
||||
strm->allocator);
|
||||
|
||||
lzma_next_end(&strm->internal->next, strm->allocator);
|
||||
lzma_free(strm->internal, strm->allocator);
|
||||
strm->internal = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_check
|
||||
lzma_get_check(const lzma_stream *strm)
|
||||
{
|
||||
return strm->internal->next.get_check(strm->internal->next.coder);
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
/// \file common.h
|
||||
/// \brief Definitions common to the whole liblzma library
|
||||
//
|
||||
// Copyright (C) 2007 Lasse Collin
|
||||
// Copyright (C) 2007-2008 Lasse Collin
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -20,7 +20,8 @@
|
||||
#ifndef LZMA_COMMON_H
|
||||
#define LZMA_COMMON_H
|
||||
|
||||
#include "sysdefs.h"
|
||||
#include "../../common/sysdefs.h"
|
||||
#include "../../common/integer.h"
|
||||
|
||||
// Don't use ifdef...
|
||||
#if HAVE_VISIBILITY
|
||||
@@ -30,20 +31,47 @@
|
||||
#endif
|
||||
|
||||
|
||||
// These allow helping the compiler in some often-executed branches, whose
|
||||
// result is almost always the same.
|
||||
#ifdef __GNUC__
|
||||
# define likely(expr) __builtin_expect(expr, true)
|
||||
# define unlikely(expr) __builtin_expect(expr, false)
|
||||
#else
|
||||
# define likely(expr) (expr)
|
||||
# define unlikely(expr) (expr)
|
||||
#endif
|
||||
|
||||
|
||||
/// Size of temporary buffers needed in some filters
|
||||
#define LZMA_BUFFER_SIZE 4096
|
||||
|
||||
|
||||
/// Start of internal Filter ID space. These IDs must never be used
|
||||
/// in Streams.
|
||||
#define LZMA_FILTER_RESERVED_START (LZMA_VLI_C(1) << 62)
|
||||
|
||||
|
||||
/// Internal helper filter used by Subblock decoder. It is mapped to an
|
||||
/// otherwise invalid Filter ID, which is impossible to get from any input
|
||||
/// file (even if malicious file).
|
||||
#define LZMA_FILTER_SUBBLOCK_HELPER (UINT64_MAX - 2)
|
||||
#define LZMA_FILTER_SUBBLOCK_HELPER (LZMA_FILTER_RESERVED_START + 1)
|
||||
|
||||
|
||||
/// Supported flags that can be passed to lzma_stream_decoder()
|
||||
/// or lzma_auto_decoder().
|
||||
#define LZMA_SUPPORTED_FLAGS \
|
||||
( LZMA_TELL_NO_CHECK \
|
||||
| LZMA_TELL_UNSUPPORTED_CHECK \
|
||||
| LZMA_TELL_ANY_CHECK \
|
||||
| LZMA_CONCATENATED )
|
||||
|
||||
|
||||
///////////
|
||||
// Types //
|
||||
///////////
|
||||
|
||||
/// Type of encoder/decoder specific data; the actual structure is defined
|
||||
/// differently in different coders.
|
||||
typedef struct lzma_coder_s lzma_coder;
|
||||
|
||||
typedef struct lzma_next_coder_s lzma_next_coder;
|
||||
@@ -51,10 +79,15 @@ typedef struct lzma_next_coder_s lzma_next_coder;
|
||||
typedef struct lzma_filter_info_s lzma_filter_info;
|
||||
|
||||
|
||||
/// Type of a function used to initialize a filter encoder or decoder
|
||||
typedef lzma_ret (*lzma_init_function)(
|
||||
lzma_next_coder *next, lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters);
|
||||
|
||||
/// Type of a function to do some kind of coding work (filters, Stream,
|
||||
/// Block encoders/decoders etc.). Some special coders use don't use both
|
||||
/// input and output buffers, but for simplicity they still use this same
|
||||
/// function prototype.
|
||||
typedef lzma_ret (*lzma_code_function)(
|
||||
lzma_coder *coder, lzma_allocator *allocator,
|
||||
const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
@@ -62,10 +95,24 @@ typedef lzma_ret (*lzma_code_function)(
|
||||
size_t *restrict out_pos, size_t out_size,
|
||||
lzma_action action);
|
||||
|
||||
/// Type of a function to free the memory allocated for the coder
|
||||
typedef void (*lzma_end_function)(
|
||||
lzma_coder *coder, lzma_allocator *allocator);
|
||||
|
||||
|
||||
/// Raw coder validates and converts an array of lzma_filter structures to
|
||||
/// an array of lzma_filter_info structures. This array is used with
|
||||
/// lzma_next_filter_init to initialize the filter chain.
|
||||
struct lzma_filter_info_s {
|
||||
/// Pointer to function used to initialize the filter.
|
||||
/// This is NULL to indicate end of array.
|
||||
lzma_init_function init;
|
||||
|
||||
/// Pointer to filter's options structure
|
||||
void *options;
|
||||
};
|
||||
|
||||
|
||||
/// Hold data and function pointers of the next filter in the chain.
|
||||
struct lzma_next_coder_s {
|
||||
/// Pointer to coder-specific data
|
||||
@@ -73,28 +120,50 @@ struct lzma_next_coder_s {
|
||||
|
||||
/// "Pointer" to init function. This is never called here.
|
||||
/// We need only to detect if we are initializing a coder
|
||||
/// that was allocated earlier. See code.c and next_coder.c.
|
||||
/// that was allocated earlier. See lzma_next_coder_init and
|
||||
/// lzma_next_strm_init macros in this file.
|
||||
uintptr_t init;
|
||||
|
||||
/// Pointer to function to do the actual coding
|
||||
lzma_code_function code;
|
||||
|
||||
/// Pointer to function to free lzma_next_coder.coder
|
||||
/// Pointer to function to free lzma_next_coder.coder. This can
|
||||
/// be NULL; in that case, lzma_free is called to free
|
||||
/// lzma_next_coder.coder.
|
||||
lzma_end_function end;
|
||||
|
||||
/// Pointer to function to return the type of the integrity check.
|
||||
/// Most coders won't support this.
|
||||
lzma_check (*get_check)(const lzma_coder *coder);
|
||||
|
||||
/// Pointer to function to get and/or change the memory usage limit.
|
||||
/// If memlimit == 0, the limit is not changed.
|
||||
uint64_t (*memconfig)(lzma_coder *coder, uint64_t memlimit);
|
||||
};
|
||||
|
||||
|
||||
/// Macro to initialize lzma_next_coder structure
|
||||
#define LZMA_NEXT_CODER_INIT \
|
||||
(lzma_next_coder){ \
|
||||
.coder = NULL, \
|
||||
.init = 0, \
|
||||
.init = (uintptr_t)(NULL), \
|
||||
.code = NULL, \
|
||||
.end = NULL, \
|
||||
.get_check = NULL, \
|
||||
.memconfig = NULL, \
|
||||
}
|
||||
|
||||
|
||||
/// Internal data for lzma_strm_init, lzma_code, and lzma_end. A pointer to
|
||||
/// this is stored in lzma_stream.
|
||||
struct lzma_internal_s {
|
||||
/// The actual coder that should do something useful
|
||||
lzma_next_coder next;
|
||||
|
||||
/// Track the state of the coder. This is used to validate arguments
|
||||
/// so that the actual coders can rely on e.g. that LZMA_SYNC_FLUSH
|
||||
/// is used on every call to lzma_code until next.code has returned
|
||||
/// LZMA_STREAM_END.
|
||||
enum {
|
||||
ISEQ_RUN,
|
||||
ISEQ_SYNC_FLUSH,
|
||||
@@ -104,37 +173,20 @@ struct lzma_internal_s {
|
||||
ISEQ_ERROR,
|
||||
} sequence;
|
||||
|
||||
bool supported_actions[4];
|
||||
bool allow_buf_error;
|
||||
/// A copy of lzma_stream avail_in. This is used to verify that the
|
||||
/// amount of input doesn't change once e.g. LZMA_FINISH has been
|
||||
/// used.
|
||||
size_t avail_in;
|
||||
|
||||
/// Indicates which lzma_action values are allowed by next.code.
|
||||
bool supported_actions[4];
|
||||
|
||||
/// If true, lzma_code will return LZMA_BUF_ERROR if no progress was
|
||||
/// made (no input consumed and no output produced by next.code).
|
||||
bool allow_buf_error;
|
||||
};
|
||||
|
||||
|
||||
struct lzma_filter_info_s {
|
||||
/// Pointer to function used to initialize the filter.
|
||||
/// This is NULL to indicate end of array.
|
||||
lzma_init_function init;
|
||||
|
||||
/// Pointer to filter's options structure
|
||||
void *options;
|
||||
|
||||
/// Uncompressed size of the filter, or LZMA_VLI_VALUE_UNKNOWN
|
||||
/// if unknown.
|
||||
lzma_vli uncompressed_size;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
typedef struct {
|
||||
lzma_init_function init;
|
||||
uint32_t (*input_alignment)(lzma_vli id, const void *options);
|
||||
uint32_t (*output_alignment)(lzma_vli id, const void *options);
|
||||
bool changes_uncompressed_size;
|
||||
bool supports_eopm;
|
||||
} lzma_filter_hook;
|
||||
*/
|
||||
|
||||
|
||||
///////////////
|
||||
// Functions //
|
||||
///////////////
|
||||
@@ -146,126 +198,69 @@ extern void *lzma_alloc(size_t size, lzma_allocator *allocator)
|
||||
/// Frees memory
|
||||
extern void lzma_free(void *ptr, lzma_allocator *allocator);
|
||||
|
||||
/// Initializes lzma_stream FIXME desc
|
||||
|
||||
/// Allocates strm->internal if it is NULL, and initializes *strm and
|
||||
/// strm->internal. This function is only called via lzma_next_strm_init macro.
|
||||
extern lzma_ret lzma_strm_init(lzma_stream *strm);
|
||||
|
||||
///
|
||||
/// Initializes the next filter in the chain, if any. This takes care of
|
||||
/// freeing the memory of previously initialized filter if it is different
|
||||
/// than the filter being initialized now. This way the actual filter
|
||||
/// initialization functions don't need to use lzma_next_coder_init macro.
|
||||
extern lzma_ret lzma_next_filter_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters);
|
||||
|
||||
///
|
||||
extern void lzma_next_coder_end(lzma_next_coder *next,
|
||||
lzma_allocator *allocator);
|
||||
/// Frees the memory allocated for next->coder either using next->end or,
|
||||
/// if next->end is NULL, using lzma_free.
|
||||
extern void lzma_next_end(lzma_next_coder *next, lzma_allocator *allocator);
|
||||
|
||||
|
||||
extern lzma_ret lzma_filter_flags_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, lzma_options_filter *options);
|
||||
|
||||
extern lzma_ret lzma_block_header_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, lzma_options_block *options);
|
||||
|
||||
extern lzma_ret lzma_stream_encoder_single_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_options_stream *options);
|
||||
|
||||
extern lzma_ret lzma_stream_decoder_init(
|
||||
lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_extra **header, lzma_extra **footer);
|
||||
|
||||
|
||||
/// \brief Wrapper for memcpy()
|
||||
///
|
||||
/// This function copies as much data as possible from in[] to out[] and
|
||||
/// updates *in_pos and *out_pos accordingly.
|
||||
///
|
||||
static inline size_t
|
||||
bufcpy(const uint8_t *restrict in, size_t *restrict in_pos, size_t in_size,
|
||||
uint8_t *restrict out, size_t *restrict out_pos,
|
||||
size_t out_size)
|
||||
{
|
||||
const size_t in_avail = in_size - *in_pos;
|
||||
const size_t out_avail = out_size - *out_pos;
|
||||
const size_t copy_size = MIN(in_avail, out_avail);
|
||||
|
||||
memcpy(out + *out_pos, in + *in_pos, copy_size);
|
||||
|
||||
*in_pos += copy_size;
|
||||
*out_pos += copy_size;
|
||||
|
||||
return copy_size;
|
||||
}
|
||||
|
||||
|
||||
/// \brief Initializing the next coder
|
||||
///
|
||||
/// lzma_next_coder can point to different types of coders. The existing
|
||||
/// coder may be different than what we are initializing now. In that case
|
||||
/// we must git rid of the old coder first. Otherwise we reuse the existing
|
||||
/// coder structure.
|
||||
///
|
||||
#define lzma_next_coder_init2(next, allocator, cmpfunc, func, ...) \
|
||||
do { \
|
||||
if ((uintptr_t)(&cmpfunc) != (next)->init) \
|
||||
lzma_next_coder_end(next, allocator); \
|
||||
const lzma_ret ret = func(next, __VA_ARGS__); \
|
||||
if (ret == LZMA_OK) { \
|
||||
(next)->init = (uintptr_t)(&cmpfunc); \
|
||||
assert((next)->code != NULL); \
|
||||
assert((next)->end != NULL); \
|
||||
} else { \
|
||||
lzma_next_coder_end(next, allocator); \
|
||||
} \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
/// \brief Initializing lzma_next_coder
|
||||
///
|
||||
/// Call the initialization function, which must take at least one
|
||||
/// argument in addition to lzma_next_coder and lzma_allocator.
|
||||
#define lzma_next_coder_init(func, next, allocator, ...) \
|
||||
lzma_next_coder_init2(next, allocator, \
|
||||
func, func, allocator, __VA_ARGS__)
|
||||
|
||||
|
||||
/// \brief Initializing lzma_stream
|
||||
///
|
||||
/// lzma_strm initialization with more detailed options.
|
||||
#define lzma_next_strm_init2(strm, cmpfunc, func, ...) \
|
||||
do { \
|
||||
lzma_ret ret = lzma_strm_init(strm); \
|
||||
if (ret != LZMA_OK) \
|
||||
return ret; \
|
||||
if ((uintptr_t)(&cmpfunc) != (strm)->internal->next.init) \
|
||||
lzma_next_coder_end(\
|
||||
&(strm)->internal->next, (strm)->allocator); \
|
||||
ret = func(&(strm)->internal->next, __VA_ARGS__); \
|
||||
if (ret != LZMA_OK) { \
|
||||
lzma_end(strm); \
|
||||
return ret; \
|
||||
} \
|
||||
(strm)->internal->next.init = (uintptr_t)(&cmpfunc); \
|
||||
assert((strm)->internal->next.code != NULL); \
|
||||
assert((strm)->internal->next.end != NULL); \
|
||||
} while (0)
|
||||
|
||||
/// \brief Initializing lzma_stream
|
||||
///
|
||||
/// Call the initialization function, which must take at least one
|
||||
/// argument in addition to lzma_next_coder and lzma_allocator.
|
||||
#define lzma_next_strm_init(strm, func, ...) \
|
||||
lzma_next_strm_init2(strm, func, func, (strm)->allocator, __VA_ARGS__)
|
||||
/// Copy as much data as possible from in[] to out[] and update *in_pos
|
||||
/// and *out_pos accordingly. Returns the number of bytes copied.
|
||||
extern size_t lzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
size_t in_size, uint8_t *restrict out,
|
||||
size_t *restrict out_pos, size_t out_size);
|
||||
|
||||
|
||||
/// \brief Return if expression doesn't evaluate to LZMA_OK
|
||||
///
|
||||
/// There are several situations where we want to return immediatelly
|
||||
/// with the value of expr if it isn't LZMA_OK. This macro shortens
|
||||
/// the code a bit.
|
||||
///
|
||||
/// the code a little.
|
||||
#define return_if_error(expr) \
|
||||
do { \
|
||||
const lzma_ret ret_ = expr; \
|
||||
const lzma_ret ret_ = (expr); \
|
||||
if (ret_ != LZMA_OK) \
|
||||
return ret_; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/// If next isn't already initialized, free the previous coder. Then mark
|
||||
/// that next is _possibly_ initialized for the coder using this macro.
|
||||
/// "Possibly" means that if e.g. allocation of next->coder fails, the
|
||||
/// structure isn't actually initialized for this coder, but leaving
|
||||
/// next->init to func is still OK.
|
||||
#define lzma_next_coder_init(func, next, allocator) \
|
||||
do { \
|
||||
if ((uintptr_t)(&func) != (next)->init) \
|
||||
lzma_next_end(next, allocator); \
|
||||
(next)->init = (uintptr_t)(&func); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/// Initializes lzma_strm and calls func() to initialize strm->internal->next.
|
||||
/// (The function being called will use lzma_next_coder_init()). If
|
||||
/// initialization fails, memory that wasn't freed by func() is freed
|
||||
/// along strm->internal.
|
||||
#define lzma_next_strm_init(func, strm, ...) \
|
||||
do { \
|
||||
return_if_error(lzma_strm_init(strm)); \
|
||||
const lzma_ret ret_ = func(&(strm)->internal->next, \
|
||||
(strm)->allocator, __VA_ARGS__); \
|
||||
if (ret_ != LZMA_OK) { \
|
||||
lzma_end(strm); \
|
||||
return ret_; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file copy_coder.c
|
||||
/// \brief The Copy filter encoder and decoder
|
||||
//
|
||||
// Copyright (C) 2007 Lasse Collin
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "copy_coder.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
lzma_next_coder next;
|
||||
lzma_vli uncompressed_size;
|
||||
};
|
||||
|
||||
|
||||
#ifdef HAVE_ENCODER
|
||||
static lzma_ret
|
||||
copy_encode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
size_t in_size, uint8_t *restrict out,
|
||||
size_t *restrict out_pos, size_t out_size, lzma_action action)
|
||||
{
|
||||
// If we aren't the last filter in the chain, the Copy filter
|
||||
// is totally useless. Note that it is job of the next coder to
|
||||
// take care of Uncompressed Size, so we don't need to update our
|
||||
// coder->uncompressed_size at all.
|
||||
if (coder->next.code != NULL)
|
||||
return coder->next.code(coder->next.coder, allocator,
|
||||
in, in_pos, in_size, out, out_pos, out_size,
|
||||
action);
|
||||
|
||||
// If we get here, we are the last filter in the chain.
|
||||
assert(coder->uncompressed_size <= LZMA_VLI_VALUE_MAX);
|
||||
|
||||
const size_t in_avail = in_size - *in_pos;
|
||||
|
||||
// Check that we don't have too much input.
|
||||
if ((lzma_vli)(in_avail) > coder->uncompressed_size)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
// Check that once LZMA_FINISH has been given, the amount of input
|
||||
// matches uncompressed_size, which is always known.
|
||||
if (action == LZMA_FINISH
|
||||
&& coder->uncompressed_size != (lzma_vli)(in_avail))
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
// We are the last coder in the chain.
|
||||
// Just copy as much data as possible.
|
||||
const size_t in_used = bufcpy(
|
||||
in, in_pos, in_size, out, out_pos, out_size);
|
||||
|
||||
// Update uncompressed_size if it is known.
|
||||
if (coder->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN)
|
||||
coder->uncompressed_size -= in_used;
|
||||
|
||||
// LZMA_SYNC_FLUSH and LZMA_FINISH are the same thing for us.
|
||||
if ((action != LZMA_RUN && *in_pos == in_size)
|
||||
|| coder->uncompressed_size == 0)
|
||||
return LZMA_STREAM_END;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_DECODER
|
||||
static lzma_ret
|
||||
copy_decode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
size_t in_size, uint8_t *restrict out,
|
||||
size_t *restrict out_pos, size_t out_size, lzma_action action)
|
||||
{
|
||||
if (coder->next.code != NULL)
|
||||
return coder->next.code(coder->next.coder, allocator,
|
||||
in, in_pos, in_size, out, out_pos, out_size,
|
||||
action);
|
||||
|
||||
assert(coder->uncompressed_size <= LZMA_VLI_VALUE_MAX);
|
||||
|
||||
const size_t in_avail = in_size - *in_pos;
|
||||
|
||||
// Limit in_size so that we don't copy too much.
|
||||
if ((lzma_vli)(in_avail) > coder->uncompressed_size)
|
||||
in_size = *in_pos + (size_t)(coder->uncompressed_size);
|
||||
|
||||
// We are the last coder in the chain.
|
||||
// Just copy as much data as possible.
|
||||
const size_t in_used = bufcpy(
|
||||
in, in_pos, in_size, out, out_pos, out_size);
|
||||
|
||||
// Update uncompressed_size if it is known.
|
||||
if (coder->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN)
|
||||
coder->uncompressed_size -= in_used;
|
||||
|
||||
return coder->uncompressed_size == 0 ? LZMA_STREAM_END : LZMA_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
copy_coder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
{
|
||||
lzma_next_coder_end(&coder->next, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
copy_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters, lzma_code_function encode)
|
||||
{
|
||||
// Allocate memory for the decoder if needed.
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->code = encode;
|
||||
next->end = ©_coder_end;
|
||||
next->coder->next = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
// Copy Uncompressed Size which is used to limit the output size.
|
||||
next->coder->uncompressed_size = filters[0].uncompressed_size;
|
||||
|
||||
// Initialize the next decoder in the chain, if any.
|
||||
return lzma_next_filter_init(
|
||||
&next->coder->next, allocator, filters + 1);
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_ENCODER
|
||||
extern lzma_ret
|
||||
lzma_copy_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
lzma_next_coder_init(copy_coder_init, next, allocator, filters,
|
||||
©_encode);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_DECODER
|
||||
extern lzma_ret
|
||||
lzma_copy_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
lzma_next_coder_init(copy_coder_init, next, allocator, filters,
|
||||
©_decode);
|
||||
}
|
||||
#endif
|
||||
@@ -1,204 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file delta_coder.c
|
||||
/// \brief Encoder and decoder for the Delta filter
|
||||
//
|
||||
// Copyright (C) 2007 Lasse Collin
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "delta_coder.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
/// Next coder in the chain
|
||||
lzma_next_coder next;
|
||||
|
||||
/// Uncompressed size - This is needed when we are the last
|
||||
/// filter in the chain.
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
/// Delta distance
|
||||
size_t distance;
|
||||
|
||||
/// True if we are encoding; false if decoding
|
||||
bool is_encoder;
|
||||
|
||||
/// Position in history[]
|
||||
uint8_t pos;
|
||||
|
||||
/// Buffer to hold history of the original data
|
||||
uint8_t history[LZMA_DELTA_DISTANCE_MAX];
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
encode_buffer(lzma_coder *coder, uint8_t *buffer, size_t size)
|
||||
{
|
||||
const size_t distance = coder->distance;
|
||||
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
const uint8_t tmp = coder->history[
|
||||
(distance + coder->pos) & 0xFF];
|
||||
coder->history[coder->pos--] = buffer[i];
|
||||
buffer[i] -= tmp;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
decode_buffer(lzma_coder *coder, uint8_t *buffer, size_t size)
|
||||
{
|
||||
const size_t distance = coder->distance;
|
||||
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
buffer[i] += coder->history[(distance + coder->pos) & 0xFF];
|
||||
coder->history[coder->pos--] = buffer[i];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
delta_code(lzma_coder *coder, lzma_allocator *allocator,
|
||||
const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
size_t in_size, uint8_t *restrict out,
|
||||
size_t *restrict out_pos, size_t out_size, lzma_action action)
|
||||
{
|
||||
const size_t out_start = *out_pos;
|
||||
size_t size;
|
||||
lzma_ret ret;
|
||||
|
||||
if (coder->next.code == NULL) {
|
||||
const size_t in_avail = in_size - *in_pos;
|
||||
|
||||
if (coder->is_encoder) {
|
||||
// Check that we don't have too much input.
|
||||
if ((lzma_vli)(in_avail) > coder->uncompressed_size)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
// Check that once LZMA_FINISH has been given, the
|
||||
// amount of input matches uncompressed_size if it
|
||||
// is known.
|
||||
if (action == LZMA_FINISH && coder->uncompressed_size
|
||||
!= LZMA_VLI_VALUE_UNKNOWN
|
||||
&& coder->uncompressed_size
|
||||
!= (lzma_vli)(in_avail))
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
} else {
|
||||
// Limit in_size so that we don't copy too much.
|
||||
if ((lzma_vli)(in_avail) > coder->uncompressed_size)
|
||||
in_size = *in_pos + (size_t)(
|
||||
coder->uncompressed_size);
|
||||
}
|
||||
|
||||
size = bufcpy(in, in_pos, in_size, out, out_pos, out_size);
|
||||
|
||||
if (coder->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN)
|
||||
coder->uncompressed_size -= size;
|
||||
|
||||
// action can be LZMA_FINISH only in the encoder.
|
||||
ret = (action == LZMA_FINISH && *in_pos == in_size)
|
||||
|| coder->uncompressed_size == 0
|
||||
? LZMA_STREAM_END : LZMA_OK;
|
||||
|
||||
} else {
|
||||
ret = coder->next.code(coder->next.coder, allocator,
|
||||
in, in_pos, in_size, out, out_pos, out_size,
|
||||
action);
|
||||
if (ret != LZMA_OK && ret != LZMA_STREAM_END)
|
||||
return ret;
|
||||
|
||||
size = *out_pos - out_start;
|
||||
}
|
||||
|
||||
if (coder->is_encoder)
|
||||
encode_buffer(coder, out + out_start, size);
|
||||
else
|
||||
decode_buffer(coder, out + out_start, size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
delta_coder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
{
|
||||
lzma_next_coder_end(&coder->next, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
delta_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters, bool is_encoder)
|
||||
{
|
||||
// Allocate memory for the decoder if needed.
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->code = &delta_code;
|
||||
next->end = &delta_coder_end;
|
||||
next->coder->next = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
// Copy Uncompressed Size which is used to limit the output size.
|
||||
next->coder->uncompressed_size = filters[0].uncompressed_size;
|
||||
|
||||
// The coder acts slightly differently as encoder and decoder.
|
||||
next->coder->is_encoder = is_encoder;
|
||||
|
||||
// Set the delta distance.
|
||||
if (filters[0].options == NULL)
|
||||
return LZMA_PROG_ERROR;
|
||||
next->coder->distance = ((lzma_options_delta *)(filters[0].options))
|
||||
->distance;
|
||||
if (next->coder->distance < LZMA_DELTA_DISTANCE_MIN
|
||||
|| next->coder->distance > LZMA_DELTA_DISTANCE_MAX)
|
||||
return LZMA_HEADER_ERROR;
|
||||
|
||||
// Initialize the rest of the variables.
|
||||
next->coder->pos = 0;
|
||||
memzero(next->coder->history, LZMA_DELTA_DISTANCE_MAX);
|
||||
|
||||
// Initialize the next decoder in the chain, if any.
|
||||
return lzma_next_filter_init(&next->coder->next,
|
||||
allocator, filters + 1);
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_ENCODER
|
||||
extern lzma_ret
|
||||
lzma_delta_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
return delta_coder_init(next, allocator, filters, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_DECODER
|
||||
extern lzma_ret
|
||||
lzma_delta_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
return delta_coder_init(next, allocator, filters, false);
|
||||
}
|
||||
#endif
|
||||
124
src/liblzma/common/easy.c
Normal file
124
src/liblzma/common/easy.c
Normal file
@@ -0,0 +1,124 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file easy.c
|
||||
/// \brief Easy Stream encoder initialization
|
||||
//
|
||||
// Copyright (C) 2008 Lasse Collin
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stream_encoder.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
lzma_next_coder stream_encoder;
|
||||
|
||||
/// We need to keep the filters array available in case
|
||||
/// LZMA_FULL_FLUSH is used.
|
||||
lzma_filter filters[5];
|
||||
};
|
||||
|
||||
|
||||
static bool
|
||||
easy_set_filters(lzma_filter *filters, uint32_t level)
|
||||
{
|
||||
bool error = false;
|
||||
|
||||
if (level == 0) {
|
||||
// TODO FIXME Use Subblock or LZMA2 with no compression.
|
||||
error = true;
|
||||
|
||||
#ifdef HAVE_ENCODER_LZMA2
|
||||
} else if (level <= 9) {
|
||||
filters[0].id = LZMA_FILTER_LZMA2;
|
||||
filters[0].options = (void *)(&lzma_preset_lzma[level - 1]);
|
||||
filters[1].id = LZMA_VLI_VALUE_UNKNOWN;
|
||||
#endif
|
||||
|
||||
} else {
|
||||
error = true;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
easy_encode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
size_t in_size, uint8_t *restrict out,
|
||||
size_t *restrict out_pos, size_t out_size, lzma_action action)
|
||||
{
|
||||
return coder->stream_encoder.code(
|
||||
coder->stream_encoder.coder, allocator,
|
||||
in, in_pos, in_size, out, out_pos, out_size, action);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
easy_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
{
|
||||
lzma_next_end(&coder->stream_encoder, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
easy_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_easy_level level)
|
||||
{
|
||||
lzma_next_coder_init(easy_encoder_init, next, allocator);
|
||||
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->code = &easy_encode;
|
||||
next->end = &easy_encoder_end;
|
||||
|
||||
next->coder->stream_encoder = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
if (easy_set_filters(next->coder->filters, level))
|
||||
return LZMA_HEADER_ERROR;
|
||||
|
||||
return lzma_stream_encoder_init(&next->coder->stream_encoder,
|
||||
allocator, next->coder->filters, LZMA_CHECK_CRC32);
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_ret
|
||||
lzma_easy_encoder(lzma_stream *strm, lzma_easy_level level)
|
||||
{
|
||||
lzma_next_strm_init(easy_encoder_init, strm, level);
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = true;
|
||||
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
|
||||
strm->internal->supported_actions[LZMA_FULL_FLUSH] = true;
|
||||
strm->internal->supported_actions[LZMA_FINISH] = true;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API uint64_t
|
||||
lzma_easy_memory_usage(lzma_easy_level level)
|
||||
{
|
||||
lzma_filter filters[5];
|
||||
if (easy_set_filters(filters, level))
|
||||
return UINT32_MAX;
|
||||
|
||||
return lzma_memusage_encoder(filters);
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file features.c
|
||||
/// \brief Information about features enabled at compile time
|
||||
//
|
||||
// Copyright (C) 2007 Lasse Collin
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
static const lzma_vli filters[] = {
|
||||
#ifdef HAVE_FILTER_COPY
|
||||
LZMA_FILTER_COPY,
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FILTER_SUBBLOCK
|
||||
LZMA_FILTER_SUBBLOCK,
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FILTER_X86
|
||||
LZMA_FILTER_X86,
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FILTER_POWERPC
|
||||
LZMA_FILTER_POWERPC,
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FILTER_IA64
|
||||
LZMA_FILTER_IA64,
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FILTER_ARM
|
||||
LZMA_FILTER_ARM,
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FILTER_ARMTHUMB
|
||||
LZMA_FILTER_ARMTHUMB,
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FILTER_SPARC
|
||||
LZMA_FILTER_SPARC,
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FILTER_DELTA
|
||||
LZMA_FILTER_DELTA,
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FILTER_LZMA
|
||||
LZMA_FILTER_LZMA,
|
||||
#endif
|
||||
|
||||
LZMA_VLI_VALUE_UNKNOWN
|
||||
};
|
||||
|
||||
|
||||
LZMA_API const lzma_vli *const lzma_available_filter_encoders = filters;
|
||||
|
||||
LZMA_API const lzma_vli *const lzma_available_filter_decoders = filters;
|
||||
262
src/liblzma/common/filter_common.c
Normal file
262
src/liblzma/common/filter_common.c
Normal file
@@ -0,0 +1,262 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file filter_common.c
|
||||
/// \brief Filter-specific stuff common for both encoder and decoder
|
||||
//
|
||||
// Copyright (C) 2008 Lasse Collin
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "filter_common.h"
|
||||
|
||||
|
||||
static const struct {
|
||||
/// Filter ID
|
||||
lzma_vli id;
|
||||
|
||||
/// True if it is OK to use this filter as non-last filter in
|
||||
/// the chain.
|
||||
bool non_last_ok;
|
||||
|
||||
/// True if it is OK to use this filter as the last filter in
|
||||
/// the chain.
|
||||
bool last_ok;
|
||||
|
||||
/// True if the filter may change the size of the data (that is, the
|
||||
/// amount of encoded output can be different than the amount of
|
||||
/// uncompressed input).
|
||||
bool changes_size;
|
||||
|
||||
} features[] = {
|
||||
#if defined (HAVE_ENCODER_LZMA) || defined(HAVE_DECODER_LZMA)
|
||||
{
|
||||
.id = LZMA_FILTER_LZMA,
|
||||
.non_last_ok = false,
|
||||
.last_ok = true,
|
||||
.changes_size = true,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_DECODER_LZMA2
|
||||
{
|
||||
.id = LZMA_FILTER_LZMA2,
|
||||
.non_last_ok = false,
|
||||
.last_ok = true,
|
||||
.changes_size = true,
|
||||
},
|
||||
#endif
|
||||
#if defined(HAVE_ENCODER_SUBBLOCK) || defined(HAVE_DECODER_SUBBLOCK)
|
||||
{
|
||||
.id = LZMA_FILTER_SUBBLOCK,
|
||||
.non_last_ok = true,
|
||||
.last_ok = true,
|
||||
.changes_size = true,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_DECODER_X86
|
||||
{
|
||||
.id = LZMA_FILTER_X86,
|
||||
.non_last_ok = true,
|
||||
.last_ok = false,
|
||||
.changes_size = false,
|
||||
},
|
||||
#endif
|
||||
#if defined(HAVE_ENCODER_POWERPC) || defined(HAVE_DECODER_POWERPC)
|
||||
{
|
||||
.id = LZMA_FILTER_POWERPC,
|
||||
.non_last_ok = true,
|
||||
.last_ok = false,
|
||||
.changes_size = false,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_DECODER_IA64
|
||||
{
|
||||
.id = LZMA_FILTER_IA64,
|
||||
.non_last_ok = true,
|
||||
.last_ok = false,
|
||||
.changes_size = false,
|
||||
},
|
||||
#endif
|
||||
#if defined(HAVE_ENCODER_ARM) || defined(HAVE_DECODER_ARM)
|
||||
{
|
||||
.id = LZMA_FILTER_ARM,
|
||||
.non_last_ok = true,
|
||||
.last_ok = false,
|
||||
.changes_size = false,
|
||||
},
|
||||
#endif
|
||||
#if defined(HAVE_ENCODER_ARMTHUMB) || defined(HAVE_DECODER_ARMTHUMB)
|
||||
{
|
||||
.id = LZMA_FILTER_ARMTHUMB,
|
||||
.non_last_ok = true,
|
||||
.last_ok = false,
|
||||
.changes_size = false,
|
||||
},
|
||||
#endif
|
||||
#if defined(HAVE_ENCODER_SPARC) || defined(HAVE_DECODER_SPARC)
|
||||
{
|
||||
.id = LZMA_FILTER_SPARC,
|
||||
.non_last_ok = true,
|
||||
.last_ok = false,
|
||||
.changes_size = false,
|
||||
},
|
||||
#endif
|
||||
#if defined(HAVE_ENCODER_DELTA) || defined(HAVE_DECODER_DELTA)
|
||||
{
|
||||
.id = LZMA_FILTER_DELTA,
|
||||
.non_last_ok = true,
|
||||
.last_ok = false,
|
||||
.changes_size = false,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.id = LZMA_VLI_VALUE_UNKNOWN
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static lzma_ret
|
||||
validate_chain(const lzma_filter *filters, size_t *count)
|
||||
{
|
||||
// There must be at least one filter.
|
||||
if (filters == NULL || filters[0].id == LZMA_VLI_VALUE_UNKNOWN)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Number of non-last filters that may change the size of the data
|
||||
// significantly (that is, more than 1-2 % or so).
|
||||
size_t changes_size_count = 0;
|
||||
|
||||
// True if it is OK to add a new filter after the current filter.
|
||||
bool non_last_ok = true;
|
||||
|
||||
// True if the last filter in the given chain is actually usable as
|
||||
// the last filter. Only filters that support embedding End of Payload
|
||||
// Marker can be used as the last filter in the chain.
|
||||
bool last_ok = false;
|
||||
|
||||
size_t i = 0;
|
||||
do {
|
||||
size_t j;
|
||||
for (j = 0; filters[i].id != features[j].id; ++j)
|
||||
if (features[j].id == LZMA_VLI_VALUE_UNKNOWN)
|
||||
return LZMA_HEADER_ERROR;
|
||||
|
||||
// If the previous filter in the chain cannot be a non-last
|
||||
// filter, the chain is invalid.
|
||||
if (!non_last_ok)
|
||||
return LZMA_HEADER_ERROR;
|
||||
|
||||
non_last_ok = features[j].non_last_ok;
|
||||
last_ok = features[j].last_ok;
|
||||
changes_size_count += features[j].changes_size;
|
||||
|
||||
} while (filters[++i].id != LZMA_VLI_VALUE_UNKNOWN);
|
||||
|
||||
// There must be 1-4 filters. The last filter must be usable as
|
||||
// the last filter in the chain. At maximum of three filters are
|
||||
// allowed to change the size of the data.
|
||||
if (i > LZMA_BLOCK_FILTERS_MAX || !last_ok || changes_size_count > 3)
|
||||
return LZMA_HEADER_ERROR;
|
||||
|
||||
*count = i;
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_raw_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
const lzma_filter *options,
|
||||
lzma_filter_find coder_find, bool is_encoder)
|
||||
{
|
||||
// Do some basic validation and get the number of filters.
|
||||
size_t count;
|
||||
return_if_error(validate_chain(options, &count));
|
||||
|
||||
// Set the filter functions and copy the options pointer.
|
||||
lzma_filter_info filters[LZMA_BLOCK_FILTERS_MAX + 1];
|
||||
if (is_encoder) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
// The order of the filters is reversed in the
|
||||
// encoder. It allows more efficient handling
|
||||
// of the uncompressed data.
|
||||
const size_t j = count - i - 1;
|
||||
|
||||
const lzma_filter_coder *const fc
|
||||
= coder_find(options[i].id);
|
||||
if (fc == NULL || fc->init == NULL)
|
||||
return LZMA_HEADER_ERROR;
|
||||
|
||||
filters[j].init = fc->init;
|
||||
filters[j].options = options[i].options;
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
const lzma_filter_coder *const fc
|
||||
= coder_find(options[i].id);
|
||||
if (fc == NULL || fc->init == NULL)
|
||||
return LZMA_HEADER_ERROR;
|
||||
|
||||
filters[i].init = fc->init;
|
||||
filters[i].options = options[i].options;
|
||||
}
|
||||
}
|
||||
|
||||
// Terminate the array.
|
||||
filters[count].init = NULL;
|
||||
|
||||
// Initialize the filters.
|
||||
const lzma_ret ret = lzma_next_filter_init(next, allocator, filters);
|
||||
if (ret != LZMA_OK)
|
||||
lzma_next_end(next, allocator);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
extern uint64_t
|
||||
lzma_memusage_coder(lzma_filter_find coder_find,
|
||||
const lzma_filter *filters)
|
||||
{
|
||||
// The chain has to have at least one filter.
|
||||
if (filters[0].id == LZMA_VLI_VALUE_UNKNOWN)
|
||||
return UINT64_MAX;
|
||||
|
||||
uint64_t total = 0;
|
||||
size_t i = 0;
|
||||
|
||||
do {
|
||||
const lzma_filter_coder *const fc
|
||||
= coder_find(filters[i].id);
|
||||
if (fc == NULL)
|
||||
return UINT64_MAX; // Unsupported Filter ID
|
||||
|
||||
if (fc->memusage == NULL) {
|
||||
// This filter doesn't have a function to calculate
|
||||
// the memory usage. Such filters need only little
|
||||
// memory, so we use 1 KiB as a good estimate.
|
||||
total += 1024;
|
||||
} else {
|
||||
// Call the filter-specific memory usage calculation
|
||||
// function.
|
||||
const uint64_t usage
|
||||
= fc->memusage(filters[i].options);
|
||||
if (usage == UINT64_MAX)
|
||||
return UINT64_MAX; // Invalid options
|
||||
|
||||
total += usage;
|
||||
}
|
||||
} while (filters[++i].id != LZMA_VLI_VALUE_UNKNOWN);
|
||||
|
||||
// Add some fixed amount of extra. It's to compensate memory usage
|
||||
// of Stream, Block etc. coders, malloc() overhead, stack etc.
|
||||
return total + (1U << 15);
|
||||
}
|
||||
55
src/liblzma/common/filter_common.h
Normal file
55
src/liblzma/common/filter_common.h
Normal file
@@ -0,0 +1,55 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file filter_common.c
|
||||
/// \brief Filter-specific stuff common for both encoder and decoder
|
||||
//
|
||||
// Copyright (C) 2008 Lasse Collin
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_FILTER_COMMON_H
|
||||
#define LZMA_FILTER_COMMON_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
/// Both lzma_filter_encoder and lzma_filter_decoder begin with these members.
|
||||
typedef struct {
|
||||
/// Filter ID
|
||||
lzma_vli id;
|
||||
|
||||
/// Initializes the filter encoder and calls lzma_next_filter_init()
|
||||
/// for filters + 1.
|
||||
lzma_init_function init;
|
||||
|
||||
/// Calculates memory usage of the encoder. If the options are
|
||||
/// invalid, UINT64_MAX is returned.
|
||||
uint64_t (*memusage)(const void *options);
|
||||
|
||||
} lzma_filter_coder;
|
||||
|
||||
|
||||
typedef const lzma_filter_coder *(*lzma_filter_find)(lzma_vli id);
|
||||
|
||||
|
||||
extern lzma_ret lzma_raw_coder_init(
|
||||
lzma_next_coder *next, lzma_allocator *allocator,
|
||||
const lzma_filter *filters,
|
||||
lzma_filter_find coder_find, bool is_encoder);
|
||||
|
||||
|
||||
extern uint64_t lzma_memusage_coder(lzma_filter_find coder_find,
|
||||
const lzma_filter *filters);
|
||||
|
||||
|
||||
#endif
|
||||
206
src/liblzma/common/filter_decoder.c
Normal file
206
src/liblzma/common/filter_decoder.c
Normal file
@@ -0,0 +1,206 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file filter_decoder.c
|
||||
/// \brief Filter ID mapping to filter-specific functions
|
||||
//
|
||||
// Copyright (C) 2008 Lasse Collin
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "filter_decoder.h"
|
||||
#include "filter_common.h"
|
||||
#include "lzma_decoder.h"
|
||||
#include "lzma2_decoder.h"
|
||||
#include "subblock_decoder.h"
|
||||
#include "subblock_decoder_helper.h"
|
||||
#include "simple_decoder.h"
|
||||
#include "delta_decoder.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
/// Filter ID
|
||||
lzma_vli id;
|
||||
|
||||
/// Initializes the filter encoder and calls lzma_next_filter_init()
|
||||
/// for filters + 1.
|
||||
lzma_init_function init;
|
||||
|
||||
/// Calculates memory usage of the encoder. If the options are
|
||||
/// invalid, UINT64_MAX is returned.
|
||||
uint64_t (*memusage)(const void *options);
|
||||
|
||||
/// Decodes Filter Properties.
|
||||
///
|
||||
/// \return - LZMA_OK: Properties decoded successfully.
|
||||
/// - LZMA_HEADER_ERROR: Unsupported properties
|
||||
/// - LZMA_MEM_ERROR: Memory allocation failed.
|
||||
lzma_ret (*props_decode)(void **options, lzma_allocator *allocator,
|
||||
const uint8_t *props, size_t props_size);
|
||||
|
||||
} lzma_filter_decoder;
|
||||
|
||||
|
||||
static const lzma_filter_decoder decoders[] = {
|
||||
#ifdef HAVE_DECODER_LZMA
|
||||
{
|
||||
.id = LZMA_FILTER_LZMA,
|
||||
.init = &lzma_lzma_decoder_init,
|
||||
.memusage = &lzma_lzma_decoder_memusage,
|
||||
.props_decode = &lzma_lzma_props_decode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_DECODER_LZMA2
|
||||
{
|
||||
.id = LZMA_FILTER_LZMA2,
|
||||
.init = &lzma_lzma2_decoder_init,
|
||||
.memusage = &lzma_lzma2_decoder_memusage,
|
||||
.props_decode = &lzma_lzma2_props_decode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_DECODER_SUBBLOCK
|
||||
{
|
||||
.id = LZMA_FILTER_SUBBLOCK,
|
||||
.init = &lzma_subblock_decoder_init,
|
||||
// .memusage = &lzma_subblock_decoder_memusage,
|
||||
.props_decode = NULL,
|
||||
},
|
||||
{
|
||||
.id = LZMA_FILTER_SUBBLOCK_HELPER,
|
||||
.init = &lzma_subblock_decoder_helper_init,
|
||||
.memusage = NULL,
|
||||
.props_decode = NULL,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_DECODER_X86
|
||||
{
|
||||
.id = LZMA_FILTER_X86,
|
||||
.init = &lzma_simple_x86_decoder_init,
|
||||
.memusage = NULL,
|
||||
.props_decode = &lzma_simple_props_decode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_DECODER_POWERPC
|
||||
{
|
||||
.id = LZMA_FILTER_POWERPC,
|
||||
.init = &lzma_simple_powerpc_decoder_init,
|
||||
.memusage = NULL,
|
||||
.props_decode = &lzma_simple_props_decode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_DECODER_IA64
|
||||
{
|
||||
.id = LZMA_FILTER_IA64,
|
||||
.init = &lzma_simple_ia64_decoder_init,
|
||||
.memusage = NULL,
|
||||
.props_decode = &lzma_simple_props_decode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_DECODER_ARM
|
||||
{
|
||||
.id = LZMA_FILTER_ARM,
|
||||
.init = &lzma_simple_arm_decoder_init,
|
||||
.memusage = NULL,
|
||||
.props_decode = &lzma_simple_props_decode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_DECODER_ARMTHUMB
|
||||
{
|
||||
.id = LZMA_FILTER_ARMTHUMB,
|
||||
.init = &lzma_simple_armthumb_decoder_init,
|
||||
.memusage = NULL,
|
||||
.props_decode = &lzma_simple_props_decode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_DECODER_SPARC
|
||||
{
|
||||
.id = LZMA_FILTER_SPARC,
|
||||
.init = &lzma_simple_sparc_decoder_init,
|
||||
.memusage = NULL,
|
||||
.props_decode = &lzma_simple_props_decode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_DECODER_DELTA
|
||||
{
|
||||
.id = LZMA_FILTER_DELTA,
|
||||
.init = &lzma_delta_decoder_init,
|
||||
.memusage = NULL,
|
||||
.props_decode = &lzma_delta_props_decode,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
static const lzma_filter_decoder *
|
||||
decoder_find(lzma_vli id)
|
||||
{
|
||||
for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i)
|
||||
if (decoders[i].id == id)
|
||||
return decoders + i;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_bool
|
||||
lzma_filter_decoder_is_supported(lzma_vli id)
|
||||
{
|
||||
return decoder_find(id) != NULL;
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_raw_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
const lzma_filter *options)
|
||||
{
|
||||
return lzma_raw_coder_init(next, allocator,
|
||||
options, (lzma_filter_find)(&decoder_find), false);
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_ret
|
||||
lzma_raw_decoder(lzma_stream *strm, const lzma_filter *options)
|
||||
{
|
||||
lzma_next_strm_init(lzma_raw_decoder_init, strm, options);
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = true;
|
||||
strm->internal->supported_actions[LZMA_FINISH] = true;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API uint64_t
|
||||
lzma_memusage_decoder(const lzma_filter *filters)
|
||||
{
|
||||
return lzma_memusage_coder(
|
||||
(lzma_filter_find)(&decoder_find), filters);
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_ret
|
||||
lzma_properties_decode(lzma_filter *filter, lzma_allocator *allocator,
|
||||
const uint8_t *props, size_t props_size)
|
||||
{
|
||||
// Make it always NULL so that the caller can always safely free() it.
|
||||
filter->options = NULL;
|
||||
|
||||
const lzma_filter_decoder *const fd = decoder_find(filter->id);
|
||||
if (fd == NULL)
|
||||
return LZMA_HEADER_ERROR;
|
||||
|
||||
if (fd->props_decode == NULL)
|
||||
return props_size == 0 ? LZMA_OK : LZMA_HEADER_ERROR;
|
||||
|
||||
return fd->props_decode(
|
||||
&filter->options, allocator, props, props_size);
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file metadata_encoder.h
|
||||
/// \brief Encodes metadata to be stored into Metadata Blocks
|
||||
/// \file filter_decoder.c
|
||||
/// \brief Filter ID mapping to filter-specific functions
|
||||
//
|
||||
// Copyright (C) 2007 Lasse Collin
|
||||
// Copyright (C) 2008 Lasse Collin
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -17,14 +17,14 @@
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_METADATA_ENCODER_H
|
||||
#define LZMA_METADATA_ENCODER_H
|
||||
#ifndef LZMA_FILTER_DECODER_H
|
||||
#define LZMA_FILTER_DECODER_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
extern lzma_ret lzma_metadata_encoder_init(
|
||||
extern lzma_ret lzma_raw_decoder_init(
|
||||
lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_options_block *options, const lzma_metadata *metadata);
|
||||
const lzma_filter *options);
|
||||
|
||||
#endif
|
||||
278
src/liblzma/common/filter_encoder.c
Normal file
278
src/liblzma/common/filter_encoder.c
Normal file
@@ -0,0 +1,278 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file filter_decoder.c
|
||||
/// \brief Filter ID mapping to filter-specific functions
|
||||
//
|
||||
// Copyright (C) 2008 Lasse Collin
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "filter_encoder.h"
|
||||
#include "filter_common.h"
|
||||
#include "lzma_encoder.h"
|
||||
#include "lzma2_encoder.h"
|
||||
#include "subblock_encoder.h"
|
||||
#include "simple_encoder.h"
|
||||
#include "delta_encoder.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
/// Filter ID
|
||||
lzma_vli id;
|
||||
|
||||
/// Initializes the filter encoder and calls lzma_next_filter_init()
|
||||
/// for filters + 1.
|
||||
lzma_init_function init;
|
||||
|
||||
/// Calculates memory usage of the encoder. If the options are
|
||||
/// invalid, UINT64_MAX is returned.
|
||||
uint64_t (*memusage)(const void *options);
|
||||
|
||||
/// Calculates the minimum sane size for Blocks (or other types of
|
||||
/// chunks) to which the input data can be splitted to make
|
||||
/// multithreaded encoding possible. If this is NULL, it is assumed
|
||||
/// that the encoder is fast enough with single thread.
|
||||
lzma_vli (*chunk_size)(const void *options);
|
||||
|
||||
/// Tells the size of the Filter Properties field. If options are
|
||||
/// invalid, UINT32_MAX is returned. If this is NULL, props_size_fixed
|
||||
/// is used.
|
||||
lzma_ret (*props_size_get)(uint32_t *size, const void *options);
|
||||
uint32_t props_size_fixed;
|
||||
|
||||
/// Encodes Filter Properties.
|
||||
///
|
||||
/// \return - LZMA_OK: Properties encoded sucessfully.
|
||||
/// - LZMA_HEADER_ERROR: Unsupported options
|
||||
/// - LZMA_PROG_ERROR: Invalid options or not enough
|
||||
/// output space
|
||||
lzma_ret (*props_encode)(const void *options, uint8_t *out);
|
||||
|
||||
} lzma_filter_encoder;
|
||||
|
||||
|
||||
static const lzma_filter_encoder encoders[] = {
|
||||
#ifdef HAVE_ENCODER_LZMA
|
||||
{
|
||||
.id = LZMA_FILTER_LZMA,
|
||||
.init = &lzma_lzma_encoder_init,
|
||||
.memusage = &lzma_lzma_encoder_memusage,
|
||||
.chunk_size = NULL, // FIXME
|
||||
.props_size_get = NULL,
|
||||
.props_size_fixed = 5,
|
||||
.props_encode = &lzma_lzma_props_encode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_ENCODER_LZMA2
|
||||
{
|
||||
.id = LZMA_FILTER_LZMA2,
|
||||
.init = &lzma_lzma2_encoder_init,
|
||||
.memusage = &lzma_lzma2_encoder_memusage,
|
||||
.chunk_size = NULL, // FIXME
|
||||
.props_size_get = NULL,
|
||||
.props_size_fixed = 1,
|
||||
.props_encode = &lzma_lzma2_props_encode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_ENCODER_SUBBLOCK
|
||||
{
|
||||
.id = LZMA_FILTER_SUBBLOCK,
|
||||
.init = &lzma_subblock_encoder_init,
|
||||
// .memusage = &lzma_subblock_encoder_memusage,
|
||||
.chunk_size = NULL,
|
||||
.props_size_get = NULL,
|
||||
.props_size_fixed = 0,
|
||||
.props_encode = NULL,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_ENCODER_X86
|
||||
{
|
||||
.id = LZMA_FILTER_X86,
|
||||
.init = &lzma_simple_x86_encoder_init,
|
||||
.memusage = NULL,
|
||||
.chunk_size = NULL,
|
||||
.props_size_get = &lzma_simple_props_size,
|
||||
.props_encode = &lzma_simple_props_encode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_ENCODER_POWERPC
|
||||
{
|
||||
.id = LZMA_FILTER_POWERPC,
|
||||
.init = &lzma_simple_powerpc_encoder_init,
|
||||
.memusage = NULL,
|
||||
.chunk_size = NULL,
|
||||
.props_size_get = &lzma_simple_props_size,
|
||||
.props_encode = &lzma_simple_props_encode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_ENCODER_IA64
|
||||
{
|
||||
.id = LZMA_FILTER_IA64,
|
||||
.init = &lzma_simple_ia64_encoder_init,
|
||||
.memusage = NULL,
|
||||
.chunk_size = NULL,
|
||||
.props_size_get = &lzma_simple_props_size,
|
||||
.props_encode = &lzma_simple_props_encode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_ENCODER_ARM
|
||||
{
|
||||
.id = LZMA_FILTER_ARM,
|
||||
.init = &lzma_simple_arm_encoder_init,
|
||||
.memusage = NULL,
|
||||
.chunk_size = NULL,
|
||||
.props_size_get = &lzma_simple_props_size,
|
||||
.props_encode = &lzma_simple_props_encode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_ENCODER_ARMTHUMB
|
||||
{
|
||||
.id = LZMA_FILTER_ARMTHUMB,
|
||||
.init = &lzma_simple_armthumb_encoder_init,
|
||||
.memusage = NULL,
|
||||
.chunk_size = NULL,
|
||||
.props_size_get = &lzma_simple_props_size,
|
||||
.props_encode = &lzma_simple_props_encode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_ENCODER_SPARC
|
||||
{
|
||||
.id = LZMA_FILTER_SPARC,
|
||||
.init = &lzma_simple_sparc_encoder_init,
|
||||
.memusage = NULL,
|
||||
.chunk_size = NULL,
|
||||
.props_size_get = &lzma_simple_props_size,
|
||||
.props_encode = &lzma_simple_props_encode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_ENCODER_DELTA
|
||||
{
|
||||
.id = LZMA_FILTER_DELTA,
|
||||
.init = &lzma_delta_encoder_init,
|
||||
.memusage = NULL,
|
||||
.chunk_size = NULL,
|
||||
.props_size_get = NULL,
|
||||
.props_size_fixed = 1,
|
||||
.props_encode = &lzma_delta_props_encode,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
static const lzma_filter_encoder *
|
||||
encoder_find(lzma_vli id)
|
||||
{
|
||||
for (size_t i = 0; i < ARRAY_SIZE(encoders); ++i)
|
||||
if (encoders[i].id == id)
|
||||
return encoders + i;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_bool
|
||||
lzma_filter_encoder_is_supported(lzma_vli id)
|
||||
{
|
||||
return encoder_find(id) != NULL;
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_raw_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
const lzma_filter *options)
|
||||
{
|
||||
return lzma_raw_coder_init(next, allocator,
|
||||
options, (lzma_filter_find)(&encoder_find), true);
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_ret
|
||||
lzma_raw_encoder(lzma_stream *strm, const lzma_filter *options)
|
||||
{
|
||||
lzma_next_strm_init(lzma_raw_coder_init, strm, options,
|
||||
(lzma_filter_find)(&encoder_find), true);
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = true;
|
||||
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
|
||||
strm->internal->supported_actions[LZMA_FINISH] = true;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API uint64_t
|
||||
lzma_memusage_encoder(const lzma_filter *filters)
|
||||
{
|
||||
return lzma_memusage_coder(
|
||||
(lzma_filter_find)(&encoder_find), filters);
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_vli
|
||||
lzma_chunk_size(const lzma_filter *filters)
|
||||
{
|
||||
lzma_vli max = 0;
|
||||
|
||||
for (size_t i = 0; filters[i].id != LZMA_VLI_VALUE_UNKNOWN; ++i) {
|
||||
const lzma_filter_encoder *const fe
|
||||
= encoder_find(filters[i].id);
|
||||
if (fe->chunk_size != NULL) {
|
||||
const lzma_vli size
|
||||
= fe->chunk_size(filters[i].options);
|
||||
if (size == LZMA_VLI_VALUE_UNKNOWN)
|
||||
return LZMA_VLI_VALUE_UNKNOWN;
|
||||
|
||||
if (size > max)
|
||||
max = size;
|
||||
}
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_ret
|
||||
lzma_properties_size(uint32_t *size, const lzma_filter *filter)
|
||||
{
|
||||
const lzma_filter_encoder *const fe = encoder_find(filter->id);
|
||||
if (fe == NULL) {
|
||||
// Unknown filter - if the Filter ID is a proper VLI,
|
||||
// return LZMA_HEADER_ERROR instead of LZMA_PROG_ERROR,
|
||||
// because it's possible that we just don't have support
|
||||
// compiled in for the requested filter.
|
||||
return filter->id <= LZMA_VLI_VALUE_MAX
|
||||
? LZMA_HEADER_ERROR : LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
if (fe->props_size_get == NULL) {
|
||||
// No props_size_get() function, use props_size_fixed.
|
||||
*size = fe->props_size_fixed;
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
return fe->props_size_get(size, filter->options);
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_ret
|
||||
lzma_properties_encode(const lzma_filter *filter, uint8_t *props)
|
||||
{
|
||||
const lzma_filter_encoder *const fe = encoder_find(filter->id);
|
||||
if (fe == NULL)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (fe->props_encode == NULL)
|
||||
return LZMA_OK;
|
||||
|
||||
return fe->props_encode(filter->options, props);
|
||||
}
|
||||
34
src/liblzma/common/filter_encoder.h
Normal file
34
src/liblzma/common/filter_encoder.h
Normal file
@@ -0,0 +1,34 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file filter_encoder.c
|
||||
/// \brief Filter ID mapping to filter-specific functions
|
||||
//
|
||||
// Copyright (C) 2008 Lasse Collin
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_FILTER_ENCODER_H
|
||||
#define LZMA_FILTER_ENCODER_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
// FIXME !!! Public API
|
||||
extern lzma_vli lzma_chunk_size(const lzma_filter *filters);
|
||||
|
||||
|
||||
extern lzma_ret lzma_raw_encoder_init(
|
||||
lzma_next_coder *next, lzma_allocator *allocator,
|
||||
const lzma_filter *options);
|
||||
|
||||
#endif
|
||||
@@ -17,366 +17,37 @@
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "common.h"
|
||||
#include "lzma_decoder.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
lzma_options_filter *options;
|
||||
|
||||
enum {
|
||||
SEQ_MISC,
|
||||
SEQ_ID,
|
||||
SEQ_SIZE,
|
||||
SEQ_PROPERTIES,
|
||||
} sequence;
|
||||
|
||||
/// \brief Position in variable-length integers
|
||||
size_t pos;
|
||||
|
||||
/// \brief Size of Filter Properties
|
||||
lzma_vli properties_size;
|
||||
};
|
||||
|
||||
|
||||
#ifdef HAVE_FILTER_SUBBLOCK
|
||||
static lzma_ret
|
||||
properties_subblock(lzma_coder *coder, lzma_allocator *allocator,
|
||||
const uint8_t *in lzma_attribute((unused)),
|
||||
size_t *in_pos lzma_attribute((unused)),
|
||||
size_t in_size lzma_attribute((unused)))
|
||||
{
|
||||
if (coder->properties_size != 0)
|
||||
return LZMA_HEADER_ERROR;
|
||||
|
||||
coder->options->options = lzma_alloc(
|
||||
sizeof(lzma_options_subblock), allocator);
|
||||
if (coder->options->options == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
((lzma_options_subblock *)(coder->options->options))
|
||||
->allow_subfilters = true;
|
||||
return LZMA_STREAM_END;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_FILTER_SIMPLE
|
||||
static lzma_ret
|
||||
properties_simple(lzma_coder *coder, lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t *in_pos, size_t in_size)
|
||||
{
|
||||
if (coder->properties_size == 0)
|
||||
return LZMA_STREAM_END;
|
||||
|
||||
if (coder->properties_size != 4)
|
||||
return LZMA_HEADER_ERROR;
|
||||
|
||||
lzma_options_simple *options = coder->options->options;
|
||||
|
||||
if (options == NULL) {
|
||||
options = lzma_alloc(sizeof(lzma_options_simple), allocator);
|
||||
if (options == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
options->start_offset = 0;
|
||||
coder->options->options = options;
|
||||
}
|
||||
|
||||
while (coder->pos < 4) {
|
||||
if (*in_pos == in_size)
|
||||
return LZMA_OK;
|
||||
|
||||
options->start_offset
|
||||
|= (uint32_t)(in[*in_pos]) << (8 * coder->pos);
|
||||
++*in_pos;
|
||||
++coder->pos;
|
||||
}
|
||||
|
||||
// Don't leave an options structure allocated if start_offset is zero.
|
||||
if (options->start_offset == 0) {
|
||||
lzma_free(options, allocator);
|
||||
coder->options->options = NULL;
|
||||
}
|
||||
|
||||
return LZMA_STREAM_END;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_FILTER_DELTA
|
||||
static lzma_ret
|
||||
properties_delta(lzma_coder *coder, lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t *in_pos, size_t in_size)
|
||||
{
|
||||
if (coder->properties_size != 1)
|
||||
return LZMA_HEADER_ERROR;
|
||||
|
||||
if (*in_pos == in_size)
|
||||
return LZMA_OK;
|
||||
|
||||
lzma_options_delta *options = lzma_alloc(
|
||||
sizeof(lzma_options_delta), allocator);
|
||||
if (options == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
coder->options->options = options;
|
||||
|
||||
options->distance = (uint32_t)(in[*in_pos]) + 1;
|
||||
++*in_pos;
|
||||
|
||||
return LZMA_STREAM_END;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_FILTER_LZMA
|
||||
static lzma_ret
|
||||
properties_lzma(lzma_coder *coder, lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t *in_pos, size_t in_size)
|
||||
{
|
||||
// LZMA properties are always two bytes (at least for now).
|
||||
if (coder->properties_size != 2)
|
||||
return LZMA_HEADER_ERROR;
|
||||
|
||||
assert(coder->pos < 2);
|
||||
|
||||
while (*in_pos < in_size) {
|
||||
switch (coder->pos) {
|
||||
case 0:
|
||||
// Allocate the options structure.
|
||||
coder->options->options = lzma_alloc(
|
||||
sizeof(lzma_options_lzma), allocator);
|
||||
if (coder->options->options == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
// Decode lc, lp, and pb.
|
||||
if (lzma_lzma_decode_properties(
|
||||
coder->options->options, in[*in_pos]))
|
||||
return LZMA_HEADER_ERROR;
|
||||
|
||||
++*in_pos;
|
||||
++coder->pos;
|
||||
break;
|
||||
|
||||
case 1: {
|
||||
lzma_options_lzma *options = coder->options->options;
|
||||
|
||||
// Check that reserved bits are unset.
|
||||
if (in[*in_pos] & 0xC0)
|
||||
return LZMA_HEADER_ERROR;
|
||||
|
||||
// Decode the dictionary size. See the file format
|
||||
// specification section 4.3.4.2 to understand this.
|
||||
if (in[*in_pos] == 0) {
|
||||
options->dictionary_size = 1;
|
||||
|
||||
} else if (in[*in_pos] > 59) {
|
||||
// Dictionary size is over 1 GiB.
|
||||
// It's not supported at the moment.
|
||||
return LZMA_HEADER_ERROR;
|
||||
# if LZMA_DICTIONARY_SIZE_MAX != UINT32_C(1) << 30
|
||||
# error Update the if()-condition a few lines
|
||||
# error above to match LZMA_DICTIONARY_SIZE_MAX.
|
||||
# endif
|
||||
|
||||
} else {
|
||||
options->dictionary_size
|
||||
= 2 | ((in[*in_pos] + 1) & 1);
|
||||
options->dictionary_size
|
||||
<<= (in[*in_pos] - 1) / 2;
|
||||
}
|
||||
|
||||
++*in_pos;
|
||||
return LZMA_STREAM_END;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(coder->pos < 2);
|
||||
return LZMA_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static lzma_ret
|
||||
filter_flags_decode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
size_t in_size, uint8_t *restrict out lzma_attribute((unused)),
|
||||
size_t *restrict out_pos lzma_attribute((unused)),
|
||||
size_t out_size lzma_attribute((unused)),
|
||||
lzma_action action lzma_attribute((unused)))
|
||||
{
|
||||
while (*in_pos < in_size || coder->sequence == SEQ_PROPERTIES)
|
||||
switch (coder->sequence) {
|
||||
case SEQ_MISC:
|
||||
// Determine the Filter ID and Size of Filter Properties.
|
||||
if (in[*in_pos] >= 0xE0) {
|
||||
// Using External ID. Prepare the ID
|
||||
// for variable-length integer parsing.
|
||||
coder->options->id = 0;
|
||||
|
||||
if (in[*in_pos] == 0xFF) {
|
||||
// Mark that Size of Filter Properties is
|
||||
// unknown, so we know later that there is
|
||||
// external Size of Filter Properties present.
|
||||
coder->properties_size
|
||||
= LZMA_VLI_VALUE_UNKNOWN;
|
||||
} else {
|
||||
// Take Size of Filter Properties from Misc.
|
||||
coder->properties_size = in[*in_pos] - 0xE0;
|
||||
}
|
||||
|
||||
coder->sequence = SEQ_ID;
|
||||
|
||||
} else {
|
||||
// The Filter ID is the same as Misc.
|
||||
coder->options->id = in[*in_pos];
|
||||
|
||||
// The Size of Filter Properties can be calculated
|
||||
// from Misc too.
|
||||
coder->properties_size = in[*in_pos] / 0x20;
|
||||
|
||||
coder->sequence = SEQ_PROPERTIES;
|
||||
}
|
||||
|
||||
++*in_pos;
|
||||
break;
|
||||
|
||||
case SEQ_ID: {
|
||||
const lzma_ret ret = lzma_vli_decode(&coder->options->id,
|
||||
&coder->pos, in, in_pos, in_size);
|
||||
if (ret != LZMA_STREAM_END)
|
||||
return ret;
|
||||
|
||||
if (coder->properties_size == LZMA_VLI_VALUE_UNKNOWN) {
|
||||
// We have also external Size of Filter
|
||||
// Properties. Prepare the size for
|
||||
// variable-length integer parsing.
|
||||
coder->properties_size = 0;
|
||||
coder->sequence = SEQ_SIZE;
|
||||
} else {
|
||||
coder->sequence = SEQ_PROPERTIES;
|
||||
}
|
||||
|
||||
// Reset pos for its next job.
|
||||
coder->pos = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case SEQ_SIZE: {
|
||||
const lzma_ret ret = lzma_vli_decode(&coder->properties_size,
|
||||
&coder->pos, in, in_pos, in_size);
|
||||
if (ret != LZMA_STREAM_END)
|
||||
return ret;
|
||||
|
||||
coder->pos = 0;
|
||||
coder->sequence = SEQ_PROPERTIES;
|
||||
break;
|
||||
}
|
||||
|
||||
case SEQ_PROPERTIES: {
|
||||
lzma_ret (*get_properties)(lzma_coder *coder,
|
||||
lzma_allocator *allocator, const uint8_t *in,
|
||||
size_t *in_pos, size_t in_size);
|
||||
|
||||
switch (coder->options->id) {
|
||||
#ifdef HAVE_FILTER_COPY
|
||||
case LZMA_FILTER_COPY:
|
||||
return coder->properties_size > 0
|
||||
? LZMA_HEADER_ERROR : LZMA_STREAM_END;
|
||||
#endif
|
||||
#ifdef HAVE_FILTER_SUBBLOCK
|
||||
case LZMA_FILTER_SUBBLOCK:
|
||||
get_properties = &properties_subblock;
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_FILTER_SIMPLE
|
||||
# ifdef HAVE_FILTER_X86
|
||||
case LZMA_FILTER_X86:
|
||||
# endif
|
||||
# ifdef HAVE_FILTER_POWERPC
|
||||
case LZMA_FILTER_POWERPC:
|
||||
# endif
|
||||
# ifdef HAVE_FILTER_IA64
|
||||
case LZMA_FILTER_IA64:
|
||||
# endif
|
||||
# ifdef HAVE_FILTER_ARM
|
||||
case LZMA_FILTER_ARM:
|
||||
# endif
|
||||
# ifdef HAVE_FILTER_ARMTHUMB
|
||||
case LZMA_FILTER_ARMTHUMB:
|
||||
# endif
|
||||
# ifdef HAVE_FILTER_SPARC
|
||||
case LZMA_FILTER_SPARC:
|
||||
# endif
|
||||
get_properties = &properties_simple;
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_FILTER_DELTA
|
||||
case LZMA_FILTER_DELTA:
|
||||
get_properties = &properties_delta;
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_FILTER_LZMA
|
||||
case LZMA_FILTER_LZMA:
|
||||
get_properties = &properties_lzma;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return LZMA_HEADER_ERROR;
|
||||
}
|
||||
|
||||
return get_properties(coder, allocator, in, in_pos, in_size);
|
||||
}
|
||||
|
||||
default:
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
filter_flags_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
{
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_filter_flags_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, lzma_options_filter *options)
|
||||
{
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->code = &filter_flags_decode;
|
||||
next->end = &filter_flags_decoder_end;
|
||||
}
|
||||
|
||||
options->id = 0;
|
||||
options->options = NULL;
|
||||
|
||||
next->coder->options = options;
|
||||
next->coder->sequence = SEQ_MISC;
|
||||
next->coder->pos = 0;
|
||||
next->coder->properties_size = 0;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
#include "filter_decoder.h"
|
||||
|
||||
|
||||
extern LZMA_API lzma_ret
|
||||
lzma_filter_flags_decoder(lzma_stream *strm, lzma_options_filter *options)
|
||||
lzma_filter_flags_decode(
|
||||
lzma_filter *filter, lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t *in_pos, size_t in_size)
|
||||
{
|
||||
lzma_next_strm_init(strm, lzma_filter_flags_decoder_init, options);
|
||||
// Set the pointer to NULL so the caller can always safely free it.
|
||||
filter->options = NULL;
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = true;
|
||||
// Filter ID
|
||||
return_if_error(lzma_vli_decode(&filter->id, NULL,
|
||||
in, in_pos, in_size));
|
||||
|
||||
return LZMA_OK;
|
||||
if (filter->id >= LZMA_FILTER_RESERVED_START)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
// Size of Properties
|
||||
lzma_vli props_size;
|
||||
return_if_error(lzma_vli_decode(&props_size, NULL,
|
||||
in, in_pos, in_size));
|
||||
|
||||
// Filter Properties
|
||||
if (in_size - *in_pos < props_size)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
const lzma_ret ret = lzma_properties_decode(
|
||||
filter, allocator, in + *in_pos, props_size);
|
||||
|
||||
*in_pos += props_size;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -17,343 +17,47 @@
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "common.h"
|
||||
#include "lzma_encoder.h"
|
||||
#include "filter_encoder.h"
|
||||
|
||||
|
||||
/// \brief Calculates the size of the Filter Properties field
|
||||
///
|
||||
/// This currently can return only LZMA_OK or LZMA_HEADER_ERROR, but
|
||||
/// with some new filters it may return also LZMA_PROG_ERROR.
|
||||
static lzma_ret
|
||||
get_properties_size(uint32_t *size, const lzma_options_filter *options)
|
||||
extern LZMA_API lzma_ret
|
||||
lzma_filter_flags_size(uint32_t *size, const lzma_filter *filter)
|
||||
{
|
||||
lzma_ret ret = LZMA_OK;
|
||||
if (filter->id >= LZMA_FILTER_RESERVED_START)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
switch (options->id) {
|
||||
#ifdef HAVE_FILTER_COPY
|
||||
case LZMA_FILTER_COPY:
|
||||
*size = 0;
|
||||
break;
|
||||
#endif
|
||||
return_if_error(lzma_properties_size(size, filter));
|
||||
|
||||
#ifdef HAVE_FILTER_SUBBLOCK
|
||||
case LZMA_FILTER_SUBBLOCK:
|
||||
*size = 0;
|
||||
break;
|
||||
#endif
|
||||
*size += lzma_vli_size(filter->id) + lzma_vli_size(*size);
|
||||
|
||||
#ifdef HAVE_FILTER_SIMPLE
|
||||
# ifdef HAVE_FILTER_X86
|
||||
case LZMA_FILTER_X86:
|
||||
# endif
|
||||
# ifdef HAVE_FILTER_POWERPC
|
||||
case LZMA_FILTER_POWERPC:
|
||||
# endif
|
||||
# ifdef HAVE_FILTER_IA64
|
||||
case LZMA_FILTER_IA64:
|
||||
# endif
|
||||
# ifdef HAVE_FILTER_ARM
|
||||
case LZMA_FILTER_ARM:
|
||||
# endif
|
||||
# ifdef HAVE_FILTER_ARMTHUMB
|
||||
case LZMA_FILTER_ARMTHUMB:
|
||||
# endif
|
||||
# ifdef HAVE_FILTER_SPARC
|
||||
case LZMA_FILTER_SPARC:
|
||||
# endif
|
||||
if (options->options == NULL || ((const lzma_options_simple *)(
|
||||
options->options))->start_offset == 0)
|
||||
*size = 0;
|
||||
else
|
||||
*size = 4;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FILTER_DELTA
|
||||
case LZMA_FILTER_DELTA:
|
||||
*size = 1;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FILTER_LZMA
|
||||
case LZMA_FILTER_LZMA:
|
||||
*size = 2;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
// Unknown filter - if the Filter ID is a proper VLI,
|
||||
// return LZMA_HEADER_ERROR instead of LZMA_PROG_ERROR,
|
||||
// because it's possible that we just don't have support
|
||||
// compiled in for the requested filter.
|
||||
ret = options->id <= LZMA_VLI_VALUE_MAX
|
||||
? LZMA_HEADER_ERROR : LZMA_PROG_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_ret
|
||||
lzma_filter_flags_size(uint32_t *size, const lzma_options_filter *options)
|
||||
lzma_filter_flags_encode(const lzma_filter *filter,
|
||||
uint8_t *out, size_t *out_pos, size_t out_size)
|
||||
{
|
||||
// Get size of Filter Properties.
|
||||
uint32_t prop_size;
|
||||
const lzma_ret ret = get_properties_size(&prop_size, options);
|
||||
if (ret != LZMA_OK)
|
||||
return ret;
|
||||
|
||||
// Size of Filter ID field if it exists.
|
||||
size_t id_size;
|
||||
size_t prop_size_size;
|
||||
if (options->id < 0xE0
|
||||
&& (lzma_vli)(prop_size) == options->id / 0x20) {
|
||||
// ID and Size of Filter Properties fit into Misc.
|
||||
id_size = 0;
|
||||
prop_size_size = 0;
|
||||
|
||||
} else {
|
||||
// At least Filter ID is stored using the External ID field.
|
||||
id_size = lzma_vli_size(options->id);
|
||||
if (id_size == 0)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (prop_size <= 30) {
|
||||
// Size of Filter Properties fits into Misc still.
|
||||
prop_size_size = 0;
|
||||
} else {
|
||||
// The Size of Filter Properties field is used too.
|
||||
prop_size_size = lzma_vli_size(prop_size);
|
||||
if (prop_size_size == 0)
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// 1 is for the Misc field.
|
||||
*size = 1 + id_size + prop_size_size + prop_size;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_FILTER_SIMPLE
|
||||
/// Encodes Filter Properties of the so called simple filters
|
||||
static lzma_ret
|
||||
properties_simple(uint8_t *out, size_t *out_pos, size_t out_size,
|
||||
const lzma_options_simple *options)
|
||||
{
|
||||
if (options == NULL || options->start_offset == 0)
|
||||
return LZMA_OK;
|
||||
|
||||
if (out_size - *out_pos < 4)
|
||||
return LZMA_BUF_ERROR;
|
||||
|
||||
for (size_t i = 0; i < 4; ++i)
|
||||
out[(*out_pos)++] = options->start_offset >> (i * 8);
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_FILTER_DELTA
|
||||
/// Encodes Filter Properties of the Delta filter
|
||||
static lzma_ret
|
||||
properties_delta(uint8_t *out, size_t *out_pos, size_t out_size,
|
||||
const lzma_options_delta *options)
|
||||
{
|
||||
if (options == NULL)
|
||||
// Filter ID
|
||||
if (filter->id >= LZMA_FILTER_RESERVED_START)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// It's possible that newer liblzma versions will support larger
|
||||
// distance values.
|
||||
if (options->distance < LZMA_DELTA_DISTANCE_MIN
|
||||
|| options->distance > LZMA_DELTA_DISTANCE_MAX)
|
||||
return LZMA_HEADER_ERROR;
|
||||
return_if_error(lzma_vli_encode(filter->id, NULL,
|
||||
out, out_pos, out_size));
|
||||
|
||||
if (out_size - *out_pos < 1)
|
||||
return LZMA_BUF_ERROR;
|
||||
|
||||
out[*out_pos] = options->distance - LZMA_DELTA_DISTANCE_MIN;
|
||||
++*out_pos;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_FILTER_LZMA
|
||||
/// Encodes LZMA Properties and Dictionary Flags (two bytes)
|
||||
static lzma_ret
|
||||
properties_lzma(uint8_t *out, size_t *out_pos, size_t out_size,
|
||||
const lzma_options_lzma *options)
|
||||
{
|
||||
if (options == NULL)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (out_size - *out_pos < 2)
|
||||
return LZMA_BUF_ERROR;
|
||||
|
||||
// LZMA Properties
|
||||
if (lzma_lzma_encode_properties(options, out + *out_pos))
|
||||
return LZMA_HEADER_ERROR;
|
||||
|
||||
++*out_pos;
|
||||
|
||||
// Dictionary flags
|
||||
//
|
||||
// Dictionary size is encoded using six bits of
|
||||
// which one is mantissa and five are exponent.
|
||||
//
|
||||
// There are some limits that must hold to keep
|
||||
// this coding working.
|
||||
# if LZMA_DICTIONARY_SIZE_MAX > UINT32_MAX / 2
|
||||
# error LZMA_DICTIONARY_SIZE_MAX is too big.
|
||||
# endif
|
||||
# if LZMA_DICTIONARY_SIZE_MIN < 1
|
||||
# error LZMA_DICTIONARY_SIZE_MIN cannot be zero.
|
||||
# endif
|
||||
|
||||
// Validate it:
|
||||
if (options->dictionary_size < LZMA_DICTIONARY_SIZE_MIN
|
||||
|| options->dictionary_size > LZMA_DICTIONARY_SIZE_MAX)
|
||||
return LZMA_HEADER_ERROR;
|
||||
|
||||
if (options->dictionary_size == 1) {
|
||||
// Special case
|
||||
out[*out_pos] = 0x00;
|
||||
} else {
|
||||
// TODO This could be more elegant.
|
||||
uint32_t i = 1;
|
||||
while (((2 | ((i + 1) & 1)) << ((i - 1) / 2))
|
||||
< options->dictionary_size)
|
||||
++i;
|
||||
out[*out_pos] = i;
|
||||
}
|
||||
|
||||
++*out_pos;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
extern LZMA_API lzma_ret
|
||||
lzma_filter_flags_encode(uint8_t *out, size_t *out_pos, size_t out_size,
|
||||
const lzma_options_filter *options)
|
||||
{
|
||||
// Minimum output is one byte (everything fits into Misc).
|
||||
// The caller should have checked that there is enough output space,
|
||||
// so we return LZMA_PROG_ERROR instead of LZMA_BUF_ERROR.
|
||||
if (*out_pos >= out_size)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Get size of Filter Properties.
|
||||
uint32_t prop_size;
|
||||
lzma_ret ret = get_properties_size(&prop_size, options);
|
||||
if (ret != LZMA_OK)
|
||||
return ret;
|
||||
|
||||
// Misc, External ID, and Size of Properties
|
||||
if (options->id < 0xE0
|
||||
&& (lzma_vli)(prop_size) == options->id / 0x20) {
|
||||
// ID and Size of Filter Properties fit into Misc.
|
||||
out[*out_pos] = options->id;
|
||||
++*out_pos;
|
||||
|
||||
} else if (prop_size <= 30) {
|
||||
// Size of Filter Properties fits into Misc.
|
||||
out[*out_pos] = prop_size + 0xE0;
|
||||
++*out_pos;
|
||||
|
||||
// External ID is used to encode the Filter ID. If encoding
|
||||
// the VLI fails, it's because the caller has given as too
|
||||
// little output space, which it should have checked already.
|
||||
// So return LZMA_PROG_ERROR, not LZMA_BUF_ERROR.
|
||||
size_t dummy = 0;
|
||||
if (lzma_vli_encode(options->id, &dummy, 1,
|
||||
out, out_pos, out_size) != LZMA_STREAM_END)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
} else {
|
||||
// Nothing fits into Misc.
|
||||
out[*out_pos] = 0xFF;
|
||||
++*out_pos;
|
||||
|
||||
// External ID is used to encode the Filter ID.
|
||||
size_t dummy = 0;
|
||||
if (lzma_vli_encode(options->id, &dummy, 1,
|
||||
out, out_pos, out_size) != LZMA_STREAM_END)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// External Size of Filter Properties
|
||||
dummy = 0;
|
||||
if (lzma_vli_encode(prop_size, &dummy, 1,
|
||||
out, out_pos, out_size) != LZMA_STREAM_END)
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
// Size of Properties
|
||||
uint32_t props_size;
|
||||
return_if_error(lzma_properties_size(&props_size, filter));
|
||||
return_if_error(lzma_vli_encode(props_size, NULL,
|
||||
out, out_pos, out_size));
|
||||
|
||||
// Filter Properties
|
||||
switch (options->id) {
|
||||
#ifdef HAVE_FILTER_COPY
|
||||
case LZMA_FILTER_COPY:
|
||||
assert(prop_size == 0);
|
||||
ret = options->options == NULL ? LZMA_OK : LZMA_HEADER_ERROR;
|
||||
break;
|
||||
#endif
|
||||
if (out_size - *out_pos < props_size)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
#ifdef HAVE_FILTER_SUBBLOCK
|
||||
case LZMA_FILTER_SUBBLOCK:
|
||||
assert(prop_size == 0);
|
||||
ret = LZMA_OK;
|
||||
break;
|
||||
#endif
|
||||
return_if_error(lzma_properties_encode(filter, out + *out_pos));
|
||||
|
||||
#ifdef HAVE_FILTER_SIMPLE
|
||||
# ifdef HAVE_FILTER_X86
|
||||
case LZMA_FILTER_X86:
|
||||
# endif
|
||||
# ifdef HAVE_FILTER_POWERPC
|
||||
case LZMA_FILTER_POWERPC:
|
||||
# endif
|
||||
# ifdef HAVE_FILTER_IA64
|
||||
case LZMA_FILTER_IA64:
|
||||
# endif
|
||||
# ifdef HAVE_FILTER_ARM
|
||||
case LZMA_FILTER_ARM:
|
||||
# endif
|
||||
# ifdef HAVE_FILTER_ARMTHUMB
|
||||
case LZMA_FILTER_ARMTHUMB:
|
||||
# endif
|
||||
# ifdef HAVE_FILTER_SPARC
|
||||
case LZMA_FILTER_SPARC:
|
||||
# endif
|
||||
ret = properties_simple(out, out_pos, out_size,
|
||||
options->options);
|
||||
break;
|
||||
#endif
|
||||
*out_pos += props_size;
|
||||
|
||||
#ifdef HAVE_FILTER_DELTA
|
||||
case LZMA_FILTER_DELTA:
|
||||
ret = properties_delta(out, out_pos, out_size,
|
||||
options->options);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FILTER_LZMA
|
||||
case LZMA_FILTER_LZMA:
|
||||
ret = properties_lzma(out, out_pos, out_size,
|
||||
options->options);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
ret = LZMA_PROG_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file index.c
|
||||
/// \brief Handling of Index in Metadata
|
||||
/// \brief Handling of Index
|
||||
//
|
||||
// Copyright (C) 2007 Lasse Collin
|
||||
//
|
||||
@@ -17,124 +17,733 @@
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "common.h"
|
||||
#include "index.h"
|
||||
|
||||
|
||||
/**
|
||||
* \brief Duplicates an Index list
|
||||
*
|
||||
* \return A copy of the Index list, or NULL if memory allocation
|
||||
* failed or the original Index was empty.
|
||||
*/
|
||||
extern LZMA_API lzma_index *
|
||||
lzma_index_dup(const lzma_index *old_current, lzma_allocator *allocator)
|
||||
/// Number of Records to allocate at once.
|
||||
#define INDEX_GROUP_SIZE 256
|
||||
|
||||
|
||||
typedef struct lzma_index_group_s lzma_index_group;
|
||||
struct lzma_index_group_s {
|
||||
/// Next group
|
||||
lzma_index_group *prev;
|
||||
|
||||
/// Previous group
|
||||
lzma_index_group *next;
|
||||
|
||||
/// Index of the last Record in this group
|
||||
size_t last;
|
||||
|
||||
/// Total Size fields as cumulative sum relative to the beginning
|
||||
/// of the group. The total size of the group is total_sums[last].
|
||||
lzma_vli total_sums[INDEX_GROUP_SIZE];
|
||||
|
||||
/// Uncompressed Size fields as cumulative sum relative to the
|
||||
/// beginning of the group. The uncompressed size of the group is
|
||||
/// uncompressed_sums[last].
|
||||
lzma_vli uncompressed_sums[INDEX_GROUP_SIZE];
|
||||
|
||||
/// True if the Record is padding
|
||||
bool paddings[INDEX_GROUP_SIZE];
|
||||
};
|
||||
|
||||
|
||||
struct lzma_index_s {
|
||||
/// Total size of the Blocks and padding
|
||||
lzma_vli total_size;
|
||||
|
||||
/// Uncompressed size of the Stream
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
/// Number of non-padding records. This is needed by Index encoder.
|
||||
lzma_vli count;
|
||||
|
||||
/// Size of the List of Records field; this is updated every time
|
||||
/// a new non-padding Record is added.
|
||||
lzma_vli index_list_size;
|
||||
|
||||
/// This is zero if no Indexes have been combined with
|
||||
/// lzma_index_cat(). With combined Indexes, this contains the sizes
|
||||
/// of all but latest the Streams, including possible Stream Padding
|
||||
/// fields.
|
||||
lzma_vli padding_size;
|
||||
|
||||
/// First group of Records
|
||||
lzma_index_group *head;
|
||||
|
||||
/// Last group of Records
|
||||
lzma_index_group *tail;
|
||||
|
||||
/// Tracking the read position
|
||||
struct {
|
||||
/// Group where the current read position is.
|
||||
lzma_index_group *group;
|
||||
|
||||
/// The most recently read record in *group
|
||||
lzma_vli record;
|
||||
|
||||
/// Uncompressed offset of the beginning of *group relative
|
||||
/// to the beginning of the Stream
|
||||
lzma_vli uncompressed_offset;
|
||||
|
||||
/// Compressed offset of the beginning of *group relative
|
||||
/// to the beginning of the Stream
|
||||
lzma_vli stream_offset;
|
||||
} current;
|
||||
|
||||
/// Information about earlier Indexes when multiple Indexes have
|
||||
/// been combined.
|
||||
struct {
|
||||
/// Sum of the Record counts of the all but the last Stream.
|
||||
lzma_vli count;
|
||||
|
||||
/// Sum of the List of Records fields of all but the last
|
||||
/// Stream. This is needed when a new Index is concatenated
|
||||
/// to this lzma_index structure.
|
||||
lzma_vli index_list_size;
|
||||
} old;
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
free_index_list(lzma_index *i, lzma_allocator *allocator)
|
||||
{
|
||||
lzma_index *new_head = NULL;
|
||||
lzma_index *new_current = NULL;
|
||||
lzma_index_group *g = i->head;
|
||||
|
||||
while (old_current != NULL) {
|
||||
lzma_index *i = lzma_alloc(sizeof(lzma_index), allocator);
|
||||
if (i == NULL) {
|
||||
lzma_index_free(new_head, allocator);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
i->total_size = old_current->total_size;
|
||||
i->uncompressed_size = old_current->uncompressed_size;
|
||||
i->next = NULL;
|
||||
|
||||
if (new_head == NULL)
|
||||
new_head = i;
|
||||
else
|
||||
new_current->next = i;
|
||||
|
||||
new_current = i;
|
||||
old_current = old_current->next;
|
||||
}
|
||||
|
||||
return new_head;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Frees an Index list
|
||||
*
|
||||
* All Index Recors in the list are freed. This function is convenient when
|
||||
* getting rid of lzma_metadata structures containing an Index.
|
||||
*/
|
||||
extern LZMA_API void
|
||||
lzma_index_free(lzma_index *i, lzma_allocator *allocator)
|
||||
{
|
||||
while (i != NULL) {
|
||||
lzma_index *tmp = i->next;
|
||||
lzma_free(i, allocator);
|
||||
i = tmp;
|
||||
while (g != NULL) {
|
||||
lzma_index_group *tmp = g->next;
|
||||
lzma_free(g, allocator);
|
||||
g = tmp;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculates properties of an Index list
|
||||
*
|
||||
*
|
||||
*/
|
||||
extern LZMA_API lzma_ret
|
||||
lzma_index_count(const lzma_index *i, size_t *count,
|
||||
lzma_vli *lzma_restrict total_size,
|
||||
lzma_vli *lzma_restrict uncompressed_size)
|
||||
extern LZMA_API lzma_index *
|
||||
lzma_index_init(lzma_index *i, lzma_allocator *allocator)
|
||||
{
|
||||
*count = 0;
|
||||
*total_size = 0;
|
||||
*uncompressed_size = 0;
|
||||
|
||||
while (i != NULL) {
|
||||
if (i->total_size == LZMA_VLI_VALUE_UNKNOWN) {
|
||||
*total_size = LZMA_VLI_VALUE_UNKNOWN;
|
||||
} else if (i->total_size > LZMA_VLI_VALUE_MAX) {
|
||||
return LZMA_PROG_ERROR;
|
||||
} else if (*total_size != LZMA_VLI_VALUE_UNKNOWN) {
|
||||
*total_size += i->total_size;
|
||||
if (*total_size > LZMA_VLI_VALUE_MAX)
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
if (i->uncompressed_size == LZMA_VLI_VALUE_UNKNOWN) {
|
||||
*uncompressed_size = LZMA_VLI_VALUE_UNKNOWN;
|
||||
} else if (i->uncompressed_size > LZMA_VLI_VALUE_MAX) {
|
||||
return LZMA_PROG_ERROR;
|
||||
} else if (*uncompressed_size != LZMA_VLI_VALUE_UNKNOWN) {
|
||||
*uncompressed_size += i->uncompressed_size;
|
||||
if (*uncompressed_size > LZMA_VLI_VALUE_MAX)
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
++*count;
|
||||
i = i->next;
|
||||
if (i == NULL) {
|
||||
i = lzma_alloc(sizeof(lzma_index), allocator);
|
||||
if (i == NULL)
|
||||
return NULL;
|
||||
} else {
|
||||
free_index_list(i, allocator);
|
||||
}
|
||||
|
||||
// FIXME ?
|
||||
if (*total_size == LZMA_VLI_VALUE_UNKNOWN
|
||||
|| *uncompressed_size == LZMA_VLI_VALUE_UNKNOWN)
|
||||
return LZMA_HEADER_ERROR;
|
||||
i->total_size = 0;
|
||||
i->uncompressed_size = 0;
|
||||
i->count = 0;
|
||||
i->index_list_size = 0;
|
||||
i->padding_size = 0;
|
||||
i->head = NULL;
|
||||
i->tail = NULL;
|
||||
i->current.group = NULL;
|
||||
i->old.count = 0;
|
||||
i->old.index_list_size = 0;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API void
|
||||
lzma_index_end(lzma_index *i, lzma_allocator *allocator)
|
||||
{
|
||||
if (i != NULL) {
|
||||
free_index_list(i, allocator);
|
||||
lzma_free(i, allocator);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_vli
|
||||
lzma_index_count(const lzma_index *i)
|
||||
{
|
||||
return i->count;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_vli
|
||||
lzma_index_size(const lzma_index *i)
|
||||
{
|
||||
return index_size(i->count, i->index_list_size);
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_vli
|
||||
lzma_index_total_size(const lzma_index *i)
|
||||
{
|
||||
return i->total_size;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_vli
|
||||
lzma_index_stream_size(const lzma_index *i)
|
||||
{
|
||||
// Stream Header + Blocks + Index + Stream Footer
|
||||
return LZMA_STREAM_HEADER_SIZE + i->total_size
|
||||
+ index_size(i->count, i->index_list_size)
|
||||
+ LZMA_STREAM_HEADER_SIZE;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_vli
|
||||
lzma_index_file_size(const lzma_index *i)
|
||||
{
|
||||
// If multiple Streams are concatenated, the Stream Header, Index,
|
||||
// and Stream Footer fields of all but the last Stream are already
|
||||
// included in padding_size. Thus, we need to calculate only the
|
||||
// size of the last Index, not all Indexes.
|
||||
return i->total_size + i->padding_size
|
||||
+ index_size(i->count - i->old.count,
|
||||
i->index_list_size - i->old.index_list_size)
|
||||
+ LZMA_STREAM_HEADER_SIZE * 2;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_vli
|
||||
lzma_index_uncompressed_size(const lzma_index *i)
|
||||
{
|
||||
return i->uncompressed_size;
|
||||
}
|
||||
|
||||
|
||||
extern uint32_t
|
||||
lzma_index_padding_size(const lzma_index *i)
|
||||
{
|
||||
return (LZMA_VLI_C(4)
|
||||
- index_size_unpadded(i->count, i->index_list_size)) & 3;
|
||||
}
|
||||
|
||||
|
||||
/// Helper function for index_append()
|
||||
static lzma_ret
|
||||
index_append_real(lzma_index *i, lzma_allocator *allocator,
|
||||
lzma_vli total_size, lzma_vli uncompressed_size,
|
||||
bool is_padding)
|
||||
{
|
||||
// Add the new record.
|
||||
if (i->tail == NULL || i->tail->last == INDEX_GROUP_SIZE - 1) {
|
||||
// Allocate a new group.
|
||||
lzma_index_group *g = lzma_alloc(sizeof(lzma_index_group),
|
||||
allocator);
|
||||
if (g == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
// Initialize the group and set its first record.
|
||||
g->prev = i->tail;
|
||||
g->next = NULL;
|
||||
g->last = 0;
|
||||
g->total_sums[0] = total_size;
|
||||
g->uncompressed_sums[0] = uncompressed_size;
|
||||
g->paddings[0] = is_padding;
|
||||
|
||||
// If this is the first group, make it the head.
|
||||
if (i->head == NULL)
|
||||
i->head = g;
|
||||
else
|
||||
i->tail->next = g;
|
||||
|
||||
// Make it the new tail.
|
||||
i->tail = g;
|
||||
|
||||
} else {
|
||||
// i->tail has space left for at least one record.
|
||||
i->tail->total_sums[i->tail->last + 1]
|
||||
= i->tail->total_sums[i->tail->last]
|
||||
+ total_size;
|
||||
i->tail->uncompressed_sums[i->tail->last + 1]
|
||||
= i->tail->uncompressed_sums[i->tail->last]
|
||||
+ uncompressed_size;
|
||||
i->tail->paddings[i->tail->last + 1] = is_padding;
|
||||
++i->tail->last;
|
||||
}
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern LZMA_API lzma_bool
|
||||
lzma_index_is_equal(const lzma_index *a, const lzma_index *b)
|
||||
static lzma_ret
|
||||
index_append(lzma_index *i, lzma_allocator *allocator, lzma_vli total_size,
|
||||
lzma_vli uncompressed_size, bool is_padding)
|
||||
{
|
||||
while (a != NULL && b != NULL) {
|
||||
if (a->total_size != b->total_size || a->uncompressed_size
|
||||
!= b->uncompressed_size)
|
||||
return false;
|
||||
if (total_size > LZMA_VLI_VALUE_MAX
|
||||
|| uncompressed_size > LZMA_VLI_VALUE_MAX)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
a = a->next;
|
||||
b = b->next;
|
||||
// This looks a bit ugly. We want to first validate that the Index
|
||||
// and Stream stay in valid limits after adding this Record. After
|
||||
// validating, we may need to allocate a new lzma_index_group (it's
|
||||
// slightly more correct to validate before allocating, YMMV).
|
||||
lzma_ret ret;
|
||||
|
||||
if (is_padding) {
|
||||
assert(uncompressed_size == 0);
|
||||
|
||||
// First update the info so we can validate it.
|
||||
i->padding_size += total_size;
|
||||
|
||||
if (i->padding_size > LZMA_VLI_VALUE_MAX
|
||||
|| lzma_index_file_size(i)
|
||||
> LZMA_VLI_VALUE_MAX)
|
||||
ret = LZMA_DATA_ERROR; // Would grow past the limits.
|
||||
else
|
||||
ret = index_append_real(i, allocator,
|
||||
total_size, uncompressed_size, true);
|
||||
|
||||
// If something went wrong, undo the updated value.
|
||||
if (ret != LZMA_OK)
|
||||
i->padding_size -= total_size;
|
||||
|
||||
} else {
|
||||
// First update the overall info so we can validate it.
|
||||
const lzma_vli index_list_size_add
|
||||
= lzma_vli_size(total_size / 4 - 1)
|
||||
+ lzma_vli_size(uncompressed_size);
|
||||
|
||||
i->total_size += total_size;
|
||||
i->uncompressed_size += uncompressed_size;
|
||||
++i->count;
|
||||
i->index_list_size += index_list_size_add;
|
||||
|
||||
if (i->total_size > LZMA_VLI_VALUE_MAX
|
||||
|| i->uncompressed_size > LZMA_VLI_VALUE_MAX
|
||||
|| lzma_index_size(i) > LZMA_BACKWARD_SIZE_MAX
|
||||
|| lzma_index_file_size(i)
|
||||
> LZMA_VLI_VALUE_MAX)
|
||||
ret = LZMA_DATA_ERROR; // Would grow past the limits.
|
||||
else
|
||||
ret = index_append_real(i, allocator,
|
||||
total_size, uncompressed_size, false);
|
||||
|
||||
if (ret != LZMA_OK) {
|
||||
// Something went wrong. Undo the updates.
|
||||
i->total_size -= total_size;
|
||||
i->uncompressed_size -= uncompressed_size;
|
||||
--i->count;
|
||||
i->index_list_size -= index_list_size_add;
|
||||
}
|
||||
}
|
||||
|
||||
return a == b;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_ret
|
||||
lzma_index_append(lzma_index *i, lzma_allocator *allocator,
|
||||
lzma_vli total_size, lzma_vli uncompressed_size)
|
||||
{
|
||||
return index_append(i, allocator,
|
||||
total_size, uncompressed_size, false);
|
||||
}
|
||||
|
||||
|
||||
/// Initialize i->current to point to the first Record.
|
||||
static bool
|
||||
init_current(lzma_index *i)
|
||||
{
|
||||
if (i->head == NULL) {
|
||||
assert(i->count == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
assert(i->count > 0);
|
||||
|
||||
i->current.group = i->head;
|
||||
i->current.record = 0;
|
||||
i->current.stream_offset = LZMA_STREAM_HEADER_SIZE;
|
||||
i->current.uncompressed_offset = 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// Go backward to the previous group.
|
||||
static void
|
||||
previous_group(lzma_index *i)
|
||||
{
|
||||
assert(i->current.group->prev != NULL);
|
||||
|
||||
// Go to the previous group first.
|
||||
i->current.group = i->current.group->prev;
|
||||
i->current.record = i->current.group->last;
|
||||
|
||||
// Then update the offsets.
|
||||
i->current.stream_offset -= i->current.group
|
||||
->total_sums[i->current.group->last];
|
||||
i->current.uncompressed_offset -= i->current.group
|
||||
->uncompressed_sums[i->current.group->last];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/// Go forward to the next group.
|
||||
static void
|
||||
next_group(lzma_index *i)
|
||||
{
|
||||
assert(i->current.group->next != NULL);
|
||||
|
||||
// Update the offsets first.
|
||||
i->current.stream_offset += i->current.group
|
||||
->total_sums[i->current.group->last];
|
||||
i->current.uncompressed_offset += i->current.group
|
||||
->uncompressed_sums[i->current.group->last];
|
||||
|
||||
// Then go to the next group.
|
||||
i->current.record = 0;
|
||||
i->current.group = i->current.group->next;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/// Set *info from i->current.
|
||||
static void
|
||||
set_info(const lzma_index *i, lzma_index_record *info)
|
||||
{
|
||||
info->total_size = i->current.group->total_sums[i->current.record];
|
||||
info->uncompressed_size = i->current.group->uncompressed_sums[
|
||||
i->current.record];
|
||||
|
||||
info->stream_offset = i->current.stream_offset;
|
||||
info->uncompressed_offset = i->current.uncompressed_offset;
|
||||
|
||||
// If it's not the first Record in this group, we need to do some
|
||||
// adjustements.
|
||||
if (i->current.record > 0) {
|
||||
// _sums[] are cumulative, thus we need to substract the
|
||||
// _previous _sums[] to get the sizes of this Record.
|
||||
info->total_size -= i->current.group
|
||||
->total_sums[i->current.record - 1];
|
||||
info->uncompressed_size -= i->current.group
|
||||
->uncompressed_sums[i->current.record - 1];
|
||||
|
||||
// i->current.{total,uncompressed}_offsets have the offset
|
||||
// of the beginning of the group, thus we need to add the
|
||||
// appropriate amount to get the offsetes of this Record.
|
||||
info->stream_offset += i->current.group
|
||||
->total_sums[i->current.record - 1];
|
||||
info->uncompressed_offset += i->current.group
|
||||
->uncompressed_sums[i->current.record - 1];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_bool
|
||||
lzma_index_read(lzma_index *i, lzma_index_record *info)
|
||||
{
|
||||
if (i->current.group == NULL) {
|
||||
// We are at the beginning of the Record list. Set up
|
||||
// i->current point at the first Record. Return if there
|
||||
// are no Records.
|
||||
if (init_current(i))
|
||||
return true;
|
||||
} else do {
|
||||
// Try to go the next Record.
|
||||
if (i->current.record < i->current.group->last)
|
||||
++i->current.record;
|
||||
else if (i->current.group->next == NULL)
|
||||
return true;
|
||||
else
|
||||
next_group(i);
|
||||
} while (i->current.group->paddings[i->current.record]);
|
||||
|
||||
// We found a new Record. Set the information to *info.
|
||||
set_info(i, info);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API void
|
||||
lzma_index_rewind(lzma_index *i)
|
||||
{
|
||||
i->current.group = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_bool
|
||||
lzma_index_locate(lzma_index *i, lzma_index_record *info, lzma_vli target)
|
||||
{
|
||||
// Check if it is possible to fullfill the request.
|
||||
if (target >= i->uncompressed_size)
|
||||
return true;
|
||||
|
||||
// Now we know that we will have an answer. Initialize the current
|
||||
// read position if needed.
|
||||
if (i->current.group == NULL && init_current(i))
|
||||
return true;
|
||||
|
||||
// Locate the group where the wanted Block is. First search forward.
|
||||
while (i->current.uncompressed_offset <= target) {
|
||||
// If the first uncompressed byte of the next group is past
|
||||
// the target offset, it has to be this or an earlier group.
|
||||
if (i->current.uncompressed_offset + i->current.group
|
||||
->uncompressed_sums[i->current.group->last]
|
||||
> target)
|
||||
break;
|
||||
|
||||
// Go forward to the next group.
|
||||
next_group(i);
|
||||
}
|
||||
|
||||
// Then search backward.
|
||||
while (i->current.uncompressed_offset > target)
|
||||
previous_group(i);
|
||||
|
||||
// Now the target Block is somewhere in i->current.group. Offsets
|
||||
// in groups are relative to the beginning of the group, thus
|
||||
// we must adjust the target before starting the search loop.
|
||||
assert(target >= i->current.uncompressed_offset);
|
||||
target -= i->current.uncompressed_offset;
|
||||
|
||||
// Use binary search to locate the exact Record. It is the first
|
||||
// Record whose uncompressed_sums[] value is greater than target.
|
||||
// This is because we want the rightmost Record that fullfills the
|
||||
// search criterion. It is possible that there are empty Blocks or
|
||||
// padding, we don't want to return them.
|
||||
size_t left = 0;
|
||||
size_t right = i->current.group->last;
|
||||
|
||||
while (left < right) {
|
||||
const size_t pos = left + (right - left) / 2;
|
||||
if (i->current.group->uncompressed_sums[pos] <= target)
|
||||
left = pos + 1;
|
||||
else
|
||||
right = pos;
|
||||
}
|
||||
|
||||
i->current.record = left;
|
||||
|
||||
#ifndef NDEBUG
|
||||
// The found Record must not be padding or have zero uncompressed size.
|
||||
assert(!i->current.group->paddings[i->current.record]);
|
||||
|
||||
if (i->current.record == 0)
|
||||
assert(i->current.group->uncompressed_sums[0] > 0);
|
||||
else
|
||||
assert(i->current.group->uncompressed_sums[i->current.record]
|
||||
- i->current.group->uncompressed_sums[
|
||||
i->current.record - 1] > 0);
|
||||
#endif
|
||||
|
||||
set_info(i, info);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_ret
|
||||
lzma_index_cat(lzma_index *restrict dest, lzma_index *restrict src,
|
||||
lzma_allocator *allocator, lzma_vli padding)
|
||||
{
|
||||
if (dest == NULL || src == NULL || dest == src
|
||||
|| padding > LZMA_VLI_VALUE_MAX)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Check that the combined size of the Indexes stays within limits.
|
||||
{
|
||||
const lzma_vli dest_size = lzma_index_file_size(dest);
|
||||
const lzma_vli src_size = lzma_index_file_size(src);
|
||||
if (dest_size + src_size > LZMA_VLI_VALUE_UNKNOWN
|
||||
|| dest_size + src_size + padding
|
||||
> LZMA_VLI_VALUE_UNKNOWN)
|
||||
return LZMA_DATA_ERROR;
|
||||
}
|
||||
|
||||
// Add a padding Record to take into account the size of
|
||||
// Index + Stream Footer + Stream Padding + Stream Header.
|
||||
//
|
||||
// NOTE: This cannot overflow, because Index Size is always
|
||||
// far smaller than LZMA_VLI_VALUE_MAX, and adding two VLIs
|
||||
// (Index Size and padding) doesn't overflow. It may become
|
||||
// an invalid VLI if padding is huge, but that is caught by
|
||||
// index_append().
|
||||
padding += index_size(dest->count - dest->old.count,
|
||||
dest->index_list_size
|
||||
- dest->old.index_list_size)
|
||||
+ LZMA_STREAM_HEADER_SIZE * 2;
|
||||
|
||||
// Add the padding Record.
|
||||
return_if_error(index_append(
|
||||
dest, allocator, padding, 0, true));
|
||||
|
||||
// Avoid wasting lots of memory if src->head has only a few records
|
||||
// that fit into dest->tail. That is, combine two groups if possible.
|
||||
//
|
||||
// NOTE: We know that dest->tail != NULL since we just appended
|
||||
// a padding Record. But we don't know about src->head.
|
||||
if (src->head != NULL && src->head->last + 1
|
||||
<= INDEX_GROUP_SIZE - dest->tail->last - 1) {
|
||||
// Copy the first Record.
|
||||
dest->tail->total_sums[dest->tail->last + 1]
|
||||
= dest->tail->total_sums[dest->tail->last]
|
||||
+ src->head->total_sums[0];
|
||||
|
||||
dest->tail->uncompressed_sums[dest->tail->last + 1]
|
||||
= dest->tail->uncompressed_sums[dest->tail->last]
|
||||
+ src->head->uncompressed_sums[0];
|
||||
|
||||
dest->tail->paddings[dest->tail->last + 1]
|
||||
= src->head->paddings[0];
|
||||
|
||||
++dest->tail->last;
|
||||
|
||||
// Copy the rest.
|
||||
for (size_t i = 1; i < src->head->last; ++i) {
|
||||
dest->tail->total_sums[dest->tail->last + 1]
|
||||
= dest->tail->total_sums[dest->tail->last]
|
||||
+ src->head->total_sums[i + 1]
|
||||
- src->head->total_sums[i];
|
||||
|
||||
dest->tail->uncompressed_sums[dest->tail->last + 1]
|
||||
= dest->tail->uncompressed_sums[
|
||||
dest->tail->last]
|
||||
+ src->head->uncompressed_sums[i + 1]
|
||||
- src->head->uncompressed_sums[i];
|
||||
|
||||
dest->tail->paddings[dest->tail->last + 1]
|
||||
= src->head->paddings[i + 1];
|
||||
|
||||
++dest->tail->last;
|
||||
}
|
||||
|
||||
// Free the head group of *src. Don't bother updating prev
|
||||
// pointers since those won't be used for anything before
|
||||
// we deallocate the whole *src structure.
|
||||
lzma_index_group *tmp = src->head;
|
||||
src->head = src->head->next;
|
||||
lzma_free(tmp, allocator);
|
||||
}
|
||||
|
||||
// If there are groups left in *src, join them as is. Note that if we
|
||||
// are combining already combined Indexes, src->head can be non-NULL
|
||||
// even if we just combined the old src->head to dest->tail.
|
||||
if (src->head != NULL) {
|
||||
src->head->prev = dest->tail;
|
||||
dest->tail->next = src->head;
|
||||
dest->tail = src->tail;
|
||||
}
|
||||
|
||||
// Update information about earlier Indexes. Only the last Index
|
||||
// from *src won't be counted in dest->old. The last Index is left
|
||||
// open and can be even appended with lzma_index_append().
|
||||
dest->old.count = dest->count + src->old.count;
|
||||
dest->old.index_list_size
|
||||
= dest->index_list_size + src->old.index_list_size;
|
||||
|
||||
// Update overall information.
|
||||
dest->total_size += src->total_size;
|
||||
dest->uncompressed_size += src->uncompressed_size;
|
||||
dest->count += src->count;
|
||||
dest->index_list_size += src->index_list_size;
|
||||
dest->padding_size += src->padding_size;
|
||||
|
||||
// *src has nothing left but the base structure.
|
||||
lzma_free(src, allocator);
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_index *
|
||||
lzma_index_dup(const lzma_index *src, lzma_allocator *allocator)
|
||||
{
|
||||
lzma_index *dest = lzma_alloc(sizeof(lzma_index), allocator);
|
||||
if (dest == NULL)
|
||||
return NULL;
|
||||
|
||||
// Copy the base structure except the pointers.
|
||||
*dest = *src;
|
||||
dest->head = NULL;
|
||||
dest->tail = NULL;
|
||||
dest->current.group = NULL;
|
||||
|
||||
// Copy the Records.
|
||||
const lzma_index_group *src_group = src->head;
|
||||
while (src_group != NULL) {
|
||||
// Allocate a new group.
|
||||
lzma_index_group *dest_group = lzma_alloc(
|
||||
sizeof(lzma_index_group), allocator);
|
||||
if (dest_group == NULL) {
|
||||
lzma_index_end(dest, allocator);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Set the pointers.
|
||||
dest_group->prev = dest->tail;
|
||||
dest_group->next = NULL;
|
||||
|
||||
if (dest->head == NULL)
|
||||
dest->head = dest_group;
|
||||
else
|
||||
dest->tail->next = dest_group;
|
||||
|
||||
dest->tail = dest_group;
|
||||
|
||||
dest_group->last = src_group->last;
|
||||
|
||||
// Copy the arrays so that we don't read uninitialized memory.
|
||||
const size_t count = src_group->last + 1;
|
||||
memcpy(dest_group->total_sums, src_group->total_sums,
|
||||
sizeof(lzma_vli) * count);
|
||||
memcpy(dest_group->uncompressed_sums,
|
||||
src_group->uncompressed_sums,
|
||||
sizeof(lzma_vli) * count);
|
||||
memcpy(dest_group->paddings, src_group->paddings,
|
||||
sizeof(bool) * count);
|
||||
|
||||
// Copy also the read position.
|
||||
if (src_group == src->current.group)
|
||||
dest->current.group = dest->tail;
|
||||
|
||||
src_group = src_group->next;
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API lzma_bool
|
||||
lzma_index_equal(const lzma_index *a, const lzma_index *b)
|
||||
{
|
||||
// No point to compare more if the pointers are the same.
|
||||
if (a == b)
|
||||
return true;
|
||||
|
||||
// Compare the basic properties.
|
||||
if (a->total_size != b->total_size
|
||||
|| a->uncompressed_size != b->uncompressed_size
|
||||
|| a->index_list_size != b->index_list_size
|
||||
|| a->count != b->count)
|
||||
return false;
|
||||
|
||||
// Compare the Records.
|
||||
const lzma_index_group *ag = a->head;
|
||||
const lzma_index_group *bg = b->head;
|
||||
while (ag != NULL && bg != NULL) {
|
||||
const size_t count = ag->last + 1;
|
||||
if (ag->last != bg->last
|
||||
|| memcmp(ag->total_sums,
|
||||
bg->total_sums,
|
||||
sizeof(lzma_vli) * count) != 0
|
||||
|| memcmp(ag->uncompressed_sums,
|
||||
bg->uncompressed_sums,
|
||||
sizeof(lzma_vli) * count) != 0
|
||||
|| memcmp(ag->paddings, bg->paddings,
|
||||
sizeof(bool) * count) != 0)
|
||||
return false;
|
||||
|
||||
ag = ag->next;
|
||||
bg = bg->next;
|
||||
}
|
||||
|
||||
return ag == NULL && bg == NULL;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user