]> pd.if.org Git - zpackage/commitdiff
integrate lzma
authorNathan Wagner <nw@hydaspes.if.org>
Sat, 17 Sep 2016 03:19:50 +0000 (22:19 -0500)
committerNathan Wagner <nw@hydaspes.if.org>
Sat, 17 Sep 2016 07:22:13 +0000 (02:22 -0500)
127 files changed:
Makefile
lzma/api/lzma.h [new file with mode: 0644]
lzma/api/lzma/base.h [new file with mode: 0644]
lzma/api/lzma/bcj.h [new file with mode: 0644]
lzma/api/lzma/block.h [new file with mode: 0644]
lzma/api/lzma/check.h [new file with mode: 0644]
lzma/api/lzma/container.h [new file with mode: 0644]
lzma/api/lzma/delta.h [new file with mode: 0644]
lzma/api/lzma/filter.h [new file with mode: 0644]
lzma/api/lzma/hardware.h [new file with mode: 0644]
lzma/api/lzma/index.h [new file with mode: 0644]
lzma/api/lzma/index_hash.h [new file with mode: 0644]
lzma/api/lzma/lzma12.h [new file with mode: 0644]
lzma/api/lzma/stream_flags.h [new file with mode: 0644]
lzma/api/lzma/version.h [new file with mode: 0644]
lzma/api/lzma/vli.h [new file with mode: 0644]
lzma/api/sysdefs.h [new file with mode: 0644]
lzma/check/check.c [new file with mode: 0644]
lzma/check/check.h [new file with mode: 0644]
lzma/check/crc32_fast.c [new file with mode: 0644]
lzma/check/crc32_table.c [new file with mode: 0644]
lzma/check/crc32_table_be.h [new file with mode: 0644]
lzma/check/crc32_table_le.h [new file with mode: 0644]
lzma/check/crc32_tablegen.c [new file with mode: 0644]
lzma/check/crc64_fast.c [new file with mode: 0644]
lzma/check/crc64_small.c [new file with mode: 0644]
lzma/check/crc64_table.c [new file with mode: 0644]
lzma/check/crc64_table_be.h [new file with mode: 0644]
lzma/check/crc64_table_le.h [new file with mode: 0644]
lzma/check/crc64_tablegen.c [new file with mode: 0644]
lzma/check/crc_macros.h [new file with mode: 0644]
lzma/check/sha256.c [new file with mode: 0644]
lzma/common/alone_decoder.c [new file with mode: 0644]
lzma/common/alone_decoder.h [new file with mode: 0644]
lzma/common/alone_encoder.c [new file with mode: 0644]
lzma/common/auto_decoder.c [new file with mode: 0644]
lzma/common/block_buffer_decoder.c [new file with mode: 0644]
lzma/common/block_buffer_encoder.c [new file with mode: 0644]
lzma/common/block_buffer_encoder.h [new file with mode: 0644]
lzma/common/block_decoder.c [new file with mode: 0644]
lzma/common/block_decoder.h [new file with mode: 0644]
lzma/common/block_encoder.c [new file with mode: 0644]
lzma/common/block_encoder.h [new file with mode: 0644]
lzma/common/block_header_decoder.c [new file with mode: 0644]
lzma/common/block_header_encoder.c [new file with mode: 0644]
lzma/common/block_util.c [new file with mode: 0644]
lzma/common/common.c [new file with mode: 0644]
lzma/common/common.h [new file with mode: 0644]
lzma/common/easy_buffer_encoder.c [new file with mode: 0644]
lzma/common/easy_decoder_memusage.c [new file with mode: 0644]
lzma/common/easy_encoder.c [new file with mode: 0644]
lzma/common/easy_encoder_memusage.c [new file with mode: 0644]
lzma/common/easy_preset.c [new file with mode: 0644]
lzma/common/easy_preset.h [new file with mode: 0644]
lzma/common/filter_buffer_decoder.c [new file with mode: 0644]
lzma/common/filter_buffer_encoder.c [new file with mode: 0644]
lzma/common/filter_common.c [new file with mode: 0644]
lzma/common/filter_common.h [new file with mode: 0644]
lzma/common/filter_decoder.c [new file with mode: 0644]
lzma/common/filter_decoder.h [new file with mode: 0644]
lzma/common/filter_encoder.c [new file with mode: 0644]
lzma/common/filter_encoder.h [new file with mode: 0644]
lzma/common/filter_flags_decoder.c [new file with mode: 0644]
lzma/common/filter_flags_encoder.c [new file with mode: 0644]
lzma/common/hardware_cputhreads.c [new file with mode: 0644]
lzma/common/hardware_physmem.c [new file with mode: 0644]
lzma/common/index.c [new file with mode: 0644]
lzma/common/index.h [new file with mode: 0644]
lzma/common/index_decoder.c [new file with mode: 0644]
lzma/common/index_encoder.c [new file with mode: 0644]
lzma/common/index_encoder.h [new file with mode: 0644]
lzma/common/index_hash.c [new file with mode: 0644]
lzma/common/memcmplen.h [new file with mode: 0644]
lzma/common/outqueue.c [new file with mode: 0644]
lzma/common/outqueue.h [new file with mode: 0644]
lzma/common/stream_buffer_decoder.c [new file with mode: 0644]
lzma/common/stream_buffer_encoder.c [new file with mode: 0644]
lzma/common/stream_decoder.c [new file with mode: 0644]
lzma/common/stream_decoder.h [new file with mode: 0644]
lzma/common/stream_encoder.c [new file with mode: 0644]
lzma/common/stream_flags_common.c [new file with mode: 0644]
lzma/common/stream_flags_common.h [new file with mode: 0644]
lzma/common/stream_flags_decoder.c [new file with mode: 0644]
lzma/common/stream_flags_encoder.c [new file with mode: 0644]
lzma/common/vli_decoder.c [new file with mode: 0644]
lzma/common/vli_encoder.c [new file with mode: 0644]
lzma/common/vli_size.c [new file with mode: 0644]
lzma/delta/delta_common.h [new file with mode: 0644]
lzma/delta/delta_decoder.h [new file with mode: 0644]
lzma/delta/delta_encoder.h [new file with mode: 0644]
lzma/lz/lz_decoder.c [new file with mode: 0644]
lzma/lz/lz_decoder.h [new file with mode: 0644]
lzma/lz/lz_encoder.c [new file with mode: 0644]
lzma/lz/lz_encoder.h [new file with mode: 0644]
lzma/lz/lz_encoder_hash.h [new file with mode: 0644]
lzma/lz/lz_encoder_hash_table.h [new file with mode: 0644]
lzma/lz/lz_encoder_mf.c [new file with mode: 0644]
lzma/lzma/fastpos.h [new file with mode: 0644]
lzma/lzma/fastpos_table.c [new file with mode: 0644]
lzma/lzma/fastpos_tablegen.c [new file with mode: 0644]
lzma/lzma/lzma2_decoder.c [new file with mode: 0644]
lzma/lzma/lzma2_decoder.h [new file with mode: 0644]
lzma/lzma/lzma2_encoder.c [new file with mode: 0644]
lzma/lzma/lzma2_encoder.h [new file with mode: 0644]
lzma/lzma/lzma_common.h [new file with mode: 0644]
lzma/lzma/lzma_decoder.c [new file with mode: 0644]
lzma/lzma/lzma_decoder.h [new file with mode: 0644]
lzma/lzma/lzma_encoder.c [new file with mode: 0644]
lzma/lzma/lzma_encoder.h [new file with mode: 0644]
lzma/lzma/lzma_encoder_optimum_fast.c [new file with mode: 0644]
lzma/lzma/lzma_encoder_optimum_normal.c [new file with mode: 0644]
lzma/lzma/lzma_encoder_presets.c [new file with mode: 0644]
lzma/lzma/lzma_encoder_private.h [new file with mode: 0644]
lzma/rangecoder/price.h [new file with mode: 0644]
lzma/rangecoder/price_table.c [new file with mode: 0644]
lzma/rangecoder/range_common.h [new file with mode: 0644]
lzma/rangecoder/range_decoder.h [new file with mode: 0644]
lzma/rangecoder/range_encoder.h [new file with mode: 0644]
lzma/simple/simple_coder.h [new file with mode: 0644]
lzma/simple/simple_decoder.h [new file with mode: 0644]
lzma/simple/simple_encoder.h [new file with mode: 0644]
lzma/tuklib/mythread.h [new file with mode: 0644]
lzma/tuklib/tuklib_common.h [new file with mode: 0644]
lzma/tuklib/tuklib_config.h [new file with mode: 0644]
lzma/tuklib/tuklib_cpucores.h [new file with mode: 0644]
lzma/tuklib/tuklib_integer.h [new file with mode: 0644]
lzma/tuklib/tuklib_physmem.h [new file with mode: 0644]

index 053af317e05bcf4e425210a4d6bf306ddc58cc92..7270bde66368565c3159bfebc4d35c7d630e4bdb 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,14 @@
-CFLAGS=-Wall -std=c99 -I. -L.
+CFLAGS=-Wall -std=c99 -I. -Ilzma/api -Ilzma/tuklib -Ilzma/lzma -Ilzma/common -Ilzma/check -Ilzma/lz -Ilzma/rangecoder -Ilzma/simple -Ilzma/delta -DHAVE_CHECK_CRC64 -DHAVE_CHECK_CRC32 -DHAVE_ENCODER_LZMA2 -DHAVE_DECODER_LZMA2 -DHAVE_MF_BT4
 LDFLAGS=-L.
 
+LZMACHECKSRC=lzma/check/check.c lzma/check/crc32_fast.c lzma/check/crc64_fast.c lzma/check/crc32_table.c lzma/check/crc64_table.c
+LZMASRC=$(shell ls lzma/lzma/*.c lzma/common/*.c lzma/lz/*.c) $(LZMACHECKSRC) lzma/rangecoder/price_table.c
+LZMAOBJ=$(filter-out lzma/common/stream_encoder_mt.o, $(LZMASRC:%.c=%.o))
+
 def: libzpm.a
+d:
+       printf '%s\n' $(LZMAOBJ)
+
 
 programs: elftype soname zpm-addfile zpm-extract
 
@@ -15,17 +22,20 @@ soname: elf/soname.c
        $(CC) $(CFLAGS) -o $@ $+
 
 zpm-addfile: zpm-addfile.o libzpm.a
-       $(CC) $(CFLAGS) -o $@ $< -lsqlite3 -llzma -lzpm
+       $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -lsqlite3 -lzpm
 
 zpm-extract: zpm-extract.o libzpm.a
-       $(CC) $(CFLAGS) -o $@ $< -lsqlite3 -llzma -lzpm
+       $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -lsqlite3 -llzma -lzpm
 
 newdb.c: db.sql
        echo "char createdb[] = {" > $@
        xxd -i < $< >> $@
        echo "};" >> $@
 
-libzpm.a: lib/sha256.o lib/db.o lib/compress.o lib/uncompress.o newdb.o lib/zpm.o
+
+libzpm.a: lib/sha256.o lib/db.o lib/compress.o lib/uncompress.o newdb.o lib/zpm.o \
+       sqlite3.o \
+       $(LZMAOBJ)
        ar rcuv $@ $+
 
 install: elftype
@@ -43,4 +53,4 @@ install: elftype
        #SPOOL=$(DESTDIR)/var/lib/admin/notes ./zpm-sequence -c notes
 
 clean:
-       rm -f *.o
+       rm -f *.o lib/*.o $(LZMAOBJ) liblzma.a
diff --git a/lzma/api/lzma.h b/lzma/api/lzma.h
new file mode 100644 (file)
index 0000000..ce675a7
--- /dev/null
@@ -0,0 +1,321 @@
+/**
+ * \file        api/lzma.h
+ * \brief       The public API of liblzma data compression library
+ *
+ * liblzma is a public domain general-purpose data compression library with
+ * a zlib-like API. The native file format is .xz, but also the old .lzma
+ * format and raw (no headers) streams are supported. Multiple compression
+ * algorithms (filters) are supported. Currently LZMA2 is the primary filter.
+ *
+ * liblzma is part of XZ Utils <http://tukaani.org/xz/>. XZ Utils includes
+ * a gzip-like command line tool named xz and some other tools. XZ Utils
+ * is developed and maintained by Lasse Collin.
+ *
+ * Major parts of liblzma are based on Igor Pavlov's public domain LZMA SDK
+ * <http://7-zip.org/sdk.html>.
+ *
+ * The SHA-256 implementation is based on the public domain code found from
+ * 7-Zip <http://7-zip.org/>, which has a modified version of the public
+ * domain SHA-256 code found from Crypto++ <http://www.cryptopp.com/>.
+ * The SHA-256 code in Crypto++ was written by Kevin Springle and Wei Dai.
+ */
+
+/*
+ * Author: Lasse Collin
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ */
+
+#ifndef 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 already or if LZMA_MANUAL_HEADERS
+ * has been defined.
+ *
+ * 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, in case of incomplete inttypes.h, unsigned int is 32-bit.
+ * If the application already takes care of setting up all the types and
+ * macros properly (for example by using gnulib's stdint.h or inttypes.h),
+ * we try to detect that the macros are already defined and don't include
+ * inttypes.h here again. However, you may define LZMA_MANUAL_HEADERS to
+ * force this file to never include any system headers.
+ *
+ * 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 as an 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. sizeof(bool) in C99 isn't
+ * necessarily the same as sizeof(bool) in C++.
+ */
+
+#ifndef LZMA_MANUAL_HEADERS
+       /*
+        * I suppose this works portably also in C++. Note that in C++,
+        * we need to get size_t into the global namespace.
+        */
+#      include <stddef.h>
+
+       /*
+        * Skip inttypes.h if we already have all the required macros. If we
+        * have the macros, we assume that we have the matching typedefs too.
+        */
+#      if !defined(UINT32_C) || !defined(UINT64_C) \
+                       || !defined(UINT32_MAX) || !defined(UINT64_MAX)
+               /*
+                * MSVC versions older than 2013 have no C99 support, and
+                * thus they cannot be used to compile liblzma. Using an
+                * existing liblzma.dll with old MSVC can work though(*),
+                * but we need to define the required standard integer
+                * types here in a MSVC-specific way.
+                *
+                * (*) If you do this, the existing liblzma.dll probably uses
+                *     a different runtime library than your MSVC-built
+                *     application. Mixing runtimes is generally bad, but
+                *     in this case it should work as long as you avoid
+                *     the few rarely-needed liblzma functions that allocate
+                *     memory and expect the caller to free it using free().
+                */
+#              if defined(_WIN32) && defined(_MSC_VER) && _MSC_VER < 1800
+                       typedef unsigned __int8 uint8_t;
+                       typedef unsigned __int32 uint32_t;
+                       typedef unsigned __int64 uint64_t;
+#              else
+                       /* Use the standard inttypes.h. */
+#                      ifdef __cplusplus
+                               /*
+                                * C99 sections 7.18.2 and 7.18.4 specify
+                                * that C++ implementations define the limit
+                                * and constant macros only if specifically
+                                * requested. Note that if you want the
+                                * format macros (PRIu64 etc.) 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>
+#              endif
+
+               /*
+                * 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 setup the types manually
+                * before including lzma.h.
+                */
+#              ifndef UINT32_C
+#                      if defined(_WIN32) && defined(_MSC_VER)
+#                              define UINT32_C(n) n ## UI32
+#                      else
+#                              define UINT32_C(n) n ## U
+#                      endif
+#              endif
+
+#              ifndef UINT64_C
+#                      if defined(_WIN32) && defined(_MSC_VER)
+#                              define UINT64_C(n) n ## UI64
+#                      else
+                               /* Get ULONG_MAX. */
+#                              include <limits.h>
+#                              if ULONG_MAX == 4294967295UL
+#                                      define UINT64_C(n) n ## ULL
+#                              else
+#                                      define UINT64_C(n) n ## UL
+#                              endif
+#                      endif
+#              endif
+
+#              ifndef UINT32_MAX
+#                      define UINT32_MAX (UINT32_C(4294967295))
+#              endif
+
+#              ifndef UINT64_MAX
+#                      define UINT64_MAX (UINT64_C(18446744073709551615))
+#              endif
+#      endif
+#endif /* ifdef LZMA_MANUAL_HEADERS */
+
+
+/******************
+ * LZMA_API macro *
+ ******************/
+
+/*
+ * Some systems require that the functions and function pointers are
+ * declared specially in the headers. LZMA_API_IMPORT is for importing
+ * symbols and LZMA_API_CALL is to specify the calling convention.
+ *
+ * By default it is assumed that the application will link dynamically
+ * against liblzma. #define LZMA_API_STATIC in your application if you
+ * want to link against static liblzma. If you don't care about portability
+ * to operating systems like Windows, or at least don't care about linking
+ * against static liblzma on them, don't worry about LZMA_API_STATIC. That
+ * is, most developers will never need to use LZMA_API_STATIC.
+ *
+ * The GCC variants are a special case on Windows (Cygwin and MinGW).
+ * We rely on GCC doing the right thing with its auto-import feature,
+ * and thus don't use __declspec(dllimport). This way developers don't
+ * need to worry about LZMA_API_STATIC. Also the calling convention is
+ * omitted on Cygwin but not on MinGW.
+ */
+#ifndef LZMA_API_IMPORT
+#      if !defined(LZMA_API_STATIC) && defined(_WIN32) && !defined(__GNUC__)
+#              define LZMA_API_IMPORT __declspec(dllimport)
+#      else
+#              define LZMA_API_IMPORT
+#      endif
+#endif
+
+#ifndef LZMA_API_CALL
+#      if defined(_WIN32) && !defined(__CYGWIN__)
+#              define LZMA_API_CALL __cdecl
+#      else
+#              define LZMA_API_CALL
+#      endif
+#endif
+
+#ifndef LZMA_API
+#      define LZMA_API(type) LZMA_API_IMPORT type LZMA_API_CALL
+#endif
+
+
+/***********
+ * nothrow *
+ ***********/
+
+/*
+ * None of the functions in liblzma may throw an exception. Even
+ * the functions that use callback functions won't throw exceptions,
+ * because liblzma would break if a callback function threw an exception.
+ */
+#ifndef lzma_nothrow
+#      if defined(__cplusplus)
+#              define lzma_nothrow throw()
+#      elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
+#              define lzma_nothrow __attribute__((__nothrow__))
+#      else
+#              define lzma_nothrow
+#      endif
+#endif
+
+
+/********************
+ * GNU C extensions *
+ ********************/
+
+/*
+ * GNU C extensions are used conditionally in the public API. It doesn't
+ * break anything if these are sometimes enabled and sometimes not, only
+ * affects warnings and optimizations.
+ */
+#if __GNUC__ >= 3
+#      ifndef lzma_attribute
+#              define lzma_attribute(attr) __attribute__(attr)
+#      endif
+
+       /* warn_unused_result was added in GCC 3.4. */
+#      ifndef lzma_attr_warn_unused_result
+#              if __GNUC__ == 3 && __GNUC_MINOR__ < 4
+#                      define lzma_attr_warn_unused_result
+#              endif
+#      endif
+
+#else
+#      ifndef lzma_attribute
+#              define lzma_attribute(attr)
+#      endif
+#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
+
+
+/**************
+ * Subheaders *
+ **************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Subheaders check that this is defined. It is to prevent including
+ * them directly from applications.
+ */
+#define LZMA_H_INTERNAL 1
+
+/* Basic features */
+#include "lzma/version.h"
+#include "lzma/base.h"
+#include "lzma/vli.h"
+#include "lzma/check.h"
+
+/* Filters */
+#include "lzma/filter.h"
+#include "lzma/bcj.h"
+#include "lzma/delta.h"
+#include "lzma/lzma12.h"
+
+/* Container formats */
+#include "lzma/container.h"
+
+/* Advanced features */
+#include "lzma/stream_flags.h"
+#include "lzma/block.h"
+#include "lzma/index.h"
+#include "lzma/index_hash.h"
+
+/* Hardware information */
+#include "lzma/hardware.h"
+
+/*
+ * All subheaders included. Undefine LZMA_H_INTERNAL to prevent applications
+ * re-including the subheaders.
+ */
+#undef LZMA_H_INTERNAL
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef LZMA_H */
diff --git a/lzma/api/lzma/base.h b/lzma/api/lzma/base.h
new file mode 100644 (file)
index 0000000..7a31a42
--- /dev/null
@@ -0,0 +1,654 @@
+/**
+ * \file        lzma/base.h
+ * \brief       Data types and functions used in many places in liblzma API
+ */
+
+/*
+ * Author: Lasse Collin
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ *
+ * See ../lzma.h for information about liblzma as a whole.
+ */
+
+#ifndef LZMA_H_INTERNAL
+#      error Never include this file directly. Use <lzma.h> instead.
+#endif
+
+
+/**
+ * \brief       Boolean
+ *
+ * This is here because C89 doesn't have stdbool.h. To set a value for
+ * variables having type lzma_bool, you can use
+ *   - C99's `true' and `false' from stdbool.h;
+ *   - C++'s internal `true' and `false'; or
+ *   - integers one (true) and zero (false).
+ */
+typedef unsigned char lzma_bool;
+
+
+/**
+ * \brief       Type of reserved enumeration variable in structures
+ *
+ * To avoid breaking library ABI when new features are added, several
+ * structures contain extra variables that may be used in future. Since
+ * sizeof(enum) can be different than sizeof(int), and sizeof(enum) may
+ * even vary depending on the range of enumeration constants, we specify
+ * a separate type to be used for reserved enumeration variables. All
+ * enumeration constants in liblzma API will be non-negative and less
+ * than 128, which should guarantee that the ABI won't break even when
+ * new constants are added to existing enumerations.
+ */
+typedef enum {
+       LZMA_RESERVED_ENUM      = 0
+} lzma_reserved_enum;
+
+
+/**
+ * \brief       Return values used by several functions in liblzma
+ *
+ * Check the descriptions of specific functions to find out which return
+ * values they can return. With some functions the return values may have
+ * more specific meanings than described here; those differences are
+ * described per-function basis.
+ */
+typedef enum {
+       LZMA_OK                 = 0,
+               /**<
+                * \brief       Operation completed successfully
+                */
+
+       LZMA_STREAM_END         = 1,
+               /**<
+                * \brief       End of stream was reached
+                *
+                * In encoder, LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, or
+                * LZMA_FINISH was finished. In decoder, this indicates
+                * that all the data was successfully decoded.
+                *
+                * In all cases, when LZMA_STREAM_END is returned, the last
+                * output bytes should be picked from strm->next_out.
+                */
+
+       LZMA_NO_CHECK           = 2,
+               /**<
+                * \brief       Input stream has no integrity check
+                *
+                * This return value can be returned only if the
+                * LZMA_TELL_NO_CHECK flag was used when initializing
+                * the decoder. LZMA_NO_CHECK is just a warning, and
+                * the decoding can be continued normally.
+                *
+                * It is possible to call lzma_get_check() immediately after
+                * lzma_code has returned LZMA_NO_CHECK. The result will
+                * naturally be LZMA_CHECK_NONE, but the possibility to call
+                * lzma_get_check() may be convenient in some applications.
+                */
+
+       LZMA_UNSUPPORTED_CHECK  = 3,
+               /**<
+                * \brief       Cannot calculate the integrity check
+                *
+                * The usage of this return value is different in encoders
+                * and decoders.
+                *
+                * Encoders can return this value only from the initialization
+                * function. If initialization fails with this value, the
+                * encoding cannot be done, because there's no way to produce
+                * output with the correct integrity check.
+                *
+                * Decoders can return this value only from lzma_code() and
+                * only if the LZMA_TELL_UNSUPPORTED_CHECK flag was used when
+                * initializing the decoder. The decoding can still be
+                * continued normally even if the check type is unsupported,
+                * but naturally the check will not be validated, and possible
+                * errors may go undetected.
+                *
+                * With decoder, it is possible to call lzma_get_check()
+                * immediately after lzma_code() has returned
+                * LZMA_UNSUPPORTED_CHECK. This way it is possible to find
+                * out what the unsupported Check ID was.
+                */
+
+       LZMA_GET_CHECK          = 4,
+               /**<
+                * \brief       Integrity check type is now available
+                *
+                * This value can be returned only by the lzma_code() function
+                * and only if the decoder was initialized with the
+                * LZMA_TELL_ANY_CHECK flag. LZMA_GET_CHECK tells the
+                * application that it may now call lzma_get_check() to find
+                * out the Check ID. This can be used, for example, to
+                * implement a decoder that accepts only files that have
+                * strong enough integrity check.
+                */
+
+       LZMA_MEM_ERROR          = 5,
+               /**<
+                * \brief       Cannot allocate memory
+                *
+                * Memory allocation failed, or the size of the allocation
+                * would be greater than SIZE_MAX.
+                *
+                * Due to internal implementation reasons, the coding cannot
+                * be continued even if more memory were made available after
+                * LZMA_MEM_ERROR.
+                */
+
+       LZMA_MEMLIMIT_ERROR     = 6,
+               /**
+                * \brief       Memory usage limit was reached
+                *
+                * Decoder would need more memory than allowed by the
+                * specified memory usage limit. To continue decoding,
+                * the memory usage limit has to be increased with
+                * lzma_memlimit_set().
+                */
+
+       LZMA_FORMAT_ERROR       = 7,
+               /**<
+                * \brief       File format not recognized
+                *
+                * The decoder did not recognize the input as supported file
+                * format. This error can occur, for example, when trying to
+                * decode .lzma format file with lzma_stream_decoder,
+                * because lzma_stream_decoder accepts only the .xz format.
+                */
+
+       LZMA_OPTIONS_ERROR      = 8,
+               /**<
+                * \brief       Invalid or unsupported options
+                *
+                * Invalid or unsupported options, for example
+                *  - unsupported filter(s) or filter options; or
+                *  - reserved bits set in headers (decoder only).
+                *
+                * Rebuilding liblzma with more features enabled, or
+                * upgrading to a newer version of liblzma may help.
+                */
+
+       LZMA_DATA_ERROR         = 9,
+               /**<
+                * \brief       Data is corrupt
+                *
+                * The usage of this return value is different in encoders
+                * and decoders. In both encoder and decoder, the coding
+                * cannot continue after this error.
+                *
+                * Encoders return this if size limits of the target file
+                * format would be exceeded. These limits are huge, thus
+                * getting this error from an encoder is mostly theoretical.
+                * For example, the maximum compressed and uncompressed
+                * size of a .xz Stream is roughly 8 EiB (2^63 bytes).
+                *
+                * Decoders return this error if the input data is corrupt.
+                * This can mean, for example, invalid CRC32 in headers
+                * or invalid check of uncompressed data.
+                */
+
+       LZMA_BUF_ERROR          = 10,
+               /**<
+                * \brief       No progress is possible
+                *
+                * This error code is returned when the coder cannot consume
+                * any new input and produce any new output. The most common
+                * reason for this error is that the input stream being
+                * decoded is truncated or corrupt.
+                *
+                * This error is not fatal. Coding can be continued normally
+                * by providing more input and/or more output space, if
+                * possible.
+                *
+                * Typically the first call to lzma_code() that can do no
+                * progress returns LZMA_OK instead of LZMA_BUF_ERROR. Only
+                * the second consecutive call doing no progress will return
+                * LZMA_BUF_ERROR. This is intentional.
+                *
+                * With zlib, Z_BUF_ERROR may be returned even if the
+                * application is doing nothing wrong, so apps will need
+                * to handle Z_BUF_ERROR specially. The above hack
+                * guarantees that liblzma never returns LZMA_BUF_ERROR
+                * to properly written applications unless the input file
+                * is truncated or corrupt. This should simplify the
+                * applications a little.
+                */
+
+       LZMA_PROG_ERROR         = 11,
+               /**<
+                * \brief       Programming error
+                *
+                * This indicates that the arguments given to the function are
+                * invalid or the internal state of the decoder is corrupt.
+                *   - Function arguments are invalid or the structures
+                *     pointed by the argument pointers are invalid
+                *     e.g. if strm->next_out has been set to NULL and
+                *     strm->avail_out > 0 when calling lzma_code().
+                *   - lzma_* functions have been called in wrong order
+                *     e.g. lzma_code() was called right after lzma_end().
+                *   - If errors occur randomly, the reason might be flaky
+                *     hardware.
+                *
+                * If you think that your code is correct, this error code
+                * can be a sign of a bug in liblzma. See the documentation
+                * how to report bugs.
+                */
+} lzma_ret;
+
+
+/**
+ * \brief       The `action' argument for lzma_code()
+ *
+ * After the first use of LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, LZMA_FULL_BARRIER,
+ * or LZMA_FINISH, the same `action' must is used until lzma_code() returns
+ * LZMA_STREAM_END. Also, the amount of input (that is, strm->avail_in) must
+ * not be modified by the application until lzma_code() returns
+ * LZMA_STREAM_END. Changing the `action' or modifying the amount of input
+ * will make lzma_code() return LZMA_PROG_ERROR.
+ */
+typedef enum {
+       LZMA_RUN = 0,
+               /**<
+                * \brief       Continue coding
+                *
+                * Encoder: Encode as much input as possible. Some internal
+                * buffering will probably be done (depends on the filter
+                * chain in use), which causes latency: the input used won't
+                * usually be decodeable from the output of the same
+                * lzma_code() call.
+                *
+                * Decoder: Decode as much input as possible and produce as
+                * much output as possible.
+                */
+
+       LZMA_SYNC_FLUSH = 1,
+               /**<
+                * \brief       Make all the input available at output
+                *
+                * Normally the encoder introduces some latency.
+                * LZMA_SYNC_FLUSH forces all the buffered data to be
+                * available at output without resetting the internal
+                * state of the encoder. This way it is possible to use
+                * compressed stream for example for communication over
+                * network.
+                *
+                * Only some filters support LZMA_SYNC_FLUSH. Trying to use
+                * LZMA_SYNC_FLUSH with filters that don't support it will
+                * make lzma_code() return LZMA_OPTIONS_ERROR. For example,
+                * LZMA1 doesn't support LZMA_SYNC_FLUSH but LZMA2 does.
+                *
+                * Using LZMA_SYNC_FLUSH very often can dramatically reduce
+                * the compression ratio. With some filters (for example,
+                * LZMA2), fine-tuning the compression options may help
+                * mitigate this problem significantly (for example,
+                * match finder with LZMA2).
+                *
+                * Decoders don't support LZMA_SYNC_FLUSH.
+                */
+
+       LZMA_FULL_FLUSH = 2,
+               /**<
+                * \brief       Finish encoding of the current Block
+                *
+                * All the input data going to the current Block must have
+                * been given to the encoder (the last bytes can still be
+                * pending in *next_in). Call lzma_code() with LZMA_FULL_FLUSH
+                * until it returns LZMA_STREAM_END. Then continue normally
+                * with LZMA_RUN or finish the Stream with LZMA_FINISH.
+                *
+                * This action is currently supported only by Stream encoder
+                * and easy encoder (which uses Stream encoder). If there is
+                * no unfinished Block, no empty Block is created.
+                */
+
+       LZMA_FULL_BARRIER = 4,
+               /**<
+                * \brief       Finish encoding of the current Block
+                *
+                * This is like LZMA_FULL_FLUSH except that this doesn't
+                * necessarily wait until all the input has been made
+                * available via the output buffer. That is, lzma_code()
+                * might return LZMA_STREAM_END as soon as all the input
+                * has been consumed (avail_in == 0).
+                *
+                * LZMA_FULL_BARRIER is useful with a threaded encoder if
+                * one wants to split the .xz Stream into Blocks at specific
+                * offsets but doesn't care if the output isn't flushed
+                * immediately. Using LZMA_FULL_BARRIER allows keeping
+                * the threads busy while LZMA_FULL_FLUSH would make
+                * lzma_code() wait until all the threads have finished
+                * until more data could be passed to the encoder.
+                *
+                * With a lzma_stream initialized with the single-threaded
+                * lzma_stream_encoder() or lzma_easy_encoder(),
+                * LZMA_FULL_BARRIER is an alias for LZMA_FULL_FLUSH.
+                */
+
+       LZMA_FINISH = 3
+               /**<
+                * \brief       Finish the coding operation
+                *
+                * All the input data must have been given to the encoder
+                * (the last bytes can still be pending in next_in).
+                * Call lzma_code() with LZMA_FINISH until it returns
+                * LZMA_STREAM_END. Once LZMA_FINISH has been used,
+                * the amount of input must no longer be changed by
+                * the application.
+                *
+                * When decoding, using LZMA_FINISH is optional unless the
+                * LZMA_CONCATENATED flag was used when the decoder was
+                * initialized. When LZMA_CONCATENATED was not used, the only
+                * effect of LZMA_FINISH is that the amount of input must not
+                * be changed just like in the encoder.
+                */
+} lzma_action;
+
+
+/**
+ * \brief       Custom functions for memory handling
+ *
+ * A pointer to lzma_allocator may be passed via lzma_stream structure
+ * to liblzma, and some advanced functions take a pointer to lzma_allocator
+ * as a separate function argument. The library will use the functions
+ * specified in lzma_allocator for memory handling instead of the default
+ * malloc() and free(). C++ users should note that the custom memory
+ * handling functions must not throw exceptions.
+ *
+ * Single-threaded mode only: liblzma doesn't make an internal copy of
+ * lzma_allocator. Thus, it is OK to change these function pointers in
+ * the middle of the coding process, but obviously it must be done
+ * carefully to make sure that the replacement `free' can deallocate
+ * memory allocated by the earlier `alloc' function(s).
+ *
+ * Multithreaded mode: liblzma might internally store pointers to the
+ * lzma_allocator given via the lzma_stream structure. The application
+ * must not change the allocator pointer in lzma_stream or the contents
+ * of the pointed lzma_allocator structure until lzma_end() has been used
+ * to free the memory associated with that lzma_stream. The allocation
+ * functions might be called simultaneously from multiple threads, and
+ * thus they must be thread safe.
+ */
+typedef struct {
+       /**
+        * \brief       Pointer to a custom memory allocation function
+        *
+        * If you don't want a custom allocator, but still want
+        * custom free(), set this to NULL and liblzma will use
+        * the standard malloc().
+        *
+        * \param       opaque  lzma_allocator.opaque (see below)
+        * \param       nmemb   Number of elements like in calloc(). liblzma
+        *                      will always set nmemb to 1, so it is safe to
+        *                      ignore nmemb in a custom allocator if you like.
+        *                      The nmemb argument exists only for
+        *                      compatibility with zlib and libbzip2.
+        * \param       size    Size of an element in bytes.
+        *                      liblzma never sets this to zero.
+        *
+        * \return      Pointer to the beginning of a memory block of
+        *              `size' bytes, or NULL if allocation fails
+        *              for some reason. When allocation fails, functions
+        *              of liblzma return LZMA_MEM_ERROR.
+        *
+        * 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 in physical memory until it is actually used. With small
+        * input files, liblzma may actually need only a fraction of the
+        * memory that it requested for allocation.
+        *
+        * \note        LZMA_MEM_ERROR is also used when the size of the
+        *              allocation would be greater than SIZE_MAX. Thus,
+        *              don't assume that the custom allocator must have
+        *              returned NULL if some function from liblzma
+        *              returns LZMA_MEM_ERROR.
+        */
+       void *(LZMA_API_CALL *alloc)(void *opaque, size_t nmemb, size_t size);
+
+       /**
+        * \brief       Pointer to a custom memory freeing function
+        *
+        * If you don't want a custom freeing function, but still
+        * want a custom allocator, set this to NULL and liblzma
+        * will use the standard free().
+        *
+        * \param       opaque  lzma_allocator.opaque (see below)
+        * \param       ptr     Pointer returned by lzma_allocator.alloc(),
+        *                      or when it is set to NULL, a pointer returned
+        *                      by the standard malloc().
+        */
+       void (LZMA_API_CALL *free)(void *opaque, void *ptr);
+
+       /**
+        * \brief       Pointer passed to .alloc() and .free()
+        *
+        * opaque is passed as the first argument to lzma_allocator.alloc()
+        * and lzma_allocator.free(). This intended to ease implementing
+        * custom memory allocation functions for use with liblzma.
+        *
+        * If you don't need this, you should set this to NULL.
+        */
+       void *opaque;
+
+} lzma_allocator;
+
+
+/**
+ * \brief       Internal data structure
+ *
+ * The contents of this structure is not visible outside the library.
+ */
+typedef struct lzma_internal_s lzma_internal;
+
+
+/**
+ * \brief       Passing data to and from liblzma
+ *
+ * The lzma_stream structure is used for
+ *  - passing pointers to input and output buffers to liblzma;
+ *  - defining custom memory hander functions; and
+ *  - holding a pointer to coder-specific internal data structures.
+ *
+ * Typical usage:
+ *
+ *  - After allocating lzma_stream (on stack or with malloc()), it must be
+ *    initialized to LZMA_STREAM_INIT (see LZMA_STREAM_INIT for details).
+ *
+ *  - Initialize a coder to the lzma_stream, for example by using
+ *    lzma_easy_encoder() or lzma_auto_decoder(). Some notes:
+ *      - In contrast to zlib, strm->next_in and strm->next_out are
+ *        ignored by all initialization functions, thus it is safe
+ *        to not initialize them yet.
+ *      - The initialization functions always set strm->total_in and
+ *        strm->total_out to zero.
+ *      - If the initialization function fails, no memory is left allocated
+ *        that would require freeing with lzma_end() even if some memory was
+ *        associated with the lzma_stream structure when the initialization
+ *        function was called.
+ *
+ *  - Use lzma_code() to do the actual work.
+ *
+ *  - Once the coding has been finished, the existing lzma_stream can be
+ *    reused. It is OK to reuse lzma_stream with different initialization
+ *    function without calling lzma_end() first. Old allocations are
+ *    automatically freed.
+ *
+ *  - Finally, use lzma_end() to free the allocated memory. lzma_end() never
+ *    frees the lzma_stream structure itself.
+ *
+ * Application may modify the values of total_in and total_out as it wants.
+ * They are updated by liblzma to match the amount of data read and
+ * written but aren't used for anything else except as a possible return
+ * values from lzma_get_progress().
+ */
+typedef struct {
+       const uint8_t *next_in; /**< Pointer to the next input byte. */
+       size_t avail_in;    /**< Number of available input bytes in next_in. */
+       uint64_t total_in;  /**< Total number of bytes read by liblzma. */
+
+       uint8_t *next_out;  /**< Pointer to the next output position. */
+       size_t avail_out;   /**< Amount of free space in next_out. */
+       uint64_t total_out; /**< Total number of bytes written by liblzma. */
+
+       /**
+        * \brief       Custom memory allocation functions
+        *
+        * In most cases this is NULL which makes liblzma use
+        * the standard malloc() and free().
+        *
+        * \note        In 5.0.x this is not a const pointer.
+        */
+       const lzma_allocator *allocator;
+
+       /** Internal state is not visible to applications. */
+       lzma_internal *internal;
+
+       /*
+        * Reserved space to allow possible future extensions without
+        * breaking the ABI. Excluding the initialization of this structure,
+        * you should not touch these, because the names of these variables
+        * may change.
+        */
+       void *reserved_ptr1;
+       void *reserved_ptr2;
+       void *reserved_ptr3;
+       void *reserved_ptr4;
+       uint64_t reserved_int1;
+       uint64_t reserved_int2;
+       size_t reserved_int3;
+       size_t reserved_int4;
+       lzma_reserved_enum reserved_enum1;
+       lzma_reserved_enum reserved_enum2;
+
+} lzma_stream;
+
+
+/**
+ * \brief       Initialization for lzma_stream
+ *
+ * When you declare an instance of lzma_stream, you can immediately
+ * initialize it so that initialization functions know that no memory
+ * has been allocated yet:
+ *
+ *     lzma_stream strm = LZMA_STREAM_INIT;
+ *
+ * If you need to initialize a dynamically allocated lzma_stream, you can use
+ * memset(strm_pointer, 0, sizeof(lzma_stream)). Strictly speaking, this
+ * violates the C standard since NULL may have different internal
+ * representation than zero, but it should be portable enough in practice.
+ * Anyway, for maximum portability, you can use something like this:
+ *
+ *     lzma_stream tmp = LZMA_STREAM_INIT;
+ *     *strm = tmp;
+ */
+#define LZMA_STREAM_INIT \
+       { NULL, 0, 0, NULL, 0, 0, NULL, NULL, \
+       NULL, NULL, NULL, NULL, 0, 0, 0, 0, \
+       LZMA_RESERVED_ENUM, LZMA_RESERVED_ENUM }
+
+
+/**
+ * \brief       Encode or decode data
+ *
+ * Once the lzma_stream has been successfully initialized (e.g. with
+ * lzma_stream_encoder()), the actual encoding or decoding is done
+ * using this function. The application has to update strm->next_in,
+ * strm->avail_in, strm->next_out, and strm->avail_out to pass input
+ * to and get output from liblzma.
+ *
+ * See the description of the coder-specific initialization function to find
+ * out what `action' values are supported by the coder.
+ */
+extern LZMA_API(lzma_ret) lzma_code(lzma_stream *strm, lzma_action action)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Free memory allocated for the coder data structures
+ *
+ * \param       strm    Pointer to lzma_stream that is at least initialized
+ *                      with LZMA_STREAM_INIT.
+ *
+ * After lzma_end(strm), strm->internal is guaranteed to be NULL. No other
+ * members of the lzma_stream structure are touched.
+ *
+ * \note        zlib indicates an error if application end()s unfinished
+ *              stream structure. liblzma doesn't do this, and assumes that
+ *              application knows what it is doing.
+ */
+extern LZMA_API(void) lzma_end(lzma_stream *strm) lzma_nothrow;
+
+
+/**
+ * \brief       Get progress information
+ *
+ * In single-threaded mode, applications can get progress information from
+ * strm->total_in and strm->total_out. In multi-threaded mode this is less
+ * useful because a significant amount of both input and output data gets
+ * buffered internally by liblzma. This makes total_in and total_out give
+ * misleading information and also makes the progress indicator updates
+ * non-smooth.
+ *
+ * This function gives realistic progress information also in multi-threaded
+ * mode by taking into account the progress made by each thread. In
+ * single-threaded mode *progress_in and *progress_out are set to
+ * strm->total_in and strm->total_out, respectively.
+ */
+extern LZMA_API(void) lzma_get_progress(lzma_stream *strm,
+               uint64_t *progress_in, uint64_t *progress_out) lzma_nothrow;
+
+
+/**
+ * \brief       Get the memory usage of decoder filter chain
+ *
+ * This function is currently supported only when *strm has been initialized
+ * with a function that takes a memlimit argument. With other functions, you
+ * should use e.g. lzma_raw_encoder_memusage() or lzma_raw_decoder_memusage()
+ * to estimate the memory requirements.
+ *
+ * This function is useful e.g. after LZMA_MEMLIMIT_ERROR to find out how big
+ * the memory usage limit should have been to decode the input. Note that
+ * this may give misleading information if decoding .xz Streams that have
+ * multiple Blocks, because each Block can have different memory requirements.
+ *
+ * \return      How much memory is currently allocated for the filter
+ *              decoders. If no filter chain is currently allocated,
+ *              some non-zero value is still returned, which is less than
+ *              or equal to what any filter chain would indicate as its
+ *              memory requirement.
+ *
+ *              If this function isn't supported by *strm or some other error
+ *              occurs, zero is returned.
+ */
+extern LZMA_API(uint64_t) lzma_memusage(const lzma_stream *strm)
+               lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Get the current memory usage limit
+ *
+ * This function is supported only when *strm has been initialized with
+ * a function that takes a memlimit argument.
+ *
+ * \return      On success, the current memory usage limit is returned
+ *              (always non-zero). On error, zero is returned.
+ */
+extern LZMA_API(uint64_t) lzma_memlimit_get(const lzma_stream *strm)
+               lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Set the memory usage limit
+ *
+ * This function is supported only when *strm has been initialized with
+ * a function that takes a memlimit argument.
+ *
+ * \return      - LZMA_OK: New memory usage limit successfully set.
+ *              - LZMA_MEMLIMIT_ERROR: The new limit is too small.
+ *                The limit was not changed.
+ *              - LZMA_PROG_ERROR: Invalid arguments, e.g. *strm doesn't
+ *                support memory usage limit or memlimit was zero.
+ */
+extern LZMA_API(lzma_ret) lzma_memlimit_set(
+               lzma_stream *strm, uint64_t memlimit) lzma_nothrow;
diff --git a/lzma/api/lzma/bcj.h b/lzma/api/lzma/bcj.h
new file mode 100644 (file)
index 0000000..8e37538
--- /dev/null
@@ -0,0 +1,90 @@
+/**
+ * \file        lzma/bcj.h
+ * \brief       Branch/Call/Jump conversion filters
+ */
+
+/*
+ * Author: Lasse Collin
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ *
+ * See ../lzma.h for information about liblzma as a whole.
+ */
+
+#ifndef LZMA_H_INTERNAL
+#      error Never include this file directly. Use <lzma.h> instead.
+#endif
+
+
+/* Filter IDs for lzma_filter.id */
+
+#define LZMA_FILTER_X86         LZMA_VLI_C(0x04)
+       /**<
+        * Filter for x86 binaries
+        */
+
+#define LZMA_FILTER_POWERPC     LZMA_VLI_C(0x05)
+       /**<
+        * Filter for Big endian PowerPC binaries
+        */
+
+#define LZMA_FILTER_IA64        LZMA_VLI_C(0x06)
+       /**<
+        * Filter for IA-64 (Itanium) binaries.
+        */
+
+#define LZMA_FILTER_ARM         LZMA_VLI_C(0x07)
+       /**<
+        * Filter for ARM binaries.
+        */
+
+#define LZMA_FILTER_ARMTHUMB    LZMA_VLI_C(0x08)
+       /**<
+        * Filter for ARM-Thumb binaries.
+        */
+
+#define LZMA_FILTER_SPARC       LZMA_VLI_C(0x09)
+       /**<
+        * Filter for SPARC binaries.
+        */
+
+
+/**
+ * \brief       Options for BCJ filters
+ *
+ * The BCJ filters never change the size of the data. Specifying options
+ * for them is optional: if pointer to options is NULL, default value is
+ * used. You probably never need to specify options to BCJ filters, so just
+ * set the options pointer to NULL and be happy.
+ *
+ * If options with non-default values have been specified when encoding,
+ * the same options must also be specified when decoding.
+ *
+ * \note        At the moment, none of the BCJ filters support
+ *              LZMA_SYNC_FLUSH. If LZMA_SYNC_FLUSH is specified,
+ *              LZMA_OPTIONS_ERROR will be returned. If there is need,
+ *              partial support for LZMA_SYNC_FLUSH can be added in future.
+ *              Partial means that flushing would be possible only at
+ *              offsets that are multiple of 2, 4, or 16 depending on
+ *              the filter, except x86 which cannot be made to support
+ *              LZMA_SYNC_FLUSH predictably.
+ */
+typedef struct {
+       /**
+        * \brief       Start offset for conversions
+        *
+        * This setting is useful only when the same filter is used
+        * _separately_ for multiple sections of the same executable file,
+        * and the sections contain cross-section branch/call/jump
+        * instructions. In that case it is beneficial to set the start
+        * offset of the non-first sections so that the relative addresses
+        * of the cross-section branch/call/jump instructions will use the
+        * same absolute addresses as in the first section.
+        *
+        * When the pointer to options is NULL, the default value (zero)
+        * is used.
+        */
+       uint32_t start_offset;
+
+} lzma_options_bcj;
diff --git a/lzma/api/lzma/block.h b/lzma/api/lzma/block.h
new file mode 100644 (file)
index 0000000..7bdcfd7
--- /dev/null
@@ -0,0 +1,581 @@
+/**
+ * \file        lzma/block.h
+ * \brief       .xz Block handling
+ */
+
+/*
+ * Author: Lasse Collin
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ *
+ * See ../lzma.h for information about liblzma as a whole.
+ */
+
+#ifndef LZMA_H_INTERNAL
+#      error Never include this file directly. Use <lzma.h> instead.
+#endif
+
+
+/**
+ * \brief       Options for the Block and Block Header encoders and decoders
+ *
+ * Different Block handling functions use different parts of this structure.
+ * Some read some members, other functions write, and some do both. Only the
+ * members listed for reading need to be initialized when the specified
+ * functions are called. The members marked for writing will be assigned
+ * new values at some point either by calling the given function or by
+ * later calls to lzma_code().
+ */
+typedef struct {
+       /**
+        * \brief       Block format version
+        *
+        * To prevent API and ABI breakages when new features are needed,
+        * a version number is used to indicate which fields in this
+        * structure are in use:
+        *   - liblzma >= 5.0.0: version = 0 is supported.
+        *   - liblzma >= 5.1.4beta: Support for version = 1 was added,
+        *     which adds the ignore_check field.
+        *
+        * If version is greater than one, most Block related functions
+        * will return LZMA_OPTIONS_ERROR (lzma_block_header_decode() works
+        * with any version value).
+        *
+        * Read by:
+        *  - All functions that take pointer to lzma_block as argument,
+        *    including lzma_block_header_decode().
+        *
+        * Written by:
+        *  - lzma_block_header_decode()
+        */
+       uint32_t version;
+
+       /**
+        * \brief       Size of the Block Header field
+        *
+        * This is always a multiple of four.
+        *
+        * Read by:
+        *  - lzma_block_header_encode()
+        *  - lzma_block_header_decode()
+        *  - lzma_block_compressed_size()
+        *  - lzma_block_unpadded_size()
+        *  - lzma_block_total_size()
+        *  - lzma_block_decoder()
+        *  - lzma_block_buffer_decode()
+        *
+        * Written by:
+        *  - lzma_block_header_size()
+        *  - lzma_block_buffer_encode()
+        */
+       uint32_t header_size;
+#      define LZMA_BLOCK_HEADER_SIZE_MIN 8
+#      define LZMA_BLOCK_HEADER_SIZE_MAX 1024
+
+       /**
+        * \brief       Type of integrity Check
+        *
+        * The Check ID is not stored into the Block Header, thus its value
+        * must be provided also when decoding.
+        *
+        * Read by:
+        *  - lzma_block_header_encode()
+        *  - lzma_block_header_decode()
+        *  - lzma_block_compressed_size()
+        *  - lzma_block_unpadded_size()
+        *  - lzma_block_total_size()
+        *  - lzma_block_encoder()
+        *  - lzma_block_decoder()
+        *  - lzma_block_buffer_encode()
+        *  - lzma_block_buffer_decode()
+        */
+       lzma_check check;
+
+       /**
+        * \brief       Size of the Compressed Data in bytes
+        *
+        * Encoding: If this is not LZMA_VLI_UNKNOWN, Block Header encoder
+        * will store this value to the Block Header. Block encoder doesn't
+        * care about this value, but will set it once the encoding has been
+        * finished.
+        *
+        * Decoding: If this is not LZMA_VLI_UNKNOWN, Block decoder will
+        * verify that the size of the Compressed Data field matches
+        * compressed_size.
+        *
+        * Usually you don't know this value when encoding in streamed mode,
+        * and thus cannot write this field into the Block Header.
+        *
+        * In non-streamed mode you can reserve space for this field before
+        * encoding the actual Block. After encoding the data, finish the
+        * Block by encoding the Block Header. Steps in detail:
+        *
+        *  - Set compressed_size to some big enough value. If you don't know
+        *    better, use LZMA_VLI_MAX, but remember that bigger values take
+        *    more space in Block Header.
+        *
+        *  - Call lzma_block_header_size() to see how much space you need to
+        *    reserve for the Block Header.
+        *
+        *  - Encode the Block using lzma_block_encoder() and lzma_code().
+        *    It sets compressed_size to the correct value.
+        *
+        *  - Use lzma_block_header_encode() to encode the Block Header.
+        *    Because space was reserved in the first step, you don't need
+        *    to call lzma_block_header_size() anymore, because due to
+        *    reserving, header_size has to be big enough. If it is "too big",
+        *    lzma_block_header_encode() will add enough Header Padding to
+        *    make Block Header to match the size specified by header_size.
+        *
+        * Read by:
+        *  - lzma_block_header_size()
+        *  - lzma_block_header_encode()
+        *  - lzma_block_compressed_size()
+        *  - lzma_block_unpadded_size()
+        *  - lzma_block_total_size()
+        *  - lzma_block_decoder()
+        *  - lzma_block_buffer_decode()
+        *
+        * Written by:
+        *  - lzma_block_header_decode()
+        *  - lzma_block_compressed_size()
+        *  - lzma_block_encoder()
+        *  - lzma_block_decoder()
+        *  - lzma_block_buffer_encode()
+        *  - lzma_block_buffer_decode()
+        */
+       lzma_vli compressed_size;
+
+       /**
+        * \brief       Uncompressed Size in bytes
+        *
+        * This is handled very similarly to compressed_size above.
+        *
+        * uncompressed_size is needed by fewer functions than
+        * compressed_size. This is because uncompressed_size isn't
+        * needed to validate that Block stays within proper limits.
+        *
+        * Read by:
+        *  - lzma_block_header_size()
+        *  - lzma_block_header_encode()
+        *  - lzma_block_decoder()
+        *  - lzma_block_buffer_decode()
+        *
+        * Written by:
+        *  - lzma_block_header_decode()
+        *  - lzma_block_encoder()
+        *  - lzma_block_decoder()
+        *  - lzma_block_buffer_encode()
+        *  - lzma_block_buffer_decode()
+        */
+       lzma_vli uncompressed_size;
+
+       /**
+        * \brief       Array of filters
+        *
+        * There can be 1-4 filters. The end of the array is marked with
+        * .id = LZMA_VLI_UNKNOWN.
+        *
+        * Read by:
+        *  - lzma_block_header_size()
+        *  - lzma_block_header_encode()
+        *  - lzma_block_encoder()
+        *  - lzma_block_decoder()
+        *  - lzma_block_buffer_encode()
+        *  - lzma_block_buffer_decode()
+        *
+        * Written by:
+        *  - lzma_block_header_decode(): Note that this does NOT free()
+        *    the old filter options structures. All unused filters[] will
+        *    have .id == LZMA_VLI_UNKNOWN and .options == NULL. If
+        *    decoding fails, all filters[] are guaranteed to be
+        *    LZMA_VLI_UNKNOWN and NULL.
+        *
+        * \note        Because of the array is terminated with
+        *              .id = LZMA_VLI_UNKNOWN, the actual array must
+        *              have LZMA_FILTERS_MAX + 1 members or the Block
+        *              Header decoder will overflow the buffer.
+        */
+       lzma_filter *filters;
+
+       /**
+        * \brief       Raw value stored in the Check field
+        *
+        * After successful coding, the first lzma_check_size(check) bytes
+        * of this array contain the raw value stored in the Check field.
+        *
+        * Note that CRC32 and CRC64 are stored in little endian byte order.
+        * Take it into account if you display the Check values to the user.
+        *
+        * Written by:
+        *  - lzma_block_encoder()
+        *  - lzma_block_decoder()
+        *  - lzma_block_buffer_encode()
+        *  - lzma_block_buffer_decode()
+        */
+       uint8_t raw_check[LZMA_CHECK_SIZE_MAX];
+
+       /*
+        * Reserved space to allow possible future extensions without
+        * breaking the ABI. 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.
+        */
+       void *reserved_ptr1;
+       void *reserved_ptr2;
+       void *reserved_ptr3;
+       uint32_t reserved_int1;
+       uint32_t reserved_int2;
+       lzma_vli reserved_int3;
+       lzma_vli reserved_int4;
+       lzma_vli reserved_int5;
+       lzma_vli reserved_int6;
+       lzma_vli reserved_int7;
+       lzma_vli reserved_int8;
+       lzma_reserved_enum reserved_enum1;
+       lzma_reserved_enum reserved_enum2;
+       lzma_reserved_enum reserved_enum3;
+       lzma_reserved_enum reserved_enum4;
+
+       /**
+        * \brief       A flag to Block decoder to not verify the Check field
+        *
+        * This field is supported by liblzma >= 5.1.4beta if .version >= 1.
+        *
+        * If this is set to true, the integrity check won't be calculated
+        * and verified. Unless you know what you are doing, you should
+        * leave this to false. (A reason to set this to true is when the
+        * file integrity is verified externally anyway and you want to
+        * speed up the decompression, which matters mostly when using
+        * SHA-256 as the integrity check.)
+        *
+        * If .version >= 1, read by:
+        *   - lzma_block_decoder()
+        *   - lzma_block_buffer_decode()
+        *
+        * Written by (.version is ignored):
+        *   - lzma_block_header_decode() always sets this to false
+        */
+       lzma_bool ignore_check;
+
+       lzma_bool reserved_bool2;
+       lzma_bool reserved_bool3;
+       lzma_bool reserved_bool4;
+       lzma_bool reserved_bool5;
+       lzma_bool reserved_bool6;
+       lzma_bool reserved_bool7;
+       lzma_bool reserved_bool8;
+
+} lzma_block;
+
+
+/**
+ * \brief       Decode the Block Header Size field
+ *
+ * To decode Block Header using lzma_block_header_decode(), the size of the
+ * Block Header has to be known and stored into lzma_block.header_size.
+ * The size can be calculated from the first byte of a Block using this macro.
+ * Note that if the first byte is 0x00, it indicates beginning of Index; use
+ * this macro only when the byte is not 0x00.
+ *
+ * There is no encoding macro, because Block Header encoder is enough for that.
+ */
+#define lzma_block_header_size_decode(b) (((uint32_t)(b) + 1) * 4)
+
+
+/**
+ * \brief       Calculate Block Header Size
+ *
+ * Calculate the minimum size needed for the Block Header field using the
+ * settings specified in the lzma_block structure. Note that it is OK to
+ * increase the calculated header_size value as long as it is a multiple of
+ * four and doesn't exceed LZMA_BLOCK_HEADER_SIZE_MAX. Increasing header_size
+ * just means that lzma_block_header_encode() will add Header Padding.
+ *
+ * \return      - LZMA_OK: Size calculated successfully and stored to
+ *                block->header_size.
+ *              - LZMA_OPTIONS_ERROR: Unsupported version, filters or
+ *                filter options.
+ *              - LZMA_PROG_ERROR: Invalid values like compressed_size == 0.
+ *
+ * \note        This doesn't check that all the options are valid i.e. this
+ *              may return LZMA_OK even if lzma_block_header_encode() or
+ *              lzma_block_encoder() would fail. If you want to validate the
+ *              filter chain, consider using lzma_memlimit_encoder() which as
+ *              a side-effect validates the filter chain.
+ */
+extern LZMA_API(lzma_ret) lzma_block_header_size(lzma_block *block)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Encode Block Header
+ *
+ * The caller must have calculated the size of the Block Header already with
+ * lzma_block_header_size(). If a value larger than the one calculated by
+ * lzma_block_header_size() is used, the Block Header will be padded to the
+ * specified size.
+ *
+ * \param       out         Beginning of the output buffer. This must be
+ *                          at least block->header_size bytes.
+ * \param       block       Block options to be encoded.
+ *
+ * \return      - LZMA_OK: Encoding was successful. block->header_size
+ *                bytes were written to output buffer.
+ *              - LZMA_OPTIONS_ERROR: Invalid or unsupported options.
+ *              - LZMA_PROG_ERROR: Invalid arguments, for example
+ *                block->header_size is invalid or block->filters is NULL.
+ */
+extern LZMA_API(lzma_ret) lzma_block_header_encode(
+               const lzma_block *block, uint8_t *out)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Decode Block Header
+ *
+ * block->version should (usually) be set to the highest value supported
+ * by the application. If the application sets block->version to a value
+ * higher than supported by the current liblzma version, this function will
+ * downgrade block->version to the highest value supported by it. Thus one
+ * should check the value of block->version after calling this function if
+ * block->version was set to a non-zero value and the application doesn't
+ * otherwise know that the liblzma version being used is new enough to
+ * support the specified block->version.
+ *
+ * The size of the Block Header must have already been decoded with
+ * lzma_block_header_size_decode() macro and stored to block->header_size.
+ *
+ * The integrity check type from Stream Header must have been stored
+ * to block->check.
+ *
+ * block->filters must have been allocated, but they don't need to be
+ * initialized (possible existing filter options are not freed).
+ *
+ * \param       block       Destination for Block options.
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() (and also free()
+ *                          if an error occurs).
+ * \param       in          Beginning of the input buffer. This must be
+ *                          at least block->header_size bytes.
+ *
+ * \return      - LZMA_OK: Decoding was successful. block->header_size
+ *                bytes were read from the input buffer.
+ *              - LZMA_OPTIONS_ERROR: The Block Header specifies some
+ *                unsupported options such as unsupported filters. This can
+ *                happen also if block->version was set to a too low value
+ *                compared to what would be required to properly represent
+ *                the information stored in the Block Header.
+ *              - LZMA_DATA_ERROR: Block Header is corrupt, for example,
+ *                the CRC32 doesn't match.
+ *              - LZMA_PROG_ERROR: Invalid arguments, for example
+ *                block->header_size is invalid or block->filters is NULL.
+ */
+extern LZMA_API(lzma_ret) lzma_block_header_decode(lzma_block *block,
+               const lzma_allocator *allocator, const uint8_t *in)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Validate and set Compressed Size according to Unpadded Size
+ *
+ * Block Header stores Compressed Size, but Index has Unpadded Size. If the
+ * application has already parsed the Index and is now decoding Blocks,
+ * it can calculate Compressed Size from Unpadded Size. This function does
+ * exactly that with error checking:
+ *
+ *  - Compressed Size calculated from Unpadded Size must be positive integer,
+ *    that is, Unpadded Size must be big enough that after Block Header and
+ *    Check fields there's still at least one byte for Compressed Size.
+ *
+ *  - If Compressed Size was present in Block Header, the new value
+ *    calculated from Unpadded Size is compared against the value
+ *    from Block Header.
+ *
+ * \note        This function must be called _after_ decoding the Block Header
+ *              field so that it can properly validate Compressed Size if it
+ *              was present in Block Header.
+ *
+ * \return      - LZMA_OK: block->compressed_size was set successfully.
+ *              - LZMA_DATA_ERROR: unpadded_size is too small compared to
+ *                block->header_size and lzma_check_size(block->check).
+ *              - LZMA_PROG_ERROR: Some values are invalid. For example,
+ *                block->header_size must be a multiple of four and
+ *                between 8 and 1024 inclusive.
+ */
+extern LZMA_API(lzma_ret) lzma_block_compressed_size(
+               lzma_block *block, lzma_vli unpadded_size)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Calculate Unpadded Size
+ *
+ * The Index field stores Unpadded Size and Uncompressed Size. The latter
+ * can be taken directly from the lzma_block structure after coding a Block,
+ * but Unpadded Size needs to be calculated from Block Header Size,
+ * Compressed Size, and size of the Check field. This is where this function
+ * is needed.
+ *
+ * \return      Unpadded Size on success, or zero on error.
+ */
+extern LZMA_API(lzma_vli) lzma_block_unpadded_size(const lzma_block *block)
+               lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Calculate the total encoded size of a Block
+ *
+ * This is equivalent to lzma_block_unpadded_size() except that the returned
+ * value includes the size of the Block Padding field.
+ *
+ * \return      On success, total encoded size of the Block. On error,
+ *              zero is returned.
+ */
+extern LZMA_API(lzma_vli) lzma_block_total_size(const lzma_block *block)
+               lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Initialize .xz Block encoder
+ *
+ * Valid actions for lzma_code() are LZMA_RUN, LZMA_SYNC_FLUSH (only if the
+ * filter chain supports it), and LZMA_FINISH.
+ *
+ * \return      - LZMA_OK: All good, continue with lzma_code().
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_UNSUPPORTED_CHECK: block->check specifies a Check ID
+ *                that is not supported by this buid of liblzma. Initializing
+ *                the encoder failed.
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_block_encoder(
+               lzma_stream *strm, lzma_block *block)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Initialize .xz Block decoder
+ *
+ * Valid actions for lzma_code() are LZMA_RUN and LZMA_FINISH. Using
+ * LZMA_FINISH is not required. It is supported only for convenience.
+ *
+ * \return      - LZMA_OK: All good, continue with lzma_code().
+ *              - LZMA_UNSUPPORTED_CHECK: Initialization was successful, but
+ *                the given Check ID is not supported, thus Check will be
+ *                ignored.
+ *              - LZMA_PROG_ERROR
+ *              - LZMA_MEM_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_block_decoder(
+               lzma_stream *strm, lzma_block *block)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Calculate maximum output size for single-call Block encoding
+ *
+ * This is equivalent to lzma_stream_buffer_bound() but for .xz Blocks.
+ * See the documentation of lzma_stream_buffer_bound().
+ */
+extern LZMA_API(size_t) lzma_block_buffer_bound(size_t uncompressed_size)
+               lzma_nothrow;
+
+
+/**
+ * \brief       Single-call .xz Block encoder
+ *
+ * In contrast to the multi-call encoder initialized with
+ * lzma_block_encoder(), this function encodes also the Block Header. This
+ * is required to make it possible to write appropriate Block Header also
+ * in case the data isn't compressible, and different filter chain has to be
+ * used to encode the data in uncompressed form using uncompressed chunks
+ * of the LZMA2 filter.
+ *
+ * When the data isn't compressible, header_size, compressed_size, and
+ * uncompressed_size are set just like when the data was compressible, but
+ * it is possible that header_size is too small to hold the filter chain
+ * specified in block->filters, because that isn't necessarily the filter
+ * chain that was actually used to encode the data. lzma_block_unpadded_size()
+ * still works normally, because it doesn't read the filters array.
+ *
+ * \param       block       Block options: block->version, block->check,
+ *                          and block->filters must have been initialized.
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
+ * \param       in          Beginning of the input buffer
+ * \param       in_size     Size of the input buffer
+ * \param       out         Beginning of the output buffer
+ * \param       out_pos     The next byte will be written to out[*out_pos].
+ *                          *out_pos is updated only if encoding succeeds.
+ * \param       out_size    Size of the out buffer; the first byte into
+ *                          which no data is written to is out[out_size].
+ *
+ * \return      - LZMA_OK: Encoding was successful.
+ *              - LZMA_BUF_ERROR: Not enough output buffer space.
+ *              - LZMA_UNSUPPORTED_CHECK
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_DATA_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_block_buffer_encode(
+               lzma_block *block, const lzma_allocator *allocator,
+               const uint8_t *in, size_t in_size,
+               uint8_t *out, size_t *out_pos, size_t out_size)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Single-call uncompressed .xz Block encoder
+ *
+ * This is like lzma_block_buffer_encode() except this doesn't try to
+ * compress the data and instead encodes the data using LZMA2 uncompressed
+ * chunks. The required output buffer size can be determined with
+ * lzma_block_buffer_bound().
+ *
+ * Since the data won't be compressed, this function ignores block->filters.
+ * This function doesn't take lzma_allocator because this function doesn't
+ * allocate any memory from the heap.
+ */
+extern LZMA_API(lzma_ret) lzma_block_uncomp_encode(lzma_block *block,
+               const uint8_t *in, size_t in_size,
+               uint8_t *out, size_t *out_pos, size_t out_size)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Single-call .xz Block decoder
+ *
+ * This is single-call equivalent of lzma_block_decoder(), and requires that
+ * the caller has already decoded Block Header and checked its memory usage.
+ *
+ * \param       block       Block options just like with lzma_block_decoder().
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
+ * \param       in          Beginning of the input buffer
+ * \param       in_pos      The next byte will be read from in[*in_pos].
+ *                          *in_pos is updated only if decoding succeeds.
+ * \param       in_size     Size of the input buffer; the first byte that
+ *                          won't be read is in[in_size].
+ * \param       out         Beginning of the output buffer
+ * \param       out_pos     The next byte will be written to out[*out_pos].
+ *                          *out_pos is updated only if encoding succeeds.
+ * \param       out_size    Size of the out buffer; the first byte into
+ *                          which no data is written to is out[out_size].
+ *
+ * \return      - LZMA_OK: Decoding was successful.
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_DATA_ERROR
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_BUF_ERROR: Output buffer was too small.
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_block_buffer_decode(
+               lzma_block *block, const lzma_allocator *allocator,
+               const uint8_t *in, size_t *in_pos, size_t in_size,
+               uint8_t *out, size_t *out_pos, size_t out_size)
+               lzma_nothrow;
diff --git a/lzma/api/lzma/check.h b/lzma/api/lzma/check.h
new file mode 100644 (file)
index 0000000..6a243db
--- /dev/null
@@ -0,0 +1,150 @@
+/**
+ * \file        lzma/check.h
+ * \brief       Integrity checks
+ */
+
+/*
+ * Author: Lasse Collin
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ *
+ * See ../lzma.h for information about liblzma as a whole.
+ */
+
+#ifndef LZMA_H_INTERNAL
+#      error Never include this file directly. Use <lzma.h> instead.
+#endif
+
+
+/**
+ * \brief       Type of the integrity check (Check ID)
+ *
+ * The .xz format supports multiple types of checks that are calculated
+ * from the uncompressed data. They vary in both speed and ability to
+ * detect errors.
+ */
+typedef enum {
+       LZMA_CHECK_NONE     = 0,
+               /**<
+                * No Check is calculated.
+                *
+                * Size of the Check field: 0 bytes
+                */
+
+       LZMA_CHECK_CRC32    = 1,
+               /**<
+                * CRC32 using the polynomial from the IEEE 802.3 standard
+                *
+                * Size of the Check field: 4 bytes
+                */
+
+       LZMA_CHECK_CRC64    = 4,
+               /**<
+                * CRC64 using the polynomial from the ECMA-182 standard
+                *
+                * Size of the Check field: 8 bytes
+                */
+
+       LZMA_CHECK_SHA256   = 10
+               /**<
+                * SHA-256
+                *
+                * Size of the Check field: 32 bytes
+                */
+} lzma_check;
+
+
+/**
+ * \brief       Maximum valid Check ID
+ *
+ * The .xz file format specification specifies 16 Check IDs (0-15). Some
+ * of them are only reserved, that is, no actual Check algorithm has been
+ * assigned. When decoding, liblzma still accepts unknown Check IDs for
+ * future compatibility. If a valid but unsupported Check ID is detected,
+ * liblzma can indicate a warning; see the flags LZMA_TELL_NO_CHECK,
+ * LZMA_TELL_UNSUPPORTED_CHECK, and LZMA_TELL_ANY_CHECK in container.h.
+ */
+#define LZMA_CHECK_ID_MAX 15
+
+
+/**
+ * \brief       Test if the given Check ID is supported
+ *
+ * Return 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.
+ *
+ * You can assume that LZMA_CHECK_NONE and LZMA_CHECK_CRC32 are always
+ * supported (even if liblzma is built with limited features).
+ */
+extern LZMA_API(lzma_bool) lzma_check_is_supported(lzma_check check)
+               lzma_nothrow lzma_attr_const;
+
+
+/**
+ * \brief       Get the size of the Check field with the 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:
+ * { 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 LZMA_API(uint32_t) lzma_check_size(lzma_check check)
+               lzma_nothrow lzma_attr_const;
+
+
+/**
+ * \brief       Maximum size of a Check field
+ */
+#define LZMA_CHECK_SIZE_MAX 64
+
+
+/**
+ * \brief       Calculate CRC32
+ *
+ * Calculate CRC32 using the polynomial from the IEEE 802.3 standard.
+ *
+ * \param       buf     Pointer to the input buffer
+ * \param       size    Size of the input buffer
+ * \param       crc     Previously returned CRC value. This is used to
+ *                      calculate the CRC of a big buffer in smaller chunks.
+ *                      Set to zero when starting a new calculation.
+ *
+ * \return      Updated CRC value, which can be passed to this function
+ *              again to continue CRC calculation.
+ */
+extern LZMA_API(uint32_t) lzma_crc32(
+               const uint8_t *buf, size_t size, uint32_t crc)
+               lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Calculate CRC64
+ *
+ * Calculate CRC64 using the polynomial from the ECMA-182 standard.
+ *
+ * This function is used similarly to lzma_crc32(). See its documentation.
+ */
+extern LZMA_API(uint64_t) lzma_crc64(
+               const uint8_t *buf, size_t size, uint64_t crc)
+               lzma_nothrow lzma_attr_pure;
+
+
+/*
+ * SHA-256 functions are currently not exported to public API.
+ * Contact Lasse Collin if you think it should be.
+ */
+
+
+/**
+ * \brief       Get the type of the integrity check
+ *
+ * This function can be called only immediately after lzma_code() has
+ * returned LZMA_NO_CHECK, LZMA_UNSUPPORTED_CHECK, or LZMA_GET_CHECK.
+ * Calling this function in any other situation has undefined behavior.
+ */
+extern LZMA_API(lzma_check) lzma_get_check(const lzma_stream *strm)
+               lzma_nothrow;
diff --git a/lzma/api/lzma/container.h b/lzma/api/lzma/container.h
new file mode 100644 (file)
index 0000000..86991ad
--- /dev/null
@@ -0,0 +1,619 @@
+/**
+ * \file        lzma/container.h
+ * \brief       File formats
+ */
+
+/*
+ * Author: Lasse Collin
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ *
+ * See ../lzma.h for information about liblzma as a whole.
+ */
+
+#ifndef LZMA_H_INTERNAL
+#      error Never include this file directly. Use <lzma.h> instead.
+#endif
+
+
+/************
+ * Encoding *
+ ************/
+
+/**
+ * \brief       Default compression preset
+ *
+ * It's not straightforward to recommend a default preset, because in some
+ * cases keeping the resource usage relatively low is more important that
+ * getting the maximum compression ratio.
+ */
+#define LZMA_PRESET_DEFAULT     UINT32_C(6)
+
+
+/**
+ * \brief       Mask for preset level
+ *
+ * This is useful only if you need to extract the level from the preset
+ * variable. That should be rare.
+ */
+#define LZMA_PRESET_LEVEL_MASK  UINT32_C(0x1F)
+
+
+/*
+ * Preset flags
+ *
+ * Currently only one flag is defined.
+ */
+
+/**
+ * \brief       Extreme compression preset
+ *
+ * This flag modifies the preset to make the encoding significantly slower
+ * while improving the compression ratio only marginally. This is useful
+ * when you don't mind wasting time to get as small result as possible.
+ *
+ * This flag doesn't affect the memory usage requirements of the decoder (at
+ * least not significantly). The memory usage of the encoder may be increased
+ * a little but only at the lowest preset levels (0-3).
+ */
+#define LZMA_PRESET_EXTREME       (UINT32_C(1) << 31)
+
+
+/**
+ * \brief       Multithreading options
+ */
+typedef struct {
+       /**
+        * \brief       Flags
+        *
+        * Set this to zero if no flags are wanted.
+        *
+        * No flags are currently supported.
+        */
+       uint32_t flags;
+
+       /**
+        * \brief       Number of worker threads to use
+        */
+       uint32_t threads;
+
+       /**
+        * \brief       Maximum uncompressed size of a Block
+        *
+        * The encoder will start a new .xz Block every block_size bytes.
+        * Using LZMA_FULL_FLUSH or LZMA_FULL_BARRIER with lzma_code()
+        * the caller may tell liblzma to start a new Block earlier.
+        *
+        * With LZMA2, a recommended block size is 2-4 times the LZMA2
+        * dictionary size. With very small dictionaries, it is recommended
+        * to use at least 1 MiB block size for good compression ratio, even
+        * if this is more than four times the dictionary size. Note that
+        * these are only recommendations for typical use cases; feel free
+        * to use other values. Just keep in mind that using a block size
+        * less than the LZMA2 dictionary size is waste of RAM.
+        *
+        * Set this to 0 to let liblzma choose the block size depending
+        * on the compression options. For LZMA2 it will be 3*dict_size
+        * or 1 MiB, whichever is more.
+        *
+        * For each thread, about 3 * block_size bytes of memory will be
+        * allocated. This may change in later liblzma versions. If so,
+        * the memory usage will probably be reduced, not increased.
+        */
+       uint64_t block_size;
+
+       /**
+        * \brief       Timeout to allow lzma_code() to return early
+        *
+        * Multithreading can make liblzma to consume input and produce
+        * output in a very bursty way: it may first read a lot of input
+        * to fill internal buffers, then no input or output occurs for
+        * a while.
+        *
+        * In single-threaded mode, lzma_code() won't return until it has
+        * either consumed all the input or filled the output buffer. If
+        * this is done in multithreaded mode, it may cause a call
+        * lzma_code() to take even tens of seconds, which isn't acceptable
+        * in all applications.
+        *
+        * To avoid very long blocking times in lzma_code(), a timeout
+        * (in milliseconds) may be set here. If lzma_code() would block
+        * longer than this number of milliseconds, it will return with
+        * LZMA_OK. Reasonable values are 100 ms or more. The xz command
+        * line tool uses 300 ms.
+        *
+        * If long blocking times are fine for you, set timeout to a special
+        * value of 0, which will disable the timeout mechanism and will make
+        * lzma_code() block until all the input is consumed or the output
+        * buffer has been filled.
+        *
+        * \note        Even with a timeout, lzma_code() might sometimes take
+        *              somewhat long time to return. No timing guarantees
+        *              are made.
+        */
+       uint32_t timeout;
+
+       /**
+        * \brief       Compression preset (level and possible flags)
+        *
+        * The preset is set just like with lzma_easy_encoder().
+        * The preset is ignored if filters below is non-NULL.
+        */
+       uint32_t preset;
+
+       /**
+        * \brief       Filter chain (alternative to a preset)
+        *
+        * If this is NULL, the preset above is used. Otherwise the preset
+        * is ignored and the filter chain specified here is used.
+        */
+       const lzma_filter *filters;
+
+       /**
+        * \brief       Integrity check type
+        *
+        * See check.h for available checks. The xz command line tool
+        * defaults to LZMA_CHECK_CRC64, which is a good choice if you
+        * are unsure.
+        */
+       lzma_check check;
+
+       /*
+        * Reserved space to allow possible future extensions without
+        * breaking the ABI. 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.
+        */
+       lzma_reserved_enum reserved_enum1;
+       lzma_reserved_enum reserved_enum2;
+       lzma_reserved_enum reserved_enum3;
+       uint32_t reserved_int1;
+       uint32_t reserved_int2;
+       uint32_t reserved_int3;
+       uint32_t reserved_int4;
+       uint64_t reserved_int5;
+       uint64_t reserved_int6;
+       uint64_t reserved_int7;
+       uint64_t reserved_int8;
+       void *reserved_ptr1;
+       void *reserved_ptr2;
+       void *reserved_ptr3;
+       void *reserved_ptr4;
+
+} lzma_mt;
+
+
+/**
+ * \brief       Calculate approximate memory usage of easy encoder
+ *
+ * This function is a wrapper for lzma_raw_encoder_memusage().
+ *
+ * \param       preset  Compression preset (level and possible flags)
+ *
+ * \return      Number of bytes of memory required for the given
+ *              preset when encoding. If an error occurs, for example
+ *              due to unsupported preset, UINT64_MAX is returned.
+ */
+extern LZMA_API(uint64_t) lzma_easy_encoder_memusage(uint32_t preset)
+               lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Calculate approximate decoder memory usage of a preset
+ *
+ * This function is a wrapper for lzma_raw_decoder_memusage().
+ *
+ * \param       preset  Compression preset (level and possible flags)
+ *
+ * \return      Number of bytes of memory required to decompress a file
+ *              that was compressed using the given preset. If an error
+ *              occurs, for example due to unsupported preset, UINT64_MAX
+ *              is returned.
+ */
+extern LZMA_API(uint64_t) lzma_easy_decoder_memusage(uint32_t preset)
+               lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Initialize .xz Stream encoder using a preset number
+ *
+ * This function is intended for those who just want to use the basic features
+ * if liblzma (that is, most developers out there).
+ *
+ * \param       strm    Pointer to lzma_stream that is at least initialized
+ *                      with LZMA_STREAM_INIT.
+ * \param       preset  Compression preset to use. A preset consist of level
+ *                      number and zero or more flags. Usually flags aren't
+ *                      used, so preset is simply a number [0, 9] which match
+ *                      the options -0 ... -9 of the xz command line tool.
+ *                      Additional flags can be be set using bitwise-or with
+ *                      the preset level number, e.g. 6 | LZMA_PRESET_EXTREME.
+ * \param       check   Integrity check type to use. See check.h for available
+ *                      checks. The xz command line tool defaults to
+ *                      LZMA_CHECK_CRC64, which is a good choice if you are
+ *                      unsure. LZMA_CHECK_CRC32 is good too as long as the
+ *                      uncompressed file is not many gigabytes.
+ *
+ * \return      - LZMA_OK: Initialization succeeded. Use lzma_code() to
+ *                encode your data.
+ *              - LZMA_MEM_ERROR: Memory allocation failed.
+ *              - LZMA_OPTIONS_ERROR: The given compression preset is not
+ *                supported by this build of liblzma.
+ *              - LZMA_UNSUPPORTED_CHECK: The given check type is not
+ *                supported by this liblzma build.
+ *              - LZMA_PROG_ERROR: One or more of the parameters have values
+ *                that will never be valid. For example, strm == NULL.
+ *
+ * If initialization fails (return value is not LZMA_OK), all the memory
+ * allocated for *strm by liblzma is always freed. Thus, there is no need
+ * to call lzma_end() after failed initialization.
+ *
+ * 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 or flags that don't support LZMA_SYNC_FLUSH.
+ */
+extern LZMA_API(lzma_ret) lzma_easy_encoder(
+               lzma_stream *strm, uint32_t preset, lzma_check check)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Single-call .xz Stream encoding using a preset number
+ *
+ * The maximum required output buffer size can be calculated with
+ * lzma_stream_buffer_bound().
+ *
+ * \param       preset      Compression preset to use. See the description
+ *                          in lzma_easy_encoder().
+ * \param       check       Type of the integrity check to calculate from
+ *                          uncompressed data.
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
+ * \param       in          Beginning of the input buffer
+ * \param       in_size     Size of the input buffer
+ * \param       out         Beginning of the output buffer
+ * \param       out_pos     The next byte will be written to out[*out_pos].
+ *                          *out_pos is updated only if encoding succeeds.
+ * \param       out_size    Size of the out buffer; the first byte into
+ *                          which no data is written to is out[out_size].
+ *
+ * \return      - LZMA_OK: Encoding was successful.
+ *              - LZMA_BUF_ERROR: Not enough output buffer space.
+ *              - LZMA_UNSUPPORTED_CHECK
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_DATA_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_easy_buffer_encode(
+               uint32_t preset, lzma_check check,
+               const lzma_allocator *allocator,
+               const uint8_t *in, size_t in_size,
+               uint8_t *out, size_t *out_pos, size_t out_size) lzma_nothrow;
+
+
+/**
+ * \brief       Initialize .xz Stream encoder using a custom filter chain
+ *
+ * \param       strm    Pointer to properly prepared lzma_stream
+ * \param       filters Array of filters. This must be terminated with
+ *                      filters[n].id = LZMA_VLI_UNKNOWN. See filter.h for
+ *                      more information.
+ * \param       check   Type of the integrity check to calculate from
+ *                      uncompressed data.
+ *
+ * \return      - LZMA_OK: Initialization was successful.
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_UNSUPPORTED_CHECK
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_stream_encoder(lzma_stream *strm,
+               const lzma_filter *filters, lzma_check check)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Calculate approximate memory usage of multithreaded .xz encoder
+ *
+ * Since doing the encoding in threaded mode doesn't affect the memory
+ * requirements of single-threaded decompressor, you can use
+ * lzma_easy_decoder_memusage(options->preset) or
+ * lzma_raw_decoder_memusage(options->filters) to calculate
+ * the decompressor memory requirements.
+ *
+ * \param       options Compression options
+ *
+ * \return      Number of bytes of memory required for encoding with the
+ *              given options. If an error occurs, for example due to
+ *              unsupported preset or filter chain, UINT64_MAX is returned.
+ */
+extern LZMA_API(uint64_t) lzma_stream_encoder_mt_memusage(
+               const lzma_mt *options) lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Initialize multithreaded .xz Stream encoder
+ *
+ * This provides the functionality of lzma_easy_encoder() and
+ * lzma_stream_encoder() as a single function for multithreaded use.
+ *
+ * The supported actions for lzma_code() are LZMA_RUN, LZMA_FULL_FLUSH,
+ * LZMA_FULL_BARRIER, and LZMA_FINISH. Support for LZMA_SYNC_FLUSH might be
+ * added in the future.
+ *
+ * \param       strm    Pointer to properly prepared lzma_stream
+ * \param       options Pointer to multithreaded compression options
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_UNSUPPORTED_CHECK
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_stream_encoder_mt(
+               lzma_stream *strm, const lzma_mt *options)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Initialize .lzma encoder (legacy file format)
+ *
+ * The .lzma format is sometimes called the LZMA_Alone format, which is the
+ * reason for the name of this function. The .lzma format supports only the
+ * LZMA1 filter. There is no support for integrity checks like CRC32.
+ *
+ * Use this function if and only if you need to create files readable by
+ * legacy LZMA tools such as LZMA Utils 4.32.x. Moving to the .xz format
+ * is strongly recommended.
+ *
+ * The valid action values for lzma_code() are LZMA_RUN and LZMA_FINISH.
+ * No kind of flushing is supported, because the file format doesn't make
+ * it possible.
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_alone_encoder(
+               lzma_stream *strm, const lzma_options_lzma *options)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Calculate output buffer size for single-call Stream encoder
+ *
+ * When trying to compress uncompressible data, the encoded size will be
+ * slightly bigger than the input data. This function calculates how much
+ * output buffer space is required to be sure that lzma_stream_buffer_encode()
+ * doesn't return LZMA_BUF_ERROR.
+ *
+ * The calculated value is not exact, but it is guaranteed to be big enough.
+ * The actual maximum output space required may be slightly smaller (up to
+ * about 100 bytes). This should not be a problem in practice.
+ *
+ * If the calculated maximum size doesn't fit into size_t or would make the
+ * Stream grow past LZMA_VLI_MAX (which should never happen in practice),
+ * zero is returned to indicate the error.
+ *
+ * \note        The limit calculated by this function applies only to
+ *              single-call encoding. Multi-call encoding may (and probably
+ *              will) have larger maximum expansion when encoding
+ *              uncompressible data. Currently there is no function to
+ *              calculate the maximum expansion of multi-call encoding.
+ */
+extern LZMA_API(size_t) lzma_stream_buffer_bound(size_t uncompressed_size)
+               lzma_nothrow;
+
+
+/**
+ * \brief       Single-call .xz Stream encoder
+ *
+ * \param       filters     Array of filters. This must be terminated with
+ *                          filters[n].id = LZMA_VLI_UNKNOWN. See filter.h
+ *                          for more information.
+ * \param       check       Type of the integrity check to calculate from
+ *                          uncompressed data.
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
+ * \param       in          Beginning of the input buffer
+ * \param       in_size     Size of the input buffer
+ * \param       out         Beginning of the output buffer
+ * \param       out_pos     The next byte will be written to out[*out_pos].
+ *                          *out_pos is updated only if encoding succeeds.
+ * \param       out_size    Size of the out buffer; the first byte into
+ *                          which no data is written to is out[out_size].
+ *
+ * \return      - LZMA_OK: Encoding was successful.
+ *              - LZMA_BUF_ERROR: Not enough output buffer space.
+ *              - LZMA_UNSUPPORTED_CHECK
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_DATA_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_stream_buffer_encode(
+               lzma_filter *filters, lzma_check check,
+               const lzma_allocator *allocator,
+               const uint8_t *in, size_t in_size,
+               uint8_t *out, size_t *out_pos, size_t out_size)
+               lzma_nothrow 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 files will trigger LZMA_NO_CHECK
+ * if LZMA_TELL_NO_CHECK is used.
+ */
+#define LZMA_TELL_NO_CHECK              UINT32_C(0x01)
+
+
+/**
+ * This flag makes lzma_code() return LZMA_UNSUPPORTED_CHECK if the input
+ * stream has an integrity check, but the type of the integrity check is not
+ * supported by this liblzma version or build. Such files can still be
+ * decoded, but the integrity check cannot be verified.
+ */
+#define LZMA_TELL_UNSUPPORTED_CHECK     UINT32_C(0x02)
+
+
+/**
+ * This flag makes lzma_code() return LZMA_GET_CHECK as soon as the type
+ * of the integrity check is known. The type can then be got with
+ * lzma_get_check().
+ */
+#define LZMA_TELL_ANY_CHECK             UINT32_C(0x04)
+
+
+/**
+ * This flag makes lzma_code() not calculate and verify the integrity check
+ * of the compressed data in .xz files. This means that invalid integrity
+ * check values won't be detected and LZMA_DATA_ERROR won't be returned in
+ * such cases.
+ *
+ * This flag only affects the checks of the compressed data itself; the CRC32
+ * values in the .xz headers will still be verified normally.
+ *
+ * Don't use this flag unless you know what you are doing. Possible reasons
+ * to use this flag:
+ *
+ *   - Trying to recover data from a corrupt .xz file.
+ *
+ *   - Speeding up decompression, which matters mostly with SHA-256
+ *     or with files that have compressed extremely well. It's recommended
+ *     to not use this flag for this purpose unless the file integrity is
+ *     verified externally in some other way.
+ *
+ * Support for this flag was added in liblzma 5.1.4beta.
+ */
+#define LZMA_IGNORE_CHECK               UINT32_C(0x10)
+
+
+/**
+ * This flag enables decoding of concatenated files with file formats that
+ * allow concatenating compressed files as is. From the formats currently
+ * supported by liblzma, only the .xz format allows concatenated files.
+ * Concatenated files are not allowed with the legacy .lzma format.
+ *
+ * This flag also affects the usage of the `action' argument for lzma_code().
+ * When LZMA_CONCATENATED is used, lzma_code() won't return LZMA_STREAM_END
+ * unless LZMA_FINISH is used as `action'. Thus, the application has to set
+ * LZMA_FINISH in the same way as it does when encoding.
+ *
+ * If LZMA_CONCATENATED is not used, the decoders still accept LZMA_FINISH
+ * as `action' for lzma_code(), but the usage of LZMA_FINISH isn't required.
+ */
+#define LZMA_CONCATENATED               UINT32_C(0x08)
+
+
+/**
+ * \brief       Initialize .xz Stream decoder
+ *
+ * \param       strm        Pointer to properly prepared lzma_stream
+ * \param       memlimit    Memory usage limit as bytes. Use UINT64_MAX
+ *                          to effectively disable the limiter.
+ * \param       flags       Bitwise-or of zero or more of the decoder flags:
+ *                          LZMA_TELL_NO_CHECK, LZMA_TELL_UNSUPPORTED_CHECK,
+ *                          LZMA_TELL_ANY_CHECK, LZMA_CONCATENATED
+ *
+ * \return      - LZMA_OK: Initialization was successful.
+ *              - LZMA_MEM_ERROR: Cannot allocate memory.
+ *              - LZMA_OPTIONS_ERROR: Unsupported flags
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_stream_decoder(
+               lzma_stream *strm, uint64_t memlimit, uint32_t flags)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Decode .xz Streams and .lzma files with autodetection
+ *
+ * This decoder autodetects between the .xz and .lzma file formats, and
+ * calls lzma_stream_decoder() or lzma_alone_decoder() once the type
+ * of the input file has been detected.
+ *
+ * \param       strm        Pointer to properly prepared lzma_stream
+ * \param       memlimit    Memory usage limit as bytes. Use UINT64_MAX
+ *                          to effectively disable the limiter.
+ * \param       flags       Bitwise-or of flags, or zero for no flags.
+ *
+ * \return      - LZMA_OK: Initialization was successful.
+ *              - LZMA_MEM_ERROR: Cannot allocate memory.
+ *              - LZMA_OPTIONS_ERROR: Unsupported flags
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_auto_decoder(
+               lzma_stream *strm, uint64_t memlimit, uint32_t flags)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Initialize .lzma decoder (legacy file format)
+ *
+ * Valid `action' arguments to lzma_code() are LZMA_RUN and LZMA_FINISH.
+ * There is no need to use LZMA_FINISH, but allowing it may simplify
+ * certain types of applications.
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_alone_decoder(
+               lzma_stream *strm, uint64_t memlimit)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Single-call .xz Stream decoder
+ *
+ * \param       memlimit    Pointer to how much memory the decoder is allowed
+ *                          to allocate. The value pointed by this pointer is
+ *                          modified if and only if LZMA_MEMLIMIT_ERROR is
+ *                          returned.
+ * \param       flags       Bitwise-or of zero or more of the decoder flags:
+ *                          LZMA_TELL_NO_CHECK, LZMA_TELL_UNSUPPORTED_CHECK,
+ *                          LZMA_CONCATENATED. Note that LZMA_TELL_ANY_CHECK
+ *                          is not allowed and will return LZMA_PROG_ERROR.
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
+ * \param       in          Beginning of the input buffer
+ * \param       in_pos      The next byte will be read from in[*in_pos].
+ *                          *in_pos is updated only if decoding succeeds.
+ * \param       in_size     Size of the input buffer; the first byte that
+ *                          won't be read is in[in_size].
+ * \param       out         Beginning of the output buffer
+ * \param       out_pos     The next byte will be written to out[*out_pos].
+ *                          *out_pos is updated only if decoding succeeds.
+ * \param       out_size    Size of the out buffer; the first byte into
+ *                          which no data is written to is out[out_size].
+ *
+ * \return      - LZMA_OK: Decoding was successful.
+ *              - LZMA_FORMAT_ERROR
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_DATA_ERROR
+ *              - LZMA_NO_CHECK: This can be returned only if using
+ *                the LZMA_TELL_NO_CHECK flag.
+ *              - LZMA_UNSUPPORTED_CHECK: This can be returned only if using
+ *                the LZMA_TELL_UNSUPPORTED_CHECK flag.
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_MEMLIMIT_ERROR: Memory usage limit was reached.
+ *                The minimum required memlimit value was stored to *memlimit.
+ *              - LZMA_BUF_ERROR: Output buffer was too small.
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_stream_buffer_decode(
+               uint64_t *memlimit, uint32_t flags,
+               const lzma_allocator *allocator,
+               const uint8_t *in, size_t *in_pos, size_t in_size,
+               uint8_t *out, size_t *out_pos, size_t out_size)
+               lzma_nothrow lzma_attr_warn_unused_result;
diff --git a/lzma/api/lzma/delta.h b/lzma/api/lzma/delta.h
new file mode 100644 (file)
index 0000000..592fc4f
--- /dev/null
@@ -0,0 +1,77 @@
+/**
+ * \file        lzma/delta.h
+ * \brief       Delta filter
+ */
+
+/*
+ * Author: Lasse Collin
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ *
+ * See ../lzma.h for information about liblzma as a whole.
+ */
+
+#ifndef LZMA_H_INTERNAL
+#      error Never include this file directly. Use <lzma.h> instead.
+#endif
+
+
+/**
+ * \brief       Filter ID
+ *
+ * Filter ID of the Delta filter. This is used as lzma_filter.id.
+ */
+#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;
+
+
+/**
+ * \brief       Options for the Delta filter
+ *
+ * These options are needed by both encoder and decoder.
+ */
+typedef struct {
+       /** For now, this must always be LZMA_DELTA_TYPE_BYTE. */
+       lzma_delta_type type;
+
+       /**
+        * \brief       Delta distance
+        *
+        * With the only currently supported type, LZMA_DELTA_TYPE_BYTE,
+        * the distance is as bytes.
+        *
+        * Examples:
+        *  - 16-bit stereo audio: distance = 4 bytes
+        *  - 24-bit RGB image data: distance = 3 bytes
+        */
+       uint32_t dist;
+#      define LZMA_DELTA_DIST_MIN 1
+#      define LZMA_DELTA_DIST_MAX 256
+
+       /*
+        * Reserved space to allow possible future extensions without
+        * breaking the ABI. 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;
+       uint32_t reserved_int3;
+       uint32_t reserved_int4;
+       void *reserved_ptr1;
+       void *reserved_ptr2;
+
+} lzma_options_delta;
diff --git a/lzma/api/lzma/filter.h b/lzma/api/lzma/filter.h
new file mode 100644 (file)
index 0000000..4e78752
--- /dev/null
@@ -0,0 +1,425 @@
+/**
+ * \file        lzma/filter.h
+ * \brief       Common filter related types and functions
+ */
+
+/*
+ * Author: Lasse Collin
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ *
+ * See ../lzma.h for information about liblzma as a whole.
+ */
+
+#ifndef LZMA_H_INTERNAL
+#      error Never include this file directly. Use <lzma.h> instead.
+#endif
+
+
+/**
+ * \brief       Maximum number of filters in a chain
+ *
+ * A filter chain can have 1-4 filters, of which three are allowed to change
+ * the size of the data. Usually only one or two filters are needed.
+ */
+#define LZMA_FILTERS_MAX 4
+
+
+/**
+ * \brief       Filter options
+ *
+ * This structure is used to pass Filter ID and a pointer filter's
+ * options to liblzma. A few functions work with a single lzma_filter
+ * structure, while most functions expect a filter chain.
+ *
+ * A filter chain is indicated with an array of lzma_filter structures.
+ * The array is terminated with .id = LZMA_VLI_UNKNOWN. Thus, the filter
+ * array must have LZMA_FILTERS_MAX + 1 elements (that is, five) to
+ * be able to hold any arbitrary filter chain. This is important when
+ * using lzma_block_header_decode() from block.h, because too small
+ * array would make liblzma write past the end of the filters array.
+ */
+typedef struct {
+       /**
+        * \brief       Filter ID
+        *
+        * Use constants whose name begin with `LZMA_FILTER_' to specify
+        * different filters. In an array of lzma_filter structures, use
+        * LZMA_VLI_UNKNOWN to indicate end of filters.
+        *
+        * \note        This is not an enum, because on some systems enums
+        *              cannot be 64-bit.
+        */
+       lzma_vli id;
+
+       /**
+        * \brief       Pointer to filter-specific options structure
+        *
+        * If the filter doesn't need options, set this to NULL. If id is
+        * set to LZMA_VLI_UNKNOWN, options is ignored, and thus
+        * doesn't need be initialized.
+        */
+       void *options;
+
+} lzma_filter;
+
+
+/**
+ * \brief       Test if the given Filter ID is supported for encoding
+ *
+ * Return true if the give Filter ID is supported for encoding by this
+ * liblzma build. Otherwise false is returned.
+ *
+ * There is no way to list which filters are available in this particular
+ * liblzma version and build. It would be useless, because the application
+ * couldn't know what kind of options the filter would need.
+ */
+extern LZMA_API(lzma_bool) lzma_filter_encoder_is_supported(lzma_vli id)
+               lzma_nothrow lzma_attr_const;
+
+
+/**
+ * \brief       Test if the given Filter ID is supported for decoding
+ *
+ * Return true if the give Filter ID is supported for decoding by this
+ * liblzma build. Otherwise false is returned.
+ */
+extern LZMA_API(lzma_bool) lzma_filter_decoder_is_supported(lzma_vli id)
+               lzma_nothrow lzma_attr_const;
+
+
+/**
+ * \brief       Copy the filters array
+ *
+ * Copy the Filter IDs and filter-specific options from src to dest.
+ * Up to LZMA_FILTERS_MAX filters are copied, plus the terminating
+ * .id == LZMA_VLI_UNKNOWN. Thus, dest should have at least
+ * LZMA_FILTERS_MAX + 1 elements space unless the caller knows that
+ * src is smaller than that.
+ *
+ * Unless the filter-specific options is NULL, the Filter ID has to be
+ * supported by liblzma, because liblzma needs to know the size of every
+ * filter-specific options structure. The filter-specific options are not
+ * validated. If options is NULL, any unsupported Filter IDs are copied
+ * without returning an error.
+ *
+ * Old filter-specific options in dest are not freed, so dest doesn't
+ * need to be initialized by the caller in any way.
+ *
+ * If an error occurs, memory possibly already allocated by this function
+ * is always freed.
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_OPTIONS_ERROR: Unsupported Filter ID and its options
+ *                is not NULL.
+ *              - LZMA_PROG_ERROR: src or dest is NULL.
+ */
+extern LZMA_API(lzma_ret) lzma_filters_copy(
+               const lzma_filter *src, lzma_filter *dest,
+               const lzma_allocator *allocator) lzma_nothrow;
+
+
+/**
+ * \brief       Calculate approximate memory requirements for raw encoder
+ *
+ * This function can be used to calculate the memory requirements for
+ * Block and Stream encoders too because Block and Stream encoders don't
+ * need significantly more memory than raw encoder.
+ *
+ * \param       filters     Array of filters terminated with
+ *                          .id == LZMA_VLI_UNKNOWN.
+ *
+ * \return      Number of bytes of memory required for the given
+ *              filter chain when encoding. If an error occurs,
+ *              for example due to unsupported filter chain,
+ *              UINT64_MAX is returned.
+ */
+extern LZMA_API(uint64_t) lzma_raw_encoder_memusage(const lzma_filter *filters)
+               lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Calculate approximate memory requirements for raw decoder
+ *
+ * This function can be used to calculate the memory requirements for
+ * Block and Stream decoders too because Block and Stream decoders don't
+ * need significantly more memory than raw decoder.
+ *
+ * \param       filters     Array of filters terminated with
+ *                          .id == LZMA_VLI_UNKNOWN.
+ *
+ * \return      Number of bytes of memory required for the given
+ *              filter chain when decoding. If an error occurs,
+ *              for example due to unsupported filter chain,
+ *              UINT64_MAX is returned.
+ */
+extern LZMA_API(uint64_t) lzma_raw_decoder_memusage(const lzma_filter *filters)
+               lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Initialize raw encoder
+ *
+ * This function may be useful when implementing custom file formats.
+ *
+ * \param       strm    Pointer to properly prepared lzma_stream
+ * \param       filters Array of lzma_filter structures. The end of the
+ *                      array must be marked with .id = LZMA_VLI_UNKNOWN.
+ *
+ * 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_OPTIONS_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_raw_encoder(
+               lzma_stream *strm, const lzma_filter *filters)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Initialize raw decoder
+ *
+ * The initialization of raw decoder goes similarly to raw encoder.
+ *
+ * The `action' with lzma_code() can be LZMA_RUN or LZMA_FINISH. Using
+ * LZMA_FINISH is not required, it is supported just for convenience.
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_raw_decoder(
+               lzma_stream *strm, const lzma_filter *filters)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Update the filter chain in the encoder
+ *
+ * This function is for advanced users only. This function has two slightly
+ * different purposes:
+ *
+ *  - After LZMA_FULL_FLUSH when using Stream encoder: Set a new filter
+ *    chain, which will be used starting from the next Block.
+ *
+ *  - After LZMA_SYNC_FLUSH using Raw, Block, or Stream encoder: Change
+ *    the filter-specific options in the middle of encoding. The actual
+ *    filters in the chain (Filter IDs) cannot be changed. In the future,
+ *    it might become possible to change the filter options without
+ *    using LZMA_SYNC_FLUSH.
+ *
+ * While rarely useful, this function may be called also when no data has
+ * been compressed yet. In that case, this function will behave as if
+ * LZMA_FULL_FLUSH (Stream encoder) or LZMA_SYNC_FLUSH (Raw or Block
+ * encoder) had been used right before calling this function.
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_MEMLIMIT_ERROR
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_filters_update(
+               lzma_stream *strm, const lzma_filter *filters) lzma_nothrow;
+
+
+/**
+ * \brief       Single-call raw encoder
+ *
+ * \param       filters     Array of lzma_filter structures. The end of the
+ *                          array must be marked with .id = LZMA_VLI_UNKNOWN.
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
+ * \param       in          Beginning of the input buffer
+ * \param       in_size     Size of the input buffer
+ * \param       out         Beginning of the output buffer
+ * \param       out_pos     The next byte will be written to out[*out_pos].
+ *                          *out_pos is updated only if encoding succeeds.
+ * \param       out_size    Size of the out buffer; the first byte into
+ *                          which no data is written to is out[out_size].
+ *
+ * \return      - LZMA_OK: Encoding was successful.
+ *              - LZMA_BUF_ERROR: Not enough output buffer space.
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_DATA_ERROR
+ *              - LZMA_PROG_ERROR
+ *
+ * \note        There is no function to calculate how big output buffer
+ *              would surely be big enough. (lzma_stream_buffer_bound()
+ *              works only for lzma_stream_buffer_encode(); raw encoder
+ *              won't necessarily meet that bound.)
+ */
+extern LZMA_API(lzma_ret) lzma_raw_buffer_encode(
+               const lzma_filter *filters, const lzma_allocator *allocator,
+               const uint8_t *in, size_t in_size, uint8_t *out,
+               size_t *out_pos, size_t out_size) lzma_nothrow;
+
+
+/**
+ * \brief       Single-call raw decoder
+ *
+ * \param       filters     Array of lzma_filter structures. The end of the
+ *                          array must be marked with .id = LZMA_VLI_UNKNOWN.
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
+ * \param       in          Beginning of the input buffer
+ * \param       in_pos      The next byte will be read from in[*in_pos].
+ *                          *in_pos is updated only if decoding succeeds.
+ * \param       in_size     Size of the input buffer; the first byte that
+ *                          won't be read is in[in_size].
+ * \param       out         Beginning of the output buffer
+ * \param       out_pos     The next byte will be written to out[*out_pos].
+ *                          *out_pos is updated only if encoding succeeds.
+ * \param       out_size    Size of the out buffer; the first byte into
+ *                          which no data is written to is out[out_size].
+ */
+extern LZMA_API(lzma_ret) lzma_raw_buffer_decode(
+               const lzma_filter *filters, const lzma_allocator *allocator,
+               const uint8_t *in, size_t *in_pos, size_t in_size,
+               uint8_t *out, size_t *out_pos, size_t out_size) lzma_nothrow;
+
+
+/**
+ * \brief       Get the size of the Filter Properties field
+ *
+ * This function may be useful when implementing custom file formats
+ * using the raw encoder and decoder.
+ *
+ * \param       size    Pointer to uint32_t to hold the size of the properties
+ * \param       filter  Filter ID and options (the size of the properties may
+ *                      vary depending on the options)
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_PROG_ERROR
+ *
+ * \note        This function validates the Filter ID, but does not
+ *              necessarily validate the options. Thus, it is possible
+ *              that this returns LZMA_OK while the following call to
+ *              lzma_properties_encode() returns LZMA_OPTIONS_ERROR.
+ */
+extern LZMA_API(lzma_ret) lzma_properties_size(
+               uint32_t *size, const lzma_filter *filter) lzma_nothrow;
+
+
+/**
+ * \brief       Encode the Filter Properties field
+ *
+ * \param       filter  Filter ID and options
+ * \param       props   Buffer to hold the encoded options. The size of
+ *                      buffer must have been already determined with
+ *                      lzma_properties_size().
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_PROG_ERROR
+ *
+ * \note        Even this function won't validate more options than actually
+ *              necessary. Thus, it is possible that encoding the properties
+ *              succeeds but using the same options to initialize the encoder
+ *              will fail.
+ *
+ * \note        If lzma_properties_size() indicated that the size
+ *              of the Filter Properties field is zero, calling
+ *              lzma_properties_encode() is not required, but it
+ *              won't do any harm either.
+ */
+extern LZMA_API(lzma_ret) lzma_properties_encode(
+               const lzma_filter *filter, uint8_t *props) lzma_nothrow;
+
+
+/**
+ * \brief       Decode the Filter Properties field
+ *
+ * \param       filter      filter->id must have been set to the correct
+ *                          Filter ID. filter->options doesn't need to be
+ *                          initialized (it's not freed by this function). The
+ *                          decoded options will be stored to filter->options.
+ *                          filter->options is set to NULL if there are no
+ *                          properties or if an error occurs.
+ * \param       allocator   Custom memory allocator used to allocate the
+ *                          options. Set to NULL to use the default malloc(),
+ *                          and in case of an error, also free().
+ * \param       props       Input buffer containing the properties.
+ * \param       props_size  Size of the properties. This must be the exact
+ *                          size; giving too much or too little input will
+ *                          return LZMA_OPTIONS_ERROR.
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_MEM_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_properties_decode(
+               lzma_filter *filter, const lzma_allocator *allocator,
+               const uint8_t *props, size_t props_size) lzma_nothrow;
+
+
+/**
+ * \brief       Calculate encoded size of a Filter Flags field
+ *
+ * Knowing the size of Filter Flags is useful to know when allocating
+ * memory to hold the encoded Filter Flags.
+ *
+ * \param       size    Pointer to integer to hold the calculated size
+ * \param       filter  Filter ID and associated options whose encoded
+ *                      size is to be calculated
+ *
+ * \return      - LZMA_OK: *size set successfully. Note that this doesn't
+ *                guarantee that filter->options is valid, thus
+ *                lzma_filter_flags_encode() may still fail.
+ *              - LZMA_OPTIONS_ERROR: Unknown Filter ID or unsupported options.
+ *              - LZMA_PROG_ERROR: Invalid options
+ *
+ * \note        If you need to calculate size of List of Filter Flags,
+ *              you need to loop over every lzma_filter entry.
+ */
+extern LZMA_API(lzma_ret) lzma_filter_flags_size(
+               uint32_t *size, const lzma_filter *filter)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Encode Filter Flags into given buffer
+ *
+ * In contrast to some functions, this doesn't allocate the needed buffer.
+ * This is due to how this function is used internally by liblzma.
+ *
+ * \param       filter      Filter ID and options to be encoded
+ * \param       out         Beginning of the output buffer
+ * \param       out_pos     out[*out_pos] is the next write position. This
+ *                          is updated by the encoder.
+ * \param       out_size    out[out_size] is the first byte to not write.
+ *
+ * \return      - LZMA_OK: Encoding was successful.
+ *              - LZMA_OPTIONS_ERROR: Invalid or unsupported options.
+ *              - LZMA_PROG_ERROR: Invalid options or not enough output
+ *                buffer space (you should have checked it with
+ *                lzma_filter_flags_size()).
+ */
+extern LZMA_API(lzma_ret) lzma_filter_flags_encode(const lzma_filter *filter,
+               uint8_t *out, size_t *out_pos, size_t out_size)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Decode Filter Flags from given buffer
+ *
+ * The decoded result is stored into *filter. The old value of
+ * filter->options is not free()d.
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_filter_flags_decode(
+               lzma_filter *filter, const lzma_allocator *allocator,
+               const uint8_t *in, size_t *in_pos, size_t in_size)
+               lzma_nothrow lzma_attr_warn_unused_result;
diff --git a/lzma/api/lzma/hardware.h b/lzma/api/lzma/hardware.h
new file mode 100644 (file)
index 0000000..5321d9a
--- /dev/null
@@ -0,0 +1,64 @@
+/**
+ * \file        lzma/hardware.h
+ * \brief       Hardware information
+ *
+ * Since liblzma can consume a lot of system resources, it also provides
+ * ways to limit the resource usage. Applications linking against liblzma
+ * need to do the actual decisions how much resources to let liblzma to use.
+ * To ease making these decisions, liblzma provides functions to find out
+ * the relevant capabilities of the underlaying hardware. Currently there
+ * is only a function to find out the amount of RAM, but in the future there
+ * will be also a function to detect how many concurrent threads the system
+ * can run.
+ *
+ * \note        On some operating systems, these function may temporarily
+ *              load a shared library or open file descriptor(s) to find out
+ *              the requested hardware information. Unless the application
+ *              assumes that specific file descriptors are not touched by
+ *              other threads, this should have no effect on thread safety.
+ *              Possible operations involving file descriptors will restart
+ *              the syscalls if they return EINTR.
+ */
+
+/*
+ * Author: Lasse Collin
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ *
+ * See ../lzma.h for information about liblzma as a whole.
+ */
+
+#ifndef LZMA_H_INTERNAL
+#      error Never include this file directly. Use <lzma.h> instead.
+#endif
+
+
+/**
+ * \brief       Get the total amount of physical memory (RAM) in bytes
+ *
+ * This function may be useful when determining a reasonable memory
+ * usage limit for decompressing or how much memory it is OK to use
+ * for compressing.
+ *
+ * \return      On success, the total amount of physical memory in bytes
+ *              is returned. If the amount of RAM cannot be determined,
+ *              zero is returned. This can happen if an error occurs
+ *              or if there is no code in liblzma to detect the amount
+ *              of RAM on the specific operating system.
+ */
+extern LZMA_API(uint64_t) lzma_physmem(void) lzma_nothrow;
+
+
+/**
+ * \brief       Get the number of processor cores or threads
+ *
+ * This function may be useful when determining how many threads to use.
+ * If the hardware supports more than one thread per CPU core, the number
+ * of hardware threads is returned if that information is available.
+ *
+ * \brief       On success, the number of available CPU threads or cores is
+ *              returned. If this information isn't available or an error
+ *              occurs, zero is returned.
+ */
+extern LZMA_API(uint32_t) lzma_cputhreads(void) lzma_nothrow;
diff --git a/lzma/api/lzma/index.h b/lzma/api/lzma/index.h
new file mode 100644 (file)
index 0000000..dda60ec
--- /dev/null
@@ -0,0 +1,682 @@
+/**
+ * \file        lzma/index.h
+ * \brief       Handling of .xz Index and related information
+ */
+
+/*
+ * Author: Lasse Collin
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ *
+ * See ../lzma.h for information about liblzma as a whole.
+ */
+
+#ifndef LZMA_H_INTERNAL
+#      error Never include this file directly. Use <lzma.h> instead.
+#endif
+
+
+/**
+ * \brief       Opaque data type to hold the Index(es) and other information
+ *
+ * lzma_index often holds just one .xz Index and possibly the Stream Flags
+ * of the same Stream and size of the Stream Padding field. However,
+ * multiple lzma_indexes can be concatenated with lzma_index_cat() and then
+ * there may be information about multiple Streams in the same lzma_index.
+ *
+ * Notes about thread safety: Only one thread may modify lzma_index at
+ * a time. All functions that take non-const pointer to lzma_index
+ * modify it. As long as no thread is modifying the lzma_index, getting
+ * information from the same lzma_index can be done from multiple threads
+ * at the same time with functions that take a const pointer to
+ * lzma_index or use lzma_index_iter. The same iterator must be used
+ * only by one thread at a time, of course, but there can be as many
+ * iterators for the same lzma_index as needed.
+ */
+typedef struct lzma_index_s lzma_index;
+
+
+/**
+ * \brief       Iterator to get information about Blocks and Streams
+ */
+typedef struct {
+       struct {
+               /**
+                * \brief       Pointer to Stream Flags
+                *
+                * This is NULL if Stream Flags have not been set for
+                * this Stream with lzma_index_stream_flags().
+                */
+               const lzma_stream_flags *flags;
+
+               const void *reserved_ptr1;
+               const void *reserved_ptr2;
+               const void *reserved_ptr3;
+
+               /**
+                * \brief       Stream number in the lzma_index
+                *
+                * The first Stream is 1.
+                */
+               lzma_vli number;
+
+               /**
+                * \brief       Number of Blocks in the Stream
+                *
+                * If this is zero, the block structure below has
+                * undefined values.
+                */
+               lzma_vli block_count;
+
+               /**
+                * \brief       Compressed start offset of this Stream
+                *
+                * The offset is relative to the beginning of the lzma_index
+                * (i.e. usually the beginning of the .xz file).
+                */
+               lzma_vli compressed_offset;
+
+               /**
+                * \brief       Uncompressed start offset of this Stream
+                *
+                * The offset is relative to the beginning of the lzma_index
+                * (i.e. usually the beginning of the .xz file).
+                */
+               lzma_vli uncompressed_offset;
+
+               /**
+                * \brief       Compressed size of this Stream
+                *
+                * This includes all headers except the possible
+                * Stream Padding after this Stream.
+                */
+               lzma_vli compressed_size;
+
+               /**
+                * \brief       Uncompressed size of this Stream
+                */
+               lzma_vli uncompressed_size;
+
+               /**
+                * \brief       Size of Stream Padding after this Stream
+                *
+                * If it hasn't been set with lzma_index_stream_padding(),
+                * this defaults to zero. Stream Padding is always
+                * a multiple of four bytes.
+                */
+               lzma_vli padding;
+
+               lzma_vli reserved_vli1;
+               lzma_vli reserved_vli2;
+               lzma_vli reserved_vli3;
+               lzma_vli reserved_vli4;
+       } stream;
+
+       struct {
+               /**
+                * \brief       Block number in the file
+                *
+                * The first Block is 1.
+                */
+               lzma_vli number_in_file;
+
+               /**
+                * \brief       Compressed start offset of this Block
+                *
+                * This offset is relative to the beginning of the
+                * lzma_index (i.e. usually the beginning of the .xz file).
+                * Normally this is where you should seek in the .xz file
+                * to start decompressing this Block.
+                */
+               lzma_vli compressed_file_offset;
+
+               /**
+                * \brief       Uncompressed start offset of this Block
+                *
+                * This offset is relative to the beginning of the lzma_index
+                * (i.e. usually the beginning of the .xz file).
+                *
+                * When doing random-access reading, it is possible that
+                * the target offset is not exactly at Block boundary. One
+                * will need to compare the target offset against
+                * uncompressed_file_offset or uncompressed_stream_offset,
+                * and possibly decode and throw away some amount of data
+                * before reaching the target offset.
+                */
+               lzma_vli uncompressed_file_offset;
+
+               /**
+                * \brief       Block number in this Stream
+                *
+                * The first Block is 1.
+                */
+               lzma_vli number_in_stream;
+
+               /**
+                * \brief       Compressed start offset of this Block
+                *
+                * This offset is relative to the beginning of the Stream
+                * containing this Block.
+                */
+               lzma_vli compressed_stream_offset;
+
+               /**
+                * \brief       Uncompressed start offset of this Block
+                *
+                * This offset is relative to the beginning of the Stream
+                * containing this Block.
+                */
+               lzma_vli uncompressed_stream_offset;
+
+               /**
+                * \brief       Uncompressed size of this Block
+                *
+                * You should pass this to the Block decoder if you will
+                * decode this Block. It will allow the Block decoder to
+                * validate the uncompressed size.
+                */
+               lzma_vli uncompressed_size;
+
+               /**
+                * \brief       Unpadded size of this Block
+                *
+                * You should pass this to the Block decoder if you will
+                * decode this Block. It will allow the Block decoder to
+                * validate the unpadded size.
+                */
+               lzma_vli unpadded_size;
+
+               /**
+                * \brief       Total compressed size
+                *
+                * This includes all headers and padding in this Block.
+                * This is useful if you need to know how many bytes
+                * the Block decoder will actually read.
+                */
+               lzma_vli total_size;
+
+               lzma_vli reserved_vli1;
+               lzma_vli reserved_vli2;
+               lzma_vli reserved_vli3;
+               lzma_vli reserved_vli4;
+
+               const void *reserved_ptr1;
+               const void *reserved_ptr2;
+               const void *reserved_ptr3;
+               const void *reserved_ptr4;
+       } block;
+
+       /*
+        * Internal data which is used to store the state of the iterator.
+        * The exact format may vary between liblzma versions, so don't
+        * touch these in any way.
+        */
+       union {
+               const void *p;
+               size_t s;
+               lzma_vli v;
+       } internal[6];
+} lzma_index_iter;
+
+
+/**
+ * \brief       Operation mode for lzma_index_iter_next()
+ */
+typedef enum {
+       LZMA_INDEX_ITER_ANY             = 0,
+               /**<
+                * \brief       Get the next Block or Stream
+                *
+                * Go to the next Block if the current Stream has at least
+                * one Block left. Otherwise go to the next Stream even if
+                * it has no Blocks. If the Stream has no Blocks
+                * (lzma_index_iter.stream.block_count == 0),
+                * lzma_index_iter.block will have undefined values.
+                */
+
+       LZMA_INDEX_ITER_STREAM          = 1,
+               /**<
+                * \brief       Get the next Stream
+                *
+                * Go to the next Stream even if the current Stream has
+                * unread Blocks left. If the next Stream has at least one
+                * Block, the iterator will point to the first Block.
+                * If there are no Blocks, lzma_index_iter.block will have
+                * undefined values.
+                */
+
+       LZMA_INDEX_ITER_BLOCK           = 2,
+               /**<
+                * \brief       Get the next Block
+                *
+                * Go to the next Block if the current Stream has at least
+                * one Block left. If the current Stream has no Blocks left,
+                * the next Stream with at least one Block is located and
+                * the iterator will be made to point to the first Block of
+                * that Stream.
+                */
+
+       LZMA_INDEX_ITER_NONEMPTY_BLOCK  = 3
+               /**<
+                * \brief       Get the next non-empty Block
+                *
+                * This is like LZMA_INDEX_ITER_BLOCK except that it will
+                * skip Blocks whose Uncompressed Size is zero.
+                */
+
+} lzma_index_iter_mode;
+
+
+/**
+ * \brief       Calculate memory usage of lzma_index
+ *
+ * On disk, the size of the Index field depends on both the number of Records
+ * stored and how big values the Records store (due to variable-length integer
+ * encoding). When the Index is kept in lzma_index structure, the memory usage
+ * depends only on the number of Records/Blocks stored in the Index(es), and
+ * in case of concatenated lzma_indexes, the number of Streams. The size in
+ * RAM is almost always significantly bigger than in the encoded form on disk.
+ *
+ * This function calculates an approximate amount of memory needed hold
+ * the given number of Streams and Blocks in lzma_index structure. This
+ * value may vary between CPU architectures and also between liblzma versions
+ * if the internal implementation is modified.
+ */
+extern LZMA_API(uint64_t) lzma_index_memusage(
+               lzma_vli streams, lzma_vli blocks) lzma_nothrow;
+
+
+/**
+ * \brief       Calculate the memory usage of an existing lzma_index
+ *
+ * This is a shorthand for lzma_index_memusage(lzma_index_stream_count(i),
+ * lzma_index_block_count(i)).
+ */
+extern LZMA_API(uint64_t) lzma_index_memused(const lzma_index *i)
+               lzma_nothrow;
+
+
+/**
+ * \brief       Allocate and initialize a new lzma_index structure
+ *
+ * \return      On success, a pointer to an empty initialized lzma_index is
+ *              returned. If allocation fails, NULL is returned.
+ */
+extern LZMA_API(lzma_index *) lzma_index_init(const lzma_allocator *allocator)
+               lzma_nothrow;
+
+
+/**
+ * \brief       Deallocate lzma_index
+ *
+ * If i is NULL, this does nothing.
+ */
+extern LZMA_API(void) lzma_index_end(
+               lzma_index *i, const lzma_allocator *allocator) lzma_nothrow;
+
+
+/**
+ * \brief       Add a new Block to lzma_index
+ *
+ * \param       i                 Pointer to a lzma_index structure
+ * \param       allocator         Pointer to lzma_allocator, or NULL to
+ *                                use malloc()
+ * \param       unpadded_size     Unpadded Size of a Block. This can be
+ *                                calculated with lzma_block_unpadded_size()
+ *                                after encoding or decoding the Block.
+ * \param       uncompressed_size Uncompressed Size of a Block. This can be
+ *                                taken directly from lzma_block structure
+ *                                after encoding or decoding the Block.
+ *
+ * Appending a new Block does not invalidate iterators. For example,
+ * if an iterator was pointing to the end of the lzma_index, after
+ * lzma_index_append() it is possible to read the next Block with
+ * an existing iterator.
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_DATA_ERROR: Compressed or uncompressed size of the
+ *                Stream or size of the Index field would grow too big.
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_index_append(
+               lzma_index *i, const lzma_allocator *allocator,
+               lzma_vli unpadded_size, lzma_vli uncompressed_size)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Set the Stream Flags
+ *
+ * Set the Stream Flags of the last (and typically the only) Stream
+ * in lzma_index. This can be useful when reading information from the
+ * lzma_index, because to decode Blocks, knowing the integrity check type
+ * is needed.
+ *
+ * The given Stream Flags are copied into internal preallocated structure
+ * in the lzma_index, thus the caller doesn't need to keep the *stream_flags
+ * available after calling this function.
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_OPTIONS_ERROR: Unsupported stream_flags->version.
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_index_stream_flags(
+               lzma_index *i, const lzma_stream_flags *stream_flags)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Get the types of integrity Checks
+ *
+ * If lzma_index_stream_flags() is used to set the Stream Flags for
+ * every Stream, lzma_index_checks() can be used to get a bitmask to
+ * indicate which Check types have been used. It can be useful e.g. if
+ * showing the Check types to the user.
+ *
+ * The bitmask is 1 << check_id, e.g. CRC32 is 1 << 1 and SHA-256 is 1 << 10.
+ */
+extern LZMA_API(uint32_t) lzma_index_checks(const lzma_index *i)
+               lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Set the amount of Stream Padding
+ *
+ * Set the amount of Stream Padding of the last (and typically the only)
+ * Stream in the lzma_index. This is needed when planning to do random-access
+ * reading within multiple concatenated Streams.
+ *
+ * By default, the amount of Stream Padding is assumed to be zero bytes.
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_DATA_ERROR: The file size would grow too big.
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_index_stream_padding(
+               lzma_index *i, lzma_vli stream_padding)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Get the number of Streams
+ */
+extern LZMA_API(lzma_vli) lzma_index_stream_count(const lzma_index *i)
+               lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Get the number of Blocks
+ *
+ * This returns the total number of Blocks in lzma_index. To get number
+ * of Blocks in individual Streams, use lzma_index_iter.
+ */
+extern LZMA_API(lzma_vli) lzma_index_block_count(const lzma_index *i)
+               lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Get the size of the Index field as bytes
+ *
+ * This is needed to verify the Backward Size field in the Stream Footer.
+ */
+extern LZMA_API(lzma_vli) lzma_index_size(const lzma_index *i)
+               lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Get the total size of the Stream
+ *
+ * If multiple lzma_indexes have been combined, this works as if the Blocks
+ * were in a single Stream. This is useful if you are going to combine
+ * Blocks from multiple Streams into a single new Stream.
+ */
+extern LZMA_API(lzma_vli) lzma_index_stream_size(const lzma_index *i)
+               lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Get the total size of the Blocks
+ *
+ * This doesn't include the Stream Header, Stream Footer, Stream Padding,
+ * or Index fields.
+ */
+extern LZMA_API(lzma_vli) lzma_index_total_size(const lzma_index *i)
+               lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Get the total size of the file
+ *
+ * When no lzma_indexes have been combined with lzma_index_cat() and there is
+ * no Stream Padding, this function is identical to lzma_index_stream_size().
+ * If multiple lzma_indexes have been combined, this includes also the headers
+ * of each separate Stream and the possible Stream Padding fields.
+ */
+extern LZMA_API(lzma_vli) lzma_index_file_size(const lzma_index *i)
+               lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Get the uncompressed size of the file
+ */
+extern LZMA_API(lzma_vli) lzma_index_uncompressed_size(const lzma_index *i)
+               lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Initialize an iterator
+ *
+ * \param       iter    Pointer to a lzma_index_iter structure
+ * \param       i       lzma_index to which the iterator will be associated
+ *
+ * This function associates the iterator with the given lzma_index, and calls
+ * lzma_index_iter_rewind() on the iterator.
+ *
+ * This function doesn't allocate any memory, thus there is no
+ * lzma_index_iter_end(). The iterator is valid as long as the
+ * associated lzma_index is valid, that is, until lzma_index_end() or
+ * using it as source in lzma_index_cat(). Specifically, lzma_index doesn't
+ * become invalid if new Blocks are added to it with lzma_index_append() or
+ * if it is used as the destination in lzma_index_cat().
+ *
+ * It is safe to make copies of an initialized lzma_index_iter, for example,
+ * to easily restart reading at some particular position.
+ */
+extern LZMA_API(void) lzma_index_iter_init(
+               lzma_index_iter *iter, const lzma_index *i) lzma_nothrow;
+
+
+/**
+ * \brief       Rewind the iterator
+ *
+ * Rewind the iterator so that next call to lzma_index_iter_next() will
+ * return the first Block or Stream.
+ */
+extern LZMA_API(void) lzma_index_iter_rewind(lzma_index_iter *iter)
+               lzma_nothrow;
+
+
+/**
+ * \brief       Get the next Block or Stream
+ *
+ * \param       iter    Iterator initialized with lzma_index_iter_init()
+ * \param       mode    Specify what kind of information the caller wants
+ *                      to get. See lzma_index_iter_mode for details.
+ *
+ * \return      If next Block or Stream matching the mode was found, *iter
+ *              is updated and this function returns false. If no Block or
+ *              Stream matching the mode is found, *iter is not modified
+ *              and this function returns true. If mode is set to an unknown
+ *              value, *iter is not modified and this function returns true.
+ */
+extern LZMA_API(lzma_bool) lzma_index_iter_next(
+               lzma_index_iter *iter, lzma_index_iter_mode mode)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Locate a Block
+ *
+ * If it is possible to seek in the .xz file, it is possible to parse
+ * the Index field(s) and use lzma_index_iter_locate() to do random-access
+ * reading with granularity of Block size.
+ *
+ * \param       iter    Iterator that was earlier initialized with
+ *                      lzma_index_iter_init().
+ * \param       target  Uncompressed target offset which the caller would
+ *                      like to locate from the Stream
+ *
+ * If the target is smaller than the uncompressed size of the Stream (can be
+ * checked with lzma_index_uncompressed_size()):
+ *  - Information about the Stream and Block containing the requested
+ *    uncompressed offset is stored into *iter.
+ *  - Internal state of the iterator is adjusted so that
+ *    lzma_index_iter_next() can be used to read subsequent Blocks or Streams.
+ *  - This function returns false.
+ *
+ * If target is greater than the uncompressed size of the Stream, *iter
+ * is not modified, and this function returns true.
+ */
+extern LZMA_API(lzma_bool) lzma_index_iter_locate(
+               lzma_index_iter *iter, lzma_vli target) lzma_nothrow;
+
+
+/**
+ * \brief       Concatenate lzma_indexes
+ *
+ * Concatenating lzma_indexes is useful when doing random-access reading in
+ * multi-Stream .xz file, or when combining multiple Streams into single
+ * Stream.
+ *
+ * \param       dest      lzma_index after which src is appended
+ * \param       src       lzma_index to be appended after dest. If this
+ *                        function succeeds, the memory allocated for src
+ *                        is freed or moved to be part of dest, and all
+ *                        iterators pointing to src will become invalid.
+ * \param       allocator Custom memory allocator; can be NULL to use
+ *                        malloc() and free().
+ *
+ * \return      - LZMA_OK: lzma_indexes were concatenated successfully.
+ *                src is now a dangling pointer.
+ *              - LZMA_DATA_ERROR: *dest would grow too big.
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_index_cat(lzma_index *dest, lzma_index *src,
+               const lzma_allocator *allocator)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Duplicate lzma_index
+ *
+ * \return      A copy of the lzma_index, or NULL if memory allocation failed.
+ */
+extern LZMA_API(lzma_index *) lzma_index_dup(
+               const lzma_index *i, const lzma_allocator *allocator)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Initialize .xz Index encoder
+ *
+ * \param       strm        Pointer to properly prepared lzma_stream
+ * \param       i           Pointer to lzma_index which should be encoded.
+ *
+ * The valid `action' values for lzma_code() are LZMA_RUN and LZMA_FINISH.
+ * It is enough to use only one of them (you can choose freely; use LZMA_RUN
+ * to support liblzma versions older than 5.0.0).
+ *
+ * \return      - LZMA_OK: Initialization succeeded, continue with lzma_code().
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_index_encoder(
+               lzma_stream *strm, const lzma_index *i)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Initialize .xz Index decoder
+ *
+ * \param       strm        Pointer to properly prepared lzma_stream
+ * \param       i           The decoded Index will be made available via
+ *                          this pointer. Initially this function will
+ *                          set *i to NULL (the old value is ignored). If
+ *                          decoding succeeds (lzma_code() returns
+ *                          LZMA_STREAM_END), *i will be set to point
+ *                          to a new lzma_index, which the application
+ *                          has to later free with lzma_index_end().
+ * \param       memlimit    How much memory the resulting lzma_index is
+ *                          allowed to require.
+ *
+ * The valid `action' values for lzma_code() are LZMA_RUN and LZMA_FINISH.
+ * It is enough to use only one of them (you can choose freely; use LZMA_RUN
+ * to support liblzma versions older than 5.0.0).
+ *
+ * \return      - LZMA_OK: Initialization succeeded, continue with lzma_code().
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_MEMLIMIT_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_index_decoder(
+               lzma_stream *strm, lzma_index **i, uint64_t memlimit)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Single-call .xz Index encoder
+ *
+ * \param       i         lzma_index to be encoded
+ * \param       out       Beginning of the output buffer
+ * \param       out_pos   The next byte will be written to out[*out_pos].
+ *                        *out_pos is updated only if encoding succeeds.
+ * \param       out_size  Size of the out buffer; the first byte into
+ *                        which no data is written to is out[out_size].
+ *
+ * \return      - LZMA_OK: Encoding was successful.
+ *              - LZMA_BUF_ERROR: Output buffer is too small. Use
+ *                lzma_index_size() to find out how much output
+ *                space is needed.
+ *              - LZMA_PROG_ERROR
+ *
+ * \note        This function doesn't take allocator argument since all
+ *              the internal data is allocated on stack.
+ */
+extern LZMA_API(lzma_ret) lzma_index_buffer_encode(const lzma_index *i,
+               uint8_t *out, size_t *out_pos, size_t out_size) lzma_nothrow;
+
+
+/**
+ * \brief       Single-call .xz Index decoder
+ *
+ * \param       i           If decoding succeeds, *i will point to a new
+ *                          lzma_index, which the application has to
+ *                          later free with lzma_index_end(). If an error
+ *                          occurs, *i will be NULL. The old value of *i
+ *                          is always ignored and thus doesn't need to be
+ *                          initialized by the caller.
+ * \param       memlimit    Pointer to how much memory the resulting
+ *                          lzma_index is allowed to require. The value
+ *                          pointed by this pointer is modified if and only
+ *                          if LZMA_MEMLIMIT_ERROR is returned.
+ * \param       allocator   Pointer to lzma_allocator, or NULL to use malloc()
+ * \param       in          Beginning of the input buffer
+ * \param       in_pos      The next byte will be read from in[*in_pos].
+ *                          *in_pos is updated only if decoding succeeds.
+ * \param       in_size     Size of the input buffer; the first byte that
+ *                          won't be read is in[in_size].
+ *
+ * \return      - LZMA_OK: Decoding was successful.
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_MEMLIMIT_ERROR: Memory usage limit was reached.
+ *                The minimum required memlimit value was stored to *memlimit.
+ *              - LZMA_DATA_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_index_buffer_decode(lzma_index **i,
+               uint64_t *memlimit, const lzma_allocator *allocator,
+               const uint8_t *in, size_t *in_pos, size_t in_size)
+               lzma_nothrow;
diff --git a/lzma/api/lzma/index_hash.h b/lzma/api/lzma/index_hash.h
new file mode 100644 (file)
index 0000000..9287f1d
--- /dev/null
@@ -0,0 +1,107 @@
+/**
+ * \file        lzma/index_hash.h
+ * \brief       Validate Index by using a hash function
+ *
+ * Hashing makes it possible to use constant amount of memory to validate
+ * Index of arbitrary size.
+ */
+
+/*
+ * Author: Lasse Collin
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ *
+ * See ../lzma.h for information about liblzma as a whole.
+ */
+
+#ifndef LZMA_H_INTERNAL
+#      error Never include this file directly. Use <lzma.h> instead.
+#endif
+
+/**
+ * \brief       Opaque data type to hold the Index hash
+ */
+typedef struct lzma_index_hash_s lzma_index_hash;
+
+
+/**
+ * \brief       Allocate and initialize a new lzma_index_hash structure
+ *
+ * If index_hash is NULL, a new lzma_index_hash structure is allocated,
+ * initialized, and a pointer to it returned. If allocation fails, NULL
+ * is returned.
+ *
+ * If index_hash is non-NULL, it is reinitialized and the same pointer
+ * returned. In this case, return value cannot be NULL or a different
+ * pointer than the index_hash that was given as an argument.
+ */
+extern LZMA_API(lzma_index_hash *) lzma_index_hash_init(
+               lzma_index_hash *index_hash, const lzma_allocator *allocator)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Deallocate lzma_index_hash structure
+ */
+extern LZMA_API(void) lzma_index_hash_end(
+               lzma_index_hash *index_hash, const lzma_allocator *allocator)
+               lzma_nothrow;
+
+
+/**
+ * \brief       Add a new Record to an Index hash
+ *
+ * \param       index             Pointer to a lzma_index_hash structure
+ * \param       unpadded_size     Unpadded Size of a Block
+ * \param       uncompressed_size Uncompressed Size of a Block
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_DATA_ERROR: Compressed or uncompressed size of the
+ *                Stream or size of the Index field would grow too big.
+ *              - LZMA_PROG_ERROR: Invalid arguments or this function is being
+ *                used when lzma_index_hash_decode() has already been used.
+ */
+extern LZMA_API(lzma_ret) lzma_index_hash_append(lzma_index_hash *index_hash,
+               lzma_vli unpadded_size, lzma_vli uncompressed_size)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Decode and validate the Index field
+ *
+ * After telling the sizes of all Blocks with lzma_index_hash_append(),
+ * the actual Index field is decoded with this function. Specifically,
+ * once decoding of the Index field has been started, no more Records
+ * can be added using lzma_index_hash_append().
+ *
+ * This function doesn't use lzma_stream structure to pass the input data.
+ * Instead, the input buffer is specified using three arguments. This is
+ * because it matches better the internal APIs of liblzma.
+ *
+ * \param       index_hash      Pointer to a lzma_index_hash structure
+ * \param       in              Pointer to the beginning of the input buffer
+ * \param       in_pos          in[*in_pos] is the next byte to process
+ * \param       in_size         in[in_size] is the first byte not to process
+ *
+ * \return      - LZMA_OK: So far good, but more input is needed.
+ *              - LZMA_STREAM_END: Index decoded successfully and it matches
+ *                the Records given with lzma_index_hash_append().
+ *              - LZMA_DATA_ERROR: Index is corrupt or doesn't match the
+ *                information given with lzma_index_hash_append().
+ *              - LZMA_BUF_ERROR: Cannot progress because *in_pos >= in_size.
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_index_hash_decode(lzma_index_hash *index_hash,
+               const uint8_t *in, size_t *in_pos, size_t in_size)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Get the size of the Index field as bytes
+ *
+ * This is needed to verify the Backward Size field in the Stream Footer.
+ */
+extern LZMA_API(lzma_vli) lzma_index_hash_size(
+               const lzma_index_hash *index_hash)
+               lzma_nothrow lzma_attr_pure;
diff --git a/lzma/api/lzma/lzma12.h b/lzma/api/lzma/lzma12.h
new file mode 100644 (file)
index 0000000..4e32fa3
--- /dev/null
@@ -0,0 +1,420 @@
+/**
+ * \file        lzma/lzma12.h
+ * \brief       LZMA1 and LZMA2 filters
+ */
+
+/*
+ * Author: Lasse Collin
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ *
+ * See ../lzma.h for information about liblzma as a whole.
+ */
+
+#ifndef LZMA_H_INTERNAL
+#      error Never include this file directly. Use <lzma.h> instead.
+#endif
+
+
+/**
+ * \brief       LZMA1 Filter ID
+ *
+ * LZMA1 is the very same thing as what was called just LZMA in LZMA Utils,
+ * 7-Zip, and LZMA SDK. It's called LZMA1 here to prevent developers from
+ * accidentally using LZMA when they actually want LZMA2.
+ *
+ * LZMA1 shouldn't be used for new applications unless you _really_ know
+ * what you are doing. LZMA2 is almost always a better choice.
+ */
+#define LZMA_FILTER_LZMA1       LZMA_VLI_C(0x4000000000000001)
+
+/**
+ * \brief       LZMA2 Filter ID
+ *
+ * Usually you want this instead of LZMA1. Compared to LZMA1, LZMA2 adds
+ * support for LZMA_SYNC_FLUSH, uncompressed chunks (smaller expansion
+ * when trying to compress uncompressible data), possibility to change
+ * lc/lp/pb in the middle of encoding, and some other internal improvements.
+ */
+#define LZMA_FILTER_LZMA2       LZMA_VLI_C(0x21)
+
+
+/**
+ * \brief       Match finders
+ *
+ * Match finder has major effect on both speed and compression ratio.
+ * Usually hash chains are faster than binary trees.
+ *
+ * If you will use LZMA_SYNC_FLUSH often, the hash chains may be a better
+ * choice, because binary trees get much higher compression ratio penalty
+ * with LZMA_SYNC_FLUSH.
+ *
+ * The memory usage formulas are only rough estimates, which are closest to
+ * reality when dict_size is a power of two. The formulas are  more complex
+ * in reality, and can also change a little between liblzma versions. Use
+ * lzma_raw_encoder_memusage() to get more accurate estimate of memory usage.
+ */
+typedef enum {
+       LZMA_MF_HC3     = 0x03,
+               /**<
+                * \brief       Hash Chain with 2- and 3-byte hashing
+                *
+                * Minimum nice_len: 3
+                *
+                * Memory usage:
+                *  - dict_size <= 16 MiB: dict_size * 7.5
+                *  - dict_size > 16 MiB: dict_size * 5.5 + 64 MiB
+                */
+
+       LZMA_MF_HC4     = 0x04,
+               /**<
+                * \brief       Hash Chain with 2-, 3-, and 4-byte hashing
+                *
+                * Minimum nice_len: 4
+                *
+                * Memory usage:
+                *  - dict_size <= 32 MiB: dict_size * 7.5
+                *  - dict_size > 32 MiB: dict_size * 6.5
+                */
+
+       LZMA_MF_BT2     = 0x12,
+               /**<
+                * \brief       Binary Tree with 2-byte hashing
+                *
+                * Minimum nice_len: 2
+                *
+                * Memory usage: dict_size * 9.5
+                */
+
+       LZMA_MF_BT3     = 0x13,
+               /**<
+                * \brief       Binary Tree with 2- and 3-byte hashing
+                *
+                * Minimum nice_len: 3
+                *
+                * Memory usage:
+                *  - dict_size <= 16 MiB: dict_size * 11.5
+                *  - dict_size > 16 MiB: dict_size * 9.5 + 64 MiB
+                */
+
+       LZMA_MF_BT4     = 0x14
+               /**<
+                * \brief       Binary Tree with 2-, 3-, and 4-byte hashing
+                *
+                * Minimum nice_len: 4
+                *
+                * Memory usage:
+                *  - dict_size <= 32 MiB: dict_size * 11.5
+                *  - dict_size > 32 MiB: dict_size * 10.5
+                */
+} lzma_match_finder;
+
+
+/**
+ * \brief       Test if given match finder is supported
+ *
+ * Return 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_API(lzma_bool) lzma_mf_is_supported(lzma_match_finder match_finder)
+               lzma_nothrow lzma_attr_const;
+
+
+/**
+ * \brief       Compression modes
+ *
+ * This selects the function used to analyze the data produced by the match
+ * finder.
+ */
+typedef enum {
+       LZMA_MODE_FAST = 1,
+               /**<
+                * \brief       Fast compression
+                *
+                * Fast mode is usually at its best when combined with
+                * a hash chain match finder.
+                */
+
+       LZMA_MODE_NORMAL = 2
+               /**<
+                * \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 LZMA1 or LZMA2 encoder.
+                */
+} lzma_mode;
+
+
+/**
+ * \brief       Test if given compression mode is supported
+ *
+ * Return 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_API(lzma_bool) lzma_mode_is_supported(lzma_mode mode)
+               lzma_nothrow lzma_attr_const;
+
+
+/**
+ * \brief       Options specific to the LZMA1 and LZMA2 filters
+ *
+ * Since LZMA1 and LZMA2 share most of the code, it's simplest to share
+ * the options structure too. For encoding, all but the reserved variables
+ * need to be initialized unless specifically mentioned otherwise.
+ * lzma_lzma_preset() can be used to get a good starting point.
+ *
+ * For raw decoding, both LZMA1 and LZMA2 need dict_size, preset_dict, and
+ * preset_dict_size (if preset_dict != NULL). LZMA1 needs also lc, lp, and pb.
+ */
+typedef struct {
+       /**
+        * \brief       Dictionary size in bytes
+        *
+        * Dictionary size indicates how many bytes of the recently processed
+        * uncompressed data is kept in memory. One method to reduce size of
+        * the uncompressed data is to store distance-length pairs, which
+        * indicate what data to repeat from the dictionary buffer. Thus,
+        * the bigger the dictionary, the better the compression ratio
+        * usually is.
+        *
+        * Maximum size of the dictionary depends on multiple things:
+        *  - Memory usage limit
+        *  - Available address space (not a problem on 64-bit systems)
+        *  - Selected match finder (encoder only)
+        *
+        * Currently the maximum dictionary size for encoding is 1.5 GiB
+        * (i.e. (UINT32_C(1) << 30) + (UINT32_C(1) << 29)) even on 64-bit
+        * systems for certain match finder implementation reasons. In the
+        * future, there may be match finders that support bigger
+        * dictionaries.
+        *
+        * Decoder already supports dictionaries up to 4 GiB - 1 B (i.e.
+        * UINT32_MAX), so increasing the maximum dictionary size of the
+        * encoder won't cause problems for old decoders.
+        *
+        * Because extremely small dictionaries sizes would have unneeded
+        * overhead in the decoder, the minimum dictionary size is 4096 bytes.
+        *
+        * \note        When decoding, too big dictionary does no other harm
+        *              than wasting memory.
+        */
+       uint32_t dict_size;
+#      define LZMA_DICT_SIZE_MIN       UINT32_C(4096)
+#      define LZMA_DICT_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. It is useful when compressing many
+        * similar, relatively small chunks of data independently from
+        * each other. The preset dictionary should contain typical
+        * strings that occur in the files being compressed. The most
+        * probable strings should be near the end of the preset dictionary.
+        *
+        * This feature should be used only in special situations. For
+        * now, 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 .xz or .lzma file with preset dictionary, it
+        * cannot be decoded with the regular decoder functions. In the
+        * future, the .xz format will likely get support for preset
+        * dictionary though.
+        */
+       const uint8_t *preset_dict;
+
+       /**
+        * \brief       Size of the preset dictionary
+        *
+        * Specifies the size of the preset dictionary. If the size is
+        * bigger than dict_size, only the last dict_size bytes are
+        * processed.
+        *
+        * This variable is read only when preset_dict is not NULL.
+        * If preset_dict is not NULL but preset_dict_size is zero,
+        * no preset dictionary is used (identical to only setting
+        * preset_dict to NULL).
+        */
+       uint32_t preset_dict_size;
+
+       /**
+        * \brief       Number of literal context bits
+        *
+        * How many of the highest bits of the previous uncompressed
+        * eight-bit byte (also known as `literal') are taken into
+        * account when predicting the bits of the next literal.
+        *
+        * E.g. in typical English text, an upper-case letter is
+        * often followed by a lower-case letter, and a lower-case
+        * letter is usually followed by another lower-case letter.
+        * In the US-ASCII character set, the highest three bits are 010
+        * for upper-case letters and 011 for lower-case letters.
+        * When lc is at least 3, the literal coding can take advantage of
+        * this property in the uncompressed data.
+        *
+        * There is a limit that applies to literal context bits and literal
+        * position bits together: lc + lp <= 4. Without this limit the
+        * decoding could become very slow, which could have security related
+        * results in some cases like email servers doing virus scanning.
+        * This limit also simplifies the internal implementation in liblzma.
+        *
+        * There may be LZMA1 streams that have lc + lp > 4 (maximum possible
+        * lc would be 8). It is not possible to decode such streams with
+        * liblzma.
+        */
+       uint32_t lc;
+#      define LZMA_LCLP_MIN    0
+#      define LZMA_LCLP_MAX    4
+#      define LZMA_LC_DEFAULT  3
+
+       /**
+        * \brief       Number of literal position bits
+        *
+        * lp affects what kind of alignment in the uncompressed data is
+        * assumed when encoding literals. A literal is a single 8-bit byte.
+        * See pb below for more information about alignment.
+        */
+       uint32_t lp;
+#      define LZMA_LP_DEFAULT  0
+
+       /**
+        * \brief       Number of position bits
+        *
+        * pb affects what kind of alignment in the uncompressed data is
+        * assumed in general. The default means four-byte alignment
+        * (2^ pb =2^2=4), which is often a good choice when there's
+        * no better guess.
+        *
+        * When the aligment is known, setting pb accordingly may reduce
+        * the file size a little. E.g. with text files having one-byte
+        * alignment (US-ASCII, ISO-8859-*, UTF-8), setting pb=0 can
+        * improve compression slightly. For UTF-16 text, pb=1 is a good
+        * choice. If the alignment is an odd number like 3 bytes, pb=0
+        * might be the best choice.
+        *
+        * Even though the assumed alignment can be adjusted with pb and
+        * lp, LZMA1 and LZMA2 still slightly favor 16-byte alignment.
+        * It might be worth taking into account when designing file formats
+        * that are likely to be often compressed with LZMA1 or LZMA2.
+        */
+       uint32_t pb;
+#      define LZMA_PB_MIN      0
+#      define LZMA_PB_MAX      4
+#      define LZMA_PB_DEFAULT  2
+
+       /** Compression mode */
+       lzma_mode mode;
+
+       /**
+        * \brief       Nice length of a match
+        *
+        * This determines how many bytes the encoder compares from the match
+        * candidates when looking for the best match. Once a match of at
+        * least nice_len bytes long is found, the encoder stops looking for
+        * better candidates and encodes the match. (Naturally, if the found
+        * match is actually longer than nice_len, the actual length is
+        * encoded; it's not truncated to nice_len.)
+        *
+        * Bigger values usually increase the compression ratio and
+        * compression time. For most files, 32 to 128 is a good value,
+        * which gives very good compression ratio at good speed.
+        *
+        * The exact minimum value depends on the match finder. The maximum
+        * is 273, which is the maximum length of a match that LZMA1 and
+        * LZMA2 can encode.
+        */
+       uint32_t nice_len;
+
+       /** Match finder ID */
+       lzma_match_finder mf;
+
+       /**
+        * \brief       Maximum search depth in the match finder
+        *
+        * For every input byte, match finder searches through the hash chain
+        * or binary tree in a loop, each iteration going one step deeper in
+        * the chain or tree. The searching stops if
+        *  - a match of at least nice_len bytes long is found;
+        *  - all match candidates from the hash chain or binary tree have
+        *    been checked; or
+        *  - maximum search depth is reached.
+        *
+        * Maximum search depth is needed to prevent the match finder from
+        * wasting too much time in case there are lots of short match
+        * candidates. On the other hand, stopping the search before all
+        * candidates have been checked can reduce compression ratio.
+        *
+        * Setting depth to zero tells liblzma to use an automatic default
+        * value, that depends on the selected match finder and nice_len.
+        * The default is in the range [4, 200] or so (it may vary between
+        * liblzma versions).
+        *
+        * Using a bigger depth value than the default can increase
+        * compression ratio in some cases. There is no strict maximum value,
+        * but high values (thousands or millions) should be used with care:
+        * the encoder could remain fast enough with typical input, but
+        * malicious input could cause the match finder to slow down
+        * dramatically, possibly creating a denial of service attack.
+        */
+       uint32_t depth;
+
+       /*
+        * Reserved space to allow possible future extensions without
+        * breaking the ABI. 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;
+       uint32_t reserved_int5;
+       uint32_t reserved_int6;
+       uint32_t reserved_int7;
+       uint32_t reserved_int8;
+       lzma_reserved_enum reserved_enum1;
+       lzma_reserved_enum reserved_enum2;
+       lzma_reserved_enum reserved_enum3;
+       lzma_reserved_enum reserved_enum4;
+       void *reserved_ptr1;
+       void *reserved_ptr2;
+
+} lzma_options_lzma;
+
+
+/**
+ * \brief       Set a compression preset to lzma_options_lzma structure
+ *
+ * 0 is the fastest and 9 is the slowest. These match the switches -0 .. -9
+ * of the xz command line tool. In addition, it is possible to bitwise-or
+ * flags to the preset. Currently only LZMA_PRESET_EXTREME is supported.
+ * The flags are defined in container.h, because the flags are used also
+ * with lzma_easy_encoder().
+ *
+ * The preset values are subject to changes between liblzma versions.
+ *
+ * This function is available only if LZMA1 or LZMA2 encoder has been enabled
+ * when building liblzma.
+ *
+ * \return      On success, false is returned. If the preset is not
+ *              supported, true is returned.
+ */
+extern LZMA_API(lzma_bool) lzma_lzma_preset(
+               lzma_options_lzma *options, uint32_t preset) lzma_nothrow;
diff --git a/lzma/api/lzma/stream_flags.h b/lzma/api/lzma/stream_flags.h
new file mode 100644 (file)
index 0000000..bbdd408
--- /dev/null
@@ -0,0 +1,223 @@
+/**
+ * \file        lzma/stream_flags.h
+ * \brief       .xz Stream Header and Stream Footer encoder and decoder
+ */
+
+/*
+ * Author: Lasse Collin
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ *
+ * See ../lzma.h for information about liblzma as a whole.
+ */
+
+#ifndef LZMA_H_INTERNAL
+#      error Never include this file directly. Use <lzma.h> instead.
+#endif
+
+
+/**
+ * \brief       Size of Stream Header and Stream Footer
+ *
+ * Stream Header and Stream Footer have the same size and they are not
+ * going to change even if a newer version of the .xz file format is
+ * developed in future.
+ */
+#define LZMA_STREAM_HEADER_SIZE 12
+
+
+/**
+ * \brief       Options for encoding/decoding Stream Header and Stream Footer
+ */
+typedef struct {
+       /**
+        * \brief       Stream Flags format version
+        *
+        * To prevent API and ABI breakages if new features are needed in
+        * Stream Header or Stream Footer, a version number is used to
+        * indicate which fields in this structure are in use. For now,
+        * version must always be zero. With non-zero version, the
+        * lzma_stream_header_encode() and lzma_stream_footer_encode()
+        * will return LZMA_OPTIONS_ERROR.
+        *
+        * lzma_stream_header_decode() and lzma_stream_footer_decode()
+        * will always set this to the lowest value that supports all the
+        * features indicated by the Stream Flags field. The application
+        * must check that the version number set by the decoding functions
+        * is supported by the application. Otherwise it is possible that
+        * the application will decode the Stream incorrectly.
+        */
+       uint32_t version;
+
+       /**
+        * \brief       Backward Size
+        *
+        * Backward Size must be a multiple of four bytes. In this Stream
+        * format version, Backward Size is the size of the Index field.
+        *
+        * Backward Size isn't actually part of the Stream Flags field, but
+        * it is convenient to include in this structure anyway. Backward
+        * Size is present only in the Stream Footer. There is no need to
+        * initialize backward_size when encoding Stream Header.
+        *
+        * lzma_stream_header_decode() always sets backward_size to
+        * LZMA_VLI_UNKNOWN so that it is convenient to use
+        * lzma_stream_flags_compare() when both Stream Header and Stream
+        * Footer have been decoded.
+        */
+       lzma_vli backward_size;
+#      define LZMA_BACKWARD_SIZE_MIN 4
+#      define LZMA_BACKWARD_SIZE_MAX (LZMA_VLI_C(1) << 34)
+
+       /**
+        * \brief       Check ID
+        *
+        * This indicates the type of the integrity check calculated from
+        * uncompressed data.
+        */
+       lzma_check check;
+
+       /*
+        * Reserved space to allow possible future extensions without
+        * breaking the ABI. You should not touch these, because the
+        * names of these variables may change.
+        *
+        * (We will never be able to use all of these since Stream Flags
+        * is just two bytes plus Backward Size of four bytes. But it's
+        * nice to have the proper types when they are needed.)
+        */
+       lzma_reserved_enum reserved_enum1;
+       lzma_reserved_enum reserved_enum2;
+       lzma_reserved_enum reserved_enum3;
+       lzma_reserved_enum reserved_enum4;
+       lzma_bool reserved_bool1;
+       lzma_bool reserved_bool2;
+       lzma_bool reserved_bool3;
+       lzma_bool reserved_bool4;
+       lzma_bool reserved_bool5;
+       lzma_bool reserved_bool6;
+       lzma_bool reserved_bool7;
+       lzma_bool reserved_bool8;
+       uint32_t reserved_int1;
+       uint32_t reserved_int2;
+
+} lzma_stream_flags;
+
+
+/**
+ * \brief       Encode Stream Header
+ *
+ * \param       options     Stream Header options to be encoded.
+ *                          options->backward_size is ignored and doesn't
+ *                          need to be initialized.
+ * \param       out         Beginning of the output buffer of
+ *                          LZMA_STREAM_HEADER_SIZE bytes.
+ *
+ * \return      - LZMA_OK: Encoding was successful.
+ *              - LZMA_OPTIONS_ERROR: options->version is not supported by
+ *                this liblzma version.
+ *              - LZMA_PROG_ERROR: Invalid options.
+ */
+extern LZMA_API(lzma_ret) lzma_stream_header_encode(
+               const lzma_stream_flags *options, uint8_t *out)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Encode Stream Footer
+ *
+ * \param       options     Stream Footer options to be encoded.
+ * \param       out         Beginning of the output buffer of
+ *                          LZMA_STREAM_HEADER_SIZE bytes.
+ *
+ * \return      - LZMA_OK: Encoding was successful.
+ *              - LZMA_OPTIONS_ERROR: options->version is not supported by
+ *                this liblzma version.
+ *              - LZMA_PROG_ERROR: Invalid options.
+ */
+extern LZMA_API(lzma_ret) lzma_stream_footer_encode(
+               const lzma_stream_flags *options, uint8_t *out)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Decode Stream Header
+ *
+ * \param       options     Target for the decoded Stream Header options.
+ * \param       in          Beginning of the input buffer of
+ *                          LZMA_STREAM_HEADER_SIZE bytes.
+ *
+ * options->backward_size is always set to LZMA_VLI_UNKNOWN. This is to
+ * help comparing Stream Flags from Stream Header and Stream Footer with
+ * lzma_stream_flags_compare().
+ *
+ * \return      - LZMA_OK: Decoding was successful.
+ *              - LZMA_FORMAT_ERROR: Magic bytes don't match, thus the given
+ *                buffer cannot be Stream Header.
+ *              - LZMA_DATA_ERROR: CRC32 doesn't match, thus the header
+ *                is corrupt.
+ *              - LZMA_OPTIONS_ERROR: Unsupported options are present
+ *                in the header.
+ *
+ * \note        When decoding .xz files that contain multiple Streams, it may
+ *              make sense to print "file format not recognized" only if
+ *              decoding of the Stream Header of the _first_ Stream gives
+ *              LZMA_FORMAT_ERROR. If non-first Stream Header gives
+ *              LZMA_FORMAT_ERROR, the message used for LZMA_DATA_ERROR is
+ *              probably more appropriate.
+ *
+ *              For example, Stream decoder in liblzma uses LZMA_DATA_ERROR if
+ *              LZMA_FORMAT_ERROR is returned by lzma_stream_header_decode()
+ *              when decoding non-first Stream.
+ */
+extern LZMA_API(lzma_ret) lzma_stream_header_decode(
+               lzma_stream_flags *options, const uint8_t *in)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Decode Stream Footer
+ *
+ * \param       options     Target for the decoded Stream Header options.
+ * \param       in          Beginning of the input buffer of
+ *                          LZMA_STREAM_HEADER_SIZE bytes.
+ *
+ * \return      - LZMA_OK: Decoding was successful.
+ *              - LZMA_FORMAT_ERROR: Magic bytes don't match, thus the given
+ *                buffer cannot be Stream Footer.
+ *              - LZMA_DATA_ERROR: CRC32 doesn't match, thus the Stream Footer
+ *                is corrupt.
+ *              - LZMA_OPTIONS_ERROR: Unsupported options are present
+ *                in Stream Footer.
+ *
+ * \note        If Stream Header was already decoded successfully, but
+ *              decoding Stream Footer returns LZMA_FORMAT_ERROR, the
+ *              application should probably report some other error message
+ *              than "file format not recognized", since the file more likely
+ *              is corrupt (possibly truncated). Stream decoder in liblzma
+ *              uses LZMA_DATA_ERROR in this situation.
+ */
+extern LZMA_API(lzma_ret) lzma_stream_footer_decode(
+               lzma_stream_flags *options, const uint8_t *in)
+               lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Compare two lzma_stream_flags structures
+ *
+ * backward_size values are compared only if both are not
+ * LZMA_VLI_UNKNOWN.
+ *
+ * \return      - LZMA_OK: Both are equal. If either had backward_size set
+ *                to LZMA_VLI_UNKNOWN, backward_size values were not
+ *                compared or validated.
+ *              - LZMA_DATA_ERROR: The structures differ.
+ *              - LZMA_OPTIONS_ERROR: version in either structure is greater
+ *                than the maximum supported version (currently zero).
+ *              - LZMA_PROG_ERROR: Invalid value, e.g. invalid check or
+ *                backward_size.
+ */
+extern LZMA_API(lzma_ret) lzma_stream_flags_compare(
+               const lzma_stream_flags *a, const lzma_stream_flags *b)
+               lzma_nothrow lzma_attr_pure;
diff --git a/lzma/api/lzma/version.h b/lzma/api/lzma/version.h
new file mode 100644 (file)
index 0000000..2c26ed2
--- /dev/null
@@ -0,0 +1,121 @@
+/**
+ * \file        lzma/version.h
+ * \brief       Version number
+ */
+
+/*
+ * Author: Lasse Collin
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ *
+ * See ../lzma.h for information about liblzma as a whole.
+ */
+
+#ifndef LZMA_H_INTERNAL
+#      error Never include this file directly. Use <lzma.h> instead.
+#endif
+
+
+/*
+ * Version number split into components
+ */
+#define LZMA_VERSION_MAJOR 5
+#define LZMA_VERSION_MINOR 3
+#define LZMA_VERSION_PATCH 0
+#define LZMA_VERSION_STABILITY LZMA_VERSION_STABILITY_ALPHA
+
+#ifndef LZMA_VERSION_COMMIT
+#      define LZMA_VERSION_COMMIT ""
+#endif
+
+
+/*
+ * Map symbolic stability levels to integers.
+ */
+#define LZMA_VERSION_STABILITY_ALPHA 0
+#define LZMA_VERSION_STABILITY_BETA 1
+#define LZMA_VERSION_STABILITY_STABLE 2
+
+
+/**
+ * \brief       Compile-time version number
+ *
+ * The version number is of format xyyyzzzs where
+ *  - x = major
+ *  - yyy = minor
+ *  - zzz = revision
+ *  - s indicates stability: 0 = alpha, 1 = beta, 2 = stable
+ *
+ * The same xyyyzzz triplet is never reused with different stability levels.
+ * For example, if 5.1.0alpha has been released, there will never be 5.1.0beta
+ * or 5.1.0 stable.
+ *
+ * \note        The version number of liblzma has nothing to with
+ *              the version number of Igor Pavlov's LZMA SDK.
+ */
+#define LZMA_VERSION (LZMA_VERSION_MAJOR * UINT32_C(10000000) \
+               + LZMA_VERSION_MINOR * UINT32_C(10000) \
+               + LZMA_VERSION_PATCH * UINT32_C(10) \
+               + LZMA_VERSION_STABILITY)
+
+
+/*
+ * Macros to construct the compile-time version string
+ */
+#if LZMA_VERSION_STABILITY == LZMA_VERSION_STABILITY_ALPHA
+#      define LZMA_VERSION_STABILITY_STRING "alpha"
+#elif LZMA_VERSION_STABILITY == LZMA_VERSION_STABILITY_BETA
+#      define LZMA_VERSION_STABILITY_STRING "beta"
+#elif LZMA_VERSION_STABILITY == LZMA_VERSION_STABILITY_STABLE
+#      define LZMA_VERSION_STABILITY_STRING ""
+#else
+#      error Incorrect LZMA_VERSION_STABILITY
+#endif
+
+#define LZMA_VERSION_STRING_C_(major, minor, patch, stability, commit) \
+               #major "." #minor "." #patch stability commit
+
+#define LZMA_VERSION_STRING_C(major, minor, patch, stability, commit) \
+               LZMA_VERSION_STRING_C_(major, minor, patch, stability, commit)
+
+
+/**
+ * \brief       Compile-time version as a string
+ *
+ * This can be for example "4.999.5alpha", "4.999.8beta", or "5.0.0" (stable
+ * versions don't have any "stable" suffix). In future, a snapshot built
+ * from source code repository may include an additional suffix, for example
+ * "4.999.8beta-21-g1d92". The commit ID won't be available in numeric form
+ * in LZMA_VERSION macro.
+ */
+#define LZMA_VERSION_STRING LZMA_VERSION_STRING_C( \
+               LZMA_VERSION_MAJOR, LZMA_VERSION_MINOR, \
+               LZMA_VERSION_PATCH, LZMA_VERSION_STABILITY_STRING, \
+               LZMA_VERSION_COMMIT)
+
+
+/* #ifndef is needed for use with windres (MinGW or Cygwin). */
+#ifndef LZMA_H_INTERNAL_RC
+
+/**
+ * \brief       Run-time version number as an integer
+ *
+ * Return the value of LZMA_VERSION macro at the compile time of liblzma.
+ * This allows the application to compare if it was built against the same,
+ * older, or newer version of liblzma that is currently running.
+ */
+extern LZMA_API(uint32_t) lzma_version_number(void)
+               lzma_nothrow lzma_attr_const;
+
+
+/**
+ * \brief       Run-time version as a string
+ *
+ * This function may be useful if you want to display which version of
+ * liblzma your application is currently using.
+ */
+extern LZMA_API(const char *) lzma_version_string(void)
+               lzma_nothrow lzma_attr_const;
+
+#endif
diff --git a/lzma/api/lzma/vli.h b/lzma/api/lzma/vli.h
new file mode 100644 (file)
index 0000000..9ad13f2
--- /dev/null
@@ -0,0 +1,166 @@
+/**
+ * \file        lzma/vli.h
+ * \brief       Variable-length integer handling
+ *
+ * In the .xz format, most integers are encoded in a variable-length
+ * representation, which is sometimes called little endian base-128 encoding.
+ * This saves space when smaller values are more likely than bigger values.
+ *
+ * The encoding scheme encodes seven bits to every byte, using minimum
+ * number of bytes required to represent the given value. Encodings that use
+ * non-minimum number of bytes are invalid, thus every integer has exactly
+ * one encoded representation. The maximum number of bits in a VLI is 63,
+ * thus the vli argument must be less than or equal to UINT64_MAX / 2. You
+ * should use LZMA_VLI_MAX for clarity.
+ */
+
+/*
+ * Author: Lasse Collin
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ *
+ * See ../lzma.h for information about liblzma as a whole.
+ */
+
+#ifndef LZMA_H_INTERNAL
+#      error Never include this file directly. Use <lzma.h> instead.
+#endif
+
+
+/**
+ * \brief       Maximum supported value of a variable-length integer
+ */
+#define LZMA_VLI_MAX (UINT64_MAX / 2)
+
+/**
+ * \brief       VLI value to denote that the value is unknown
+ */
+#define LZMA_VLI_UNKNOWN UINT64_MAX
+
+/**
+ * \brief       Maximum supported encoded length of variable length integers
+ */
+#define LZMA_VLI_BYTES_MAX 9
+
+/**
+ * \brief       VLI constant suffix
+ */
+#define LZMA_VLI_C(n) UINT64_C(n)
+
+
+/**
+ * \brief       Variable-length integer type
+ *
+ * Valid VLI values are in the range [0, LZMA_VLI_MAX]. Unknown value is
+ * indicated with LZMA_VLI_UNKNOWN, which is the maximum value of the
+ * underlaying integer type.
+ *
+ * lzma_vli will be uint64_t for the foreseeable future. If a bigger size
+ * is needed in the future, it is guaranteed that 2 * LZMA_VLI_MAX will
+ * not overflow lzma_vli. This simplifies integer overflow detection.
+ */
+typedef uint64_t lzma_vli;
+
+
+/**
+ * \brief       Validate a variable-length integer
+ *
+ * This is useful to test that application has given acceptable values
+ * for example in the uncompressed_size and compressed_size variables.
+ *
+ * \return      True if the integer is representable as VLI or if it
+ *              indicates unknown value.
+ */
+#define lzma_vli_is_valid(vli) \
+       ((vli) <= LZMA_VLI_MAX || (vli) == LZMA_VLI_UNKNOWN)
+
+
+/**
+ * \brief       Encode a variable-length integer
+ *
+ * This function has two modes: single-call and multi-call. Single-call mode
+ * encodes the whole integer at once; it is an error if the output buffer is
+ * too small. Multi-call mode saves the position in *vli_pos, and thus it is
+ * possible to continue encoding if the buffer becomes full before the whole
+ * integer has been encoded.
+ *
+ * \param       vli       Integer to be encoded
+ * \param       vli_pos   How many VLI-encoded bytes have already been written
+ *                        out. When starting to encode a new integer in
+ *                        multi-call mode, *vli_pos must be set to zero.
+ *                        To use single-call encoding, set vli_pos to NULL.
+ * \param       out       Beginning of the output buffer
+ * \param       out_pos   The next byte will be written to out[*out_pos].
+ * \param       out_size  Size of the out buffer; the first byte into
+ *                        which no data is written to is out[out_size].
+ *
+ * \return      Slightly different return values are used in multi-call and
+ *              single-call modes.
+ *
+ *              Single-call (vli_pos == NULL):
+ *              - LZMA_OK: Integer successfully encoded.
+ *              - LZMA_PROG_ERROR: Arguments are not sane. This can be due
+ *                to too little output space; single-call mode doesn't use
+ *                LZMA_BUF_ERROR, since the application should have checked
+ *                the encoded size with lzma_vli_size().
+ *
+ *              Multi-call (vli_pos != NULL):
+ *              - LZMA_OK: So far all OK, but the integer is not
+ *                completely written out yet.
+ *              - LZMA_STREAM_END: Integer successfully encoded.
+ *              - LZMA_BUF_ERROR: No output space was provided.
+ *              - LZMA_PROG_ERROR: Arguments are not sane.
+ */
+extern LZMA_API(lzma_ret) lzma_vli_encode(lzma_vli vli, size_t *vli_pos,
+               uint8_t *out, size_t *out_pos, size_t out_size) lzma_nothrow;
+
+
+/**
+ * \brief       Decode a variable-length integer
+ *
+ * Like lzma_vli_encode(), this function has single-call and multi-call modes.
+ *
+ * \param       vli       Pointer to decoded integer. The decoder will
+ *                        initialize it to zero when *vli_pos == 0, so
+ *                        application isn't required to initialize *vli.
+ * \param       vli_pos   How many bytes have already been decoded. When
+ *                        starting to decode a new integer in multi-call
+ *                        mode, *vli_pos must be initialized to zero. To
+ *                        use single-call decoding, set vli_pos to NULL.
+ * \param       in        Beginning of the input buffer
+ * \param       in_pos    The next byte will be read from in[*in_pos].
+ * \param       in_size   Size of the input buffer; the first byte that
+ *                        won't be read is in[in_size].
+ *
+ * \return      Slightly different return values are used in multi-call and
+ *              single-call modes.
+ *
+ *              Single-call (vli_pos == NULL):
+ *              - LZMA_OK: Integer successfully decoded.
+ *              - LZMA_DATA_ERROR: Integer is corrupt. This includes hitting
+ *                the end of the input buffer before the whole integer was
+ *                decoded; providing no input at all will use LZMA_DATA_ERROR.
+ *              - LZMA_PROG_ERROR: Arguments are not sane.
+ *
+ *              Multi-call (vli_pos != NULL):
+ *              - LZMA_OK: So far all OK, but the integer is not
+ *                completely decoded yet.
+ *              - LZMA_STREAM_END: Integer successfully decoded.
+ *              - LZMA_DATA_ERROR: Integer is corrupt.
+ *              - LZMA_BUF_ERROR: No input was provided.
+ *              - LZMA_PROG_ERROR: Arguments are not sane.
+ */
+extern LZMA_API(lzma_ret) lzma_vli_decode(lzma_vli *vli, size_t *vli_pos,
+               const uint8_t *in, size_t *in_pos, size_t in_size)
+               lzma_nothrow;
+
+
+/**
+ * \brief       Get the number of bytes required to encode a VLI
+ *
+ * \return      Number of bytes on success (1-9). If vli isn't valid,
+ *              zero is returned.
+ */
+extern LZMA_API(uint32_t) lzma_vli_size(lzma_vli vli)
+               lzma_nothrow lzma_attr_pure;
diff --git a/lzma/api/sysdefs.h b/lzma/api/sysdefs.h
new file mode 100644 (file)
index 0000000..23b7ad2
--- /dev/null
@@ -0,0 +1,203 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       sysdefs.h
+/// \brief      Common includes, definitions, system-specific things etc.
+///
+/// This file is used also by the lzma command line tool, that's why this
+/// file is separate from common.h.
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_SYSDEFS_H
+#define LZMA_SYSDEFS_H
+
+//////////////
+// Includes //
+//////////////
+
+#ifdef HAVE_CONFIG_H
+#      include <config.h>
+#endif
+
+// Get standard-compliant stdio functions under MinGW and MinGW-w64.
+#ifdef __MINGW32__
+#      define __USE_MINGW_ANSI_STDIO 1
+#endif
+
+// size_t and NULL
+#include <stddef.h>
+
+#ifdef HAVE_INTTYPES_H
+#      include <inttypes.h>
+#endif
+
+// C99 says that inttypes.h always includes stdint.h, but some systems
+// don't do that, and require including stdint.h separately.
+//#ifdef HAVE_STDINT_H
+#      include <stdint.h>
+//#endif
+
+// Some pre-C99 systems have SIZE_MAX in limits.h instead of stdint.h. The
+// limits are also used to figure out some macros missing from pre-C99 systems.
+#ifdef HAVE_LIMITS_H
+#      include <limits.h>
+#endif
+
+// Be more compatible with systems that have non-conforming inttypes.h.
+// We assume that int is 32-bit and that long is either 32-bit or 64-bit.
+// Full Autoconf test could be more correct, but this should work well enough.
+// Note that this duplicates some code from lzma.h, but this is better since
+// we can work without inttypes.h thanks to Autoconf tests.
+#ifndef UINT32_C
+#      if UINT_MAX != 4294967295U
+#              error UINT32_C is not defined and unsigned int is not 32-bit.
+#      endif
+#      define UINT32_C(n) n ## U
+#endif
+#ifndef UINT32_MAX
+#      define UINT32_MAX UINT32_C(4294967295)
+#endif
+#ifndef PRIu32
+#      define PRIu32 "u"
+#endif
+#ifndef PRIx32
+#      define PRIx32 "x"
+#endif
+#ifndef PRIX32
+#      define PRIX32 "X"
+#endif
+
+#if ULONG_MAX == 4294967295UL
+#      ifndef UINT64_C
+#              define UINT64_C(n) n ## ULL
+#      endif
+#      ifndef PRIu64
+#              define PRIu64 "llu"
+#      endif
+#      ifndef PRIx64
+#              define PRIx64 "llx"
+#      endif
+#      ifndef PRIX64
+#              define PRIX64 "llX"
+#      endif
+#else
+#      ifndef UINT64_C
+#              define UINT64_C(n) n ## UL
+#      endif
+#      ifndef PRIu64
+#              define PRIu64 "lu"
+#      endif
+#      ifndef PRIx64
+#              define PRIx64 "lx"
+#      endif
+#      ifndef PRIX64
+#              define PRIX64 "lX"
+#      endif
+#endif
+#ifndef UINT64_MAX
+#      define UINT64_MAX UINT64_C(18446744073709551615)
+#endif
+
+// Incorrect(?) SIZE_MAX:
+//   - Interix headers typedef size_t to unsigned long,
+//     but a few lines later define SIZE_MAX to INT32_MAX.
+//   - SCO OpenServer (x86) headers typedef size_t to unsigned int
+//     but define SIZE_MAX to INT32_MAX.
+#if defined(__INTERIX) || defined(_SCO_DS)
+#      undef SIZE_MAX
+#endif
+
+// The code currently assumes that size_t is either 32-bit or 64-bit.
+#ifndef SIZE_MAX
+#      if SIZEOF_SIZE_T == 4
+#              define SIZE_MAX UINT32_MAX
+#      elif SIZEOF_SIZE_T == 8
+#              define SIZE_MAX UINT64_MAX
+#      else
+#              error size_t is not 32-bit or 64-bit
+#      endif
+#endif
+#if SIZE_MAX != UINT32_MAX && SIZE_MAX != UINT64_MAX
+#      error size_t is not 32-bit or 64-bit
+#endif
+
+#include <stdlib.h>
+#include <assert.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);
+//
+#      include <stdbool.h>
+#if 0
+#ifdef HAVE_STDBOOL_H
+#      include <stdbool.h>
+#else
+#      if ! HAVE__BOOL
+typedef unsigned char _Bool;
+#      endif
+#      define bool _Bool
+#      define false 0
+#      define true 1
+#      define __bool_true_false_are_defined 1
+#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.
+#include <string.h>
+
+#ifdef HAVE_STRINGS_H
+#      include <strings.h>
+#endif
+
+#ifdef HAVE_MEMORY_H
+#      include <memory.h>
+#endif
+
+// As of MSVC 2013, inline and restrict are supported with
+// non-standard keywords.
+#if defined(_WIN32) && defined(_MSC_VER)
+#      ifndef inline
+#              define inline __inline
+#      endif
+#      ifndef restrict
+#              define restrict __restrict
+#      endif
+#endif
+
+////////////
+// Macros //
+////////////
+
+#undef memzero
+#define memzero(s, n) memset(s, 0, n)
+
+// NOTE: Avoid using MIN() and MAX(), because even conditionally defining
+// those macros can cause some portability trouble, since on some systems
+// the system headers insist defining their own versions.
+#define my_min(x, y) ((x) < (y) ? (x) : (y))
+#define my_max(x, y) ((x) > (y) ? (x) : (y))
+
+#ifndef ARRAY_SIZE
+#      define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
+#endif
+
+#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4
+#      define lzma_attr_alloc_size(x) __attribute__((__alloc_size__(x)))
+#else
+#      define lzma_attr_alloc_size(x)
+#endif
+
+#endif
diff --git a/lzma/check/check.c b/lzma/check/check.c
new file mode 100644 (file)
index 0000000..428ddae
--- /dev/null
@@ -0,0 +1,174 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       check.c
+/// \brief      Single API to access different integrity checks
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "check.h"
+
+
+extern LZMA_API(lzma_bool)
+lzma_check_is_supported(lzma_check type)
+{
+       if ((unsigned int)(type) > LZMA_CHECK_ID_MAX)
+               return false;
+
+       static const lzma_bool available_checks[LZMA_CHECK_ID_MAX + 1] = {
+               true,   // LZMA_CHECK_NONE
+
+#ifdef HAVE_CHECK_CRC32
+               true,
+#else
+               false,
+#endif
+
+               false,  // Reserved
+               false,  // Reserved
+
+#ifdef HAVE_CHECK_CRC64
+               true,
+#else
+               false,
+#endif
+
+               false,  // Reserved
+               false,  // Reserved
+               false,  // Reserved
+               false,  // Reserved
+               false,  // Reserved
+
+#ifdef HAVE_CHECK_SHA256
+               true,
+#else
+               false,
+#endif
+
+               false,  // Reserved
+               false,  // Reserved
+               false,  // Reserved
+               false,  // Reserved
+               false,  // Reserved
+       };
+
+       return available_checks[(unsigned int)(type)];
+}
+
+
+extern LZMA_API(uint32_t)
+lzma_check_size(lzma_check type)
+{
+       if ((unsigned int)(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 int)(type)];
+}
+
+
+extern void
+lzma_check_init(lzma_check_state *check, lzma_check type)
+{
+       switch (type) {
+       case LZMA_CHECK_NONE:
+               break;
+
+#ifdef HAVE_CHECK_CRC32
+       case LZMA_CHECK_CRC32:
+               check->state.crc32 = 0;
+               break;
+#endif
+
+#ifdef HAVE_CHECK_CRC64
+       case LZMA_CHECK_CRC64:
+               check->state.crc64 = 0;
+               break;
+#endif
+
+#ifdef HAVE_CHECK_SHA256
+       case LZMA_CHECK_SHA256:
+               lzma_sha256_init(check);
+               break;
+#endif
+
+       default:
+               break;
+       }
+
+       return;
+}
+
+
+extern void
+lzma_check_update(lzma_check_state *check, lzma_check type,
+               const uint8_t *buf, size_t size)
+{
+       switch (type) {
+#ifdef HAVE_CHECK_CRC32
+       case LZMA_CHECK_CRC32:
+               check->state.crc32 = lzma_crc32(buf, size, check->state.crc32);
+               break;
+#endif
+
+#ifdef HAVE_CHECK_CRC64
+       case LZMA_CHECK_CRC64:
+               check->state.crc64 = lzma_crc64(buf, size, check->state.crc64);
+               break;
+#endif
+
+#ifdef HAVE_CHECK_SHA256
+       case LZMA_CHECK_SHA256:
+               lzma_sha256_update(buf, size, check);
+               break;
+#endif
+
+       default:
+               break;
+       }
+
+       return;
+}
+
+
+extern void
+lzma_check_finish(lzma_check_state *check, lzma_check type)
+{
+       switch (type) {
+#ifdef HAVE_CHECK_CRC32
+       case LZMA_CHECK_CRC32:
+               check->buffer.u32[0] = conv32le(check->state.crc32);
+               break;
+#endif
+
+#ifdef HAVE_CHECK_CRC64
+       case LZMA_CHECK_CRC64:
+               check->buffer.u64[0] = conv64le(check->state.crc64);
+               break;
+#endif
+
+#ifdef HAVE_CHECK_SHA256
+       case LZMA_CHECK_SHA256:
+               lzma_sha256_finish(check);
+               break;
+#endif
+
+       default:
+               break;
+       }
+
+       return;
+}
diff --git a/lzma/check/check.h b/lzma/check/check.h
new file mode 100644 (file)
index 0000000..3007d88
--- /dev/null
@@ -0,0 +1,172 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       check.h
+/// \brief      Internal API to different integrity check functions
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_CHECK_H
+#define LZMA_CHECK_H
+
+#include "common.h"
+
+// If the function for external SHA-256 is missing, use the internal SHA-256
+// code. Due to how configure works, these defines can only get defined when
+// both a usable header and a type have already been found.
+#if !(defined(HAVE_CC_SHA256_INIT) \
+               || defined(HAVE_SHA256_INIT) \
+               || defined(HAVE_SHA256INIT))
+#      define HAVE_INTERNAL_SHA256 1
+#endif
+
+#if defined(HAVE_INTERNAL_SHA256)
+// Nothing
+#elif defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H)
+#      include <CommonCrypto/CommonDigest.h>
+#elif defined(HAVE_SHA256_H)
+#      include <sys/types.h>
+#      include <sha256.h>
+#elif defined(HAVE_SHA2_H)
+#      include <sys/types.h>
+#      include <sha2.h>
+#endif
+
+#if defined(HAVE_INTERNAL_SHA256)
+/// State for the internal SHA-256 implementation
+typedef struct {
+       /// Internal state
+       uint32_t state[8];
+
+       /// Size of the message excluding padding
+       uint64_t size;
+} lzma_sha256_state;
+#elif defined(HAVE_CC_SHA256_CTX)
+typedef CC_SHA256_CTX lzma_sha256_state;
+#elif defined(HAVE_SHA256_CTX)
+typedef SHA256_CTX lzma_sha256_state;
+#elif defined(HAVE_SHA2_CTX)
+typedef SHA2_CTX lzma_sha256_state;
+#endif
+
+#if defined(HAVE_INTERNAL_SHA256)
+// Nothing
+#elif defined(HAVE_CC_SHA256_INIT)
+#      define LZMA_SHA256FUNC(x) CC_SHA256_ ## x
+#elif defined(HAVE_SHA256_INIT)
+#      define LZMA_SHA256FUNC(x) SHA256_ ## x
+#elif defined(HAVE_SHA256INIT)
+#      define LZMA_SHA256FUNC(x) SHA256 ## x
+#endif
+
+// Index hashing needs the best possible hash function (preferably
+// a cryptographic hash) for maximum reliability.
+#if defined(HAVE_CHECK_SHA256)
+#      define LZMA_CHECK_BEST LZMA_CHECK_SHA256
+#elif defined(HAVE_CHECK_CRC64)
+#      define LZMA_CHECK_BEST LZMA_CHECK_CRC64
+#else
+#      define LZMA_CHECK_BEST LZMA_CHECK_CRC32
+#endif
+
+
+/// \brief      Structure to hold internal state of the check being calculated
+///
+/// \note       This is not in the public API because this structure may
+///             change in future if new integrity check algorithms are added.
+typedef struct {
+       /// Buffer to hold the final result and a temporary buffer for SHA256.
+       union {
+               uint8_t u8[64];
+               uint32_t u32[16];
+               uint64_t u64[8];
+       } buffer;
+
+       /// Check-specific data
+       union {
+               uint32_t crc32;
+               uint64_t crc64;
+               lzma_sha256_state sha256;
+       } state;
+
+} lzma_check_state;
+
+
+/// lzma_crc32_table[0] is needed by LZ encoder so we need to keep
+/// the array two-dimensional.
+#ifdef HAVE_SMALL
+extern uint32_t lzma_crc32_table[1][256];
+extern void lzma_crc32_init(void);
+#else
+extern const uint32_t lzma_crc32_table[8][256];
+extern const uint64_t lzma_crc64_table[4][256];
+#endif
+
+
+/// \brief      Initialize *check depending on type
+///
+/// \return     LZMA_OK on success. LZMA_UNSUPPORTED_CHECK if the type is not
+///             supported by the current version or build of liblzma.
+///             LZMA_PROG_ERROR if type > LZMA_CHECK_ID_MAX.
+extern void lzma_check_init(lzma_check_state *check, lzma_check type);
+
+/// Update the check state
+extern void lzma_check_update(lzma_check_state *check, lzma_check type,
+               const uint8_t *buf, size_t size);
+
+/// Finish the check calculation and store the result to check->buffer.u8.
+extern void lzma_check_finish(lzma_check_state *check, lzma_check type);
+
+
+#ifndef LZMA_SHA256FUNC
+
+/// Prepare SHA-256 state for new input.
+extern void lzma_sha256_init(lzma_check_state *check);
+
+/// Update the SHA-256 hash state
+extern void lzma_sha256_update(
+               const uint8_t *buf, size_t size, lzma_check_state *check);
+
+/// Finish the SHA-256 calculation and store the result to check->buffer.u8.
+extern void lzma_sha256_finish(lzma_check_state *check);
+
+
+#else
+
+static inline void
+lzma_sha256_init(lzma_check_state *check)
+{
+       LZMA_SHA256FUNC(Init)(&check->state.sha256);
+}
+
+
+static inline void
+lzma_sha256_update(const uint8_t *buf, size_t size, lzma_check_state *check)
+{
+#if defined(HAVE_CC_SHA256_INIT) && SIZE_MAX > UINT32_MAX
+       // Darwin's CC_SHA256_Update takes uint32_t as the buffer size,
+       // so use a loop to support size_t.
+       while (size > UINT32_MAX) {
+               LZMA_SHA256FUNC(Update)(&check->state.sha256, buf, UINT32_MAX);
+               buf += UINT32_MAX;
+               size -= UINT32_MAX;
+       }
+#endif
+
+       LZMA_SHA256FUNC(Update)(&check->state.sha256, buf, size);
+}
+
+
+static inline void
+lzma_sha256_finish(lzma_check_state *check)
+{
+       LZMA_SHA256FUNC(Final)(check->buffer.u8, &check->state.sha256);
+}
+
+#endif
+
+#endif
diff --git a/lzma/check/crc32_fast.c b/lzma/check/crc32_fast.c
new file mode 100644 (file)
index 0000000..3de0263
--- /dev/null
@@ -0,0 +1,82 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       crc32.c
+/// \brief      CRC32 calculation
+///
+/// Calculate the CRC32 using the slice-by-eight algorithm.
+/// It is explained in this document:
+/// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
+/// The code in this file is not the same as in Intel's paper, but
+/// the basic principle is identical.
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "check.h"
+#include "crc_macros.h"
+
+
+// If you make any changes, do some benchmarking! Seemingly unrelated
+// changes can very easily ruin the performance (and very probably is
+// very compiler dependent).
+extern LZMA_API(uint32_t)
+lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc)
+{
+       crc = ~crc;
+
+#ifdef WORDS_BIGENDIAN
+       crc = bswap32(crc);
+#endif
+
+       if (size > 8) {
+               // Fix the alignment, if needed. The if statement above
+               // ensures that this won't read past the end of buf[].
+               while ((uintptr_t)(buf) & 7) {
+                       crc = lzma_crc32_table[0][*buf++ ^ A(crc)] ^ S8(crc);
+                       --size;
+               }
+
+               // Calculate the position where to stop.
+               const uint8_t *const limit = buf + (size & ~(size_t)(7));
+
+               // Calculate how many bytes must be calculated separately
+               // before returning the result.
+               size &= (size_t)(7);
+
+               // Calculate the CRC32 using the slice-by-eight algorithm.
+               while (buf < limit) {
+                       crc ^= *(const uint32_t *)(buf);
+                       buf += 4;
+
+                       crc = lzma_crc32_table[7][A(crc)]
+                           ^ lzma_crc32_table[6][B(crc)]
+                           ^ lzma_crc32_table[5][C(crc)]
+                           ^ lzma_crc32_table[4][D(crc)];
+
+                       const uint32_t tmp = *(const uint32_t *)(buf);
+                       buf += 4;
+
+                       // At least with some compilers, it is critical for
+                       // performance, that the crc variable is XORed
+                       // between the two table-lookup pairs.
+                       crc = lzma_crc32_table[3][A(tmp)]
+                           ^ lzma_crc32_table[2][B(tmp)]
+                           ^ crc
+                           ^ lzma_crc32_table[1][C(tmp)]
+                           ^ lzma_crc32_table[0][D(tmp)];
+               }
+       }
+
+       while (size-- != 0)
+               crc = lzma_crc32_table[0][*buf++ ^ A(crc)] ^ S8(crc);
+
+#ifdef WORDS_BIGENDIAN
+       crc = bswap32(crc);
+#endif
+
+       return ~crc;
+}
diff --git a/lzma/check/crc32_table.c b/lzma/check/crc32_table.c
new file mode 100644 (file)
index 0000000..368874e
--- /dev/null
@@ -0,0 +1,19 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       crc32_table.c
+/// \brief      Precalculated CRC32 table with correct endianness
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+#ifdef WORDS_BIGENDIAN
+#      include "crc32_table_be.h"
+#else
+#      include "crc32_table_le.h"
+#endif
diff --git a/lzma/check/crc32_table_be.h b/lzma/check/crc32_table_be.h
new file mode 100644 (file)
index 0000000..c483cb6
--- /dev/null
@@ -0,0 +1,525 @@
+/* This file has been automatically generated by crc32_tablegen.c. */
+
+const uint32_t lzma_crc32_table[8][256] = {
+       {
+               0x00000000, 0x96300777, 0x2C610EEE, 0xBA510999,
+               0x19C46D07, 0x8FF46A70, 0x35A563E9, 0xA395649E,
+               0x3288DB0E, 0xA4B8DC79, 0x1EE9D5E0, 0x88D9D297,
+               0x2B4CB609, 0xBD7CB17E, 0x072DB8E7, 0x911DBF90,
+               0x6410B71D, 0xF220B06A, 0x4871B9F3, 0xDE41BE84,
+               0x7DD4DA1A, 0xEBE4DD6D, 0x51B5D4F4, 0xC785D383,
+               0x56986C13, 0xC0A86B64, 0x7AF962FD, 0xECC9658A,
+               0x4F5C0114, 0xD96C0663, 0x633D0FFA, 0xF50D088D,
+               0xC8206E3B, 0x5E10694C, 0xE44160D5, 0x727167A2,
+               0xD1E4033C, 0x47D4044B, 0xFD850DD2, 0x6BB50AA5,
+               0xFAA8B535, 0x6C98B242, 0xD6C9BBDB, 0x40F9BCAC,
+               0xE36CD832, 0x755CDF45, 0xCF0DD6DC, 0x593DD1AB,
+               0xAC30D926, 0x3A00DE51, 0x8051D7C8, 0x1661D0BF,
+               0xB5F4B421, 0x23C4B356, 0x9995BACF, 0x0FA5BDB8,
+               0x9EB80228, 0x0888055F, 0xB2D90CC6, 0x24E90BB1,
+               0x877C6F2F, 0x114C6858, 0xAB1D61C1, 0x3D2D66B6,
+               0x9041DC76, 0x0671DB01, 0xBC20D298, 0x2A10D5EF,
+               0x8985B171, 0x1FB5B606, 0xA5E4BF9F, 0x33D4B8E8,
+               0xA2C90778, 0x34F9000F, 0x8EA80996, 0x18980EE1,
+               0xBB0D6A7F, 0x2D3D6D08, 0x976C6491, 0x015C63E6,
+               0xF4516B6B, 0x62616C1C, 0xD8306585, 0x4E0062F2,
+               0xED95066C, 0x7BA5011B, 0xC1F40882, 0x57C40FF5,
+               0xC6D9B065, 0x50E9B712, 0xEAB8BE8B, 0x7C88B9FC,
+               0xDF1DDD62, 0x492DDA15, 0xF37CD38C, 0x654CD4FB,
+               0x5861B24D, 0xCE51B53A, 0x7400BCA3, 0xE230BBD4,
+               0x41A5DF4A, 0xD795D83D, 0x6DC4D1A4, 0xFBF4D6D3,
+               0x6AE96943, 0xFCD96E34, 0x468867AD, 0xD0B860DA,
+               0x732D0444, 0xE51D0333, 0x5F4C0AAA, 0xC97C0DDD,
+               0x3C710550, 0xAA410227, 0x10100BBE, 0x86200CC9,
+               0x25B56857, 0xB3856F20, 0x09D466B9, 0x9FE461CE,
+               0x0EF9DE5E, 0x98C9D929, 0x2298D0B0, 0xB4A8D7C7,
+               0x173DB359, 0x810DB42E, 0x3B5CBDB7, 0xAD6CBAC0,
+               0x2083B8ED, 0xB6B3BF9A, 0x0CE2B603, 0x9AD2B174,
+               0x3947D5EA, 0xAF77D29D, 0x1526DB04, 0x8316DC73,
+               0x120B63E3, 0x843B6494, 0x3E6A6D0D, 0xA85A6A7A,
+               0x0BCF0EE4, 0x9DFF0993, 0x27AE000A, 0xB19E077D,
+               0x44930FF0, 0xD2A30887, 0x68F2011E, 0xFEC20669,
+               0x5D5762F7, 0xCB676580, 0x71366C19, 0xE7066B6E,
+               0x761BD4FE, 0xE02BD389, 0x5A7ADA10, 0xCC4ADD67,
+               0x6FDFB9F9, 0xF9EFBE8E, 0x43BEB717, 0xD58EB060,
+               0xE8A3D6D6, 0x7E93D1A1, 0xC4C2D838, 0x52F2DF4F,
+               0xF167BBD1, 0x6757BCA6, 0xDD06B53F, 0x4B36B248,
+               0xDA2B0DD8, 0x4C1B0AAF, 0xF64A0336, 0x607A0441,
+               0xC3EF60DF, 0x55DF67A8, 0xEF8E6E31, 0x79BE6946,
+               0x8CB361CB, 0x1A8366BC, 0xA0D26F25, 0x36E26852,
+               0x95770CCC, 0x03470BBB, 0xB9160222, 0x2F260555,
+               0xBE3BBAC5, 0x280BBDB2, 0x925AB42B, 0x046AB35C,
+               0xA7FFD7C2, 0x31CFD0B5, 0x8B9ED92C, 0x1DAEDE5B,
+               0xB0C2649B, 0x26F263EC, 0x9CA36A75, 0x0A936D02,
+               0xA906099C, 0x3F360EEB, 0x85670772, 0x13570005,
+               0x824ABF95, 0x147AB8E2, 0xAE2BB17B, 0x381BB60C,
+               0x9B8ED292, 0x0DBED5E5, 0xB7EFDC7C, 0x21DFDB0B,
+               0xD4D2D386, 0x42E2D4F1, 0xF8B3DD68, 0x6E83DA1F,
+               0xCD16BE81, 0x5B26B9F6, 0xE177B06F, 0x7747B718,
+               0xE65A0888, 0x706A0FFF, 0xCA3B0666, 0x5C0B0111,
+               0xFF9E658F, 0x69AE62F8, 0xD3FF6B61, 0x45CF6C16,
+               0x78E20AA0, 0xEED20DD7, 0x5483044E, 0xC2B30339,
+               0x612667A7, 0xF71660D0, 0x4D476949, 0xDB776E3E,
+               0x4A6AD1AE, 0xDC5AD6D9, 0x660BDF40, 0xF03BD837,
+               0x53AEBCA9, 0xC59EBBDE, 0x7FCFB247, 0xE9FFB530,
+               0x1CF2BDBD, 0x8AC2BACA, 0x3093B353, 0xA6A3B424,
+               0x0536D0BA, 0x9306D7CD, 0x2957DE54, 0xBF67D923,
+               0x2E7A66B3, 0xB84A61C4, 0x021B685D, 0x942B6F2A,
+               0x37BE0BB4, 0xA18E0CC3, 0x1BDF055A, 0x8DEF022D
+       }, {
+               0x00000000, 0x41311B19, 0x82623632, 0xC3532D2B,
+               0x04C56C64, 0x45F4777D, 0x86A75A56, 0xC796414F,
+               0x088AD9C8, 0x49BBC2D1, 0x8AE8EFFA, 0xCBD9F4E3,
+               0x0C4FB5AC, 0x4D7EAEB5, 0x8E2D839E, 0xCF1C9887,
+               0x5112C24A, 0x1023D953, 0xD370F478, 0x9241EF61,
+               0x55D7AE2E, 0x14E6B537, 0xD7B5981C, 0x96848305,
+               0x59981B82, 0x18A9009B, 0xDBFA2DB0, 0x9ACB36A9,
+               0x5D5D77E6, 0x1C6C6CFF, 0xDF3F41D4, 0x9E0E5ACD,
+               0xA2248495, 0xE3159F8C, 0x2046B2A7, 0x6177A9BE,
+               0xA6E1E8F1, 0xE7D0F3E8, 0x2483DEC3, 0x65B2C5DA,
+               0xAAAE5D5D, 0xEB9F4644, 0x28CC6B6F, 0x69FD7076,
+               0xAE6B3139, 0xEF5A2A20, 0x2C09070B, 0x6D381C12,
+               0xF33646DF, 0xB2075DC6, 0x715470ED, 0x30656BF4,
+               0xF7F32ABB, 0xB6C231A2, 0x75911C89, 0x34A00790,
+               0xFBBC9F17, 0xBA8D840E, 0x79DEA925, 0x38EFB23C,
+               0xFF79F373, 0xBE48E86A, 0x7D1BC541, 0x3C2ADE58,
+               0x054F79F0, 0x447E62E9, 0x872D4FC2, 0xC61C54DB,
+               0x018A1594, 0x40BB0E8D, 0x83E823A6, 0xC2D938BF,
+               0x0DC5A038, 0x4CF4BB21, 0x8FA7960A, 0xCE968D13,
+               0x0900CC5C, 0x4831D745, 0x8B62FA6E, 0xCA53E177,
+               0x545DBBBA, 0x156CA0A3, 0xD63F8D88, 0x970E9691,
+               0x5098D7DE, 0x11A9CCC7, 0xD2FAE1EC, 0x93CBFAF5,
+               0x5CD76272, 0x1DE6796B, 0xDEB55440, 0x9F844F59,
+               0x58120E16, 0x1923150F, 0xDA703824, 0x9B41233D,
+               0xA76BFD65, 0xE65AE67C, 0x2509CB57, 0x6438D04E,
+               0xA3AE9101, 0xE29F8A18, 0x21CCA733, 0x60FDBC2A,
+               0xAFE124AD, 0xEED03FB4, 0x2D83129F, 0x6CB20986,
+               0xAB2448C9, 0xEA1553D0, 0x29467EFB, 0x687765E2,
+               0xF6793F2F, 0xB7482436, 0x741B091D, 0x352A1204,
+               0xF2BC534B, 0xB38D4852, 0x70DE6579, 0x31EF7E60,
+               0xFEF3E6E7, 0xBFC2FDFE, 0x7C91D0D5, 0x3DA0CBCC,
+               0xFA368A83, 0xBB07919A, 0x7854BCB1, 0x3965A7A8,
+               0x4B98833B, 0x0AA99822, 0xC9FAB509, 0x88CBAE10,
+               0x4F5DEF5F, 0x0E6CF446, 0xCD3FD96D, 0x8C0EC274,
+               0x43125AF3, 0x022341EA, 0xC1706CC1, 0x804177D8,
+               0x47D73697, 0x06E62D8E, 0xC5B500A5, 0x84841BBC,
+               0x1A8A4171, 0x5BBB5A68, 0x98E87743, 0xD9D96C5A,
+               0x1E4F2D15, 0x5F7E360C, 0x9C2D1B27, 0xDD1C003E,
+               0x120098B9, 0x533183A0, 0x9062AE8B, 0xD153B592,
+               0x16C5F4DD, 0x57F4EFC4, 0x94A7C2EF, 0xD596D9F6,
+               0xE9BC07AE, 0xA88D1CB7, 0x6BDE319C, 0x2AEF2A85,
+               0xED796BCA, 0xAC4870D3, 0x6F1B5DF8, 0x2E2A46E1,
+               0xE136DE66, 0xA007C57F, 0x6354E854, 0x2265F34D,
+               0xE5F3B202, 0xA4C2A91B, 0x67918430, 0x26A09F29,
+               0xB8AEC5E4, 0xF99FDEFD, 0x3ACCF3D6, 0x7BFDE8CF,
+               0xBC6BA980, 0xFD5AB299, 0x3E099FB2, 0x7F3884AB,
+               0xB0241C2C, 0xF1150735, 0x32462A1E, 0x73773107,
+               0xB4E17048, 0xF5D06B51, 0x3683467A, 0x77B25D63,
+               0x4ED7FACB, 0x0FE6E1D2, 0xCCB5CCF9, 0x8D84D7E0,
+               0x4A1296AF, 0x0B238DB6, 0xC870A09D, 0x8941BB84,
+               0x465D2303, 0x076C381A, 0xC43F1531, 0x850E0E28,
+               0x42984F67, 0x03A9547E, 0xC0FA7955, 0x81CB624C,
+               0x1FC53881, 0x5EF42398, 0x9DA70EB3, 0xDC9615AA,
+               0x1B0054E5, 0x5A314FFC, 0x996262D7, 0xD85379CE,
+               0x174FE149, 0x567EFA50, 0x952DD77B, 0xD41CCC62,
+               0x138A8D2D, 0x52BB9634, 0x91E8BB1F, 0xD0D9A006,
+               0xECF37E5E, 0xADC26547, 0x6E91486C, 0x2FA05375,
+               0xE836123A, 0xA9070923, 0x6A542408, 0x2B653F11,
+               0xE479A796, 0xA548BC8F, 0x661B91A4, 0x272A8ABD,
+               0xE0BCCBF2, 0xA18DD0EB, 0x62DEFDC0, 0x23EFE6D9,
+               0xBDE1BC14, 0xFCD0A70D, 0x3F838A26, 0x7EB2913F,
+               0xB924D070, 0xF815CB69, 0x3B46E642, 0x7A77FD5B,
+               0xB56B65DC, 0xF45A7EC5, 0x370953EE, 0x763848F7,
+               0xB1AE09B8, 0xF09F12A1, 0x33CC3F8A, 0x72FD2493
+       }, {
+               0x00000000, 0x376AC201, 0x6ED48403, 0x59BE4602,
+               0xDCA80907, 0xEBC2CB06, 0xB27C8D04, 0x85164F05,
+               0xB851130E, 0x8F3BD10F, 0xD685970D, 0xE1EF550C,
+               0x64F91A09, 0x5393D808, 0x0A2D9E0A, 0x3D475C0B,
+               0x70A3261C, 0x47C9E41D, 0x1E77A21F, 0x291D601E,
+               0xAC0B2F1B, 0x9B61ED1A, 0xC2DFAB18, 0xF5B56919,
+               0xC8F23512, 0xFF98F713, 0xA626B111, 0x914C7310,
+               0x145A3C15, 0x2330FE14, 0x7A8EB816, 0x4DE47A17,
+               0xE0464D38, 0xD72C8F39, 0x8E92C93B, 0xB9F80B3A,
+               0x3CEE443F, 0x0B84863E, 0x523AC03C, 0x6550023D,
+               0x58175E36, 0x6F7D9C37, 0x36C3DA35, 0x01A91834,
+               0x84BF5731, 0xB3D59530, 0xEA6BD332, 0xDD011133,
+               0x90E56B24, 0xA78FA925, 0xFE31EF27, 0xC95B2D26,
+               0x4C4D6223, 0x7B27A022, 0x2299E620, 0x15F32421,
+               0x28B4782A, 0x1FDEBA2B, 0x4660FC29, 0x710A3E28,
+               0xF41C712D, 0xC376B32C, 0x9AC8F52E, 0xADA2372F,
+               0xC08D9A70, 0xF7E75871, 0xAE591E73, 0x9933DC72,
+               0x1C259377, 0x2B4F5176, 0x72F11774, 0x459BD575,
+               0x78DC897E, 0x4FB64B7F, 0x16080D7D, 0x2162CF7C,
+               0xA4748079, 0x931E4278, 0xCAA0047A, 0xFDCAC67B,
+               0xB02EBC6C, 0x87447E6D, 0xDEFA386F, 0xE990FA6E,
+               0x6C86B56B, 0x5BEC776A, 0x02523168, 0x3538F369,
+               0x087FAF62, 0x3F156D63, 0x66AB2B61, 0x51C1E960,
+               0xD4D7A665, 0xE3BD6464, 0xBA032266, 0x8D69E067,
+               0x20CBD748, 0x17A11549, 0x4E1F534B, 0x7975914A,
+               0xFC63DE4F, 0xCB091C4E, 0x92B75A4C, 0xA5DD984D,
+               0x989AC446, 0xAFF00647, 0xF64E4045, 0xC1248244,
+               0x4432CD41, 0x73580F40, 0x2AE64942, 0x1D8C8B43,
+               0x5068F154, 0x67023355, 0x3EBC7557, 0x09D6B756,
+               0x8CC0F853, 0xBBAA3A52, 0xE2147C50, 0xD57EBE51,
+               0xE839E25A, 0xDF53205B, 0x86ED6659, 0xB187A458,
+               0x3491EB5D, 0x03FB295C, 0x5A456F5E, 0x6D2FAD5F,
+               0x801B35E1, 0xB771F7E0, 0xEECFB1E2, 0xD9A573E3,
+               0x5CB33CE6, 0x6BD9FEE7, 0x3267B8E5, 0x050D7AE4,
+               0x384A26EF, 0x0F20E4EE, 0x569EA2EC, 0x61F460ED,
+               0xE4E22FE8, 0xD388EDE9, 0x8A36ABEB, 0xBD5C69EA,
+               0xF0B813FD, 0xC7D2D1FC, 0x9E6C97FE, 0xA90655FF,
+               0x2C101AFA, 0x1B7AD8FB, 0x42C49EF9, 0x75AE5CF8,
+               0x48E900F3, 0x7F83C2F2, 0x263D84F0, 0x115746F1,
+               0x944109F4, 0xA32BCBF5, 0xFA958DF7, 0xCDFF4FF6,
+               0x605D78D9, 0x5737BAD8, 0x0E89FCDA, 0x39E33EDB,
+               0xBCF571DE, 0x8B9FB3DF, 0xD221F5DD, 0xE54B37DC,
+               0xD80C6BD7, 0xEF66A9D6, 0xB6D8EFD4, 0x81B22DD5,
+               0x04A462D0, 0x33CEA0D1, 0x6A70E6D3, 0x5D1A24D2,
+               0x10FE5EC5, 0x27949CC4, 0x7E2ADAC6, 0x494018C7,
+               0xCC5657C2, 0xFB3C95C3, 0xA282D3C1, 0x95E811C0,
+               0xA8AF4DCB, 0x9FC58FCA, 0xC67BC9C8, 0xF1110BC9,
+               0x740744CC, 0x436D86CD, 0x1AD3C0CF, 0x2DB902CE,
+               0x4096AF91, 0x77FC6D90, 0x2E422B92, 0x1928E993,
+               0x9C3EA696, 0xAB546497, 0xF2EA2295, 0xC580E094,
+               0xF8C7BC9F, 0xCFAD7E9E, 0x9613389C, 0xA179FA9D,
+               0x246FB598, 0x13057799, 0x4ABB319B, 0x7DD1F39A,
+               0x3035898D, 0x075F4B8C, 0x5EE10D8E, 0x698BCF8F,
+               0xEC9D808A, 0xDBF7428B, 0x82490489, 0xB523C688,
+               0x88649A83, 0xBF0E5882, 0xE6B01E80, 0xD1DADC81,
+               0x54CC9384, 0x63A65185, 0x3A181787, 0x0D72D586,
+               0xA0D0E2A9, 0x97BA20A8, 0xCE0466AA, 0xF96EA4AB,
+               0x7C78EBAE, 0x4B1229AF, 0x12AC6FAD, 0x25C6ADAC,
+               0x1881F1A7, 0x2FEB33A6, 0x765575A4, 0x413FB7A5,
+               0xC429F8A0, 0xF3433AA1, 0xAAFD7CA3, 0x9D97BEA2,
+               0xD073C4B5, 0xE71906B4, 0xBEA740B6, 0x89CD82B7,
+               0x0CDBCDB2, 0x3BB10FB3, 0x620F49B1, 0x55658BB0,
+               0x6822D7BB, 0x5F4815BA, 0x06F653B8, 0x319C91B9,
+               0xB48ADEBC, 0x83E01CBD, 0xDA5E5ABF, 0xED3498BE
+       }, {
+               0x00000000, 0x6567BCB8, 0x8BC809AA, 0xEEAFB512,
+               0x5797628F, 0x32F0DE37, 0xDC5F6B25, 0xB938D79D,
+               0xEF28B4C5, 0x8A4F087D, 0x64E0BD6F, 0x018701D7,
+               0xB8BFD64A, 0xDDD86AF2, 0x3377DFE0, 0x56106358,
+               0x9F571950, 0xFA30A5E8, 0x149F10FA, 0x71F8AC42,
+               0xC8C07BDF, 0xADA7C767, 0x43087275, 0x266FCECD,
+               0x707FAD95, 0x1518112D, 0xFBB7A43F, 0x9ED01887,
+               0x27E8CF1A, 0x428F73A2, 0xAC20C6B0, 0xC9477A08,
+               0x3EAF32A0, 0x5BC88E18, 0xB5673B0A, 0xD00087B2,
+               0x6938502F, 0x0C5FEC97, 0xE2F05985, 0x8797E53D,
+               0xD1878665, 0xB4E03ADD, 0x5A4F8FCF, 0x3F283377,
+               0x8610E4EA, 0xE3775852, 0x0DD8ED40, 0x68BF51F8,
+               0xA1F82BF0, 0xC49F9748, 0x2A30225A, 0x4F579EE2,
+               0xF66F497F, 0x9308F5C7, 0x7DA740D5, 0x18C0FC6D,
+               0x4ED09F35, 0x2BB7238D, 0xC518969F, 0xA07F2A27,
+               0x1947FDBA, 0x7C204102, 0x928FF410, 0xF7E848A8,
+               0x3D58149B, 0x583FA823, 0xB6901D31, 0xD3F7A189,
+               0x6ACF7614, 0x0FA8CAAC, 0xE1077FBE, 0x8460C306,
+               0xD270A05E, 0xB7171CE6, 0x59B8A9F4, 0x3CDF154C,
+               0x85E7C2D1, 0xE0807E69, 0x0E2FCB7B, 0x6B4877C3,
+               0xA20F0DCB, 0xC768B173, 0x29C70461, 0x4CA0B8D9,
+               0xF5986F44, 0x90FFD3FC, 0x7E5066EE, 0x1B37DA56,
+               0x4D27B90E, 0x284005B6, 0xC6EFB0A4, 0xA3880C1C,
+               0x1AB0DB81, 0x7FD76739, 0x9178D22B, 0xF41F6E93,
+               0x03F7263B, 0x66909A83, 0x883F2F91, 0xED589329,
+               0x546044B4, 0x3107F80C, 0xDFA84D1E, 0xBACFF1A6,
+               0xECDF92FE, 0x89B82E46, 0x67179B54, 0x027027EC,
+               0xBB48F071, 0xDE2F4CC9, 0x3080F9DB, 0x55E74563,
+               0x9CA03F6B, 0xF9C783D3, 0x176836C1, 0x720F8A79,
+               0xCB375DE4, 0xAE50E15C, 0x40FF544E, 0x2598E8F6,
+               0x73888BAE, 0x16EF3716, 0xF8408204, 0x9D273EBC,
+               0x241FE921, 0x41785599, 0xAFD7E08B, 0xCAB05C33,
+               0x3BB659ED, 0x5ED1E555, 0xB07E5047, 0xD519ECFF,
+               0x6C213B62, 0x094687DA, 0xE7E932C8, 0x828E8E70,
+               0xD49EED28, 0xB1F95190, 0x5F56E482, 0x3A31583A,
+               0x83098FA7, 0xE66E331F, 0x08C1860D, 0x6DA63AB5,
+               0xA4E140BD, 0xC186FC05, 0x2F294917, 0x4A4EF5AF,
+               0xF3762232, 0x96119E8A, 0x78BE2B98, 0x1DD99720,
+               0x4BC9F478, 0x2EAE48C0, 0xC001FDD2, 0xA566416A,
+               0x1C5E96F7, 0x79392A4F, 0x97969F5D, 0xF2F123E5,
+               0x05196B4D, 0x607ED7F5, 0x8ED162E7, 0xEBB6DE5F,
+               0x528E09C2, 0x37E9B57A, 0xD9460068, 0xBC21BCD0,
+               0xEA31DF88, 0x8F566330, 0x61F9D622, 0x049E6A9A,
+               0xBDA6BD07, 0xD8C101BF, 0x366EB4AD, 0x53090815,
+               0x9A4E721D, 0xFF29CEA5, 0x11867BB7, 0x74E1C70F,
+               0xCDD91092, 0xA8BEAC2A, 0x46111938, 0x2376A580,
+               0x7566C6D8, 0x10017A60, 0xFEAECF72, 0x9BC973CA,
+               0x22F1A457, 0x479618EF, 0xA939ADFD, 0xCC5E1145,
+               0x06EE4D76, 0x6389F1CE, 0x8D2644DC, 0xE841F864,
+               0x51792FF9, 0x341E9341, 0xDAB12653, 0xBFD69AEB,
+               0xE9C6F9B3, 0x8CA1450B, 0x620EF019, 0x07694CA1,
+               0xBE519B3C, 0xDB362784, 0x35999296, 0x50FE2E2E,
+               0x99B95426, 0xFCDEE89E, 0x12715D8C, 0x7716E134,
+               0xCE2E36A9, 0xAB498A11, 0x45E63F03, 0x208183BB,
+               0x7691E0E3, 0x13F65C5B, 0xFD59E949, 0x983E55F1,
+               0x2106826C, 0x44613ED4, 0xAACE8BC6, 0xCFA9377E,
+               0x38417FD6, 0x5D26C36E, 0xB389767C, 0xD6EECAC4,
+               0x6FD61D59, 0x0AB1A1E1, 0xE41E14F3, 0x8179A84B,
+               0xD769CB13, 0xB20E77AB, 0x5CA1C2B9, 0x39C67E01,
+               0x80FEA99C, 0xE5991524, 0x0B36A036, 0x6E511C8E,
+               0xA7166686, 0xC271DA3E, 0x2CDE6F2C, 0x49B9D394,
+               0xF0810409, 0x95E6B8B1, 0x7B490DA3, 0x1E2EB11B,
+               0x483ED243, 0x2D596EFB, 0xC3F6DBE9, 0xA6916751,
+               0x1FA9B0CC, 0x7ACE0C74, 0x9461B966, 0xF10605DE
+       }, {
+               0x00000000, 0xB029603D, 0x6053C07A, 0xD07AA047,
+               0xC0A680F5, 0x708FE0C8, 0xA0F5408F, 0x10DC20B2,
+               0xC14B7030, 0x7162100D, 0xA118B04A, 0x1131D077,
+               0x01EDF0C5, 0xB1C490F8, 0x61BE30BF, 0xD1975082,
+               0x8297E060, 0x32BE805D, 0xE2C4201A, 0x52ED4027,
+               0x42316095, 0xF21800A8, 0x2262A0EF, 0x924BC0D2,
+               0x43DC9050, 0xF3F5F06D, 0x238F502A, 0x93A63017,
+               0x837A10A5, 0x33537098, 0xE329D0DF, 0x5300B0E2,
+               0x042FC1C1, 0xB406A1FC, 0x647C01BB, 0xD4556186,
+               0xC4894134, 0x74A02109, 0xA4DA814E, 0x14F3E173,
+               0xC564B1F1, 0x754DD1CC, 0xA537718B, 0x151E11B6,
+               0x05C23104, 0xB5EB5139, 0x6591F17E, 0xD5B89143,
+               0x86B821A1, 0x3691419C, 0xE6EBE1DB, 0x56C281E6,
+               0x461EA154, 0xF637C169, 0x264D612E, 0x96640113,
+               0x47F35191, 0xF7DA31AC, 0x27A091EB, 0x9789F1D6,
+               0x8755D164, 0x377CB159, 0xE706111E, 0x572F7123,
+               0x4958F358, 0xF9719365, 0x290B3322, 0x9922531F,
+               0x89FE73AD, 0x39D71390, 0xE9ADB3D7, 0x5984D3EA,
+               0x88138368, 0x383AE355, 0xE8404312, 0x5869232F,
+               0x48B5039D, 0xF89C63A0, 0x28E6C3E7, 0x98CFA3DA,
+               0xCBCF1338, 0x7BE67305, 0xAB9CD342, 0x1BB5B37F,
+               0x0B6993CD, 0xBB40F3F0, 0x6B3A53B7, 0xDB13338A,
+               0x0A846308, 0xBAAD0335, 0x6AD7A372, 0xDAFEC34F,
+               0xCA22E3FD, 0x7A0B83C0, 0xAA712387, 0x1A5843BA,
+               0x4D773299, 0xFD5E52A4, 0x2D24F2E3, 0x9D0D92DE,
+               0x8DD1B26C, 0x3DF8D251, 0xED827216, 0x5DAB122B,
+               0x8C3C42A9, 0x3C152294, 0xEC6F82D3, 0x5C46E2EE,
+               0x4C9AC25C, 0xFCB3A261, 0x2CC90226, 0x9CE0621B,
+               0xCFE0D2F9, 0x7FC9B2C4, 0xAFB31283, 0x1F9A72BE,
+               0x0F46520C, 0xBF6F3231, 0x6F159276, 0xDF3CF24B,
+               0x0EABA2C9, 0xBE82C2F4, 0x6EF862B3, 0xDED1028E,
+               0xCE0D223C, 0x7E244201, 0xAE5EE246, 0x1E77827B,
+               0x92B0E6B1, 0x2299868C, 0xF2E326CB, 0x42CA46F6,
+               0x52166644, 0xE23F0679, 0x3245A63E, 0x826CC603,
+               0x53FB9681, 0xE3D2F6BC, 0x33A856FB, 0x838136C6,
+               0x935D1674, 0x23747649, 0xF30ED60E, 0x4327B633,
+               0x102706D1, 0xA00E66EC, 0x7074C6AB, 0xC05DA696,
+               0xD0818624, 0x60A8E619, 0xB0D2465E, 0x00FB2663,
+               0xD16C76E1, 0x614516DC, 0xB13FB69B, 0x0116D6A6,
+               0x11CAF614, 0xA1E39629, 0x7199366E, 0xC1B05653,
+               0x969F2770, 0x26B6474D, 0xF6CCE70A, 0x46E58737,
+               0x5639A785, 0xE610C7B8, 0x366A67FF, 0x864307C2,
+               0x57D45740, 0xE7FD377D, 0x3787973A, 0x87AEF707,
+               0x9772D7B5, 0x275BB788, 0xF72117CF, 0x470877F2,
+               0x1408C710, 0xA421A72D, 0x745B076A, 0xC4726757,
+               0xD4AE47E5, 0x648727D8, 0xB4FD879F, 0x04D4E7A2,
+               0xD543B720, 0x656AD71D, 0xB510775A, 0x05391767,
+               0x15E537D5, 0xA5CC57E8, 0x75B6F7AF, 0xC59F9792,
+               0xDBE815E9, 0x6BC175D4, 0xBBBBD593, 0x0B92B5AE,
+               0x1B4E951C, 0xAB67F521, 0x7B1D5566, 0xCB34355B,
+               0x1AA365D9, 0xAA8A05E4, 0x7AF0A5A3, 0xCAD9C59E,
+               0xDA05E52C, 0x6A2C8511, 0xBA562556, 0x0A7F456B,
+               0x597FF589, 0xE95695B4, 0x392C35F3, 0x890555CE,
+               0x99D9757C, 0x29F01541, 0xF98AB506, 0x49A3D53B,
+               0x983485B9, 0x281DE584, 0xF86745C3, 0x484E25FE,
+               0x5892054C, 0xE8BB6571, 0x38C1C536, 0x88E8A50B,
+               0xDFC7D428, 0x6FEEB415, 0xBF941452, 0x0FBD746F,
+               0x1F6154DD, 0xAF4834E0, 0x7F3294A7, 0xCF1BF49A,
+               0x1E8CA418, 0xAEA5C425, 0x7EDF6462, 0xCEF6045F,
+               0xDE2A24ED, 0x6E0344D0, 0xBE79E497, 0x0E5084AA,
+               0x5D503448, 0xED795475, 0x3D03F432, 0x8D2A940F,
+               0x9DF6B4BD, 0x2DDFD480, 0xFDA574C7, 0x4D8C14FA,
+               0x9C1B4478, 0x2C322445, 0xFC488402, 0x4C61E43F,
+               0x5CBDC48D, 0xEC94A4B0, 0x3CEE04F7, 0x8CC764CA
+       }, {
+               0x00000000, 0xA5D35CCB, 0x0BA1C84D, 0xAE729486,
+               0x1642919B, 0xB391CD50, 0x1DE359D6, 0xB830051D,
+               0x6D8253EC, 0xC8510F27, 0x66239BA1, 0xC3F0C76A,
+               0x7BC0C277, 0xDE139EBC, 0x70610A3A, 0xD5B256F1,
+               0x9B02D603, 0x3ED18AC8, 0x90A31E4E, 0x35704285,
+               0x8D404798, 0x28931B53, 0x86E18FD5, 0x2332D31E,
+               0xF68085EF, 0x5353D924, 0xFD214DA2, 0x58F21169,
+               0xE0C21474, 0x451148BF, 0xEB63DC39, 0x4EB080F2,
+               0x3605AC07, 0x93D6F0CC, 0x3DA4644A, 0x98773881,
+               0x20473D9C, 0x85946157, 0x2BE6F5D1, 0x8E35A91A,
+               0x5B87FFEB, 0xFE54A320, 0x502637A6, 0xF5F56B6D,
+               0x4DC56E70, 0xE81632BB, 0x4664A63D, 0xE3B7FAF6,
+               0xAD077A04, 0x08D426CF, 0xA6A6B249, 0x0375EE82,
+               0xBB45EB9F, 0x1E96B754, 0xB0E423D2, 0x15377F19,
+               0xC08529E8, 0x65567523, 0xCB24E1A5, 0x6EF7BD6E,
+               0xD6C7B873, 0x7314E4B8, 0xDD66703E, 0x78B52CF5,
+               0x6C0A580F, 0xC9D904C4, 0x67AB9042, 0xC278CC89,
+               0x7A48C994, 0xDF9B955F, 0x71E901D9, 0xD43A5D12,
+               0x01880BE3, 0xA45B5728, 0x0A29C3AE, 0xAFFA9F65,
+               0x17CA9A78, 0xB219C6B3, 0x1C6B5235, 0xB9B80EFE,
+               0xF7088E0C, 0x52DBD2C7, 0xFCA94641, 0x597A1A8A,
+               0xE14A1F97, 0x4499435C, 0xEAEBD7DA, 0x4F388B11,
+               0x9A8ADDE0, 0x3F59812B, 0x912B15AD, 0x34F84966,
+               0x8CC84C7B, 0x291B10B0, 0x87698436, 0x22BAD8FD,
+               0x5A0FF408, 0xFFDCA8C3, 0x51AE3C45, 0xF47D608E,
+               0x4C4D6593, 0xE99E3958, 0x47ECADDE, 0xE23FF115,
+               0x378DA7E4, 0x925EFB2F, 0x3C2C6FA9, 0x99FF3362,
+               0x21CF367F, 0x841C6AB4, 0x2A6EFE32, 0x8FBDA2F9,
+               0xC10D220B, 0x64DE7EC0, 0xCAACEA46, 0x6F7FB68D,
+               0xD74FB390, 0x729CEF5B, 0xDCEE7BDD, 0x793D2716,
+               0xAC8F71E7, 0x095C2D2C, 0xA72EB9AA, 0x02FDE561,
+               0xBACDE07C, 0x1F1EBCB7, 0xB16C2831, 0x14BF74FA,
+               0xD814B01E, 0x7DC7ECD5, 0xD3B57853, 0x76662498,
+               0xCE562185, 0x6B857D4E, 0xC5F7E9C8, 0x6024B503,
+               0xB596E3F2, 0x1045BF39, 0xBE372BBF, 0x1BE47774,
+               0xA3D47269, 0x06072EA2, 0xA875BA24, 0x0DA6E6EF,
+               0x4316661D, 0xE6C53AD6, 0x48B7AE50, 0xED64F29B,
+               0x5554F786, 0xF087AB4D, 0x5EF53FCB, 0xFB266300,
+               0x2E9435F1, 0x8B47693A, 0x2535FDBC, 0x80E6A177,
+               0x38D6A46A, 0x9D05F8A1, 0x33776C27, 0x96A430EC,
+               0xEE111C19, 0x4BC240D2, 0xE5B0D454, 0x4063889F,
+               0xF8538D82, 0x5D80D149, 0xF3F245CF, 0x56211904,
+               0x83934FF5, 0x2640133E, 0x883287B8, 0x2DE1DB73,
+               0x95D1DE6E, 0x300282A5, 0x9E701623, 0x3BA34AE8,
+               0x7513CA1A, 0xD0C096D1, 0x7EB20257, 0xDB615E9C,
+               0x63515B81, 0xC682074A, 0x68F093CC, 0xCD23CF07,
+               0x189199F6, 0xBD42C53D, 0x133051BB, 0xB6E30D70,
+               0x0ED3086D, 0xAB0054A6, 0x0572C020, 0xA0A19CEB,
+               0xB41EE811, 0x11CDB4DA, 0xBFBF205C, 0x1A6C7C97,
+               0xA25C798A, 0x078F2541, 0xA9FDB1C7, 0x0C2EED0C,
+               0xD99CBBFD, 0x7C4FE736, 0xD23D73B0, 0x77EE2F7B,
+               0xCFDE2A66, 0x6A0D76AD, 0xC47FE22B, 0x61ACBEE0,
+               0x2F1C3E12, 0x8ACF62D9, 0x24BDF65F, 0x816EAA94,
+               0x395EAF89, 0x9C8DF342, 0x32FF67C4, 0x972C3B0F,
+               0x429E6DFE, 0xE74D3135, 0x493FA5B3, 0xECECF978,
+               0x54DCFC65, 0xF10FA0AE, 0x5F7D3428, 0xFAAE68E3,
+               0x821B4416, 0x27C818DD, 0x89BA8C5B, 0x2C69D090,
+               0x9459D58D, 0x318A8946, 0x9FF81DC0, 0x3A2B410B,
+               0xEF9917FA, 0x4A4A4B31, 0xE438DFB7, 0x41EB837C,
+               0xF9DB8661, 0x5C08DAAA, 0xF27A4E2C, 0x57A912E7,
+               0x19199215, 0xBCCACEDE, 0x12B85A58, 0xB76B0693,
+               0x0F5B038E, 0xAA885F45, 0x04FACBC3, 0xA1299708,
+               0x749BC1F9, 0xD1489D32, 0x7F3A09B4, 0xDAE9557F,
+               0x62D95062, 0xC70A0CA9, 0x6978982F, 0xCCABC4E4
+       }, {
+               0x00000000, 0xB40B77A6, 0x29119F97, 0x9D1AE831,
+               0x13244FF4, 0xA72F3852, 0x3A35D063, 0x8E3EA7C5,
+               0x674EEF33, 0xD3459895, 0x4E5F70A4, 0xFA540702,
+               0x746AA0C7, 0xC061D761, 0x5D7B3F50, 0xE97048F6,
+               0xCE9CDE67, 0x7A97A9C1, 0xE78D41F0, 0x53863656,
+               0xDDB89193, 0x69B3E635, 0xF4A90E04, 0x40A279A2,
+               0xA9D23154, 0x1DD946F2, 0x80C3AEC3, 0x34C8D965,
+               0xBAF67EA0, 0x0EFD0906, 0x93E7E137, 0x27EC9691,
+               0x9C39BDCF, 0x2832CA69, 0xB5282258, 0x012355FE,
+               0x8F1DF23B, 0x3B16859D, 0xA60C6DAC, 0x12071A0A,
+               0xFB7752FC, 0x4F7C255A, 0xD266CD6B, 0x666DBACD,
+               0xE8531D08, 0x5C586AAE, 0xC142829F, 0x7549F539,
+               0x52A563A8, 0xE6AE140E, 0x7BB4FC3F, 0xCFBF8B99,
+               0x41812C5C, 0xF58A5BFA, 0x6890B3CB, 0xDC9BC46D,
+               0x35EB8C9B, 0x81E0FB3D, 0x1CFA130C, 0xA8F164AA,
+               0x26CFC36F, 0x92C4B4C9, 0x0FDE5CF8, 0xBBD52B5E,
+               0x79750B44, 0xCD7E7CE2, 0x506494D3, 0xE46FE375,
+               0x6A5144B0, 0xDE5A3316, 0x4340DB27, 0xF74BAC81,
+               0x1E3BE477, 0xAA3093D1, 0x372A7BE0, 0x83210C46,
+               0x0D1FAB83, 0xB914DC25, 0x240E3414, 0x900543B2,
+               0xB7E9D523, 0x03E2A285, 0x9EF84AB4, 0x2AF33D12,
+               0xA4CD9AD7, 0x10C6ED71, 0x8DDC0540, 0x39D772E6,
+               0xD0A73A10, 0x64AC4DB6, 0xF9B6A587, 0x4DBDD221,
+               0xC38375E4, 0x77880242, 0xEA92EA73, 0x5E999DD5,
+               0xE54CB68B, 0x5147C12D, 0xCC5D291C, 0x78565EBA,
+               0xF668F97F, 0x42638ED9, 0xDF7966E8, 0x6B72114E,
+               0x820259B8, 0x36092E1E, 0xAB13C62F, 0x1F18B189,
+               0x9126164C, 0x252D61EA, 0xB83789DB, 0x0C3CFE7D,
+               0x2BD068EC, 0x9FDB1F4A, 0x02C1F77B, 0xB6CA80DD,
+               0x38F42718, 0x8CFF50BE, 0x11E5B88F, 0xA5EECF29,
+               0x4C9E87DF, 0xF895F079, 0x658F1848, 0xD1846FEE,
+               0x5FBAC82B, 0xEBB1BF8D, 0x76AB57BC, 0xC2A0201A,
+               0xF2EA1688, 0x46E1612E, 0xDBFB891F, 0x6FF0FEB9,
+               0xE1CE597C, 0x55C52EDA, 0xC8DFC6EB, 0x7CD4B14D,
+               0x95A4F9BB, 0x21AF8E1D, 0xBCB5662C, 0x08BE118A,
+               0x8680B64F, 0x328BC1E9, 0xAF9129D8, 0x1B9A5E7E,
+               0x3C76C8EF, 0x887DBF49, 0x15675778, 0xA16C20DE,
+               0x2F52871B, 0x9B59F0BD, 0x0643188C, 0xB2486F2A,
+               0x5B3827DC, 0xEF33507A, 0x7229B84B, 0xC622CFED,
+               0x481C6828, 0xFC171F8E, 0x610DF7BF, 0xD5068019,
+               0x6ED3AB47, 0xDAD8DCE1, 0x47C234D0, 0xF3C94376,
+               0x7DF7E4B3, 0xC9FC9315, 0x54E67B24, 0xE0ED0C82,
+               0x099D4474, 0xBD9633D2, 0x208CDBE3, 0x9487AC45,
+               0x1AB90B80, 0xAEB27C26, 0x33A89417, 0x87A3E3B1,
+               0xA04F7520, 0x14440286, 0x895EEAB7, 0x3D559D11,
+               0xB36B3AD4, 0x07604D72, 0x9A7AA543, 0x2E71D2E5,
+               0xC7019A13, 0x730AEDB5, 0xEE100584, 0x5A1B7222,
+               0xD425D5E7, 0x602EA241, 0xFD344A70, 0x493F3DD6,
+               0x8B9F1DCC, 0x3F946A6A, 0xA28E825B, 0x1685F5FD,
+               0x98BB5238, 0x2CB0259E, 0xB1AACDAF, 0x05A1BA09,
+               0xECD1F2FF, 0x58DA8559, 0xC5C06D68, 0x71CB1ACE,
+               0xFFF5BD0B, 0x4BFECAAD, 0xD6E4229C, 0x62EF553A,
+               0x4503C3AB, 0xF108B40D, 0x6C125C3C, 0xD8192B9A,
+               0x56278C5F, 0xE22CFBF9, 0x7F3613C8, 0xCB3D646E,
+               0x224D2C98, 0x96465B3E, 0x0B5CB30F, 0xBF57C4A9,
+               0x3169636C, 0x856214CA, 0x1878FCFB, 0xAC738B5D,
+               0x17A6A003, 0xA3ADD7A5, 0x3EB73F94, 0x8ABC4832,
+               0x0482EFF7, 0xB0899851, 0x2D937060, 0x999807C6,
+               0x70E84F30, 0xC4E33896, 0x59F9D0A7, 0xEDF2A701,
+               0x63CC00C4, 0xD7C77762, 0x4ADD9F53, 0xFED6E8F5,
+               0xD93A7E64, 0x6D3109C2, 0xF02BE1F3, 0x44209655,
+               0xCA1E3190, 0x7E154636, 0xE30FAE07, 0x5704D9A1,
+               0xBE749157, 0x0A7FE6F1, 0x97650EC0, 0x236E7966,
+               0xAD50DEA3, 0x195BA905, 0x84414134, 0x304A3692
+       }, {
+               0x00000000, 0x9E00AACC, 0x7D072542, 0xE3078F8E,
+               0xFA0E4A84, 0x640EE048, 0x87096FC6, 0x1909C50A,
+               0xB51BE5D3, 0x2B1B4F1F, 0xC81CC091, 0x561C6A5D,
+               0x4F15AF57, 0xD115059B, 0x32128A15, 0xAC1220D9,
+               0x2B31BB7C, 0xB53111B0, 0x56369E3E, 0xC83634F2,
+               0xD13FF1F8, 0x4F3F5B34, 0xAC38D4BA, 0x32387E76,
+               0x9E2A5EAF, 0x002AF463, 0xE32D7BED, 0x7D2DD121,
+               0x6424142B, 0xFA24BEE7, 0x19233169, 0x87239BA5,
+               0x566276F9, 0xC862DC35, 0x2B6553BB, 0xB565F977,
+               0xAC6C3C7D, 0x326C96B1, 0xD16B193F, 0x4F6BB3F3,
+               0xE379932A, 0x7D7939E6, 0x9E7EB668, 0x007E1CA4,
+               0x1977D9AE, 0x87777362, 0x6470FCEC, 0xFA705620,
+               0x7D53CD85, 0xE3536749, 0x0054E8C7, 0x9E54420B,
+               0x875D8701, 0x195D2DCD, 0xFA5AA243, 0x645A088F,
+               0xC8482856, 0x5648829A, 0xB54F0D14, 0x2B4FA7D8,
+               0x324662D2, 0xAC46C81E, 0x4F414790, 0xD141ED5C,
+               0xEDC29D29, 0x73C237E5, 0x90C5B86B, 0x0EC512A7,
+               0x17CCD7AD, 0x89CC7D61, 0x6ACBF2EF, 0xF4CB5823,
+               0x58D978FA, 0xC6D9D236, 0x25DE5DB8, 0xBBDEF774,
+               0xA2D7327E, 0x3CD798B2, 0xDFD0173C, 0x41D0BDF0,
+               0xC6F32655, 0x58F38C99, 0xBBF40317, 0x25F4A9DB,
+               0x3CFD6CD1, 0xA2FDC61D, 0x41FA4993, 0xDFFAE35F,
+               0x73E8C386, 0xEDE8694A, 0x0EEFE6C4, 0x90EF4C08,
+               0x89E68902, 0x17E623CE, 0xF4E1AC40, 0x6AE1068C,
+               0xBBA0EBD0, 0x25A0411C, 0xC6A7CE92, 0x58A7645E,
+               0x41AEA154, 0xDFAE0B98, 0x3CA98416, 0xA2A92EDA,
+               0x0EBB0E03, 0x90BBA4CF, 0x73BC2B41, 0xEDBC818D,
+               0xF4B54487, 0x6AB5EE4B, 0x89B261C5, 0x17B2CB09,
+               0x909150AC, 0x0E91FA60, 0xED9675EE, 0x7396DF22,
+               0x6A9F1A28, 0xF49FB0E4, 0x17983F6A, 0x899895A6,
+               0x258AB57F, 0xBB8A1FB3, 0x588D903D, 0xC68D3AF1,
+               0xDF84FFFB, 0x41845537, 0xA283DAB9, 0x3C837075,
+               0xDA853B53, 0x4485919F, 0xA7821E11, 0x3982B4DD,
+               0x208B71D7, 0xBE8BDB1B, 0x5D8C5495, 0xC38CFE59,
+               0x6F9EDE80, 0xF19E744C, 0x1299FBC2, 0x8C99510E,
+               0x95909404, 0x0B903EC8, 0xE897B146, 0x76971B8A,
+               0xF1B4802F, 0x6FB42AE3, 0x8CB3A56D, 0x12B30FA1,
+               0x0BBACAAB, 0x95BA6067, 0x76BDEFE9, 0xE8BD4525,
+               0x44AF65FC, 0xDAAFCF30, 0x39A840BE, 0xA7A8EA72,
+               0xBEA12F78, 0x20A185B4, 0xC3A60A3A, 0x5DA6A0F6,
+               0x8CE74DAA, 0x12E7E766, 0xF1E068E8, 0x6FE0C224,
+               0x76E9072E, 0xE8E9ADE2, 0x0BEE226C, 0x95EE88A0,
+               0x39FCA879, 0xA7FC02B5, 0x44FB8D3B, 0xDAFB27F7,
+               0xC3F2E2FD, 0x5DF24831, 0xBEF5C7BF, 0x20F56D73,
+               0xA7D6F6D6, 0x39D65C1A, 0xDAD1D394, 0x44D17958,
+               0x5DD8BC52, 0xC3D8169E, 0x20DF9910, 0xBEDF33DC,
+               0x12CD1305, 0x8CCDB9C9, 0x6FCA3647, 0xF1CA9C8B,
+               0xE8C35981, 0x76C3F34D, 0x95C47CC3, 0x0BC4D60F,
+               0x3747A67A, 0xA9470CB6, 0x4A408338, 0xD44029F4,
+               0xCD49ECFE, 0x53494632, 0xB04EC9BC, 0x2E4E6370,
+               0x825C43A9, 0x1C5CE965, 0xFF5B66EB, 0x615BCC27,
+               0x7852092D, 0xE652A3E1, 0x05552C6F, 0x9B5586A3,
+               0x1C761D06, 0x8276B7CA, 0x61713844, 0xFF719288,
+               0xE6785782, 0x7878FD4E, 0x9B7F72C0, 0x057FD80C,
+               0xA96DF8D5, 0x376D5219, 0xD46ADD97, 0x4A6A775B,
+               0x5363B251, 0xCD63189D, 0x2E649713, 0xB0643DDF,
+               0x6125D083, 0xFF257A4F, 0x1C22F5C1, 0x82225F0D,
+               0x9B2B9A07, 0x052B30CB, 0xE62CBF45, 0x782C1589,
+               0xD43E3550, 0x4A3E9F9C, 0xA9391012, 0x3739BADE,
+               0x2E307FD4, 0xB030D518, 0x53375A96, 0xCD37F05A,
+               0x4A146BFF, 0xD414C133, 0x37134EBD, 0xA913E471,
+               0xB01A217B, 0x2E1A8BB7, 0xCD1D0439, 0x531DAEF5,
+               0xFF0F8E2C, 0x610F24E0, 0x8208AB6E, 0x1C0801A2,
+               0x0501C4A8, 0x9B016E64, 0x7806E1EA, 0xE6064B26
+       }
+};
diff --git a/lzma/check/crc32_table_le.h b/lzma/check/crc32_table_le.h
new file mode 100644 (file)
index 0000000..25f4fc4
--- /dev/null
@@ -0,0 +1,525 @@
+/* This file has been automatically generated by crc32_tablegen.c. */
+
+const uint32_t lzma_crc32_table[8][256] = {
+       {
+               0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
+               0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+               0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+               0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+               0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
+               0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+               0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
+               0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+               0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+               0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+               0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
+               0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+               0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
+               0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+               0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+               0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+               0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
+               0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+               0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
+               0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+               0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
+               0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+               0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
+               0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+               0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
+               0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+               0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+               0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+               0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
+               0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+               0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
+               0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+               0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
+               0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+               0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
+               0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+               0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
+               0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+               0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
+               0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+               0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
+               0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+               0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
+               0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+               0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+               0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+               0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
+               0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+               0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
+               0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+               0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
+               0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+               0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
+               0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+               0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
+               0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+               0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
+               0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+               0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
+               0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+               0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
+               0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+               0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+               0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+       }, {
+               0x00000000, 0x191B3141, 0x32366282, 0x2B2D53C3,
+               0x646CC504, 0x7D77F445, 0x565AA786, 0x4F4196C7,
+               0xC8D98A08, 0xD1C2BB49, 0xFAEFE88A, 0xE3F4D9CB,
+               0xACB54F0C, 0xB5AE7E4D, 0x9E832D8E, 0x87981CCF,
+               0x4AC21251, 0x53D92310, 0x78F470D3, 0x61EF4192,
+               0x2EAED755, 0x37B5E614, 0x1C98B5D7, 0x05838496,
+               0x821B9859, 0x9B00A918, 0xB02DFADB, 0xA936CB9A,
+               0xE6775D5D, 0xFF6C6C1C, 0xD4413FDF, 0xCD5A0E9E,
+               0x958424A2, 0x8C9F15E3, 0xA7B24620, 0xBEA97761,
+               0xF1E8E1A6, 0xE8F3D0E7, 0xC3DE8324, 0xDAC5B265,
+               0x5D5DAEAA, 0x44469FEB, 0x6F6BCC28, 0x7670FD69,
+               0x39316BAE, 0x202A5AEF, 0x0B07092C, 0x121C386D,
+               0xDF4636F3, 0xC65D07B2, 0xED705471, 0xF46B6530,
+               0xBB2AF3F7, 0xA231C2B6, 0x891C9175, 0x9007A034,
+               0x179FBCFB, 0x0E848DBA, 0x25A9DE79, 0x3CB2EF38,
+               0x73F379FF, 0x6AE848BE, 0x41C51B7D, 0x58DE2A3C,
+               0xF0794F05, 0xE9627E44, 0xC24F2D87, 0xDB541CC6,
+               0x94158A01, 0x8D0EBB40, 0xA623E883, 0xBF38D9C2,
+               0x38A0C50D, 0x21BBF44C, 0x0A96A78F, 0x138D96CE,
+               0x5CCC0009, 0x45D73148, 0x6EFA628B, 0x77E153CA,
+               0xBABB5D54, 0xA3A06C15, 0x888D3FD6, 0x91960E97,
+               0xDED79850, 0xC7CCA911, 0xECE1FAD2, 0xF5FACB93,
+               0x7262D75C, 0x6B79E61D, 0x4054B5DE, 0x594F849F,
+               0x160E1258, 0x0F152319, 0x243870DA, 0x3D23419B,
+               0x65FD6BA7, 0x7CE65AE6, 0x57CB0925, 0x4ED03864,
+               0x0191AEA3, 0x188A9FE2, 0x33A7CC21, 0x2ABCFD60,
+               0xAD24E1AF, 0xB43FD0EE, 0x9F12832D, 0x8609B26C,
+               0xC94824AB, 0xD05315EA, 0xFB7E4629, 0xE2657768,
+               0x2F3F79F6, 0x362448B7, 0x1D091B74, 0x04122A35,
+               0x4B53BCF2, 0x52488DB3, 0x7965DE70, 0x607EEF31,
+               0xE7E6F3FE, 0xFEFDC2BF, 0xD5D0917C, 0xCCCBA03D,
+               0x838A36FA, 0x9A9107BB, 0xB1BC5478, 0xA8A76539,
+               0x3B83984B, 0x2298A90A, 0x09B5FAC9, 0x10AECB88,
+               0x5FEF5D4F, 0x46F46C0E, 0x6DD93FCD, 0x74C20E8C,
+               0xF35A1243, 0xEA412302, 0xC16C70C1, 0xD8774180,
+               0x9736D747, 0x8E2DE606, 0xA500B5C5, 0xBC1B8484,
+               0x71418A1A, 0x685ABB5B, 0x4377E898, 0x5A6CD9D9,
+               0x152D4F1E, 0x0C367E5F, 0x271B2D9C, 0x3E001CDD,
+               0xB9980012, 0xA0833153, 0x8BAE6290, 0x92B553D1,
+               0xDDF4C516, 0xC4EFF457, 0xEFC2A794, 0xF6D996D5,
+               0xAE07BCE9, 0xB71C8DA8, 0x9C31DE6B, 0x852AEF2A,
+               0xCA6B79ED, 0xD37048AC, 0xF85D1B6F, 0xE1462A2E,
+               0x66DE36E1, 0x7FC507A0, 0x54E85463, 0x4DF36522,
+               0x02B2F3E5, 0x1BA9C2A4, 0x30849167, 0x299FA026,
+               0xE4C5AEB8, 0xFDDE9FF9, 0xD6F3CC3A, 0xCFE8FD7B,
+               0x80A96BBC, 0x99B25AFD, 0xB29F093E, 0xAB84387F,
+               0x2C1C24B0, 0x350715F1, 0x1E2A4632, 0x07317773,
+               0x4870E1B4, 0x516BD0F5, 0x7A468336, 0x635DB277,
+               0xCBFAD74E, 0xD2E1E60F, 0xF9CCB5CC, 0xE0D7848D,
+               0xAF96124A, 0xB68D230B, 0x9DA070C8, 0x84BB4189,
+               0x03235D46, 0x1A386C07, 0x31153FC4, 0x280E0E85,
+               0x674F9842, 0x7E54A903, 0x5579FAC0, 0x4C62CB81,
+               0x8138C51F, 0x9823F45E, 0xB30EA79D, 0xAA1596DC,
+               0xE554001B, 0xFC4F315A, 0xD7626299, 0xCE7953D8,
+               0x49E14F17, 0x50FA7E56, 0x7BD72D95, 0x62CC1CD4,
+               0x2D8D8A13, 0x3496BB52, 0x1FBBE891, 0x06A0D9D0,
+               0x5E7EF3EC, 0x4765C2AD, 0x6C48916E, 0x7553A02F,
+               0x3A1236E8, 0x230907A9, 0x0824546A, 0x113F652B,
+               0x96A779E4, 0x8FBC48A5, 0xA4911B66, 0xBD8A2A27,
+               0xF2CBBCE0, 0xEBD08DA1, 0xC0FDDE62, 0xD9E6EF23,
+               0x14BCE1BD, 0x0DA7D0FC, 0x268A833F, 0x3F91B27E,
+               0x70D024B9, 0x69CB15F8, 0x42E6463B, 0x5BFD777A,
+               0xDC656BB5, 0xC57E5AF4, 0xEE530937, 0xF7483876,
+               0xB809AEB1, 0xA1129FF0, 0x8A3FCC33, 0x9324FD72
+       }, {
+               0x00000000, 0x01C26A37, 0x0384D46E, 0x0246BE59,
+               0x0709A8DC, 0x06CBC2EB, 0x048D7CB2, 0x054F1685,
+               0x0E1351B8, 0x0FD13B8F, 0x0D9785D6, 0x0C55EFE1,
+               0x091AF964, 0x08D89353, 0x0A9E2D0A, 0x0B5C473D,
+               0x1C26A370, 0x1DE4C947, 0x1FA2771E, 0x1E601D29,
+               0x1B2F0BAC, 0x1AED619B, 0x18ABDFC2, 0x1969B5F5,
+               0x1235F2C8, 0x13F798FF, 0x11B126A6, 0x10734C91,
+               0x153C5A14, 0x14FE3023, 0x16B88E7A, 0x177AE44D,
+               0x384D46E0, 0x398F2CD7, 0x3BC9928E, 0x3A0BF8B9,
+               0x3F44EE3C, 0x3E86840B, 0x3CC03A52, 0x3D025065,
+               0x365E1758, 0x379C7D6F, 0x35DAC336, 0x3418A901,
+               0x3157BF84, 0x3095D5B3, 0x32D36BEA, 0x331101DD,
+               0x246BE590, 0x25A98FA7, 0x27EF31FE, 0x262D5BC9,
+               0x23624D4C, 0x22A0277B, 0x20E69922, 0x2124F315,
+               0x2A78B428, 0x2BBADE1F, 0x29FC6046, 0x283E0A71,
+               0x2D711CF4, 0x2CB376C3, 0x2EF5C89A, 0x2F37A2AD,
+               0x709A8DC0, 0x7158E7F7, 0x731E59AE, 0x72DC3399,
+               0x7793251C, 0x76514F2B, 0x7417F172, 0x75D59B45,
+               0x7E89DC78, 0x7F4BB64F, 0x7D0D0816, 0x7CCF6221,
+               0x798074A4, 0x78421E93, 0x7A04A0CA, 0x7BC6CAFD,
+               0x6CBC2EB0, 0x6D7E4487, 0x6F38FADE, 0x6EFA90E9,
+               0x6BB5866C, 0x6A77EC5B, 0x68315202, 0x69F33835,
+               0x62AF7F08, 0x636D153F, 0x612BAB66, 0x60E9C151,
+               0x65A6D7D4, 0x6464BDE3, 0x662203BA, 0x67E0698D,
+               0x48D7CB20, 0x4915A117, 0x4B531F4E, 0x4A917579,
+               0x4FDE63FC, 0x4E1C09CB, 0x4C5AB792, 0x4D98DDA5,
+               0x46C49A98, 0x4706F0AF, 0x45404EF6, 0x448224C1,
+               0x41CD3244, 0x400F5873, 0x4249E62A, 0x438B8C1D,
+               0x54F16850, 0x55330267, 0x5775BC3E, 0x56B7D609,
+               0x53F8C08C, 0x523AAABB, 0x507C14E2, 0x51BE7ED5,
+               0x5AE239E8, 0x5B2053DF, 0x5966ED86, 0x58A487B1,
+               0x5DEB9134, 0x5C29FB03, 0x5E6F455A, 0x5FAD2F6D,
+               0xE1351B80, 0xE0F771B7, 0xE2B1CFEE, 0xE373A5D9,
+               0xE63CB35C, 0xE7FED96B, 0xE5B86732, 0xE47A0D05,
+               0xEF264A38, 0xEEE4200F, 0xECA29E56, 0xED60F461,
+               0xE82FE2E4, 0xE9ED88D3, 0xEBAB368A, 0xEA695CBD,
+               0xFD13B8F0, 0xFCD1D2C7, 0xFE976C9E, 0xFF5506A9,
+               0xFA1A102C, 0xFBD87A1B, 0xF99EC442, 0xF85CAE75,
+               0xF300E948, 0xF2C2837F, 0xF0843D26, 0xF1465711,
+               0xF4094194, 0xF5CB2BA3, 0xF78D95FA, 0xF64FFFCD,
+               0xD9785D60, 0xD8BA3757, 0xDAFC890E, 0xDB3EE339,
+               0xDE71F5BC, 0xDFB39F8B, 0xDDF521D2, 0xDC374BE5,
+               0xD76B0CD8, 0xD6A966EF, 0xD4EFD8B6, 0xD52DB281,
+               0xD062A404, 0xD1A0CE33, 0xD3E6706A, 0xD2241A5D,
+               0xC55EFE10, 0xC49C9427, 0xC6DA2A7E, 0xC7184049,
+               0xC25756CC, 0xC3953CFB, 0xC1D382A2, 0xC011E895,
+               0xCB4DAFA8, 0xCA8FC59F, 0xC8C97BC6, 0xC90B11F1,
+               0xCC440774, 0xCD866D43, 0xCFC0D31A, 0xCE02B92D,
+               0x91AF9640, 0x906DFC77, 0x922B422E, 0x93E92819,
+               0x96A63E9C, 0x976454AB, 0x9522EAF2, 0x94E080C5,
+               0x9FBCC7F8, 0x9E7EADCF, 0x9C381396, 0x9DFA79A1,
+               0x98B56F24, 0x99770513, 0x9B31BB4A, 0x9AF3D17D,
+               0x8D893530, 0x8C4B5F07, 0x8E0DE15E, 0x8FCF8B69,
+               0x8A809DEC, 0x8B42F7DB, 0x89044982, 0x88C623B5,
+               0x839A6488, 0x82580EBF, 0x801EB0E6, 0x81DCDAD1,
+               0x8493CC54, 0x8551A663, 0x8717183A, 0x86D5720D,
+               0xA9E2D0A0, 0xA820BA97, 0xAA6604CE, 0xABA46EF9,
+               0xAEEB787C, 0xAF29124B, 0xAD6FAC12, 0xACADC625,
+               0xA7F18118, 0xA633EB2F, 0xA4755576, 0xA5B73F41,
+               0xA0F829C4, 0xA13A43F3, 0xA37CFDAA, 0xA2BE979D,
+               0xB5C473D0, 0xB40619E7, 0xB640A7BE, 0xB782CD89,
+               0xB2CDDB0C, 0xB30FB13B, 0xB1490F62, 0xB08B6555,
+               0xBBD72268, 0xBA15485F, 0xB853F606, 0xB9919C31,
+               0xBCDE8AB4, 0xBD1CE083, 0xBF5A5EDA, 0xBE9834ED
+       }, {
+               0x00000000, 0xB8BC6765, 0xAA09C88B, 0x12B5AFEE,
+               0x8F629757, 0x37DEF032, 0x256B5FDC, 0x9DD738B9,
+               0xC5B428EF, 0x7D084F8A, 0x6FBDE064, 0xD7018701,
+               0x4AD6BFB8, 0xF26AD8DD, 0xE0DF7733, 0x58631056,
+               0x5019579F, 0xE8A530FA, 0xFA109F14, 0x42ACF871,
+               0xDF7BC0C8, 0x67C7A7AD, 0x75720843, 0xCDCE6F26,
+               0x95AD7F70, 0x2D111815, 0x3FA4B7FB, 0x8718D09E,
+               0x1ACFE827, 0xA2738F42, 0xB0C620AC, 0x087A47C9,
+               0xA032AF3E, 0x188EC85B, 0x0A3B67B5, 0xB28700D0,
+               0x2F503869, 0x97EC5F0C, 0x8559F0E2, 0x3DE59787,
+               0x658687D1, 0xDD3AE0B4, 0xCF8F4F5A, 0x7733283F,
+               0xEAE41086, 0x525877E3, 0x40EDD80D, 0xF851BF68,
+               0xF02BF8A1, 0x48979FC4, 0x5A22302A, 0xE29E574F,
+               0x7F496FF6, 0xC7F50893, 0xD540A77D, 0x6DFCC018,
+               0x359FD04E, 0x8D23B72B, 0x9F9618C5, 0x272A7FA0,
+               0xBAFD4719, 0x0241207C, 0x10F48F92, 0xA848E8F7,
+               0x9B14583D, 0x23A83F58, 0x311D90B6, 0x89A1F7D3,
+               0x1476CF6A, 0xACCAA80F, 0xBE7F07E1, 0x06C36084,
+               0x5EA070D2, 0xE61C17B7, 0xF4A9B859, 0x4C15DF3C,
+               0xD1C2E785, 0x697E80E0, 0x7BCB2F0E, 0xC377486B,
+               0xCB0D0FA2, 0x73B168C7, 0x6104C729, 0xD9B8A04C,
+               0x446F98F5, 0xFCD3FF90, 0xEE66507E, 0x56DA371B,
+               0x0EB9274D, 0xB6054028, 0xA4B0EFC6, 0x1C0C88A3,
+               0x81DBB01A, 0x3967D77F, 0x2BD27891, 0x936E1FF4,
+               0x3B26F703, 0x839A9066, 0x912F3F88, 0x299358ED,
+               0xB4446054, 0x0CF80731, 0x1E4DA8DF, 0xA6F1CFBA,
+               0xFE92DFEC, 0x462EB889, 0x549B1767, 0xEC277002,
+               0x71F048BB, 0xC94C2FDE, 0xDBF98030, 0x6345E755,
+               0x6B3FA09C, 0xD383C7F9, 0xC1366817, 0x798A0F72,
+               0xE45D37CB, 0x5CE150AE, 0x4E54FF40, 0xF6E89825,
+               0xAE8B8873, 0x1637EF16, 0x048240F8, 0xBC3E279D,
+               0x21E91F24, 0x99557841, 0x8BE0D7AF, 0x335CB0CA,
+               0xED59B63B, 0x55E5D15E, 0x47507EB0, 0xFFEC19D5,
+               0x623B216C, 0xDA874609, 0xC832E9E7, 0x708E8E82,
+               0x28ED9ED4, 0x9051F9B1, 0x82E4565F, 0x3A58313A,
+               0xA78F0983, 0x1F336EE6, 0x0D86C108, 0xB53AA66D,
+               0xBD40E1A4, 0x05FC86C1, 0x1749292F, 0xAFF54E4A,
+               0x322276F3, 0x8A9E1196, 0x982BBE78, 0x2097D91D,
+               0x78F4C94B, 0xC048AE2E, 0xD2FD01C0, 0x6A4166A5,
+               0xF7965E1C, 0x4F2A3979, 0x5D9F9697, 0xE523F1F2,
+               0x4D6B1905, 0xF5D77E60, 0xE762D18E, 0x5FDEB6EB,
+               0xC2098E52, 0x7AB5E937, 0x680046D9, 0xD0BC21BC,
+               0x88DF31EA, 0x3063568F, 0x22D6F961, 0x9A6A9E04,
+               0x07BDA6BD, 0xBF01C1D8, 0xADB46E36, 0x15080953,
+               0x1D724E9A, 0xA5CE29FF, 0xB77B8611, 0x0FC7E174,
+               0x9210D9CD, 0x2AACBEA8, 0x38191146, 0x80A57623,
+               0xD8C66675, 0x607A0110, 0x72CFAEFE, 0xCA73C99B,
+               0x57A4F122, 0xEF189647, 0xFDAD39A9, 0x45115ECC,
+               0x764DEE06, 0xCEF18963, 0xDC44268D, 0x64F841E8,
+               0xF92F7951, 0x41931E34, 0x5326B1DA, 0xEB9AD6BF,
+               0xB3F9C6E9, 0x0B45A18C, 0x19F00E62, 0xA14C6907,
+               0x3C9B51BE, 0x842736DB, 0x96929935, 0x2E2EFE50,
+               0x2654B999, 0x9EE8DEFC, 0x8C5D7112, 0x34E11677,
+               0xA9362ECE, 0x118A49AB, 0x033FE645, 0xBB838120,
+               0xE3E09176, 0x5B5CF613, 0x49E959FD, 0xF1553E98,
+               0x6C820621, 0xD43E6144, 0xC68BCEAA, 0x7E37A9CF,
+               0xD67F4138, 0x6EC3265D, 0x7C7689B3, 0xC4CAEED6,
+               0x591DD66F, 0xE1A1B10A, 0xF3141EE4, 0x4BA87981,
+               0x13CB69D7, 0xAB770EB2, 0xB9C2A15C, 0x017EC639,
+               0x9CA9FE80, 0x241599E5, 0x36A0360B, 0x8E1C516E,
+               0x866616A7, 0x3EDA71C2, 0x2C6FDE2C, 0x94D3B949,
+               0x090481F0, 0xB1B8E695, 0xA30D497B, 0x1BB12E1E,
+               0x43D23E48, 0xFB6E592D, 0xE9DBF6C3, 0x516791A6,
+               0xCCB0A91F, 0x740CCE7A, 0x66B96194, 0xDE0506F1
+       }, {
+               0x00000000, 0x3D6029B0, 0x7AC05360, 0x47A07AD0,
+               0xF580A6C0, 0xC8E08F70, 0x8F40F5A0, 0xB220DC10,
+               0x30704BC1, 0x0D106271, 0x4AB018A1, 0x77D03111,
+               0xC5F0ED01, 0xF890C4B1, 0xBF30BE61, 0x825097D1,
+               0x60E09782, 0x5D80BE32, 0x1A20C4E2, 0x2740ED52,
+               0x95603142, 0xA80018F2, 0xEFA06222, 0xD2C04B92,
+               0x5090DC43, 0x6DF0F5F3, 0x2A508F23, 0x1730A693,
+               0xA5107A83, 0x98705333, 0xDFD029E3, 0xE2B00053,
+               0xC1C12F04, 0xFCA106B4, 0xBB017C64, 0x866155D4,
+               0x344189C4, 0x0921A074, 0x4E81DAA4, 0x73E1F314,
+               0xF1B164C5, 0xCCD14D75, 0x8B7137A5, 0xB6111E15,
+               0x0431C205, 0x3951EBB5, 0x7EF19165, 0x4391B8D5,
+               0xA121B886, 0x9C419136, 0xDBE1EBE6, 0xE681C256,
+               0x54A11E46, 0x69C137F6, 0x2E614D26, 0x13016496,
+               0x9151F347, 0xAC31DAF7, 0xEB91A027, 0xD6F18997,
+               0x64D15587, 0x59B17C37, 0x1E1106E7, 0x23712F57,
+               0x58F35849, 0x659371F9, 0x22330B29, 0x1F532299,
+               0xAD73FE89, 0x9013D739, 0xD7B3ADE9, 0xEAD38459,
+               0x68831388, 0x55E33A38, 0x124340E8, 0x2F236958,
+               0x9D03B548, 0xA0639CF8, 0xE7C3E628, 0xDAA3CF98,
+               0x3813CFCB, 0x0573E67B, 0x42D39CAB, 0x7FB3B51B,
+               0xCD93690B, 0xF0F340BB, 0xB7533A6B, 0x8A3313DB,
+               0x0863840A, 0x3503ADBA, 0x72A3D76A, 0x4FC3FEDA,
+               0xFDE322CA, 0xC0830B7A, 0x872371AA, 0xBA43581A,
+               0x9932774D, 0xA4525EFD, 0xE3F2242D, 0xDE920D9D,
+               0x6CB2D18D, 0x51D2F83D, 0x167282ED, 0x2B12AB5D,
+               0xA9423C8C, 0x9422153C, 0xD3826FEC, 0xEEE2465C,
+               0x5CC29A4C, 0x61A2B3FC, 0x2602C92C, 0x1B62E09C,
+               0xF9D2E0CF, 0xC4B2C97F, 0x8312B3AF, 0xBE729A1F,
+               0x0C52460F, 0x31326FBF, 0x7692156F, 0x4BF23CDF,
+               0xC9A2AB0E, 0xF4C282BE, 0xB362F86E, 0x8E02D1DE,
+               0x3C220DCE, 0x0142247E, 0x46E25EAE, 0x7B82771E,
+               0xB1E6B092, 0x8C869922, 0xCB26E3F2, 0xF646CA42,
+               0x44661652, 0x79063FE2, 0x3EA64532, 0x03C66C82,
+               0x8196FB53, 0xBCF6D2E3, 0xFB56A833, 0xC6368183,
+               0x74165D93, 0x49767423, 0x0ED60EF3, 0x33B62743,
+               0xD1062710, 0xEC660EA0, 0xABC67470, 0x96A65DC0,
+               0x248681D0, 0x19E6A860, 0x5E46D2B0, 0x6326FB00,
+               0xE1766CD1, 0xDC164561, 0x9BB63FB1, 0xA6D61601,
+               0x14F6CA11, 0x2996E3A1, 0x6E369971, 0x5356B0C1,
+               0x70279F96, 0x4D47B626, 0x0AE7CCF6, 0x3787E546,
+               0x85A73956, 0xB8C710E6, 0xFF676A36, 0xC2074386,
+               0x4057D457, 0x7D37FDE7, 0x3A978737, 0x07F7AE87,
+               0xB5D77297, 0x88B75B27, 0xCF1721F7, 0xF2770847,
+               0x10C70814, 0x2DA721A4, 0x6A075B74, 0x576772C4,
+               0xE547AED4, 0xD8278764, 0x9F87FDB4, 0xA2E7D404,
+               0x20B743D5, 0x1DD76A65, 0x5A7710B5, 0x67173905,
+               0xD537E515, 0xE857CCA5, 0xAFF7B675, 0x92979FC5,
+               0xE915E8DB, 0xD475C16B, 0x93D5BBBB, 0xAEB5920B,
+               0x1C954E1B, 0x21F567AB, 0x66551D7B, 0x5B3534CB,
+               0xD965A31A, 0xE4058AAA, 0xA3A5F07A, 0x9EC5D9CA,
+               0x2CE505DA, 0x11852C6A, 0x562556BA, 0x6B457F0A,
+               0x89F57F59, 0xB49556E9, 0xF3352C39, 0xCE550589,
+               0x7C75D999, 0x4115F029, 0x06B58AF9, 0x3BD5A349,
+               0xB9853498, 0x84E51D28, 0xC34567F8, 0xFE254E48,
+               0x4C059258, 0x7165BBE8, 0x36C5C138, 0x0BA5E888,
+               0x28D4C7DF, 0x15B4EE6F, 0x521494BF, 0x6F74BD0F,
+               0xDD54611F, 0xE03448AF, 0xA794327F, 0x9AF41BCF,
+               0x18A48C1E, 0x25C4A5AE, 0x6264DF7E, 0x5F04F6CE,
+               0xED242ADE, 0xD044036E, 0x97E479BE, 0xAA84500E,
+               0x4834505D, 0x755479ED, 0x32F4033D, 0x0F942A8D,
+               0xBDB4F69D, 0x80D4DF2D, 0xC774A5FD, 0xFA148C4D,
+               0x78441B9C, 0x4524322C, 0x028448FC, 0x3FE4614C,
+               0x8DC4BD5C, 0xB0A494EC, 0xF704EE3C, 0xCA64C78C
+       }, {
+               0x00000000, 0xCB5CD3A5, 0x4DC8A10B, 0x869472AE,
+               0x9B914216, 0x50CD91B3, 0xD659E31D, 0x1D0530B8,
+               0xEC53826D, 0x270F51C8, 0xA19B2366, 0x6AC7F0C3,
+               0x77C2C07B, 0xBC9E13DE, 0x3A0A6170, 0xF156B2D5,
+               0x03D6029B, 0xC88AD13E, 0x4E1EA390, 0x85427035,
+               0x9847408D, 0x531B9328, 0xD58FE186, 0x1ED33223,
+               0xEF8580F6, 0x24D95353, 0xA24D21FD, 0x6911F258,
+               0x7414C2E0, 0xBF481145, 0x39DC63EB, 0xF280B04E,
+               0x07AC0536, 0xCCF0D693, 0x4A64A43D, 0x81387798,
+               0x9C3D4720, 0x57619485, 0xD1F5E62B, 0x1AA9358E,
+               0xEBFF875B, 0x20A354FE, 0xA6372650, 0x6D6BF5F5,
+               0x706EC54D, 0xBB3216E8, 0x3DA66446, 0xF6FAB7E3,
+               0x047A07AD, 0xCF26D408, 0x49B2A6A6, 0x82EE7503,
+               0x9FEB45BB, 0x54B7961E, 0xD223E4B0, 0x197F3715,
+               0xE82985C0, 0x23755665, 0xA5E124CB, 0x6EBDF76E,
+               0x73B8C7D6, 0xB8E41473, 0x3E7066DD, 0xF52CB578,
+               0x0F580A6C, 0xC404D9C9, 0x4290AB67, 0x89CC78C2,
+               0x94C9487A, 0x5F959BDF, 0xD901E971, 0x125D3AD4,
+               0xE30B8801, 0x28575BA4, 0xAEC3290A, 0x659FFAAF,
+               0x789ACA17, 0xB3C619B2, 0x35526B1C, 0xFE0EB8B9,
+               0x0C8E08F7, 0xC7D2DB52, 0x4146A9FC, 0x8A1A7A59,
+               0x971F4AE1, 0x5C439944, 0xDAD7EBEA, 0x118B384F,
+               0xE0DD8A9A, 0x2B81593F, 0xAD152B91, 0x6649F834,
+               0x7B4CC88C, 0xB0101B29, 0x36846987, 0xFDD8BA22,
+               0x08F40F5A, 0xC3A8DCFF, 0x453CAE51, 0x8E607DF4,
+               0x93654D4C, 0x58399EE9, 0xDEADEC47, 0x15F13FE2,
+               0xE4A78D37, 0x2FFB5E92, 0xA96F2C3C, 0x6233FF99,
+               0x7F36CF21, 0xB46A1C84, 0x32FE6E2A, 0xF9A2BD8F,
+               0x0B220DC1, 0xC07EDE64, 0x46EAACCA, 0x8DB67F6F,
+               0x90B34FD7, 0x5BEF9C72, 0xDD7BEEDC, 0x16273D79,
+               0xE7718FAC, 0x2C2D5C09, 0xAAB92EA7, 0x61E5FD02,
+               0x7CE0CDBA, 0xB7BC1E1F, 0x31286CB1, 0xFA74BF14,
+               0x1EB014D8, 0xD5ECC77D, 0x5378B5D3, 0x98246676,
+               0x852156CE, 0x4E7D856B, 0xC8E9F7C5, 0x03B52460,
+               0xF2E396B5, 0x39BF4510, 0xBF2B37BE, 0x7477E41B,
+               0x6972D4A3, 0xA22E0706, 0x24BA75A8, 0xEFE6A60D,
+               0x1D661643, 0xD63AC5E6, 0x50AEB748, 0x9BF264ED,
+               0x86F75455, 0x4DAB87F0, 0xCB3FF55E, 0x006326FB,
+               0xF135942E, 0x3A69478B, 0xBCFD3525, 0x77A1E680,
+               0x6AA4D638, 0xA1F8059D, 0x276C7733, 0xEC30A496,
+               0x191C11EE, 0xD240C24B, 0x54D4B0E5, 0x9F886340,
+               0x828D53F8, 0x49D1805D, 0xCF45F2F3, 0x04192156,
+               0xF54F9383, 0x3E134026, 0xB8873288, 0x73DBE12D,
+               0x6EDED195, 0xA5820230, 0x2316709E, 0xE84AA33B,
+               0x1ACA1375, 0xD196C0D0, 0x5702B27E, 0x9C5E61DB,
+               0x815B5163, 0x4A0782C6, 0xCC93F068, 0x07CF23CD,
+               0xF6999118, 0x3DC542BD, 0xBB513013, 0x700DE3B6,
+               0x6D08D30E, 0xA65400AB, 0x20C07205, 0xEB9CA1A0,
+               0x11E81EB4, 0xDAB4CD11, 0x5C20BFBF, 0x977C6C1A,
+               0x8A795CA2, 0x41258F07, 0xC7B1FDA9, 0x0CED2E0C,
+               0xFDBB9CD9, 0x36E74F7C, 0xB0733DD2, 0x7B2FEE77,
+               0x662ADECF, 0xAD760D6A, 0x2BE27FC4, 0xE0BEAC61,
+               0x123E1C2F, 0xD962CF8A, 0x5FF6BD24, 0x94AA6E81,
+               0x89AF5E39, 0x42F38D9C, 0xC467FF32, 0x0F3B2C97,
+               0xFE6D9E42, 0x35314DE7, 0xB3A53F49, 0x78F9ECEC,
+               0x65FCDC54, 0xAEA00FF1, 0x28347D5F, 0xE368AEFA,
+               0x16441B82, 0xDD18C827, 0x5B8CBA89, 0x90D0692C,
+               0x8DD55994, 0x46898A31, 0xC01DF89F, 0x0B412B3A,
+               0xFA1799EF, 0x314B4A4A, 0xB7DF38E4, 0x7C83EB41,
+               0x6186DBF9, 0xAADA085C, 0x2C4E7AF2, 0xE712A957,
+               0x15921919, 0xDECECABC, 0x585AB812, 0x93066BB7,
+               0x8E035B0F, 0x455F88AA, 0xC3CBFA04, 0x089729A1,
+               0xF9C19B74, 0x329D48D1, 0xB4093A7F, 0x7F55E9DA,
+               0x6250D962, 0xA90C0AC7, 0x2F987869, 0xE4C4ABCC
+       }, {
+               0x00000000, 0xA6770BB4, 0x979F1129, 0x31E81A9D,
+               0xF44F2413, 0x52382FA7, 0x63D0353A, 0xC5A73E8E,
+               0x33EF4E67, 0x959845D3, 0xA4705F4E, 0x020754FA,
+               0xC7A06A74, 0x61D761C0, 0x503F7B5D, 0xF64870E9,
+               0x67DE9CCE, 0xC1A9977A, 0xF0418DE7, 0x56368653,
+               0x9391B8DD, 0x35E6B369, 0x040EA9F4, 0xA279A240,
+               0x5431D2A9, 0xF246D91D, 0xC3AEC380, 0x65D9C834,
+               0xA07EF6BA, 0x0609FD0E, 0x37E1E793, 0x9196EC27,
+               0xCFBD399C, 0x69CA3228, 0x582228B5, 0xFE552301,
+               0x3BF21D8F, 0x9D85163B, 0xAC6D0CA6, 0x0A1A0712,
+               0xFC5277FB, 0x5A257C4F, 0x6BCD66D2, 0xCDBA6D66,
+               0x081D53E8, 0xAE6A585C, 0x9F8242C1, 0x39F54975,
+               0xA863A552, 0x0E14AEE6, 0x3FFCB47B, 0x998BBFCF,
+               0x5C2C8141, 0xFA5B8AF5, 0xCBB39068, 0x6DC49BDC,
+               0x9B8CEB35, 0x3DFBE081, 0x0C13FA1C, 0xAA64F1A8,
+               0x6FC3CF26, 0xC9B4C492, 0xF85CDE0F, 0x5E2BD5BB,
+               0x440B7579, 0xE27C7ECD, 0xD3946450, 0x75E36FE4,
+               0xB044516A, 0x16335ADE, 0x27DB4043, 0x81AC4BF7,
+               0x77E43B1E, 0xD19330AA, 0xE07B2A37, 0x460C2183,
+               0x83AB1F0D, 0x25DC14B9, 0x14340E24, 0xB2430590,
+               0x23D5E9B7, 0x85A2E203, 0xB44AF89E, 0x123DF32A,
+               0xD79ACDA4, 0x71EDC610, 0x4005DC8D, 0xE672D739,
+               0x103AA7D0, 0xB64DAC64, 0x87A5B6F9, 0x21D2BD4D,
+               0xE47583C3, 0x42028877, 0x73EA92EA, 0xD59D995E,
+               0x8BB64CE5, 0x2DC14751, 0x1C295DCC, 0xBA5E5678,
+               0x7FF968F6, 0xD98E6342, 0xE86679DF, 0x4E11726B,
+               0xB8590282, 0x1E2E0936, 0x2FC613AB, 0x89B1181F,
+               0x4C162691, 0xEA612D25, 0xDB8937B8, 0x7DFE3C0C,
+               0xEC68D02B, 0x4A1FDB9F, 0x7BF7C102, 0xDD80CAB6,
+               0x1827F438, 0xBE50FF8C, 0x8FB8E511, 0x29CFEEA5,
+               0xDF879E4C, 0x79F095F8, 0x48188F65, 0xEE6F84D1,
+               0x2BC8BA5F, 0x8DBFB1EB, 0xBC57AB76, 0x1A20A0C2,
+               0x8816EAF2, 0x2E61E146, 0x1F89FBDB, 0xB9FEF06F,
+               0x7C59CEE1, 0xDA2EC555, 0xEBC6DFC8, 0x4DB1D47C,
+               0xBBF9A495, 0x1D8EAF21, 0x2C66B5BC, 0x8A11BE08,
+               0x4FB68086, 0xE9C18B32, 0xD82991AF, 0x7E5E9A1B,
+               0xEFC8763C, 0x49BF7D88, 0x78576715, 0xDE206CA1,
+               0x1B87522F, 0xBDF0599B, 0x8C184306, 0x2A6F48B2,
+               0xDC27385B, 0x7A5033EF, 0x4BB82972, 0xEDCF22C6,
+               0x28681C48, 0x8E1F17FC, 0xBFF70D61, 0x198006D5,
+               0x47ABD36E, 0xE1DCD8DA, 0xD034C247, 0x7643C9F3,
+               0xB3E4F77D, 0x1593FCC9, 0x247BE654, 0x820CEDE0,
+               0x74449D09, 0xD23396BD, 0xE3DB8C20, 0x45AC8794,
+               0x800BB91A, 0x267CB2AE, 0x1794A833, 0xB1E3A387,
+               0x20754FA0, 0x86024414, 0xB7EA5E89, 0x119D553D,
+               0xD43A6BB3, 0x724D6007, 0x43A57A9A, 0xE5D2712E,
+               0x139A01C7, 0xB5ED0A73, 0x840510EE, 0x22721B5A,
+               0xE7D525D4, 0x41A22E60, 0x704A34FD, 0xD63D3F49,
+               0xCC1D9F8B, 0x6A6A943F, 0x5B828EA2, 0xFDF58516,
+               0x3852BB98, 0x9E25B02C, 0xAFCDAAB1, 0x09BAA105,
+               0xFFF2D1EC, 0x5985DA58, 0x686DC0C5, 0xCE1ACB71,
+               0x0BBDF5FF, 0xADCAFE4B, 0x9C22E4D6, 0x3A55EF62,
+               0xABC30345, 0x0DB408F1, 0x3C5C126C, 0x9A2B19D8,
+               0x5F8C2756, 0xF9FB2CE2, 0xC813367F, 0x6E643DCB,
+               0x982C4D22, 0x3E5B4696, 0x0FB35C0B, 0xA9C457BF,
+               0x6C636931, 0xCA146285, 0xFBFC7818, 0x5D8B73AC,
+               0x03A0A617, 0xA5D7ADA3, 0x943FB73E, 0x3248BC8A,
+               0xF7EF8204, 0x519889B0, 0x6070932D, 0xC6079899,
+               0x304FE870, 0x9638E3C4, 0xA7D0F959, 0x01A7F2ED,
+               0xC400CC63, 0x6277C7D7, 0x539FDD4A, 0xF5E8D6FE,
+               0x647E3AD9, 0xC209316D, 0xF3E12BF0, 0x55962044,
+               0x90311ECA, 0x3646157E, 0x07AE0FE3, 0xA1D90457,
+               0x579174BE, 0xF1E67F0A, 0xC00E6597, 0x66796E23,
+               0xA3DE50AD, 0x05A95B19, 0x34414184, 0x92364A30
+       }, {
+               0x00000000, 0xCCAA009E, 0x4225077D, 0x8E8F07E3,
+               0x844A0EFA, 0x48E00E64, 0xC66F0987, 0x0AC50919,
+               0xD3E51BB5, 0x1F4F1B2B, 0x91C01CC8, 0x5D6A1C56,
+               0x57AF154F, 0x9B0515D1, 0x158A1232, 0xD92012AC,
+               0x7CBB312B, 0xB01131B5, 0x3E9E3656, 0xF23436C8,
+               0xF8F13FD1, 0x345B3F4F, 0xBAD438AC, 0x767E3832,
+               0xAF5E2A9E, 0x63F42A00, 0xED7B2DE3, 0x21D12D7D,
+               0x2B142464, 0xE7BE24FA, 0x69312319, 0xA59B2387,
+               0xF9766256, 0x35DC62C8, 0xBB53652B, 0x77F965B5,
+               0x7D3C6CAC, 0xB1966C32, 0x3F196BD1, 0xF3B36B4F,
+               0x2A9379E3, 0xE639797D, 0x68B67E9E, 0xA41C7E00,
+               0xAED97719, 0x62737787, 0xECFC7064, 0x205670FA,
+               0x85CD537D, 0x496753E3, 0xC7E85400, 0x0B42549E,
+               0x01875D87, 0xCD2D5D19, 0x43A25AFA, 0x8F085A64,
+               0x562848C8, 0x9A824856, 0x140D4FB5, 0xD8A74F2B,
+               0xD2624632, 0x1EC846AC, 0x9047414F, 0x5CED41D1,
+               0x299DC2ED, 0xE537C273, 0x6BB8C590, 0xA712C50E,
+               0xADD7CC17, 0x617DCC89, 0xEFF2CB6A, 0x2358CBF4,
+               0xFA78D958, 0x36D2D9C6, 0xB85DDE25, 0x74F7DEBB,
+               0x7E32D7A2, 0xB298D73C, 0x3C17D0DF, 0xF0BDD041,
+               0x5526F3C6, 0x998CF358, 0x1703F4BB, 0xDBA9F425,
+               0xD16CFD3C, 0x1DC6FDA2, 0x9349FA41, 0x5FE3FADF,
+               0x86C3E873, 0x4A69E8ED, 0xC4E6EF0E, 0x084CEF90,
+               0x0289E689, 0xCE23E617, 0x40ACE1F4, 0x8C06E16A,
+               0xD0EBA0BB, 0x1C41A025, 0x92CEA7C6, 0x5E64A758,
+               0x54A1AE41, 0x980BAEDF, 0x1684A93C, 0xDA2EA9A2,
+               0x030EBB0E, 0xCFA4BB90, 0x412BBC73, 0x8D81BCED,
+               0x8744B5F4, 0x4BEEB56A, 0xC561B289, 0x09CBB217,
+               0xAC509190, 0x60FA910E, 0xEE7596ED, 0x22DF9673,
+               0x281A9F6A, 0xE4B09FF4, 0x6A3F9817, 0xA6959889,
+               0x7FB58A25, 0xB31F8ABB, 0x3D908D58, 0xF13A8DC6,
+               0xFBFF84DF, 0x37558441, 0xB9DA83A2, 0x7570833C,
+               0x533B85DA, 0x9F918544, 0x111E82A7, 0xDDB48239,
+               0xD7718B20, 0x1BDB8BBE, 0x95548C5D, 0x59FE8CC3,
+               0x80DE9E6F, 0x4C749EF1, 0xC2FB9912, 0x0E51998C,
+               0x04949095, 0xC83E900B, 0x46B197E8, 0x8A1B9776,
+               0x2F80B4F1, 0xE32AB46F, 0x6DA5B38C, 0xA10FB312,
+               0xABCABA0B, 0x6760BA95, 0xE9EFBD76, 0x2545BDE8,
+               0xFC65AF44, 0x30CFAFDA, 0xBE40A839, 0x72EAA8A7,
+               0x782FA1BE, 0xB485A120, 0x3A0AA6C3, 0xF6A0A65D,
+               0xAA4DE78C, 0x66E7E712, 0xE868E0F1, 0x24C2E06F,
+               0x2E07E976, 0xE2ADE9E8, 0x6C22EE0B, 0xA088EE95,
+               0x79A8FC39, 0xB502FCA7, 0x3B8DFB44, 0xF727FBDA,
+               0xFDE2F2C3, 0x3148F25D, 0xBFC7F5BE, 0x736DF520,
+               0xD6F6D6A7, 0x1A5CD639, 0x94D3D1DA, 0x5879D144,
+               0x52BCD85D, 0x9E16D8C3, 0x1099DF20, 0xDC33DFBE,
+               0x0513CD12, 0xC9B9CD8C, 0x4736CA6F, 0x8B9CCAF1,
+               0x8159C3E8, 0x4DF3C376, 0xC37CC495, 0x0FD6C40B,
+               0x7AA64737, 0xB60C47A9, 0x3883404A, 0xF42940D4,
+               0xFEEC49CD, 0x32464953, 0xBCC94EB0, 0x70634E2E,
+               0xA9435C82, 0x65E95C1C, 0xEB665BFF, 0x27CC5B61,
+               0x2D095278, 0xE1A352E6, 0x6F2C5505, 0xA386559B,
+               0x061D761C, 0xCAB77682, 0x44387161, 0x889271FF,
+               0x825778E6, 0x4EFD7878, 0xC0727F9B, 0x0CD87F05,
+               0xD5F86DA9, 0x19526D37, 0x97DD6AD4, 0x5B776A4A,
+               0x51B26353, 0x9D1863CD, 0x1397642E, 0xDF3D64B0,
+               0x83D02561, 0x4F7A25FF, 0xC1F5221C, 0x0D5F2282,
+               0x079A2B9B, 0xCB302B05, 0x45BF2CE6, 0x89152C78,
+               0x50353ED4, 0x9C9F3E4A, 0x121039A9, 0xDEBA3937,
+               0xD47F302E, 0x18D530B0, 0x965A3753, 0x5AF037CD,
+               0xFF6B144A, 0x33C114D4, 0xBD4E1337, 0x71E413A9,
+               0x7B211AB0, 0xB78B1A2E, 0x39041DCD, 0xF5AE1D53,
+               0x2C8E0FFF, 0xE0240F61, 0x6EAB0882, 0xA201081C,
+               0xA8C40105, 0x646E019B, 0xEAE10678, 0x264B06E6
+       }
+};
diff --git a/lzma/check/crc32_tablegen.c b/lzma/check/crc32_tablegen.c
new file mode 100644 (file)
index 0000000..44bd668
--- /dev/null
@@ -0,0 +1,117 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       crc32_tablegen.c
+/// \brief      Generate crc32_table_le.h and crc32_table_be.h
+///
+/// Compiling: gcc -std=c99 -o crc32_tablegen crc32_tablegen.c
+/// Add -DWORDS_BIGENDIAN to generate big endian table.
+/// Add -DLZ_HASH_TABLE to generate lz_encoder_hash_table.h (little endian).
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "tuklib_integer.h"
+
+
+static uint32_t crc32_table[8][256];
+
+
+static void
+init_crc32_table(void)
+{
+       static const uint32_t poly32 = UINT32_C(0xEDB88320);
+
+       for (size_t s = 0; s < 8; ++s) {
+               for (size_t b = 0; b < 256; ++b) {
+                       uint32_t r = s == 0 ? b : crc32_table[s - 1][b];
+
+                       for (size_t i = 0; i < 8; ++i) {
+                               if (r & 1)
+                                       r = (r >> 1) ^ poly32;
+                               else
+                                       r >>= 1;
+                       }
+
+                       crc32_table[s][b] = r;
+               }
+       }
+
+#ifdef WORDS_BIGENDIAN
+       for (size_t s = 0; s < 8; ++s)
+               for (size_t b = 0; b < 256; ++b)
+                       crc32_table[s][b] = bswap32(crc32_table[s][b]);
+#endif
+
+       return;
+}
+
+
+static void
+print_crc32_table(void)
+{
+       printf("/* This file has been automatically generated by "
+                       "crc32_tablegen.c. */\n\n"
+                       "const uint32_t lzma_crc32_table[8][256] = {\n\t{");
+
+       for (size_t s = 0; s < 8; ++s) {
+               for (size_t b = 0; b < 256; ++b) {
+                       if ((b % 4) == 0)
+                               printf("\n\t\t");
+
+                       printf("0x%08" PRIX32, crc32_table[s][b]);
+
+                       if (b != 255)
+                               printf(",%s", (b+1) % 4 == 0 ? "" : " ");
+               }
+
+               if (s == 7)
+                       printf("\n\t}\n};\n");
+               else
+                       printf("\n\t}, {");
+       }
+
+       return;
+}
+
+
+static void
+print_lz_table(void)
+{
+       printf("/* This file has been automatically generated by "
+                       "crc32_tablegen.c. */\n\n"
+                       "const uint32_t lzma_lz_hash_table[256] = {");
+
+       for (size_t b = 0; b < 256; ++b) {
+               if ((b % 4) == 0)
+                       printf("\n\t");
+
+               printf("0x%08" PRIX32, crc32_table[0][b]);
+
+               if (b != 255)
+                       printf(",%s", (b+1) % 4 == 0 ? "" : " ");
+       }
+
+       printf("\n};\n");
+
+       return;
+}
+
+
+int
+main(void)
+{
+       init_crc32_table();
+
+#ifdef LZ_HASH_TABLE
+       print_lz_table();
+#else
+       print_crc32_table();
+#endif
+
+       return 0;
+}
diff --git a/lzma/check/crc64_fast.c b/lzma/check/crc64_fast.c
new file mode 100644 (file)
index 0000000..52af29e
--- /dev/null
@@ -0,0 +1,72 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       crc64.c
+/// \brief      CRC64 calculation
+///
+/// Calculate the CRC64 using the slice-by-four algorithm. This is the same
+/// idea that is used in crc32_fast.c, but for CRC64 we use only four tables
+/// instead of eight to avoid increasing CPU cache usage.
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "check.h"
+#include "crc_macros.h"
+
+
+#ifdef WORDS_BIGENDIAN
+#      define A1(x) ((x) >> 56)
+#else
+#      define A1 A
+#endif
+
+
+// See the comments in crc32_fast.c. They aren't duplicated here.
+extern LZMA_API(uint64_t)
+lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc)
+{
+       crc = ~crc;
+
+#ifdef WORDS_BIGENDIAN
+       crc = bswap64(crc);
+#endif
+
+       if (size > 4) {
+               while ((uintptr_t)(buf) & 3) {
+                       crc = lzma_crc64_table[0][*buf++ ^ A1(crc)] ^ S8(crc);
+                       --size;
+               }
+
+               const uint8_t *const limit = buf + (size & ~(size_t)(3));
+               size &= (size_t)(3);
+
+               while (buf < limit) {
+#ifdef WORDS_BIGENDIAN
+                       const uint32_t tmp = (crc >> 32)
+                                       ^ *(const uint32_t *)(buf);
+#else
+                       const uint32_t tmp = crc ^ *(const uint32_t *)(buf);
+#endif
+                       buf += 4;
+
+                       crc = lzma_crc64_table[3][A(tmp)]
+                           ^ lzma_crc64_table[2][B(tmp)]
+                           ^ S32(crc)
+                           ^ lzma_crc64_table[1][C(tmp)]
+                           ^ lzma_crc64_table[0][D(tmp)];
+               }
+       }
+
+       while (size-- != 0)
+               crc = lzma_crc64_table[0][*buf++ ^ A1(crc)] ^ S8(crc);
+
+#ifdef WORDS_BIGENDIAN
+       crc = bswap64(crc);
+#endif
+
+       return ~crc;
+}
diff --git a/lzma/check/crc64_small.c b/lzma/check/crc64_small.c
new file mode 100644 (file)
index 0000000..55d7231
--- /dev/null
@@ -0,0 +1,53 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       crc64_small.c
+/// \brief      CRC64 calculation (size-optimized)
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "check.h"
+
+
+static uint64_t crc64_table[256];
+
+
+static void
+crc64_init(void)
+{
+       static const uint64_t poly64 = UINT64_C(0xC96C5795D7870F42);
+
+       for (size_t b = 0; b < 256; ++b) {
+               uint64_t r = b;
+               for (size_t i = 0; i < 8; ++i) {
+                       if (r & 1)
+                               r = (r >> 1) ^ poly64;
+                       else
+                               r >>= 1;
+               }
+
+               crc64_table[b] = r;
+       }
+
+       return;
+}
+
+
+extern LZMA_API(uint64_t)
+lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc)
+{
+       mythread_once(crc64_init);
+
+       crc = ~crc;
+
+       while (size != 0) {
+               crc = crc64_table[*buf++ ^ (crc & 0xFF)] ^ (crc >> 8);
+               --size;
+       }
+
+       return ~crc;
+}
diff --git a/lzma/check/crc64_table.c b/lzma/check/crc64_table.c
new file mode 100644 (file)
index 0000000..1fbcd94
--- /dev/null
@@ -0,0 +1,19 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       crc64_table.c
+/// \brief      Precalculated CRC64 table with correct endianness
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+#ifdef WORDS_BIGENDIAN
+#      include "crc64_table_be.h"
+#else
+#      include "crc64_table_le.h"
+#endif
diff --git a/lzma/check/crc64_table_be.h b/lzma/check/crc64_table_be.h
new file mode 100644 (file)
index 0000000..ea074f3
--- /dev/null
@@ -0,0 +1,521 @@
+/* This file has been automatically generated by crc64_tablegen.c. */
+
+const uint64_t lzma_crc64_table[4][256] = {
+       {
+               UINT64_C(0x0000000000000000), UINT64_C(0x6F5FA703BE4C2EB3),
+               UINT64_C(0x5BA040A8573684F4), UINT64_C(0x34FFE7ABE97AAA47),
+               UINT64_C(0x335E8FFF84C3D07B), UINT64_C(0x5C0128FC3A8FFEC8),
+               UINT64_C(0x68FECF57D3F5548F), UINT64_C(0x07A168546DB97A3C),
+               UINT64_C(0x66BC1EFF0987A1F7), UINT64_C(0x09E3B9FCB7CB8F44),
+               UINT64_C(0x3D1C5E575EB12503), UINT64_C(0x5243F954E0FD0BB0),
+               UINT64_C(0x55E291008D44718C), UINT64_C(0x3ABD360333085F3F),
+               UINT64_C(0x0E42D1A8DA72F578), UINT64_C(0x611D76AB643EDBCB),
+               UINT64_C(0x4966335138A19B7D), UINT64_C(0x2639945286EDB5CE),
+               UINT64_C(0x12C673F96F971F89), UINT64_C(0x7D99D4FAD1DB313A),
+               UINT64_C(0x7A38BCAEBC624B06), UINT64_C(0x15671BAD022E65B5),
+               UINT64_C(0x2198FC06EB54CFF2), UINT64_C(0x4EC75B055518E141),
+               UINT64_C(0x2FDA2DAE31263A8A), UINT64_C(0x40858AAD8F6A1439),
+               UINT64_C(0x747A6D066610BE7E), UINT64_C(0x1B25CA05D85C90CD),
+               UINT64_C(0x1C84A251B5E5EAF1), UINT64_C(0x73DB05520BA9C442),
+               UINT64_C(0x4724E2F9E2D36E05), UINT64_C(0x287B45FA5C9F40B6),
+               UINT64_C(0x92CC66A2704237FB), UINT64_C(0xFD93C1A1CE0E1948),
+               UINT64_C(0xC96C260A2774B30F), UINT64_C(0xA633810999389DBC),
+               UINT64_C(0xA192E95DF481E780), UINT64_C(0xCECD4E5E4ACDC933),
+               UINT64_C(0xFA32A9F5A3B76374), UINT64_C(0x956D0EF61DFB4DC7),
+               UINT64_C(0xF470785D79C5960C), UINT64_C(0x9B2FDF5EC789B8BF),
+               UINT64_C(0xAFD038F52EF312F8), UINT64_C(0xC08F9FF690BF3C4B),
+               UINT64_C(0xC72EF7A2FD064677), UINT64_C(0xA87150A1434A68C4),
+               UINT64_C(0x9C8EB70AAA30C283), UINT64_C(0xF3D11009147CEC30),
+               UINT64_C(0xDBAA55F348E3AC86), UINT64_C(0xB4F5F2F0F6AF8235),
+               UINT64_C(0x800A155B1FD52872), UINT64_C(0xEF55B258A19906C1),
+               UINT64_C(0xE8F4DA0CCC207CFD), UINT64_C(0x87AB7D0F726C524E),
+               UINT64_C(0xB3549AA49B16F809), UINT64_C(0xDC0B3DA7255AD6BA),
+               UINT64_C(0xBD164B0C41640D71), UINT64_C(0xD249EC0FFF2823C2),
+               UINT64_C(0xE6B60BA416528985), UINT64_C(0x89E9ACA7A81EA736),
+               UINT64_C(0x8E48C4F3C5A7DD0A), UINT64_C(0xE11763F07BEBF3B9),
+               UINT64_C(0xD5E8845B929159FE), UINT64_C(0xBAB723582CDD774D),
+               UINT64_C(0xA187C3EBCA2BB664), UINT64_C(0xCED864E8746798D7),
+               UINT64_C(0xFA2783439D1D3290), UINT64_C(0x9578244023511C23),
+               UINT64_C(0x92D94C144EE8661F), UINT64_C(0xFD86EB17F0A448AC),
+               UINT64_C(0xC9790CBC19DEE2EB), UINT64_C(0xA626ABBFA792CC58),
+               UINT64_C(0xC73BDD14C3AC1793), UINT64_C(0xA8647A177DE03920),
+               UINT64_C(0x9C9B9DBC949A9367), UINT64_C(0xF3C43ABF2AD6BDD4),
+               UINT64_C(0xF46552EB476FC7E8), UINT64_C(0x9B3AF5E8F923E95B),
+               UINT64_C(0xAFC512431059431C), UINT64_C(0xC09AB540AE156DAF),
+               UINT64_C(0xE8E1F0BAF28A2D19), UINT64_C(0x87BE57B94CC603AA),
+               UINT64_C(0xB341B012A5BCA9ED), UINT64_C(0xDC1E17111BF0875E),
+               UINT64_C(0xDBBF7F457649FD62), UINT64_C(0xB4E0D846C805D3D1),
+               UINT64_C(0x801F3FED217F7996), UINT64_C(0xEF4098EE9F335725),
+               UINT64_C(0x8E5DEE45FB0D8CEE), UINT64_C(0xE10249464541A25D),
+               UINT64_C(0xD5FDAEEDAC3B081A), UINT64_C(0xBAA209EE127726A9),
+               UINT64_C(0xBD0361BA7FCE5C95), UINT64_C(0xD25CC6B9C1827226),
+               UINT64_C(0xE6A3211228F8D861), UINT64_C(0x89FC861196B4F6D2),
+               UINT64_C(0x334BA549BA69819F), UINT64_C(0x5C14024A0425AF2C),
+               UINT64_C(0x68EBE5E1ED5F056B), UINT64_C(0x07B442E253132BD8),
+               UINT64_C(0x00152AB63EAA51E4), UINT64_C(0x6F4A8DB580E67F57),
+               UINT64_C(0x5BB56A1E699CD510), UINT64_C(0x34EACD1DD7D0FBA3),
+               UINT64_C(0x55F7BBB6B3EE2068), UINT64_C(0x3AA81CB50DA20EDB),
+               UINT64_C(0x0E57FB1EE4D8A49C), UINT64_C(0x61085C1D5A948A2F),
+               UINT64_C(0x66A93449372DF013), UINT64_C(0x09F6934A8961DEA0),
+               UINT64_C(0x3D0974E1601B74E7), UINT64_C(0x5256D3E2DE575A54),
+               UINT64_C(0x7A2D961882C81AE2), UINT64_C(0x1572311B3C843451),
+               UINT64_C(0x218DD6B0D5FE9E16), UINT64_C(0x4ED271B36BB2B0A5),
+               UINT64_C(0x497319E7060BCA99), UINT64_C(0x262CBEE4B847E42A),
+               UINT64_C(0x12D3594F513D4E6D), UINT64_C(0x7D8CFE4CEF7160DE),
+               UINT64_C(0x1C9188E78B4FBB15), UINT64_C(0x73CE2FE4350395A6),
+               UINT64_C(0x4731C84FDC793FE1), UINT64_C(0x286E6F4C62351152),
+               UINT64_C(0x2FCF07180F8C6B6E), UINT64_C(0x4090A01BB1C045DD),
+               UINT64_C(0x746F47B058BAEF9A), UINT64_C(0x1B30E0B3E6F6C129),
+               UINT64_C(0x420F87D795576CC9), UINT64_C(0x2D5020D42B1B427A),
+               UINT64_C(0x19AFC77FC261E83D), UINT64_C(0x76F0607C7C2DC68E),
+               UINT64_C(0x715108281194BCB2), UINT64_C(0x1E0EAF2BAFD89201),
+               UINT64_C(0x2AF1488046A23846), UINT64_C(0x45AEEF83F8EE16F5),
+               UINT64_C(0x24B399289CD0CD3E), UINT64_C(0x4BEC3E2B229CE38D),
+               UINT64_C(0x7F13D980CBE649CA), UINT64_C(0x104C7E8375AA6779),
+               UINT64_C(0x17ED16D718131D45), UINT64_C(0x78B2B1D4A65F33F6),
+               UINT64_C(0x4C4D567F4F2599B1), UINT64_C(0x2312F17CF169B702),
+               UINT64_C(0x0B69B486ADF6F7B4), UINT64_C(0x6436138513BAD907),
+               UINT64_C(0x50C9F42EFAC07340), UINT64_C(0x3F96532D448C5DF3),
+               UINT64_C(0x38373B79293527CF), UINT64_C(0x57689C7A9779097C),
+               UINT64_C(0x63977BD17E03A33B), UINT64_C(0x0CC8DCD2C04F8D88),
+               UINT64_C(0x6DD5AA79A4715643), UINT64_C(0x028A0D7A1A3D78F0),
+               UINT64_C(0x3675EAD1F347D2B7), UINT64_C(0x592A4DD24D0BFC04),
+               UINT64_C(0x5E8B258620B28638), UINT64_C(0x31D482859EFEA88B),
+               UINT64_C(0x052B652E778402CC), UINT64_C(0x6A74C22DC9C82C7F),
+               UINT64_C(0xD0C3E175E5155B32), UINT64_C(0xBF9C46765B597581),
+               UINT64_C(0x8B63A1DDB223DFC6), UINT64_C(0xE43C06DE0C6FF175),
+               UINT64_C(0xE39D6E8A61D68B49), UINT64_C(0x8CC2C989DF9AA5FA),
+               UINT64_C(0xB83D2E2236E00FBD), UINT64_C(0xD762892188AC210E),
+               UINT64_C(0xB67FFF8AEC92FAC5), UINT64_C(0xD920588952DED476),
+               UINT64_C(0xEDDFBF22BBA47E31), UINT64_C(0x8280182105E85082),
+               UINT64_C(0x8521707568512ABE), UINT64_C(0xEA7ED776D61D040D),
+               UINT64_C(0xDE8130DD3F67AE4A), UINT64_C(0xB1DE97DE812B80F9),
+               UINT64_C(0x99A5D224DDB4C04F), UINT64_C(0xF6FA752763F8EEFC),
+               UINT64_C(0xC205928C8A8244BB), UINT64_C(0xAD5A358F34CE6A08),
+               UINT64_C(0xAAFB5DDB59771034), UINT64_C(0xC5A4FAD8E73B3E87),
+               UINT64_C(0xF15B1D730E4194C0), UINT64_C(0x9E04BA70B00DBA73),
+               UINT64_C(0xFF19CCDBD43361B8), UINT64_C(0x90466BD86A7F4F0B),
+               UINT64_C(0xA4B98C738305E54C), UINT64_C(0xCBE62B703D49CBFF),
+               UINT64_C(0xCC47432450F0B1C3), UINT64_C(0xA318E427EEBC9F70),
+               UINT64_C(0x97E7038C07C63537), UINT64_C(0xF8B8A48FB98A1B84),
+               UINT64_C(0xE388443C5F7CDAAD), UINT64_C(0x8CD7E33FE130F41E),
+               UINT64_C(0xB8280494084A5E59), UINT64_C(0xD777A397B60670EA),
+               UINT64_C(0xD0D6CBC3DBBF0AD6), UINT64_C(0xBF896CC065F32465),
+               UINT64_C(0x8B768B6B8C898E22), UINT64_C(0xE4292C6832C5A091),
+               UINT64_C(0x85345AC356FB7B5A), UINT64_C(0xEA6BFDC0E8B755E9),
+               UINT64_C(0xDE941A6B01CDFFAE), UINT64_C(0xB1CBBD68BF81D11D),
+               UINT64_C(0xB66AD53CD238AB21), UINT64_C(0xD935723F6C748592),
+               UINT64_C(0xEDCA9594850E2FD5), UINT64_C(0x829532973B420166),
+               UINT64_C(0xAAEE776D67DD41D0), UINT64_C(0xC5B1D06ED9916F63),
+               UINT64_C(0xF14E37C530EBC524), UINT64_C(0x9E1190C68EA7EB97),
+               UINT64_C(0x99B0F892E31E91AB), UINT64_C(0xF6EF5F915D52BF18),
+               UINT64_C(0xC210B83AB428155F), UINT64_C(0xAD4F1F390A643BEC),
+               UINT64_C(0xCC5269926E5AE027), UINT64_C(0xA30DCE91D016CE94),
+               UINT64_C(0x97F2293A396C64D3), UINT64_C(0xF8AD8E3987204A60),
+               UINT64_C(0xFF0CE66DEA99305C), UINT64_C(0x9053416E54D51EEF),
+               UINT64_C(0xA4ACA6C5BDAFB4A8), UINT64_C(0xCBF301C603E39A1B),
+               UINT64_C(0x7144229E2F3EED56), UINT64_C(0x1E1B859D9172C3E5),
+               UINT64_C(0x2AE46236780869A2), UINT64_C(0x45BBC535C6444711),
+               UINT64_C(0x421AAD61ABFD3D2D), UINT64_C(0x2D450A6215B1139E),
+               UINT64_C(0x19BAEDC9FCCBB9D9), UINT64_C(0x76E54ACA4287976A),
+               UINT64_C(0x17F83C6126B94CA1), UINT64_C(0x78A79B6298F56212),
+               UINT64_C(0x4C587CC9718FC855), UINT64_C(0x2307DBCACFC3E6E6),
+               UINT64_C(0x24A6B39EA27A9CDA), UINT64_C(0x4BF9149D1C36B269),
+               UINT64_C(0x7F06F336F54C182E), UINT64_C(0x105954354B00369D),
+               UINT64_C(0x382211CF179F762B), UINT64_C(0x577DB6CCA9D35898),
+               UINT64_C(0x6382516740A9F2DF), UINT64_C(0x0CDDF664FEE5DC6C),
+               UINT64_C(0x0B7C9E30935CA650), UINT64_C(0x642339332D1088E3),
+               UINT64_C(0x50DCDE98C46A22A4), UINT64_C(0x3F83799B7A260C17),
+               UINT64_C(0x5E9E0F301E18D7DC), UINT64_C(0x31C1A833A054F96F),
+               UINT64_C(0x053E4F98492E5328), UINT64_C(0x6A61E89BF7627D9B),
+               UINT64_C(0x6DC080CF9ADB07A7), UINT64_C(0x029F27CC24972914),
+               UINT64_C(0x3660C067CDED8353), UINT64_C(0x593F676473A1ADE0)
+       }, {
+               UINT64_C(0x0000000000000000), UINT64_C(0x0DF1D05C9279E954),
+               UINT64_C(0x1AE2A1B924F3D2A9), UINT64_C(0x171371E5B68A3BFD),
+               UINT64_C(0xB1DA4DDC62497DC1), UINT64_C(0xBC2B9D80F0309495),
+               UINT64_C(0xAB38EC6546BAAF68), UINT64_C(0xA6C93C39D4C3463C),
+               UINT64_C(0xE7AB9517EE3D2210), UINT64_C(0xEA5A454B7C44CB44),
+               UINT64_C(0xFD4934AECACEF0B9), UINT64_C(0xF0B8E4F258B719ED),
+               UINT64_C(0x5671D8CB8C745FD1), UINT64_C(0x5B8008971E0DB685),
+               UINT64_C(0x4C937972A8878D78), UINT64_C(0x4162A92E3AFE642C),
+               UINT64_C(0xCE572B2FDC7B4420), UINT64_C(0xC3A6FB734E02AD74),
+               UINT64_C(0xD4B58A96F8889689), UINT64_C(0xD9445ACA6AF17FDD),
+               UINT64_C(0x7F8D66F3BE3239E1), UINT64_C(0x727CB6AF2C4BD0B5),
+               UINT64_C(0x656FC74A9AC1EB48), UINT64_C(0x689E171608B8021C),
+               UINT64_C(0x29FCBE3832466630), UINT64_C(0x240D6E64A03F8F64),
+               UINT64_C(0x331E1F8116B5B499), UINT64_C(0x3EEFCFDD84CC5DCD),
+               UINT64_C(0x9826F3E4500F1BF1), UINT64_C(0x95D723B8C276F2A5),
+               UINT64_C(0x82C4525D74FCC958), UINT64_C(0x8F358201E685200C),
+               UINT64_C(0x9CAF565EB8F78840), UINT64_C(0x915E86022A8E6114),
+               UINT64_C(0x864DF7E79C045AE9), UINT64_C(0x8BBC27BB0E7DB3BD),
+               UINT64_C(0x2D751B82DABEF581), UINT64_C(0x2084CBDE48C71CD5),
+               UINT64_C(0x3797BA3BFE4D2728), UINT64_C(0x3A666A676C34CE7C),
+               UINT64_C(0x7B04C34956CAAA50), UINT64_C(0x76F51315C4B34304),
+               UINT64_C(0x61E662F0723978F9), UINT64_C(0x6C17B2ACE04091AD),
+               UINT64_C(0xCADE8E953483D791), UINT64_C(0xC72F5EC9A6FA3EC5),
+               UINT64_C(0xD03C2F2C10700538), UINT64_C(0xDDCDFF708209EC6C),
+               UINT64_C(0x52F87D71648CCC60), UINT64_C(0x5F09AD2DF6F52534),
+               UINT64_C(0x481ADCC8407F1EC9), UINT64_C(0x45EB0C94D206F79D),
+               UINT64_C(0xE32230AD06C5B1A1), UINT64_C(0xEED3E0F194BC58F5),
+               UINT64_C(0xF9C0911422366308), UINT64_C(0xF4314148B04F8A5C),
+               UINT64_C(0xB553E8668AB1EE70), UINT64_C(0xB8A2383A18C80724),
+               UINT64_C(0xAFB149DFAE423CD9), UINT64_C(0xA24099833C3BD58D),
+               UINT64_C(0x0489A5BAE8F893B1), UINT64_C(0x097875E67A817AE5),
+               UINT64_C(0x1E6B0403CC0B4118), UINT64_C(0x139AD45F5E72A84C),
+               UINT64_C(0x385FADBC70EF1181), UINT64_C(0x35AE7DE0E296F8D5),
+               UINT64_C(0x22BD0C05541CC328), UINT64_C(0x2F4CDC59C6652A7C),
+               UINT64_C(0x8985E06012A66C40), UINT64_C(0x8474303C80DF8514),
+               UINT64_C(0x936741D93655BEE9), UINT64_C(0x9E969185A42C57BD),
+               UINT64_C(0xDFF438AB9ED23391), UINT64_C(0xD205E8F70CABDAC5),
+               UINT64_C(0xC5169912BA21E138), UINT64_C(0xC8E7494E2858086C),
+               UINT64_C(0x6E2E7577FC9B4E50), UINT64_C(0x63DFA52B6EE2A704),
+               UINT64_C(0x74CCD4CED8689CF9), UINT64_C(0x793D04924A1175AD),
+               UINT64_C(0xF6088693AC9455A1), UINT64_C(0xFBF956CF3EEDBCF5),
+               UINT64_C(0xECEA272A88678708), UINT64_C(0xE11BF7761A1E6E5C),
+               UINT64_C(0x47D2CB4FCEDD2860), UINT64_C(0x4A231B135CA4C134),
+               UINT64_C(0x5D306AF6EA2EFAC9), UINT64_C(0x50C1BAAA7857139D),
+               UINT64_C(0x11A3138442A977B1), UINT64_C(0x1C52C3D8D0D09EE5),
+               UINT64_C(0x0B41B23D665AA518), UINT64_C(0x06B06261F4234C4C),
+               UINT64_C(0xA0795E5820E00A70), UINT64_C(0xAD888E04B299E324),
+               UINT64_C(0xBA9BFFE10413D8D9), UINT64_C(0xB76A2FBD966A318D),
+               UINT64_C(0xA4F0FBE2C81899C1), UINT64_C(0xA9012BBE5A617095),
+               UINT64_C(0xBE125A5BECEB4B68), UINT64_C(0xB3E38A077E92A23C),
+               UINT64_C(0x152AB63EAA51E400), UINT64_C(0x18DB666238280D54),
+               UINT64_C(0x0FC817878EA236A9), UINT64_C(0x0239C7DB1CDBDFFD),
+               UINT64_C(0x435B6EF52625BBD1), UINT64_C(0x4EAABEA9B45C5285),
+               UINT64_C(0x59B9CF4C02D66978), UINT64_C(0x54481F1090AF802C),
+               UINT64_C(0xF2812329446CC610), UINT64_C(0xFF70F375D6152F44),
+               UINT64_C(0xE8638290609F14B9), UINT64_C(0xE59252CCF2E6FDED),
+               UINT64_C(0x6AA7D0CD1463DDE1), UINT64_C(0x67560091861A34B5),
+               UINT64_C(0x7045717430900F48), UINT64_C(0x7DB4A128A2E9E61C),
+               UINT64_C(0xDB7D9D11762AA020), UINT64_C(0xD68C4D4DE4534974),
+               UINT64_C(0xC19F3CA852D97289), UINT64_C(0xCC6EECF4C0A09BDD),
+               UINT64_C(0x8D0C45DAFA5EFFF1), UINT64_C(0x80FD9586682716A5),
+               UINT64_C(0x97EEE463DEAD2D58), UINT64_C(0x9A1F343F4CD4C40C),
+               UINT64_C(0x3CD6080698178230), UINT64_C(0x3127D85A0A6E6B64),
+               UINT64_C(0x2634A9BFBCE45099), UINT64_C(0x2BC579E32E9DB9CD),
+               UINT64_C(0xF5A054D6CA71FB90), UINT64_C(0xF851848A580812C4),
+               UINT64_C(0xEF42F56FEE822939), UINT64_C(0xE2B325337CFBC06D),
+               UINT64_C(0x447A190AA8388651), UINT64_C(0x498BC9563A416F05),
+               UINT64_C(0x5E98B8B38CCB54F8), UINT64_C(0x536968EF1EB2BDAC),
+               UINT64_C(0x120BC1C1244CD980), UINT64_C(0x1FFA119DB63530D4),
+               UINT64_C(0x08E9607800BF0B29), UINT64_C(0x0518B02492C6E27D),
+               UINT64_C(0xA3D18C1D4605A441), UINT64_C(0xAE205C41D47C4D15),
+               UINT64_C(0xB9332DA462F676E8), UINT64_C(0xB4C2FDF8F08F9FBC),
+               UINT64_C(0x3BF77FF9160ABFB0), UINT64_C(0x3606AFA5847356E4),
+               UINT64_C(0x2115DE4032F96D19), UINT64_C(0x2CE40E1CA080844D),
+               UINT64_C(0x8A2D32257443C271), UINT64_C(0x87DCE279E63A2B25),
+               UINT64_C(0x90CF939C50B010D8), UINT64_C(0x9D3E43C0C2C9F98C),
+               UINT64_C(0xDC5CEAEEF8379DA0), UINT64_C(0xD1AD3AB26A4E74F4),
+               UINT64_C(0xC6BE4B57DCC44F09), UINT64_C(0xCB4F9B0B4EBDA65D),
+               UINT64_C(0x6D86A7329A7EE061), UINT64_C(0x6077776E08070935),
+               UINT64_C(0x7764068BBE8D32C8), UINT64_C(0x7A95D6D72CF4DB9C),
+               UINT64_C(0x690F0288728673D0), UINT64_C(0x64FED2D4E0FF9A84),
+               UINT64_C(0x73EDA3315675A179), UINT64_C(0x7E1C736DC40C482D),
+               UINT64_C(0xD8D54F5410CF0E11), UINT64_C(0xD5249F0882B6E745),
+               UINT64_C(0xC237EEED343CDCB8), UINT64_C(0xCFC63EB1A64535EC),
+               UINT64_C(0x8EA4979F9CBB51C0), UINT64_C(0x835547C30EC2B894),
+               UINT64_C(0x94463626B8488369), UINT64_C(0x99B7E67A2A316A3D),
+               UINT64_C(0x3F7EDA43FEF22C01), UINT64_C(0x328F0A1F6C8BC555),
+               UINT64_C(0x259C7BFADA01FEA8), UINT64_C(0x286DABA6487817FC),
+               UINT64_C(0xA75829A7AEFD37F0), UINT64_C(0xAAA9F9FB3C84DEA4),
+               UINT64_C(0xBDBA881E8A0EE559), UINT64_C(0xB04B584218770C0D),
+               UINT64_C(0x1682647BCCB44A31), UINT64_C(0x1B73B4275ECDA365),
+               UINT64_C(0x0C60C5C2E8479898), UINT64_C(0x0191159E7A3E71CC),
+               UINT64_C(0x40F3BCB040C015E0), UINT64_C(0x4D026CECD2B9FCB4),
+               UINT64_C(0x5A111D096433C749), UINT64_C(0x57E0CD55F64A2E1D),
+               UINT64_C(0xF129F16C22896821), UINT64_C(0xFCD82130B0F08175),
+               UINT64_C(0xEBCB50D5067ABA88), UINT64_C(0xE63A8089940353DC),
+               UINT64_C(0xCDFFF96ABA9EEA11), UINT64_C(0xC00E293628E70345),
+               UINT64_C(0xD71D58D39E6D38B8), UINT64_C(0xDAEC888F0C14D1EC),
+               UINT64_C(0x7C25B4B6D8D797D0), UINT64_C(0x71D464EA4AAE7E84),
+               UINT64_C(0x66C7150FFC244579), UINT64_C(0x6B36C5536E5DAC2D),
+               UINT64_C(0x2A546C7D54A3C801), UINT64_C(0x27A5BC21C6DA2155),
+               UINT64_C(0x30B6CDC470501AA8), UINT64_C(0x3D471D98E229F3FC),
+               UINT64_C(0x9B8E21A136EAB5C0), UINT64_C(0x967FF1FDA4935C94),
+               UINT64_C(0x816C801812196769), UINT64_C(0x8C9D504480608E3D),
+               UINT64_C(0x03A8D24566E5AE31), UINT64_C(0x0E590219F49C4765),
+               UINT64_C(0x194A73FC42167C98), UINT64_C(0x14BBA3A0D06F95CC),
+               UINT64_C(0xB2729F9904ACD3F0), UINT64_C(0xBF834FC596D53AA4),
+               UINT64_C(0xA8903E20205F0159), UINT64_C(0xA561EE7CB226E80D),
+               UINT64_C(0xE403475288D88C21), UINT64_C(0xE9F2970E1AA16575),
+               UINT64_C(0xFEE1E6EBAC2B5E88), UINT64_C(0xF31036B73E52B7DC),
+               UINT64_C(0x55D90A8EEA91F1E0), UINT64_C(0x5828DAD278E818B4),
+               UINT64_C(0x4F3BAB37CE622349), UINT64_C(0x42CA7B6B5C1BCA1D),
+               UINT64_C(0x5150AF3402696251), UINT64_C(0x5CA17F6890108B05),
+               UINT64_C(0x4BB20E8D269AB0F8), UINT64_C(0x4643DED1B4E359AC),
+               UINT64_C(0xE08AE2E860201F90), UINT64_C(0xED7B32B4F259F6C4),
+               UINT64_C(0xFA68435144D3CD39), UINT64_C(0xF799930DD6AA246D),
+               UINT64_C(0xB6FB3A23EC544041), UINT64_C(0xBB0AEA7F7E2DA915),
+               UINT64_C(0xAC199B9AC8A792E8), UINT64_C(0xA1E84BC65ADE7BBC),
+               UINT64_C(0x072177FF8E1D3D80), UINT64_C(0x0AD0A7A31C64D4D4),
+               UINT64_C(0x1DC3D646AAEEEF29), UINT64_C(0x1032061A3897067D),
+               UINT64_C(0x9F07841BDE122671), UINT64_C(0x92F654474C6BCF25),
+               UINT64_C(0x85E525A2FAE1F4D8), UINT64_C(0x8814F5FE68981D8C),
+               UINT64_C(0x2EDDC9C7BC5B5BB0), UINT64_C(0x232C199B2E22B2E4),
+               UINT64_C(0x343F687E98A88919), UINT64_C(0x39CEB8220AD1604D),
+               UINT64_C(0x78AC110C302F0461), UINT64_C(0x755DC150A256ED35),
+               UINT64_C(0x624EB0B514DCD6C8), UINT64_C(0x6FBF60E986A53F9C),
+               UINT64_C(0xC9765CD0526679A0), UINT64_C(0xC4878C8CC01F90F4),
+               UINT64_C(0xD394FD697695AB09), UINT64_C(0xDE652D35E4EC425D)
+       }, {
+               UINT64_C(0x0000000000000000), UINT64_C(0xCB6D6A914AE10B3F),
+               UINT64_C(0x96DBD42295C2177E), UINT64_C(0x5DB6BEB3DF231C41),
+               UINT64_C(0x2CB7A9452A852FFC), UINT64_C(0xE7DAC3D4606424C3),
+               UINT64_C(0xBA6C7D67BF473882), UINT64_C(0x710117F6F5A633BD),
+               UINT64_C(0xDD705D247FA5876A), UINT64_C(0x161D37B535448C55),
+               UINT64_C(0x4BAB8906EA679014), UINT64_C(0x80C6E397A0869B2B),
+               UINT64_C(0xF1C7F4615520A896), UINT64_C(0x3AAA9EF01FC1A3A9),
+               UINT64_C(0x671C2043C0E2BFE8), UINT64_C(0xAC714AD28A03B4D7),
+               UINT64_C(0xBAE1BA48FE4A0FD5), UINT64_C(0x718CD0D9B4AB04EA),
+               UINT64_C(0x2C3A6E6A6B8818AB), UINT64_C(0xE75704FB21691394),
+               UINT64_C(0x9656130DD4CF2029), UINT64_C(0x5D3B799C9E2E2B16),
+               UINT64_C(0x008DC72F410D3757), UINT64_C(0xCBE0ADBE0BEC3C68),
+               UINT64_C(0x6791E76C81EF88BF), UINT64_C(0xACFC8DFDCB0E8380),
+               UINT64_C(0xF14A334E142D9FC1), UINT64_C(0x3A2759DF5ECC94FE),
+               UINT64_C(0x4B264E29AB6AA743), UINT64_C(0x804B24B8E18BAC7C),
+               UINT64_C(0xDDFD9A0B3EA8B03D), UINT64_C(0x1690F09A7449BB02),
+               UINT64_C(0xF1DD7B3ED73AC638), UINT64_C(0x3AB011AF9DDBCD07),
+               UINT64_C(0x6706AF1C42F8D146), UINT64_C(0xAC6BC58D0819DA79),
+               UINT64_C(0xDD6AD27BFDBFE9C4), UINT64_C(0x1607B8EAB75EE2FB),
+               UINT64_C(0x4BB10659687DFEBA), UINT64_C(0x80DC6CC8229CF585),
+               UINT64_C(0x2CAD261AA89F4152), UINT64_C(0xE7C04C8BE27E4A6D),
+               UINT64_C(0xBA76F2383D5D562C), UINT64_C(0x711B98A977BC5D13),
+               UINT64_C(0x001A8F5F821A6EAE), UINT64_C(0xCB77E5CEC8FB6591),
+               UINT64_C(0x96C15B7D17D879D0), UINT64_C(0x5DAC31EC5D3972EF),
+               UINT64_C(0x4B3CC1762970C9ED), UINT64_C(0x8051ABE76391C2D2),
+               UINT64_C(0xDDE71554BCB2DE93), UINT64_C(0x168A7FC5F653D5AC),
+               UINT64_C(0x678B683303F5E611), UINT64_C(0xACE602A24914ED2E),
+               UINT64_C(0xF150BC119637F16F), UINT64_C(0x3A3DD680DCD6FA50),
+               UINT64_C(0x964C9C5256D54E87), UINT64_C(0x5D21F6C31C3445B8),
+               UINT64_C(0x00974870C31759F9), UINT64_C(0xCBFA22E189F652C6),
+               UINT64_C(0xBAFB35177C50617B), UINT64_C(0x71965F8636B16A44),
+               UINT64_C(0x2C20E135E9927605), UINT64_C(0xE74D8BA4A3737D3A),
+               UINT64_C(0xE2BBF77CAE758C71), UINT64_C(0x29D69DEDE494874E),
+               UINT64_C(0x7460235E3BB79B0F), UINT64_C(0xBF0D49CF71569030),
+               UINT64_C(0xCE0C5E3984F0A38D), UINT64_C(0x056134A8CE11A8B2),
+               UINT64_C(0x58D78A1B1132B4F3), UINT64_C(0x93BAE08A5BD3BFCC),
+               UINT64_C(0x3FCBAA58D1D00B1B), UINT64_C(0xF4A6C0C99B310024),
+               UINT64_C(0xA9107E7A44121C65), UINT64_C(0x627D14EB0EF3175A),
+               UINT64_C(0x137C031DFB5524E7), UINT64_C(0xD811698CB1B42FD8),
+               UINT64_C(0x85A7D73F6E973399), UINT64_C(0x4ECABDAE247638A6),
+               UINT64_C(0x585A4D34503F83A4), UINT64_C(0x933727A51ADE889B),
+               UINT64_C(0xCE819916C5FD94DA), UINT64_C(0x05ECF3878F1C9FE5),
+               UINT64_C(0x74EDE4717ABAAC58), UINT64_C(0xBF808EE0305BA767),
+               UINT64_C(0xE2363053EF78BB26), UINT64_C(0x295B5AC2A599B019),
+               UINT64_C(0x852A10102F9A04CE), UINT64_C(0x4E477A81657B0FF1),
+               UINT64_C(0x13F1C432BA5813B0), UINT64_C(0xD89CAEA3F0B9188F),
+               UINT64_C(0xA99DB955051F2B32), UINT64_C(0x62F0D3C44FFE200D),
+               UINT64_C(0x3F466D7790DD3C4C), UINT64_C(0xF42B07E6DA3C3773),
+               UINT64_C(0x13668C42794F4A49), UINT64_C(0xD80BE6D333AE4176),
+               UINT64_C(0x85BD5860EC8D5D37), UINT64_C(0x4ED032F1A66C5608),
+               UINT64_C(0x3FD1250753CA65B5), UINT64_C(0xF4BC4F96192B6E8A),
+               UINT64_C(0xA90AF125C60872CB), UINT64_C(0x62679BB48CE979F4),
+               UINT64_C(0xCE16D16606EACD23), UINT64_C(0x057BBBF74C0BC61C),
+               UINT64_C(0x58CD05449328DA5D), UINT64_C(0x93A06FD5D9C9D162),
+               UINT64_C(0xE2A178232C6FE2DF), UINT64_C(0x29CC12B2668EE9E0),
+               UINT64_C(0x747AAC01B9ADF5A1), UINT64_C(0xBF17C690F34CFE9E),
+               UINT64_C(0xA987360A8705459C), UINT64_C(0x62EA5C9BCDE44EA3),
+               UINT64_C(0x3F5CE22812C752E2), UINT64_C(0xF43188B9582659DD),
+               UINT64_C(0x85309F4FAD806A60), UINT64_C(0x4E5DF5DEE761615F),
+               UINT64_C(0x13EB4B6D38427D1E), UINT64_C(0xD88621FC72A37621),
+               UINT64_C(0x74F76B2EF8A0C2F6), UINT64_C(0xBF9A01BFB241C9C9),
+               UINT64_C(0xE22CBF0C6D62D588), UINT64_C(0x2941D59D2783DEB7),
+               UINT64_C(0x5840C26BD225ED0A), UINT64_C(0x932DA8FA98C4E635),
+               UINT64_C(0xCE9B164947E7FA74), UINT64_C(0x05F67CD80D06F14B),
+               UINT64_C(0xC477EFF95CEB18E3), UINT64_C(0x0F1A8568160A13DC),
+               UINT64_C(0x52AC3BDBC9290F9D), UINT64_C(0x99C1514A83C804A2),
+               UINT64_C(0xE8C046BC766E371F), UINT64_C(0x23AD2C2D3C8F3C20),
+               UINT64_C(0x7E1B929EE3AC2061), UINT64_C(0xB576F80FA94D2B5E),
+               UINT64_C(0x1907B2DD234E9F89), UINT64_C(0xD26AD84C69AF94B6),
+               UINT64_C(0x8FDC66FFB68C88F7), UINT64_C(0x44B10C6EFC6D83C8),
+               UINT64_C(0x35B01B9809CBB075), UINT64_C(0xFEDD7109432ABB4A),
+               UINT64_C(0xA36BCFBA9C09A70B), UINT64_C(0x6806A52BD6E8AC34),
+               UINT64_C(0x7E9655B1A2A11736), UINT64_C(0xB5FB3F20E8401C09),
+               UINT64_C(0xE84D819337630048), UINT64_C(0x2320EB027D820B77),
+               UINT64_C(0x5221FCF4882438CA), UINT64_C(0x994C9665C2C533F5),
+               UINT64_C(0xC4FA28D61DE62FB4), UINT64_C(0x0F9742475707248B),
+               UINT64_C(0xA3E60895DD04905C), UINT64_C(0x688B620497E59B63),
+               UINT64_C(0x353DDCB748C68722), UINT64_C(0xFE50B62602278C1D),
+               UINT64_C(0x8F51A1D0F781BFA0), UINT64_C(0x443CCB41BD60B49F),
+               UINT64_C(0x198A75F26243A8DE), UINT64_C(0xD2E71F6328A2A3E1),
+               UINT64_C(0x35AA94C78BD1DEDB), UINT64_C(0xFEC7FE56C130D5E4),
+               UINT64_C(0xA37140E51E13C9A5), UINT64_C(0x681C2A7454F2C29A),
+               UINT64_C(0x191D3D82A154F127), UINT64_C(0xD2705713EBB5FA18),
+               UINT64_C(0x8FC6E9A03496E659), UINT64_C(0x44AB83317E77ED66),
+               UINT64_C(0xE8DAC9E3F47459B1), UINT64_C(0x23B7A372BE95528E),
+               UINT64_C(0x7E011DC161B64ECF), UINT64_C(0xB56C77502B5745F0),
+               UINT64_C(0xC46D60A6DEF1764D), UINT64_C(0x0F000A3794107D72),
+               UINT64_C(0x52B6B4844B336133), UINT64_C(0x99DBDE1501D26A0C),
+               UINT64_C(0x8F4B2E8F759BD10E), UINT64_C(0x4426441E3F7ADA31),
+               UINT64_C(0x1990FAADE059C670), UINT64_C(0xD2FD903CAAB8CD4F),
+               UINT64_C(0xA3FC87CA5F1EFEF2), UINT64_C(0x6891ED5B15FFF5CD),
+               UINT64_C(0x352753E8CADCE98C), UINT64_C(0xFE4A3979803DE2B3),
+               UINT64_C(0x523B73AB0A3E5664), UINT64_C(0x9956193A40DF5D5B),
+               UINT64_C(0xC4E0A7899FFC411A), UINT64_C(0x0F8DCD18D51D4A25),
+               UINT64_C(0x7E8CDAEE20BB7998), UINT64_C(0xB5E1B07F6A5A72A7),
+               UINT64_C(0xE8570ECCB5796EE6), UINT64_C(0x233A645DFF9865D9),
+               UINT64_C(0x26CC1885F29E9492), UINT64_C(0xEDA17214B87F9FAD),
+               UINT64_C(0xB017CCA7675C83EC), UINT64_C(0x7B7AA6362DBD88D3),
+               UINT64_C(0x0A7BB1C0D81BBB6E), UINT64_C(0xC116DB5192FAB051),
+               UINT64_C(0x9CA065E24DD9AC10), UINT64_C(0x57CD0F730738A72F),
+               UINT64_C(0xFBBC45A18D3B13F8), UINT64_C(0x30D12F30C7DA18C7),
+               UINT64_C(0x6D67918318F90486), UINT64_C(0xA60AFB1252180FB9),
+               UINT64_C(0xD70BECE4A7BE3C04), UINT64_C(0x1C668675ED5F373B),
+               UINT64_C(0x41D038C6327C2B7A), UINT64_C(0x8ABD5257789D2045),
+               UINT64_C(0x9C2DA2CD0CD49B47), UINT64_C(0x5740C85C46359078),
+               UINT64_C(0x0AF676EF99168C39), UINT64_C(0xC19B1C7ED3F78706),
+               UINT64_C(0xB09A0B882651B4BB), UINT64_C(0x7BF761196CB0BF84),
+               UINT64_C(0x2641DFAAB393A3C5), UINT64_C(0xED2CB53BF972A8FA),
+               UINT64_C(0x415DFFE973711C2D), UINT64_C(0x8A30957839901712),
+               UINT64_C(0xD7862BCBE6B30B53), UINT64_C(0x1CEB415AAC52006C),
+               UINT64_C(0x6DEA56AC59F433D1), UINT64_C(0xA6873C3D131538EE),
+               UINT64_C(0xFB31828ECC3624AF), UINT64_C(0x305CE81F86D72F90),
+               UINT64_C(0xD71163BB25A452AA), UINT64_C(0x1C7C092A6F455995),
+               UINT64_C(0x41CAB799B06645D4), UINT64_C(0x8AA7DD08FA874EEB),
+               UINT64_C(0xFBA6CAFE0F217D56), UINT64_C(0x30CBA06F45C07669),
+               UINT64_C(0x6D7D1EDC9AE36A28), UINT64_C(0xA610744DD0026117),
+               UINT64_C(0x0A613E9F5A01D5C0), UINT64_C(0xC10C540E10E0DEFF),
+               UINT64_C(0x9CBAEABDCFC3C2BE), UINT64_C(0x57D7802C8522C981),
+               UINT64_C(0x26D697DA7084FA3C), UINT64_C(0xEDBBFD4B3A65F103),
+               UINT64_C(0xB00D43F8E546ED42), UINT64_C(0x7B602969AFA7E67D),
+               UINT64_C(0x6DF0D9F3DBEE5D7F), UINT64_C(0xA69DB362910F5640),
+               UINT64_C(0xFB2B0DD14E2C4A01), UINT64_C(0x3046674004CD413E),
+               UINT64_C(0x414770B6F16B7283), UINT64_C(0x8A2A1A27BB8A79BC),
+               UINT64_C(0xD79CA49464A965FD), UINT64_C(0x1CF1CE052E486EC2),
+               UINT64_C(0xB08084D7A44BDA15), UINT64_C(0x7BEDEE46EEAAD12A),
+               UINT64_C(0x265B50F53189CD6B), UINT64_C(0xED363A647B68C654),
+               UINT64_C(0x9C372D928ECEF5E9), UINT64_C(0x575A4703C42FFED6),
+               UINT64_C(0x0AECF9B01B0CE297), UINT64_C(0xC181932151EDE9A8)
+       }, {
+               UINT64_C(0x0000000000000000), UINT64_C(0xDCA12C225E8AEE1D),
+               UINT64_C(0xB8435944BC14DD3B), UINT64_C(0x64E27566E29E3326),
+               UINT64_C(0x7087B2887829BA77), UINT64_C(0xAC269EAA26A3546A),
+               UINT64_C(0xC8C4EBCCC43D674C), UINT64_C(0x1465C7EE9AB78951),
+               UINT64_C(0xE00E6511F15274EF), UINT64_C(0x3CAF4933AFD89AF2),
+               UINT64_C(0x584D3C554D46A9D4), UINT64_C(0x84EC107713CC47C9),
+               UINT64_C(0x9089D799897BCE98), UINT64_C(0x4C28FBBBD7F12085),
+               UINT64_C(0x28CA8EDD356F13A3), UINT64_C(0xF46BA2FF6BE5FDBE),
+               UINT64_C(0x4503C48DC90A304C), UINT64_C(0x99A2E8AF9780DE51),
+               UINT64_C(0xFD409DC9751EED77), UINT64_C(0x21E1B1EB2B94036A),
+               UINT64_C(0x35847605B1238A3B), UINT64_C(0xE9255A27EFA96426),
+               UINT64_C(0x8DC72F410D375700), UINT64_C(0x5166036353BDB91D),
+               UINT64_C(0xA50DA19C385844A3), UINT64_C(0x79AC8DBE66D2AABE),
+               UINT64_C(0x1D4EF8D8844C9998), UINT64_C(0xC1EFD4FADAC67785),
+               UINT64_C(0xD58A13144071FED4), UINT64_C(0x092B3F361EFB10C9),
+               UINT64_C(0x6DC94A50FC6523EF), UINT64_C(0xB1686672A2EFCDF2),
+               UINT64_C(0x8A06881B93156098), UINT64_C(0x56A7A439CD9F8E85),
+               UINT64_C(0x3245D15F2F01BDA3), UINT64_C(0xEEE4FD7D718B53BE),
+               UINT64_C(0xFA813A93EB3CDAEF), UINT64_C(0x262016B1B5B634F2),
+               UINT64_C(0x42C263D7572807D4), UINT64_C(0x9E634FF509A2E9C9),
+               UINT64_C(0x6A08ED0A62471477), UINT64_C(0xB6A9C1283CCDFA6A),
+               UINT64_C(0xD24BB44EDE53C94C), UINT64_C(0x0EEA986C80D92751),
+               UINT64_C(0x1A8F5F821A6EAE00), UINT64_C(0xC62E73A044E4401D),
+               UINT64_C(0xA2CC06C6A67A733B), UINT64_C(0x7E6D2AE4F8F09D26),
+               UINT64_C(0xCF054C965A1F50D4), UINT64_C(0x13A460B40495BEC9),
+               UINT64_C(0x774615D2E60B8DEF), UINT64_C(0xABE739F0B88163F2),
+               UINT64_C(0xBF82FE1E2236EAA3), UINT64_C(0x6323D23C7CBC04BE),
+               UINT64_C(0x07C1A75A9E223798), UINT64_C(0xDB608B78C0A8D985),
+               UINT64_C(0x2F0B2987AB4D243B), UINT64_C(0xF3AA05A5F5C7CA26),
+               UINT64_C(0x974870C31759F900), UINT64_C(0x4BE95CE149D3171D),
+               UINT64_C(0x5F8C9B0FD3649E4C), UINT64_C(0x832DB72D8DEE7051),
+               UINT64_C(0xE7CFC24B6F704377), UINT64_C(0x3B6EEE6931FAAD6A),
+               UINT64_C(0x91131E980D8418A2), UINT64_C(0x4DB232BA530EF6BF),
+               UINT64_C(0x295047DCB190C599), UINT64_C(0xF5F16BFEEF1A2B84),
+               UINT64_C(0xE194AC1075ADA2D5), UINT64_C(0x3D3580322B274CC8),
+               UINT64_C(0x59D7F554C9B97FEE), UINT64_C(0x8576D976973391F3),
+               UINT64_C(0x711D7B89FCD66C4D), UINT64_C(0xADBC57ABA25C8250),
+               UINT64_C(0xC95E22CD40C2B176), UINT64_C(0x15FF0EEF1E485F6B),
+               UINT64_C(0x019AC90184FFD63A), UINT64_C(0xDD3BE523DA753827),
+               UINT64_C(0xB9D9904538EB0B01), UINT64_C(0x6578BC676661E51C),
+               UINT64_C(0xD410DA15C48E28EE), UINT64_C(0x08B1F6379A04C6F3),
+               UINT64_C(0x6C538351789AF5D5), UINT64_C(0xB0F2AF7326101BC8),
+               UINT64_C(0xA497689DBCA79299), UINT64_C(0x783644BFE22D7C84),
+               UINT64_C(0x1CD431D900B34FA2), UINT64_C(0xC0751DFB5E39A1BF),
+               UINT64_C(0x341EBF0435DC5C01), UINT64_C(0xE8BF93266B56B21C),
+               UINT64_C(0x8C5DE64089C8813A), UINT64_C(0x50FCCA62D7426F27),
+               UINT64_C(0x44990D8C4DF5E676), UINT64_C(0x983821AE137F086B),
+               UINT64_C(0xFCDA54C8F1E13B4D), UINT64_C(0x207B78EAAF6BD550),
+               UINT64_C(0x1B1596839E91783A), UINT64_C(0xC7B4BAA1C01B9627),
+               UINT64_C(0xA356CFC72285A501), UINT64_C(0x7FF7E3E57C0F4B1C),
+               UINT64_C(0x6B92240BE6B8C24D), UINT64_C(0xB7330829B8322C50),
+               UINT64_C(0xD3D17D4F5AAC1F76), UINT64_C(0x0F70516D0426F16B),
+               UINT64_C(0xFB1BF3926FC30CD5), UINT64_C(0x27BADFB03149E2C8),
+               UINT64_C(0x4358AAD6D3D7D1EE), UINT64_C(0x9FF986F48D5D3FF3),
+               UINT64_C(0x8B9C411A17EAB6A2), UINT64_C(0x573D6D38496058BF),
+               UINT64_C(0x33DF185EABFE6B99), UINT64_C(0xEF7E347CF5748584),
+               UINT64_C(0x5E16520E579B4876), UINT64_C(0x82B77E2C0911A66B),
+               UINT64_C(0xE6550B4AEB8F954D), UINT64_C(0x3AF42768B5057B50),
+               UINT64_C(0x2E91E0862FB2F201), UINT64_C(0xF230CCA471381C1C),
+               UINT64_C(0x96D2B9C293A62F3A), UINT64_C(0x4A7395E0CD2CC127),
+               UINT64_C(0xBE18371FA6C93C99), UINT64_C(0x62B91B3DF843D284),
+               UINT64_C(0x065B6E5B1ADDE1A2), UINT64_C(0xDAFA427944570FBF),
+               UINT64_C(0xCE9F8597DEE086EE), UINT64_C(0x123EA9B5806A68F3),
+               UINT64_C(0x76DCDCD362F45BD5), UINT64_C(0xAA7DF0F13C7EB5C8),
+               UINT64_C(0xA739329F30A7E9D6), UINT64_C(0x7B981EBD6E2D07CB),
+               UINT64_C(0x1F7A6BDB8CB334ED), UINT64_C(0xC3DB47F9D239DAF0),
+               UINT64_C(0xD7BE8017488E53A1), UINT64_C(0x0B1FAC351604BDBC),
+               UINT64_C(0x6FFDD953F49A8E9A), UINT64_C(0xB35CF571AA106087),
+               UINT64_C(0x4737578EC1F59D39), UINT64_C(0x9B967BAC9F7F7324),
+               UINT64_C(0xFF740ECA7DE14002), UINT64_C(0x23D522E8236BAE1F),
+               UINT64_C(0x37B0E506B9DC274E), UINT64_C(0xEB11C924E756C953),
+               UINT64_C(0x8FF3BC4205C8FA75), UINT64_C(0x535290605B421468),
+               UINT64_C(0xE23AF612F9ADD99A), UINT64_C(0x3E9BDA30A7273787),
+               UINT64_C(0x5A79AF5645B904A1), UINT64_C(0x86D883741B33EABC),
+               UINT64_C(0x92BD449A818463ED), UINT64_C(0x4E1C68B8DF0E8DF0),
+               UINT64_C(0x2AFE1DDE3D90BED6), UINT64_C(0xF65F31FC631A50CB),
+               UINT64_C(0x0234930308FFAD75), UINT64_C(0xDE95BF2156754368),
+               UINT64_C(0xBA77CA47B4EB704E), UINT64_C(0x66D6E665EA619E53),
+               UINT64_C(0x72B3218B70D61702), UINT64_C(0xAE120DA92E5CF91F),
+               UINT64_C(0xCAF078CFCCC2CA39), UINT64_C(0x165154ED92482424),
+               UINT64_C(0x2D3FBA84A3B2894E), UINT64_C(0xF19E96A6FD386753),
+               UINT64_C(0x957CE3C01FA65475), UINT64_C(0x49DDCFE2412CBA68),
+               UINT64_C(0x5DB8080CDB9B3339), UINT64_C(0x8119242E8511DD24),
+               UINT64_C(0xE5FB5148678FEE02), UINT64_C(0x395A7D6A3905001F),
+               UINT64_C(0xCD31DF9552E0FDA1), UINT64_C(0x1190F3B70C6A13BC),
+               UINT64_C(0x757286D1EEF4209A), UINT64_C(0xA9D3AAF3B07ECE87),
+               UINT64_C(0xBDB66D1D2AC947D6), UINT64_C(0x6117413F7443A9CB),
+               UINT64_C(0x05F5345996DD9AED), UINT64_C(0xD954187BC85774F0),
+               UINT64_C(0x683C7E096AB8B902), UINT64_C(0xB49D522B3432571F),
+               UINT64_C(0xD07F274DD6AC6439), UINT64_C(0x0CDE0B6F88268A24),
+               UINT64_C(0x18BBCC8112910375), UINT64_C(0xC41AE0A34C1BED68),
+               UINT64_C(0xA0F895C5AE85DE4E), UINT64_C(0x7C59B9E7F00F3053),
+               UINT64_C(0x88321B189BEACDED), UINT64_C(0x5493373AC56023F0),
+               UINT64_C(0x3071425C27FE10D6), UINT64_C(0xECD06E7E7974FECB),
+               UINT64_C(0xF8B5A990E3C3779A), UINT64_C(0x241485B2BD499987),
+               UINT64_C(0x40F6F0D45FD7AAA1), UINT64_C(0x9C57DCF6015D44BC),
+               UINT64_C(0x362A2C073D23F174), UINT64_C(0xEA8B002563A91F69),
+               UINT64_C(0x8E69754381372C4F), UINT64_C(0x52C85961DFBDC252),
+               UINT64_C(0x46AD9E8F450A4B03), UINT64_C(0x9A0CB2AD1B80A51E),
+               UINT64_C(0xFEEEC7CBF91E9638), UINT64_C(0x224FEBE9A7947825),
+               UINT64_C(0xD6244916CC71859B), UINT64_C(0x0A85653492FB6B86),
+               UINT64_C(0x6E671052706558A0), UINT64_C(0xB2C63C702EEFB6BD),
+               UINT64_C(0xA6A3FB9EB4583FEC), UINT64_C(0x7A02D7BCEAD2D1F1),
+               UINT64_C(0x1EE0A2DA084CE2D7), UINT64_C(0xC2418EF856C60CCA),
+               UINT64_C(0x7329E88AF429C138), UINT64_C(0xAF88C4A8AAA32F25),
+               UINT64_C(0xCB6AB1CE483D1C03), UINT64_C(0x17CB9DEC16B7F21E),
+               UINT64_C(0x03AE5A028C007B4F), UINT64_C(0xDF0F7620D28A9552),
+               UINT64_C(0xBBED03463014A674), UINT64_C(0x674C2F646E9E4869),
+               UINT64_C(0x93278D9B057BB5D7), UINT64_C(0x4F86A1B95BF15BCA),
+               UINT64_C(0x2B64D4DFB96F68EC), UINT64_C(0xF7C5F8FDE7E586F1),
+               UINT64_C(0xE3A03F137D520FA0), UINT64_C(0x3F01133123D8E1BD),
+               UINT64_C(0x5BE36657C146D29B), UINT64_C(0x87424A759FCC3C86),
+               UINT64_C(0xBC2CA41CAE3691EC), UINT64_C(0x608D883EF0BC7FF1),
+               UINT64_C(0x046FFD5812224CD7), UINT64_C(0xD8CED17A4CA8A2CA),
+               UINT64_C(0xCCAB1694D61F2B9B), UINT64_C(0x100A3AB68895C586),
+               UINT64_C(0x74E84FD06A0BF6A0), UINT64_C(0xA84963F2348118BD),
+               UINT64_C(0x5C22C10D5F64E503), UINT64_C(0x8083ED2F01EE0B1E),
+               UINT64_C(0xE4619849E3703838), UINT64_C(0x38C0B46BBDFAD625),
+               UINT64_C(0x2CA57385274D5F74), UINT64_C(0xF0045FA779C7B169),
+               UINT64_C(0x94E62AC19B59824F), UINT64_C(0x484706E3C5D36C52),
+               UINT64_C(0xF92F6091673CA1A0), UINT64_C(0x258E4CB339B64FBD),
+               UINT64_C(0x416C39D5DB287C9B), UINT64_C(0x9DCD15F785A29286),
+               UINT64_C(0x89A8D2191F151BD7), UINT64_C(0x5509FE3B419FF5CA),
+               UINT64_C(0x31EB8B5DA301C6EC), UINT64_C(0xED4AA77FFD8B28F1),
+               UINT64_C(0x19210580966ED54F), UINT64_C(0xC58029A2C8E43B52),
+               UINT64_C(0xA1625CC42A7A0874), UINT64_C(0x7DC370E674F0E669),
+               UINT64_C(0x69A6B708EE476F38), UINT64_C(0xB5079B2AB0CD8125),
+               UINT64_C(0xD1E5EE4C5253B203), UINT64_C(0x0D44C26E0CD95C1E)
+       }
+};
diff --git a/lzma/check/crc64_table_le.h b/lzma/check/crc64_table_le.h
new file mode 100644 (file)
index 0000000..1196b31
--- /dev/null
@@ -0,0 +1,521 @@
+/* This file has been automatically generated by crc64_tablegen.c. */
+
+const uint64_t lzma_crc64_table[4][256] = {
+       {
+               UINT64_C(0x0000000000000000), UINT64_C(0xB32E4CBE03A75F6F),
+               UINT64_C(0xF4843657A840A05B), UINT64_C(0x47AA7AE9ABE7FF34),
+               UINT64_C(0x7BD0C384FF8F5E33), UINT64_C(0xC8FE8F3AFC28015C),
+               UINT64_C(0x8F54F5D357CFFE68), UINT64_C(0x3C7AB96D5468A107),
+               UINT64_C(0xF7A18709FF1EBC66), UINT64_C(0x448FCBB7FCB9E309),
+               UINT64_C(0x0325B15E575E1C3D), UINT64_C(0xB00BFDE054F94352),
+               UINT64_C(0x8C71448D0091E255), UINT64_C(0x3F5F08330336BD3A),
+               UINT64_C(0x78F572DAA8D1420E), UINT64_C(0xCBDB3E64AB761D61),
+               UINT64_C(0x7D9BA13851336649), UINT64_C(0xCEB5ED8652943926),
+               UINT64_C(0x891F976FF973C612), UINT64_C(0x3A31DBD1FAD4997D),
+               UINT64_C(0x064B62BCAEBC387A), UINT64_C(0xB5652E02AD1B6715),
+               UINT64_C(0xF2CF54EB06FC9821), UINT64_C(0x41E11855055BC74E),
+               UINT64_C(0x8A3A2631AE2DDA2F), UINT64_C(0x39146A8FAD8A8540),
+               UINT64_C(0x7EBE1066066D7A74), UINT64_C(0xCD905CD805CA251B),
+               UINT64_C(0xF1EAE5B551A2841C), UINT64_C(0x42C4A90B5205DB73),
+               UINT64_C(0x056ED3E2F9E22447), UINT64_C(0xB6409F5CFA457B28),
+               UINT64_C(0xFB374270A266CC92), UINT64_C(0x48190ECEA1C193FD),
+               UINT64_C(0x0FB374270A266CC9), UINT64_C(0xBC9D3899098133A6),
+               UINT64_C(0x80E781F45DE992A1), UINT64_C(0x33C9CD4A5E4ECDCE),
+               UINT64_C(0x7463B7A3F5A932FA), UINT64_C(0xC74DFB1DF60E6D95),
+               UINT64_C(0x0C96C5795D7870F4), UINT64_C(0xBFB889C75EDF2F9B),
+               UINT64_C(0xF812F32EF538D0AF), UINT64_C(0x4B3CBF90F69F8FC0),
+               UINT64_C(0x774606FDA2F72EC7), UINT64_C(0xC4684A43A15071A8),
+               UINT64_C(0x83C230AA0AB78E9C), UINT64_C(0x30EC7C140910D1F3),
+               UINT64_C(0x86ACE348F355AADB), UINT64_C(0x3582AFF6F0F2F5B4),
+               UINT64_C(0x7228D51F5B150A80), UINT64_C(0xC10699A158B255EF),
+               UINT64_C(0xFD7C20CC0CDAF4E8), UINT64_C(0x4E526C720F7DAB87),
+               UINT64_C(0x09F8169BA49A54B3), UINT64_C(0xBAD65A25A73D0BDC),
+               UINT64_C(0x710D64410C4B16BD), UINT64_C(0xC22328FF0FEC49D2),
+               UINT64_C(0x85895216A40BB6E6), UINT64_C(0x36A71EA8A7ACE989),
+               UINT64_C(0x0ADDA7C5F3C4488E), UINT64_C(0xB9F3EB7BF06317E1),
+               UINT64_C(0xFE5991925B84E8D5), UINT64_C(0x4D77DD2C5823B7BA),
+               UINT64_C(0x64B62BCAEBC387A1), UINT64_C(0xD7986774E864D8CE),
+               UINT64_C(0x90321D9D438327FA), UINT64_C(0x231C512340247895),
+               UINT64_C(0x1F66E84E144CD992), UINT64_C(0xAC48A4F017EB86FD),
+               UINT64_C(0xEBE2DE19BC0C79C9), UINT64_C(0x58CC92A7BFAB26A6),
+               UINT64_C(0x9317ACC314DD3BC7), UINT64_C(0x2039E07D177A64A8),
+               UINT64_C(0x67939A94BC9D9B9C), UINT64_C(0xD4BDD62ABF3AC4F3),
+               UINT64_C(0xE8C76F47EB5265F4), UINT64_C(0x5BE923F9E8F53A9B),
+               UINT64_C(0x1C4359104312C5AF), UINT64_C(0xAF6D15AE40B59AC0),
+               UINT64_C(0x192D8AF2BAF0E1E8), UINT64_C(0xAA03C64CB957BE87),
+               UINT64_C(0xEDA9BCA512B041B3), UINT64_C(0x5E87F01B11171EDC),
+               UINT64_C(0x62FD4976457FBFDB), UINT64_C(0xD1D305C846D8E0B4),
+               UINT64_C(0x96797F21ED3F1F80), UINT64_C(0x2557339FEE9840EF),
+               UINT64_C(0xEE8C0DFB45EE5D8E), UINT64_C(0x5DA24145464902E1),
+               UINT64_C(0x1A083BACEDAEFDD5), UINT64_C(0xA9267712EE09A2BA),
+               UINT64_C(0x955CCE7FBA6103BD), UINT64_C(0x267282C1B9C65CD2),
+               UINT64_C(0x61D8F8281221A3E6), UINT64_C(0xD2F6B4961186FC89),
+               UINT64_C(0x9F8169BA49A54B33), UINT64_C(0x2CAF25044A02145C),
+               UINT64_C(0x6B055FEDE1E5EB68), UINT64_C(0xD82B1353E242B407),
+               UINT64_C(0xE451AA3EB62A1500), UINT64_C(0x577FE680B58D4A6F),
+               UINT64_C(0x10D59C691E6AB55B), UINT64_C(0xA3FBD0D71DCDEA34),
+               UINT64_C(0x6820EEB3B6BBF755), UINT64_C(0xDB0EA20DB51CA83A),
+               UINT64_C(0x9CA4D8E41EFB570E), UINT64_C(0x2F8A945A1D5C0861),
+               UINT64_C(0x13F02D374934A966), UINT64_C(0xA0DE61894A93F609),
+               UINT64_C(0xE7741B60E174093D), UINT64_C(0x545A57DEE2D35652),
+               UINT64_C(0xE21AC88218962D7A), UINT64_C(0x5134843C1B317215),
+               UINT64_C(0x169EFED5B0D68D21), UINT64_C(0xA5B0B26BB371D24E),
+               UINT64_C(0x99CA0B06E7197349), UINT64_C(0x2AE447B8E4BE2C26),
+               UINT64_C(0x6D4E3D514F59D312), UINT64_C(0xDE6071EF4CFE8C7D),
+               UINT64_C(0x15BB4F8BE788911C), UINT64_C(0xA6950335E42FCE73),
+               UINT64_C(0xE13F79DC4FC83147), UINT64_C(0x521135624C6F6E28),
+               UINT64_C(0x6E6B8C0F1807CF2F), UINT64_C(0xDD45C0B11BA09040),
+               UINT64_C(0x9AEFBA58B0476F74), UINT64_C(0x29C1F6E6B3E0301B),
+               UINT64_C(0xC96C5795D7870F42), UINT64_C(0x7A421B2BD420502D),
+               UINT64_C(0x3DE861C27FC7AF19), UINT64_C(0x8EC62D7C7C60F076),
+               UINT64_C(0xB2BC941128085171), UINT64_C(0x0192D8AF2BAF0E1E),
+               UINT64_C(0x4638A2468048F12A), UINT64_C(0xF516EEF883EFAE45),
+               UINT64_C(0x3ECDD09C2899B324), UINT64_C(0x8DE39C222B3EEC4B),
+               UINT64_C(0xCA49E6CB80D9137F), UINT64_C(0x7967AA75837E4C10),
+               UINT64_C(0x451D1318D716ED17), UINT64_C(0xF6335FA6D4B1B278),
+               UINT64_C(0xB199254F7F564D4C), UINT64_C(0x02B769F17CF11223),
+               UINT64_C(0xB4F7F6AD86B4690B), UINT64_C(0x07D9BA1385133664),
+               UINT64_C(0x4073C0FA2EF4C950), UINT64_C(0xF35D8C442D53963F),
+               UINT64_C(0xCF273529793B3738), UINT64_C(0x7C0979977A9C6857),
+               UINT64_C(0x3BA3037ED17B9763), UINT64_C(0x888D4FC0D2DCC80C),
+               UINT64_C(0x435671A479AAD56D), UINT64_C(0xF0783D1A7A0D8A02),
+               UINT64_C(0xB7D247F3D1EA7536), UINT64_C(0x04FC0B4DD24D2A59),
+               UINT64_C(0x3886B22086258B5E), UINT64_C(0x8BA8FE9E8582D431),
+               UINT64_C(0xCC0284772E652B05), UINT64_C(0x7F2CC8C92DC2746A),
+               UINT64_C(0x325B15E575E1C3D0), UINT64_C(0x8175595B76469CBF),
+               UINT64_C(0xC6DF23B2DDA1638B), UINT64_C(0x75F16F0CDE063CE4),
+               UINT64_C(0x498BD6618A6E9DE3), UINT64_C(0xFAA59ADF89C9C28C),
+               UINT64_C(0xBD0FE036222E3DB8), UINT64_C(0x0E21AC88218962D7),
+               UINT64_C(0xC5FA92EC8AFF7FB6), UINT64_C(0x76D4DE52895820D9),
+               UINT64_C(0x317EA4BB22BFDFED), UINT64_C(0x8250E80521188082),
+               UINT64_C(0xBE2A516875702185), UINT64_C(0x0D041DD676D77EEA),
+               UINT64_C(0x4AAE673FDD3081DE), UINT64_C(0xF9802B81DE97DEB1),
+               UINT64_C(0x4FC0B4DD24D2A599), UINT64_C(0xFCEEF8632775FAF6),
+               UINT64_C(0xBB44828A8C9205C2), UINT64_C(0x086ACE348F355AAD),
+               UINT64_C(0x34107759DB5DFBAA), UINT64_C(0x873E3BE7D8FAA4C5),
+               UINT64_C(0xC094410E731D5BF1), UINT64_C(0x73BA0DB070BA049E),
+               UINT64_C(0xB86133D4DBCC19FF), UINT64_C(0x0B4F7F6AD86B4690),
+               UINT64_C(0x4CE50583738CB9A4), UINT64_C(0xFFCB493D702BE6CB),
+               UINT64_C(0xC3B1F050244347CC), UINT64_C(0x709FBCEE27E418A3),
+               UINT64_C(0x3735C6078C03E797), UINT64_C(0x841B8AB98FA4B8F8),
+               UINT64_C(0xADDA7C5F3C4488E3), UINT64_C(0x1EF430E13FE3D78C),
+               UINT64_C(0x595E4A08940428B8), UINT64_C(0xEA7006B697A377D7),
+               UINT64_C(0xD60ABFDBC3CBD6D0), UINT64_C(0x6524F365C06C89BF),
+               UINT64_C(0x228E898C6B8B768B), UINT64_C(0x91A0C532682C29E4),
+               UINT64_C(0x5A7BFB56C35A3485), UINT64_C(0xE955B7E8C0FD6BEA),
+               UINT64_C(0xAEFFCD016B1A94DE), UINT64_C(0x1DD181BF68BDCBB1),
+               UINT64_C(0x21AB38D23CD56AB6), UINT64_C(0x9285746C3F7235D9),
+               UINT64_C(0xD52F0E859495CAED), UINT64_C(0x6601423B97329582),
+               UINT64_C(0xD041DD676D77EEAA), UINT64_C(0x636F91D96ED0B1C5),
+               UINT64_C(0x24C5EB30C5374EF1), UINT64_C(0x97EBA78EC690119E),
+               UINT64_C(0xAB911EE392F8B099), UINT64_C(0x18BF525D915FEFF6),
+               UINT64_C(0x5F1528B43AB810C2), UINT64_C(0xEC3B640A391F4FAD),
+               UINT64_C(0x27E05A6E926952CC), UINT64_C(0x94CE16D091CE0DA3),
+               UINT64_C(0xD3646C393A29F297), UINT64_C(0x604A2087398EADF8),
+               UINT64_C(0x5C3099EA6DE60CFF), UINT64_C(0xEF1ED5546E415390),
+               UINT64_C(0xA8B4AFBDC5A6ACA4), UINT64_C(0x1B9AE303C601F3CB),
+               UINT64_C(0x56ED3E2F9E224471), UINT64_C(0xE5C372919D851B1E),
+               UINT64_C(0xA26908783662E42A), UINT64_C(0x114744C635C5BB45),
+               UINT64_C(0x2D3DFDAB61AD1A42), UINT64_C(0x9E13B115620A452D),
+               UINT64_C(0xD9B9CBFCC9EDBA19), UINT64_C(0x6A978742CA4AE576),
+               UINT64_C(0xA14CB926613CF817), UINT64_C(0x1262F598629BA778),
+               UINT64_C(0x55C88F71C97C584C), UINT64_C(0xE6E6C3CFCADB0723),
+               UINT64_C(0xDA9C7AA29EB3A624), UINT64_C(0x69B2361C9D14F94B),
+               UINT64_C(0x2E184CF536F3067F), UINT64_C(0x9D36004B35545910),
+               UINT64_C(0x2B769F17CF112238), UINT64_C(0x9858D3A9CCB67D57),
+               UINT64_C(0xDFF2A94067518263), UINT64_C(0x6CDCE5FE64F6DD0C),
+               UINT64_C(0x50A65C93309E7C0B), UINT64_C(0xE388102D33392364),
+               UINT64_C(0xA4226AC498DEDC50), UINT64_C(0x170C267A9B79833F),
+               UINT64_C(0xDCD7181E300F9E5E), UINT64_C(0x6FF954A033A8C131),
+               UINT64_C(0x28532E49984F3E05), UINT64_C(0x9B7D62F79BE8616A),
+               UINT64_C(0xA707DB9ACF80C06D), UINT64_C(0x14299724CC279F02),
+               UINT64_C(0x5383EDCD67C06036), UINT64_C(0xE0ADA17364673F59)
+       }, {
+               UINT64_C(0x0000000000000000), UINT64_C(0x54E979925CD0F10D),
+               UINT64_C(0xA9D2F324B9A1E21A), UINT64_C(0xFD3B8AB6E5711317),
+               UINT64_C(0xC17D4962DC4DDAB1), UINT64_C(0x959430F0809D2BBC),
+               UINT64_C(0x68AFBA4665EC38AB), UINT64_C(0x3C46C3D4393CC9A6),
+               UINT64_C(0x10223DEE1795ABE7), UINT64_C(0x44CB447C4B455AEA),
+               UINT64_C(0xB9F0CECAAE3449FD), UINT64_C(0xED19B758F2E4B8F0),
+               UINT64_C(0xD15F748CCBD87156), UINT64_C(0x85B60D1E9708805B),
+               UINT64_C(0x788D87A87279934C), UINT64_C(0x2C64FE3A2EA96241),
+               UINT64_C(0x20447BDC2F2B57CE), UINT64_C(0x74AD024E73FBA6C3),
+               UINT64_C(0x899688F8968AB5D4), UINT64_C(0xDD7FF16ACA5A44D9),
+               UINT64_C(0xE13932BEF3668D7F), UINT64_C(0xB5D04B2CAFB67C72),
+               UINT64_C(0x48EBC19A4AC76F65), UINT64_C(0x1C02B80816179E68),
+               UINT64_C(0x3066463238BEFC29), UINT64_C(0x648F3FA0646E0D24),
+               UINT64_C(0x99B4B516811F1E33), UINT64_C(0xCD5DCC84DDCFEF3E),
+               UINT64_C(0xF11B0F50E4F32698), UINT64_C(0xA5F276C2B823D795),
+               UINT64_C(0x58C9FC745D52C482), UINT64_C(0x0C2085E60182358F),
+               UINT64_C(0x4088F7B85E56AF9C), UINT64_C(0x14618E2A02865E91),
+               UINT64_C(0xE95A049CE7F74D86), UINT64_C(0xBDB37D0EBB27BC8B),
+               UINT64_C(0x81F5BEDA821B752D), UINT64_C(0xD51CC748DECB8420),
+               UINT64_C(0x28274DFE3BBA9737), UINT64_C(0x7CCE346C676A663A),
+               UINT64_C(0x50AACA5649C3047B), UINT64_C(0x0443B3C41513F576),
+               UINT64_C(0xF9783972F062E661), UINT64_C(0xAD9140E0ACB2176C),
+               UINT64_C(0x91D78334958EDECA), UINT64_C(0xC53EFAA6C95E2FC7),
+               UINT64_C(0x380570102C2F3CD0), UINT64_C(0x6CEC098270FFCDDD),
+               UINT64_C(0x60CC8C64717DF852), UINT64_C(0x3425F5F62DAD095F),
+               UINT64_C(0xC91E7F40C8DC1A48), UINT64_C(0x9DF706D2940CEB45),
+               UINT64_C(0xA1B1C506AD3022E3), UINT64_C(0xF558BC94F1E0D3EE),
+               UINT64_C(0x086336221491C0F9), UINT64_C(0x5C8A4FB0484131F4),
+               UINT64_C(0x70EEB18A66E853B5), UINT64_C(0x2407C8183A38A2B8),
+               UINT64_C(0xD93C42AEDF49B1AF), UINT64_C(0x8DD53B3C839940A2),
+               UINT64_C(0xB193F8E8BAA58904), UINT64_C(0xE57A817AE6757809),
+               UINT64_C(0x18410BCC03046B1E), UINT64_C(0x4CA8725E5FD49A13),
+               UINT64_C(0x8111EF70BCAD5F38), UINT64_C(0xD5F896E2E07DAE35),
+               UINT64_C(0x28C31C54050CBD22), UINT64_C(0x7C2A65C659DC4C2F),
+               UINT64_C(0x406CA61260E08589), UINT64_C(0x1485DF803C307484),
+               UINT64_C(0xE9BE5536D9416793), UINT64_C(0xBD572CA48591969E),
+               UINT64_C(0x9133D29EAB38F4DF), UINT64_C(0xC5DAAB0CF7E805D2),
+               UINT64_C(0x38E121BA129916C5), UINT64_C(0x6C0858284E49E7C8),
+               UINT64_C(0x504E9BFC77752E6E), UINT64_C(0x04A7E26E2BA5DF63),
+               UINT64_C(0xF99C68D8CED4CC74), UINT64_C(0xAD75114A92043D79),
+               UINT64_C(0xA15594AC938608F6), UINT64_C(0xF5BCED3ECF56F9FB),
+               UINT64_C(0x088767882A27EAEC), UINT64_C(0x5C6E1E1A76F71BE1),
+               UINT64_C(0x6028DDCE4FCBD247), UINT64_C(0x34C1A45C131B234A),
+               UINT64_C(0xC9FA2EEAF66A305D), UINT64_C(0x9D135778AABAC150),
+               UINT64_C(0xB177A9428413A311), UINT64_C(0xE59ED0D0D8C3521C),
+               UINT64_C(0x18A55A663DB2410B), UINT64_C(0x4C4C23F46162B006),
+               UINT64_C(0x700AE020585E79A0), UINT64_C(0x24E399B2048E88AD),
+               UINT64_C(0xD9D81304E1FF9BBA), UINT64_C(0x8D316A96BD2F6AB7),
+               UINT64_C(0xC19918C8E2FBF0A4), UINT64_C(0x9570615ABE2B01A9),
+               UINT64_C(0x684BEBEC5B5A12BE), UINT64_C(0x3CA2927E078AE3B3),
+               UINT64_C(0x00E451AA3EB62A15), UINT64_C(0x540D28386266DB18),
+               UINT64_C(0xA936A28E8717C80F), UINT64_C(0xFDDFDB1CDBC73902),
+               UINT64_C(0xD1BB2526F56E5B43), UINT64_C(0x85525CB4A9BEAA4E),
+               UINT64_C(0x7869D6024CCFB959), UINT64_C(0x2C80AF90101F4854),
+               UINT64_C(0x10C66C44292381F2), UINT64_C(0x442F15D675F370FF),
+               UINT64_C(0xB9149F60908263E8), UINT64_C(0xEDFDE6F2CC5292E5),
+               UINT64_C(0xE1DD6314CDD0A76A), UINT64_C(0xB5341A8691005667),
+               UINT64_C(0x480F903074714570), UINT64_C(0x1CE6E9A228A1B47D),
+               UINT64_C(0x20A02A76119D7DDB), UINT64_C(0x744953E44D4D8CD6),
+               UINT64_C(0x8972D952A83C9FC1), UINT64_C(0xDD9BA0C0F4EC6ECC),
+               UINT64_C(0xF1FF5EFADA450C8D), UINT64_C(0xA51627688695FD80),
+               UINT64_C(0x582DADDE63E4EE97), UINT64_C(0x0CC4D44C3F341F9A),
+               UINT64_C(0x308217980608D63C), UINT64_C(0x646B6E0A5AD82731),
+               UINT64_C(0x9950E4BCBFA93426), UINT64_C(0xCDB99D2EE379C52B),
+               UINT64_C(0x90FB71CAD654A0F5), UINT64_C(0xC41208588A8451F8),
+               UINT64_C(0x392982EE6FF542EF), UINT64_C(0x6DC0FB7C3325B3E2),
+               UINT64_C(0x518638A80A197A44), UINT64_C(0x056F413A56C98B49),
+               UINT64_C(0xF854CB8CB3B8985E), UINT64_C(0xACBDB21EEF686953),
+               UINT64_C(0x80D94C24C1C10B12), UINT64_C(0xD43035B69D11FA1F),
+               UINT64_C(0x290BBF007860E908), UINT64_C(0x7DE2C69224B01805),
+               UINT64_C(0x41A405461D8CD1A3), UINT64_C(0x154D7CD4415C20AE),
+               UINT64_C(0xE876F662A42D33B9), UINT64_C(0xBC9F8FF0F8FDC2B4),
+               UINT64_C(0xB0BF0A16F97FF73B), UINT64_C(0xE4567384A5AF0636),
+               UINT64_C(0x196DF93240DE1521), UINT64_C(0x4D8480A01C0EE42C),
+               UINT64_C(0x71C2437425322D8A), UINT64_C(0x252B3AE679E2DC87),
+               UINT64_C(0xD810B0509C93CF90), UINT64_C(0x8CF9C9C2C0433E9D),
+               UINT64_C(0xA09D37F8EEEA5CDC), UINT64_C(0xF4744E6AB23AADD1),
+               UINT64_C(0x094FC4DC574BBEC6), UINT64_C(0x5DA6BD4E0B9B4FCB),
+               UINT64_C(0x61E07E9A32A7866D), UINT64_C(0x350907086E777760),
+               UINT64_C(0xC8328DBE8B066477), UINT64_C(0x9CDBF42CD7D6957A),
+               UINT64_C(0xD073867288020F69), UINT64_C(0x849AFFE0D4D2FE64),
+               UINT64_C(0x79A1755631A3ED73), UINT64_C(0x2D480CC46D731C7E),
+               UINT64_C(0x110ECF10544FD5D8), UINT64_C(0x45E7B682089F24D5),
+               UINT64_C(0xB8DC3C34EDEE37C2), UINT64_C(0xEC3545A6B13EC6CF),
+               UINT64_C(0xC051BB9C9F97A48E), UINT64_C(0x94B8C20EC3475583),
+               UINT64_C(0x698348B826364694), UINT64_C(0x3D6A312A7AE6B799),
+               UINT64_C(0x012CF2FE43DA7E3F), UINT64_C(0x55C58B6C1F0A8F32),
+               UINT64_C(0xA8FE01DAFA7B9C25), UINT64_C(0xFC177848A6AB6D28),
+               UINT64_C(0xF037FDAEA72958A7), UINT64_C(0xA4DE843CFBF9A9AA),
+               UINT64_C(0x59E50E8A1E88BABD), UINT64_C(0x0D0C771842584BB0),
+               UINT64_C(0x314AB4CC7B648216), UINT64_C(0x65A3CD5E27B4731B),
+               UINT64_C(0x989847E8C2C5600C), UINT64_C(0xCC713E7A9E159101),
+               UINT64_C(0xE015C040B0BCF340), UINT64_C(0xB4FCB9D2EC6C024D),
+               UINT64_C(0x49C73364091D115A), UINT64_C(0x1D2E4AF655CDE057),
+               UINT64_C(0x216889226CF129F1), UINT64_C(0x7581F0B03021D8FC),
+               UINT64_C(0x88BA7A06D550CBEB), UINT64_C(0xDC53039489803AE6),
+               UINT64_C(0x11EA9EBA6AF9FFCD), UINT64_C(0x4503E72836290EC0),
+               UINT64_C(0xB8386D9ED3581DD7), UINT64_C(0xECD1140C8F88ECDA),
+               UINT64_C(0xD097D7D8B6B4257C), UINT64_C(0x847EAE4AEA64D471),
+               UINT64_C(0x794524FC0F15C766), UINT64_C(0x2DAC5D6E53C5366B),
+               UINT64_C(0x01C8A3547D6C542A), UINT64_C(0x5521DAC621BCA527),
+               UINT64_C(0xA81A5070C4CDB630), UINT64_C(0xFCF329E2981D473D),
+               UINT64_C(0xC0B5EA36A1218E9B), UINT64_C(0x945C93A4FDF17F96),
+               UINT64_C(0x6967191218806C81), UINT64_C(0x3D8E608044509D8C),
+               UINT64_C(0x31AEE56645D2A803), UINT64_C(0x65479CF41902590E),
+               UINT64_C(0x987C1642FC734A19), UINT64_C(0xCC956FD0A0A3BB14),
+               UINT64_C(0xF0D3AC04999F72B2), UINT64_C(0xA43AD596C54F83BF),
+               UINT64_C(0x59015F20203E90A8), UINT64_C(0x0DE826B27CEE61A5),
+               UINT64_C(0x218CD888524703E4), UINT64_C(0x7565A11A0E97F2E9),
+               UINT64_C(0x885E2BACEBE6E1FE), UINT64_C(0xDCB7523EB73610F3),
+               UINT64_C(0xE0F191EA8E0AD955), UINT64_C(0xB418E878D2DA2858),
+               UINT64_C(0x492362CE37AB3B4F), UINT64_C(0x1DCA1B5C6B7BCA42),
+               UINT64_C(0x5162690234AF5051), UINT64_C(0x058B1090687FA15C),
+               UINT64_C(0xF8B09A268D0EB24B), UINT64_C(0xAC59E3B4D1DE4346),
+               UINT64_C(0x901F2060E8E28AE0), UINT64_C(0xC4F659F2B4327BED),
+               UINT64_C(0x39CDD344514368FA), UINT64_C(0x6D24AAD60D9399F7),
+               UINT64_C(0x414054EC233AFBB6), UINT64_C(0x15A92D7E7FEA0ABB),
+               UINT64_C(0xE892A7C89A9B19AC), UINT64_C(0xBC7BDE5AC64BE8A1),
+               UINT64_C(0x803D1D8EFF772107), UINT64_C(0xD4D4641CA3A7D00A),
+               UINT64_C(0x29EFEEAA46D6C31D), UINT64_C(0x7D0697381A063210),
+               UINT64_C(0x712612DE1B84079F), UINT64_C(0x25CF6B4C4754F692),
+               UINT64_C(0xD8F4E1FAA225E585), UINT64_C(0x8C1D9868FEF51488),
+               UINT64_C(0xB05B5BBCC7C9DD2E), UINT64_C(0xE4B2222E9B192C23),
+               UINT64_C(0x1989A8987E683F34), UINT64_C(0x4D60D10A22B8CE39),
+               UINT64_C(0x61042F300C11AC78), UINT64_C(0x35ED56A250C15D75),
+               UINT64_C(0xC8D6DC14B5B04E62), UINT64_C(0x9C3FA586E960BF6F),
+               UINT64_C(0xA0796652D05C76C9), UINT64_C(0xF4901FC08C8C87C4),
+               UINT64_C(0x09AB957669FD94D3), UINT64_C(0x5D42ECE4352D65DE)
+       }, {
+               UINT64_C(0x0000000000000000), UINT64_C(0x3F0BE14A916A6DCB),
+               UINT64_C(0x7E17C29522D4DB96), UINT64_C(0x411C23DFB3BEB65D),
+               UINT64_C(0xFC2F852A45A9B72C), UINT64_C(0xC3246460D4C3DAE7),
+               UINT64_C(0x823847BF677D6CBA), UINT64_C(0xBD33A6F5F6170171),
+               UINT64_C(0x6A87A57F245D70DD), UINT64_C(0x558C4435B5371D16),
+               UINT64_C(0x149067EA0689AB4B), UINT64_C(0x2B9B86A097E3C680),
+               UINT64_C(0x96A8205561F4C7F1), UINT64_C(0xA9A3C11FF09EAA3A),
+               UINT64_C(0xE8BFE2C043201C67), UINT64_C(0xD7B4038AD24A71AC),
+               UINT64_C(0xD50F4AFE48BAE1BA), UINT64_C(0xEA04ABB4D9D08C71),
+               UINT64_C(0xAB18886B6A6E3A2C), UINT64_C(0x94136921FB0457E7),
+               UINT64_C(0x2920CFD40D135696), UINT64_C(0x162B2E9E9C793B5D),
+               UINT64_C(0x57370D412FC78D00), UINT64_C(0x683CEC0BBEADE0CB),
+               UINT64_C(0xBF88EF816CE79167), UINT64_C(0x80830ECBFD8DFCAC),
+               UINT64_C(0xC19F2D144E334AF1), UINT64_C(0xFE94CC5EDF59273A),
+               UINT64_C(0x43A76AAB294E264B), UINT64_C(0x7CAC8BE1B8244B80),
+               UINT64_C(0x3DB0A83E0B9AFDDD), UINT64_C(0x02BB49749AF09016),
+               UINT64_C(0x38C63AD73E7BDDF1), UINT64_C(0x07CDDB9DAF11B03A),
+               UINT64_C(0x46D1F8421CAF0667), UINT64_C(0x79DA19088DC56BAC),
+               UINT64_C(0xC4E9BFFD7BD26ADD), UINT64_C(0xFBE25EB7EAB80716),
+               UINT64_C(0xBAFE7D685906B14B), UINT64_C(0x85F59C22C86CDC80),
+               UINT64_C(0x52419FA81A26AD2C), UINT64_C(0x6D4A7EE28B4CC0E7),
+               UINT64_C(0x2C565D3D38F276BA), UINT64_C(0x135DBC77A9981B71),
+               UINT64_C(0xAE6E1A825F8F1A00), UINT64_C(0x9165FBC8CEE577CB),
+               UINT64_C(0xD079D8177D5BC196), UINT64_C(0xEF72395DEC31AC5D),
+               UINT64_C(0xEDC9702976C13C4B), UINT64_C(0xD2C29163E7AB5180),
+               UINT64_C(0x93DEB2BC5415E7DD), UINT64_C(0xACD553F6C57F8A16),
+               UINT64_C(0x11E6F50333688B67), UINT64_C(0x2EED1449A202E6AC),
+               UINT64_C(0x6FF1379611BC50F1), UINT64_C(0x50FAD6DC80D63D3A),
+               UINT64_C(0x874ED556529C4C96), UINT64_C(0xB845341CC3F6215D),
+               UINT64_C(0xF95917C370489700), UINT64_C(0xC652F689E122FACB),
+               UINT64_C(0x7B61507C1735FBBA), UINT64_C(0x446AB136865F9671),
+               UINT64_C(0x057692E935E1202C), UINT64_C(0x3A7D73A3A48B4DE7),
+               UINT64_C(0x718C75AE7CF7BBE2), UINT64_C(0x4E8794E4ED9DD629),
+               UINT64_C(0x0F9BB73B5E236074), UINT64_C(0x30905671CF490DBF),
+               UINT64_C(0x8DA3F084395E0CCE), UINT64_C(0xB2A811CEA8346105),
+               UINT64_C(0xF3B432111B8AD758), UINT64_C(0xCCBFD35B8AE0BA93),
+               UINT64_C(0x1B0BD0D158AACB3F), UINT64_C(0x2400319BC9C0A6F4),
+               UINT64_C(0x651C12447A7E10A9), UINT64_C(0x5A17F30EEB147D62),
+               UINT64_C(0xE72455FB1D037C13), UINT64_C(0xD82FB4B18C6911D8),
+               UINT64_C(0x9933976E3FD7A785), UINT64_C(0xA6387624AEBDCA4E),
+               UINT64_C(0xA4833F50344D5A58), UINT64_C(0x9B88DE1AA5273793),
+               UINT64_C(0xDA94FDC5169981CE), UINT64_C(0xE59F1C8F87F3EC05),
+               UINT64_C(0x58ACBA7A71E4ED74), UINT64_C(0x67A75B30E08E80BF),
+               UINT64_C(0x26BB78EF533036E2), UINT64_C(0x19B099A5C25A5B29),
+               UINT64_C(0xCE049A2F10102A85), UINT64_C(0xF10F7B65817A474E),
+               UINT64_C(0xB01358BA32C4F113), UINT64_C(0x8F18B9F0A3AE9CD8),
+               UINT64_C(0x322B1F0555B99DA9), UINT64_C(0x0D20FE4FC4D3F062),
+               UINT64_C(0x4C3CDD90776D463F), UINT64_C(0x73373CDAE6072BF4),
+               UINT64_C(0x494A4F79428C6613), UINT64_C(0x7641AE33D3E60BD8),
+               UINT64_C(0x375D8DEC6058BD85), UINT64_C(0x08566CA6F132D04E),
+               UINT64_C(0xB565CA530725D13F), UINT64_C(0x8A6E2B19964FBCF4),
+               UINT64_C(0xCB7208C625F10AA9), UINT64_C(0xF479E98CB49B6762),
+               UINT64_C(0x23CDEA0666D116CE), UINT64_C(0x1CC60B4CF7BB7B05),
+               UINT64_C(0x5DDA28934405CD58), UINT64_C(0x62D1C9D9D56FA093),
+               UINT64_C(0xDFE26F2C2378A1E2), UINT64_C(0xE0E98E66B212CC29),
+               UINT64_C(0xA1F5ADB901AC7A74), UINT64_C(0x9EFE4CF390C617BF),
+               UINT64_C(0x9C4505870A3687A9), UINT64_C(0xA34EE4CD9B5CEA62),
+               UINT64_C(0xE252C71228E25C3F), UINT64_C(0xDD592658B98831F4),
+               UINT64_C(0x606A80AD4F9F3085), UINT64_C(0x5F6161E7DEF55D4E),
+               UINT64_C(0x1E7D42386D4BEB13), UINT64_C(0x2176A372FC2186D8),
+               UINT64_C(0xF6C2A0F82E6BF774), UINT64_C(0xC9C941B2BF019ABF),
+               UINT64_C(0x88D5626D0CBF2CE2), UINT64_C(0xB7DE83279DD54129),
+               UINT64_C(0x0AED25D26BC24058), UINT64_C(0x35E6C498FAA82D93),
+               UINT64_C(0x74FAE74749169BCE), UINT64_C(0x4BF1060DD87CF605),
+               UINT64_C(0xE318EB5CF9EF77C4), UINT64_C(0xDC130A1668851A0F),
+               UINT64_C(0x9D0F29C9DB3BAC52), UINT64_C(0xA204C8834A51C199),
+               UINT64_C(0x1F376E76BC46C0E8), UINT64_C(0x203C8F3C2D2CAD23),
+               UINT64_C(0x6120ACE39E921B7E), UINT64_C(0x5E2B4DA90FF876B5),
+               UINT64_C(0x899F4E23DDB20719), UINT64_C(0xB694AF694CD86AD2),
+               UINT64_C(0xF7888CB6FF66DC8F), UINT64_C(0xC8836DFC6E0CB144),
+               UINT64_C(0x75B0CB09981BB035), UINT64_C(0x4ABB2A430971DDFE),
+               UINT64_C(0x0BA7099CBACF6BA3), UINT64_C(0x34ACE8D62BA50668),
+               UINT64_C(0x3617A1A2B155967E), UINT64_C(0x091C40E8203FFBB5),
+               UINT64_C(0x4800633793814DE8), UINT64_C(0x770B827D02EB2023),
+               UINT64_C(0xCA382488F4FC2152), UINT64_C(0xF533C5C265964C99),
+               UINT64_C(0xB42FE61DD628FAC4), UINT64_C(0x8B2407574742970F),
+               UINT64_C(0x5C9004DD9508E6A3), UINT64_C(0x639BE59704628B68),
+               UINT64_C(0x2287C648B7DC3D35), UINT64_C(0x1D8C270226B650FE),
+               UINT64_C(0xA0BF81F7D0A1518F), UINT64_C(0x9FB460BD41CB3C44),
+               UINT64_C(0xDEA84362F2758A19), UINT64_C(0xE1A3A228631FE7D2),
+               UINT64_C(0xDBDED18BC794AA35), UINT64_C(0xE4D530C156FEC7FE),
+               UINT64_C(0xA5C9131EE54071A3), UINT64_C(0x9AC2F254742A1C68),
+               UINT64_C(0x27F154A1823D1D19), UINT64_C(0x18FAB5EB135770D2),
+               UINT64_C(0x59E69634A0E9C68F), UINT64_C(0x66ED777E3183AB44),
+               UINT64_C(0xB15974F4E3C9DAE8), UINT64_C(0x8E5295BE72A3B723),
+               UINT64_C(0xCF4EB661C11D017E), UINT64_C(0xF045572B50776CB5),
+               UINT64_C(0x4D76F1DEA6606DC4), UINT64_C(0x727D1094370A000F),
+               UINT64_C(0x3361334B84B4B652), UINT64_C(0x0C6AD20115DEDB99),
+               UINT64_C(0x0ED19B758F2E4B8F), UINT64_C(0x31DA7A3F1E442644),
+               UINT64_C(0x70C659E0ADFA9019), UINT64_C(0x4FCDB8AA3C90FDD2),
+               UINT64_C(0xF2FE1E5FCA87FCA3), UINT64_C(0xCDF5FF155BED9168),
+               UINT64_C(0x8CE9DCCAE8532735), UINT64_C(0xB3E23D8079394AFE),
+               UINT64_C(0x64563E0AAB733B52), UINT64_C(0x5B5DDF403A195699),
+               UINT64_C(0x1A41FC9F89A7E0C4), UINT64_C(0x254A1DD518CD8D0F),
+               UINT64_C(0x9879BB20EEDA8C7E), UINT64_C(0xA7725A6A7FB0E1B5),
+               UINT64_C(0xE66E79B5CC0E57E8), UINT64_C(0xD96598FF5D643A23),
+               UINT64_C(0x92949EF28518CC26), UINT64_C(0xAD9F7FB81472A1ED),
+               UINT64_C(0xEC835C67A7CC17B0), UINT64_C(0xD388BD2D36A67A7B),
+               UINT64_C(0x6EBB1BD8C0B17B0A), UINT64_C(0x51B0FA9251DB16C1),
+               UINT64_C(0x10ACD94DE265A09C), UINT64_C(0x2FA73807730FCD57),
+               UINT64_C(0xF8133B8DA145BCFB), UINT64_C(0xC718DAC7302FD130),
+               UINT64_C(0x8604F9188391676D), UINT64_C(0xB90F185212FB0AA6),
+               UINT64_C(0x043CBEA7E4EC0BD7), UINT64_C(0x3B375FED7586661C),
+               UINT64_C(0x7A2B7C32C638D041), UINT64_C(0x45209D785752BD8A),
+               UINT64_C(0x479BD40CCDA22D9C), UINT64_C(0x789035465CC84057),
+               UINT64_C(0x398C1699EF76F60A), UINT64_C(0x0687F7D37E1C9BC1),
+               UINT64_C(0xBBB45126880B9AB0), UINT64_C(0x84BFB06C1961F77B),
+               UINT64_C(0xC5A393B3AADF4126), UINT64_C(0xFAA872F93BB52CED),
+               UINT64_C(0x2D1C7173E9FF5D41), UINT64_C(0x121790397895308A),
+               UINT64_C(0x530BB3E6CB2B86D7), UINT64_C(0x6C0052AC5A41EB1C),
+               UINT64_C(0xD133F459AC56EA6D), UINT64_C(0xEE3815133D3C87A6),
+               UINT64_C(0xAF2436CC8E8231FB), UINT64_C(0x902FD7861FE85C30),
+               UINT64_C(0xAA52A425BB6311D7), UINT64_C(0x9559456F2A097C1C),
+               UINT64_C(0xD44566B099B7CA41), UINT64_C(0xEB4E87FA08DDA78A),
+               UINT64_C(0x567D210FFECAA6FB), UINT64_C(0x6976C0456FA0CB30),
+               UINT64_C(0x286AE39ADC1E7D6D), UINT64_C(0x176102D04D7410A6),
+               UINT64_C(0xC0D5015A9F3E610A), UINT64_C(0xFFDEE0100E540CC1),
+               UINT64_C(0xBEC2C3CFBDEABA9C), UINT64_C(0x81C922852C80D757),
+               UINT64_C(0x3CFA8470DA97D626), UINT64_C(0x03F1653A4BFDBBED),
+               UINT64_C(0x42ED46E5F8430DB0), UINT64_C(0x7DE6A7AF6929607B),
+               UINT64_C(0x7F5DEEDBF3D9F06D), UINT64_C(0x40560F9162B39DA6),
+               UINT64_C(0x014A2C4ED10D2BFB), UINT64_C(0x3E41CD0440674630),
+               UINT64_C(0x83726BF1B6704741), UINT64_C(0xBC798ABB271A2A8A),
+               UINT64_C(0xFD65A96494A49CD7), UINT64_C(0xC26E482E05CEF11C),
+               UINT64_C(0x15DA4BA4D78480B0), UINT64_C(0x2AD1AAEE46EEED7B),
+               UINT64_C(0x6BCD8931F5505B26), UINT64_C(0x54C6687B643A36ED),
+               UINT64_C(0xE9F5CE8E922D379C), UINT64_C(0xD6FE2FC403475A57),
+               UINT64_C(0x97E20C1BB0F9EC0A), UINT64_C(0xA8E9ED51219381C1)
+       }, {
+               UINT64_C(0x0000000000000000), UINT64_C(0x1DEE8A5E222CA1DC),
+               UINT64_C(0x3BDD14BC445943B8), UINT64_C(0x26339EE26675E264),
+               UINT64_C(0x77BA297888B28770), UINT64_C(0x6A54A326AA9E26AC),
+               UINT64_C(0x4C673DC4CCEBC4C8), UINT64_C(0x5189B79AEEC76514),
+               UINT64_C(0xEF7452F111650EE0), UINT64_C(0xF29AD8AF3349AF3C),
+               UINT64_C(0xD4A9464D553C4D58), UINT64_C(0xC947CC137710EC84),
+               UINT64_C(0x98CE7B8999D78990), UINT64_C(0x8520F1D7BBFB284C),
+               UINT64_C(0xA3136F35DD8ECA28), UINT64_C(0xBEFDE56BFFA26BF4),
+               UINT64_C(0x4C300AC98DC40345), UINT64_C(0x51DE8097AFE8A299),
+               UINT64_C(0x77ED1E75C99D40FD), UINT64_C(0x6A03942BEBB1E121),
+               UINT64_C(0x3B8A23B105768435), UINT64_C(0x2664A9EF275A25E9),
+               UINT64_C(0x0057370D412FC78D), UINT64_C(0x1DB9BD5363036651),
+               UINT64_C(0xA34458389CA10DA5), UINT64_C(0xBEAAD266BE8DAC79),
+               UINT64_C(0x98994C84D8F84E1D), UINT64_C(0x8577C6DAFAD4EFC1),
+               UINT64_C(0xD4FE714014138AD5), UINT64_C(0xC910FB1E363F2B09),
+               UINT64_C(0xEF2365FC504AC96D), UINT64_C(0xF2CDEFA2726668B1),
+               UINT64_C(0x986015931B88068A), UINT64_C(0x858E9FCD39A4A756),
+               UINT64_C(0xA3BD012F5FD14532), UINT64_C(0xBE538B717DFDE4EE),
+               UINT64_C(0xEFDA3CEB933A81FA), UINT64_C(0xF234B6B5B1162026),
+               UINT64_C(0xD4072857D763C242), UINT64_C(0xC9E9A209F54F639E),
+               UINT64_C(0x771447620AED086A), UINT64_C(0x6AFACD3C28C1A9B6),
+               UINT64_C(0x4CC953DE4EB44BD2), UINT64_C(0x5127D9806C98EA0E),
+               UINT64_C(0x00AE6E1A825F8F1A), UINT64_C(0x1D40E444A0732EC6),
+               UINT64_C(0x3B737AA6C606CCA2), UINT64_C(0x269DF0F8E42A6D7E),
+               UINT64_C(0xD4501F5A964C05CF), UINT64_C(0xC9BE9504B460A413),
+               UINT64_C(0xEF8D0BE6D2154677), UINT64_C(0xF26381B8F039E7AB),
+               UINT64_C(0xA3EA36221EFE82BF), UINT64_C(0xBE04BC7C3CD22363),
+               UINT64_C(0x9837229E5AA7C107), UINT64_C(0x85D9A8C0788B60DB),
+               UINT64_C(0x3B244DAB87290B2F), UINT64_C(0x26CAC7F5A505AAF3),
+               UINT64_C(0x00F95917C3704897), UINT64_C(0x1D17D349E15CE94B),
+               UINT64_C(0x4C9E64D30F9B8C5F), UINT64_C(0x5170EE8D2DB72D83),
+               UINT64_C(0x7743706F4BC2CFE7), UINT64_C(0x6AADFA3169EE6E3B),
+               UINT64_C(0xA218840D981E1391), UINT64_C(0xBFF60E53BA32B24D),
+               UINT64_C(0x99C590B1DC475029), UINT64_C(0x842B1AEFFE6BF1F5),
+               UINT64_C(0xD5A2AD7510AC94E1), UINT64_C(0xC84C272B3280353D),
+               UINT64_C(0xEE7FB9C954F5D759), UINT64_C(0xF391339776D97685),
+               UINT64_C(0x4D6CD6FC897B1D71), UINT64_C(0x50825CA2AB57BCAD),
+               UINT64_C(0x76B1C240CD225EC9), UINT64_C(0x6B5F481EEF0EFF15),
+               UINT64_C(0x3AD6FF8401C99A01), UINT64_C(0x273875DA23E53BDD),
+               UINT64_C(0x010BEB384590D9B9), UINT64_C(0x1CE5616667BC7865),
+               UINT64_C(0xEE288EC415DA10D4), UINT64_C(0xF3C6049A37F6B108),
+               UINT64_C(0xD5F59A785183536C), UINT64_C(0xC81B102673AFF2B0),
+               UINT64_C(0x9992A7BC9D6897A4), UINT64_C(0x847C2DE2BF443678),
+               UINT64_C(0xA24FB300D931D41C), UINT64_C(0xBFA1395EFB1D75C0),
+               UINT64_C(0x015CDC3504BF1E34), UINT64_C(0x1CB2566B2693BFE8),
+               UINT64_C(0x3A81C88940E65D8C), UINT64_C(0x276F42D762CAFC50),
+               UINT64_C(0x76E6F54D8C0D9944), UINT64_C(0x6B087F13AE213898),
+               UINT64_C(0x4D3BE1F1C854DAFC), UINT64_C(0x50D56BAFEA787B20),
+               UINT64_C(0x3A78919E8396151B), UINT64_C(0x27961BC0A1BAB4C7),
+               UINT64_C(0x01A58522C7CF56A3), UINT64_C(0x1C4B0F7CE5E3F77F),
+               UINT64_C(0x4DC2B8E60B24926B), UINT64_C(0x502C32B8290833B7),
+               UINT64_C(0x761FAC5A4F7DD1D3), UINT64_C(0x6BF126046D51700F),
+               UINT64_C(0xD50CC36F92F31BFB), UINT64_C(0xC8E24931B0DFBA27),
+               UINT64_C(0xEED1D7D3D6AA5843), UINT64_C(0xF33F5D8DF486F99F),
+               UINT64_C(0xA2B6EA171A419C8B), UINT64_C(0xBF586049386D3D57),
+               UINT64_C(0x996BFEAB5E18DF33), UINT64_C(0x848574F57C347EEF),
+               UINT64_C(0x76489B570E52165E), UINT64_C(0x6BA611092C7EB782),
+               UINT64_C(0x4D958FEB4A0B55E6), UINT64_C(0x507B05B56827F43A),
+               UINT64_C(0x01F2B22F86E0912E), UINT64_C(0x1C1C3871A4CC30F2),
+               UINT64_C(0x3A2FA693C2B9D296), UINT64_C(0x27C12CCDE095734A),
+               UINT64_C(0x993CC9A61F3718BE), UINT64_C(0x84D243F83D1BB962),
+               UINT64_C(0xA2E1DD1A5B6E5B06), UINT64_C(0xBF0F57447942FADA),
+               UINT64_C(0xEE86E0DE97859FCE), UINT64_C(0xF3686A80B5A93E12),
+               UINT64_C(0xD55BF462D3DCDC76), UINT64_C(0xC8B57E3CF1F07DAA),
+               UINT64_C(0xD6E9A7309F3239A7), UINT64_C(0xCB072D6EBD1E987B),
+               UINT64_C(0xED34B38CDB6B7A1F), UINT64_C(0xF0DA39D2F947DBC3),
+               UINT64_C(0xA1538E481780BED7), UINT64_C(0xBCBD041635AC1F0B),
+               UINT64_C(0x9A8E9AF453D9FD6F), UINT64_C(0x876010AA71F55CB3),
+               UINT64_C(0x399DF5C18E573747), UINT64_C(0x24737F9FAC7B969B),
+               UINT64_C(0x0240E17DCA0E74FF), UINT64_C(0x1FAE6B23E822D523),
+               UINT64_C(0x4E27DCB906E5B037), UINT64_C(0x53C956E724C911EB),
+               UINT64_C(0x75FAC80542BCF38F), UINT64_C(0x6814425B60905253),
+               UINT64_C(0x9AD9ADF912F63AE2), UINT64_C(0x873727A730DA9B3E),
+               UINT64_C(0xA104B94556AF795A), UINT64_C(0xBCEA331B7483D886),
+               UINT64_C(0xED6384819A44BD92), UINT64_C(0xF08D0EDFB8681C4E),
+               UINT64_C(0xD6BE903DDE1DFE2A), UINT64_C(0xCB501A63FC315FF6),
+               UINT64_C(0x75ADFF0803933402), UINT64_C(0x6843755621BF95DE),
+               UINT64_C(0x4E70EBB447CA77BA), UINT64_C(0x539E61EA65E6D666),
+               UINT64_C(0x0217D6708B21B372), UINT64_C(0x1FF95C2EA90D12AE),
+               UINT64_C(0x39CAC2CCCF78F0CA), UINT64_C(0x24244892ED545116),
+               UINT64_C(0x4E89B2A384BA3F2D), UINT64_C(0x536738FDA6969EF1),
+               UINT64_C(0x7554A61FC0E37C95), UINT64_C(0x68BA2C41E2CFDD49),
+               UINT64_C(0x39339BDB0C08B85D), UINT64_C(0x24DD11852E241981),
+               UINT64_C(0x02EE8F674851FBE5), UINT64_C(0x1F0005396A7D5A39),
+               UINT64_C(0xA1FDE05295DF31CD), UINT64_C(0xBC136A0CB7F39011),
+               UINT64_C(0x9A20F4EED1867275), UINT64_C(0x87CE7EB0F3AAD3A9),
+               UINT64_C(0xD647C92A1D6DB6BD), UINT64_C(0xCBA943743F411761),
+               UINT64_C(0xED9ADD965934F505), UINT64_C(0xF07457C87B1854D9),
+               UINT64_C(0x02B9B86A097E3C68), UINT64_C(0x1F5732342B529DB4),
+               UINT64_C(0x3964ACD64D277FD0), UINT64_C(0x248A26886F0BDE0C),
+               UINT64_C(0x7503911281CCBB18), UINT64_C(0x68ED1B4CA3E01AC4),
+               UINT64_C(0x4EDE85AEC595F8A0), UINT64_C(0x53300FF0E7B9597C),
+               UINT64_C(0xEDCDEA9B181B3288), UINT64_C(0xF02360C53A379354),
+               UINT64_C(0xD610FE275C427130), UINT64_C(0xCBFE74797E6ED0EC),
+               UINT64_C(0x9A77C3E390A9B5F8), UINT64_C(0x879949BDB2851424),
+               UINT64_C(0xA1AAD75FD4F0F640), UINT64_C(0xBC445D01F6DC579C),
+               UINT64_C(0x74F1233D072C2A36), UINT64_C(0x691FA96325008BEA),
+               UINT64_C(0x4F2C37814375698E), UINT64_C(0x52C2BDDF6159C852),
+               UINT64_C(0x034B0A458F9EAD46), UINT64_C(0x1EA5801BADB20C9A),
+               UINT64_C(0x38961EF9CBC7EEFE), UINT64_C(0x257894A7E9EB4F22),
+               UINT64_C(0x9B8571CC164924D6), UINT64_C(0x866BFB923465850A),
+               UINT64_C(0xA05865705210676E), UINT64_C(0xBDB6EF2E703CC6B2),
+               UINT64_C(0xEC3F58B49EFBA3A6), UINT64_C(0xF1D1D2EABCD7027A),
+               UINT64_C(0xD7E24C08DAA2E01E), UINT64_C(0xCA0CC656F88E41C2),
+               UINT64_C(0x38C129F48AE82973), UINT64_C(0x252FA3AAA8C488AF),
+               UINT64_C(0x031C3D48CEB16ACB), UINT64_C(0x1EF2B716EC9DCB17),
+               UINT64_C(0x4F7B008C025AAE03), UINT64_C(0x52958AD220760FDF),
+               UINT64_C(0x74A614304603EDBB), UINT64_C(0x69489E6E642F4C67),
+               UINT64_C(0xD7B57B059B8D2793), UINT64_C(0xCA5BF15BB9A1864F),
+               UINT64_C(0xEC686FB9DFD4642B), UINT64_C(0xF186E5E7FDF8C5F7),
+               UINT64_C(0xA00F527D133FA0E3), UINT64_C(0xBDE1D8233113013F),
+               UINT64_C(0x9BD246C15766E35B), UINT64_C(0x863CCC9F754A4287),
+               UINT64_C(0xEC9136AE1CA42CBC), UINT64_C(0xF17FBCF03E888D60),
+               UINT64_C(0xD74C221258FD6F04), UINT64_C(0xCAA2A84C7AD1CED8),
+               UINT64_C(0x9B2B1FD69416ABCC), UINT64_C(0x86C59588B63A0A10),
+               UINT64_C(0xA0F60B6AD04FE874), UINT64_C(0xBD188134F26349A8),
+               UINT64_C(0x03E5645F0DC1225C), UINT64_C(0x1E0BEE012FED8380),
+               UINT64_C(0x383870E3499861E4), UINT64_C(0x25D6FABD6BB4C038),
+               UINT64_C(0x745F4D278573A52C), UINT64_C(0x69B1C779A75F04F0),
+               UINT64_C(0x4F82599BC12AE694), UINT64_C(0x526CD3C5E3064748),
+               UINT64_C(0xA0A13C6791602FF9), UINT64_C(0xBD4FB639B34C8E25),
+               UINT64_C(0x9B7C28DBD5396C41), UINT64_C(0x8692A285F715CD9D),
+               UINT64_C(0xD71B151F19D2A889), UINT64_C(0xCAF59F413BFE0955),
+               UINT64_C(0xECC601A35D8BEB31), UINT64_C(0xF1288BFD7FA74AED),
+               UINT64_C(0x4FD56E9680052119), UINT64_C(0x523BE4C8A22980C5),
+               UINT64_C(0x74087A2AC45C62A1), UINT64_C(0x69E6F074E670C37D),
+               UINT64_C(0x386F47EE08B7A669), UINT64_C(0x2581CDB02A9B07B5),
+               UINT64_C(0x03B253524CEEE5D1), UINT64_C(0x1E5CD90C6EC2440D)
+       }
+};
diff --git a/lzma/check/crc64_tablegen.c b/lzma/check/crc64_tablegen.c
new file mode 100644 (file)
index 0000000..40fcf49
--- /dev/null
@@ -0,0 +1,88 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       crc64_tablegen.c
+/// \brief      Generate crc64_table_le.h and crc64_table_be.h
+///
+/// Compiling: gcc -std=c99 -o crc64_tablegen crc64_tablegen.c
+/// Add -DWORDS_BIGENDIAN to generate big endian table.
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "tuklib_integer.h"
+
+
+static uint64_t crc64_table[4][256];
+
+
+extern void
+init_crc64_table(void)
+{
+       static const uint64_t poly64 = UINT64_C(0xC96C5795D7870F42);
+
+       for (size_t s = 0; s < 4; ++s) {
+               for (size_t b = 0; b < 256; ++b) {
+                       uint64_t r = s == 0 ? b : crc64_table[s - 1][b];
+
+                       for (size_t i = 0; i < 8; ++i) {
+                               if (r & 1)
+                                       r = (r >> 1) ^ poly64;
+                               else
+                                       r >>= 1;
+                       }
+
+                       crc64_table[s][b] = r;
+               }
+       }
+
+#ifdef WORDS_BIGENDIAN
+       for (size_t s = 0; s < 4; ++s)
+               for (size_t b = 0; b < 256; ++b)
+                       crc64_table[s][b] = bswap64(crc64_table[s][b]);
+#endif
+
+       return;
+}
+
+
+static void
+print_crc64_table(void)
+{
+       printf("/* This file has been automatically generated by "
+                       "crc64_tablegen.c. */\n\n"
+                       "const uint64_t lzma_crc64_table[4][256] = {\n\t{");
+
+       for (size_t s = 0; s < 4; ++s) {
+               for (size_t b = 0; b < 256; ++b) {
+                       if ((b % 2) == 0)
+                               printf("\n\t\t");
+
+                       printf("UINT64_C(0x%016" PRIX64 ")",
+                                       crc64_table[s][b]);
+
+                       if (b != 255)
+                               printf(",%s", (b+1) % 2 == 0 ? "" : " ");
+               }
+
+               if (s == 3)
+                       printf("\n\t}\n};\n");
+               else
+                       printf("\n\t}, {");
+       }
+
+       return;
+}
+
+
+int
+main(void)
+{
+       init_crc64_table();
+       print_crc64_table();
+       return 0;
+}
diff --git a/lzma/check/crc_macros.h b/lzma/check/crc_macros.h
new file mode 100644 (file)
index 0000000..a7c21b7
--- /dev/null
@@ -0,0 +1,30 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       crc_macros.h
+/// \brief      Some endian-dependent macros for CRC32 and CRC64
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef WORDS_BIGENDIAN
+#      define A(x) ((x) >> 24)
+#      define B(x) (((x) >> 16) & 0xFF)
+#      define C(x) (((x) >> 8) & 0xFF)
+#      define D(x) ((x) & 0xFF)
+
+#      define S8(x) ((x) << 8)
+#      define S32(x) ((x) << 32)
+
+#else
+#      define A(x) ((x) & 0xFF)
+#      define B(x) (((x) >> 8) & 0xFF)
+#      define C(x) (((x) >> 16) & 0xFF)
+#      define D(x) ((x) >> 24)
+
+#      define S8(x) ((x) >> 8)
+#      define S32(x) ((x) >> 32)
+#endif
diff --git a/lzma/check/sha256.c b/lzma/check/sha256.c
new file mode 100644 (file)
index 0000000..5eede5c
--- /dev/null
@@ -0,0 +1,196 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       sha256.c
+/// \brief      SHA-256
+///
+/// \todo       Crypto++ has x86 ASM optimizations. They use SSE so if they
+///             are imported to liblzma, SSE instructions need to be used
+///             conditionally to keep the code working on older boxes.
+//
+//  This code is based on the code found from 7-Zip, which has a modified
+//  version of the SHA-256 found from Crypto++ <http://www.cryptopp.com/>.
+//  The code was modified a little to fit into liblzma.
+//
+//  Authors:    Kevin Springle
+//              Wei Dai
+//              Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "check.h"
+
+// Rotate a uint32_t. GCC can optimize this to a rotate instruction
+// at least on x86.
+static inline uint32_t
+rotr_32(uint32_t num, unsigned amount)
+{
+        return (num >> amount) | (num << (32 - amount));
+}
+
+#define blk0(i) (W[i] = conv32be(data[i]))
+#define blk2(i) (W[i & 15] += s1(W[(i - 2) & 15]) + W[(i - 7) & 15] \
+               + s0(W[(i - 15) & 15]))
+
+#define Ch(x, y, z) (z ^ (x & (y ^ z)))
+#define Maj(x, y, z) ((x & (y ^ z)) + (y & z))
+
+#define a(i) T[(0 - i) & 7]
+#define b(i) T[(1 - i) & 7]
+#define c(i) T[(2 - i) & 7]
+#define d(i) T[(3 - i) & 7]
+#define e(i) T[(4 - i) & 7]
+#define f(i) T[(5 - i) & 7]
+#define g(i) T[(6 - i) & 7]
+#define h(i) T[(7 - i) & 7]
+
+#define R(i, j, blk) \
+       h(i) += S1(e(i)) + Ch(e(i), f(i), g(i)) + SHA256_K[i + j] + blk; \
+       d(i) += h(i); \
+       h(i) += S0(a(i)) + Maj(a(i), b(i), c(i))
+#define R0(i) R(i, 0, blk0(i))
+#define R2(i) R(i, j, blk2(i))
+
+#define S0(x) rotr_32(x ^ rotr_32(x ^ rotr_32(x, 9), 11), 2)
+#define S1(x) rotr_32(x ^ rotr_32(x ^ rotr_32(x, 14), 5), 6)
+#define s0(x) (rotr_32(x ^ rotr_32(x, 11), 7) ^ (x >> 3))
+#define s1(x) (rotr_32(x ^ rotr_32(x, 2), 17) ^ (x >> 10))
+
+
+static const uint32_t SHA256_K[64] = {
+       0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
+       0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
+       0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
+       0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
+       0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
+       0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
+       0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
+       0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
+       0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
+       0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
+       0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
+       0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
+       0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
+       0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
+       0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
+       0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
+};
+
+
+static void
+transform(uint32_t state[8], const uint32_t data[16])
+{
+       uint32_t W[16];
+       uint32_t T[8];
+
+       // Copy state[] to working vars.
+       memcpy(T, state, sizeof(T));
+
+       // The first 16 operations unrolled
+       R0( 0); R0( 1); R0( 2); R0( 3);
+       R0( 4); R0( 5); R0( 6); R0( 7);
+       R0( 8); R0( 9); R0(10); R0(11);
+       R0(12); R0(13); R0(14); R0(15);
+
+       // The remaining 48 operations partially unrolled
+       for (unsigned int j = 16; j < 64; j += 16) {
+               R2( 0); R2( 1); R2( 2); R2( 3);
+               R2( 4); R2( 5); R2( 6); R2( 7);
+               R2( 8); R2( 9); R2(10); R2(11);
+               R2(12); R2(13); R2(14); R2(15);
+       }
+
+       // Add the working vars back into state[].
+       state[0] += a(0);
+       state[1] += b(0);
+       state[2] += c(0);
+       state[3] += d(0);
+       state[4] += e(0);
+       state[5] += f(0);
+       state[6] += g(0);
+       state[7] += h(0);
+}
+
+
+static void
+process(lzma_check_state *check)
+{
+       transform(check->state.sha256.state, check->buffer.u32);
+       return;
+}
+
+
+extern void
+lzma_sha256_init(lzma_check_state *check)
+{
+       static const uint32_t s[8] = {
+               0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
+               0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19,
+       };
+
+       memcpy(check->state.sha256.state, s, sizeof(s));
+       check->state.sha256.size = 0;
+
+       return;
+}
+
+
+extern void
+lzma_sha256_update(const uint8_t *buf, size_t size, lzma_check_state *check)
+{
+       // Copy the input data into a properly aligned temporary buffer.
+       // This way we can be called with arbitrarily sized buffers
+       // (no need to be multiple of 64 bytes), and the code works also
+       // on architectures that don't allow unaligned memory access.
+       while (size > 0) {
+               const size_t copy_start = check->state.sha256.size & 0x3F;
+               size_t copy_size = 64 - copy_start;
+               if (copy_size > size)
+                       copy_size = size;
+
+               memcpy(check->buffer.u8 + copy_start, buf, copy_size);
+
+               buf += copy_size;
+               size -= copy_size;
+               check->state.sha256.size += copy_size;
+
+               if ((check->state.sha256.size & 0x3F) == 0)
+                       process(check);
+       }
+
+       return;
+}
+
+
+extern void
+lzma_sha256_finish(lzma_check_state *check)
+{
+       // Add padding as described in RFC 3174 (it describes SHA-1 but
+       // the same padding style is used for SHA-256 too).
+       size_t pos = check->state.sha256.size & 0x3F;
+       check->buffer.u8[pos++] = 0x80;
+
+       while (pos != 64 - 8) {
+               if (pos == 64) {
+                       process(check);
+                       pos = 0;
+               }
+
+               check->buffer.u8[pos++] = 0x00;
+       }
+
+       // Convert the message size from bytes to bits.
+       check->state.sha256.size *= 8;
+
+       check->buffer.u64[(64 - 8) / 8] = conv64be(check->state.sha256.size);
+
+       process(check);
+
+       for (size_t i = 0; i < 8; ++i)
+               check->buffer.u32[i] = conv32be(check->state.sha256.state[i]);
+
+       return;
+}
diff --git a/lzma/common/alone_decoder.c b/lzma/common/alone_decoder.c
new file mode 100644 (file)
index 0000000..c1360ca
--- /dev/null
@@ -0,0 +1,238 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       alone_decoder.c
+/// \brief      Decoder for LZMA_Alone files
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "alone_decoder.h"
+#include "lzma_decoder.h"
+#include "lz_decoder.h"
+
+
+struct lzma_coder_s {
+       lzma_next_coder next;
+
+       enum {
+               SEQ_PROPERTIES,
+               SEQ_DICTIONARY_SIZE,
+               SEQ_UNCOMPRESSED_SIZE,
+               SEQ_CODER_INIT,
+               SEQ_CODE,
+       } sequence;
+
+       /// If true, reject files that are unlikely to be .lzma files.
+       /// If false, more non-.lzma files get accepted and will give
+       /// LZMA_DATA_ERROR either immediately or after a few output bytes.
+       bool picky;
+
+       /// Position in the header fields
+       size_t pos;
+
+       /// Uncompressed size decoded from the header
+       lzma_vli uncompressed_size;
+
+       /// Memory usage limit
+       uint64_t memlimit;
+
+       /// Amount of memory actually needed (only an estimate)
+       uint64_t memusage;
+
+       /// Options decoded from the header needed to initialize
+       /// the LZMA decoder
+       lzma_options_lzma options;
+};
+
+
+static lzma_ret
+alone_decode(lzma_coder *coder,
+               const lzma_allocator *allocator lzma_attribute((__unused__)),
+               const uint8_t *restrict in, size_t *restrict in_pos,
+               size_t in_size, uint8_t *restrict out,
+               size_t *restrict out_pos, size_t out_size,
+               lzma_action action)
+{
+       while (*out_pos < out_size
+                       && (coder->sequence == SEQ_CODE || *in_pos < in_size))
+       switch (coder->sequence) {
+       case SEQ_PROPERTIES:
+               if (lzma_lzma_lclppb_decode(&coder->options, in[*in_pos]))
+                       return LZMA_FORMAT_ERROR;
+
+               coder->sequence = SEQ_DICTIONARY_SIZE;
+               ++*in_pos;
+               break;
+
+       case SEQ_DICTIONARY_SIZE:
+               coder->options.dict_size
+                               |= (size_t)(in[*in_pos]) << (coder->pos * 8);
+
+               if (++coder->pos == 4) {
+                       if (coder->picky && coder->options.dict_size
+                                       != UINT32_MAX) {
+                               // A hack to ditch tons of false positives:
+                               // We allow only dictionary sizes that are
+                               // 2^n or 2^n + 2^(n-1). LZMA_Alone created
+                               // only files with 2^n, but accepts any
+                               // dictionary size.
+                               uint32_t d = coder->options.dict_size - 1;
+                               d |= d >> 2;
+                               d |= d >> 3;
+                               d |= d >> 4;
+                               d |= d >> 8;
+                               d |= d >> 16;
+                               ++d;
+
+                               if (d != coder->options.dict_size)
+                                       return LZMA_FORMAT_ERROR;
+                       }
+
+                       coder->pos = 0;
+                       coder->sequence = SEQ_UNCOMPRESSED_SIZE;
+               }
+
+               ++*in_pos;
+               break;
+
+       case SEQ_UNCOMPRESSED_SIZE:
+               coder->uncompressed_size
+                               |= (lzma_vli)(in[*in_pos]) << (coder->pos * 8);
+               ++*in_pos;
+               if (++coder->pos < 8)
+                       break;
+
+               // Another hack to ditch false positives: Assume that
+               // if the uncompressed size is known, it must be less
+               // than 256 GiB.
+               if (coder->picky
+                               && coder->uncompressed_size != LZMA_VLI_UNKNOWN
+                               && coder->uncompressed_size
+                                       >= (LZMA_VLI_C(1) << 38))
+                       return LZMA_FORMAT_ERROR;
+
+               // Calculate the memory usage so that it is ready
+               // for SEQ_CODER_INIT.
+               coder->memusage = lzma_lzma_decoder_memusage(&coder->options)
+                               + LZMA_MEMUSAGE_BASE;
+
+               coder->pos = 0;
+               coder->sequence = SEQ_CODER_INIT;
+
+       // Fall through
+
+       case SEQ_CODER_INIT: {
+               if (coder->memusage > coder->memlimit)
+                       return LZMA_MEMLIMIT_ERROR;
+
+               lzma_filter_info filters[2] = {
+                       {
+                               .init = &lzma_lzma_decoder_init,
+                               .options = &coder->options,
+                       }, {
+                               .init = NULL,
+                       }
+               };
+
+               const lzma_ret ret = lzma_next_filter_init(&coder->next,
+                               allocator, filters);
+               if (ret != LZMA_OK)
+                       return ret;
+
+               // Use a hack to set the uncompressed size.
+               lzma_lz_decoder_uncompressed(coder->next.coder,
+                               coder->uncompressed_size);
+
+               coder->sequence = SEQ_CODE;
+               break;
+       }
+
+       case SEQ_CODE: {
+               return coder->next.code(coder->next.coder,
+                               allocator, in, in_pos, in_size,
+                               out, out_pos, out_size, action);
+       }
+
+       default:
+               return LZMA_PROG_ERROR;
+       }
+
+       return LZMA_OK;
+}
+
+
+static void
+alone_decoder_end(lzma_coder *coder, const lzma_allocator *allocator)
+{
+       lzma_next_end(&coder->next, allocator);
+       lzma_free(coder, allocator);
+       return;
+}
+
+
+static lzma_ret
+alone_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
+               uint64_t *old_memlimit, uint64_t new_memlimit)
+{
+       *memusage = coder->memusage;
+       *old_memlimit = coder->memlimit;
+
+       if (new_memlimit != 0) {
+               if (new_memlimit < coder->memusage)
+                       return LZMA_MEMLIMIT_ERROR;
+
+               coder->memlimit = new_memlimit;
+       }
+
+       return LZMA_OK;
+}
+
+
+extern lzma_ret
+lzma_alone_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
+               uint64_t memlimit, bool picky)
+{
+       lzma_next_coder_init(&lzma_alone_decoder_init, next, allocator);
+
+       if (memlimit == 0)
+               return LZMA_PROG_ERROR;
+
+       if (next->coder == NULL) {
+               next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+               if (next->coder == NULL)
+                       return LZMA_MEM_ERROR;
+
+               next->code = &alone_decode;
+               next->end = &alone_decoder_end;
+               next->memconfig = &alone_decoder_memconfig;
+               next->coder->next = LZMA_NEXT_CODER_INIT;
+       }
+
+       next->coder->sequence = SEQ_PROPERTIES;
+       next->coder->picky = picky;
+       next->coder->pos = 0;
+       next->coder->options.dict_size = 0;
+       next->coder->options.preset_dict = NULL;
+       next->coder->options.preset_dict_size = 0;
+       next->coder->uncompressed_size = 0;
+       next->coder->memlimit = memlimit;
+       next->coder->memusage = LZMA_MEMUSAGE_BASE;
+
+       return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_alone_decoder(lzma_stream *strm, uint64_t memlimit)
+{
+       lzma_next_strm_init(lzma_alone_decoder_init, strm, memlimit, false);
+
+       strm->internal->supported_actions[LZMA_RUN] = true;
+       strm->internal->supported_actions[LZMA_FINISH] = true;
+
+       return LZMA_OK;
+}
diff --git a/lzma/common/alone_decoder.h b/lzma/common/alone_decoder.h
new file mode 100644 (file)
index 0000000..dfa031a
--- /dev/null
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       alone_decoder.h
+/// \brief      Decoder for LZMA_Alone files
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_ALONE_DECODER_H
+#define LZMA_ALONE_DECODER_H
+
+#include "common.h"
+
+
+extern lzma_ret lzma_alone_decoder_init(
+               lzma_next_coder *next, const lzma_allocator *allocator,
+               uint64_t memlimit, bool picky);
+
+#endif
diff --git a/lzma/common/alone_encoder.c b/lzma/common/alone_encoder.c
new file mode 100644 (file)
index 0000000..a2bc9ee
--- /dev/null
@@ -0,0 +1,157 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       alone_decoder.c
+/// \brief      Decoder for LZMA_Alone files
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+#include "lzma_encoder.h"
+
+
+#define ALONE_HEADER_SIZE (1 + 4 + 8)
+
+
+struct lzma_coder_s {
+       lzma_next_coder next;
+
+       enum {
+               SEQ_HEADER,
+               SEQ_CODE,
+       } sequence;
+
+       size_t header_pos;
+       uint8_t header[ALONE_HEADER_SIZE];
+};
+
+
+static lzma_ret
+alone_encode(lzma_coder *coder,
+               const lzma_allocator *allocator lzma_attribute((__unused__)),
+               const uint8_t *restrict in, size_t *restrict in_pos,
+               size_t in_size, uint8_t *restrict out,
+               size_t *restrict out_pos, size_t out_size,
+               lzma_action action)
+{
+       while (*out_pos < out_size)
+       switch (coder->sequence) {
+       case SEQ_HEADER:
+               lzma_bufcpy(coder->header, &coder->header_pos,
+                               ALONE_HEADER_SIZE,
+                               out, out_pos, out_size);
+               if (coder->header_pos < ALONE_HEADER_SIZE)
+                       return LZMA_OK;
+
+               coder->sequence = SEQ_CODE;
+               break;
+
+       case SEQ_CODE:
+               return coder->next.code(coder->next.coder,
+                               allocator, in, in_pos, in_size,
+                               out, out_pos, out_size, action);
+
+       default:
+               assert(0);
+               return LZMA_PROG_ERROR;
+       }
+
+       return LZMA_OK;
+}
+
+
+static void
+alone_encoder_end(lzma_coder *coder, const lzma_allocator *allocator)
+{
+       lzma_next_end(&coder->next, allocator);
+       lzma_free(coder, allocator);
+       return;
+}
+
+
+// At least for now, this is not used by any internal function.
+static lzma_ret
+alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
+               const lzma_options_lzma *options)
+{
+       lzma_next_coder_init(&alone_encoder_init, next, allocator);
+
+       if (next->coder == NULL) {
+               next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+               if (next->coder == NULL)
+                       return LZMA_MEM_ERROR;
+
+               next->code = &alone_encode;
+               next->end = &alone_encoder_end;
+               next->coder->next = LZMA_NEXT_CODER_INIT;
+       }
+
+       // Basic initializations
+       next->coder->sequence = SEQ_HEADER;
+       next->coder->header_pos = 0;
+
+       // Encode the header:
+       // - Properties (1 byte)
+       if (lzma_lzma_lclppb_encode(options, next->coder->header))
+               return LZMA_OPTIONS_ERROR;
+
+       // - Dictionary size (4 bytes)
+       if (options->dict_size < LZMA_DICT_SIZE_MIN)
+               return LZMA_OPTIONS_ERROR;
+
+       // Round up to the next 2^n or 2^n + 2^(n - 1) depending on which
+       // one is the next unless it is UINT32_MAX. While the header would
+       // allow any 32-bit integer, we do this to keep the decoder of liblzma
+       // accepting the resulting files.
+       uint32_t d = options->dict_size - 1;
+       d |= d >> 2;
+       d |= d >> 3;
+       d |= d >> 4;
+       d |= d >> 8;
+       d |= d >> 16;
+       if (d != UINT32_MAX)
+               ++d;
+
+       unaligned_write32le(next->coder->header + 1, d);
+
+       // - Uncompressed size (always unknown and using EOPM)
+       memset(next->coder->header + 1 + 4, 0xFF, 8);
+
+       // Initialize the LZMA encoder.
+       const lzma_filter_info filters[2] = {
+               {
+                       .init = &lzma_lzma_encoder_init,
+                       .options = (void *)(options),
+               }, {
+                       .init = NULL,
+               }
+       };
+
+       return lzma_next_filter_init(&next->coder->next, allocator, filters);
+}
+
+
+/*
+extern lzma_ret
+lzma_alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
+               const lzma_options_alone *options)
+{
+       lzma_next_coder_init(&alone_encoder_init, next, allocator, options);
+}
+*/
+
+
+extern LZMA_API(lzma_ret)
+lzma_alone_encoder(lzma_stream *strm, const lzma_options_lzma *options)
+{
+       lzma_next_strm_init(alone_encoder_init, strm, options);
+
+       strm->internal->supported_actions[LZMA_RUN] = true;
+       strm->internal->supported_actions[LZMA_FINISH] = true;
+
+       return LZMA_OK;
+}
diff --git a/lzma/common/auto_decoder.c b/lzma/common/auto_decoder.c
new file mode 100644 (file)
index 0000000..bf35507
--- /dev/null
@@ -0,0 +1,186 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       auto_decoder.c
+/// \brief      Autodetect between .xz Stream and .lzma (LZMA_Alone) formats
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "stream_decoder.h"
+#include "alone_decoder.h"
+
+
+struct lzma_coder_s {
+       /// Stream decoder or LZMA_Alone decoder
+       lzma_next_coder next;
+
+       uint64_t memlimit;
+       uint32_t flags;
+
+       enum {
+               SEQ_INIT,
+               SEQ_CODE,
+               SEQ_FINISH,
+       } sequence;
+};
+
+
+static lzma_ret
+auto_decode(lzma_coder *coder, const lzma_allocator *allocator,
+               const uint8_t *restrict in, size_t *restrict in_pos,
+               size_t in_size, uint8_t *restrict out,
+               size_t *restrict out_pos, size_t out_size, lzma_action action)
+{
+       switch (coder->sequence) {
+       case SEQ_INIT:
+               if (*in_pos >= in_size)
+                       return LZMA_OK;
+
+               // Update the sequence now, because we want to continue from
+               // SEQ_CODE even if we return some LZMA_*_CHECK.
+               coder->sequence = SEQ_CODE;
+
+               // Detect the file format. For now this is simple, since if
+               // it doesn't start with 0xFD (the first magic byte of the
+               // new format), it has to be LZMA_Alone, or something that
+               // we don't support at all.
+               if (in[*in_pos] == 0xFD) {
+                       return_if_error(lzma_stream_decoder_init(
+                                       &coder->next, allocator,
+                                       coder->memlimit, coder->flags));
+               } else {
+                       return_if_error(lzma_alone_decoder_init(&coder->next,
+                                       allocator, coder->memlimit, true));
+
+                       // If the application wants to know about missing
+                       // integrity check or about the check in general, we
+                       // need to handle it here, because LZMA_Alone decoder
+                       // doesn't accept any flags.
+                       if (coder->flags & LZMA_TELL_NO_CHECK)
+                               return LZMA_NO_CHECK;
+
+                       if (coder->flags & LZMA_TELL_ANY_CHECK)
+                               return LZMA_GET_CHECK;
+               }
+
+       // Fall through
+
+       case SEQ_CODE: {
+               const lzma_ret ret = coder->next.code(
+                               coder->next.coder, allocator,
+                               in, in_pos, in_size,
+                               out, out_pos, out_size, action);
+               if (ret != LZMA_STREAM_END
+                               || (coder->flags & LZMA_CONCATENATED) == 0)
+                       return ret;
+
+               coder->sequence = SEQ_FINISH;
+       }
+
+       // Fall through
+
+       case SEQ_FINISH:
+               // When LZMA_DECODE_CONCATENATED was used and we were decoding
+               // LZMA_Alone file, we need to check check that there is no
+               // trailing garbage and wait for LZMA_FINISH.
+               if (*in_pos < in_size)
+                       return LZMA_DATA_ERROR;
+
+               return action == LZMA_FINISH ? LZMA_STREAM_END : LZMA_OK;
+
+       default:
+               assert(0);
+               return LZMA_PROG_ERROR;
+       }
+}
+
+
+static void
+auto_decoder_end(lzma_coder *coder, const lzma_allocator *allocator)
+{
+       lzma_next_end(&coder->next, allocator);
+       lzma_free(coder, allocator);
+       return;
+}
+
+
+static lzma_check
+auto_decoder_get_check(const lzma_coder *coder)
+{
+       // It is LZMA_Alone if get_check is NULL.
+       return coder->next.get_check == NULL ? LZMA_CHECK_NONE
+                       : coder->next.get_check(coder->next.coder);
+}
+
+
+static lzma_ret
+auto_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
+               uint64_t *old_memlimit, uint64_t new_memlimit)
+{
+       lzma_ret ret;
+
+       if (coder->next.memconfig != NULL) {
+               ret = coder->next.memconfig(coder->next.coder,
+                               memusage, old_memlimit, new_memlimit);
+               assert(*old_memlimit == coder->memlimit);
+       } else {
+               // No coder is configured yet. Use the base value as
+               // the current memory usage.
+               *memusage = LZMA_MEMUSAGE_BASE;
+               *old_memlimit = coder->memlimit;
+               ret = LZMA_OK;
+       }
+
+       if (ret == LZMA_OK && new_memlimit != 0)
+               coder->memlimit = new_memlimit;
+
+       return ret;
+}
+
+
+static lzma_ret
+auto_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
+               uint64_t memlimit, uint32_t flags)
+{
+       lzma_next_coder_init(&auto_decoder_init, next, allocator);
+
+       if (memlimit == 0)
+               return LZMA_PROG_ERROR;
+
+       if (flags & ~LZMA_SUPPORTED_FLAGS)
+               return LZMA_OPTIONS_ERROR;
+
+       if (next->coder == NULL) {
+               next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+               if (next->coder == NULL)
+                       return LZMA_MEM_ERROR;
+
+               next->code = &auto_decode;
+               next->end = &auto_decoder_end;
+               next->get_check = &auto_decoder_get_check;
+               next->memconfig = &auto_decoder_memconfig;
+               next->coder->next = LZMA_NEXT_CODER_INIT;
+       }
+
+       next->coder->memlimit = memlimit;
+       next->coder->flags = flags;
+       next->coder->sequence = SEQ_INIT;
+
+       return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_auto_decoder(lzma_stream *strm, uint64_t memlimit, uint32_t flags)
+{
+       lzma_next_strm_init(auto_decoder_init, strm, memlimit, flags);
+
+       strm->internal->supported_actions[LZMA_RUN] = true;
+       strm->internal->supported_actions[LZMA_FINISH] = true;
+
+       return LZMA_OK;
+}
diff --git a/lzma/common/block_buffer_decoder.c b/lzma/common/block_buffer_decoder.c
new file mode 100644 (file)
index 0000000..b0ded90
--- /dev/null
@@ -0,0 +1,80 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       block_buffer_decoder.c
+/// \brief      Single-call .xz Block decoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "block_decoder.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_block_buffer_decode(lzma_block *block, const lzma_allocator *allocator,
+               const uint8_t *in, size_t *in_pos, size_t in_size,
+               uint8_t *out, size_t *out_pos, size_t out_size)
+{
+       if (in_pos == NULL || (in == NULL && *in_pos != in_size)
+                       || *in_pos > in_size || out_pos == NULL
+                       || (out == NULL && *out_pos != out_size)
+                       || *out_pos > out_size)
+               return LZMA_PROG_ERROR;
+
+       // Initialize the Block decoder.
+       lzma_next_coder block_decoder = LZMA_NEXT_CODER_INIT;
+       lzma_ret ret = lzma_block_decoder_init(
+                       &block_decoder, allocator, block);
+
+       if (ret == LZMA_OK) {
+               // Save the positions so that we can restore them in case
+               // an error occurs.
+               const size_t in_start = *in_pos;
+               const size_t out_start = *out_pos;
+
+               // Do the actual decoding.
+               ret = block_decoder.code(block_decoder.coder, allocator,
+                               in, in_pos, in_size, out, out_pos, out_size,
+                               LZMA_FINISH);
+
+               if (ret == LZMA_STREAM_END) {
+                       ret = LZMA_OK;
+               } else {
+                       if (ret == LZMA_OK) {
+                               // Either the input was truncated or the
+                               // output buffer was too small.
+                               assert(*in_pos == in_size
+                                               || *out_pos == out_size);
+
+                               // If all the input was consumed, then the
+                               // input is truncated, even if the output
+                               // buffer is also full. This is because
+                               // processing the last byte of the Block
+                               // never produces output.
+                               //
+                               // NOTE: This assumption may break when new
+                               // filters are added, if the end marker of
+                               // the filter doesn't consume at least one
+                               // complete byte.
+                               if (*in_pos == in_size)
+                                       ret = LZMA_DATA_ERROR;
+                               else
+                                       ret = LZMA_BUF_ERROR;
+                       }
+
+                       // Restore the positions.
+                       *in_pos = in_start;
+                       *out_pos = out_start;
+               }
+       }
+
+       // Free the decoder memory. This needs to be done even if
+       // initialization fails, because the internal API doesn't
+       // require the initialization function to free its memory on error.
+       lzma_next_end(&block_decoder, allocator);
+
+       return ret;
+}
diff --git a/lzma/common/block_buffer_encoder.c b/lzma/common/block_buffer_encoder.c
new file mode 100644 (file)
index 0000000..39e263a
--- /dev/null
@@ -0,0 +1,337 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       block_buffer_encoder.c
+/// \brief      Single-call .xz Block encoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "block_buffer_encoder.h"
+#include "block_encoder.h"
+#include "filter_encoder.h"
+#include "lzma2_encoder.h"
+#include "check.h"
+
+
+/// Estimate the maximum size of the Block Header and Check fields for
+/// a Block that uses LZMA2 uncompressed chunks. We could use
+/// lzma_block_header_size() but this is simpler.
+///
+/// Block Header Size + Block Flags + Compressed Size
+/// + Uncompressed Size + Filter Flags for LZMA2 + CRC32 + Check
+/// and round up to the next multiple of four to take Header Padding
+/// into account.
+#define HEADERS_BOUND ((1 + 1 + 2 * LZMA_VLI_BYTES_MAX + 3 + 4 \
+               + LZMA_CHECK_SIZE_MAX + 3) & ~3)
+
+
+static uint64_t
+lzma2_bound(uint64_t uncompressed_size)
+{
+       // Prevent integer overflow in overhead calculation.
+       if (uncompressed_size > COMPRESSED_SIZE_MAX)
+               return 0;
+
+       // Calculate the exact overhead of the LZMA2 headers: Round
+       // uncompressed_size up to the next multiple of LZMA2_CHUNK_MAX,
+       // multiply by the size of per-chunk header, and add one byte for
+       // the end marker.
+       const uint64_t overhead = ((uncompressed_size + LZMA2_CHUNK_MAX - 1)
+                               / LZMA2_CHUNK_MAX)
+                       * LZMA2_HEADER_UNCOMPRESSED + 1;
+
+       // Catch the possible integer overflow.
+       if (COMPRESSED_SIZE_MAX - overhead < uncompressed_size)
+               return 0;
+
+       return uncompressed_size + overhead;
+}
+
+
+extern uint64_t
+lzma_block_buffer_bound64(uint64_t uncompressed_size)
+{
+       // If the data doesn't compress, we always use uncompressed
+       // LZMA2 chunks.
+       uint64_t lzma2_size = lzma2_bound(uncompressed_size);
+       if (lzma2_size == 0)
+               return 0;
+
+       // Take Block Padding into account.
+       lzma2_size = (lzma2_size + 3) & ~UINT64_C(3);
+
+       // No risk of integer overflow because lzma2_bound() already takes
+       // into account the size of the headers in the Block.
+       return HEADERS_BOUND + lzma2_size;
+}
+
+
+extern LZMA_API(size_t)
+lzma_block_buffer_bound(size_t uncompressed_size)
+{
+       uint64_t ret = lzma_block_buffer_bound64(uncompressed_size);
+
+#if SIZE_MAX < UINT64_MAX
+       // Catch the possible integer overflow on 32-bit systems.
+       if (ret > SIZE_MAX)
+               return 0;
+#endif
+
+       return ret;
+}
+
+
+static lzma_ret
+block_encode_uncompressed(lzma_block *block, const uint8_t *in, size_t in_size,
+               uint8_t *out, size_t *out_pos, size_t out_size)
+{
+       // Use LZMA2 uncompressed chunks. We wouldn't need a dictionary at
+       // all, but LZMA2 always requires a dictionary, so use the minimum
+       // value to minimize memory usage of the decoder.
+       lzma_options_lzma lzma2 = {
+               .dict_size = LZMA_DICT_SIZE_MIN,
+       };
+
+       lzma_filter filters[2];
+       filters[0].id = LZMA_FILTER_LZMA2;
+       filters[0].options = &lzma2;
+       filters[1].id = LZMA_VLI_UNKNOWN;
+
+       // Set the above filter options to *block temporarily so that we can
+       // encode the Block Header.
+       lzma_filter *filters_orig = block->filters;
+       block->filters = filters;
+
+       if (lzma_block_header_size(block) != LZMA_OK) {
+               block->filters = filters_orig;
+               return LZMA_PROG_ERROR;
+       }
+
+       // Check that there's enough output space. The caller has already
+       // set block->compressed_size to what lzma2_bound() has returned,
+       // so we can reuse that value. We know that compressed_size is a
+       // known valid VLI and header_size is a small value so their sum
+       // will never overflow.
+       assert(block->compressed_size == lzma2_bound(in_size));
+       if (out_size - *out_pos
+                       < block->header_size + block->compressed_size) {
+               block->filters = filters_orig;
+               return LZMA_BUF_ERROR;
+       }
+
+       if (lzma_block_header_encode(block, out + *out_pos) != LZMA_OK) {
+               block->filters = filters_orig;
+               return LZMA_PROG_ERROR;
+       }
+
+       block->filters = filters_orig;
+       *out_pos += block->header_size;
+
+       // Encode the data using LZMA2 uncompressed chunks.
+       size_t in_pos = 0;
+       uint8_t control = 0x01; // Dictionary reset
+
+       while (in_pos < in_size) {
+               // Control byte: Indicate uncompressed chunk, of which
+               // the first resets the dictionary.
+               out[(*out_pos)++] = control;
+               control = 0x02; // No dictionary reset
+
+               // Size of the uncompressed chunk
+               const size_t copy_size
+                               = my_min(in_size - in_pos, LZMA2_CHUNK_MAX);
+               out[(*out_pos)++] = (copy_size - 1) >> 8;
+               out[(*out_pos)++] = (copy_size - 1) & 0xFF;
+
+               // The actual data
+               assert(*out_pos + copy_size <= out_size);
+               memcpy(out + *out_pos, in + in_pos, copy_size);
+
+               in_pos += copy_size;
+               *out_pos += copy_size;
+       }
+
+       // End marker
+       out[(*out_pos)++] = 0x00;
+       assert(*out_pos <= out_size);
+
+       return LZMA_OK;
+}
+
+
+static lzma_ret
+block_encode_normal(lzma_block *block, const lzma_allocator *allocator,
+               const uint8_t *in, size_t in_size,
+               uint8_t *out, size_t *out_pos, size_t out_size)
+{
+       // Find out the size of the Block Header.
+       return_if_error(lzma_block_header_size(block));
+
+       // Reserve space for the Block Header and skip it for now.
+       if (out_size - *out_pos <= block->header_size)
+               return LZMA_BUF_ERROR;
+
+       const size_t out_start = *out_pos;
+       *out_pos += block->header_size;
+
+       // Limit out_size so that we stop encoding if the output would grow
+       // bigger than what uncompressed Block would be.
+       if (out_size - *out_pos > block->compressed_size)
+               out_size = *out_pos + block->compressed_size;
+
+       // TODO: In many common cases this could be optimized to use
+       // significantly less memory.
+       lzma_next_coder raw_encoder = LZMA_NEXT_CODER_INIT;
+       lzma_ret ret = lzma_raw_encoder_init(
+                       &raw_encoder, allocator, block->filters);
+
+       if (ret == LZMA_OK) {
+               size_t in_pos = 0;
+               ret = raw_encoder.code(raw_encoder.coder, allocator,
+                               in, &in_pos, in_size, out, out_pos, out_size,
+                               LZMA_FINISH);
+       }
+
+       // NOTE: This needs to be run even if lzma_raw_encoder_init() failed.
+       lzma_next_end(&raw_encoder, allocator);
+
+       if (ret == LZMA_STREAM_END) {
+               // Compression was successful. Write the Block Header.
+               block->compressed_size
+                               = *out_pos - (out_start + block->header_size);
+               ret = lzma_block_header_encode(block, out + out_start);
+               if (ret != LZMA_OK)
+                       ret = LZMA_PROG_ERROR;
+
+       } else if (ret == LZMA_OK) {
+               // Output buffer became full.
+               ret = LZMA_BUF_ERROR;
+       }
+
+       // Reset *out_pos if something went wrong.
+       if (ret != LZMA_OK)
+               *out_pos = out_start;
+
+       return ret;
+}
+
+
+static lzma_ret
+block_buffer_encode(lzma_block *block, const lzma_allocator *allocator,
+               const uint8_t *in, size_t in_size,
+               uint8_t *out, size_t *out_pos, size_t out_size,
+               bool try_to_compress)
+{
+       // Validate the arguments.
+       if (block == NULL || (in == NULL && in_size != 0) || out == NULL
+                       || out_pos == NULL || *out_pos > out_size)
+               return LZMA_PROG_ERROR;
+
+       // The contents of the structure may depend on the version so
+       // check the version before validating the contents of *block.
+       if (block->version > 1)
+               return LZMA_OPTIONS_ERROR;
+
+       if ((unsigned int)(block->check) > LZMA_CHECK_ID_MAX
+                       || (try_to_compress && block->filters == NULL))
+               return LZMA_PROG_ERROR;
+
+       if (!lzma_check_is_supported(block->check))
+               return LZMA_UNSUPPORTED_CHECK;
+
+       // Size of a Block has to be a multiple of four, so limit the size
+       // here already. This way we don't need to check it again when adding
+       // Block Padding.
+       out_size -= (out_size - *out_pos) & 3;
+
+       // Get the size of the Check field.
+       const size_t check_size = lzma_check_size(block->check);
+       assert(check_size != UINT32_MAX);
+
+       // Reserve space for the Check field.
+       if (out_size - *out_pos <= check_size)
+               return LZMA_BUF_ERROR;
+
+       out_size -= check_size;
+
+       // Initialize block->uncompressed_size and calculate the worst-case
+       // value for block->compressed_size.
+       block->uncompressed_size = in_size;
+       block->compressed_size = lzma2_bound(in_size);
+       if (block->compressed_size == 0)
+               return LZMA_DATA_ERROR;
+
+       // Do the actual compression.
+       lzma_ret ret = LZMA_BUF_ERROR;
+       if (try_to_compress)
+               ret = block_encode_normal(block, allocator,
+                               in, in_size, out, out_pos, out_size);
+
+       if (ret != LZMA_OK) {
+               // If the error was something else than output buffer
+               // becoming full, return the error now.
+               if (ret != LZMA_BUF_ERROR)
+                       return ret;
+
+               // The data was uncompressible (at least with the options
+               // given to us) or the output buffer was too small. Use the
+               // uncompressed chunks of LZMA2 to wrap the data into a valid
+               // Block. If we haven't been given enough output space, even
+               // this may fail.
+               return_if_error(block_encode_uncompressed(block, in, in_size,
+                               out, out_pos, out_size));
+       }
+
+       assert(*out_pos <= out_size);
+
+       // Block Padding. No buffer overflow here, because we already adjusted
+       // out_size so that (out_size - out_start) is a multiple of four.
+       // Thus, if the buffer is full, the loop body can never run.
+       for (size_t i = (size_t)(block->compressed_size); i & 3; ++i) {
+               assert(*out_pos < out_size);
+               out[(*out_pos)++] = 0x00;
+       }
+
+       // If there's no Check field, we are done now.
+       if (check_size > 0) {
+               // Calculate the integrity check. We reserved space for
+               // the Check field earlier so we don't need to check for
+               // available output space here.
+               lzma_check_state check;
+               lzma_check_init(&check, block->check);
+               lzma_check_update(&check, block->check, in, in_size);
+               lzma_check_finish(&check, block->check);
+
+               memcpy(block->raw_check, check.buffer.u8, check_size);
+               memcpy(out + *out_pos, check.buffer.u8, check_size);
+               *out_pos += check_size;
+       }
+
+       return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_block_buffer_encode(lzma_block *block, const lzma_allocator *allocator,
+               const uint8_t *in, size_t in_size,
+               uint8_t *out, size_t *out_pos, size_t out_size)
+{
+       return block_buffer_encode(block, allocator,
+                       in, in_size, out, out_pos, out_size, true);
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_block_uncomp_encode(lzma_block *block,
+               const uint8_t *in, size_t in_size,
+               uint8_t *out, size_t *out_pos, size_t out_size)
+{
+       // It won't allocate any memory from heap so no need
+       // for lzma_allocator.
+       return block_buffer_encode(block, NULL,
+                       in, in_size, out, out_pos, out_size, false);
+}
diff --git a/lzma/common/block_buffer_encoder.h b/lzma/common/block_buffer_encoder.h
new file mode 100644 (file)
index 0000000..653207f
--- /dev/null
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       block_buffer_encoder.h
+/// \brief      Single-call .xz Block encoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_BLOCK_BUFFER_ENCODER_H
+#define LZMA_BLOCK_BUFFER_ENCODER_H
+
+#include "common.h"
+
+
+/// uint64_t version of lzma_block_buffer_bound(). It is used by
+/// stream_encoder_mt.c. Probably the original lzma_block_buffer_bound()
+/// should have been 64-bit, but fixing it would break the ABI.
+extern uint64_t lzma_block_buffer_bound64(uint64_t uncompressed_size);
+
+#endif
diff --git a/lzma/common/block_decoder.c b/lzma/common/block_decoder.c
new file mode 100644 (file)
index 0000000..685c3b0
--- /dev/null
@@ -0,0 +1,252 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       block_decoder.c
+/// \brief      Decodes .xz Blocks
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "block_decoder.h"
+#include "filter_decoder.h"
+#include "check.h"
+
+
+struct lzma_coder_s {
+       enum {
+               SEQ_CODE,
+               SEQ_PADDING,
+               SEQ_CHECK,
+       } sequence;
+
+       /// The filters in the chain; initialized with lzma_raw_decoder_init().
+       lzma_next_coder next;
+
+       /// Decoding options; we also write Compressed Size and Uncompressed
+       /// Size back to this structure when the decoding has been finished.
+       lzma_block *block;
+
+       /// Compressed Size calculated while decoding
+       lzma_vli compressed_size;
+
+       /// Uncompressed Size calculated while decoding
+       lzma_vli uncompressed_size;
+
+       /// Maximum allowed Compressed Size; this takes into account the
+       /// size of the Block Header and Check fields when Compressed Size
+       /// is unknown.
+       lzma_vli compressed_limit;
+
+       /// Position when reading the Check field
+       size_t check_pos;
+
+       /// Check of the uncompressed data
+       lzma_check_state check;
+
+       /// True if the integrity check won't be calculated and verified.
+       bool ignore_check;
+};
+
+
+static inline bool
+update_size(lzma_vli *size, lzma_vli add, lzma_vli limit)
+{
+       if (limit > LZMA_VLI_MAX)
+               limit = LZMA_VLI_MAX;
+
+       if (limit < *size || limit - *size < add)
+               return true;
+
+       *size += add;
+
+       return false;
+}
+
+
+static inline bool
+is_size_valid(lzma_vli size, lzma_vli reference)
+{
+       return reference == LZMA_VLI_UNKNOWN || reference == size;
+}
+
+
+static lzma_ret
+block_decode(lzma_coder *coder, const lzma_allocator *allocator,
+               const uint8_t *restrict in, size_t *restrict in_pos,
+               size_t in_size, uint8_t *restrict out,
+               size_t *restrict out_pos, size_t out_size, lzma_action action)
+{
+       switch (coder->sequence) {
+       case SEQ_CODE: {
+               const size_t in_start = *in_pos;
+               const size_t out_start = *out_pos;
+
+               const lzma_ret ret = coder->next.code(coder->next.coder,
+                               allocator, in, in_pos, in_size,
+                               out, out_pos, out_size, action);
+
+               const size_t in_used = *in_pos - in_start;
+               const size_t out_used = *out_pos - out_start;
+
+               // NOTE: We compare to compressed_limit here, which prevents
+               // the total size of the Block growing past LZMA_VLI_MAX.
+               if (update_size(&coder->compressed_size, in_used,
+                                       coder->compressed_limit)
+                               || update_size(&coder->uncompressed_size,
+                                       out_used,
+                                       coder->block->uncompressed_size))
+                       return LZMA_DATA_ERROR;
+
+               if (!coder->ignore_check)
+                       lzma_check_update(&coder->check, coder->block->check,
+                                       out + out_start, out_used);
+
+               if (ret != LZMA_STREAM_END)
+                       return ret;
+
+               // Compressed and Uncompressed Sizes are now at their final
+               // values. Verify that they match the values given to us.
+               if (!is_size_valid(coder->compressed_size,
+                                       coder->block->compressed_size)
+                               || !is_size_valid(coder->uncompressed_size,
+                                       coder->block->uncompressed_size))
+                       return LZMA_DATA_ERROR;
+
+               // Copy the values into coder->block. The caller
+               // may use this information to construct Index.
+               coder->block->compressed_size = coder->compressed_size;
+               coder->block->uncompressed_size = coder->uncompressed_size;
+
+               coder->sequence = SEQ_PADDING;
+       }
+
+       // Fall through
+
+       case SEQ_PADDING:
+               // Compressed Data is padded to a multiple of four bytes.
+               while (coder->compressed_size & 3) {
+                       if (*in_pos >= in_size)
+                               return LZMA_OK;
+
+                       // We use compressed_size here just get the Padding
+                       // right. The actual Compressed Size was stored to
+                       // coder->block already, and won't be modified by
+                       // us anymore.
+                       ++coder->compressed_size;
+
+                       if (in[(*in_pos)++] != 0x00)
+                               return LZMA_DATA_ERROR;
+               }
+
+               if (coder->block->check == LZMA_CHECK_NONE)
+                       return LZMA_STREAM_END;
+
+               if (!coder->ignore_check)
+                       lzma_check_finish(&coder->check, coder->block->check);
+
+               coder->sequence = SEQ_CHECK;
+
+       // Fall through
+
+       case SEQ_CHECK: {
+               const size_t check_size = lzma_check_size(coder->block->check);
+               lzma_bufcpy(in, in_pos, in_size, coder->block->raw_check,
+                               &coder->check_pos, check_size);
+               if (coder->check_pos < check_size)
+                       return LZMA_OK;
+
+               // Validate the Check only if we support it.
+               // coder->check.buffer may be uninitialized
+               // when the Check ID is not supported.
+               if (!coder->ignore_check
+                               && lzma_check_is_supported(coder->block->check)
+                               && memcmp(coder->block->raw_check,
+                                       coder->check.buffer.u8,
+                                       check_size) != 0)
+                       return LZMA_DATA_ERROR;
+
+               return LZMA_STREAM_END;
+       }
+       }
+
+       return LZMA_PROG_ERROR;
+}
+
+
+static void
+block_decoder_end(lzma_coder *coder, const lzma_allocator *allocator)
+{
+       lzma_next_end(&coder->next, allocator);
+       lzma_free(coder, allocator);
+       return;
+}
+
+
+extern lzma_ret
+lzma_block_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
+               lzma_block *block)
+{
+       lzma_next_coder_init(&lzma_block_decoder_init, next, allocator);
+
+       // Validate the options. lzma_block_unpadded_size() does that for us
+       // except for Uncompressed Size and filters. Filters are validated
+       // by the raw decoder.
+       if (lzma_block_unpadded_size(block) == 0
+                       || !lzma_vli_is_valid(block->uncompressed_size))
+               return LZMA_PROG_ERROR;
+
+       // Allocate and initialize *next->coder if needed.
+       if (next->coder == NULL) {
+               next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+               if (next->coder == NULL)
+                       return LZMA_MEM_ERROR;
+
+               next->code = &block_decode;
+               next->end = &block_decoder_end;
+               next->coder->next = LZMA_NEXT_CODER_INIT;
+       }
+
+       // Basic initializations
+       next->coder->sequence = SEQ_CODE;
+       next->coder->block = block;
+       next->coder->compressed_size = 0;
+       next->coder->uncompressed_size = 0;
+
+       // If Compressed Size is not known, we calculate the maximum allowed
+       // value so that encoded size of the Block (including Block Padding)
+       // is still a valid VLI and a multiple of four.
+       next->coder->compressed_limit
+                       = block->compressed_size == LZMA_VLI_UNKNOWN
+                               ? (LZMA_VLI_MAX & ~LZMA_VLI_C(3))
+                                       - block->header_size
+                                       - lzma_check_size(block->check)
+                               : block->compressed_size;
+
+       // Initialize the check. It's caller's problem if the Check ID is not
+       // supported, and the Block decoder cannot verify the Check field.
+       // Caller can test lzma_check_is_supported(block->check).
+       next->coder->check_pos = 0;
+       lzma_check_init(&next->coder->check, block->check);
+
+       next->coder->ignore_check = block->version >= 1
+                       ? block->ignore_check : false;
+
+       // Initialize the filter chain.
+       return lzma_raw_decoder_init(&next->coder->next, allocator,
+                       block->filters);
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_block_decoder(lzma_stream *strm, lzma_block *block)
+{
+       lzma_next_strm_init(lzma_block_decoder_init, strm, block);
+
+       strm->internal->supported_actions[LZMA_RUN] = true;
+       strm->internal->supported_actions[LZMA_FINISH] = true;
+
+       return LZMA_OK;
+}
diff --git a/lzma/common/block_decoder.h b/lzma/common/block_decoder.h
new file mode 100644 (file)
index 0000000..718c5ce
--- /dev/null
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       block_decoder.h
+/// \brief      Decodes .xz Blocks
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_BLOCK_DECODER_H
+#define LZMA_BLOCK_DECODER_H
+
+#include "common.h"
+
+
+extern lzma_ret lzma_block_decoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator, lzma_block *block);
+
+#endif
diff --git a/lzma/common/block_encoder.c b/lzma/common/block_encoder.c
new file mode 100644 (file)
index 0000000..def5864
--- /dev/null
@@ -0,0 +1,217 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       block_encoder.c
+/// \brief      Encodes .xz Blocks
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "block_encoder.h"
+#include "filter_encoder.h"
+#include "check.h"
+
+
+struct lzma_coder_s {
+       /// The filters in the chain; initialized with lzma_raw_decoder_init().
+       lzma_next_coder next;
+
+       /// Encoding options; we also write Unpadded Size, Compressed Size,
+       /// and Uncompressed Size back to this structure when the encoding
+       /// has been finished.
+       lzma_block *block;
+
+       enum {
+               SEQ_CODE,
+               SEQ_PADDING,
+               SEQ_CHECK,
+       } sequence;
+
+       /// Compressed Size calculated while encoding
+       lzma_vli compressed_size;
+
+       /// Uncompressed Size calculated while encoding
+       lzma_vli uncompressed_size;
+
+       /// Position in the Check field
+       size_t pos;
+
+       /// Check of the uncompressed data
+       lzma_check_state check;
+};
+
+
+static lzma_ret
+block_encode(lzma_coder *coder, const lzma_allocator *allocator,
+               const uint8_t *restrict in, size_t *restrict in_pos,
+               size_t in_size, uint8_t *restrict out,
+               size_t *restrict out_pos, size_t out_size, lzma_action action)
+{
+       // Check that our amount of input stays in proper limits.
+       if (LZMA_VLI_MAX - coder->uncompressed_size < in_size - *in_pos)
+               return LZMA_DATA_ERROR;
+
+       switch (coder->sequence) {
+       case SEQ_CODE: {
+               const size_t in_start = *in_pos;
+               const size_t out_start = *out_pos;
+
+               const lzma_ret ret = coder->next.code(coder->next.coder,
+                               allocator, in, in_pos, in_size,
+                               out, out_pos, out_size, action);
+
+               const size_t in_used = *in_pos - in_start;
+               const size_t out_used = *out_pos - out_start;
+
+               if (COMPRESSED_SIZE_MAX - coder->compressed_size < out_used)
+                       return LZMA_DATA_ERROR;
+
+               coder->compressed_size += out_used;
+
+               // No need to check for overflow because we have already
+               // checked it at the beginning of this function.
+               coder->uncompressed_size += in_used;
+
+               lzma_check_update(&coder->check, coder->block->check,
+                               in + in_start, in_used);
+
+               if (ret != LZMA_STREAM_END || action == LZMA_SYNC_FLUSH)
+                       return ret;
+
+               assert(*in_pos == in_size);
+               assert(action == LZMA_FINISH);
+
+               // Copy the values into coder->block. The caller
+               // may use this information to construct Index.
+               coder->block->compressed_size = coder->compressed_size;
+               coder->block->uncompressed_size = coder->uncompressed_size;
+
+               coder->sequence = SEQ_PADDING;
+       }
+
+       // Fall through
+
+       case SEQ_PADDING:
+               // Pad Compressed Data to a multiple of four bytes. We can
+               // use coder->compressed_size for this since we don't need
+               // it for anything else anymore.
+               while (coder->compressed_size & 3) {
+                       if (*out_pos >= out_size)
+                               return LZMA_OK;
+
+                       out[*out_pos] = 0x00;
+                       ++*out_pos;
+                       ++coder->compressed_size;
+               }
+
+               if (coder->block->check == LZMA_CHECK_NONE)
+                       return LZMA_STREAM_END;
+
+               lzma_check_finish(&coder->check, coder->block->check);
+
+               coder->sequence = SEQ_CHECK;
+
+       // Fall through
+
+       case SEQ_CHECK: {
+               const size_t check_size = lzma_check_size(coder->block->check);
+               lzma_bufcpy(coder->check.buffer.u8, &coder->pos, check_size,
+                               out, out_pos, out_size);
+               if (coder->pos < check_size)
+                       return LZMA_OK;
+
+               memcpy(coder->block->raw_check, coder->check.buffer.u8,
+                               check_size);
+               return LZMA_STREAM_END;
+       }
+       }
+
+       return LZMA_PROG_ERROR;
+}
+
+
+static void
+block_encoder_end(lzma_coder *coder, const lzma_allocator *allocator)
+{
+       lzma_next_end(&coder->next, allocator);
+       lzma_free(coder, allocator);
+       return;
+}
+
+
+static lzma_ret
+block_encoder_update(lzma_coder *coder, const lzma_allocator *allocator,
+               const lzma_filter *filters lzma_attribute((__unused__)),
+               const lzma_filter *reversed_filters)
+{
+       if (coder->sequence != SEQ_CODE)
+               return LZMA_PROG_ERROR;
+
+       return lzma_next_filter_update(
+                       &coder->next, allocator, reversed_filters);
+}
+
+
+extern lzma_ret
+lzma_block_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
+               lzma_block *block)
+{
+       lzma_next_coder_init(&lzma_block_encoder_init, next, allocator);
+
+       if (block == NULL)
+               return LZMA_PROG_ERROR;
+
+       // The contents of the structure may depend on the version so
+       // check the version first.
+       if (block->version > 1)
+               return LZMA_OPTIONS_ERROR;
+
+       // If the Check ID is not supported, we cannot calculate the check and
+       // thus not create a proper Block.
+       if ((unsigned int)(block->check) > LZMA_CHECK_ID_MAX)
+               return LZMA_PROG_ERROR;
+
+       if (!lzma_check_is_supported(block->check))
+               return LZMA_UNSUPPORTED_CHECK;
+
+       // Allocate and initialize *next->coder if needed.
+       if (next->coder == NULL) {
+               next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+               if (next->coder == NULL)
+                       return LZMA_MEM_ERROR;
+
+               next->code = &block_encode;
+               next->end = &block_encoder_end;
+               next->update = &block_encoder_update;
+               next->coder->next = LZMA_NEXT_CODER_INIT;
+       }
+
+       // Basic initializations
+       next->coder->sequence = SEQ_CODE;
+       next->coder->block = block;
+       next->coder->compressed_size = 0;
+       next->coder->uncompressed_size = 0;
+       next->coder->pos = 0;
+
+       // Initialize the check
+       lzma_check_init(&next->coder->check, block->check);
+
+       // Initialize the requested filters.
+       return lzma_raw_encoder_init(&next->coder->next, allocator,
+                       block->filters);
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_block_encoder(lzma_stream *strm, lzma_block *block)
+{
+       lzma_next_strm_init(lzma_block_encoder_init, strm, block);
+
+       strm->internal->supported_actions[LZMA_RUN] = true;
+       strm->internal->supported_actions[LZMA_FINISH] = true;
+
+       return LZMA_OK;
+}
diff --git a/lzma/common/block_encoder.h b/lzma/common/block_encoder.h
new file mode 100644 (file)
index 0000000..bd97c18
--- /dev/null
@@ -0,0 +1,47 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       block_encoder.h
+/// \brief      Encodes .xz Blocks
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_BLOCK_ENCODER_H
+#define LZMA_BLOCK_ENCODER_H
+
+#include "common.h"
+
+
+/// \brief      Biggest Compressed Size value that the Block encoder supports
+///
+/// The maximum size of a single Block is limited by the maximum size of
+/// a Stream, which in theory is 2^63 - 3 bytes (i.e. LZMA_VLI_MAX - 3).
+/// While the size is really big and no one should hit it in practice, we
+/// take it into account in some places anyway to catch some errors e.g. if
+/// application passes insanely big value to some function.
+///
+/// We could take into account the headers etc. to determine the exact
+/// maximum size of the Compressed Data field, but the complexity would give
+/// us nothing useful. Instead, limit the size of Compressed Data so that
+/// even with biggest possible Block Header and Check fields the total
+/// encoded size of the Block stays as a valid VLI. This doesn't guarantee
+/// that the size of the Stream doesn't grow too big, but that problem is
+/// taken care outside the Block handling code.
+///
+/// ~LZMA_VLI_C(3) is to guarantee that if we need padding at the end of
+/// the Compressed Data field, it will still stay in the proper limit.
+///
+/// This constant is in this file because it is needed in both
+/// block_encoder.c and block_buffer_encoder.c.
+#define COMPRESSED_SIZE_MAX ((LZMA_VLI_MAX - LZMA_BLOCK_HEADER_SIZE_MAX \
+               - LZMA_CHECK_SIZE_MAX) & ~LZMA_VLI_C(3))
+
+
+extern lzma_ret lzma_block_encoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator, lzma_block *block);
+
+#endif
diff --git a/lzma/common/block_header_decoder.c b/lzma/common/block_header_decoder.c
new file mode 100644 (file)
index 0000000..1dd982f
--- /dev/null
@@ -0,0 +1,124 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       block_header_decoder.c
+/// \brief      Decodes Block Header from .xz files
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+#include "check.h"
+
+
+static void
+free_properties(lzma_block *block, const lzma_allocator *allocator)
+{
+       // Free allocated filter options. The last array member is not
+       // touched after the initialization in the beginning of
+       // lzma_block_header_decode(), so we don't need to touch that here.
+       for (size_t i = 0; i < LZMA_FILTERS_MAX; ++i) {
+               lzma_free(block->filters[i].options, allocator);
+               block->filters[i].id = LZMA_VLI_UNKNOWN;
+               block->filters[i].options = NULL;
+       }
+
+       return;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_block_header_decode(lzma_block *block,
+               const lzma_allocator *allocator, const uint8_t *in)
+{
+       // NOTE: We consider the header to be corrupt not only when the
+       // CRC32 doesn't match, but also when variable-length integers
+       // are invalid or over 63 bits, or if the header is too small
+       // to contain the claimed information.
+
+       // Initialize the filter options array. This way the caller can
+       // safely free() the options even if an error occurs in this function.
+       for (size_t i = 0; i <= LZMA_FILTERS_MAX; ++i) {
+               block->filters[i].id = LZMA_VLI_UNKNOWN;
+               block->filters[i].options = NULL;
+       }
+
+       // Versions 0 and 1 are supported. If a newer version was specified,
+       // we need to downgrade it.
+       if (block->version > 1)
+               block->version = 1;
+
+       // This isn't a Block Header option, but since the decompressor will
+       // read it if version >= 1, it's better to initialize it here than
+       // to expect the caller to do it since in almost all cases this
+       // should be false.
+       block->ignore_check = false;
+
+       // Validate Block Header Size and Check type. The caller must have
+       // already set these, so it is a programming error if this test fails.
+       if (lzma_block_header_size_decode(in[0]) != block->header_size
+                       || (unsigned int)(block->check) > LZMA_CHECK_ID_MAX)
+               return LZMA_PROG_ERROR;
+
+       // Exclude the CRC32 field.
+       const size_t in_size = block->header_size - 4;
+
+       // Verify CRC32
+       if (lzma_crc32(in, in_size, 0) != unaligned_read32le(in + in_size))
+               return LZMA_DATA_ERROR;
+
+       // Check for unsupported flags.
+       if (in[1] & 0x3C)
+               return LZMA_OPTIONS_ERROR;
+
+       // Start after the Block Header Size and Block Flags fields.
+       size_t in_pos = 2;
+
+       // Compressed Size
+       if (in[1] & 0x40) {
+               return_if_error(lzma_vli_decode(&block->compressed_size,
+                               NULL, in, &in_pos, in_size));
+
+               // Validate Compressed Size. This checks that it isn't zero
+               // and that the total size of the Block is a valid VLI.
+               if (lzma_block_unpadded_size(block) == 0)
+                       return LZMA_DATA_ERROR;
+       } else {
+               block->compressed_size = LZMA_VLI_UNKNOWN;
+       }
+
+       // Uncompressed Size
+       if (in[1] & 0x80)
+               return_if_error(lzma_vli_decode(&block->uncompressed_size,
+                               NULL, in, &in_pos, in_size));
+       else
+               block->uncompressed_size = LZMA_VLI_UNKNOWN;
+
+       // Filter Flags
+       const size_t filter_count = (in[1] & 3) + 1;
+       for (size_t i = 0; i < filter_count; ++i) {
+               const lzma_ret ret = lzma_filter_flags_decode(
+                               &block->filters[i], allocator,
+                               in, &in_pos, in_size);
+               if (ret != LZMA_OK) {
+                       free_properties(block, allocator);
+                       return ret;
+               }
+       }
+
+       // Padding
+       while (in_pos < in_size) {
+               if (in[in_pos++] != 0x00) {
+                       free_properties(block, allocator);
+
+                       // Possibly some new field present so use
+                       // LZMA_OPTIONS_ERROR instead of LZMA_DATA_ERROR.
+                       return LZMA_OPTIONS_ERROR;
+               }
+       }
+
+       return LZMA_OK;
+}
diff --git a/lzma/common/block_header_encoder.c b/lzma/common/block_header_encoder.c
new file mode 100644 (file)
index 0000000..5c5f542
--- /dev/null
@@ -0,0 +1,132 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       block_header_encoder.c
+/// \brief      Encodes Block Header for .xz files
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+#include "check.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_block_header_size(lzma_block *block)
+{
+       if (block->version > 1)
+               return LZMA_OPTIONS_ERROR;
+
+       // Block Header Size + Block Flags + CRC32.
+       uint32_t size = 1 + 1 + 4;
+
+       // Compressed Size
+       if (block->compressed_size != LZMA_VLI_UNKNOWN) {
+               const uint32_t add = lzma_vli_size(block->compressed_size);
+               if (add == 0 || block->compressed_size == 0)
+                       return LZMA_PROG_ERROR;
+
+               size += add;
+       }
+
+       // Uncompressed Size
+       if (block->uncompressed_size != LZMA_VLI_UNKNOWN) {
+               const uint32_t add = lzma_vli_size(block->uncompressed_size);
+               if (add == 0)
+                       return LZMA_PROG_ERROR;
+
+               size += add;
+       }
+
+       // List of Filter Flags
+       if (block->filters == NULL || block->filters[0].id == LZMA_VLI_UNKNOWN)
+               return LZMA_PROG_ERROR;
+
+       for (size_t i = 0; block->filters[i].id != LZMA_VLI_UNKNOWN; ++i) {
+               // Don't allow too many filters.
+               if (i == LZMA_FILTERS_MAX)
+                       return LZMA_PROG_ERROR;
+
+               uint32_t add;
+               return_if_error(lzma_filter_flags_size(&add,
+                               block->filters + i));
+
+               size += add;
+       }
+
+       // Pad to a multiple of four bytes.
+       block->header_size = (size + 3) & ~UINT32_C(3);
+
+       // NOTE: We don't verify that the encoded size of the Block stays
+       // within limits. This is because it is possible that we are called
+       // with exaggerated Compressed Size (e.g. LZMA_VLI_MAX) to reserve
+       // space for Block Header, and later called again with lower,
+       // real values.
+
+       return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_block_header_encode(const lzma_block *block, uint8_t *out)
+{
+       // Validate everything but filters.
+       if (lzma_block_unpadded_size(block) == 0
+                       || !lzma_vli_is_valid(block->uncompressed_size))
+               return LZMA_PROG_ERROR;
+
+       // Indicate the size of the buffer _excluding_ the CRC32 field.
+       const size_t out_size = block->header_size - 4;
+
+       // Store the Block Header Size.
+       out[0] = out_size / 4;
+
+       // We write Block Flags in pieces.
+       out[1] = 0x00;
+       size_t out_pos = 2;
+
+       // Compressed Size
+       if (block->compressed_size != LZMA_VLI_UNKNOWN) {
+               return_if_error(lzma_vli_encode(block->compressed_size, NULL,
+                               out, &out_pos, out_size));
+
+               out[1] |= 0x40;
+       }
+
+       // Uncompressed Size
+       if (block->uncompressed_size != LZMA_VLI_UNKNOWN) {
+               return_if_error(lzma_vli_encode(block->uncompressed_size, NULL,
+                               out, &out_pos, out_size));
+
+               out[1] |= 0x80;
+       }
+
+       // Filter Flags
+       if (block->filters == NULL || block->filters[0].id == LZMA_VLI_UNKNOWN)
+               return LZMA_PROG_ERROR;
+
+       size_t filter_count = 0;
+       do {
+               // There can be a maximum of four filters.
+               if (filter_count == LZMA_FILTERS_MAX)
+                       return LZMA_PROG_ERROR;
+
+               return_if_error(lzma_filter_flags_encode(
+                               block->filters + filter_count,
+                               out, &out_pos, out_size));
+
+       } while (block->filters[++filter_count].id != LZMA_VLI_UNKNOWN);
+
+       out[1] |= filter_count - 1;
+
+       // Padding
+       memzero(out + out_pos, out_size - out_pos);
+
+       // CRC32
+       unaligned_write32le(out + out_size, lzma_crc32(out, out_size, 0));
+
+       return LZMA_OK;
+}
diff --git a/lzma/common/block_util.c b/lzma/common/block_util.c
new file mode 100644 (file)
index 0000000..00c7fe8
--- /dev/null
@@ -0,0 +1,90 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       block_header.c
+/// \brief      Utility functions to handle lzma_block
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+#include "index.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_block_compressed_size(lzma_block *block, lzma_vli unpadded_size)
+{
+       // Validate everything but Uncompressed Size and filters.
+       if (lzma_block_unpadded_size(block) == 0)
+               return LZMA_PROG_ERROR;
+
+       const uint32_t container_size = block->header_size
+                       + lzma_check_size(block->check);
+
+       // Validate that Compressed Size will be greater than zero.
+       if (unpadded_size <= container_size)
+               return LZMA_DATA_ERROR;
+
+       // Calculate what Compressed Size is supposed to be.
+       // If Compressed Size was present in Block Header,
+       // compare that the new value matches it.
+       const lzma_vli compressed_size = unpadded_size - container_size;
+       if (block->compressed_size != LZMA_VLI_UNKNOWN
+                       && block->compressed_size != compressed_size)
+               return LZMA_DATA_ERROR;
+
+       block->compressed_size = compressed_size;
+
+       return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_vli)
+lzma_block_unpadded_size(const lzma_block *block)
+{
+       // Validate the values that we are interested in i.e. all but
+       // Uncompressed Size and the filters.
+       //
+       // NOTE: This function is used for validation too, so it is
+       // essential that these checks are always done even if
+       // Compressed Size is unknown.
+       if (block == NULL || block->version > 1
+                       || block->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
+                       || block->header_size > LZMA_BLOCK_HEADER_SIZE_MAX
+                       || (block->header_size & 3)
+                       || !lzma_vli_is_valid(block->compressed_size)
+                       || block->compressed_size == 0
+                       || (unsigned int)(block->check) > LZMA_CHECK_ID_MAX)
+               return 0;
+
+       // If Compressed Size is unknown, return that we cannot know
+       // size of the Block either.
+       if (block->compressed_size == LZMA_VLI_UNKNOWN)
+               return LZMA_VLI_UNKNOWN;
+
+       // Calculate Unpadded Size and validate it.
+       const lzma_vli unpadded_size = block->compressed_size
+                               + block->header_size
+                               + lzma_check_size(block->check);
+
+       assert(unpadded_size >= UNPADDED_SIZE_MIN);
+       if (unpadded_size > UNPADDED_SIZE_MAX)
+               return 0;
+
+       return unpadded_size;
+}
+
+
+extern LZMA_API(lzma_vli)
+lzma_block_total_size(const lzma_block *block)
+{
+       lzma_vli unpadded_size = lzma_block_unpadded_size(block);
+
+       if (unpadded_size != LZMA_VLI_UNKNOWN)
+               unpadded_size = vli_ceil4(unpadded_size);
+
+       return unpadded_size;
+}
diff --git a/lzma/common/common.c b/lzma/common/common.c
new file mode 100644 (file)
index 0000000..28aa2b7
--- /dev/null
@@ -0,0 +1,443 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       common.h
+/// \brief      Common functions needed in many places in liblzma
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+
+/////////////
+// Version //
+/////////////
+
+extern LZMA_API(uint32_t)
+lzma_version_number(void)
+{
+       return LZMA_VERSION;
+}
+
+
+extern LZMA_API(const char *)
+lzma_version_string(void)
+{
+       return LZMA_VERSION_STRING;
+}
+
+
+///////////////////////
+// Memory allocation //
+///////////////////////
+
+extern void * lzma_attribute((__malloc__)) lzma_attr_alloc_size(1)
+lzma_alloc(size_t size, const 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_attribute((__malloc__)) lzma_attr_alloc_size(1)
+lzma_alloc_zero(size_t size, const lzma_allocator *allocator)
+{
+       // Some calloc() 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);
+               if (ptr != NULL)
+                       memzero(ptr, size);
+       } else {
+               ptr = calloc(1, size);
+       }
+
+       return ptr;
+}
+
+
+extern void
+lzma_free(void *ptr, const 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 = my_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, const lzma_allocator *allocator,
+               const lzma_filter_info *filters)
+{
+       lzma_next_coder_init(filters[0].init, next, allocator);
+       next->id = filters[0].id;
+       return filters[0].init == NULL
+                       ? LZMA_OK : filters[0].init(next, allocator, filters);
+}
+
+
+extern lzma_ret
+lzma_next_filter_update(lzma_next_coder *next, const lzma_allocator *allocator,
+               const lzma_filter *reversed_filters)
+{
+       // Check that the application isn't trying to change the Filter ID.
+       // End of filters is indicated with LZMA_VLI_UNKNOWN in both
+       // reversed_filters[0].id and next->id.
+       if (reversed_filters[0].id != next->id)
+               return LZMA_PROG_ERROR;
+
+       if (reversed_filters[0].id == LZMA_VLI_UNKNOWN)
+               return LZMA_OK;
+
+       assert(next->update != NULL);
+       return next->update(next->coder, allocator, NULL, reversed_filters);
+}
+
+
+extern void
+lzma_next_end(lzma_next_coder *next, const lzma_allocator *allocator)
+{
+       if (next->init != (uintptr_t)(NULL)) {
+               // To avoid tiny end functions that simply call
+               // lzma_free(coder, allocator), we allow leaving next->end
+               // NULL and call lzma_free() here.
+               if (next->end != NULL)
+                       next->end(next->coder, allocator);
+               else
+                       lzma_free(next->coder, allocator);
+
+               // Reset the variables so the we don't accidentally think
+               // that it is an already initialized coder.
+               *next = LZMA_NEXT_CODER_INIT;
+       }
+
+       return;
+}
+
+
+//////////////////////////////////////
+// External to internal API wrapper //
+//////////////////////////////////////
+
+extern lzma_ret
+lzma_strm_init(lzma_stream *strm)
+{
+       if (strm == NULL)
+               return LZMA_PROG_ERROR;
+
+       if (strm->internal == NULL) {
+               strm->internal = lzma_alloc(sizeof(lzma_internal),
+                               strm->allocator);
+               if (strm->internal == NULL)
+                       return LZMA_MEM_ERROR;
+
+               strm->internal->next = LZMA_NEXT_CODER_INIT;
+       }
+
+       memzero(strm->internal->supported_actions,
+                       sizeof(strm->internal->supported_actions));
+       strm->internal->sequence = ISEQ_RUN;
+       strm->internal->allow_buf_error = false;
+
+       strm->total_in = 0;
+       strm->total_out = 0;
+
+       return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_code(lzma_stream *strm, lzma_action action)
+{
+       // Sanity checks
+       if ((strm->next_in == NULL && strm->avail_in != 0)
+                       || (strm->next_out == NULL && strm->avail_out != 0)
+                       || strm->internal == NULL
+                       || strm->internal->next.code == NULL
+                       || (unsigned int)(action) > LZMA_ACTION_MAX
+                       || !strm->internal->supported_actions[action])
+               return LZMA_PROG_ERROR;
+
+       // Check if unsupported members have been set to non-zero or non-NULL,
+       // which would indicate that some new feature is wanted.
+       if (strm->reserved_ptr1 != NULL
+                       || strm->reserved_ptr2 != NULL
+                       || strm->reserved_ptr3 != NULL
+                       || strm->reserved_ptr4 != NULL
+                       || strm->reserved_int1 != 0
+                       || strm->reserved_int2 != 0
+                       || strm->reserved_int3 != 0
+                       || strm->reserved_int4 != 0
+                       || strm->reserved_enum1 != LZMA_RESERVED_ENUM
+                       || strm->reserved_enum2 != LZMA_RESERVED_ENUM)
+               return LZMA_OPTIONS_ERROR;
+
+       switch (strm->internal->sequence) {
+       case ISEQ_RUN:
+               switch (action) {
+               case LZMA_RUN:
+                       break;
+
+               case LZMA_SYNC_FLUSH:
+                       strm->internal->sequence = ISEQ_SYNC_FLUSH;
+                       break;
+
+               case LZMA_FULL_FLUSH:
+                       strm->internal->sequence = ISEQ_FULL_FLUSH;
+                       break;
+
+               case LZMA_FINISH:
+                       strm->internal->sequence = ISEQ_FINISH;
+                       break;
+
+               case LZMA_FULL_BARRIER:
+                       strm->internal->sequence = ISEQ_FULL_BARRIER;
+                       break;
+               }
+
+               break;
+
+       case ISEQ_SYNC_FLUSH:
+               // The same action must be used until we return
+               // LZMA_STREAM_END, and the amount of input must not change.
+               if (action != LZMA_SYNC_FLUSH
+                               || strm->internal->avail_in != strm->avail_in)
+                       return LZMA_PROG_ERROR;
+
+               break;
+
+       case ISEQ_FULL_FLUSH:
+               if (action != LZMA_FULL_FLUSH
+                               || strm->internal->avail_in != strm->avail_in)
+                       return LZMA_PROG_ERROR;
+
+               break;
+
+       case ISEQ_FINISH:
+               if (action != LZMA_FINISH
+                               || strm->internal->avail_in != strm->avail_in)
+                       return LZMA_PROG_ERROR;
+
+               break;
+
+       case ISEQ_FULL_BARRIER:
+               if (action != LZMA_FULL_BARRIER
+                               || strm->internal->avail_in != strm->avail_in)
+                       return LZMA_PROG_ERROR;
+
+               break;
+
+       case ISEQ_END:
+               return LZMA_STREAM_END;
+
+       case ISEQ_ERROR:
+       default:
+               return LZMA_PROG_ERROR;
+       }
+
+       size_t in_pos = 0;
+       size_t out_pos = 0;
+       lzma_ret ret = strm->internal->next.code(
+                       strm->internal->next.coder, strm->allocator,
+                       strm->next_in, &in_pos, strm->avail_in,
+                       strm->next_out, &out_pos, strm->avail_out, action);
+
+       strm->next_in += in_pos;
+       strm->avail_in -= in_pos;
+       strm->total_in += in_pos;
+
+       strm->next_out += out_pos;
+       strm->avail_out -= out_pos;
+       strm->total_out += out_pos;
+
+       strm->internal->avail_in = strm->avail_in;
+
+       // Cast is needed to silence a warning about LZMA_TIMED_OUT, which
+       // isn't part of lzma_ret enumeration.
+       switch ((unsigned int)(ret)) {
+       case LZMA_OK:
+               // Don't return LZMA_BUF_ERROR when it happens the first time.
+               // This is to avoid returning LZMA_BUF_ERROR when avail_out
+               // was zero but still there was no more data left to written
+               // to next_out.
+               if (out_pos == 0 && in_pos == 0) {
+                       if (strm->internal->allow_buf_error)
+                               ret = LZMA_BUF_ERROR;
+                       else
+                               strm->internal->allow_buf_error = true;
+               } else {
+                       strm->internal->allow_buf_error = false;
+               }
+               break;
+
+       case LZMA_TIMED_OUT:
+               strm->internal->allow_buf_error = false;
+               ret = LZMA_OK;
+               break;
+
+       case LZMA_STREAM_END:
+               if (strm->internal->sequence == ISEQ_SYNC_FLUSH
+                               || strm->internal->sequence == ISEQ_FULL_FLUSH
+                               || strm->internal->sequence
+                                       == ISEQ_FULL_BARRIER)
+                       strm->internal->sequence = ISEQ_RUN;
+               else
+                       strm->internal->sequence = ISEQ_END;
+
+       // Fall through
+
+       case LZMA_NO_CHECK:
+       case LZMA_UNSUPPORTED_CHECK:
+       case LZMA_GET_CHECK:
+       case LZMA_MEMLIMIT_ERROR:
+               // Something else than LZMA_OK, but not a fatal error,
+               // that is, coding may be continued (except if ISEQ_END).
+               strm->internal->allow_buf_error = false;
+               break;
+
+       default:
+               // All the other errors are fatal; coding cannot be continued.
+               assert(ret != LZMA_BUF_ERROR);
+               strm->internal->sequence = ISEQ_ERROR;
+               break;
+       }
+
+       return ret;
+}
+
+
+extern LZMA_API(void)
+lzma_end(lzma_stream *strm)
+{
+       if (strm != NULL && strm->internal != NULL) {
+               lzma_next_end(&strm->internal->next, strm->allocator);
+               lzma_free(strm->internal, strm->allocator);
+               strm->internal = NULL;
+       }
+
+       return;
+}
+
+
+extern LZMA_API(void)
+lzma_get_progress(lzma_stream *strm,
+               uint64_t *progress_in, uint64_t *progress_out)
+{
+       if (strm->internal->next.get_progress != NULL) {
+               strm->internal->next.get_progress(strm->internal->next.coder,
+                               progress_in, progress_out);
+       } else {
+               *progress_in = strm->total_in;
+               *progress_out = strm->total_out;
+       }
+
+       return;
+}
+
+
+extern LZMA_API(lzma_check)
+lzma_get_check(const lzma_stream *strm)
+{
+       // Return LZMA_CHECK_NONE if we cannot know the check type.
+       // It's a bug in the application if this happens.
+       if (strm->internal->next.get_check == NULL)
+               return LZMA_CHECK_NONE;
+
+       return strm->internal->next.get_check(strm->internal->next.coder);
+}
+
+
+extern LZMA_API(uint64_t)
+lzma_memusage(const lzma_stream *strm)
+{
+       uint64_t memusage;
+       uint64_t old_memlimit;
+
+       if (strm == NULL || strm->internal == NULL
+                       || strm->internal->next.memconfig == NULL
+                       || strm->internal->next.memconfig(
+                               strm->internal->next.coder,
+                               &memusage, &old_memlimit, 0) != LZMA_OK)
+               return 0;
+
+       return memusage;
+}
+
+
+extern LZMA_API(uint64_t)
+lzma_memlimit_get(const lzma_stream *strm)
+{
+       uint64_t old_memlimit;
+       uint64_t memusage;
+
+       if (strm == NULL || strm->internal == NULL
+                       || strm->internal->next.memconfig == NULL
+                       || strm->internal->next.memconfig(
+                               strm->internal->next.coder,
+                               &memusage, &old_memlimit, 0) != LZMA_OK)
+               return 0;
+
+       return old_memlimit;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_memlimit_set(lzma_stream *strm, uint64_t new_memlimit)
+{
+       // Dummy variables to simplify memconfig functions
+       uint64_t old_memlimit;
+       uint64_t memusage;
+
+       if (strm == NULL || strm->internal == NULL
+                       || strm->internal->next.memconfig == NULL)
+               return LZMA_PROG_ERROR;
+
+       if (new_memlimit != 0 && new_memlimit < LZMA_MEMUSAGE_BASE)
+               return LZMA_MEMLIMIT_ERROR;
+
+       return strm->internal->next.memconfig(strm->internal->next.coder,
+                       &memusage, &old_memlimit, new_memlimit);
+}
diff --git a/lzma/common/common.h b/lzma/common/common.h
new file mode 100644 (file)
index 0000000..955d784
--- /dev/null
@@ -0,0 +1,318 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       common.h
+/// \brief      Definitions common to the whole liblzma library
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_COMMON_H
+#define LZMA_COMMON_H
+
+#include "sysdefs.h"
+#include "mythread.h"
+#include "tuklib_integer.h"
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+#      ifdef DLL_EXPORT
+#              define LZMA_API_EXPORT __declspec(dllexport)
+#      else
+#              define LZMA_API_EXPORT
+#      endif
+// Don't use ifdef or defined() below.
+#elif HAVE_VISIBILITY
+#      define LZMA_API_EXPORT __attribute__((__visibility__("default")))
+#else
+#      define LZMA_API_EXPORT
+#endif
+
+#define LZMA_API(type) LZMA_API_EXPORT type LZMA_API_CALL
+
+#include "lzma.h"
+
+// These allow helping the compiler in some often-executed branches, whose
+// result is almost always the same.
+#ifdef __GNUC__
+#      define likely(expr) __builtin_expect(expr, true)
+#      define unlikely(expr) __builtin_expect(expr, false)
+#else
+#      define likely(expr) (expr)
+#      define unlikely(expr) (expr)
+#endif
+
+
+/// Size of temporary buffers needed in some filters
+#define LZMA_BUFFER_SIZE 4096
+
+
+/// Maximum number of worker threads within one multithreaded component.
+/// The limit exists solely to make it simpler to prevent integer overflows
+/// when allocating structures etc. This should be big enough for now...
+/// the code won't scale anywhere close to this number anyway.
+#define LZMA_THREADS_MAX 16384
+
+
+/// Starting value for memory usage estimates. Instead of calculating size
+/// of _every_ structure and taking into account malloc() overhead etc., we
+/// add a base size to all memory usage estimates. It's not very accurate
+/// but should be easily good enough.
+#define LZMA_MEMUSAGE_BASE (UINT64_C(1) << 15)
+
+/// Start of internal Filter ID space. These IDs must never be used
+/// in Streams.
+#define LZMA_FILTER_RESERVED_START (LZMA_VLI_C(1) << 62)
+
+
+/// Supported flags that can be passed to lzma_stream_decoder()
+/// or lzma_auto_decoder().
+#define LZMA_SUPPORTED_FLAGS \
+       ( LZMA_TELL_NO_CHECK \
+       | LZMA_TELL_UNSUPPORTED_CHECK \
+       | LZMA_TELL_ANY_CHECK \
+       | LZMA_IGNORE_CHECK \
+       | LZMA_CONCATENATED )
+
+
+/// Largest valid lzma_action value as unsigned integer.
+#define LZMA_ACTION_MAX ((unsigned int)(LZMA_FULL_BARRIER))
+
+
+/// Special return value (lzma_ret) to indicate that a timeout was reached
+/// and lzma_code() must not return LZMA_BUF_ERROR. This is converted to
+/// LZMA_OK in lzma_code(). This is not in the lzma_ret enumeration because
+/// there's no need to have it in the public API.
+#define LZMA_TIMED_OUT 32
+
+
+/// Type of encoder/decoder specific data; the actual structure is defined
+/// differently in different coders.
+typedef struct lzma_coder_s lzma_coder;
+
+typedef struct lzma_next_coder_s lzma_next_coder;
+
+typedef struct lzma_filter_info_s lzma_filter_info;
+
+
+/// Type of a function used to initialize a filter encoder or decoder
+typedef lzma_ret (*lzma_init_function)(
+               lzma_next_coder *next, const lzma_allocator *allocator,
+               const lzma_filter_info *filters);
+
+/// Type of a function to do some kind of coding work (filters, Stream,
+/// Block encoders/decoders etc.). Some special coders use don't use both
+/// input and output buffers, but for simplicity they still use this same
+/// function prototype.
+typedef lzma_ret (*lzma_code_function)(
+               lzma_coder *coder, const lzma_allocator *allocator,
+               const uint8_t *restrict in, size_t *restrict in_pos,
+               size_t in_size, uint8_t *restrict out,
+               size_t *restrict out_pos, size_t out_size,
+               lzma_action action);
+
+/// Type of a function to free the memory allocated for the coder
+typedef void (*lzma_end_function)(
+               lzma_coder *coder, const lzma_allocator *allocator);
+
+
+/// Raw coder validates and converts an array of lzma_filter structures to
+/// an array of lzma_filter_info structures. This array is used with
+/// lzma_next_filter_init to initialize the filter chain.
+struct lzma_filter_info_s {
+       /// Filter ID. This is used only by the encoder
+       /// with lzma_filters_update().
+       lzma_vli id;
+
+       /// Pointer to function used to initialize the filter.
+       /// This is NULL to indicate end of array.
+       lzma_init_function init;
+
+       /// Pointer to filter's options structure
+       void *options;
+};
+
+
+/// Hold data and function pointers of the next filter in the chain.
+struct lzma_next_coder_s {
+       /// Pointer to coder-specific data
+       lzma_coder *coder;
+
+       /// Filter ID. This is LZMA_VLI_UNKNOWN when this structure doesn't
+       /// point to a filter coder.
+       lzma_vli id;
+
+       /// "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 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 a function to get progress information. If this is NULL,
+       /// lzma_stream.total_in and .total_out are used instead.
+       void (*get_progress)(lzma_coder *coder,
+                       uint64_t *progress_in, uint64_t *progress_out);
+
+       /// Pointer to function to return the type of the integrity check.
+       /// Most coders won't support this.
+       lzma_check (*get_check)(const lzma_coder *coder);
+
+       /// Pointer to function to get and/or change the memory usage limit.
+       /// If new_memlimit == 0, the limit is not changed.
+       lzma_ret (*memconfig)(lzma_coder *coder, uint64_t *memusage,
+                       uint64_t *old_memlimit, uint64_t new_memlimit);
+
+       /// Update the filter-specific options or the whole filter chain
+       /// in the encoder.
+       lzma_ret (*update)(lzma_coder *coder, const lzma_allocator *allocator,
+                       const lzma_filter *filters,
+                       const lzma_filter *reversed_filters);
+};
+
+
+/// Macro to initialize lzma_next_coder structure
+#define LZMA_NEXT_CODER_INIT \
+       (lzma_next_coder){ \
+               .coder = NULL, \
+               .init = (uintptr_t)(NULL), \
+               .id = LZMA_VLI_UNKNOWN, \
+               .code = NULL, \
+               .end = NULL, \
+               .get_progress = NULL, \
+               .get_check = NULL, \
+               .memconfig = NULL, \
+               .update = 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_FULL_BARRIER,
+               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[LZMA_ACTION_MAX + 1];
+
+       /// 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;
+};
+
+
+/// Allocates memory
+extern void *lzma_alloc(size_t size, const lzma_allocator *allocator)
+               lzma_attribute((__malloc__)) lzma_attr_alloc_size(1);
+
+/// Allocates memory and zeroes it (like calloc()). This can be faster
+/// than lzma_alloc() + memzero() while being backward compatible with
+/// custom allocators.
+extern void * lzma_attribute((__malloc__)) lzma_attr_alloc_size(1)
+               lzma_alloc_zero(size_t size, const lzma_allocator *allocator);
+
+/// Frees memory
+extern void lzma_free(void *ptr, const lzma_allocator *allocator);
+
+
+/// Allocates strm->internal if it is NULL, and initializes *strm and
+/// strm->internal. This function is only called via lzma_next_strm_init macro.
+extern lzma_ret lzma_strm_init(lzma_stream *strm);
+
+/// Initializes the next filter in the chain, if any. This takes care of
+/// freeing the memory of previously initialized filter if it is different
+/// than the filter being initialized now. This way the actual filter
+/// initialization functions don't need to use lzma_next_coder_init macro.
+extern lzma_ret lzma_next_filter_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters);
+
+/// Update the next filter in the chain, if any. This checks that
+/// the application is not trying to change the Filter IDs.
+extern lzma_ret lzma_next_filter_update(
+               lzma_next_coder *next, const lzma_allocator *allocator,
+               const lzma_filter *reversed_filters);
+
+/// Frees the memory allocated for next->coder either using next->end or,
+/// if next->end is NULL, using lzma_free.
+extern void lzma_next_end(lzma_next_coder *next,
+               const lzma_allocator *allocator);
+
+
+/// Copy as much data as possible from in[] to out[] and update *in_pos
+/// and *out_pos accordingly. Returns the number of bytes copied.
+extern size_t lzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos,
+               size_t in_size, uint8_t *restrict out,
+               size_t *restrict out_pos, size_t out_size);
+
+
+/// \brief      Return if expression doesn't evaluate to LZMA_OK
+///
+/// There are several situations where we want to return immediately
+/// with the value of expr if it isn't LZMA_OK. This macro shortens
+/// the code a little.
+#define return_if_error(expr) \
+do { \
+       const lzma_ret ret_ = (expr); \
+       if (ret_ != LZMA_OK) \
+               return ret_; \
+} while (0)
+
+
+/// If next isn't already initialized, free the previous coder. Then mark
+/// that next is _possibly_ initialized for the coder using this macro.
+/// "Possibly" means that if e.g. allocation of next->coder fails, the
+/// structure isn't actually initialized for this coder, but leaving
+/// next->init to func is still OK.
+#define lzma_next_coder_init(func, next, allocator) \
+do { \
+       if ((uintptr_t)(func) != (next)->init) \
+               lzma_next_end(next, allocator); \
+       (next)->init = (uintptr_t)(func); \
+} while (0)
+
+
+/// Initializes lzma_strm and calls func() to initialize strm->internal->next.
+/// (The function being called will use lzma_next_coder_init()). If
+/// initialization fails, memory that wasn't freed by func() is freed
+/// along strm->internal.
+#define lzma_next_strm_init(func, strm, ...) \
+do { \
+       return_if_error(lzma_strm_init(strm)); \
+       const lzma_ret ret_ = func(&(strm)->internal->next, \
+                       (strm)->allocator, __VA_ARGS__); \
+       if (ret_ != LZMA_OK) { \
+               lzma_end(strm); \
+               return ret_; \
+       } \
+} while (0)
+
+#endif
diff --git a/lzma/common/easy_buffer_encoder.c b/lzma/common/easy_buffer_encoder.c
new file mode 100644 (file)
index 0000000..48eb56f
--- /dev/null
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       easy_buffer_encoder.c
+/// \brief      Easy single-call .xz Stream encoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "easy_preset.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_easy_buffer_encode(uint32_t preset, lzma_check check,
+               const lzma_allocator *allocator, const uint8_t *in,
+               size_t in_size, uint8_t *out, size_t *out_pos, size_t out_size)
+{
+       lzma_options_easy opt_easy;
+       if (lzma_easy_preset(&opt_easy, preset))
+               return LZMA_OPTIONS_ERROR;
+
+       return lzma_stream_buffer_encode(opt_easy.filters, check,
+                       allocator, in, in_size, out, out_pos, out_size);
+}
diff --git a/lzma/common/easy_decoder_memusage.c b/lzma/common/easy_decoder_memusage.c
new file mode 100644 (file)
index 0000000..20bcd5b
--- /dev/null
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       easy_decoder_memusage.c
+/// \brief      Decoder memory usage calculation to match easy encoder presets
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "easy_preset.h"
+
+
+extern LZMA_API(uint64_t)
+lzma_easy_decoder_memusage(uint32_t preset)
+{
+       lzma_options_easy opt_easy;
+       if (lzma_easy_preset(&opt_easy, preset))
+               return UINT32_MAX;
+
+       return lzma_raw_decoder_memusage(opt_easy.filters);
+}
diff --git a/lzma/common/easy_encoder.c b/lzma/common/easy_encoder.c
new file mode 100644 (file)
index 0000000..5cb492d
--- /dev/null
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       easy_encoder.c
+/// \brief      Easy .xz Stream encoder initialization
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "easy_preset.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_easy_encoder(lzma_stream *strm, uint32_t preset, lzma_check check)
+{
+       lzma_options_easy opt_easy;
+       if (lzma_easy_preset(&opt_easy, preset))
+               return LZMA_OPTIONS_ERROR;
+
+       return lzma_stream_encoder(strm, opt_easy.filters, check);
+}
diff --git a/lzma/common/easy_encoder_memusage.c b/lzma/common/easy_encoder_memusage.c
new file mode 100644 (file)
index 0000000..e910575
--- /dev/null
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       easy_encoder_memusage.c
+/// \brief      Easy .xz Stream encoder memory usage calculation
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "easy_preset.h"
+
+
+extern LZMA_API(uint64_t)
+lzma_easy_encoder_memusage(uint32_t preset)
+{
+       lzma_options_easy opt_easy;
+       if (lzma_easy_preset(&opt_easy, preset))
+               return UINT32_MAX;
+
+       return lzma_raw_encoder_memusage(opt_easy.filters);
+}
diff --git a/lzma/common/easy_preset.c b/lzma/common/easy_preset.c
new file mode 100644 (file)
index 0000000..2f98598
--- /dev/null
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       easy_preset.c
+/// \brief      Preset handling for easy encoder and decoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "easy_preset.h"
+
+
+extern bool
+lzma_easy_preset(lzma_options_easy *opt_easy, uint32_t preset)
+{
+       if (lzma_lzma_preset(&opt_easy->opt_lzma, preset))
+               return true;
+
+       opt_easy->filters[0].id = LZMA_FILTER_LZMA2;
+       opt_easy->filters[0].options = &opt_easy->opt_lzma;
+       opt_easy->filters[1].id = LZMA_VLI_UNKNOWN;
+
+       return false;
+}
diff --git a/lzma/common/easy_preset.h b/lzma/common/easy_preset.h
new file mode 100644 (file)
index 0000000..382ade8
--- /dev/null
@@ -0,0 +1,32 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       easy_preset.h
+/// \brief      Preset handling for easy encoder and decoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+
+typedef struct {
+       /// We need to keep the filters array available in case
+       /// LZMA_FULL_FLUSH is used.
+       lzma_filter filters[LZMA_FILTERS_MAX + 1];
+
+       /// Options for LZMA2
+       lzma_options_lzma opt_lzma;
+
+       // Options for more filters can be added later, so this struct
+       // is not ready to be put into the public API.
+
+} lzma_options_easy;
+
+
+/// Set *easy to the settings given by the preset. Returns true on error,
+/// false on success.
+extern bool lzma_easy_preset(lzma_options_easy *easy, uint32_t preset);
diff --git a/lzma/common/filter_buffer_decoder.c b/lzma/common/filter_buffer_decoder.c
new file mode 100644 (file)
index 0000000..6620986
--- /dev/null
@@ -0,0 +1,88 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       filter_buffer_decoder.c
+/// \brief      Single-call raw decoding
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "filter_decoder.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_raw_buffer_decode(
+               const lzma_filter *filters, const lzma_allocator *allocator,
+               const uint8_t *in, size_t *in_pos, size_t in_size,
+               uint8_t *out, size_t *out_pos, size_t out_size)
+{
+       // Validate what isn't validated later in filter_common.c.
+       if (in == NULL || in_pos == NULL || *in_pos > in_size || out == NULL
+                       || out_pos == NULL || *out_pos > out_size)
+               return LZMA_PROG_ERROR;
+
+       // Initialize the decoer.
+       lzma_next_coder next = LZMA_NEXT_CODER_INIT;
+       return_if_error(lzma_raw_decoder_init(&next, allocator, filters));
+
+       // Store the positions so that we can restore them if something
+       // goes wrong.
+       const size_t in_start = *in_pos;
+       const size_t out_start = *out_pos;
+
+       // Do the actual decoding and free decoder's memory.
+       lzma_ret ret = next.code(next.coder, allocator, in, in_pos, in_size,
+                       out, out_pos, out_size, LZMA_FINISH);
+
+       if (ret == LZMA_STREAM_END) {
+               ret = LZMA_OK;
+       } else {
+               if (ret == LZMA_OK) {
+                       // Either the input was truncated or the
+                       // output buffer was too small.
+                       assert(*in_pos == in_size || *out_pos == out_size);
+
+                       if (*in_pos != in_size) {
+                               // Since input wasn't consumed completely,
+                               // the output buffer became full and is
+                               // too small.
+                               ret = LZMA_BUF_ERROR;
+
+                       } else if (*out_pos != out_size) {
+                               // Since output didn't became full, the input
+                               // has to be truncated.
+                               ret = LZMA_DATA_ERROR;
+
+                       } else {
+                               // All the input was consumed and output
+                               // buffer is full. Now we don't immediately
+                               // know the reason for the error. Try
+                               // decoding one more byte. If it succeeds,
+                               // then the output buffer was too small. If
+                               // we cannot get a new output byte, the input
+                               // is truncated.
+                               uint8_t tmp[1];
+                               size_t tmp_pos = 0;
+                               (void)next.code(next.coder, allocator,
+                                               in, in_pos, in_size,
+                                               tmp, &tmp_pos, 1, LZMA_FINISH);
+
+                               if (tmp_pos == 1)
+                                       ret = LZMA_BUF_ERROR;
+                               else
+                                       ret = LZMA_DATA_ERROR;
+                       }
+               }
+
+               // Restore the positions.
+               *in_pos = in_start;
+               *out_pos = out_start;
+       }
+
+       lzma_next_end(&next, allocator);
+
+       return ret;
+}
diff --git a/lzma/common/filter_buffer_encoder.c b/lzma/common/filter_buffer_encoder.c
new file mode 100644 (file)
index 0000000..dda18e3
--- /dev/null
@@ -0,0 +1,55 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       filter_buffer_encoder.c
+/// \brief      Single-call raw encoding
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "filter_encoder.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_raw_buffer_encode(
+               const lzma_filter *filters, const lzma_allocator *allocator,
+               const uint8_t *in, size_t in_size,
+               uint8_t *out, size_t *out_pos, size_t out_size)
+{
+       // Validate what isn't validated later in filter_common.c.
+       if ((in == NULL && in_size != 0) || out == NULL
+                       || out_pos == NULL || *out_pos > out_size)
+               return LZMA_PROG_ERROR;
+
+       // Initialize the encoder
+       lzma_next_coder next = LZMA_NEXT_CODER_INIT;
+       return_if_error(lzma_raw_encoder_init(&next, allocator, filters));
+
+       // Store the output position so that we can restore it if
+       // something goes wrong.
+       const size_t out_start = *out_pos;
+
+       // Do the actual encoding and free coder's memory.
+       size_t in_pos = 0;
+       lzma_ret ret = next.code(next.coder, allocator, in, &in_pos, in_size,
+                       out, out_pos, out_size, LZMA_FINISH);
+       lzma_next_end(&next, allocator);
+
+       if (ret == LZMA_STREAM_END) {
+               ret = LZMA_OK;
+       } else {
+               if (ret == LZMA_OK) {
+                       // Output buffer was too small.
+                       assert(*out_pos == out_size);
+                       ret = LZMA_BUF_ERROR;
+               }
+
+               // Restore the output position.
+               *out_pos = out_start;
+       }
+
+       return ret;
+}
diff --git a/lzma/common/filter_common.c b/lzma/common/filter_common.c
new file mode 100644 (file)
index 0000000..9ad5d5d
--- /dev/null
@@ -0,0 +1,337 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       filter_common.c
+/// \brief      Filter-specific stuff common for both encoder and decoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "filter_common.h"
+
+
+static const struct {
+       /// Filter ID
+       lzma_vli id;
+
+       /// Size of the filter-specific options structure
+       size_t options_size;
+
+       /// 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_LZMA1) || defined(HAVE_DECODER_LZMA1)
+       {
+               .id = LZMA_FILTER_LZMA1,
+               .options_size = sizeof(lzma_options_lzma),
+               .non_last_ok = false,
+               .last_ok = true,
+               .changes_size = true,
+       },
+#endif
+#if defined(HAVE_ENCODER_LZMA2) || defined(HAVE_DECODER_LZMA2)
+       {
+               .id = LZMA_FILTER_LZMA2,
+               .options_size = sizeof(lzma_options_lzma),
+               .non_last_ok = false,
+               .last_ok = true,
+               .changes_size = true,
+       },
+#endif
+#if defined(HAVE_ENCODER_X86) || defined(HAVE_DECODER_X86)
+       {
+               .id = LZMA_FILTER_X86,
+               .options_size = sizeof(lzma_options_bcj),
+               .non_last_ok = true,
+               .last_ok = false,
+               .changes_size = false,
+       },
+#endif
+#if defined(HAVE_ENCODER_POWERPC) || defined(HAVE_DECODER_POWERPC)
+       {
+               .id = LZMA_FILTER_POWERPC,
+               .options_size = sizeof(lzma_options_bcj),
+               .non_last_ok = true,
+               .last_ok = false,
+               .changes_size = false,
+       },
+#endif
+#if defined(HAVE_ENCODER_IA64) || defined(HAVE_DECODER_IA64)
+       {
+               .id = LZMA_FILTER_IA64,
+               .options_size = sizeof(lzma_options_bcj),
+               .non_last_ok = true,
+               .last_ok = false,
+               .changes_size = false,
+       },
+#endif
+#if defined(HAVE_ENCODER_ARM) || defined(HAVE_DECODER_ARM)
+       {
+               .id = LZMA_FILTER_ARM,
+               .options_size = sizeof(lzma_options_bcj),
+               .non_last_ok = true,
+               .last_ok = false,
+               .changes_size = false,
+       },
+#endif
+#if defined(HAVE_ENCODER_ARMTHUMB) || defined(HAVE_DECODER_ARMTHUMB)
+       {
+               .id = LZMA_FILTER_ARMTHUMB,
+               .options_size = sizeof(lzma_options_bcj),
+               .non_last_ok = true,
+               .last_ok = false,
+               .changes_size = false,
+       },
+#endif
+#if defined(HAVE_ENCODER_SPARC) || defined(HAVE_DECODER_SPARC)
+       {
+               .id = LZMA_FILTER_SPARC,
+               .options_size = sizeof(lzma_options_bcj),
+               .non_last_ok = true,
+               .last_ok = false,
+               .changes_size = false,
+       },
+#endif
+#if defined(HAVE_ENCODER_DELTA) || defined(HAVE_DECODER_DELTA)
+       {
+               .id = LZMA_FILTER_DELTA,
+               .options_size = sizeof(lzma_options_delta),
+               .non_last_ok = true,
+               .last_ok = false,
+               .changes_size = false,
+       },
+#endif
+       {
+               .id = LZMA_VLI_UNKNOWN
+       }
+};
+
+
+extern LZMA_API(lzma_ret)
+lzma_filters_copy(const lzma_filter *src, lzma_filter *dest,
+               const lzma_allocator *allocator)
+{
+       if (src == NULL || dest == NULL)
+               return LZMA_PROG_ERROR;
+
+       lzma_ret ret;
+       size_t i;
+       for (i = 0; src[i].id != LZMA_VLI_UNKNOWN; ++i) {
+               // There must be a maximum of four filters plus
+               // the array terminator.
+               if (i == LZMA_FILTERS_MAX) {
+                       ret = LZMA_OPTIONS_ERROR;
+                       goto error;
+               }
+
+               dest[i].id = src[i].id;
+
+               if (src[i].options == NULL) {
+                       dest[i].options = NULL;
+               } else {
+                       // See if the filter is supported only when the
+                       // options is not NULL. This might be convenient
+                       // sometimes if the app is actually copying only
+                       // a partial filter chain with a place holder ID.
+                       //
+                       // When options is not NULL, the Filter ID must be
+                       // supported by us, because otherwise we don't know
+                       // how big the options are.
+                       size_t j;
+                       for (j = 0; src[i].id != features[j].id; ++j) {
+                               if (features[j].id == LZMA_VLI_UNKNOWN) {
+                                       ret = LZMA_OPTIONS_ERROR;
+                                       goto error;
+                               }
+                       }
+
+                       // Allocate and copy the options.
+                       dest[i].options = lzma_alloc(features[j].options_size,
+                                       allocator);
+                       if (dest[i].options == NULL) {
+                               ret = LZMA_MEM_ERROR;
+                               goto error;
+                       }
+
+                       memcpy(dest[i].options, src[i].options,
+                                       features[j].options_size);
+               }
+       }
+
+       // Terminate the filter array.
+       assert(i <= LZMA_FILTERS_MAX + 1);
+       dest[i].id = LZMA_VLI_UNKNOWN;
+       dest[i].options = NULL;
+
+       return LZMA_OK;
+
+error:
+       // Free the options which we have already allocated.
+       while (i-- > 0) {
+               lzma_free(dest[i].options, allocator);
+               dest[i].options = NULL;
+       }
+
+       return ret;
+}
+
+
+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_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_UNKNOWN)
+                               return LZMA_OPTIONS_ERROR;
+
+               // If the previous filter in the chain cannot be a non-last
+               // filter, the chain is invalid.
+               if (!non_last_ok)
+                       return LZMA_OPTIONS_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_UNKNOWN);
+
+       // There must be 1-4 filters. The last filter must be usable as
+       // the last filter in the chain. A maximum of three filters are
+       // allowed to change the size of the data.
+       if (i > LZMA_FILTERS_MAX || !last_ok || changes_size_count > 3)
+               return LZMA_OPTIONS_ERROR;
+
+       *count = i;
+       return LZMA_OK;
+}
+
+
+extern lzma_ret
+lzma_raw_coder_init(lzma_next_coder *next, const 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_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_OPTIONS_ERROR;
+
+                       filters[j].id = options[i].id;
+                       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_OPTIONS_ERROR;
+
+                       filters[i].id = options[i].id;
+                       filters[i].init = fc->init;
+                       filters[i].options = options[i].options;
+               }
+       }
+
+       // Terminate the array.
+       filters[count].id = LZMA_VLI_UNKNOWN;
+       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_raw_coder_memusage(lzma_filter_find coder_find,
+               const lzma_filter *filters)
+{
+       // The chain has to have at least one filter.
+       {
+               size_t tmp;
+               if (validate_chain(filters, &tmp) != LZMA_OK)
+                       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 and validate the options. Such
+                       // filters need only little memory, so we use 1 KiB
+                       // as a good estimate. They also accept all possible
+                       // options, so there's no need to worry about lack
+                       // of validation.
+                       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_UNKNOWN);
+
+       // Add some fixed amount of extra. It's to compensate memory usage
+       // of Stream, Block etc. coders, malloc() overhead, stack etc.
+       return total + LZMA_MEMUSAGE_BASE;
+}
diff --git a/lzma/common/filter_common.h b/lzma/common/filter_common.h
new file mode 100644 (file)
index 0000000..42a26a2
--- /dev/null
@@ -0,0 +1,48 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       filter_common.c
+/// \brief      Filter-specific stuff common for both encoder and decoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_FILTER_COMMON_H
+#define LZMA_FILTER_COMMON_H
+
+#include "common.h"
+
+
+/// Both lzma_filter_encoder and lzma_filter_decoder begin with these members.
+typedef struct {
+       /// Filter ID
+       lzma_vli id;
+
+       /// Initializes the filter encoder and calls lzma_next_filter_init()
+       /// for filters + 1.
+       lzma_init_function init;
+
+       /// Calculates memory usage of the encoder. If the options are
+       /// invalid, UINT64_MAX is returned.
+       uint64_t (*memusage)(const void *options);
+
+} lzma_filter_coder;
+
+
+typedef const lzma_filter_coder *(*lzma_filter_find)(lzma_vli id);
+
+
+extern lzma_ret lzma_raw_coder_init(
+               lzma_next_coder *next, const lzma_allocator *allocator,
+               const lzma_filter *filters,
+               lzma_filter_find coder_find, bool is_encoder);
+
+
+extern uint64_t lzma_raw_coder_memusage(lzma_filter_find coder_find,
+               const lzma_filter *filters);
+
+
+#endif
diff --git a/lzma/common/filter_decoder.c b/lzma/common/filter_decoder.c
new file mode 100644 (file)
index 0000000..c75b0a8
--- /dev/null
@@ -0,0 +1,184 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       filter_decoder.c
+/// \brief      Filter ID mapping to filter-specific functions
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "filter_decoder.h"
+#include "filter_common.h"
+#include "lzma_decoder.h"
+#include "lzma2_decoder.h"
+#include "simple_decoder.h"
+#include "delta_decoder.h"
+
+
+typedef struct {
+       /// Filter ID
+       lzma_vli id;
+
+       /// Initializes the filter encoder and calls lzma_next_filter_init()
+       /// for filters + 1.
+       lzma_init_function init;
+
+       /// Calculates memory usage of the encoder. If the options are
+       /// invalid, UINT64_MAX is returned.
+       uint64_t (*memusage)(const void *options);
+
+       /// Decodes Filter Properties.
+       ///
+       /// \return     - LZMA_OK: Properties decoded successfully.
+       ///             - LZMA_OPTIONS_ERROR: Unsupported properties
+       ///             - LZMA_MEM_ERROR: Memory allocation failed.
+       lzma_ret (*props_decode)(
+                       void **options, const lzma_allocator *allocator,
+                       const uint8_t *props, size_t props_size);
+
+} lzma_filter_decoder;
+
+
+static const lzma_filter_decoder decoders[] = {
+#ifdef HAVE_DECODER_LZMA1
+       {
+               .id = LZMA_FILTER_LZMA1,
+               .init = &lzma_lzma_decoder_init,
+               .memusage = &lzma_lzma_decoder_memusage,
+               .props_decode = &lzma_lzma_props_decode,
+       },
+#endif
+#ifdef HAVE_DECODER_LZMA2
+       {
+               .id = LZMA_FILTER_LZMA2,
+               .init = &lzma_lzma2_decoder_init,
+               .memusage = &lzma_lzma2_decoder_memusage,
+               .props_decode = &lzma_lzma2_props_decode,
+       },
+#endif
+#ifdef HAVE_DECODER_X86
+       {
+               .id = LZMA_FILTER_X86,
+               .init = &lzma_simple_x86_decoder_init,
+               .memusage = NULL,
+               .props_decode = &lzma_simple_props_decode,
+       },
+#endif
+#ifdef HAVE_DECODER_POWERPC
+       {
+               .id = LZMA_FILTER_POWERPC,
+               .init = &lzma_simple_powerpc_decoder_init,
+               .memusage = NULL,
+               .props_decode = &lzma_simple_props_decode,
+       },
+#endif
+#ifdef HAVE_DECODER_IA64
+       {
+               .id = LZMA_FILTER_IA64,
+               .init = &lzma_simple_ia64_decoder_init,
+               .memusage = NULL,
+               .props_decode = &lzma_simple_props_decode,
+       },
+#endif
+#ifdef HAVE_DECODER_ARM
+       {
+               .id = LZMA_FILTER_ARM,
+               .init = &lzma_simple_arm_decoder_init,
+               .memusage = NULL,
+               .props_decode = &lzma_simple_props_decode,
+       },
+#endif
+#ifdef HAVE_DECODER_ARMTHUMB
+       {
+               .id = LZMA_FILTER_ARMTHUMB,
+               .init = &lzma_simple_armthumb_decoder_init,
+               .memusage = NULL,
+               .props_decode = &lzma_simple_props_decode,
+       },
+#endif
+#ifdef HAVE_DECODER_SPARC
+       {
+               .id = LZMA_FILTER_SPARC,
+               .init = &lzma_simple_sparc_decoder_init,
+               .memusage = NULL,
+               .props_decode = &lzma_simple_props_decode,
+       },
+#endif
+#ifdef HAVE_DECODER_DELTA
+       {
+               .id = LZMA_FILTER_DELTA,
+               .init = &lzma_delta_decoder_init,
+               .memusage = &lzma_delta_coder_memusage,
+               .props_decode = &lzma_delta_props_decode,
+       },
+#endif
+};
+
+
+static const lzma_filter_decoder *
+decoder_find(lzma_vli id)
+{
+       for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i)
+               if (decoders[i].id == id)
+                       return decoders + i;
+
+       return NULL;
+}
+
+
+extern LZMA_API(lzma_bool)
+lzma_filter_decoder_is_supported(lzma_vli id)
+{
+       return decoder_find(id) != NULL;
+}
+
+
+extern lzma_ret
+lzma_raw_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
+               const lzma_filter *options)
+{
+       return lzma_raw_coder_init(next, allocator,
+                       options, (lzma_filter_find)(&decoder_find), false);
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_raw_decoder(lzma_stream *strm, const lzma_filter *options)
+{
+       lzma_next_strm_init(lzma_raw_decoder_init, strm, options);
+
+       strm->internal->supported_actions[LZMA_RUN] = true;
+       strm->internal->supported_actions[LZMA_FINISH] = true;
+
+       return LZMA_OK;
+}
+
+
+extern LZMA_API(uint64_t)
+lzma_raw_decoder_memusage(const lzma_filter *filters)
+{
+       return lzma_raw_coder_memusage(
+                       (lzma_filter_find)(&decoder_find), filters);
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_properties_decode(lzma_filter *filter, const 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_OPTIONS_ERROR;
+
+       if (fd->props_decode == NULL)
+               return props_size == 0 ? LZMA_OK : LZMA_OPTIONS_ERROR;
+
+       return fd->props_decode(
+                       &filter->options, allocator, props, props_size);
+}
diff --git a/lzma/common/filter_decoder.h b/lzma/common/filter_decoder.h
new file mode 100644 (file)
index 0000000..a2e255f
--- /dev/null
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       filter_decoder.c
+/// \brief      Filter ID mapping to filter-specific functions
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_FILTER_DECODER_H
+#define LZMA_FILTER_DECODER_H
+
+#include "common.h"
+
+
+extern lzma_ret lzma_raw_decoder_init(
+               lzma_next_coder *next, const lzma_allocator *allocator,
+               const lzma_filter *options);
+
+#endif
diff --git a/lzma/common/filter_encoder.c b/lzma/common/filter_encoder.c
new file mode 100644 (file)
index 0000000..c5d8f39
--- /dev/null
@@ -0,0 +1,286 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       filter_decoder.c
+/// \brief      Filter ID mapping to filter-specific functions
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "filter_encoder.h"
+#include "filter_common.h"
+#include "lzma_encoder.h"
+#include "lzma2_encoder.h"
+#include "simple_encoder.h"
+#include "delta_encoder.h"
+
+
+typedef struct {
+       /// Filter ID
+       lzma_vli id;
+
+       /// Initializes the filter encoder and calls lzma_next_filter_init()
+       /// for filters + 1.
+       lzma_init_function init;
+
+       /// Calculates memory usage of the encoder. If the options are
+       /// invalid, UINT64_MAX is returned.
+       uint64_t (*memusage)(const void *options);
+
+       /// Calculates the recommended Uncompressed Size for .xz Blocks to
+       /// which the input data can be split to make multithreaded
+       /// encoding possible. If this is NULL, it is assumed that
+       /// the encoder is fast enough with single thread.
+       uint64_t (*block_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 successfully.
+       ///             - LZMA_OPTIONS_ERROR: Unsupported options
+       ///             - LZMA_PROG_ERROR: Invalid options or not enough
+       ///               output space
+       lzma_ret (*props_encode)(const void *options, uint8_t *out);
+
+} lzma_filter_encoder;
+
+
+static const lzma_filter_encoder encoders[] = {
+#ifdef HAVE_ENCODER_LZMA1
+       {
+               .id = LZMA_FILTER_LZMA1,
+               .init = &lzma_lzma_encoder_init,
+               .memusage = &lzma_lzma_encoder_memusage,
+               .block_size = NULL, // FIXME
+               .props_size_get = NULL,
+               .props_size_fixed = 5,
+               .props_encode = &lzma_lzma_props_encode,
+       },
+#endif
+#ifdef HAVE_ENCODER_LZMA2
+       {
+               .id = LZMA_FILTER_LZMA2,
+               .init = &lzma_lzma2_encoder_init,
+               .memusage = &lzma_lzma2_encoder_memusage,
+               .block_size = &lzma_lzma2_block_size, // FIXME
+               .props_size_get = NULL,
+               .props_size_fixed = 1,
+               .props_encode = &lzma_lzma2_props_encode,
+       },
+#endif
+#ifdef HAVE_ENCODER_X86
+       {
+               .id = LZMA_FILTER_X86,
+               .init = &lzma_simple_x86_encoder_init,
+               .memusage = NULL,
+               .block_size = NULL,
+               .props_size_get = &lzma_simple_props_size,
+               .props_encode = &lzma_simple_props_encode,
+       },
+#endif
+#ifdef HAVE_ENCODER_POWERPC
+       {
+               .id = LZMA_FILTER_POWERPC,
+               .init = &lzma_simple_powerpc_encoder_init,
+               .memusage = NULL,
+               .block_size = NULL,
+               .props_size_get = &lzma_simple_props_size,
+               .props_encode = &lzma_simple_props_encode,
+       },
+#endif
+#ifdef HAVE_ENCODER_IA64
+       {
+               .id = LZMA_FILTER_IA64,
+               .init = &lzma_simple_ia64_encoder_init,
+               .memusage = NULL,
+               .block_size = NULL,
+               .props_size_get = &lzma_simple_props_size,
+               .props_encode = &lzma_simple_props_encode,
+       },
+#endif
+#ifdef HAVE_ENCODER_ARM
+       {
+               .id = LZMA_FILTER_ARM,
+               .init = &lzma_simple_arm_encoder_init,
+               .memusage = NULL,
+               .block_size = NULL,
+               .props_size_get = &lzma_simple_props_size,
+               .props_encode = &lzma_simple_props_encode,
+       },
+#endif
+#ifdef HAVE_ENCODER_ARMTHUMB
+       {
+               .id = LZMA_FILTER_ARMTHUMB,
+               .init = &lzma_simple_armthumb_encoder_init,
+               .memusage = NULL,
+               .block_size = NULL,
+               .props_size_get = &lzma_simple_props_size,
+               .props_encode = &lzma_simple_props_encode,
+       },
+#endif
+#ifdef HAVE_ENCODER_SPARC
+       {
+               .id = LZMA_FILTER_SPARC,
+               .init = &lzma_simple_sparc_encoder_init,
+               .memusage = NULL,
+               .block_size = NULL,
+               .props_size_get = &lzma_simple_props_size,
+               .props_encode = &lzma_simple_props_encode,
+       },
+#endif
+#ifdef HAVE_ENCODER_DELTA
+       {
+               .id = LZMA_FILTER_DELTA,
+               .init = &lzma_delta_encoder_init,
+               .memusage = &lzma_delta_coder_memusage,
+               .block_size = NULL,
+               .props_size_get = NULL,
+               .props_size_fixed = 1,
+               .props_encode = &lzma_delta_props_encode,
+       },
+#endif
+};
+
+
+static const lzma_filter_encoder *
+encoder_find(lzma_vli id)
+{
+       for (size_t i = 0; i < ARRAY_SIZE(encoders); ++i)
+               if (encoders[i].id == id)
+                       return encoders + i;
+
+       return NULL;
+}
+
+
+extern LZMA_API(lzma_bool)
+lzma_filter_encoder_is_supported(lzma_vli id)
+{
+       return encoder_find(id) != NULL;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_filters_update(lzma_stream *strm, const lzma_filter *filters)
+{
+       if (strm->internal->next.update == NULL)
+               return LZMA_PROG_ERROR;
+
+       // Validate the filter chain.
+       if (lzma_raw_encoder_memusage(filters) == UINT64_MAX)
+               return LZMA_OPTIONS_ERROR;
+
+       // The actual filter chain in the encoder is reversed. Some things
+       // still want the normal order chain, so we provide both.
+       size_t count = 1;
+       while (filters[count].id != LZMA_VLI_UNKNOWN)
+               ++count;
+
+       lzma_filter reversed_filters[LZMA_FILTERS_MAX + 1];
+       for (size_t i = 0; i < count; ++i)
+               reversed_filters[count - i - 1] = filters[i];
+
+       reversed_filters[count].id = LZMA_VLI_UNKNOWN;
+
+       return strm->internal->next.update(strm->internal->next.coder,
+                       strm->allocator, filters, reversed_filters);
+}
+
+
+extern lzma_ret
+lzma_raw_encoder_init(lzma_next_coder *next, const 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_raw_encoder_memusage(const lzma_filter *filters)
+{
+       return lzma_raw_coder_memusage(
+                       (lzma_filter_find)(&encoder_find), filters);
+}
+
+
+extern uint64_t
+lzma_mt_block_size(const lzma_filter *filters)
+{
+       uint64_t max = 0;
+
+       for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i) {
+               const lzma_filter_encoder *const fe
+                               = encoder_find(filters[i].id);
+               if (fe->block_size != NULL) {
+                       const uint64_t size
+                                       = fe->block_size(filters[i].options);
+                       if (size == 0)
+                               return 0;
+
+                       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_OPTIONS_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_MAX
+                               ? LZMA_OPTIONS_ERROR : LZMA_PROG_ERROR;
+       }
+
+       if (fe->props_size_get == NULL) {
+               // No props_size_get() function, use props_size_fixed.
+               *size = fe->props_size_fixed;
+               return LZMA_OK;
+       }
+
+       return fe->props_size_get(size, filter->options);
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_properties_encode(const lzma_filter *filter, uint8_t *props)
+{
+       const lzma_filter_encoder *const fe = encoder_find(filter->id);
+       if (fe == NULL)
+               return LZMA_PROG_ERROR;
+
+       if (fe->props_encode == NULL)
+               return LZMA_OK;
+
+       return fe->props_encode(filter->options, props);
+}
diff --git a/lzma/common/filter_encoder.h b/lzma/common/filter_encoder.h
new file mode 100644 (file)
index 0000000..f1d5683
--- /dev/null
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       filter_encoder.c
+/// \brief      Filter ID mapping to filter-specific functions
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_FILTER_ENCODER_H
+#define LZMA_FILTER_ENCODER_H
+
+#include "common.h"
+
+
+// FIXME: Might become a part of the public API.
+extern uint64_t lzma_mt_block_size(const lzma_filter *filters);
+
+
+extern lzma_ret lzma_raw_encoder_init(
+               lzma_next_coder *next, const lzma_allocator *allocator,
+               const lzma_filter *filters);
+
+#endif
diff --git a/lzma/common/filter_flags_decoder.c b/lzma/common/filter_flags_decoder.c
new file mode 100644 (file)
index 0000000..ddfb085
--- /dev/null
@@ -0,0 +1,46 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       filter_flags_decoder.c
+/// \brief      Decodes a Filter Flags field
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "filter_decoder.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_filter_flags_decode(
+               lzma_filter *filter, const lzma_allocator *allocator,
+               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.
+       filter->options = NULL;
+
+       // Filter ID
+       return_if_error(lzma_vli_decode(&filter->id, NULL,
+                       in, in_pos, in_size));
+
+       if (filter->id >= LZMA_FILTER_RESERVED_START)
+               return LZMA_DATA_ERROR;
+
+       // Size of Properties
+       lzma_vli props_size;
+       return_if_error(lzma_vli_decode(&props_size, NULL,
+                       in, in_pos, in_size));
+
+       // Filter Properties
+       if (in_size - *in_pos < props_size)
+               return LZMA_DATA_ERROR;
+
+       const lzma_ret ret = lzma_properties_decode(
+                       filter, allocator, in + *in_pos, props_size);
+
+       *in_pos += props_size;
+
+       return ret;
+}
diff --git a/lzma/common/filter_flags_encoder.c b/lzma/common/filter_flags_encoder.c
new file mode 100644 (file)
index 0000000..d110566
--- /dev/null
@@ -0,0 +1,56 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       filter_flags_encoder.c
+/// \brief      Decodes a Filter Flags field
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "filter_encoder.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_filter_flags_size(uint32_t *size, const lzma_filter *filter)
+{
+       if (filter->id >= LZMA_FILTER_RESERVED_START)
+               return LZMA_PROG_ERROR;
+
+       return_if_error(lzma_properties_size(size, filter));
+
+       *size += lzma_vli_size(filter->id) + lzma_vli_size(*size);
+
+       return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_filter_flags_encode(const lzma_filter *filter,
+               uint8_t *out, size_t *out_pos, size_t out_size)
+{
+       // Filter ID
+       if (filter->id >= LZMA_FILTER_RESERVED_START)
+               return LZMA_PROG_ERROR;
+
+       return_if_error(lzma_vli_encode(filter->id, NULL,
+                       out, out_pos, out_size));
+
+       // Size of Properties
+       uint32_t props_size;
+       return_if_error(lzma_properties_size(&props_size, filter));
+       return_if_error(lzma_vli_encode(props_size, NULL,
+                       out, out_pos, out_size));
+
+       // Filter Properties
+       if (out_size - *out_pos < props_size)
+               return LZMA_PROG_ERROR;
+
+       return_if_error(lzma_properties_encode(filter, out + *out_pos));
+
+       *out_pos += props_size;
+
+       return LZMA_OK;
+}
diff --git a/lzma/common/hardware_cputhreads.c b/lzma/common/hardware_cputhreads.c
new file mode 100644 (file)
index 0000000..f468366
--- /dev/null
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       hardware_cputhreads.c
+/// \brief      Get the number of CPU threads or cores
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+#include "tuklib_cpucores.h"
+
+
+extern LZMA_API(uint32_t)
+lzma_cputhreads(void)
+{
+       return tuklib_cpucores();
+}
diff --git a/lzma/common/hardware_physmem.c b/lzma/common/hardware_physmem.c
new file mode 100644 (file)
index 0000000..7405b65
--- /dev/null
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       hardware_physmem.c
+/// \brief      Get the total amount of physical memory (RAM)
+//
+//  Author:     Jonathan Nieder
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+#include "tuklib_physmem.h"
+
+
+extern LZMA_API(uint64_t)
+lzma_physmem(void)
+{
+       // It is simpler to make lzma_physmem() a wrapper for
+       // tuklib_physmem() than to hack appropriate symbol visiblity
+       // support for the tuklib modules.
+       return tuklib_physmem();
+}
diff --git a/lzma/common/index.c b/lzma/common/index.c
new file mode 100644 (file)
index 0000000..26e4e51
--- /dev/null
@@ -0,0 +1,1250 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       index.c
+/// \brief      Handling of .xz Indexes and some other Stream information
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "index.h"
+#include "stream_flags_common.h"
+
+
+/// \brief      How many Records to allocate at once
+///
+/// This should be big enough to avoid making lots of tiny allocations
+/// but small enough to avoid too much unused memory at once.
+#define INDEX_GROUP_SIZE 512
+
+
+/// \brief      How many Records can be allocated at once at maximum
+#define PREALLOC_MAX ((SIZE_MAX - sizeof(index_group)) / sizeof(index_record))
+
+
+/// \brief      Base structure for index_stream and index_group structures
+typedef struct index_tree_node_s index_tree_node;
+struct index_tree_node_s {
+       /// Uncompressed start offset of this Stream (relative to the
+       /// beginning of the file) or Block (relative to the beginning
+       /// of the Stream)
+       lzma_vli uncompressed_base;
+
+       /// Compressed start offset of this Stream or Block
+       lzma_vli compressed_base;
+
+       index_tree_node *parent;
+       index_tree_node *left;
+       index_tree_node *right;
+};
+
+
+/// \brief      AVL tree to hold index_stream or index_group structures
+typedef struct {
+       /// Root node
+       index_tree_node *root;
+
+       /// Leftmost node. Since the tree will be filled sequentially,
+       /// this won't change after the first node has been added to
+       /// the tree.
+       index_tree_node *leftmost;
+
+       /// The rightmost node in the tree. Since the tree is filled
+       /// sequentially, this is always the node where to add the new data.
+       index_tree_node *rightmost;
+
+       /// Number of nodes in the tree
+       uint32_t count;
+
+} index_tree;
+
+
+typedef struct {
+       lzma_vli uncompressed_sum;
+       lzma_vli unpadded_sum;
+} index_record;
+
+
+typedef struct {
+       /// Every Record group is part of index_stream.groups tree.
+       index_tree_node node;
+
+       /// Number of Blocks in this Stream before this group.
+       lzma_vli number_base;
+
+       /// Number of Records that can be put in records[].
+       size_t allocated;
+
+       /// Index of the last Record in use.
+       size_t last;
+
+       /// The sizes in this array are stored as cumulative sums relative
+       /// to the beginning of the Stream. This makes it possible to
+       /// use binary search in lzma_index_locate().
+       ///
+       /// Note that the cumulative summing is done specially for
+       /// unpadded_sum: The previous value is rounded up to the next
+       /// multiple of four before adding the Unpadded Size of the new
+       /// Block. The total encoded size of the Blocks in the Stream
+       /// is records[last].unpadded_sum in the last Record group of
+       /// the Stream.
+       ///
+       /// For example, if the Unpadded Sizes are 39, 57, and 81, the
+       /// stored values are 39, 97 (40 + 57), and 181 (100 + 181).
+       /// The total encoded size of these Blocks is 184.
+       ///
+       /// This is a flexible array, because it makes easy to optimize
+       /// memory usage in case someone concatenates many Streams that
+       /// have only one or few Blocks.
+       index_record records[];
+
+} index_group;
+
+
+typedef struct {
+       /// Every index_stream is a node in the tree of Sreams.
+       index_tree_node node;
+
+       /// Number of this Stream (first one is 1)
+       uint32_t number;
+
+       /// Total number of Blocks before this Stream
+       lzma_vli block_number_base;
+
+       /// Record groups of this Stream are stored in a tree.
+       /// It's a T-tree with AVL-tree balancing. There are
+       /// INDEX_GROUP_SIZE Records per node by default.
+       /// This keeps the number of memory allocations reasonable
+       /// and finding a Record is fast.
+       index_tree groups;
+
+       /// Number of Records in this Stream
+       lzma_vli record_count;
+
+       /// Size of the List of Records field in this Stream. This is used
+       /// together with record_count to calculate the size of the Index
+       /// field and thus the total size of the Stream.
+       lzma_vli index_list_size;
+
+       /// Stream Flags of this Stream. This is meaningful only if
+       /// the Stream Flags have been told us with lzma_index_stream_flags().
+       /// Initially stream_flags.version is set to UINT32_MAX to indicate
+       /// that the Stream Flags are unknown.
+       lzma_stream_flags stream_flags;
+
+       /// Amount of Stream Padding after this Stream. This defaults to
+       /// zero and can be set with lzma_index_stream_padding().
+       lzma_vli stream_padding;
+
+} index_stream;
+
+
+struct lzma_index_s {
+       /// AVL-tree containing the Stream(s). Often there is just one
+       /// Stream, but using a tree keeps lookups fast even when there
+       /// are many concatenated Streams.
+       index_tree streams;
+
+       /// Uncompressed size of all the Blocks in the Stream(s)
+       lzma_vli uncompressed_size;
+
+       /// Total size of all the Blocks in the Stream(s)
+       lzma_vli total_size;
+
+       /// Total number of Records in all Streams in this lzma_index
+       lzma_vli record_count;
+
+       /// Size of the List of Records field if all the Streams in this
+       /// lzma_index were packed into a single Stream (makes it simpler to
+       /// take many .xz files and combine them into a single Stream).
+       ///
+       /// This value together with record_count is needed to calculate
+       /// Backward Size that is stored into Stream Footer.
+       lzma_vli index_list_size;
+
+       /// How many Records to allocate at once in lzma_index_append().
+       /// This defaults to INDEX_GROUP_SIZE but can be overriden with
+       /// lzma_index_prealloc().
+       size_t prealloc;
+
+       /// Bitmask indicating what integrity check types have been used
+       /// as set by lzma_index_stream_flags(). The bit of the last Stream
+       /// is not included here, since it is possible to change it by
+       /// calling lzma_index_stream_flags() again.
+       uint32_t checks;
+};
+
+
+static void
+index_tree_init(index_tree *tree)
+{
+       tree->root = NULL;
+       tree->leftmost = NULL;
+       tree->rightmost = NULL;
+       tree->count = 0;
+       return;
+}
+
+
+/// Helper for index_tree_end()
+static void
+index_tree_node_end(index_tree_node *node, const lzma_allocator *allocator,
+               void (*free_func)(void *node, const lzma_allocator *allocator))
+{
+       // The tree won't ever be very huge, so recursion should be fine.
+       // 20 levels in the tree is likely quite a lot already in practice.
+       if (node->left != NULL)
+               index_tree_node_end(node->left, allocator, free_func);
+
+       if (node->right != NULL)
+               index_tree_node_end(node->right, allocator, free_func);
+
+       free_func(node, allocator);
+       return;
+}
+
+
+/// Free the memory allocated for a tree. Each node is freed using the
+/// given free_func which is either &lzma_free or &index_stream_end.
+/// The latter is used to free the Record groups from each index_stream
+/// before freeing the index_stream itself.
+static void
+index_tree_end(index_tree *tree, const lzma_allocator *allocator,
+               void (*free_func)(void *node, const lzma_allocator *allocator))
+{
+       assert(free_func != NULL);
+
+       if (tree->root != NULL)
+               index_tree_node_end(tree->root, allocator, free_func);
+
+       return;
+}
+
+
+/// Add a new node to the tree. node->uncompressed_base and
+/// node->compressed_base must have been set by the caller already.
+static void
+index_tree_append(index_tree *tree, index_tree_node *node)
+{
+       node->parent = tree->rightmost;
+       node->left = NULL;
+       node->right = NULL;
+
+       ++tree->count;
+
+       // Handle the special case of adding the first node.
+       if (tree->root == NULL) {
+               tree->root = node;
+               tree->leftmost = node;
+               tree->rightmost = node;
+               return;
+       }
+
+       // The tree is always filled sequentially.
+       assert(tree->rightmost->uncompressed_base <= node->uncompressed_base);
+       assert(tree->rightmost->compressed_base < node->compressed_base);
+
+       // Add the new node after the rightmost node. It's the correct
+       // place due to the reason above.
+       tree->rightmost->right = node;
+       tree->rightmost = node;
+
+       // Balance the AVL-tree if needed. We don't need to keep the balance
+       // factors in nodes, because we always fill the tree sequentially,
+       // and thus know the state of the tree just by looking at the node
+       // count. From the node count we can calculate how many steps to go
+       // up in the tree to find the rotation root.
+       uint32_t up = tree->count ^ (UINT32_C(1) << bsr32(tree->count));
+       if (up != 0) {
+               // Locate the root node for the rotation.
+               up = ctz32(tree->count) + 2;
+               do {
+                       node = node->parent;
+               } while (--up > 0);
+
+               // Rotate left using node as the rotation root.
+               index_tree_node *pivot = node->right;
+
+               if (node->parent == NULL) {
+                       tree->root = pivot;
+               } else {
+                       assert(node->parent->right == node);
+                       node->parent->right = pivot;
+               }
+
+               pivot->parent = node->parent;
+
+               node->right = pivot->left;
+               if (node->right != NULL)
+                       node->right->parent = node;
+
+               pivot->left = node;
+               node->parent = pivot;
+       }
+
+       return;
+}
+
+
+/// Get the next node in the tree. Return NULL if there are no more nodes.
+static void *
+index_tree_next(const index_tree_node *node)
+{
+       if (node->right != NULL) {
+               node = node->right;
+               while (node->left != NULL)
+                       node = node->left;
+
+               return (void *)(node);
+       }
+
+       while (node->parent != NULL && node->parent->right == node)
+               node = node->parent;
+
+       return (void *)(node->parent);
+}
+
+
+/// Locate a node that contains the given uncompressed offset. It is
+/// caller's job to check that target is not bigger than the uncompressed
+/// size of the tree (the last node would be returned in that case still).
+static void *
+index_tree_locate(const index_tree *tree, lzma_vli target)
+{
+       const index_tree_node *result = NULL;
+       const index_tree_node *node = tree->root;
+
+       assert(tree->leftmost == NULL
+                       || tree->leftmost->uncompressed_base == 0);
+
+       // Consecutive nodes may have the same uncompressed_base.
+       // We must pick the rightmost one.
+       while (node != NULL) {
+               if (node->uncompressed_base > target) {
+                       node = node->left;
+               } else {
+                       result = node;
+                       node = node->right;
+               }
+       }
+
+       return (void *)(result);
+}
+
+
+/// Allocate and initialize a new Stream using the given base offsets.
+static index_stream *
+index_stream_init(lzma_vli compressed_base, lzma_vli uncompressed_base,
+               uint32_t stream_number, lzma_vli block_number_base,
+               const lzma_allocator *allocator)
+{
+       index_stream *s = lzma_alloc(sizeof(index_stream), allocator);
+       if (s == NULL)
+               return NULL;
+
+       s->node.uncompressed_base = uncompressed_base;
+       s->node.compressed_base = compressed_base;
+       s->node.parent = NULL;
+       s->node.left = NULL;
+       s->node.right = NULL;
+
+       s->number = stream_number;
+       s->block_number_base = block_number_base;
+
+       index_tree_init(&s->groups);
+
+       s->record_count = 0;
+       s->index_list_size = 0;
+       s->stream_flags.version = UINT32_MAX;
+       s->stream_padding = 0;
+
+       return s;
+}
+
+
+/// Free the memory allocated for a Stream and its Record groups.
+static void
+index_stream_end(void *node, const lzma_allocator *allocator)
+{
+       index_stream *s = node;
+       index_tree_end(&s->groups, allocator, &lzma_free);
+       lzma_free(s, allocator);
+       return;
+}
+
+
+static lzma_index *
+index_init_plain(const lzma_allocator *allocator)
+{
+       lzma_index *i = lzma_alloc(sizeof(lzma_index), allocator);
+       if (i != NULL) {
+               index_tree_init(&i->streams);
+               i->uncompressed_size = 0;
+               i->total_size = 0;
+               i->record_count = 0;
+               i->index_list_size = 0;
+               i->prealloc = INDEX_GROUP_SIZE;
+               i->checks = 0;
+       }
+
+       return i;
+}
+
+
+extern LZMA_API(lzma_index *)
+lzma_index_init(const lzma_allocator *allocator)
+{
+       lzma_index *i = index_init_plain(allocator);
+       if (i == NULL)
+               return NULL;
+
+       index_stream *s = index_stream_init(0, 0, 1, 0, allocator);
+       if (s == NULL) {
+               lzma_free(i, allocator);
+               return NULL;
+       }
+
+       index_tree_append(&i->streams, &s->node);
+
+       return i;
+}
+
+
+extern LZMA_API(void)
+lzma_index_end(lzma_index *i, const lzma_allocator *allocator)
+{
+       // NOTE: If you modify this function, check also the bottom
+       // of lzma_index_cat().
+       if (i != NULL) {
+               index_tree_end(&i->streams, allocator, &index_stream_end);
+               lzma_free(i, allocator);
+       }
+
+       return;
+}
+
+
+extern void
+lzma_index_prealloc(lzma_index *i, lzma_vli records)
+{
+       if (records > PREALLOC_MAX)
+               records = PREALLOC_MAX;
+
+       i->prealloc = (size_t)(records);
+       return;
+}
+
+
+extern LZMA_API(uint64_t)
+lzma_index_memusage(lzma_vli streams, lzma_vli blocks)
+{
+       // This calculates an upper bound that is only a little bit
+       // bigger than the exact maximum memory usage with the given
+       // parameters.
+
+       // Typical malloc() overhead is 2 * sizeof(void *) but we take
+       // a little bit extra just in case. Using LZMA_MEMUSAGE_BASE
+       // instead would give too inaccurate estimate.
+       const size_t alloc_overhead = 4 * sizeof(void *);
+
+       // Amount of memory needed for each Stream base structures.
+       // We assume that every Stream has at least one Block and
+       // thus at least one group.
+       const size_t stream_base = sizeof(index_stream)
+                       + sizeof(index_group) + 2 * alloc_overhead;
+
+       // Amount of memory needed per group.
+       const size_t group_base = sizeof(index_group)
+                       + INDEX_GROUP_SIZE * sizeof(index_record)
+                       + alloc_overhead;
+
+       // Number of groups. There may actually be more, but that overhead
+       // has been taken into account in stream_base already.
+       const lzma_vli groups
+                       = (blocks + INDEX_GROUP_SIZE - 1) / INDEX_GROUP_SIZE;
+
+       // Memory used by index_stream and index_group structures.
+       const uint64_t streams_mem = streams * stream_base;
+       const uint64_t groups_mem = groups * group_base;
+
+       // Memory used by the base structure.
+       const uint64_t index_base = sizeof(lzma_index) + alloc_overhead;
+
+       // Validate the arguments and catch integer overflows.
+       // Maximum number of Streams is "only" UINT32_MAX, because
+       // that limit is used by the tree containing the Streams.
+       const uint64_t limit = UINT64_MAX - index_base;
+       if (streams == 0 || streams > UINT32_MAX || blocks > LZMA_VLI_MAX
+                       || streams > limit / stream_base
+                       || groups > limit / group_base
+                       || limit - streams_mem < groups_mem)
+               return UINT64_MAX;
+
+       return index_base + streams_mem + groups_mem;
+}
+
+
+extern LZMA_API(uint64_t)
+lzma_index_memused(const lzma_index *i)
+{
+       return lzma_index_memusage(i->streams.count, i->record_count);
+}
+
+
+extern LZMA_API(lzma_vli)
+lzma_index_block_count(const lzma_index *i)
+{
+       return i->record_count;
+}
+
+
+extern LZMA_API(lzma_vli)
+lzma_index_stream_count(const lzma_index *i)
+{
+       return i->streams.count;
+}
+
+
+extern LZMA_API(lzma_vli)
+lzma_index_size(const lzma_index *i)
+{
+       return index_size(i->record_count, i->index_list_size);
+}
+
+
+extern LZMA_API(lzma_vli)
+lzma_index_total_size(const lzma_index *i)
+{
+       return i->total_size;
+}
+
+
+extern LZMA_API(lzma_vli)
+lzma_index_stream_size(const lzma_index *i)
+{
+       // Stream Header + Blocks + Index + Stream Footer
+       return LZMA_STREAM_HEADER_SIZE + i->total_size
+                       + index_size(i->record_count, i->index_list_size)
+                       + LZMA_STREAM_HEADER_SIZE;
+}
+
+
+static lzma_vli
+index_file_size(lzma_vli compressed_base, lzma_vli unpadded_sum,
+               lzma_vli record_count, lzma_vli index_list_size,
+               lzma_vli stream_padding)
+{
+       // Earlier Streams and Stream Paddings + Stream Header
+       // + Blocks + Index + Stream Footer + Stream Padding
+       //
+       // This might go over LZMA_VLI_MAX due to too big unpadded_sum
+       // when this function is used in lzma_index_append().
+       lzma_vli file_size = compressed_base + 2 * LZMA_STREAM_HEADER_SIZE
+                       + stream_padding + vli_ceil4(unpadded_sum);
+       if (file_size > LZMA_VLI_MAX)
+               return LZMA_VLI_UNKNOWN;
+
+       // The same applies here.
+       file_size += index_size(record_count, index_list_size);
+       if (file_size > LZMA_VLI_MAX)
+               return LZMA_VLI_UNKNOWN;
+
+       return file_size;
+}
+
+
+extern LZMA_API(lzma_vli)
+lzma_index_file_size(const lzma_index *i)
+{
+       const index_stream *s = (const index_stream *)(i->streams.rightmost);
+       const index_group *g = (const index_group *)(s->groups.rightmost);
+       return index_file_size(s->node.compressed_base,
+                       g == NULL ? 0 : g->records[g->last].unpadded_sum,
+                       s->record_count, s->index_list_size,
+                       s->stream_padding);
+}
+
+
+extern LZMA_API(lzma_vli)
+lzma_index_uncompressed_size(const lzma_index *i)
+{
+       return i->uncompressed_size;
+}
+
+
+extern LZMA_API(uint32_t)
+lzma_index_checks(const lzma_index *i)
+{
+       uint32_t checks = i->checks;
+
+       // Get the type of the Check of the last Stream too.
+       const index_stream *s = (const index_stream *)(i->streams.rightmost);
+       if (s->stream_flags.version != UINT32_MAX)
+               checks |= UINT32_C(1) << s->stream_flags.check;
+
+       return checks;
+}
+
+
+extern uint32_t
+lzma_index_padding_size(const lzma_index *i)
+{
+       return (LZMA_VLI_C(4) - index_size_unpadded(
+                       i->record_count, i->index_list_size)) & 3;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_index_stream_flags(lzma_index *i, const lzma_stream_flags *stream_flags)
+{
+       if (i == NULL || stream_flags == NULL)
+               return LZMA_PROG_ERROR;
+
+       // Validate the Stream Flags.
+       return_if_error(lzma_stream_flags_compare(
+                       stream_flags, stream_flags));
+
+       index_stream *s = (index_stream *)(i->streams.rightmost);
+       s->stream_flags = *stream_flags;
+
+       return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_index_stream_padding(lzma_index *i, lzma_vli stream_padding)
+{
+       if (i == NULL || stream_padding > LZMA_VLI_MAX
+                       || (stream_padding & 3) != 0)
+               return LZMA_PROG_ERROR;
+
+       index_stream *s = (index_stream *)(i->streams.rightmost);
+
+       // Check that the new value won't make the file grow too big.
+       const lzma_vli old_stream_padding = s->stream_padding;
+       s->stream_padding = 0;
+       if (lzma_index_file_size(i) + stream_padding > LZMA_VLI_MAX) {
+               s->stream_padding = old_stream_padding;
+               return LZMA_DATA_ERROR;
+       }
+
+       s->stream_padding = stream_padding;
+       return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_index_append(lzma_index *i, const lzma_allocator *allocator,
+               lzma_vli unpadded_size, lzma_vli uncompressed_size)
+{
+       // Validate.
+       if (i == NULL || unpadded_size < UNPADDED_SIZE_MIN
+                       || unpadded_size > UNPADDED_SIZE_MAX
+                       || uncompressed_size > LZMA_VLI_MAX)
+               return LZMA_PROG_ERROR;
+
+       index_stream *s = (index_stream *)(i->streams.rightmost);
+       index_group *g = (index_group *)(s->groups.rightmost);
+
+       const lzma_vli compressed_base = g == NULL ? 0
+                       : vli_ceil4(g->records[g->last].unpadded_sum);
+       const lzma_vli uncompressed_base = g == NULL ? 0
+                       : g->records[g->last].uncompressed_sum;
+       const uint32_t index_list_size_add = lzma_vli_size(unpadded_size)
+                       + lzma_vli_size(uncompressed_size);
+
+       // Check that the file size will stay within limits.
+       if (index_file_size(s->node.compressed_base,
+                       compressed_base + unpadded_size, s->record_count + 1,
+                       s->index_list_size + index_list_size_add,
+                       s->stream_padding) == LZMA_VLI_UNKNOWN)
+               return LZMA_DATA_ERROR;
+
+       // The size of the Index field must not exceed the maximum value
+       // that can be stored in the Backward Size field.
+       if (index_size(i->record_count + 1,
+                       i->index_list_size + index_list_size_add)
+                       > LZMA_BACKWARD_SIZE_MAX)
+               return LZMA_DATA_ERROR;
+
+       if (g != NULL && g->last + 1 < g->allocated) {
+               // There is space in the last group at least for one Record.
+               ++g->last;
+       } else {
+               // We need to allocate a new group.
+               g = lzma_alloc(sizeof(index_group)
+                               + i->prealloc * sizeof(index_record),
+                               allocator);
+               if (g == NULL)
+                       return LZMA_MEM_ERROR;
+
+               g->last = 0;
+               g->allocated = i->prealloc;
+
+               // Reset prealloc so that if the application happens to
+               // add new Records, the allocation size will be sane.
+               i->prealloc = INDEX_GROUP_SIZE;
+
+               // Set the start offsets of this group.
+               g->node.uncompressed_base = uncompressed_base;
+               g->node.compressed_base = compressed_base;
+               g->number_base = s->record_count + 1;
+
+               // Add the new group to the Stream.
+               index_tree_append(&s->groups, &g->node);
+       }
+
+       // Add the new Record to the group.
+       g->records[g->last].uncompressed_sum
+                       = uncompressed_base + uncompressed_size;
+       g->records[g->last].unpadded_sum
+                       = compressed_base + unpadded_size;
+
+       // Update the totals.
+       ++s->record_count;
+       s->index_list_size += index_list_size_add;
+
+       i->total_size += vli_ceil4(unpadded_size);
+       i->uncompressed_size += uncompressed_size;
+       ++i->record_count;
+       i->index_list_size += index_list_size_add;
+
+       return LZMA_OK;
+}
+
+
+/// Structure to pass info to index_cat_helper()
+typedef struct {
+       /// Uncompressed size of the destination
+       lzma_vli uncompressed_size;
+
+       /// Compressed file size of the destination
+       lzma_vli file_size;
+
+       /// Same as above but for Block numbers
+       lzma_vli block_number_add;
+
+       /// Number of Streams that were in the destination index before we
+       /// started appending new Streams from the source index. This is
+       /// used to fix the Stream numbering.
+       uint32_t stream_number_add;
+
+       /// Destination index' Stream tree
+       index_tree *streams;
+
+} index_cat_info;
+
+
+/// Add the Stream nodes from the source index to dest using recursion.
+/// Simplest iterative traversal of the source tree wouldn't work, because
+/// we update the pointers in nodes when moving them to the destination tree.
+static void
+index_cat_helper(const index_cat_info *info, index_stream *this)
+{
+       index_stream *left = (index_stream *)(this->node.left);
+       index_stream *right = (index_stream *)(this->node.right);
+
+       if (left != NULL)
+               index_cat_helper(info, left);
+
+       this->node.uncompressed_base += info->uncompressed_size;
+       this->node.compressed_base += info->file_size;
+       this->number += info->stream_number_add;
+       this->block_number_base += info->block_number_add;
+       index_tree_append(info->streams, &this->node);
+
+       if (right != NULL)
+               index_cat_helper(info, right);
+
+       return;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_index_cat(lzma_index *restrict dest, lzma_index *restrict src,
+               const lzma_allocator *allocator)
+{
+       const lzma_vli dest_file_size = lzma_index_file_size(dest);
+
+       // Check that we don't exceed the file size limits.
+       if (dest_file_size + lzma_index_file_size(src) > LZMA_VLI_MAX
+                       || dest->uncompressed_size + src->uncompressed_size
+                               > LZMA_VLI_MAX)
+               return LZMA_DATA_ERROR;
+
+       // Check that the encoded size of the combined lzma_indexes stays
+       // within limits. In theory, this should be done only if we know
+       // that the user plans to actually combine the Streams and thus
+       // construct a single Index (probably rare). However, exceeding
+       // this limit is quite theoretical, so we do this check always
+       // to simplify things elsewhere.
+       {
+               const lzma_vli dest_size = index_size_unpadded(
+                               dest->record_count, dest->index_list_size);
+               const lzma_vli src_size = index_size_unpadded(
+                               src->record_count, src->index_list_size);
+               if (vli_ceil4(dest_size + src_size) > LZMA_BACKWARD_SIZE_MAX)
+                       return LZMA_DATA_ERROR;
+       }
+
+       // Optimize the last group to minimize memory usage. Allocation has
+       // to be done before modifying dest or src.
+       {
+               index_stream *s = (index_stream *)(dest->streams.rightmost);
+               index_group *g = (index_group *)(s->groups.rightmost);
+               if (g != NULL && g->last + 1 < g->allocated) {
+                       assert(g->node.left == NULL);
+                       assert(g->node.right == NULL);
+
+                       index_group *newg = lzma_alloc(sizeof(index_group)
+                                       + (g->last + 1)
+                                       * sizeof(index_record),
+                                       allocator);
+                       if (newg == NULL)
+                               return LZMA_MEM_ERROR;
+
+                       newg->node = g->node;
+                       newg->allocated = g->last + 1;
+                       newg->last = g->last;
+                       newg->number_base = g->number_base;
+
+                       memcpy(newg->records, g->records, newg->allocated
+                                       * sizeof(index_record));
+
+                       if (g->node.parent != NULL) {
+                               assert(g->node.parent->right == &g->node);
+                               g->node.parent->right = &newg->node;
+                       }
+
+                       if (s->groups.leftmost == &g->node) {
+                               assert(s->groups.root == &g->node);
+                               s->groups.leftmost = &newg->node;
+                               s->groups.root = &newg->node;
+                       }
+
+                       if (s->groups.rightmost == &g->node)
+                               s->groups.rightmost = &newg->node;
+
+                       lzma_free(g, allocator);
+
+                       // NOTE: newg isn't leaked here because
+                       // newg == (void *)&newg->node.
+               }
+       }
+
+       // Add all the Streams from src to dest. Update the base offsets
+       // of each Stream from src.
+       const index_cat_info info = {
+               .uncompressed_size = dest->uncompressed_size,
+               .file_size = dest_file_size,
+               .stream_number_add = dest->streams.count,
+               .block_number_add = dest->record_count,
+               .streams = &dest->streams,
+       };
+       index_cat_helper(&info, (index_stream *)(src->streams.root));
+
+       // Update info about all the combined Streams.
+       dest->uncompressed_size += src->uncompressed_size;
+       dest->total_size += src->total_size;
+       dest->record_count += src->record_count;
+       dest->index_list_size += src->index_list_size;
+       dest->checks = lzma_index_checks(dest) | src->checks;
+
+       // There's nothing else left in src than the base structure.
+       lzma_free(src, allocator);
+
+       return LZMA_OK;
+}
+
+
+/// Duplicate an index_stream.
+static index_stream *
+index_dup_stream(const index_stream *src, const lzma_allocator *allocator)
+{
+       // Catch a somewhat theoretical integer overflow.
+       if (src->record_count > PREALLOC_MAX)
+               return NULL;
+
+       // Allocate and initialize a new Stream.
+       index_stream *dest = index_stream_init(src->node.compressed_base,
+                       src->node.uncompressed_base, src->number,
+                       src->block_number_base, allocator);
+       if (dest == NULL)
+               return NULL;
+
+       // Copy the overall information.
+       dest->record_count = src->record_count;
+       dest->index_list_size = src->index_list_size;
+       dest->stream_flags = src->stream_flags;
+       dest->stream_padding = src->stream_padding;
+
+       // Return if there are no groups to duplicate.
+       if (src->groups.leftmost == NULL)
+               return dest;
+
+       // Allocate memory for the Records. We put all the Records into
+       // a single group. It's simplest and also tends to make
+       // lzma_index_locate() a little bit faster with very big Indexes.
+       index_group *destg = lzma_alloc(sizeof(index_group)
+                       + src->record_count * sizeof(index_record),
+                       allocator);
+       if (destg == NULL) {
+               index_stream_end(dest, allocator);
+               return NULL;
+       }
+
+       // Initialize destg.
+       destg->node.uncompressed_base = 0;
+       destg->node.compressed_base = 0;
+       destg->number_base = 1;
+       destg->allocated = src->record_count;
+       destg->last = src->record_count - 1;
+
+       // Go through all the groups in src and copy the Records into destg.
+       const index_group *srcg = (const index_group *)(src->groups.leftmost);
+       size_t i = 0;
+       do {
+               memcpy(destg->records + i, srcg->records,
+                               (srcg->last + 1) * sizeof(index_record));
+               i += srcg->last + 1;
+               srcg = index_tree_next(&srcg->node);
+       } while (srcg != NULL);
+
+       assert(i == destg->allocated);
+
+       // Add the group to the new Stream.
+       index_tree_append(&dest->groups, &destg->node);
+
+       return dest;
+}
+
+
+extern LZMA_API(lzma_index *)
+lzma_index_dup(const lzma_index *src, const lzma_allocator *allocator)
+{
+       // Allocate the base structure (no initial Stream).
+       lzma_index *dest = index_init_plain(allocator);
+       if (dest == NULL)
+               return NULL;
+
+       // Copy the totals.
+       dest->uncompressed_size = src->uncompressed_size;
+       dest->total_size = src->total_size;
+       dest->record_count = src->record_count;
+       dest->index_list_size = src->index_list_size;
+
+       // Copy the Streams and the groups in them.
+       const index_stream *srcstream
+                       = (const index_stream *)(src->streams.leftmost);
+       do {
+               index_stream *deststream = index_dup_stream(
+                               srcstream, allocator);
+               if (deststream == NULL) {
+                       lzma_index_end(dest, allocator);
+                       return NULL;
+               }
+
+               index_tree_append(&dest->streams, &deststream->node);
+
+               srcstream = index_tree_next(&srcstream->node);
+       } while (srcstream != NULL);
+
+       return dest;
+}
+
+
+/// Indexing for lzma_index_iter.internal[]
+enum {
+       ITER_INDEX,
+       ITER_STREAM,
+       ITER_GROUP,
+       ITER_RECORD,
+       ITER_METHOD,
+};
+
+
+/// Values for lzma_index_iter.internal[ITER_METHOD].s
+enum {
+       ITER_METHOD_NORMAL,
+       ITER_METHOD_NEXT,
+       ITER_METHOD_LEFTMOST,
+};
+
+
+static void
+iter_set_info(lzma_index_iter *iter)
+{
+       const lzma_index *i = iter->internal[ITER_INDEX].p;
+       const index_stream *stream = iter->internal[ITER_STREAM].p;
+       const index_group *group = iter->internal[ITER_GROUP].p;
+       const size_t record = iter->internal[ITER_RECORD].s;
+
+       // lzma_index_iter.internal must not contain a pointer to the last
+       // group in the index, because that may be reallocated by
+       // lzma_index_cat().
+       if (group == NULL) {
+               // There are no groups.
+               assert(stream->groups.root == NULL);
+               iter->internal[ITER_METHOD].s = ITER_METHOD_LEFTMOST;
+
+       } else if (i->streams.rightmost != &stream->node
+                       || stream->groups.rightmost != &group->node) {
+               // The group is not not the last group in the index.
+               iter->internal[ITER_METHOD].s = ITER_METHOD_NORMAL;
+
+       } else if (stream->groups.leftmost != &group->node) {
+               // The group isn't the only group in the Stream, thus we
+               // know that it must have a parent group i.e. it's not
+               // the root node.
+               assert(stream->groups.root != &group->node);
+               assert(group->node.parent->right == &group->node);
+               iter->internal[ITER_METHOD].s = ITER_METHOD_NEXT;
+               iter->internal[ITER_GROUP].p = group->node.parent;
+
+       } else {
+               // The Stream has only one group.
+               assert(stream->groups.root == &group->node);
+               assert(group->node.parent == NULL);
+               iter->internal[ITER_METHOD].s = ITER_METHOD_LEFTMOST;
+               iter->internal[ITER_GROUP].p = NULL;
+       }
+
+       // NOTE: lzma_index_iter.stream.number is lzma_vli but we use uint32_t
+       // internally.
+       iter->stream.number = stream->number;
+       iter->stream.block_count = stream->record_count;
+       iter->stream.compressed_offset = stream->node.compressed_base;
+       iter->stream.uncompressed_offset = stream->node.uncompressed_base;
+
+       // iter->stream.flags will be NULL if the Stream Flags haven't been
+       // set with lzma_index_stream_flags().
+       iter->stream.flags = stream->stream_flags.version == UINT32_MAX
+                       ? NULL : &stream->stream_flags;
+       iter->stream.padding = stream->stream_padding;
+
+       if (stream->groups.rightmost == NULL) {
+               // Stream has no Blocks.
+               iter->stream.compressed_size = index_size(0, 0)
+                               + 2 * LZMA_STREAM_HEADER_SIZE;
+               iter->stream.uncompressed_size = 0;
+       } else {
+               const index_group *g = (const index_group *)(
+                               stream->groups.rightmost);
+
+               // Stream Header + Stream Footer + Index + Blocks
+               iter->stream.compressed_size = 2 * LZMA_STREAM_HEADER_SIZE
+                               + index_size(stream->record_count,
+                                       stream->index_list_size)
+                               + vli_ceil4(g->records[g->last].unpadded_sum);
+               iter->stream.uncompressed_size
+                               = g->records[g->last].uncompressed_sum;
+       }
+
+       if (group != NULL) {
+               iter->block.number_in_stream = group->number_base + record;
+               iter->block.number_in_file = iter->block.number_in_stream
+                               + stream->block_number_base;
+
+               iter->block.compressed_stream_offset
+                               = record == 0 ? group->node.compressed_base
+                               : vli_ceil4(group->records[
+                                       record - 1].unpadded_sum);
+               iter->block.uncompressed_stream_offset
+                               = record == 0 ? group->node.uncompressed_base
+                               : group->records[record - 1].uncompressed_sum;
+
+               iter->block.uncompressed_size
+                               = group->records[record].uncompressed_sum
+                               - iter->block.uncompressed_stream_offset;
+               iter->block.unpadded_size
+                               = group->records[record].unpadded_sum
+                               - iter->block.compressed_stream_offset;
+               iter->block.total_size = vli_ceil4(iter->block.unpadded_size);
+
+               iter->block.compressed_stream_offset
+                               += LZMA_STREAM_HEADER_SIZE;
+
+               iter->block.compressed_file_offset
+                               = iter->block.compressed_stream_offset
+                               + iter->stream.compressed_offset;
+               iter->block.uncompressed_file_offset
+                               = iter->block.uncompressed_stream_offset
+                               + iter->stream.uncompressed_offset;
+       }
+
+       return;
+}
+
+
+extern LZMA_API(void)
+lzma_index_iter_init(lzma_index_iter *iter, const lzma_index *i)
+{
+       iter->internal[ITER_INDEX].p = i;
+       lzma_index_iter_rewind(iter);
+       return;
+}
+
+
+extern LZMA_API(void)
+lzma_index_iter_rewind(lzma_index_iter *iter)
+{
+       iter->internal[ITER_STREAM].p = NULL;
+       iter->internal[ITER_GROUP].p = NULL;
+       iter->internal[ITER_RECORD].s = 0;
+       iter->internal[ITER_METHOD].s = ITER_METHOD_NORMAL;
+       return;
+}
+
+
+extern LZMA_API(lzma_bool)
+lzma_index_iter_next(lzma_index_iter *iter, lzma_index_iter_mode mode)
+{
+       // Catch unsupported mode values.
+       if ((unsigned int)(mode) > LZMA_INDEX_ITER_NONEMPTY_BLOCK)
+               return true;
+
+       const lzma_index *i = iter->internal[ITER_INDEX].p;
+       const index_stream *stream = iter->internal[ITER_STREAM].p;
+       const index_group *group = NULL;
+       size_t record = iter->internal[ITER_RECORD].s;
+
+       // If we are being asked for the next Stream, leave group to NULL
+       // so that the rest of the this function thinks that this Stream
+       // has no groups and will thus go to the next Stream.
+       if (mode != LZMA_INDEX_ITER_STREAM) {
+               // Get the pointer to the current group. See iter_set_inf()
+               // for explanation.
+               switch (iter->internal[ITER_METHOD].s) {
+               case ITER_METHOD_NORMAL:
+                       group = iter->internal[ITER_GROUP].p;
+                       break;
+
+               case ITER_METHOD_NEXT:
+                       group = index_tree_next(iter->internal[ITER_GROUP].p);
+                       break;
+
+               case ITER_METHOD_LEFTMOST:
+                       group = (const index_group *)(
+                                       stream->groups.leftmost);
+                       break;
+               }
+       }
+
+again:
+       if (stream == NULL) {
+               // We at the beginning of the lzma_index.
+               // Locate the first Stream.
+               stream = (const index_stream *)(i->streams.leftmost);
+               if (mode >= LZMA_INDEX_ITER_BLOCK) {
+                       // Since we are being asked to return information
+                       // about the first a Block, skip Streams that have
+                       // no Blocks.
+                       while (stream->groups.leftmost == NULL) {
+                               stream = index_tree_next(&stream->node);
+                               if (stream == NULL)
+                                       return true;
+                       }
+               }
+
+               // Start from the first Record in the Stream.
+               group = (const index_group *)(stream->groups.leftmost);
+               record = 0;
+
+       } else if (group != NULL && record < group->last) {
+               // The next Record is in the same group.
+               ++record;
+
+       } else {
+               // This group has no more Records or this Stream has
+               // no Blocks at all.
+               record = 0;
+
+               // If group is not NULL, this Stream has at least one Block
+               // and thus at least one group. Find the next group.
+               if (group != NULL)
+                       group = index_tree_next(&group->node);
+
+               if (group == NULL) {
+                       // This Stream has no more Records. Find the next
+                       // Stream. If we are being asked to return information
+                       // about a Block, we skip empty Streams.
+                       do {
+                               stream = index_tree_next(&stream->node);
+                               if (stream == NULL)
+                                       return true;
+                       } while (mode >= LZMA_INDEX_ITER_BLOCK
+                                       && stream->groups.leftmost == NULL);
+
+                       group = (const index_group *)(
+                                       stream->groups.leftmost);
+               }
+       }
+
+       if (mode == LZMA_INDEX_ITER_NONEMPTY_BLOCK) {
+               // We need to look for the next Block again if this Block
+               // is empty.
+               if (record == 0) {
+                       if (group->node.uncompressed_base
+                                       == group->records[0].uncompressed_sum)
+                               goto again;
+               } else if (group->records[record - 1].uncompressed_sum
+                               == group->records[record].uncompressed_sum) {
+                       goto again;
+               }
+       }
+
+       iter->internal[ITER_STREAM].p = stream;
+       iter->internal[ITER_GROUP].p = group;
+       iter->internal[ITER_RECORD].s = record;
+
+       iter_set_info(iter);
+
+       return false;
+}
+
+
+extern LZMA_API(lzma_bool)
+lzma_index_iter_locate(lzma_index_iter *iter, lzma_vli target)
+{
+       const lzma_index *i = iter->internal[ITER_INDEX].p;
+
+       // If the target is past the end of the file, return immediately.
+       if (i->uncompressed_size <= target)
+               return true;
+
+       // Locate the Stream containing the target offset.
+       const index_stream *stream = index_tree_locate(&i->streams, target);
+       assert(stream != NULL);
+       target -= stream->node.uncompressed_base;
+
+       // Locate the group containing the target offset.
+       const index_group *group = index_tree_locate(&stream->groups, target);
+       assert(group != NULL);
+
+       // Use binary search to locate the exact Record. It is the first
+       // Record whose uncompressed_sum is greater than target.
+       // This is because we want the rightmost Record that fullfills the
+       // search criterion. It is possible that there are empty Blocks;
+       // we don't want to return them.
+       size_t left = 0;
+       size_t right = group->last;
+
+       while (left < right) {
+               const size_t pos = left + (right - left) / 2;
+               if (group->records[pos].uncompressed_sum <= target)
+                       left = pos + 1;
+               else
+                       right = pos;
+       }
+
+       iter->internal[ITER_STREAM].p = stream;
+       iter->internal[ITER_GROUP].p = group;
+       iter->internal[ITER_RECORD].s = left;
+
+       iter_set_info(iter);
+
+       return false;
+}
diff --git a/lzma/common/index.h b/lzma/common/index.h
new file mode 100644 (file)
index 0000000..64e9724
--- /dev/null
@@ -0,0 +1,73 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       index.h
+/// \brief      Handling of Index
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_INDEX_H
+#define LZMA_INDEX_H
+
+#include "common.h"
+
+
+/// Minimum Unpadded Size
+#define UNPADDED_SIZE_MIN LZMA_VLI_C(5)
+
+/// Maximum Unpadded Size
+#define UNPADDED_SIZE_MAX (LZMA_VLI_MAX & ~LZMA_VLI_C(3))
+
+
+/// Get the size of the Index Padding field. This is needed by Index encoder
+/// and decoder, but applications should have no use for this.
+extern uint32_t lzma_index_padding_size(const lzma_index *i);
+
+
+/// Set for how many Records to allocate memory the next time
+/// lzma_index_append() needs to allocate space for a new Record.
+/// This is used only by the Index decoder.
+extern void lzma_index_prealloc(lzma_index *i, lzma_vli records);
+
+
+/// Round the variable-length integer to the next multiple of four.
+static inline lzma_vli
+vli_ceil4(lzma_vli vli)
+{
+       assert(vli <= LZMA_VLI_MAX);
+       return (vli + 3) & ~LZMA_VLI_C(3);
+}
+
+
+/// Calculate the size of the Index field excluding Index Padding
+static inline lzma_vli
+index_size_unpadded(lzma_vli count, lzma_vli index_list_size)
+{
+       // Index Indicator + Number of Records + List of Records + CRC32
+       return 1 + lzma_vli_size(count) + index_list_size + 4;
+}
+
+
+/// Calculate the size of the Index field including Index Padding
+static inline lzma_vli
+index_size(lzma_vli count, lzma_vli index_list_size)
+{
+       return vli_ceil4(index_size_unpadded(count, index_list_size));
+}
+
+
+/// Calculate the total size of the Stream
+static inline lzma_vli
+index_stream_size(lzma_vli blocks_size,
+               lzma_vli count, lzma_vli index_list_size)
+{
+       return LZMA_STREAM_HEADER_SIZE + blocks_size
+                       + index_size(count, index_list_size)
+                       + LZMA_STREAM_HEADER_SIZE;
+}
+
+#endif
diff --git a/lzma/common/index_decoder.c b/lzma/common/index_decoder.c
new file mode 100644 (file)
index 0000000..795d183
--- /dev/null
@@ -0,0 +1,345 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       index_decoder.c
+/// \brief      Decodes the Index field
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "index.h"
+#include "check.h"
+
+
+struct lzma_coder_s {
+       enum {
+               SEQ_INDICATOR,
+               SEQ_COUNT,
+               SEQ_MEMUSAGE,
+               SEQ_UNPADDED,
+               SEQ_UNCOMPRESSED,
+               SEQ_PADDING_INIT,
+               SEQ_PADDING,
+               SEQ_CRC32,
+       } sequence;
+
+       /// Memory usage limit
+       uint64_t memlimit;
+
+       /// Target Index
+       lzma_index *index;
+
+       /// Pointer give by the application, which is set after
+       /// successful decoding.
+       lzma_index **index_ptr;
+
+       /// Number of Records left to decode.
+       lzma_vli count;
+
+       /// The most recent Unpadded Size field
+       lzma_vli unpadded_size;
+
+       /// The most recent Uncompressed Size field
+       lzma_vli uncompressed_size;
+
+       /// Position in integers
+       size_t pos;
+
+       /// CRC32 of the List of Records field
+       uint32_t crc32;
+};
+
+
+static lzma_ret
+index_decode(lzma_coder *coder, const lzma_allocator *allocator,
+               const uint8_t *restrict in, size_t *restrict in_pos,
+               size_t in_size,
+               uint8_t *restrict out lzma_attribute((__unused__)),
+               size_t *restrict out_pos lzma_attribute((__unused__)),
+               size_t out_size lzma_attribute((__unused__)),
+               lzma_action action lzma_attribute((__unused__)))
+{
+       // Similar optimization as in index_encoder.c
+       const size_t in_start = *in_pos;
+       lzma_ret ret = LZMA_OK;
+
+       while (*in_pos < in_size)
+       switch (coder->sequence) {
+       case SEQ_INDICATOR:
+               // Return LZMA_DATA_ERROR instead of e.g. LZMA_PROG_ERROR or
+               // LZMA_FORMAT_ERROR, because a typical usage case for Index
+               // decoder is when parsing the Stream backwards. If seeking
+               // backward from the Stream Footer gives us something that
+               // doesn't begin with Index Indicator, the file is considered
+               // corrupt, not "programming error" or "unrecognized file
+               // format". One could argue that the application should
+               // verify the Index Indicator before trying to decode the
+               // Index, but well, I suppose it is simpler this way.
+               if (in[(*in_pos)++] != 0x00)
+                       return LZMA_DATA_ERROR;
+
+               coder->sequence = SEQ_COUNT;
+               break;
+
+       case SEQ_COUNT:
+               ret = lzma_vli_decode(&coder->count, &coder->pos,
+                               in, in_pos, in_size);
+               if (ret != LZMA_STREAM_END)
+                       goto out;
+
+               coder->pos = 0;
+               coder->sequence = SEQ_MEMUSAGE;
+
+       // Fall through
+
+       case SEQ_MEMUSAGE:
+               if (lzma_index_memusage(1, coder->count) > coder->memlimit) {
+                       ret = LZMA_MEMLIMIT_ERROR;
+                       goto out;
+               }
+
+               // Tell the Index handling code how many Records this
+               // Index has to allow it to allocate memory more efficiently.
+               lzma_index_prealloc(coder->index, coder->count);
+
+               ret = LZMA_OK;
+               coder->sequence = coder->count == 0
+                               ? SEQ_PADDING_INIT : SEQ_UNPADDED;
+               break;
+
+       case SEQ_UNPADDED:
+       case SEQ_UNCOMPRESSED: {
+               lzma_vli *size = coder->sequence == SEQ_UNPADDED
+                               ? &coder->unpadded_size
+                               : &coder->uncompressed_size;
+
+               ret = lzma_vli_decode(size, &coder->pos,
+                               in, in_pos, in_size);
+               if (ret != LZMA_STREAM_END)
+                       goto out;
+
+               ret = LZMA_OK;
+               coder->pos = 0;
+
+               if (coder->sequence == SEQ_UNPADDED) {
+                       // Validate that encoded Unpadded Size isn't too small
+                       // or too big.
+                       if (coder->unpadded_size < UNPADDED_SIZE_MIN
+                                       || coder->unpadded_size
+                                               > UNPADDED_SIZE_MAX)
+                               return LZMA_DATA_ERROR;
+
+                       coder->sequence = SEQ_UNCOMPRESSED;
+               } else {
+                       // Add the decoded Record to the Index.
+                       return_if_error(lzma_index_append(
+                                       coder->index, allocator,
+                                       coder->unpadded_size,
+                                       coder->uncompressed_size));
+
+                       // Check if this was the last Record.
+                       coder->sequence = --coder->count == 0
+                                       ? SEQ_PADDING_INIT
+                                       : SEQ_UNPADDED;
+               }
+
+               break;
+       }
+
+       case SEQ_PADDING_INIT:
+               coder->pos = lzma_index_padding_size(coder->index);
+               coder->sequence = SEQ_PADDING;
+
+       // Fall through
+
+       case SEQ_PADDING:
+               if (coder->pos > 0) {
+                       --coder->pos;
+                       if (in[(*in_pos)++] != 0x00)
+                               return LZMA_DATA_ERROR;
+
+                       break;
+               }
+
+               // Finish the CRC32 calculation.
+               coder->crc32 = lzma_crc32(in + in_start,
+                               *in_pos - in_start, coder->crc32);
+
+               coder->sequence = SEQ_CRC32;
+
+       // Fall through
+
+       case SEQ_CRC32:
+               do {
+                       if (*in_pos == in_size)
+                               return LZMA_OK;
+
+                       if (((coder->crc32 >> (coder->pos * 8)) & 0xFF)
+                                       != in[(*in_pos)++])
+                               return LZMA_DATA_ERROR;
+
+               } while (++coder->pos < 4);
+
+               // Decoding was successful, now we can let the application
+               // see the decoded Index.
+               *coder->index_ptr = coder->index;
+
+               // Make index NULL so we don't free it unintentionally.
+               coder->index = NULL;
+
+               return LZMA_STREAM_END;
+
+       default:
+               assert(0);
+               return LZMA_PROG_ERROR;
+       }
+
+out:
+       // Update the CRC32,
+       coder->crc32 = lzma_crc32(in + in_start,
+                       *in_pos - in_start, coder->crc32);
+
+       return ret;
+}
+
+
+static void
+index_decoder_end(lzma_coder *coder, const lzma_allocator *allocator)
+{
+       lzma_index_end(coder->index, allocator);
+       lzma_free(coder, allocator);
+       return;
+}
+
+
+static lzma_ret
+index_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
+               uint64_t *old_memlimit, uint64_t new_memlimit)
+{
+       *memusage = lzma_index_memusage(1, coder->count);
+       *old_memlimit = coder->memlimit;
+
+       if (new_memlimit != 0) {
+               if (new_memlimit < *memusage)
+                       return LZMA_MEMLIMIT_ERROR;
+
+               coder->memlimit = new_memlimit;
+       }
+
+       return LZMA_OK;
+}
+
+
+static lzma_ret
+index_decoder_reset(lzma_coder *coder, const lzma_allocator *allocator,
+               lzma_index **i, uint64_t memlimit)
+{
+       // Remember the pointer given by the application. We will set it
+       // to point to the decoded Index only if decoding is successful.
+       // Before that, keep it NULL so that applications can always safely
+       // pass it to lzma_index_end() no matter did decoding succeed or not.
+       coder->index_ptr = i;
+       *i = NULL;
+
+       // We always allocate a new lzma_index.
+       coder->index = lzma_index_init(allocator);
+       if (coder->index == NULL)
+               return LZMA_MEM_ERROR;
+
+       // Initialize the rest.
+       coder->sequence = SEQ_INDICATOR;
+       coder->memlimit = memlimit;
+       coder->count = 0; // Needs to be initialized due to _memconfig().
+       coder->pos = 0;
+       coder->crc32 = 0;
+
+       return LZMA_OK;
+}
+
+
+static lzma_ret
+index_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
+               lzma_index **i, uint64_t memlimit)
+{
+       lzma_next_coder_init(&index_decoder_init, next, allocator);
+
+       if (i == NULL || memlimit == 0)
+               return LZMA_PROG_ERROR;
+
+       if (next->coder == NULL) {
+               next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+               if (next->coder == NULL)
+                       return LZMA_MEM_ERROR;
+
+               next->code = &index_decode;
+               next->end = &index_decoder_end;
+               next->memconfig = &index_decoder_memconfig;
+               next->coder->index = NULL;
+       } else {
+               lzma_index_end(next->coder->index, allocator);
+       }
+
+       return index_decoder_reset(next->coder, allocator, i, memlimit);
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_index_decoder(lzma_stream *strm, lzma_index **i, uint64_t memlimit)
+{
+       lzma_next_strm_init(index_decoder_init, strm, i, memlimit);
+
+       strm->internal->supported_actions[LZMA_RUN] = true;
+       strm->internal->supported_actions[LZMA_FINISH] = true;
+
+       return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_index_buffer_decode(lzma_index **i, uint64_t *memlimit,
+               const lzma_allocator *allocator,
+               const uint8_t *in, size_t *in_pos, size_t in_size)
+{
+       // Sanity checks
+       if (i == NULL || memlimit == NULL
+                       || in == NULL || in_pos == NULL || *in_pos > in_size)
+               return LZMA_PROG_ERROR;
+
+       // Initialize the decoder.
+       lzma_coder coder;
+       return_if_error(index_decoder_reset(&coder, allocator, i, *memlimit));
+
+       // Store the input start position so that we can restore it in case
+       // of an error.
+       const size_t in_start = *in_pos;
+
+       // Do the actual decoding.
+       lzma_ret ret = index_decode(&coder, allocator, in, in_pos, in_size,
+                       NULL, NULL, 0, LZMA_RUN);
+
+       if (ret == LZMA_STREAM_END) {
+               ret = LZMA_OK;
+       } else {
+               // Something went wrong, free the Index structure and restore
+               // the input position.
+               lzma_index_end(coder.index, allocator);
+               *in_pos = in_start;
+
+               if (ret == LZMA_OK) {
+                       // The input is truncated or otherwise corrupt.
+                       // Use LZMA_DATA_ERROR instead of LZMA_BUF_ERROR
+                       // like lzma_vli_decode() does in single-call mode.
+                       ret = LZMA_DATA_ERROR;
+
+               } else if (ret == LZMA_MEMLIMIT_ERROR) {
+                       // Tell the caller how much memory would have
+                       // been needed.
+                       *memlimit = lzma_index_memusage(1, coder.count);
+               }
+       }
+
+       return ret;
+}
diff --git a/lzma/common/index_encoder.c b/lzma/common/index_encoder.c
new file mode 100644 (file)
index 0000000..d25ac7d
--- /dev/null
@@ -0,0 +1,254 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       index_encoder.c
+/// \brief      Encodes the Index field
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "index_encoder.h"
+#include "index.h"
+#include "check.h"
+
+
+struct lzma_coder_s {
+       enum {
+               SEQ_INDICATOR,
+               SEQ_COUNT,
+               SEQ_UNPADDED,
+               SEQ_UNCOMPRESSED,
+               SEQ_NEXT,
+               SEQ_PADDING,
+               SEQ_CRC32,
+       } sequence;
+
+       /// Index being encoded
+       const lzma_index *index;
+
+       /// Iterator for the Index being encoded
+       lzma_index_iter iter;
+
+       /// Position in integers
+       size_t pos;
+
+       /// CRC32 of the List of Records field
+       uint32_t crc32;
+};
+
+
+static lzma_ret
+index_encode(lzma_coder *coder,
+               const lzma_allocator *allocator lzma_attribute((__unused__)),
+               const uint8_t *restrict in lzma_attribute((__unused__)),
+               size_t *restrict in_pos lzma_attribute((__unused__)),
+               size_t in_size lzma_attribute((__unused__)),
+               uint8_t *restrict out, size_t *restrict out_pos,
+               size_t out_size,
+               lzma_action action lzma_attribute((__unused__)))
+{
+       // Position where to start calculating CRC32. The idea is that we
+       // need to call lzma_crc32() only once per call to index_encode().
+       const size_t out_start = *out_pos;
+
+       // Return value to use if we return at the end of this function.
+       // We use "goto out" to jump out of the while-switch construct
+       // instead of returning directly, because that way we don't need
+       // to copypaste the lzma_crc32() call to many places.
+       lzma_ret ret = LZMA_OK;
+
+       while (*out_pos < out_size)
+       switch (coder->sequence) {
+       case SEQ_INDICATOR:
+               out[*out_pos] = 0x00;
+               ++*out_pos;
+               coder->sequence = SEQ_COUNT;
+               break;
+
+       case SEQ_COUNT: {
+               const lzma_vli count = lzma_index_block_count(coder->index);
+               ret = lzma_vli_encode(count, &coder->pos,
+                               out, out_pos, out_size);
+               if (ret != LZMA_STREAM_END)
+                       goto out;
+
+               ret = LZMA_OK;
+               coder->pos = 0;
+               coder->sequence = SEQ_NEXT;
+               break;
+       }
+
+       case SEQ_NEXT:
+               if (lzma_index_iter_next(
+                               &coder->iter, LZMA_INDEX_ITER_BLOCK)) {
+                       // Get the size of the Index Padding field.
+                       coder->pos = lzma_index_padding_size(coder->index);
+                       assert(coder->pos <= 3);
+                       coder->sequence = SEQ_PADDING;
+                       break;
+               }
+
+               coder->sequence = SEQ_UNPADDED;
+
+       // Fall through
+
+       case SEQ_UNPADDED:
+       case SEQ_UNCOMPRESSED: {
+               const lzma_vli size = coder->sequence == SEQ_UNPADDED
+                               ? coder->iter.block.unpadded_size
+                               : coder->iter.block.uncompressed_size;
+
+               ret = lzma_vli_encode(size, &coder->pos,
+                               out, out_pos, out_size);
+               if (ret != LZMA_STREAM_END)
+                       goto out;
+
+               ret = LZMA_OK;
+               coder->pos = 0;
+
+               // Advance to SEQ_UNCOMPRESSED or SEQ_NEXT.
+               ++coder->sequence;
+               break;
+       }
+
+       case SEQ_PADDING:
+               if (coder->pos > 0) {
+                       --coder->pos;
+                       out[(*out_pos)++] = 0x00;
+                       break;
+               }
+
+               // Finish the CRC32 calculation.
+               coder->crc32 = lzma_crc32(out + out_start,
+                               *out_pos - out_start, coder->crc32);
+
+               coder->sequence = SEQ_CRC32;
+
+       // Fall through
+
+       case SEQ_CRC32:
+               // We don't use the main loop, because we don't want
+               // coder->crc32 to be touched anymore.
+               do {
+                       if (*out_pos == out_size)
+                               return LZMA_OK;
+
+                       out[*out_pos] = (coder->crc32 >> (coder->pos * 8))
+                                       & 0xFF;
+                       ++*out_pos;
+
+               } while (++coder->pos < 4);
+
+               return LZMA_STREAM_END;
+
+       default:
+               assert(0);
+               return LZMA_PROG_ERROR;
+       }
+
+out:
+       // Update the CRC32.
+       coder->crc32 = lzma_crc32(out + out_start,
+                       *out_pos - out_start, coder->crc32);
+
+       return ret;
+}
+
+
+static void
+index_encoder_end(lzma_coder *coder, const lzma_allocator *allocator)
+{
+       lzma_free(coder, allocator);
+       return;
+}
+
+
+static void
+index_encoder_reset(lzma_coder *coder, const lzma_index *i)
+{
+       lzma_index_iter_init(&coder->iter, i);
+
+       coder->sequence = SEQ_INDICATOR;
+       coder->index = i;
+       coder->pos = 0;
+       coder->crc32 = 0;
+
+       return;
+}
+
+
+extern lzma_ret
+lzma_index_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
+               const lzma_index *i)
+{
+       lzma_next_coder_init(&lzma_index_encoder_init, next, allocator);
+
+       if (i == NULL)
+               return LZMA_PROG_ERROR;
+
+       if (next->coder == NULL) {
+               next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+               if (next->coder == NULL)
+                       return LZMA_MEM_ERROR;
+
+               next->code = &index_encode;
+               next->end = &index_encoder_end;
+       }
+
+       index_encoder_reset(next->coder, i);
+
+       return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_index_encoder(lzma_stream *strm, const lzma_index *i)
+{
+       lzma_next_strm_init(lzma_index_encoder_init, strm, i);
+
+       strm->internal->supported_actions[LZMA_RUN] = true;
+       strm->internal->supported_actions[LZMA_FINISH] = true;
+
+       return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_index_buffer_encode(const lzma_index *i,
+               uint8_t *out, size_t *out_pos, size_t out_size)
+{
+       // Validate the arguments.
+       if (i == NULL || out == NULL || out_pos == NULL || *out_pos > out_size)
+               return LZMA_PROG_ERROR;
+
+       // Don't try to encode if there's not enough output space.
+       if (out_size - *out_pos < lzma_index_size(i))
+               return LZMA_BUF_ERROR;
+
+       // The Index encoder needs just one small data structure so we can
+       // allocate it on stack.
+       lzma_coder coder;
+       index_encoder_reset(&coder, i);
+
+       // Do the actual encoding. This should never fail, but store
+       // the original *out_pos just in case.
+       const size_t out_start = *out_pos;
+       lzma_ret ret = index_encode(&coder, NULL, NULL, NULL, 0,
+                       out, out_pos, out_size, LZMA_RUN);
+
+       if (ret == LZMA_STREAM_END) {
+               ret = LZMA_OK;
+       } else {
+               // We should never get here, but just in case, restore the
+               // output position and set the error accordingly if something
+               // goes wrong and debugging isn't enabled.
+               assert(0);
+               *out_pos = out_start;
+               ret = LZMA_PROG_ERROR;
+       }
+
+       return ret;
+}
diff --git a/lzma/common/index_encoder.h b/lzma/common/index_encoder.h
new file mode 100644 (file)
index 0000000..4d55cd1
--- /dev/null
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       index_encoder.h
+/// \brief      Encodes the Index field
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_INDEX_ENCODER_H
+#define LZMA_INDEX_ENCODER_H
+
+#include "common.h"
+
+
+extern lzma_ret lzma_index_encoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator, const lzma_index *i);
+
+
+#endif
diff --git a/lzma/common/index_hash.c b/lzma/common/index_hash.c
new file mode 100644 (file)
index 0000000..d7a0344
--- /dev/null
@@ -0,0 +1,334 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       index_hash.c
+/// \brief      Validates Index by using a hash function
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+#include "index.h"
+#include "check.h"
+
+
+typedef struct {
+       /// Sum of the Block sizes (including Block Padding)
+       lzma_vli blocks_size;
+
+       /// Sum of the Uncompressed Size fields
+       lzma_vli uncompressed_size;
+
+       /// Number of Records
+       lzma_vli count;
+
+       /// Size of the List of Index Records as bytes
+       lzma_vli index_list_size;
+
+       /// Check calculated from Unpadded Sizes and Uncompressed Sizes.
+       lzma_check_state check;
+
+} lzma_index_hash_info;
+
+
+struct lzma_index_hash_s {
+       enum {
+               SEQ_BLOCK,
+               SEQ_COUNT,
+               SEQ_UNPADDED,
+               SEQ_UNCOMPRESSED,
+               SEQ_PADDING_INIT,
+               SEQ_PADDING,
+               SEQ_CRC32,
+       } sequence;
+
+       /// Information collected while decoding the actual Blocks.
+       lzma_index_hash_info blocks;
+
+       /// Information collected from the Index field.
+       lzma_index_hash_info records;
+
+       /// Number of Records not fully decoded
+       lzma_vli remaining;
+
+       /// Unpadded Size currently being read from an Index Record.
+       lzma_vli unpadded_size;
+
+       /// Uncompressed Size currently being read from an Index Record.
+       lzma_vli uncompressed_size;
+
+       /// Position in variable-length integers when decoding them from
+       /// the List of Records.
+       size_t pos;
+
+       /// CRC32 of the Index
+       uint32_t crc32;
+};
+
+
+extern LZMA_API(lzma_index_hash *)
+lzma_index_hash_init(lzma_index_hash *index_hash,
+               const lzma_allocator *allocator)
+{
+       if (index_hash == NULL) {
+               index_hash = lzma_alloc(sizeof(lzma_index_hash), allocator);
+               if (index_hash == NULL)
+                       return NULL;
+       }
+
+       index_hash->sequence = SEQ_BLOCK;
+       index_hash->blocks.blocks_size = 0;
+       index_hash->blocks.uncompressed_size = 0;
+       index_hash->blocks.count = 0;
+       index_hash->blocks.index_list_size = 0;
+       index_hash->records.blocks_size = 0;
+       index_hash->records.uncompressed_size = 0;
+       index_hash->records.count = 0;
+       index_hash->records.index_list_size = 0;
+       index_hash->unpadded_size = 0;
+       index_hash->uncompressed_size = 0;
+       index_hash->pos = 0;
+       index_hash->crc32 = 0;
+
+       // These cannot fail because LZMA_CHECK_BEST is known to be supported.
+       (void)lzma_check_init(&index_hash->blocks.check, LZMA_CHECK_BEST);
+       (void)lzma_check_init(&index_hash->records.check, LZMA_CHECK_BEST);
+
+       return index_hash;
+}
+
+
+extern LZMA_API(void)
+lzma_index_hash_end(lzma_index_hash *index_hash,
+               const lzma_allocator *allocator)
+{
+       lzma_free(index_hash, allocator);
+       return;
+}
+
+
+extern LZMA_API(lzma_vli)
+lzma_index_hash_size(const lzma_index_hash *index_hash)
+{
+       // Get the size of the Index from ->blocks instead of ->records for
+       // cases where application wants to know the Index Size before
+       // decoding the Index.
+       return index_size(index_hash->blocks.count,
+                       index_hash->blocks.index_list_size);
+}
+
+
+/// Updates the sizes and the hash without any validation.
+static lzma_ret
+hash_append(lzma_index_hash_info *info, lzma_vli unpadded_size,
+               lzma_vli uncompressed_size)
+{
+       info->blocks_size += vli_ceil4(unpadded_size);
+       info->uncompressed_size += uncompressed_size;
+       info->index_list_size += lzma_vli_size(unpadded_size)
+                       + lzma_vli_size(uncompressed_size);
+       ++info->count;
+
+       const lzma_vli sizes[2] = { unpadded_size, uncompressed_size };
+       lzma_check_update(&info->check, LZMA_CHECK_BEST,
+                       (const uint8_t *)(sizes), sizeof(sizes));
+
+       return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_index_hash_append(lzma_index_hash *index_hash, lzma_vli unpadded_size,
+               lzma_vli uncompressed_size)
+{
+       // Validate the arguments.
+       if (index_hash->sequence != SEQ_BLOCK
+                       || unpadded_size < UNPADDED_SIZE_MIN
+                       || unpadded_size > UNPADDED_SIZE_MAX
+                       || uncompressed_size > LZMA_VLI_MAX)
+               return LZMA_PROG_ERROR;
+
+       // Update the hash.
+       return_if_error(hash_append(&index_hash->blocks,
+                       unpadded_size, uncompressed_size));
+
+       // Validate the properties of *info are still in allowed limits.
+       if (index_hash->blocks.blocks_size > LZMA_VLI_MAX
+                       || index_hash->blocks.uncompressed_size > LZMA_VLI_MAX
+                       || index_size(index_hash->blocks.count,
+                                       index_hash->blocks.index_list_size)
+                               > LZMA_BACKWARD_SIZE_MAX
+                       || index_stream_size(index_hash->blocks.blocks_size,
+                                       index_hash->blocks.count,
+                                       index_hash->blocks.index_list_size)
+                               > LZMA_VLI_MAX)
+               return LZMA_DATA_ERROR;
+
+       return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_index_hash_decode(lzma_index_hash *index_hash, const uint8_t *in,
+               size_t *in_pos, size_t in_size)
+{
+       // Catch zero input buffer here, because in contrast to Index encoder
+       // and decoder functions, applications call this function directly
+       // instead of via lzma_code(), which does the buffer checking.
+       if (*in_pos >= in_size)
+               return LZMA_BUF_ERROR;
+
+       // NOTE: This function has many similarities to index_encode() and
+       // index_decode() functions found from index_encoder.c and
+       // index_decoder.c. See the comments especially in index_encoder.c.
+       const size_t in_start = *in_pos;
+       lzma_ret ret = LZMA_OK;
+
+       while (*in_pos < in_size)
+       switch (index_hash->sequence) {
+       case SEQ_BLOCK:
+               // Check the Index Indicator is present.
+               if (in[(*in_pos)++] != 0x00)
+                       return LZMA_DATA_ERROR;
+
+               index_hash->sequence = SEQ_COUNT;
+               break;
+
+       case SEQ_COUNT: {
+               ret = lzma_vli_decode(&index_hash->remaining,
+                               &index_hash->pos, in, in_pos, in_size);
+               if (ret != LZMA_STREAM_END)
+                       goto out;
+
+               // The count must match the count of the Blocks decoded.
+               if (index_hash->remaining != index_hash->blocks.count)
+                       return LZMA_DATA_ERROR;
+
+               ret = LZMA_OK;
+               index_hash->pos = 0;
+
+               // Handle the special case when there are no Blocks.
+               index_hash->sequence = index_hash->remaining == 0
+                               ? SEQ_PADDING_INIT : SEQ_UNPADDED;
+               break;
+       }
+
+       case SEQ_UNPADDED:
+       case SEQ_UNCOMPRESSED: {
+               lzma_vli *size = index_hash->sequence == SEQ_UNPADDED
+                               ? &index_hash->unpadded_size
+                               : &index_hash->uncompressed_size;
+
+               ret = lzma_vli_decode(size, &index_hash->pos,
+                               in, in_pos, in_size);
+               if (ret != LZMA_STREAM_END)
+                       goto out;
+
+               ret = LZMA_OK;
+               index_hash->pos = 0;
+
+               if (index_hash->sequence == SEQ_UNPADDED) {
+                       if (index_hash->unpadded_size < UNPADDED_SIZE_MIN
+                                       || index_hash->unpadded_size
+                                               > UNPADDED_SIZE_MAX)
+                               return LZMA_DATA_ERROR;
+
+                       index_hash->sequence = SEQ_UNCOMPRESSED;
+               } else {
+                       // Update the hash.
+                       return_if_error(hash_append(&index_hash->records,
+                                       index_hash->unpadded_size,
+                                       index_hash->uncompressed_size));
+
+                       // Verify that we don't go over the known sizes. Note
+                       // that this validation is simpler than the one used
+                       // in lzma_index_hash_append(), because here we know
+                       // that values in index_hash->blocks are already
+                       // validated and we are fine as long as we don't
+                       // exceed them in index_hash->records.
+                       if (index_hash->blocks.blocks_size
+                                       < index_hash->records.blocks_size
+                                       || index_hash->blocks.uncompressed_size
+                                       < index_hash->records.uncompressed_size
+                                       || index_hash->blocks.index_list_size
+                                       < index_hash->records.index_list_size)
+                               return LZMA_DATA_ERROR;
+
+                       // Check if this was the last Record.
+                       index_hash->sequence = --index_hash->remaining == 0
+                                       ? SEQ_PADDING_INIT : SEQ_UNPADDED;
+               }
+
+               break;
+       }
+
+       case SEQ_PADDING_INIT:
+               index_hash->pos = (LZMA_VLI_C(4) - index_size_unpadded(
+                               index_hash->records.count,
+                               index_hash->records.index_list_size)) & 3;
+               index_hash->sequence = SEQ_PADDING;
+
+       // Fall through
+
+       case SEQ_PADDING:
+               if (index_hash->pos > 0) {
+                       --index_hash->pos;
+                       if (in[(*in_pos)++] != 0x00)
+                               return LZMA_DATA_ERROR;
+
+                       break;
+               }
+
+               // Compare the sizes.
+               if (index_hash->blocks.blocks_size
+                               != index_hash->records.blocks_size
+                               || index_hash->blocks.uncompressed_size
+                               != index_hash->records.uncompressed_size
+                               || index_hash->blocks.index_list_size
+                               != index_hash->records.index_list_size)
+                       return LZMA_DATA_ERROR;
+
+               // Finish the hashes and compare them.
+               lzma_check_finish(&index_hash->blocks.check, LZMA_CHECK_BEST);
+               lzma_check_finish(&index_hash->records.check, LZMA_CHECK_BEST);
+               if (memcmp(index_hash->blocks.check.buffer.u8,
+                               index_hash->records.check.buffer.u8,
+                               lzma_check_size(LZMA_CHECK_BEST)) != 0)
+                       return LZMA_DATA_ERROR;
+
+               // Finish the CRC32 calculation.
+               index_hash->crc32 = lzma_crc32(in + in_start,
+                               *in_pos - in_start, index_hash->crc32);
+
+               index_hash->sequence = SEQ_CRC32;
+
+       // Fall through
+
+       case SEQ_CRC32:
+               do {
+                       if (*in_pos == in_size)
+                               return LZMA_OK;
+
+                       if (((index_hash->crc32 >> (index_hash->pos * 8))
+                                       & 0xFF) != in[(*in_pos)++])
+                               return LZMA_DATA_ERROR;
+
+               } while (++index_hash->pos < 4);
+
+               return LZMA_STREAM_END;
+
+       default:
+               assert(0);
+               return LZMA_PROG_ERROR;
+       }
+
+out:
+       // Update the CRC32,
+       index_hash->crc32 = lzma_crc32(in + in_start,
+                       *in_pos - in_start, index_hash->crc32);
+
+       return ret;
+}
diff --git a/lzma/common/memcmplen.h b/lzma/common/memcmplen.h
new file mode 100644 (file)
index 0000000..c1efc9e
--- /dev/null
@@ -0,0 +1,175 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       memcmplen.h
+/// \brief      Optimized comparison of two buffers
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_MEMCMPLEN_H
+#define LZMA_MEMCMPLEN_H
+
+#include "common.h"
+
+#ifdef HAVE_IMMINTRIN_H
+#      include <immintrin.h>
+#endif
+
+
+/// Find out how many equal bytes the two buffers have.
+///
+/// \param      buf1    First buffer
+/// \param      buf2    Second buffer
+/// \param      len     How many bytes have already been compared and will
+///                     be assumed to match
+/// \param      limit   How many bytes to compare at most, including the
+///                     already-compared bytes. This must be significantly
+///                     smaller than UINT32_MAX to avoid integer overflows.
+///                     Up to LZMA_MEMCMPLEN_EXTRA bytes may be read past
+///                     the specified limit from both buf1 and buf2.
+///
+/// \return     Number of equal bytes in the buffers is returned.
+///             This is always at least len and at most limit.
+///
+/// \note       LZMA_MEMCMPLEN_EXTRA defines how many extra bytes may be read.
+///             It's rounded up to 2^n. This extra amount needs to be
+///             allocated in the buffers being used. It needs to be
+///             initialized too to keep Valgrind quiet.
+static inline uint32_t lzma_attribute((__always_inline__))
+lzma_memcmplen(const uint8_t *buf1, const uint8_t *buf2,
+               uint32_t len, uint32_t limit)
+{
+       assert(len <= limit);
+       assert(limit <= UINT32_MAX / 2);
+
+#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \
+               && ((TUKLIB_GNUC_REQ(3, 4) && defined(__x86_64__)) \
+                       || (defined(__INTEL_COMPILER) && defined(__x86_64__)) \
+                       || (defined(__INTEL_COMPILER) && defined(_M_X64)) \
+                       || (defined(_MSC_VER) && defined(_M_X64)))
+       // NOTE: This will use 64-bit unaligned access which
+       // TUKLIB_FAST_UNALIGNED_ACCESS wasn't meant to permit, but
+       // it's convenient here at least as long as it's x86-64 only.
+       //
+       // I keep this x86-64 only for now since that's where I know this
+       // to be a good method. This may be fine on other 64-bit CPUs too.
+       // On big endian one should use xor instead of subtraction and switch
+       // to __builtin_clzll().
+#define LZMA_MEMCMPLEN_EXTRA 8
+       while (len < limit) {
+               const uint64_t x = *(const uint64_t *)(buf1 + len)
+                               - *(const uint64_t *)(buf2 + len);
+               if (x != 0) {
+#      if defined(_M_X64) // MSVC or Intel C compiler on Windows
+                       unsigned long tmp;
+                       _BitScanForward64(&tmp, x);
+                       len += (uint32_t)tmp >> 3;
+#      else // GCC, clang, or Intel C compiler
+                       len += (uint32_t)__builtin_ctzll(x) >> 3;
+#      endif
+                       return my_min(len, limit);
+               }
+
+               len += 8;
+       }
+
+       return limit;
+
+#elif defined(TUKLIB_FAST_UNALIGNED_ACCESS) \
+               && defined(HAVE__MM_MOVEMASK_EPI8) \
+               && ((defined(__GNUC__) && defined(__SSE2_MATH__)) \
+                       || (defined(__INTEL_COMPILER) && defined(__SSE2__)) \
+                       || (defined(_MSC_VER) && defined(_M_IX86_FP) \
+                               && _M_IX86_FP >= 2))
+       // NOTE: Like above, this will use 128-bit unaligned access which
+       // TUKLIB_FAST_UNALIGNED_ACCESS wasn't meant to permit.
+       //
+       // SSE2 version for 32-bit and 64-bit x86. On x86-64 the above
+       // version is sometimes significantly faster and sometimes
+       // slightly slower than this SSE2 version, so this SSE2
+       // version isn't used on x86-64.
+#      define LZMA_MEMCMPLEN_EXTRA 16
+       while (len < limit) {
+               const uint32_t x = 0xFFFF ^ _mm_movemask_epi8(_mm_cmpeq_epi8(
+                       _mm_loadu_si128((const __m128i *)(buf1 + len)),
+                       _mm_loadu_si128((const __m128i *)(buf2 + len))));
+
+               if (x != 0) {
+#      if defined(__INTEL_COMPILER)
+                       len += _bit_scan_forward(x);
+#      elif defined(_MSC_VER)
+                       unsigned long tmp;
+                       _BitScanForward(&tmp, x);
+                       len += tmp;
+#      else
+                       len += __builtin_ctz(x);
+#      endif
+                       return my_min(len, limit);
+               }
+
+               len += 16;
+       }
+
+       return limit;
+
+#elif defined(TUKLIB_FAST_UNALIGNED_ACCESS) && !defined(WORDS_BIGENDIAN)
+       // Generic 32-bit little endian method
+#      define LZMA_MEMCMPLEN_EXTRA 4
+       while (len < limit) {
+               uint32_t x = *(const uint32_t *)(buf1 + len)
+                               - *(const uint32_t *)(buf2 + len);
+               if (x != 0) {
+                       if ((x & 0xFFFF) == 0) {
+                               len += 2;
+                               x >>= 16;
+                       }
+
+                       if ((x & 0xFF) == 0)
+                               ++len;
+
+                       return my_min(len, limit);
+               }
+
+               len += 4;
+       }
+
+       return limit;
+
+#elif defined(TUKLIB_FAST_UNALIGNED_ACCESS) && defined(WORDS_BIGENDIAN)
+       // Generic 32-bit big endian method
+#      define LZMA_MEMCMPLEN_EXTRA 4
+       while (len < limit) {
+               uint32_t x = *(const uint32_t *)(buf1 + len)
+                               ^ *(const uint32_t *)(buf2 + len);
+               if (x != 0) {
+                       if ((x & 0xFFFF0000) == 0) {
+                               len += 2;
+                               x <<= 16;
+                       }
+
+                       if ((x & 0xFF000000) == 0)
+                               ++len;
+
+                       return my_min(len, limit);
+               }
+
+               len += 4;
+       }
+
+       return limit;
+
+#else
+       // Simple portable version that doesn't use unaligned access.
+#      define LZMA_MEMCMPLEN_EXTRA 0
+       while (len < limit && buf1[len] == buf2[len])
+               ++len;
+
+       return len;
+#endif
+}
+
+#endif
diff --git a/lzma/common/outqueue.c b/lzma/common/outqueue.c
new file mode 100644 (file)
index 0000000..2dc8a38
--- /dev/null
@@ -0,0 +1,184 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       outqueue.c
+/// \brief      Output queue handling in multithreaded coding
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "outqueue.h"
+
+
+/// This is to ease integer overflow checking: We may allocate up to
+/// 2 * LZMA_THREADS_MAX buffers and we need some extra memory for other
+/// data structures (that's the second /2).
+#define BUF_SIZE_MAX (UINT64_MAX / LZMA_THREADS_MAX / 2 / 2)
+
+
+static lzma_ret
+get_options(uint64_t *bufs_alloc_size, uint32_t *bufs_count,
+               uint64_t buf_size_max, uint32_t threads)
+{
+       if (threads > LZMA_THREADS_MAX || buf_size_max > BUF_SIZE_MAX)
+               return LZMA_OPTIONS_ERROR;
+
+       // The number of buffers is twice the number of threads.
+       // This wastes RAM but keeps the threads busy when buffers
+       // finish out of order.
+       //
+       // NOTE: If this is changed, update BUF_SIZE_MAX too.
+       *bufs_count = threads * 2;
+       *bufs_alloc_size = *bufs_count * buf_size_max;
+
+       return LZMA_OK;
+}
+
+
+extern uint64_t
+lzma_outq_memusage(uint64_t buf_size_max, uint32_t threads)
+{
+       uint64_t bufs_alloc_size;
+       uint32_t bufs_count;
+
+       if (get_options(&bufs_alloc_size, &bufs_count, buf_size_max, threads)
+                       != LZMA_OK)
+               return UINT64_MAX;
+
+       return sizeof(lzma_outq) + bufs_count * sizeof(lzma_outbuf)
+                       + bufs_alloc_size;
+}
+
+
+extern lzma_ret
+lzma_outq_init(lzma_outq *outq, const lzma_allocator *allocator,
+               uint64_t buf_size_max, uint32_t threads)
+{
+       uint64_t bufs_alloc_size;
+       uint32_t bufs_count;
+
+       // Set bufs_count and bufs_alloc_size.
+       return_if_error(get_options(&bufs_alloc_size, &bufs_count,
+                       buf_size_max, threads));
+
+       // Allocate memory if needed.
+       if (outq->buf_size_max != buf_size_max
+                       || outq->bufs_allocated != bufs_count) {
+               lzma_outq_end(outq, allocator);
+
+#if SIZE_MAX < UINT64_MAX
+               if (bufs_alloc_size > SIZE_MAX)
+                       return LZMA_MEM_ERROR;
+#endif
+
+               outq->bufs = lzma_alloc(bufs_count * sizeof(lzma_outbuf),
+                               allocator);
+               outq->bufs_mem = lzma_alloc((size_t)(bufs_alloc_size),
+                               allocator);
+
+               if (outq->bufs == NULL || outq->bufs_mem == NULL) {
+                       lzma_outq_end(outq, allocator);
+                       return LZMA_MEM_ERROR;
+               }
+       }
+
+       // Initialize the rest of the main structure. Initialization of
+       // outq->bufs[] is done when they are actually needed.
+       outq->buf_size_max = (size_t)(buf_size_max);
+       outq->bufs_allocated = bufs_count;
+       outq->bufs_pos = 0;
+       outq->bufs_used = 0;
+       outq->read_pos = 0;
+
+       return LZMA_OK;
+}
+
+
+extern void
+lzma_outq_end(lzma_outq *outq, const lzma_allocator *allocator)
+{
+       lzma_free(outq->bufs, allocator);
+       outq->bufs = NULL;
+
+       lzma_free(outq->bufs_mem, allocator);
+       outq->bufs_mem = NULL;
+
+       return;
+}
+
+
+extern lzma_outbuf *
+lzma_outq_get_buf(lzma_outq *outq)
+{
+       // Caller must have checked it with lzma_outq_has_buf().
+       assert(outq->bufs_used < outq->bufs_allocated);
+
+       // Initialize the new buffer.
+       lzma_outbuf *buf = &outq->bufs[outq->bufs_pos];
+       buf->buf = outq->bufs_mem + outq->bufs_pos * outq->buf_size_max;
+       buf->size = 0;
+       buf->finished = false;
+
+       // Update the queue state.
+       if (++outq->bufs_pos == outq->bufs_allocated)
+               outq->bufs_pos = 0;
+
+       ++outq->bufs_used;
+
+       return buf;
+}
+
+
+extern bool
+lzma_outq_is_readable(const lzma_outq *outq)
+{
+       uint32_t i = outq->bufs_pos - outq->bufs_used;
+       if (outq->bufs_pos < outq->bufs_used)
+               i += outq->bufs_allocated;
+
+       return outq->bufs[i].finished;
+}
+
+
+extern lzma_ret
+lzma_outq_read(lzma_outq *restrict outq, uint8_t *restrict out,
+               size_t *restrict out_pos, size_t out_size,
+               lzma_vli *restrict unpadded_size,
+               lzma_vli *restrict uncompressed_size)
+{
+       // There must be at least one buffer from which to read.
+       if (outq->bufs_used == 0)
+               return LZMA_OK;
+
+       // Get the buffer.
+       uint32_t i = outq->bufs_pos - outq->bufs_used;
+       if (outq->bufs_pos < outq->bufs_used)
+               i += outq->bufs_allocated;
+
+       lzma_outbuf *buf = &outq->bufs[i];
+
+       // If it isn't finished yet, we cannot read from it.
+       if (!buf->finished)
+               return LZMA_OK;
+
+       // Copy from the buffer to output.
+       lzma_bufcpy(buf->buf, &outq->read_pos, buf->size,
+                       out, out_pos, out_size);
+
+       // Return if we didn't get all the data from the buffer.
+       if (outq->read_pos < buf->size)
+               return LZMA_OK;
+
+       // The buffer was finished. Tell the caller its size information.
+       *unpadded_size = buf->unpadded_size;
+       *uncompressed_size = buf->uncompressed_size;
+
+       // Free this buffer for further use.
+       --outq->bufs_used;
+       outq->read_pos = 0;
+
+       return LZMA_STREAM_END;
+}
diff --git a/lzma/common/outqueue.h b/lzma/common/outqueue.h
new file mode 100644 (file)
index 0000000..079634d
--- /dev/null
@@ -0,0 +1,156 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       outqueue.h
+/// \brief      Output queue handling in multithreaded coding
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+
+/// Output buffer for a single thread
+typedef struct {
+       /// Pointer to the output buffer of lzma_outq.buf_size_max bytes
+       uint8_t *buf;
+
+       /// Amount of data written to buf
+       size_t size;
+
+       /// Additional size information
+       lzma_vli unpadded_size;
+       lzma_vli uncompressed_size;
+
+       /// True when no more data will be written into this buffer.
+       ///
+       /// \note       This is read by another thread and thus access
+       ///             to this variable needs a mutex.
+       bool finished;
+
+} lzma_outbuf;
+
+
+typedef struct {
+       /// Array of buffers that are used cyclically.
+       lzma_outbuf *bufs;
+
+       /// Memory allocated for all the buffers
+       uint8_t *bufs_mem;
+
+       /// Amount of buffer space available in each buffer
+       size_t buf_size_max;
+
+       /// Number of buffers allocated
+       uint32_t bufs_allocated;
+
+       /// Position in the bufs array. The next buffer to be taken
+       /// into use is bufs[bufs_pos].
+       uint32_t bufs_pos;
+
+       /// Number of buffers in use
+       uint32_t bufs_used;
+
+       /// Position in the buffer in lzma_outq_read()
+       size_t read_pos;
+
+} lzma_outq;
+
+
+/**
+ * \brief       Calculate the memory usage of an output queue
+ *
+ * \return      Approximate memory usage in bytes or UINT64_MAX on error.
+ */
+extern uint64_t lzma_outq_memusage(uint64_t buf_size_max, uint32_t threads);
+
+
+/// \brief      Initialize an output queue
+///
+/// \param      outq            Pointer to an output queue. Before calling
+///                             this function the first time, *outq should
+///                             have been zeroed with memzero() so that this
+///                             function knows that there are no previous
+///                             allocations to free.
+/// \param      allocator       Pointer to allocator or NULL
+/// \param      buf_size_max    Maximum amount of data that a single buffer
+///                             in the queue may need to store.
+/// \param      threads         Number of buffers that may be in use
+///                             concurrently. Note that more than this number
+///                             of buffers will actually get allocated to
+///                             improve performance when buffers finish
+///                             out of order.
+///
+/// \return     - LZMA_OK
+///             - LZMA_MEM_ERROR
+///
+extern lzma_ret lzma_outq_init(
+               lzma_outq *outq, const lzma_allocator *allocator,
+               uint64_t buf_size_max, uint32_t threads);
+
+
+/// \brief      Free the memory associated with the output queue
+extern void lzma_outq_end(lzma_outq *outq, const lzma_allocator *allocator);
+
+
+/// \brief      Get a new buffer
+///
+/// lzma_outq_has_buf() must be used to check that there is a buffer
+/// available before calling lzma_outq_get_buf().
+///
+extern lzma_outbuf *lzma_outq_get_buf(lzma_outq *outq);
+
+
+/// \brief      Test if there is data ready to be read
+///
+/// Call to this function must be protected with the same mutex that
+/// is used to protect lzma_outbuf.finished.
+///
+extern bool lzma_outq_is_readable(const lzma_outq *outq);
+
+
+/// \brief      Read finished data
+///
+/// \param      outq            Pointer to an output queue
+/// \param      out             Beginning of the output buffer
+/// \param      out_pos         The next byte will be written to
+///                             out[*out_pos].
+/// \param      out_size        Size of the out buffer; the first byte into
+///                             which no data is written to is out[out_size].
+/// \param      unpadded_size   Unpadded Size from the Block encoder
+/// \param      uncompressed_size Uncompressed Size from the Block encoder
+///
+/// \return     - LZMA: All OK. Either no data was available or the buffer
+///               being read didn't become empty yet.
+///             - LZMA_STREAM_END: The buffer being read was finished.
+///               *unpadded_size and *uncompressed_size were set.
+///
+/// \note       This reads lzma_outbuf.finished variables and thus call
+///             to this function needs to be protected with a mutex.
+///
+extern lzma_ret lzma_outq_read(lzma_outq *restrict outq,
+               uint8_t *restrict out, size_t *restrict out_pos,
+               size_t out_size, lzma_vli *restrict unpadded_size,
+               lzma_vli *restrict uncompressed_size);
+
+
+/// \brief      Test if there is at least one buffer free
+///
+/// This must be used before getting a new buffer with lzma_outq_get_buf().
+///
+static inline bool
+lzma_outq_has_buf(const lzma_outq *outq)
+{
+       return outq->bufs_used < outq->bufs_allocated;
+}
+
+
+/// \brief      Test if the queue is completely empty
+static inline bool
+lzma_outq_is_empty(const lzma_outq *outq)
+{
+       return outq->bufs_used == 0;
+}
diff --git a/lzma/common/stream_buffer_decoder.c b/lzma/common/stream_buffer_decoder.c
new file mode 100644 (file)
index 0000000..b9745b5
--- /dev/null
@@ -0,0 +1,91 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       stream_buffer_decoder.c
+/// \brief      Single-call .xz Stream decoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "stream_decoder.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_stream_buffer_decode(uint64_t *memlimit, uint32_t flags,
+               const lzma_allocator *allocator,
+               const uint8_t *in, size_t *in_pos, size_t in_size,
+               uint8_t *out, size_t *out_pos, size_t out_size)
+{
+       // Sanity checks
+       if (in_pos == NULL || (in == NULL && *in_pos != in_size)
+                       || *in_pos > in_size || out_pos == NULL
+                       || (out == NULL && *out_pos != out_size)
+                       || *out_pos > out_size)
+               return LZMA_PROG_ERROR;
+
+       // Catch flags that are not allowed in buffer-to-buffer decoding.
+       if (flags & LZMA_TELL_ANY_CHECK)
+               return LZMA_PROG_ERROR;
+
+       // Initialize the Stream decoder.
+       // TODO: We need something to tell the decoder that it can use the
+       // output buffer as workspace, and thus save significant amount of RAM.
+       lzma_next_coder stream_decoder = LZMA_NEXT_CODER_INIT;
+       lzma_ret ret = lzma_stream_decoder_init(
+                       &stream_decoder, allocator, *memlimit, flags);
+
+       if (ret == LZMA_OK) {
+               // Save the positions so that we can restore them in case
+               // an error occurs.
+               const size_t in_start = *in_pos;
+               const size_t out_start = *out_pos;
+
+               // Do the actual decoding.
+               ret = stream_decoder.code(stream_decoder.coder, allocator,
+                               in, in_pos, in_size, out, out_pos, out_size,
+                               LZMA_FINISH);
+
+               if (ret == LZMA_STREAM_END) {
+                       ret = LZMA_OK;
+               } else {
+                       // Something went wrong, restore the positions.
+                       *in_pos = in_start;
+                       *out_pos = out_start;
+
+                       if (ret == LZMA_OK) {
+                               // Either the input was truncated or the
+                               // output buffer was too small.
+                               assert(*in_pos == in_size
+                                               || *out_pos == out_size);
+
+                               // If all the input was consumed, then the
+                               // input is truncated, even if the output
+                               // buffer is also full. This is because
+                               // processing the last byte of the Stream
+                               // never produces output.
+                               if (*in_pos == in_size)
+                                       ret = LZMA_DATA_ERROR;
+                               else
+                                       ret = LZMA_BUF_ERROR;
+
+                       } else if (ret == LZMA_MEMLIMIT_ERROR) {
+                               // Let the caller know how much memory would
+                               // have been needed.
+                               uint64_t memusage;
+                               (void)stream_decoder.memconfig(
+                                               stream_decoder.coder,
+                                               memlimit, &memusage, 0);
+                       }
+               }
+       }
+
+       // Free the decoder memory. This needs to be done even if
+       // initialization fails, because the internal API doesn't
+       // require the initialization function to free its memory on error.
+       lzma_next_end(&stream_decoder, allocator);
+
+       return ret;
+}
diff --git a/lzma/common/stream_buffer_encoder.c b/lzma/common/stream_buffer_encoder.c
new file mode 100644 (file)
index 0000000..af49554
--- /dev/null
@@ -0,0 +1,141 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       stream_buffer_encoder.c
+/// \brief      Single-call .xz Stream encoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "index.h"
+
+
+/// Maximum size of Index that has exactly one Record.
+/// Index Indicator + Number of Records + Record + CRC32 rounded up to
+/// the next multiple of four.
+#define INDEX_BOUND ((1 + 1 + 2 * LZMA_VLI_BYTES_MAX + 4 + 3) & ~3)
+
+/// Stream Header, Stream Footer, and Index
+#define HEADERS_BOUND (2 * LZMA_STREAM_HEADER_SIZE + INDEX_BOUND)
+
+
+extern LZMA_API(size_t)
+lzma_stream_buffer_bound(size_t uncompressed_size)
+{
+       // Get the maximum possible size of a Block.
+       const size_t block_bound = lzma_block_buffer_bound(uncompressed_size);
+       if (block_bound == 0)
+               return 0;
+
+       // Catch the possible integer overflow and also prevent the size of
+       // the Stream exceeding LZMA_VLI_MAX (theoretically possible on
+       // 64-bit systems).
+       if (my_min(SIZE_MAX, LZMA_VLI_MAX) - block_bound < HEADERS_BOUND)
+               return 0;
+
+       return block_bound + HEADERS_BOUND;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_stream_buffer_encode(lzma_filter *filters, lzma_check check,
+               const lzma_allocator *allocator,
+               const uint8_t *in, size_t in_size,
+               uint8_t *out, size_t *out_pos_ptr, size_t out_size)
+{
+       // Sanity checks
+       if (filters == NULL || (unsigned int)(check) > LZMA_CHECK_ID_MAX
+                       || (in == NULL && in_size != 0) || out == NULL
+                       || out_pos_ptr == NULL || *out_pos_ptr > out_size)
+               return LZMA_PROG_ERROR;
+
+       if (!lzma_check_is_supported(check))
+               return LZMA_UNSUPPORTED_CHECK;
+
+       // Note for the paranoids: Index encoder prevents the Stream from
+       // getting too big and still being accepted with LZMA_OK, and Block
+       // encoder catches if the input is too big. So we don't need to
+       // separately check if the buffers are too big.
+
+       // Use a local copy. We update *out_pos_ptr only if everything
+       // succeeds.
+       size_t out_pos = *out_pos_ptr;
+
+       // Check that there's enough space for both Stream Header and
+       // Stream Footer.
+       if (out_size - out_pos <= 2 * LZMA_STREAM_HEADER_SIZE)
+               return LZMA_BUF_ERROR;
+
+       // Reserve space for Stream Footer so we don't need to check for
+       // available space again before encoding Stream Footer.
+       out_size -= LZMA_STREAM_HEADER_SIZE;
+
+       // Encode the Stream Header.
+       lzma_stream_flags stream_flags = {
+               .version = 0,
+               .check = check,
+       };
+
+       if (lzma_stream_header_encode(&stream_flags, out + out_pos)
+                       != LZMA_OK)
+               return LZMA_PROG_ERROR;
+
+       out_pos += LZMA_STREAM_HEADER_SIZE;
+
+       // Encode a Block but only if there is at least one byte of input.
+       lzma_block block = {
+               .version = 0,
+               .check = check,
+               .filters = filters,
+       };
+
+       if (in_size > 0)
+               return_if_error(lzma_block_buffer_encode(&block, allocator,
+                               in, in_size, out, &out_pos, out_size));
+
+       // Index
+       {
+               // Create an Index. It will have one Record if there was
+               // at least one byte of input to encode. Otherwise the
+               // Index will be empty.
+               lzma_index *i = lzma_index_init(allocator);
+               if (i == NULL)
+                       return LZMA_MEM_ERROR;
+
+               lzma_ret ret = LZMA_OK;
+
+               if (in_size > 0)
+                       ret = lzma_index_append(i, allocator,
+                                       lzma_block_unpadded_size(&block),
+                                       block.uncompressed_size);
+
+               // If adding the Record was successful, encode the Index
+               // and get its size which will be stored into Stream Footer.
+               if (ret == LZMA_OK) {
+                       ret = lzma_index_buffer_encode(
+                                       i, out, &out_pos, out_size);
+
+                       stream_flags.backward_size = lzma_index_size(i);
+               }
+
+               lzma_index_end(i, allocator);
+
+               if (ret != LZMA_OK)
+                       return ret;
+       }
+
+       // Stream Footer. We have already reserved space for this.
+       if (lzma_stream_footer_encode(&stream_flags, out + out_pos)
+                       != LZMA_OK)
+               return LZMA_PROG_ERROR;
+
+       out_pos += LZMA_STREAM_HEADER_SIZE;
+
+       // Everything went fine, make the new output position available
+       // to the application.
+       *out_pos_ptr = out_pos;
+       return LZMA_OK;
+}
diff --git a/lzma/common/stream_decoder.c b/lzma/common/stream_decoder.c
new file mode 100644 (file)
index 0000000..3ab938c
--- /dev/null
@@ -0,0 +1,462 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       stream_decoder.c
+/// \brief      Decodes .xz Streams
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "stream_decoder.h"
+#include "block_decoder.h"
+
+
+struct lzma_coder_s {
+       enum {
+               SEQ_STREAM_HEADER,
+               SEQ_BLOCK_HEADER,
+               SEQ_BLOCK,
+               SEQ_INDEX,
+               SEQ_STREAM_FOOTER,
+               SEQ_STREAM_PADDING,
+       } sequence;
+
+       /// Block or Metadata decoder. This takes little memory and the same
+       /// data structure can be used to decode every Block Header, so it's
+       /// a good idea to have a separate lzma_next_coder structure for it.
+       lzma_next_coder block_decoder;
+
+       /// Block options decoded by the Block Header decoder and used by
+       /// the Block decoder.
+       lzma_block block_options;
+
+       /// Stream Flags from Stream Header
+       lzma_stream_flags stream_flags;
+
+       /// Index is hashed so that it can be compared to the sizes of Blocks
+       /// with O(1) memory usage.
+       lzma_index_hash *index_hash;
+
+       /// Memory usage limit
+       uint64_t memlimit;
+
+       /// Amount of memory actually needed (only an estimate)
+       uint64_t memusage;
+
+       /// If true, LZMA_NO_CHECK is returned if the Stream has
+       /// no integrity check.
+       bool tell_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 tell_unsupported_check;
+
+       /// If true, LZMA_GET_CHECK is returned after decoding Stream Header.
+       bool tell_any_check;
+
+       /// If true, we will tell the Block decoder to skip calculating
+       /// and verifying the integrity check.
+       bool ignore_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.
+       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.
+       /// Block Header has biggest maximum size.
+       uint8_t buffer[LZMA_BLOCK_HEADER_SIZE_MAX];
+};
+
+
+static lzma_ret
+stream_decoder_reset(lzma_coder *coder, const 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->pos = 0;
+
+       return LZMA_OK;
+}
+
+
+static lzma_ret
+stream_decode(lzma_coder *coder, const lzma_allocator *allocator,
+               const uint8_t *restrict in, size_t *restrict in_pos,
+               size_t in_size, uint8_t *restrict out,
+               size_t *restrict out_pos, size_t out_size, lzma_action action)
+{
+       // When decoding the actual Block, it may be able to produce more
+       // output even if we don't give it any new input.
+       while (true)
+       switch (coder->sequence) {
+       case SEQ_STREAM_HEADER: {
+               // Copy the Stream Header to the internal buffer.
+               lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
+                               LZMA_STREAM_HEADER_SIZE);
+
+               // Return if we didn't get the whole Stream Header yet.
+               if (coder->pos < LZMA_STREAM_HEADER_SIZE)
+                       return LZMA_OK;
+
+               coder->pos = 0;
+
+               // Decode the Stream Header.
+               const lzma_ret ret = lzma_stream_header_decode(
+                               &coder->stream_flags, coder->buffer);
+               if (ret != LZMA_OK)
+                       return ret == LZMA_FORMAT_ERROR && !coder->first_stream
+                                       ? LZMA_DATA_ERROR : ret;
+
+               // If we are decoding concatenated Streams, and the later
+               // Streams have invalid Header Magic Bytes, we give
+               // LZMA_DATA_ERROR instead of LZMA_FORMAT_ERROR.
+               coder->first_stream = false;
+
+               // Copy the type of the Check so that Block Header and Block
+               // decoders see it.
+               coder->block_options.check = coder->stream_flags.check;
+
+               // Even if we return LZMA_*_CHECK below, we want
+               // to continue from Block Header decoding.
+               coder->sequence = SEQ_BLOCK_HEADER;
+
+               // Detect if there's no integrity check or if it is
+               // unsupported if those were requested by the application.
+               if (coder->tell_no_check && coder->stream_flags.check
+                               == LZMA_CHECK_NONE)
+                       return LZMA_NO_CHECK;
+
+               if (coder->tell_unsupported_check
+                               && !lzma_check_is_supported(
+                                       coder->stream_flags.check))
+                       return LZMA_UNSUPPORTED_CHECK;
+
+               if (coder->tell_any_check)
+                       return LZMA_GET_CHECK;
+       }
+
+       // Fall through
+
+       case SEQ_BLOCK_HEADER: {
+               if (*in_pos >= in_size)
+                       return LZMA_OK;
+
+               if (coder->pos == 0) {
+                       // Detect if it's Index.
+                       if (in[*in_pos] == 0x00) {
+                               coder->sequence = SEQ_INDEX;
+                               break;
+                       }
+
+                       // Calculate the size of the Block Header. Note that
+                       // Block Header decoder wants to see this byte too
+                       // so don't advance *in_pos.
+                       coder->block_options.header_size
+                                       = lzma_block_header_size_decode(
+                                               in[*in_pos]);
+               }
+
+               // Copy the Block Header to the internal buffer.
+               lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
+                               coder->block_options.header_size);
+
+               // Return if we didn't get the whole Block Header yet.
+               if (coder->pos < coder->block_options.header_size)
+                       return LZMA_OK;
+
+               coder->pos = 0;
+
+               // Version 1 is needed to support the .ignore_check option.
+               coder->block_options.version = 1;
+
+               // Set up a buffer to hold the filter chain. Block Header
+               // decoder will initialize all members of this array so
+               // we don't need to do it here.
+               lzma_filter filters[LZMA_FILTERS_MAX + 1];
+               coder->block_options.filters = filters;
+
+               // Decode the Block Header.
+               return_if_error(lzma_block_header_decode(&coder->block_options,
+                               allocator, coder->buffer));
+
+               // If LZMA_IGNORE_CHECK was used, this flag needs to be set.
+               // It has to be set after lzma_block_header_decode() because
+               // it always resets this to false.
+               coder->block_options.ignore_check = coder->ignore_check;
+
+               // Check the memory usage limit.
+               const uint64_t memusage = lzma_raw_decoder_memusage(filters);
+               lzma_ret ret;
+
+               if (memusage == UINT64_MAX) {
+                       // One or more unknown Filter IDs.
+                       ret = LZMA_OPTIONS_ERROR;
+               } else {
+                       // Now we can set coder->memusage since we know that
+                       // the filter chain is valid. We don't want
+                       // lzma_memusage() to return UINT64_MAX in case of
+                       // invalid filter chain.
+                       coder->memusage = memusage;
+
+                       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
+               // only to initialize the Block decoder.
+               for (size_t i = 0; i < LZMA_FILTERS_MAX; ++i)
+                       lzma_free(filters[i].options, allocator);
+
+               coder->block_options.filters = NULL;
+
+               // Check if memory usage calculation and Block enocoder
+               // initialization succeeded.
+               if (ret != LZMA_OK)
+                       return ret;
+
+               coder->sequence = SEQ_BLOCK;
+       }
+
+       // Fall through
+
+       case SEQ_BLOCK: {
+               const lzma_ret ret = coder->block_decoder.code(
+                               coder->block_decoder.coder, allocator,
+                               in, in_pos, in_size, out, out_pos, out_size,
+                               action);
+
+               if (ret != LZMA_STREAM_END)
+                       return ret;
+
+               // Block decoded successfully. Add the new size pair to
+               // the Index hash.
+               return_if_error(lzma_index_hash_append(coder->index_hash,
+                               lzma_block_unpadded_size(
+                                       &coder->block_options),
+                               coder->block_options.uncompressed_size));
+
+               coder->sequence = SEQ_BLOCK_HEADER;
+               break;
+       }
+
+       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
+               // from the sizes of the Blocks (if any).
+               const lzma_ret ret = lzma_index_hash_decode(coder->index_hash,
+                               in, in_pos, in_size);
+               if (ret != LZMA_STREAM_END)
+                       return ret;
+
+               coder->sequence = SEQ_STREAM_FOOTER;
+       }
+
+       // Fall through
+
+       case SEQ_STREAM_FOOTER: {
+               // Copy the Stream Footer to the internal buffer.
+               lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
+                               LZMA_STREAM_HEADER_SIZE);
+
+               // Return if we didn't get the whole Stream Footer yet.
+               if (coder->pos < LZMA_STREAM_HEADER_SIZE)
+                       return LZMA_OK;
+
+               coder->pos = 0;
+
+               // Decode the Stream Footer. The decoder gives
+               // LZMA_FORMAT_ERROR if the magic bytes don't match,
+               // so convert that return code to LZMA_DATA_ERROR.
+               lzma_stream_flags footer_flags;
+               const lzma_ret ret = lzma_stream_footer_decode(
+                               &footer_flags, coder->buffer);
+               if (ret != LZMA_OK)
+                       return ret == LZMA_FORMAT_ERROR
+                                       ? LZMA_DATA_ERROR : ret;
+
+               // Check that Index Size stored in the Stream Footer matches
+               // the real size of the Index field.
+               if (lzma_index_hash_size(coder->index_hash)
+                               != footer_flags.backward_size)
+                       return LZMA_DATA_ERROR;
+
+               // Compare that the Stream Flags fields are identical in
+               // both Stream Header and Stream Footer.
+               return_if_error(lzma_stream_flags_compare(
+                               &coder->stream_flags, &footer_flags));
+
+               if (!coder->concatenated)
+                       return LZMA_STREAM_END;
+
+               coder->sequence = SEQ_STREAM_PADDING;
+       }
+
+       // Fall through
+
+       case SEQ_STREAM_PADDING:
+               assert(coder->concatenated);
+
+               // Skip over possible Stream Padding.
+               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 the byte is not zero, it probably indicates
+                       // beginning of a new Stream (or the file is corrupt).
+                       if (in[*in_pos] != 0x00)
+                               break;
+
+                       ++*in_pos;
+                       coder->pos = (coder->pos + 1) & 3;
+               }
+
+               // Stream Padding must be a multiple of four bytes (empty
+               // Stream Padding is OK).
+               if (coder->pos != 0) {
+                       ++*in_pos;
+                       return LZMA_DATA_ERROR;
+               }
+
+               // Prepare to decode the next Stream.
+               return_if_error(stream_decoder_reset(coder, allocator));
+               break;
+
+       default:
+               assert(0);
+               return LZMA_PROG_ERROR;
+       }
+
+       // Never reached
+}
+
+
+static void
+stream_decoder_end(lzma_coder *coder, const lzma_allocator *allocator)
+{
+       lzma_next_end(&coder->block_decoder, allocator);
+       lzma_index_hash_end(coder->index_hash, allocator);
+       lzma_free(coder, allocator);
+       return;
+}
+
+
+static lzma_check
+stream_decoder_get_check(const lzma_coder *coder)
+{
+       return coder->stream_flags.check;
+}
+
+
+static lzma_ret
+stream_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
+               uint64_t *old_memlimit, uint64_t new_memlimit)
+{
+       *memusage = coder->memusage;
+       *old_memlimit = coder->memlimit;
+
+       if (new_memlimit != 0) {
+               if (new_memlimit < coder->memusage)
+                       return LZMA_MEMLIMIT_ERROR;
+
+               coder->memlimit = new_memlimit;
+       }
+
+       return LZMA_OK;
+}
+
+
+extern lzma_ret
+lzma_stream_decoder_init(
+               lzma_next_coder *next, const lzma_allocator *allocator,
+               uint64_t memlimit, uint32_t flags)
+{
+       lzma_next_coder_init(&lzma_stream_decoder_init, next, allocator);
+
+       if (memlimit == 0)
+               return LZMA_PROG_ERROR;
+
+       if (flags & ~LZMA_SUPPORTED_FLAGS)
+               return LZMA_OPTIONS_ERROR;
+
+       if (next->coder == NULL) {
+               next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+               if (next->coder == NULL)
+                       return LZMA_MEM_ERROR;
+
+               next->code = &stream_decode;
+               next->end = &stream_decoder_end;
+               next->get_check = &stream_decoder_get_check;
+               next->memconfig = &stream_decoder_memconfig;
+
+               next->coder->block_decoder = LZMA_NEXT_CODER_INIT;
+               next->coder->index_hash = NULL;
+       }
+
+       next->coder->memlimit = memlimit;
+       next->coder->memusage = LZMA_MEMUSAGE_BASE;
+       next->coder->tell_no_check = (flags & LZMA_TELL_NO_CHECK) != 0;
+       next->coder->tell_unsupported_check
+                       = (flags & LZMA_TELL_UNSUPPORTED_CHECK) != 0;
+       next->coder->tell_any_check = (flags & LZMA_TELL_ANY_CHECK) != 0;
+       next->coder->ignore_check = (flags & LZMA_IGNORE_CHECK) != 0;
+       next->coder->concatenated = (flags & LZMA_CONCATENATED) != 0;
+       next->coder->first_stream = true;
+
+       return stream_decoder_reset(next->coder, allocator);
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_stream_decoder(lzma_stream *strm, uint64_t memlimit, uint32_t flags)
+{
+       lzma_next_strm_init(lzma_stream_decoder_init, strm, memlimit, flags);
+
+       strm->internal->supported_actions[LZMA_RUN] = true;
+       strm->internal->supported_actions[LZMA_FINISH] = true;
+
+       return LZMA_OK;
+}
diff --git a/lzma/common/stream_decoder.h b/lzma/common/stream_decoder.h
new file mode 100644 (file)
index 0000000..c13c6ba
--- /dev/null
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       stream_decoder.h
+/// \brief      Decodes .xz Streams
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_STREAM_DECODER_H
+#define LZMA_STREAM_DECODER_H
+
+#include "common.h"
+
+extern lzma_ret lzma_stream_decoder_init(
+               lzma_next_coder *next, const lzma_allocator *allocator,
+               uint64_t memlimit, uint32_t flags);
+
+#endif
diff --git a/lzma/common/stream_encoder.c b/lzma/common/stream_encoder.c
new file mode 100644 (file)
index 0000000..a7663bc
--- /dev/null
@@ -0,0 +1,332 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       stream_encoder.c
+/// \brief      Encodes .xz Streams
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "block_encoder.h"
+#include "index_encoder.h"
+
+
+struct lzma_coder_s {
+       enum {
+               SEQ_STREAM_HEADER,
+               SEQ_BLOCK_INIT,
+               SEQ_BLOCK_HEADER,
+               SEQ_BLOCK_ENCODE,
+               SEQ_INDEX_ENCODE,
+               SEQ_STREAM_FOOTER,
+       } sequence;
+
+       /// True if Block encoder has been initialized by
+       /// stream_encoder_init() or stream_encoder_update()
+       /// and thus doesn't need to be initialized in stream_encode().
+       bool block_encoder_is_initialized;
+
+       /// Block
+       lzma_next_coder block_encoder;
+
+       /// Options for the Block encoder
+       lzma_block block_options;
+
+       /// The filter chain currently in use
+       lzma_filter filters[LZMA_FILTERS_MAX + 1];
+
+       /// Index encoder. This is separate from Block encoder, because this
+       /// doesn't take much memory, and when encoding multiple Streams
+       /// with the same encoding options we avoid reallocating memory.
+       lzma_next_coder index_encoder;
+
+       /// Index to hold sizes of the Blocks
+       lzma_index *index;
+
+       /// Read position in buffer[]
+       size_t buffer_pos;
+
+       /// Total number of bytes in buffer[]
+       size_t buffer_size;
+
+       /// Buffer to hold Stream Header, Block Header, and Stream Footer.
+       /// Block Header has biggest maximum size.
+       uint8_t buffer[LZMA_BLOCK_HEADER_SIZE_MAX];
+};
+
+
+static lzma_ret
+block_encoder_init(lzma_coder *coder, const lzma_allocator *allocator)
+{
+       // Prepare the Block options. Even though Block encoder doesn't need
+       // compressed_size, uncompressed_size, and header_size to be
+       // initialized, it is a good idea to do it here, because this way
+       // we catch if someone gave us Filter ID that cannot be used in
+       // Blocks/Streams.
+       coder->block_options.compressed_size = LZMA_VLI_UNKNOWN;
+       coder->block_options.uncompressed_size = LZMA_VLI_UNKNOWN;
+
+       return_if_error(lzma_block_header_size(&coder->block_options));
+
+       // Initialize the actual Block encoder.
+       return lzma_block_encoder_init(&coder->block_encoder, allocator,
+                       &coder->block_options);
+}
+
+
+static lzma_ret
+stream_encode(lzma_coder *coder, const lzma_allocator *allocator,
+               const uint8_t *restrict in, size_t *restrict in_pos,
+               size_t in_size, uint8_t *restrict out,
+               size_t *restrict out_pos, size_t out_size, lzma_action action)
+{
+       // Main loop
+       while (*out_pos < out_size)
+       switch (coder->sequence) {
+       case SEQ_STREAM_HEADER:
+       case SEQ_BLOCK_HEADER:
+       case SEQ_STREAM_FOOTER:
+               lzma_bufcpy(coder->buffer, &coder->buffer_pos,
+                               coder->buffer_size, out, out_pos, out_size);
+               if (coder->buffer_pos < coder->buffer_size)
+                       return LZMA_OK;
+
+               if (coder->sequence == SEQ_STREAM_FOOTER)
+                       return LZMA_STREAM_END;
+
+               coder->buffer_pos = 0;
+               ++coder->sequence;
+               break;
+
+       case SEQ_BLOCK_INIT: {
+               if (*in_pos == in_size) {
+                       // If we are requested to flush or finish the current
+                       // Block, return LZMA_STREAM_END immediately since
+                       // there's nothing to do.
+                       if (action != LZMA_FINISH)
+                               return action == LZMA_RUN
+                                               ? LZMA_OK : LZMA_STREAM_END;
+
+                       // The application had used LZMA_FULL_FLUSH to finish
+                       // the previous Block, but now wants to finish without
+                       // encoding new data, or it is simply creating an
+                       // empty Stream with no Blocks.
+                       //
+                       // Initialize the Index encoder, and continue to
+                       // actually encoding the Index.
+                       return_if_error(lzma_index_encoder_init(
+                                       &coder->index_encoder, allocator,
+                                       coder->index));
+                       coder->sequence = SEQ_INDEX_ENCODE;
+                       break;
+               }
+
+               // Initialize the Block encoder unless it was already
+               // initialized by stream_encoder_init() or
+               // stream_encoder_update().
+               if (!coder->block_encoder_is_initialized)
+                       return_if_error(block_encoder_init(coder, allocator));
+
+               // Make it false so that we don't skip the initialization
+               // with the next Block.
+               coder->block_encoder_is_initialized = false;
+
+               // Encode the Block Header. This shouldn't fail since we have
+               // already initialized the Block encoder.
+               if (lzma_block_header_encode(&coder->block_options,
+                               coder->buffer) != LZMA_OK)
+                       return LZMA_PROG_ERROR;
+
+               coder->buffer_size = coder->block_options.header_size;
+               coder->sequence = SEQ_BLOCK_HEADER;
+               break;
+       }
+
+       case SEQ_BLOCK_ENCODE: {
+               static const lzma_action convert[LZMA_ACTION_MAX + 1] = {
+                       LZMA_RUN,
+                       LZMA_SYNC_FLUSH,
+                       LZMA_FINISH,
+                       LZMA_FINISH,
+                       LZMA_FINISH,
+               };
+
+               const lzma_ret ret = coder->block_encoder.code(
+                               coder->block_encoder.coder, allocator,
+                               in, in_pos, in_size,
+                               out, out_pos, out_size, convert[action]);
+               if (ret != LZMA_STREAM_END || action == LZMA_SYNC_FLUSH)
+                       return ret;
+
+               // Add a new Index Record.
+               const lzma_vli unpadded_size = lzma_block_unpadded_size(
+                               &coder->block_options);
+               assert(unpadded_size != 0);
+               return_if_error(lzma_index_append(coder->index, allocator,
+                               unpadded_size,
+                               coder->block_options.uncompressed_size));
+
+               coder->sequence = SEQ_BLOCK_INIT;
+               break;
+       }
+
+       case SEQ_INDEX_ENCODE: {
+               // Call the Index encoder. It doesn't take any input, so
+               // those pointers can be NULL.
+               const lzma_ret ret = coder->index_encoder.code(
+                               coder->index_encoder.coder, allocator,
+                               NULL, NULL, 0,
+                               out, out_pos, out_size, LZMA_RUN);
+               if (ret != LZMA_STREAM_END)
+                       return ret;
+
+               // Encode the Stream Footer into coder->buffer.
+               const lzma_stream_flags stream_flags = {
+                       .version = 0,
+                       .backward_size = lzma_index_size(coder->index),
+                       .check = coder->block_options.check,
+               };
+
+               if (lzma_stream_footer_encode(&stream_flags, coder->buffer)
+                               != LZMA_OK)
+                       return LZMA_PROG_ERROR;
+
+               coder->buffer_size = LZMA_STREAM_HEADER_SIZE;
+               coder->sequence = SEQ_STREAM_FOOTER;
+               break;
+       }
+
+       default:
+               assert(0);
+               return LZMA_PROG_ERROR;
+       }
+
+       return LZMA_OK;
+}
+
+
+static void
+stream_encoder_end(lzma_coder *coder, const lzma_allocator *allocator)
+{
+       lzma_next_end(&coder->block_encoder, allocator);
+       lzma_next_end(&coder->index_encoder, allocator);
+       lzma_index_end(coder->index, allocator);
+
+       for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
+               lzma_free(coder->filters[i].options, allocator);
+
+       lzma_free(coder, allocator);
+       return;
+}
+
+
+static lzma_ret
+stream_encoder_update(lzma_coder *coder, const lzma_allocator *allocator,
+               const lzma_filter *filters,
+               const lzma_filter *reversed_filters)
+{
+       if (coder->sequence <= SEQ_BLOCK_INIT) {
+               // There is no incomplete Block waiting to be finished,
+               // thus we can change the whole filter chain. Start by
+               // trying to initialize the Block encoder with the new
+               // chain. This way we detect if the chain is valid.
+               coder->block_encoder_is_initialized = false;
+               coder->block_options.filters = (lzma_filter *)(filters);
+               const lzma_ret ret = block_encoder_init(coder, allocator);
+               coder->block_options.filters = coder->filters;
+               if (ret != LZMA_OK)
+                       return ret;
+
+               coder->block_encoder_is_initialized = true;
+
+       } else if (coder->sequence <= SEQ_BLOCK_ENCODE) {
+               // We are in the middle of a Block. Try to update only
+               // the filter-specific options.
+               return_if_error(coder->block_encoder.update(
+                               coder->block_encoder.coder, allocator,
+                               filters, reversed_filters));
+       } else {
+               // Trying to update the filter chain when we are already
+               // encoding Index or Stream Footer.
+               return LZMA_PROG_ERROR;
+       }
+
+       // Free the copy of the old chain and make a copy of the new chain.
+       for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
+               lzma_free(coder->filters[i].options, allocator);
+
+       return lzma_filters_copy(filters, coder->filters, allocator);
+}
+
+
+static lzma_ret
+stream_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
+               const lzma_filter *filters, lzma_check check)
+{
+       lzma_next_coder_init(&stream_encoder_init, next, allocator);
+
+       if (filters == NULL)
+               return LZMA_PROG_ERROR;
+
+       if (next->coder == NULL) {
+               next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+               if (next->coder == NULL)
+                       return LZMA_MEM_ERROR;
+
+               next->code = &stream_encode;
+               next->end = &stream_encoder_end;
+               next->update = &stream_encoder_update;
+
+               next->coder->filters[0].id = LZMA_VLI_UNKNOWN;
+               next->coder->block_encoder = LZMA_NEXT_CODER_INIT;
+               next->coder->index_encoder = LZMA_NEXT_CODER_INIT;
+               next->coder->index = NULL;
+       }
+
+       // Basic initializations
+       next->coder->sequence = SEQ_STREAM_HEADER;
+       next->coder->block_options.version = 0;
+       next->coder->block_options.check = check;
+
+       // Initialize the Index
+       lzma_index_end(next->coder->index, allocator);
+       next->coder->index = lzma_index_init(allocator);
+       if (next->coder->index == NULL)
+               return LZMA_MEM_ERROR;
+
+       // Encode the Stream Header
+       lzma_stream_flags stream_flags = {
+               .version = 0,
+               .check = check,
+       };
+       return_if_error(lzma_stream_header_encode(
+                       &stream_flags, next->coder->buffer));
+
+       next->coder->buffer_pos = 0;
+       next->coder->buffer_size = LZMA_STREAM_HEADER_SIZE;
+
+       // Initialize the Block encoder. This way we detect unsupported
+       // filter chains when initializing the Stream encoder instead of
+       // giving an error after Stream Header has already written out.
+       return stream_encoder_update(
+                       next->coder, allocator, filters, NULL);
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_stream_encoder(lzma_stream *strm,
+               const lzma_filter *filters, lzma_check check)
+{
+       lzma_next_strm_init(stream_encoder_init, strm, filters, check);
+
+       strm->internal->supported_actions[LZMA_RUN] = true;
+       strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
+       strm->internal->supported_actions[LZMA_FULL_FLUSH] = true;
+       strm->internal->supported_actions[LZMA_FULL_BARRIER] = true;
+       strm->internal->supported_actions[LZMA_FINISH] = true;
+
+       return LZMA_OK;
+}
diff --git a/lzma/common/stream_flags_common.c b/lzma/common/stream_flags_common.c
new file mode 100644 (file)
index 0000000..fbe8eb8
--- /dev/null
@@ -0,0 +1,47 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       stream_flags_common.c
+/// \brief      Common stuff for Stream flags coders
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "stream_flags_common.h"
+
+
+const uint8_t lzma_header_magic[6] = { 0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00 };
+const uint8_t lzma_footer_magic[2] = { 0x59, 0x5A };
+
+
+extern LZMA_API(lzma_ret)
+lzma_stream_flags_compare(
+               const lzma_stream_flags *a, const lzma_stream_flags *b)
+{
+       // We can compare only version 0 structures.
+       if (a->version != 0 || b->version != 0)
+               return LZMA_OPTIONS_ERROR;
+
+       // Check type
+       if ((unsigned int)(a->check) > LZMA_CHECK_ID_MAX
+                       || (unsigned int)(b->check) > LZMA_CHECK_ID_MAX)
+               return LZMA_PROG_ERROR;
+
+       if (a->check != b->check)
+               return LZMA_DATA_ERROR;
+
+       // Backward Sizes are compared only if they are known in both.
+       if (a->backward_size != LZMA_VLI_UNKNOWN
+                       && b->backward_size != LZMA_VLI_UNKNOWN) {
+               if (!is_backward_size_valid(a) || !is_backward_size_valid(b))
+                       return LZMA_PROG_ERROR;
+
+               if (a->backward_size != b->backward_size)
+                       return LZMA_DATA_ERROR;
+       }
+
+       return LZMA_OK;
+}
diff --git a/lzma/common/stream_flags_common.h b/lzma/common/stream_flags_common.h
new file mode 100644 (file)
index 0000000..9f3122a
--- /dev/null
@@ -0,0 +1,33 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       stream_flags_common.h
+/// \brief      Common stuff for Stream flags coders
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_STREAM_FLAGS_COMMON_H
+#define LZMA_STREAM_FLAGS_COMMON_H
+
+#include "common.h"
+
+/// Size of the Stream Flags field
+#define LZMA_STREAM_FLAGS_SIZE 2
+
+extern const uint8_t lzma_header_magic[6];
+extern const uint8_t lzma_footer_magic[2];
+
+
+static inline bool
+is_backward_size_valid(const lzma_stream_flags *options)
+{
+       return options->backward_size >= LZMA_BACKWARD_SIZE_MIN
+                       && options->backward_size <= LZMA_BACKWARD_SIZE_MAX
+                       && (options->backward_size & 3) == 0;
+}
+
+#endif
diff --git a/lzma/common/stream_flags_decoder.c b/lzma/common/stream_flags_decoder.c
new file mode 100644 (file)
index 0000000..1bc2f97
--- /dev/null
@@ -0,0 +1,82 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       stream_flags_decoder.c
+/// \brief      Decodes Stream Header and Stream Footer from .xz files
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "stream_flags_common.h"
+
+
+static bool
+stream_flags_decode(lzma_stream_flags *options, const uint8_t *in)
+{
+       // Reserved bits must be unset.
+       if (in[0] != 0x00 || (in[1] & 0xF0))
+               return true;
+
+       options->version = 0;
+       options->check = in[1] & 0x0F;
+
+       return false;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_stream_header_decode(lzma_stream_flags *options, const uint8_t *in)
+{
+       // Magic
+       if (memcmp(in, lzma_header_magic, sizeof(lzma_header_magic)) != 0)
+               return LZMA_FORMAT_ERROR;
+
+       // Verify the CRC32 so we can distinguish between corrupt
+       // and unsupported files.
+       const uint32_t crc = lzma_crc32(in + sizeof(lzma_header_magic),
+                       LZMA_STREAM_FLAGS_SIZE, 0);
+       if (crc != unaligned_read32le(in + sizeof(lzma_header_magic)
+                       + LZMA_STREAM_FLAGS_SIZE))
+               return LZMA_DATA_ERROR;
+
+       // Stream Flags
+       if (stream_flags_decode(options, in + sizeof(lzma_header_magic)))
+               return LZMA_OPTIONS_ERROR;
+
+       // Set Backward Size to indicate unknown value. That way
+       // lzma_stream_flags_compare() can be used to compare Stream Header
+       // and Stream Footer while keeping it useful also for comparing
+       // two Stream Footers.
+       options->backward_size = LZMA_VLI_UNKNOWN;
+
+       return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_stream_footer_decode(lzma_stream_flags *options, const uint8_t *in)
+{
+       // Magic
+       if (memcmp(in + sizeof(uint32_t) * 2 + LZMA_STREAM_FLAGS_SIZE,
+                       lzma_footer_magic, sizeof(lzma_footer_magic)) != 0)
+               return LZMA_FORMAT_ERROR;
+
+       // CRC32
+       const uint32_t crc = lzma_crc32(in + sizeof(uint32_t),
+                       sizeof(uint32_t) + LZMA_STREAM_FLAGS_SIZE, 0);
+       if (crc != unaligned_read32le(in))
+               return LZMA_DATA_ERROR;
+
+       // Stream Flags
+       if (stream_flags_decode(options, in + sizeof(uint32_t) * 2))
+               return LZMA_OPTIONS_ERROR;
+
+       // Backward Size
+       options->backward_size = unaligned_read32le(in + sizeof(uint32_t));
+       options->backward_size = (options->backward_size + 1) * 4;
+
+       return LZMA_OK;
+}
diff --git a/lzma/common/stream_flags_encoder.c b/lzma/common/stream_flags_encoder.c
new file mode 100644 (file)
index 0000000..4e71715
--- /dev/null
@@ -0,0 +1,86 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       stream_flags_encoder.c
+/// \brief      Encodes Stream Header and Stream Footer for .xz files
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "stream_flags_common.h"
+
+
+static bool
+stream_flags_encode(const lzma_stream_flags *options, uint8_t *out)
+{
+       if ((unsigned int)(options->check) > LZMA_CHECK_ID_MAX)
+               return true;
+
+       out[0] = 0x00;
+       out[1] = options->check;
+
+       return false;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_stream_header_encode(const lzma_stream_flags *options, uint8_t *out)
+{
+       assert(sizeof(lzma_header_magic) + LZMA_STREAM_FLAGS_SIZE
+                       + 4 == LZMA_STREAM_HEADER_SIZE);
+
+       if (options->version != 0)
+               return LZMA_OPTIONS_ERROR;
+
+       // Magic
+       memcpy(out, lzma_header_magic, sizeof(lzma_header_magic));
+
+       // Stream Flags
+       if (stream_flags_encode(options, out + sizeof(lzma_header_magic)))
+               return LZMA_PROG_ERROR;
+
+       // CRC32 of the Stream Header
+       const uint32_t crc = lzma_crc32(out + sizeof(lzma_header_magic),
+                       LZMA_STREAM_FLAGS_SIZE, 0);
+
+       unaligned_write32le(out + sizeof(lzma_header_magic)
+                       + LZMA_STREAM_FLAGS_SIZE, crc);
+
+       return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_stream_footer_encode(const lzma_stream_flags *options, uint8_t *out)
+{
+       assert(2 * 4 + LZMA_STREAM_FLAGS_SIZE + sizeof(lzma_footer_magic)
+                       == LZMA_STREAM_HEADER_SIZE);
+
+       if (options->version != 0)
+               return LZMA_OPTIONS_ERROR;
+
+       // Backward Size
+       if (!is_backward_size_valid(options))
+               return LZMA_PROG_ERROR;
+
+       unaligned_write32le(out + 4, options->backward_size / 4 - 1);
+
+       // Stream Flags
+       if (stream_flags_encode(options, out + 2 * 4))
+               return LZMA_PROG_ERROR;
+
+       // CRC32
+       const uint32_t crc = lzma_crc32(
+                       out + 4, 4 + LZMA_STREAM_FLAGS_SIZE, 0);
+
+       unaligned_write32le(out, crc);
+
+       // Magic
+       memcpy(out + 2 * 4 + LZMA_STREAM_FLAGS_SIZE,
+                       lzma_footer_magic, sizeof(lzma_footer_magic));
+
+       return LZMA_OK;
+}
diff --git a/lzma/common/vli_decoder.c b/lzma/common/vli_decoder.c
new file mode 100644 (file)
index 0000000..c181828
--- /dev/null
@@ -0,0 +1,86 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       vli_decoder.c
+/// \brief      Decodes variable-length integers
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_vli_decode(lzma_vli *restrict vli, size_t *vli_pos,
+               const uint8_t *restrict in, size_t *restrict in_pos,
+               size_t in_size)
+{
+       // If we haven't been given vli_pos, work in single-call mode.
+       size_t vli_pos_internal = 0;
+       if (vli_pos == NULL) {
+               vli_pos = &vli_pos_internal;
+               *vli = 0;
+
+               // If there's no input, use LZMA_DATA_ERROR. This way it is
+               // easy to decode VLIs from buffers that have known size,
+               // and get the correct error code in case the buffer is
+               // 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 {
+               // Read the next byte. Use a temporary variable so that we
+               // can update *in_pos immediately.
+               const uint8_t byte = in[*in_pos];
+               ++*in_pos;
+
+               // Add the newly read byte to *vli.
+               *vli += (lzma_vli)(byte & 0x7F) << (*vli_pos * 7);
+               ++*vli_pos;
+
+               // Check if this is the last byte of a multibyte integer.
+               if ((byte & 0x80) == 0) {
+                       // We don't allow using variable-length integers as
+                       // padding i.e. the encoding must use the most the
+                       // compact form.
+                       if (byte == 0x00 && *vli_pos > 1)
+                               return LZMA_DATA_ERROR;
+
+                       return vli_pos == &vli_pos_internal
+                                       ? LZMA_OK : LZMA_STREAM_END;
+               }
+
+               // There is at least one more byte coming. If we have already
+               // read maximum number of bytes, the integer is considered
+               // corrupt.
+               //
+               // If we need bigger integers in future, old versions liblzma
+               // will confusingly indicate the file being corrupt istead of
+               // unsupported. I suppose it's still better this way, because
+               // in the foreseeable future (writing this in 2008) the only
+               // reason why files would appear having over 63-bit integers
+               // is that the files are simply corrupt.
+               if (*vli_pos == LZMA_VLI_BYTES_MAX)
+                       return LZMA_DATA_ERROR;
+
+       } while (*in_pos < in_size);
+
+       return vli_pos == &vli_pos_internal ? LZMA_DATA_ERROR : LZMA_OK;
+}
diff --git a/lzma/common/vli_encoder.c b/lzma/common/vli_encoder.c
new file mode 100644 (file)
index 0000000..f864269
--- /dev/null
@@ -0,0 +1,69 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       vli_encoder.c
+/// \brief      Encodes variable-length integers
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_vli_encode(lzma_vli vli, size_t *vli_pos,
+               uint8_t *restrict out, size_t *restrict out_pos,
+               size_t out_size)
+{
+       // If we haven't been given vli_pos, work in single-call mode.
+       size_t vli_pos_internal = 0;
+       if (vli_pos == NULL) {
+               vli_pos = &vli_pos_internal;
+
+               // In single-call mode, we expect that the caller has
+               // reserved enough output space.
+               if (*out_pos >= out_size)
+                       return LZMA_PROG_ERROR;
+       } else {
+               // This never happens when we are called by liblzma, but
+               // may happen if called directly from an application.
+               if (*out_pos >= out_size)
+                       return LZMA_BUF_ERROR;
+       }
+
+       // Validate the arguments.
+       if (*vli_pos >= LZMA_VLI_BYTES_MAX || vli > LZMA_VLI_MAX)
+               return LZMA_PROG_ERROR;
+
+       // Shift vli so that the next bits to encode are the lowest. In
+       // single-call mode this never changes vli since *vli_pos is zero.
+       vli >>= *vli_pos * 7;
+
+       // Write the non-last bytes in a loop.
+       while (vli >= 0x80) {
+               // We don't need *vli_pos during this function call anymore,
+               // but update it here so that it is ready if we need to
+               // return before the whole integer has been decoded.
+               ++*vli_pos;
+               assert(*vli_pos < LZMA_VLI_BYTES_MAX);
+
+               // Write the next byte.
+               out[*out_pos] = (uint8_t)(vli) | 0x80;
+               vli >>= 7;
+
+               if (++*out_pos == out_size)
+                       return vli_pos == &vli_pos_internal
+                                       ? LZMA_PROG_ERROR : LZMA_OK;
+       }
+
+       // Write the last byte.
+       out[*out_pos] = (uint8_t)(vli);
+       ++*out_pos;
+       ++*vli_pos;
+
+       return vli_pos == &vli_pos_internal ? LZMA_OK : LZMA_STREAM_END;
+
+}
diff --git a/lzma/common/vli_size.c b/lzma/common/vli_size.c
new file mode 100644 (file)
index 0000000..ec1b4fa
--- /dev/null
@@ -0,0 +1,30 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       vli_size.c
+/// \brief      Calculates the encoded size of a variable-length integer
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+
+extern LZMA_API(uint32_t)
+lzma_vli_size(lzma_vli vli)
+{
+       if (vli > LZMA_VLI_MAX)
+               return 0;
+
+       uint32_t i = 0;
+       do {
+               vli >>= 7;
+               ++i;
+       } while (vli != 0);
+
+       assert(i <= LZMA_VLI_BYTES_MAX);
+       return i;
+}
diff --git a/lzma/delta/delta_common.h b/lzma/delta/delta_common.h
new file mode 100644 (file)
index 0000000..7e7e1ba
--- /dev/null
@@ -0,0 +1,20 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       delta_common.h
+/// \brief      Common stuff for Delta encoder and decoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_DELTA_COMMON_H
+#define LZMA_DELTA_COMMON_H
+
+#include "common.h"
+
+extern uint64_t lzma_delta_coder_memusage(const void *options);
+
+#endif
diff --git a/lzma/delta/delta_decoder.h b/lzma/delta/delta_decoder.h
new file mode 100644 (file)
index 0000000..ad89cc6
--- /dev/null
@@ -0,0 +1,26 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       delta_decoder.h
+/// \brief      Delta filter decoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_DELTA_DECODER_H
+#define LZMA_DELTA_DECODER_H
+
+#include "delta_common.h"
+
+extern lzma_ret lzma_delta_decoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters);
+
+extern lzma_ret lzma_delta_props_decode(
+               void **options, const lzma_allocator *allocator,
+               const uint8_t *props, size_t props_size);
+
+#endif
diff --git a/lzma/delta/delta_encoder.h b/lzma/delta/delta_encoder.h
new file mode 100644 (file)
index 0000000..4ab9847
--- /dev/null
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       delta_encoder.h
+/// \brief      Delta filter encoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_DELTA_ENCODER_H
+#define LZMA_DELTA_ENCODER_H
+
+#include "delta_common.h"
+
+extern lzma_ret lzma_delta_encoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters);
+
+extern lzma_ret lzma_delta_props_encode(const void *options, uint8_t *out);
+
+#endif
diff --git a/lzma/lz/lz_decoder.c b/lzma/lz/lz_decoder.c
new file mode 100644 (file)
index 0000000..2328a8e
--- /dev/null
@@ -0,0 +1,300 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lz_decoder.c
+/// \brief      LZ out window
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// liblzma supports multiple LZ77-based filters. The LZ part is shared
+// between these filters. The LZ code takes care of dictionary handling
+// and passing the data between filters in the chain. The filter-specific
+// part decodes from the input buffer to the dictionary.
+
+
+#include "lz_decoder.h"
+
+
+struct lzma_coder_s {
+       /// Dictionary (history buffer)
+       lzma_dict dict;
+
+       /// The actual LZ-based decoder e.g. LZMA
+       lzma_lz_decoder lz;
+
+       /// Next filter in the chain, if any. Note that LZMA and LZMA2 are
+       /// only allowed as the last filter, but the long-range filter in
+       /// future can be in the middle of the chain.
+       lzma_next_coder next;
+
+       /// True if the next filter in the chain has returned LZMA_STREAM_END.
+       bool next_finished;
+
+       /// True if the LZ decoder (e.g. LZMA) has detected end of payload
+       /// marker. This may become true before next_finished becomes true.
+       bool this_finished;
+
+       /// Temporary buffer needed when the LZ-based filter is not the last
+       /// filter in the chain. The output of the next filter is first
+       /// decoded into buffer[], which is then used as input for the actual
+       /// LZ-based decoder.
+       struct {
+               size_t pos;
+               size_t size;
+               uint8_t buffer[LZMA_BUFFER_SIZE];
+       } temp;
+};
+
+
+static void
+lz_decoder_reset(lzma_coder *coder)
+{
+       coder->dict.pos = 0;
+       coder->dict.full = 0;
+       coder->dict.buf[coder->dict.size - 1] = '\0';
+       coder->dict.need_reset = false;
+       return;
+}
+
+
+static lzma_ret
+decode_buffer(lzma_coder *coder,
+               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)
+{
+       while (true) {
+               // Wrap the dictionary if needed.
+               if (coder->dict.pos == coder->dict.size)
+                       coder->dict.pos = 0;
+
+               // Store the current dictionary position. It is needed to know
+               // where to start copying to the out[] buffer.
+               const size_t dict_start = coder->dict.pos;
+
+               // Calculate how much we allow coder->lz.code() to decode.
+               // It must not decode past the end of the dictionary
+               // buffer, and we don't want it to decode more than is
+               // actually needed to fill the out[] buffer.
+               coder->dict.limit = coder->dict.pos
+                               + my_min(out_size - *out_pos,
+                                       coder->dict.size - coder->dict.pos);
+
+               // Call the coder->lz.code() to do the actual decoding.
+               const lzma_ret ret = coder->lz.code(
+                               coder->lz.coder, &coder->dict,
+                               in, in_pos, in_size);
+
+               // Copy the decoded data from the dictionary to the out[]
+               // buffer.
+               const size_t copy_size = coder->dict.pos - dict_start;
+               assert(copy_size <= out_size - *out_pos);
+               memcpy(out + *out_pos, coder->dict.buf + dict_start,
+                               copy_size);
+               *out_pos += copy_size;
+
+               // Reset the dictionary if so requested by coder->lz.code().
+               if (coder->dict.need_reset) {
+                       lz_decoder_reset(coder);
+
+                       // Since we reset dictionary, we don't check if
+                       // dictionary became full.
+                       if (ret != LZMA_OK || *out_pos == out_size)
+                               return ret;
+               } else {
+                       // Return if everything got decoded or an error
+                       // occurred, or if there's no more data to decode.
+                       //
+                       // Note that detecting if there's something to decode
+                       // is done by looking if dictionary become full
+                       // instead of looking if *in_pos == in_size. This
+                       // is because it is possible that all the input was
+                       // consumed already but some data is pending to be
+                       // written to the dictionary.
+                       if (ret != LZMA_OK || *out_pos == out_size
+                                       || coder->dict.pos < coder->dict.size)
+                               return ret;
+               }
+       }
+}
+
+
+static lzma_ret
+lz_decode(lzma_coder *coder,
+               const lzma_allocator *allocator lzma_attribute((__unused__)),
+               const uint8_t *restrict in, size_t *restrict in_pos,
+               size_t in_size, uint8_t *restrict out,
+               size_t *restrict out_pos, size_t out_size,
+               lzma_action action)
+{
+       if (coder->next.code == NULL)
+               return decode_buffer(coder, in, in_pos, in_size,
+                               out, out_pos, out_size);
+
+       // We aren't the last coder in the chain, we need to decode
+       // our input to a temporary buffer.
+       while (*out_pos < out_size) {
+               // Fill the temporary buffer if it is empty.
+               if (!coder->next_finished
+                               && coder->temp.pos == coder->temp.size) {
+                       coder->temp.pos = 0;
+                       coder->temp.size = 0;
+
+                       const lzma_ret ret = coder->next.code(
+                                       coder->next.coder,
+                                       allocator, in, in_pos, in_size,
+                                       coder->temp.buffer, &coder->temp.size,
+                                       LZMA_BUFFER_SIZE, action);
+
+                       if (ret == LZMA_STREAM_END)
+                               coder->next_finished = true;
+                       else if (ret != LZMA_OK || coder->temp.size == 0)
+                               return ret;
+               }
+
+               if (coder->this_finished) {
+                       if (coder->temp.size != 0)
+                               return LZMA_DATA_ERROR;
+
+                       if (coder->next_finished)
+                               return LZMA_STREAM_END;
+
+                       return LZMA_OK;
+               }
+
+               const lzma_ret ret = decode_buffer(coder, coder->temp.buffer,
+                               &coder->temp.pos, coder->temp.size,
+                               out, out_pos, out_size);
+
+               if (ret == LZMA_STREAM_END)
+                       coder->this_finished = true;
+               else if (ret != LZMA_OK)
+                       return ret;
+               else if (coder->next_finished && *out_pos < out_size)
+                       return LZMA_DATA_ERROR;
+       }
+
+       return LZMA_OK;
+}
+
+
+static void
+lz_decoder_end(lzma_coder *coder, const lzma_allocator *allocator)
+{
+       lzma_next_end(&coder->next, allocator);
+       lzma_free(coder->dict.buf, allocator);
+
+       if (coder->lz.end != NULL)
+               coder->lz.end(coder->lz.coder, allocator);
+       else
+               lzma_free(coder->lz.coder, allocator);
+
+       lzma_free(coder, allocator);
+       return;
+}
+
+
+extern lzma_ret
+lzma_lz_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
+               const lzma_filter_info *filters,
+               lzma_ret (*lz_init)(lzma_lz_decoder *lz,
+                       const lzma_allocator *allocator, const void *options,
+                       lzma_lz_options *lz_options))
+{
+       // Allocate the base structure if it isn't already allocated.
+       if (next->coder == NULL) {
+               next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+               if (next->coder == NULL)
+                       return LZMA_MEM_ERROR;
+
+               next->code = &lz_decode;
+               next->end = &lz_decoder_end;
+
+               next->coder->dict.buf = NULL;
+               next->coder->dict.size = 0;
+               next->coder->lz = LZMA_LZ_DECODER_INIT;
+               next->coder->next = LZMA_NEXT_CODER_INIT;
+       }
+
+       // Allocate and initialize the LZ-based decoder. It will also give
+       // us the dictionary size.
+       lzma_lz_options lz_options;
+       return_if_error(lz_init(&next->coder->lz, allocator,
+                       filters[0].options, &lz_options));
+
+       // If the dictionary size is very small, increase it to 4096 bytes.
+       // This is to prevent constant wrapping of the dictionary, which
+       // would slow things down. The downside is that since we don't check
+       // separately for the real dictionary size, we may happily accept
+       // corrupt files.
+       if (lz_options.dict_size < 4096)
+               lz_options.dict_size = 4096;
+
+       // Make dictionary size a multipe of 16. Some LZ-based decoders like
+       // LZMA use the lowest bits lzma_dict.pos to know the alignment of the
+       // data. Aligned buffer is also good when memcpying from the
+       // dictionary to the output buffer, since applications are
+       // recommended to give aligned buffers to liblzma.
+       //
+       // Avoid integer overflow.
+       if (lz_options.dict_size > SIZE_MAX - 15)
+               return LZMA_MEM_ERROR;
+
+       lz_options.dict_size = (lz_options.dict_size + 15) & ~((size_t)(15));
+
+       // Allocate and initialize the dictionary.
+       if (next->coder->dict.size != lz_options.dict_size) {
+               lzma_free(next->coder->dict.buf, allocator);
+               next->coder->dict.buf
+                               = lzma_alloc(lz_options.dict_size, allocator);
+               if (next->coder->dict.buf == NULL)
+                       return LZMA_MEM_ERROR;
+
+               next->coder->dict.size = lz_options.dict_size;
+       }
+
+       lz_decoder_reset(next->coder);
+
+       // Use the preset dictionary if it was given to us.
+       if (lz_options.preset_dict != NULL
+                       && lz_options.preset_dict_size > 0) {
+               // If the preset dictionary is bigger than the actual
+               // dictionary, copy only the tail.
+               const size_t copy_size = my_min(lz_options.preset_dict_size,
+                               lz_options.dict_size);
+               const size_t offset = lz_options.preset_dict_size - copy_size;
+               memcpy(next->coder->dict.buf, lz_options.preset_dict + offset,
+                               copy_size);
+               next->coder->dict.pos = copy_size;
+               next->coder->dict.full = copy_size;
+       }
+
+       // Miscellaneous initializations
+       next->coder->next_finished = false;
+       next->coder->this_finished = false;
+       next->coder->temp.pos = 0;
+       next->coder->temp.size = 0;
+
+       // Initialize the next filter in the chain, if any.
+       return lzma_next_filter_init(&next->coder->next, allocator,
+                       filters + 1);
+}
+
+
+extern uint64_t
+lzma_lz_decoder_memusage(size_t dictionary_size)
+{
+       return sizeof(lzma_coder) + (uint64_t)(dictionary_size);
+}
+
+
+extern void
+lzma_lz_decoder_uncompressed(lzma_coder *coder, lzma_vli uncompressed_size)
+{
+       coder->lz.set_uncompressed(coder->lz.coder, uncompressed_size);
+}
diff --git a/lzma/lz/lz_decoder.h b/lzma/lz/lz_decoder.h
new file mode 100644 (file)
index 0000000..277900a
--- /dev/null
@@ -0,0 +1,235 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lz_decoder.h
+/// \brief      LZ out window
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_LZ_DECODER_H
+#define LZMA_LZ_DECODER_H
+
+#include "common.h"
+
+
+typedef struct {
+       /// Pointer to the dictionary buffer. It can be an allocated buffer
+       /// internal to liblzma, or it can a be a buffer given by the
+       /// application when in single-call mode (not implemented yet).
+       uint8_t *buf;
+
+       /// Write position in dictionary. The next byte will be written to
+       /// buf[pos].
+       size_t pos;
+
+       /// Indicates how full the dictionary is. This is used by
+       /// dict_is_distance_valid() to detect corrupt files that would
+       /// read beyond the beginning of the dictionary.
+       size_t full;
+
+       /// Write limit
+       size_t limit;
+
+       /// Size of the dictionary
+       size_t size;
+
+       /// True when dictionary should be reset before decoding more data.
+       bool need_reset;
+
+} lzma_dict;
+
+
+typedef struct {
+       size_t dict_size;
+       const uint8_t *preset_dict;
+       size_t preset_dict_size;
+} lzma_lz_options;
+
+
+typedef struct {
+       /// Data specific to the LZ-based decoder
+       lzma_coder *coder;
+
+       /// Function to decode from in[] to *dict
+       lzma_ret (*code)(lzma_coder *restrict coder,
+                       lzma_dict *restrict dict, const uint8_t *restrict in,
+                       size_t *restrict in_pos, size_t in_size);
+
+       void (*reset)(lzma_coder *coder, const void *options);
+
+       /// Set the uncompressed size
+       void (*set_uncompressed)(lzma_coder *coder,
+                       lzma_vli uncompressed_size);
+
+       /// Free allocated resources
+       void (*end)(lzma_coder *coder, const lzma_allocator *allocator);
+
+} lzma_lz_decoder;
+
+
+#define LZMA_LZ_DECODER_INIT \
+       (lzma_lz_decoder){ \
+               .coder = NULL, \
+               .code = NULL, \
+               .reset = NULL, \
+               .set_uncompressed = NULL, \
+               .end = NULL, \
+       }
+
+
+extern lzma_ret lzma_lz_decoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters,
+               lzma_ret (*lz_init)(lzma_lz_decoder *lz,
+                       const lzma_allocator *allocator, const void *options,
+                       lzma_lz_options *lz_options));
+
+extern uint64_t lzma_lz_decoder_memusage(size_t dictionary_size);
+
+extern void lzma_lz_decoder_uncompressed(
+               lzma_coder *coder, lzma_vli uncompressed_size);
+
+
+//////////////////////
+// Inline functions //
+//////////////////////
+
+/// Get a byte from the history buffer.
+static inline uint8_t
+dict_get(const lzma_dict *const dict, const uint32_t distance)
+{
+       return dict->buf[dict->pos - distance - 1
+                       + (distance < dict->pos ? 0 : dict->size)];
+}
+
+
+/// Test if dictionary is empty.
+static inline bool
+dict_is_empty(const lzma_dict *const dict)
+{
+       return dict->full == 0;
+}
+
+
+/// Validate the match distance
+static inline bool
+dict_is_distance_valid(const lzma_dict *const dict, const size_t distance)
+{
+       return dict->full > distance;
+}
+
+
+/// Repeat *len bytes at distance.
+static inline bool
+dict_repeat(lzma_dict *dict, uint32_t distance, uint32_t *len)
+{
+       // Don't write past the end of the dictionary.
+       const size_t dict_avail = dict->limit - dict->pos;
+       uint32_t left = my_min(dict_avail, *len);
+       *len -= left;
+
+       // Repeat a block of data from the history. Because memcpy() is faster
+       // than copying byte by byte in a loop, the copying process gets split
+       // into three cases.
+       if (distance < left) {
+               // Source and target areas overlap, thus we can't use
+               // memcpy() nor even memmove() safely.
+               do {
+                       dict->buf[dict->pos] = dict_get(dict, distance);
+                       ++dict->pos;
+               } while (--left > 0);
+
+       } else if (distance < dict->pos) {
+               // The easiest and fastest case
+               memcpy(dict->buf + dict->pos,
+                               dict->buf + dict->pos - distance - 1,
+                               left);
+               dict->pos += left;
+
+       } else {
+               // The bigger the dictionary, the more rare this
+               // case occurs. We need to "wrap" the dict, thus
+               // we might need two memcpy() to copy all the data.
+               assert(dict->full == dict->size);
+               const uint32_t copy_pos
+                               = dict->pos - distance - 1 + dict->size;
+               uint32_t copy_size = dict->size - copy_pos;
+
+               if (copy_size < left) {
+                       memmove(dict->buf + dict->pos, dict->buf + copy_pos,
+                                       copy_size);
+                       dict->pos += copy_size;
+                       copy_size = left - copy_size;
+                       memcpy(dict->buf + dict->pos, dict->buf, copy_size);
+                       dict->pos += copy_size;
+               } else {
+                       memmove(dict->buf + dict->pos, dict->buf + copy_pos,
+                                       left);
+                       dict->pos += left;
+               }
+       }
+
+       // Update how full the dictionary is.
+       if (dict->full < dict->pos)
+               dict->full = dict->pos;
+
+       return unlikely(*len != 0);
+}
+
+
+/// Puts one byte into the dictionary. Returns true if the dictionary was
+/// already full and the byte couldn't be added.
+static inline bool
+dict_put(lzma_dict *dict, uint8_t byte)
+{
+       if (unlikely(dict->pos == dict->limit))
+               return true;
+
+       dict->buf[dict->pos++] = byte;
+
+       if (dict->pos > dict->full)
+               dict->full = dict->pos;
+
+       return false;
+}
+
+
+/// Copies arbitrary amount of data into the dictionary.
+static inline void
+dict_write(lzma_dict *restrict dict, const uint8_t *restrict in,
+               size_t *restrict in_pos, size_t in_size,
+               size_t *restrict left)
+{
+       // NOTE: If we are being given more data than the size of the
+       // dictionary, it could be possible to optimize the LZ decoder
+       // so that not everything needs to go through the dictionary.
+       // This shouldn't be very common thing in practice though, and
+       // the slowdown of one extra memcpy() isn't bad compared to how
+       // much time it would have taken if the data were compressed.
+
+       if (in_size - *in_pos > *left)
+               in_size = *in_pos + *left;
+
+       *left -= lzma_bufcpy(in, in_pos, in_size,
+                       dict->buf, &dict->pos, dict->limit);
+
+       if (dict->pos > dict->full)
+               dict->full = dict->pos;
+
+       return;
+}
+
+
+static inline void
+dict_reset(lzma_dict *dict)
+{
+       dict->need_reset = true;
+       return;
+}
+
+#endif
diff --git a/lzma/lz/lz_encoder.c b/lzma/lz/lz_encoder.c
new file mode 100644 (file)
index 0000000..5a2be79
--- /dev/null
@@ -0,0 +1,609 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lz_encoder.c
+/// \brief      LZ in window
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "lz_encoder.h"
+#include "lz_encoder_hash.h"
+
+// See lz_encoder_hash.h. This is a bit hackish but avoids making
+// endianness a conditional in makefiles.
+#if defined(WORDS_BIGENDIAN) && !defined(HAVE_SMALL)
+#      include "lz_encoder_hash_table.h"
+#endif
+
+#include "memcmplen.h"
+
+
+struct lzma_coder_s {
+       /// LZ-based encoder e.g. LZMA
+       lzma_lz_encoder lz;
+
+       /// History buffer and match finder
+       lzma_mf mf;
+
+       /// Next coder in the chain
+       lzma_next_coder next;
+};
+
+
+/// \brief      Moves the data in the input window to free space for new data
+///
+/// mf->buffer is a sliding input window, which keeps mf->keep_size_before
+/// bytes of input history available all the time. Now and then we need to
+/// "slide" the buffer to make space for the new data to the end of the
+/// buffer. At the same time, data older than keep_size_before is dropped.
+///
+static void
+move_window(lzma_mf *mf)
+{
+       // Align the move to a multiple of 16 bytes. Some LZ-based encoders
+       // like LZMA use the lowest bits of mf->read_pos to know the
+       // alignment of the uncompressed data. We also get better speed
+       // for memmove() with aligned buffers.
+       assert(mf->read_pos > mf->keep_size_before);
+       const uint32_t move_offset
+               = (mf->read_pos - mf->keep_size_before) & ~UINT32_C(15);
+
+       assert(mf->write_pos > move_offset);
+       const size_t move_size = mf->write_pos - move_offset;
+
+       assert(move_offset + move_size <= mf->size);
+
+       memmove(mf->buffer, mf->buffer + move_offset, move_size);
+
+       mf->offset += move_offset;
+       mf->read_pos -= move_offset;
+       mf->read_limit -= move_offset;
+       mf->write_pos -= move_offset;
+
+       return;
+}
+
+
+/// \brief      Tries to fill the input window (mf->buffer)
+///
+/// If we are the last encoder in the chain, our input data is in in[].
+/// Otherwise we call the next filter in the chain to process in[] and
+/// write its output to mf->buffer.
+///
+/// This function must not be called once it has returned LZMA_STREAM_END.
+///
+static lzma_ret
+fill_window(lzma_coder *coder, const lzma_allocator *allocator,
+               const uint8_t *in, size_t *in_pos, size_t in_size,
+               lzma_action action)
+{
+       assert(coder->mf.read_pos <= coder->mf.write_pos);
+
+       // Move the sliding window if needed.
+       if (coder->mf.read_pos >= coder->mf.size - coder->mf.keep_size_after)
+               move_window(&coder->mf);
+
+       // Maybe this is ugly, but lzma_mf uses uint32_t for most things
+       // (which I find cleanest), but we need size_t here when filling
+       // the history window.
+       size_t write_pos = coder->mf.write_pos;
+       lzma_ret ret;
+       if (coder->next.code == NULL) {
+               // Not using a filter, simply memcpy() as much as possible.
+               lzma_bufcpy(in, in_pos, in_size, coder->mf.buffer,
+                               &write_pos, coder->mf.size);
+
+               ret = action != LZMA_RUN && *in_pos == in_size
+                               ? LZMA_STREAM_END : LZMA_OK;
+
+       } else {
+               ret = coder->next.code(coder->next.coder, allocator,
+                               in, in_pos, in_size,
+                               coder->mf.buffer, &write_pos,
+                               coder->mf.size, action);
+       }
+
+       coder->mf.write_pos = write_pos;
+
+       // Silence Valgrind. lzma_memcmplen() can read extra bytes
+       // and Valgrind will give warnings if those bytes are uninitialized
+       // because Valgrind cannot see that the values of the uninitialized
+       // bytes are eventually ignored.
+       memzero(coder->mf.buffer + write_pos, LZMA_MEMCMPLEN_EXTRA);
+
+       // If end of stream has been reached or flushing completed, we allow
+       // the encoder to process all the input (that is, read_pos is allowed
+       // to reach write_pos). Otherwise we keep keep_size_after bytes
+       // available as prebuffer.
+       if (ret == LZMA_STREAM_END) {
+               assert(*in_pos == in_size);
+               ret = LZMA_OK;
+               coder->mf.action = action;
+               coder->mf.read_limit = coder->mf.write_pos;
+
+       } else if (coder->mf.write_pos > coder->mf.keep_size_after) {
+               // This needs to be done conditionally, because if we got
+               // only little new input, there may be too little input
+               // to do any encoding yet.
+               coder->mf.read_limit = coder->mf.write_pos
+                               - coder->mf.keep_size_after;
+       }
+
+       // Restart the match finder after finished LZMA_SYNC_FLUSH.
+       if (coder->mf.pending > 0
+                       && coder->mf.read_pos < coder->mf.read_limit) {
+               // Match finder may update coder->pending and expects it to
+               // start from zero, so use a temporary variable.
+               const uint32_t pending = coder->mf.pending;
+               coder->mf.pending = 0;
+
+               // Rewind read_pos so that the match finder can hash
+               // the pending bytes.
+               assert(coder->mf.read_pos >= pending);
+               coder->mf.read_pos -= pending;
+
+               // Call the skip function directly instead of using
+               // mf_skip(), since we don't want to touch mf->read_ahead.
+               coder->mf.skip(&coder->mf, pending);
+       }
+
+       return ret;
+}
+
+
+static lzma_ret
+lz_encode(lzma_coder *coder, const lzma_allocator *allocator,
+               const uint8_t *restrict in, size_t *restrict in_pos,
+               size_t in_size,
+               uint8_t *restrict out, size_t *restrict out_pos,
+               size_t out_size, lzma_action action)
+{
+       while (*out_pos < out_size
+                       && (*in_pos < in_size || action != LZMA_RUN)) {
+               // Read more data to coder->mf.buffer if needed.
+               if (coder->mf.action == LZMA_RUN && coder->mf.read_pos
+                               >= coder->mf.read_limit)
+                       return_if_error(fill_window(coder, allocator,
+                                       in, in_pos, in_size, action));
+
+               // Encode
+               const lzma_ret ret = coder->lz.code(coder->lz.coder,
+                               &coder->mf, out, out_pos, out_size);
+               if (ret != LZMA_OK) {
+                       // Setting this to LZMA_RUN for cases when we are
+                       // flushing. It doesn't matter when finishing or if
+                       // an error occurred.
+                       coder->mf.action = LZMA_RUN;
+                       return ret;
+               }
+       }
+
+       return LZMA_OK;
+}
+
+
+static bool
+lz_encoder_prepare(lzma_mf *mf, const lzma_allocator *allocator,
+               const lzma_lz_options *lz_options)
+{
+       // For now, the dictionary size is limited to 1.5 GiB. This may grow
+       // in the future if needed, but it needs a little more work than just
+       // changing this check.
+       if (lz_options->dict_size < LZMA_DICT_SIZE_MIN
+                       || lz_options->dict_size
+                               > (UINT32_C(1) << 30) + (UINT32_C(1) << 29)
+                       || lz_options->nice_len > lz_options->match_len_max)
+               return true;
+
+       mf->keep_size_before = lz_options->before_size + lz_options->dict_size;
+
+       mf->keep_size_after = lz_options->after_size
+                       + lz_options->match_len_max;
+
+       // To avoid constant memmove()s, allocate some extra space. Since
+       // memmove()s become more expensive when the size of the buffer
+       // increases, we reserve more space when a large dictionary is
+       // used to make the memmove() calls rarer.
+       //
+       // This works with dictionaries up to about 3 GiB. If bigger
+       // dictionary is wanted, some extra work is needed:
+       //   - Several variables in lzma_mf have to be changed from uint32_t
+       //     to size_t.
+       //   - Memory usage calculation needs something too, e.g. use uint64_t
+       //     for mf->size.
+       uint32_t reserve = lz_options->dict_size / 2;
+       if (reserve > (UINT32_C(1) << 30))
+               reserve /= 2;
+
+       reserve += (lz_options->before_size + lz_options->match_len_max
+                       + lz_options->after_size) / 2 + (UINT32_C(1) << 19);
+
+       const uint32_t old_size = mf->size;
+       mf->size = mf->keep_size_before + reserve + mf->keep_size_after;
+
+       // Deallocate the old history buffer if it exists but has different
+       // size than what is needed now.
+       if (mf->buffer != NULL && old_size != mf->size) {
+               lzma_free(mf->buffer, allocator);
+               mf->buffer = NULL;
+       }
+
+       // Match finder options
+       mf->match_len_max = lz_options->match_len_max;
+       mf->nice_len = lz_options->nice_len;
+
+       // cyclic_size has to stay smaller than 2 Gi. Note that this doesn't
+       // mean limiting dictionary size to less than 2 GiB. With a match
+       // finder that uses multibyte resolution (hashes start at e.g. every
+       // fourth byte), cyclic_size would stay below 2 Gi even when
+       // dictionary size is greater than 2 GiB.
+       //
+       // It would be possible to allow cyclic_size >= 2 Gi, but then we
+       // would need to be careful to use 64-bit types in various places
+       // (size_t could do since we would need bigger than 32-bit address
+       // space anyway). It would also require either zeroing a multigigabyte
+       // buffer at initialization (waste of time and RAM) or allow
+       // normalization in lz_encoder_mf.c to access uninitialized
+       // memory to keep the code simpler. The current way is simple and
+       // still allows pretty big dictionaries, so I don't expect these
+       // limits to change.
+       mf->cyclic_size = lz_options->dict_size + 1;
+
+       // Validate the match finder ID and setup the function pointers.
+       switch (lz_options->match_finder) {
+#ifdef HAVE_MF_HC3
+       case LZMA_MF_HC3:
+               mf->find = &lzma_mf_hc3_find;
+               mf->skip = &lzma_mf_hc3_skip;
+               break;
+#endif
+#ifdef HAVE_MF_HC4
+       case LZMA_MF_HC4:
+               mf->find = &lzma_mf_hc4_find;
+               mf->skip = &lzma_mf_hc4_skip;
+               break;
+#endif
+#ifdef HAVE_MF_BT2
+       case LZMA_MF_BT2:
+               mf->find = &lzma_mf_bt2_find;
+               mf->skip = &lzma_mf_bt2_skip;
+               break;
+#endif
+#ifdef HAVE_MF_BT3
+       case LZMA_MF_BT3:
+               mf->find = &lzma_mf_bt3_find;
+               mf->skip = &lzma_mf_bt3_skip;
+               break;
+#endif
+#ifdef HAVE_MF_BT4
+       case LZMA_MF_BT4:
+               mf->find = &lzma_mf_bt4_find;
+               mf->skip = &lzma_mf_bt4_skip;
+               break;
+#endif
+
+       default:
+               return true;
+       }
+
+       // Calculate the sizes of mf->hash and mf->son and check that
+       // nice_len is big enough for the selected match finder.
+       const uint32_t hash_bytes = lz_options->match_finder & 0x0F;
+       if (hash_bytes > mf->nice_len)
+               return true;
+
+       const bool is_bt = (lz_options->match_finder & 0x10) != 0;
+       uint32_t hs;
+
+       if (hash_bytes == 2) {
+               hs = 0xFFFF;
+       } else {
+               // Round dictionary size up to the next 2^n - 1 so it can
+               // be used as a hash mask.
+               hs = lz_options->dict_size - 1;
+               hs |= hs >> 1;
+               hs |= hs >> 2;
+               hs |= hs >> 4;
+               hs |= hs >> 8;
+               hs >>= 1;
+               hs |= 0xFFFF;
+
+               if (hs > (UINT32_C(1) << 24)) {
+                       if (hash_bytes == 3)
+                               hs = (UINT32_C(1) << 24) - 1;
+                       else
+                               hs >>= 1;
+               }
+       }
+
+       mf->hash_mask = hs;
+
+       ++hs;
+       if (hash_bytes > 2)
+               hs += HASH_2_SIZE;
+       if (hash_bytes > 3)
+               hs += HASH_3_SIZE;
+/*
+       No match finder uses this at the moment.
+       if (mf->hash_bytes > 4)
+               hs += HASH_4_SIZE;
+*/
+
+       const uint32_t old_hash_count = mf->hash_count;
+       const uint32_t old_sons_count = mf->sons_count;
+       mf->hash_count = hs;
+       mf->sons_count = mf->cyclic_size;
+       if (is_bt)
+               mf->sons_count *= 2;
+
+       // Deallocate the old hash array if it exists and has different size
+       // than what is needed now.
+       if (old_hash_count != mf->hash_count
+                       || old_sons_count != mf->sons_count) {
+               lzma_free(mf->hash, allocator);
+               mf->hash = NULL;
+
+               lzma_free(mf->son, allocator);
+               mf->son = NULL;
+       }
+
+       // Maximum number of match finder cycles
+       mf->depth = lz_options->depth;
+       if (mf->depth == 0) {
+               if (is_bt)
+                       mf->depth = 16 + mf->nice_len / 2;
+               else
+                       mf->depth = 4 + mf->nice_len / 4;
+       }
+
+       return false;
+}
+
+
+static bool
+lz_encoder_init(lzma_mf *mf, const lzma_allocator *allocator,
+               const lzma_lz_options *lz_options)
+{
+       // Allocate the history buffer.
+       if (mf->buffer == NULL) {
+               // lzma_memcmplen() is used for the dictionary buffer
+               // so we need to allocate a few extra bytes to prevent
+               // it from reading past the end of the buffer.
+               mf->buffer = lzma_alloc(mf->size + LZMA_MEMCMPLEN_EXTRA,
+                               allocator);
+               if (mf->buffer == NULL)
+                       return true;
+
+               // Keep Valgrind happy with lzma_memcmplen() and initialize
+               // the extra bytes whose value may get read but which will
+               // effectively get ignored.
+               memzero(mf->buffer + mf->size, LZMA_MEMCMPLEN_EXTRA);
+       }
+
+       // Use cyclic_size as initial mf->offset. This allows
+       // avoiding a few branches in the match finders. The downside is
+       // that match finder needs to be normalized more often, which may
+       // hurt performance with huge dictionaries.
+       mf->offset = mf->cyclic_size;
+       mf->read_pos = 0;
+       mf->read_ahead = 0;
+       mf->read_limit = 0;
+       mf->write_pos = 0;
+       mf->pending = 0;
+
+#if UINT32_MAX >= SIZE_MAX / 4
+       // Check for integer overflow. (Huge dictionaries are not
+       // possible on 32-bit CPU.)
+       if (mf->hash_count > SIZE_MAX / sizeof(uint32_t)
+                       || mf->sons_count > SIZE_MAX / sizeof(uint32_t))
+               return true;
+#endif
+
+       // Allocate and initialize the hash table. Since EMPTY_HASH_VALUE
+       // is zero, we can use lzma_alloc_zero() or memzero() for mf->hash.
+       //
+       // We don't need to initialize mf->son, but not doing that may
+       // make Valgrind complain in normalization (see normalize() in
+       // lz_encoder_mf.c). Skipping the initialization is *very* good
+       // when big dictionary is used but only small amount of data gets
+       // actually compressed: most of the mf->son won't get actually
+       // allocated by the kernel, so we avoid wasting RAM and improve
+       // initialization speed a lot.
+       if (mf->hash == NULL) {
+               mf->hash = lzma_alloc_zero(mf->hash_count * sizeof(uint32_t),
+                               allocator);
+               mf->son = lzma_alloc(mf->sons_count * sizeof(uint32_t),
+                               allocator);
+
+               if (mf->hash == NULL || mf->son == NULL) {
+                       lzma_free(mf->hash, allocator);
+                       mf->hash = NULL;
+
+                       lzma_free(mf->son, allocator);
+                       mf->son = NULL;
+
+                       return true;
+               }
+       } else {
+/*
+               for (uint32_t i = 0; i < mf->hash_count; ++i)
+                       mf->hash[i] = EMPTY_HASH_VALUE;
+*/
+               memzero(mf->hash, mf->hash_count * sizeof(uint32_t));
+       }
+
+       mf->cyclic_pos = 0;
+
+       // Handle preset dictionary.
+       if (lz_options->preset_dict != NULL
+                       && lz_options->preset_dict_size > 0) {
+               // If the preset dictionary is bigger than the actual
+               // dictionary, use only the tail.
+               mf->write_pos = my_min(lz_options->preset_dict_size, mf->size);
+               memcpy(mf->buffer, lz_options->preset_dict
+                               + lz_options->preset_dict_size - mf->write_pos,
+                               mf->write_pos);
+               mf->action = LZMA_SYNC_FLUSH;
+               mf->skip(mf, mf->write_pos);
+       }
+
+       mf->action = LZMA_RUN;
+
+       return false;
+}
+
+
+extern uint64_t
+lzma_lz_encoder_memusage(const lzma_lz_options *lz_options)
+{
+       // Old buffers must not exist when calling lz_encoder_prepare().
+       lzma_mf mf = {
+               .buffer = NULL,
+               .hash = NULL,
+               .son = NULL,
+               .hash_count = 0,
+               .sons_count = 0,
+       };
+
+       // Setup the size information into mf.
+       if (lz_encoder_prepare(&mf, NULL, lz_options))
+               return UINT64_MAX;
+
+       // Calculate the memory usage.
+       return ((uint64_t)(mf.hash_count) + mf.sons_count) * sizeof(uint32_t)
+                       + mf.size + sizeof(lzma_coder);
+}
+
+
+static void
+lz_encoder_end(lzma_coder *coder, const lzma_allocator *allocator)
+{
+       lzma_next_end(&coder->next, allocator);
+
+       lzma_free(coder->mf.son, allocator);
+       lzma_free(coder->mf.hash, allocator);
+       lzma_free(coder->mf.buffer, allocator);
+
+       if (coder->lz.end != NULL)
+               coder->lz.end(coder->lz.coder, allocator);
+       else
+               lzma_free(coder->lz.coder, allocator);
+
+       lzma_free(coder, allocator);
+       return;
+}
+
+
+static lzma_ret
+lz_encoder_update(lzma_coder *coder, const lzma_allocator *allocator,
+               const lzma_filter *filters_null lzma_attribute((__unused__)),
+               const lzma_filter *reversed_filters)
+{
+       if (coder->lz.options_update == NULL)
+               return LZMA_PROG_ERROR;
+
+       return_if_error(coder->lz.options_update(
+                       coder->lz.coder, reversed_filters));
+
+       return lzma_next_filter_update(
+                       &coder->next, allocator, reversed_filters + 1);
+}
+
+
+extern lzma_ret
+lzma_lz_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
+               const lzma_filter_info *filters,
+               lzma_ret (*lz_init)(lzma_lz_encoder *lz,
+                       const lzma_allocator *allocator, const void *options,
+                       lzma_lz_options *lz_options))
+{
+#ifdef HAVE_SMALL
+       // We need that the CRC32 table has been initialized.
+       lzma_crc32_init();
+#endif
+
+       // Allocate and initialize the base data structure.
+       if (next->coder == NULL) {
+               next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+               if (next->coder == NULL)
+                       return LZMA_MEM_ERROR;
+
+               next->code = &lz_encode;
+               next->end = &lz_encoder_end;
+               next->update = &lz_encoder_update;
+
+               next->coder->lz.coder = NULL;
+               next->coder->lz.code = NULL;
+               next->coder->lz.end = NULL;
+
+               // mf.size is initialized to silence Valgrind
+               // when used on optimized binaries (GCC may reorder
+               // code in a way that Valgrind gets unhappy).
+               next->coder->mf.buffer = NULL;
+               next->coder->mf.size = 0;
+               next->coder->mf.hash = NULL;
+               next->coder->mf.son = NULL;
+               next->coder->mf.hash_count = 0;
+               next->coder->mf.sons_count = 0;
+
+               next->coder->next = LZMA_NEXT_CODER_INIT;
+       }
+
+       // Initialize the LZ-based encoder.
+       lzma_lz_options lz_options;
+       return_if_error(lz_init(&next->coder->lz, allocator,
+                       filters[0].options, &lz_options));
+
+       // Setup the size information into next->coder->mf and deallocate
+       // old buffers if they have wrong size.
+       if (lz_encoder_prepare(&next->coder->mf, allocator, &lz_options))
+               return LZMA_OPTIONS_ERROR;
+
+       // Allocate new buffers if needed, and do the rest of
+       // the initialization.
+       if (lz_encoder_init(&next->coder->mf, allocator, &lz_options))
+               return LZMA_MEM_ERROR;
+
+       // Initialize the next filter in the chain, if any.
+       return lzma_next_filter_init(&next->coder->next, allocator,
+                       filters + 1);
+}
+
+
+extern LZMA_API(lzma_bool)
+lzma_mf_is_supported(lzma_match_finder mf)
+{
+       bool ret = false;
+
+#ifdef HAVE_MF_HC3
+       if (mf == LZMA_MF_HC3)
+               ret = true;
+#endif
+
+#ifdef HAVE_MF_HC4
+       if (mf == LZMA_MF_HC4)
+               ret = true;
+#endif
+
+#ifdef HAVE_MF_BT2
+       if (mf == LZMA_MF_BT2)
+               ret = true;
+#endif
+
+#ifdef HAVE_MF_BT3
+       if (mf == LZMA_MF_BT3)
+               ret = true;
+#endif
+
+#ifdef HAVE_MF_BT4
+       if (mf == LZMA_MF_BT4)
+               ret = true;
+#endif
+
+       return ret;
+}
diff --git a/lzma/lz/lz_encoder.h b/lzma/lz/lz_encoder.h
new file mode 100644 (file)
index 0000000..dad9c6b
--- /dev/null
@@ -0,0 +1,328 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lz_encoder.h
+/// \brief      LZ in window and match finder API
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_LZ_ENCODER_H
+#define LZMA_LZ_ENCODER_H
+
+#include "common.h"
+
+
+/// A table of these is used by the LZ-based encoder to hold
+/// the length-distance pairs found by the match finder.
+typedef struct {
+       uint32_t len;
+       uint32_t dist;
+} lzma_match;
+
+
+typedef struct lzma_mf_s lzma_mf;
+struct lzma_mf_s {
+       ///////////////
+       // In Window //
+       ///////////////
+
+       /// Pointer to buffer with data to be compressed
+       uint8_t *buffer;
+
+       /// Total size of the allocated buffer (that is, including all
+       /// the extra space)
+       uint32_t size;
+
+       /// Number of bytes that must be kept available in our input history.
+       /// That is, once keep_size_before bytes have been processed,
+       /// buffer[read_pos - keep_size_before] is the oldest byte that
+       /// must be available for reading.
+       uint32_t keep_size_before;
+
+       /// Number of bytes that must be kept in buffer after read_pos.
+       /// That is, read_pos <= write_pos - keep_size_after as long as
+       /// action is LZMA_RUN; when action != LZMA_RUN, read_pos is allowed
+       /// to reach write_pos so that the last bytes get encoded too.
+       uint32_t keep_size_after;
+
+       /// Match finders store locations of matches using 32-bit integers.
+       /// To avoid adjusting several megabytes of integers every time the
+       /// input window is moved with move_window, we only adjust the
+       /// offset of the buffer. Thus, buffer[value_in_hash_table - offset]
+       /// is the byte pointed by value_in_hash_table.
+       uint32_t offset;
+
+       /// buffer[read_pos] is the next byte to run through the match
+       /// finder. This is incremented in the match finder once the byte
+       /// has been processed.
+       uint32_t read_pos;
+
+       /// Number of bytes that have been ran through the match finder, but
+       /// which haven't been encoded by the LZ-based encoder yet.
+       uint32_t read_ahead;
+
+       /// As long as read_pos is less than read_limit, there is enough
+       /// input available in buffer for at least one encoding loop.
+       ///
+       /// Because of the stateful API, read_limit may and will get greater
+       /// than read_pos quite often. This is taken into account when
+       /// calculating the value for keep_size_after.
+       uint32_t read_limit;
+
+       /// buffer[write_pos] is the first byte that doesn't contain valid
+       /// uncompressed data; that is, the next input byte will be copied
+       /// to buffer[write_pos].
+       uint32_t write_pos;
+
+       /// Number of bytes not hashed before read_pos. This is needed to
+       /// restart the match finder after LZMA_SYNC_FLUSH.
+       uint32_t pending;
+
+       //////////////////
+       // Match Finder //
+       //////////////////
+
+       /// Find matches. Returns the number of distance-length pairs written
+       /// to the matches array. This is called only via lzma_mf_find().
+       uint32_t (*find)(lzma_mf *mf, lzma_match *matches);
+
+       /// Skips num bytes. This is like find() but doesn't make the
+       /// distance-length pairs available, thus being a little faster.
+       /// This is called only via mf_skip().
+       void (*skip)(lzma_mf *mf, uint32_t num);
+
+       uint32_t *hash;
+       uint32_t *son;
+       uint32_t cyclic_pos;
+       uint32_t cyclic_size; // Must be dictionary size + 1.
+       uint32_t hash_mask;
+
+       /// Maximum number of loops in the match finder
+       uint32_t depth;
+
+       /// Maximum length of a match that the match finder will try to find.
+       uint32_t nice_len;
+
+       /// Maximum length of a match supported by the LZ-based encoder.
+       /// If the longest match found by the match finder is nice_len,
+       /// mf_find() tries to expand it up to match_len_max bytes.
+       uint32_t match_len_max;
+
+       /// When running out of input, binary tree match finders need to know
+       /// if it is due to flushing or finishing. The action is used also
+       /// by the LZ-based encoders themselves.
+       lzma_action action;
+
+       /// Number of elements in hash[]
+       uint32_t hash_count;
+
+       /// Number of elements in son[]
+       uint32_t sons_count;
+};
+
+
+typedef struct {
+       /// Extra amount of data to keep available before the "actual"
+       /// dictionary.
+       size_t before_size;
+
+       /// Size of the history buffer
+       size_t dict_size;
+
+       /// Extra amount of data to keep available after the "actual"
+       /// dictionary.
+       size_t after_size;
+
+       /// Maximum length of a match that the LZ-based encoder can accept.
+       /// This is used to extend matches of length nice_len to the
+       /// maximum possible length.
+       size_t match_len_max;
+
+       /// Match finder will search matches up to this length.
+       /// This must be less than or equal to match_len_max.
+       size_t nice_len;
+
+       /// Type of the match finder to use
+       lzma_match_finder match_finder;
+
+       /// Maximum search depth
+       uint32_t depth;
+
+       /// TODO: Comment
+       const uint8_t *preset_dict;
+
+       uint32_t preset_dict_size;
+
+} lzma_lz_options;
+
+
+// The total usable buffer space at any moment outside the match finder:
+// before_size + dict_size + after_size + match_len_max
+//
+// In reality, there's some extra space allocated to prevent the number of
+// memmove() calls reasonable. The bigger the dict_size is, the bigger
+// this extra buffer will be since with bigger dictionaries memmove() would
+// also take longer.
+//
+// A single encoder loop in the LZ-based encoder may call the match finder
+// (mf_find() or mf_skip()) at most after_size times. In other words,
+// a single encoder loop may increment lzma_mf.read_pos at most after_size
+// times. Since matches are looked up to
+// lzma_mf.buffer[lzma_mf.read_pos + match_len_max - 1], the total
+// amount of extra buffer needed after dict_size becomes
+// after_size + match_len_max.
+//
+// before_size has two uses. The first one is to keep literals available
+// in cases when the LZ-based encoder has made some read ahead.
+// TODO: Maybe this could be changed by making the LZ-based encoders to
+// store the actual literals as they do with length-distance pairs.
+//
+// Algorithms such as LZMA2 first try to compress a chunk, and then check
+// if the encoded result is smaller than the uncompressed one. If the chunk
+// was uncompressible, it is better to store it in uncompressed form in
+// the output stream. To do this, the whole uncompressed chunk has to be
+// still available in the history buffer. before_size achieves that.
+
+
+typedef struct {
+       /// Data specific to the LZ-based encoder
+       lzma_coder *coder;
+
+       /// Function to encode from *dict to out[]
+       lzma_ret (*code)(lzma_coder *restrict coder,
+                       lzma_mf *restrict mf, uint8_t *restrict out,
+                       size_t *restrict out_pos, size_t out_size);
+
+       /// Free allocated resources
+       void (*end)(lzma_coder *coder, const lzma_allocator *allocator);
+
+       /// Update the options in the middle of the encoding.
+       lzma_ret (*options_update)(lzma_coder *coder,
+                       const lzma_filter *filter);
+
+} lzma_lz_encoder;
+
+
+// Basic steps:
+//  1. Input gets copied into the dictionary.
+//  2. Data in dictionary gets run through the match finder byte by byte.
+//  3. The literals and matches are encoded using e.g. LZMA.
+//
+// The bytes that have been ran through the match finder, but not encoded yet,
+// are called `read ahead'.
+
+
+/// Get pointer to the first byte not ran through the match finder
+static inline const uint8_t *
+mf_ptr(const lzma_mf *mf)
+{
+       return mf->buffer + mf->read_pos;
+}
+
+
+/// Get the number of bytes that haven't been ran through the match finder yet.
+static inline uint32_t
+mf_avail(const lzma_mf *mf)
+{
+       return mf->write_pos - mf->read_pos;
+}
+
+
+/// Get the number of bytes that haven't been encoded yet (some of these
+/// bytes may have been ran through the match finder though).
+static inline uint32_t
+mf_unencoded(const lzma_mf *mf)
+{
+       return mf->write_pos - mf->read_pos + mf->read_ahead;
+}
+
+
+/// Calculate the absolute offset from the beginning of the most recent
+/// dictionary reset. Only the lowest four bits are important, so there's no
+/// problem that we don't know the 64-bit size of the data encoded so far.
+///
+/// NOTE: When moving the input window, we need to do it so that the lowest
+/// bits of dict->read_pos are not modified to keep this macro working
+/// as intended.
+static inline uint32_t
+mf_position(const lzma_mf *mf)
+{
+       return mf->read_pos - mf->read_ahead;
+}
+
+
+/// Since everything else begins with mf_, use it also for lzma_mf_find().
+#define mf_find lzma_mf_find
+
+
+/// Skip the given number of bytes. This is used when a good match was found.
+/// For example, if mf_find() finds a match of 200 bytes long, the first byte
+/// of that match was already consumed by mf_find(), and the rest 199 bytes
+/// have to be skipped with mf_skip(mf, 199).
+static inline void
+mf_skip(lzma_mf *mf, uint32_t amount)
+{
+       if (amount != 0) {
+               mf->skip(mf, amount);
+               mf->read_ahead += amount;
+       }
+}
+
+
+/// Copies at most *left number of bytes from the history buffer
+/// to out[]. This is needed by LZMA2 to encode uncompressed chunks.
+static inline void
+mf_read(lzma_mf *mf, uint8_t *out, size_t *out_pos, size_t out_size,
+               size_t *left)
+{
+       const size_t out_avail = out_size - *out_pos;
+       const size_t copy_size = my_min(out_avail, *left);
+
+       assert(mf->read_ahead == 0);
+       assert(mf->read_pos >= *left);
+
+       memcpy(out + *out_pos, mf->buffer + mf->read_pos - *left,
+                       copy_size);
+
+       *out_pos += copy_size;
+       *left -= copy_size;
+       return;
+}
+
+
+extern lzma_ret lzma_lz_encoder_init(
+               lzma_next_coder *next, const lzma_allocator *allocator,
+               const lzma_filter_info *filters,
+               lzma_ret (*lz_init)(lzma_lz_encoder *lz,
+                       const lzma_allocator *allocator, const void *options,
+                       lzma_lz_options *lz_options));
+
+
+extern uint64_t lzma_lz_encoder_memusage(const lzma_lz_options *lz_options);
+
+
+// These are only for LZ encoder's internal use.
+extern uint32_t lzma_mf_find(
+               lzma_mf *mf, uint32_t *count, lzma_match *matches);
+
+extern uint32_t lzma_mf_hc3_find(lzma_mf *dict, lzma_match *matches);
+extern void lzma_mf_hc3_skip(lzma_mf *dict, uint32_t amount);
+
+extern uint32_t lzma_mf_hc4_find(lzma_mf *dict, lzma_match *matches);
+extern void lzma_mf_hc4_skip(lzma_mf *dict, uint32_t amount);
+
+extern uint32_t lzma_mf_bt2_find(lzma_mf *dict, lzma_match *matches);
+extern void lzma_mf_bt2_skip(lzma_mf *dict, uint32_t amount);
+
+extern uint32_t lzma_mf_bt3_find(lzma_mf *dict, lzma_match *matches);
+extern void lzma_mf_bt3_skip(lzma_mf *dict, uint32_t amount);
+
+extern uint32_t lzma_mf_bt4_find(lzma_mf *dict, lzma_match *matches);
+extern void lzma_mf_bt4_skip(lzma_mf *dict, uint32_t amount);
+
+#endif
diff --git a/lzma/lz/lz_encoder_hash.h b/lzma/lz/lz_encoder_hash.h
new file mode 100644 (file)
index 0000000..342a333
--- /dev/null
@@ -0,0 +1,108 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lz_encoder_hash.h
+/// \brief      Hash macros for match finders
+//
+//  Author:     Igor Pavlov
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_LZ_ENCODER_HASH_H
+#define LZMA_LZ_ENCODER_HASH_H
+
+#if defined(WORDS_BIGENDIAN) && !defined(HAVE_SMALL)
+       // This is to make liblzma produce the same output on big endian
+       // systems that it does on little endian systems. lz_encoder.c
+       // takes care of including the actual table.
+       extern const uint32_t lzma_lz_hash_table[256];
+#      define hash_table lzma_lz_hash_table
+#else
+#      include "check.h"
+#      define hash_table lzma_crc32_table[0]
+#endif
+
+#define HASH_2_SIZE (UINT32_C(1) << 10)
+#define HASH_3_SIZE (UINT32_C(1) << 16)
+#define HASH_4_SIZE (UINT32_C(1) << 20)
+
+#define HASH_2_MASK (HASH_2_SIZE - 1)
+#define HASH_3_MASK (HASH_3_SIZE - 1)
+#define HASH_4_MASK (HASH_4_SIZE - 1)
+
+#define FIX_3_HASH_SIZE (HASH_2_SIZE)
+#define FIX_4_HASH_SIZE (HASH_2_SIZE + HASH_3_SIZE)
+#define FIX_5_HASH_SIZE (HASH_2_SIZE + HASH_3_SIZE + HASH_4_SIZE)
+
+// Endianness doesn't matter in hash_2_calc() (no effect on the output).
+#ifdef TUKLIB_FAST_UNALIGNED_ACCESS
+#      define hash_2_calc() \
+               const uint32_t hash_value = *(const uint16_t *)(cur)
+#else
+#      define hash_2_calc() \
+               const uint32_t hash_value \
+                       = (uint32_t)(cur[0]) | ((uint32_t)(cur[1]) << 8)
+#endif
+
+#define hash_3_calc() \
+       const uint32_t temp = hash_table[cur[0]] ^ cur[1]; \
+       const uint32_t hash_2_value = temp & HASH_2_MASK; \
+       const uint32_t hash_value \
+                       = (temp ^ ((uint32_t)(cur[2]) << 8)) & mf->hash_mask
+
+#define hash_4_calc() \
+       const uint32_t temp = hash_table[cur[0]] ^ cur[1]; \
+       const uint32_t hash_2_value = temp & HASH_2_MASK; \
+       const uint32_t hash_3_value \
+                       = (temp ^ ((uint32_t)(cur[2]) << 8)) & HASH_3_MASK; \
+       const uint32_t hash_value = (temp ^ ((uint32_t)(cur[2]) << 8) \
+                       ^ (hash_table[cur[3]] << 5)) & mf->hash_mask
+
+
+// The following are not currently used.
+
+#define hash_5_calc() \
+       const uint32_t temp = hash_table[cur[0]] ^ cur[1]; \
+       const uint32_t hash_2_value = temp & HASH_2_MASK; \
+       const uint32_t hash_3_value \
+                       = (temp ^ ((uint32_t)(cur[2]) << 8)) & HASH_3_MASK; \
+       uint32_t hash_4_value = (temp ^ ((uint32_t)(cur[2]) << 8) ^ \
+                       ^ hash_table[cur[3]] << 5); \
+       const uint32_t hash_value \
+                       = (hash_4_value ^ (hash_table[cur[4]] << 3)) \
+                               & mf->hash_mask; \
+       hash_4_value &= HASH_4_MASK
+
+/*
+#define hash_zip_calc() \
+       const uint32_t hash_value \
+                       = (((uint32_t)(cur[0]) | ((uint32_t)(cur[1]) << 8)) \
+                               ^ hash_table[cur[2]]) & 0xFFFF
+*/
+
+#define hash_zip_calc() \
+       const uint32_t hash_value \
+                       = (((uint32_t)(cur[2]) | ((uint32_t)(cur[0]) << 8)) \
+                               ^ hash_table[cur[1]]) & 0xFFFF
+
+#define mt_hash_2_calc() \
+       const uint32_t hash_2_value \
+                       = (hash_table[cur[0]] ^ cur[1]) & HASH_2_MASK
+
+#define mt_hash_3_calc() \
+       const uint32_t temp = hash_table[cur[0]] ^ cur[1]; \
+       const uint32_t hash_2_value = temp & HASH_2_MASK; \
+       const uint32_t hash_3_value \
+                       = (temp ^ ((uint32_t)(cur[2]) << 8)) & HASH_3_MASK
+
+#define mt_hash_4_calc() \
+       const uint32_t temp = hash_table[cur[0]] ^ cur[1]; \
+       const uint32_t hash_2_value = temp & HASH_2_MASK; \
+       const uint32_t hash_3_value \
+                       = (temp ^ ((uint32_t)(cur[2]) << 8)) & HASH_3_MASK; \
+       const uint32_t hash_4_value = (temp ^ ((uint32_t)(cur[2]) << 8) ^ \
+                       (hash_table[cur[3]] << 5)) & HASH_4_MASK
+
+#endif
diff --git a/lzma/lz/lz_encoder_hash_table.h b/lzma/lz/lz_encoder_hash_table.h
new file mode 100644 (file)
index 0000000..8c51717
--- /dev/null
@@ -0,0 +1,68 @@
+/* This file has been automatically generated by crc32_tablegen.c. */
+
+const uint32_t lzma_lz_hash_table[256] = {
+       0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
+       0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+       0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+       0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+       0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
+       0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+       0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
+       0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+       0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+       0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+       0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
+       0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+       0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
+       0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+       0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+       0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+       0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
+       0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+       0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
+       0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+       0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
+       0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+       0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
+       0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+       0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
+       0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+       0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+       0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+       0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
+       0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+       0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
+       0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+       0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
+       0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+       0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
+       0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+       0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
+       0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+       0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
+       0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+       0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
+       0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+       0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
+       0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+       0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+       0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+       0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
+       0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+       0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
+       0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+       0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
+       0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+       0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
+       0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+       0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
+       0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+       0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
+       0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+       0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
+       0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+       0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
+       0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+       0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+       0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+};
diff --git a/lzma/lz/lz_encoder_mf.c b/lzma/lz/lz_encoder_mf.c
new file mode 100644 (file)
index 0000000..7852077
--- /dev/null
@@ -0,0 +1,744 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lz_encoder_mf.c
+/// \brief      Match finders
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "lz_encoder.h"
+#include "lz_encoder_hash.h"
+#include "memcmplen.h"
+
+
+/// \brief      Find matches starting from the current byte
+///
+/// \return     The length of the longest match found
+extern uint32_t
+lzma_mf_find(lzma_mf *mf, uint32_t *count_ptr, lzma_match *matches)
+{
+       // Call the match finder. It returns the number of length-distance
+       // pairs found.
+       // FIXME: Minimum count is zero, what _exactly_ is the maximum?
+       const uint32_t count = mf->find(mf, matches);
+
+       // Length of the longest match; assume that no matches were found
+       // and thus the maximum length is zero.
+       uint32_t len_best = 0;
+
+       if (count > 0) {
+#ifndef NDEBUG
+               // Validate the matches.
+               for (uint32_t i = 0; i < count; ++i) {
+                       assert(matches[i].len <= mf->nice_len);
+                       assert(matches[i].dist < mf->read_pos);
+                       assert(memcmp(mf_ptr(mf) - 1,
+                               mf_ptr(mf) - matches[i].dist - 2,
+                               matches[i].len) == 0);
+               }
+#endif
+
+               // The last used element in the array contains
+               // the longest match.
+               len_best = matches[count - 1].len;
+
+               // If a match of maximum search length was found, try to
+               // extend the match to maximum possible length.
+               if (len_best == mf->nice_len) {
+                       // The limit for the match length is either the
+                       // maximum match length supported by the LZ-based
+                       // encoder or the number of bytes left in the
+                       // dictionary, whichever is smaller.
+                       uint32_t limit = mf_avail(mf) + 1;
+                       if (limit > mf->match_len_max)
+                               limit = mf->match_len_max;
+
+                       // Pointer to the byte we just ran through
+                       // the match finder.
+                       const uint8_t *p1 = mf_ptr(mf) - 1;
+
+                       // Pointer to the beginning of the match. We need -1
+                       // here because the match distances are zero based.
+                       const uint8_t *p2 = p1 - matches[count - 1].dist - 1;
+
+                       len_best = lzma_memcmplen(p1, p2, len_best, limit);
+               }
+       }
+
+       *count_ptr = count;
+
+       // Finally update the read position to indicate that match finder was
+       // run for this dictionary offset.
+       ++mf->read_ahead;
+
+       return len_best;
+}
+
+
+/// Hash value to indicate unused element in the hash. Since we start the
+/// positions from dict_size + 1, zero is always too far to qualify
+/// as usable match position.
+#define EMPTY_HASH_VALUE 0
+
+
+/// Normalization must be done when lzma_mf.offset + lzma_mf.read_pos
+/// reaches MUST_NORMALIZE_POS.
+#define MUST_NORMALIZE_POS UINT32_MAX
+
+
+/// \brief      Normalizes hash values
+///
+/// The hash arrays store positions of match candidates. The positions are
+/// relative to an arbitrary offset that is not the same as the absolute
+/// offset in the input stream. The relative position of the current byte
+/// is lzma_mf.offset + lzma_mf.read_pos. The distances of the matches are
+/// the differences of the current read position and the position found from
+/// the hash.
+///
+/// To prevent integer overflows of the offsets stored in the hash arrays,
+/// we need to "normalize" the stored values now and then. During the
+/// normalization, we drop values that indicate distance greater than the
+/// dictionary size, thus making space for new values.
+static void
+normalize(lzma_mf *mf)
+{
+       assert(mf->read_pos + mf->offset == MUST_NORMALIZE_POS);
+
+       // In future we may not want to touch the lowest bits, because there
+       // may be match finders that use larger resolution than one byte.
+       const uint32_t subvalue
+                       = (MUST_NORMALIZE_POS - mf->cyclic_size);
+                               // & (~(UINT32_C(1) << 10) - 1);
+
+       for (uint32_t i = 0; i < mf->hash_count; ++i) {
+               // If the distance is greater than the dictionary size,
+               // we can simply mark the hash element as empty.
+               if (mf->hash[i] <= subvalue)
+                       mf->hash[i] = EMPTY_HASH_VALUE;
+               else
+                       mf->hash[i] -= subvalue;
+       }
+
+       for (uint32_t i = 0; i < mf->sons_count; ++i) {
+               // Do the same for mf->son.
+               //
+               // NOTE: There may be uninitialized elements in mf->son.
+               // Valgrind may complain that the "if" below depends on
+               // an uninitialized value. In this case it is safe to ignore
+               // the warning. See also the comments in lz_encoder_init()
+               // in lz_encoder.c.
+               if (mf->son[i] <= subvalue)
+                       mf->son[i] = EMPTY_HASH_VALUE;
+               else
+                       mf->son[i] -= subvalue;
+       }
+
+       // Update offset to match the new locations.
+       mf->offset -= subvalue;
+
+       return;
+}
+
+
+/// Mark the current byte as processed from point of view of the match finder.
+static void
+move_pos(lzma_mf *mf)
+{
+       if (++mf->cyclic_pos == mf->cyclic_size)
+               mf->cyclic_pos = 0;
+
+       ++mf->read_pos;
+       assert(mf->read_pos <= mf->write_pos);
+
+       if (unlikely(mf->read_pos + mf->offset == UINT32_MAX))
+               normalize(mf);
+}
+
+
+/// When flushing, we cannot run the match finder unless there is nice_len
+/// bytes available in the dictionary. Instead, we skip running the match
+/// finder (indicating that no match was found), and count how many bytes we
+/// have ignored this way.
+///
+/// When new data is given after the flushing was completed, the match finder
+/// is restarted by rewinding mf->read_pos backwards by mf->pending. Then
+/// the missed bytes are added to the hash using the match finder's skip
+/// function (with small amount of input, it may start using mf->pending
+/// again if flushing).
+///
+/// Due to this rewinding, we don't touch cyclic_pos or test for
+/// normalization. It will be done when the match finder's skip function
+/// catches up after a flush.
+static void
+move_pending(lzma_mf *mf)
+{
+       ++mf->read_pos;
+       assert(mf->read_pos <= mf->write_pos);
+       ++mf->pending;
+}
+
+
+/// Calculate len_limit and determine if there is enough input to run
+/// the actual match finder code. Sets up "cur" and "pos". This macro
+/// is used by all find functions and binary tree skip functions. Hash
+/// chain skip function doesn't need len_limit so a simpler code is used
+/// in them.
+#define header(is_bt, len_min, ret_op) \
+       uint32_t len_limit = mf_avail(mf); \
+       if (mf->nice_len <= len_limit) { \
+               len_limit = mf->nice_len; \
+       } else if (len_limit < (len_min) \
+                       || (is_bt && mf->action == LZMA_SYNC_FLUSH)) { \
+               assert(mf->action != LZMA_RUN); \
+               move_pending(mf); \
+               ret_op; \
+       } \
+       const uint8_t *cur = mf_ptr(mf); \
+       const uint32_t pos = mf->read_pos + mf->offset
+
+
+/// Header for find functions. "return 0" indicates that zero matches
+/// were found.
+#define header_find(is_bt, len_min) \
+       header(is_bt, len_min, return 0); \
+       uint32_t matches_count = 0
+
+
+/// Header for a loop in a skip function. "continue" tells to skip the rest
+/// of the code in the loop.
+#define header_skip(is_bt, len_min) \
+       header(is_bt, len_min, continue)
+
+
+/// Calls hc_find_func() or bt_find_func() and calculates the total number
+/// of matches found. Updates the dictionary position and returns the number
+/// of matches found.
+#define call_find(func, len_best) \
+do { \
+       matches_count = func(len_limit, pos, cur, cur_match, mf->depth, \
+                               mf->son, mf->cyclic_pos, mf->cyclic_size, \
+                               matches + matches_count, len_best) \
+                       - matches; \
+       move_pos(mf); \
+       return matches_count; \
+} while (0)
+
+
+////////////////
+// Hash Chain //
+////////////////
+
+#if defined(HAVE_MF_HC3) || defined(HAVE_MF_HC4)
+///
+///
+/// \param      len_limit       Don't look for matches longer than len_limit.
+/// \param      pos             lzma_mf.read_pos + lzma_mf.offset
+/// \param      cur             Pointer to current byte (mf_ptr(mf))
+/// \param      cur_match       Start position of the current match candidate
+/// \param      depth           Maximum length of the hash chain
+/// \param      son             lzma_mf.son (contains the hash chain)
+/// \param      cyclic_pos
+/// \param      cyclic_size
+/// \param      matches         Array to hold the matches.
+/// \param      len_best        The length of the longest match found so far.
+static lzma_match *
+hc_find_func(
+               const uint32_t len_limit,
+               const uint32_t pos,
+               const uint8_t *const cur,
+               uint32_t cur_match,
+               uint32_t depth,
+               uint32_t *const son,
+               const uint32_t cyclic_pos,
+               const uint32_t cyclic_size,
+               lzma_match *matches,
+               uint32_t len_best)
+{
+       son[cyclic_pos] = cur_match;
+
+       while (true) {
+               const uint32_t delta = pos - cur_match;
+               if (depth-- == 0 || delta >= cyclic_size)
+                       return matches;
+
+               const uint8_t *const pb = cur - delta;
+               cur_match = son[cyclic_pos - delta
+                               + (delta > cyclic_pos ? cyclic_size : 0)];
+
+               if (pb[len_best] == cur[len_best] && pb[0] == cur[0]) {
+                       uint32_t len = lzma_memcmplen(pb, cur, 1, len_limit);
+
+                       if (len_best < len) {
+                               len_best = len;
+                               matches->len = len;
+                               matches->dist = delta - 1;
+                               ++matches;
+
+                               if (len == len_limit)
+                                       return matches;
+                       }
+               }
+       }
+}
+
+
+#define hc_find(len_best) \
+       call_find(hc_find_func, len_best)
+
+
+#define hc_skip() \
+do { \
+       mf->son[mf->cyclic_pos] = cur_match; \
+       move_pos(mf); \
+} while (0)
+
+#endif
+
+
+#ifdef HAVE_MF_HC3
+extern uint32_t
+lzma_mf_hc3_find(lzma_mf *mf, lzma_match *matches)
+{
+       header_find(false, 3);
+
+       hash_3_calc();
+
+       const uint32_t delta2 = pos - mf->hash[hash_2_value];
+       const uint32_t cur_match = mf->hash[FIX_3_HASH_SIZE + hash_value];
+
+       mf->hash[hash_2_value] = pos;
+       mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
+
+       uint32_t len_best = 2;
+
+       if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
+               len_best = lzma_memcmplen(cur - delta2, cur,
+                               len_best, len_limit);
+
+               matches[0].len = len_best;
+               matches[0].dist = delta2 - 1;
+               matches_count = 1;
+
+               if (len_best == len_limit) {
+                       hc_skip();
+                       return 1; // matches_count
+               }
+       }
+
+       hc_find(len_best);
+}
+
+
+extern void
+lzma_mf_hc3_skip(lzma_mf *mf, uint32_t amount)
+{
+       do {
+               if (mf_avail(mf) < 3) {
+                       move_pending(mf);
+                       continue;
+               }
+
+               const uint8_t *cur = mf_ptr(mf);
+               const uint32_t pos = mf->read_pos + mf->offset;
+
+               hash_3_calc();
+
+               const uint32_t cur_match
+                               = mf->hash[FIX_3_HASH_SIZE + hash_value];
+
+               mf->hash[hash_2_value] = pos;
+               mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
+
+               hc_skip();
+
+       } while (--amount != 0);
+}
+#endif
+
+
+#ifdef HAVE_MF_HC4
+extern uint32_t
+lzma_mf_hc4_find(lzma_mf *mf, lzma_match *matches)
+{
+       header_find(false, 4);
+
+       hash_4_calc();
+
+       uint32_t delta2 = pos - mf->hash[hash_2_value];
+       const uint32_t delta3
+                       = pos - mf->hash[FIX_3_HASH_SIZE + hash_3_value];
+       const uint32_t cur_match = mf->hash[FIX_4_HASH_SIZE + hash_value];
+
+       mf->hash[hash_2_value ] = pos;
+       mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
+       mf->hash[FIX_4_HASH_SIZE + hash_value] = pos;
+
+       uint32_t len_best = 1;
+
+       if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
+               len_best = 2;
+               matches[0].len = 2;
+               matches[0].dist = delta2 - 1;
+               matches_count = 1;
+       }
+
+       if (delta2 != delta3 && delta3 < mf->cyclic_size
+                       && *(cur - delta3) == *cur) {
+               len_best = 3;
+               matches[matches_count++].dist = delta3 - 1;
+               delta2 = delta3;
+       }
+
+       if (matches_count != 0) {
+               len_best = lzma_memcmplen(cur - delta2, cur,
+                               len_best, len_limit);
+
+               matches[matches_count - 1].len = len_best;
+
+               if (len_best == len_limit) {
+                       hc_skip();
+                       return matches_count;
+               }
+       }
+
+       if (len_best < 3)
+               len_best = 3;
+
+       hc_find(len_best);
+}
+
+
+extern void
+lzma_mf_hc4_skip(lzma_mf *mf, uint32_t amount)
+{
+       do {
+               if (mf_avail(mf) < 4) {
+                       move_pending(mf);
+                       continue;
+               }
+
+               const uint8_t *cur = mf_ptr(mf);
+               const uint32_t pos = mf->read_pos + mf->offset;
+
+               hash_4_calc();
+
+               const uint32_t cur_match
+                               = mf->hash[FIX_4_HASH_SIZE + hash_value];
+
+               mf->hash[hash_2_value] = pos;
+               mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
+               mf->hash[FIX_4_HASH_SIZE + hash_value] = pos;
+
+               hc_skip();
+
+       } while (--amount != 0);
+}
+#endif
+
+
+/////////////////
+// Binary Tree //
+/////////////////
+
+#if defined(HAVE_MF_BT2) || defined(HAVE_MF_BT3) || defined(HAVE_MF_BT4)
+static lzma_match *
+bt_find_func(
+               const uint32_t len_limit,
+               const uint32_t pos,
+               const uint8_t *const cur,
+               uint32_t cur_match,
+               uint32_t depth,
+               uint32_t *const son,
+               const uint32_t cyclic_pos,
+               const uint32_t cyclic_size,
+               lzma_match *matches,
+               uint32_t len_best)
+{
+       uint32_t *ptr0 = son + (cyclic_pos << 1) + 1;
+       uint32_t *ptr1 = son + (cyclic_pos << 1);
+
+       uint32_t len0 = 0;
+       uint32_t len1 = 0;
+
+       while (true) {
+               const uint32_t delta = pos - cur_match;
+               if (depth-- == 0 || delta >= cyclic_size) {
+                       *ptr0 = EMPTY_HASH_VALUE;
+                       *ptr1 = EMPTY_HASH_VALUE;
+                       return matches;
+               }
+
+               uint32_t *const pair = son + ((cyclic_pos - delta
+                               + (delta > cyclic_pos ? cyclic_size : 0))
+                               << 1);
+
+               const uint8_t *const pb = cur - delta;
+               uint32_t len = my_min(len0, len1);
+
+               if (pb[len] == cur[len]) {
+                       len = lzma_memcmplen(pb, cur, len + 1, len_limit);
+
+                       if (len_best < len) {
+                               len_best = len;
+                               matches->len = len;
+                               matches->dist = delta - 1;
+                               ++matches;
+
+                               if (len == len_limit) {
+                                       *ptr1 = pair[0];
+                                       *ptr0 = pair[1];
+                                       return matches;
+                               }
+                       }
+               }
+
+               if (pb[len] < cur[len]) {
+                       *ptr1 = cur_match;
+                       ptr1 = pair + 1;
+                       cur_match = *ptr1;
+                       len1 = len;
+               } else {
+                       *ptr0 = cur_match;
+                       ptr0 = pair;
+                       cur_match = *ptr0;
+                       len0 = len;
+               }
+       }
+}
+
+
+static void
+bt_skip_func(
+               const uint32_t len_limit,
+               const uint32_t pos,
+               const uint8_t *const cur,
+               uint32_t cur_match,
+               uint32_t depth,
+               uint32_t *const son,
+               const uint32_t cyclic_pos,
+               const uint32_t cyclic_size)
+{
+       uint32_t *ptr0 = son + (cyclic_pos << 1) + 1;
+       uint32_t *ptr1 = son + (cyclic_pos << 1);
+
+       uint32_t len0 = 0;
+       uint32_t len1 = 0;
+
+       while (true) {
+               const uint32_t delta = pos - cur_match;
+               if (depth-- == 0 || delta >= cyclic_size) {
+                       *ptr0 = EMPTY_HASH_VALUE;
+                       *ptr1 = EMPTY_HASH_VALUE;
+                       return;
+               }
+
+               uint32_t *pair = son + ((cyclic_pos - delta
+                               + (delta > cyclic_pos ? cyclic_size : 0))
+                               << 1);
+               const uint8_t *pb = cur - delta;
+               uint32_t len = my_min(len0, len1);
+
+               if (pb[len] == cur[len]) {
+                       len = lzma_memcmplen(pb, cur, len + 1, len_limit);
+
+                       if (len == len_limit) {
+                               *ptr1 = pair[0];
+                               *ptr0 = pair[1];
+                               return;
+                       }
+               }
+
+               if (pb[len] < cur[len]) {
+                       *ptr1 = cur_match;
+                       ptr1 = pair + 1;
+                       cur_match = *ptr1;
+                       len1 = len;
+               } else {
+                       *ptr0 = cur_match;
+                       ptr0 = pair;
+                       cur_match = *ptr0;
+                       len0 = len;
+               }
+       }
+}
+
+
+#define bt_find(len_best) \
+       call_find(bt_find_func, len_best)
+
+#define bt_skip() \
+do { \
+       bt_skip_func(len_limit, pos, cur, cur_match, mf->depth, \
+                       mf->son, mf->cyclic_pos, \
+                       mf->cyclic_size); \
+       move_pos(mf); \
+} while (0)
+
+#endif
+
+
+#ifdef HAVE_MF_BT2
+extern uint32_t
+lzma_mf_bt2_find(lzma_mf *mf, lzma_match *matches)
+{
+       header_find(true, 2);
+
+       hash_2_calc();
+
+       const uint32_t cur_match = mf->hash[hash_value];
+       mf->hash[hash_value] = pos;
+
+       bt_find(1);
+}
+
+
+extern void
+lzma_mf_bt2_skip(lzma_mf *mf, uint32_t amount)
+{
+       do {
+               header_skip(true, 2);
+
+               hash_2_calc();
+
+               const uint32_t cur_match = mf->hash[hash_value];
+               mf->hash[hash_value] = pos;
+
+               bt_skip();
+
+       } while (--amount != 0);
+}
+#endif
+
+
+#ifdef HAVE_MF_BT3
+extern uint32_t
+lzma_mf_bt3_find(lzma_mf *mf, lzma_match *matches)
+{
+       header_find(true, 3);
+
+       hash_3_calc();
+
+       const uint32_t delta2 = pos - mf->hash[hash_2_value];
+       const uint32_t cur_match = mf->hash[FIX_3_HASH_SIZE + hash_value];
+
+       mf->hash[hash_2_value] = pos;
+       mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
+
+       uint32_t len_best = 2;
+
+       if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
+               len_best = lzma_memcmplen(
+                               cur, cur - delta2, len_best, len_limit);
+
+               matches[0].len = len_best;
+               matches[0].dist = delta2 - 1;
+               matches_count = 1;
+
+               if (len_best == len_limit) {
+                       bt_skip();
+                       return 1; // matches_count
+               }
+       }
+
+       bt_find(len_best);
+}
+
+
+extern void
+lzma_mf_bt3_skip(lzma_mf *mf, uint32_t amount)
+{
+       do {
+               header_skip(true, 3);
+
+               hash_3_calc();
+
+               const uint32_t cur_match
+                               = mf->hash[FIX_3_HASH_SIZE + hash_value];
+
+               mf->hash[hash_2_value] = pos;
+               mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
+
+               bt_skip();
+
+       } while (--amount != 0);
+}
+#endif
+
+
+#ifdef HAVE_MF_BT4
+extern uint32_t
+lzma_mf_bt4_find(lzma_mf *mf, lzma_match *matches)
+{
+       header_find(true, 4);
+
+       hash_4_calc();
+
+       uint32_t delta2 = pos - mf->hash[hash_2_value];
+       const uint32_t delta3
+                       = pos - mf->hash[FIX_3_HASH_SIZE + hash_3_value];
+       const uint32_t cur_match = mf->hash[FIX_4_HASH_SIZE + hash_value];
+
+       mf->hash[hash_2_value] = pos;
+       mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
+       mf->hash[FIX_4_HASH_SIZE + hash_value] = pos;
+
+       uint32_t len_best = 1;
+
+       if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
+               len_best = 2;
+               matches[0].len = 2;
+               matches[0].dist = delta2 - 1;
+               matches_count = 1;
+       }
+
+       if (delta2 != delta3 && delta3 < mf->cyclic_size
+                       && *(cur - delta3) == *cur) {
+               len_best = 3;
+               matches[matches_count++].dist = delta3 - 1;
+               delta2 = delta3;
+       }
+
+       if (matches_count != 0) {
+               len_best = lzma_memcmplen(
+                               cur, cur - delta2, len_best, len_limit);
+
+               matches[matches_count - 1].len = len_best;
+
+               if (len_best == len_limit) {
+                       bt_skip();
+                       return matches_count;
+               }
+       }
+
+       if (len_best < 3)
+               len_best = 3;
+
+       bt_find(len_best);
+}
+
+
+extern void
+lzma_mf_bt4_skip(lzma_mf *mf, uint32_t amount)
+{
+       do {
+               header_skip(true, 4);
+
+               hash_4_calc();
+
+               const uint32_t cur_match
+                               = mf->hash[FIX_4_HASH_SIZE + hash_value];
+
+               mf->hash[hash_2_value] = pos;
+               mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
+               mf->hash[FIX_4_HASH_SIZE + hash_value] = pos;
+
+               bt_skip();
+
+       } while (--amount != 0);
+}
+#endif
diff --git a/lzma/lzma/fastpos.h b/lzma/lzma/fastpos.h
new file mode 100644 (file)
index 0000000..a3feea5
--- /dev/null
@@ -0,0 +1,141 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       fastpos.h
+/// \brief      Kind of two-bit version of bit scan reverse
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_FASTPOS_H
+#define LZMA_FASTPOS_H
+
+// LZMA encodes match distances by storing the highest two bits using
+// a six-bit value [0, 63], and then the missing lower bits.
+// Dictionary size is also stored using this encoding in the .xz
+// file format header.
+//
+// fastpos.h provides a way to quickly find out the correct six-bit
+// values. The following table gives some examples of this encoding:
+//
+//     dist   return
+//       0       0
+//       1       1
+//       2       2
+//       3       3
+//       4       4
+//       5       4
+//       6       5
+//       7       5
+//       8       6
+//      11       6
+//      12       7
+//     ...      ...
+//      15       7
+//      16       8
+//      17       8
+//     ...      ...
+//      23       8
+//      24       9
+//      25       9
+//     ...      ...
+//
+//
+// Provided functions or macros
+// ----------------------------
+//
+// get_dist_slot(dist) is the basic version. get_dist_slot_2(dist)
+// assumes that dist >= FULL_DISTANCES, thus the result is at least
+// FULL_DISTANCES_BITS * 2. Using get_dist_slot(dist) instead of
+// get_dist_slot_2(dist) would give the same result, but get_dist_slot_2(dist)
+// should be tiny bit faster due to the assumption being made.
+//
+//
+// Size vs. speed
+// --------------
+//
+// With some CPUs that have fast BSR (bit scan reverse) instruction, the
+// size optimized version is slightly faster than the bigger table based
+// approach. Such CPUs include Intel Pentium Pro, Pentium II, Pentium III
+// and Core 2 (possibly others). AMD K7 seems to have slower BSR, but that
+// would still have speed roughly comparable to the table version. Older
+// x86 CPUs like the original Pentium have very slow BSR; on those systems
+// the table version is a lot faster.
+//
+// On some CPUs, the table version is a lot faster when using position
+// dependent code, but with position independent code the size optimized
+// version is slightly faster. This occurs at least on 32-bit SPARC (no
+// ASM optimizations).
+//
+// I'm making the table version the default, because that has good speed
+// on all systems I have tried. The size optimized version is sometimes
+// slightly faster, but sometimes it is a lot slower.
+
+#ifdef HAVE_SMALL
+#      define get_dist_slot(dist) \
+               ((dist) <= 4 ? (dist) : get_dist_slot_2(dist))
+
+static inline uint32_t
+get_dist_slot_2(uint32_t dist)
+{
+       const uint32_t i = bsr32(dist);
+       return (i + i) + ((dist >> (i - 1)) & 1);
+}
+
+
+#else
+
+#define FASTPOS_BITS 13
+
+extern const uint8_t lzma_fastpos[1 << FASTPOS_BITS];
+
+
+#define fastpos_shift(extra, n) \
+       ((extra) + (n) * (FASTPOS_BITS - 1))
+
+#define fastpos_limit(extra, n) \
+       (UINT32_C(1) << (FASTPOS_BITS + fastpos_shift(extra, n)))
+
+#define fastpos_result(dist, extra, n) \
+       lzma_fastpos[(dist) >> fastpos_shift(extra, n)] \
+                       + 2 * fastpos_shift(extra, n)
+
+
+static inline uint32_t
+get_dist_slot(uint32_t dist)
+{
+       // If it is small enough, we can pick the result directly from
+       // the precalculated table.
+       if (dist < fastpos_limit(0, 0))
+               return lzma_fastpos[dist];
+
+       if (dist < fastpos_limit(0, 1))
+               return fastpos_result(dist, 0, 1);
+
+       return fastpos_result(dist, 0, 2);
+}
+
+
+#ifdef FULL_DISTANCES_BITS
+static inline uint32_t
+get_dist_slot_2(uint32_t dist)
+{
+       assert(dist >= FULL_DISTANCES);
+
+       if (dist < fastpos_limit(FULL_DISTANCES_BITS - 1, 0))
+               return fastpos_result(dist, FULL_DISTANCES_BITS - 1, 0);
+
+       if (dist < fastpos_limit(FULL_DISTANCES_BITS - 1, 1))
+               return fastpos_result(dist, FULL_DISTANCES_BITS - 1, 1);
+
+       return fastpos_result(dist, FULL_DISTANCES_BITS - 1, 2);
+}
+#endif
+
+#endif
+
+#endif
diff --git a/lzma/lzma/fastpos_table.c b/lzma/lzma/fastpos_table.c
new file mode 100644 (file)
index 0000000..6a3ceac
--- /dev/null
@@ -0,0 +1,519 @@
+/* This file has been automatically generated by fastpos_tablegen.c. */
+
+#include "common.h"
+#include "fastpos.h"
+
+const uint8_t lzma_fastpos[1 << FASTPOS_BITS] = {
+         0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,
+         8,  8,  8,  8,  8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9,
+        10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+        11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+        12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+        12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+        13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+        13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+        14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+        14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+        14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+        14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+        15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+        15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+        15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+        15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+        16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+        16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+        16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+        16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+        16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+        16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+        16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+        16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+        17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+        18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+        18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+        18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+        18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+        18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+        18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+        18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+        18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+        18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+        18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+        18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+        18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+        18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+        18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+        18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+        18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+        19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+        25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25
+};
diff --git a/lzma/lzma/fastpos_tablegen.c b/lzma/lzma/fastpos_tablegen.c
new file mode 100644 (file)
index 0000000..c97e6f4
--- /dev/null
@@ -0,0 +1,56 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       fastpos_tablegen.c
+/// \brief      Generates the lzma_fastpos[] lookup table
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include "fastpos.h"
+
+
+int
+main(void)
+{
+       uint8_t fastpos[1 << FASTPOS_BITS];
+
+       const uint8_t fast_slots = 2 * FASTPOS_BITS;
+       uint32_t c = 2;
+
+       fastpos[0] = 0;
+       fastpos[1] = 1;
+
+       for (uint8_t slot_fast = 2; slot_fast < fast_slots; ++slot_fast) {
+               const uint32_t k = 1 << ((slot_fast >> 1) - 1);
+               for (uint32_t j = 0; j < k; ++j, ++c)
+                       fastpos[c] = slot_fast;
+       }
+
+       printf("/* This file has been automatically generated "
+                       "by fastpos_tablegen.c. */\n\n"
+                       "#include \"common.h\"\n"
+                       "#include \"fastpos.h\"\n\n"
+                       "const uint8_t lzma_fastpos[1 << FASTPOS_BITS] = {");
+
+       for (size_t i = 0; i < (1 << FASTPOS_BITS); ++i) {
+               if (i % 16 == 0)
+                       printf("\n\t");
+
+               printf("%3u", (unsigned int)(fastpos[i]));
+
+               if (i != (1 << FASTPOS_BITS) - 1)
+                       printf(",");
+       }
+
+       printf("\n};\n");
+
+       return 0;
+}
diff --git a/lzma/lzma/lzma2_decoder.c b/lzma/lzma/lzma2_decoder.c
new file mode 100644 (file)
index 0000000..84982d2
--- /dev/null
@@ -0,0 +1,304 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma2_decoder.c
+/// \brief      LZMA2 decoder
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "lzma2_decoder.h"
+#include "lz_decoder.h"
+#include "lzma_decoder.h"
+
+
+struct lzma_coder_s {
+       enum sequence {
+               SEQ_CONTROL,
+               SEQ_UNCOMPRESSED_1,
+               SEQ_UNCOMPRESSED_2,
+               SEQ_COMPRESSED_0,
+               SEQ_COMPRESSED_1,
+               SEQ_PROPERTIES,
+               SEQ_LZMA,
+               SEQ_COPY,
+       } sequence;
+
+       /// Sequence after the size fields have been decoded.
+       enum sequence next_sequence;
+
+       /// LZMA decoder
+       lzma_lz_decoder lzma;
+
+       /// Uncompressed size of LZMA chunk
+       size_t uncompressed_size;
+
+       /// Compressed size of the chunk (naturally equals to uncompressed
+       /// size of uncompressed chunk)
+       size_t compressed_size;
+
+       /// True if properties are needed. This is false before the
+       /// first LZMA chunk.
+       bool need_properties;
+
+       /// True if dictionary reset is needed. This is false before the
+       /// first chunk (LZMA or uncompressed).
+       bool need_dictionary_reset;
+
+       lzma_options_lzma options;
+};
+
+
+static lzma_ret
+lzma2_decode(lzma_coder *restrict coder, lzma_dict *restrict dict,
+               const uint8_t *restrict in, size_t *restrict in_pos,
+               size_t in_size)
+{
+       // With SEQ_LZMA it is possible that no new input is needed to do
+       // some progress. The rest of the sequences assume that there is
+       // at least one byte of input.
+       while (*in_pos < in_size || coder->sequence == SEQ_LZMA)
+       switch (coder->sequence) {
+       case SEQ_CONTROL: {
+               const uint32_t control = in[*in_pos];
+               ++*in_pos;
+
+               // End marker
+               if (control == 0x00)
+                       return LZMA_STREAM_END;
+
+               if (control >= 0xE0 || control == 1) {
+                       // Dictionary reset implies that next LZMA chunk has
+                       // to set new properties.
+                       coder->need_properties = true;
+                       coder->need_dictionary_reset = true;
+               } else if (coder->need_dictionary_reset) {
+                       return LZMA_DATA_ERROR;
+               }
+
+               if (control >= 0x80) {
+                       // LZMA chunk. The highest five bits of the
+                       // uncompressed size are taken from the control byte.
+                       coder->uncompressed_size = (control & 0x1F) << 16;
+                       coder->sequence = SEQ_UNCOMPRESSED_1;
+
+                       // See if there are new properties or if we need to
+                       // reset the state.
+                       if (control >= 0xC0) {
+                               // When there are new properties, state reset
+                               // is done at SEQ_PROPERTIES.
+                               coder->need_properties = false;
+                               coder->next_sequence = SEQ_PROPERTIES;
+
+                       } else if (coder->need_properties) {
+                               return LZMA_DATA_ERROR;
+
+                       } else {
+                               coder->next_sequence = SEQ_LZMA;
+
+                               // If only state reset is wanted with old
+                               // properties, do the resetting here for
+                               // simplicity.
+                               if (control >= 0xA0)
+                                       coder->lzma.reset(coder->lzma.coder,
+                                                       &coder->options);
+                       }
+               } else {
+                       // Invalid control values
+                       if (control > 2)
+                               return LZMA_DATA_ERROR;
+
+                       // It's uncompressed chunk
+                       coder->sequence = SEQ_COMPRESSED_0;
+                       coder->next_sequence = SEQ_COPY;
+               }
+
+               if (coder->need_dictionary_reset) {
+                       // Finish the dictionary reset and let the caller
+                       // flush the dictionary to the actual output buffer.
+                       coder->need_dictionary_reset = false;
+                       dict_reset(dict);
+                       return LZMA_OK;
+               }
+
+               break;
+       }
+
+       case SEQ_UNCOMPRESSED_1:
+               coder->uncompressed_size += (uint32_t)(in[(*in_pos)++]) << 8;
+               coder->sequence = SEQ_UNCOMPRESSED_2;
+               break;
+
+       case SEQ_UNCOMPRESSED_2:
+               coder->uncompressed_size += in[(*in_pos)++] + 1;
+               coder->sequence = SEQ_COMPRESSED_0;
+               coder->lzma.set_uncompressed(coder->lzma.coder,
+                               coder->uncompressed_size);
+               break;
+
+       case SEQ_COMPRESSED_0:
+               coder->compressed_size = (uint32_t)(in[(*in_pos)++]) << 8;
+               coder->sequence = SEQ_COMPRESSED_1;
+               break;
+
+       case SEQ_COMPRESSED_1:
+               coder->compressed_size += in[(*in_pos)++] + 1;
+               coder->sequence = coder->next_sequence;
+               break;
+
+       case SEQ_PROPERTIES:
+               if (lzma_lzma_lclppb_decode(&coder->options, in[(*in_pos)++]))
+                       return LZMA_DATA_ERROR;
+
+               coder->lzma.reset(coder->lzma.coder, &coder->options);
+
+               coder->sequence = SEQ_LZMA;
+               break;
+
+       case SEQ_LZMA: {
+               // Store the start offset so that we can update
+               // coder->compressed_size later.
+               const size_t in_start = *in_pos;
+
+               // Decode from in[] to *dict.
+               const lzma_ret ret = coder->lzma.code(coder->lzma.coder,
+                               dict, in, in_pos, in_size);
+
+               // Validate and update coder->compressed_size.
+               const size_t in_used = *in_pos - in_start;
+               if (in_used > coder->compressed_size)
+                       return LZMA_DATA_ERROR;
+
+               coder->compressed_size -= in_used;
+
+               // Return if we didn't finish the chunk, or an error occurred.
+               if (ret != LZMA_STREAM_END)
+                       return ret;
+
+               // The LZMA decoder must have consumed the whole chunk now.
+               // We don't need to worry about uncompressed size since it
+               // is checked by the LZMA decoder.
+               if (coder->compressed_size != 0)
+                       return LZMA_DATA_ERROR;
+
+               coder->sequence = SEQ_CONTROL;
+               break;
+       }
+
+       case SEQ_COPY: {
+               // Copy from input to the dictionary as is.
+               dict_write(dict, in, in_pos, in_size, &coder->compressed_size);
+               if (coder->compressed_size != 0)
+                       return LZMA_OK;
+
+               coder->sequence = SEQ_CONTROL;
+               break;
+       }
+
+       default:
+               assert(0);
+               return LZMA_PROG_ERROR;
+       }
+
+       return LZMA_OK;
+}
+
+
+static void
+lzma2_decoder_end(lzma_coder *coder, const lzma_allocator *allocator)
+{
+       assert(coder->lzma.end == NULL);
+       lzma_free(coder->lzma.coder, allocator);
+
+       lzma_free(coder, allocator);
+
+       return;
+}
+
+
+static lzma_ret
+lzma2_decoder_init(lzma_lz_decoder *lz, const lzma_allocator *allocator,
+               const void *opt, lzma_lz_options *lz_options)
+{
+       if (lz->coder == NULL) {
+               lz->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+               if (lz->coder == NULL)
+                       return LZMA_MEM_ERROR;
+
+               lz->code = &lzma2_decode;
+               lz->end = &lzma2_decoder_end;
+
+               lz->coder->lzma = LZMA_LZ_DECODER_INIT;
+       }
+
+       const lzma_options_lzma *options = opt;
+
+       lz->coder->sequence = SEQ_CONTROL;
+       lz->coder->need_properties = true;
+       lz->coder->need_dictionary_reset = options->preset_dict == NULL
+                       || options->preset_dict_size == 0;
+
+       return lzma_lzma_decoder_create(&lz->coder->lzma,
+                       allocator, options, lz_options);
+}
+
+
+extern lzma_ret
+lzma_lzma2_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
+               const lzma_filter_info *filters)
+{
+       // LZMA2 can only be the last filter in the chain. This is enforced
+       // by the raw_decoder initialization.
+       assert(filters[1].init == NULL);
+
+       return lzma_lz_decoder_init(next, allocator, filters,
+                       &lzma2_decoder_init);
+}
+
+
+extern uint64_t
+lzma_lzma2_decoder_memusage(const void *options)
+{
+       return sizeof(lzma_coder)
+                       + lzma_lzma_decoder_memusage_nocheck(options);
+}
+
+
+extern lzma_ret
+lzma_lzma2_props_decode(void **options, const lzma_allocator *allocator,
+               const uint8_t *props, size_t props_size)
+{
+       if (props_size != 1)
+               return LZMA_OPTIONS_ERROR;
+
+       // Check that reserved bits are unset.
+       if (props[0] & 0xC0)
+               return LZMA_OPTIONS_ERROR;
+
+       // Decode the dictionary size.
+       if (props[0] > 40)
+               return LZMA_OPTIONS_ERROR;
+
+       lzma_options_lzma *opt = lzma_alloc(
+                       sizeof(lzma_options_lzma), allocator);
+       if (opt == NULL)
+               return LZMA_MEM_ERROR;
+
+       if (props[0] == 40) {
+               opt->dict_size = UINT32_MAX;
+       } else {
+               opt->dict_size = 2 | (props[0] & 1);
+               opt->dict_size <<= props[0] / 2 + 11;
+       }
+
+       opt->preset_dict = NULL;
+       opt->preset_dict_size = 0;
+
+       *options = opt;
+
+       return LZMA_OK;
+}
diff --git a/lzma/lzma/lzma2_decoder.h b/lzma/lzma/lzma2_decoder.h
new file mode 100644 (file)
index 0000000..ef2dcbf
--- /dev/null
@@ -0,0 +1,29 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma2_decoder.h
+/// \brief      LZMA2 decoder
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_LZMA2_DECODER_H
+#define LZMA_LZMA2_DECODER_H
+
+#include "common.h"
+
+extern lzma_ret lzma_lzma2_decoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters);
+
+extern uint64_t lzma_lzma2_decoder_memusage(const void *options);
+
+extern lzma_ret lzma_lzma2_props_decode(
+               void **options, const lzma_allocator *allocator,
+               const uint8_t *props, size_t props_size);
+
+#endif
diff --git a/lzma/lzma/lzma2_encoder.c b/lzma/lzma/lzma2_encoder.c
new file mode 100644 (file)
index 0000000..b6756bf
--- /dev/null
@@ -0,0 +1,403 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma2_encoder.c
+/// \brief      LZMA2 encoder
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "lz_encoder.h"
+#include "lzma_encoder.h"
+#include "fastpos.h"
+#include "lzma2_encoder.h"
+
+
+struct lzma_coder_s {
+       enum {
+               SEQ_INIT,
+               SEQ_LZMA_ENCODE,
+               SEQ_LZMA_COPY,
+               SEQ_UNCOMPRESSED_HEADER,
+               SEQ_UNCOMPRESSED_COPY,
+       } sequence;
+
+       /// LZMA encoder
+       lzma_coder *lzma;
+
+       /// LZMA options currently in use.
+       lzma_options_lzma opt_cur;
+
+       bool need_properties;
+       bool need_state_reset;
+       bool need_dictionary_reset;
+
+       /// Uncompressed size of a chunk
+       size_t uncompressed_size;
+
+       /// Compressed size of a chunk (excluding headers); this is also used
+       /// to indicate the end of buf[] in SEQ_LZMA_COPY.
+       size_t compressed_size;
+
+       /// Read position in buf[]
+       size_t buf_pos;
+
+       /// Buffer to hold the chunk header and LZMA compressed data
+       uint8_t buf[LZMA2_HEADER_MAX + LZMA2_CHUNK_MAX];
+};
+
+
+static void
+lzma2_header_lzma(lzma_coder *coder)
+{
+       assert(coder->uncompressed_size > 0);
+       assert(coder->uncompressed_size <= LZMA2_UNCOMPRESSED_MAX);
+       assert(coder->compressed_size > 0);
+       assert(coder->compressed_size <= LZMA2_CHUNK_MAX);
+
+       size_t pos;
+
+       if (coder->need_properties) {
+               pos = 0;
+
+               if (coder->need_dictionary_reset)
+                       coder->buf[pos] = 0x80 + (3 << 5);
+               else
+                       coder->buf[pos] = 0x80 + (2 << 5);
+       } else {
+               pos = 1;
+
+               if (coder->need_state_reset)
+                       coder->buf[pos] = 0x80 + (1 << 5);
+               else
+                       coder->buf[pos] = 0x80;
+       }
+
+       // Set the start position for copying.
+       coder->buf_pos = pos;
+
+       // Uncompressed size
+       size_t size = coder->uncompressed_size - 1;
+       coder->buf[pos++] += size >> 16;
+       coder->buf[pos++] = (size >> 8) & 0xFF;
+       coder->buf[pos++] = size & 0xFF;
+
+       // Compressed size
+       size = coder->compressed_size - 1;
+       coder->buf[pos++] = size >> 8;
+       coder->buf[pos++] = size & 0xFF;
+
+       // Properties, if needed
+       if (coder->need_properties)
+               lzma_lzma_lclppb_encode(&coder->opt_cur, coder->buf + pos);
+
+       coder->need_properties = false;
+       coder->need_state_reset = false;
+       coder->need_dictionary_reset = false;
+
+       // The copying code uses coder->compressed_size to indicate the end
+       // of coder->buf[], so we need add the maximum size of the header here.
+       coder->compressed_size += LZMA2_HEADER_MAX;
+
+       return;
+}
+
+
+static void
+lzma2_header_uncompressed(lzma_coder *coder)
+{
+       assert(coder->uncompressed_size > 0);
+       assert(coder->uncompressed_size <= LZMA2_CHUNK_MAX);
+
+       // If this is the first chunk, we need to include dictionary
+       // reset indicator.
+       if (coder->need_dictionary_reset)
+               coder->buf[0] = 1;
+       else
+               coder->buf[0] = 2;
+
+       coder->need_dictionary_reset = false;
+
+       // "Compressed" size
+       coder->buf[1] = (coder->uncompressed_size - 1) >> 8;
+       coder->buf[2] = (coder->uncompressed_size - 1) & 0xFF;
+
+       // Set the start position for copying.
+       coder->buf_pos = 0;
+       return;
+}
+
+
+static lzma_ret
+lzma2_encode(lzma_coder *restrict coder, lzma_mf *restrict mf,
+               uint8_t *restrict out, size_t *restrict out_pos,
+               size_t out_size)
+{
+       while (*out_pos < out_size)
+       switch (coder->sequence) {
+       case SEQ_INIT:
+               // If there's no input left and we are flushing or finishing,
+               // don't start a new chunk.
+               if (mf_unencoded(mf) == 0) {
+                       // Write end of payload marker if finishing.
+                       if (mf->action == LZMA_FINISH)
+                               out[(*out_pos)++] = 0;
+
+                       return mf->action == LZMA_RUN
+                                       ? LZMA_OK : LZMA_STREAM_END;
+               }
+
+               if (coder->need_state_reset)
+                       return_if_error(lzma_lzma_encoder_reset(
+                                       coder->lzma, &coder->opt_cur));
+
+               coder->uncompressed_size = 0;
+               coder->compressed_size = 0;
+               coder->sequence = SEQ_LZMA_ENCODE;
+
+       // Fall through
+
+       case SEQ_LZMA_ENCODE: {
+               // Calculate how much more uncompressed data this chunk
+               // could accept.
+               const uint32_t left = LZMA2_UNCOMPRESSED_MAX
+                               - coder->uncompressed_size;
+               uint32_t limit;
+
+               if (left < mf->match_len_max) {
+                       // Must flush immediately since the next LZMA symbol
+                       // could make the uncompressed size of the chunk too
+                       // big.
+                       limit = 0;
+               } else {
+                       // Calculate maximum read_limit that is OK from point
+                       // of view of LZMA2 chunk size.
+                       limit = mf->read_pos - mf->read_ahead
+                                       + left - mf->match_len_max;
+               }
+
+               // Save the start position so that we can update
+               // coder->uncompressed_size.
+               const uint32_t read_start = mf->read_pos - mf->read_ahead;
+
+               // Call the LZMA encoder until the chunk is finished.
+               const lzma_ret ret = lzma_lzma_encode(coder->lzma, mf,
+                               coder->buf + LZMA2_HEADER_MAX,
+                               &coder->compressed_size,
+                               LZMA2_CHUNK_MAX, limit);
+
+               coder->uncompressed_size += mf->read_pos - mf->read_ahead
+                               - read_start;
+
+               assert(coder->compressed_size <= LZMA2_CHUNK_MAX);
+               assert(coder->uncompressed_size <= LZMA2_UNCOMPRESSED_MAX);
+
+               if (ret != LZMA_STREAM_END)
+                       return LZMA_OK;
+
+               // See if the chunk compressed. If it didn't, we encode it
+               // as uncompressed chunk. This saves a few bytes of space
+               // and makes decoding faster.
+               if (coder->compressed_size >= coder->uncompressed_size) {
+                       coder->uncompressed_size += mf->read_ahead;
+                       assert(coder->uncompressed_size
+                                       <= LZMA2_UNCOMPRESSED_MAX);
+                       mf->read_ahead = 0;
+                       lzma2_header_uncompressed(coder);
+                       coder->need_state_reset = true;
+                       coder->sequence = SEQ_UNCOMPRESSED_HEADER;
+                       break;
+               }
+
+               // The chunk did compress at least by one byte, so we store
+               // the chunk as LZMA.
+               lzma2_header_lzma(coder);
+
+               coder->sequence = SEQ_LZMA_COPY;
+       }
+
+       // Fall through
+
+       case SEQ_LZMA_COPY:
+               // Copy the compressed chunk along its headers to the
+               // output buffer.
+               lzma_bufcpy(coder->buf, &coder->buf_pos,
+                               coder->compressed_size,
+                               out, out_pos, out_size);
+               if (coder->buf_pos != coder->compressed_size)
+                       return LZMA_OK;
+
+               coder->sequence = SEQ_INIT;
+               break;
+
+       case SEQ_UNCOMPRESSED_HEADER:
+               // Copy the three-byte header to indicate uncompressed chunk.
+               lzma_bufcpy(coder->buf, &coder->buf_pos,
+                               LZMA2_HEADER_UNCOMPRESSED,
+                               out, out_pos, out_size);
+               if (coder->buf_pos != LZMA2_HEADER_UNCOMPRESSED)
+                       return LZMA_OK;
+
+               coder->sequence = SEQ_UNCOMPRESSED_COPY;
+
+       // Fall through
+
+       case SEQ_UNCOMPRESSED_COPY:
+               // Copy the uncompressed data as is from the dictionary
+               // to the output buffer.
+               mf_read(mf, out, out_pos, out_size, &coder->uncompressed_size);
+               if (coder->uncompressed_size != 0)
+                       return LZMA_OK;
+
+               coder->sequence = SEQ_INIT;
+               break;
+       }
+
+       return LZMA_OK;
+}
+
+
+static void
+lzma2_encoder_end(lzma_coder *coder, const lzma_allocator *allocator)
+{
+       lzma_free(coder->lzma, allocator);
+       lzma_free(coder, allocator);
+       return;
+}
+
+
+static lzma_ret
+lzma2_encoder_options_update(lzma_coder *coder, const lzma_filter *filter)
+{
+       // New options can be set only when there is no incomplete chunk.
+       // This is the case at the beginning of the raw stream and right
+       // after LZMA_SYNC_FLUSH.
+       if (filter->options == NULL || coder->sequence != SEQ_INIT)
+               return LZMA_PROG_ERROR;
+
+       // Look if there are new options. At least for now,
+       // only lc/lp/pb can be changed.
+       const lzma_options_lzma *opt = filter->options;
+       if (coder->opt_cur.lc != opt->lc || coder->opt_cur.lp != opt->lp
+                       || coder->opt_cur.pb != opt->pb) {
+               // Validate the options.
+               if (opt->lc > LZMA_LCLP_MAX || opt->lp > LZMA_LCLP_MAX
+                               || opt->lc + opt->lp > LZMA_LCLP_MAX
+                               || opt->pb > LZMA_PB_MAX)
+                       return LZMA_OPTIONS_ERROR;
+
+               // The new options will be used when the encoder starts
+               // a new LZMA2 chunk.
+               coder->opt_cur.lc = opt->lc;
+               coder->opt_cur.lp = opt->lp;
+               coder->opt_cur.pb = opt->pb;
+               coder->need_properties = true;
+               coder->need_state_reset = true;
+       }
+
+       return LZMA_OK;
+}
+
+
+static lzma_ret
+lzma2_encoder_init(lzma_lz_encoder *lz, const lzma_allocator *allocator,
+               const void *options, lzma_lz_options *lz_options)
+{
+       if (options == NULL)
+               return LZMA_PROG_ERROR;
+
+       if (lz->coder == NULL) {
+               lz->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+               if (lz->coder == NULL)
+                       return LZMA_MEM_ERROR;
+
+               lz->code = &lzma2_encode;
+               lz->end = &lzma2_encoder_end;
+               lz->options_update = &lzma2_encoder_options_update;
+
+               lz->coder->lzma = NULL;
+       }
+
+       lz->coder->opt_cur = *(const lzma_options_lzma *)(options);
+
+       lz->coder->sequence = SEQ_INIT;
+       lz->coder->need_properties = true;
+       lz->coder->need_state_reset = false;
+       lz->coder->need_dictionary_reset
+                       = lz->coder->opt_cur.preset_dict == NULL
+                       || lz->coder->opt_cur.preset_dict_size == 0;
+
+       // Initialize LZMA encoder
+       return_if_error(lzma_lzma_encoder_create(&lz->coder->lzma, allocator,
+                       &lz->coder->opt_cur, lz_options));
+
+       // Make sure that we will always have enough history available in
+       // case we need to use uncompressed chunks. They are used when the
+       // compressed size of a chunk is not smaller than the uncompressed
+       // size, so we need to have at least LZMA2_COMPRESSED_MAX bytes
+       // history available.
+       if (lz_options->before_size + lz_options->dict_size < LZMA2_CHUNK_MAX)
+               lz_options->before_size
+                               = LZMA2_CHUNK_MAX - lz_options->dict_size;
+
+       return LZMA_OK;
+}
+
+
+extern lzma_ret
+lzma_lzma2_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
+               const lzma_filter_info *filters)
+{
+       return lzma_lz_encoder_init(
+                       next, allocator, filters, &lzma2_encoder_init);
+}
+
+
+extern uint64_t
+lzma_lzma2_encoder_memusage(const void *options)
+{
+       const uint64_t lzma_mem = lzma_lzma_encoder_memusage(options);
+       if (lzma_mem == UINT64_MAX)
+               return UINT64_MAX;
+
+       return sizeof(lzma_coder) + lzma_mem;
+}
+
+
+extern lzma_ret
+lzma_lzma2_props_encode(const void *options, uint8_t *out)
+{
+       const lzma_options_lzma *const opt = options;
+       uint32_t d = my_max(opt->dict_size, LZMA_DICT_SIZE_MIN);
+
+       // Round up to the next 2^n - 1 or 2^n + 2^(n - 1) - 1 depending
+       // on which one is the next:
+       --d;
+       d |= d >> 2;
+       d |= d >> 3;
+       d |= d >> 4;
+       d |= d >> 8;
+       d |= d >> 16;
+
+       // Get the highest two bits using the proper encoding:
+       if (d == UINT32_MAX)
+               out[0] = 40;
+       else
+               out[0] = get_dist_slot(d + 1) - 24;
+
+       return LZMA_OK;
+}
+
+
+extern uint64_t
+lzma_lzma2_block_size(const void *options)
+{
+       const lzma_options_lzma *const opt = options;
+
+       // Use at least 1 MiB to keep compression ratio better.
+       return my_max((uint64_t)(opt->dict_size) * 3, UINT64_C(1) << 20);
+}
diff --git a/lzma/lzma/lzma2_encoder.h b/lzma/lzma/lzma2_encoder.h
new file mode 100644 (file)
index 0000000..515f183
--- /dev/null
@@ -0,0 +1,43 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma2_encoder.h
+/// \brief      LZMA2 encoder
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_LZMA2_ENCODER_H
+#define LZMA_LZMA2_ENCODER_H
+
+#include "common.h"
+
+
+/// Maximum number of bytes of actual data per chunk (no headers)
+#define LZMA2_CHUNK_MAX (UINT32_C(1) << 16)
+
+/// Maximum uncompressed size of LZMA chunk (no headers)
+#define LZMA2_UNCOMPRESSED_MAX (UINT32_C(1) << 21)
+
+/// Maximum size of LZMA2 headers
+#define LZMA2_HEADER_MAX 6
+
+/// Size of a header for uncompressed chunk
+#define LZMA2_HEADER_UNCOMPRESSED 3
+
+
+extern lzma_ret lzma_lzma2_encoder_init(
+               lzma_next_coder *next, const lzma_allocator *allocator,
+               const lzma_filter_info *filters);
+
+extern uint64_t lzma_lzma2_encoder_memusage(const void *options);
+
+extern lzma_ret lzma_lzma2_props_encode(const void *options, uint8_t *out);
+
+extern uint64_t lzma_lzma2_block_size(const void *options);
+
+#endif
diff --git a/lzma/lzma/lzma_common.h b/lzma/lzma/lzma_common.h
new file mode 100644 (file)
index 0000000..09efd38
--- /dev/null
@@ -0,0 +1,224 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma_common.h
+/// \brief      Private definitions common to LZMA encoder and decoder
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_LZMA_COMMON_H
+#define LZMA_LZMA_COMMON_H
+
+#include "common.h"
+#include "range_common.h"
+
+
+///////////////////
+// Miscellaneous //
+///////////////////
+
+/// Maximum number of position states. A position state is the lowest pos bits
+/// number of bits of the current uncompressed offset. In some places there
+/// are different sets of probabilities for different pos states.
+#define POS_STATES_MAX (1 << LZMA_PB_MAX)
+
+
+/// Validates lc, lp, and pb.
+static inline bool
+is_lclppb_valid(const lzma_options_lzma *options)
+{
+       return options->lc <= LZMA_LCLP_MAX && options->lp <= LZMA_LCLP_MAX
+                       && options->lc + options->lp <= LZMA_LCLP_MAX
+                       && options->pb <= LZMA_PB_MAX;
+}
+
+
+///////////
+// State //
+///////////
+
+/// This enum is used to track which events have occurred most recently and
+/// in which order. This information is used to predict the next event.
+///
+/// Events:
+///  - Literal: One 8-bit byte
+///  - Match: Repeat a chunk of data at some distance
+///  - Long repeat: Multi-byte match at a recently seen distance
+///  - Short repeat: One-byte repeat at a recently seen distance
+///
+/// The event names are in from STATE_oldest_older_previous. REP means
+/// either short or long repeated match, and NONLIT means any non-literal.
+typedef enum {
+       STATE_LIT_LIT,
+       STATE_MATCH_LIT_LIT,
+       STATE_REP_LIT_LIT,
+       STATE_SHORTREP_LIT_LIT,
+       STATE_MATCH_LIT,
+       STATE_REP_LIT,
+       STATE_SHORTREP_LIT,
+       STATE_LIT_MATCH,
+       STATE_LIT_LONGREP,
+       STATE_LIT_SHORTREP,
+       STATE_NONLIT_MATCH,
+       STATE_NONLIT_REP,
+} lzma_lzma_state;
+
+
+/// Total number of states
+#define STATES 12
+
+/// The lowest 7 states indicate that the previous state was a literal.
+#define LIT_STATES 7
+
+
+/// Indicate that the latest state was a literal.
+#define update_literal(state) \
+       state = ((state) <= STATE_SHORTREP_LIT_LIT \
+                       ? STATE_LIT_LIT \
+                       : ((state) <= STATE_LIT_SHORTREP \
+                               ? (state) - 3 \
+                               : (state) - 6))
+
+/// Indicate that the latest state was a match.
+#define update_match(state) \
+       state = ((state) < LIT_STATES ? STATE_LIT_MATCH : STATE_NONLIT_MATCH)
+
+/// Indicate that the latest state was a long repeated match.
+#define update_long_rep(state) \
+       state = ((state) < LIT_STATES ? STATE_LIT_LONGREP : STATE_NONLIT_REP)
+
+/// Indicate that the latest state was a short match.
+#define update_short_rep(state) \
+       state = ((state) < LIT_STATES ? STATE_LIT_SHORTREP : STATE_NONLIT_REP)
+
+/// Test if the previous state was a literal.
+#define is_literal_state(state) \
+       ((state) < LIT_STATES)
+
+
+/////////////
+// Literal //
+/////////////
+
+/// Each literal coder is divided in three sections:
+///   - 0x001-0x0FF: Without match byte
+///   - 0x101-0x1FF: With match byte; match bit is 0
+///   - 0x201-0x2FF: With match byte; match bit is 1
+///
+/// Match byte is used when the previous LZMA symbol was something else than
+/// a literal (that is, it was some kind of match).
+#define LITERAL_CODER_SIZE 0x300
+
+/// Maximum number of literal coders
+#define LITERAL_CODERS_MAX (1 << LZMA_LCLP_MAX)
+
+/// Locate the literal coder for the next literal byte. The choice depends on
+///   - the lowest literal_pos_bits bits of the position of the current
+///     byte; and
+///   - the highest literal_context_bits bits of the previous byte.
+#define literal_subcoder(probs, lc, lp_mask, pos, prev_byte) \
+       ((probs)[(((pos) & lp_mask) << lc) + ((prev_byte) >> (8 - lc))])
+
+
+static inline void
+literal_init(probability (*probs)[LITERAL_CODER_SIZE],
+               uint32_t lc, uint32_t lp)
+{
+       assert(lc + lp <= LZMA_LCLP_MAX);
+
+       const uint32_t coders = 1U << (lc + lp);
+
+       for (uint32_t i = 0; i < coders; ++i)
+               for (uint32_t j = 0; j < LITERAL_CODER_SIZE; ++j)
+                       bit_reset(probs[i][j]);
+
+       return;
+}
+
+
+//////////////////
+// Match length //
+//////////////////
+
+// Minimum length of a match is two bytes.
+#define MATCH_LEN_MIN 2
+
+// Match length is encoded with 4, 5, or 10 bits.
+//
+// Length   Bits
+//  2-9      4 = Choice=0 + 3 bits
+// 10-17     5 = Choice=1 + Choice2=0 + 3 bits
+// 18-273   10 = Choice=1 + Choice2=1 + 8 bits
+#define LEN_LOW_BITS 3
+#define LEN_LOW_SYMBOLS (1 << LEN_LOW_BITS)
+#define LEN_MID_BITS 3
+#define LEN_MID_SYMBOLS (1 << LEN_MID_BITS)
+#define LEN_HIGH_BITS 8
+#define LEN_HIGH_SYMBOLS (1 << LEN_HIGH_BITS)
+#define LEN_SYMBOLS (LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS + LEN_HIGH_SYMBOLS)
+
+// Maximum length of a match is 273 which is a result of the encoding
+// described above.
+#define MATCH_LEN_MAX (MATCH_LEN_MIN + LEN_SYMBOLS - 1)
+
+
+////////////////////
+// Match distance //
+////////////////////
+
+// Different sets of probabilities are used for match distances that have very
+// short match length: Lengths of 2, 3, and 4 bytes have a separate set of
+// probabilities for each length. The matches with longer length use a shared
+// set of probabilities.
+#define DIST_STATES 4
+
+// Macro to get the index of the appropriate probability array.
+#define get_dist_state(len) \
+       ((len) < DIST_STATES + MATCH_LEN_MIN \
+               ? (len) - MATCH_LEN_MIN \
+               : DIST_STATES - 1)
+
+// The highest two bits of a match distance (distance slot) are encoded
+// using six bits. See fastpos.h for more explanation.
+#define DIST_SLOT_BITS 6
+#define DIST_SLOTS (1 << DIST_SLOT_BITS)
+
+// Match distances up to 127 are fully encoded using probabilities. Since
+// the highest two bits (distance slot) are always encoded using six bits,
+// the distances 0-3 don't need any additional bits to encode, since the
+// distance slot itself is the same as the actual distance. DIST_MODEL_START
+// indicates the first distance slot where at least one additional bit is
+// needed.
+#define DIST_MODEL_START 4
+
+// Match distances greater than 127 are encoded in three pieces:
+//   - distance slot: the highest two bits
+//   - direct bits: 2-26 bits below the highest two bits
+//   - alignment bits: four lowest bits
+//
+// Direct bits don't use any probabilities.
+//
+// The distance slot value of 14 is for distances 128-191 (see the table in
+// fastpos.h to understand why).
+#define DIST_MODEL_END 14
+
+// Distance slots that indicate a distance <= 127.
+#define FULL_DISTANCES_BITS (DIST_MODEL_END / 2)
+#define FULL_DISTANCES (1 << FULL_DISTANCES_BITS)
+
+// For match distances greater than 127, only the highest two bits and the
+// lowest four bits (alignment) is encoded using probabilities.
+#define ALIGN_BITS 4
+#define ALIGN_SIZE (1 << ALIGN_BITS)
+#define ALIGN_MASK (ALIGN_SIZE - 1)
+
+// LZMA remembers the four most recent match distances. Reusing these distances
+// tends to take less space than re-encoding the actual distance value.
+#define REPS 4
+
+#endif
diff --git a/lzma/lzma/lzma_decoder.c b/lzma/lzma/lzma_decoder.c
new file mode 100644 (file)
index 0000000..b8f9317
--- /dev/null
@@ -0,0 +1,1061 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma_decoder.c
+/// \brief      LZMA decoder
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "lz_decoder.h"
+#include "lzma_common.h"
+#include "lzma_decoder.h"
+#include "range_decoder.h"
+
+
+#ifdef HAVE_SMALL
+
+// Macros for (somewhat) size-optimized code.
+#define seq_4(seq) seq
+
+#define seq_6(seq) seq
+
+#define seq_8(seq) seq
+
+#define seq_len(seq) \
+       seq ## _CHOICE, \
+       seq ## _CHOICE2, \
+       seq ## _BITTREE
+
+#define len_decode(target, ld, pos_state, seq) \
+do { \
+case seq ## _CHOICE: \
+       rc_if_0(ld.choice, seq ## _CHOICE) { \
+               rc_update_0(ld.choice); \
+               probs = ld.low[pos_state];\
+               limit = LEN_LOW_SYMBOLS; \
+               target = MATCH_LEN_MIN; \
+       } else { \
+               rc_update_1(ld.choice); \
+case seq ## _CHOICE2: \
+               rc_if_0(ld.choice2, seq ## _CHOICE2) { \
+                       rc_update_0(ld.choice2); \
+                       probs = ld.mid[pos_state]; \
+                       limit = LEN_MID_SYMBOLS; \
+                       target = MATCH_LEN_MIN + LEN_LOW_SYMBOLS; \
+               } else { \
+                       rc_update_1(ld.choice2); \
+                       probs = ld.high; \
+                       limit = LEN_HIGH_SYMBOLS; \
+                       target = MATCH_LEN_MIN + LEN_LOW_SYMBOLS \
+                                       + LEN_MID_SYMBOLS; \
+               } \
+       } \
+       symbol = 1; \
+case seq ## _BITTREE: \
+       do { \
+               rc_bit(probs[symbol], , , seq ## _BITTREE); \
+       } while (symbol < limit); \
+       target += symbol - limit; \
+} while (0)
+
+#else // HAVE_SMALL
+
+// Unrolled versions
+#define seq_4(seq) \
+       seq ## 0, \
+       seq ## 1, \
+       seq ## 2, \
+       seq ## 3
+
+#define seq_6(seq) \
+       seq ## 0, \
+       seq ## 1, \
+       seq ## 2, \
+       seq ## 3, \
+       seq ## 4, \
+       seq ## 5
+
+#define seq_8(seq) \
+       seq ## 0, \
+       seq ## 1, \
+       seq ## 2, \
+       seq ## 3, \
+       seq ## 4, \
+       seq ## 5, \
+       seq ## 6, \
+       seq ## 7
+
+#define seq_len(seq) \
+       seq ## _CHOICE, \
+       seq ## _LOW0, \
+       seq ## _LOW1, \
+       seq ## _LOW2, \
+       seq ## _CHOICE2, \
+       seq ## _MID0, \
+       seq ## _MID1, \
+       seq ## _MID2, \
+       seq ## _HIGH0, \
+       seq ## _HIGH1, \
+       seq ## _HIGH2, \
+       seq ## _HIGH3, \
+       seq ## _HIGH4, \
+       seq ## _HIGH5, \
+       seq ## _HIGH6, \
+       seq ## _HIGH7
+
+#define len_decode(target, ld, pos_state, seq) \
+do { \
+       symbol = 1; \
+case seq ## _CHOICE: \
+       rc_if_0(ld.choice, seq ## _CHOICE) { \
+               rc_update_0(ld.choice); \
+               rc_bit_case(ld.low[pos_state][symbol], , , seq ## _LOW0); \
+               rc_bit_case(ld.low[pos_state][symbol], , , seq ## _LOW1); \
+               rc_bit_case(ld.low[pos_state][symbol], , , seq ## _LOW2); \
+               target = symbol - LEN_LOW_SYMBOLS + MATCH_LEN_MIN; \
+       } else { \
+               rc_update_1(ld.choice); \
+case seq ## _CHOICE2: \
+               rc_if_0(ld.choice2, seq ## _CHOICE2) { \
+                       rc_update_0(ld.choice2); \
+                       rc_bit_case(ld.mid[pos_state][symbol], , , \
+                                       seq ## _MID0); \
+                       rc_bit_case(ld.mid[pos_state][symbol], , , \
+                                       seq ## _MID1); \
+                       rc_bit_case(ld.mid[pos_state][symbol], , , \
+                                       seq ## _MID2); \
+                       target = symbol - LEN_MID_SYMBOLS \
+                                       + MATCH_LEN_MIN + LEN_LOW_SYMBOLS; \
+               } else { \
+                       rc_update_1(ld.choice2); \
+                       rc_bit_case(ld.high[symbol], , , seq ## _HIGH0); \
+                       rc_bit_case(ld.high[symbol], , , seq ## _HIGH1); \
+                       rc_bit_case(ld.high[symbol], , , seq ## _HIGH2); \
+                       rc_bit_case(ld.high[symbol], , , seq ## _HIGH3); \
+                       rc_bit_case(ld.high[symbol], , , seq ## _HIGH4); \
+                       rc_bit_case(ld.high[symbol], , , seq ## _HIGH5); \
+                       rc_bit_case(ld.high[symbol], , , seq ## _HIGH6); \
+                       rc_bit_case(ld.high[symbol], , , seq ## _HIGH7); \
+                       target = symbol - LEN_HIGH_SYMBOLS \
+                                       + MATCH_LEN_MIN \
+                                       + LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS; \
+               } \
+       } \
+} while (0)
+
+#endif // HAVE_SMALL
+
+
+/// Length decoder probabilities; see comments in lzma_common.h.
+typedef struct {
+       probability choice;
+       probability choice2;
+       probability low[POS_STATES_MAX][LEN_LOW_SYMBOLS];
+       probability mid[POS_STATES_MAX][LEN_MID_SYMBOLS];
+       probability high[LEN_HIGH_SYMBOLS];
+} lzma_length_decoder;
+
+
+struct lzma_coder_s {
+       ///////////////////
+       // Probabilities //
+       ///////////////////
+
+       /// Literals; see comments in lzma_common.h.
+       probability literal[LITERAL_CODERS_MAX][LITERAL_CODER_SIZE];
+
+       /// If 1, it's a match. Otherwise it's a single 8-bit literal.
+       probability is_match[STATES][POS_STATES_MAX];
+
+       /// If 1, it's a repeated match. The distance is one of rep0 .. rep3.
+       probability is_rep[STATES];
+
+       /// If 0, distance of a repeated match is rep0.
+       /// Otherwise check is_rep1.
+       probability is_rep0[STATES];
+
+       /// If 0, distance of a repeated match is rep1.
+       /// Otherwise check is_rep2.
+       probability is_rep1[STATES];
+
+       /// If 0, distance of a repeated match is rep2. Otherwise it is rep3.
+       probability is_rep2[STATES];
+
+       /// If 1, the repeated match has length of one byte. Otherwise
+       /// the length is decoded from rep_len_decoder.
+       probability is_rep0_long[STATES][POS_STATES_MAX];
+
+       /// Probability tree for the highest two bits of the match distance.
+       /// There is a separate probability tree for match lengths of
+       /// 2 (i.e. MATCH_LEN_MIN), 3, 4, and [5, 273].
+       probability dist_slot[DIST_STATES][DIST_SLOTS];
+
+       /// Probability trees for additional bits for match distance when the
+       /// distance is in the range [4, 127].
+       probability pos_special[FULL_DISTANCES - DIST_MODEL_END];
+
+       /// Probability tree for the lowest four bits of a match distance
+       /// that is equal to or greater than 128.
+       probability pos_align[ALIGN_SIZE];
+
+       /// Length of a normal match
+       lzma_length_decoder match_len_decoder;
+
+       /// Length of a repeated match
+       lzma_length_decoder rep_len_decoder;
+
+       ///////////////////
+       // Decoder state //
+       ///////////////////
+
+       // Range coder
+       lzma_range_decoder rc;
+
+       // Types of the most recently seen LZMA symbols
+       lzma_lzma_state state;
+
+       uint32_t rep0;      ///< Distance of the latest match
+       uint32_t rep1;      ///< Distance of second latest match
+       uint32_t rep2;      ///< Distance of third latest match
+       uint32_t rep3;      ///< Distance of fourth latest match
+
+       uint32_t pos_mask; // (1U << pb) - 1
+       uint32_t literal_context_bits;
+       uint32_t literal_pos_mask;
+
+       /// Uncompressed size as bytes, or LZMA_VLI_UNKNOWN if end of
+       /// payload marker is expected.
+       lzma_vli uncompressed_size;
+
+       ////////////////////////////////
+       // State of incomplete symbol //
+       ////////////////////////////////
+
+       /// Position where to continue the decoder loop
+       enum {
+               SEQ_NORMALIZE,
+               SEQ_IS_MATCH,
+               seq_8(SEQ_LITERAL),
+               seq_8(SEQ_LITERAL_MATCHED),
+               SEQ_LITERAL_WRITE,
+               SEQ_IS_REP,
+               seq_len(SEQ_MATCH_LEN),
+               seq_6(SEQ_DIST_SLOT),
+               SEQ_DIST_MODEL,
+               SEQ_DIRECT,
+               seq_4(SEQ_ALIGN),
+               SEQ_EOPM,
+               SEQ_IS_REP0,
+               SEQ_SHORTREP,
+               SEQ_IS_REP0_LONG,
+               SEQ_IS_REP1,
+               SEQ_IS_REP2,
+               seq_len(SEQ_REP_LEN),
+               SEQ_COPY,
+       } sequence;
+
+       /// Base of the current probability tree
+       probability *probs;
+
+       /// Symbol being decoded. This is also used as an index variable in
+       /// bittree decoders: probs[symbol]
+       uint32_t symbol;
+
+       /// Used as a loop termination condition on bittree decoders and
+       /// direct bits decoder.
+       uint32_t limit;
+
+       /// Matched literal decoder: 0x100 or 0 to help avoiding branches.
+       /// Bittree reverse decoders: Offset of the next bit: 1 << offset
+       uint32_t offset;
+
+       /// If decoding a literal: match byte.
+       /// If decoding a match: length of the match.
+       uint32_t len;
+};
+
+
+static lzma_ret
+lzma_decode(lzma_coder *restrict coder, lzma_dict *restrict dictptr,
+               const uint8_t *restrict in,
+               size_t *restrict in_pos, size_t in_size)
+{
+       ////////////////////
+       // Initialization //
+       ////////////////////
+
+       {
+               const lzma_ret ret = rc_read_init(
+                               &coder->rc, in, in_pos, in_size);
+               if (ret != LZMA_STREAM_END)
+                       return ret;
+       }
+
+       ///////////////
+       // Variables //
+       ///////////////
+
+       // Making local copies of often-used variables improves both
+       // speed and readability.
+
+       lzma_dict dict = *dictptr;
+
+       const size_t dict_start = dict.pos;
+
+       // Range decoder
+       rc_to_local(coder->rc, *in_pos);
+
+       // State
+       uint32_t state = coder->state;
+       uint32_t rep0 = coder->rep0;
+       uint32_t rep1 = coder->rep1;
+       uint32_t rep2 = coder->rep2;
+       uint32_t rep3 = coder->rep3;
+
+       const uint32_t pos_mask = coder->pos_mask;
+
+       // These variables are actually needed only if we last time ran
+       // out of input in the middle of the decoder loop.
+       probability *probs = coder->probs;
+       uint32_t symbol = coder->symbol;
+       uint32_t limit = coder->limit;
+       uint32_t offset = coder->offset;
+       uint32_t len = coder->len;
+
+       const uint32_t literal_pos_mask = coder->literal_pos_mask;
+       const uint32_t literal_context_bits = coder->literal_context_bits;
+
+       // Temporary variables
+       uint32_t pos_state = dict.pos & pos_mask;
+
+       lzma_ret ret = LZMA_OK;
+
+       // If uncompressed size is known, there must be no end of payload
+       // marker.
+       const bool no_eopm = coder->uncompressed_size
+                       != LZMA_VLI_UNKNOWN;
+       if (no_eopm && coder->uncompressed_size < dict.limit - dict.pos)
+               dict.limit = dict.pos + (size_t)(coder->uncompressed_size);
+
+       // The main decoder loop. The "switch" is used to restart the decoder at
+       // correct location. Once restarted, the "switch" is no longer used.
+       switch (coder->sequence)
+       while (true) {
+               // Calculate new pos_state. This is skipped on the first loop
+               // since we already calculated it when setting up the local
+               // variables.
+               pos_state = dict.pos & pos_mask;
+
+       case SEQ_NORMALIZE:
+       case SEQ_IS_MATCH:
+               if (unlikely(no_eopm && dict.pos == dict.limit))
+                       break;
+
+               rc_if_0(coder->is_match[state][pos_state], SEQ_IS_MATCH) {
+                       rc_update_0(coder->is_match[state][pos_state]);
+
+                       // It's a literal i.e. a single 8-bit byte.
+
+                       probs = literal_subcoder(coder->literal,
+                                       literal_context_bits, literal_pos_mask,
+                                       dict.pos, dict_get(&dict, 0));
+                       symbol = 1;
+
+                       if (is_literal_state(state)) {
+                               // Decode literal without match byte.
+#ifdef HAVE_SMALL
+       case SEQ_LITERAL:
+                               do {
+                                       rc_bit(probs[symbol], , , SEQ_LITERAL);
+                               } while (symbol < (1 << 8));
+#else
+                               rc_bit_case(probs[symbol], , , SEQ_LITERAL0);
+                               rc_bit_case(probs[symbol], , , SEQ_LITERAL1);
+                               rc_bit_case(probs[symbol], , , SEQ_LITERAL2);
+                               rc_bit_case(probs[symbol], , , SEQ_LITERAL3);
+                               rc_bit_case(probs[symbol], , , SEQ_LITERAL4);
+                               rc_bit_case(probs[symbol], , , SEQ_LITERAL5);
+                               rc_bit_case(probs[symbol], , , SEQ_LITERAL6);
+                               rc_bit_case(probs[symbol], , , SEQ_LITERAL7);
+#endif
+                       } else {
+                               // Decode literal with match byte.
+                               //
+                               // We store the byte we compare against
+                               // ("match byte") to "len" to minimize the
+                               // number of variables we need to store
+                               // between decoder calls.
+                               len = dict_get(&dict, rep0) << 1;
+
+                               // The usage of "offset" allows omitting some
+                               // branches, which should give tiny speed
+                               // improvement on some CPUs. "offset" gets
+                               // set to zero if match_bit didn't match.
+                               offset = 0x100;
+
+#ifdef HAVE_SMALL
+       case SEQ_LITERAL_MATCHED:
+                               do {
+                                       const uint32_t match_bit
+                                                       = len & offset;
+                                       const uint32_t subcoder_index
+                                                       = offset + match_bit
+                                                       + symbol;
+
+                                       rc_bit(probs[subcoder_index],
+                                                       offset &= ~match_bit,
+                                                       offset &= match_bit,
+                                                       SEQ_LITERAL_MATCHED);
+
+                                       // It seems to be faster to do this
+                                       // here instead of putting it to the
+                                       // beginning of the loop and then
+                                       // putting the "case" in the middle
+                                       // of the loop.
+                                       len <<= 1;
+
+                               } while (symbol < (1 << 8));
+#else
+                               // Unroll the loop.
+                               uint32_t match_bit;
+                               uint32_t subcoder_index;
+
+#      define d(seq) \
+               case seq: \
+                       match_bit = len & offset; \
+                       subcoder_index = offset + match_bit + symbol; \
+                       rc_bit(probs[subcoder_index], \
+                                       offset &= ~match_bit, \
+                                       offset &= match_bit, \
+                                       seq)
+
+                               d(SEQ_LITERAL_MATCHED0);
+                               len <<= 1;
+                               d(SEQ_LITERAL_MATCHED1);
+                               len <<= 1;
+                               d(SEQ_LITERAL_MATCHED2);
+                               len <<= 1;
+                               d(SEQ_LITERAL_MATCHED3);
+                               len <<= 1;
+                               d(SEQ_LITERAL_MATCHED4);
+                               len <<= 1;
+                               d(SEQ_LITERAL_MATCHED5);
+                               len <<= 1;
+                               d(SEQ_LITERAL_MATCHED6);
+                               len <<= 1;
+                               d(SEQ_LITERAL_MATCHED7);
+#      undef d
+#endif
+                       }
+
+                       //update_literal(state);
+                       // Use a lookup table to update to literal state,
+                       // since compared to other state updates, this would
+                       // need two branches.
+                       static const lzma_lzma_state next_state[] = {
+                               STATE_LIT_LIT,
+                               STATE_LIT_LIT,
+                               STATE_LIT_LIT,
+                               STATE_LIT_LIT,
+                               STATE_MATCH_LIT_LIT,
+                               STATE_REP_LIT_LIT,
+                               STATE_SHORTREP_LIT_LIT,
+                               STATE_MATCH_LIT,
+                               STATE_REP_LIT,
+                               STATE_SHORTREP_LIT,
+                               STATE_MATCH_LIT,
+                               STATE_REP_LIT
+                       };
+                       state = next_state[state];
+
+       case SEQ_LITERAL_WRITE:
+                       if (unlikely(dict_put(&dict, symbol))) {
+                               coder->sequence = SEQ_LITERAL_WRITE;
+                               goto out;
+                       }
+
+                       continue;
+               }
+
+               // Instead of a new byte we are going to get a byte range
+               // (distance and length) which will be repeated from our
+               // output history.
+
+               rc_update_1(coder->is_match[state][pos_state]);
+
+       case SEQ_IS_REP:
+               rc_if_0(coder->is_rep[state], SEQ_IS_REP) {
+                       // Not a repeated match
+                       rc_update_0(coder->is_rep[state]);
+                       update_match(state);
+
+                       // The latest three match distances are kept in
+                       // memory in case there are repeated matches.
+                       rep3 = rep2;
+                       rep2 = rep1;
+                       rep1 = rep0;
+
+                       // Decode the length of the match.
+                       len_decode(len, coder->match_len_decoder,
+                                       pos_state, SEQ_MATCH_LEN);
+
+                       // Prepare to decode the highest two bits of the
+                       // match distance.
+                       probs = coder->dist_slot[get_dist_state(len)];
+                       symbol = 1;
+
+#ifdef HAVE_SMALL
+       case SEQ_DIST_SLOT:
+                       do {
+                               rc_bit(probs[symbol], , , SEQ_DIST_SLOT);
+                       } while (symbol < DIST_SLOTS);
+#else
+                       rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT0);
+                       rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT1);
+                       rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT2);
+                       rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT3);
+                       rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT4);
+                       rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT5);
+#endif
+                       // Get rid of the highest bit that was needed for
+                       // indexing of the probability array.
+                       symbol -= DIST_SLOTS;
+                       assert(symbol <= 63);
+
+                       if (symbol < DIST_MODEL_START) {
+                               // Match distances [0, 3] have only two bits.
+                               rep0 = symbol;
+                       } else {
+                               // Decode the lowest [1, 29] bits of
+                               // the match distance.
+                               limit = (symbol >> 1) - 1;
+                               assert(limit >= 1 && limit <= 30);
+                               rep0 = 2 + (symbol & 1);
+
+                               if (symbol < DIST_MODEL_END) {
+                                       // Prepare to decode the low bits for
+                                       // a distance of [4, 127].
+                                       assert(limit <= 5);
+                                       rep0 <<= limit;
+                                       assert(rep0 <= 96);
+                                       // -1 is fine, because we start
+                                       // decoding at probs[1], not probs[0].
+                                       // NOTE: This violates the C standard,
+                                       // since we are doing pointer
+                                       // arithmetic past the beginning of
+                                       // the array.
+                                       assert((int32_t)(rep0 - symbol - 1)
+                                                       >= -1);
+                                       assert((int32_t)(rep0 - symbol - 1)
+                                                       <= 82);
+                                       probs = coder->pos_special + rep0
+                                                       - symbol - 1;
+                                       symbol = 1;
+                                       offset = 0;
+       case SEQ_DIST_MODEL:
+#ifdef HAVE_SMALL
+                                       do {
+                                               rc_bit(probs[symbol], ,
+                                                       rep0 += 1 << offset,
+                                                       SEQ_DIST_MODEL);
+                                       } while (++offset < limit);
+#else
+                                       switch (limit) {
+                                       case 5:
+                                               assert(offset == 0);
+                                               rc_bit(probs[symbol], ,
+                                                       rep0 += 1,
+                                                       SEQ_DIST_MODEL);
+                                               ++offset;
+                                               --limit;
+                                       case 4:
+                                               rc_bit(probs[symbol], ,
+                                                       rep0 += 1 << offset,
+                                                       SEQ_DIST_MODEL);
+                                               ++offset;
+                                               --limit;
+                                       case 3:
+                                               rc_bit(probs[symbol], ,
+                                                       rep0 += 1 << offset,
+                                                       SEQ_DIST_MODEL);
+                                               ++offset;
+                                               --limit;
+                                       case 2:
+                                               rc_bit(probs[symbol], ,
+                                                       rep0 += 1 << offset,
+                                                       SEQ_DIST_MODEL);
+                                               ++offset;
+                                               --limit;
+                                       case 1:
+                                               // We need "symbol" only for
+                                               // indexing the probability
+                                               // array, thus we can use
+                                               // rc_bit_last() here to omit
+                                               // the unneeded updating of
+                                               // "symbol".
+                                               rc_bit_last(probs[symbol], ,
+                                                       rep0 += 1 << offset,
+                                                       SEQ_DIST_MODEL);
+                                       }
+#endif
+                               } else {
+                                       // The distance is >= 128. Decode the
+                                       // lower bits without probabilities
+                                       // except the lowest four bits.
+                                       assert(symbol >= 14);
+                                       assert(limit >= 6);
+                                       limit -= ALIGN_BITS;
+                                       assert(limit >= 2);
+       case SEQ_DIRECT:
+                                       // Not worth manual unrolling
+                                       do {
+                                               rc_direct(rep0, SEQ_DIRECT);
+                                       } while (--limit > 0);
+
+                                       // Decode the lowest four bits using
+                                       // probabilities.
+                                       rep0 <<= ALIGN_BITS;
+                                       symbol = 1;
+#ifdef HAVE_SMALL
+                                       offset = 0;
+       case SEQ_ALIGN:
+                                       do {
+                                               rc_bit(coder->pos_align[
+                                                               symbol], ,
+                                                       rep0 += 1 << offset,
+                                                       SEQ_ALIGN);
+                                       } while (++offset < ALIGN_BITS);
+#else
+       case SEQ_ALIGN0:
+                                       rc_bit(coder->pos_align[symbol], ,
+                                                       rep0 += 1, SEQ_ALIGN0);
+       case SEQ_ALIGN1:
+                                       rc_bit(coder->pos_align[symbol], ,
+                                                       rep0 += 2, SEQ_ALIGN1);
+       case SEQ_ALIGN2:
+                                       rc_bit(coder->pos_align[symbol], ,
+                                                       rep0 += 4, SEQ_ALIGN2);
+       case SEQ_ALIGN3:
+                                       // Like in SEQ_DIST_MODEL, we don't
+                                       // need "symbol" for anything else
+                                       // than indexing the probability array.
+                                       rc_bit_last(coder->pos_align[symbol], ,
+                                                       rep0 += 8, SEQ_ALIGN3);
+#endif
+
+                                       if (rep0 == UINT32_MAX) {
+                                               // End of payload marker was
+                                               // found. It must not be
+                                               // present if uncompressed
+                                               // size is known.
+                                               if (coder->uncompressed_size
+                                               != LZMA_VLI_UNKNOWN) {
+                                                       ret = LZMA_DATA_ERROR;
+                                                       goto out;
+                                               }
+
+       case SEQ_EOPM:
+                                               // LZMA1 stream with
+                                               // end-of-payload marker.
+                                               rc_normalize(SEQ_EOPM);
+                                               ret = LZMA_STREAM_END;
+                                               goto out;
+                                       }
+                               }
+                       }
+
+                       // Validate the distance we just decoded.
+                       if (unlikely(!dict_is_distance_valid(&dict, rep0))) {
+                               ret = LZMA_DATA_ERROR;
+                               goto out;
+                       }
+
+               } else {
+                       rc_update_1(coder->is_rep[state]);
+
+                       // Repeated match
+                       //
+                       // The match distance is a value that we have had
+                       // earlier. The latest four match distances are
+                       // available as rep0, rep1, rep2 and rep3. We will
+                       // now decode which of them is the new distance.
+                       //
+                       // There cannot be a match if we haven't produced
+                       // any output, so check that first.
+                       if (unlikely(!dict_is_distance_valid(&dict, 0))) {
+                               ret = LZMA_DATA_ERROR;
+                               goto out;
+                       }
+
+       case SEQ_IS_REP0:
+                       rc_if_0(coder->is_rep0[state], SEQ_IS_REP0) {
+                               rc_update_0(coder->is_rep0[state]);
+                               // The distance is rep0.
+
+       case SEQ_IS_REP0_LONG:
+                               rc_if_0(coder->is_rep0_long[state][pos_state],
+                                               SEQ_IS_REP0_LONG) {
+                                       rc_update_0(coder->is_rep0_long[
+                                                       state][pos_state]);
+
+                                       update_short_rep(state);
+
+       case SEQ_SHORTREP:
+                                       if (unlikely(dict_put(&dict, dict_get(
+                                                       &dict, rep0)))) {
+                                               coder->sequence = SEQ_SHORTREP;
+                                               goto out;
+                                       }
+
+                                       continue;
+                               }
+
+                               // Repeating more than one byte at
+                               // distance of rep0.
+                               rc_update_1(coder->is_rep0_long[
+                                               state][pos_state]);
+
+                       } else {
+                               rc_update_1(coder->is_rep0[state]);
+
+       case SEQ_IS_REP1:
+                               // The distance is rep1, rep2 or rep3. Once
+                               // we find out which one of these three, it
+                               // is stored to rep0 and rep1, rep2 and rep3
+                               // are updated accordingly.
+                               rc_if_0(coder->is_rep1[state], SEQ_IS_REP1) {
+                                       rc_update_0(coder->is_rep1[state]);
+
+                                       const uint32_t distance = rep1;
+                                       rep1 = rep0;
+                                       rep0 = distance;
+
+                               } else {
+                                       rc_update_1(coder->is_rep1[state]);
+       case SEQ_IS_REP2:
+                                       rc_if_0(coder->is_rep2[state],
+                                                       SEQ_IS_REP2) {
+                                               rc_update_0(coder->is_rep2[
+                                                               state]);
+
+                                               const uint32_t distance = rep2;
+                                               rep2 = rep1;
+                                               rep1 = rep0;
+                                               rep0 = distance;
+
+                                       } else {
+                                               rc_update_1(coder->is_rep2[
+                                                               state]);
+
+                                               const uint32_t distance = rep3;
+                                               rep3 = rep2;
+                                               rep2 = rep1;
+                                               rep1 = rep0;
+                                               rep0 = distance;
+                                       }
+                               }
+                       }
+
+                       update_long_rep(state);
+
+                       // Decode the length of the repeated match.
+                       len_decode(len, coder->rep_len_decoder,
+                                       pos_state, SEQ_REP_LEN);
+               }
+
+               /////////////////////////////////
+               // Repeat from history buffer. //
+               /////////////////////////////////
+
+               // The length is always between these limits. There is no way
+               // to trigger the algorithm to set len outside this range.
+               assert(len >= MATCH_LEN_MIN);
+               assert(len <= MATCH_LEN_MAX);
+
+       case SEQ_COPY:
+               // Repeat len bytes from distance of rep0.
+               if (unlikely(dict_repeat(&dict, rep0, &len))) {
+                       coder->sequence = SEQ_COPY;
+                       goto out;
+               }
+       }
+
+       rc_normalize(SEQ_NORMALIZE);
+       coder->sequence = SEQ_IS_MATCH;
+
+out:
+       // Save state
+
+       // NOTE: Must not copy dict.limit.
+       dictptr->pos = dict.pos;
+       dictptr->full = dict.full;
+
+       rc_from_local(coder->rc, *in_pos);
+
+       coder->state = state;
+       coder->rep0 = rep0;
+       coder->rep1 = rep1;
+       coder->rep2 = rep2;
+       coder->rep3 = rep3;
+
+       coder->probs = probs;
+       coder->symbol = symbol;
+       coder->limit = limit;
+       coder->offset = offset;
+       coder->len = len;
+
+       // Update the remaining amount of uncompressed data if uncompressed
+       // size was known.
+       if (coder->uncompressed_size != LZMA_VLI_UNKNOWN) {
+               coder->uncompressed_size -= dict.pos - dict_start;
+
+               // Since there cannot be end of payload marker if the
+               // uncompressed size was known, we check here if we
+               // finished decoding.
+               if (coder->uncompressed_size == 0 && ret == LZMA_OK
+                               && coder->sequence != SEQ_NORMALIZE)
+                       ret = coder->sequence == SEQ_IS_MATCH
+                                       ? LZMA_STREAM_END : LZMA_DATA_ERROR;
+       }
+
+       // We can do an additional check in the range decoder to catch some
+       // corrupted files.
+       if (ret == LZMA_STREAM_END) {
+               if (!rc_is_finished(coder->rc))
+                       ret = LZMA_DATA_ERROR;
+
+               // Reset the range decoder so that it is ready to reinitialize
+               // for a new LZMA2 chunk.
+               rc_reset(coder->rc);
+       }
+
+       return ret;
+}
+
+
+
+static void
+lzma_decoder_uncompressed(lzma_coder *coder, lzma_vli uncompressed_size)
+{
+       coder->uncompressed_size = uncompressed_size;
+}
+
+/*
+extern void
+lzma_lzma_decoder_uncompressed(void *coder_ptr, lzma_vli uncompressed_size)
+{
+       // This is hack.
+       (*(lzma_coder **)(coder))->uncompressed_size = uncompressed_size;
+}
+*/
+
+static void
+lzma_decoder_reset(lzma_coder *coder, const void *opt)
+{
+       const lzma_options_lzma *options = opt;
+
+       // NOTE: We assume that lc/lp/pb are valid since they were
+       // successfully decoded with lzma_lzma_decode_properties().
+
+       // Calculate pos_mask. We don't need pos_bits as is for anything.
+       coder->pos_mask = (1U << options->pb) - 1;
+
+       // Initialize the literal decoder.
+       literal_init(coder->literal, options->lc, options->lp);
+
+       coder->literal_context_bits = options->lc;
+       coder->literal_pos_mask = (1U << options->lp) - 1;
+
+       // State
+       coder->state = STATE_LIT_LIT;
+       coder->rep0 = 0;
+       coder->rep1 = 0;
+       coder->rep2 = 0;
+       coder->rep3 = 0;
+       coder->pos_mask = (1U << options->pb) - 1;
+
+       // Range decoder
+       rc_reset(coder->rc);
+
+       // Bit and bittree decoders
+       for (uint32_t i = 0; i < STATES; ++i) {
+               for (uint32_t j = 0; j <= coder->pos_mask; ++j) {
+                       bit_reset(coder->is_match[i][j]);
+                       bit_reset(coder->is_rep0_long[i][j]);
+               }
+
+               bit_reset(coder->is_rep[i]);
+               bit_reset(coder->is_rep0[i]);
+               bit_reset(coder->is_rep1[i]);
+               bit_reset(coder->is_rep2[i]);
+       }
+
+       for (uint32_t i = 0; i < DIST_STATES; ++i)
+               bittree_reset(coder->dist_slot[i], DIST_SLOT_BITS);
+
+       for (uint32_t i = 0; i < FULL_DISTANCES - DIST_MODEL_END; ++i)
+               bit_reset(coder->pos_special[i]);
+
+       bittree_reset(coder->pos_align, ALIGN_BITS);
+
+       // Len decoders (also bit/bittree)
+       const uint32_t num_pos_states = 1U << options->pb;
+       bit_reset(coder->match_len_decoder.choice);
+       bit_reset(coder->match_len_decoder.choice2);
+       bit_reset(coder->rep_len_decoder.choice);
+       bit_reset(coder->rep_len_decoder.choice2);
+
+       for (uint32_t pos_state = 0; pos_state < num_pos_states; ++pos_state) {
+               bittree_reset(coder->match_len_decoder.low[pos_state],
+                               LEN_LOW_BITS);
+               bittree_reset(coder->match_len_decoder.mid[pos_state],
+                               LEN_MID_BITS);
+
+               bittree_reset(coder->rep_len_decoder.low[pos_state],
+                               LEN_LOW_BITS);
+               bittree_reset(coder->rep_len_decoder.mid[pos_state],
+                               LEN_MID_BITS);
+       }
+
+       bittree_reset(coder->match_len_decoder.high, LEN_HIGH_BITS);
+       bittree_reset(coder->rep_len_decoder.high, LEN_HIGH_BITS);
+
+       coder->sequence = SEQ_IS_MATCH;
+       coder->probs = NULL;
+       coder->symbol = 0;
+       coder->limit = 0;
+       coder->offset = 0;
+       coder->len = 0;
+
+       return;
+}
+
+
+extern lzma_ret
+lzma_lzma_decoder_create(lzma_lz_decoder *lz, const lzma_allocator *allocator,
+               const void *opt, lzma_lz_options *lz_options)
+{
+       if (lz->coder == NULL) {
+               lz->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+               if (lz->coder == NULL)
+                       return LZMA_MEM_ERROR;
+
+               lz->code = &lzma_decode;
+               lz->reset = &lzma_decoder_reset;
+               lz->set_uncompressed = &lzma_decoder_uncompressed;
+       }
+
+       // All dictionary sizes are OK here. LZ decoder will take care of
+       // the special cases.
+       const lzma_options_lzma *options = opt;
+       lz_options->dict_size = options->dict_size;
+       lz_options->preset_dict = options->preset_dict;
+       lz_options->preset_dict_size = options->preset_dict_size;
+
+       return LZMA_OK;
+}
+
+
+/// Allocate and initialize LZMA decoder. This is used only via LZ
+/// initialization (lzma_lzma_decoder_init() passes function pointer to
+/// the LZ initialization).
+static lzma_ret
+lzma_decoder_init(lzma_lz_decoder *lz, const lzma_allocator *allocator,
+               const void *options, lzma_lz_options *lz_options)
+{
+       if (!is_lclppb_valid(options))
+               return LZMA_PROG_ERROR;
+
+       return_if_error(lzma_lzma_decoder_create(
+                       lz, allocator, options, lz_options));
+
+       lzma_decoder_reset(lz->coder, options);
+       lzma_decoder_uncompressed(lz->coder, LZMA_VLI_UNKNOWN);
+
+       return LZMA_OK;
+}
+
+
+extern lzma_ret
+lzma_lzma_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
+               const lzma_filter_info *filters)
+{
+       // LZMA can only be the last filter in the chain. This is enforced
+       // by the raw_decoder initialization.
+       assert(filters[1].init == NULL);
+
+       return lzma_lz_decoder_init(next, allocator, filters,
+                       &lzma_decoder_init);
+}
+
+
+extern bool
+lzma_lzma_lclppb_decode(lzma_options_lzma *options, uint8_t byte)
+{
+       if (byte > (4 * 5 + 4) * 9 + 8)
+               return true;
+
+       // See the file format specification to understand this.
+       options->pb = byte / (9 * 5);
+       byte -= options->pb * 9 * 5;
+       options->lp = byte / 9;
+       options->lc = byte - options->lp * 9;
+
+       return options->lc + options->lp > LZMA_LCLP_MAX;
+}
+
+
+extern uint64_t
+lzma_lzma_decoder_memusage_nocheck(const void *options)
+{
+       const lzma_options_lzma *const opt = options;
+       return sizeof(lzma_coder) + lzma_lz_decoder_memusage(opt->dict_size);
+}
+
+
+extern uint64_t
+lzma_lzma_decoder_memusage(const void *options)
+{
+       if (!is_lclppb_valid(options))
+               return UINT64_MAX;
+
+       return lzma_lzma_decoder_memusage_nocheck(options);
+}
+
+
+extern lzma_ret
+lzma_lzma_props_decode(void **options, const lzma_allocator *allocator,
+               const uint8_t *props, size_t props_size)
+{
+       if (props_size != 5)
+               return LZMA_OPTIONS_ERROR;
+
+       lzma_options_lzma *opt
+                       = lzma_alloc(sizeof(lzma_options_lzma), allocator);
+       if (opt == NULL)
+               return LZMA_MEM_ERROR;
+
+       if (lzma_lzma_lclppb_decode(opt, props[0]))
+               goto error;
+
+       // All dictionary sizes are accepted, including zero. LZ decoder
+       // will automatically use a dictionary at least a few KiB even if
+       // a smaller dictionary is requested.
+       opt->dict_size = unaligned_read32le(props + 1);
+
+       opt->preset_dict = NULL;
+       opt->preset_dict_size = 0;
+
+       *options = opt;
+
+       return LZMA_OK;
+
+error:
+       lzma_free(opt, allocator);
+       return LZMA_OPTIONS_ERROR;
+}
diff --git a/lzma/lzma/lzma_decoder.h b/lzma/lzma/lzma_decoder.h
new file mode 100644 (file)
index 0000000..fa8ecb2
--- /dev/null
@@ -0,0 +1,53 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma_decoder.h
+/// \brief      LZMA decoder API
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_LZMA_DECODER_H
+#define LZMA_LZMA_DECODER_H
+
+#include "common.h"
+
+
+/// Allocates and initializes LZMA decoder
+extern lzma_ret lzma_lzma_decoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters);
+
+extern uint64_t lzma_lzma_decoder_memusage(const void *options);
+
+extern lzma_ret lzma_lzma_props_decode(
+               void **options, const lzma_allocator *allocator,
+               const uint8_t *props, size_t props_size);
+
+
+/// \brief      Decodes the LZMA Properties byte (lc/lp/pb)
+///
+/// \return     true if error occurred, false on success
+///
+extern bool lzma_lzma_lclppb_decode(
+               lzma_options_lzma *options, uint8_t byte);
+
+
+#ifdef LZMA_LZ_DECODER_H
+/// Allocate and setup function pointers only. This is used by LZMA1 and
+/// LZMA2 decoders.
+extern lzma_ret lzma_lzma_decoder_create(
+               lzma_lz_decoder *lz, const lzma_allocator *allocator,
+               const void *opt, lzma_lz_options *lz_options);
+
+/// Gets memory usage without validating lc/lp/pb. This is used by LZMA2
+/// decoder, because raw LZMA2 decoding doesn't need lc/lp/pb.
+extern uint64_t lzma_lzma_decoder_memusage_nocheck(const void *options);
+
+#endif
+
+#endif
diff --git a/lzma/lzma/lzma_encoder.c b/lzma/lzma/lzma_encoder.c
new file mode 100644 (file)
index 0000000..4c5f99c
--- /dev/null
@@ -0,0 +1,676 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma_encoder.c
+/// \brief      LZMA encoder
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "lzma2_encoder.h"
+#include "lzma_encoder_private.h"
+#include "fastpos.h"
+
+
+/////////////
+// Literal //
+/////////////
+
+static inline void
+literal_matched(lzma_range_encoder *rc, probability *subcoder,
+               uint32_t match_byte, uint32_t symbol)
+{
+       uint32_t offset = 0x100;
+       symbol += UINT32_C(1) << 8;
+
+       do {
+               match_byte <<= 1;
+               const uint32_t match_bit = match_byte & offset;
+               const uint32_t subcoder_index
+                               = offset + match_bit + (symbol >> 8);
+               const uint32_t bit = (symbol >> 7) & 1;
+               rc_bit(rc, &subcoder[subcoder_index], bit);
+
+               symbol <<= 1;
+               offset &= ~(match_byte ^ symbol);
+
+       } while (symbol < (UINT32_C(1) << 16));
+}
+
+
+static inline void
+literal(lzma_coder *coder, lzma_mf *mf, uint32_t position)
+{
+       // Locate the literal byte to be encoded and the subcoder.
+       const uint8_t cur_byte = mf->buffer[
+                       mf->read_pos - mf->read_ahead];
+       probability *subcoder = literal_subcoder(coder->literal,
+                       coder->literal_context_bits, coder->literal_pos_mask,
+                       position, mf->buffer[mf->read_pos - mf->read_ahead - 1]);
+
+       if (is_literal_state(coder->state)) {
+               // Previous LZMA-symbol was a literal. Encode a normal
+               // literal without a match byte.
+               rc_bittree(&coder->rc, subcoder, 8, cur_byte);
+       } else {
+               // Previous LZMA-symbol was a match. Use the last byte of
+               // the match as a "match byte". That is, compare the bits
+               // of the current literal and the match byte.
+               const uint8_t match_byte = mf->buffer[
+                               mf->read_pos - coder->reps[0] - 1
+                               - mf->read_ahead];
+               literal_matched(&coder->rc, subcoder, match_byte, cur_byte);
+       }
+
+       update_literal(coder->state);
+}
+
+
+//////////////////
+// Match length //
+//////////////////
+
+static void
+length_update_prices(lzma_length_encoder *lc, const uint32_t pos_state)
+{
+       const uint32_t table_size = lc->table_size;
+       lc->counters[pos_state] = table_size;
+
+       const uint32_t a0 = rc_bit_0_price(lc->choice);
+       const uint32_t a1 = rc_bit_1_price(lc->choice);
+       const uint32_t b0 = a1 + rc_bit_0_price(lc->choice2);
+       const uint32_t b1 = a1 + rc_bit_1_price(lc->choice2);
+       uint32_t *const prices = lc->prices[pos_state];
+
+       uint32_t i;
+       for (i = 0; i < table_size && i < LEN_LOW_SYMBOLS; ++i)
+               prices[i] = a0 + rc_bittree_price(lc->low[pos_state],
+                               LEN_LOW_BITS, i);
+
+       for (; i < table_size && i < LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS; ++i)
+               prices[i] = b0 + rc_bittree_price(lc->mid[pos_state],
+                               LEN_MID_BITS, i - LEN_LOW_SYMBOLS);
+
+       for (; i < table_size; ++i)
+               prices[i] = b1 + rc_bittree_price(lc->high, LEN_HIGH_BITS,
+                               i - LEN_LOW_SYMBOLS - LEN_MID_SYMBOLS);
+
+       return;
+}
+
+
+static inline void
+length(lzma_range_encoder *rc, lzma_length_encoder *lc,
+               const uint32_t pos_state, uint32_t len, const bool fast_mode)
+{
+       assert(len <= MATCH_LEN_MAX);
+       len -= MATCH_LEN_MIN;
+
+       if (len < LEN_LOW_SYMBOLS) {
+               rc_bit(rc, &lc->choice, 0);
+               rc_bittree(rc, lc->low[pos_state], LEN_LOW_BITS, len);
+       } else {
+               rc_bit(rc, &lc->choice, 1);
+               len -= LEN_LOW_SYMBOLS;
+
+               if (len < LEN_MID_SYMBOLS) {
+                       rc_bit(rc, &lc->choice2, 0);
+                       rc_bittree(rc, lc->mid[pos_state], LEN_MID_BITS, len);
+               } else {
+                       rc_bit(rc, &lc->choice2, 1);
+                       len -= LEN_MID_SYMBOLS;
+                       rc_bittree(rc, lc->high, LEN_HIGH_BITS, len);
+               }
+       }
+
+       // Only getoptimum uses the prices so don't update the table when
+       // in fast mode.
+       if (!fast_mode)
+               if (--lc->counters[pos_state] == 0)
+                       length_update_prices(lc, pos_state);
+}
+
+
+///////////
+// Match //
+///////////
+
+static inline void
+match(lzma_coder *coder, const uint32_t pos_state,
+               const uint32_t distance, const uint32_t len)
+{
+       update_match(coder->state);
+
+       length(&coder->rc, &coder->match_len_encoder, pos_state, len,
+                       coder->fast_mode);
+
+       const uint32_t dist_slot = get_dist_slot(distance);
+       const uint32_t dist_state = get_dist_state(len);
+       rc_bittree(&coder->rc, coder->dist_slot[dist_state],
+                       DIST_SLOT_BITS, dist_slot);
+
+       if (dist_slot >= DIST_MODEL_START) {
+               const uint32_t footer_bits = (dist_slot >> 1) - 1;
+               const uint32_t base = (2 | (dist_slot & 1)) << footer_bits;
+               const uint32_t dist_reduced = distance - base;
+
+               if (dist_slot < DIST_MODEL_END) {
+                       // Careful here: base - dist_slot - 1 can be -1, but
+                       // rc_bittree_reverse starts at probs[1], not probs[0].
+                       rc_bittree_reverse(&coder->rc,
+                               coder->dist_special + base - dist_slot - 1,
+                               footer_bits, dist_reduced);
+               } else {
+                       rc_direct(&coder->rc, dist_reduced >> ALIGN_BITS,
+                                       footer_bits - ALIGN_BITS);
+                       rc_bittree_reverse(
+                                       &coder->rc, coder->dist_align,
+                                       ALIGN_BITS, dist_reduced & ALIGN_MASK);
+                       ++coder->align_price_count;
+               }
+       }
+
+       coder->reps[3] = coder->reps[2];
+       coder->reps[2] = coder->reps[1];
+       coder->reps[1] = coder->reps[0];
+       coder->reps[0] = distance;
+       ++coder->match_price_count;
+}
+
+
+////////////////////
+// Repeated match //
+////////////////////
+
+static inline void
+rep_match(lzma_coder *coder, const uint32_t pos_state,
+               const uint32_t rep, const uint32_t len)
+{
+       if (rep == 0) {
+               rc_bit(&coder->rc, &coder->is_rep0[coder->state], 0);
+               rc_bit(&coder->rc,
+                               &coder->is_rep0_long[coder->state][pos_state],
+                               len != 1);
+       } else {
+               const uint32_t distance = coder->reps[rep];
+               rc_bit(&coder->rc, &coder->is_rep0[coder->state], 1);
+
+               if (rep == 1) {
+                       rc_bit(&coder->rc, &coder->is_rep1[coder->state], 0);
+               } else {
+                       rc_bit(&coder->rc, &coder->is_rep1[coder->state], 1);
+                       rc_bit(&coder->rc, &coder->is_rep2[coder->state],
+                                       rep - 2);
+
+                       if (rep == 3)
+                               coder->reps[3] = coder->reps[2];
+
+                       coder->reps[2] = coder->reps[1];
+               }
+
+               coder->reps[1] = coder->reps[0];
+               coder->reps[0] = distance;
+       }
+
+       if (len == 1) {
+               update_short_rep(coder->state);
+       } else {
+               length(&coder->rc, &coder->rep_len_encoder, pos_state, len,
+                               coder->fast_mode);
+               update_long_rep(coder->state);
+       }
+}
+
+
+//////////
+// Main //
+//////////
+
+static void
+encode_symbol(lzma_coder *coder, lzma_mf *mf,
+               uint32_t back, uint32_t len, uint32_t position)
+{
+       const uint32_t pos_state = position & coder->pos_mask;
+
+       if (back == UINT32_MAX) {
+               // Literal i.e. eight-bit byte
+               assert(len == 1);
+               rc_bit(&coder->rc,
+                               &coder->is_match[coder->state][pos_state], 0);
+               literal(coder, mf, position);
+       } else {
+               // Some type of match
+               rc_bit(&coder->rc,
+                       &coder->is_match[coder->state][pos_state], 1);
+
+               if (back < REPS) {
+                       // It's a repeated match i.e. the same distance
+                       // has been used earlier.
+                       rc_bit(&coder->rc, &coder->is_rep[coder->state], 1);
+                       rep_match(coder, pos_state, back, len);
+               } else {
+                       // Normal match
+                       rc_bit(&coder->rc, &coder->is_rep[coder->state], 0);
+                       match(coder, pos_state, back - REPS, len);
+               }
+       }
+
+       assert(mf->read_ahead >= len);
+       mf->read_ahead -= len;
+}
+
+
+static bool
+encode_init(lzma_coder *coder, lzma_mf *mf)
+{
+       assert(mf_position(mf) == 0);
+
+       if (mf->read_pos == mf->read_limit) {
+               if (mf->action == LZMA_RUN)
+                       return false; // We cannot do anything.
+
+               // We are finishing (we cannot get here when flushing).
+               assert(mf->write_pos == mf->read_pos);
+               assert(mf->action == LZMA_FINISH);
+       } else {
+               // Do the actual initialization. The first LZMA symbol must
+               // always be a literal.
+               mf_skip(mf, 1);
+               mf->read_ahead = 0;
+               rc_bit(&coder->rc, &coder->is_match[0][0], 0);
+               rc_bittree(&coder->rc, coder->literal[0], 8, mf->buffer[0]);
+       }
+
+       // Initialization is done (except if empty file).
+       coder->is_initialized = true;
+
+       return true;
+}
+
+
+static void
+encode_eopm(lzma_coder *coder, uint32_t position)
+{
+       const uint32_t pos_state = position & coder->pos_mask;
+       rc_bit(&coder->rc, &coder->is_match[coder->state][pos_state], 1);
+       rc_bit(&coder->rc, &coder->is_rep[coder->state], 0);
+       match(coder, pos_state, UINT32_MAX, MATCH_LEN_MIN);
+}
+
+
+/// Number of bytes that a single encoding loop in lzma_lzma_encode() can
+/// consume from the dictionary. This limit comes from lzma_lzma_optimum()
+/// and may need to be updated if that function is significantly modified.
+#define LOOP_INPUT_MAX (OPTS + 1)
+
+
+extern lzma_ret
+lzma_lzma_encode(lzma_coder *restrict coder, lzma_mf *restrict mf,
+               uint8_t *restrict out, size_t *restrict out_pos,
+               size_t out_size, uint32_t limit)
+{
+       // Initialize the stream if no data has been encoded yet.
+       if (!coder->is_initialized && !encode_init(coder, mf))
+               return LZMA_OK;
+
+       // Get the lowest bits of the uncompressed offset from the LZ layer.
+       uint32_t position = mf_position(mf);
+
+       while (true) {
+               // Encode pending bits, if any. Calling this before encoding
+               // the next symbol is needed only with plain LZMA, since
+               // LZMA2 always provides big enough buffer to flush
+               // everything out from the range encoder. For the same reason,
+               // rc_encode() never returns true when this function is used
+               // as part of LZMA2 encoder.
+               if (rc_encode(&coder->rc, out, out_pos, out_size)) {
+                       assert(limit == UINT32_MAX);
+                       return LZMA_OK;
+               }
+
+               // With LZMA2 we need to take care that compressed size of
+               // a chunk doesn't get too big.
+               // FIXME? Check if this could be improved.
+               if (limit != UINT32_MAX
+                               && (mf->read_pos - mf->read_ahead >= limit
+                                       || *out_pos + rc_pending(&coder->rc)
+                                               >= LZMA2_CHUNK_MAX
+                                                       - LOOP_INPUT_MAX))
+                       break;
+
+               // Check that there is some input to process.
+               if (mf->read_pos >= mf->read_limit) {
+                       if (mf->action == LZMA_RUN)
+                               return LZMA_OK;
+
+                       if (mf->read_ahead == 0)
+                               break;
+               }
+
+               // Get optimal match (repeat position and length).
+               // Value ranges for pos:
+               //   - [0, REPS): repeated match
+               //   - [REPS, UINT32_MAX):
+               //     match at (pos - REPS)
+               //   - UINT32_MAX: not a match but a literal
+               // Value ranges for len:
+               //   - [MATCH_LEN_MIN, MATCH_LEN_MAX]
+               uint32_t len;
+               uint32_t back;
+
+               if (coder->fast_mode)
+                       lzma_lzma_optimum_fast(coder, mf, &back, &len);
+               else
+                       lzma_lzma_optimum_normal(
+                                       coder, mf, &back, &len, position);
+
+               encode_symbol(coder, mf, back, len, position);
+
+               position += len;
+       }
+
+       if (!coder->is_flushed) {
+               coder->is_flushed = true;
+
+               // We don't support encoding plain LZMA streams without EOPM,
+               // and LZMA2 doesn't use EOPM at LZMA level.
+               if (limit == UINT32_MAX)
+                       encode_eopm(coder, position);
+
+               // Flush the remaining bytes from the range encoder.
+               rc_flush(&coder->rc);
+
+               // Copy the remaining bytes to the output buffer. If there
+               // isn't enough output space, we will copy out the remaining
+               // bytes on the next call to this function by using
+               // the rc_encode() call in the encoding loop above.
+               if (rc_encode(&coder->rc, out, out_pos, out_size)) {
+                       assert(limit == UINT32_MAX);
+                       return LZMA_OK;
+               }
+       }
+
+       // Make it ready for the next LZMA2 chunk.
+       coder->is_flushed = false;
+
+       return LZMA_STREAM_END;
+}
+
+
+static lzma_ret
+lzma_encode(lzma_coder *restrict coder, lzma_mf *restrict mf,
+               uint8_t *restrict out, size_t *restrict out_pos,
+               size_t out_size)
+{
+       // Plain LZMA has no support for sync-flushing.
+       if (unlikely(mf->action == LZMA_SYNC_FLUSH))
+               return LZMA_OPTIONS_ERROR;
+
+       return lzma_lzma_encode(coder, mf, out, out_pos, out_size, UINT32_MAX);
+}
+
+
+////////////////////
+// Initialization //
+////////////////////
+
+static bool
+is_options_valid(const lzma_options_lzma *options)
+{
+       // Validate some of the options. LZ encoder validates nice_len too
+       // but we need a valid value here earlier.
+       return is_lclppb_valid(options)
+                       && options->nice_len >= MATCH_LEN_MIN
+                       && options->nice_len <= MATCH_LEN_MAX
+                       && (options->mode == LZMA_MODE_FAST
+                               || options->mode == LZMA_MODE_NORMAL);
+}
+
+
+static void
+set_lz_options(lzma_lz_options *lz_options, const lzma_options_lzma *options)
+{
+       // LZ encoder initialization does the validation for these so we
+       // don't need to validate here.
+       lz_options->before_size = OPTS;
+       lz_options->dict_size = options->dict_size;
+       lz_options->after_size = LOOP_INPUT_MAX;
+       lz_options->match_len_max = MATCH_LEN_MAX;
+       lz_options->nice_len = options->nice_len;
+       lz_options->match_finder = options->mf;
+       lz_options->depth = options->depth;
+       lz_options->preset_dict = options->preset_dict;
+       lz_options->preset_dict_size = options->preset_dict_size;
+       return;
+}
+
+
+static void
+length_encoder_reset(lzma_length_encoder *lencoder,
+               const uint32_t num_pos_states, const bool fast_mode)
+{
+       bit_reset(lencoder->choice);
+       bit_reset(lencoder->choice2);
+
+       for (size_t pos_state = 0; pos_state < num_pos_states; ++pos_state) {
+               bittree_reset(lencoder->low[pos_state], LEN_LOW_BITS);
+               bittree_reset(lencoder->mid[pos_state], LEN_MID_BITS);
+       }
+
+       bittree_reset(lencoder->high, LEN_HIGH_BITS);
+
+       if (!fast_mode)
+               for (uint32_t pos_state = 0; pos_state < num_pos_states;
+                               ++pos_state)
+                       length_update_prices(lencoder, pos_state);
+
+       return;
+}
+
+
+extern lzma_ret
+lzma_lzma_encoder_reset(lzma_coder *coder, const lzma_options_lzma *options)
+{
+       if (!is_options_valid(options))
+               return LZMA_OPTIONS_ERROR;
+
+       coder->pos_mask = (1U << options->pb) - 1;
+       coder->literal_context_bits = options->lc;
+       coder->literal_pos_mask = (1U << options->lp) - 1;
+
+       // Range coder
+       rc_reset(&coder->rc);
+
+       // State
+       coder->state = STATE_LIT_LIT;
+       for (size_t i = 0; i < REPS; ++i)
+               coder->reps[i] = 0;
+
+       literal_init(coder->literal, options->lc, options->lp);
+
+       // Bit encoders
+       for (size_t i = 0; i < STATES; ++i) {
+               for (size_t j = 0; j <= coder->pos_mask; ++j) {
+                       bit_reset(coder->is_match[i][j]);
+                       bit_reset(coder->is_rep0_long[i][j]);
+               }
+
+               bit_reset(coder->is_rep[i]);
+               bit_reset(coder->is_rep0[i]);
+               bit_reset(coder->is_rep1[i]);
+               bit_reset(coder->is_rep2[i]);
+       }
+
+       for (size_t i = 0; i < FULL_DISTANCES - DIST_MODEL_END; ++i)
+               bit_reset(coder->dist_special[i]);
+
+       // Bit tree encoders
+       for (size_t i = 0; i < DIST_STATES; ++i)
+               bittree_reset(coder->dist_slot[i], DIST_SLOT_BITS);
+
+       bittree_reset(coder->dist_align, ALIGN_BITS);
+
+       // Length encoders
+       length_encoder_reset(&coder->match_len_encoder,
+                       1U << options->pb, coder->fast_mode);
+
+       length_encoder_reset(&coder->rep_len_encoder,
+                       1U << options->pb, coder->fast_mode);
+
+       // Price counts are incremented every time appropriate probabilities
+       // are changed. price counts are set to zero when the price tables
+       // are updated, which is done when the appropriate price counts have
+       // big enough value, and lzma_mf.read_ahead == 0 which happens at
+       // least every OPTS (a few thousand) possible price count increments.
+       //
+       // By resetting price counts to UINT32_MAX / 2, we make sure that the
+       // price tables will be initialized before they will be used (since
+       // the value is definitely big enough), and that it is OK to increment
+       // price counts without risk of integer overflow (since UINT32_MAX / 2
+       // is small enough). The current code doesn't increment price counts
+       // before initializing price tables, but it maybe done in future if
+       // we add support for saving the state between LZMA2 chunks.
+       coder->match_price_count = UINT32_MAX / 2;
+       coder->align_price_count = UINT32_MAX / 2;
+
+       coder->opts_end_index = 0;
+       coder->opts_current_index = 0;
+
+       return LZMA_OK;
+}
+
+
+extern lzma_ret
+lzma_lzma_encoder_create(lzma_coder **coder_ptr,
+               const lzma_allocator *allocator,
+               const lzma_options_lzma *options, lzma_lz_options *lz_options)
+{
+       // Allocate lzma_coder if it wasn't already allocated.
+       if (*coder_ptr == NULL) {
+               *coder_ptr = lzma_alloc(sizeof(lzma_coder), allocator);
+               if (*coder_ptr == NULL)
+                       return LZMA_MEM_ERROR;
+       }
+
+       lzma_coder *coder = *coder_ptr;
+
+       // Set compression mode. We haven't validates the options yet,
+       // but it's OK here, since nothing bad happens with invalid
+       // options in the code below, and they will get rejected by
+       // lzma_lzma_encoder_reset() call at the end of this function.
+       switch (options->mode) {
+               case LZMA_MODE_FAST:
+                       coder->fast_mode = true;
+                       break;
+
+               case LZMA_MODE_NORMAL: {
+                       coder->fast_mode = false;
+
+                       // Set dist_table_size.
+                       // Round the dictionary size up to next 2^n.
+                       uint32_t log_size = 0;
+                       while ((UINT32_C(1) << log_size) < options->dict_size)
+                               ++log_size;
+
+                       coder->dist_table_size = log_size * 2;
+
+                       // Length encoders' price table size
+                       coder->match_len_encoder.table_size
+                               = options->nice_len + 1 - MATCH_LEN_MIN;
+                       coder->rep_len_encoder.table_size
+                               = options->nice_len + 1 - MATCH_LEN_MIN;
+                       break;
+               }
+
+               default:
+                       return LZMA_OPTIONS_ERROR;
+       }
+
+       // We don't need to write the first byte as literal if there is
+       // a non-empty preset dictionary. encode_init() wouldn't even work
+       // if there is a non-empty preset dictionary, because encode_init()
+       // assumes that position is zero and previous byte is also zero.
+       coder->is_initialized = options->preset_dict != NULL
+                       && options->preset_dict_size > 0;
+       coder->is_flushed = false;
+
+       set_lz_options(lz_options, options);
+
+       return lzma_lzma_encoder_reset(coder, options);
+}
+
+
+static lzma_ret
+lzma_encoder_init(lzma_lz_encoder *lz, const lzma_allocator *allocator,
+               const void *options, lzma_lz_options *lz_options)
+{
+       lz->code = &lzma_encode;
+       return lzma_lzma_encoder_create(
+                       &lz->coder, allocator, options, lz_options);
+}
+
+
+extern lzma_ret
+lzma_lzma_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
+               const lzma_filter_info *filters)
+{
+       return lzma_lz_encoder_init(
+                       next, allocator, filters, &lzma_encoder_init);
+}
+
+
+extern uint64_t
+lzma_lzma_encoder_memusage(const void *options)
+{
+       if (!is_options_valid(options))
+               return UINT64_MAX;
+
+       lzma_lz_options lz_options;
+       set_lz_options(&lz_options, options);
+
+       const uint64_t lz_memusage = lzma_lz_encoder_memusage(&lz_options);
+       if (lz_memusage == UINT64_MAX)
+               return UINT64_MAX;
+
+       return (uint64_t)(sizeof(lzma_coder)) + lz_memusage;
+}
+
+
+extern bool
+lzma_lzma_lclppb_encode(const lzma_options_lzma *options, uint8_t *byte)
+{
+       if (!is_lclppb_valid(options))
+               return true;
+
+       *byte = (options->pb * 5 + options->lp) * 9 + options->lc;
+       assert(*byte <= (4 * 5 + 4) * 9 + 8);
+
+       return false;
+}
+
+
+#ifdef HAVE_ENCODER_LZMA1
+extern lzma_ret
+lzma_lzma_props_encode(const void *options, uint8_t *out)
+{
+       const lzma_options_lzma *const opt = options;
+
+       if (lzma_lzma_lclppb_encode(opt, out))
+               return LZMA_PROG_ERROR;
+
+       unaligned_write32le(out + 1, opt->dict_size);
+
+       return LZMA_OK;
+}
+#endif
+
+
+extern LZMA_API(lzma_bool)
+lzma_mode_is_supported(lzma_mode mode)
+{
+       return mode == LZMA_MODE_FAST || mode == LZMA_MODE_NORMAL;
+}
diff --git a/lzma/lzma/lzma_encoder.h b/lzma/lzma/lzma_encoder.h
new file mode 100644 (file)
index 0000000..cc9cc2f
--- /dev/null
@@ -0,0 +1,55 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma_encoder.h
+/// \brief      LZMA encoder API
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_LZMA_ENCODER_H
+#define LZMA_LZMA_ENCODER_H
+
+#include "common.h"
+
+
+extern lzma_ret lzma_lzma_encoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters);
+
+
+extern uint64_t lzma_lzma_encoder_memusage(const void *options);
+
+extern lzma_ret lzma_lzma_props_encode(const void *options, uint8_t *out);
+
+
+/// Encodes lc/lp/pb into one byte. Returns false on success and true on error.
+extern bool lzma_lzma_lclppb_encode(
+               const lzma_options_lzma *options, uint8_t *byte);
+
+
+#ifdef LZMA_LZ_ENCODER_H
+
+/// Initializes raw LZMA encoder; this is used by LZMA2.
+extern lzma_ret lzma_lzma_encoder_create(
+               lzma_coder **coder_ptr, const lzma_allocator *allocator,
+               const lzma_options_lzma *options, lzma_lz_options *lz_options);
+
+
+/// Resets an already initialized LZMA encoder; this is used by LZMA2.
+extern lzma_ret lzma_lzma_encoder_reset(
+               lzma_coder *coder, const lzma_options_lzma *options);
+
+
+extern lzma_ret lzma_lzma_encode(lzma_coder *restrict coder,
+               lzma_mf *restrict mf, uint8_t *restrict out,
+               size_t *restrict out_pos, size_t out_size,
+               uint32_t read_limit);
+
+#endif
+
+#endif
diff --git a/lzma/lzma/lzma_encoder_optimum_fast.c b/lzma/lzma/lzma_encoder_optimum_fast.c
new file mode 100644 (file)
index 0000000..9b30347
--- /dev/null
@@ -0,0 +1,169 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma_encoder_optimum_fast.c
+//
+//  Author:     Igor Pavlov
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "lzma_encoder_private.h"
+#include "memcmplen.h"
+
+
+#define change_pair(small_dist, big_dist) \
+       (((big_dist) >> 7) > (small_dist))
+
+
+extern void
+lzma_lzma_optimum_fast(lzma_coder *restrict coder, lzma_mf *restrict mf,
+               uint32_t *restrict back_res, uint32_t *restrict len_res)
+{
+       const uint32_t nice_len = mf->nice_len;
+
+       uint32_t len_main;
+       uint32_t matches_count;
+       if (mf->read_ahead == 0) {
+               len_main = mf_find(mf, &matches_count, coder->matches);
+       } else {
+               assert(mf->read_ahead == 1);
+               len_main = coder->longest_match_length;
+               matches_count = coder->matches_count;
+       }
+
+       const uint8_t *buf = mf_ptr(mf) - 1;
+       const uint32_t buf_avail = my_min(mf_avail(mf) + 1, MATCH_LEN_MAX);
+
+       if (buf_avail < 2) {
+               // There's not enough input left to encode a match.
+               *back_res = UINT32_MAX;
+               *len_res = 1;
+               return;
+       }
+
+       // Look for repeated matches; scan the previous four match distances
+       uint32_t rep_len = 0;
+       uint32_t rep_index = 0;
+
+       for (uint32_t i = 0; i < REPS; ++i) {
+               // Pointer to the beginning of the match candidate
+               const uint8_t *const buf_back = buf - coder->reps[i] - 1;
+
+               // If the first two bytes (2 == MATCH_LEN_MIN) do not match,
+               // this rep is not useful.
+               if (not_equal_16(buf, buf_back))
+                       continue;
+
+               // The first two bytes matched.
+               // Calculate the length of the match.
+               const uint32_t len = lzma_memcmplen(
+                               buf, buf_back, 2, buf_avail);
+
+               // If we have found a repeated match that is at least
+               // nice_len long, return it immediately.
+               if (len >= nice_len) {
+                       *back_res = i;
+                       *len_res = len;
+                       mf_skip(mf, len - 1);
+                       return;
+               }
+
+               if (len > rep_len) {
+                       rep_index = i;
+                       rep_len = len;
+               }
+       }
+
+       // We didn't find a long enough repeated match. Encode it as a normal
+       // match if the match length is at least nice_len.
+       if (len_main >= nice_len) {
+               *back_res = coder->matches[matches_count - 1].dist + REPS;
+               *len_res = len_main;
+               mf_skip(mf, len_main - 1);
+               return;
+       }
+
+       uint32_t back_main = 0;
+       if (len_main >= 2) {
+               back_main = coder->matches[matches_count - 1].dist;
+
+               while (matches_count > 1 && len_main ==
+                               coder->matches[matches_count - 2].len + 1) {
+                       if (!change_pair(coder->matches[
+                                               matches_count - 2].dist,
+                                       back_main))
+                               break;
+
+                       --matches_count;
+                       len_main = coder->matches[matches_count - 1].len;
+                       back_main = coder->matches[matches_count - 1].dist;
+               }
+
+               if (len_main == 2 && back_main >= 0x80)
+                       len_main = 1;
+       }
+
+       if (rep_len >= 2) {
+               if (rep_len + 1 >= len_main
+                               || (rep_len + 2 >= len_main
+                                       && back_main > (UINT32_C(1) << 9))
+                               || (rep_len + 3 >= len_main
+                                       && back_main > (UINT32_C(1) << 15))) {
+                       *back_res = rep_index;
+                       *len_res = rep_len;
+                       mf_skip(mf, rep_len - 1);
+                       return;
+               }
+       }
+
+       if (len_main < 2 || buf_avail <= 2) {
+               *back_res = UINT32_MAX;
+               *len_res = 1;
+               return;
+       }
+
+       // Get the matches for the next byte. If we find a better match,
+       // the current byte is encoded as a literal.
+       coder->longest_match_length = mf_find(mf,
+                       &coder->matches_count, coder->matches);
+
+       if (coder->longest_match_length >= 2) {
+               const uint32_t new_dist = coder->matches[
+                               coder->matches_count - 1].dist;
+
+               if ((coder->longest_match_length >= len_main
+                                       && new_dist < back_main)
+                               || (coder->longest_match_length == len_main + 1
+                                       && !change_pair(back_main, new_dist))
+                               || (coder->longest_match_length > len_main + 1)
+                               || (coder->longest_match_length + 1 >= len_main
+                                       && len_main >= 3
+                                       && change_pair(new_dist, back_main))) {
+                       *back_res = UINT32_MAX;
+                       *len_res = 1;
+                       return;
+               }
+       }
+
+       // In contrast to LZMA SDK, dictionary could not have been moved
+       // between mf_find() calls, thus it is safe to just increment
+       // the old buf pointer instead of recalculating it with mf_ptr().
+       ++buf;
+
+       const uint32_t limit = my_max(2, len_main - 1);
+
+       for (uint32_t i = 0; i < REPS; ++i) {
+               if (memcmp(buf, buf - coder->reps[i] - 1, limit) == 0) {
+                       *back_res = UINT32_MAX;
+                       *len_res = 1;
+                       return;
+               }
+       }
+
+       *back_res = back_main + REPS;
+       *len_res = len_main;
+       mf_skip(mf, len_main - 2);
+       return;
+}
diff --git a/lzma/lzma/lzma_encoder_optimum_normal.c b/lzma/lzma/lzma_encoder_optimum_normal.c
new file mode 100644 (file)
index 0000000..a360579
--- /dev/null
@@ -0,0 +1,854 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma_encoder_optimum_normal.c
+//
+//  Author:     Igor Pavlov
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "lzma_encoder_private.h"
+#include "fastpos.h"
+#include "memcmplen.h"
+
+
+////////////
+// Prices //
+////////////
+
+static uint32_t
+get_literal_price(const lzma_coder *const coder, const uint32_t pos,
+               const uint32_t prev_byte, const bool match_mode,
+               uint32_t match_byte, uint32_t symbol)
+{
+       const probability *const subcoder = literal_subcoder(coder->literal,
+                       coder->literal_context_bits, coder->literal_pos_mask,
+                       pos, prev_byte);
+
+       uint32_t price = 0;
+
+       if (!match_mode) {
+               price = rc_bittree_price(subcoder, 8, symbol);
+       } else {
+               uint32_t offset = 0x100;
+               symbol += UINT32_C(1) << 8;
+
+               do {
+                       match_byte <<= 1;
+
+                       const uint32_t match_bit = match_byte & offset;
+                       const uint32_t subcoder_index
+                                       = offset + match_bit + (symbol >> 8);
+                       const uint32_t bit = (symbol >> 7) & 1;
+                       price += rc_bit_price(subcoder[subcoder_index], bit);
+
+                       symbol <<= 1;
+                       offset &= ~(match_byte ^ symbol);
+
+               } while (symbol < (UINT32_C(1) << 16));
+       }
+
+       return price;
+}
+
+
+static inline uint32_t
+get_len_price(const lzma_length_encoder *const lencoder,
+               const uint32_t len, const uint32_t pos_state)
+{
+       // NOTE: Unlike the other price tables, length prices are updated
+       // in lzma_encoder.c
+       return lencoder->prices[pos_state][len - MATCH_LEN_MIN];
+}
+
+
+static inline uint32_t
+get_short_rep_price(const lzma_coder *const coder,
+               const lzma_lzma_state state, const uint32_t pos_state)
+{
+       return rc_bit_0_price(coder->is_rep0[state])
+               + rc_bit_0_price(coder->is_rep0_long[state][pos_state]);
+}
+
+
+static inline uint32_t
+get_pure_rep_price(const lzma_coder *const coder, const uint32_t rep_index,
+               const lzma_lzma_state state, uint32_t pos_state)
+{
+       uint32_t price;
+
+       if (rep_index == 0) {
+               price = rc_bit_0_price(coder->is_rep0[state]);
+               price += rc_bit_1_price(coder->is_rep0_long[state][pos_state]);
+       } else {
+               price = rc_bit_1_price(coder->is_rep0[state]);
+
+               if (rep_index == 1) {
+                       price += rc_bit_0_price(coder->is_rep1[state]);
+               } else {
+                       price += rc_bit_1_price(coder->is_rep1[state]);
+                       price += rc_bit_price(coder->is_rep2[state],
+                                       rep_index - 2);
+               }
+       }
+
+       return price;
+}
+
+
+static inline uint32_t
+get_rep_price(const lzma_coder *const coder, const uint32_t rep_index,
+               const uint32_t len, const lzma_lzma_state state,
+               const uint32_t pos_state)
+{
+       return get_len_price(&coder->rep_len_encoder, len, pos_state)
+               + get_pure_rep_price(coder, rep_index, state, pos_state);
+}
+
+
+static inline uint32_t
+get_dist_len_price(const lzma_coder *const coder, const uint32_t dist,
+               const uint32_t len, const uint32_t pos_state)
+{
+       const uint32_t dist_state = get_dist_state(len);
+       uint32_t price;
+
+       if (dist < FULL_DISTANCES) {
+               price = coder->dist_prices[dist_state][dist];
+       } else {
+               const uint32_t dist_slot = get_dist_slot_2(dist);
+               price = coder->dist_slot_prices[dist_state][dist_slot]
+                               + coder->align_prices[dist & ALIGN_MASK];
+       }
+
+       price += get_len_price(&coder->match_len_encoder, len, pos_state);
+
+       return price;
+}
+
+
+static void
+fill_dist_prices(lzma_coder *coder)
+{
+       for (uint32_t dist_state = 0; dist_state < DIST_STATES; ++dist_state) {
+
+               uint32_t *const dist_slot_prices
+                               = coder->dist_slot_prices[dist_state];
+
+               // Price to encode the dist_slot.
+               for (uint32_t dist_slot = 0;
+                               dist_slot < coder->dist_table_size; ++dist_slot)
+                       dist_slot_prices[dist_slot] = rc_bittree_price(
+                                       coder->dist_slot[dist_state],
+                                       DIST_SLOT_BITS, dist_slot);
+
+               // For matches with distance >= FULL_DISTANCES, add the price
+               // of the direct bits part of the match distance. (Align bits
+               // are handled by fill_align_prices()).
+               for (uint32_t dist_slot = DIST_MODEL_END;
+                               dist_slot < coder->dist_table_size;
+                               ++dist_slot)
+                       dist_slot_prices[dist_slot] += rc_direct_price(
+                                       ((dist_slot >> 1) - 1) - ALIGN_BITS);
+
+               // Distances in the range [0, 3] are fully encoded with
+               // dist_slot, so they are used for coder->dist_prices
+               // as is.
+               for (uint32_t i = 0; i < DIST_MODEL_START; ++i)
+                       coder->dist_prices[dist_state][i]
+                                       = dist_slot_prices[i];
+       }
+
+       // Distances in the range [4, 127] depend on dist_slot and
+       // dist_special. We do this in a loop separate from the above
+       // loop to avoid redundant calls to get_dist_slot().
+       for (uint32_t i = DIST_MODEL_START; i < FULL_DISTANCES; ++i) {
+               const uint32_t dist_slot = get_dist_slot(i);
+               const uint32_t footer_bits = ((dist_slot >> 1) - 1);
+               const uint32_t base = (2 | (dist_slot & 1)) << footer_bits;
+               const uint32_t price = rc_bittree_reverse_price(
+                               coder->dist_special + base - dist_slot - 1,
+                               footer_bits, i - base);
+
+               for (uint32_t dist_state = 0; dist_state < DIST_STATES;
+                               ++dist_state)
+                       coder->dist_prices[dist_state][i]
+                                       = price + coder->dist_slot_prices[
+                                               dist_state][dist_slot];
+       }
+
+       coder->match_price_count = 0;
+       return;
+}
+
+
+static void
+fill_align_prices(lzma_coder *coder)
+{
+       for (uint32_t i = 0; i < ALIGN_SIZE; ++i)
+               coder->align_prices[i] = rc_bittree_reverse_price(
+                               coder->dist_align, ALIGN_BITS, i);
+
+       coder->align_price_count = 0;
+       return;
+}
+
+
+/////////////
+// Optimal //
+/////////////
+
+static inline void
+make_literal(lzma_optimal *optimal)
+{
+       optimal->back_prev = UINT32_MAX;
+       optimal->prev_1_is_literal = false;
+}
+
+
+static inline void
+make_short_rep(lzma_optimal *optimal)
+{
+       optimal->back_prev = 0;
+       optimal->prev_1_is_literal = false;
+}
+
+
+#define is_short_rep(optimal) \
+       ((optimal).back_prev == 0)
+
+
+static void
+backward(lzma_coder *restrict coder, uint32_t *restrict len_res,
+               uint32_t *restrict back_res, uint32_t cur)
+{
+       coder->opts_end_index = cur;
+
+       uint32_t pos_mem = coder->opts[cur].pos_prev;
+       uint32_t back_mem = coder->opts[cur].back_prev;
+
+       do {
+               if (coder->opts[cur].prev_1_is_literal) {
+                       make_literal(&coder->opts[pos_mem]);
+                       coder->opts[pos_mem].pos_prev = pos_mem - 1;
+
+                       if (coder->opts[cur].prev_2) {
+                               coder->opts[pos_mem - 1].prev_1_is_literal
+                                               = false;
+                               coder->opts[pos_mem - 1].pos_prev
+                                               = coder->opts[cur].pos_prev_2;
+                               coder->opts[pos_mem - 1].back_prev
+                                               = coder->opts[cur].back_prev_2;
+                       }
+               }
+
+               const uint32_t pos_prev = pos_mem;
+               const uint32_t back_cur = back_mem;
+
+               back_mem = coder->opts[pos_prev].back_prev;
+               pos_mem = coder->opts[pos_prev].pos_prev;
+
+               coder->opts[pos_prev].back_prev = back_cur;
+               coder->opts[pos_prev].pos_prev = cur;
+               cur = pos_prev;
+
+       } while (cur != 0);
+
+       coder->opts_current_index = coder->opts[0].pos_prev;
+       *len_res = coder->opts[0].pos_prev;
+       *back_res = coder->opts[0].back_prev;
+
+       return;
+}
+
+
+//////////
+// Main //
+//////////
+
+static inline uint32_t
+helper1(lzma_coder *restrict coder, lzma_mf *restrict mf,
+               uint32_t *restrict back_res, uint32_t *restrict len_res,
+               uint32_t position)
+{
+       const uint32_t nice_len = mf->nice_len;
+
+       uint32_t len_main;
+       uint32_t matches_count;
+
+       if (mf->read_ahead == 0) {
+               len_main = mf_find(mf, &matches_count, coder->matches);
+       } else {
+               assert(mf->read_ahead == 1);
+               len_main = coder->longest_match_length;
+               matches_count = coder->matches_count;
+       }
+
+       const uint32_t buf_avail = my_min(mf_avail(mf) + 1, MATCH_LEN_MAX);
+       if (buf_avail < 2) {
+               *back_res = UINT32_MAX;
+               *len_res = 1;
+               return UINT32_MAX;
+       }
+
+       const uint8_t *const buf = mf_ptr(mf) - 1;
+
+       uint32_t rep_lens[REPS];
+       uint32_t rep_max_index = 0;
+
+       for (uint32_t i = 0; i < REPS; ++i) {
+               const uint8_t *const buf_back = buf - coder->reps[i] - 1;
+
+               if (not_equal_16(buf, buf_back)) {
+                       rep_lens[i] = 0;
+                       continue;
+               }
+
+               rep_lens[i] = lzma_memcmplen(buf, buf_back, 2, buf_avail);
+
+               if (rep_lens[i] > rep_lens[rep_max_index])
+                       rep_max_index = i;
+       }
+
+       if (rep_lens[rep_max_index] >= nice_len) {
+               *back_res = rep_max_index;
+               *len_res = rep_lens[rep_max_index];
+               mf_skip(mf, *len_res - 1);
+               return UINT32_MAX;
+       }
+
+
+       if (len_main >= nice_len) {
+               *back_res = coder->matches[matches_count - 1].dist + REPS;
+               *len_res = len_main;
+               mf_skip(mf, len_main - 1);
+               return UINT32_MAX;
+       }
+
+       const uint8_t current_byte = *buf;
+       const uint8_t match_byte = *(buf - coder->reps[0] - 1);
+
+       if (len_main < 2 && current_byte != match_byte
+                       && rep_lens[rep_max_index] < 2) {
+               *back_res = UINT32_MAX;
+               *len_res = 1;
+               return UINT32_MAX;
+       }
+
+       coder->opts[0].state = coder->state;
+
+       const uint32_t pos_state = position & coder->pos_mask;
+
+       coder->opts[1].price = rc_bit_0_price(
+                               coder->is_match[coder->state][pos_state])
+                       + get_literal_price(coder, position, buf[-1],
+                               !is_literal_state(coder->state),
+                               match_byte, current_byte);
+
+       make_literal(&coder->opts[1]);
+
+       const uint32_t match_price = rc_bit_1_price(
+                       coder->is_match[coder->state][pos_state]);
+       const uint32_t rep_match_price = match_price
+                       + rc_bit_1_price(coder->is_rep[coder->state]);
+
+       if (match_byte == current_byte) {
+               const uint32_t short_rep_price = rep_match_price
+                               + get_short_rep_price(
+                                       coder, coder->state, pos_state);
+
+               if (short_rep_price < coder->opts[1].price) {
+                       coder->opts[1].price = short_rep_price;
+                       make_short_rep(&coder->opts[1]);
+               }
+       }
+
+       const uint32_t len_end = my_max(len_main, rep_lens[rep_max_index]);
+
+       if (len_end < 2) {
+               *back_res = coder->opts[1].back_prev;
+               *len_res = 1;
+               return UINT32_MAX;
+       }
+
+       coder->opts[1].pos_prev = 0;
+
+       for (uint32_t i = 0; i < REPS; ++i)
+               coder->opts[0].backs[i] = coder->reps[i];
+
+       uint32_t len = len_end;
+       do {
+               coder->opts[len].price = RC_INFINITY_PRICE;
+       } while (--len >= 2);
+
+
+       for (uint32_t i = 0; i < REPS; ++i) {
+               uint32_t rep_len = rep_lens[i];
+               if (rep_len < 2)
+                       continue;
+
+               const uint32_t price = rep_match_price + get_pure_rep_price(
+                               coder, i, coder->state, pos_state);
+
+               do {
+                       const uint32_t cur_and_len_price = price
+                                       + get_len_price(
+                                               &coder->rep_len_encoder,
+                                               rep_len, pos_state);
+
+                       if (cur_and_len_price < coder->opts[rep_len].price) {
+                               coder->opts[rep_len].price = cur_and_len_price;
+                               coder->opts[rep_len].pos_prev = 0;
+                               coder->opts[rep_len].back_prev = i;
+                               coder->opts[rep_len].prev_1_is_literal = false;
+                       }
+               } while (--rep_len >= 2);
+       }
+
+
+       const uint32_t normal_match_price = match_price
+                       + rc_bit_0_price(coder->is_rep[coder->state]);
+
+       len = rep_lens[0] >= 2 ? rep_lens[0] + 1 : 2;
+       if (len <= len_main) {
+               uint32_t i = 0;
+               while (len > coder->matches[i].len)
+                       ++i;
+
+               for(; ; ++len) {
+                       const uint32_t dist = coder->matches[i].dist;
+                       const uint32_t cur_and_len_price = normal_match_price
+                                       + get_dist_len_price(coder,
+                                               dist, len, pos_state);
+
+                       if (cur_and_len_price < coder->opts[len].price) {
+                               coder->opts[len].price = cur_and_len_price;
+                               coder->opts[len].pos_prev = 0;
+                               coder->opts[len].back_prev = dist + REPS;
+                               coder->opts[len].prev_1_is_literal = false;
+                       }
+
+                       if (len == coder->matches[i].len)
+                               if (++i == matches_count)
+                                       break;
+               }
+       }
+
+       return len_end;
+}
+
+
+static inline uint32_t
+helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
+               uint32_t len_end, uint32_t position, const uint32_t cur,
+               const uint32_t nice_len, const uint32_t buf_avail_full)
+{
+       uint32_t matches_count = coder->matches_count;
+       uint32_t new_len = coder->longest_match_length;
+       uint32_t pos_prev = coder->opts[cur].pos_prev;
+       lzma_lzma_state state;
+
+       if (coder->opts[cur].prev_1_is_literal) {
+               --pos_prev;
+
+               if (coder->opts[cur].prev_2) {
+                       state = coder->opts[coder->opts[cur].pos_prev_2].state;
+
+                       if (coder->opts[cur].back_prev_2 < REPS)
+                               update_long_rep(state);
+                       else
+                               update_match(state);
+
+               } else {
+                       state = coder->opts[pos_prev].state;
+               }
+
+               update_literal(state);
+
+       } else {
+               state = coder->opts[pos_prev].state;
+       }
+
+       if (pos_prev == cur - 1) {
+               if (is_short_rep(coder->opts[cur]))
+                       update_short_rep(state);
+               else
+                       update_literal(state);
+       } else {
+               uint32_t pos;
+               if (coder->opts[cur].prev_1_is_literal
+                               && coder->opts[cur].prev_2) {
+                       pos_prev = coder->opts[cur].pos_prev_2;
+                       pos = coder->opts[cur].back_prev_2;
+                       update_long_rep(state);
+               } else {
+                       pos = coder->opts[cur].back_prev;
+                       if (pos < REPS)
+                               update_long_rep(state);
+                       else
+                               update_match(state);
+               }
+
+               if (pos < REPS) {
+                       reps[0] = coder->opts[pos_prev].backs[pos];
+
+                       uint32_t i;
+                       for (i = 1; i <= pos; ++i)
+                               reps[i] = coder->opts[pos_prev].backs[i - 1];
+
+                       for (; i < REPS; ++i)
+                               reps[i] = coder->opts[pos_prev].backs[i];
+
+               } else {
+                       reps[0] = pos - REPS;
+
+                       for (uint32_t i = 1; i < REPS; ++i)
+                               reps[i] = coder->opts[pos_prev].backs[i - 1];
+               }
+       }
+
+       coder->opts[cur].state = state;
+
+       for (uint32_t i = 0; i < REPS; ++i)
+               coder->opts[cur].backs[i] = reps[i];
+
+       const uint32_t cur_price = coder->opts[cur].price;
+
+       const uint8_t current_byte = *buf;
+       const uint8_t match_byte = *(buf - reps[0] - 1);
+
+       const uint32_t pos_state = position & coder->pos_mask;
+
+       const uint32_t cur_and_1_price = cur_price
+                       + rc_bit_0_price(coder->is_match[state][pos_state])
+                       + get_literal_price(coder, position, buf[-1],
+                       !is_literal_state(state), match_byte, current_byte);
+
+       bool next_is_literal = false;
+
+       if (cur_and_1_price < coder->opts[cur + 1].price) {
+               coder->opts[cur + 1].price = cur_and_1_price;
+               coder->opts[cur + 1].pos_prev = cur;
+               make_literal(&coder->opts[cur + 1]);
+               next_is_literal = true;
+       }
+
+       const uint32_t match_price = cur_price
+                       + rc_bit_1_price(coder->is_match[state][pos_state]);
+       const uint32_t rep_match_price = match_price
+                       + rc_bit_1_price(coder->is_rep[state]);
+
+       if (match_byte == current_byte
+                       && !(coder->opts[cur + 1].pos_prev < cur
+                               && coder->opts[cur + 1].back_prev == 0)) {
+
+               const uint32_t short_rep_price = rep_match_price
+                               + get_short_rep_price(coder, state, pos_state);
+
+               if (short_rep_price <= coder->opts[cur + 1].price) {
+                       coder->opts[cur + 1].price = short_rep_price;
+                       coder->opts[cur + 1].pos_prev = cur;
+                       make_short_rep(&coder->opts[cur + 1]);
+                       next_is_literal = true;
+               }
+       }
+
+       if (buf_avail_full < 2)
+               return len_end;
+
+       const uint32_t buf_avail = my_min(buf_avail_full, nice_len);
+
+       if (!next_is_literal && match_byte != current_byte) { // speed optimization
+               // try literal + rep0
+               const uint8_t *const buf_back = buf - reps[0] - 1;
+               const uint32_t limit = my_min(buf_avail_full, nice_len + 1);
+
+               const uint32_t len_test = lzma_memcmplen(buf, buf_back, 1, limit) - 1;
+
+               if (len_test >= 2) {
+                       lzma_lzma_state state_2 = state;
+                       update_literal(state_2);
+
+                       const uint32_t pos_state_next = (position + 1) & coder->pos_mask;
+                       const uint32_t next_rep_match_price = cur_and_1_price
+                                       + rc_bit_1_price(coder->is_match[state_2][pos_state_next])
+                                       + rc_bit_1_price(coder->is_rep[state_2]);
+
+                       //for (; len_test >= 2; --len_test) {
+                       const uint32_t offset = cur + 1 + len_test;
+
+                       while (len_end < offset)
+                               coder->opts[++len_end].price = RC_INFINITY_PRICE;
+
+                       const uint32_t cur_and_len_price = next_rep_match_price
+                                       + get_rep_price(coder, 0, len_test,
+                                               state_2, pos_state_next);
+
+                       if (cur_and_len_price < coder->opts[offset].price) {
+                               coder->opts[offset].price = cur_and_len_price;
+                               coder->opts[offset].pos_prev = cur + 1;
+                               coder->opts[offset].back_prev = 0;
+                               coder->opts[offset].prev_1_is_literal = true;
+                               coder->opts[offset].prev_2 = false;
+                       }
+                       //}
+               }
+       }
+
+
+       uint32_t start_len = 2; // speed optimization
+
+       for (uint32_t rep_index = 0; rep_index < REPS; ++rep_index) {
+               const uint8_t *const buf_back = buf - reps[rep_index] - 1;
+               if (not_equal_16(buf, buf_back))
+                       continue;
+
+               uint32_t len_test = lzma_memcmplen(buf, buf_back, 2, buf_avail);
+
+               while (len_end < cur + len_test)
+                       coder->opts[++len_end].price = RC_INFINITY_PRICE;
+
+               const uint32_t len_test_temp = len_test;
+               const uint32_t price = rep_match_price + get_pure_rep_price(
+                               coder, rep_index, state, pos_state);
+
+               do {
+                       const uint32_t cur_and_len_price = price
+                                       + get_len_price(&coder->rep_len_encoder,
+                                                       len_test, pos_state);
+
+                       if (cur_and_len_price < coder->opts[cur + len_test].price) {
+                               coder->opts[cur + len_test].price = cur_and_len_price;
+                               coder->opts[cur + len_test].pos_prev = cur;
+                               coder->opts[cur + len_test].back_prev = rep_index;
+                               coder->opts[cur + len_test].prev_1_is_literal = false;
+                       }
+               } while (--len_test >= 2);
+
+               len_test = len_test_temp;
+
+               if (rep_index == 0)
+                       start_len = len_test + 1;
+
+
+               uint32_t len_test_2 = len_test + 1;
+               const uint32_t limit = my_min(buf_avail_full,
+                               len_test_2 + nice_len);
+               for (; len_test_2 < limit
+                               && buf[len_test_2] == buf_back[len_test_2];
+                               ++len_test_2) ;
+
+               len_test_2 -= len_test + 1;
+
+               if (len_test_2 >= 2) {
+                       lzma_lzma_state state_2 = state;
+                       update_long_rep(state_2);
+
+                       uint32_t pos_state_next = (position + len_test) & coder->pos_mask;
+
+                       const uint32_t cur_and_len_literal_price = price
+                                       + get_len_price(&coder->rep_len_encoder,
+                                               len_test, pos_state)
+                                       + rc_bit_0_price(coder->is_match[state_2][pos_state_next])
+                                       + get_literal_price(coder, position + len_test,
+                                               buf[len_test - 1], true,
+                                               buf_back[len_test], buf[len_test]);
+
+                       update_literal(state_2);
+
+                       pos_state_next = (position + len_test + 1) & coder->pos_mask;
+
+                       const uint32_t next_rep_match_price = cur_and_len_literal_price
+                                       + rc_bit_1_price(coder->is_match[state_2][pos_state_next])
+                                       + rc_bit_1_price(coder->is_rep[state_2]);
+
+                       //for(; len_test_2 >= 2; len_test_2--) {
+                       const uint32_t offset = cur + len_test + 1 + len_test_2;
+
+                       while (len_end < offset)
+                               coder->opts[++len_end].price = RC_INFINITY_PRICE;
+
+                       const uint32_t cur_and_len_price = next_rep_match_price
+                                       + get_rep_price(coder, 0, len_test_2,
+                                               state_2, pos_state_next);
+
+                       if (cur_and_len_price < coder->opts[offset].price) {
+                               coder->opts[offset].price = cur_and_len_price;
+                               coder->opts[offset].pos_prev = cur + len_test + 1;
+                               coder->opts[offset].back_prev = 0;
+                               coder->opts[offset].prev_1_is_literal = true;
+                               coder->opts[offset].prev_2 = true;
+                               coder->opts[offset].pos_prev_2 = cur;
+                               coder->opts[offset].back_prev_2 = rep_index;
+                       }
+                       //}
+               }
+       }
+
+
+       //for (uint32_t len_test = 2; len_test <= new_len; ++len_test)
+       if (new_len > buf_avail) {
+               new_len = buf_avail;
+
+               matches_count = 0;
+               while (new_len > coder->matches[matches_count].len)
+                       ++matches_count;
+
+               coder->matches[matches_count++].len = new_len;
+       }
+
+
+       if (new_len >= start_len) {
+               const uint32_t normal_match_price = match_price
+                               + rc_bit_0_price(coder->is_rep[state]);
+
+               while (len_end < cur + new_len)
+                       coder->opts[++len_end].price = RC_INFINITY_PRICE;
+
+               uint32_t i = 0;
+               while (start_len > coder->matches[i].len)
+                       ++i;
+
+               for (uint32_t len_test = start_len; ; ++len_test) {
+                       const uint32_t cur_back = coder->matches[i].dist;
+                       uint32_t cur_and_len_price = normal_match_price
+                                       + get_dist_len_price(coder,
+                                               cur_back, len_test, pos_state);
+
+                       if (cur_and_len_price < coder->opts[cur + len_test].price) {
+                               coder->opts[cur + len_test].price = cur_and_len_price;
+                               coder->opts[cur + len_test].pos_prev = cur;
+                               coder->opts[cur + len_test].back_prev
+                                               = cur_back + REPS;
+                               coder->opts[cur + len_test].prev_1_is_literal = false;
+                       }
+
+                       if (len_test == coder->matches[i].len) {
+                               // Try Match + Literal + Rep0
+                               const uint8_t *const buf_back = buf - cur_back - 1;
+                               uint32_t len_test_2 = len_test + 1;
+                               const uint32_t limit = my_min(buf_avail_full,
+                                               len_test_2 + nice_len);
+
+                               for (; len_test_2 < limit &&
+                                               buf[len_test_2] == buf_back[len_test_2];
+                                               ++len_test_2) ;
+
+                               len_test_2 -= len_test + 1;
+
+                               if (len_test_2 >= 2) {
+                                       lzma_lzma_state state_2 = state;
+                                       update_match(state_2);
+                                       uint32_t pos_state_next
+                                                       = (position + len_test) & coder->pos_mask;
+
+                                       const uint32_t cur_and_len_literal_price = cur_and_len_price
+                                                       + rc_bit_0_price(
+                                                               coder->is_match[state_2][pos_state_next])
+                                                       + get_literal_price(coder,
+                                                               position + len_test,
+                                                               buf[len_test - 1],
+                                                               true,
+                                                               buf_back[len_test],
+                                                               buf[len_test]);
+
+                                       update_literal(state_2);
+                                       pos_state_next = (pos_state_next + 1) & coder->pos_mask;
+
+                                       const uint32_t next_rep_match_price
+                                                       = cur_and_len_literal_price
+                                                       + rc_bit_1_price(
+                                                               coder->is_match[state_2][pos_state_next])
+                                                       + rc_bit_1_price(coder->is_rep[state_2]);
+
+                                       // for(; len_test_2 >= 2; --len_test_2) {
+                                       const uint32_t offset = cur + len_test + 1 + len_test_2;
+
+                                       while (len_end < offset)
+                                               coder->opts[++len_end].price = RC_INFINITY_PRICE;
+
+                                       cur_and_len_price = next_rep_match_price
+                                                       + get_rep_price(coder, 0, len_test_2,
+                                                               state_2, pos_state_next);
+
+                                       if (cur_and_len_price < coder->opts[offset].price) {
+                                               coder->opts[offset].price = cur_and_len_price;
+                                               coder->opts[offset].pos_prev = cur + len_test + 1;
+                                               coder->opts[offset].back_prev = 0;
+                                               coder->opts[offset].prev_1_is_literal = true;
+                                               coder->opts[offset].prev_2 = true;
+                                               coder->opts[offset].pos_prev_2 = cur;
+                                               coder->opts[offset].back_prev_2
+                                                               = cur_back + REPS;
+                                       }
+                                       //}
+                               }
+
+                               if (++i == matches_count)
+                                       break;
+                       }
+               }
+       }
+
+       return len_end;
+}
+
+
+extern void
+lzma_lzma_optimum_normal(lzma_coder *restrict coder, lzma_mf *restrict mf,
+               uint32_t *restrict back_res, uint32_t *restrict len_res,
+               uint32_t position)
+{
+       // If we have symbols pending, return the next pending symbol.
+       if (coder->opts_end_index != coder->opts_current_index) {
+               assert(mf->read_ahead > 0);
+               *len_res = coder->opts[coder->opts_current_index].pos_prev
+                               - coder->opts_current_index;
+               *back_res = coder->opts[coder->opts_current_index].back_prev;
+               coder->opts_current_index = coder->opts[
+                               coder->opts_current_index].pos_prev;
+               return;
+       }
+
+       // Update the price tables. In LZMA SDK <= 4.60 (and possibly later)
+       // this was done in both initialization function and in the main loop.
+       // In liblzma they were moved into this single place.
+       if (mf->read_ahead == 0) {
+               if (coder->match_price_count >= (1 << 7))
+                       fill_dist_prices(coder);
+
+               if (coder->align_price_count >= ALIGN_SIZE)
+                       fill_align_prices(coder);
+       }
+
+       // TODO: This needs quite a bit of cleaning still. But splitting
+       // the original function into two pieces makes it at least a little
+       // more readable, since those two parts don't share many variables.
+
+       uint32_t len_end = helper1(coder, mf, back_res, len_res, position);
+       if (len_end == UINT32_MAX)
+               return;
+
+       uint32_t reps[REPS];
+       memcpy(reps, coder->reps, sizeof(reps));
+
+       uint32_t cur;
+       for (cur = 1; cur < len_end; ++cur) {
+               assert(cur < OPTS);
+
+               coder->longest_match_length = mf_find(
+                               mf, &coder->matches_count, coder->matches);
+
+               if (coder->longest_match_length >= mf->nice_len)
+                       break;
+
+               len_end = helper2(coder, reps, mf_ptr(mf) - 1, len_end,
+                               position + cur, cur, mf->nice_len,
+                               my_min(mf_avail(mf) + 1, OPTS - 1 - cur));
+       }
+
+       backward(coder, len_res, back_res, cur);
+       return;
+}
diff --git a/lzma/lzma/lzma_encoder_presets.c b/lzma/lzma/lzma_encoder_presets.c
new file mode 100644 (file)
index 0000000..711df02
--- /dev/null
@@ -0,0 +1,64 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma_encoder_presets.c
+/// \brief      Encoder presets
+/// \note       xz needs this even when only decoding is enabled.
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+
+extern LZMA_API(lzma_bool)
+lzma_lzma_preset(lzma_options_lzma *options, uint32_t preset)
+{
+       const uint32_t level = preset & LZMA_PRESET_LEVEL_MASK;
+       const uint32_t flags = preset & ~LZMA_PRESET_LEVEL_MASK;
+       const uint32_t supported_flags = LZMA_PRESET_EXTREME;
+
+       if (level > 9 || (flags & ~supported_flags))
+               return true;
+
+       options->preset_dict = NULL;
+       options->preset_dict_size = 0;
+
+       options->lc = LZMA_LC_DEFAULT;
+       options->lp = LZMA_LP_DEFAULT;
+       options->pb = LZMA_PB_DEFAULT;
+
+       static const uint8_t dict_pow2[]
+                       = { 18, 20, 21, 22, 22, 23, 23, 24, 25, 26 };
+       options->dict_size = UINT32_C(1) << dict_pow2[level];
+
+       if (level <= 3) {
+               options->mode = LZMA_MODE_FAST;
+               options->mf = level == 0 ? LZMA_MF_HC3 : LZMA_MF_HC4;
+               options->nice_len = level <= 1 ? 128 : 273;
+               static const uint8_t depths[] = { 4, 8, 24, 48 };
+               options->depth = depths[level];
+       } else {
+               options->mode = LZMA_MODE_NORMAL;
+               options->mf = LZMA_MF_BT4;
+               options->nice_len = level == 4 ? 16 : level == 5 ? 32 : 64;
+               options->depth = 0;
+       }
+
+       if (flags & LZMA_PRESET_EXTREME) {
+               options->mode = LZMA_MODE_NORMAL;
+               options->mf = LZMA_MF_BT4;
+               if (level == 3 || level == 5) {
+                       options->nice_len = 192;
+                       options->depth = 0;
+               } else {
+                       options->nice_len = 273;
+                       options->depth = 512;
+               }
+       }
+
+       return false;
+}
diff --git a/lzma/lzma/lzma_encoder_private.h b/lzma/lzma/lzma_encoder_private.h
new file mode 100644 (file)
index 0000000..2f62d6c
--- /dev/null
@@ -0,0 +1,148 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma_encoder_private.h
+/// \brief      Private definitions for LZMA encoder
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_LZMA_ENCODER_PRIVATE_H
+#define LZMA_LZMA_ENCODER_PRIVATE_H
+
+#include "lz_encoder.h"
+#include "range_encoder.h"
+#include "lzma_common.h"
+#include "lzma_encoder.h"
+
+
+// Macro to compare if the first two bytes in two buffers differ. This is
+// needed in lzma_lzma_optimum_*() to test if the match is at least
+// MATCH_LEN_MIN bytes. Unaligned access gives tiny gain so there's no
+// reason to not use it when it is supported.
+#ifdef TUKLIB_FAST_UNALIGNED_ACCESS
+#      define not_equal_16(a, b) \
+               (*(const uint16_t *)(a) != *(const uint16_t *)(b))
+#else
+#      define not_equal_16(a, b) \
+               ((a)[0] != (b)[0] || (a)[1] != (b)[1])
+#endif
+
+
+// Optimal - Number of entries in the optimum array.
+#define OPTS (1 << 12)
+
+
+typedef struct {
+       probability choice;
+       probability choice2;
+       probability low[POS_STATES_MAX][LEN_LOW_SYMBOLS];
+       probability mid[POS_STATES_MAX][LEN_MID_SYMBOLS];
+       probability high[LEN_HIGH_SYMBOLS];
+
+       uint32_t prices[POS_STATES_MAX][LEN_SYMBOLS];
+       uint32_t table_size;
+       uint32_t counters[POS_STATES_MAX];
+
+} lzma_length_encoder;
+
+
+typedef struct {
+       lzma_lzma_state state;
+
+       bool prev_1_is_literal;
+       bool prev_2;
+
+       uint32_t pos_prev_2;
+       uint32_t back_prev_2;
+
+       uint32_t price;
+       uint32_t pos_prev;  // pos_next;
+       uint32_t back_prev;
+
+       uint32_t backs[REPS];
+
+} lzma_optimal;
+
+
+struct lzma_coder_s {
+       /// Range encoder
+       lzma_range_encoder rc;
+
+       /// State
+       lzma_lzma_state state;
+
+       /// The four most recent match distances
+       uint32_t reps[REPS];
+
+       /// Array of match candidates
+       lzma_match matches[MATCH_LEN_MAX + 1];
+
+       /// Number of match candidates in matches[]
+       uint32_t matches_count;
+
+       /// Variable to hold the length of the longest match between calls
+       /// to lzma_lzma_optimum_*().
+       uint32_t longest_match_length;
+
+       /// True if using getoptimumfast
+       bool fast_mode;
+
+       /// True if the encoder has been initialized by encoding the first
+       /// byte as a literal.
+       bool is_initialized;
+
+       /// True if the range encoder has been flushed, but not all bytes
+       /// have been written to the output buffer yet.
+       bool is_flushed;
+
+       uint32_t pos_mask;         ///< (1 << pos_bits) - 1
+       uint32_t literal_context_bits;
+       uint32_t literal_pos_mask;
+
+       // These are the same as in lzma_decoder.c. See comments there.
+       probability literal[LITERAL_CODERS_MAX][LITERAL_CODER_SIZE];
+       probability is_match[STATES][POS_STATES_MAX];
+       probability is_rep[STATES];
+       probability is_rep0[STATES];
+       probability is_rep1[STATES];
+       probability is_rep2[STATES];
+       probability is_rep0_long[STATES][POS_STATES_MAX];
+       probability dist_slot[DIST_STATES][DIST_SLOTS];
+       probability dist_special[FULL_DISTANCES - DIST_MODEL_END];
+       probability dist_align[ALIGN_SIZE];
+
+       // These are the same as in lzma_decoder.c except that the encoders
+       // include also price tables.
+       lzma_length_encoder match_len_encoder;
+       lzma_length_encoder rep_len_encoder;
+
+       // Price tables
+       uint32_t dist_slot_prices[DIST_STATES][DIST_SLOTS];
+       uint32_t dist_prices[DIST_STATES][FULL_DISTANCES];
+       uint32_t dist_table_size;
+       uint32_t match_price_count;
+
+       uint32_t align_prices[ALIGN_SIZE];
+       uint32_t align_price_count;
+
+       // Optimal
+       uint32_t opts_end_index;
+       uint32_t opts_current_index;
+       lzma_optimal opts[OPTS];
+};
+
+
+extern void lzma_lzma_optimum_fast(
+               lzma_coder *restrict coder, lzma_mf *restrict mf,
+               uint32_t *restrict back_res, uint32_t *restrict len_res);
+
+extern void lzma_lzma_optimum_normal(lzma_coder *restrict coder,
+               lzma_mf *restrict mf, uint32_t *restrict back_res,
+               uint32_t *restrict len_res, uint32_t position);
+
+#endif
diff --git a/lzma/rangecoder/price.h b/lzma/rangecoder/price.h
new file mode 100644 (file)
index 0000000..8ae02ca
--- /dev/null
@@ -0,0 +1,92 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       price.h
+/// \brief      Probability price calculation
+//
+//  Author:     Igor Pavlov
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_PRICE_H
+#define LZMA_PRICE_H
+
+
+#define RC_MOVE_REDUCING_BITS 4
+#define RC_BIT_PRICE_SHIFT_BITS 4
+#define RC_PRICE_TABLE_SIZE (RC_BIT_MODEL_TOTAL >> RC_MOVE_REDUCING_BITS)
+
+#define RC_INFINITY_PRICE (UINT32_C(1) << 30)
+
+
+/// Lookup table for the inline functions defined in this file.
+extern const uint8_t lzma_rc_prices[RC_PRICE_TABLE_SIZE];
+
+
+static inline uint32_t
+rc_bit_price(const probability prob, const uint32_t bit)
+{
+       return lzma_rc_prices[(prob ^ ((UINT32_C(0) - bit)
+                       & (RC_BIT_MODEL_TOTAL - 1))) >> RC_MOVE_REDUCING_BITS];
+}
+
+
+static inline uint32_t
+rc_bit_0_price(const probability prob)
+{
+       return lzma_rc_prices[prob >> RC_MOVE_REDUCING_BITS];
+}
+
+
+static inline uint32_t
+rc_bit_1_price(const probability prob)
+{
+       return lzma_rc_prices[(prob ^ (RC_BIT_MODEL_TOTAL - 1))
+                       >> RC_MOVE_REDUCING_BITS];
+}
+
+
+static inline uint32_t
+rc_bittree_price(const probability *const probs,
+               const uint32_t bit_levels, uint32_t symbol)
+{
+       uint32_t price = 0;
+       symbol += UINT32_C(1) << bit_levels;
+
+       do {
+               const uint32_t bit = symbol & 1;
+               symbol >>= 1;
+               price += rc_bit_price(probs[symbol], bit);
+       } while (symbol != 1);
+
+       return price;
+}
+
+
+static inline uint32_t
+rc_bittree_reverse_price(const probability *const probs,
+               uint32_t bit_levels, uint32_t symbol)
+{
+       uint32_t price = 0;
+       uint32_t model_index = 1;
+
+       do {
+               const uint32_t bit = symbol & 1;
+               symbol >>= 1;
+               price += rc_bit_price(probs[model_index], bit);
+               model_index = (model_index << 1) + bit;
+       } while (--bit_levels != 0);
+
+       return price;
+}
+
+
+static inline uint32_t
+rc_direct_price(const uint32_t bits)
+{
+        return bits << RC_BIT_PRICE_SHIFT_BITS;
+}
+
+#endif
diff --git a/lzma/rangecoder/price_table.c b/lzma/rangecoder/price_table.c
new file mode 100644 (file)
index 0000000..ac64bf6
--- /dev/null
@@ -0,0 +1,22 @@
+/* This file has been automatically generated by price_tablegen.c. */
+
+#include "range_encoder.h"
+
+const uint8_t lzma_rc_prices[RC_PRICE_TABLE_SIZE] = {
+        128, 103,  91,  84,  78,  73,  69,  66,
+         63,  61,  58,  56,  54,  52,  51,  49,
+         48,  46,  45,  44,  43,  42,  41,  40,
+         39,  38,  37,  36,  35,  34,  34,  33,
+         32,  31,  31,  30,  29,  29,  28,  28,
+         27,  26,  26,  25,  25,  24,  24,  23,
+         23,  22,  22,  22,  21,  21,  20,  20,
+         19,  19,  19,  18,  18,  17,  17,  17,
+         16,  16,  16,  15,  15,  15,  14,  14,
+         14,  13,  13,  13,  12,  12,  12,  11,
+         11,  11,  11,  10,  10,  10,  10,   9,
+          9,   9,   9,   8,   8,   8,   8,   7,
+          7,   7,   7,   6,   6,   6,   6,   5,
+          5,   5,   5,   5,   4,   4,   4,   4,
+          3,   3,   3,   3,   3,   2,   2,   2,
+          2,   2,   2,   1,   1,   1,   1,   1
+};
diff --git a/lzma/rangecoder/range_common.h b/lzma/rangecoder/range_common.h
new file mode 100644 (file)
index 0000000..0e64241
--- /dev/null
@@ -0,0 +1,73 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       range_common.h
+/// \brief      Common things for range encoder and decoder
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_RANGE_COMMON_H
+#define LZMA_RANGE_COMMON_H
+
+#ifdef HAVE_CONFIG_H
+#      include "common.h"
+#endif
+
+
+///////////////
+// Constants //
+///////////////
+
+#define RC_SHIFT_BITS 8
+#define RC_TOP_BITS 24
+#define RC_TOP_VALUE (UINT32_C(1) << RC_TOP_BITS)
+#define RC_BIT_MODEL_TOTAL_BITS 11
+#define RC_BIT_MODEL_TOTAL (UINT32_C(1) << RC_BIT_MODEL_TOTAL_BITS)
+#define RC_MOVE_BITS 5
+
+
+////////////
+// Macros //
+////////////
+
+// Resets the probability so that both 0 and 1 have probability of 50 %
+#define bit_reset(prob) \
+       prob = RC_BIT_MODEL_TOTAL >> 1
+
+// This does the same for a complete bit tree.
+// (A tree represented as an array.)
+#define bittree_reset(probs, bit_levels) \
+       for (uint32_t bt_i = 0; bt_i < (1 << (bit_levels)); ++bt_i) \
+               bit_reset((probs)[bt_i])
+
+
+//////////////////////
+// Type definitions //
+//////////////////////
+
+/// \brief      Type of probabilities used with range coder
+///
+/// This needs to be at least 12-bit integer, so uint16_t is a logical choice.
+/// However, on some architecture and compiler combinations, a bigger type
+/// may give better speed, because the probability variables are accessed
+/// a lot. On the other hand, bigger probability type increases cache
+/// footprint, since there are 2 to 14 thousand probability variables in
+/// LZMA (assuming the limit of lc + lp <= 4; with lc + lp <= 12 there
+/// would be about 1.5 million variables).
+///
+/// With malicious files, the initialization speed of the LZMA decoder can
+/// become important. In that case, smaller probability variables mean that
+/// there is less bytes to write to RAM, which makes initialization faster.
+/// With big probability type, the initialization can become so slow that it
+/// can be a problem e.g. for email servers doing virus scanning.
+///
+/// I will be sticking to uint16_t unless some specific architectures
+/// are *much* faster (20-50 %) with uint32_t.
+typedef uint16_t probability;
+
+#endif
diff --git a/lzma/rangecoder/range_decoder.h b/lzma/rangecoder/range_decoder.h
new file mode 100644 (file)
index 0000000..e0b051f
--- /dev/null
@@ -0,0 +1,185 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       range_decoder.h
+/// \brief      Range Decoder
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_RANGE_DECODER_H
+#define LZMA_RANGE_DECODER_H
+
+#include "range_common.h"
+
+
+typedef struct {
+       uint32_t range;
+       uint32_t code;
+       uint32_t init_bytes_left;
+} lzma_range_decoder;
+
+
+/// Reads the first five bytes to initialize the range decoder.
+static inline lzma_ret
+rc_read_init(lzma_range_decoder *rc, const uint8_t *restrict in,
+               size_t *restrict in_pos, size_t in_size)
+{
+       while (rc->init_bytes_left > 0) {
+               if (*in_pos == in_size)
+                       return LZMA_OK;
+
+               // The first byte is always 0x00. It could have been omitted
+               // in LZMA2 but it wasn't, so one byte is wasted in every
+               // LZMA2 chunk.
+               if (rc->init_bytes_left == 5 && in[*in_pos] != 0x00)
+                       return LZMA_DATA_ERROR;
+
+               rc->code = (rc->code << 8) | in[*in_pos];
+               ++*in_pos;
+               --rc->init_bytes_left;
+       }
+
+       return LZMA_STREAM_END;
+}
+
+
+/// Makes local copies of range decoder and *in_pos variables. Doing this
+/// improves speed significantly. The range decoder macros expect also
+/// variables `in' and `in_size' to be defined.
+#define rc_to_local(range_decoder, in_pos) \
+       lzma_range_decoder rc = range_decoder; \
+       size_t rc_in_pos = (in_pos); \
+       uint32_t rc_bound
+
+
+/// Stores the local copes back to the range decoder structure.
+#define rc_from_local(range_decoder, in_pos) \
+do { \
+       range_decoder = rc; \
+       in_pos = rc_in_pos; \
+} while (0)
+
+
+/// Resets the range decoder structure.
+#define rc_reset(range_decoder) \
+do { \
+       (range_decoder).range = UINT32_MAX; \
+       (range_decoder).code = 0; \
+       (range_decoder).init_bytes_left = 5; \
+} while (0)
+
+
+/// When decoding has been properly finished, rc.code is always zero unless
+/// the input stream is corrupt. So checking this can catch some corrupt
+/// files especially if they don't have any other integrity check.
+#define rc_is_finished(range_decoder) \
+       ((range_decoder).code == 0)
+
+
+/// Read the next input byte if needed. If more input is needed but there is
+/// no more input available, "goto out" is used to jump out of the main
+/// decoder loop.
+#define rc_normalize(seq) \
+do { \
+       if (rc.range < RC_TOP_VALUE) { \
+               if (unlikely(rc_in_pos == in_size)) { \
+                       coder->sequence = seq; \
+                       goto out; \
+               } \
+               rc.range <<= RC_SHIFT_BITS; \
+               rc.code = (rc.code << RC_SHIFT_BITS) | in[rc_in_pos++]; \
+       } \
+} while (0)
+
+
+/// Start decoding a bit. This must be used together with rc_update_0()
+/// and rc_update_1():
+///
+///     rc_if_0(prob, seq) {
+///         rc_update_0(prob);
+///         // Do something
+///     } else {
+///         rc_update_1(prob);
+///         // Do something else
+///     }
+///
+#define rc_if_0(prob, seq) \
+       rc_normalize(seq); \
+       rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) * (prob); \
+       if (rc.code < rc_bound)
+
+
+/// Update the range decoder state and the used probability variable to
+/// match a decoded bit of 0.
+#define rc_update_0(prob) \
+do { \
+       rc.range = rc_bound; \
+       prob += (RC_BIT_MODEL_TOTAL - (prob)) >> RC_MOVE_BITS; \
+} while (0)
+
+
+/// Update the range decoder state and the used probability variable to
+/// match a decoded bit of 1.
+#define rc_update_1(prob) \
+do { \
+       rc.range -= rc_bound; \
+       rc.code -= rc_bound; \
+       prob -= (prob) >> RC_MOVE_BITS; \
+} while (0)
+
+
+/// Decodes one bit and runs action0 or action1 depending on the decoded bit.
+/// This macro is used as the last step in bittree reverse decoders since
+/// those don't use "symbol" for anything else than indexing the probability
+/// arrays.
+#define rc_bit_last(prob, action0, action1, seq) \
+do { \
+       rc_if_0(prob, seq) { \
+               rc_update_0(prob); \
+               action0; \
+       } else { \
+               rc_update_1(prob); \
+               action1; \
+       } \
+} while (0)
+
+
+/// Decodes one bit, updates "symbol", and runs action0 or action1 depending
+/// on the decoded bit.
+#define rc_bit(prob, action0, action1, seq) \
+       rc_bit_last(prob, \
+               symbol <<= 1; action0, \
+               symbol = (symbol << 1) + 1; action1, \
+               seq);
+
+
+/// Like rc_bit() but add "case seq:" as a prefix. This makes the unrolled
+/// loops more readable because the code isn't littered with "case"
+/// statements. On the other hand this also makes it less readable, since
+/// spotting the places where the decoder loop may be restarted is less
+/// obvious.
+#define rc_bit_case(prob, action0, action1, seq) \
+       case seq: rc_bit(prob, action0, action1, seq)
+
+
+/// Decode a bit without using a probability.
+#define rc_direct(dest, seq) \
+do { \
+       rc_normalize(seq); \
+       rc.range >>= 1; \
+       rc.code -= rc.range; \
+       rc_bound = UINT32_C(0) - (rc.code >> 31); \
+       rc.code += rc.range & rc_bound; \
+       dest = (dest << 1) + (rc_bound + 1); \
+} while (0)
+
+
+// NOTE: No macros are provided for bittree decoding. It seems to be simpler
+// to just write them open in the code.
+
+#endif
diff --git a/lzma/rangecoder/range_encoder.h b/lzma/rangecoder/range_encoder.h
new file mode 100644 (file)
index 0000000..29e90c0
--- /dev/null
@@ -0,0 +1,233 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       range_encoder.h
+/// \brief      Range Encoder
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_RANGE_ENCODER_H
+#define LZMA_RANGE_ENCODER_H
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include "range_common.h"
+#include "price.h"
+
+
+/// Maximum number of symbols that can be put pending into lzma_range_encoder
+/// structure between calls to lzma_rc_encode(). For LZMA, 52+5 is enough
+/// (match with big distance and length followed by range encoder flush).
+#define RC_SYMBOLS_MAX 58
+
+
+typedef struct {
+       uint64_t low;
+       uint64_t cache_size;
+       uint32_t range;
+       uint8_t cache;
+
+       /// Number of symbols in the tables
+       size_t count;
+
+       /// rc_encode()'s position in the tables
+       size_t pos;
+
+       /// Symbols to encode
+       enum {
+               RC_BIT_0,
+               RC_BIT_1,
+               RC_DIRECT_0,
+               RC_DIRECT_1,
+               RC_FLUSH,
+       } symbols[RC_SYMBOLS_MAX];
+
+       /// Probabilities associated with RC_BIT_0 or RC_BIT_1
+       probability *probs[RC_SYMBOLS_MAX];
+
+} lzma_range_encoder;
+
+
+static inline void
+rc_reset(lzma_range_encoder *rc)
+{
+       rc->low = 0;
+       rc->cache_size = 1;
+       rc->range = UINT32_MAX;
+       rc->cache = 0;
+       rc->count = 0;
+       rc->pos = 0;
+}
+
+
+static inline void
+rc_bit(lzma_range_encoder *rc, probability *prob, uint32_t bit)
+{
+       rc->symbols[rc->count] = bit;
+       rc->probs[rc->count] = prob;
+       ++rc->count;
+}
+
+
+static inline void
+rc_bittree(lzma_range_encoder *rc, probability *probs,
+               uint32_t bit_count, uint32_t symbol)
+{
+       uint32_t model_index = 1;
+
+       do {
+               const uint32_t bit = (symbol >> --bit_count) & 1;
+               rc_bit(rc, &probs[model_index], bit);
+               model_index = (model_index << 1) + bit;
+       } while (bit_count != 0);
+}
+
+
+static inline void
+rc_bittree_reverse(lzma_range_encoder *rc, probability *probs,
+               uint32_t bit_count, uint32_t symbol)
+{
+       uint32_t model_index = 1;
+
+       do {
+               const uint32_t bit = symbol & 1;
+               symbol >>= 1;
+               rc_bit(rc, &probs[model_index], bit);
+               model_index = (model_index << 1) + bit;
+       } while (--bit_count != 0);
+}
+
+
+static inline void
+rc_direct(lzma_range_encoder *rc,
+               uint32_t value, uint32_t bit_count)
+{
+       do {
+               rc->symbols[rc->count++]
+                               = RC_DIRECT_0 + ((value >> --bit_count) & 1);
+       } while (bit_count != 0);
+}
+
+
+static inline void
+rc_flush(lzma_range_encoder *rc)
+{
+       for (size_t i = 0; i < 5; ++i)
+               rc->symbols[rc->count++] = RC_FLUSH;
+}
+
+
+static inline bool
+rc_shift_low(lzma_range_encoder *rc,
+               uint8_t *out, size_t *out_pos, size_t out_size)
+{
+       if ((uint32_t)(rc->low) < (uint32_t)(0xFF000000)
+                       || (uint32_t)(rc->low >> 32) != 0) {
+               do {
+                       if (*out_pos == out_size)
+                               return true;
+
+                       out[*out_pos] = rc->cache + (uint8_t)(rc->low >> 32);
+                       ++*out_pos;
+                       rc->cache = 0xFF;
+
+               } while (--rc->cache_size != 0);
+
+               rc->cache = (rc->low >> 24) & 0xFF;
+       }
+
+       ++rc->cache_size;
+       rc->low = (rc->low & 0x00FFFFFF) << RC_SHIFT_BITS;
+
+       return false;
+}
+
+
+static inline bool
+rc_encode(lzma_range_encoder *rc,
+               uint8_t *out, size_t *out_pos, size_t out_size)
+{
+       assert(rc->count <= RC_SYMBOLS_MAX);
+
+       while (rc->pos < rc->count) {
+               // Normalize
+               if (rc->range < RC_TOP_VALUE) {
+                       if (rc_shift_low(rc, out, out_pos, out_size))
+                               return true;
+
+                       rc->range <<= RC_SHIFT_BITS;
+               }
+
+               // Encode a bit
+               switch (rc->symbols[rc->pos]) {
+               case RC_BIT_0: {
+                       probability prob = *rc->probs[rc->pos];
+                       rc->range = (rc->range >> RC_BIT_MODEL_TOTAL_BITS)
+                                       * prob;
+                       prob += (RC_BIT_MODEL_TOTAL - prob) >> RC_MOVE_BITS;
+                       *rc->probs[rc->pos] = prob;
+                       break;
+               }
+
+               case RC_BIT_1: {
+                       probability prob = *rc->probs[rc->pos];
+                       const uint32_t bound = prob * (rc->range
+                                       >> RC_BIT_MODEL_TOTAL_BITS);
+                       rc->low += bound;
+                       rc->range -= bound;
+                       prob -= prob >> RC_MOVE_BITS;
+                       *rc->probs[rc->pos] = prob;
+                       break;
+               }
+
+               case RC_DIRECT_0:
+                       rc->range >>= 1;
+                       break;
+
+               case RC_DIRECT_1:
+                       rc->range >>= 1;
+                       rc->low += rc->range;
+                       break;
+
+               case RC_FLUSH:
+                       // Prevent further normalizations.
+                       rc->range = UINT32_MAX;
+
+                       // Flush the last five bytes (see rc_flush()).
+                       do {
+                               if (rc_shift_low(rc, out, out_pos, out_size))
+                                       return true;
+                       } while (++rc->pos < rc->count);
+
+                       // Reset the range encoder so we are ready to continue
+                       // encoding if we weren't finishing the stream.
+                       rc_reset(rc);
+                       return false;
+
+               default:
+                       assert(0);
+                       break;
+               }
+
+               ++rc->pos;
+       }
+
+       rc->count = 0;
+       rc->pos = 0;
+
+       return false;
+}
+
+
+static inline uint64_t
+rc_pending(const lzma_range_encoder *rc)
+{
+       return rc->cache_size + 5 - 1;
+}
+
+#endif
diff --git a/lzma/simple/simple_coder.h b/lzma/simple/simple_coder.h
new file mode 100644 (file)
index 0000000..19c2ee0
--- /dev/null
@@ -0,0 +1,72 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       simple_coder.h
+/// \brief      Wrapper for simple filters
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_SIMPLE_CODER_H
+#define LZMA_SIMPLE_CODER_H
+
+#include "common.h"
+
+
+extern lzma_ret lzma_simple_x86_encoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters);
+
+extern lzma_ret lzma_simple_x86_decoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters);
+
+
+extern lzma_ret lzma_simple_powerpc_encoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters);
+
+extern lzma_ret lzma_simple_powerpc_decoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters);
+
+
+extern lzma_ret lzma_simple_ia64_encoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters);
+
+extern lzma_ret lzma_simple_ia64_decoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters);
+
+
+extern lzma_ret lzma_simple_arm_encoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters);
+
+extern lzma_ret lzma_simple_arm_decoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters);
+
+
+extern lzma_ret lzma_simple_armthumb_encoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters);
+
+extern lzma_ret lzma_simple_armthumb_decoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters);
+
+
+extern lzma_ret lzma_simple_sparc_encoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters);
+
+extern lzma_ret lzma_simple_sparc_decoder_init(lzma_next_coder *next,
+               const lzma_allocator *allocator,
+               const lzma_filter_info *filters);
+
+#endif
diff --git a/lzma/simple/simple_decoder.h b/lzma/simple/simple_decoder.h
new file mode 100644 (file)
index 0000000..bed8d37
--- /dev/null
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       simple_decoder.h
+/// \brief      Properties decoder for simple filters
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_SIMPLE_DECODER_H
+#define LZMA_SIMPLE_DECODER_H
+
+#include "simple_coder.h"
+
+extern lzma_ret lzma_simple_props_decode(
+               void **options, const lzma_allocator *allocator,
+               const uint8_t *props, size_t props_size);
+
+#endif
diff --git a/lzma/simple/simple_encoder.h b/lzma/simple/simple_encoder.h
new file mode 100644 (file)
index 0000000..1cee482
--- /dev/null
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       simple_encoder.c
+/// \brief      Properties encoder for simple filters
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_SIMPLE_ENCODER_H
+#define LZMA_SIMPLE_ENCODER_H
+
+#include "simple_coder.h"
+
+
+extern lzma_ret lzma_simple_props_size(uint32_t *size, const void *options);
+
+extern lzma_ret lzma_simple_props_encode(const void *options, uint8_t *out);
+
+#endif
diff --git a/lzma/tuklib/mythread.h b/lzma/tuklib/mythread.h
new file mode 100644 (file)
index 0000000..be22654
--- /dev/null
@@ -0,0 +1,521 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       mythread.h
+/// \brief      Some threading related helper macros and functions
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef MYTHREAD_H
+#define MYTHREAD_H
+
+#include "sysdefs.h"
+
+// If any type of threading is enabled, #define MYTHREAD_ENABLED.
+#if defined(MYTHREAD_POSIX) || defined(MYTHREAD_WIN95) \
+               || defined(MYTHREAD_VISTA)
+#      define MYTHREAD_ENABLED 1
+#endif
+
+
+#ifdef MYTHREAD_ENABLED
+
+////////////////////////////////////////
+// Shared between all threading types //
+////////////////////////////////////////
+
+// Locks a mutex for a duration of a block.
+//
+// Perform mythread_mutex_lock(&mutex) in the beginning of a block
+// and mythread_mutex_unlock(&mutex) at the end of the block. "break"
+// may be used to unlock the mutex and jump out of the block.
+// mythread_sync blocks may be nested.
+//
+// Example:
+//
+//     mythread_sync(mutex) {
+//         foo();
+//         if (some_error)
+//             break; // Skips bar()
+//         bar();
+//     }
+//
+// At least GCC optimizes the loops completely away so it doesn't slow
+// things down at all compared to plain mythread_mutex_lock(&mutex)
+// and mythread_mutex_unlock(&mutex) calls.
+//
+#define mythread_sync(mutex) mythread_sync_helper1(mutex, __LINE__)
+#define mythread_sync_helper1(mutex, line) mythread_sync_helper2(mutex, line)
+#define mythread_sync_helper2(mutex, line) \
+       for (unsigned int mythread_i_ ## line = 0; \
+                       mythread_i_ ## line \
+                               ? (mythread_mutex_unlock(&(mutex)), 0) \
+                               : (mythread_mutex_lock(&(mutex)), 1); \
+                       mythread_i_ ## line = 1) \
+               for (unsigned int mythread_j_ ## line = 0; \
+                               !mythread_j_ ## line; \
+                               mythread_j_ ## line = 1)
+#endif
+
+
+#if !defined(MYTHREAD_ENABLED)
+
+//////////////////
+// No threading //
+//////////////////
+
+// Calls the given function once. This isn't thread safe.
+#define mythread_once(func) \
+do { \
+       static bool once_ = false; \
+       if (!once_) { \
+               func(); \
+               once_ = true; \
+       } \
+} while (0)
+
+
+#if !(defined(_WIN32) && !defined(__CYGWIN__))
+// Use sigprocmask() to set the signal mask in single-threaded programs.
+#include <signal.h>
+
+static inline void
+mythread_sigmask(int how, const sigset_t *restrict set,
+               sigset_t *restrict oset)
+{
+       int ret = sigprocmask(how, set, oset);
+       assert(ret == 0);
+       (void)ret;
+}
+#endif
+
+
+#elif defined(MYTHREAD_POSIX)
+
+////////////////////
+// Using pthreads //
+////////////////////
+
+#include <sys/time.h>
+#include <pthread.h>
+#include <signal.h>
+#include <time.h>
+#include <errno.h>
+
+#define MYTHREAD_RET_TYPE void *
+#define MYTHREAD_RET_VALUE NULL
+
+typedef pthread_t mythread;
+typedef pthread_mutex_t mythread_mutex;
+
+typedef struct {
+       pthread_cond_t cond;
+#ifdef HAVE_CLOCK_GETTIME
+       // Clock ID (CLOCK_REALTIME or CLOCK_MONOTONIC) associated with
+       // the condition variable.
+       clockid_t clk_id;
+#endif
+} mythread_cond;
+
+typedef struct timespec mythread_condtime;
+
+
+// Calls the given function once in a thread-safe way.
+#define mythread_once(func) \
+       do { \
+               static pthread_once_t once_ = PTHREAD_ONCE_INIT; \
+               pthread_once(&once_, &func); \
+       } while (0)
+
+
+// Use pthread_sigmask() to set the signal mask in multi-threaded programs.
+// Do nothing on OpenVMS since it lacks pthread_sigmask().
+static inline void
+mythread_sigmask(int how, const sigset_t *restrict set,
+               sigset_t *restrict oset)
+{
+#ifdef __VMS
+       (void)how;
+       (void)set;
+       (void)oset;
+#else
+       int ret = pthread_sigmask(how, set, oset);
+       assert(ret == 0);
+       (void)ret;
+#endif
+}
+
+
+// Creates a new thread with all signals blocked. Returns zero on success
+// and non-zero on error.
+static inline int
+mythread_create(mythread *thread, void *(*func)(void *arg), void *arg)
+{
+       sigset_t old;
+       sigset_t all;
+       sigfillset(&all);
+
+       mythread_sigmask(SIG_SETMASK, &all, &old);
+       const int ret = pthread_create(thread, NULL, func, arg);
+       mythread_sigmask(SIG_SETMASK, &old, NULL);
+
+       return ret;
+}
+
+// Joins a thread. Returns zero on success and non-zero on error.
+static inline int
+mythread_join(mythread thread)
+{
+       return pthread_join(thread, NULL);
+}
+
+
+// Initiatlizes a mutex. Returns zero on success and non-zero on error.
+static inline int
+mythread_mutex_init(mythread_mutex *mutex)
+{
+       return pthread_mutex_init(mutex, NULL);
+}
+
+static inline void
+mythread_mutex_destroy(mythread_mutex *mutex)
+{
+       int ret = pthread_mutex_destroy(mutex);
+       assert(ret == 0);
+       (void)ret;
+}
+
+static inline void
+mythread_mutex_lock(mythread_mutex *mutex)
+{
+       int ret = pthread_mutex_lock(mutex);
+       assert(ret == 0);
+       (void)ret;
+}
+
+static inline void
+mythread_mutex_unlock(mythread_mutex *mutex)
+{
+       int ret = pthread_mutex_unlock(mutex);
+       assert(ret == 0);
+       (void)ret;
+}
+
+
+// Initializes a condition variable.
+//
+// Using CLOCK_MONOTONIC instead of the default CLOCK_REALTIME makes the
+// timeout in pthread_cond_timedwait() work correctly also if system time
+// is suddenly changed. Unfortunately CLOCK_MONOTONIC isn't available
+// everywhere while the default CLOCK_REALTIME is, so the default is
+// used if CLOCK_MONOTONIC isn't available.
+//
+// If clock_gettime() isn't available at all, gettimeofday() will be used.
+static inline int
+mythread_cond_init(mythread_cond *mycond)
+{
+#ifdef HAVE_CLOCK_GETTIME
+       // NOTE: HAVE_DECL_CLOCK_MONOTONIC is always defined to 0 or 1.
+#      if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && HAVE_DECL_CLOCK_MONOTONIC
+       struct timespec ts;
+       pthread_condattr_t condattr;
+
+       // POSIX doesn't seem to *require* that pthread_condattr_setclock()
+       // will fail if given an unsupported clock ID. Test that
+       // CLOCK_MONOTONIC really is supported using clock_gettime().
+       if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0
+                       && pthread_condattr_init(&condattr) == 0) {
+               int ret = pthread_condattr_setclock(
+                               &condattr, CLOCK_MONOTONIC);
+               if (ret == 0)
+                       ret = pthread_cond_init(&mycond->cond, &condattr);
+
+               pthread_condattr_destroy(&condattr);
+
+               if (ret == 0) {
+                       mycond->clk_id = CLOCK_MONOTONIC;
+                       return 0;
+               }
+       }
+
+       // If anything above fails, fall back to the default CLOCK_REALTIME.
+       // POSIX requires that all implementations of clock_gettime() must
+       // support at least CLOCK_REALTIME.
+#      endif
+
+       mycond->clk_id = CLOCK_REALTIME;
+#endif
+
+       return pthread_cond_init(&mycond->cond, NULL);
+}
+
+static inline void
+mythread_cond_destroy(mythread_cond *cond)
+{
+       int ret = pthread_cond_destroy(&cond->cond);
+       assert(ret == 0);
+       (void)ret;
+}
+
+static inline void
+mythread_cond_signal(mythread_cond *cond)
+{
+       int ret = pthread_cond_signal(&cond->cond);
+       assert(ret == 0);
+       (void)ret;
+}
+
+static inline void
+mythread_cond_wait(mythread_cond *cond, mythread_mutex *mutex)
+{
+       int ret = pthread_cond_wait(&cond->cond, mutex);
+       assert(ret == 0);
+       (void)ret;
+}
+
+// Waits on a condition or until a timeout expires. If the timeout expires,
+// non-zero is returned, otherwise zero is returned.
+static inline int
+mythread_cond_timedwait(mythread_cond *cond, mythread_mutex *mutex,
+               const mythread_condtime *condtime)
+{
+       int ret = pthread_cond_timedwait(&cond->cond, mutex, condtime);
+       assert(ret == 0 || ret == ETIMEDOUT);
+       return ret;
+}
+
+// Sets condtime to the absolute time that is timeout_ms milliseconds
+// in the future. The type of the clock to use is taken from cond.
+static inline void
+mythread_condtime_set(mythread_condtime *condtime, const mythread_cond *cond,
+               uint32_t timeout_ms)
+{
+       condtime->tv_sec = timeout_ms / 1000;
+       condtime->tv_nsec = (timeout_ms % 1000) * 1000000;
+
+#ifdef HAVE_CLOCK_GETTIME
+       struct timespec now;
+       int ret = clock_gettime(cond->clk_id, &now);
+       assert(ret == 0);
+       (void)ret;
+
+       condtime->tv_sec += now.tv_sec;
+       condtime->tv_nsec += now.tv_nsec;
+#else
+       (void)cond;
+
+       struct timeval now;
+       gettimeofday(&now, NULL);
+
+       condtime->tv_sec += now.tv_sec;
+       condtime->tv_nsec += now.tv_usec * 1000L;
+#endif
+
+       // tv_nsec must stay in the range [0, 999_999_999].
+       if (condtime->tv_nsec >= 1000000000L) {
+               condtime->tv_nsec -= 1000000000L;
+               ++condtime->tv_sec;
+       }
+}
+
+
+#elif defined(MYTHREAD_WIN95) || defined(MYTHREAD_VISTA)
+
+/////////////////////
+// Windows threads //
+/////////////////////
+
+#define WIN32_LEAN_AND_MEAN
+#ifdef MYTHREAD_VISTA
+#      undef _WIN32_WINNT
+#      define _WIN32_WINNT 0x0600
+#endif
+#include <windows.h>
+#include <process.h>
+
+#define MYTHREAD_RET_TYPE unsigned int __stdcall
+#define MYTHREAD_RET_VALUE 0
+
+typedef HANDLE mythread;
+typedef CRITICAL_SECTION mythread_mutex;
+
+#ifdef MYTHREAD_WIN95
+typedef HANDLE mythread_cond;
+#else
+typedef CONDITION_VARIABLE mythread_cond;
+#endif
+
+typedef struct {
+       // Tick count (milliseconds) in the beginning of the timeout.
+       // NOTE: This is 32 bits so it wraps around after 49.7 days.
+       // Multi-day timeouts may not work as expected.
+       DWORD start;
+
+       // Length of the timeout in milliseconds. The timeout expires
+       // when the current tick count minus "start" is equal or greater
+       // than "timeout".
+       DWORD timeout;
+} mythread_condtime;
+
+
+// mythread_once() is only available with Vista threads.
+#ifdef MYTHREAD_VISTA
+#define mythread_once(func) \
+       do { \
+               static INIT_ONCE once_ = INIT_ONCE_STATIC_INIT; \
+               BOOL pending_; \
+               if (!InitOnceBeginInitialize(&once_, 0, &pending_, NULL)) \
+                       abort(); \
+               if (pending_) \
+                       func(); \
+               if (!InitOnceComplete(&once, 0, NULL)) \
+                       abort(); \
+       } while (0)
+#endif
+
+
+// mythread_sigmask() isn't available on Windows. Even a dummy version would
+// make no sense because the other POSIX signal functions are missing anyway.
+
+
+static inline int
+mythread_create(mythread *thread,
+               unsigned int (__stdcall *func)(void *arg), void *arg)
+{
+       uintptr_t ret = _beginthreadex(NULL, 0, func, arg, 0, NULL);
+       if (ret == 0)
+               return -1;
+
+       *thread = (HANDLE)ret;
+       return 0;
+}
+
+static inline int
+mythread_join(mythread thread)
+{
+       int ret = 0;
+
+       if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0)
+               ret = -1;
+
+       if (!CloseHandle(thread))
+               ret = -1;
+
+       return ret;
+}
+
+
+static inline int
+mythread_mutex_init(mythread_mutex *mutex)
+{
+       InitializeCriticalSection(mutex);
+       return 0;
+}
+
+static inline void
+mythread_mutex_destroy(mythread_mutex *mutex)
+{
+       DeleteCriticalSection(mutex);
+}
+
+static inline void
+mythread_mutex_lock(mythread_mutex *mutex)
+{
+       EnterCriticalSection(mutex);
+}
+
+static inline void
+mythread_mutex_unlock(mythread_mutex *mutex)
+{
+       LeaveCriticalSection(mutex);
+}
+
+
+static inline int
+mythread_cond_init(mythread_cond *cond)
+{
+#ifdef MYTHREAD_WIN95
+       *cond = CreateEvent(NULL, FALSE, FALSE, NULL);
+       return *cond == NULL ? -1 : 0;
+#else
+       InitializeConditionVariable(cond);
+       return 0;
+#endif
+}
+
+static inline void
+mythread_cond_destroy(mythread_cond *cond)
+{
+#ifdef MYTHREAD_WIN95
+       CloseHandle(*cond);
+#else
+       (void)cond;
+#endif
+}
+
+static inline void
+mythread_cond_signal(mythread_cond *cond)
+{
+#ifdef MYTHREAD_WIN95
+       SetEvent(*cond);
+#else
+       WakeConditionVariable(cond);
+#endif
+}
+
+static inline void
+mythread_cond_wait(mythread_cond *cond, mythread_mutex *mutex)
+{
+#ifdef MYTHREAD_WIN95
+       LeaveCriticalSection(mutex);
+       WaitForSingleObject(*cond, INFINITE);
+       EnterCriticalSection(mutex);
+#else
+       BOOL ret = SleepConditionVariableCS(cond, mutex, INFINITE);
+       assert(ret);
+       (void)ret;
+#endif
+}
+
+static inline int
+mythread_cond_timedwait(mythread_cond *cond, mythread_mutex *mutex,
+               const mythread_condtime *condtime)
+{
+#ifdef MYTHREAD_WIN95
+       LeaveCriticalSection(mutex);
+#endif
+
+       DWORD elapsed = GetTickCount() - condtime->start;
+       DWORD timeout = elapsed >= condtime->timeout
+                       ? 0 : condtime->timeout - elapsed;
+
+#ifdef MYTHREAD_WIN95
+       DWORD ret = WaitForSingleObject(*cond, timeout);
+       assert(ret == WAIT_OBJECT_0 || ret == WAIT_TIMEOUT);
+
+       EnterCriticalSection(mutex);
+
+       return ret == WAIT_TIMEOUT;
+#else
+       BOOL ret = SleepConditionVariableCS(cond, mutex, timeout);
+       assert(ret || GetLastError() == ERROR_TIMEOUT);
+       return !ret;
+#endif
+}
+
+static inline void
+mythread_condtime_set(mythread_condtime *condtime, const mythread_cond *cond,
+               uint32_t timeout)
+{
+       (void)cond;
+       condtime->start = GetTickCount();
+       condtime->timeout = timeout;
+}
+
+#endif
+
+#endif
diff --git a/lzma/tuklib/tuklib_common.h b/lzma/tuklib/tuklib_common.h
new file mode 100644 (file)
index 0000000..31fbab5
--- /dev/null
@@ -0,0 +1,71 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       tuklib_common.h
+/// \brief      Common definitions for tuklib modules
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef TUKLIB_COMMON_H
+#define TUKLIB_COMMON_H
+
+// The config file may be replaced by a package-specific file.
+// It should include at least stddef.h, inttypes.h, and limits.h.
+#include "tuklib_config.h"
+
+// TUKLIB_SYMBOL_PREFIX is prefixed to all symbols exported by
+// the tuklib modules. If you use a tuklib module in a library,
+// you should use TUKLIB_SYMBOL_PREFIX to make sure that there
+// are no symbol conflicts in case someone links your library
+// into application that also uses the same tuklib module.
+#ifndef TUKLIB_SYMBOL_PREFIX
+#      define TUKLIB_SYMBOL_PREFIX
+#endif
+
+#define TUKLIB_CAT_X(a, b) a ## b
+#define TUKLIB_CAT(a, b) TUKLIB_CAT_X(a, b)
+
+#ifndef TUKLIB_SYMBOL
+#      define TUKLIB_SYMBOL(sym) TUKLIB_CAT(TUKLIB_SYMBOL_PREFIX, sym)
+#endif
+
+#ifndef TUKLIB_DECLS_BEGIN
+#      ifdef __cplusplus
+#              define TUKLIB_DECLS_BEGIN extern "C" {
+#      else
+#              define TUKLIB_DECLS_BEGIN
+#      endif
+#endif
+
+#ifndef TUKLIB_DECLS_END
+#      ifdef __cplusplus
+#              define TUKLIB_DECLS_END }
+#      else
+#              define TUKLIB_DECLS_END
+#      endif
+#endif
+
+#if defined(__GNUC__) && defined(__GNUC_MINOR__)
+#      define TUKLIB_GNUC_REQ(major, minor) \
+               ((__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)) \
+                       || __GNUC__ > (major))
+#else
+#      define TUKLIB_GNUC_REQ(major, minor) 0
+#endif
+
+#if TUKLIB_GNUC_REQ(2, 5)
+#      define tuklib_attr_noreturn __attribute__((__noreturn__))
+#else
+#      define tuklib_attr_noreturn
+#endif
+
+#if (defined(_WIN32) && !defined(__CYGWIN__)) \
+               || defined(__OS2__) || defined(__MSDOS__)
+#      define TUKLIB_DOSLIKE 1
+#endif
+
+#endif
diff --git a/lzma/tuklib/tuklib_config.h b/lzma/tuklib/tuklib_config.h
new file mode 100644 (file)
index 0000000..549cb24
--- /dev/null
@@ -0,0 +1,7 @@
+#ifdef HAVE_CONFIG_H
+#      include "sysdefs.h"
+#else
+#      include <stddef.h>
+#      include <inttypes.h>
+#      include <limits.h>
+#endif
diff --git a/lzma/tuklib/tuklib_cpucores.h b/lzma/tuklib/tuklib_cpucores.h
new file mode 100644 (file)
index 0000000..be1ce1c
--- /dev/null
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       tuklib_cpucores.h
+/// \brief      Get the number of CPU cores online
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef TUKLIB_CPUCORES_H
+#define TUKLIB_CPUCORES_H
+
+#include "tuklib_common.h"
+TUKLIB_DECLS_BEGIN
+
+#define tuklib_cpucores TUKLIB_SYMBOL(tuklib_cpucores)
+extern uint32_t tuklib_cpucores(void);
+
+TUKLIB_DECLS_END
+#endif
diff --git a/lzma/tuklib/tuklib_integer.h b/lzma/tuklib/tuklib_integer.h
new file mode 100644 (file)
index 0000000..a7fda67
--- /dev/null
@@ -0,0 +1,523 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       tuklib_integer.h
+/// \brief      Various integer and bit operations
+///
+/// This file provides macros or functions to do some basic integer and bit
+/// operations.
+///
+/// Endianness related integer operations (XX = 16, 32, or 64; Y = b or l):
+///   - Byte swapping: bswapXX(num)
+///   - Byte order conversions to/from native: convXXYe(num)
+///   - Aligned reads: readXXYe(ptr)
+///   - Aligned writes: writeXXYe(ptr, num)
+///   - Unaligned reads (16/32-bit only): unaligned_readXXYe(ptr)
+///   - Unaligned writes (16/32-bit only): unaligned_writeXXYe(ptr, num)
+///
+/// Since they can macros, the arguments should have no side effects since
+/// they may be evaluated more than once.
+///
+/// \todo       PowerPC and possibly some other architectures support
+///             byte swapping load and store instructions. This file
+///             doesn't take advantage of those instructions.
+///
+/// Bit scan operations for non-zero 32-bit integers:
+///   - Bit scan reverse (find highest non-zero bit): bsr32(num)
+///   - Count leading zeros: clz32(num)
+///   - Count trailing zeros: ctz32(num)
+///   - Bit scan forward (simply an alias for ctz32()): bsf32(num)
+///
+/// The above bit scan operations return 0-31. If num is zero,
+/// the result is undefined.
+//
+//  Authors:    Lasse Collin
+//              Joachim Henke
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef TUKLIB_INTEGER_H
+#define TUKLIB_INTEGER_H
+
+#include "tuklib_common.h"
+
+
+////////////////////////////////////////
+// Operating system specific features //
+////////////////////////////////////////
+
+#if defined(HAVE_BYTESWAP_H)
+       // glibc, uClibc, dietlibc
+#      include <byteswap.h>
+#      ifdef HAVE_BSWAP_16
+#              define bswap16(num) bswap_16(num)
+#      endif
+#      ifdef HAVE_BSWAP_32
+#              define bswap32(num) bswap_32(num)
+#      endif
+#      ifdef HAVE_BSWAP_64
+#              define bswap64(num) bswap_64(num)
+#      endif
+
+#elif defined(HAVE_SYS_ENDIAN_H)
+       // *BSDs and Darwin
+#      include <sys/endian.h>
+
+#elif defined(HAVE_SYS_BYTEORDER_H)
+       // Solaris
+#      include <sys/byteorder.h>
+#      ifdef BSWAP_16
+#              define bswap16(num) BSWAP_16(num)
+#      endif
+#      ifdef BSWAP_32
+#              define bswap32(num) BSWAP_32(num)
+#      endif
+#      ifdef BSWAP_64
+#              define bswap64(num) BSWAP_64(num)
+#      endif
+#      ifdef BE_16
+#              define conv16be(num) BE_16(num)
+#      endif
+#      ifdef BE_32
+#              define conv32be(num) BE_32(num)
+#      endif
+#      ifdef BE_64
+#              define conv64be(num) BE_64(num)
+#      endif
+#      ifdef LE_16
+#              define conv16le(num) LE_16(num)
+#      endif
+#      ifdef LE_32
+#              define conv32le(num) LE_32(num)
+#      endif
+#      ifdef LE_64
+#              define conv64le(num) LE_64(num)
+#      endif
+#endif
+
+
+///////////////////
+// Byte swapping //
+///////////////////
+
+#ifndef bswap16
+#      define bswap16(num) \
+               (((uint16_t)(num) << 8) | ((uint16_t)(num) >> 8))
+#endif
+
+#ifndef bswap32
+#      define bswap32(num) \
+               ( (((uint32_t)(num) << 24)                       ) \
+               | (((uint32_t)(num) <<  8) & UINT32_C(0x00FF0000)) \
+               | (((uint32_t)(num) >>  8) & UINT32_C(0x0000FF00)) \
+               | (((uint32_t)(num) >> 24)                       ) )
+#endif
+
+#ifndef bswap64
+#      define bswap64(num) \
+               ( (((uint64_t)(num) << 56)                               ) \
+               | (((uint64_t)(num) << 40) & UINT64_C(0x00FF000000000000)) \
+               | (((uint64_t)(num) << 24) & UINT64_C(0x0000FF0000000000)) \
+               | (((uint64_t)(num) <<  8) & UINT64_C(0x000000FF00000000)) \
+               | (((uint64_t)(num) >>  8) & UINT64_C(0x00000000FF000000)) \
+               | (((uint64_t)(num) >> 24) & UINT64_C(0x0000000000FF0000)) \
+               | (((uint64_t)(num) >> 40) & UINT64_C(0x000000000000FF00)) \
+               | (((uint64_t)(num) >> 56)                               ) )
+#endif
+
+// Define conversion macros using the basic byte swapping macros.
+#ifdef WORDS_BIGENDIAN
+#      ifndef conv16be
+#              define conv16be(num) ((uint16_t)(num))
+#      endif
+#      ifndef conv32be
+#              define conv32be(num) ((uint32_t)(num))
+#      endif
+#      ifndef conv64be
+#              define conv64be(num) ((uint64_t)(num))
+#      endif
+#      ifndef conv16le
+#              define conv16le(num) bswap16(num)
+#      endif
+#      ifndef conv32le
+#              define conv32le(num) bswap32(num)
+#      endif
+#      ifndef conv64le
+#              define conv64le(num) bswap64(num)
+#      endif
+#else
+#      ifndef conv16be
+#              define conv16be(num) bswap16(num)
+#      endif
+#      ifndef conv32be
+#              define conv32be(num) bswap32(num)
+#      endif
+#      ifndef conv64be
+#              define conv64be(num) bswap64(num)
+#      endif
+#      ifndef conv16le
+#              define conv16le(num) ((uint16_t)(num))
+#      endif
+#      ifndef conv32le
+#              define conv32le(num) ((uint32_t)(num))
+#      endif
+#      ifndef conv64le
+#              define conv64le(num) ((uint64_t)(num))
+#      endif
+#endif
+
+
+//////////////////////////////
+// Aligned reads and writes //
+//////////////////////////////
+
+static inline uint16_t
+read16be(const uint8_t *buf)
+{
+       uint16_t num = *(const uint16_t *)buf;
+       return conv16be(num);
+}
+
+
+static inline uint16_t
+read16le(const uint8_t *buf)
+{
+       uint16_t num = *(const uint16_t *)buf;
+       return conv16le(num);
+}
+
+
+static inline uint32_t
+read32be(const uint8_t *buf)
+{
+       uint32_t num = *(const uint32_t *)buf;
+       return conv32be(num);
+}
+
+
+static inline uint32_t
+read32le(const uint8_t *buf)
+{
+       uint32_t num = *(const uint32_t *)buf;
+       return conv32le(num);
+}
+
+
+static inline uint64_t
+read64be(const uint8_t *buf)
+{
+       uint64_t num = *(const uint64_t *)buf;
+       return conv64be(num);
+}
+
+
+static inline uint64_t
+read64le(const uint8_t *buf)
+{
+       uint64_t num = *(const uint64_t *)buf;
+       return conv64le(num);
+}
+
+
+// NOTE: Possible byte swapping must be done in a macro to allow GCC
+// to optimize byte swapping of constants when using glibc's or *BSD's
+// byte swapping macros. The actual write is done in an inline function
+// to make type checking of the buf pointer possible similarly to readXXYe()
+// functions.
+
+#define write16be(buf, num) write16ne((buf), conv16be(num))
+#define write16le(buf, num) write16ne((buf), conv16le(num))
+#define write32be(buf, num) write32ne((buf), conv32be(num))
+#define write32le(buf, num) write32ne((buf), conv32le(num))
+#define write64be(buf, num) write64ne((buf), conv64be(num))
+#define write64le(buf, num) write64ne((buf), conv64le(num))
+
+
+static inline void
+write16ne(uint8_t *buf, uint16_t num)
+{
+       *(uint16_t *)buf = num;
+       return;
+}
+
+
+static inline void
+write32ne(uint8_t *buf, uint32_t num)
+{
+       *(uint32_t *)buf = num;
+       return;
+}
+
+
+static inline void
+write64ne(uint8_t *buf, uint64_t num)
+{
+       *(uint64_t *)buf = num;
+       return;
+}
+
+
+////////////////////////////////
+// Unaligned reads and writes //
+////////////////////////////////
+
+// NOTE: TUKLIB_FAST_UNALIGNED_ACCESS indicates only support for 16-bit and
+// 32-bit unaligned integer loads and stores. It's possible that 64-bit
+// unaligned access doesn't work or is slower than byte-by-byte access.
+// Since unaligned 64-bit is probably not needed as often as 16-bit or
+// 32-bit, we simply don't support 64-bit unaligned access for now.
+#ifdef TUKLIB_FAST_UNALIGNED_ACCESS
+#      define unaligned_read16be read16be
+#      define unaligned_read16le read16le
+#      define unaligned_read32be read32be
+#      define unaligned_read32le read32le
+#      define unaligned_write16be write16be
+#      define unaligned_write16le write16le
+#      define unaligned_write32be write32be
+#      define unaligned_write32le write32le
+
+#else
+
+static inline uint16_t
+unaligned_read16be(const uint8_t *buf)
+{
+       uint16_t num = ((uint16_t)buf[0] << 8) | (uint16_t)buf[1];
+       return num;
+}
+
+
+static inline uint16_t
+unaligned_read16le(const uint8_t *buf)
+{
+       uint16_t num = ((uint16_t)buf[0]) | ((uint16_t)buf[1] << 8);
+       return num;
+}
+
+
+static inline uint32_t
+unaligned_read32be(const uint8_t *buf)
+{
+       uint32_t num = (uint32_t)buf[0] << 24;
+       num |= (uint32_t)buf[1] << 16;
+       num |= (uint32_t)buf[2] << 8;
+       num |= (uint32_t)buf[3];
+       return num;
+}
+
+
+static inline uint32_t
+unaligned_read32le(const uint8_t *buf)
+{
+       uint32_t num = (uint32_t)buf[0];
+       num |= (uint32_t)buf[1] << 8;
+       num |= (uint32_t)buf[2] << 16;
+       num |= (uint32_t)buf[3] << 24;
+       return num;
+}
+
+
+static inline void
+unaligned_write16be(uint8_t *buf, uint16_t num)
+{
+       buf[0] = (uint8_t)(num >> 8);
+       buf[1] = (uint8_t)num;
+       return;
+}
+
+
+static inline void
+unaligned_write16le(uint8_t *buf, uint16_t num)
+{
+       buf[0] = (uint8_t)num;
+       buf[1] = (uint8_t)(num >> 8);
+       return;
+}
+
+
+static inline void
+unaligned_write32be(uint8_t *buf, uint32_t num)
+{
+       buf[0] = (uint8_t)(num >> 24);
+       buf[1] = (uint8_t)(num >> 16);
+       buf[2] = (uint8_t)(num >> 8);
+       buf[3] = (uint8_t)num;
+       return;
+}
+
+
+static inline void
+unaligned_write32le(uint8_t *buf, uint32_t num)
+{
+       buf[0] = (uint8_t)num;
+       buf[1] = (uint8_t)(num >> 8);
+       buf[2] = (uint8_t)(num >> 16);
+       buf[3] = (uint8_t)(num >> 24);
+       return;
+}
+
+#endif
+
+
+static inline uint32_t
+bsr32(uint32_t n)
+{
+       // Check for ICC first, since it tends to define __GNUC__ too.
+#if defined(__INTEL_COMPILER)
+       return _bit_scan_reverse(n);
+
+#elif TUKLIB_GNUC_REQ(3, 4) && UINT_MAX == UINT32_MAX
+       // GCC >= 3.4 has __builtin_clz(), which gives good results on
+       // multiple architectures. On x86, __builtin_clz() ^ 31U becomes
+       // either plain BSR (so the XOR gets optimized away) or LZCNT and
+       // XOR (if -march indicates that SSE4a instructions are supported).
+       return __builtin_clz(n) ^ 31U;
+
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+       uint32_t i;
+       __asm__("bsrl %1, %0" : "=r" (i) : "rm" (n));
+       return i;
+
+#elif defined(_MSC_VER) && _MSC_VER >= 1400
+       // MSVC isn't supported by tuklib, but since this code exists,
+       // it doesn't hurt to have it here anyway.
+       uint32_t i;
+       _BitScanReverse((DWORD *)&i, n);
+       return i;
+
+#else
+       uint32_t i = 31;
+
+       if ((n & UINT32_C(0xFFFF0000)) == 0) {
+               n <<= 16;
+               i = 15;
+       }
+
+       if ((n & UINT32_C(0xFF000000)) == 0) {
+               n <<= 8;
+               i -= 8;
+       }
+
+       if ((n & UINT32_C(0xF0000000)) == 0) {
+               n <<= 4;
+               i -= 4;
+       }
+
+       if ((n & UINT32_C(0xC0000000)) == 0) {
+               n <<= 2;
+               i -= 2;
+       }
+
+       if ((n & UINT32_C(0x80000000)) == 0)
+               --i;
+
+       return i;
+#endif
+}
+
+
+static inline uint32_t
+clz32(uint32_t n)
+{
+#if defined(__INTEL_COMPILER)
+       return _bit_scan_reverse(n) ^ 31U;
+
+#elif TUKLIB_GNUC_REQ(3, 4) && UINT_MAX == UINT32_MAX
+       return __builtin_clz(n);
+
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+       uint32_t i;
+       __asm__("bsrl %1, %0\n\t"
+               "xorl $31, %0"
+               : "=r" (i) : "rm" (n));
+       return i;
+
+#elif defined(_MSC_VER) && _MSC_VER >= 1400
+       uint32_t i;
+       _BitScanReverse((DWORD *)&i, n);
+       return i ^ 31U;
+
+#else
+       uint32_t i = 0;
+
+       if ((n & UINT32_C(0xFFFF0000)) == 0) {
+               n <<= 16;
+               i = 16;
+       }
+
+       if ((n & UINT32_C(0xFF000000)) == 0) {
+               n <<= 8;
+               i += 8;
+       }
+
+       if ((n & UINT32_C(0xF0000000)) == 0) {
+               n <<= 4;
+               i += 4;
+       }
+
+       if ((n & UINT32_C(0xC0000000)) == 0) {
+               n <<= 2;
+               i += 2;
+       }
+
+       if ((n & UINT32_C(0x80000000)) == 0)
+               ++i;
+
+       return i;
+#endif
+}
+
+
+static inline uint32_t
+ctz32(uint32_t n)
+{
+#if defined(__INTEL_COMPILER)
+       return _bit_scan_forward(n);
+
+#elif TUKLIB_GNUC_REQ(3, 4) && UINT_MAX >= UINT32_MAX
+       return __builtin_ctz(n);
+
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+       uint32_t i;
+       __asm__("bsfl %1, %0" : "=r" (i) : "rm" (n));
+       return i;
+
+#elif defined(_MSC_VER) && _MSC_VER >= 1400
+       uint32_t i;
+       _BitScanForward((DWORD *)&i, n);
+       return i;
+
+#else
+       uint32_t i = 0;
+
+       if ((n & UINT32_C(0x0000FFFF)) == 0) {
+               n >>= 16;
+               i = 16;
+       }
+
+       if ((n & UINT32_C(0x000000FF)) == 0) {
+               n >>= 8;
+               i += 8;
+       }
+
+       if ((n & UINT32_C(0x0000000F)) == 0) {
+               n >>= 4;
+               i += 4;
+       }
+
+       if ((n & UINT32_C(0x00000003)) == 0) {
+               n >>= 2;
+               i += 2;
+       }
+
+       if ((n & UINT32_C(0x00000001)) == 0)
+               ++i;
+
+       return i;
+#endif
+}
+
+#define bsf32 ctz32
+
+#endif
diff --git a/lzma/tuklib/tuklib_physmem.h b/lzma/tuklib/tuklib_physmem.h
new file mode 100644 (file)
index 0000000..09e2a51
--- /dev/null
@@ -0,0 +1,28 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       tuklib_physmem.h
+/// \brief      Get the amount of physical memory
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef TUKLIB_PHYSMEM_H
+#define TUKLIB_PHYSMEM_H
+
+#include "tuklib_common.h"
+TUKLIB_DECLS_BEGIN
+
+#define tuklib_physmem TUKLIB_SYMBOL(tuklib_physmem)
+extern uint64_t tuklib_physmem(void);
+///<
+/// \brief      Get the amount of physical memory in bytes
+///
+/// \return     Amount of physical memory in bytes. On error, zero is
+///             returned.
+
+TUKLIB_DECLS_END
+#endif