mirror of
https://github.com/Kitware/CMake.git
synced 2026-02-16 12:11:04 -06:00
liblzma 2018-04-29 (b5be61cc)
Code extracted from:
https://git.tukaani.org/xz.git
at commit b5be61cc06088bb07f488f9baf7d447ff47b37c1 (v5.2.4).
This commit is contained in:
committed by
Brad King
parent
897b790d57
commit
352b8fa70d
2
COPYING
2
COPYING
@@ -47,7 +47,7 @@ XZ Utils Licensing
|
||||
naturally it is not legally required. Here is an example of a good
|
||||
notice to put into "about box" or into documentation:
|
||||
|
||||
This software includes code from XZ Utils <http://tukaani.org/xz/>.
|
||||
This software includes code from XZ Utils <https://tukaani.org/xz/>.
|
||||
|
||||
The following license texts are included in the following files:
|
||||
- COPYING.LGPLv2.1: GNU Lesser General Public License version 2.1
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#define MY_VERSION LZMA_VERSION_MAJOR,LZMA_VERSION_MINOR,LZMA_VERSION_PATCH,MY_BUILD
|
||||
|
||||
#define MY_FILENAME MY_NAME MY_SUFFIX
|
||||
#define MY_COMPANY "The Tukaani Project <http://tukaani.org/>"
|
||||
#define MY_COMPANY "The Tukaani Project <https://tukaani.org/>"
|
||||
#define MY_PRODUCT PACKAGE_NAME " <" PACKAGE_URL ">"
|
||||
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
@@ -165,6 +165,16 @@ typedef unsigned char _Bool;
|
||||
# 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 //
|
||||
|
||||
@@ -98,6 +98,17 @@
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
// Compiler-specific features //
|
||||
////////////////////////////////
|
||||
|
||||
// Newer Intel C compilers require immintrin.h for _bit_scan_reverse()
|
||||
// and such functions.
|
||||
#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1500)
|
||||
# include <immintrin.h>
|
||||
#endif
|
||||
|
||||
|
||||
///////////////////
|
||||
// Byte swapping //
|
||||
///////////////////
|
||||
@@ -321,8 +332,8 @@ unaligned_read32le(const uint8_t *buf)
|
||||
static inline void
|
||||
unaligned_write16be(uint8_t *buf, uint16_t num)
|
||||
{
|
||||
buf[0] = num >> 8;
|
||||
buf[1] = num;
|
||||
buf[0] = (uint8_t)(num >> 8);
|
||||
buf[1] = (uint8_t)num;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -330,8 +341,8 @@ unaligned_write16be(uint8_t *buf, uint16_t num)
|
||||
static inline void
|
||||
unaligned_write16le(uint8_t *buf, uint16_t num)
|
||||
{
|
||||
buf[0] = num;
|
||||
buf[1] = num >> 8;
|
||||
buf[0] = (uint8_t)num;
|
||||
buf[1] = (uint8_t)(num >> 8);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -339,10 +350,10 @@ unaligned_write16le(uint8_t *buf, uint16_t num)
|
||||
static inline void
|
||||
unaligned_write32be(uint8_t *buf, uint32_t num)
|
||||
{
|
||||
buf[0] = num >> 24;
|
||||
buf[1] = num >> 16;
|
||||
buf[2] = num >> 8;
|
||||
buf[3] = 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;
|
||||
}
|
||||
|
||||
@@ -350,10 +361,10 @@ unaligned_write32be(uint8_t *buf, uint32_t num)
|
||||
static inline void
|
||||
unaligned_write32le(uint8_t *buf, uint32_t num)
|
||||
{
|
||||
buf[0] = num;
|
||||
buf[1] = num >> 8;
|
||||
buf[2] = num >> 16;
|
||||
buf[3] = num >> 24;
|
||||
buf[0] = (uint8_t)num;
|
||||
buf[1] = (uint8_t)(num >> 8);
|
||||
buf[2] = (uint8_t)(num >> 16);
|
||||
buf[3] = (uint8_t)(num >> 24);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -82,12 +82,20 @@
|
||||
# if !defined(UINT32_C) || !defined(UINT64_C) \
|
||||
|| !defined(UINT32_MAX) || !defined(UINT64_MAX)
|
||||
/*
|
||||
* MSVC has no C99 support, and thus it cannot be used to
|
||||
* compile liblzma. The liblzma API has to still be usable
|
||||
* from MSVC, so we need to define the required standard
|
||||
* integer types here.
|
||||
* 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)
|
||||
# if defined(_WIN32) && defined(_MSC_VER) && _MSC_VER < 1800
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
@@ -211,7 +219,11 @@
|
||||
*/
|
||||
#ifndef lzma_nothrow
|
||||
# if defined(__cplusplus)
|
||||
# define lzma_nothrow throw()
|
||||
# if __cplusplus >= 201103L
|
||||
# define lzma_nothrow noexcept
|
||||
# else
|
||||
# define lzma_nothrow throw()
|
||||
# endif
|
||||
# elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
|
||||
# define lzma_nothrow __attribute__((__nothrow__))
|
||||
# else
|
||||
@@ -286,7 +298,7 @@ extern "C" {
|
||||
#include "lzma/filter.h"
|
||||
#include "lzma/bcj.h"
|
||||
#include "lzma/delta.h"
|
||||
#include "lzma/lzma.h"
|
||||
#include "lzma/lzma12.h"
|
||||
|
||||
/* Container formats */
|
||||
#include "lzma/container.h"
|
||||
|
||||
@@ -240,12 +240,12 @@ typedef enum {
|
||||
/**
|
||||
* \brief The `action' argument for lzma_code()
|
||||
*
|
||||
* After the first use of LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, or LZMA_FINISH,
|
||||
* the same `action' must is used until lzma_code() returns LZMA_STREAM_END.
|
||||
* Also, the amount of input (that is, strm->avail_in) must not be modified
|
||||
* by the application until lzma_code() returns LZMA_STREAM_END. Changing the
|
||||
* `action' or modifying the amount of input will make lzma_code() return
|
||||
* LZMA_PROG_ERROR.
|
||||
* 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,
|
||||
@@ -293,7 +293,7 @@ typedef enum {
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
@@ -302,6 +302,29 @@ typedef enum {
|
||||
* 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
|
||||
@@ -332,11 +355,19 @@ typedef enum {
|
||||
* malloc() and free(). C++ users should note that the custom memory
|
||||
* handling functions must not throw exceptions.
|
||||
*
|
||||
* 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).
|
||||
* 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 {
|
||||
/**
|
||||
@@ -448,7 +479,8 @@ typedef struct lzma_internal_s lzma_internal;
|
||||
*
|
||||
* 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.
|
||||
* 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. */
|
||||
@@ -464,8 +496,10 @@ typedef struct {
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
lzma_allocator *allocator;
|
||||
const lzma_allocator *allocator;
|
||||
|
||||
/** Internal state is not visible to applications. */
|
||||
lzma_internal *internal;
|
||||
@@ -546,6 +580,25 @@ extern LZMA_API(lzma_ret) lzma_code(lzma_stream *strm, lzma_action action)
|
||||
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
|
||||
*
|
||||
@@ -591,11 +644,16 @@ extern LZMA_API(uint64_t) lzma_memlimit_get(const lzma_stream *strm)
|
||||
* This function is supported only when *strm has been initialized with
|
||||
* a function that takes a memlimit argument.
|
||||
*
|
||||
* liblzma 5.2.3 and earlier has a bug where memlimit value of 0 causes
|
||||
* this function to do nothing (leaving the limit unchanged) and still
|
||||
* return LZMA_OK. Later versions treat 0 as if 1 had been specified (so
|
||||
* lzma_memlimit_get() will return 1 even if you specify 0 here).
|
||||
*
|
||||
* \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.
|
||||
* support memory usage limit.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_memlimit_set(
|
||||
lzma_stream *strm, uint64_t memlimit) lzma_nothrow;
|
||||
|
||||
@@ -31,11 +31,16 @@ typedef struct {
|
||||
/**
|
||||
* \brief Block format version
|
||||
*
|
||||
* To prevent API and ABI breakages if new features are needed in
|
||||
* the Block field, 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, most Block related functions will
|
||||
* return LZMA_OPTIONS_ERROR.
|
||||
* 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,
|
||||
@@ -233,7 +238,28 @@ typedef struct {
|
||||
lzma_reserved_enum reserved_enum2;
|
||||
lzma_reserved_enum reserved_enum3;
|
||||
lzma_reserved_enum reserved_enum4;
|
||||
lzma_bool reserved_bool1;
|
||||
|
||||
/**
|
||||
* \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;
|
||||
@@ -310,10 +336,14 @@ extern LZMA_API(lzma_ret) lzma_block_header_encode(
|
||||
/**
|
||||
* \brief Decode Block Header
|
||||
*
|
||||
* block->version should be set to the highest value supported by the
|
||||
* application; currently the only possible version is zero. This function
|
||||
* will set version to the lowest value that still supports all the features
|
||||
* required by the 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.
|
||||
@@ -344,7 +374,7 @@ extern LZMA_API(lzma_ret) lzma_block_header_encode(
|
||||
* block->header_size is invalid or block->filters is NULL.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_block_header_decode(lzma_block *block,
|
||||
lzma_allocator *allocator, const uint8_t *in)
|
||||
const lzma_allocator *allocator, const uint8_t *in)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
@@ -493,7 +523,25 @@ extern LZMA_API(size_t) lzma_block_buffer_bound(size_t uncompressed_size)
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_block_buffer_encode(
|
||||
lzma_block *block, lzma_allocator *allocator,
|
||||
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;
|
||||
@@ -527,7 +575,7 @@ extern LZMA_API(lzma_ret) lzma_block_buffer_encode(
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_block_buffer_decode(
|
||||
lzma_block *block, lzma_allocator *allocator,
|
||||
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;
|
||||
|
||||
@@ -60,6 +60,131 @@
|
||||
#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
|
||||
*
|
||||
@@ -165,7 +290,8 @@ extern LZMA_API(lzma_ret) lzma_easy_encoder(
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_easy_buffer_encode(
|
||||
uint32_t preset, lzma_check check,
|
||||
lzma_allocator *allocator, const uint8_t *in, size_t in_size,
|
||||
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;
|
||||
|
||||
|
||||
@@ -190,6 +316,49 @@ extern LZMA_API(lzma_ret) lzma_stream_encoder(lzma_stream *strm,
|
||||
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)
|
||||
*
|
||||
@@ -269,7 +438,8 @@ extern LZMA_API(size_t) lzma_stream_buffer_bound(size_t uncompressed_size)
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_stream_buffer_encode(
|
||||
lzma_filter *filters, lzma_check check,
|
||||
lzma_allocator *allocator, const uint8_t *in, size_t in_size,
|
||||
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;
|
||||
|
||||
@@ -304,6 +474,30 @@ extern LZMA_API(lzma_ret) lzma_stream_buffer_encode(
|
||||
#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
|
||||
@@ -326,7 +520,10 @@ extern LZMA_API(lzma_ret) lzma_stream_buffer_encode(
|
||||
*
|
||||
* \param strm Pointer to properly prepared lzma_stream
|
||||
* \param memlimit Memory usage limit as bytes. Use UINT64_MAX
|
||||
* to effectively disable the limiter.
|
||||
* to effectively disable the limiter. liblzma
|
||||
* 5.2.3 and earlier don't allow 0 here and return
|
||||
* LZMA_PROG_ERROR; later versions treat 0 as if 1
|
||||
* had been specified.
|
||||
* \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
|
||||
@@ -350,7 +547,10 @@ extern LZMA_API(lzma_ret) lzma_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.
|
||||
* to effectively disable the limiter. liblzma
|
||||
* 5.2.3 and earlier don't allow 0 here and return
|
||||
* LZMA_PROG_ERROR; later versions treat 0 as if 1
|
||||
* had been specified.
|
||||
* \param flags Bitwise-or of flags, or zero for no flags.
|
||||
*
|
||||
* \return - LZMA_OK: Initialization was successful.
|
||||
@@ -366,9 +566,16 @@ extern LZMA_API(lzma_ret) lzma_auto_decoder(
|
||||
/**
|
||||
* \brief Initialize .lzma decoder (legacy file format)
|
||||
*
|
||||
* \param strm Pointer to properly prepared lzma_stream
|
||||
* \param memlimit Memory usage limit as bytes. Use UINT64_MAX
|
||||
* to effectively disable the limiter. liblzma
|
||||
* 5.2.3 and earlier don't allow 0 here and return
|
||||
* LZMA_PROG_ERROR; later versions treat 0 as if 1
|
||||
* had been specified.
|
||||
*
|
||||
* 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.
|
||||
* There is no need to use LZMA_FINISH, but it's allowed because it may
|
||||
* simplify certain types of applications.
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_MEM_ERROR
|
||||
@@ -418,7 +625,8 @@ extern LZMA_API(lzma_ret) lzma_alone_decoder(
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_stream_buffer_decode(
|
||||
uint64_t *memlimit, uint32_t flags, lzma_allocator *allocator,
|
||||
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;
|
||||
|
||||
@@ -116,8 +116,9 @@ extern LZMA_API(lzma_bool) lzma_filter_decoder_is_supported(lzma_vli id)
|
||||
* 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, lzma_allocator *allocator) lzma_nothrow;
|
||||
extern LZMA_API(lzma_ret) lzma_filters_copy(
|
||||
const lzma_filter *src, lzma_filter *dest,
|
||||
const lzma_allocator *allocator) lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
@@ -256,7 +257,7 @@ extern LZMA_API(lzma_ret) lzma_filters_update(
|
||||
* won't necessarily meet that bound.)
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_raw_buffer_encode(
|
||||
const lzma_filter *filters, lzma_allocator *allocator,
|
||||
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;
|
||||
|
||||
@@ -280,7 +281,7 @@ extern LZMA_API(lzma_ret) lzma_raw_buffer_encode(
|
||||
* which no data is written to is out[out_size].
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_raw_buffer_decode(
|
||||
const lzma_filter *filters, lzma_allocator *allocator,
|
||||
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;
|
||||
|
||||
@@ -356,7 +357,7 @@ extern LZMA_API(lzma_ret) lzma_properties_encode(
|
||||
* - LZMA_MEM_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_properties_decode(
|
||||
lzma_filter *filter, lzma_allocator *allocator,
|
||||
lzma_filter *filter, const lzma_allocator *allocator,
|
||||
const uint8_t *props, size_t props_size) lzma_nothrow;
|
||||
|
||||
|
||||
@@ -419,6 +420,6 @@ extern LZMA_API(lzma_ret) lzma_filter_flags_encode(const lzma_filter *filter,
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_filter_flags_decode(
|
||||
lzma_filter *filter, lzma_allocator *allocator,
|
||||
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;
|
||||
|
||||
@@ -48,3 +48,17 @@
|
||||
* 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;
|
||||
|
||||
@@ -303,7 +303,7 @@ extern LZMA_API(uint64_t) lzma_index_memused(const lzma_index *i)
|
||||
* \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(lzma_allocator *allocator)
|
||||
extern LZMA_API(lzma_index *) lzma_index_init(const lzma_allocator *allocator)
|
||||
lzma_nothrow;
|
||||
|
||||
|
||||
@@ -312,8 +312,8 @@ extern LZMA_API(lzma_index *) lzma_index_init(lzma_allocator *allocator)
|
||||
*
|
||||
* If i is NULL, this does nothing.
|
||||
*/
|
||||
extern LZMA_API(void) lzma_index_end(lzma_index *i, lzma_allocator *allocator)
|
||||
lzma_nothrow;
|
||||
extern LZMA_API(void) lzma_index_end(
|
||||
lzma_index *i, const lzma_allocator *allocator) lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
@@ -341,7 +341,7 @@ extern LZMA_API(void) lzma_index_end(lzma_index *i, lzma_allocator *allocator)
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_index_append(
|
||||
lzma_index *i, lzma_allocator *allocator,
|
||||
lzma_index *i, const lzma_allocator *allocator,
|
||||
lzma_vli unpadded_size, lzma_vli uncompressed_size)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
@@ -564,8 +564,8 @@ extern LZMA_API(lzma_bool) lzma_index_iter_locate(
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_index_cat(
|
||||
lzma_index *dest, lzma_index *src, lzma_allocator *allocator)
|
||||
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;
|
||||
|
||||
|
||||
@@ -575,7 +575,7 @@ extern LZMA_API(lzma_ret) lzma_index_cat(
|
||||
* \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, lzma_allocator *allocator)
|
||||
const lzma_index *i, const lzma_allocator *allocator)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
@@ -586,8 +586,7 @@ extern LZMA_API(lzma_index *) lzma_index_dup(
|
||||
* \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).
|
||||
* It is enough to use only one of them (you can choose freely).
|
||||
*
|
||||
* \return - LZMA_OK: Initialization succeeded, continue with lzma_code().
|
||||
* - LZMA_MEM_ERROR
|
||||
@@ -610,16 +609,21 @@ extern LZMA_API(lzma_ret) lzma_index_encoder(
|
||||
* 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.
|
||||
* allowed to require. liblzma 5.2.3 and earlier
|
||||
* don't allow 0 here and return LZMA_PROG_ERROR;
|
||||
* later versions treat 0 as if 1 had been specified.
|
||||
*
|
||||
* 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).
|
||||
* Valid `action' arguments to lzma_code() are LZMA_RUN and LZMA_FINISH.
|
||||
* There is no need to use LZMA_FINISH, but it's allowed because it may
|
||||
* simplify certain types of applications.
|
||||
*
|
||||
* \return - LZMA_OK: Initialization succeeded, continue with lzma_code().
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_MEMLIMIT_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*
|
||||
* liblzma 5.2.3 and older list also LZMA_MEMLIMIT_ERROR here
|
||||
* but that error code has never been possible from this
|
||||
* initialization function.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_index_decoder(
|
||||
lzma_stream *strm, lzma_index **i, uint64_t memlimit)
|
||||
@@ -677,6 +681,6 @@ extern LZMA_API(lzma_ret) lzma_index_buffer_encode(const lzma_index *i,
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_index_buffer_decode(lzma_index **i,
|
||||
uint64_t *memlimit, lzma_allocator *allocator,
|
||||
uint64_t *memlimit, const lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t *in_pos, size_t in_size)
|
||||
lzma_nothrow;
|
||||
|
||||
@@ -37,7 +37,7 @@ typedef struct lzma_index_hash_s lzma_index_hash;
|
||||
* 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, lzma_allocator *allocator)
|
||||
lzma_index_hash *index_hash, const lzma_allocator *allocator)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ extern LZMA_API(lzma_index_hash *) lzma_index_hash_init(
|
||||
* \brief Deallocate lzma_index_hash structure
|
||||
*/
|
||||
extern LZMA_API(void) lzma_index_hash_end(
|
||||
lzma_index_hash *index_hash, lzma_allocator *allocator)
|
||||
lzma_index_hash *index_hash, const lzma_allocator *allocator)
|
||||
lzma_nothrow;
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* \file lzma/lzma.h
|
||||
* \file lzma/lzma12.h
|
||||
* \brief LZMA1 and LZMA2 filters
|
||||
*/
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
* Version number split into components
|
||||
*/
|
||||
#define LZMA_VERSION_MAJOR 5
|
||||
#define LZMA_VERSION_MINOR 0
|
||||
#define LZMA_VERSION_PATCH 8
|
||||
#define LZMA_VERSION_MINOR 2
|
||||
#define LZMA_VERSION_PATCH 4
|
||||
#define LZMA_VERSION_STABILITY LZMA_VERSION_STABILITY_STABLE
|
||||
|
||||
#ifndef LZMA_VERSION_COMMIT
|
||||
|
||||
@@ -15,6 +15,53 @@
|
||||
|
||||
#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.
|
||||
@@ -43,14 +90,7 @@ typedef struct {
|
||||
union {
|
||||
uint32_t crc32;
|
||||
uint64_t crc64;
|
||||
|
||||
struct {
|
||||
/// Internal state
|
||||
uint32_t state[8];
|
||||
|
||||
/// Size of the message excluding padding
|
||||
uint64_t size;
|
||||
} sha256;
|
||||
lzma_sha256_state sha256;
|
||||
} state;
|
||||
|
||||
} lzma_check_state;
|
||||
@@ -82,6 +122,8 @@ extern void lzma_check_update(lzma_check_state *check, lzma_check type,
|
||||
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);
|
||||
|
||||
@@ -92,4 +134,39 @@ extern void lzma_sha256_update(
|
||||
/// 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
|
||||
|
||||
@@ -21,22 +21,22 @@
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Avoid bogus warnings in transform().
|
||||
#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 2) || __GNUC__ > 4
|
||||
# pragma GCC diagnostic ignored "-Wuninitialized"
|
||||
#endif
|
||||
|
||||
#include "check.h"
|
||||
|
||||
// At least on x86, GCC is able to optimize this to a rotate instruction.
|
||||
#define rotr_32(num, amount) ((num) >> (amount) | (num) << (32 - (amount)))
|
||||
// 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] = data[i])
|
||||
#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 & (x | y)))
|
||||
#define Maj(x, y, z) ((x & (y ^ z)) + (y & z))
|
||||
|
||||
#define a(i) T[(0 - i) & 7]
|
||||
#define b(i) T[(1 - i) & 7]
|
||||
@@ -47,16 +47,17 @@
|
||||
#define g(i) T[(6 - i) & 7]
|
||||
#define h(i) T[(7 - i) & 7]
|
||||
|
||||
#define R(i) \
|
||||
h(i) += S1(e(i)) + Ch(e(i), f(i), g(i)) + SHA256_K[i + j] \
|
||||
+ (j ? blk2(i) : blk0(i)); \
|
||||
#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, 2) ^ rotr_32(x, 13) ^ rotr_32(x, 22))
|
||||
#define S1(x) (rotr_32(x, 6) ^ rotr_32(x, 11) ^ rotr_32(x, 25))
|
||||
#define s0(x) (rotr_32(x, 7) ^ rotr_32(x, 18) ^ (x >> 3))
|
||||
#define s1(x) (rotr_32(x, 17) ^ rotr_32(x, 19) ^ (x >> 10))
|
||||
#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] = {
|
||||
@@ -88,12 +89,18 @@ transform(uint32_t state[8], const uint32_t data[16])
|
||||
// Copy state[] to working vars.
|
||||
memcpy(T, state, sizeof(T));
|
||||
|
||||
// 64 operations, partially loop unrolled
|
||||
for (unsigned int j = 0; j < 64; j += 16) {
|
||||
R( 0); R( 1); R( 2); R( 3);
|
||||
R( 4); R( 5); R( 6); R( 7);
|
||||
R( 8); R( 9); R(10); R(11);
|
||||
R(12); R(13); R(14); R(15);
|
||||
// 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[].
|
||||
@@ -111,18 +118,7 @@ transform(uint32_t state[8], const uint32_t data[16])
|
||||
static void
|
||||
process(lzma_check_state *check)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
transform(check->state.sha256.state, check->buffer.u32);
|
||||
|
||||
#else
|
||||
uint32_t data[16];
|
||||
|
||||
for (size_t i = 0; i < 16; ++i)
|
||||
data[i] = bswap32(check->buffer.u32[i]);
|
||||
|
||||
transform(check->state.sha256.state, data);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "lz_decoder.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
typedef struct {
|
||||
lzma_next_coder next;
|
||||
|
||||
enum {
|
||||
@@ -46,17 +46,19 @@ struct lzma_coder_s {
|
||||
/// Options decoded from the header needed to initialize
|
||||
/// the LZMA decoder
|
||||
lzma_options_lzma options;
|
||||
};
|
||||
} lzma_alone_coder;
|
||||
|
||||
|
||||
static lzma_ret
|
||||
alone_decode(lzma_coder *coder,
|
||||
lzma_allocator *allocator lzma_attribute((__unused__)),
|
||||
alone_decode(void *coder_ptr,
|
||||
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)
|
||||
{
|
||||
lzma_alone_coder *coder = coder_ptr;
|
||||
|
||||
while (*out_pos < out_size
|
||||
&& (coder->sequence == SEQ_CODE || *in_pos < in_size))
|
||||
switch (coder->sequence) {
|
||||
@@ -166,8 +168,9 @@ alone_decode(lzma_coder *coder,
|
||||
|
||||
|
||||
static void
|
||||
alone_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
alone_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_alone_coder *coder = coder_ptr;
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
@@ -175,9 +178,11 @@ alone_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
|
||||
|
||||
static lzma_ret
|
||||
alone_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
|
||||
alone_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
|
||||
uint64_t *old_memlimit, uint64_t new_memlimit)
|
||||
{
|
||||
lzma_alone_coder *coder = coder_ptr;
|
||||
|
||||
*memusage = coder->memusage;
|
||||
*old_memlimit = coder->memlimit;
|
||||
|
||||
@@ -193,34 +198,34 @@ alone_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_alone_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
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;
|
||||
lzma_alone_coder *coder = next->coder;
|
||||
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
if (coder == NULL) {
|
||||
coder = lzma_alloc(sizeof(lzma_alone_coder), allocator);
|
||||
if (coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->coder = coder;
|
||||
next->code = &alone_decode;
|
||||
next->end = &alone_decoder_end;
|
||||
next->memconfig = &alone_decoder_memconfig;
|
||||
next->coder->next = LZMA_NEXT_CODER_INIT;
|
||||
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;
|
||||
coder->sequence = SEQ_PROPERTIES;
|
||||
coder->picky = picky;
|
||||
coder->pos = 0;
|
||||
coder->options.dict_size = 0;
|
||||
coder->options.preset_dict = NULL;
|
||||
coder->options.preset_dict_size = 0;
|
||||
coder->uncompressed_size = 0;
|
||||
coder->memlimit = my_max(1, memlimit);
|
||||
coder->memusage = LZMA_MEMUSAGE_BASE;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
|
||||
extern lzma_ret lzma_alone_decoder_init(
|
||||
lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
uint64_t memlimit, bool picky);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#define ALONE_HEADER_SIZE (1 + 4 + 8)
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
typedef struct {
|
||||
lzma_next_coder next;
|
||||
|
||||
enum {
|
||||
@@ -27,17 +27,19 @@ struct lzma_coder_s {
|
||||
|
||||
size_t header_pos;
|
||||
uint8_t header[ALONE_HEADER_SIZE];
|
||||
};
|
||||
} lzma_alone_coder;
|
||||
|
||||
|
||||
static lzma_ret
|
||||
alone_encode(lzma_coder *coder,
|
||||
lzma_allocator *allocator lzma_attribute((__unused__)),
|
||||
alone_encode(void *coder_ptr,
|
||||
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)
|
||||
{
|
||||
lzma_alone_coder *coder = coder_ptr;
|
||||
|
||||
while (*out_pos < out_size)
|
||||
switch (coder->sequence) {
|
||||
case SEQ_HEADER:
|
||||
@@ -65,8 +67,9 @@ alone_encode(lzma_coder *coder,
|
||||
|
||||
|
||||
static void
|
||||
alone_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
alone_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_alone_coder *coder = coder_ptr;
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
@@ -75,28 +78,31 @@ alone_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
|
||||
// At least for now, this is not used by any internal function.
|
||||
static lzma_ret
|
||||
alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
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)
|
||||
lzma_alone_coder *coder = next->coder;
|
||||
|
||||
if (coder == NULL) {
|
||||
coder = lzma_alloc(sizeof(lzma_alone_coder), allocator);
|
||||
if (coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->coder = coder;
|
||||
next->code = &alone_encode;
|
||||
next->end = &alone_encoder_end;
|
||||
next->coder->next = LZMA_NEXT_CODER_INIT;
|
||||
coder->next = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
// Basic initializations
|
||||
next->coder->sequence = SEQ_HEADER;
|
||||
next->coder->header_pos = 0;
|
||||
coder->sequence = SEQ_HEADER;
|
||||
coder->header_pos = 0;
|
||||
|
||||
// Encode the header:
|
||||
// - Properties (1 byte)
|
||||
if (lzma_lzma_lclppb_encode(options, next->coder->header))
|
||||
if (lzma_lzma_lclppb_encode(options, coder->header))
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
// - Dictionary size (4 bytes)
|
||||
@@ -116,10 +122,10 @@ alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
if (d != UINT32_MAX)
|
||||
++d;
|
||||
|
||||
unaligned_write32le(next->coder->header + 1, d);
|
||||
unaligned_write32le(coder->header + 1, d);
|
||||
|
||||
// - Uncompressed size (always unknown and using EOPM)
|
||||
memset(next->coder->header + 1 + 4, 0xFF, 8);
|
||||
memset(coder->header + 1 + 4, 0xFF, 8);
|
||||
|
||||
// Initialize the LZMA encoder.
|
||||
const lzma_filter_info filters[2] = {
|
||||
@@ -131,13 +137,13 @@ alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
}
|
||||
};
|
||||
|
||||
return lzma_next_filter_init(&next->coder->next, allocator, filters);
|
||||
return lzma_next_filter_init(&coder->next, allocator, filters);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
extern lzma_ret
|
||||
lzma_alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
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);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "alone_decoder.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
typedef struct {
|
||||
/// Stream decoder or LZMA_Alone decoder
|
||||
lzma_next_coder next;
|
||||
|
||||
@@ -26,15 +26,17 @@ struct lzma_coder_s {
|
||||
SEQ_CODE,
|
||||
SEQ_FINISH,
|
||||
} sequence;
|
||||
};
|
||||
} lzma_auto_coder;
|
||||
|
||||
|
||||
static lzma_ret
|
||||
auto_decode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
auto_decode(void *coder_ptr, 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)
|
||||
{
|
||||
lzma_auto_coder *coder = coder_ptr;
|
||||
|
||||
switch (coder->sequence) {
|
||||
case SEQ_INIT:
|
||||
if (*in_pos >= in_size)
|
||||
@@ -100,8 +102,9 @@ auto_decode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
|
||||
|
||||
static void
|
||||
auto_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
auto_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_auto_coder *coder = coder_ptr;
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
@@ -109,8 +112,10 @@ auto_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
|
||||
|
||||
static lzma_check
|
||||
auto_decoder_get_check(const lzma_coder *coder)
|
||||
auto_decoder_get_check(const void *coder_ptr)
|
||||
{
|
||||
const lzma_auto_coder *coder = coder_ptr;
|
||||
|
||||
// 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);
|
||||
@@ -118,9 +123,11 @@ auto_decoder_get_check(const lzma_coder *coder)
|
||||
|
||||
|
||||
static lzma_ret
|
||||
auto_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
|
||||
auto_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
|
||||
uint64_t *old_memlimit, uint64_t new_memlimit)
|
||||
{
|
||||
lzma_auto_coder *coder = coder_ptr;
|
||||
|
||||
lzma_ret ret;
|
||||
|
||||
if (coder->next.memconfig != NULL) {
|
||||
@@ -132,7 +139,10 @@ auto_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
|
||||
// the current memory usage.
|
||||
*memusage = LZMA_MEMUSAGE_BASE;
|
||||
*old_memlimit = coder->memlimit;
|
||||
|
||||
ret = LZMA_OK;
|
||||
if (new_memlimit != 0 && new_memlimit < *memusage)
|
||||
ret = LZMA_MEMLIMIT_ERROR;
|
||||
}
|
||||
|
||||
if (ret == LZMA_OK && new_memlimit != 0)
|
||||
@@ -143,32 +153,31 @@ auto_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
|
||||
|
||||
|
||||
static lzma_ret
|
||||
auto_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
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)
|
||||
lzma_auto_coder *coder = next->coder;
|
||||
if (coder == NULL) {
|
||||
coder = lzma_alloc(sizeof(lzma_auto_coder), allocator);
|
||||
if (coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->coder = coder;
|
||||
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;
|
||||
coder->next = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
next->coder->memlimit = memlimit;
|
||||
next->coder->flags = flags;
|
||||
next->coder->sequence = SEQ_INIT;
|
||||
coder->memlimit = my_max(1, memlimit);
|
||||
coder->flags = flags;
|
||||
coder->sequence = SEQ_INIT;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_block_buffer_decode(lzma_block *block, lzma_allocator *allocator,
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "block_buffer_encoder.h"
|
||||
#include "block_encoder.h"
|
||||
#include "filter_encoder.h"
|
||||
#include "lzma2_encoder.h"
|
||||
@@ -28,8 +29,8 @@
|
||||
+ LZMA_CHECK_SIZE_MAX + 3) & ~3)
|
||||
|
||||
|
||||
static lzma_vli
|
||||
lzma2_bound(lzma_vli uncompressed_size)
|
||||
static uint64_t
|
||||
lzma2_bound(uint64_t uncompressed_size)
|
||||
{
|
||||
// Prevent integer overflow in overhead calculation.
|
||||
if (uncompressed_size > COMPRESSED_SIZE_MAX)
|
||||
@@ -39,7 +40,7 @@ lzma2_bound(lzma_vli uncompressed_size)
|
||||
// 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 lzma_vli overhead = ((uncompressed_size + LZMA2_CHUNK_MAX - 1)
|
||||
const uint64_t overhead = ((uncompressed_size + LZMA2_CHUNK_MAX - 1)
|
||||
/ LZMA2_CHUNK_MAX)
|
||||
* LZMA2_HEADER_UNCOMPRESSED + 1;
|
||||
|
||||
@@ -51,30 +52,36 @@ lzma2_bound(lzma_vli uncompressed_size)
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(size_t)
|
||||
lzma_block_buffer_bound(size_t uncompressed_size)
|
||||
extern uint64_t
|
||||
lzma_block_buffer_bound64(uint64_t uncompressed_size)
|
||||
{
|
||||
// For now, if the data doesn't compress, we always use uncompressed
|
||||
// chunks of LZMA2. In future we may use Subblock filter too, but
|
||||
// but for simplicity we probably will still use the same bound
|
||||
// calculation even though Subblock filter would have slightly less
|
||||
// overhead.
|
||||
lzma_vli lzma2_size = lzma2_bound(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) & ~LZMA_VLI_C(3);
|
||||
lzma2_size = (lzma2_size + 3) & ~UINT64_C(3);
|
||||
|
||||
#if SIZE_MAX < LZMA_VLI_MAX
|
||||
// Catch the possible integer overflow on 32-bit systems. There's no
|
||||
// overflow on 64-bit systems, because lzma2_bound() already takes
|
||||
// No risk of integer overflow because lzma2_bound() already takes
|
||||
// into account the size of the headers in the Block.
|
||||
if (SIZE_MAX - HEADERS_BOUND < lzma2_size)
|
||||
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 HEADERS_BOUND + lzma2_size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -82,9 +89,6 @@ 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)
|
||||
{
|
||||
// TODO: Figure out if the last filter is LZMA2 or Subblock and use
|
||||
// that filter to encode the uncompressed chunks.
|
||||
|
||||
// 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.
|
||||
@@ -160,16 +164,11 @@ block_encode_uncompressed(lzma_block *block, const uint8_t *in, size_t in_size,
|
||||
|
||||
|
||||
static lzma_ret
|
||||
block_encode_normal(lzma_block *block, lzma_allocator *allocator,
|
||||
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.
|
||||
block->compressed_size = lzma2_bound(in_size);
|
||||
if (block->compressed_size == 0)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
block->uncompressed_size = in_size;
|
||||
return_if_error(lzma_block_header_size(block));
|
||||
|
||||
// Reserve space for the Block Header and skip it for now.
|
||||
@@ -221,10 +220,11 @@ block_encode_normal(lzma_block *block, lzma_allocator *allocator,
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_block_buffer_encode(lzma_block *block, lzma_allocator *allocator,
|
||||
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)
|
||||
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
|
||||
@@ -233,11 +233,11 @@ lzma_block_buffer_encode(lzma_block *block, lzma_allocator *allocator,
|
||||
|
||||
// The contents of the structure may depend on the version so
|
||||
// check the version before validating the contents of *block.
|
||||
if (block->version != 0)
|
||||
if (block->version > 1)
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
if ((unsigned int)(block->check) > LZMA_CHECK_ID_MAX
|
||||
|| block->filters == NULL)
|
||||
|| (try_to_compress && block->filters == NULL))
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (!lzma_check_is_supported(block->check))
|
||||
@@ -258,9 +258,19 @@ lzma_block_buffer_encode(lzma_block *block, lzma_allocator *allocator,
|
||||
|
||||
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.
|
||||
const lzma_ret ret = block_encode_normal(block, allocator,
|
||||
in, in_size, out, out_pos, out_size);
|
||||
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.
|
||||
@@ -303,3 +313,25 @@ lzma_block_buffer_encode(lzma_block *block, lzma_allocator *allocator,
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
24
liblzma/common/block_buffer_encoder.h
Normal file
24
liblzma/common/block_buffer_encoder.h
Normal file
@@ -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
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "check.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
typedef struct {
|
||||
enum {
|
||||
SEQ_CODE,
|
||||
SEQ_PADDING,
|
||||
@@ -45,7 +45,10 @@ struct lzma_coder_s {
|
||||
|
||||
/// Check of the uncompressed data
|
||||
lzma_check_state check;
|
||||
};
|
||||
|
||||
/// True if the integrity check won't be calculated and verified.
|
||||
bool ignore_check;
|
||||
} lzma_block_coder;
|
||||
|
||||
|
||||
static inline bool
|
||||
@@ -71,11 +74,13 @@ is_size_valid(lzma_vli size, lzma_vli reference)
|
||||
|
||||
|
||||
static lzma_ret
|
||||
block_decode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
block_decode(void *coder_ptr, 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)
|
||||
{
|
||||
lzma_block_coder *coder = coder_ptr;
|
||||
|
||||
switch (coder->sequence) {
|
||||
case SEQ_CODE: {
|
||||
const size_t in_start = *in_pos;
|
||||
@@ -97,8 +102,9 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
coder->block->uncompressed_size))
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
lzma_check_update(&coder->check, coder->block->check,
|
||||
out + out_start, out_used);
|
||||
if (!coder->ignore_check)
|
||||
lzma_check_update(&coder->check, coder->block->check,
|
||||
out + out_start, out_used);
|
||||
|
||||
if (ret != LZMA_STREAM_END)
|
||||
return ret;
|
||||
@@ -140,7 +146,9 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
if (coder->block->check == LZMA_CHECK_NONE)
|
||||
return LZMA_STREAM_END;
|
||||
|
||||
lzma_check_finish(&coder->check, coder->block->check);
|
||||
if (!coder->ignore_check)
|
||||
lzma_check_finish(&coder->check, coder->block->check);
|
||||
|
||||
coder->sequence = SEQ_CHECK;
|
||||
|
||||
// Fall through
|
||||
@@ -155,7 +163,8 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
// Validate the Check only if we support it.
|
||||
// coder->check.buffer may be uninitialized
|
||||
// when the Check ID is not supported.
|
||||
if (lzma_check_is_supported(coder->block->check)
|
||||
if (!coder->ignore_check
|
||||
&& lzma_check_is_supported(coder->block->check)
|
||||
&& memcmp(coder->block->raw_check,
|
||||
coder->check.buffer.u8,
|
||||
check_size) != 0)
|
||||
@@ -170,8 +179,9 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
|
||||
|
||||
static void
|
||||
block_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
block_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_block_coder *coder = coder_ptr;
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
@@ -179,7 +189,7 @@ block_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
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);
|
||||
@@ -191,27 +201,29 @@ lzma_block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
|| !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)
|
||||
// Allocate *next->coder if needed.
|
||||
lzma_block_coder *coder = next->coder;
|
||||
if (coder == NULL) {
|
||||
coder = lzma_alloc(sizeof(lzma_block_coder), allocator);
|
||||
if (coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->coder = coder;
|
||||
next->code = &block_decode;
|
||||
next->end = &block_decoder_end;
|
||||
next->coder->next = LZMA_NEXT_CODER_INIT;
|
||||
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;
|
||||
coder->sequence = SEQ_CODE;
|
||||
coder->block = block;
|
||||
coder->compressed_size = 0;
|
||||
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
|
||||
coder->compressed_limit
|
||||
= block->compressed_size == LZMA_VLI_UNKNOWN
|
||||
? (LZMA_VLI_MAX & ~LZMA_VLI_C(3))
|
||||
- block->header_size
|
||||
@@ -221,11 +233,14 @@ lzma_block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
// 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);
|
||||
coder->check_pos = 0;
|
||||
lzma_check_init(&coder->check, block->check);
|
||||
|
||||
coder->ignore_check = block->version >= 1
|
||||
? block->ignore_check : false;
|
||||
|
||||
// Initialize the filter chain.
|
||||
return lzma_raw_decoder_init(&next->coder->next, allocator,
|
||||
return lzma_raw_decoder_init(&coder->next, allocator,
|
||||
block->filters);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,6 @@
|
||||
|
||||
|
||||
extern lzma_ret lzma_block_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, lzma_block *block);
|
||||
const lzma_allocator *allocator, lzma_block *block);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "check.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
typedef struct {
|
||||
/// The filters in the chain; initialized with lzma_raw_decoder_init().
|
||||
lzma_next_coder next;
|
||||
|
||||
@@ -41,15 +41,17 @@ struct lzma_coder_s {
|
||||
|
||||
/// Check of the uncompressed data
|
||||
lzma_check_state check;
|
||||
};
|
||||
} lzma_block_coder;
|
||||
|
||||
|
||||
static lzma_ret
|
||||
block_encode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
block_encode(void *coder_ptr, 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)
|
||||
{
|
||||
lzma_block_coder *coder = coder_ptr;
|
||||
|
||||
// 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;
|
||||
@@ -134,8 +136,9 @@ block_encode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
|
||||
|
||||
static void
|
||||
block_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
block_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_block_coder *coder = coder_ptr;
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
@@ -143,10 +146,12 @@ block_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
|
||||
|
||||
static lzma_ret
|
||||
block_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
|
||||
block_encoder_update(void *coder_ptr, const lzma_allocator *allocator,
|
||||
const lzma_filter *filters lzma_attribute((__unused__)),
|
||||
const lzma_filter *reversed_filters)
|
||||
{
|
||||
lzma_block_coder *coder = coder_ptr;
|
||||
|
||||
if (coder->sequence != SEQ_CODE)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
@@ -156,7 +161,7 @@ block_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
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);
|
||||
@@ -166,7 +171,7 @@ lzma_block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
|
||||
// The contents of the structure may depend on the version so
|
||||
// check the version first.
|
||||
if (block->version != 0)
|
||||
if (block->version > 1)
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
// If the Check ID is not supported, we cannot calculate the check and
|
||||
@@ -178,30 +183,31 @@ lzma_block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
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)
|
||||
lzma_block_coder *coder = next->coder;
|
||||
if (coder == NULL) {
|
||||
coder = lzma_alloc(sizeof(lzma_block_coder), allocator);
|
||||
if (coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->coder = coder;
|
||||
next->code = &block_encode;
|
||||
next->end = &block_encoder_end;
|
||||
next->update = &block_encoder_update;
|
||||
next->coder->next = LZMA_NEXT_CODER_INIT;
|
||||
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;
|
||||
coder->sequence = SEQ_CODE;
|
||||
coder->block = block;
|
||||
coder->compressed_size = 0;
|
||||
coder->uncompressed_size = 0;
|
||||
coder->pos = 0;
|
||||
|
||||
// Initialize the check
|
||||
lzma_check_init(&next->coder->check, block->check);
|
||||
lzma_check_init(&coder->check, block->check);
|
||||
|
||||
// Initialize the requested filters.
|
||||
return lzma_raw_encoder_init(&next->coder->next, allocator,
|
||||
block->filters);
|
||||
return lzma_raw_encoder_init(&coder->next, allocator, block->filters);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -42,6 +42,6 @@
|
||||
|
||||
|
||||
extern lzma_ret lzma_block_encoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, lzma_block *block);
|
||||
const lzma_allocator *allocator, lzma_block *block);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
|
||||
static void
|
||||
free_properties(lzma_block *block, lzma_allocator *allocator)
|
||||
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
|
||||
@@ -32,7 +32,7 @@ free_properties(lzma_block *block, lzma_allocator *allocator)
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_block_header_decode(lzma_block *block,
|
||||
lzma_allocator *allocator, const uint8_t *in)
|
||||
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
|
||||
@@ -46,8 +46,16 @@ lzma_block_header_decode(lzma_block *block,
|
||||
block->filters[i].options = NULL;
|
||||
}
|
||||
|
||||
// Always zero for now.
|
||||
block->version = 0;
|
||||
// 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.
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_block_header_size(lzma_block *block)
|
||||
{
|
||||
if (block->version != 0)
|
||||
if (block->version > 1)
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
// Block Header Size + Block Flags + CRC32.
|
||||
|
||||
@@ -51,7 +51,7 @@ lzma_block_unpadded_size(const lzma_block *block)
|
||||
// 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 != 0
|
||||
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)
|
||||
|
||||
@@ -36,7 +36,7 @@ lzma_version_string(void)
|
||||
///////////////////////
|
||||
|
||||
extern void * lzma_attribute((__malloc__)) lzma_attr_alloc_size(1)
|
||||
lzma_alloc(size_t size, lzma_allocator *allocator)
|
||||
lzma_alloc(size_t size, const lzma_allocator *allocator)
|
||||
{
|
||||
// Some malloc() variants return NULL if called with size == 0.
|
||||
if (size == 0)
|
||||
@@ -53,8 +53,29 @@ lzma_alloc(size_t size, lzma_allocator *allocator)
|
||||
}
|
||||
|
||||
|
||||
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, lzma_allocator *allocator)
|
||||
lzma_free(void *ptr, const lzma_allocator *allocator)
|
||||
{
|
||||
if (allocator != NULL && allocator->free != NULL)
|
||||
allocator->free(allocator->opaque, ptr);
|
||||
@@ -88,7 +109,7 @@ lzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_next_filter_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
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);
|
||||
@@ -99,7 +120,7 @@ lzma_next_filter_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_next_filter_update(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
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.
|
||||
@@ -117,7 +138,7 @@ lzma_next_filter_update(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
|
||||
|
||||
extern void
|
||||
lzma_next_end(lzma_next_coder *next, lzma_allocator *allocator)
|
||||
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
|
||||
@@ -156,10 +177,8 @@ lzma_strm_init(lzma_stream *strm)
|
||||
strm->internal->next = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = false;
|
||||
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = false;
|
||||
strm->internal->supported_actions[LZMA_FULL_FLUSH] = false;
|
||||
strm->internal->supported_actions[LZMA_FINISH] = false;
|
||||
memzero(strm->internal->supported_actions,
|
||||
sizeof(strm->internal->supported_actions));
|
||||
strm->internal->sequence = ISEQ_RUN;
|
||||
strm->internal->allow_buf_error = false;
|
||||
|
||||
@@ -178,7 +197,7 @@ lzma_code(lzma_stream *strm, lzma_action action)
|
||||
|| (strm->next_out == NULL && strm->avail_out != 0)
|
||||
|| strm->internal == NULL
|
||||
|| strm->internal->next.code == NULL
|
||||
|| (unsigned int)(action) > LZMA_FINISH
|
||||
|| (unsigned int)(action) > LZMA_ACTION_MAX
|
||||
|| !strm->internal->supported_actions[action])
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
@@ -213,6 +232,10 @@ lzma_code(lzma_stream *strm, lzma_action action)
|
||||
case LZMA_FINISH:
|
||||
strm->internal->sequence = ISEQ_FINISH;
|
||||
break;
|
||||
|
||||
case LZMA_FULL_BARRIER:
|
||||
strm->internal->sequence = ISEQ_FULL_BARRIER;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -240,6 +263,13 @@ lzma_code(lzma_stream *strm, lzma_action action)
|
||||
|
||||
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;
|
||||
|
||||
@@ -265,7 +295,9 @@ lzma_code(lzma_stream *strm, lzma_action action)
|
||||
|
||||
strm->internal->avail_in = strm->avail_in;
|
||||
|
||||
switch (ret) {
|
||||
// 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
|
||||
@@ -281,9 +313,16 @@ lzma_code(lzma_stream *strm, lzma_action action)
|
||||
}
|
||||
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_FLUSH
|
||||
|| strm->internal->sequence
|
||||
== ISEQ_FULL_BARRIER)
|
||||
strm->internal->sequence = ISEQ_RUN;
|
||||
else
|
||||
strm->internal->sequence = ISEQ_END;
|
||||
@@ -323,6 +362,22 @@ lzma_end(lzma_stream *strm)
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -380,8 +435,10 @@ lzma_memlimit_set(lzma_stream *strm, uint64_t new_memlimit)
|
||||
|| strm->internal->next.memconfig == NULL)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (new_memlimit != 0 && new_memlimit < LZMA_MEMUSAGE_BASE)
|
||||
return LZMA_MEMLIMIT_ERROR;
|
||||
// Zero is a special value that cannot be used as an actual limit.
|
||||
// If 0 was specified, use 1 instead.
|
||||
if (new_memlimit == 0)
|
||||
new_memlimit = 1;
|
||||
|
||||
return strm->internal->next.memconfig(strm->internal->next.coder,
|
||||
&memusage, &old_memlimit, new_memlimit);
|
||||
|
||||
@@ -49,6 +49,13 @@
|
||||
#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
|
||||
@@ -66,12 +73,20 @@
|
||||
( LZMA_TELL_NO_CHECK \
|
||||
| LZMA_TELL_UNSUPPORTED_CHECK \
|
||||
| LZMA_TELL_ANY_CHECK \
|
||||
| LZMA_IGNORE_CHECK \
|
||||
| LZMA_CONCATENATED )
|
||||
|
||||
|
||||
/// Type of encoder/decoder specific data; the actual structure is defined
|
||||
/// differently in different coders.
|
||||
typedef struct lzma_coder_s lzma_coder;
|
||||
/// 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
|
||||
|
||||
|
||||
typedef struct lzma_next_coder_s lzma_next_coder;
|
||||
|
||||
@@ -80,7 +95,7 @@ typedef struct lzma_filter_info_s lzma_filter_info;
|
||||
|
||||
/// Type of a function used to initialize a filter encoder or decoder
|
||||
typedef lzma_ret (*lzma_init_function)(
|
||||
lzma_next_coder *next, lzma_allocator *allocator,
|
||||
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,
|
||||
@@ -88,7 +103,7 @@ typedef lzma_ret (*lzma_init_function)(
|
||||
/// input and output buffers, but for simplicity they still use this same
|
||||
/// function prototype.
|
||||
typedef lzma_ret (*lzma_code_function)(
|
||||
lzma_coder *coder, lzma_allocator *allocator,
|
||||
void *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,
|
||||
@@ -96,7 +111,7 @@ typedef lzma_ret (*lzma_code_function)(
|
||||
|
||||
/// Type of a function to free the memory allocated for the coder
|
||||
typedef void (*lzma_end_function)(
|
||||
lzma_coder *coder, lzma_allocator *allocator);
|
||||
void *coder, const lzma_allocator *allocator);
|
||||
|
||||
|
||||
/// Raw coder validates and converts an array of lzma_filter structures to
|
||||
@@ -119,7 +134,7 @@ struct lzma_filter_info_s {
|
||||
/// 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;
|
||||
void *coder;
|
||||
|
||||
/// Filter ID. This is LZMA_VLI_UNKNOWN when this structure doesn't
|
||||
/// point to a filter coder.
|
||||
@@ -139,18 +154,23 @@ struct lzma_next_coder_s {
|
||||
/// 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)(void *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);
|
||||
lzma_check (*get_check)(const void *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,
|
||||
lzma_ret (*memconfig)(void *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, lzma_allocator *allocator,
|
||||
lzma_ret (*update)(void *coder, const lzma_allocator *allocator,
|
||||
const lzma_filter *filters,
|
||||
const lzma_filter *reversed_filters);
|
||||
};
|
||||
@@ -164,6 +184,7 @@ struct lzma_next_coder_s {
|
||||
.id = LZMA_VLI_UNKNOWN, \
|
||||
.code = NULL, \
|
||||
.end = NULL, \
|
||||
.get_progress = NULL, \
|
||||
.get_check = NULL, \
|
||||
.memconfig = NULL, \
|
||||
.update = NULL, \
|
||||
@@ -185,6 +206,7 @@ struct lzma_internal_s {
|
||||
ISEQ_SYNC_FLUSH,
|
||||
ISEQ_FULL_FLUSH,
|
||||
ISEQ_FINISH,
|
||||
ISEQ_FULL_BARRIER,
|
||||
ISEQ_END,
|
||||
ISEQ_ERROR,
|
||||
} sequence;
|
||||
@@ -195,7 +217,7 @@ struct lzma_internal_s {
|
||||
size_t avail_in;
|
||||
|
||||
/// Indicates which lzma_action values are allowed by next.code.
|
||||
bool supported_actions[4];
|
||||
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).
|
||||
@@ -204,11 +226,17 @@ struct lzma_internal_s {
|
||||
|
||||
|
||||
/// Allocates memory
|
||||
extern void *lzma_alloc(size_t size, lzma_allocator *allocator)
|
||||
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, lzma_allocator *allocator);
|
||||
extern void lzma_free(void *ptr, const lzma_allocator *allocator);
|
||||
|
||||
|
||||
/// Allocates strm->internal if it is NULL, and initializes *strm and
|
||||
@@ -220,17 +248,19 @@ extern lzma_ret lzma_strm_init(lzma_stream *strm);
|
||||
/// than the filter being initialized now. This way the actual filter
|
||||
/// initialization functions don't need to use lzma_next_coder_init macro.
|
||||
extern lzma_ret lzma_next_filter_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters);
|
||||
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, lzma_allocator *allocator,
|
||||
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, lzma_allocator *allocator);
|
||||
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
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_easy_buffer_encode(uint32_t preset, lzma_check check,
|
||||
lzma_allocator *allocator, const uint8_t *in, size_t in_size,
|
||||
uint8_t *out, size_t *out_pos, size_t out_size)
|
||||
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))
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "easy_preset.h"
|
||||
#include "stream_encoder.h"
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_raw_buffer_decode(const lzma_filter *filters, lzma_allocator *allocator,
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -14,9 +14,10 @@
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_raw_buffer_encode(const lzma_filter *filters, lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t in_size, uint8_t *out,
|
||||
size_t *out_pos, size_t out_size)
|
||||
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
|
||||
|
||||
@@ -123,7 +123,7 @@ static const struct {
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_filters_copy(const lzma_filter *src, lzma_filter *dest,
|
||||
lzma_allocator *allocator)
|
||||
const lzma_allocator *allocator)
|
||||
{
|
||||
if (src == NULL || dest == NULL)
|
||||
return LZMA_PROG_ERROR;
|
||||
@@ -239,7 +239,7 @@ validate_chain(const lzma_filter *filters, size_t *count)
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_raw_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_raw_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter *options,
|
||||
lzma_filter_find coder_find, bool is_encoder)
|
||||
{
|
||||
|
||||
@@ -36,7 +36,7 @@ typedef const lzma_filter_coder *(*lzma_filter_find)(lzma_vli id);
|
||||
|
||||
|
||||
extern lzma_ret lzma_raw_coder_init(
|
||||
lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter *filters,
|
||||
lzma_filter_find coder_find, bool is_encoder);
|
||||
|
||||
|
||||
@@ -35,7 +35,8 @@ typedef struct {
|
||||
/// \return - LZMA_OK: Properties decoded successfully.
|
||||
/// - LZMA_OPTIONS_ERROR: Unsupported properties
|
||||
/// - LZMA_MEM_ERROR: Memory allocation failed.
|
||||
lzma_ret (*props_decode)(void **options, lzma_allocator *allocator,
|
||||
lzma_ret (*props_decode)(
|
||||
void **options, const lzma_allocator *allocator,
|
||||
const uint8_t *props, size_t props_size);
|
||||
|
||||
} lzma_filter_decoder;
|
||||
@@ -136,7 +137,7 @@ lzma_filter_decoder_is_supported(lzma_vli id)
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_raw_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_raw_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter *options)
|
||||
{
|
||||
return lzma_raw_coder_init(next, allocator,
|
||||
@@ -165,7 +166,7 @@ lzma_raw_decoder_memusage(const lzma_filter *filters)
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_properties_decode(lzma_filter *filter, lzma_allocator *allocator,
|
||||
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.
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
|
||||
extern lzma_ret lzma_raw_decoder_init(
|
||||
lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter *options);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -30,11 +30,11 @@ typedef struct {
|
||||
/// invalid, UINT64_MAX is returned.
|
||||
uint64_t (*memusage)(const void *options);
|
||||
|
||||
/// Calculates the minimum sane size for Blocks (or other types of
|
||||
/// chunks) to which the input data can be split to make
|
||||
/// multithreaded encoding possible. If this is NULL, it is assumed
|
||||
/// that the encoder is fast enough with single thread.
|
||||
lzma_vli (*chunk_size)(const void *options);
|
||||
/// 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
|
||||
@@ -59,7 +59,7 @@ static const lzma_filter_encoder encoders[] = {
|
||||
.id = LZMA_FILTER_LZMA1,
|
||||
.init = &lzma_lzma_encoder_init,
|
||||
.memusage = &lzma_lzma_encoder_memusage,
|
||||
.chunk_size = NULL, // FIXME
|
||||
.block_size = NULL, // FIXME
|
||||
.props_size_get = NULL,
|
||||
.props_size_fixed = 5,
|
||||
.props_encode = &lzma_lzma_props_encode,
|
||||
@@ -70,7 +70,7 @@ static const lzma_filter_encoder encoders[] = {
|
||||
.id = LZMA_FILTER_LZMA2,
|
||||
.init = &lzma_lzma2_encoder_init,
|
||||
.memusage = &lzma_lzma2_encoder_memusage,
|
||||
.chunk_size = NULL, // FIXME
|
||||
.block_size = &lzma_lzma2_block_size, // FIXME
|
||||
.props_size_get = NULL,
|
||||
.props_size_fixed = 1,
|
||||
.props_encode = &lzma_lzma2_props_encode,
|
||||
@@ -81,7 +81,7 @@ static const lzma_filter_encoder encoders[] = {
|
||||
.id = LZMA_FILTER_X86,
|
||||
.init = &lzma_simple_x86_encoder_init,
|
||||
.memusage = NULL,
|
||||
.chunk_size = NULL,
|
||||
.block_size = NULL,
|
||||
.props_size_get = &lzma_simple_props_size,
|
||||
.props_encode = &lzma_simple_props_encode,
|
||||
},
|
||||
@@ -91,7 +91,7 @@ static const lzma_filter_encoder encoders[] = {
|
||||
.id = LZMA_FILTER_POWERPC,
|
||||
.init = &lzma_simple_powerpc_encoder_init,
|
||||
.memusage = NULL,
|
||||
.chunk_size = NULL,
|
||||
.block_size = NULL,
|
||||
.props_size_get = &lzma_simple_props_size,
|
||||
.props_encode = &lzma_simple_props_encode,
|
||||
},
|
||||
@@ -101,7 +101,7 @@ static const lzma_filter_encoder encoders[] = {
|
||||
.id = LZMA_FILTER_IA64,
|
||||
.init = &lzma_simple_ia64_encoder_init,
|
||||
.memusage = NULL,
|
||||
.chunk_size = NULL,
|
||||
.block_size = NULL,
|
||||
.props_size_get = &lzma_simple_props_size,
|
||||
.props_encode = &lzma_simple_props_encode,
|
||||
},
|
||||
@@ -111,7 +111,7 @@ static const lzma_filter_encoder encoders[] = {
|
||||
.id = LZMA_FILTER_ARM,
|
||||
.init = &lzma_simple_arm_encoder_init,
|
||||
.memusage = NULL,
|
||||
.chunk_size = NULL,
|
||||
.block_size = NULL,
|
||||
.props_size_get = &lzma_simple_props_size,
|
||||
.props_encode = &lzma_simple_props_encode,
|
||||
},
|
||||
@@ -121,7 +121,7 @@ static const lzma_filter_encoder encoders[] = {
|
||||
.id = LZMA_FILTER_ARMTHUMB,
|
||||
.init = &lzma_simple_armthumb_encoder_init,
|
||||
.memusage = NULL,
|
||||
.chunk_size = NULL,
|
||||
.block_size = NULL,
|
||||
.props_size_get = &lzma_simple_props_size,
|
||||
.props_encode = &lzma_simple_props_encode,
|
||||
},
|
||||
@@ -131,7 +131,7 @@ static const lzma_filter_encoder encoders[] = {
|
||||
.id = LZMA_FILTER_SPARC,
|
||||
.init = &lzma_simple_sparc_encoder_init,
|
||||
.memusage = NULL,
|
||||
.chunk_size = NULL,
|
||||
.block_size = NULL,
|
||||
.props_size_get = &lzma_simple_props_size,
|
||||
.props_encode = &lzma_simple_props_encode,
|
||||
},
|
||||
@@ -141,7 +141,7 @@ static const lzma_filter_encoder encoders[] = {
|
||||
.id = LZMA_FILTER_DELTA,
|
||||
.init = &lzma_delta_encoder_init,
|
||||
.memusage = &lzma_delta_coder_memusage,
|
||||
.chunk_size = NULL,
|
||||
.block_size = NULL,
|
||||
.props_size_get = NULL,
|
||||
.props_size_fixed = 1,
|
||||
.props_encode = &lzma_delta_props_encode,
|
||||
@@ -196,7 +196,7 @@ lzma_filters_update(lzma_stream *strm, const lzma_filter *filters)
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_raw_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_raw_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter *options)
|
||||
{
|
||||
return lzma_raw_coder_init(next, allocator,
|
||||
@@ -226,20 +226,19 @@ lzma_raw_encoder_memusage(const lzma_filter *filters)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
extern LZMA_API(lzma_vli)
|
||||
lzma_chunk_size(const lzma_filter *filters)
|
||||
extern uint64_t
|
||||
lzma_mt_block_size(const lzma_filter *filters)
|
||||
{
|
||||
lzma_vli max = 0;
|
||||
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->chunk_size != NULL) {
|
||||
const lzma_vli size
|
||||
= fe->chunk_size(filters[i].options);
|
||||
if (size == LZMA_VLI_UNKNOWN)
|
||||
return LZMA_VLI_UNKNOWN;
|
||||
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;
|
||||
@@ -248,7 +247,6 @@ lzma_chunk_size(const lzma_filter *filters)
|
||||
|
||||
return max;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
#include "common.h"
|
||||
|
||||
|
||||
// FIXME: Might become a part of the public API once finished.
|
||||
// extern lzma_vli lzma_chunk_size(const lzma_filter *filters);
|
||||
// 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, lzma_allocator *allocator,
|
||||
lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter *filters);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_filter_flags_decode(
|
||||
lzma_filter *filter, lzma_allocator *allocator,
|
||||
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.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file stream_encoder.h
|
||||
/// \brief Encodes .xz Streams
|
||||
/// \file hardware_cputhreads.c
|
||||
/// \brief Get the number of CPU threads or cores
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
@@ -10,14 +10,13 @@
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_STREAM_ENCODER_H
|
||||
#define LZMA_STREAM_ENCODER_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "tuklib_cpucores.h"
|
||||
|
||||
extern lzma_ret lzma_stream_encoder_init(
|
||||
lzma_next_coder *next, lzma_allocator *allocator,
|
||||
const lzma_filter *filters, lzma_check check);
|
||||
|
||||
#endif
|
||||
extern LZMA_API(uint32_t)
|
||||
lzma_cputhreads(void)
|
||||
{
|
||||
return tuklib_cpucores();
|
||||
}
|
||||
@@ -191,8 +191,8 @@ index_tree_init(index_tree *tree)
|
||||
|
||||
/// Helper for index_tree_end()
|
||||
static void
|
||||
index_tree_node_end(index_tree_node *node, lzma_allocator *allocator,
|
||||
void (*free_func)(void *node, lzma_allocator *allocator))
|
||||
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.
|
||||
@@ -202,22 +202,21 @@ index_tree_node_end(index_tree_node *node, lzma_allocator *allocator,
|
||||
if (node->right != NULL)
|
||||
index_tree_node_end(node->right, allocator, free_func);
|
||||
|
||||
if (free_func != NULL)
|
||||
free_func(node, allocator);
|
||||
|
||||
lzma_free(node, allocator);
|
||||
free_func(node, allocator);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/// Free the meory allocated for a tree. If free_func is not NULL,
|
||||
/// it is called on each node before freeing the node. This is used
|
||||
/// to free the Record groups from each index_stream before freeing
|
||||
/// the index_stream itself.
|
||||
/// 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, lzma_allocator *allocator,
|
||||
void (*free_func)(void *node, lzma_allocator *allocator))
|
||||
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);
|
||||
|
||||
@@ -339,8 +338,8 @@ index_tree_locate(const index_tree *tree, lzma_vli target)
|
||||
/// 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,
|
||||
lzma_vli stream_number, lzma_vli block_number_base,
|
||||
lzma_allocator *allocator)
|
||||
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)
|
||||
@@ -368,16 +367,17 @@ index_stream_init(lzma_vli compressed_base, lzma_vli uncompressed_base,
|
||||
|
||||
/// Free the memory allocated for a Stream and its Record groups.
|
||||
static void
|
||||
index_stream_end(void *node, lzma_allocator *allocator)
|
||||
index_stream_end(void *node, const lzma_allocator *allocator)
|
||||
{
|
||||
index_stream *s = node;
|
||||
index_tree_end(&s->groups, allocator, NULL);
|
||||
index_tree_end(&s->groups, allocator, &lzma_free);
|
||||
lzma_free(s, allocator);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static lzma_index *
|
||||
index_init_plain(lzma_allocator *allocator)
|
||||
index_init_plain(const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_index *i = lzma_alloc(sizeof(lzma_index), allocator);
|
||||
if (i != NULL) {
|
||||
@@ -395,7 +395,7 @@ index_init_plain(lzma_allocator *allocator)
|
||||
|
||||
|
||||
extern LZMA_API(lzma_index *)
|
||||
lzma_index_init(lzma_allocator *allocator)
|
||||
lzma_index_init(const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_index *i = index_init_plain(allocator);
|
||||
if (i == NULL)
|
||||
@@ -414,7 +414,7 @@ lzma_index_init(lzma_allocator *allocator)
|
||||
|
||||
|
||||
extern LZMA_API(void)
|
||||
lzma_index_end(lzma_index *i, lzma_allocator *allocator)
|
||||
lzma_index_end(lzma_index *i, const lzma_allocator *allocator)
|
||||
{
|
||||
// NOTE: If you modify this function, check also the bottom
|
||||
// of lzma_index_cat().
|
||||
@@ -637,7 +637,7 @@ lzma_index_stream_padding(lzma_index *i, lzma_vli stream_padding)
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_index_append(lzma_index *i, lzma_allocator *allocator,
|
||||
lzma_index_append(lzma_index *i, const lzma_allocator *allocator,
|
||||
lzma_vli unpadded_size, lzma_vli uncompressed_size)
|
||||
{
|
||||
// Validate.
|
||||
@@ -765,7 +765,7 @@ index_cat_helper(const index_cat_info *info, index_stream *this)
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_index_cat(lzma_index *restrict dest, lzma_index *restrict src,
|
||||
lzma_allocator *allocator)
|
||||
const lzma_allocator *allocator)
|
||||
{
|
||||
const lzma_vli dest_file_size = lzma_index_file_size(dest);
|
||||
|
||||
@@ -829,6 +829,9 @@ lzma_index_cat(lzma_index *restrict dest, lzma_index *restrict src,
|
||||
s->groups.rightmost = &newg->node;
|
||||
|
||||
lzma_free(g, allocator);
|
||||
|
||||
// NOTE: newg isn't leaked here because
|
||||
// newg == (void *)&newg->node.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -859,7 +862,7 @@ lzma_index_cat(lzma_index *restrict dest, lzma_index *restrict src,
|
||||
|
||||
/// Duplicate an index_stream.
|
||||
static index_stream *
|
||||
index_dup_stream(const index_stream *src, lzma_allocator *allocator)
|
||||
index_dup_stream(const index_stream *src, const lzma_allocator *allocator)
|
||||
{
|
||||
// Catch a somewhat theoretical integer overflow.
|
||||
if (src->record_count > PREALLOC_MAX)
|
||||
@@ -869,11 +872,8 @@ index_dup_stream(const index_stream *src, lzma_allocator *allocator)
|
||||
index_stream *dest = index_stream_init(src->node.compressed_base,
|
||||
src->node.uncompressed_base, src->number,
|
||||
src->block_number_base, allocator);
|
||||
|
||||
// Return immediately if allocation failed or if there are
|
||||
// no groups to duplicate.
|
||||
if (dest == NULL || src->groups.leftmost == NULL)
|
||||
return dest;
|
||||
if (dest == NULL)
|
||||
return NULL;
|
||||
|
||||
// Copy the overall information.
|
||||
dest->record_count = src->record_count;
|
||||
@@ -881,6 +881,10 @@ index_dup_stream(const index_stream *src, lzma_allocator *allocator)
|
||||
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.
|
||||
@@ -919,7 +923,7 @@ index_dup_stream(const index_stream *src, lzma_allocator *allocator)
|
||||
|
||||
|
||||
extern LZMA_API(lzma_index *)
|
||||
lzma_index_dup(const lzma_index *src, lzma_allocator *allocator)
|
||||
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);
|
||||
@@ -1008,6 +1012,8 @@ iter_set_info(lzma_index_iter *iter)
|
||||
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;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "check.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
typedef struct {
|
||||
enum {
|
||||
SEQ_INDICATOR,
|
||||
SEQ_COUNT,
|
||||
@@ -50,11 +50,11 @@ struct lzma_coder_s {
|
||||
|
||||
/// CRC32 of the List of Records field
|
||||
uint32_t crc32;
|
||||
};
|
||||
} lzma_index_coder;
|
||||
|
||||
|
||||
static lzma_ret
|
||||
index_decode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
index_decode(void *coder_ptr, 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__)),
|
||||
@@ -62,6 +62,8 @@ index_decode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
size_t out_size lzma_attribute((__unused__)),
|
||||
lzma_action action lzma_attribute((__unused__)))
|
||||
{
|
||||
lzma_index_coder *coder = coder_ptr;
|
||||
|
||||
// Similar optimization as in index_encoder.c
|
||||
const size_t in_start = *in_pos;
|
||||
lzma_ret ret = LZMA_OK;
|
||||
@@ -207,8 +209,9 @@ out:
|
||||
|
||||
|
||||
static void
|
||||
index_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
index_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_index_coder *coder = coder_ptr;
|
||||
lzma_index_end(coder->index, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
@@ -216,9 +219,11 @@ index_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
|
||||
|
||||
static lzma_ret
|
||||
index_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
|
||||
index_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
|
||||
uint64_t *old_memlimit, uint64_t new_memlimit)
|
||||
{
|
||||
lzma_index_coder *coder = coder_ptr;
|
||||
|
||||
*memusage = lzma_index_memusage(1, coder->count);
|
||||
*old_memlimit = coder->memlimit;
|
||||
|
||||
@@ -234,7 +239,7 @@ index_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
|
||||
|
||||
|
||||
static lzma_ret
|
||||
index_decoder_reset(lzma_coder *coder, lzma_allocator *allocator,
|
||||
index_decoder_reset(lzma_index_coder *coder, const lzma_allocator *allocator,
|
||||
lzma_index **i, uint64_t memlimit)
|
||||
{
|
||||
// Remember the pointer given by the application. We will set it
|
||||
@@ -251,7 +256,7 @@ index_decoder_reset(lzma_coder *coder, lzma_allocator *allocator,
|
||||
|
||||
// Initialize the rest.
|
||||
coder->sequence = SEQ_INDICATOR;
|
||||
coder->memlimit = memlimit;
|
||||
coder->memlimit = my_max(1, memlimit);
|
||||
coder->count = 0; // Needs to be initialized due to _memconfig().
|
||||
coder->pos = 0;
|
||||
coder->crc32 = 0;
|
||||
@@ -261,28 +266,30 @@ index_decoder_reset(lzma_coder *coder, lzma_allocator *allocator,
|
||||
|
||||
|
||||
static lzma_ret
|
||||
index_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
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)
|
||||
if (i == NULL)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
lzma_index_coder *coder = next->coder;
|
||||
if (coder == NULL) {
|
||||
coder = lzma_alloc(sizeof(lzma_index_coder), allocator);
|
||||
if (coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->coder = coder;
|
||||
next->code = &index_decode;
|
||||
next->end = &index_decoder_end;
|
||||
next->memconfig = &index_decoder_memconfig;
|
||||
next->coder->index = NULL;
|
||||
coder->index = NULL;
|
||||
} else {
|
||||
lzma_index_end(next->coder->index, allocator);
|
||||
lzma_index_end(coder->index, allocator);
|
||||
}
|
||||
|
||||
return index_decoder_reset(next->coder, allocator, i, memlimit);
|
||||
return index_decoder_reset(coder, allocator, i, memlimit);
|
||||
}
|
||||
|
||||
|
||||
@@ -299,8 +306,8 @@ lzma_index_decoder(lzma_stream *strm, lzma_index **i, uint64_t memlimit)
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_index_buffer_decode(
|
||||
lzma_index **i, uint64_t *memlimit, lzma_allocator *allocator,
|
||||
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
|
||||
@@ -309,7 +316,7 @@ lzma_index_buffer_decode(
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Initialize the decoder.
|
||||
lzma_coder coder;
|
||||
lzma_index_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
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "check.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
typedef struct {
|
||||
enum {
|
||||
SEQ_INDICATOR,
|
||||
SEQ_COUNT,
|
||||
@@ -37,12 +37,12 @@ struct lzma_coder_s {
|
||||
|
||||
/// CRC32 of the List of Records field
|
||||
uint32_t crc32;
|
||||
};
|
||||
} lzma_index_coder;
|
||||
|
||||
|
||||
static lzma_ret
|
||||
index_encode(lzma_coder *coder,
|
||||
lzma_allocator *allocator lzma_attribute((__unused__)),
|
||||
index_encode(void *coder_ptr,
|
||||
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__)),
|
||||
@@ -50,6 +50,8 @@ index_encode(lzma_coder *coder,
|
||||
size_t out_size,
|
||||
lzma_action action lzma_attribute((__unused__)))
|
||||
{
|
||||
lzma_index_coder *coder = coder_ptr;
|
||||
|
||||
// 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;
|
||||
@@ -159,7 +161,7 @@ out:
|
||||
|
||||
|
||||
static void
|
||||
index_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
index_encoder_end(void *coder, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
@@ -167,7 +169,7 @@ index_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
|
||||
|
||||
static void
|
||||
index_encoder_reset(lzma_coder *coder, const lzma_index *i)
|
||||
index_encoder_reset(lzma_index_coder *coder, const lzma_index *i)
|
||||
{
|
||||
lzma_index_iter_init(&coder->iter, i);
|
||||
|
||||
@@ -181,7 +183,7 @@ index_encoder_reset(lzma_coder *coder, const lzma_index *i)
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_index_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
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);
|
||||
@@ -190,7 +192,7 @@ lzma_index_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
next->coder = lzma_alloc(sizeof(lzma_index_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
@@ -230,7 +232,7 @@ lzma_index_buffer_encode(const lzma_index *i,
|
||||
|
||||
// The Index encoder needs just one small data structure so we can
|
||||
// allocate it on stack.
|
||||
lzma_coder coder;
|
||||
lzma_index_coder coder;
|
||||
index_encoder_reset(&coder, i);
|
||||
|
||||
// Do the actual encoding. This should never fail, but store
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
|
||||
extern lzma_ret lzma_index_encoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_index *i);
|
||||
const lzma_allocator *allocator, const lzma_index *i);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -70,7 +70,8 @@ struct lzma_index_hash_s {
|
||||
|
||||
|
||||
extern LZMA_API(lzma_index_hash *)
|
||||
lzma_index_hash_init(lzma_index_hash *index_hash, lzma_allocator *allocator)
|
||||
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);
|
||||
@@ -101,7 +102,8 @@ lzma_index_hash_init(lzma_index_hash *index_hash, lzma_allocator *allocator)
|
||||
|
||||
|
||||
extern LZMA_API(void)
|
||||
lzma_index_hash_end(lzma_index_hash *index_hash, lzma_allocator *allocator)
|
||||
lzma_index_hash_end(lzma_index_hash *index_hash,
|
||||
const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_free(index_hash, allocator);
|
||||
return;
|
||||
|
||||
175
liblzma/common/memcmplen.h
Normal file
175
liblzma/common/memcmplen.h
Normal file
@@ -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
|
||||
184
liblzma/common/outqueue.c
Normal file
184
liblzma/common/outqueue.c
Normal file
@@ -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;
|
||||
}
|
||||
156
liblzma/common/outqueue.h
Normal file
156
liblzma/common/outqueue.h
Normal file
@@ -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;
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_stream_buffer_decode(uint64_t *memlimit, uint32_t flags,
|
||||
lzma_allocator *allocator,
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -42,7 +42,8 @@ lzma_stream_buffer_bound(size_t uncompressed_size)
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_stream_buffer_encode(lzma_filter *filters, lzma_check check,
|
||||
lzma_allocator *allocator, const uint8_t *in, size_t in_size,
|
||||
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
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "block_decoder.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
typedef struct {
|
||||
enum {
|
||||
SEQ_STREAM_HEADER,
|
||||
SEQ_BLOCK_HEADER,
|
||||
@@ -57,6 +57,10 @@ struct lzma_coder_s {
|
||||
/// 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
|
||||
@@ -76,11 +80,11 @@ struct lzma_coder_s {
|
||||
/// Buffer to hold Stream Header, Block Header, and Stream Footer.
|
||||
/// Block Header has biggest maximum size.
|
||||
uint8_t buffer[LZMA_BLOCK_HEADER_SIZE_MAX];
|
||||
};
|
||||
} lzma_stream_coder;
|
||||
|
||||
|
||||
static lzma_ret
|
||||
stream_decoder_reset(lzma_coder *coder, lzma_allocator *allocator)
|
||||
stream_decoder_reset(lzma_stream_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);
|
||||
@@ -96,11 +100,13 @@ stream_decoder_reset(lzma_coder *coder, lzma_allocator *allocator)
|
||||
|
||||
|
||||
static lzma_ret
|
||||
stream_decode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
stream_decode(void *coder_ptr, 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)
|
||||
{
|
||||
lzma_stream_coder *coder = coder_ptr;
|
||||
|
||||
// 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)
|
||||
@@ -182,8 +188,8 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
|
||||
coder->pos = 0;
|
||||
|
||||
// Version 0 is currently the only possible version.
|
||||
coder->block_options.version = 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
|
||||
@@ -195,6 +201,11 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
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;
|
||||
@@ -366,8 +377,9 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
|
||||
|
||||
static void
|
||||
stream_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
stream_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_stream_coder *coder = coder_ptr;
|
||||
lzma_next_end(&coder->block_decoder, allocator);
|
||||
lzma_index_hash_end(coder->index_hash, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
@@ -376,16 +388,19 @@ stream_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
|
||||
|
||||
static lzma_check
|
||||
stream_decoder_get_check(const lzma_coder *coder)
|
||||
stream_decoder_get_check(const void *coder_ptr)
|
||||
{
|
||||
const lzma_stream_coder *coder = coder_ptr;
|
||||
return coder->stream_flags.check;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
stream_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
|
||||
stream_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
|
||||
uint64_t *old_memlimit, uint64_t new_memlimit)
|
||||
{
|
||||
lzma_stream_coder *coder = coder_ptr;
|
||||
|
||||
*memusage = coder->memusage;
|
||||
*old_memlimit = coder->memlimit;
|
||||
|
||||
@@ -401,41 +416,42 @@ stream_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_stream_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
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)
|
||||
lzma_stream_coder *coder = next->coder;
|
||||
if (coder == NULL) {
|
||||
coder = lzma_alloc(sizeof(lzma_stream_coder), allocator);
|
||||
if (coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->coder = coder;
|
||||
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;
|
||||
coder->block_decoder = LZMA_NEXT_CODER_INIT;
|
||||
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
|
||||
coder->memlimit = my_max(1, memlimit);
|
||||
coder->memusage = LZMA_MEMUSAGE_BASE;
|
||||
coder->tell_no_check = (flags & LZMA_TELL_NO_CHECK) != 0;
|
||||
coder->tell_unsupported_check
|
||||
= (flags & LZMA_TELL_UNSUPPORTED_CHECK) != 0;
|
||||
next->coder->tell_any_check = (flags & LZMA_TELL_ANY_CHECK) != 0;
|
||||
next->coder->concatenated = (flags & LZMA_CONCATENATED) != 0;
|
||||
next->coder->first_stream = true;
|
||||
coder->tell_any_check = (flags & LZMA_TELL_ANY_CHECK) != 0;
|
||||
coder->ignore_check = (flags & LZMA_IGNORE_CHECK) != 0;
|
||||
coder->concatenated = (flags & LZMA_CONCATENATED) != 0;
|
||||
coder->first_stream = true;
|
||||
|
||||
return stream_decoder_reset(next->coder, allocator);
|
||||
return stream_decoder_reset(coder, allocator);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
extern lzma_ret lzma_stream_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, uint64_t memlimit, uint32_t flags);
|
||||
extern lzma_ret lzma_stream_decoder_init(
|
||||
lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
uint64_t memlimit, uint32_t flags);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,12 +10,11 @@
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stream_encoder.h"
|
||||
#include "block_encoder.h"
|
||||
#include "index_encoder.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
typedef struct {
|
||||
enum {
|
||||
SEQ_STREAM_HEADER,
|
||||
SEQ_BLOCK_INIT,
|
||||
@@ -26,7 +25,7 @@ struct lzma_coder_s {
|
||||
} sequence;
|
||||
|
||||
/// True if Block encoder has been initialized by
|
||||
/// lzma_stream_encoder_init() or stream_encoder_update()
|
||||
/// stream_encoder_init() or stream_encoder_update()
|
||||
/// and thus doesn't need to be initialized in stream_encode().
|
||||
bool block_encoder_is_initialized;
|
||||
|
||||
@@ -56,11 +55,11 @@ struct lzma_coder_s {
|
||||
/// Buffer to hold Stream Header, Block Header, and Stream Footer.
|
||||
/// Block Header has biggest maximum size.
|
||||
uint8_t buffer[LZMA_BLOCK_HEADER_SIZE_MAX];
|
||||
};
|
||||
} lzma_stream_coder;
|
||||
|
||||
|
||||
static lzma_ret
|
||||
block_encoder_init(lzma_coder *coder, lzma_allocator *allocator)
|
||||
block_encoder_init(lzma_stream_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
|
||||
@@ -79,11 +78,13 @@ block_encoder_init(lzma_coder *coder, lzma_allocator *allocator)
|
||||
|
||||
|
||||
static lzma_ret
|
||||
stream_encode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
stream_encode(void *coder_ptr, 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)
|
||||
{
|
||||
lzma_stream_coder *coder = coder_ptr;
|
||||
|
||||
// Main loop
|
||||
while (*out_pos < out_size)
|
||||
switch (coder->sequence) {
|
||||
@@ -126,7 +127,7 @@ stream_encode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
}
|
||||
|
||||
// Initialize the Block encoder unless it was already
|
||||
// initialized by lzma_stream_encoder_init() or
|
||||
// initialized by stream_encoder_init() or
|
||||
// stream_encoder_update().
|
||||
if (!coder->block_encoder_is_initialized)
|
||||
return_if_error(block_encoder_init(coder, allocator));
|
||||
@@ -147,11 +148,12 @@ stream_encode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
}
|
||||
|
||||
case SEQ_BLOCK_ENCODE: {
|
||||
static const lzma_action convert[4] = {
|
||||
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(
|
||||
@@ -209,8 +211,10 @@ stream_encode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
|
||||
|
||||
static void
|
||||
stream_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
stream_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_stream_coder *coder = coder_ptr;
|
||||
|
||||
lzma_next_end(&coder->block_encoder, allocator);
|
||||
lzma_next_end(&coder->index_encoder, allocator);
|
||||
lzma_index_end(coder->index, allocator);
|
||||
@@ -224,10 +228,12 @@ stream_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
|
||||
|
||||
static lzma_ret
|
||||
stream_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
|
||||
stream_encoder_update(void *coder_ptr, const lzma_allocator *allocator,
|
||||
const lzma_filter *filters,
|
||||
const lzma_filter *reversed_filters)
|
||||
{
|
||||
lzma_stream_coder *coder = coder_ptr;
|
||||
|
||||
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
|
||||
@@ -262,39 +268,42 @@ stream_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_stream_encoder_init(lzma_next_coder *next, lzma_allocator *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(&lzma_stream_encoder_init, next, allocator);
|
||||
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)
|
||||
lzma_stream_coder *coder = next->coder;
|
||||
|
||||
if (coder == NULL) {
|
||||
coder = lzma_alloc(sizeof(lzma_stream_coder), allocator);
|
||||
if (coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->coder = coder;
|
||||
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;
|
||||
coder->filters[0].id = LZMA_VLI_UNKNOWN;
|
||||
coder->block_encoder = LZMA_NEXT_CODER_INIT;
|
||||
coder->index_encoder = LZMA_NEXT_CODER_INIT;
|
||||
coder->index = NULL;
|
||||
}
|
||||
|
||||
// Basic initializations
|
||||
next->coder->sequence = SEQ_STREAM_HEADER;
|
||||
next->coder->block_options.version = 0;
|
||||
next->coder->block_options.check = check;
|
||||
coder->sequence = SEQ_STREAM_HEADER;
|
||||
coder->block_options.version = 0;
|
||||
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)
|
||||
lzma_index_end(coder->index, allocator);
|
||||
coder->index = lzma_index_init(allocator);
|
||||
if (coder->index == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
// Encode the Stream Header
|
||||
@@ -303,16 +312,15 @@ lzma_stream_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
.check = check,
|
||||
};
|
||||
return_if_error(lzma_stream_header_encode(
|
||||
&stream_flags, next->coder->buffer));
|
||||
&stream_flags, coder->buffer));
|
||||
|
||||
next->coder->buffer_pos = 0;
|
||||
next->coder->buffer_size = LZMA_STREAM_HEADER_SIZE;
|
||||
coder->buffer_pos = 0;
|
||||
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);
|
||||
return stream_encoder_update(coder, allocator, filters, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -320,11 +328,12 @@ extern LZMA_API(lzma_ret)
|
||||
lzma_stream_encoder(lzma_stream *strm,
|
||||
const lzma_filter *filters, lzma_check check)
|
||||
{
|
||||
lzma_next_strm_init(lzma_stream_encoder_init, strm, filters, 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;
|
||||
|
||||
1143
liblzma/common/stream_encoder_mt.c
Normal file
1143
liblzma/common/stream_encoder_mt.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -15,8 +15,9 @@
|
||||
|
||||
|
||||
static void
|
||||
delta_coder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
delta_coder_end(void *coder_ptr, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_delta_coder *coder = coder_ptr;
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
@@ -24,18 +25,21 @@ delta_coder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_delta_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_delta_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
// Allocate memory for the decoder if needed.
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
lzma_delta_coder *coder = next->coder;
|
||||
if (coder == NULL) {
|
||||
coder = lzma_alloc(sizeof(lzma_delta_coder), allocator);
|
||||
if (coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->coder = coder;
|
||||
|
||||
// End function is the same for encoder and decoder.
|
||||
next->end = &delta_coder_end;
|
||||
next->coder->next = LZMA_NEXT_CODER_INIT;
|
||||
coder->next = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
// Validate the options.
|
||||
@@ -44,15 +48,14 @@ lzma_delta_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
|
||||
// Set the delta distance.
|
||||
const lzma_options_delta *opt = filters[0].options;
|
||||
next->coder->distance = opt->dist;
|
||||
coder->distance = opt->dist;
|
||||
|
||||
// Initialize the rest of the variables.
|
||||
next->coder->pos = 0;
|
||||
memzero(next->coder->history, LZMA_DELTA_DIST_MAX);
|
||||
coder->pos = 0;
|
||||
memzero(coder->history, LZMA_DELTA_DIST_MAX);
|
||||
|
||||
// Initialize the next decoder in the chain, if any.
|
||||
return lzma_next_filter_init(&next->coder->next,
|
||||
allocator, filters + 1);
|
||||
return lzma_next_filter_init(&coder->next, allocator, filters + 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -66,5 +69,5 @@ lzma_delta_coder_memusage(const void *options)
|
||||
|| opt->dist > LZMA_DELTA_DIST_MAX)
|
||||
return UINT64_MAX;
|
||||
|
||||
return sizeof(lzma_coder);
|
||||
return sizeof(lzma_delta_coder);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
|
||||
static void
|
||||
decode_buffer(lzma_coder *coder, uint8_t *buffer, size_t size)
|
||||
decode_buffer(lzma_delta_coder *coder, uint8_t *buffer, size_t size)
|
||||
{
|
||||
const size_t distance = coder->distance;
|
||||
|
||||
@@ -27,11 +27,13 @@ decode_buffer(lzma_coder *coder, uint8_t *buffer, size_t size)
|
||||
|
||||
|
||||
static lzma_ret
|
||||
delta_decode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
delta_decode(void *coder_ptr, 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)
|
||||
{
|
||||
lzma_delta_coder *coder = coder_ptr;
|
||||
|
||||
assert(coder->next.code != NULL);
|
||||
|
||||
const size_t out_start = *out_pos;
|
||||
@@ -47,7 +49,7 @@ delta_decode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_delta_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_delta_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
next->code = &delta_decode;
|
||||
@@ -56,7 +58,7 @@ lzma_delta_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_delta_props_decode(void **options, lzma_allocator *allocator,
|
||||
lzma_delta_props_decode(void **options, const lzma_allocator *allocator,
|
||||
const uint8_t *props, size_t props_size)
|
||||
{
|
||||
if (props_size != 1)
|
||||
|
||||
@@ -16,10 +16,11 @@
|
||||
#include "delta_common.h"
|
||||
|
||||
extern lzma_ret lzma_delta_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters);
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters);
|
||||
|
||||
extern lzma_ret lzma_delta_props_decode(
|
||||
void **options, lzma_allocator *allocator,
|
||||
void **options, const lzma_allocator *allocator,
|
||||
const uint8_t *props, size_t props_size);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
/// is the first filter in the chain (and thus the last filter in the
|
||||
/// encoder's filter stack).
|
||||
static void
|
||||
copy_and_encode(lzma_coder *coder,
|
||||
copy_and_encode(lzma_delta_coder *coder,
|
||||
const uint8_t *restrict in, uint8_t *restrict out, size_t size)
|
||||
{
|
||||
const size_t distance = coder->distance;
|
||||
@@ -35,7 +35,7 @@ copy_and_encode(lzma_coder *coder,
|
||||
/// Encodes the data in place. This is used when we are the last filter
|
||||
/// in the chain (and thus non-last filter in the encoder's filter stack).
|
||||
static void
|
||||
encode_in_place(lzma_coder *coder, uint8_t *buffer, size_t size)
|
||||
encode_in_place(lzma_delta_coder *coder, uint8_t *buffer, size_t size)
|
||||
{
|
||||
const size_t distance = coder->distance;
|
||||
|
||||
@@ -49,11 +49,13 @@ encode_in_place(lzma_coder *coder, uint8_t *buffer, size_t size)
|
||||
|
||||
|
||||
static lzma_ret
|
||||
delta_encode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
delta_encode(void *coder_ptr, 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)
|
||||
{
|
||||
lzma_delta_coder *coder = coder_ptr;
|
||||
|
||||
lzma_ret ret;
|
||||
|
||||
if (coder->next.code == NULL) {
|
||||
@@ -84,10 +86,12 @@ delta_encode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
|
||||
|
||||
static lzma_ret
|
||||
delta_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
|
||||
delta_encoder_update(void *coder_ptr, const lzma_allocator *allocator,
|
||||
const lzma_filter *filters_null lzma_attribute((__unused__)),
|
||||
const lzma_filter *reversed_filters)
|
||||
{
|
||||
lzma_delta_coder *coder = coder_ptr;
|
||||
|
||||
// Delta doesn't and will never support changing the options in
|
||||
// the middle of encoding. If the app tries to change them, we
|
||||
// simply ignore them.
|
||||
@@ -97,7 +101,7 @@ delta_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_delta_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_delta_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
next->code = &delta_encode;
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
#include "delta_common.h"
|
||||
|
||||
extern lzma_ret lzma_delta_encoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters);
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters);
|
||||
|
||||
extern lzma_ret lzma_delta_props_encode(const void *options, uint8_t *out);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
#include "delta_common.h"
|
||||
|
||||
struct lzma_coder_s {
|
||||
typedef struct {
|
||||
/// Next coder in the chain
|
||||
lzma_next_coder next;
|
||||
|
||||
@@ -27,11 +27,11 @@ struct lzma_coder_s {
|
||||
|
||||
/// Buffer to hold history of the original data
|
||||
uint8_t history[LZMA_DELTA_DIST_MAX];
|
||||
};
|
||||
} lzma_delta_coder;
|
||||
|
||||
|
||||
extern lzma_ret lzma_delta_coder_init(
|
||||
lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,4 +16,4 @@ URL: @PACKAGE_URL@
|
||||
Version: @PACKAGE_VERSION@
|
||||
Cflags: -I${includedir}
|
||||
Libs: -L${libdir} -llzma
|
||||
Libs.private: @PTHREAD_CFLAGS@ @PTHREAD_LIBS@
|
||||
Libs.private: @PTHREAD_CFLAGS@ @LIBS@
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "lz_decoder.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
typedef struct {
|
||||
/// Dictionary (history buffer)
|
||||
lzma_dict dict;
|
||||
|
||||
@@ -48,7 +48,7 @@ struct lzma_coder_s {
|
||||
size_t size;
|
||||
uint8_t buffer[LZMA_BUFFER_SIZE];
|
||||
} temp;
|
||||
};
|
||||
} lzma_coder;
|
||||
|
||||
|
||||
static void
|
||||
@@ -125,13 +125,15 @@ decode_buffer(lzma_coder *coder,
|
||||
|
||||
|
||||
static lzma_ret
|
||||
lz_decode(lzma_coder *coder,
|
||||
lzma_allocator *allocator lzma_attribute((__unused__)),
|
||||
lz_decode(void *coder_ptr,
|
||||
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)
|
||||
{
|
||||
lzma_coder *coder = coder_ptr;
|
||||
|
||||
if (coder->next.code == NULL)
|
||||
return decode_buffer(coder, in, in_pos, in_size,
|
||||
out, out_pos, out_size);
|
||||
@@ -184,8 +186,10 @@ lz_decode(lzma_coder *coder,
|
||||
|
||||
|
||||
static void
|
||||
lz_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
lz_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_coder *coder = coder_ptr;
|
||||
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
lzma_free(coder->dict.buf, allocator);
|
||||
|
||||
@@ -200,31 +204,33 @@ lz_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_lz_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
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,
|
||||
lzma_allocator *allocator, const void *options,
|
||||
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)
|
||||
lzma_coder *coder = next->coder;
|
||||
if (coder == NULL) {
|
||||
coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->coder = coder;
|
||||
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;
|
||||
coder->dict.buf = NULL;
|
||||
coder->dict.size = 0;
|
||||
coder->lz = LZMA_LZ_DECODER_INIT;
|
||||
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,
|
||||
return_if_error(lz_init(&coder->lz, allocator,
|
||||
filters[0].options, &lz_options));
|
||||
|
||||
// If the dictionary size is very small, increase it to 4096 bytes.
|
||||
@@ -248,14 +254,14 @@ lzma_lz_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
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
|
||||
if (coder->dict.size != lz_options.dict_size) {
|
||||
lzma_free(coder->dict.buf, allocator);
|
||||
coder->dict.buf
|
||||
= lzma_alloc(lz_options.dict_size, allocator);
|
||||
if (next->coder->dict.buf == NULL)
|
||||
if (coder->dict.buf == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->coder->dict.size = lz_options.dict_size;
|
||||
coder->dict.size = lz_options.dict_size;
|
||||
}
|
||||
|
||||
lz_decoder_reset(next->coder);
|
||||
@@ -268,21 +274,20 @@ lzma_lz_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
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,
|
||||
memcpy(coder->dict.buf, lz_options.preset_dict + offset,
|
||||
copy_size);
|
||||
next->coder->dict.pos = copy_size;
|
||||
next->coder->dict.full = copy_size;
|
||||
coder->dict.pos = copy_size;
|
||||
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;
|
||||
coder->next_finished = false;
|
||||
coder->this_finished = false;
|
||||
coder->temp.pos = 0;
|
||||
coder->temp.size = 0;
|
||||
|
||||
// Initialize the next filter in the chain, if any.
|
||||
return lzma_next_filter_init(&next->coder->next, allocator,
|
||||
filters + 1);
|
||||
return lzma_next_filter_init(&coder->next, allocator, filters + 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -294,7 +299,8 @@ lzma_lz_decoder_memusage(size_t dictionary_size)
|
||||
|
||||
|
||||
extern void
|
||||
lzma_lz_decoder_uncompressed(lzma_coder *coder, lzma_vli uncompressed_size)
|
||||
lzma_lz_decoder_uncompressed(void *coder_ptr, lzma_vli uncompressed_size)
|
||||
{
|
||||
lzma_coder *coder = coder_ptr;
|
||||
coder->lz.set_uncompressed(coder->lz.coder, uncompressed_size);
|
||||
}
|
||||
|
||||
@@ -53,21 +53,20 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
/// Data specific to the LZ-based decoder
|
||||
lzma_coder *coder;
|
||||
void *coder;
|
||||
|
||||
/// Function to decode from in[] to *dict
|
||||
lzma_ret (*code)(lzma_coder *restrict coder,
|
||||
lzma_ret (*code)(void *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);
|
||||
void (*reset)(void *coder, const void *options);
|
||||
|
||||
/// Set the uncompressed size
|
||||
void (*set_uncompressed)(lzma_coder *coder,
|
||||
lzma_vli uncompressed_size);
|
||||
void (*set_uncompressed)(void *coder, lzma_vli uncompressed_size);
|
||||
|
||||
/// Free allocated resources
|
||||
void (*end)(lzma_coder *coder, lzma_allocator *allocator);
|
||||
void (*end)(void *coder, const lzma_allocator *allocator);
|
||||
|
||||
} lzma_lz_decoder;
|
||||
|
||||
@@ -83,15 +82,16 @@ typedef struct {
|
||||
|
||||
|
||||
extern lzma_ret lzma_lz_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters,
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters,
|
||||
lzma_ret (*lz_init)(lzma_lz_decoder *lz,
|
||||
lzma_allocator *allocator, const void *options,
|
||||
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);
|
||||
void *coder, lzma_vli uncompressed_size);
|
||||
|
||||
|
||||
//////////////////////
|
||||
|
||||
@@ -20,8 +20,10 @@
|
||||
# include "lz_encoder_hash_table.h"
|
||||
#endif
|
||||
|
||||
#include "memcmplen.h"
|
||||
|
||||
struct lzma_coder_s {
|
||||
|
||||
typedef struct {
|
||||
/// LZ-based encoder e.g. LZMA
|
||||
lzma_lz_encoder lz;
|
||||
|
||||
@@ -30,7 +32,7 @@ struct lzma_coder_s {
|
||||
|
||||
/// Next coder in the chain
|
||||
lzma_next_coder next;
|
||||
};
|
||||
} lzma_coder;
|
||||
|
||||
|
||||
/// \brief Moves the data in the input window to free space for new data
|
||||
@@ -76,8 +78,9 @@ move_window(lzma_mf *mf)
|
||||
/// This function must not be called once it has returned LZMA_STREAM_END.
|
||||
///
|
||||
static lzma_ret
|
||||
fill_window(lzma_coder *coder, lzma_allocator *allocator, const uint8_t *in,
|
||||
size_t *in_pos, size_t in_size, lzma_action action)
|
||||
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);
|
||||
|
||||
@@ -107,6 +110,12 @@ fill_window(lzma_coder *coder, lzma_allocator *allocator, const uint8_t *in,
|
||||
|
||||
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
|
||||
@@ -130,7 +139,7 @@ fill_window(lzma_coder *coder, lzma_allocator *allocator, const uint8_t *in,
|
||||
&& 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 size_t pending = coder->mf.pending;
|
||||
const uint32_t pending = coder->mf.pending;
|
||||
coder->mf.pending = 0;
|
||||
|
||||
// Rewind read_pos so that the match finder can hash
|
||||
@@ -148,12 +157,14 @@ fill_window(lzma_coder *coder, lzma_allocator *allocator, const uint8_t *in,
|
||||
|
||||
|
||||
static lzma_ret
|
||||
lz_encode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
lz_encode(void *coder_ptr, 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)
|
||||
{
|
||||
lzma_coder *coder = coder_ptr;
|
||||
|
||||
while (*out_pos < out_size
|
||||
&& (*in_pos < in_size || action != LZMA_RUN)) {
|
||||
// Read more data to coder->mf.buffer if needed.
|
||||
@@ -179,7 +190,7 @@ lz_encode(lzma_coder *coder, lzma_allocator *allocator,
|
||||
|
||||
|
||||
static bool
|
||||
lz_encoder_prepare(lzma_mf *mf, lzma_allocator *allocator,
|
||||
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
|
||||
@@ -325,25 +336,22 @@ lz_encoder_prepare(lzma_mf *mf, lzma_allocator *allocator,
|
||||
hs += HASH_4_SIZE;
|
||||
*/
|
||||
|
||||
// If the above code calculating hs is modified, make sure that
|
||||
// this assertion stays valid (UINT32_MAX / 5 is not strictly the
|
||||
// exact limit). If it doesn't, you need to calculate that
|
||||
// hash_size_sum + sons_count cannot overflow.
|
||||
assert(hs < UINT32_MAX / 5);
|
||||
|
||||
const uint32_t old_count = mf->hash_size_sum + mf->sons_count;
|
||||
mf->hash_size_sum = hs;
|
||||
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;
|
||||
|
||||
const uint32_t new_count = mf->hash_size_sum + mf->sons_count;
|
||||
|
||||
// Deallocate the old hash array if it exists and has different size
|
||||
// than what is needed now.
|
||||
if (old_count != new_count) {
|
||||
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
|
||||
@@ -360,14 +368,23 @@ lz_encoder_prepare(lzma_mf *mf, lzma_allocator *allocator,
|
||||
|
||||
|
||||
static bool
|
||||
lz_encoder_init(lzma_mf *mf, lzma_allocator *allocator,
|
||||
lz_encoder_init(lzma_mf *mf, const lzma_allocator *allocator,
|
||||
const lzma_lz_options *lz_options)
|
||||
{
|
||||
// Allocate the history buffer.
|
||||
if (mf->buffer == NULL) {
|
||||
mf->buffer = lzma_alloc(mf->size, allocator);
|
||||
// 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
|
||||
@@ -381,44 +398,49 @@ lz_encoder_init(lzma_mf *mf, lzma_allocator *allocator,
|
||||
mf->write_pos = 0;
|
||||
mf->pending = 0;
|
||||
|
||||
// Allocate match finder's hash array.
|
||||
const size_t alloc_count = mf->hash_size_sum + mf->sons_count;
|
||||
|
||||
#if UINT32_MAX >= SIZE_MAX / 4
|
||||
// Check for integer overflow. (Huge dictionaries are not
|
||||
// possible on 32-bit CPU.)
|
||||
if (alloc_count > SIZE_MAX / sizeof(uint32_t))
|
||||
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(alloc_count * sizeof(uint32_t),
|
||||
mf->hash = lzma_alloc_zero(mf->hash_count * sizeof(uint32_t),
|
||||
allocator);
|
||||
if (mf->hash == NULL)
|
||||
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->son = mf->hash + mf->hash_size_sum;
|
||||
mf->cyclic_pos = 0;
|
||||
|
||||
// Initialize the hash table. Since EMPTY_HASH_VALUE is zero, we
|
||||
// can use memset().
|
||||
/*
|
||||
for (uint32_t i = 0; i < hash_size_sum; ++i)
|
||||
mf->hash[i] = EMPTY_HASH_VALUE;
|
||||
*/
|
||||
memzero(mf->hash, (size_t)(mf->hash_size_sum) * sizeof(uint32_t));
|
||||
|
||||
// We don't need to initialize mf->son, but not doing that will
|
||||
// make Valgrind complain in normalization (see normalize() in
|
||||
// lz_encoder_mf.c).
|
||||
//
|
||||
// Skipping this initialization is *very* good when big dictionary is
|
||||
// used but only small amount of data gets actually compressed: most
|
||||
// of the mf->hash won't get actually allocated by the kernel, so
|
||||
// we avoid wasting RAM and improve initialization speed a lot.
|
||||
//memzero(mf->son, (size_t)(mf->sons_count) * sizeof(uint32_t));
|
||||
|
||||
// Handle preset dictionary.
|
||||
if (lz_options->preset_dict != NULL
|
||||
&& lz_options->preset_dict_size > 0) {
|
||||
@@ -445,7 +467,8 @@ lzma_lz_encoder_memusage(const lzma_lz_options *lz_options)
|
||||
lzma_mf mf = {
|
||||
.buffer = NULL,
|
||||
.hash = NULL,
|
||||
.hash_size_sum = 0,
|
||||
.son = NULL,
|
||||
.hash_count = 0,
|
||||
.sons_count = 0,
|
||||
};
|
||||
|
||||
@@ -454,17 +477,19 @@ lzma_lz_encoder_memusage(const lzma_lz_options *lz_options)
|
||||
return UINT64_MAX;
|
||||
|
||||
// Calculate the memory usage.
|
||||
return (uint64_t)(mf.hash_size_sum + mf.sons_count)
|
||||
* sizeof(uint32_t)
|
||||
+ (uint64_t)(mf.size) + sizeof(lzma_coder);
|
||||
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, lzma_allocator *allocator)
|
||||
lz_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_coder *coder = coder_ptr;
|
||||
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
|
||||
lzma_free(coder->mf.son, allocator);
|
||||
lzma_free(coder->mf.hash, allocator);
|
||||
lzma_free(coder->mf.buffer, allocator);
|
||||
|
||||
@@ -479,10 +504,12 @@ lz_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
|
||||
|
||||
static lzma_ret
|
||||
lz_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
|
||||
lz_encoder_update(void *coder_ptr, const lzma_allocator *allocator,
|
||||
const lzma_filter *filters_null lzma_attribute((__unused__)),
|
||||
const lzma_filter *reversed_filters)
|
||||
{
|
||||
lzma_coder *coder = coder_ptr;
|
||||
|
||||
if (coder->lz.options_update == NULL)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
@@ -495,10 +522,10 @@ lz_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_lz_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
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,
|
||||
lzma_allocator *allocator, const void *options,
|
||||
const lzma_allocator *allocator, const void *options,
|
||||
lzma_lz_options *lz_options))
|
||||
{
|
||||
#ifdef HAVE_SMALL
|
||||
@@ -507,45 +534,51 @@ lzma_lz_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
#endif
|
||||
|
||||
// Allocate and initialize the base data structure.
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
lzma_coder *coder = next->coder;
|
||||
if (coder == NULL) {
|
||||
coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->coder = coder;
|
||||
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;
|
||||
coder->lz.coder = NULL;
|
||||
coder->lz.code = NULL;
|
||||
coder->lz.end = NULL;
|
||||
|
||||
next->coder->mf.buffer = NULL;
|
||||
next->coder->mf.hash = NULL;
|
||||
next->coder->mf.hash_size_sum = 0;
|
||||
next->coder->mf.sons_count = 0;
|
||||
// mf.size is initialized to silence Valgrind
|
||||
// when used on optimized binaries (GCC may reorder
|
||||
// code in a way that Valgrind gets unhappy).
|
||||
coder->mf.buffer = NULL;
|
||||
coder->mf.size = 0;
|
||||
coder->mf.hash = NULL;
|
||||
coder->mf.son = NULL;
|
||||
coder->mf.hash_count = 0;
|
||||
coder->mf.sons_count = 0;
|
||||
|
||||
next->coder->next = LZMA_NEXT_CODER_INIT;
|
||||
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,
|
||||
return_if_error(lz_init(&coder->lz, allocator,
|
||||
filters[0].options, &lz_options));
|
||||
|
||||
// Setup the size information into next->coder->mf and deallocate
|
||||
// Setup the size information into coder->mf and deallocate
|
||||
// old buffers if they have wrong size.
|
||||
if (lz_encoder_prepare(&next->coder->mf, allocator, &lz_options))
|
||||
if (lz_encoder_prepare(&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))
|
||||
if (lz_encoder_init(&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);
|
||||
return lzma_next_filter_init(&coder->next, allocator, filters + 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ struct lzma_mf_s {
|
||||
lzma_action action;
|
||||
|
||||
/// Number of elements in hash[]
|
||||
uint32_t hash_size_sum;
|
||||
uint32_t hash_count;
|
||||
|
||||
/// Number of elements in son[]
|
||||
uint32_t sons_count;
|
||||
@@ -191,19 +191,18 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
/// Data specific to the LZ-based encoder
|
||||
lzma_coder *coder;
|
||||
void *coder;
|
||||
|
||||
/// Function to encode from *dict to out[]
|
||||
lzma_ret (*code)(lzma_coder *restrict coder,
|
||||
lzma_ret (*code)(void *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, lzma_allocator *allocator);
|
||||
void (*end)(void *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_ret (*options_update)(void *coder, const lzma_filter *filter);
|
||||
|
||||
} lzma_lz_encoder;
|
||||
|
||||
@@ -296,10 +295,10 @@ mf_read(lzma_mf *mf, uint8_t *out, size_t *out_pos, size_t out_size,
|
||||
|
||||
|
||||
extern lzma_ret lzma_lz_encoder_init(
|
||||
lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters,
|
||||
lzma_ret (*lz_init)(lzma_lz_encoder *lz,
|
||||
lzma_allocator *allocator, const void *options,
|
||||
const lzma_allocator *allocator, const void *options,
|
||||
lzma_lz_options *lz_options));
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "lz_encoder.h"
|
||||
#include "lz_encoder_hash.h"
|
||||
#include "memcmplen.h"
|
||||
|
||||
|
||||
/// \brief Find matches starting from the current byte
|
||||
@@ -65,9 +66,7 @@ lzma_mf_find(lzma_mf *mf, uint32_t *count_ptr, lzma_match *matches)
|
||||
// here because the match distances are zero based.
|
||||
const uint8_t *p2 = p1 - matches[count - 1].dist - 1;
|
||||
|
||||
while (len_best < limit
|
||||
&& p1[len_best] == p2[len_best])
|
||||
++len_best;
|
||||
len_best = lzma_memcmplen(p1, p2, len_best, limit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,24 +115,27 @@ normalize(lzma_mf *mf)
|
||||
= (MUST_NORMALIZE_POS - mf->cyclic_size);
|
||||
// & (~(UINT32_C(1) << 10) - 1);
|
||||
|
||||
const uint32_t count = mf->hash_size_sum + mf->sons_count;
|
||||
uint32_t *hash = mf->hash;
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
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.
|
||||
//
|
||||
// NOTE: Only the first mf->hash_size_sum elements are
|
||||
// initialized for sure. There may be uninitialized elements
|
||||
// in mf->son. Since we go through both mf->hash and
|
||||
// mf->son here in normalization, Valgrind may complain
|
||||
// that the "if" below depends on 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 (hash[i] <= subvalue)
|
||||
hash[i] = EMPTY_HASH_VALUE;
|
||||
if (mf->hash[i] <= subvalue)
|
||||
mf->hash[i] = EMPTY_HASH_VALUE;
|
||||
else
|
||||
hash[i] -= subvalue;
|
||||
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.
|
||||
@@ -269,10 +271,7 @@ hc_find_func(
|
||||
+ (delta > cyclic_pos ? cyclic_size : 0)];
|
||||
|
||||
if (pb[len_best] == cur[len_best] && pb[0] == cur[0]) {
|
||||
uint32_t len = 0;
|
||||
while (++len != len_limit)
|
||||
if (pb[len] != cur[len])
|
||||
break;
|
||||
uint32_t len = lzma_memcmplen(pb, cur, 1, len_limit);
|
||||
|
||||
if (len_best < len) {
|
||||
len_best = len;
|
||||
@@ -318,9 +317,8 @@ lzma_mf_hc3_find(lzma_mf *mf, lzma_match *matches)
|
||||
uint32_t len_best = 2;
|
||||
|
||||
if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
|
||||
for ( ; len_best != len_limit; ++len_best)
|
||||
if (*(cur + len_best - delta2) != cur[len_best])
|
||||
break;
|
||||
len_best = lzma_memcmplen(cur - delta2, cur,
|
||||
len_best, len_limit);
|
||||
|
||||
matches[0].len = len_best;
|
||||
matches[0].dist = delta2 - 1;
|
||||
@@ -397,9 +395,8 @@ lzma_mf_hc4_find(lzma_mf *mf, lzma_match *matches)
|
||||
}
|
||||
|
||||
if (matches_count != 0) {
|
||||
for ( ; len_best != len_limit; ++len_best)
|
||||
if (*(cur + len_best - delta2) != cur[len_best])
|
||||
break;
|
||||
len_best = lzma_memcmplen(cur - delta2, cur,
|
||||
len_best, len_limit);
|
||||
|
||||
matches[matches_count - 1].len = len_best;
|
||||
|
||||
@@ -484,9 +481,7 @@ bt_find_func(
|
||||
uint32_t len = my_min(len0, len1);
|
||||
|
||||
if (pb[len] == cur[len]) {
|
||||
while (++len != len_limit)
|
||||
if (pb[len] != cur[len])
|
||||
break;
|
||||
len = lzma_memcmplen(pb, cur, len + 1, len_limit);
|
||||
|
||||
if (len_best < len) {
|
||||
len_best = len;
|
||||
@@ -549,9 +544,7 @@ bt_skip_func(
|
||||
uint32_t len = my_min(len0, len1);
|
||||
|
||||
if (pb[len] == cur[len]) {
|
||||
while (++len != len_limit)
|
||||
if (pb[len] != cur[len])
|
||||
break;
|
||||
len = lzma_memcmplen(pb, cur, len + 1, len_limit);
|
||||
|
||||
if (len == len_limit) {
|
||||
*ptr1 = pair[0];
|
||||
@@ -639,9 +632,8 @@ lzma_mf_bt3_find(lzma_mf *mf, lzma_match *matches)
|
||||
uint32_t len_best = 2;
|
||||
|
||||
if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
|
||||
for ( ; len_best != len_limit; ++len_best)
|
||||
if (*(cur + len_best - delta2) != cur[len_best])
|
||||
break;
|
||||
len_best = lzma_memcmplen(
|
||||
cur, cur - delta2, len_best, len_limit);
|
||||
|
||||
matches[0].len = len_best;
|
||||
matches[0].dist = delta2 - 1;
|
||||
@@ -712,9 +704,8 @@ lzma_mf_bt4_find(lzma_mf *mf, lzma_match *matches)
|
||||
}
|
||||
|
||||
if (matches_count != 0) {
|
||||
for ( ; len_best != len_limit; ++len_best)
|
||||
if (*(cur + len_best - delta2) != cur[len_best])
|
||||
break;
|
||||
len_best = lzma_memcmplen(
|
||||
cur, cur - delta2, len_best, len_limit);
|
||||
|
||||
matches[matches_count - 1].len = len_best;
|
||||
|
||||
|
||||
@@ -14,15 +14,15 @@
|
||||
#ifndef LZMA_FASTPOS_H
|
||||
#define LZMA_FASTPOS_H
|
||||
|
||||
// LZMA encodes match distances (positions) 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 new .lzma
|
||||
// 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:
|
||||
//
|
||||
// pos return
|
||||
// dist return
|
||||
// 0 0
|
||||
// 1 1
|
||||
// 2 2
|
||||
@@ -48,10 +48,10 @@
|
||||
// Provided functions or macros
|
||||
// ----------------------------
|
||||
//
|
||||
// get_pos_slot(pos) is the basic version. get_pos_slot_2(pos)
|
||||
// assumes that pos >= FULL_DISTANCES, thus the result is at least
|
||||
// FULL_DISTANCES_BITS * 2. Using get_pos_slot(pos) instead of
|
||||
// get_pos_slot_2(pos) would give the same result, but get_pos_slot_2(pos)
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
@@ -76,13 +76,14 @@
|
||||
// slightly faster, but sometimes it is a lot slower.
|
||||
|
||||
#ifdef HAVE_SMALL
|
||||
# define get_pos_slot(pos) ((pos) <= 4 ? (pos) : get_pos_slot_2(pos))
|
||||
# define get_dist_slot(dist) \
|
||||
((dist) <= 4 ? (dist) : get_dist_slot_2(dist))
|
||||
|
||||
static inline uint32_t
|
||||
get_pos_slot_2(uint32_t pos)
|
||||
get_dist_slot_2(uint32_t dist)
|
||||
{
|
||||
const uint32_t i = bsr32(pos);
|
||||
return (i + i) + ((pos >> (i - 1)) & 1);
|
||||
const uint32_t i = bsr32(dist);
|
||||
return (i + i) + ((dist >> (i - 1)) & 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -99,39 +100,39 @@ extern const uint8_t lzma_fastpos[1 << FASTPOS_BITS];
|
||||
#define fastpos_limit(extra, n) \
|
||||
(UINT32_C(1) << (FASTPOS_BITS + fastpos_shift(extra, n)))
|
||||
|
||||
#define fastpos_result(pos, extra, n) \
|
||||
lzma_fastpos[(pos) >> 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_pos_slot(uint32_t pos)
|
||||
get_dist_slot(uint32_t dist)
|
||||
{
|
||||
// If it is small enough, we can pick the result directly from
|
||||
// the precalculated table.
|
||||
if (pos < fastpos_limit(0, 0))
|
||||
return lzma_fastpos[pos];
|
||||
if (dist < fastpos_limit(0, 0))
|
||||
return lzma_fastpos[dist];
|
||||
|
||||
if (pos < fastpos_limit(0, 1))
|
||||
return fastpos_result(pos, 0, 1);
|
||||
if (dist < fastpos_limit(0, 1))
|
||||
return fastpos_result(dist, 0, 1);
|
||||
|
||||
return fastpos_result(pos, 0, 2);
|
||||
return fastpos_result(dist, 0, 2);
|
||||
}
|
||||
|
||||
|
||||
#ifdef FULL_DISTANCES_BITS
|
||||
static inline uint32_t
|
||||
get_pos_slot_2(uint32_t pos)
|
||||
get_dist_slot_2(uint32_t dist)
|
||||
{
|
||||
assert(pos >= FULL_DISTANCES);
|
||||
assert(dist >= FULL_DISTANCES);
|
||||
|
||||
if (pos < fastpos_limit(FULL_DISTANCES_BITS - 1, 0))
|
||||
return fastpos_result(pos, FULL_DISTANCES_BITS - 1, 0);
|
||||
if (dist < fastpos_limit(FULL_DISTANCES_BITS - 1, 0))
|
||||
return fastpos_result(dist, FULL_DISTANCES_BITS - 1, 0);
|
||||
|
||||
if (pos < fastpos_limit(FULL_DISTANCES_BITS - 1, 1))
|
||||
return fastpos_result(pos, FULL_DISTANCES_BITS - 1, 1);
|
||||
if (dist < fastpos_limit(FULL_DISTANCES_BITS - 1, 1))
|
||||
return fastpos_result(dist, FULL_DISTANCES_BITS - 1, 1);
|
||||
|
||||
return fastpos_result(pos, FULL_DISTANCES_BITS - 1, 2);
|
||||
return fastpos_result(dist, FULL_DISTANCES_BITS - 1, 2);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include "lzma_decoder.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
typedef struct {
|
||||
enum sequence {
|
||||
SEQ_CONTROL,
|
||||
SEQ_UNCOMPRESSED_1,
|
||||
@@ -50,14 +50,16 @@ struct lzma_coder_s {
|
||||
bool need_dictionary_reset;
|
||||
|
||||
lzma_options_lzma options;
|
||||
};
|
||||
} lzma_lzma2_coder;
|
||||
|
||||
|
||||
static lzma_ret
|
||||
lzma2_decode(lzma_coder *restrict coder, lzma_dict *restrict dict,
|
||||
lzma2_decode(void *coder_ptr, lzma_dict *restrict dict,
|
||||
const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
size_t in_size)
|
||||
{
|
||||
lzma_lzma2_coder *restrict coder = coder_ptr;
|
||||
|
||||
// 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.
|
||||
@@ -209,8 +211,10 @@ lzma2_decode(lzma_coder *restrict coder, lzma_dict *restrict dict,
|
||||
|
||||
|
||||
static void
|
||||
lzma2_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
lzma2_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_lzma2_coder *coder = coder_ptr;
|
||||
|
||||
assert(coder->lzma.end == NULL);
|
||||
lzma_free(coder->lzma.coder, allocator);
|
||||
|
||||
@@ -221,34 +225,36 @@ lzma2_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
|
||||
|
||||
static lzma_ret
|
||||
lzma2_decoder_init(lzma_lz_decoder *lz, lzma_allocator *allocator,
|
||||
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)
|
||||
lzma_lzma2_coder *coder = lz->coder;
|
||||
if (coder == NULL) {
|
||||
coder = lzma_alloc(sizeof(lzma_lzma2_coder), allocator);
|
||||
if (coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
lz->coder = coder;
|
||||
lz->code = &lzma2_decode;
|
||||
lz->end = &lzma2_decoder_end;
|
||||
|
||||
lz->coder->lzma = LZMA_LZ_DECODER_INIT;
|
||||
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
|
||||
coder->sequence = SEQ_CONTROL;
|
||||
coder->need_properties = true;
|
||||
coder->need_dictionary_reset = options->preset_dict == NULL
|
||||
|| options->preset_dict_size == 0;
|
||||
|
||||
return lzma_lzma_decoder_create(&lz->coder->lzma,
|
||||
return lzma_lzma_decoder_create(&coder->lzma,
|
||||
allocator, options, lz_options);
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_lzma2_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
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
|
||||
@@ -263,13 +269,13 @@ lzma_lzma2_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
extern uint64_t
|
||||
lzma_lzma2_decoder_memusage(const void *options)
|
||||
{
|
||||
return sizeof(lzma_coder)
|
||||
return sizeof(lzma_lzma2_coder)
|
||||
+ lzma_lzma_decoder_memusage_nocheck(options);
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_lzma2_props_decode(void **options, lzma_allocator *allocator,
|
||||
lzma_lzma2_props_decode(void **options, const lzma_allocator *allocator,
|
||||
const uint8_t *props, size_t props_size)
|
||||
{
|
||||
if (props_size != 1)
|
||||
|
||||
@@ -17,12 +17,13 @@
|
||||
#include "common.h"
|
||||
|
||||
extern lzma_ret lzma_lzma2_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters);
|
||||
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, lzma_allocator *allocator,
|
||||
void **options, const lzma_allocator *allocator,
|
||||
const uint8_t *props, size_t props_size);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "lzma2_encoder.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
typedef struct {
|
||||
enum {
|
||||
SEQ_INIT,
|
||||
SEQ_LZMA_ENCODE,
|
||||
@@ -27,7 +27,7 @@ struct lzma_coder_s {
|
||||
} sequence;
|
||||
|
||||
/// LZMA encoder
|
||||
lzma_coder *lzma;
|
||||
void *lzma;
|
||||
|
||||
/// LZMA options currently in use.
|
||||
lzma_options_lzma opt_cur;
|
||||
@@ -48,11 +48,11 @@ struct lzma_coder_s {
|
||||
|
||||
/// Buffer to hold the chunk header and LZMA compressed data
|
||||
uint8_t buf[LZMA2_HEADER_MAX + LZMA2_CHUNK_MAX];
|
||||
};
|
||||
} lzma_lzma2_coder;
|
||||
|
||||
|
||||
static void
|
||||
lzma2_header_lzma(lzma_coder *coder)
|
||||
lzma2_header_lzma(lzma_lzma2_coder *coder)
|
||||
{
|
||||
assert(coder->uncompressed_size > 0);
|
||||
assert(coder->uncompressed_size <= LZMA2_UNCOMPRESSED_MAX);
|
||||
@@ -108,7 +108,7 @@ lzma2_header_lzma(lzma_coder *coder)
|
||||
|
||||
|
||||
static void
|
||||
lzma2_header_uncompressed(lzma_coder *coder)
|
||||
lzma2_header_uncompressed(lzma_lzma2_coder *coder)
|
||||
{
|
||||
assert(coder->uncompressed_size > 0);
|
||||
assert(coder->uncompressed_size <= LZMA2_CHUNK_MAX);
|
||||
@@ -133,10 +133,12 @@ lzma2_header_uncompressed(lzma_coder *coder)
|
||||
|
||||
|
||||
static lzma_ret
|
||||
lzma2_encode(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
lzma2_encode(void *coder_ptr, lzma_mf *restrict mf,
|
||||
uint8_t *restrict out, size_t *restrict out_pos,
|
||||
size_t out_size)
|
||||
{
|
||||
lzma_lzma2_coder *restrict coder = coder_ptr;
|
||||
|
||||
while (*out_pos < out_size)
|
||||
switch (coder->sequence) {
|
||||
case SEQ_INIT:
|
||||
@@ -262,8 +264,9 @@ lzma2_encode(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
|
||||
|
||||
static void
|
||||
lzma2_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
lzma2_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_lzma2_coder *coder = coder_ptr;
|
||||
lzma_free(coder->lzma, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
@@ -271,8 +274,10 @@ lzma2_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
|
||||
|
||||
static lzma_ret
|
||||
lzma2_encoder_options_update(lzma_coder *coder, const lzma_filter *filter)
|
||||
lzma2_encoder_options_update(void *coder_ptr, const lzma_filter *filter)
|
||||
{
|
||||
lzma_lzma2_coder *coder = coder_ptr;
|
||||
|
||||
// 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.
|
||||
@@ -304,36 +309,38 @@ lzma2_encoder_options_update(lzma_coder *coder, const lzma_filter *filter)
|
||||
|
||||
|
||||
static lzma_ret
|
||||
lzma2_encoder_init(lzma_lz_encoder *lz, lzma_allocator *allocator,
|
||||
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)
|
||||
lzma_lzma2_coder *coder = lz->coder;
|
||||
if (coder == NULL) {
|
||||
coder = lzma_alloc(sizeof(lzma_lzma2_coder), allocator);
|
||||
if (coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
lz->coder = coder;
|
||||
lz->code = &lzma2_encode;
|
||||
lz->end = &lzma2_encoder_end;
|
||||
lz->options_update = &lzma2_encoder_options_update;
|
||||
|
||||
lz->coder->lzma = NULL;
|
||||
coder->lzma = NULL;
|
||||
}
|
||||
|
||||
lz->coder->opt_cur = *(const lzma_options_lzma *)(options);
|
||||
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;
|
||||
coder->sequence = SEQ_INIT;
|
||||
coder->need_properties = true;
|
||||
coder->need_state_reset = false;
|
||||
coder->need_dictionary_reset
|
||||
= coder->opt_cur.preset_dict == NULL
|
||||
|| 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));
|
||||
return_if_error(lzma_lzma_encoder_create(&coder->lzma, allocator,
|
||||
&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
|
||||
@@ -349,7 +356,7 @@ lzma2_encoder_init(lzma_lz_encoder *lz, lzma_allocator *allocator,
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_lzma2_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_lzma2_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
return lzma_lz_encoder_init(
|
||||
@@ -364,7 +371,7 @@ lzma_lzma2_encoder_memusage(const void *options)
|
||||
if (lzma_mem == UINT64_MAX)
|
||||
return UINT64_MAX;
|
||||
|
||||
return sizeof(lzma_coder) + lzma_mem;
|
||||
return sizeof(lzma_lzma2_coder) + lzma_mem;
|
||||
}
|
||||
|
||||
|
||||
@@ -387,7 +394,17 @@ lzma_lzma2_props_encode(const void *options, uint8_t *out)
|
||||
if (d == UINT32_MAX)
|
||||
out[0] = 40;
|
||||
else
|
||||
out[0] = get_pos_slot(d + 1) - 24;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -31,11 +31,13 @@
|
||||
|
||||
|
||||
extern lzma_ret lzma_lzma2_encoder_init(
|
||||
lzma_next_coder *next, lzma_allocator *allocator,
|
||||
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
|
||||
|
||||
@@ -171,53 +171,54 @@ literal_init(probability (*probs)[LITERAL_CODER_SIZE],
|
||||
// Match distance //
|
||||
////////////////////
|
||||
|
||||
// Different set of probabilities is used for match distances that have very
|
||||
// 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 LEN_TO_POS_STATES 4
|
||||
#define DIST_STATES 4
|
||||
|
||||
// Macro to get the index of the appropriate probability array.
|
||||
#define get_len_to_pos_state(len) \
|
||||
((len) < LEN_TO_POS_STATES + MATCH_LEN_MIN \
|
||||
#define get_dist_state(len) \
|
||||
((len) < DIST_STATES + MATCH_LEN_MIN \
|
||||
? (len) - MATCH_LEN_MIN \
|
||||
: LEN_TO_POS_STATES - 1)
|
||||
: DIST_STATES - 1)
|
||||
|
||||
// The highest two bits of a match distance (pos slot) are encoded using six
|
||||
// bits. See fastpos.h for more explanation.
|
||||
#define POS_SLOT_BITS 6
|
||||
#define POS_SLOTS (1 << POS_SLOT_BITS)
|
||||
// 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 (pos slot) are always encoded using six bits, the
|
||||
// distances 0-3 don't need any additional bits to encode, since the pos
|
||||
// slot itself is the same as the actual distance. START_POS_MODEL_INDEX
|
||||
// indicates the first pos slot where at least one additional bit is needed.
|
||||
#define START_POS_MODEL_INDEX 4
|
||||
// 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:
|
||||
// - pos slot: the highest two bits
|
||||
// - 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 pos slot value of 14 is for distances 128-191 (see the table in
|
||||
// The distance slot value of 14 is for distances 128-191 (see the table in
|
||||
// fastpos.h to understand why).
|
||||
#define END_POS_MODEL_INDEX 14
|
||||
#define DIST_MODEL_END 14
|
||||
|
||||
// Pos slots that indicate a distance <= 127.
|
||||
#define FULL_DISTANCES_BITS (END_POS_MODEL_INDEX / 2)
|
||||
// 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_TABLE_SIZE (1 << ALIGN_BITS)
|
||||
#define ALIGN_MASK (ALIGN_TABLE_SIZE - 1)
|
||||
#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 REP_DISTANCES 4
|
||||
#define REPS 4
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
#include "lzma_decoder.h"
|
||||
#include "range_decoder.h"
|
||||
|
||||
// The macros unroll loops with switch statements.
|
||||
// Silence warnings about missing fall-through comments.
|
||||
#if TUKLIB_GNUC_REQ(7, 0)
|
||||
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_SMALL
|
||||
|
||||
@@ -161,7 +167,7 @@ typedef struct {
|
||||
} lzma_length_decoder;
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
typedef struct {
|
||||
///////////////////
|
||||
// Probabilities //
|
||||
///////////////////
|
||||
@@ -193,15 +199,15 @@ struct lzma_coder_s {
|
||||
/// 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 pos_slot[LEN_TO_POS_STATES][POS_SLOTS];
|
||||
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 - END_POS_MODEL_INDEX];
|
||||
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_TABLE_SIZE];
|
||||
probability pos_align[ALIGN_SIZE];
|
||||
|
||||
/// Length of a normal match
|
||||
lzma_length_decoder match_len_decoder;
|
||||
@@ -245,8 +251,8 @@ struct lzma_coder_s {
|
||||
SEQ_LITERAL_WRITE,
|
||||
SEQ_IS_REP,
|
||||
seq_len(SEQ_MATCH_LEN),
|
||||
seq_6(SEQ_POS_SLOT),
|
||||
SEQ_POS_MODEL,
|
||||
seq_6(SEQ_DIST_SLOT),
|
||||
SEQ_DIST_MODEL,
|
||||
SEQ_DIRECT,
|
||||
seq_4(SEQ_ALIGN),
|
||||
SEQ_EOPM,
|
||||
@@ -277,20 +283,26 @@ struct lzma_coder_s {
|
||||
/// If decoding a literal: match byte.
|
||||
/// If decoding a match: length of the match.
|
||||
uint32_t len;
|
||||
};
|
||||
} lzma_lzma1_decoder;
|
||||
|
||||
|
||||
static lzma_ret
|
||||
lzma_decode(lzma_coder *restrict coder, lzma_dict *restrict dictptr,
|
||||
lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
|
||||
const uint8_t *restrict in,
|
||||
size_t *restrict in_pos, size_t in_size)
|
||||
{
|
||||
lzma_lzma1_decoder *restrict coder = coder_ptr;
|
||||
|
||||
////////////////////
|
||||
// Initialization //
|
||||
////////////////////
|
||||
|
||||
if (!rc_read_init(&coder->rc, in, in_pos, in_size))
|
||||
return LZMA_OK;
|
||||
{
|
||||
const lzma_ret ret = rc_read_init(
|
||||
&coder->rc, in, in_pos, in_size);
|
||||
if (ret != LZMA_STREAM_END)
|
||||
return ret;
|
||||
}
|
||||
|
||||
///////////////
|
||||
// Variables //
|
||||
@@ -502,28 +514,28 @@ lzma_decode(lzma_coder *restrict coder, lzma_dict *restrict dictptr,
|
||||
|
||||
// Prepare to decode the highest two bits of the
|
||||
// match distance.
|
||||
probs = coder->pos_slot[get_len_to_pos_state(len)];
|
||||
probs = coder->dist_slot[get_dist_state(len)];
|
||||
symbol = 1;
|
||||
|
||||
#ifdef HAVE_SMALL
|
||||
case SEQ_POS_SLOT:
|
||||
case SEQ_DIST_SLOT:
|
||||
do {
|
||||
rc_bit(probs[symbol], , , SEQ_POS_SLOT);
|
||||
} while (symbol < POS_SLOTS);
|
||||
rc_bit(probs[symbol], , , SEQ_DIST_SLOT);
|
||||
} while (symbol < DIST_SLOTS);
|
||||
#else
|
||||
rc_bit_case(probs[symbol], , , SEQ_POS_SLOT0);
|
||||
rc_bit_case(probs[symbol], , , SEQ_POS_SLOT1);
|
||||
rc_bit_case(probs[symbol], , , SEQ_POS_SLOT2);
|
||||
rc_bit_case(probs[symbol], , , SEQ_POS_SLOT3);
|
||||
rc_bit_case(probs[symbol], , , SEQ_POS_SLOT4);
|
||||
rc_bit_case(probs[symbol], , , SEQ_POS_SLOT5);
|
||||
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 -= POS_SLOTS;
|
||||
symbol -= DIST_SLOTS;
|
||||
assert(symbol <= 63);
|
||||
|
||||
if (symbol < START_POS_MODEL_INDEX) {
|
||||
if (symbol < DIST_MODEL_START) {
|
||||
// Match distances [0, 3] have only two bits.
|
||||
rep0 = symbol;
|
||||
} else {
|
||||
@@ -533,7 +545,7 @@ lzma_decode(lzma_coder *restrict coder, lzma_dict *restrict dictptr,
|
||||
assert(limit >= 1 && limit <= 30);
|
||||
rep0 = 2 + (symbol & 1);
|
||||
|
||||
if (symbol < END_POS_MODEL_INDEX) {
|
||||
if (symbol < DIST_MODEL_END) {
|
||||
// Prepare to decode the low bits for
|
||||
// a distance of [4, 127].
|
||||
assert(limit <= 5);
|
||||
@@ -553,12 +565,12 @@ lzma_decode(lzma_coder *restrict coder, lzma_dict *restrict dictptr,
|
||||
- symbol - 1;
|
||||
symbol = 1;
|
||||
offset = 0;
|
||||
case SEQ_POS_MODEL:
|
||||
case SEQ_DIST_MODEL:
|
||||
#ifdef HAVE_SMALL
|
||||
do {
|
||||
rc_bit(probs[symbol], ,
|
||||
rep0 += 1 << offset,
|
||||
SEQ_POS_MODEL);
|
||||
SEQ_DIST_MODEL);
|
||||
} while (++offset < limit);
|
||||
#else
|
||||
switch (limit) {
|
||||
@@ -566,25 +578,25 @@ lzma_decode(lzma_coder *restrict coder, lzma_dict *restrict dictptr,
|
||||
assert(offset == 0);
|
||||
rc_bit(probs[symbol], ,
|
||||
rep0 += 1,
|
||||
SEQ_POS_MODEL);
|
||||
SEQ_DIST_MODEL);
|
||||
++offset;
|
||||
--limit;
|
||||
case 4:
|
||||
rc_bit(probs[symbol], ,
|
||||
rep0 += 1 << offset,
|
||||
SEQ_POS_MODEL);
|
||||
SEQ_DIST_MODEL);
|
||||
++offset;
|
||||
--limit;
|
||||
case 3:
|
||||
rc_bit(probs[symbol], ,
|
||||
rep0 += 1 << offset,
|
||||
SEQ_POS_MODEL);
|
||||
SEQ_DIST_MODEL);
|
||||
++offset;
|
||||
--limit;
|
||||
case 2:
|
||||
rc_bit(probs[symbol], ,
|
||||
rep0 += 1 << offset,
|
||||
SEQ_POS_MODEL);
|
||||
SEQ_DIST_MODEL);
|
||||
++offset;
|
||||
--limit;
|
||||
case 1:
|
||||
@@ -596,7 +608,7 @@ lzma_decode(lzma_coder *restrict coder, lzma_dict *restrict dictptr,
|
||||
// "symbol".
|
||||
rc_bit_last(probs[symbol], ,
|
||||
rep0 += 1 << offset,
|
||||
SEQ_POS_MODEL);
|
||||
SEQ_DIST_MODEL);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
@@ -637,7 +649,7 @@ lzma_decode(lzma_coder *restrict coder, lzma_dict *restrict dictptr,
|
||||
rc_bit(coder->pos_align[symbol], ,
|
||||
rep0 += 4, SEQ_ALIGN2);
|
||||
case SEQ_ALIGN3:
|
||||
// Like in SEQ_POS_MODEL, we don't
|
||||
// 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], ,
|
||||
@@ -836,23 +848,17 @@ out:
|
||||
|
||||
|
||||
static void
|
||||
lzma_decoder_uncompressed(lzma_coder *coder, lzma_vli uncompressed_size)
|
||||
lzma_decoder_uncompressed(void *coder_ptr, lzma_vli uncompressed_size)
|
||||
{
|
||||
lzma_lzma1_decoder *coder = coder_ptr;
|
||||
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)
|
||||
lzma_decoder_reset(void *coder_ptr, const void *opt)
|
||||
{
|
||||
lzma_lzma1_decoder *coder = coder_ptr;
|
||||
const lzma_options_lzma *options = opt;
|
||||
|
||||
// NOTE: We assume that lc/lp/pb are valid since they were
|
||||
@@ -891,10 +897,10 @@ lzma_decoder_reset(lzma_coder *coder, const void *opt)
|
||||
bit_reset(coder->is_rep2[i]);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < LEN_TO_POS_STATES; ++i)
|
||||
bittree_reset(coder->pos_slot[i], POS_SLOT_BITS);
|
||||
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 - END_POS_MODEL_INDEX; ++i)
|
||||
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);
|
||||
@@ -933,11 +939,11 @@ lzma_decoder_reset(lzma_coder *coder, const void *opt)
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_lzma_decoder_create(lzma_lz_decoder *lz, lzma_allocator *allocator,
|
||||
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);
|
||||
lz->coder = lzma_alloc(sizeof(lzma_lzma1_decoder), allocator);
|
||||
if (lz->coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
@@ -961,7 +967,7 @@ lzma_lzma_decoder_create(lzma_lz_decoder *lz, lzma_allocator *allocator,
|
||||
/// initialization (lzma_lzma_decoder_init() passes function pointer to
|
||||
/// the LZ initialization).
|
||||
static lzma_ret
|
||||
lzma_decoder_init(lzma_lz_decoder *lz, lzma_allocator *allocator,
|
||||
lzma_decoder_init(lzma_lz_decoder *lz, const lzma_allocator *allocator,
|
||||
const void *options, lzma_lz_options *lz_options)
|
||||
{
|
||||
if (!is_lclppb_valid(options))
|
||||
@@ -978,7 +984,7 @@ lzma_decoder_init(lzma_lz_decoder *lz, lzma_allocator *allocator,
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_lzma_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
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
|
||||
@@ -1010,7 +1016,8 @@ 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);
|
||||
return sizeof(lzma_lzma1_decoder)
|
||||
+ lzma_lz_decoder_memusage(opt->dict_size);
|
||||
}
|
||||
|
||||
|
||||
@@ -1025,7 +1032,7 @@ lzma_lzma_decoder_memusage(const void *options)
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_lzma_props_decode(void **options, lzma_allocator *allocator,
|
||||
lzma_lzma_props_decode(void **options, const lzma_allocator *allocator,
|
||||
const uint8_t *props, size_t props_size)
|
||||
{
|
||||
if (props_size != 5)
|
||||
|
||||
@@ -19,12 +19,13 @@
|
||||
|
||||
/// Allocates and initializes LZMA decoder
|
||||
extern lzma_ret lzma_lzma_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters);
|
||||
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, lzma_allocator *allocator,
|
||||
void **options, const lzma_allocator *allocator,
|
||||
const uint8_t *props, size_t props_size);
|
||||
|
||||
|
||||
@@ -40,7 +41,7 @@ extern bool lzma_lzma_lclppb_decode(
|
||||
/// 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, lzma_allocator *allocator,
|
||||
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
|
||||
|
||||
@@ -43,7 +43,7 @@ literal_matched(lzma_range_encoder *rc, probability *subcoder,
|
||||
|
||||
|
||||
static inline void
|
||||
literal(lzma_coder *coder, lzma_mf *mf, uint32_t position)
|
||||
literal(lzma_lzma1_encoder *coder, lzma_mf *mf, uint32_t position)
|
||||
{
|
||||
// Locate the literal byte to be encoded and the subcoder.
|
||||
const uint8_t cur_byte = mf->buffer[
|
||||
@@ -140,7 +140,7 @@ length(lzma_range_encoder *rc, lzma_length_encoder *lc,
|
||||
///////////
|
||||
|
||||
static inline void
|
||||
match(lzma_coder *coder, const uint32_t pos_state,
|
||||
match(lzma_lzma1_encoder *coder, const uint32_t pos_state,
|
||||
const uint32_t distance, const uint32_t len)
|
||||
{
|
||||
update_match(coder->state);
|
||||
@@ -148,28 +148,28 @@ match(lzma_coder *coder, const uint32_t pos_state,
|
||||
length(&coder->rc, &coder->match_len_encoder, pos_state, len,
|
||||
coder->fast_mode);
|
||||
|
||||
const uint32_t pos_slot = get_pos_slot(distance);
|
||||
const uint32_t len_to_pos_state = get_len_to_pos_state(len);
|
||||
rc_bittree(&coder->rc, coder->pos_slot[len_to_pos_state],
|
||||
POS_SLOT_BITS, pos_slot);
|
||||
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 (pos_slot >= START_POS_MODEL_INDEX) {
|
||||
const uint32_t footer_bits = (pos_slot >> 1) - 1;
|
||||
const uint32_t base = (2 | (pos_slot & 1)) << footer_bits;
|
||||
const uint32_t pos_reduced = distance - base;
|
||||
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 (pos_slot < END_POS_MODEL_INDEX) {
|
||||
// Careful here: base - pos_slot - 1 can be -1, but
|
||||
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->pos_special + base - pos_slot - 1,
|
||||
footer_bits, pos_reduced);
|
||||
coder->dist_special + base - dist_slot - 1,
|
||||
footer_bits, dist_reduced);
|
||||
} else {
|
||||
rc_direct(&coder->rc, pos_reduced >> ALIGN_BITS,
|
||||
rc_direct(&coder->rc, dist_reduced >> ALIGN_BITS,
|
||||
footer_bits - ALIGN_BITS);
|
||||
rc_bittree_reverse(
|
||||
&coder->rc, coder->pos_align,
|
||||
ALIGN_BITS, pos_reduced & ALIGN_MASK);
|
||||
&coder->rc, coder->dist_align,
|
||||
ALIGN_BITS, dist_reduced & ALIGN_MASK);
|
||||
++coder->align_price_count;
|
||||
}
|
||||
}
|
||||
@@ -187,7 +187,7 @@ match(lzma_coder *coder, const uint32_t pos_state,
|
||||
////////////////////
|
||||
|
||||
static inline void
|
||||
rep_match(lzma_coder *coder, const uint32_t pos_state,
|
||||
rep_match(lzma_lzma1_encoder *coder, const uint32_t pos_state,
|
||||
const uint32_t rep, const uint32_t len)
|
||||
{
|
||||
if (rep == 0) {
|
||||
@@ -231,7 +231,7 @@ rep_match(lzma_coder *coder, const uint32_t pos_state,
|
||||
//////////
|
||||
|
||||
static void
|
||||
encode_symbol(lzma_coder *coder, lzma_mf *mf,
|
||||
encode_symbol(lzma_lzma1_encoder *coder, lzma_mf *mf,
|
||||
uint32_t back, uint32_t len, uint32_t position)
|
||||
{
|
||||
const uint32_t pos_state = position & coder->pos_mask;
|
||||
@@ -247,7 +247,7 @@ encode_symbol(lzma_coder *coder, lzma_mf *mf,
|
||||
rc_bit(&coder->rc,
|
||||
&coder->is_match[coder->state][pos_state], 1);
|
||||
|
||||
if (back < REP_DISTANCES) {
|
||||
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);
|
||||
@@ -255,7 +255,7 @@ encode_symbol(lzma_coder *coder, lzma_mf *mf,
|
||||
} else {
|
||||
// Normal match
|
||||
rc_bit(&coder->rc, &coder->is_rep[coder->state], 0);
|
||||
match(coder, pos_state, back - REP_DISTANCES, len);
|
||||
match(coder, pos_state, back - REPS, len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,7 +265,7 @@ encode_symbol(lzma_coder *coder, lzma_mf *mf,
|
||||
|
||||
|
||||
static bool
|
||||
encode_init(lzma_coder *coder, lzma_mf *mf)
|
||||
encode_init(lzma_lzma1_encoder *coder, lzma_mf *mf)
|
||||
{
|
||||
assert(mf_position(mf) == 0);
|
||||
|
||||
@@ -293,7 +293,7 @@ encode_init(lzma_coder *coder, lzma_mf *mf)
|
||||
|
||||
|
||||
static void
|
||||
encode_eopm(lzma_coder *coder, uint32_t position)
|
||||
encode_eopm(lzma_lzma1_encoder *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);
|
||||
@@ -309,7 +309,7 @@ encode_eopm(lzma_coder *coder, uint32_t position)
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_lzma_encode(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
lzma_lzma_encode(lzma_lzma1_encoder *restrict coder, lzma_mf *restrict mf,
|
||||
uint8_t *restrict out, size_t *restrict out_pos,
|
||||
size_t out_size, uint32_t limit)
|
||||
{
|
||||
@@ -353,9 +353,9 @@ lzma_lzma_encode(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
|
||||
// Get optimal match (repeat position and length).
|
||||
// Value ranges for pos:
|
||||
// - [0, REP_DISTANCES): repeated match
|
||||
// - [REP_DISTANCES, UINT32_MAX):
|
||||
// match at (pos - REP_DISTANCES)
|
||||
// - [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]
|
||||
@@ -402,7 +402,7 @@ lzma_lzma_encode(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
|
||||
|
||||
static lzma_ret
|
||||
lzma_encode(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
lzma_encode(void *coder, lzma_mf *restrict mf,
|
||||
uint8_t *restrict out, size_t *restrict out_pos,
|
||||
size_t out_size)
|
||||
{
|
||||
@@ -464,7 +464,7 @@ length_encoder_reset(lzma_length_encoder *lencoder,
|
||||
bittree_reset(lencoder->high, LEN_HIGH_BITS);
|
||||
|
||||
if (!fast_mode)
|
||||
for (size_t pos_state = 0; pos_state < num_pos_states;
|
||||
for (uint32_t pos_state = 0; pos_state < num_pos_states;
|
||||
++pos_state)
|
||||
length_update_prices(lencoder, pos_state);
|
||||
|
||||
@@ -473,7 +473,8 @@ length_encoder_reset(lzma_length_encoder *lencoder,
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_lzma_encoder_reset(lzma_coder *coder, const lzma_options_lzma *options)
|
||||
lzma_lzma_encoder_reset(lzma_lzma1_encoder *coder,
|
||||
const lzma_options_lzma *options)
|
||||
{
|
||||
if (!is_options_valid(options))
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
@@ -487,7 +488,7 @@ lzma_lzma_encoder_reset(lzma_coder *coder, const lzma_options_lzma *options)
|
||||
|
||||
// State
|
||||
coder->state = STATE_LIT_LIT;
|
||||
for (size_t i = 0; i < REP_DISTANCES; ++i)
|
||||
for (size_t i = 0; i < REPS; ++i)
|
||||
coder->reps[i] = 0;
|
||||
|
||||
literal_init(coder->literal, options->lc, options->lp);
|
||||
@@ -505,14 +506,14 @@ lzma_lzma_encoder_reset(lzma_coder *coder, const lzma_options_lzma *options)
|
||||
bit_reset(coder->is_rep2[i]);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < FULL_DISTANCES - END_POS_MODEL_INDEX; ++i)
|
||||
bit_reset(coder->pos_special[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 < LEN_TO_POS_STATES; ++i)
|
||||
bittree_reset(coder->pos_slot[i], POS_SLOT_BITS);
|
||||
for (size_t i = 0; i < DIST_STATES; ++i)
|
||||
bittree_reset(coder->dist_slot[i], DIST_SLOT_BITS);
|
||||
|
||||
bittree_reset(coder->pos_align, ALIGN_BITS);
|
||||
bittree_reset(coder->dist_align, ALIGN_BITS);
|
||||
|
||||
// Length encoders
|
||||
length_encoder_reset(&coder->match_len_encoder,
|
||||
@@ -545,17 +546,18 @@ lzma_lzma_encoder_reset(lzma_coder *coder, const lzma_options_lzma *options)
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_lzma_encoder_create(lzma_coder **coder_ptr, lzma_allocator *allocator,
|
||||
lzma_lzma_encoder_create(void **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.
|
||||
// Allocate lzma_lzma1_encoder if it wasn't already allocated.
|
||||
if (*coder_ptr == NULL) {
|
||||
*coder_ptr = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
*coder_ptr = lzma_alloc(sizeof(lzma_lzma1_encoder), allocator);
|
||||
if (*coder_ptr == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
}
|
||||
|
||||
lzma_coder *coder = *coder_ptr;
|
||||
lzma_lzma1_encoder *coder = *coder_ptr;
|
||||
|
||||
// Set compression mode. We haven't validates the options yet,
|
||||
// but it's OK here, since nothing bad happens with invalid
|
||||
@@ -604,7 +606,7 @@ lzma_lzma_encoder_create(lzma_coder **coder_ptr, lzma_allocator *allocator,
|
||||
|
||||
|
||||
static lzma_ret
|
||||
lzma_encoder_init(lzma_lz_encoder *lz, lzma_allocator *allocator,
|
||||
lzma_encoder_init(lzma_lz_encoder *lz, const lzma_allocator *allocator,
|
||||
const void *options, lzma_lz_options *lz_options)
|
||||
{
|
||||
lz->code = &lzma_encode;
|
||||
@@ -614,7 +616,7 @@ lzma_encoder_init(lzma_lz_encoder *lz, lzma_allocator *allocator,
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_lzma_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_lzma_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
return lzma_lz_encoder_init(
|
||||
@@ -635,7 +637,7 @@ lzma_lzma_encoder_memusage(const void *options)
|
||||
if (lz_memusage == UINT64_MAX)
|
||||
return UINT64_MAX;
|
||||
|
||||
return (uint64_t)(sizeof(lzma_coder)) + lz_memusage;
|
||||
return (uint64_t)(sizeof(lzma_lzma1_encoder)) + lz_memusage;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -17,8 +17,12 @@
|
||||
#include "common.h"
|
||||
|
||||
|
||||
typedef struct lzma_lzma1_encoder_s lzma_lzma1_encoder;
|
||||
|
||||
|
||||
extern lzma_ret lzma_lzma_encoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters);
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters);
|
||||
|
||||
|
||||
extern uint64_t lzma_lzma_encoder_memusage(const void *options);
|
||||
@@ -35,16 +39,16 @@ extern bool lzma_lzma_lclppb_encode(
|
||||
|
||||
/// Initializes raw LZMA encoder; this is used by LZMA2.
|
||||
extern lzma_ret lzma_lzma_encoder_create(
|
||||
lzma_coder **coder_ptr, lzma_allocator *allocator,
|
||||
void **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);
|
||||
lzma_lzma1_encoder *coder, const lzma_options_lzma *options);
|
||||
|
||||
|
||||
extern lzma_ret lzma_lzma_encode(lzma_coder *restrict coder,
|
||||
extern lzma_ret lzma_lzma_encode(lzma_lzma1_encoder *restrict coder,
|
||||
lzma_mf *restrict mf, uint8_t *restrict out,
|
||||
size_t *restrict out_pos, size_t out_size,
|
||||
uint32_t read_limit);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "lzma_encoder_private.h"
|
||||
#include "memcmplen.h"
|
||||
|
||||
|
||||
#define change_pair(small_dist, big_dist) \
|
||||
@@ -17,7 +18,8 @@
|
||||
|
||||
|
||||
extern void
|
||||
lzma_lzma_optimum_fast(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
lzma_lzma_optimum_fast(lzma_lzma1_encoder *restrict coder,
|
||||
lzma_mf *restrict mf,
|
||||
uint32_t *restrict back_res, uint32_t *restrict len_res)
|
||||
{
|
||||
const uint32_t nice_len = mf->nice_len;
|
||||
@@ -46,7 +48,7 @@ lzma_lzma_optimum_fast(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
uint32_t rep_len = 0;
|
||||
uint32_t rep_index = 0;
|
||||
|
||||
for (uint32_t i = 0; i < REP_DISTANCES; ++i) {
|
||||
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;
|
||||
|
||||
@@ -57,9 +59,8 @@ lzma_lzma_optimum_fast(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
|
||||
// The first two bytes matched.
|
||||
// Calculate the length of the match.
|
||||
uint32_t len;
|
||||
for (len = 2; len < buf_avail
|
||||
&& buf[len] == buf_back[len]; ++len) ;
|
||||
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.
|
||||
@@ -79,8 +80,7 @@ lzma_lzma_optimum_fast(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
// 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
|
||||
+ REP_DISTANCES;
|
||||
*back_res = coder->matches[matches_count - 1].dist + REPS;
|
||||
*len_res = len_main;
|
||||
mf_skip(mf, len_main - 1);
|
||||
return;
|
||||
@@ -153,26 +153,17 @@ lzma_lzma_optimum_fast(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
// the old buf pointer instead of recalculating it with mf_ptr().
|
||||
++buf;
|
||||
|
||||
const uint32_t limit = len_main - 1;
|
||||
const uint32_t limit = my_max(2, len_main - 1);
|
||||
|
||||
for (uint32_t i = 0; i < REP_DISTANCES; ++i) {
|
||||
const uint8_t *const buf_back = buf - coder->reps[i] - 1;
|
||||
|
||||
if (not_equal_16(buf, buf_back))
|
||||
continue;
|
||||
|
||||
uint32_t len;
|
||||
for (len = 2; len < limit
|
||||
&& buf[len] == buf_back[len]; ++len) ;
|
||||
|
||||
if (len >= limit) {
|
||||
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 + REP_DISTANCES;
|
||||
*back_res = back_main + REPS;
|
||||
*len_res = len_main;
|
||||
mf_skip(mf, len_main - 2);
|
||||
return;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "lzma_encoder_private.h"
|
||||
#include "fastpos.h"
|
||||
#include "memcmplen.h"
|
||||
|
||||
|
||||
////////////
|
||||
@@ -18,7 +19,7 @@
|
||||
////////////
|
||||
|
||||
static uint32_t
|
||||
get_literal_price(const lzma_coder *const coder, const uint32_t pos,
|
||||
get_literal_price(const lzma_lzma1_encoder *const coder, const uint32_t pos,
|
||||
const uint32_t prev_byte, const bool match_mode,
|
||||
uint32_t match_byte, uint32_t symbol)
|
||||
{
|
||||
@@ -64,7 +65,7 @@ get_len_price(const lzma_length_encoder *const lencoder,
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
get_short_rep_price(const lzma_coder *const coder,
|
||||
get_short_rep_price(const lzma_lzma1_encoder *const coder,
|
||||
const lzma_lzma_state state, const uint32_t pos_state)
|
||||
{
|
||||
return rc_bit_0_price(coder->is_rep0[state])
|
||||
@@ -73,7 +74,7 @@ get_short_rep_price(const lzma_coder *const coder,
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
get_pure_rep_price(const lzma_coder *const coder, const uint32_t rep_index,
|
||||
get_pure_rep_price(const lzma_lzma1_encoder *const coder, const uint32_t rep_index,
|
||||
const lzma_lzma_state state, uint32_t pos_state)
|
||||
{
|
||||
uint32_t price;
|
||||
@@ -98,7 +99,7 @@ get_pure_rep_price(const lzma_coder *const coder, const uint32_t rep_index,
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
get_rep_price(const lzma_coder *const coder, const uint32_t rep_index,
|
||||
get_rep_price(const lzma_lzma1_encoder *const coder, const uint32_t rep_index,
|
||||
const uint32_t len, const lzma_lzma_state state,
|
||||
const uint32_t pos_state)
|
||||
{
|
||||
@@ -108,18 +109,18 @@ get_rep_price(const lzma_coder *const coder, const uint32_t rep_index,
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
get_pos_len_price(const lzma_coder *const coder, const uint32_t pos,
|
||||
get_dist_len_price(const lzma_lzma1_encoder *const coder, const uint32_t dist,
|
||||
const uint32_t len, const uint32_t pos_state)
|
||||
{
|
||||
const uint32_t len_to_pos_state = get_len_to_pos_state(len);
|
||||
const uint32_t dist_state = get_dist_state(len);
|
||||
uint32_t price;
|
||||
|
||||
if (pos < FULL_DISTANCES) {
|
||||
price = coder->distances_prices[len_to_pos_state][pos];
|
||||
if (dist < FULL_DISTANCES) {
|
||||
price = coder->dist_prices[dist_state][dist];
|
||||
} else {
|
||||
const uint32_t pos_slot = get_pos_slot_2(pos);
|
||||
price = coder->pos_slot_prices[len_to_pos_state][pos_slot]
|
||||
+ coder->align_prices[pos & ALIGN_MASK];
|
||||
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);
|
||||
@@ -129,55 +130,53 @@ get_pos_len_price(const lzma_coder *const coder, const uint32_t pos,
|
||||
|
||||
|
||||
static void
|
||||
fill_distances_prices(lzma_coder *coder)
|
||||
fill_dist_prices(lzma_lzma1_encoder *coder)
|
||||
{
|
||||
for (uint32_t len_to_pos_state = 0;
|
||||
len_to_pos_state < LEN_TO_POS_STATES;
|
||||
++len_to_pos_state) {
|
||||
for (uint32_t dist_state = 0; dist_state < DIST_STATES; ++dist_state) {
|
||||
|
||||
uint32_t *const pos_slot_prices
|
||||
= coder->pos_slot_prices[len_to_pos_state];
|
||||
uint32_t *const dist_slot_prices
|
||||
= coder->dist_slot_prices[dist_state];
|
||||
|
||||
// Price to encode the pos_slot.
|
||||
for (uint32_t pos_slot = 0;
|
||||
pos_slot < coder->dist_table_size; ++pos_slot)
|
||||
pos_slot_prices[pos_slot] = rc_bittree_price(
|
||||
coder->pos_slot[len_to_pos_state],
|
||||
POS_SLOT_BITS, pos_slot);
|
||||
// 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 pos_slot = END_POS_MODEL_INDEX;
|
||||
pos_slot < coder->dist_table_size; ++pos_slot)
|
||||
pos_slot_prices[pos_slot] += rc_direct_price(
|
||||
((pos_slot >> 1) - 1) - ALIGN_BITS);
|
||||
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
|
||||
// pos_slot, so they are used for coder->distances_prices
|
||||
// dist_slot, so they are used for coder->dist_prices
|
||||
// as is.
|
||||
for (uint32_t i = 0; i < START_POS_MODEL_INDEX; ++i)
|
||||
coder->distances_prices[len_to_pos_state][i]
|
||||
= pos_slot_prices[i];
|
||||
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 pos_slot and pos_special.
|
||||
// We do this in a loop separate from the above loop to avoid
|
||||
// redundant calls to get_pos_slot().
|
||||
for (uint32_t i = START_POS_MODEL_INDEX; i < FULL_DISTANCES; ++i) {
|
||||
const uint32_t pos_slot = get_pos_slot(i);
|
||||
const uint32_t footer_bits = ((pos_slot >> 1) - 1);
|
||||
const uint32_t base = (2 | (pos_slot & 1)) << footer_bits;
|
||||
// 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->pos_special + base - pos_slot - 1,
|
||||
coder->dist_special + base - dist_slot - 1,
|
||||
footer_bits, i - base);
|
||||
|
||||
for (uint32_t len_to_pos_state = 0;
|
||||
len_to_pos_state < LEN_TO_POS_STATES;
|
||||
++len_to_pos_state)
|
||||
coder->distances_prices[len_to_pos_state][i]
|
||||
= price + coder->pos_slot_prices[
|
||||
len_to_pos_state][pos_slot];
|
||||
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;
|
||||
@@ -186,11 +185,11 @@ fill_distances_prices(lzma_coder *coder)
|
||||
|
||||
|
||||
static void
|
||||
fill_align_prices(lzma_coder *coder)
|
||||
fill_align_prices(lzma_lzma1_encoder *coder)
|
||||
{
|
||||
for (uint32_t i = 0; i < ALIGN_TABLE_SIZE; ++i)
|
||||
for (uint32_t i = 0; i < ALIGN_SIZE; ++i)
|
||||
coder->align_prices[i] = rc_bittree_reverse_price(
|
||||
coder->pos_align, ALIGN_BITS, i);
|
||||
coder->dist_align, ALIGN_BITS, i);
|
||||
|
||||
coder->align_price_count = 0;
|
||||
return;
|
||||
@@ -222,7 +221,7 @@ make_short_rep(lzma_optimal *optimal)
|
||||
|
||||
|
||||
static void
|
||||
backward(lzma_coder *restrict coder, uint32_t *restrict len_res,
|
||||
backward(lzma_lzma1_encoder *restrict coder, uint32_t *restrict len_res,
|
||||
uint32_t *restrict back_res, uint32_t cur)
|
||||
{
|
||||
coder->opts_end_index = cur;
|
||||
@@ -270,7 +269,7 @@ backward(lzma_coder *restrict coder, uint32_t *restrict len_res,
|
||||
//////////
|
||||
|
||||
static inline uint32_t
|
||||
helper1(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
helper1(lzma_lzma1_encoder *restrict coder, lzma_mf *restrict mf,
|
||||
uint32_t *restrict back_res, uint32_t *restrict len_res,
|
||||
uint32_t position)
|
||||
{
|
||||
@@ -296,10 +295,10 @@ helper1(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
|
||||
const uint8_t *const buf = mf_ptr(mf) - 1;
|
||||
|
||||
uint32_t rep_lens[REP_DISTANCES];
|
||||
uint32_t rep_lens[REPS];
|
||||
uint32_t rep_max_index = 0;
|
||||
|
||||
for (uint32_t i = 0; i < REP_DISTANCES; ++i) {
|
||||
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)) {
|
||||
@@ -307,13 +306,9 @@ helper1(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t len_test;
|
||||
for (len_test = 2; len_test < buf_avail
|
||||
&& buf[len_test] == buf_back[len_test];
|
||||
++len_test) ;
|
||||
rep_lens[i] = lzma_memcmplen(buf, buf_back, 2, buf_avail);
|
||||
|
||||
rep_lens[i] = len_test;
|
||||
if (len_test > rep_lens[rep_max_index])
|
||||
if (rep_lens[i] > rep_lens[rep_max_index])
|
||||
rep_max_index = i;
|
||||
}
|
||||
|
||||
@@ -326,8 +321,7 @@ helper1(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
|
||||
|
||||
if (len_main >= nice_len) {
|
||||
*back_res = coder->matches[matches_count - 1].dist
|
||||
+ REP_DISTANCES;
|
||||
*back_res = coder->matches[matches_count - 1].dist + REPS;
|
||||
*len_res = len_main;
|
||||
mf_skip(mf, len_main - 1);
|
||||
return UINT32_MAX;
|
||||
@@ -381,7 +375,7 @@ helper1(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
|
||||
coder->opts[1].pos_prev = 0;
|
||||
|
||||
for (uint32_t i = 0; i < REP_DISTANCES; ++i)
|
||||
for (uint32_t i = 0; i < REPS; ++i)
|
||||
coder->opts[0].backs[i] = coder->reps[i];
|
||||
|
||||
uint32_t len = len_end;
|
||||
@@ -390,7 +384,7 @@ helper1(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
} while (--len >= 2);
|
||||
|
||||
|
||||
for (uint32_t i = 0; i < REP_DISTANCES; ++i) {
|
||||
for (uint32_t i = 0; i < REPS; ++i) {
|
||||
uint32_t rep_len = rep_lens[i];
|
||||
if (rep_len < 2)
|
||||
continue;
|
||||
@@ -426,14 +420,13 @@ helper1(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
for(; ; ++len) {
|
||||
const uint32_t dist = coder->matches[i].dist;
|
||||
const uint32_t cur_and_len_price = normal_match_price
|
||||
+ get_pos_len_price(coder,
|
||||
+ 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 + REP_DISTANCES;
|
||||
coder->opts[len].back_prev = dist + REPS;
|
||||
coder->opts[len].prev_1_is_literal = false;
|
||||
}
|
||||
|
||||
@@ -448,7 +441,7 @@ helper1(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
|
||||
helper2(lzma_lzma1_encoder *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)
|
||||
{
|
||||
@@ -463,7 +456,7 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
|
||||
if (coder->opts[cur].prev_2) {
|
||||
state = coder->opts[coder->opts[cur].pos_prev_2].state;
|
||||
|
||||
if (coder->opts[cur].back_prev_2 < REP_DISTANCES)
|
||||
if (coder->opts[cur].back_prev_2 < REPS)
|
||||
update_long_rep(state);
|
||||
else
|
||||
update_match(state);
|
||||
@@ -492,33 +485,33 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
|
||||
update_long_rep(state);
|
||||
} else {
|
||||
pos = coder->opts[cur].back_prev;
|
||||
if (pos < REP_DISTANCES)
|
||||
if (pos < REPS)
|
||||
update_long_rep(state);
|
||||
else
|
||||
update_match(state);
|
||||
}
|
||||
|
||||
if (pos < REP_DISTANCES) {
|
||||
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 < REP_DISTANCES; ++i)
|
||||
for (; i < REPS; ++i)
|
||||
reps[i] = coder->opts[pos_prev].backs[i];
|
||||
|
||||
} else {
|
||||
reps[0] = pos - REP_DISTANCES;
|
||||
reps[0] = pos - REPS;
|
||||
|
||||
for (uint32_t i = 1; i < REP_DISTANCES; ++i)
|
||||
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 < REP_DISTANCES; ++i)
|
||||
for (uint32_t i = 0; i < REPS; ++i)
|
||||
coder->opts[cur].backs[i] = reps[i];
|
||||
|
||||
const uint32_t cur_price = coder->opts[cur].price;
|
||||
@@ -572,11 +565,7 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
|
||||
const uint8_t *const buf_back = buf - reps[0] - 1;
|
||||
const uint32_t limit = my_min(buf_avail_full, nice_len + 1);
|
||||
|
||||
uint32_t len_test = 1;
|
||||
while (len_test < limit && buf[len_test] == buf_back[len_test])
|
||||
++len_test;
|
||||
|
||||
--len_test;
|
||||
const uint32_t len_test = lzma_memcmplen(buf, buf_back, 1, limit) - 1;
|
||||
|
||||
if (len_test >= 2) {
|
||||
lzma_lzma_state state_2 = state;
|
||||
@@ -611,15 +600,12 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
|
||||
|
||||
uint32_t start_len = 2; // speed optimization
|
||||
|
||||
for (uint32_t rep_index = 0; rep_index < REP_DISTANCES; ++rep_index) {
|
||||
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;
|
||||
for (len_test = 2; len_test < buf_avail
|
||||
&& buf[len_test] == buf_back[len_test];
|
||||
++len_test) ;
|
||||
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;
|
||||
@@ -728,14 +714,14 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
|
||||
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_pos_len_price(coder,
|
||||
+ 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 + REP_DISTANCES;
|
||||
= cur_back + REPS;
|
||||
coder->opts[cur + len_test].prev_1_is_literal = false;
|
||||
}
|
||||
|
||||
@@ -795,7 +781,7 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
|
||||
coder->opts[offset].prev_2 = true;
|
||||
coder->opts[offset].pos_prev_2 = cur;
|
||||
coder->opts[offset].back_prev_2
|
||||
= cur_back + REP_DISTANCES;
|
||||
= cur_back + REPS;
|
||||
}
|
||||
//}
|
||||
}
|
||||
@@ -811,7 +797,8 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
|
||||
|
||||
|
||||
extern void
|
||||
lzma_lzma_optimum_normal(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
lzma_lzma_optimum_normal(lzma_lzma1_encoder *restrict coder,
|
||||
lzma_mf *restrict mf,
|
||||
uint32_t *restrict back_res, uint32_t *restrict len_res,
|
||||
uint32_t position)
|
||||
{
|
||||
@@ -831,9 +818,9 @@ lzma_lzma_optimum_normal(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
// In liblzma they were moved into this single place.
|
||||
if (mf->read_ahead == 0) {
|
||||
if (coder->match_price_count >= (1 << 7))
|
||||
fill_distances_prices(coder);
|
||||
fill_dist_prices(coder);
|
||||
|
||||
if (coder->align_price_count >= ALIGN_TABLE_SIZE)
|
||||
if (coder->align_price_count >= ALIGN_SIZE)
|
||||
fill_align_prices(coder);
|
||||
}
|
||||
|
||||
@@ -845,7 +832,7 @@ lzma_lzma_optimum_normal(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
if (len_end == UINT32_MAX)
|
||||
return;
|
||||
|
||||
uint32_t reps[REP_DISTANCES];
|
||||
uint32_t reps[REPS];
|
||||
memcpy(reps, coder->reps, sizeof(reps));
|
||||
|
||||
uint32_t cur;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
//
|
||||
/// \file lzma_encoder_presets.c
|
||||
/// \brief Encoder presets
|
||||
/// \note xz needs this even when only decoding is enabled.
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
|
||||
@@ -64,12 +64,12 @@ typedef struct {
|
||||
uint32_t pos_prev; // pos_next;
|
||||
uint32_t back_prev;
|
||||
|
||||
uint32_t backs[REP_DISTANCES];
|
||||
uint32_t backs[REPS];
|
||||
|
||||
} lzma_optimal;
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
struct lzma_lzma1_encoder_s {
|
||||
/// Range encoder
|
||||
lzma_range_encoder rc;
|
||||
|
||||
@@ -77,7 +77,7 @@ struct lzma_coder_s {
|
||||
lzma_lzma_state state;
|
||||
|
||||
/// The four most recent match distances
|
||||
uint32_t reps[REP_DISTANCES];
|
||||
uint32_t reps[REPS];
|
||||
|
||||
/// Array of match candidates
|
||||
lzma_match matches[MATCH_LEN_MAX + 1];
|
||||
@@ -112,9 +112,9 @@ struct lzma_coder_s {
|
||||
probability is_rep1[STATES];
|
||||
probability is_rep2[STATES];
|
||||
probability is_rep0_long[STATES][POS_STATES_MAX];
|
||||
probability pos_slot[LEN_TO_POS_STATES][POS_SLOTS];
|
||||
probability pos_special[FULL_DISTANCES - END_POS_MODEL_INDEX];
|
||||
probability pos_align[ALIGN_TABLE_SIZE];
|
||||
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.
|
||||
@@ -122,12 +122,12 @@ struct lzma_coder_s {
|
||||
lzma_length_encoder rep_len_encoder;
|
||||
|
||||
// Price tables
|
||||
uint32_t pos_slot_prices[LEN_TO_POS_STATES][POS_SLOTS];
|
||||
uint32_t distances_prices[LEN_TO_POS_STATES][FULL_DISTANCES];
|
||||
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_TABLE_SIZE];
|
||||
uint32_t align_prices[ALIGN_SIZE];
|
||||
uint32_t align_price_count;
|
||||
|
||||
// Optimal
|
||||
@@ -138,10 +138,10 @@ struct lzma_coder_s {
|
||||
|
||||
|
||||
extern void lzma_lzma_optimum_fast(
|
||||
lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
lzma_lzma1_encoder *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,
|
||||
extern void lzma_lzma_optimum_normal(lzma_lzma1_encoder *restrict coder,
|
||||
lzma_mf *restrict mf, uint32_t *restrict back_res,
|
||||
uint32_t *restrict len_res, uint32_t position);
|
||||
|
||||
|
||||
@@ -14,9 +14,7 @@
|
||||
#ifndef LZMA_RANGE_COMMON_H
|
||||
#define LZMA_RANGE_COMMON_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "common.h"
|
||||
#endif
|
||||
#include "common.h"
|
||||
|
||||
|
||||
///////////////
|
||||
|
||||
@@ -25,20 +25,26 @@ typedef struct {
|
||||
|
||||
|
||||
/// Reads the first five bytes to initialize the range decoder.
|
||||
static inline bool
|
||||
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 false;
|
||||
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 true;
|
||||
return LZMA_STREAM_END;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
|
||||
static size_t
|
||||
arm_code(lzma_simple *simple lzma_attribute((__unused__)),
|
||||
arm_code(void *simple lzma_attribute((__unused__)),
|
||||
uint32_t now_pos, bool is_encoder,
|
||||
uint8_t *buffer, size_t size)
|
||||
{
|
||||
@@ -45,7 +45,7 @@ arm_code(lzma_simple *simple lzma_attribute((__unused__)),
|
||||
|
||||
|
||||
static lzma_ret
|
||||
arm_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
arm_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters, bool is_encoder)
|
||||
{
|
||||
return lzma_simple_coder_init(next, allocator, filters,
|
||||
@@ -54,7 +54,8 @@ arm_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_simple_arm_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_simple_arm_encoder_init(lzma_next_coder *next,
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
return arm_coder_init(next, allocator, filters, true);
|
||||
@@ -62,7 +63,8 @@ lzma_simple_arm_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_simple_arm_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_simple_arm_decoder_init(lzma_next_coder *next,
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
return arm_coder_init(next, allocator, filters, false);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
|
||||
static size_t
|
||||
armthumb_code(lzma_simple *simple lzma_attribute((__unused__)),
|
||||
armthumb_code(void *simple lzma_attribute((__unused__)),
|
||||
uint32_t now_pos, bool is_encoder,
|
||||
uint8_t *buffer, size_t size)
|
||||
{
|
||||
@@ -50,7 +50,7 @@ armthumb_code(lzma_simple *simple lzma_attribute((__unused__)),
|
||||
|
||||
|
||||
static lzma_ret
|
||||
armthumb_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
armthumb_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters, bool is_encoder)
|
||||
{
|
||||
return lzma_simple_coder_init(next, allocator, filters,
|
||||
@@ -60,7 +60,8 @@ armthumb_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
|
||||
extern lzma_ret
|
||||
lzma_simple_armthumb_encoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters)
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
return armthumb_coder_init(next, allocator, filters, true);
|
||||
}
|
||||
@@ -68,7 +69,8 @@ lzma_simple_armthumb_encoder_init(lzma_next_coder *next,
|
||||
|
||||
extern lzma_ret
|
||||
lzma_simple_armthumb_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters)
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
return armthumb_coder_init(next, allocator, filters, false);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
|
||||
static size_t
|
||||
ia64_code(lzma_simple *simple lzma_attribute((__unused__)),
|
||||
ia64_code(void *simple lzma_attribute((__unused__)),
|
||||
uint32_t now_pos, bool is_encoder,
|
||||
uint8_t *buffer, size_t size)
|
||||
{
|
||||
@@ -86,7 +86,7 @@ ia64_code(lzma_simple *simple lzma_attribute((__unused__)),
|
||||
|
||||
|
||||
static lzma_ret
|
||||
ia64_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
ia64_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters, bool is_encoder)
|
||||
{
|
||||
return lzma_simple_coder_init(next, allocator, filters,
|
||||
@@ -96,7 +96,8 @@ ia64_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
|
||||
extern lzma_ret
|
||||
lzma_simple_ia64_encoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters)
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
return ia64_coder_init(next, allocator, filters, true);
|
||||
}
|
||||
@@ -104,7 +105,8 @@ lzma_simple_ia64_encoder_init(lzma_next_coder *next,
|
||||
|
||||
extern lzma_ret
|
||||
lzma_simple_ia64_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters)
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
return ia64_coder_init(next, allocator, filters, false);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
|
||||
static size_t
|
||||
powerpc_code(lzma_simple *simple lzma_attribute((__unused__)),
|
||||
powerpc_code(void *simple lzma_attribute((__unused__)),
|
||||
uint32_t now_pos, bool is_encoder,
|
||||
uint8_t *buffer, size_t size)
|
||||
{
|
||||
@@ -49,7 +49,7 @@ powerpc_code(lzma_simple *simple lzma_attribute((__unused__)),
|
||||
|
||||
|
||||
static lzma_ret
|
||||
powerpc_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
powerpc_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters, bool is_encoder)
|
||||
{
|
||||
return lzma_simple_coder_init(next, allocator, filters,
|
||||
@@ -59,7 +59,8 @@ powerpc_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
|
||||
extern lzma_ret
|
||||
lzma_simple_powerpc_encoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters)
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
return powerpc_coder_init(next, allocator, filters, true);
|
||||
}
|
||||
@@ -67,7 +68,8 @@ lzma_simple_powerpc_encoder_init(lzma_next_coder *next,
|
||||
|
||||
extern lzma_ret
|
||||
lzma_simple_powerpc_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters)
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
return powerpc_coder_init(next, allocator, filters, false);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
/// Copied or encodes/decodes more data to out[].
|
||||
static lzma_ret
|
||||
copy_or_code(lzma_coder *coder, lzma_allocator *allocator,
|
||||
copy_or_code(lzma_simple_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)
|
||||
@@ -55,7 +55,7 @@ copy_or_code(lzma_coder *coder, lzma_allocator *allocator,
|
||||
|
||||
|
||||
static size_t
|
||||
call_filter(lzma_coder *coder, uint8_t *buffer, size_t size)
|
||||
call_filter(lzma_simple_coder *coder, uint8_t *buffer, size_t size)
|
||||
{
|
||||
const size_t filtered = coder->filter(coder->simple,
|
||||
coder->now_pos, coder->is_encoder,
|
||||
@@ -66,11 +66,13 @@ call_filter(lzma_coder *coder, uint8_t *buffer, size_t size)
|
||||
|
||||
|
||||
static lzma_ret
|
||||
simple_code(lzma_coder *coder, lzma_allocator *allocator,
|
||||
simple_code(void *coder_ptr, 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)
|
||||
{
|
||||
lzma_simple_coder *coder = coder_ptr;
|
||||
|
||||
// TODO: Add partial support for LZMA_SYNC_FLUSH. We can support it
|
||||
// in cases when the filter is able to filter everything. With most
|
||||
// simple filters it can be done at offset that is a multiple of 2,
|
||||
@@ -198,8 +200,9 @@ simple_code(lzma_coder *coder, lzma_allocator *allocator,
|
||||
|
||||
|
||||
static void
|
||||
simple_coder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
simple_coder_end(void *coder_ptr, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_simple_coder *coder = coder_ptr;
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
lzma_free(coder->simple, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
@@ -208,10 +211,12 @@ simple_coder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
|
||||
|
||||
static lzma_ret
|
||||
simple_coder_update(lzma_coder *coder, lzma_allocator *allocator,
|
||||
simple_coder_update(void *coder_ptr, const lzma_allocator *allocator,
|
||||
const lzma_filter *filters_null lzma_attribute((__unused__)),
|
||||
const lzma_filter *reversed_filters)
|
||||
{
|
||||
lzma_simple_coder *coder = coder_ptr;
|
||||
|
||||
// No update support, just call the next filter in the chain.
|
||||
return lzma_next_filter_update(
|
||||
&coder->next, allocator, reversed_filters + 1);
|
||||
@@ -219,59 +224,59 @@ simple_coder_update(lzma_coder *coder, lzma_allocator *allocator,
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_simple_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_simple_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters,
|
||||
size_t (*filter)(lzma_simple *simple, uint32_t now_pos,
|
||||
size_t (*filter)(void *simple, uint32_t now_pos,
|
||||
bool is_encoder, uint8_t *buffer, size_t size),
|
||||
size_t simple_size, size_t unfiltered_max,
|
||||
uint32_t alignment, bool is_encoder)
|
||||
{
|
||||
// Allocate memory for the lzma_coder structure if needed.
|
||||
if (next->coder == NULL) {
|
||||
// Allocate memory for the lzma_simple_coder structure if needed.
|
||||
lzma_simple_coder *coder = next->coder;
|
||||
if (coder == NULL) {
|
||||
// Here we allocate space also for the temporary buffer. We
|
||||
// need twice the size of unfiltered_max, because then it
|
||||
// is always possible to filter at least unfiltered_max bytes
|
||||
// more data in coder->buffer[] if it can be filled completely.
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder)
|
||||
coder = lzma_alloc(sizeof(lzma_simple_coder)
|
||||
+ 2 * unfiltered_max, allocator);
|
||||
if (next->coder == NULL)
|
||||
if (coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->coder = coder;
|
||||
next->code = &simple_code;
|
||||
next->end = &simple_coder_end;
|
||||
next->update = &simple_coder_update;
|
||||
|
||||
next->coder->next = LZMA_NEXT_CODER_INIT;
|
||||
next->coder->filter = filter;
|
||||
next->coder->allocated = 2 * unfiltered_max;
|
||||
coder->next = LZMA_NEXT_CODER_INIT;
|
||||
coder->filter = filter;
|
||||
coder->allocated = 2 * unfiltered_max;
|
||||
|
||||
// Allocate memory for filter-specific data structure.
|
||||
if (simple_size > 0) {
|
||||
next->coder->simple = lzma_alloc(
|
||||
simple_size, allocator);
|
||||
if (next->coder->simple == NULL)
|
||||
coder->simple = lzma_alloc(simple_size, allocator);
|
||||
if (coder->simple == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
} else {
|
||||
next->coder->simple = NULL;
|
||||
coder->simple = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (filters[0].options != NULL) {
|
||||
const lzma_options_bcj *simple = filters[0].options;
|
||||
next->coder->now_pos = simple->start_offset;
|
||||
if (next->coder->now_pos & (alignment - 1))
|
||||
coder->now_pos = simple->start_offset;
|
||||
if (coder->now_pos & (alignment - 1))
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
} else {
|
||||
next->coder->now_pos = 0;
|
||||
coder->now_pos = 0;
|
||||
}
|
||||
|
||||
// Reset variables.
|
||||
next->coder->is_encoder = is_encoder;
|
||||
next->coder->end_was_reached = false;
|
||||
next->coder->pos = 0;
|
||||
next->coder->filtered = 0;
|
||||
next->coder->size = 0;
|
||||
coder->is_encoder = is_encoder;
|
||||
coder->end_was_reached = false;
|
||||
coder->pos = 0;
|
||||
coder->filtered = 0;
|
||||
coder->size = 0;
|
||||
|
||||
return lzma_next_filter_init(
|
||||
&next->coder->next, allocator, filters + 1);
|
||||
return lzma_next_filter_init(&coder->next, allocator, filters + 1);
|
||||
}
|
||||
|
||||
@@ -17,44 +17,56 @@
|
||||
|
||||
|
||||
extern lzma_ret lzma_simple_x86_encoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters);
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters);
|
||||
|
||||
extern lzma_ret lzma_simple_x86_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters);
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters);
|
||||
|
||||
|
||||
extern lzma_ret lzma_simple_powerpc_encoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters);
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters);
|
||||
|
||||
extern lzma_ret lzma_simple_powerpc_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters);
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters);
|
||||
|
||||
|
||||
extern lzma_ret lzma_simple_ia64_encoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters);
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters);
|
||||
|
||||
extern lzma_ret lzma_simple_ia64_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters);
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters);
|
||||
|
||||
|
||||
extern lzma_ret lzma_simple_arm_encoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters);
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters);
|
||||
|
||||
extern lzma_ret lzma_simple_arm_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters);
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters);
|
||||
|
||||
|
||||
extern lzma_ret lzma_simple_armthumb_encoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters);
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters);
|
||||
|
||||
extern lzma_ret lzma_simple_armthumb_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters);
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters);
|
||||
|
||||
|
||||
extern lzma_ret lzma_simple_sparc_encoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters);
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters);
|
||||
|
||||
extern lzma_ret lzma_simple_sparc_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters);
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_simple_props_decode(void **options, lzma_allocator *allocator,
|
||||
lzma_simple_props_decode(void **options, const lzma_allocator *allocator,
|
||||
const uint8_t *props, size_t props_size)
|
||||
{
|
||||
if (props_size == 0)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include "simple_coder.h"
|
||||
|
||||
extern lzma_ret lzma_simple_props_decode(
|
||||
void **options, lzma_allocator *allocator,
|
||||
void **options, const lzma_allocator *allocator,
|
||||
const uint8_t *props, size_t props_size);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,9 +16,7 @@
|
||||
#include "simple_coder.h"
|
||||
|
||||
|
||||
typedef struct lzma_simple_s lzma_simple;
|
||||
|
||||
struct lzma_coder_s {
|
||||
typedef struct {
|
||||
/// Next filter in the chain
|
||||
lzma_next_coder next;
|
||||
|
||||
@@ -33,12 +31,12 @@ struct lzma_coder_s {
|
||||
|
||||
/// Pointer to filter-specific function, which does
|
||||
/// the actual filtering.
|
||||
size_t (*filter)(lzma_simple *simple, uint32_t now_pos,
|
||||
size_t (*filter)(void *simple, uint32_t now_pos,
|
||||
bool is_encoder, uint8_t *buffer, size_t size);
|
||||
|
||||
/// Pointer to filter-specific data, or NULL if filter doesn't need
|
||||
/// any extra data.
|
||||
lzma_simple *simple;
|
||||
void *simple;
|
||||
|
||||
/// The lowest 32 bits of the current position in the data. Most
|
||||
/// filters need this to do conversions between absolute and relative
|
||||
@@ -62,12 +60,13 @@ struct lzma_coder_s {
|
||||
|
||||
/// Temporary buffer
|
||||
uint8_t buffer[];
|
||||
};
|
||||
} lzma_simple_coder;
|
||||
|
||||
|
||||
extern lzma_ret lzma_simple_coder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters,
|
||||
size_t (*filter)(lzma_simple *simple, uint32_t now_pos,
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters,
|
||||
size_t (*filter)(void *simple, uint32_t now_pos,
|
||||
bool is_encoder, uint8_t *buffer, size_t size),
|
||||
size_t simple_size, size_t unfiltered_max,
|
||||
uint32_t alignment, bool is_encoder);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
|
||||
static size_t
|
||||
sparc_code(lzma_simple *simple lzma_attribute((__unused__)),
|
||||
sparc_code(void *simple lzma_attribute((__unused__)),
|
||||
uint32_t now_pos, bool is_encoder,
|
||||
uint8_t *buffer, size_t size)
|
||||
{
|
||||
@@ -57,7 +57,7 @@ sparc_code(lzma_simple *simple lzma_attribute((__unused__)),
|
||||
|
||||
|
||||
static lzma_ret
|
||||
sparc_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
sparc_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters, bool is_encoder)
|
||||
{
|
||||
return lzma_simple_coder_init(next, allocator, filters,
|
||||
@@ -67,7 +67,8 @@ sparc_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
|
||||
extern lzma_ret
|
||||
lzma_simple_sparc_encoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters)
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
return sparc_coder_init(next, allocator, filters, true);
|
||||
}
|
||||
@@ -75,7 +76,8 @@ lzma_simple_sparc_encoder_init(lzma_next_coder *next,
|
||||
|
||||
extern lzma_ret
|
||||
lzma_simple_sparc_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters)
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
return sparc_coder_init(next, allocator, filters, false);
|
||||
}
|
||||
|
||||
@@ -17,14 +17,14 @@
|
||||
#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
|
||||
|
||||
|
||||
struct lzma_simple_s {
|
||||
typedef struct {
|
||||
uint32_t prev_mask;
|
||||
uint32_t prev_pos;
|
||||
};
|
||||
} lzma_simple_x86;
|
||||
|
||||
|
||||
static size_t
|
||||
x86_code(lzma_simple *simple, uint32_t now_pos, bool is_encoder,
|
||||
x86_code(void *simple_ptr, uint32_t now_pos, bool is_encoder,
|
||||
uint8_t *buffer, size_t size)
|
||||
{
|
||||
static const bool MASK_TO_ALLOWED_STATUS[8]
|
||||
@@ -33,6 +33,7 @@ x86_code(lzma_simple *simple, uint32_t now_pos, bool is_encoder,
|
||||
static const uint32_t MASK_TO_BIT_NUMBER[8]
|
||||
= { 0, 1, 2, 2, 3, 3, 3, 3 };
|
||||
|
||||
lzma_simple_x86 *simple = simple_ptr;
|
||||
uint32_t prev_mask = simple->prev_mask;
|
||||
uint32_t prev_pos = simple->prev_pos;
|
||||
|
||||
@@ -123,15 +124,17 @@ x86_code(lzma_simple *simple, uint32_t now_pos, bool is_encoder,
|
||||
|
||||
|
||||
static lzma_ret
|
||||
x86_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
x86_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters, bool is_encoder)
|
||||
{
|
||||
const lzma_ret ret = lzma_simple_coder_init(next, allocator, filters,
|
||||
&x86_code, sizeof(lzma_simple), 5, 1, is_encoder);
|
||||
&x86_code, sizeof(lzma_simple_x86), 5, 1, is_encoder);
|
||||
|
||||
if (ret == LZMA_OK) {
|
||||
next->coder->simple->prev_mask = 0;
|
||||
next->coder->simple->prev_pos = (uint32_t)(-5);
|
||||
lzma_simple_coder *coder = next->coder;
|
||||
lzma_simple_x86 *simple = coder->simple;
|
||||
simple->prev_mask = 0;
|
||||
simple->prev_pos = (uint32_t)(-5);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -139,7 +142,8 @@ x86_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_simple_x86_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_simple_x86_encoder_init(lzma_next_coder *next,
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
return x86_coder_init(next, allocator, filters, true);
|
||||
@@ -147,7 +151,8 @@ lzma_simple_x86_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_simple_x86_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
lzma_simple_x86_decoder_init(lzma_next_coder *next,
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
return x86_coder_init(next, allocator, filters, false);
|
||||
|
||||
Reference in New Issue
Block a user