Sort of garbage collection commit. :-| Many things are still

broken. API has changed a lot and it will still change a
little more here and there. The command line tool doesn't
have all the required changes to reflect the API changes, so
it's easy to get "internal error" or trigger assertions.
This commit is contained in:
Lasse Collin 2008-08-28 22:53:15 +03:00
parent 57b9a145a5
commit 3b34851de1
277 changed files with 9164 additions and 7591 deletions

View File

@ -39,10 +39,15 @@ echo "System type:"
# This is needed to know if assembler optimizations can be used. # This is needed to know if assembler optimizations can be used.
AC_CANONICAL_HOST AC_CANONICAL_HOST
echo echo
echo "Configure options:" echo "Configure options:"
# Enable/disable debugging code:
#############
# Debugging #
#############
AC_MSG_CHECKING([if debugging code should be compiled]) AC_MSG_CHECKING([if debugging code should be compiled])
AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [Enable debugging code.]), AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [Enable debugging code.]),
[], enable_debug=no) [], enable_debug=no)
@ -53,7 +58,11 @@ else
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
fi fi
# Enable/disable the encoder components:
###########
# Encoder #
###########
AC_MSG_CHECKING([if encoder components should be built]) AC_MSG_CHECKING([if encoder components should be built])
AC_ARG_ENABLE(encoder, AC_HELP_STRING([--disable-encoder], AC_ARG_ENABLE(encoder, AC_HELP_STRING([--disable-encoder],
[Do not build the encoder components.]), [Do not build the encoder components.]),
@ -67,7 +76,11 @@ else
fi fi
AM_CONDITIONAL(COND_MAIN_ENCODER, test "x$enable_encoder" = xyes) 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_MSG_CHECKING([if decoder components should be built])
AC_ARG_ENABLE(decoder, AC_HELP_STRING([--disable-decoder], AC_ARG_ENABLE(decoder, AC_HELP_STRING([--disable-decoder],
[Do not build the decoder components.]), [Do not build the decoder components.]),
@ -84,146 +97,146 @@ else
fi fi
AM_CONDITIONAL(COND_MAIN_DECODER, test "x$enable_decoder" = xyes) 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=LIST], # 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 m4_define([SUPPORTED_FILTERS], [lzma,lzma2,subblock,delta,x86,powerpc,ia64,arm,armthumb,sparc])dnl
arm armthumb sparc delta lzma]), m4_define([SIMPLE_FILTERS], [x86,powerpc,ia64,arm,armthumb,sparc])
[], [enable_filters=copy,subblock,x86,powerpc,ia64,arm,armthumb,sparc,delta,lzma]) m4_define([LZ_FILTERS], [lzma,lzma2])
enable_filters=`echo "$enable_filters" | sed 's/,/ /g'`
enable_filters_copy=no m4_foreach([NAME], [SUPPORTED_FILTERS],
enable_filters_subblock=no [enable_filter_[]NAME=no
enable_filters_x86=no enable_encoder_[]NAME=no
enable_filters_powerpc=no enable_decoder_[]NAME=no
enable_filters_ia64=no ])dnl
enable_filters_arm=no
enable_filters_armthumb=no AC_MSG_CHECKING([which encoders to build])
enable_filters_sparc=no AC_ARG_ENABLE([encoders], AC_HELP_STRING([--enable-encoders=LIST],
enable_filters_delta=no [Comma-separated list of encoders to build. Default=all.
enable_filters_lzma=no Available encoders:]
enable_simple_filters=no m4_translit(m4_defn([SUPPORTED_FILTERS]), [,], [ ])),
if test "x$enable_filters" = xno || test "x$enable_filters" = x; then [], [enable_encoders=SUPPORTED_FILTERS])
AC_MSG_RESULT([]) enable_encoders=`echo "$enable_encoders" | sed 's/,/ /g'`
AC_MSG_ERROR([Please enable at least one filter.]) if test "x$enable_encoders" = xno || test "x$enable_encoders" = x; then
AC_MSG_RESULT([(none)])
else else
for arg in $enable_filters for arg in $enable_encoders
do do
case $arg in case $arg in m4_foreach([NAME], [SUPPORTED_FILTERS], [
copy) NAME)
enable_filters_copy=yes enable_filter_[]NAME=yes
AC_DEFINE([HAVE_FILTER_COPY], 1, enable_encoder_[]NAME=yes
[Define to 1 if support for the AC_DEFINE(HAVE_ENCODER_[]m4_toupper(NAME), [1],
Copy filter is enabled.]) [Define to 1 if] NAME [encoder 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.])
;;
*) *)
AC_MSG_RESULT([]) AC_MSG_RESULT([])
AC_MSG_ERROR([unknown filter: $arg]) AC_MSG_ERROR([unknown filter: $arg])
;; ;;
esac esac
done done
AC_MSG_RESULT([$enable_filters]) AC_MSG_RESULT([$enable_encoders])
fi 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_MSG_CHECKING([which match finders to build])
AC_ARG_ENABLE(match-finders, AC_HELP_STRING([--enable-match-finders=LIST], AC_ARG_ENABLE(match-finders, AC_HELP_STRING([--enable-match-finders=LIST],
[Comma-separated list of match finders to build. Default=all. [Comma-separated list of match finders to build. Default=all.
At least one match finder is required for encoding with At least one match finder is required for encoding with
the LZMA filter. the LZMA filter. Available match finders:]
Available match finders: hc3 hc4 bt2 bt3 bt4]), [], m4_translit(m4_defn([SUPPORTED_MATCH_FINDERS]), [,], [ ])), [],
[enable_match_finders=hc3,hc4,bt2,bt3,bt4]) [enable_match_finders=SUPPORTED_MATCH_FINDERS])
enable_match_finders=`echo "$enable_match_finders" | sed 's/,/ /g'` enable_match_finders=`echo "$enable_match_finders" | sed 's/,/ /g'`
enable_match_finders_hc3=no if test "x$enable_encoder" = xyes && test "x$enable_encoder_lz" = xyes ; then
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
for arg in $enable_match_finders for arg in $enable_match_finders
do do
case $arg in case $arg in m4_foreach([NAME], [SUPPORTED_MATCH_FINDERS], [
hc3) enable_match_finders_hc3=yes ;; NAME)
hc4) enable_match_finders_hc4=yes ;; enable_match_finder_[]NAME=yes
bt2) enable_match_finders_bt2=yes ;; AC_DEFINE(HAVE_MF_[]m4_toupper(NAME), [1],
bt3) enable_match_finders_bt3=yes ;; [Define to 1 to enable] NAME [match finder.])
bt4) enable_match_finders_bt4=yes ;; ;;])
*) *)
AC_MSG_RESULT([]) AC_MSG_RESULT([])
AC_MSG_ERROR([unknown match finder: $arg]) AC_MSG_ERROR([unknown match finder: $arg])
@ -232,48 +245,39 @@ if test "x$enable_encoder" = xyes && test "x$enable_filters_lzma" = xyes ; then
done done
AC_MSG_RESULT([$enable_match_finders]) AC_MSG_RESULT([$enable_match_finders])
else else
AC_MSG_RESULT([(none because not building the LZMA encoder)]) AC_MSG_RESULT([(none because not building any LZ-based encoder)])
fi 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_MSG_CHECKING([which integrity checks to build])
AC_ARG_ENABLE(checks, AC_HELP_STRING([--enable-checks=LIST], AC_ARG_ENABLE(checks, AC_HELP_STRING([--enable-checks=LIST],
[Comma-separated list of integrity checks to build. [Comma-separated list of integrity checks to build.
Default=all. Available integrity checks: crc32 crc64 sha256]), Default=all. Available integrity checks:]
[], [enable_checks=crc32,crc64,sha256]) m4_translit(m4_defn([SUPPORTED_CHECKS]), [,], [ ])),
[], [enable_checks=SUPPORTED_CHECKS])
enable_checks=`echo "$enable_checks" | sed 's/,/ /g'` 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 if test "x$enable_checks" = xno || test "x$enable_checks" = x; then
AC_MSG_RESULT([(none)]) AC_MSG_RESULT([(none)])
else else
for arg in $enable_checks for arg in $enable_checks
do do
case $arg in case $arg in m4_foreach([NAME], [SUPPORTED_CHECKS], [
crc32) NAME)
enable_checks_crc32=yes enable_check_[]NAME=yes
AC_DEFINE([HAVE_CHECK_CRC32], 1, AC_DEFINE(HAVE_CHECK_[]m4_toupper(NAME), [1],
[Define to 1 if CRC32 support [Define to 1 if] NAME
is enabled.]) [integrity check 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.])
;;
*) *)
AC_MSG_RESULT([]) AC_MSG_RESULT([])
AC_MSG_ERROR([unknown integrity check: $arg]) AC_MSG_ERROR([unknown integrity check: $arg])
@ -285,11 +289,16 @@ fi
if test "x$enable_checks_crc32" = xno ; then if test "x$enable_checks_crc32" = xno ; then
AC_MSG_ERROR([For now, the CRC32 check must always be enabled.]) AC_MSG_ERROR([For now, the CRC32 check must always be enabled.])
fi 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_MSG_CHECKING([if assembler optimizations should be used])
AC_ARG_ENABLE(assembler, AC_HELP_STRING([--disable-assembler], AC_ARG_ENABLE(assembler, AC_HELP_STRING([--disable-assembler],
[Do not use assembler optimizations even if such exist [Do not use assembler optimizations even if such exist
@ -321,13 +330,18 @@ case $enable_assembler in
;; ;;
*) *)
AC_MSG_RESULT([]) 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 esac
AC_MSG_RESULT([$enable_assembler]) AC_MSG_RESULT([$enable_assembler])
AM_CONDITIONAL(COND_ASM_X86, test "x$enable_assembler" = xx86) 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 #
################################
# Fast unaligned memory access
AC_MSG_CHECKING([if unaligned memory access should be used]) AC_MSG_CHECKING([if unaligned memory access should be used])
AC_ARG_ENABLE(unaligned-access, AC_HELP_STRING([--enable-unaligned-access], AC_ARG_ENABLE(unaligned-access, AC_HELP_STRING([--enable-unaligned-access],
[Enable if the system supports *fast* unaligned memory access [Enable if the system supports *fast* unaligned memory access
@ -352,12 +366,15 @@ else
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
fi fi
# Size optimization
#####################
# Size optimization #
#####################
AC_MSG_CHECKING([if small size is preferred over speed]) AC_MSG_CHECKING([if small size is preferred over speed])
AC_ARG_ENABLE(small, AC_HELP_STRING([--enable-small], AC_ARG_ENABLE(small, AC_HELP_STRING([--enable-small],
[Omit precomputed tables to make liblzma a few kilobytes [Make liblzma smaller and a little slower.
smaller. This will increase startup time of applications This is disabled by default to optimize for speed.]),
slightly, because the tables need to be computed first.]),
[], [enable_small=no]) [], [enable_small=no])
if test "x$enable_small" = xyes; then if test "x$enable_small" = xyes; then
AC_DEFINE([HAVE_SMALL], 1, [Define to 1 if optimizing for size.]) AC_DEFINE([HAVE_SMALL], 1, [Define to 1 if optimizing for size.])
@ -368,6 +385,7 @@ fi
AC_MSG_RESULT([$enable_small]) AC_MSG_RESULT([$enable_small])
AM_CONDITIONAL(COND_SMALL, test "x$enable_small" = xyes) AM_CONDITIONAL(COND_SMALL, test "x$enable_small" = xyes)
############################################################################### ###############################################################################
# Checks for programs. # Checks for programs.
############################################################################### ###############################################################################
@ -447,7 +465,6 @@ AC_TYPE_INT64_T
AC_TYPE_UINT64_T AC_TYPE_UINT64_T
AC_TYPE_UINTPTR_T AC_TYPE_UINTPTR_T
AC_CHECK_SIZEOF([unsigned long])
AC_CHECK_SIZEOF([size_t]) AC_CHECK_SIZEOF([size_t])
# The command line tool can copy high resolution timestamps if such # The command line tool can copy high resolution timestamps if such
@ -662,11 +679,12 @@ AC_CONFIG_FILES([
src/liblzma/api/Makefile src/liblzma/api/Makefile
src/liblzma/common/Makefile src/liblzma/common/Makefile
src/liblzma/check/Makefile src/liblzma/check/Makefile
src/liblzma/rangecoder/Makefile
src/liblzma/lz/Makefile src/liblzma/lz/Makefile
src/liblzma/lzma/Makefile src/liblzma/lzma/Makefile
src/liblzma/simple/Makefile
src/liblzma/subblock/Makefile src/liblzma/subblock/Makefile
src/liblzma/rangecoder/Makefile src/liblzma/delta/Makefile
src/liblzma/simple/Makefile
src/lzma/Makefile src/lzma/Makefile
src/lzmadec/Makefile src/lzmadec/Makefile
src/scripts/Makefile src/scripts/Makefile

View File

@ -16,7 +16,10 @@ noinst_PROGRAMS = \
repeat \ repeat \
sync_flush \ sync_flush \
full_flush \ full_flush \
memusage memusage \
crc32 \
known_sizes \
hex2bin
AM_CPPFLAGS = \ AM_CPPFLAGS = \
-I@top_srcdir@/src/common \ -I@top_srcdir@/src/common \

View File

@ -1,10 +1,9 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
/// \file lz_encoder_private.h /// \file crc32.c
/// \brief Private definitions for LZ encoder /// \brief Primitive CRC32 calculation tool
// //
// Copyright (C) 1999-2006 Igor Pavlov // Copyright (C) 2008 Lasse Collin
// Copyright (C) 2007 Lasse Collin
// //
// This library is free software; you can redistribute it and/or // This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public // modify it under the terms of the GNU Lesser General Public
@ -18,23 +17,29 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#ifndef LZMA_LZ_ENCODER_PRIVATE_H #include "sysdefs.h"
#define LZMA_LZ_ENCODER_PRIVATE_H #include <stdio.h>
#include "lz_encoder.h"
/// Value used to indicate unused slot
#define EMPTY_HASH_VALUE 0
/// When the dictionary and hash variables need to be adjusted to prevent
/// integer overflows. Since we use uint32_t to store the offsets, half
/// of it is the biggest safe limit.
#define MAX_VAL_FOR_NORMALIZE (UINT32_MAX / 2)
struct lzma_coder_s { int
lzma_next_coder next; main(void)
lzma_lz_encoder lz; {
}; uint32_t crc = 0;
#endif 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));
//printf("%08" PRIX32 "\n", crc);
// 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;
}

View File

@ -72,18 +72,24 @@ main(int argc, char **argv)
file_in = argc > 1 ? fopen(argv[1], "rb") : stdin; file_in = argc > 1 ? fopen(argv[1], "rb") : stdin;
// Config // Config
lzma_options_filter filters[LZMA_BLOCK_FILTERS_MAX + 1]; lzma_filter filters[LZMA_BLOCK_FILTERS_MAX + 1];
filters[0].id = LZMA_FILTER_SUBBLOCK; filters[0].id = LZMA_FILTER_LZMA2;
filters[0].options = NULL; filters[0].options = (void *)&lzma_preset_lzma[0];
filters[1].id = LZMA_VLI_VALUE_UNKNOWN; filters[1].id = LZMA_VLI_VALUE_UNKNOWN;
// Init // Init
if (lzma_stream_encoder(&strm, filters, LZMA_CHECK_CRC32) != LZMA_OK) { if (lzma_stream_encoder(&strm, filters, LZMA_CHECK_SHA256) != LZMA_OK) {
fprintf(stderr, "init failed\n"); fprintf(stderr, "init failed\n");
exit(1); exit(1);
} }
// if (lzma_easy_encoder(&strm, 1)) {
// fprintf(stderr, "init failed\n");
// exit(1);
// }
// Encoding // Encoding
encode(0, LZMA_FULL_FLUSH); encode(0, LZMA_FULL_FLUSH);
encode(6, LZMA_FULL_FLUSH); encode(6, LZMA_FULL_FLUSH);

54
debug/hex2bin.c Normal file
View 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
View 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;
}

View File

@ -23,6 +23,7 @@
int int
main(void) main(void)
{ {
lzma_init();
lzma_options_lzma lzma = { lzma_options_lzma lzma = {
.dictionary_size = (1 << 27) + (1 << 26), .dictionary_size = (1 << 27) + (1 << 26),
@ -31,7 +32,7 @@ main(void)
.pos_bits = 2, .pos_bits = 2,
.preset_dictionary = NULL, .preset_dictionary = NULL,
.preset_dictionary_size = 0, .preset_dictionary_size = 0,
.mode = LZMA_MODE_BEST, .mode = LZMA_MODE_NORMAL,
.fast_bytes = 48, .fast_bytes = 48,
.match_finder = LZMA_MF_BT4, .match_finder = LZMA_MF_BT4,
.match_finder_cycles = 0, .match_finder_cycles = 0,
@ -44,12 +45,13 @@ main(void)
{ UINT64_MAX, NULL } { UINT64_MAX, NULL }
}; };
*/ */
lzma_options_filter filters[] = { lzma_filter filters[] = {
{ LZMA_FILTER_LZMA, &lzma }, { LZMA_FILTER_LZMA, &lzma },
{ UINT64_MAX, NULL } { UINT64_MAX, NULL }
}; };
printf("%u MiB\n", lzma_memory_usage(filters, true)); printf("Encoder: %10" PRIu64 " B\n", lzma_memusage_encoder(filters));
printf("Decoder: %10" PRIu64 " B\n", lzma_memusage_decoder(filters));
return 0; return 0;
} }

View File

@ -79,9 +79,10 @@ main(int argc, char **argv)
.literal_pos_bits = LZMA_LITERAL_POS_BITS_DEFAULT, .literal_pos_bits = LZMA_LITERAL_POS_BITS_DEFAULT,
.pos_bits = LZMA_POS_BITS_DEFAULT, .pos_bits = LZMA_POS_BITS_DEFAULT,
.preset_dictionary = NULL, .preset_dictionary = NULL,
.mode = LZMA_MODE_BEST, .persistent = true,
.mode = LZMA_MODE_NORMAL,
.fast_bytes = 32, .fast_bytes = 32,
.match_finder = LZMA_MF_BT3, .match_finder = LZMA_MF_HC3,
.match_finder_cycles = 0, .match_finder_cycles = 0,
}; };
@ -101,24 +102,31 @@ main(int argc, char **argv)
opt_subblock.subfilter_options.id = LZMA_FILTER_DELTA; opt_subblock.subfilter_options.id = LZMA_FILTER_DELTA;
opt_subblock.subfilter_options.options = &opt_delta; opt_subblock.subfilter_options.options = &opt_delta;
lzma_options_filter filters[LZMA_BLOCK_FILTERS_MAX + 1]; lzma_filter filters[LZMA_BLOCK_FILTERS_MAX + 1];
filters[0].id = LZMA_FILTER_LZMA; filters[0].id = LZMA_FILTER_LZMA2;
filters[0].options = &opt_lzma; filters[0].options = &opt_lzma;
filters[1].id = LZMA_VLI_VALUE_UNKNOWN; filters[1].id = LZMA_VLI_VALUE_UNKNOWN;
// Init // Init
if (lzma_stream_encoder(&strm, filters, LZMA_CHECK_NONE) != LZMA_OK) { if (lzma_stream_encoder(&strm, filters, LZMA_CHECK_CRC32) != LZMA_OK) {
fprintf(stderr, "init failed\n"); fprintf(stderr, "init failed\n");
exit(1); exit(1);
} }
// Encoding // Encoding
/*
encode(0, LZMA_SYNC_FLUSH); encode(0, LZMA_SYNC_FLUSH);
encode(6, LZMA_SYNC_FLUSH); encode(6, LZMA_SYNC_FLUSH);
encode(0, LZMA_SYNC_FLUSH); encode(0, LZMA_SYNC_FLUSH);
encode(6, LZMA_SYNC_FLUSH); encode(7, LZMA_SYNC_FLUSH);
encode(0, LZMA_SYNC_FLUSH); encode(0, LZMA_SYNC_FLUSH);
encode(0, LZMA_FINISH); 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 // Clean up
lzma_end(&strm); lzma_end(&strm);

View File

@ -15,7 +15,7 @@
#define LZMA_INTEGER_H #define LZMA_INTEGER_H
// I'm aware of AC_CHECK_ALIGNED_ACCESS_REQUIRED from Autoconf archive, but // I'm aware of AC_CHECK_ALIGNED_ACCESS_REQUIRED from Autoconf archive, but
// it's not useful for us. We don't care if unaligned access is supported, // 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 // 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 // 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 // such systems but the Autoconf test would detect such a system as
@ -32,13 +32,13 @@
// that also allow unaligned access. Inline assembler could be OK for that. // that also allow unaligned access. Inline assembler could be OK for that.
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
# include "bswap.h" # include "bswap.h"
# define integer_convert_16(n) bswap_16(n) # define integer_le_16(n) bswap_16(n)
# define integer_convert_32(n) bswap_32(n) # define integer_le_32(n) bswap_32(n)
# define integer_convert_64(n) bswap_64(n) # define integer_le_64(n) bswap_64(n)
#else #else
# define integer_convert_16(n) (n) # define integer_le_16(n) (n)
# define integer_convert_32(n) (n) # define integer_le_32(n) (n)
# define integer_convert_64(n) (n) # define integer_le_64(n) (n)
#endif #endif
@ -46,7 +46,7 @@ static inline uint16_t
integer_read_16(const uint8_t buf[static 2]) integer_read_16(const uint8_t buf[static 2])
{ {
uint16_t ret = *(const uint16_t *)(buf); uint16_t ret = *(const uint16_t *)(buf);
return integer_convert_16(ret); return integer_le_16(ret);
} }
@ -54,7 +54,7 @@ static inline uint32_t
integer_read_32(const uint8_t buf[static 4]) integer_read_32(const uint8_t buf[static 4])
{ {
uint32_t ret = *(const uint32_t *)(buf); uint32_t ret = *(const uint32_t *)(buf);
return integer_convert_32(ret); return integer_le_32(ret);
} }
@ -63,7 +63,7 @@ static inline uint64_t
integer_read_64(const uint8_t buf[static 8]) integer_read_64(const uint8_t buf[static 8])
{ {
uint64_t ret = *(const uint64_t *)(buf); uint64_t ret = *(const uint64_t *)(buf);
return integer_convert_64(ret); return integer_le_64(ret);
} }
*/ */
@ -71,14 +71,14 @@ integer_read_64(const uint8_t buf[static 8])
static inline void static inline void
integer_write_16(uint8_t buf[static 2], uint16_t num) integer_write_16(uint8_t buf[static 2], uint16_t num)
{ {
*(uint16_t *)(buf) = integer_convert_16(num); *(uint16_t *)(buf) = integer_le_16(num);
} }
static inline void static inline void
integer_write_32(uint8_t buf[static 4], uint32_t num) integer_write_32(uint8_t buf[static 4], uint32_t num)
{ {
*(uint32_t *)(buf) = integer_convert_32(num); *(uint32_t *)(buf) = integer_le_32(num);
} }
@ -86,7 +86,7 @@ integer_write_32(uint8_t buf[static 4], uint32_t num)
static inline void static inline void
integer_write_64(uint8_t buf[static 8], uint64_t num) integer_write_64(uint8_t buf[static 8], uint64_t num)
{ {
*(uint64_t *)(buf) = integer_convert_64(num); *(uint64_t *)(buf) = integer_le_64(num);
} }
*/ */

View File

@ -31,12 +31,21 @@
# include <config.h> # include <config.h>
#endif #endif
#include <sys/types.h> // size_t and NULL
#include <stddef.h>
#ifdef HAVE_INTTYPES_H #ifdef HAVE_INTTYPES_H
# include <inttypes.h> # include <inttypes.h>
#endif #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 #ifdef HAVE_LIMITS_H
# include <limits.h> # include <limits.h>
#endif #endif
@ -44,7 +53,12 @@
// Be more compatible with systems that have non-conforming inttypes.h. // 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. // 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. // 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 #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 # define UINT32_C(n) n ## U
#endif #endif
#ifndef UINT32_MAX #ifndef UINT32_MAX
@ -56,7 +70,8 @@
#ifndef PRIX32 #ifndef PRIX32
# define PRIX32 "X" # define PRIX32 "X"
#endif #endif
#if SIZEOF_UNSIGNED_LONG == 4
#if ULONG_MAX == 4294967295UL
# ifndef UINT64_C # ifndef UINT64_C
# define UINT64_C(n) n ## ULL # define UINT64_C(n) n ## ULL
# endif # endif
@ -80,16 +95,33 @@
#ifndef UINT64_MAX #ifndef UINT64_MAX
# define UINT64_MAX UINT64_C(18446744073709551615) # define UINT64_MAX UINT64_C(18446744073709551615)
#endif #endif
// The code currently assumes that size_t is either 32-bit or 64-bit.
#ifndef SIZE_MAX #ifndef SIZE_MAX
# if SIZEOF_SIZE_T == 4 # if SIZEOF_SIZE_T == 4
# define SIZE_MAX UINT32_MAX # define SIZE_MAX UINT32_MAX
# else # elif SIZEOF_SIZE_T == 8
# define SIZE_MAX UINT64_MAX # define SIZE_MAX UINT64_MAX
# else
# error sizeof(size_t) is not 32-bit or 64-bit
# endif # endif
#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> #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 #ifdef HAVE_STDBOOL_H
# include <stdbool.h> # include <stdbool.h>
#else #else
@ -108,11 +140,13 @@ typedef unsigned char _Bool;
# ifdef NDEBUG # ifdef NDEBUG
# define assert(x) # define assert(x)
# else # else
// TODO: Pretty bad assert() macro. // TODO: Pretty bad assert macro.
# define assert(x) (!(x) && abort()) # define assert(x) (!(x) && abort())
# endif # endif
#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 #ifdef HAVE_STRING_H
# include <string.h> # include <string.h>
#endif #endif

View File

@ -22,11 +22,15 @@ liblzma_la_LIBADD = \
common/libcommon.la \ common/libcommon.la \
check/libcheck.la check/libcheck.la
if COND_FILTER_LZ
SUBDIRS += lz
liblzma_la_LIBADD += lz/liblz.la
endif
if COND_FILTER_LZMA if COND_FILTER_LZMA
SUBDIRS += lz lzma rangecoder SUBDIRS += lzma rangecoder
liblzma_la_LIBADD += \ liblzma_la_LIBADD += \
lz/liblz.la \ lzma/liblzma2.la \
lzma/liblzma4.la \
rangecoder/librangecoder.la rangecoder/librangecoder.la
endif endif
@ -35,7 +39,12 @@ SUBDIRS += subblock
liblzma_la_LIBADD += subblock/libsubblock.la liblzma_la_LIBADD += subblock/libsubblock.la
endif endif
if COND_MAIN_SIMPLE if COND_FILTER_DELTA
SUBDIRS += delta
liblzma_la_LIBADD += delta/libdelta.la
endif
if COND_FILTER_SIMPLE
SUBDIRS += simple SUBDIRS += simple
liblzma_la_LIBADD += simple/libsimple.la liblzma_la_LIBADD += simple/libsimple.la
endif endif

View File

@ -15,22 +15,18 @@
nobase_include_HEADERS = \ nobase_include_HEADERS = \
lzma.h \ lzma.h \
lzma/alignment.h \ lzma/alignment.h \
lzma/alone.h \
lzma/auto.h \
lzma/base.h \ lzma/base.h \
lzma/block.h \ lzma/block.h \
lzma/check.h \ lzma/check.h \
lzma/container.h \
lzma/delta.h \ lzma/delta.h \
lzma/easy.h \
lzma/filter.h \ lzma/filter.h \
lzma/index.h \ lzma/index.h \
lzma/index_hash.h \ lzma/index_hash.h \
lzma/init.h \ lzma/init.h \
lzma/lzma.h \ lzma/lzma.h \
lzma/memlimit.h \ lzma/memlimit.h \
lzma/raw.h \
lzma/simple.h \ lzma/simple.h \
lzma/stream.h \
lzma/stream_flags.h \ lzma/stream_flags.h \
lzma/subblock.h \ lzma/subblock.h \
lzma/version.h \ lzma/version.h \

View File

@ -17,37 +17,104 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * Lesser General Public License for more details.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Before #including this file, you must make the following types available:
* - size_t
* - uint8_t
* - int32_t
* - uint32_t
* - int64_t
* - uint64_t
*
* Before #including this file, you must make the following macros available:
* - UINT32_C(n)
* - UINT64_C(n)
* - UINT32_MAX
* - UINT64_MAX
*
* Easiest way to achieve the above is to #include sys/types.h and inttypes.h
* before #including lzma.h. However, some pre-C99 libc headers don't provide
* all the required types in inttypes.h (that file may even be missing).
* Portable applications need to provide these types themselves. This way
* liblzma API can use the standard types instead of defining its own
* (e.g. lzma_uint32).
*
* Note that the API still has lzma_bool, because using stdbool.h would
* break C89 and C++ programs on many systems.
*/ */
#ifndef LZMA_H #ifndef LZMA_H
#define LZMA_H #define LZMA_H
/*****************************
* Required standard headers *
*****************************/
/**
* 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.
*/
/* stddef.h even in C++ so that we get size_t in global namespace. */
#include <stddef.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
/****************** /******************
* GCC extensions * * GCC extensions *
******************/ ******************/
@ -57,20 +124,50 @@
* break anything if these are sometimes enabled and sometimes not, only * break anything if these are sometimes enabled and sometimes not, only
* affects warnings and optimizations. * affects warnings and optimizations.
*/ */
#if defined(__GNUC__) && __GNUC__ >= 3 #if __GNUC__ >= 3
# ifndef lzma_attribute # ifndef lzma_attribute
# define lzma_attribute(attr) __attribute__(attr) # define lzma_attribute(attr) __attribute__(attr)
# endif # endif
# ifndef lzma_restrict # ifndef lzma_restrict
# define lzma_restrict __restrict__ # define lzma_restrict __restrict__
# endif # 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 #else
# ifndef lzma_attribute # ifndef lzma_attribute
# define lzma_attribute(attr) # define lzma_attribute(attr)
# endif # endif
# ifndef lzma_restrict # ifndef lzma_restrict
# define lzma_restrict # if __STDC_VERSION__ >= 199901L
# define lzma_restrict restrict
# else
# define lzma_restrict
# endif
# 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 #endif
@ -89,36 +186,30 @@ extern "C" {
#define LZMA_H_INTERNAL 1 #define LZMA_H_INTERNAL 1
/* Basic features */ /* Basic features */
#include "lzma/version.h"
#include "lzma/init.h" #include "lzma/init.h"
#include "lzma/base.h" #include "lzma/base.h"
#include "lzma/vli.h" #include "lzma/vli.h"
#include "lzma/filter.h"
#include "lzma/check.h" #include "lzma/check.h"
/* Filters */ /* Filters */
#include "lzma/filter.h"
#include "lzma/subblock.h" #include "lzma/subblock.h"
#include "lzma/simple.h" #include "lzma/simple.h"
#include "lzma/delta.h" #include "lzma/delta.h"
#include "lzma/lzma.h" #include "lzma/lzma.h"
/* Container formats */ /* Container formats */
#include "lzma/block.h" #include "lzma/container.h"
#include "lzma/stream.h"
#include "lzma/alone.h"
#include "lzma/raw.h"
#include "lzma/auto.h"
#include "lzma/easy.h"
/* Advanced features */ /* Advanced features */
#include "lzma/alignment.h" /* FIXME */
#include "lzma/block.h"
#include "lzma/index.h" #include "lzma/index.h"
#include "lzma/index_hash.h" #include "lzma/index_hash.h"
#include "lzma/alignment.h"
#include "lzma/stream_flags.h" #include "lzma/stream_flags.h"
#include "lzma/memlimit.h" #include "lzma/memlimit.h"
/* Version number */
#include "lzma/version.h"
/* /*
* All subheaders included. Undefine LZMA_H_INTERNAL to prevent applications * All subheaders included. Undefine LZMA_H_INTERNAL to prevent applications
* re-including the subheaders. * re-including the subheaders.

View File

@ -27,7 +27,7 @@
* FIXME desc * FIXME desc
*/ */
extern uint32_t lzma_alignment_input( 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 * Knowing the alignment of the output data is useful e.g. in the Block
* encoder which tries to align the Compressed Data field optimally. * 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. * member must have .id = LZMA_VLI_VALUE_UNKNOWN.
* \param guess The value to return if the alignment of the output * \param guess The value to return if the alignment of the output
* is the same as the alignment of the input data. * 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. * options), UINT32_MAX is returned.
*/ */
extern uint32_t lzma_alignment_output( extern uint32_t lzma_alignment_output(
const lzma_options_filter *filters, uint32_t guess); const lzma_filter *filters, uint32_t guess);

View File

@ -1,52 +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 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_lzma *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);

View File

@ -1,36 +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
*
* \return - LZMA_OK: Initialization was successful.
* - LZMA_MEM_ERROR: Cannot allocate memory.
*/
extern lzma_ret lzma_auto_decoder(lzma_stream *strm);

View File

@ -134,7 +134,7 @@ typedef enum {
* \brief Unknown file format * \brief Unknown file format
*/ */
LZMA_MEMLIMIT_ERROR = -9 LZMA_MEMLIMIT_ERROR = -9,
/** /**
* \brief Memory usage limit was reached * \brief Memory usage limit was reached
* *
@ -143,6 +143,9 @@ typedef enum {
* the memory usage limit has to be increased. See functions * the memory usage limit has to be increased. See functions
* lzma_memlimit_get() and lzma_memlimit_set(). * lzma_memlimit_get() and lzma_memlimit_set().
*/ */
LZMA_NO_CHECK = -10,
LZMA_SEE_CHECK = -11
} lzma_ret; } lzma_ret;
@ -229,11 +232,6 @@ typedef struct {
/** /**
* \brief Pointer to custom memory allocation function * \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 * If you don't want a custom allocator, but still want
* custom free(), set this to NULL and liblzma will use * custom free(), set this to NULL and liblzma will use
* the standard malloc(). * the standard malloc().
@ -250,16 +248,19 @@ typedef struct {
* size nmemb * size, or NULL if allocation fails * size nmemb * size, or NULL if allocation fails
* for some reason. When allocation fails, functions * for some reason. When allocation fails, functions
* of liblzma return LZMA_MEM_ERROR. * 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.
*/ */
void *(*alloc)(void *opaque, size_t nmemb, size_t size); void *(*alloc)(void *opaque, size_t nmemb, size_t size);
/** /**
* \brief Pointer to custom memory freeing function * \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 * If you don't want a custom freeing function, but still
* want a custom allocator, set this to NULL and liblzma * want a custom allocator, set this to NULL and liblzma
* will use the standard free(). * will use the standard free().
@ -279,10 +280,6 @@ typedef struct {
* and lzma_allocator.free(). This intended to ease implementing * and lzma_allocator.free(). This intended to ease implementing
* custom memory allocation functions for use with liblzma. * custom memory allocation functions for use with liblzma.
* *
* When using lzma_memory_alloc() and lzma_memory_free(), opaque
* must point to lzma_memory_limiter structure allocated and
* initialized with lzma_memory_limiter_create().
*
* If you don't need this, you should set it to NULL. * If you don't need this, you should set it to NULL.
*/ */
void *opaque; void *opaque;
@ -347,6 +344,17 @@ typedef struct {
/** Internal state is not visible to outsiders. */ /** Internal state is not visible to outsiders. */
lzma_internal *internal; 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_stream; } lzma_stream;
@ -358,22 +366,18 @@ typedef struct {
* has been allocated yet: * has been allocated yet:
* *
* lzma_stream strm = LZMA_STREAM_INIT; * 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 * If you need to initialize a dynamically allocatedlzma_stream, you can use
* has already been allocated: * 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 could use this:
* *
* lzma_stream *strm = malloc(sizeof(lzma_stream)); * lzma_stream tmp = LZMA_STREAM_INIT;
* if (strm == NULL) * *strm = tmp;
* return LZMA_MEM_ERROR;
* *strm = LZMA_STREAM_INIT_VAR;
*/ */
extern const lzma_stream LZMA_STREAM_INIT_VAR; #define LZMA_STREAM_INIT \
{ NULL, 0, 0, NULL, 0, 0, NULL, NULL, NULL, NULL, 0, 0 }
/** /**
@ -409,7 +413,8 @@ extern const lzma_stream LZMA_STREAM_INIT_VAR;
* - LZMA_PROG_ERROR: Invalid arguments or the internal state * - LZMA_PROG_ERROR: Invalid arguments or the internal state
* of the coder is corrupt. * of the coder is corrupt.
*/ */
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;
/** /**

View File

@ -36,12 +36,13 @@ typedef struct {
* \brief Size of the Block Header * \brief Size of the Block Header
* *
* Read by: * Read by:
* - lzma_block_header_encode()
* - lzma_block_header_decode()
* - lzma_block_encoder() * - lzma_block_encoder()
* - lzma_block_decoder() * - lzma_block_decoder()
* *
* Written by: * Written by:
* - lzma_block_header_size() * - lzma_block_header_size()
* - lzma_block_header_decode()
*/ */
uint32_t header_size; uint32_t header_size;
# define LZMA_BLOCK_HEADER_SIZE_MIN 8 # define LZMA_BLOCK_HEADER_SIZE_MIN 8
@ -54,10 +55,12 @@ typedef struct {
* Header, thus its value must be provided also when decoding. * Header, thus its value must be provided also when decoding.
* *
* Read by: * Read by:
* - lzma_block_header_encode()
* - lzma_block_header_decode()
* - lzma_block_encoder() * - lzma_block_encoder()
* - lzma_block_decoder() * - lzma_block_decoder()
*/ */
lzma_check_type check; lzma_check check;
/** /**
* \brief Size of the Compressed Data in bytes * \brief Size of the Compressed Data in bytes
@ -134,17 +137,17 @@ typedef struct {
* have LZMA_BLOCK_FILTERS_MAX + 1 members or the Block * have LZMA_BLOCK_FILTERS_MAX + 1 members or the Block
* Header decoder will overflow the buffer. * Header decoder will overflow the buffer.
*/ */
lzma_options_filter *filters; lzma_filter *filters;
# define LZMA_BLOCK_FILTERS_MAX 4 # define LZMA_BLOCK_FILTERS_MAX 4
} lzma_options_block; } lzma_block;
/** /**
* \brief Decodes the Block Header Size field * \brief Decodes the Block Header Size field
* *
* To decode Block Header using lzma_block_header_decode(), the size of the * To decode Block Header using lzma_block_header_decode(), the size of the
* Block Header has to be known and stored into lzma_options_block.header_size. * 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. * 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 * Note that if the first byte is 0x00, it indicates beginning of Index; use
* this macro only when the byte is not 0x00. * this macro only when the byte is not 0x00.
@ -164,7 +167,8 @@ typedef struct {
* may return LZMA_OK even if lzma_block_header_encode() or * may return LZMA_OK even if lzma_block_header_encode() or
* lzma_block_encoder() would fail. * 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;
/** /**
@ -183,7 +187,8 @@ extern lzma_ret lzma_block_header_size(lzma_options_block *options);
* - LZMA_PROG_ERROR * - LZMA_PROG_ERROR
*/ */
extern lzma_ret lzma_block_header_encode( extern lzma_ret lzma_block_header_encode(
const lzma_options_block *options, uint8_t *out); const lzma_block *options, uint8_t *out)
lzma_attr_warn_unused_result;
/** /**
@ -203,8 +208,9 @@ extern lzma_ret lzma_block_header_encode(
* - LZMA_HEADER_ERROR: Invalid or unsupported options. * - LZMA_HEADER_ERROR: Invalid or unsupported options.
* - LZMA_PROG_ERROR * - LZMA_PROG_ERROR
*/ */
extern lzma_ret lzma_block_header_decode(lzma_options_block *options, extern lzma_ret lzma_block_header_decode(lzma_block *options,
lzma_allocator *allocator, const uint8_t *in); lzma_allocator *allocator, const uint8_t *in)
lzma_attr_warn_unused_result;
/** /**
@ -227,7 +233,8 @@ extern lzma_ret lzma_block_header_decode(lzma_options_block *options,
* options->header_size between 8 and 1024 inclusive. * options->header_size between 8 and 1024 inclusive.
*/ */
extern lzma_ret lzma_block_total_size_set( extern lzma_ret lzma_block_total_size_set(
lzma_options_block *options, lzma_vli total_size); lzma_block *options, lzma_vli total_size)
lzma_attr_warn_unused_result;
/** /**
@ -238,7 +245,8 @@ extern lzma_ret lzma_block_total_size_set(
* *
* \return Total Size on success, or zero on error. * \return Total Size on success, or zero on error.
*/ */
extern lzma_vli lzma_block_total_size_get(const lzma_options_block *options); extern lzma_vli lzma_block_total_size_get(const lzma_block *options)
lzma_attr_pure;
/** /**
@ -259,8 +267,8 @@ extern lzma_vli lzma_block_total_size_get(const lzma_options_block *options);
* *
* lzma_code() can return FIXME * lzma_code() can return FIXME
*/ */
extern lzma_ret lzma_block_encoder( extern lzma_ret lzma_block_encoder(lzma_stream *strm, lzma_block *options)
lzma_stream *strm, lzma_options_block *options); lzma_attr_warn_unused_result;
/** /**
@ -273,5 +281,5 @@ extern lzma_ret lzma_block_encoder(
* - LZMA_PROG_ERROR * - LZMA_PROG_ERROR
* - LZMA_MEM_ERROR * - LZMA_MEM_ERROR
*/ */
extern lzma_ret lzma_block_decoder( extern lzma_ret lzma_block_decoder(lzma_stream *strm, lzma_block *options)
lzma_stream *strm, lzma_options_block *options); lzma_attr_warn_unused_result;

View File

@ -56,7 +56,7 @@ typedef enum {
* *
* Size of the Check field: 32 bytes * Size of the Check field: 32 bytes
*/ */
} lzma_check_type; } lzma_check;
/** /**
@ -73,34 +73,37 @@ typedef enum {
#define LZMA_CHECK_ID_MAX 15 #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.
*/
extern const lzma_bool lzma_available_checks[LZMA_CHECK_ID_MAX + 1];
/**
* \brief Size of the Check field with different Check IDs
*
* 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.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 }
*/
extern const uint32_t lzma_check_sizes[LZMA_CHECK_ID_MAX + 1];
/** /**
* \brief Maximum size of a Check field * \brief Maximum size of a Check field
*/ */
#define LZMA_CHECK_SIZE_MAX 64 #define LZMA_CHECK_SIZE_MAX 64
/**
* \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 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 uint32_t lzma_check_size(lzma_check check) lzma_attr_const;
/** /**
* \brief Calculate CRC32 * \brief Calculate CRC32
* *
@ -115,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 * \return Updated CRC value, which can be passed to this function
* again to continue CRC calculation. * 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;
/** /**
@ -125,7 +129,8 @@ 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. * 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;
/* /*

View File

@ -0,0 +1,252 @@
/**
* \file lzma/FIXME.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 uint32_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 cause trigger LZMA_NO_CHECK
* if LZMA_WARN_NO_CHECK is used.
*/
#define LZMA_WARN_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_WARN_UNSUPPORTED_CHECK UINT32_C(0x02)
/**
* This flag makes lzma_code() return LZMA_READ_CHECK as soon as the type
* of the integrity check is known. The type can then be read with
* lzma_check_get().
*/
#define LZMA_TELL_CHECK UINT32_C(0x04)
/**
* This flag makes lzma_code() decode concatenated .lzma files.
* FIXME Explain the changed API.
*/
#define LZMA_CONCATENATED UINT32_C(0x08)
/**
* \brief Initializes decoder for .lzma Stream
*
* \param strm Pointer to propertily prepared lzma_stream
* \param memlimit Rough memory usage limit as bytes
*
* \return - LZMA_OK: Initialization was successful.
* - LZMA_MEM_ERROR: Cannot allocate memory.
*/
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_init() or lzma_alone_decoder_init() 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.
*/
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
*
* The LZMA_Alone decoder supports LZMA_SYNC_FLUSH. FIXME
*
* \return - LZMA_OK
* - LZMA_MEM_ERROR
*/
extern lzma_ret lzma_alone_decoder(lzma_stream *strm, uint64_t memlimit)
lzma_attr_warn_unused_result;

View File

@ -24,9 +24,21 @@
/** /**
* \brief Filter ID * \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. * These options are needed by both encoder and decoder.
*/ */
typedef struct { 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: * Examples:
* - 16-bit stereo audio: distance = 4 bytes * - 16-bit stereo audio: distance = 4 bytes
@ -46,4 +64,16 @@ typedef struct {
# define LZMA_DELTA_DISTANCE_MIN 1 # define LZMA_DELTA_DISTANCE_MIN 1
# define LZMA_DELTA_DISTANCE_MAX 256 # 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; } lzma_options_delta;

View File

@ -1,121 +0,0 @@
/**
* \file lzma/easy.h
* \brief Easy to use encoder initialization
*
* \author Copyright (C) 1999-2006 Igor Pavlov
* \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 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,
/**<
* No compression; the data is just wrapped into .lzma
* container.
*/
LZMA_EASY_LZMA_1,
/**<
* LZMA filter with fast compression (fast in terms of LZMA).
* 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,
LZMA_EASY_LZMA_3,
LZMA_EASY_LZMA_4,
LZMA_EASY_LZMA_5,
LZMA_EASY_LZMA_6,
LZMA_EASY_LZMA_7,
LZMA_EASY_LZMA_8,
LZMA_EASY_LZMA_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_LZMA_7
/**
* \brief Calculates rough memory requirements of a compression level
*
* This function is a wrapper for lzma_memory_usage(), which is declared
* in lzma/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 uint32_t lzma_easy_memory_usage(lzma_easy_level level);
/**
* \brief Initializes .lzma Stream encoder
*
* This function is intended for those who just want to use the basic LZMA
* features (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);

View File

@ -51,7 +51,7 @@ typedef struct {
*/ */
void *options; void *options;
} lzma_options_filter; } lzma_filter;
/** /**
@ -65,7 +65,7 @@ typedef struct {
* encoding-specific functions are probably missing from the library * encoding-specific functions are probably missing from the library
* API/ABI completely. * API/ABI completely.
*/ */
extern const lzma_vli *const lzma_available_filter_encoders; extern const lzma_vli *const lzma_filter_encoders;
/** /**
@ -79,7 +79,7 @@ extern const lzma_vli *const lzma_available_filter_encoders;
* decoding-specific functions are probably missing from the library * decoding-specific functions are probably missing from the library
* API/ABI completely. * API/ABI completely.
*/ */
extern const lzma_vli *const lzma_available_filter_decoders; extern const lzma_vli *const lzma_filter_decoders;
/** /**
@ -87,8 +87,6 @@ extern const lzma_vli *const lzma_available_filter_decoders;
* *
* \param filters Array of filters terminated with * \param filters Array of filters terminated with
* .id == LZMA_VLI_VALUE_UNKNOWN. * .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 * \return Number of mebibytes (MiB i.e. 2^20) required for the given
* encoder or decoder filter chain. * encoder or decoder filter chain.
@ -98,8 +96,55 @@ extern const lzma_vli *const lzma_available_filter_decoders;
* if calculating memory requirements of decoder, lzma_init() or * if calculating memory requirements of decoder, lzma_init() or
* lzma_init_decoder() must have been called earlier. * lzma_init_decoder() must have been called earlier.
*/ */
extern uint32_t lzma_memory_usage( // extern uint32_t lzma_memory_usage(
const lzma_options_filter *filters, lzma_bool is_encoder); // const lzma_filter *filters, lzma_bool is_encoder);
extern uint64_t lzma_memusage_encoder(const lzma_filter *filters)
lzma_attr_pure;
extern uint64_t lzma_memusage_decoder(const lzma_filter *filters)
lzma_attr_pure;
/**
* \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_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 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_filter *options)
lzma_attr_warn_unused_result;
/** /**
@ -119,10 +164,11 @@ extern uint32_t lzma_memory_usage(
* - LZMA_PROG_ERROR: Invalid options * - LZMA_PROG_ERROR: Invalid options
* *
* \note If you need to calculate size of List of Filter Flags, * \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( 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 +189,9 @@ extern lzma_ret lzma_filter_flags_size(
* buffer space (you should have checked it with * buffer space (you should have checked it with
* lzma_filter_flags_size()). * lzma_filter_flags_size()).
*/ */
extern lzma_ret lzma_filter_flags_encode(uint8_t *out, size_t *out_pos, extern lzma_ret lzma_filter_flags_encode(const lzma_filter *options,
size_t out_size, const lzma_options_filter *options); uint8_t *out, size_t *out_pos, size_t out_size)
lzma_attr_warn_unused_result;
/** /**
@ -163,5 +210,6 @@ extern lzma_ret lzma_filter_flags_encode(uint8_t *out, size_t *out_pos,
* - LZMA_PROG_ERROR * - LZMA_PROG_ERROR
*/ */
extern lzma_ret lzma_filter_flags_decode( extern lzma_ret lzma_filter_flags_decode(
lzma_options_filter *options, lzma_allocator *allocator, lzma_filter *options, lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size); const uint8_t *in, size_t *in_pos, size_t in_size)
lzma_attr_warn_unused_result;

View File

@ -66,7 +66,8 @@ typedef struct {
* In this case, return value cannot be NULL or a different pointer than * In this case, return value cannot be NULL or a different pointer than
* the i given as argument. * the i given as argument.
*/ */
extern lzma_index *lzma_index_init(lzma_index *i, lzma_allocator *allocator); extern lzma_index *lzma_index_init(lzma_index *i, lzma_allocator *allocator)
lzma_attr_warn_unused_result;
/** /**
@ -91,13 +92,14 @@ extern void lzma_index_end(lzma_index *i, lzma_allocator *allocator);
* - LZMA_PROG_ERROR * - LZMA_PROG_ERROR
*/ */
extern lzma_ret lzma_index_append(lzma_index *i, lzma_allocator *allocator, extern lzma_ret lzma_index_append(lzma_index *i, lzma_allocator *allocator,
lzma_vli total_size, lzma_vli uncompressed_size); lzma_vli total_size, lzma_vli uncompressed_size)
lzma_attr_warn_unused_result;
/** /**
* \brief Get the number of Records * \brief Get the number of Records
*/ */
extern lzma_vli lzma_index_count(const lzma_index *i); extern lzma_vli lzma_index_count(const lzma_index *i) lzma_attr_pure;
/** /**
@ -105,7 +107,7 @@ extern lzma_vli lzma_index_count(const lzma_index *i);
* *
* This is needed to verify the Index Size field from the Stream Footer. * This is needed to verify the Index Size field from the Stream Footer.
*/ */
extern lzma_vli lzma_index_size(const lzma_index *i); extern lzma_vli lzma_index_size(const lzma_index *i) lzma_attr_pure;
/** /**
@ -114,7 +116,7 @@ extern lzma_vli lzma_index_size(const lzma_index *i);
* This doesn't include the Stream Header, Stream Footer, Stream Padding, * This doesn't include the Stream Header, Stream Footer, Stream Padding,
* or Index fields. * or Index fields.
*/ */
extern lzma_vli lzma_index_total_size(const lzma_index *i); extern lzma_vli lzma_index_total_size(const lzma_index *i) lzma_attr_pure;
/** /**
@ -123,7 +125,7 @@ extern lzma_vli lzma_index_total_size(const lzma_index *i);
* If multiple Indexes have been combined, this works as if the Blocks * If multiple Indexes have been combined, this works as if the Blocks
* were in a single Stream. * were in a single Stream.
*/ */
extern lzma_vli lzma_index_stream_size(const lzma_index *i); extern lzma_vli lzma_index_stream_size(const lzma_index *i) lzma_attr_pure;
/** /**
@ -133,19 +135,21 @@ extern lzma_vli lzma_index_stream_size(const lzma_index *i);
* identical to lzma_index_stream_size(). If multiple Indexes have been * identical to lzma_index_stream_size(). If multiple Indexes have been
* combined, this includes also the possible Stream Padding fields. * combined, this includes also the possible Stream Padding fields.
*/ */
extern lzma_vli lzma_index_file_size(const lzma_index *i); extern lzma_vli lzma_index_file_size(const lzma_index *i) lzma_attr_pure;
/** /**
* \brief Get the uncompressed size of the Stream * \brief Get the uncompressed size of the Stream
*/ */
extern lzma_vli lzma_index_uncompressed_size(const lzma_index *i); extern lzma_vli lzma_index_uncompressed_size(const lzma_index *i)
lzma_attr_pure;
/** /**
* \brief Get the next Record from the Index * \brief Get the next Record from the Index
*/ */
extern lzma_bool lzma_index_read(lzma_index *i, lzma_index_record *record); extern lzma_bool lzma_index_read(lzma_index *i, lzma_index_record *record)
lzma_attr_warn_unused_result;
/** /**
@ -179,7 +183,8 @@ extern void lzma_index_rewind(lzma_index *i);
* and the read position are not modified, and this function returns true. * and the read position are not modified, and this function returns true.
*/ */
extern lzma_bool lzma_index_locate( extern lzma_bool lzma_index_locate(
lzma_index *i, lzma_index_record *record, lzma_vli target); lzma_index *i, lzma_index_record *record, lzma_vli target)
lzma_attr_warn_unused_result;
/** /**
@ -202,7 +207,8 @@ extern lzma_bool lzma_index_locate(
*/ */
extern lzma_ret lzma_index_cat(lzma_index *lzma_restrict dest, extern lzma_ret lzma_index_cat(lzma_index *lzma_restrict dest,
lzma_index *lzma_restrict src, lzma_index *lzma_restrict src,
lzma_allocator *allocator, lzma_vli padding); lzma_allocator *allocator, lzma_vli padding)
lzma_attr_warn_unused_result;
/** /**
@ -211,22 +217,26 @@ extern lzma_ret lzma_index_cat(lzma_index *lzma_restrict dest,
* \return A copy of the Index, or NULL if memory allocation failed. * \return A copy of the Index, or NULL if memory allocation failed.
*/ */
extern lzma_index *lzma_index_dup( extern lzma_index *lzma_index_dup(
const lzma_index *i, lzma_allocator *allocator); const lzma_index *i, lzma_allocator *allocator)
lzma_attr_warn_unused_result;
/** /**
* \brief Compares if two Index lists are identical * \brief Compares if two Index lists are identical
*/ */
extern lzma_bool lzma_index_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 * \brief Initializes Index encoder
*/ */
extern lzma_ret lzma_index_encoder(lzma_stream *strm, lzma_index *i); extern lzma_ret lzma_index_encoder(lzma_stream *strm, lzma_index *i)
lzma_attr_warn_unused_result;
/** /**
* \brief Initializes Index decoder * \brief Initializes Index decoder
*/ */
extern lzma_ret lzma_index_decoder(lzma_stream *strm, lzma_index **i); extern lzma_ret lzma_index_decoder(lzma_stream *strm, lzma_index **i)
lzma_attr_warn_unused_result;

View File

@ -42,7 +42,8 @@ typedef struct lzma_index_hash_s lzma_index_hash;
* pointer than the index_hash given as argument. * pointer than the index_hash given as argument.
*/ */
extern lzma_index_hash *lzma_index_hash_init( extern lzma_index_hash *lzma_index_hash_init(
lzma_index_hash *index_hash, lzma_allocator *allocator); lzma_index_hash *index_hash, lzma_allocator *allocator)
lzma_attr_warn_unused_result;
/** /**
@ -66,7 +67,8 @@ extern void lzma_index_hash_end(
* used when lzma_index_hash_decode() has already been used. * used when lzma_index_hash_decode() has already been used.
*/ */
extern lzma_ret lzma_index_hash_append(lzma_index_hash *index_hash, extern lzma_ret lzma_index_hash_append(lzma_index_hash *index_hash,
lzma_vli total_size, lzma_vli uncompressed_size); lzma_vli total_size, lzma_vli uncompressed_size)
lzma_attr_warn_unused_result;
/** /**
@ -83,7 +85,8 @@ extern lzma_ret lzma_index_hash_append(lzma_index_hash *index_hash,
* Records can be added using lzma_index_hash_append(). * Records can be added using lzma_index_hash_append().
*/ */
extern lzma_ret lzma_index_hash_decode(lzma_index_hash *index_hash, extern lzma_ret lzma_index_hash_decode(lzma_index_hash *index_hash,
const uint8_t *in, size_t *in_pos, size_t in_size); const uint8_t *in, size_t *in_pos, size_t in_size)
lzma_attr_warn_unused_result;
/** /**
@ -91,4 +94,5 @@ extern lzma_ret lzma_index_hash_decode(lzma_index_hash *index_hash,
* *
* This is needed to verify the Index Size field from the Stream Footer. * 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); extern lzma_vli lzma_index_hash_size(const lzma_index_hash *index_hash)
lzma_attr_pure;

View File

@ -24,43 +24,11 @@
/** /**
* \brief Filter ID * \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(0x40)
#define LZMA_FILTER_LZMA2 LZMA_VLI_C(0x21)
/**
* \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;
/** /**
@ -128,6 +96,72 @@ typedef enum {
} lzma_match_finder; } 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 * \brief Options specific to the LZMA method handler
*/ */
@ -156,6 +190,44 @@ typedef struct {
# define LZMA_DICTIONARY_SIZE_MAX (UINT32_C(1) << 30) # define LZMA_DICTIONARY_SIZE_MAX (UINT32_C(1) << 30)
# define LZMA_DICTIONARY_SIZE_DEFAULT (UINT32_C(1) << 23) # define LZMA_DICTIONARY_SIZE_DEFAULT (UINT32_C(1) << 23)
/**
* \brief Pointer to an initial dictionary
*
* It is possible to initialize the LZ77 history window using
* a preset dictionary. Here is a good quote from zlib's
* documentation; this applies to LZMA as is:
*
* "The dictionary should consist of strings (byte sequences) that
* are likely to be encountered later in the data to be compressed,
* with the most commonly used strings preferably put towards the
* end of the dictionary. Using a dictionary is most useful when
* the data to be compressed is short and can be predicted with
* good accuracy; the data can then be compressed better than
* with the default empty dictionary."
* (From deflateSetDictionary() in zlib.h of zlib version 1.2.3)
*
* This feature should be used only in special situations.
* It works correctly only with raw encoding and decoding.
* Currently none of the container formats supported by
* liblzma allow preset dictionary when decoding, thus if
* you create a .lzma file with preset dictionary, it cannot
* be decoded with the regular .lzma decoder functions.
*
* \todo This feature is not implemented yet.
*/
const uint8_t *preset_dictionary;
/**
* \brief Size of the preset dictionary
*
* Specifies the size of the preset dictionary. If the size is
* bigger than dictionary_size, only the last dictionary_size
* bytes are processed.
*
* This variable is read only when preset_dictionary is not NULL.
*/
uint32_t preset_dictionary_size;
/** /**
* \brief Number of literal context bits * \brief Number of literal context bits
* *
@ -203,48 +275,23 @@ typedef struct {
# define LZMA_POS_BITS_MAX 4 # define LZMA_POS_BITS_MAX 4
# define LZMA_POS_BITS_DEFAULT 2 # define LZMA_POS_BITS_DEFAULT 2
/**
* \brief Pointer to an initial dictionary
*
* It is possible to initialize the LZ77 history window using
* a preset dictionary. Here is a good quote from zlib's
* documentation; this applies to LZMA as is:
*
* "The dictionary should consist of strings (byte sequences) that
* are likely to be encountered later in the data to be compressed,
* with the most commonly used strings preferably put towards the
* end of the dictionary. Using a dictionary is most useful when
* the data to be compressed is short and can be predicted with
* good accuracy; the data can then be compressed better than
* with the default empty dictionary."
* (From deflateSetDictionary() in zlib.h of zlib version 1.2.3)
*
* This feature should be used only in special situations.
* It works correctly only with raw encoding and decoding.
* Currently none of the container formats supported by
* liblzma allow preset dictionary when decoding, thus if
* you create a .lzma file with preset dictionary, it cannot
* be decoded with the regular .lzma decoder functions.
*
* \todo This feature is not implemented yet.
*/
const uint8_t *preset_dictionary;
/**
* \brief Size of the preset dictionary
*
* Specifies the size of the preset dictionary. If the size is
* bigger than dictionary_size, only the last dictionary_size
* bytes are processed.
*
* This variable is read only when preset_dictionary is not NULL.
*/
uint32_t preset_dictionary_size;
/****************************************** /******************************************
* LZMA options needed only when encoding * * 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 compression mode */
lzma_mode mode; lzma_mode mode;
@ -275,6 +322,20 @@ typedef struct {
*/ */
uint32_t match_finder_cycles; 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; } lzma_options_lzma;
@ -286,27 +347,6 @@ typedef struct {
#define LZMA_LITERAL_BITS_MAX 4 #define LZMA_LITERAL_BITS_MAX 4
/**
* \brief Available LZMA encoding modes
*
* Pointer to an array containing the list of available encoding modes.
*
* This variable is available only if LZMA encoder has been enabled.
*/
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;
/** /**
* \brief Table of presets for the LZMA filter * \brief Table of presets for the LZMA filter
* *

View File

@ -58,7 +58,8 @@ typedef struct lzma_memlimit_s lzma_memlimit;
* lzma_memlimit_ can be used even if lzma_init() hasn't been * lzma_memlimit_ can be used even if lzma_init() hasn't been
* called. * 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 * \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,8 @@ extern size_t lzma_memlimit_get(const lzma_memlimit *mem);
* thus it will always be larger than the total number of * thus it will always be larger than the total number of
* bytes allocated via lzma_memlimit_alloc(). * 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;
/** /**
@ -134,7 +137,8 @@ extern lzma_bool lzma_memlimit_reached(lzma_memlimit *mem, lzma_bool clear);
* been allocated with lzma_memlimit_alloc() or all memory allocated * been allocated with lzma_memlimit_alloc() or all memory allocated
* has been freed or detached, this will return zero. * has been freed or detached, this will return zero.
*/ */
extern size_t lzma_memlimit_count(const lzma_memlimit *mem); extern size_t lzma_memlimit_count(const lzma_memlimit *mem)
lzma_attr_pure;
/** /**
@ -157,7 +161,8 @@ extern size_t lzma_memlimit_count(const lzma_memlimit *mem);
* invalid amount of memory being allocated. * invalid amount of memory being allocated.
*/ */
extern void *lzma_memlimit_alloc( 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;
/** /**

View File

@ -1,60 +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 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_options_filter *options);
/**
* \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);

View File

@ -21,7 +21,7 @@
#endif #endif
/* Filter IDs for lzma_options_filter.id */ /* Filter IDs for lzma_filter.id */
#define LZMA_FILTER_X86 LZMA_VLI_C(0x04) #define LZMA_FILTER_X86 LZMA_VLI_C(0x04)
/**< /**<

View File

@ -1,53 +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 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_options_filter *filters, lzma_check_type check);
/**
* \brief Initializes decoder for .lzma Stream
*
* \param strm Pointer to propertily prepared lzma_stream
*
* \return - LZMA_OK: Initialization was successful.
* - LZMA_MEM_ERROR: Cannot allocate memory.
*/
extern lzma_ret lzma_stream_decoder(lzma_stream *strm);

View File

@ -46,7 +46,7 @@ typedef struct {
/** /**
* Type of the Check calculated from uncompressed data * Type of the Check calculated from uncompressed data
*/ */
lzma_check_type check; lzma_check check;
} lzma_stream_flags; } lzma_stream_flags;
@ -64,7 +64,8 @@ typedef struct {
* - LZMA_PROG_ERROR: Invalid options. * - LZMA_PROG_ERROR: Invalid options.
*/ */
extern lzma_ret lzma_stream_header_encode( extern lzma_ret lzma_stream_header_encode(
const lzma_stream_flags *options, uint8_t *out); const lzma_stream_flags *options, uint8_t *out)
lzma_attr_warn_unused_result;
/** /**
@ -78,7 +79,8 @@ extern lzma_ret lzma_stream_header_encode(
* - LZMA_PROG_ERROR: Invalid options. * - LZMA_PROG_ERROR: Invalid options.
*/ */
extern lzma_ret lzma_stream_footer_encode( extern lzma_ret lzma_stream_footer_encode(
const lzma_stream_flags *options, uint8_t *out); const lzma_stream_flags *options, uint8_t *out)
lzma_attr_warn_unused_result;
/** /**
@ -101,7 +103,8 @@ extern lzma_ret lzma_stream_footer_encode(
* in the header. * in the header.
*/ */
extern lzma_ret lzma_stream_header_decode( extern lzma_ret lzma_stream_header_decode(
lzma_stream_flags *options, const uint8_t *in); lzma_stream_flags *options, const uint8_t *in)
lzma_attr_warn_unused_result;
/** /**
@ -120,7 +123,8 @@ extern lzma_ret lzma_stream_header_decode(
* in the footer. * in the footer.
*/ */
extern lzma_ret lzma_stream_footer_decode( extern lzma_ret lzma_stream_footer_decode(
lzma_stream_flags *options, const uint8_t *in); lzma_stream_flags *options, const uint8_t *in)
lzma_attr_warn_unused_result;
/** /**
@ -131,4 +135,5 @@ extern lzma_ret lzma_stream_footer_decode(
* \return true if both structures are considered equal; false otherwise. * \return true if both structures are considered equal; false otherwise.
*/ */
extern lzma_bool lzma_stream_flags_equal( extern lzma_bool lzma_stream_flags_equal(
const lzma_stream_flags *a, lzma_stream_flags *b); const lzma_stream_flags *a, const lzma_stream_flags *b)
lzma_attr_pure;

View File

@ -24,7 +24,7 @@
/** /**
* \brief Filter ID * \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) #define LZMA_FILTER_SUBBLOCK LZMA_VLI_C(0x01)
@ -199,6 +199,6 @@ typedef struct {
* *
* \note This variable is ignored if allow_subfilters is false. * \note This variable is ignored if allow_subfilters is false.
*/ */
lzma_options_filter subfilter_options; lzma_filter subfilter_options;
} lzma_options_subblock; } lzma_options_subblock;

View File

@ -41,17 +41,17 @@
/** /**
* \brief liblzma version number as an integer * \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, * This allows the application to compare if it was built against the same,
* older, or newer version of liblzma that is currently running. * 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 * This function may be useful if you want to display which version of
* libilzma your application is currently using. * liblzma your application is currently using.
*/ */
extern const char *const lzma_version_string; extern const char *lzma_version_string(void) lzma_attr_const;

View File

@ -71,91 +71,25 @@ typedef uint64_t lzma_vli;
((vli) <= LZMA_VLI_VALUE_MAX || (vli) == LZMA_VLI_VALUE_UNKNOWN) ((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 * \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 * representation. This saves space when smaller values are more likely
* than bigger values. * than bigger values.
* *
* The encoding scheme encodes seven bits to every byte, using minimum * The encoding scheme encodes seven bits to every byte, using minimum
* number of bytes required to represent the given value. In other words, * number of bytes required to represent the given value. Encodings that use
* it puts 7-63 bits into 1-9 bytes. This implementation limits the number * non-minimum number of bytes are invalid, thus every integer has exactly
* of bits used to 63, thus num must be at maximum of UINT64_MAX / 2. You * one encoded representation. The maximum number of bits in a VLI is 63,
* may use LZMA_VLI_VALUE_MAX for clarity. * 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 Integer to be encoded
* \param vli_pos How many VLI-encoded bytes have already been written * \param vli_pos How many VLI-encoded bytes have already been written
@ -170,19 +104,19 @@ typedef uint64_t lzma_vli;
* \return Slightly different return values are used in multi-call and * \return Slightly different return values are used in multi-call and
* single-call modes. * 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): * Multi-call (vli_pos != NULL):
* - LZMA_OK: So far all OK, but the integer is not * - LZMA_OK: So far all OK, but the integer is not
* completely written out yet. * completely written out yet.
* - LZMA_STREAM_END: Integer successfully encoded. * - LZMA_STREAM_END: Integer successfully encoded.
* - LZMA_PROG_ERROR: Arguments are not sane. This can be due * - LZMA_BUF_ERROR: No output space was provided.
* to no *out_pos == out_size; this function doesn't use * - LZMA_PROG_ERROR: Arguments are not sane.
* LZMA_BUF_ERROR.
*
* 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; this function doesn't use
* LZMA_BUF_ERROR.
*/ */
extern lzma_ret lzma_vli_encode( extern lzma_ret lzma_vli_encode(
lzma_vli vli, size_t *lzma_restrict vli_pos, lzma_vli vli, size_t *lzma_restrict vli_pos,
@ -193,6 +127,8 @@ extern lzma_ret lzma_vli_encode(
/** /**
* \brief Decodes variable-length integer * \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 * \param vli Pointer to decoded integer. The decoder will
* initialize it to zero when *vli_pos == 0, so * initialize it to zero when *vli_pos == 0, so
* application isn't required to initialize *vli. * application isn't required to initialize *vli.
@ -208,20 +144,20 @@ extern lzma_ret lzma_vli_encode(
* \return Slightly different return values are used in multi-call and * \return Slightly different return values are used in multi-call and
* single-call modes. * 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): * Multi-call (vli_pos != NULL):
* - LZMA_OK: So far all OK, but the integer is not * - LZMA_OK: So far all OK, but the integer is not
* completely decoded yet. * completely decoded yet.
* - LZMA_STREAM_END: Integer successfully decoded. * - LZMA_STREAM_END: Integer successfully decoded.
* - LZMA_DATA_ERROR: Integer is corrupt. * - LZMA_DATA_ERROR: Integer is corrupt.
* - LZMA_PROG_ERROR: Arguments are not sane. This can be * - LZMA_BUF_ERROR: No input was provided.
* due to *in_pos == in_size; this function doesn't use * - LZMA_PROG_ERROR: Arguments are not sane.
* LZMA_BUF_ERROR.
*
* Single-call (vli_pos == NULL):
* - LZMA_OK: Integer successfully decoded.
* - LZMA_DATA_ERROR: Integer is corrupt.
* - LZMA_PROG_ERROR: Arguments are not sane. This can be due to
* too little input; this function doesn't use LZMA_BUF_ERROR.
*/ */
extern lzma_ret lzma_vli_decode(lzma_vli *lzma_restrict vli, extern lzma_ret lzma_vli_decode(lzma_vli *lzma_restrict vli,
size_t *lzma_restrict vli_pos, const uint8_t *lzma_restrict in, size_t *lzma_restrict vli_pos, const uint8_t *lzma_restrict in,
@ -234,4 +170,5 @@ extern lzma_ret lzma_vli_decode(lzma_vli *lzma_restrict vli,
* \return Number of bytes on success (1-9). If vli isn't valid, * \return Number of bytes on success (1-9). If vli isn't valid,
* zero is returned. * zero is returned.
*/ */
extern uint32_t lzma_vli_size(lzma_vli vli); extern uint32_t lzma_vli_size(lzma_vli vli)
lzma_attr_pure;

View File

@ -13,60 +13,77 @@
#include "check.h" #include "check.h"
// See the .lzma header format specification section 2.1.1.2.
LZMA_API const uint32_t lzma_check_sizes[LZMA_CHECK_ID_MAX + 1] = {
0,
4, 4, 4,
8, 8, 8,
16, 16, 16,
32, 32, 32,
64, 64, 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] = { static const lzma_bool available_checks[LZMA_CHECK_ID_MAX + 1] = {
true, // LZMA_CHECK_NONE true, // LZMA_CHECK_NONE
#ifdef HAVE_CHECK_CRC32 #ifdef HAVE_CHECK_CRC32
true, true,
#else #else
false, false,
#endif #endif
false, // Reserved false, // Reserved
false, // Reserved false, // Reserved
#ifdef HAVE_CHECK_CRC64 #ifdef HAVE_CHECK_CRC64
true, true,
#else #else
false, false,
#endif #endif
false, // Reserved false, // Reserved
false, // Reserved false, // Reserved
false, // Reserved false, // Reserved
false, // Reserved false, // Reserved
false, // Reserved false, // Reserved
#ifdef HAVE_CHECK_SHA256 #ifdef HAVE_CHECK_SHA256
true, true,
#else #else
false, false,
#endif #endif
false, // Reserved false, // Reserved
false, // Reserved false, // Reserved
false, // Reserved false, // Reserved
false, // Reserved false, // Reserved
false, // Reserved false, // Reserved
}; };
return available_checks[(unsigned)(type)];
}
extern lzma_ret extern LZMA_API uint32_t
lzma_check_init(lzma_check *check, lzma_check_type type) 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) { switch (type) {
case LZMA_CHECK_NONE: case LZMA_CHECK_NONE:
break; break;
@ -90,19 +107,15 @@ lzma_check_init(lzma_check *check, lzma_check_type type)
#endif #endif
default: default:
if ((unsigned)(type) <= LZMA_CHECK_ID_MAX)
ret = LZMA_UNSUPPORTED_CHECK;
else
ret = LZMA_PROG_ERROR;
break; break;
} }
return ret; return;
} }
extern void 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) const uint8_t *buf, size_t size)
{ {
switch (type) { switch (type) {
@ -133,18 +146,18 @@ lzma_check_update(lzma_check *check, lzma_check_type type,
extern void extern void
lzma_check_finish(lzma_check *check, lzma_check_type type) lzma_check_finish(lzma_check_state *check, lzma_check type)
{ {
switch (type) { switch (type) {
#ifdef HAVE_CHECK_CRC32 #ifdef HAVE_CHECK_CRC32
case LZMA_CHECK_CRC32: case LZMA_CHECK_CRC32:
*(uint32_t *)(check->buffer) = check->state.crc32; check->buffer.u32[0] = integer_le_32(check->state.crc32);
break; break;
#endif #endif
#ifdef HAVE_CHECK_CRC64 #ifdef HAVE_CHECK_CRC64
case LZMA_CHECK_CRC64: case LZMA_CHECK_CRC64:
*(uint64_t *)(check->buffer) = check->state.crc64; check->buffer.u64[0] = integer_le_64(check->state.crc64);
break; break;
#endif #endif
@ -160,34 +173,3 @@ lzma_check_finish(lzma_check *check, lzma_check_type type)
return; 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;
case LZMA_CHECK_CRC64:
ret = check1->crc64 != check2->crc64;
break;
default:
// Unsupported check
assert(type <= 7);
ret = false;
break;
}
return ret;
}
*/

View File

@ -1,7 +1,7 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
/// \file check.h /// \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. // This code has been put into the public domain.
// //
@ -17,8 +17,8 @@
#include "common.h" #include "common.h"
// Index hashing used to verify the Index with O(1) memory usage needs // Index hashing needs the best possible hash function (preferably
// a good hash function. // a cryptographic hash) for maximum reliability.
#if defined(HAVE_CHECK_SHA256) #if defined(HAVE_CHECK_SHA256)
# define LZMA_CHECK_BEST LZMA_CHECK_SHA256 # define LZMA_CHECK_BEST LZMA_CHECK_SHA256
#elif defined(HAVE_CHECK_CRC64) #elif defined(HAVE_CHECK_CRC64)
@ -28,24 +28,17 @@
#endif #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 { typedef struct {
/// Internal state /// Buffer to hold the final result and a temporary buffer for SHA256.
uint32_t state[8]; union {
uint8_t u8[64];
/// Size of the message excluding padding uint32_t u32[16];
uint64_t size; uint64_t u64[8];
} buffer;
} lzma_sha256;
/// \note This is not in the public API because this structure will
/// change in future.
typedef struct {
// FIXME Guarantee 8-byte alignment
/// Buffer to hold the final result; this is also used as a temporary
/// buffer in SHA256. Note that this buffer must be 8-byte aligned.
uint8_t buffer[64];
/// Check-specific data /// Check-specific data
union { union {
@ -61,7 +54,7 @@ typedef struct {
} sha256; } sha256;
} state; } state;
} lzma_check; } lzma_check_state;
#ifdef HAVE_SMALL #ifdef HAVE_SMALL
@ -72,7 +65,6 @@ extern const uint32_t lzma_crc32_table[8][256];
extern const uint64_t lzma_crc64_table[4][256]; extern const uint64_t lzma_crc64_table[4][256];
#endif #endif
// Generic
/// \brief Initializes *check depending on type /// \brief Initializes *check depending on type
/// ///
@ -80,46 +72,31 @@ extern const uint64_t lzma_crc64_table[4][256];
/// supported by the current version or build of liblzma. /// supported by the current version or build of liblzma.
/// LZMA_PROG_ERROR if type > LZMA_CHECK_ID_MAX. /// 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 /// \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); const uint8_t *buf, size_t size);
/// \brief Finishes *check /// \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); extern void lzma_crc32_init(void);
// CRC64
extern void lzma_crc64_init(void); extern void lzma_crc64_init(void);
// SHA256 extern void lzma_sha256_init(lzma_check_state *check);
extern void lzma_sha256_init(lzma_check *check);
extern void lzma_sha256_update( extern void lzma_sha256_update(
const uint8_t *buf, size_t size, lzma_check *check); const uint8_t *buf, size_t size, lzma_check_state *check);
extern void lzma_sha256_finish(lzma_check *check);
extern void lzma_sha256_finish(lzma_check_state *check);
#endif #endif

View File

@ -104,16 +104,16 @@ transform(uint32_t state[static 8], const uint32_t data[static 16])
static void static void
process(lzma_check *check) process(lzma_check_state *check)
{ {
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
transform(check->state.sha256.state, (uint32_t *)(check->buffer)); transform(check->state.sha256.state, check->buffer.u32);
#else #else
uint32_t data[16]; uint32_t data[16];
for (size_t i = 0; i < 16; ++i) for (size_t i = 0; i < 16; ++i)
data[i] = bswap_32(*((uint32_t*)(check->buffer) + i)); data[i] = bswap_32(check->buffer.u32[i]);
transform(check->state.sha256.state, data); transform(check->state.sha256.state, data);
#endif #endif
@ -123,7 +123,7 @@ process(lzma_check *check)
extern void extern void
lzma_sha256_init(lzma_check *check) lzma_sha256_init(lzma_check_state *check)
{ {
static const uint32_t s[8] = { static const uint32_t s[8] = {
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
@ -138,7 +138,7 @@ lzma_sha256_init(lzma_check *check)
extern void extern void
lzma_sha256_update(const uint8_t *buf, size_t size, lzma_check *check) lzma_sha256_update(const uint8_t *buf, size_t size, lzma_check_state *check)
{ {
// Copy the input data into a properly aligned temporary buffer. // Copy the input data into a properly aligned temporary buffer.
// This way we can be called with arbitrarily sized buffers // This way we can be called with arbitrarily sized buffers
@ -150,7 +150,7 @@ lzma_sha256_update(const uint8_t *buf, size_t size, lzma_check *check)
if (copy_size > size) if (copy_size > size)
copy_size = size; copy_size = size;
memcpy(check->buffer + copy_start, buf, copy_size); memcpy(check->buffer.u8 + copy_start, buf, copy_size);
buf += copy_size; buf += copy_size;
size -= copy_size; size -= copy_size;
@ -165,12 +165,12 @@ lzma_sha256_update(const uint8_t *buf, size_t size, lzma_check *check)
extern void extern void
lzma_sha256_finish(lzma_check *check) lzma_sha256_finish(lzma_check_state *check)
{ {
// Add padding as described in RFC 3174 (it describes SHA-1 but // Add padding as described in RFC 3174 (it describes SHA-1 but
// the same padding style is used for SHA-256 too). // the same padding style is used for SHA-256 too).
size_t pos = check->state.sha256.size & 0x3F; size_t pos = check->state.sha256.size & 0x3F;
check->buffer[pos++] = 0x80; check->buffer.u8[pos++] = 0x80;
while (pos != 64 - 8) { while (pos != 64 - 8) {
if (pos == 64) { if (pos == 64) {
@ -178,28 +178,25 @@ lzma_sha256_finish(lzma_check *check)
pos = 0; pos = 0;
} }
check->buffer[pos++] = 0x00; check->buffer.u8[pos++] = 0x00;
} }
// Convert the message size from bytes to bits. // Convert the message size from bytes to bits.
check->state.sha256.size *= 8; check->state.sha256.size *= 8;
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
*(uint64_t *)(check->buffer + 64 - 8) = check->state.sha256.size; check->buffer.u64[(64 - 8) / 8] = check->state.sha256.size;
#else #else
*(uint64_t *)(check->buffer + 64 - 8) check->buffer.u64[(64 - 8) / 8] = bswap_64(check->state.sha256.size);
= bswap_64(check->state.sha256.size);
#endif #endif
process(check); process(check);
for (size_t i = 0; i < 8; ++i) for (size_t i = 0; i < 8; ++i)
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
((uint32_t *)(check->buffer))[i] check->buffer.u32[i] = check->state.sha256.state[i];
= check->state.sha256.state[i];
#else #else
((uint32_t *)(check->buffer))[i] check->buffer.u32[i] = bswap_32(check->state.sha256.state[i]);
= bswap_32(check->state.sha256.state[i]);
#endif #endif
return; return;

View File

@ -16,62 +16,43 @@ noinst_LTLIBRARIES = libcommon.la
libcommon_la_CPPFLAGS = \ libcommon_la_CPPFLAGS = \
-I@top_srcdir@/src/liblzma/api \ -I@top_srcdir@/src/liblzma/api \
-I@top_srcdir@/src/liblzma/check \ -I@top_srcdir@/src/liblzma/check \
-I@top_srcdir@/src/liblzma/rangecoder \
-I@top_srcdir@/src/liblzma/lz \ -I@top_srcdir@/src/liblzma/lz \
-I@top_srcdir@/src/liblzma/lzma \ -I@top_srcdir@/src/liblzma/lzma \
-I@top_srcdir@/src/liblzma/simple \
-I@top_srcdir@/src/liblzma/subblock \ -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 = \ libcommon_la_SOURCES = \
common.c \
common.h \ common.h \
bsr.h \ bsr.h \
allocator.c \
block_util.c \ block_util.c \
block_private.h \ block_private.h \
features.c \ filter_common.c \
filter_common.h \
index.c \ index.c \
index.h \
init.c \ init.c \
memory_limiter.c \ memory_limiter.c \
memory_usage.c \ stream_flags_common.c \
next_coder.c \ stream_flags_common.h \
raw_common.c \ vli_size.c
raw_common.h \
stream_flags_equal.c \
code.c \
version.c
if COND_FILTER_DELTA
libcommon_la_SOURCES += \
delta_common.c \
delta_common.h
if COND_MAIN_ENCODER
libcommon_la_SOURCES += \
delta_encoder.c \
delta_encoder.h
endif
if COND_MAIN_DECODER
libcommon_la_SOURCES += \
delta_decoder.c \
delta_decoder.h
endif
endif
if COND_MAIN_ENCODER if COND_MAIN_ENCODER
libcommon_la_SOURCES += \ libcommon_la_SOURCES += \
alignment.c \ alignment.c \
auto_decoder.c \
alone_encoder.c \ alone_encoder.c \
block_encoder.c \ block_encoder.c \
block_encoder.h \ block_encoder.h \
block_header_encoder.c \ block_header_encoder.c \
easy.c \ easy.c \
filter_encoder.c \
filter_encoder.h \
filter_flags_encoder.c \ filter_flags_encoder.c \
index_encoder.c \ index_encoder.c \
index_encoder.h \ index_encoder.h \
init_encoder.c \ init_encoder.c \
raw_encoder.c \
raw_encoder.h \
stream_common.c \
stream_common.h \
stream_encoder.c \ stream_encoder.c \
stream_encoder.h \ stream_encoder.h \
stream_flags_encoder.c \ stream_flags_encoder.c \
@ -82,16 +63,18 @@ if COND_MAIN_DECODER
libcommon_la_SOURCES += \ libcommon_la_SOURCES += \
alone_decoder.c \ alone_decoder.c \
alone_decoder.h \ alone_decoder.h \
auto_decoder.c \
block_decoder.c \ block_decoder.c \
block_decoder.h \ block_decoder.h \
block_header_decoder.c \ block_header_decoder.c \
filter_decoder.c \
filter_decoder.h \
filter_flags_decoder.c \ filter_flags_decoder.c \
index_decoder.c \ index_decoder.c \
index_hash.c \ index_hash.c \
init_decoder.c \ init_decoder.c \
raw_decoder.c \
raw_decoder.h \
stream_decoder.c \ stream_decoder.c \
stream_decoder.h \
stream_flags_decoder.c \ stream_flags_decoder.c \
stream_flags_decoder.h \ stream_flags_decoder.h \
vli_decoder.c vli_decoder.c

View File

@ -21,7 +21,7 @@
extern LZMA_API uint32_t 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) { for (size_t i = 0; filters[i].id != LZMA_VLI_VALUE_UNKNOWN; ++i) {
switch (filters[i].id) { switch (filters[i].id) {
@ -66,7 +66,7 @@ lzma_alignment_input(const lzma_options_filter *filters, uint32_t guess)
extern LZMA_API uint32_t 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)
{ {
if (filters[0].id == LZMA_VLI_VALUE_UNKNOWN) if (filters[0].id == LZMA_VLI_VALUE_UNKNOWN)
return UINT32_MAX; return UINT32_MAX;

View File

@ -1,58 +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);
#ifndef NDEBUG
// This helps to catch some stupid mistakes, but also hides them from
// Valgrind. Uncomment when useful.
// 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;
}

View File

@ -19,6 +19,7 @@
#include "alone_decoder.h" #include "alone_decoder.h"
#include "lzma_decoder.h" #include "lzma_decoder.h"
#include "lz_decoder.h"
struct lzma_coder_s { struct lzma_coder_s {
@ -38,6 +39,9 @@ struct lzma_coder_s {
/// Uncompressed size decoded from the header /// Uncompressed size decoded from the header
lzma_vli uncompressed_size; lzma_vli uncompressed_size;
/// Memory usage limit
uint64_t memlimit;
/// Options decoded from the header needed to initialize /// Options decoded from the header needed to initialize
/// the LZMA decoder /// the LZMA decoder
lzma_options_lzma options; lzma_options_lzma options;
@ -56,7 +60,7 @@ alone_decode(lzma_coder *coder,
&& (coder->sequence == SEQ_CODE || *in_pos < in_size)) && (coder->sequence == SEQ_CODE || *in_pos < in_size))
switch (coder->sequence) { switch (coder->sequence) {
case SEQ_PROPERTIES: case SEQ_PROPERTIES:
if (lzma_lzma_decode_properties(&coder->options, in[*in_pos])) if (lzma_lzma_lclppb_decode(&coder->options, in[*in_pos]))
return LZMA_FORMAT_ERROR; return LZMA_FORMAT_ERROR;
coder->sequence = SEQ_DICTIONARY_SIZE; coder->sequence = SEQ_DICTIONARY_SIZE;
@ -69,8 +73,6 @@ alone_decode(lzma_coder *coder,
if (++coder->pos == 4) { if (++coder->pos == 4) {
if (coder->options.dictionary_size if (coder->options.dictionary_size
< LZMA_DICTIONARY_SIZE_MIN
|| coder->options.dictionary_size
> LZMA_DICTIONARY_SIZE_MAX) > LZMA_DICTIONARY_SIZE_MAX)
return LZMA_FORMAT_ERROR; return LZMA_FORMAT_ERROR;
@ -119,7 +121,20 @@ alone_decode(lzma_coder *coder,
break; break;
case SEQ_CODER_INIT: { 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] = { lzma_filter_info filters[2] = {
{ {
.init = &lzma_lzma_decoder_init, .init = &lzma_lzma_decoder_init,
@ -135,7 +150,7 @@ alone_decode(lzma_coder *coder,
return ret; return ret;
// Use a hack to set the uncompressed size. // Use a hack to set the uncompressed size.
lzma_lzma_decoder_uncompressed_size(&coder->next, lzma_lz_decoder_uncompressed(coder->next.coder,
coder->uncompressed_size); coder->uncompressed_size);
coder->sequence = SEQ_CODE; coder->sequence = SEQ_CODE;
@ -160,15 +175,18 @@ alone_decode(lzma_coder *coder,
static void static void
alone_decoder_end(lzma_coder *coder, lzma_allocator *allocator) 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); lzma_free(coder, allocator);
return; return;
} }
static lzma_ret extern lzma_ret
alone_decoder_init(lzma_next_coder *next, lzma_allocator *allocator) 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) { if (next->coder == NULL) {
next->coder = lzma_alloc(sizeof(lzma_coder), allocator); next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
if (next->coder == NULL) if (next->coder == NULL)
@ -183,25 +201,20 @@ alone_decoder_init(lzma_next_coder *next, lzma_allocator *allocator)
next->coder->pos = 0; next->coder->pos = 0;
next->coder->options.dictionary_size = 0; next->coder->options.dictionary_size = 0;
next->coder->uncompressed_size = 0; next->coder->uncompressed_size = 0;
next->coder->memlimit = memlimit;
return LZMA_OK; return LZMA_OK;
} }
extern lzma_ret
lzma_alone_decoder_init(lzma_next_coder *next, lzma_allocator *allocator)
{
lzma_next_coder_init0(alone_decoder_init, next, allocator);
}
extern LZMA_API lzma_ret extern LZMA_API lzma_ret
lzma_alone_decoder(lzma_stream *strm) lzma_alone_decoder(lzma_stream *strm, uint64_t memlimit)
{ {
lzma_next_strm_init0(strm, alone_decoder_init); lzma_next_strm_init(lzma_alone_decoder_init, strm, memlimit);
strm->internal->supported_actions[LZMA_RUN] = true; strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true; // strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true; FIXME
strm->internal->supported_actions[LZMA_FINISH] = true;
return LZMA_OK; return LZMA_OK;
} }

View File

@ -17,8 +17,13 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#ifndef LZMA_ALONE_DECODER_H
#define LZMA_ALONE_DECODER_H
#include "common.h" #include "common.h"
extern lzma_ret lzma_alone_decoder_init( extern lzma_ret lzma_alone_decoder_init(lzma_next_coder *next,
lzma_next_coder *next, lzma_allocator *allocator); lzma_allocator *allocator, uint64_t memlimit);
#endif

View File

@ -48,7 +48,7 @@ alone_encode(lzma_coder *coder,
while (*out_pos < out_size) while (*out_pos < out_size)
switch (coder->sequence) { switch (coder->sequence) {
case SEQ_HEADER: case SEQ_HEADER:
bufcpy(coder->header, &coder->header_pos, lzma_bufcpy(coder->header, &coder->header_pos,
ALONE_HEADER_SIZE, ALONE_HEADER_SIZE,
out, out_pos, out_size); out, out_pos, out_size);
if (coder->header_pos < ALONE_HEADER_SIZE) if (coder->header_pos < ALONE_HEADER_SIZE)
@ -74,7 +74,7 @@ alone_encode(lzma_coder *coder,
static void static void
alone_encoder_end(lzma_coder *coder, lzma_allocator *allocator) 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); lzma_free(coder, allocator);
return; return;
} }
@ -85,6 +85,8 @@ static lzma_ret
alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator, alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
const lzma_options_lzma *options) const lzma_options_lzma *options)
{ {
lzma_next_coder_init(alone_encoder_init, next, allocator);
if (next->coder == NULL) { if (next->coder == NULL) {
next->coder = lzma_alloc(sizeof(lzma_coder), allocator); next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
if (next->coder == NULL) if (next->coder == NULL)
@ -101,7 +103,7 @@ alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
// Encode the header: // Encode the header:
// - Properties (1 byte) // - Properties (1 byte)
if (lzma_lzma_encode_properties(options, next->coder->header)) if (lzma_lzma_lclppb_encode(options, next->coder->header))
return LZMA_PROG_ERROR; return LZMA_PROG_ERROR;
// - Dictionary size (4 bytes) // - Dictionary size (4 bytes)
@ -113,6 +115,9 @@ alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
// one is the next. While the header would allow any 32-bit integer, // 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 // we do this to keep the decoder of liblzma accepting the resulting
// files. // 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; uint32_t d = options->dictionary_size - 1;
d |= d >> 2; d |= d >> 2;
d |= d >> 3; d |= d >> 3;
@ -153,7 +158,7 @@ lzma_alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern LZMA_API lzma_ret extern LZMA_API lzma_ret
lzma_alone_encoder(lzma_stream *strm, const lzma_options_lzma *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_RUN] = true;
strm->internal->supported_actions[LZMA_FINISH] = true; strm->internal->supported_actions[LZMA_FINISH] = true;

View File

@ -23,6 +23,8 @@
struct lzma_coder_s { struct lzma_coder_s {
lzma_next_coder next; lzma_next_coder next;
uint64_t memlimit;
uint32_t flags;
bool initialized; bool initialized;
}; };
@ -41,9 +43,11 @@ auto_decode(lzma_coder *coder, lzma_allocator *allocator,
if (in[*in_pos] == 0xFF) if (in[*in_pos] == 0xFF)
ret = lzma_stream_decoder_init( ret = lzma_stream_decoder_init(
&coder->next, allocator); &coder->next, allocator,
coder->memlimit, coder->flags);
else else
ret = lzma_alone_decoder_init(&coder->next, allocator); ret = lzma_alone_decoder_init(&coder->next,
allocator, coder->memlimit);
if (ret != LZMA_OK) if (ret != LZMA_OK)
return ret; return ret;
@ -59,15 +63,21 @@ auto_decode(lzma_coder *coder, lzma_allocator *allocator,
static void static void
auto_decoder_end(lzma_coder *coder, lzma_allocator *allocator) 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); lzma_free(coder, allocator);
return; return;
} }
static lzma_ret static lzma_ret
auto_decoder_init(lzma_next_coder *next, lzma_allocator *allocator) auto_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
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) { if (next->coder == NULL) {
next->coder = lzma_alloc(sizeof(lzma_coder), allocator); next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
if (next->coder == NULL) if (next->coder == NULL)
@ -78,30 +88,22 @@ auto_decoder_init(lzma_next_coder *next, lzma_allocator *allocator)
next->coder->next = LZMA_NEXT_CODER_INIT; next->coder->next = LZMA_NEXT_CODER_INIT;
} }
next->coder->memlimit = memlimit;
next->coder->flags = flags;
next->coder->initialized = false; next->coder->initialized = false;
return LZMA_OK; 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 extern LZMA_API lzma_ret
lzma_auto_decoder(lzma_stream *strm) lzma_auto_decoder(lzma_stream *strm, uint64_t memlimit, uint32_t flags)
{ {
lzma_next_strm_init0(strm, auto_decoder_init); lzma_next_strm_init(auto_decoder_init, strm, memlimit, flags);
strm->internal->supported_actions[LZMA_RUN] = true; strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true; // strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true; FIXME
strm->internal->supported_actions[LZMA_FINISH] = true;
return LZMA_OK; return LZMA_OK;
} }

View File

@ -19,7 +19,7 @@
#include "block_decoder.h" #include "block_decoder.h"
#include "block_private.h" #include "block_private.h"
#include "raw_decoder.h" #include "filter_decoder.h"
#include "check.h" #include "check.h"
@ -35,7 +35,7 @@ struct lzma_coder_s {
/// Decoding options; we also write Compressed Size and Uncompressed /// Decoding options; we also write Compressed Size and Uncompressed
/// Size back to this structure when the encoding has been finished. /// Size back to this structure when the encoding has been finished.
lzma_options_block *options; lzma_block *options;
/// Compressed Size calculated while encoding /// Compressed Size calculated while encoding
lzma_vli compressed_size; lzma_vli compressed_size;
@ -52,7 +52,7 @@ struct lzma_coder_s {
size_t check_pos; size_t check_pos;
/// Check of the uncompressed data /// Check of the uncompressed data
lzma_check check; lzma_check_state check;
}; };
@ -64,9 +64,6 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
{ {
switch (coder->sequence) { switch (coder->sequence) {
case SEQ_CODE: { case SEQ_CODE: {
if (*out_pos >= out_size)
return LZMA_OK;
const size_t in_start = *in_pos; const size_t in_start = *in_pos;
const size_t out_start = *out_pos; const size_t out_start = *out_pos;
@ -98,7 +95,7 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
// Fall through // Fall through
case SEQ_PADDING: case SEQ_PADDING:
// If Compressed Data is padded to a multiple of four bytes. // Compressed Data is padded to a multiple of four bytes.
while (coder->compressed_size & 3) { while (coder->compressed_size & 3) {
if (*in_pos >= in_size) if (*in_pos >= in_size)
return LZMA_OK; return LZMA_OK;
@ -132,19 +129,29 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
// Fall through // Fall through
case SEQ_CHECK: case SEQ_CHECK: {
while (*in_pos < in_size) { const bool chksup = lzma_check_is_supported(
if (in[(*in_pos)++] != coder->check.buffer[ coder->options->check);
coder->check_pos])
return LZMA_DATA_ERROR;
if (++coder->check_pos == lzma_check_sizes[ while (*in_pos < in_size) {
coder->options->check]) // 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_STREAM_END;
} }
return LZMA_OK; return LZMA_OK;
} }
}
return LZMA_PROG_ERROR; return LZMA_PROG_ERROR;
} }
@ -153,21 +160,28 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
static void static void
block_decoder_end(lzma_coder *coder, lzma_allocator *allocator) 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); lzma_free(coder, allocator);
return; return;
} }
static lzma_ret extern lzma_ret
block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator, lzma_block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
lzma_options_block *options) lzma_block *options)
{ {
lzma_next_coder_init(lzma_block_decoder_init, next, allocator);
// While lzma_block_total_size_get() is meant to calculate the Total // While lzma_block_total_size_get() is meant to calculate the Total
// Size, it also validates the options excluding the filters. // Size, it also validates the options excluding the filters.
if (lzma_block_total_size_get(options) == 0) if (lzma_block_total_size_get(options) == 0)
return LZMA_PROG_ERROR; 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. // Allocate and initialize *next->coder if needed.
if (next->coder == NULL) { if (next->coder == NULL) {
next->coder = lzma_alloc(sizeof(lzma_coder), allocator); next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
@ -192,30 +206,25 @@ block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
= options->compressed_size == LZMA_VLI_VALUE_UNKNOWN = options->compressed_size == LZMA_VLI_VALUE_UNKNOWN
? (LZMA_VLI_VALUE_MAX & ~LZMA_VLI_C(3)) ? (LZMA_VLI_VALUE_MAX & ~LZMA_VLI_C(3))
- options->header_size - options->header_size
- lzma_check_sizes[options->check] - lzma_check_size(options->check)
: options->compressed_size; : options->compressed_size;
// Initialize the check // 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; next->coder->check_pos = 0;
return_if_error(lzma_check_init(&next->coder->check, options->check)); lzma_check_init(&next->coder->check, options->check);
// Initialize the filter chain.
return lzma_raw_decoder_init(&next->coder->next, allocator, return lzma_raw_decoder_init(&next->coder->next, allocator,
options->filters); options->filters);
} }
extern lzma_ret
lzma_block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
lzma_options_block *options)
{
lzma_next_coder_init(block_decoder_init, next, allocator, options);
}
extern LZMA_API lzma_ret 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, 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_RUN] = true;
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true; strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;

View File

@ -24,6 +24,6 @@
extern lzma_ret lzma_block_decoder_init(lzma_next_coder *next, 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 #endif

View File

@ -19,7 +19,7 @@
#include "block_encoder.h" #include "block_encoder.h"
#include "block_private.h" #include "block_private.h"
#include "raw_encoder.h" #include "filter_encoder.h"
#include "check.h" #include "check.h"
@ -30,7 +30,7 @@ struct lzma_coder_s {
/// Encoding options; we also write Total Size, Compressed Size, and /// Encoding options; we also write Total Size, Compressed Size, and
/// Uncompressed Size back to this structure when the encoding has /// Uncompressed Size back to this structure when the encoding has
/// been finished. /// been finished.
lzma_options_block *options; lzma_block *options;
enum { enum {
SEQ_CODE, SEQ_CODE,
@ -48,7 +48,7 @@ struct lzma_coder_s {
size_t check_pos; size_t check_pos;
/// Check of the uncompressed data /// Check of the uncompressed data
lzma_check check; lzma_check_state check;
}; };
@ -147,11 +147,11 @@ block_encode(lzma_coder *coder, lzma_allocator *allocator,
// Fall through // Fall through
case SEQ_CHECK: case SEQ_CHECK:
out[*out_pos] = coder->check.buffer[coder->check_pos]; out[*out_pos] = coder->check.buffer.u8[coder->check_pos];
++*out_pos; ++*out_pos;
if (++coder->check_pos if (++coder->check_pos
== lzma_check_sizes[coder->options->check]) == lzma_check_size(coder->options->check))
return LZMA_STREAM_END; return LZMA_STREAM_END;
break; break;
@ -167,21 +167,31 @@ block_encode(lzma_coder *coder, lzma_allocator *allocator,
static void static void
block_encoder_end(lzma_coder *coder, lzma_allocator *allocator) 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); lzma_free(coder, allocator);
return; return;
} }
static lzma_ret extern lzma_ret
block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator, lzma_block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
lzma_options_block *options) lzma_block *options)
{ {
lzma_next_coder_init(lzma_block_encoder_init, next, allocator);
// While lzma_block_total_size_get() is meant to calculate the Total // While lzma_block_total_size_get() is meant to calculate the Total
// Size, it also validates the options excluding the filters. // Size, it also validates the options excluding the filters.
if (lzma_block_total_size_get(options) == 0) if (lzma_block_total_size_get(options) == 0)
return LZMA_PROG_ERROR; 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. // Allocate and initialize *next->coder if needed.
if (next->coder == NULL) { if (next->coder == NULL) {
next->coder = lzma_alloc(sizeof(lzma_coder), allocator); next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
@ -201,7 +211,7 @@ block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
// Initialize the check // Initialize the check
next->coder->check_pos = 0; next->coder->check_pos = 0;
return_if_error(lzma_check_init(&next->coder->check, options->check)); lzma_check_init(&next->coder->check, options->check);
// Initialize the requested filters. // Initialize the requested filters.
return lzma_raw_encoder_init(&next->coder->next, allocator, return lzma_raw_encoder_init(&next->coder->next, allocator,
@ -209,18 +219,10 @@ block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
} }
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);
}
extern LZMA_API lzma_ret 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_RUN] = true;
strm->internal->supported_actions[LZMA_FINISH] = true; strm->internal->supported_actions[LZMA_FINISH] = true;

View File

@ -24,6 +24,6 @@
extern lzma_ret lzma_block_encoder_init(lzma_next_coder *next, 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 #endif

View File

@ -22,7 +22,7 @@
static void static void
free_properties(lzma_options_block *options, lzma_allocator *allocator) free_properties(lzma_block *options, lzma_allocator *allocator)
{ {
// Free allocated filter options. The last array member is not // Free allocated filter options. The last array member is not
// touched after the initialization in the beginning of // touched after the initialization in the beginning of
@ -38,12 +38,12 @@ free_properties(lzma_options_block *options, lzma_allocator *allocator)
extern LZMA_API lzma_ret extern LZMA_API lzma_ret
lzma_block_header_decode(lzma_options_block *options, lzma_block_header_decode(lzma_block *options,
lzma_allocator *allocator, const uint8_t *in) lzma_allocator *allocator, const uint8_t *in)
{ {
// NOTE: We consider the header to be corrupt not only when the // NOTE: We consider the header to be corrupt not only when the
// CRC32 doesn't match, but also when variable-length integers // CRC32 doesn't match, but also when variable-length integers
// are invalid or not over 63 bits, or if the header is too small // are invalid or over 63 bits, or if the header is too small
// to contain the claimed information. // to contain the claimed information.
// Initialize the filter options array. This way the caller can // Initialize the filter options array. This way the caller can

View File

@ -22,7 +22,7 @@
extern LZMA_API lzma_ret extern LZMA_API lzma_ret
lzma_block_header_size(lzma_options_block *options) lzma_block_header_size(lzma_block *options)
{ {
// Block Header Size + Block Flags + CRC32. // Block Header Size + Block Flags + CRC32.
size_t size = 1 + 1 + 4; size_t size = 1 + 1 + 4;
@ -77,7 +77,7 @@ lzma_block_header_size(lzma_options_block *options)
extern LZMA_API lzma_ret extern LZMA_API lzma_ret
lzma_block_header_encode(const lzma_options_block *options, uint8_t *out) lzma_block_header_encode(const lzma_block *options, uint8_t *out)
{ {
if ((options->header_size & 3) if ((options->header_size & 3)
|| options->header_size < LZMA_BLOCK_HEADER_SIZE_MIN || options->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
@ -127,8 +127,9 @@ lzma_block_header_encode(const lzma_options_block *options, uint8_t *out)
if (filter_count == 4) if (filter_count == 4)
return LZMA_PROG_ERROR; return LZMA_PROG_ERROR;
return_if_error(lzma_filter_flags_encode(out, &out_pos, return_if_error(lzma_filter_flags_encode(
out_size, options->filters + filter_count)); options->filters + filter_count,
out, &out_pos, out_size));
} while (options->filters[++filter_count].id } while (options->filters[++filter_count].id
!= LZMA_VLI_VALUE_UNKNOWN); != LZMA_VLI_VALUE_UNKNOWN);

View File

@ -1,7 +1,7 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
/// \file block_header.c /// \file block_header.c
/// \brief Utility functions to handle lzma_options_block /// \brief Utility functions to handle lzma_block
// //
// Copyright (C) 2008 Lasse Collin // Copyright (C) 2008 Lasse Collin
// //
@ -21,7 +21,7 @@
extern LZMA_API lzma_ret extern LZMA_API lzma_ret
lzma_block_total_size_set(lzma_options_block *options, lzma_vli total_size) lzma_block_total_size_set(lzma_block *options, lzma_vli total_size)
{ {
// Validate. // Validate.
if (options->header_size < LZMA_BLOCK_HEADER_SIZE_MIN if (options->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
@ -32,7 +32,7 @@ lzma_block_total_size_set(lzma_options_block *options, lzma_vli total_size)
return LZMA_PROG_ERROR; return LZMA_PROG_ERROR;
const uint32_t container_size = options->header_size const uint32_t container_size = options->header_size
+ lzma_check_sizes[options->check]; + lzma_check_size(options->check);
// Validate that Compressed Size will be greater than zero. // Validate that Compressed Size will be greater than zero.
if (container_size <= total_size) if (container_size <= total_size)
@ -45,7 +45,7 @@ lzma_block_total_size_set(lzma_options_block *options, lzma_vli total_size)
extern LZMA_API lzma_vli extern LZMA_API lzma_vli
lzma_block_total_size_get(const lzma_options_block *options) lzma_block_total_size_get(const lzma_block *options)
{ {
// Validate the values that we are interested in. // Validate the values that we are interested in.
if (options->header_size < LZMA_BLOCK_HEADER_SIZE_MIN if (options->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
@ -61,7 +61,7 @@ lzma_block_total_size_get(const lzma_options_block *options)
const lzma_vli total_size = options->compressed_size const lzma_vli total_size = options->compressed_size
+ options->header_size + options->header_size
+ lzma_check_sizes[options->check]; + lzma_check_size(options->check);
// Validate the calculated Total Size. // Validate the calculated Total Size.
if (options->compressed_size > LZMA_VLI_VALUE_MAX if (options->compressed_size > LZMA_VLI_VALUE_MAX

View File

@ -1,9 +1,9 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
/// \file code.c /// \file common.h
/// \brief zlib-like API wrapper for liblzma's internal API /// \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 // This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public // modify it under the terms of the GNU Lesser General Public
@ -20,17 +20,115 @@
#include "common.h" #include "common.h"
LZMA_API const lzma_stream LZMA_STREAM_INIT_VAR = { /////////////
.next_in = NULL, // Version //
.avail_in = 0, /////////////
.total_in = 0,
.next_out = NULL,
.avail_out = 0,
.total_out = 0,
.allocator = NULL,
.internal = NULL,
};
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 extern lzma_ret
lzma_strm_init(lzma_stream *strm) lzma_strm_init(lzma_stream *strm)
@ -191,10 +289,7 @@ extern LZMA_API void
lzma_end(lzma_stream *strm) lzma_end(lzma_stream *strm)
{ {
if (strm != NULL && strm->internal != NULL) { if (strm != NULL && strm->internal != NULL) {
if (strm->internal->next.end != NULL) lzma_next_end(&strm->internal->next, strm->allocator);
strm->internal->next.end(strm->internal->next.coder,
strm->allocator);
lzma_free(strm->internal, strm->allocator); lzma_free(strm->internal, strm->allocator);
strm->internal = NULL; strm->internal = NULL;
} }

View File

@ -3,7 +3,7 @@
/// \file common.h /// \file common.h
/// \brief Definitions common to the whole liblzma library /// \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 // This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public // modify it under the terms of the GNU Lesser General Public
@ -46,16 +46,32 @@
#define LZMA_BUFFER_SIZE 4096 #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 /// Internal helper filter used by Subblock decoder. It is mapped to an
/// otherwise invalid Filter ID, which is impossible to get from any input /// otherwise invalid Filter ID, which is impossible to get from any input
/// file (even if malicious file). /// 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_WARN_NO_CHECK \
| LZMA_WARN_UNSUPPORTED_CHECK \
| LZMA_TELL_CHECK \
| LZMA_CONCATENATED)
/////////// ///////////
// Types // // 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_coder_s lzma_coder;
typedef struct lzma_next_coder_s lzma_next_coder; typedef struct lzma_next_coder_s lzma_next_coder;
@ -63,10 +79,15 @@ typedef struct lzma_next_coder_s lzma_next_coder;
typedef struct lzma_filter_info_s lzma_filter_info; 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)( typedef lzma_ret (*lzma_init_function)(
lzma_next_coder *next, lzma_allocator *allocator, lzma_next_coder *next, lzma_allocator *allocator,
const lzma_filter_info *filters); 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)( typedef lzma_ret (*lzma_code_function)(
lzma_coder *coder, lzma_allocator *allocator, lzma_coder *coder, lzma_allocator *allocator,
const uint8_t *restrict in, size_t *restrict in_pos, const uint8_t *restrict in, size_t *restrict in_pos,
@ -74,54 +95,14 @@ typedef lzma_ret (*lzma_code_function)(
size_t *restrict out_pos, size_t out_size, size_t *restrict out_pos, size_t out_size,
lzma_action action); lzma_action action);
/// Type of a function to free the memory allocated for the coder
typedef void (*lzma_end_function)( typedef void (*lzma_end_function)(
lzma_coder *coder, lzma_allocator *allocator); lzma_coder *coder, lzma_allocator *allocator);
/// Hold data and function pointers of the next filter in the chain. /// Raw coder validates and converts an array of lzma_filter structures to
struct lzma_next_coder_s { /// an array of lzma_filter_info structures. This array is used with
/// Pointer to coder-specific data /// lzma_next_filter_init to initialize the filter chain.
lzma_coder *coder;
/// "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.
uintptr_t init;
/// Pointer to function to do the actual coding
lzma_code_function code;
/// Pointer to function to free lzma_next_coder.coder
lzma_end_function end;
};
#define LZMA_NEXT_CODER_INIT \
(lzma_next_coder){ \
.coder = NULL, \
.init = 0, \
.code = NULL, \
.end = NULL, \
}
struct lzma_internal_s {
lzma_next_coder next;
enum {
ISEQ_RUN,
ISEQ_SYNC_FLUSH,
ISEQ_FULL_FLUSH,
ISEQ_FINISH,
ISEQ_END,
ISEQ_ERROR,
} sequence;
bool supported_actions[4];
bool allow_buf_error;
size_t avail_in;
};
struct lzma_filter_info_s { struct lzma_filter_info_s {
/// Pointer to function used to initialize the filter. /// Pointer to function used to initialize the filter.
/// This is NULL to indicate end of array. /// This is NULL to indicate end of array.
@ -132,15 +113,76 @@ struct lzma_filter_info_s {
}; };
/* /// Hold data and function pointers of the next filter in the chain.
typedef struct { struct lzma_next_coder_s {
lzma_init_function init; /// Pointer to coder-specific data
uint32_t (*input_alignment)(lzma_vli id, const void *options); lzma_coder *coder;
uint32_t (*output_alignment)(lzma_vli id, const void *options);
bool changes_uncompressed_size; /// "Pointer" to init function. This is never called here.
bool supports_eopm; /// We need only to detect if we are initializing a coder
} lzma_filter_hook; /// 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. 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 (*see_check)(const lzma_coder *coder);
// uint64_t (*memconfig)(
// lzma_coder *coder, uint64_t memlimit, bool change);
};
/// Macro to initialize lzma_next_coder structure
#define LZMA_NEXT_CODER_INIT \
(lzma_next_coder){ \
.coder = NULL, \
.init = (uintptr_t)(NULL), \
.code = NULL, \
.end = NULL, \
.see_check = 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,
ISEQ_FULL_FLUSH,
ISEQ_FINISH,
ISEQ_END,
ISEQ_ERROR,
} sequence;
/// 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;
};
/////////////// ///////////////
@ -154,126 +196,69 @@ extern void *lzma_alloc(size_t size, lzma_allocator *allocator)
/// Frees memory /// Frees memory
extern void lzma_free(void *ptr, lzma_allocator *allocator); 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); 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, extern lzma_ret lzma_next_filter_init(lzma_next_coder *next,
lzma_allocator *allocator, const lzma_filter_info *filters); lzma_allocator *allocator, const lzma_filter_info *filters);
/// /// Frees the memory allocated for next->coder either using next->end or,
extern void lzma_next_coder_end(lzma_next_coder *next, /// if next->end is NULL, using lzma_free.
lzma_allocator *allocator); extern void lzma_next_end(lzma_next_coder *next, lzma_allocator *allocator);
/// \brief Wrapper for memcpy() /// Copy as much data as possible from in[] to out[] and update *in_pos
/// /// and *out_pos accordingly. Returns the number of bytes copied.
/// This function copies as much data as possible from in[] to out[] and extern size_t lzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos,
/// updates *in_pos and *out_pos accordingly. size_t in_size, uint8_t *restrict out,
/// size_t *restrict out_pos, size_t out_size);
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_next_coder
///
/// Call the initialization function, which takes no other arguments than
/// lzma_next_coder and lzma_allocator.
#define lzma_next_coder_init0(func, next, allocator) \
lzma_next_coder_init2(next, allocator, func, func, allocator)
/// \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__)
/// \brief Initializing lzma_stream
///
/// Call the initialization function, which takes no other arguments than
/// lzma_next_coder and lzma_allocator.
#define lzma_next_strm_init0(strm, func) \
lzma_next_strm_init2(strm, func, func, (strm)->allocator)
/// \brief Return if expression doesn't evaluate to LZMA_OK /// \brief Return if expression doesn't evaluate to LZMA_OK
/// ///
/// There are several situations where we want to return immediatelly /// There are several situations where we want to return immediatelly
/// with the value of expr if it isn't LZMA_OK. This macro shortens /// 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) \ #define return_if_error(expr) \
do { \ do { \
const lzma_ret ret_ = expr; \ const lzma_ret ret_ = (expr); \
if (ret_ != LZMA_OK) \ if (ret_ != LZMA_OK) \
return ret_; \ return ret_; \
} while (0) } 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 #endif

View File

@ -25,12 +25,12 @@ struct lzma_coder_s {
/// We need to keep the filters array available in case /// We need to keep the filters array available in case
/// LZMA_FULL_FLUSH is used. /// LZMA_FULL_FLUSH is used.
lzma_options_filter filters[5]; lzma_filter filters[5];
}; };
static bool static bool
easy_set_filters(lzma_options_filter *filters, uint32_t level) easy_set_filters(lzma_filter *filters, uint32_t level)
{ {
bool error = false; bool error = false;
@ -38,9 +38,9 @@ easy_set_filters(lzma_options_filter *filters, uint32_t level)
// TODO FIXME Use Subblock or LZMA2 with no compression. // TODO FIXME Use Subblock or LZMA2 with no compression.
error = true; error = true;
#ifdef HAVE_FILTER_LZMA #ifdef HAVE_ENCODER_LZMA2
} else if (level <= 9) { } else if (level <= 9) {
filters[0].id = LZMA_FILTER_LZMA; filters[0].id = LZMA_FILTER_LZMA2;
filters[0].options = (void *)(&lzma_preset_lzma[level - 1]); filters[0].options = (void *)(&lzma_preset_lzma[level - 1]);
filters[1].id = LZMA_VLI_VALUE_UNKNOWN; filters[1].id = LZMA_VLI_VALUE_UNKNOWN;
#endif #endif
@ -68,7 +68,7 @@ easy_encode(lzma_coder *coder, lzma_allocator *allocator,
static void static void
easy_encoder_end(lzma_coder *coder, lzma_allocator *allocator) easy_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
{ {
lzma_next_coder_end(&coder->stream_encoder, allocator); lzma_next_end(&coder->stream_encoder, allocator);
lzma_free(coder, allocator); lzma_free(coder, allocator);
return; return;
} }
@ -78,6 +78,8 @@ static lzma_ret
easy_encoder_init(lzma_next_coder *next, lzma_allocator *allocator, easy_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
lzma_easy_level level) lzma_easy_level level)
{ {
lzma_next_coder_init(easy_encoder_init, next, allocator);
if (next->coder == NULL) { if (next->coder == NULL) {
next->coder = lzma_alloc(sizeof(lzma_coder), allocator); next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
if (next->coder == NULL) if (next->coder == NULL)
@ -100,7 +102,7 @@ easy_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
extern LZMA_API lzma_ret extern LZMA_API lzma_ret
lzma_easy_encoder(lzma_stream *strm, lzma_easy_level level) lzma_easy_encoder(lzma_stream *strm, lzma_easy_level level)
{ {
lzma_next_strm_init(strm, easy_encoder_init, level); lzma_next_strm_init(easy_encoder_init, strm, level);
strm->internal->supported_actions[LZMA_RUN] = true; strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true; strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
@ -114,9 +116,9 @@ lzma_easy_encoder(lzma_stream *strm, lzma_easy_level level)
extern LZMA_API uint32_t extern LZMA_API uint32_t
lzma_easy_memory_usage(lzma_easy_level level) lzma_easy_memory_usage(lzma_easy_level level)
{ {
lzma_options_filter filters[5]; lzma_filter filters[5];
if (easy_set_filters(filters, level)) if (easy_set_filters(filters, level))
return UINT32_MAX; return UINT32_MAX;
return lzma_memory_usage(filters, true); return lzma_memusage_encoder(filters);
} }

View File

@ -1,66 +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_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;

View 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);
}

View File

@ -0,0 +1,52 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \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 {
/// 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

View File

@ -0,0 +1,236 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \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 {
/// 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_vli ids[] = {
#ifdef HAVE_DECODER_LZMA
LZMA_FILTER_LZMA,
#endif
#ifdef HAVE_DECODER_LZMA2
LZMA_FILTER_LZMA2,
#endif
#ifdef HAVE_DECODER_SUBBLOCK
LZMA_FILTER_SUBBLOCK,
LZMA_FILTER_SUBBLOCK_HELPER,
#endif
#ifdef HAVE_DECODER_X86
LZMA_FILTER_X86,
#endif
#ifdef HAVE_DECODER_POWERPC
LZMA_FILTER_POWERPC,
#endif
#ifdef HAVE_DECODER_IA64
LZMA_FILTER_IA64,
#endif
#ifdef HAVE_DECODER_ARM
LZMA_FILTER_ARM,
#endif
#ifdef HAVE_DECODER_ARMTHUMB
LZMA_FILTER_ARMTHUMB,
#endif
#ifdef HAVE_DECODER_SPARC
LZMA_FILTER_SPARC,
#endif
#ifdef HAVE_DECODER_DELTA
LZMA_FILTER_DELTA,
#endif
LZMA_VLI_VALUE_UNKNOWN
};
// Using a pointer to avoid putting the size of the array to API/ABI.
LZMA_API const lzma_vli *const lzma_filter_decoders = ids;
// These must be in the same order as ids[].
static const lzma_filter_decoder funcs[] = {
#ifdef HAVE_DECODER_LZMA
{
.init = &lzma_lzma_decoder_init,
.memusage = &lzma_lzma_decoder_memusage,
.props_decode = &lzma_lzma_props_decode,
},
#endif
#ifdef HAVE_DECODER_LZMA2
{
.init = &lzma_lzma2_decoder_init,
.memusage = &lzma_lzma2_decoder_memusage,
.props_decode = &lzma_lzma2_props_decode,
},
#endif
#ifdef HAVE_DECODER_SUBBLOCK
{
.init = &lzma_subblock_decoder_init,
// .memusage = &lzma_subblock_decoder_memusage,
.props_decode = NULL,
},
{
.init = &lzma_subblock_decoder_helper_init,
.memusage = NULL,
.props_decode = NULL,
},
#endif
#ifdef HAVE_DECODER_X86
{
.init = &lzma_simple_x86_decoder_init,
.memusage = NULL,
.props_decode = &lzma_simple_props_decode,
},
#endif
#ifdef HAVE_DECODER_POWERPC
{
.init = &lzma_simple_powerpc_decoder_init,
.memusage = NULL,
.props_decode = &lzma_simple_props_decode,
},
#endif
#ifdef HAVE_DECODER_IA64
{
.init = &lzma_simple_ia64_decoder_init,
.memusage = NULL,
.props_decode = &lzma_simple_props_decode,
},
#endif
#ifdef HAVE_DECODER_ARM
{
.init = &lzma_simple_arm_decoder_init,
.memusage = NULL,
.props_decode = &lzma_simple_props_decode,
},
#endif
#ifdef HAVE_DECODER_ARMTHUMB
{
.init = &lzma_simple_armthumb_decoder_init,
.memusage = NULL,
.props_decode = &lzma_simple_props_decode,
},
#endif
#ifdef HAVE_DECODER_SPARC
{
.init = &lzma_simple_sparc_decoder_init,
.memusage = NULL,
.props_decode = &lzma_simple_props_decode,
},
#endif
#ifdef HAVE_DECODER_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; ids[i] != LZMA_VLI_VALUE_UNKNOWN; ++i)
if (ids[i] == id)
return funcs + i;
return 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_SYNC_FLUSH] = 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);
}

View File

@ -0,0 +1,35 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \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.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef LZMA_FILTER_DECODER_H
#define LZMA_FILTER_DECODER_H
#include "common.h"
// FIXME !!! Public API
extern lzma_ret lzma_properties_decode(
lzma_filter *filter, lzma_allocator *allocator,
const uint8_t *props, size_t props_size);
extern lzma_ret lzma_raw_decoder_init(
lzma_next_coder *next, lzma_allocator *allocator,
const lzma_filter *options);
#endif

View File

@ -0,0 +1,308 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \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 {
/// 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_vli ids[] = {
#ifdef HAVE_ENCODER_LZMA
LZMA_FILTER_LZMA,
#endif
#ifdef HAVE_ENCODER_LZMA2
LZMA_FILTER_LZMA2,
#endif
#ifdef HAVE_ENCODER_SUBBLOCK
LZMA_FILTER_SUBBLOCK,
#endif
#ifdef HAVE_ENCODER_X86
LZMA_FILTER_X86,
#endif
#ifdef HAVE_ENCODER_POWERPC
LZMA_FILTER_POWERPC,
#endif
#ifdef HAVE_ENCODER_IA64
LZMA_FILTER_IA64,
#endif
#ifdef HAVE_ENCODER_ARM
LZMA_FILTER_ARM,
#endif
#ifdef HAVE_ENCODER_ARMTHUMB
LZMA_FILTER_ARMTHUMB,
#endif
#ifdef HAVE_ENCODER_SPARC
LZMA_FILTER_SPARC,
#endif
#ifdef HAVE_ENCODER_DELTA
LZMA_FILTER_DELTA,
#endif
LZMA_VLI_VALUE_UNKNOWN
};
// Using a pointer to avoid putting the size of the array to API/ABI.
LZMA_API const lzma_vli *const lzma_filter_encoders = ids;
// These must be in the same order as ids[].
static const lzma_filter_encoder funcs[] = {
#ifdef HAVE_ENCODER_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
{
.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
{
.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
{
.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
{
.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
{
.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
{
.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
{
.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
{
.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
{
.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; ids[i] != LZMA_VLI_VALUE_UNKNOWN; ++i)
if (ids[i] == id)
return funcs + i;
return 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)
{
uint64_t 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() 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);
}

View File

@ -0,0 +1,38 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \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_properties_size(
uint32_t *size, const lzma_filter *filter);
extern lzma_ret lzma_properties_encode(
const lzma_filter *filter, uint8_t *props);
extern lzma_ret lzma_raw_encoder_init(
lzma_next_coder *next, lzma_allocator *allocator,
const lzma_filter *options);
#endif

View File

@ -17,192 +17,37 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include "common.h" #include "filter_decoder.h"
#include "lzma_decoder.h"
#ifdef HAVE_FILTER_SUBBLOCK
static lzma_ret
properties_subblock(lzma_options_filter *options, lzma_allocator *allocator,
const uint8_t *props lzma_attribute((unused)),
size_t prop_size lzma_attribute((unused)))
{
if (prop_size != 0)
return LZMA_HEADER_ERROR;
options->options = lzma_alloc(
sizeof(lzma_options_subblock), allocator);
if (options->options == NULL)
return LZMA_MEM_ERROR;
((lzma_options_subblock *)(options->options))->allow_subfilters = true;
return LZMA_OK;
}
#endif
#ifdef HAVE_FILTER_SIMPLE
static lzma_ret
properties_simple(lzma_options_filter *options, lzma_allocator *allocator,
const uint8_t *props, size_t prop_size)
{
if (prop_size == 0)
return LZMA_OK;
if (prop_size != 4)
return LZMA_HEADER_ERROR;
lzma_options_simple *simple = lzma_alloc(
sizeof(lzma_options_simple), allocator);
if (simple == NULL)
return LZMA_MEM_ERROR;
simple->start_offset = integer_read_32(props);
// Don't leave an options structure allocated if start_offset is zero.
if (simple->start_offset == 0)
lzma_free(simple, allocator);
else
options->options = simple;
return LZMA_OK;
}
#endif
#ifdef HAVE_FILTER_DELTA
static lzma_ret
properties_delta(lzma_options_filter *options, lzma_allocator *allocator,
const uint8_t *props, size_t prop_size)
{
if (prop_size != 1)
return LZMA_HEADER_ERROR;
options->options = lzma_alloc(sizeof(lzma_options_delta), allocator);
if (options->options == NULL)
return LZMA_MEM_ERROR;
((lzma_options_delta *)(options->options))->distance
= (uint32_t)(props[0]) + 1;
return LZMA_OK;
}
#endif
#ifdef HAVE_FILTER_LZMA
static lzma_ret
properties_lzma(lzma_options_filter *options, lzma_allocator *allocator,
const uint8_t *props, size_t prop_size)
{
// LZMA properties are always two bytes (at least for now).
if (prop_size != 2)
return LZMA_HEADER_ERROR;
lzma_options_lzma *lzma = lzma_alloc(
sizeof(lzma_options_lzma), allocator);
if (lzma == NULL)
return LZMA_MEM_ERROR;
// Decode lc, lp, and pb.
if (lzma_lzma_decode_properties(lzma, props[0]))
goto error;
// Check that reserved bits are unset.
if (props[1] & 0xC0)
goto error;
// Decode the dictionary size.
// FIXME The specification says that maximum is 4 GiB.
if (props[1] > 36)
goto 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
lzma->dictionary_size = 2 | (props[1] & 1);
lzma->dictionary_size <<= props[1] / 2 + 11;
options->options = lzma;
return LZMA_OK;
error:
lzma_free(lzma, allocator);
return LZMA_HEADER_ERROR;
}
#endif
extern LZMA_API lzma_ret extern LZMA_API lzma_ret
lzma_filter_flags_decode( lzma_filter_flags_decode(
lzma_options_filter *options, lzma_allocator *allocator, lzma_filter *filter, lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size) const uint8_t *in, size_t *in_pos, size_t in_size)
{ {
// Set the pointer to NULL so the caller can always safely free it. // Set the pointer to NULL so the caller can always safely free it.
options->options = NULL; filter->options = NULL;
// Filter ID // Filter ID
return_if_error(lzma_vli_decode(&options->id, NULL, return_if_error(lzma_vli_decode(&filter->id, NULL,
in, in_pos, in_size)); in, in_pos, in_size));
// Size of Properties if (filter->id >= LZMA_FILTER_RESERVED_START)
lzma_vli prop_size;
return_if_error(lzma_vli_decode(&prop_size, NULL,
in, in_pos, in_size));
// Check that we have enough input.
if (prop_size > in_size - *in_pos)
return LZMA_DATA_ERROR; return LZMA_DATA_ERROR;
// Determine the function to decode the properties. // Size of Properties
lzma_ret (*get_properties)(lzma_options_filter *options, lzma_vli props_size;
lzma_allocator *allocator, const uint8_t *props, return_if_error(lzma_vli_decode(&props_size, NULL,
size_t prop_size); in, in_pos, in_size));
switch (options->id) { // Filter Properties
#ifdef HAVE_FILTER_SUBBLOCK if (in_size - *in_pos < props_size)
case LZMA_FILTER_SUBBLOCK: return LZMA_DATA_ERROR;
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;
}
const uint8_t *props = in + *in_pos; const lzma_ret ret = lzma_properties_decode(
*in_pos += prop_size; filter, allocator, in + *in_pos, props_size);
return get_properties(options, allocator, props, prop_size);
*in_pos += props_size;
return ret;
} }

View File

@ -17,267 +17,46 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include "common.h" #include "filter_encoder.h"
#include "lzma_encoder.h"
#include "fastpos.h"
/// Calculate the size of the Filter Properties field extern LZMA_API lzma_ret
static lzma_ret lzma_filter_flags_size(uint32_t *size, const lzma_filter *filter)
get_properties_size(uint32_t *size, const lzma_options_filter *options)
{ {
lzma_ret ret = LZMA_OK; return_if_error(lzma_properties_size(size, filter));
switch (options->id) { // lzma_properties_size() validates the Filter ID as a side-effect,
#ifdef HAVE_FILTER_SUBBLOCK // so we know that it is a valid VLI.
case LZMA_FILTER_SUBBLOCK: *size += lzma_vli_size(filter->id) + lzma_vli_size(*size);
*size = 0;
break;
#endif
#ifdef HAVE_FILTER_SIMPLE return LZMA_OK;
# 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;
} }
extern LZMA_API lzma_ret 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. This also validates the Filter ID.
uint32_t prop_size;
return_if_error(get_properties_size(&prop_size, options));
// Calculate the size of the Filter ID and Size of Properties fields.
// These cannot fail since get_properties_size() already succeeded.
*size = lzma_vli_size(options->id) + lzma_vli_size(prop_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_PROG_ERROR;
integer_write_32(out + *out_pos, options->start_offset);
*out_pos += 4;
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)
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;
if (out_size - *out_pos < 1)
return LZMA_PROG_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_PROG_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 similar encoding that is used
// internally by LZMA.
//
// This won't work if dictionary size can be zero:
# if LZMA_DICTIONARY_SIZE_MIN < 1
# error LZMA_DICTIONARY_SIZE_MIN cannot be zero.
# endif
uint32_t d = options->dictionary_size;
// Validate it:
if (d < LZMA_DICTIONARY_SIZE_MIN || d > LZMA_DICTIONARY_SIZE_MAX)
return LZMA_HEADER_ERROR;
// Round up to to the next 2^n or 2^n + 2^(n - 1) depending on which
// one is the next:
--d;
d |= d >> 2;
d |= d >> 3;
d |= d >> 4;
d |= d >> 8;
d |= d >> 16;
++d;
// Get the highest two bits using the proper encoding:
out[*out_pos] = get_pos_slot(d) - 24;
++*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;
return_if_error(get_properties_size(&prop_size, options));
// Filter ID // Filter ID
return_if_error(lzma_vli_encode(options->id, NULL, if (filter->id >= LZMA_FILTER_RESERVED_START)
return LZMA_HEADER_ERROR;
return_if_error(lzma_vli_encode(filter->id, NULL,
out, out_pos, out_size)); out, out_pos, out_size));
// Size of Properties // Size of Properties
return_if_error(lzma_vli_encode(prop_size, NULL, 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)); out, out_pos, out_size));
// Filter Properties // Filter Properties
lzma_ret ret; if (out_size - *out_pos < props_size)
switch (options->id) { return LZMA_PROG_ERROR;
#ifdef HAVE_FILTER_SUBBLOCK
case LZMA_FILTER_SUBBLOCK:
assert(prop_size == 0);
ret = LZMA_OK;
break;
#endif
#ifdef HAVE_FILTER_SIMPLE return_if_error(lzma_properties_encode(filter, out + *out_pos));
# 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
#ifdef HAVE_FILTER_DELTA *out_pos += props_size;
case LZMA_FILTER_DELTA:
ret = properties_delta(out, out_pos, out_size,
options->options);
break;
#endif
#ifdef HAVE_FILTER_LZMA return LZMA_OK;
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;
} }

View File

@ -201,6 +201,8 @@ static lzma_ret
index_decoder_init(lzma_next_coder *next, lzma_allocator *allocator, index_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
lzma_index **i) lzma_index **i)
{ {
lzma_next_coder_init(index_decoder_init, next, allocator);
if (i == NULL) if (i == NULL)
return LZMA_PROG_ERROR; return LZMA_PROG_ERROR;
@ -231,20 +233,10 @@ index_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
} }
/*
extern lzma_ret
lzma_index_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
lzma_index **i)
{
lzma_next_coder_init(index_decoder_init, next, allocator, i);
}
*/
extern LZMA_API lzma_ret extern LZMA_API lzma_ret
lzma_index_decoder(lzma_stream *strm, lzma_index **i) lzma_index_decoder(lzma_stream *strm, lzma_index **i)
{ {
lzma_next_strm_init(strm, index_decoder_init, i); lzma_next_strm_init(index_decoder_init, strm, i);
strm->internal->supported_actions[LZMA_RUN] = true; strm->internal->supported_actions[LZMA_RUN] = true;

View File

@ -176,10 +176,12 @@ index_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
} }
static lzma_ret extern lzma_ret
index_encoder_init(lzma_next_coder *next, lzma_allocator *allocator, lzma_index_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
lzma_index *i) lzma_index *i)
{ {
lzma_next_coder_init(lzma_index_encoder_init, next, allocator);
if (i == NULL) if (i == NULL)
return LZMA_PROG_ERROR; return LZMA_PROG_ERROR;
@ -203,18 +205,10 @@ index_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
} }
extern lzma_ret
lzma_index_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
lzma_index *i)
{
lzma_next_coder_init(index_encoder_init, next, allocator, i);
}
extern LZMA_API lzma_ret extern LZMA_API lzma_ret
lzma_index_encoder(lzma_stream *strm, lzma_index *i) lzma_index_encoder(lzma_stream *strm, lzma_index *i)
{ {
lzma_next_strm_init(strm, index_encoder_init, i); lzma_next_strm_init(lzma_index_encoder_init, strm, i);
strm->internal->supported_actions[LZMA_RUN] = true; strm->internal->supported_actions[LZMA_RUN] = true;

View File

@ -36,7 +36,7 @@ typedef struct {
lzma_vli index_list_size; lzma_vli index_list_size;
/// Check calculated from Total Sizes and Uncompressed Sizes. /// Check calculated from Total Sizes and Uncompressed Sizes.
lzma_check check; lzma_check_state check;
} lzma_index_hash_info; } lzma_index_hash_info;
@ -300,9 +300,9 @@ lzma_index_hash_decode(lzma_index_hash *index_hash, const uint8_t *in,
// Finish the hashes and compare them. // Finish the hashes and compare them.
lzma_check_finish(&index_hash->blocks.check, LZMA_CHECK_BEST); lzma_check_finish(&index_hash->blocks.check, LZMA_CHECK_BEST);
lzma_check_finish(&index_hash->records.check, LZMA_CHECK_BEST); lzma_check_finish(&index_hash->records.check, LZMA_CHECK_BEST);
if (memcmp(index_hash->blocks.check.buffer, if (memcmp(index_hash->blocks.check.buffer.u8,
index_hash->records.check.buffer, index_hash->records.check.buffer.u8,
lzma_check_sizes[LZMA_CHECK_BEST]) != 0) lzma_check_size(LZMA_CHECK_BEST)) != 0)
return LZMA_DATA_ERROR; return LZMA_DATA_ERROR;
// Finish the CRC32 calculation. // Finish the CRC32 calculation.

View File

@ -31,7 +31,7 @@ lzma_init_encoder(void)
lzma_init_check(); lzma_init_check();
#if defined(HAVE_SMALL) && defined(HAVE_ENCODER) && defined(HAVE_FILTER_LZMA) #if defined(HAVE_SMALL) && defined(HAVE_ENCODER_LZMA)
lzma_rc_init(); lzma_rc_init();
#endif #endif

View File

@ -1,112 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file memory_usage.c
/// \brief Calculate rough amount of memory required by filters
//
// 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"
#include "lz_encoder.h"
#include "lzma_literal.h"
static uint64_t
get_usage(const lzma_options_filter *filter, bool is_encoder)
{
uint64_t ret;
switch (filter->id) {
case LZMA_FILTER_X86:
case LZMA_FILTER_POWERPC:
case LZMA_FILTER_IA64:
case LZMA_FILTER_ARM:
case LZMA_FILTER_ARMTHUMB:
case LZMA_FILTER_SPARC:
case LZMA_FILTER_DELTA:
// These don't require any significant amount of memory.
ret = 0;
break;
case LZMA_FILTER_SUBBLOCK:
if (is_encoder) {
const lzma_options_subblock *options = filter->options;
ret = options->subblock_data_size;
} else {
ret = 0;
}
break;
#ifdef HAVE_FILTER_LZMA
case LZMA_FILTER_LZMA: {
const lzma_options_lzma *options = filter->options;
// Literal coder - this can be signficant if both values are
// big, or if sizeof(probability) is big.
ret = literal_states(options->literal_context_bits,
options->literal_pos_bits) * LIT_SIZE
* sizeof(probability);
// Dictionary base size
ret += options->dictionary_size;
if (is_encoder) {
# ifdef HAVE_ENCODER
// This is rough, but should be accurate enough
// in practice.
ret += options->dictionary_size / 2;
uint32_t dummy1;
uint32_t dummy2;
uint32_t num_items;
if (lzma_lz_encoder_hash_properties(
options->match_finder,
options->dictionary_size,
&dummy1, &dummy2, &num_items))
return UINT64_MAX;
ret += (uint64_t)(num_items) * sizeof(uint32_t);
# else
return UINT64_MAX;
# endif
}
break;
}
#endif
default:
return UINT64_MAX;
}
return ret;
}
extern LZMA_API uint32_t
lzma_memory_usage(const lzma_options_filter *filters, lzma_bool is_encoder)
{
uint64_t usage = 0;
for (size_t i = 0; filters[i].id != UINT64_MAX; ++i) {
const uint64_t ret = get_usage(filters + i, is_encoder);
if (ret == UINT64_MAX)
return UINT32_MAX;
usage += ret;
}
// Convert to mebibytes with rounding.
return usage / (1024 * 1024) + (usage % (1024 * 1024) >= 512 ? 1 : 0);
}

View File

@ -1,65 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file next_coder.c
/// \brief Initializing and freeing the next coder in the chain
//
// 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"
extern lzma_ret
lzma_next_filter_init(lzma_next_coder *next, lzma_allocator *allocator,
const lzma_filter_info *filters)
{
lzma_ret ret = LZMA_OK;
// Free the existing coder if it is different than the current one.
if ((uintptr_t)(filters[0].init) != next->init)
lzma_next_coder_end(next, allocator);
if (filters[0].init != NULL) {
// Initialize the new coder.
ret = filters[0].init(next, allocator, filters);
// Set the init function pointer if initialization was
// successful. next->code and next->end are set by the
// initialization function itself.
if (ret == LZMA_OK) {
next->init = (uintptr_t)(filters[0].init);
assert(next->code != NULL);
assert(next->end != NULL);
} else {
lzma_next_coder_end(next, allocator);
}
}
return ret;
}
extern void
lzma_next_coder_end(lzma_next_coder *next, lzma_allocator *allocator)
{
if (next != NULL) {
if (next->end != NULL)
next->end(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;
}

View File

@ -1,127 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file raw_common.c
/// \brief Stuff shared between raw encoder and raw 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 "raw_common.h"
static lzma_ret
validate_options(const lzma_options_filter *options, size_t *count)
{
if (options == NULL)
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 change = 0;
// 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;
for (i = 0; options[i].id != LZMA_VLI_VALUE_UNKNOWN; ++i) {
switch (options[i].id) {
// Not #ifdeffing these for simplicity.
case LZMA_FILTER_X86:
case LZMA_FILTER_POWERPC:
case LZMA_FILTER_IA64:
case LZMA_FILTER_ARM:
case LZMA_FILTER_ARMTHUMB:
case LZMA_FILTER_SPARC:
case LZMA_FILTER_DELTA:
// These don't change the size of the data and cannot
// be used as the last filter in the chain.
last_ok = false;
break;
#ifdef HAVE_FILTER_SUBBLOCK
case LZMA_FILTER_SUBBLOCK:
last_ok = true;
++change;
break;
#endif
#ifdef HAVE_FILTER_LZMA
case LZMA_FILTER_LZMA:
last_ok = true;
break;
#endif
default:
return LZMA_HEADER_ERROR;
}
}
// There must be 1-4 filters and the last filter must be usable as
// the last filter in the chain.
if (i == 0 || i > 4 || !last_ok)
return LZMA_HEADER_ERROR;
// At maximum of two non-last filters are allowed to change the
// size of the data.
if (change > 2)
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_options_filter *options,
lzma_init_function (*get_function)(lzma_vli id),
bool is_encoder)
{
// Do some basic validation and get the number of filters.
size_t count;
return_if_error(validate_options(options, &count));
// Set the filter functions and copy the options pointer.
lzma_filter_info filters[count + 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;
filters[j].init = get_function(options[i].id);
if (filters[j].init == NULL)
return LZMA_HEADER_ERROR;
filters[j].options = options[i].options;
}
} else {
for (size_t i = 0; i < count; ++i) {
filters[i].init = get_function(options[i].id);
if (filters[i].init == NULL)
return LZMA_HEADER_ERROR;
filters[i].options = options[i].options;
}
}
// Terminate the array.
filters[count].init = NULL;
// Initialize the filters.
return lzma_next_filter_init(next, allocator, filters);
}

View File

@ -1,116 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file raw_decoder.c
/// \brief Raw decoder initialization API
//
// 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 "raw_decoder.h"
#include "simple_coder.h"
#include "subblock_decoder.h"
#include "subblock_decoder_helper.h"
#include "delta_decoder.h"
#include "lzma_decoder.h"
static lzma_init_function
get_function(lzma_vli id)
{
switch (id) {
#ifdef HAVE_FILTER_SUBBLOCK
case LZMA_FILTER_SUBBLOCK:
return &lzma_subblock_decoder_init;
#endif
#ifdef HAVE_FILTER_X86
case LZMA_FILTER_X86:
return &lzma_simple_x86_decoder_init;
#endif
#ifdef HAVE_FILTER_POWERPC
case LZMA_FILTER_POWERPC:
return &lzma_simple_powerpc_decoder_init;
#endif
#ifdef HAVE_FILTER_IA64
case LZMA_FILTER_IA64:
return &lzma_simple_ia64_decoder_init;
#endif
#ifdef HAVE_FILTER_ARM
case LZMA_FILTER_ARM:
return &lzma_simple_arm_decoder_init;
#endif
#ifdef HAVE_FILTER_ARMTHUMB
case LZMA_FILTER_ARMTHUMB:
return &lzma_simple_armthumb_decoder_init;
#endif
#ifdef HAVE_FILTER_SPARC
case LZMA_FILTER_SPARC:
return &lzma_simple_sparc_decoder_init;
#endif
#ifdef HAVE_FILTER_DELTA
case LZMA_FILTER_DELTA:
return &lzma_delta_decoder_init;
#endif
#ifdef HAVE_FILTER_LZMA
case LZMA_FILTER_LZMA:
return &lzma_lzma_decoder_init;
#endif
#ifdef HAVE_FILTER_SUBBLOCK
case LZMA_FILTER_SUBBLOCK_HELPER:
return &lzma_subblock_decoder_helper_init;
#endif
}
return NULL;
}
extern lzma_ret
lzma_raw_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
const lzma_options_filter *options)
{
const lzma_ret ret = lzma_raw_coder_init(next, allocator,
options, &get_function, false);
if (ret != LZMA_OK)
lzma_next_coder_end(next, allocator);
return ret;
}
extern LZMA_API lzma_ret
lzma_raw_decoder(lzma_stream *strm, const lzma_options_filter *options)
{
return_if_error(lzma_strm_init(strm));
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
const lzma_ret ret = lzma_raw_coder_init(&strm->internal->next,
strm->allocator, options, &get_function, false);
if (ret != LZMA_OK)
lzma_end(strm);
return ret;
}

View File

@ -1,111 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file raw_encoder.c
/// \brief Raw encoder initialization API
//
// 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 "raw_encoder.h"
#include "simple_coder.h"
#include "subblock_encoder.h"
#include "delta_encoder.h"
#include "lzma_encoder.h"
static lzma_init_function
get_function(lzma_vli id)
{
switch (id) {
#ifdef HAVE_FILTER_SUBBLOCK
case LZMA_FILTER_SUBBLOCK:
return &lzma_subblock_encoder_init;
#endif
#ifdef HAVE_FILTER_X86
case LZMA_FILTER_X86:
return &lzma_simple_x86_encoder_init;
#endif
#ifdef HAVE_FILTER_POWERPC
case LZMA_FILTER_POWERPC:
return &lzma_simple_powerpc_encoder_init;
#endif
#ifdef HAVE_FILTER_IA64
case LZMA_FILTER_IA64:
return &lzma_simple_ia64_encoder_init;
#endif
#ifdef HAVE_FILTER_ARM
case LZMA_FILTER_ARM:
return &lzma_simple_arm_encoder_init;
#endif
#ifdef HAVE_FILTER_ARMTHUMB
case LZMA_FILTER_ARMTHUMB:
return &lzma_simple_armthumb_encoder_init;
#endif
#ifdef HAVE_FILTER_SPARC
case LZMA_FILTER_SPARC:
return &lzma_simple_sparc_encoder_init;
#endif
#ifdef HAVE_FILTER_DELTA
case LZMA_FILTER_DELTA:
return &lzma_delta_encoder_init;
#endif
#ifdef HAVE_FILTER_LZMA
case LZMA_FILTER_LZMA:
return &lzma_lzma_encoder_init;
#endif
}
return NULL;
}
extern lzma_ret
lzma_raw_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
const lzma_options_filter *options)
{
const lzma_ret ret = lzma_raw_coder_init(next, allocator,
options, &get_function, true);
if (ret != LZMA_OK)
lzma_next_coder_end(next, allocator);
return ret;
}
extern LZMA_API lzma_ret
lzma_raw_encoder(lzma_stream *strm, const lzma_options_filter *options)
{
return_if_error(lzma_strm_init(strm));
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
const lzma_ret ret = lzma_raw_coder_init(&strm->internal->next,
strm->allocator, options, &get_function, true);
if (ret != LZMA_OK)
lzma_end(strm);
return ret;
}

View File

@ -1,23 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file stream_common.c
/// \brief Common stuff for Stream coders
//
// 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 "stream_common.h"
const uint8_t lzma_header_magic[6] = { 0xFF, 0x4C, 0x5A, 0x4D, 0x41, 0x00 };
const uint8_t lzma_footer_magic[2] = { 0x59, 0x5A };

View File

@ -17,8 +17,8 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include "stream_common.h"
#include "stream_decoder.h" #include "stream_decoder.h"
#include "stream_flags_common.h"
#include "check.h" #include "check.h"
#include "stream_flags_decoder.h" #include "stream_flags_decoder.h"
#include "block_decoder.h" #include "block_decoder.h"
@ -31,6 +31,7 @@ struct lzma_coder_s {
SEQ_BLOCK, SEQ_BLOCK,
SEQ_INDEX, SEQ_INDEX,
SEQ_STREAM_FOOTER, SEQ_STREAM_FOOTER,
SEQ_STREAM_PADDING,
} sequence; } sequence;
/// Block or Metadata decoder. This takes little memory and the same /// Block or Metadata decoder. This takes little memory and the same
@ -40,7 +41,7 @@ struct lzma_coder_s {
/// Block options decoded by the Block Header decoder and used by /// Block options decoded by the Block Header decoder and used by
/// the Block decoder. /// the Block decoder.
lzma_options_block block_options; lzma_block block_options;
/// Stream Flags from Stream Header /// Stream Flags from Stream Header
lzma_stream_flags stream_flags; lzma_stream_flags stream_flags;
@ -49,8 +50,35 @@ struct lzma_coder_s {
/// with O(1) memory usage. /// with O(1) memory usage.
lzma_index_hash *index_hash; lzma_index_hash *index_hash;
/// Write position in buffer[] /// Memory usage limit
size_t buffer_pos; uint64_t memlimit;
/// If true, LZMA_NO_CHECK is returned if the Stream has
/// no integrity check.
bool warn_no_check;
/// If true, LZMA_UNSUPPORTED_CHECK is returned if the Stream has
/// an integrity check that isn't supported by this liblzma build.
bool warn_unsupported_check;
/// If true, LZMA_SEE_CHECK is returned after decoding Stream Header.
bool tell_check;
/// If true, we will decode concatenated Streams that possibly have
/// Stream Padding between or after them. LZMA_STREAM_END is returned
/// once the application isn't giving us any new input and we aren't
/// in the middle of a Stream and possible Stream Padding is a
/// multiple of four bytes. FIXME
bool concatenated;
/// When decoding concatenated Streams, this is true as long as we
/// are decoding the first Stream. This is needed to avoid misleading
/// LZMA_FORMAT_ERROR in case the later Streams don't have valid magic
/// bytes.
bool first_stream;
/// Write position in buffer[] and position in Stream Padding
size_t pos;
/// Buffer to hold Stream Header, Block Header, and Stream Footer. /// Buffer to hold Stream Header, Block Header, and Stream Footer.
/// Block Header has biggest maximum size. /// Block Header has biggest maximum size.
@ -58,6 +86,23 @@ struct lzma_coder_s {
}; };
static lzma_ret
stream_decoder_reset(lzma_coder *coder, lzma_allocator *allocator)
{
// Initialize the Index hash used to verify the Index.
coder->index_hash = lzma_index_hash_init(coder->index_hash, allocator);
if (coder->index_hash == NULL)
return LZMA_MEM_ERROR;
// Reset the rest of the variables.
coder->sequence = SEQ_STREAM_HEADER;
coder->block_options.filters = NULL;
coder->pos = 0;
return LZMA_OK;
}
static lzma_ret static lzma_ret
stream_decode(lzma_coder *coder, lzma_allocator *allocator, stream_decode(lzma_coder *coder, lzma_allocator *allocator,
const uint8_t *restrict in, size_t *restrict in_pos, const uint8_t *restrict in, size_t *restrict in_pos,
@ -66,43 +111,56 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
{ {
// When decoding the actual Block, it may be able to produce more // When decoding the actual Block, it may be able to produce more
// output even if we don't give it any new input. // output even if we don't give it any new input.
while (*out_pos < out_size && (*in_pos < in_size while (true)
|| coder->sequence == SEQ_BLOCK))
switch (coder->sequence) { switch (coder->sequence) {
case SEQ_STREAM_HEADER: { case SEQ_STREAM_HEADER: {
// Copy the Stream Header to the internal buffer. // Copy the Stream Header to the internal buffer.
bufcpy(in, in_pos, in_size, coder->buffer, &coder->buffer_pos, lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
LZMA_STREAM_HEADER_SIZE); LZMA_STREAM_HEADER_SIZE);
// Return if we didn't get the whole Stream Header yet. // Return if we didn't get the whole Stream Header yet.
if (coder->buffer_pos < LZMA_STREAM_HEADER_SIZE) if (coder->pos < LZMA_STREAM_HEADER_SIZE)
return LZMA_OK; return LZMA_OK;
coder->buffer_pos = 0; coder->pos = 0;
// Decode the Stream Header. // Decode the Stream Header.
return_if_error(lzma_stream_header_decode( const lzma_ret ret = lzma_stream_header_decode(
&coder->stream_flags, coder->buffer)); &coder->stream_flags, coder->buffer);
if (ret != LZMA_OK)
return ret == LZMA_FORMAT_ERROR && !coder->first_stream
? LZMA_DATA_ERROR : ret;
// Copy the type of the Check so that Block Header and Block // Copy the type of the Check so that Block Header and Block
// decoders see it. // decoders see it.
coder->block_options.check = coder->stream_flags.check; coder->block_options.check = coder->stream_flags.check;
// Even if we return LZMA_UNSUPPORTED_CHECK below, we want // Even if we return LZMA_*_CHECK below, we want
// to continue from Block Header decoding. // to continue from Block Header decoding.
coder->sequence = SEQ_BLOCK_HEADER; coder->sequence = SEQ_BLOCK_HEADER;
// Detect if the Check type is supported and give appropriate // Detect if there's no integrity check or if it is
// warning if it isn't. We don't warn every time a new Block // unsupported if those were requested by the application.
// is started. if (coder->warn_no_check && coder->stream_flags.check
if (!lzma_available_checks[coder->block_options.check]) == LZMA_CHECK_NONE)
return LZMA_NO_CHECK;
if (coder->warn_unsupported_check
&& !lzma_check_is_supported(
coder->stream_flags.check))
return LZMA_UNSUPPORTED_CHECK; return LZMA_UNSUPPORTED_CHECK;
if (coder->tell_check)
return LZMA_SEE_CHECK;
break; break;
} }
case SEQ_BLOCK_HEADER: { case SEQ_BLOCK_HEADER: {
if (coder->buffer_pos == 0) { if (*in_pos >= in_size)
return LZMA_OK;
if (coder->pos == 0) {
// Detect if it's Index. // Detect if it's Index.
if (in[*in_pos] == 0x00) { if (in[*in_pos] == 0x00) {
coder->sequence = SEQ_INDEX; coder->sequence = SEQ_INDEX;
@ -118,29 +176,41 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
} }
// Copy the Block Header to the internal buffer. // Copy the Block Header to the internal buffer.
bufcpy(in, in_pos, in_size, coder->buffer, &coder->buffer_pos, lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
coder->block_options.header_size); coder->block_options.header_size);
// Return if we didn't get the whole Block Header yet. // Return if we didn't get the whole Block Header yet.
if (coder->buffer_pos < coder->block_options.header_size) if (coder->pos < coder->block_options.header_size)
return LZMA_OK; return LZMA_OK;
coder->buffer_pos = 0; coder->pos = 0;
// Set up a buffer to hold the filter chain. Block Header // Set up a buffer to hold the filter chain. Block Header
// decoder will initialize all members of this array so // decoder will initialize all members of this array so
// we don't need to do it here. // we don't need to do it here.
lzma_options_filter filters[LZMA_BLOCK_FILTERS_MAX + 1]; lzma_filter filters[LZMA_BLOCK_FILTERS_MAX + 1];
coder->block_options.filters = filters; coder->block_options.filters = filters;
// Decode the Block Header. // Decode the Block Header.
return_if_error(lzma_block_header_decode(&coder->block_options, return_if_error(lzma_block_header_decode(&coder->block_options,
allocator, coder->buffer)); allocator, coder->buffer));
// Initialize the Block decoder. // Check the memory usage limit.
const lzma_ret ret = lzma_block_decoder_init( const uint64_t memusage = lzma_memusage_decoder(filters);
&coder->block_decoder, lzma_ret ret;
allocator, &coder->block_options);
if (memusage == UINT64_MAX) {
// One or more unknown Filter IDs.
ret = LZMA_HEADER_ERROR;
} else if (memusage > coder->memlimit) {
// The chain would need too much memory.
ret = LZMA_MEMLIMIT_ERROR;
} else {
// Memory usage is OK. Initialize the Block decoder.
ret = lzma_block_decoder_init(
&coder->block_decoder,
allocator, &coder->block_options);
}
// Free the allocated filter options since they are needed // Free the allocated filter options since they are needed
// only to initialize the Block decoder. // only to initialize the Block decoder.
@ -149,10 +219,9 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
coder->block_options.filters = NULL; coder->block_options.filters = NULL;
// Check if Block enocoder initialization succeeded. Don't // Check if memory usage calculation and Block enocoder
// warn about unsupported check anymore since we did it // initialization succeeded.
// earlier if it was needed. if (ret != LZMA_OK)
if (ret != LZMA_OK && ret != LZMA_UNSUPPORTED_CHECK)
return ret; return ret;
coder->sequence = SEQ_BLOCK; coder->sequence = SEQ_BLOCK;
@ -160,7 +229,7 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
} }
case SEQ_BLOCK: { case SEQ_BLOCK: {
lzma_ret ret = coder->block_decoder.code( const lzma_ret ret = coder->block_decoder.code(
coder->block_decoder.coder, allocator, coder->block_decoder.coder, allocator,
in, in_pos, in_size, out, out_pos, out_size, in, in_pos, in_size, out, out_pos, out_size,
action); action);
@ -180,6 +249,12 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
} }
case SEQ_INDEX: { case SEQ_INDEX: {
// If we don't have any input, don't call
// lzma_index_hash_decode() since it would return
// LZMA_BUF_ERROR, which we must not do here.
if (*in_pos >= in_size)
return LZMA_OK;
// Decode the Index and compare it to the hash calculated // Decode the Index and compare it to the hash calculated
// from the sizes of the Blocks (if any). // from the sizes of the Blocks (if any).
const lzma_ret ret = lzma_index_hash_decode(coder->index_hash, const lzma_ret ret = lzma_index_hash_decode(coder->index_hash,
@ -193,14 +268,17 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
case SEQ_STREAM_FOOTER: case SEQ_STREAM_FOOTER:
// Copy the Stream Footer to the internal buffer. // Copy the Stream Footer to the internal buffer.
bufcpy(in, in_pos, in_size, coder->buffer, &coder->buffer_pos, lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
LZMA_STREAM_HEADER_SIZE); LZMA_STREAM_HEADER_SIZE);
// Return if we didn't get the whole Stream Footer yet. // Return if we didn't get the whole Stream Footer yet.
if (coder->buffer_pos < LZMA_STREAM_HEADER_SIZE) if (coder->pos < LZMA_STREAM_HEADER_SIZE)
return LZMA_OK; return LZMA_OK;
coder->pos = 0;
// Decode the Stream Footer. // Decode the Stream Footer.
// FIXME LZMA_FORMAT_ERROR doesn't make sense here.
lzma_stream_flags footer_flags; lzma_stream_flags footer_flags;
return_if_error(lzma_stream_footer_decode( return_if_error(lzma_stream_footer_decode(
&footer_flags, coder->buffer)); &footer_flags, coder->buffer));
@ -217,7 +295,48 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
&footer_flags)) &footer_flags))
return LZMA_DATA_ERROR; return LZMA_DATA_ERROR;
return LZMA_STREAM_END; if (!coder->concatenated)
return LZMA_STREAM_END;
coder->sequence = SEQ_STREAM_PADDING;
break;
case SEQ_STREAM_PADDING:
assert(coder->concatenated);
while (true) {
if (*in_pos >= in_size) {
// Unless LZMA_FINISH was used, we cannot
// know if there's more input coming later.
if (action != LZMA_FINISH)
return LZMA_OK;
// Stream Padding must be a multiple of
// four bytes.
return coder->pos == 0
? LZMA_STREAM_END
: LZMA_DATA_ERROR;
}
if (in[*in_pos] != 0x00) {
if (coder->pos != 0) {
// Stream Padding is not a multiple of
// four bytes.
++*in_pos;
return LZMA_DATA_ERROR;
}
// Prepare to decode the next Stream.
return_if_error(stream_decoder_reset(
coder, allocator));
break;
}
++*in_pos;
coder->pos = (coder->pos + 1) & 3;
}
break;
default: default:
assert(0); assert(0);
@ -231,16 +350,29 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
static void static void
stream_decoder_end(lzma_coder *coder, lzma_allocator *allocator) stream_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
{ {
lzma_next_coder_end(&coder->block_decoder, allocator); lzma_next_end(&coder->block_decoder, allocator);
lzma_index_hash_end(coder->index_hash, allocator); lzma_index_hash_end(coder->index_hash, allocator);
lzma_free(coder, allocator); lzma_free(coder, allocator);
return; return;
} }
static lzma_ret static lzma_check
stream_decoder_init(lzma_next_coder *next, lzma_allocator *allocator) stream_decoder_see_check(const lzma_coder *coder)
{ {
return coder->stream_flags.check;
}
extern lzma_ret
lzma_stream_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
uint64_t memlimit, uint32_t flags)
{
lzma_next_coder_init(lzma_stream_decoder_init, next, allocator);
if (flags & ~LZMA_SUPPORTED_FLAGS)
return LZMA_HEADER_ERROR;
if (next->coder == NULL) { if (next->coder == NULL) {
next->coder = lzma_alloc(sizeof(lzma_coder), allocator); next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
if (next->coder == NULL) if (next->coder == NULL)
@ -248,40 +380,32 @@ stream_decoder_init(lzma_next_coder *next, lzma_allocator *allocator)
next->code = &stream_decode; next->code = &stream_decode;
next->end = &stream_decoder_end; next->end = &stream_decoder_end;
next->see_check = &stream_decoder_see_check;
next->coder->block_decoder = LZMA_NEXT_CODER_INIT; next->coder->block_decoder = LZMA_NEXT_CODER_INIT;
next->coder->index_hash = NULL; next->coder->index_hash = NULL;
} }
// Initialize the Index hash used to verify the Index. next->coder->memlimit = memlimit;
next->coder->index_hash = lzma_index_hash_init( next->coder->warn_no_check = (flags & LZMA_WARN_NO_CHECK) != 0;
next->coder->index_hash, allocator); next->coder->warn_unsupported_check
if (next->coder->index_hash == NULL) = (flags & LZMA_WARN_UNSUPPORTED_CHECK) != 0;
return LZMA_MEM_ERROR; next->coder->tell_check = (flags & LZMA_TELL_CHECK) != 0;
next->coder->concatenated
= (flags & LZMA_CONCATENATED) != 0;
// Reset the rest of the variables. return stream_decoder_reset(next->coder, allocator);
next->coder->sequence = SEQ_STREAM_HEADER;
next->coder->block_options.filters = NULL;
next->coder->buffer_pos = 0;
return LZMA_OK;
}
extern lzma_ret
lzma_stream_decoder_init(lzma_next_coder *next, lzma_allocator *allocator)
{
lzma_next_coder_init0(stream_decoder_init, next, allocator);
} }
extern LZMA_API lzma_ret extern LZMA_API lzma_ret
lzma_stream_decoder(lzma_stream *strm) lzma_stream_decoder(lzma_stream *strm, uint64_t memlimit, uint32_t flags)
{ {
lzma_next_strm_init0(strm, stream_decoder_init); lzma_next_strm_init(lzma_stream_decoder_init, strm, memlimit, flags);
strm->internal->supported_actions[LZMA_RUN] = true; strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true; // strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true; // FIXME
strm->internal->supported_actions[LZMA_FINISH] = true;
return LZMA_OK; return LZMA_OK;
} }

View File

@ -22,7 +22,7 @@
#include "common.h" #include "common.h"
extern lzma_ret lzma_stream_decoder_init( extern lzma_ret lzma_stream_decoder_init(lzma_next_coder *next,
lzma_next_coder *next, lzma_allocator *allocator); lzma_allocator *allocator, uint64_t memlimit, uint32_t flags);
#endif #endif

View File

@ -17,8 +17,8 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include "stream_common.h"
#include "stream_encoder.h" #include "stream_encoder.h"
#include "stream_flags_common.h"
#include "block_encoder.h" #include "block_encoder.h"
#include "index_encoder.h" #include "index_encoder.h"
@ -37,7 +37,7 @@ struct lzma_coder_s {
lzma_next_coder block_encoder; lzma_next_coder block_encoder;
/// Options for the Block encoder /// Options for the Block encoder
lzma_options_block block_options; lzma_block block_options;
/// Index encoder. This is separate from Block encoder, because this /// Index encoder. This is separate from Block encoder, because this
/// doesn't take much memory, and when encoding multiple Streams /// doesn't take much memory, and when encoding multiple Streams
@ -86,8 +86,8 @@ stream_encode(lzma_coder *coder, lzma_allocator *allocator,
case SEQ_STREAM_HEADER: case SEQ_STREAM_HEADER:
case SEQ_BLOCK_HEADER: case SEQ_BLOCK_HEADER:
case SEQ_STREAM_FOOTER: case SEQ_STREAM_FOOTER:
bufcpy(coder->buffer, &coder->buffer_pos, coder->buffer_size, lzma_bufcpy(coder->buffer, &coder->buffer_pos,
out, out_pos, out_size); coder->buffer_size, out, out_pos, out_size);
if (coder->buffer_pos < coder->buffer_size) if (coder->buffer_pos < coder->buffer_size)
return LZMA_OK; return LZMA_OK;
@ -202,18 +202,20 @@ stream_encode(lzma_coder *coder, lzma_allocator *allocator,
static void static void
stream_encoder_end(lzma_coder *coder, lzma_allocator *allocator) stream_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
{ {
lzma_next_coder_end(&coder->block_encoder, allocator); lzma_next_end(&coder->block_encoder, allocator);
lzma_next_coder_end(&coder->index_encoder, allocator); lzma_next_end(&coder->index_encoder, allocator);
lzma_index_end(coder->index, allocator); lzma_index_end(coder->index, allocator);
lzma_free(coder, allocator); lzma_free(coder, allocator);
return; return;
} }
static lzma_ret extern lzma_ret
stream_encoder_init(lzma_next_coder *next, lzma_allocator *allocator, lzma_stream_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
const lzma_options_filter *filters, lzma_check_type check) const lzma_filter *filters, lzma_check check)
{ {
lzma_next_coder_init(lzma_stream_encoder_init, next, allocator);
if (filters == NULL) if (filters == NULL)
return LZMA_PROG_ERROR; return LZMA_PROG_ERROR;
@ -233,7 +235,7 @@ stream_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
// Basic initializations // Basic initializations
next->coder->sequence = SEQ_STREAM_HEADER; next->coder->sequence = SEQ_STREAM_HEADER;
next->coder->block_options.check = check; next->coder->block_options.check = check;
next->coder->block_options.filters = (lzma_options_filter *)(filters); next->coder->block_options.filters = (lzma_filter *)(filters);
// Initialize the Index // Initialize the Index
next->coder->index = lzma_index_init(next->coder->index, allocator); next->coder->index = lzma_index_init(next->coder->index, allocator);
@ -258,20 +260,11 @@ stream_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
} }
extern lzma_ret
lzma_stream_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
const lzma_options_filter *filters, lzma_check_type check)
{
lzma_next_coder_init(stream_encoder_init, next, allocator,
filters, check);
}
extern LZMA_API lzma_ret extern LZMA_API lzma_ret
lzma_stream_encoder(lzma_stream *strm, lzma_stream_encoder(lzma_stream *strm,
const lzma_options_filter *filters, lzma_check_type check) const lzma_filter *filters, lzma_check check)
{ {
lzma_next_strm_init(strm, stream_encoder_init, filters, check); lzma_next_strm_init(lzma_stream_encoder_init, strm, filters, check);
strm->internal->supported_actions[LZMA_RUN] = true; strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true; strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;

View File

@ -25,6 +25,6 @@
extern lzma_ret lzma_stream_encoder_init( extern lzma_ret lzma_stream_encoder_init(
lzma_next_coder *next, lzma_allocator *allocator, lzma_next_coder *next, lzma_allocator *allocator,
const lzma_options_filter *filters, lzma_check_type check); const lzma_filter *filters, lzma_check check);
#endif #endif

View File

@ -1,9 +1,9 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
/// \file stream_flags_equal.c /// \file stream_flags_common.c
/// \brief Compare Stream Header and Stream Footer /// \brief Common stuff for Stream flags coders
// //
// Copyright (C) 2008 Lasse Collin // Copyright (C) 2007-2008 Lasse Collin
// //
// This library is free software; you can redistribute it and/or // This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public // modify it under the terms of the GNU Lesser General Public
@ -17,11 +17,15 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include "common.h" #include "stream_flags_common.h"
const uint8_t lzma_header_magic[6] = { 0xFF, 0x4C, 0x5A, 0x4D, 0x41, 0x00 };
const uint8_t lzma_footer_magic[2] = { 0x59, 0x5A };
extern LZMA_API lzma_bool extern LZMA_API lzma_bool
lzma_stream_flags_equal(const lzma_stream_flags *a, lzma_stream_flags *b) lzma_stream_flags_equal(const lzma_stream_flags *a, const lzma_stream_flags *b)
{ {
if (a->check != b->check) if (a->check != b->check)
return false; return false;

View File

@ -1,7 +1,7 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
/// \file stream_common.h /// \file stream_flags_common.h
/// \brief Common stuff for Stream coders /// \brief Common stuff for Stream flags coders
// //
// Copyright (C) 2007 Lasse Collin // Copyright (C) 2007 Lasse Collin
// //
@ -17,8 +17,8 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#ifndef LZMA_STREAM_COMMON_H #ifndef LZMA_STREAM_FLAGS_COMMON_H
#define LZMA_STREAM_COMMON_H #define LZMA_STREAM_FLAGS_COMMON_H
#include "common.h" #include "common.h"

View File

@ -17,7 +17,7 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include "stream_common.h" #include "stream_flags_common.h"
static bool static bool

View File

@ -17,7 +17,7 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include "stream_common.h" #include "stream_flags_common.h"
static bool static bool

View File

@ -27,17 +27,30 @@ lzma_vli_decode(lzma_vli *restrict vli, size_t *restrict vli_pos,
{ {
// If we haven't been given vli_pos, work in single-call mode. // If we haven't been given vli_pos, work in single-call mode.
size_t vli_pos_internal = 0; size_t vli_pos_internal = 0;
if (vli_pos == NULL) if (vli_pos == NULL) {
vli_pos = &vli_pos_internal; vli_pos = &vli_pos_internal;
// Initialize *vli when starting to decode a new integer.
if (*vli_pos == 0)
*vli = 0; *vli = 0;
// Validate the arguments. // If there's no input, use LZMA_DATA_ERROR. This way it is
if (*vli_pos >= LZMA_VLI_BYTES_MAX || *in_pos >= in_size // easy to decode VLIs from buffers that have known size,
|| (*vli >> (*vli_pos * 7)) != 0) // and get the correct error code in case the buffer is
return LZMA_PROG_ERROR;; // too short.
if (*in_pos >= in_size)
return LZMA_DATA_ERROR;
} else {
// Initialize *vli when starting to decode a new integer.
if (*vli_pos == 0)
*vli = 0;
// Validate the arguments.
if (*vli_pos >= LZMA_VLI_BYTES_MAX
|| (*vli >> (*vli_pos * 7)) != 0)
return LZMA_PROG_ERROR;;
if (*in_pos >= in_size)
return LZMA_BUF_ERROR;
}
do { do {
// Read the next byte. // Read the next byte.

View File

@ -31,10 +31,12 @@ lzma_vli_encode(lzma_vli vli, size_t *restrict vli_pos,
vli_pos = &vli_pos_internal; vli_pos = &vli_pos_internal;
// Validate the arguments. // Validate the arguments.
if (*vli_pos >= LZMA_VLI_BYTES_MAX || *out_pos >= out_size if (*vli_pos >= LZMA_VLI_BYTES_MAX || vli > LZMA_VLI_VALUE_MAX)
|| vli > LZMA_VLI_VALUE_MAX)
return LZMA_PROG_ERROR; return LZMA_PROG_ERROR;
if (*out_pos >= out_size)
return LZMA_BUF_ERROR;
// Write the non-last bytes in a loop. // Write the non-last bytes in a loop.
while ((vli >> (*vli_pos * 7)) >= 0x80) { while ((vli >> (*vli_pos * 7)) >= 0x80) {
out[*out_pos] = (uint8_t)(vli >> (*vli_pos * 7)) | 0x80; out[*out_pos] = (uint8_t)(vli >> (*vli_pos * 7)) | 0x80;
@ -55,20 +57,3 @@ lzma_vli_encode(lzma_vli vli, size_t *restrict vli_pos,
return vli_pos == &vli_pos_internal ? LZMA_OK : LZMA_STREAM_END; return vli_pos == &vli_pos_internal ? LZMA_OK : LZMA_STREAM_END;
} }
extern LZMA_API uint32_t
lzma_vli_size(lzma_vli vli)
{
if (vli > LZMA_VLI_VALUE_MAX)
return 0;
uint32_t i = 0;
do {
vli >>= 7;
++i;
} while (vli != 0);
assert(i <= LZMA_VLI_BYTES_MAX);
return i;
}

View File

@ -1,9 +1,9 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
/// \file version.c /// \file vli_size.c
/// \brief liblzma version number /// \brief Calculates the encoded size of a variable-length integer
// //
// Copyright (C) 2007 Lasse Collin // Copyright (C) 2007-2008 Lasse Collin
// //
// This library is free software; you can redistribute it and/or // This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public // modify it under the terms of the GNU Lesser General Public
@ -20,6 +20,18 @@
#include "common.h" #include "common.h"
LZMA_API const uint32_t lzma_version_number = LZMA_VERSION; extern LZMA_API uint32_t
lzma_vli_size(lzma_vli vli)
{
if (vli > LZMA_VLI_VALUE_MAX)
return 0;
LZMA_API const char *const lzma_version_string = PACKAGE_VERSION; uint32_t i = 0;
do {
vli >>= 7;
++i;
} while (vli != 0);
assert(i <= LZMA_VLI_BYTES_MAX);
return i;
}

View File

@ -0,0 +1,34 @@
##
## 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_LTLIBRARIES = libdelta.la
libdelta_la_CPPFLAGS = \
-I@top_srcdir@/src/liblzma/api \
-I@top_srcdir@/src/liblzma/common
libdelta_la_SOURCES = \
delta_common.c \
delta_common.h
if COND_ENCODER_DELTA
libdelta_la_SOURCES += \
delta_encoder.c \
delta_encoder.h
endif
if COND_DECODER_DELTA
libdelta_la_SOURCES += \
delta_decoder.c \
delta_decoder.h
endif

View File

@ -23,7 +23,7 @@
static void static void
delta_coder_end(lzma_coder *coder, lzma_allocator *allocator) delta_coder_end(lzma_coder *coder, lzma_allocator *allocator)
{ {
lzma_next_coder_end(&coder->next, allocator); lzma_next_end(&coder->next, allocator);
lzma_free(coder, allocator); lzma_free(coder, allocator);
return; return;
} }

View File

@ -59,3 +59,24 @@ lzma_delta_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
{ {
return lzma_delta_coder_init(next, allocator, filters, &delta_decode); return lzma_delta_coder_init(next, allocator, filters, &delta_decode);
} }
extern lzma_ret
lzma_delta_props_decode(void **options, lzma_allocator *allocator,
const uint8_t *props, size_t props_size)
{
if (props_size != 1)
return LZMA_HEADER_ERROR;
lzma_options_delta *opt
= lzma_alloc(sizeof(lzma_options_delta), allocator);
if (opt == NULL)
return LZMA_MEM_ERROR;
opt->type = LZMA_DELTA_TYPE_BYTE;
opt->distance = props[0] + 1;
*options = opt;
return LZMA_OK;
}

View File

@ -25,4 +25,8 @@
extern lzma_ret lzma_delta_decoder_init(lzma_next_coder *next, extern lzma_ret lzma_delta_decoder_init(lzma_next_coder *next,
lzma_allocator *allocator, const lzma_filter_info *filters); lzma_allocator *allocator, const lzma_filter_info *filters);
extern lzma_ret lzma_delta_props_decode(
void **options, lzma_allocator *allocator,
const uint8_t *props, size_t props_size);
#endif #endif

View File

@ -96,3 +96,24 @@ lzma_delta_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
{ {
return lzma_delta_coder_init(next, allocator, filters, &delta_encode); return lzma_delta_coder_init(next, allocator, filters, &delta_encode);
} }
extern lzma_ret
lzma_delta_props_encode(const void *options, uint8_t *out)
{
if (options == NULL)
return LZMA_PROG_ERROR;
const lzma_options_delta *opt = options;
// It's possible that newer liblzma versions will support larger
// distance values.
if (opt->type != LZMA_DELTA_TYPE_BYTE
|| opt->distance < LZMA_DELTA_DISTANCE_MIN
|| opt->distance > LZMA_DELTA_DISTANCE_MAX)
return LZMA_HEADER_ERROR;
out[0] = opt->distance - LZMA_DELTA_DISTANCE_MIN;
return LZMA_OK;
}

View File

@ -25,4 +25,6 @@
extern lzma_ret lzma_delta_encoder_init(lzma_next_coder *next, extern lzma_ret lzma_delta_encoder_init(lzma_next_coder *next,
lzma_allocator *allocator, const lzma_filter_info *filters); lzma_allocator *allocator, const lzma_filter_info *filters);
extern lzma_ret lzma_delta_props_encode(const void *options, uint8_t *out);
#endif #endif

View File

@ -20,43 +20,16 @@ liblz_la_CPPFLAGS = \
liblz_la_SOURCES = liblz_la_SOURCES =
if COND_MAIN_ENCODER if COND_ENCODER_LZ
liblz_la_SOURCES += \ liblz_la_SOURCES += \
lz_encoder.c \ lz_encoder.c \
lz_encoder.h \ lz_encoder.h \
lz_encoder_private.h \ lz_encoder_hash.h \
match_c.h \ lz_encoder_mf.c
match_h.h
if COND_MF_HC3
liblz_la_SOURCES += hc3.c hc3.h
liblz_la_CPPFLAGS += -DHAVE_HC3
endif
if COND_MF_HC4
liblz_la_SOURCES += hc4.c hc4.h
liblz_la_CPPFLAGS += -DHAVE_HC4
endif
if COND_MF_BT2
liblz_la_SOURCES += bt2.c bt2.h
liblz_la_CPPFLAGS += -DHAVE_BT2
endif
if COND_MF_BT3
liblz_la_SOURCES += bt3.c bt3.h
liblz_la_CPPFLAGS += -DHAVE_BT3
endif
if COND_MF_BT4
liblz_la_SOURCES += bt4.c bt4.h
liblz_la_CPPFLAGS += -DHAVE_BT4
endif
endif endif
if COND_MAIN_DECODER if COND_DECODER_LZ
liblz_la_SOURCES += \ liblz_la_SOURCES += \
lz_decoder.c \ lz_decoder.c \
lz_decoder.h lz_decoder.h

View File

@ -1,27 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file bt2.c
/// \brief Binary Tree 2
//
// Copyright (C) 1999-2006 Igor Pavlov
// 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 "bt2.h"
#undef IS_HASH_CHAIN
#undef HASH_ARRAY_2
#undef HASH_ARRAY_3
#include "match_c.h"

View File

@ -1,31 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file bt2.h
/// \brief Binary Tree 2
//
// Copyright (C) 1999-2006 Igor Pavlov
// 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_BT2_H
#define LZMA_BT2_H
#undef LZMA_MATCH_FINDER_NAME_LOWER
#undef LZMA_MATCH_FINDER_NAME_UPPER
#define LZMA_MATCH_FINDER_NAME_LOWER bt2
#define LZMA_MATCH_FINDER_NAME_UPPER BT2
#include "match_h.h"
#endif

View File

@ -1,29 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file bt3.c
/// \brief Binary Tree 3
//
// Copyright (C) 1999-2006 Igor Pavlov
// 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 "bt3.h"
#undef IS_HASH_CHAIN
#undef HASH_ARRAY_2
#undef HASH_ARRAY_3
#define HASH_ARRAY_2
#include "match_c.h"

View File

@ -1,31 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file bt3.h
/// \brief Binary Tree 3
//
// Copyright (C) 1999-2006 Igor Pavlov
// 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_BT3_H
#define LZMA_BT3_H
#undef LZMA_MATCH_FINDER_NAME_LOWER
#undef LZMA_MATCH_FINDER_NAME_UPPER
#define LZMA_MATCH_FINDER_NAME_LOWER bt3
#define LZMA_MATCH_FINDER_NAME_UPPER BT3
#include "match_h.h"
#endif

View File

@ -1,30 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file bt4.c
/// \brief Binary Tree 4
//
// Copyright (C) 1999-2006 Igor Pavlov
// 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 "bt4.h"
#undef IS_HASH_CHAIN
#undef HASH_ARRAY_2
#undef HASH_ARRAY_3
#define HASH_ARRAY_2
#define HASH_ARRAY_3
#include "match_c.h"

View File

@ -1,31 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file bt4.h
/// \brief Binary Tree 4
//
// Copyright (C) 1999-2006 Igor Pavlov
// 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_BT4_H
#define LZMA_BT4_H
#undef LZMA_MATCH_FINDER_NAME_LOWER
#undef LZMA_MATCH_FINDER_NAME_UPPER
#define LZMA_MATCH_FINDER_NAME_LOWER bt4
#define LZMA_MATCH_FINDER_NAME_UPPER BT4
#include "match_h.h"
#endif

View File

@ -1,30 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file hc3.c
/// \brief Hash Chain 3
//
// Copyright (C) 1999-2006 Igor Pavlov
// 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 "hc3.h"
#undef IS_HASH_CHAIN
#undef HASH_ARRAY_2
#undef HASH_ARRAY_3
#define IS_HASH_CHAIN
#define HASH_ARRAY_2
#include "match_c.h"

View File

@ -1,31 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file hc3.h
/// \brief Hash Chain 3
//
// Copyright (C) 1999-2006 Igor Pavlov
// 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_HC3_H
#define LZMA_HC3_H
#undef LZMA_MATCH_FINDER_NAME_LOWER
#undef LZMA_MATCH_FINDER_NAME_UPPER
#define LZMA_MATCH_FINDER_NAME_LOWER hc3
#define LZMA_MATCH_FINDER_NAME_UPPER HC3
#include "match_h.h"
#endif

Some files were not shown because too many files have changed in this diff Show More