Bunch of liblzma API cleanups and fixes.
authorLasse Collin <lasse.collin@tukaani.org>
Mon, 15 Dec 2008 17:39:13 +0000 (19:39 +0200)
committerLasse Collin <lasse.collin@tukaani.org>
Mon, 15 Dec 2008 17:39:13 +0000 (19:39 +0200)
27 files changed:
src/liblzma/api/lzma.h
src/liblzma/api/lzma/base.h
src/liblzma/api/lzma/block.h
src/liblzma/api/lzma/check.h
src/liblzma/api/lzma/container.h
src/liblzma/api/lzma/delta.h
src/liblzma/api/lzma/filter.h
src/liblzma/api/lzma/index.h
src/liblzma/api/lzma/index_hash.h
src/liblzma/api/lzma/init.h
src/liblzma/api/lzma/lzma.h
src/liblzma/api/lzma/simple.h
src/liblzma/api/lzma/stream_flags.h
src/liblzma/api/lzma/version.h
src/liblzma/api/lzma/vli.h
src/liblzma/common/alone_decoder.c
src/liblzma/common/auto_decoder.c
src/liblzma/common/block_util.c
src/liblzma/common/common.c
src/liblzma/common/common.h
src/liblzma/common/easy.c
src/liblzma/common/filter_common.c
src/liblzma/common/index.c
src/liblzma/common/index_decoder.c
src/liblzma/common/stream_decoder.c
src/liblzma/lzma/lzma2_encoder.c
tests/test_index.c

index d954b8e..f852ef5 100644 (file)
@@ -30,7 +30,8 @@
  * liblzma API headers need some standard types and macros. To allow
  * including lzma.h without requiring the application to include other
  * headers first, lzma.h includes the required standard headers unless
- * they already seem to be included.
+ * they already seem to be included already or if LZMA_MANUAL_HEADERS
+ * has been defined.
  *
  * Here's what types and macros are needed and from which headers:
  *  - stddef.h: size_t, NULL
  *
  * The hacks below aren't perfect, specifically they assume that inttypes.h
  * exists and that it typedefs at least uint8_t, uint32_t, and uint64_t,
- * and that unsigned int is 32-bit. If your application already takes care
- * of setting up all the types properly (for example by using gnulib's
- * stdint.h or inttypes.h), feel free to define LZMA_MANUAL_HEADERS before
- * including lzma.h.
+ * and that, in case of incomplete inttypes.h, unsigned int is 32-bit.
+ * If the application already takes care of setting up all the types and
+ * macros properly (for example by using gnulib's stdint.h or inttypes.h),
+ * we try to detect that the macros are already defined and don't include
+ * inttypes.h here again. However, you may define LZMA_MANUAL_HEADERS to
+ * force this file to never include any system headers.
  *
  * Some could argue that liblzma API should provide all the required types,
  * for example lzma_uint64, LZMA_UINT64_C(n), and LZMA_UINT64_MAX. This was
  * types and macros in the standard headers.
  *
  * Note that liblzma API still has lzma_bool, because using stdbool.h would
- * break C89 and C++ programs on many systems.
+ * break C89 and C++ programs on many systems. sizeof(bool) in C99 isn't
+ * necessarily the same as sizeof(bool) in C++.
  */
 
-/* stddef.h even in C++ so that we get size_t in global namespace. */
-#include <stddef.h>
+#ifndef LZMA_MANUAL_HEADERS
+       /*
+        * I suppose this works portably also in C++. Note that in C++,
+        * we need to get size_t into the global namespace.
+        */
+       #include <stddef.h>
 
-#if !defined(UINT32_C) || !defined(UINT64_C) \
-               || !defined(UINT32_MAX) || !defined(UINT64_MAX)
-#      ifdef __cplusplus
-               /*
-                * C99 sections 7.18.2 and 7.18.4 specify that in C++
-                * implementations define the limit and constant macros only
-                * if specifically requested. Note that if you want the
-                * format macros too, you need to define __STDC_FORMAT_MACROS
-                * before including lzma.h, since re-including inttypes.h
-                * with __STDC_FORMAT_MACROS defined doesn't necessarily work.
-                */
-#              ifndef __STDC_LIMIT_MACROS
-#                      define __STDC_LIMIT_MACROS 1
-#              endif
-#              ifndef __STDC_CONSTANT_MACROS
-#                      define __STDC_CONSTANT_MACROS 1
+       /*
+        * Skip inttypes.h if we already have all the required macros. If we
+        * have the macros, we assume that we have the matching typedefs too.
+        */
+#      if !defined(UINT32_C) || !defined(UINT64_C) \
+                       || !defined(UINT32_MAX) || !defined(UINT64_MAX)
+#              ifdef __cplusplus
+                       /*
+                        * C99 sections 7.18.2 and 7.18.4 specify that in C++
+                        * implementations define the limit and constant
+                        * macros only if specifically requested. Note that
+                        * if you want the format macros (PRIu64 etc.) too,
+                        * you need to define __STDC_FORMAT_MACROS before
+                        * including lzma.h, since re-including inttypes.h
+                        * with __STDC_FORMAT_MACROS defined doesn't
+                        * necessarily work.
+                        */
+#                      ifndef __STDC_LIMIT_MACROS
+#                              define __STDC_LIMIT_MACROS 1
+#                      endif
+#                      ifndef __STDC_CONSTANT_MACROS
+#                              define __STDC_CONSTANT_MACROS 1
+#                      endif
 #              endif
-#      endif
 
-#      include <inttypes.h>
+#              include <inttypes.h>
 
-       /*
-        * Some old systems have only the typedefs in inttypes.h, and lack
-        * all the macros. For those systems, we need a few more hacks.
-        * We assume that unsigned int is 32-bit and unsigned long is either
-        * 32-bit or 64-bit. If these hacks aren't enough, the application
-        * has to use setup the types manually before including lzma.h.
-        */
-#      ifndef UINT32_C
-#              define UINT32_C(n) n # U
-#      endif
+               /*
+                * Some old systems have only the typedefs in inttypes.h, and
+                * lack all the macros. For those systems, we need a few more
+                * hacks. We assume that unsigned int is 32-bit and unsigned
+                * long is either 32-bit or 64-bit. If these hacks aren't
+                * enough, the application has to setup the types manually
+                * before including lzma.h.
+                */
+#              ifndef UINT32_C
+#                      define UINT32_C(n) n # U
+#              endif
 
-#      ifndef UINT64_C
-               /* Get ULONG_MAX. */
-#              ifndef __cplusplus
+#              ifndef UINT64_C
+                       /* Get ULONG_MAX. */
 #                      include <limits.h>
-#              else
-#                      include <climits>
-#              endif
-#              if ULONG_MAX == 4294967295UL
-#                      define UINT64_C(n) n ## ULL
-#              else
-#                      define UINT64_C(n) n ## UL
+#                      if ULONG_MAX == 4294967295UL
+#                              define UINT64_C(n) n ## ULL
+#                      else
+#                              define UINT64_C(n) n ## UL
+#                      endif
 #              endif
-#      endif
 
-#      ifndef UINT32_MAX
-#              define UINT32_MAX (UINT32_C(4294967295))
-#      endif
+#              ifndef UINT32_MAX
+#                      define UINT32_MAX (UINT32_C(4294967295))
+#              endif
 
-#      ifndef UINT64_MAX
-#              define UINT64_MAX (UINT64_C(18446744073709551615))
+#              ifndef UINT64_MAX
+#                      define UINT64_MAX (UINT64_C(18446744073709551615))
+#              endif
 #      endif
-#endif
+#endif /* ifdef LZMA_MANUAL_HEADERS */
 
 
 /******************
 #                      define lzma_restrict
 #              endif
 #      endif
-
-#      define lzma_attr_warn_unused_result
 #endif
 
 
@@ -204,10 +214,10 @@ extern "C" {
 
 /* Advanced features */
 #include "lzma/alignment.h" /* FIXME */
+#include "lzma/stream_flags.h"
 #include "lzma/block.h"
 #include "lzma/index.h"
 #include "lzma/index_hash.h"
-#include "lzma/stream_flags.h"
 
 /*
  * All subheaders included. Undefine LZMA_H_INTERNAL to prevent applications
index 54ac308..bc1aff7 100644 (file)
@@ -95,23 +95,23 @@ typedef enum {
                /**<
                 * \brief       Cannot calculate the integrity check
                 *
-                * The usage of this return value is slightly different in
-                * encoders and decoders.
+                * The usage of this return value is different in encoders
+                * and decoders.
                 *
                 * Encoders can return this value only from the initialization
                 * function. If initialization fails with this value, the
                 * encoding cannot be done, because there's no way to produce
                 * output with the correct integrity check.
                 *
-                * Decoders can return this value only from the lzma_code
-                * function and only if the LZMA_TELL_UNSUPPORTED_CHECK flag
-                * was used when initializing the decoder. The decoding can
-                * still be continued normally even if the check type is
-                * unsupported, but naturally the check will not be validated,
-                * and possible errors may go undetected.
+                * Decoders can return this value only from lzma_code() and
+                * only if the LZMA_TELL_UNSUPPORTED_CHECK flag was used when
+                * initializing the decoder. The decoding can still be
+                * continued normally even if the check type is unsupported,
+                * but naturally the check will not be validated, and possible
+                * errors may go undetected.
                 *
                 * With decoder, it is possible to call lzma_get_check()
-                * immediatelly after lzma_code has returned
+                * immediatelly after lzma_code() has returned
                 * LZMA_UNSUPPORTED_CHECK. This way it is possible to find
                 * out what the unsupported Check ID was.
                 */
@@ -136,8 +136,9 @@ typedef enum {
                 * Memory allocation failed, or the size of the allocation
                 * would be greater than SIZE_MAX.
                 *
-                * Due to lazy coding, the coding cannot be continued even
-                * if more memory were made available after LZMA_MEM_ERROR.
+                * Due to internal implementation reasons, the coding cannot
+                * be continued even if more memory were made available after
+                * LZMA_MEM_ERROR.
                 */
 
        LZMA_MEMLIMIT_ERROR     = 6,
@@ -146,19 +147,18 @@ typedef enum {
                 *
                 * Decoder would need more memory than allowed by the
                 * specified memory usage limit. To continue decoding,
-                * the memory usage limit has to be increased. See functions
-                * lzma_memlimit_get() and lzma_memlimit_set().
+                * the memory usage limit has to be increased with
+                * lzma_memlimit().
                 */
 
        LZMA_FORMAT_ERROR       = 7,
                /**<
-                * \brief       Unknown file format
+                * \brief       File format not recognized
                 *
                 * The decoder did not recognize the input as supported file
                 * format. This error can occur, for example, when trying to
-                * decode LZMA_Alone format file with lzma_stream_decoder,
-                * because lzma_stream_decoder accepts only the new .lzma
-                * format.
+                * decode .lzma format file with lzma_stream_decoder,
+                * because lzma_stream_decoder accepts only the .xz format.
                 */
 
        LZMA_OPTIONS_ERROR      = 8,
@@ -185,7 +185,7 @@ typedef enum {
                 * format would be exceeded. These limits are huge, thus
                 * getting this error from an encoder is mostly theoretical.
                 * For example, the maximum compressed and uncompressed
-                * size of a Stream created with lzma_stream_encoder is
+                * size of a .xz Stream created with lzma_stream_encoder is
                 * 2^63 - 1 bytes (one byte less than 8 EiB).
                 *
                 * Decoders return this error if the input data is corrupt.
@@ -209,7 +209,7 @@ typedef enum {
                 * Typically the first call to lzma_code() that can do no
                 * progress returns LZMA_OK instead of LZMA_BUF_ERROR. Only
                 * the second consecutive call doing no progress will return
-                * LZMA_BUF_ERROR. This is by design.
+                * LZMA_BUF_ERROR. This is intentional.
                 *
                 * With zlib, Z_BUF_ERROR may be returned even if the
                 * application is doing nothing wrong. The above hack
@@ -263,10 +263,7 @@ typedef enum {
                 * lzma_code() call.
                 *
                 * Decoder: Decode as much input as possible and produce as
-                * much output as possible. This action provides best
-                * throughput, but may introduce latency, because the
-                * decoder may decode more data into its internal buffers
-                * than that fits into next_out.
+                * much output as possible.
                 */
 
        LZMA_SYNC_FLUSH = 1,
@@ -297,30 +294,22 @@ typedef enum {
                /**<
                 * \brief       Make all the input available at output
                 *
-                * This is like LZMA_SYNC_FLUSH except that this resets the
-                * internal encoder state.
-                *
-                *
-                *
-                * Finishes encoding of the current Data Block. All the input
-                * data going to the current Data Block must have been given
+                * Finish encoding of the current Block. All the input
+                * data going to the current Block must have been given
                 * to the encoder (the last bytes can still be pending in
                 * next_in). Call lzma_code() with LZMA_FULL_FLUSH until
                 * it returns LZMA_STREAM_END. Then continue normally with
                 * LZMA_RUN or finish the Stream with LZMA_FINISH.
                 *
-                * This action is supported only by Stream encoder and easy
-                * encoder (which uses Stream encoder). If there is no
-                * unfinished Block, no empty Block is created.
+                * This action is currently supported only by Stream encoder
+                * and easy encoder (which uses Stream encoder). If there is
+                * no unfinished Block, no empty Block is created.
                 */
 
        LZMA_FINISH = 3
                /**<
                 * \brief       Finish the coding operation
                 *
-                *
-                *
-                *
                 * Finishes the coding operation. All the input data must
                 * have been given to the encoder (the last bytes can still
                 * be pending in next_in). Call lzma_code() with LZMA_FINISH
@@ -341,8 +330,8 @@ typedef enum {
  * \brief       Custom functions for memory handling
  *
  * A pointer to lzma_allocator may be passed via lzma_stream structure
- * to liblzma, and some advanced function take pointer lzma_allocator as
- * a separate function argument. The library will use the functions
+ * to liblzma, and some advanced functions take a pointer to lzma_allocator
+ * as a separate function argument. The library will use the functions
  * specified in lzma_allocator for memory handling instead of the default
  * malloc() and free().
  *
@@ -354,31 +343,32 @@ typedef enum {
  */
 typedef struct {
        /**
-        * \brief       Pointer to custom memory allocation function
+        * \brief       Pointer to custom memory allocation function
         *
         * If you don't want a custom allocator, but still want
         * custom free(), set this to NULL and liblzma will use
         * the standard malloc().
         *
         * \param       opaque  lzma_allocator.opaque (see below)
-        * \param       nmemb   Number of elements like in calloc().
-        *                      liblzma will always set nmemb to 1.
-        *                      This argument exists only for
+        * \param       nmemb   Number of elements like in calloc(). liblzma
+        *                      will always set nmemb to 1, so it is safe to
+        *                      ignore nmemb in a custom allocator if you like.
+        *                      The nmemb argument exists only for
         *                      compatibility with zlib and libbzip2.
         * \param       size    Size of an element in bytes.
         *                      liblzma never sets this to zero.
         *
         * \return      Pointer to the beginning of a memory block of
-        *              size nmemb * size, or NULL if allocation fails
+        *              `size' bytes, or NULL if allocation fails
         *              for some reason. When allocation fails, functions
         *              of liblzma return LZMA_MEM_ERROR.
         *
         * For performance reasons, the allocator should not waste time
         * zeroing the allocated buffers. This is not only about speed, but
         * also memory usage, since the operating system kernel doesn't
-        * necessarily allocate the requested memory until it is actually
-        * used. With small input files liblzma may actually need only a
-        * fraction of the memory that it requested for allocation.
+        * necessarily allocate the requested memory in physical memory until
+        * it is actually used. With small input files liblzma may actually
+        * need only a fraction of the memory that it requested for allocation.
         *
         * \note        LZMA_MEM_ERROR is also used when the size of the
         *              allocation would be greater than SIZE_MAX. Thus,
@@ -389,7 +379,7 @@ typedef struct {
        void *(*alloc)(void *opaque, size_t nmemb, size_t size);
 
        /**
-        * \brief       Pointer to custom memory freeing function
+        * \brief       Pointer to custom memory freeing function
         *
         * If you don't want a custom freeing function, but still
         * want a custom allocator, set this to NULL and liblzma
@@ -432,17 +422,22 @@ typedef struct lzma_internal_s lzma_internal;
  *   - defining custom memory hander functions; and
  *   - holding a pointer to coder-specific internal data structures.
  *
- * The typical usage
+ * Typical usage:
  *
  *  - After allocating lzma_stream (on stack or with malloc()), it must be
  *    initialized to LZMA_STREAM_INIT (see LZMA_STREAM_INIT for details).
  *
  *  - Initialize a coder to the lzma_stream, for example by using
- *    lzma_easy_encoder() or lzma_auto_decoder(). In contrast to zlib,
- *    strm->next_in and strm->next_out are ignored by all initialization
- *    functions, thus it is safe to not initialize them yet. The
- *    initialization functions always set strm->total_in and strm->total_out
- *    to zero.
+ *    lzma_easy_encoder() or lzma_auto_decoder(). Some notes:
+ *      - In contrast to zlib, strm->next_in and strm->next_out are
+ *        ignored by all initialization functions, thus it is safe
+ *        to not initialize them yet.
+ *      - The initialization functions always set strm->total_in and
+ *        strm->total_out to zero.
+ *      - If the initialization function fails, no memory is left allocated
+ *        that would require freeing with lzma_end() even if some memory was
+ *        associated with the lzma_stream structure when the initialization
+ *        function was called.
  *
  *  - Use lzma_code() to do the actual work.
  *
@@ -451,11 +446,12 @@ typedef struct lzma_internal_s lzma_internal;
  *    function without calling lzma_end() first. Old allocations are
  *    automatically freed.
  *
- *  - Finally, use lzma_end() to free the allocated memory.
+ *  - Finally, use lzma_end() to free the allocated memory. lzma_end() never
+ *    frees the lzma_stream structure itself.
  *
- * Application may modify values of total_in and total_out as it wants.
+ * 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 liblzma doesn't use the values internally.
+ * written, but aren't used for anything else.
  */
 typedef struct {
        const uint8_t *next_in; /**< Pointer to the next input byte. */
@@ -475,7 +471,7 @@ typedef struct {
        /** Internal state is not visible to applications. */
        lzma_internal *internal;
 
-       /**
+       /*
         * Reserved space to allow possible future extensions without
         * breaking the ABI. Excluding the initialization of this structure,
         * you should not touch these, because the names of these variables
@@ -510,11 +506,12 @@ typedef struct {
  *     *strm = tmp;
  */
 #define LZMA_STREAM_INIT \
-       { NULL, 0, 0, NULL, 0, 0, NULL, NULL, NULL, NULL, 0, 0, 0, 0 }
+       { NULL, 0, 0, NULL, 0, 0, NULL, NULL, \
+       NULL, NULL, 0, 0, LZMA_RESERVED_ENUM, LZMA_RESERVED_ENUM }
 
 
 /**
- * \brief       Encodes or decodes data
+ * \brief       Encode or decode data
  *
  * Once the lzma_stream has been successfully initialized (e.g. with
  * lzma_stream_encoder()), the actual encoding or decoding is done
@@ -531,13 +528,68 @@ extern lzma_ret lzma_code(lzma_stream *strm, lzma_action action)
 
 
 /**
- * \brief       Frees memory allocated for the coder data structures
+ * \brief       Free memory allocated for the coder data structures
  *
  * \param       strm    Pointer to lzma_stream that is at least initialized
  *                      with LZMA_STREAM_INIT.
  *
+ * After lzma_end(strm), strm->internal is guaranteed to be NULL. No other
+ * members of the lzma_stream structure are touched.
+ *
  * \note        zlib indicates an error if application end()s unfinished
- *              stream. liblzma doesn't do this, and assumes that
+ *              stream structure. liblzma doesn't do this, and assumes that
  *              application knows what it is doing.
  */
 extern void lzma_end(lzma_stream *strm);
+
+
+/**
+ * \brief       Get the memory usage of decoder filter chain
+ *
+ * This function is currently supported only when *strm has been initialized
+ * with a function that takes a memlimit argument. With other functions, you
+ * should use e.g. lzma_raw_encoder_memusage() or lzma_raw_decoder_memusage()
+ * to estimate the memory requirements.
+ *
+ * This function is useful e.g. after LZMA_MEMLIMIT_ERROR to find out how big
+ * the memory usage limit should have been to decode the input. Note that
+ * this may give misleading information if decoding .xz Streams that have
+ * multiple Blocks, because each Block can have different memory requirements.
+ *
+ * \return      Rough estimate of how much memory is currently allocated
+ *              for the filter decoders. If no filter chain is currently
+ *              allocated, some non-zero value is still returned, which is
+ *              less than or equal to what any filter chain would indicate
+ *              as its memory requirement.
+ *
+ *              If this function isn't supported by *strm or some other error
+ *              occurs, zero is returned.
+ */
+extern uint64_t lzma_memusage(const lzma_stream *strm);
+
+
+/**
+ * \brief       Get the current memory usage limit
+ *
+ * This function is supported only when *strm has been initialized with
+ * a function that takes a memlimit argument.
+ *
+ * \return      On success, the current memory usage limit is returned
+ *              (always non-zero). On error, zero is returned.
+ */
+extern uint64_t lzma_memlimit_get(const lzma_stream *strm);
+
+
+/**
+ * \brief       Set the memory usage limit
+ *
+ * This function is supported only when *strm has been initialized with
+ * a function that takes a memlimit argument.
+ *
+ * \return      - LZMA_OK: New memory usage limit successfully set.
+ *              - LZMA_MEMLIMIT_ERROR: The new limit is too small.
+ *                The limit was not changed.
+ *              - LZMA_PROG_ERROR: Invalid arguments, e.g. *strm doesn't
+ *                support memory usage limit or memlimit was zero.
+ */
+extern lzma_ret lzma_memlimit_set(lzma_stream *strm, uint64_t memlimit);
index 06c1633..2702cd5 100644 (file)
 
 
 /**
- * \brief       Options for the Block Header encoder and decoder
+ * \brief       Options for the Block and Block Header encoders and decoders
  *
- * Different things use different parts of this structure. Some read
- * some members, other functions write, and some do both. Only the
+ * Different Block handling functions use different parts of this structure.
+ * Some read some members, other functions write, and some do both. Only the
  * members listed for reading need to be initialized when the specified
  * functions are called. The members marked for writing will be assigned
  * new values at some point either by calling the given function or by
  */
 typedef struct {
        /**
-        * \brief       Size of the Block Header
+        * \brief       Size of the Block Header field
+        *
+        * This is always a multiple of four.
         *
         * Read by:
         *  - lzma_block_header_encode()
         *  - lzma_block_header_decode()
+        *  - lzma_block_compressed_size()
+        *  - lzma_block_unpadded_size()
+        *  - lzma_block_total_size()
         *  - lzma_block_decoder()
         *
         * Written by:
@@ -50,12 +55,15 @@ typedef struct {
        /**
         * \brief       Type of integrity Check
         *
-        * The type of the integrity Check is not stored into the Block
-        * Header, thus its value must be provided also when decoding.
+        * The Check ID is not stored into the Block Header, thus its value
+        * must be provided also when decoding.
         *
         * Read by:
         *  - lzma_block_header_encode()
         *  - lzma_block_header_decode()
+        *  - lzma_block_compressed_size()
+        *  - lzma_block_unpadded_size()
+        *  - lzma_block_total_size()
         *  - lzma_block_encoder()
         *  - lzma_block_decoder()
         */
@@ -64,19 +72,50 @@ typedef struct {
        /**
         * \brief       Size of the Compressed Data in bytes
         *
-        * Usually you don't know this value when encoding in streamed mode.
-        * In non-streamed mode you can reserve space for this field when
-        * encoding the Block Header the first time, and then re-encode the
-        * Block Header and copy it over the original one after the encoding
-        * of the Block has been finished.
+        * Encoding: If this is not LZMA_VLI_UNKNOWN, Block Header encoder
+        * will store this value to the Block Header. Block encoder doesn't
+        * care about this value, but will set it once the encoding has been
+        * finished.
+        *
+        * Decoding: If this is not LZMA_VLI_UNKNOWN, Block decoder will
+        * verify that the size of the Compressed Data field matches
+        * compressed_size.
+        *
+        * Usually you don't know this value when encoding in streamed mode,
+        * and thus cannot write this field into the Block Header.
+        *
+        * In non-streamed mode you can reserve space for this field before
+        * encoding the actual Block. After encoding the data, finish the
+        * Block by encoding the Block Header. Steps in detail:
+        *
+        *  - Set compressed_size to some big enough value. If you don't know
+        *    better, use LZMA_VLI_MAX, but remember that bigger values take
+        *    more space in Block Header.
+        *
+        *  - Call lzma_block_header_size() to see how much space you need to
+        *    reserve for the Block Header.
+        *
+        *  - Encode the Block using lzma_block_encoder() and lzma_code().
+        *    It sets compressed_size to the correct value.
+        *
+        *  - Use lzma_block_header_encode() to encode the Block Header.
+        *    Because space was reserved in the first step, you don't need
+        *    to call lzma_block_header_size() anymore, because due to
+        *    reserving, header_size has to be big enough. If it is "too big",
+        *    lzma_block_header_encode() will add enough Header Padding to
+        *    make Block Header to match the size specified by header_size.
         *
         * Read by:
         *  - lzma_block_header_size()
         *  - lzma_block_header_encode()
+        *  - lzma_block_compressed_size()
+        *  - lzma_block_unpadded_size()
+        *  - lzma_block_total_size()
         *  - lzma_block_decoder()
         *
         * Written by:
         *  - lzma_block_header_decode()
+        *  - lzma_block_compressed_size()
         *  - lzma_block_encoder()
         *  - lzma_block_decoder()
         */
@@ -85,18 +124,11 @@ typedef struct {
        /**
         * \brief       Uncompressed Size in bytes
         *
-        * Encoder: If this value is not LZMA_VLI_UNKNOWN, it is stored
-        * to the Uncompressed Size field in the Block Header. The real
-        * uncompressed size of the data being compressed must match
-        * the Uncompressed Size or LZMA_OPTIONS_ERROR is returned.
+        * This is handled very similarly to compressed_size above.
         *
-        * If Uncompressed Size is unknown, End of Payload Marker must
-        * be used. If uncompressed_size == LZMA_VLI_UNKNOWN and
-        * has_eopm == 0, LZMA_OPTIONS_ERROR will be returned.
-        *
-        * Decoder: If this value is not LZMA_VLI_UNKNOWN, it is
-        * compared to the real Uncompressed Size. If they do not match,
-        * LZMA_OPTIONS_ERROR is returned.
+        * Unlike compressed_size, uncompressed_size is needed by fewer
+        * functions. This is because uncompressed_size isn't needed to
+        * validate that Block stays within proper limits.
         *
         * Read by:
         *  - lzma_block_header_size()
@@ -140,7 +172,7 @@ typedef struct {
 
 
 /**
- * \brief       Decodes the Block Header Size field
+ * \brief       Decode the Block Header Size field
  *
  * To decode Block Header using lzma_block_header_decode(), the size of the
  * Block Header has to be known and stored into lzma_block.header_size.
@@ -154,100 +186,130 @@ typedef struct {
 
 
 /**
- * \brief       Calculates the size of Block Header
+ * \brief       Calculate Block Header Size
+ *
+ * Calculate the minimum size needed for the Block Header field using the
+ * settings specified in the lzma_block structure. Note that it is OK to
+ * increase the calculated header_size value as long as it is a multiple of
+ * four and doesn't exceed LZMA_BLOCK_HEADER_SIZE_MAX. Increasing header_size
+ * just means that lzma_block_header_encode() will add Header Padding.
  *
  * \return      - LZMA_OK: Size calculated successfully and stored to
- *                options->header_size.
+ *                block->header_size.
  *              - LZMA_OPTIONS_ERROR: Unsupported filters or filter options.
- *              - LZMA_PROG_ERROR: Invalid options
+ *              - LZMA_PROG_ERROR: Invalid values like compressed_size == 0.
  *
  * \note        This doesn't check that all the options are valid i.e. this
  *              may return LZMA_OK even if lzma_block_header_encode() or
- *              lzma_block_encoder() would fail.
+ *              lzma_block_encoder() would fail. If you want to validate the
+ *              filter chain, consider using lzma_memlimit_encoder() which as
+ *              a side-effect validates the filter chain.
  */
-extern lzma_ret lzma_block_header_size(lzma_block *options)
+extern lzma_ret lzma_block_header_size(lzma_block *block)
                lzma_attr_warn_unused_result;
 
 
 /**
- * \brief       Encodes Block Header
+ * \brief       Encode Block Header
  *
- * Encoding of the Block options is done with a single call instead of
- * first initializing and then doing the actual work with lzma_code().
+ * The caller must have calculated the size of the Block Header already with
+ * lzma_block_header_size(). If larger value than the one calculated by
+ * lzma_block_header_size() is used, the Block Header will be padded to the
+ * specified size.
  *
  * \param       out         Beginning of the output buffer. This must be
- *                          at least options->header_size bytes.
- * \param       options     Block options to be encoded.
+ *                          at least block->header_size bytes.
+ * \param       block       Block options to be encoded.
  *
- * \return      - LZMA_OK: Encoding was successful. options->header_size
+ * \return      - LZMA_OK: Encoding was successful. block->header_size
  *                bytes were written to output buffer.
  *              - LZMA_OPTIONS_ERROR: Invalid or unsupported options.
- *              - LZMA_PROG_ERROR
+ *              - LZMA_PROG_ERROR: Invalid arguments, for example
+ *                block->header_size is invalid or block->filters is NULL.
  */
-extern lzma_ret lzma_block_header_encode(
-               const lzma_block *options, uint8_t *out)
+extern lzma_ret lzma_block_header_encode(const lzma_block *block, uint8_t *out)
                lzma_attr_warn_unused_result;
 
 
 /**
- * \brief       Decodes Block Header
+ * \brief       Decode Block Header
  *
- * Decoding of the Block options is done with a single call instead of
- * first initializing and then doing the actual work with lzma_code().
+ * The size of the Block Header must have already been decoded with
+ * lzma_block_header_size_decode() macro and stored to block->header_size.
+ * block->filters must have been allocated, but not necessarily initialized.
+ * Possible existing filter options are _not_ freed.
  *
- * \param       options     Destination for block options
+ * \param       block       Destination for block options with header_size
+ *                          properly initialized.
  * \param       allocator   lzma_allocator for custom allocator functions.
- *                          Set to NULL to use malloc().
+ *                          Set to NULL to use malloc() (and also free()
+ *                          if an error occurs).
  * \param       in          Beginning of the input buffer. This must be
- *                          at least options->header_size bytes.
+ *                          at least block->header_size bytes.
  *
- * \return      - LZMA_OK: Decoding was successful. options->header_size
- *                bytes were written to output buffer.
- *              - LZMA_OPTIONS_ERROR: Invalid or unsupported options.
- *              - LZMA_PROG_ERROR
+ * \return      - LZMA_OK: Decoding was successful. block->header_size
+ *                bytes were read from the input buffer.
+ *              - LZMA_OPTIONS_ERROR: The Block Header specifies some
+ *                unsupported options such as unsupported filters.
+ *              - LZMA_DATA_ERROR: Block Header is corrupt, for example,
+ *                the CRC32 doesn't match.
+ *              - LZMA_PROG_ERROR: Invalid arguments, for example
+ *                block->header_size is invalid or block->filters is NULL.
  */
-extern lzma_ret lzma_block_header_decode(lzma_block *options,
+extern lzma_ret lzma_block_header_decode(lzma_block *block,
                lzma_allocator *allocator, const uint8_t *in)
                lzma_attr_warn_unused_result;
 
 
 /**
- * \brief       Sets Compressed Size according to Unpadded Size
+ * \brief       Validate and set Compressed Size according to Unpadded Size
  *
  * Block Header stores Compressed Size, but Index has Unpadded Size. If the
  * application has already parsed the Index and is now decoding Blocks,
  * it can calculate Compressed Size from Unpadded Size. This function does
- * exactly that with error checking, so application doesn't need to check,
- * for example, if the value in Index is too small to contain even the
- * Block Header. Note that you need to call this function _after_ decoding
- * the Block Header field.
+ * exactly that with error checking:
+ *
+ *  - Compressed Size calculated from Unpadded Size must be positive integer,
+ *    that is, Unpadded Size must be big enough that after Block Header and
+ *    Check fields there's still at least one byte for Compressed Size.
  *
- * \return      - LZMA_OK: options->compressed_size was set successfully.
+ *  - If Compressed Size was present in Block Header, the new value
+ *    calculated from Unpadded Size is compared against the value
+ *    from Block Header.
+ *
+ * \note        This function must be called _after_ decoding the Block Header
+ *              field so that it can properly validate Compressed Size if it
+ *              was present in Block Header.
+ *
+ * \return      - LZMA_OK: block->compressed_size was set successfully.
  *              - LZMA_DATA_ERROR: unpadded_size is too small compared to
- *                options->header_size and lzma_check_sizes[options->check].
+ *                block->header_size and lzma_check_size(block->check).
  *              - LZMA_PROG_ERROR: Some values are invalid. For example,
- *                options->header_size must be a multiple of four, and
- *                options->header_size between 8 and 1024 inclusive.
+ *                block->header_size must be a multiple of four and
+ *                between 8 and 1024 inclusive.
  */
 extern lzma_ret lzma_block_compressed_size(
-               lzma_block *options, lzma_vli unpadded_size)
+               lzma_block *block, lzma_vli unpadded_size)
                lzma_attr_warn_unused_result;
 
 
 /**
- * \brief       Calculates Unpadded Size
+ * \brief       Calculate Unpadded Size
  *
- * This function can be useful after decoding a Block to get Unpadded Size
- * that is stored in Index.
+ * The Index field stores Unpadded Size and Uncompressed Size. The latter
+ * can be taken directly from the lzma_block structure after coding a Block,
+ * but Unpadded Size needs to be calculated from Block Header Size,
+ * Compressed Size, and size of the Check field. This is where this function
+ * is needed.
  *
  * \return      Unpadded Size on success, or zero on error.
  */
-extern lzma_vli lzma_block_unpadded_size(const lzma_block *options)
+extern lzma_vli lzma_block_unpadded_size(const lzma_block *block)
                lzma_attr_pure;
 
 
 /**
- * \brief       Calculates the total encoded size of a Block
+ * \brief       Calculate the total encoded size of a Block
  *
  * This is equivalent to lzma_block_unpadded_size() except that the returned
  * value includes the size of the Block Padding field.
@@ -255,39 +317,40 @@ extern lzma_vli lzma_block_unpadded_size(const lzma_block *options)
  * \return      On success, total encoded size of the Block. On error,
  *              zero is returned.
  */
-extern lzma_vli lzma_block_total_size(const lzma_block *options)
+extern lzma_vli lzma_block_total_size(const lzma_block *block)
                lzma_attr_pure;
 
 
 /**
- * \brief       Initializes .lzma Block encoder
+ * \brief       Initialize .xz Block encoder
  *
- * This function is required for multi-thread encoding. It may also be
- * useful when implementing custom file formats.
+ * Valid actions for lzma_code() are LZMA_RUN, LZMA_SYNC_FLUSH (only if the
+ * filter chain supports it), and LZMA_FINISH.
  *
  * \return      - LZMA_OK: All good, continue with lzma_code().
  *              - LZMA_MEM_ERROR
  *              - LZMA_OPTIONS_ERROR
- *              - LZMA_UNSUPPORTED_CHECK: options->check specfies a Check
+ *              - LZMA_UNSUPPORTED_CHECK: block->check specfies a Check ID
  *                that is not supported by this buid of liblzma. Initializing
  *                the encoder failed.
  *              - LZMA_PROG_ERROR
- *
- * lzma_code() can return FIXME
  */
-extern lzma_ret lzma_block_encoder(lzma_stream *strm, lzma_block *options)
+extern lzma_ret lzma_block_encoder(lzma_stream *strm, lzma_block *block)
                lzma_attr_warn_unused_result;
 
 
 /**
- * \brief       Initializes decoder for .lzma Block
+ * \brief       Initialize .xz Block decoder
+ *
+ * Valid actions for lzma_code() are LZMA_RUN and LZMA_FINISH. Using
+ * LZMA_FINISH is not required. It is supported only for convenience.
  *
  * \return      - LZMA_OK: All good, continue with lzma_code().
  *              - LZMA_UNSUPPORTED_CHECK: Initialization was successful, but
- *                the given Check type is not supported, thus Check will be
+ *                the given Check ID is not supported, thus Check will be
  *                ignored.
  *              - LZMA_PROG_ERROR
  *              - LZMA_MEM_ERROR
  */
-extern lzma_ret lzma_block_decoder(lzma_stream *strm, lzma_block *options)
+extern lzma_ret lzma_block_decoder(lzma_stream *strm, lzma_block *block)
                lzma_attr_warn_unused_result;
index 5cba362..9897e7c 100644 (file)
 
 
 /**
- * \brief       Type of the Check
+ * \brief       Type of the integrity check (Check ID)
  *
- * The .lzma format supports multiple types of Checks that are calculated
- * from the uncompressed data (unless it is empty; then it's calculated
- * from Block Header).
+ * The .xz format supports multiple types of checks that are calculated
+ * from the uncompressed data. They very in both speed and ability to
+ * detect errors.
  */
 typedef enum {
        LZMA_CHECK_NONE     = 0,
@@ -62,11 +62,11 @@ typedef enum {
 /**
  * \brief       Maximum valid Check ID
  *
- * The .lzma file format specification specifies eight Check IDs (0-15). Some
+ * The .xz file format specification specifies 16 Check IDs (0-15). Some
  * of them are only reserved i.e. no actual Check algorithm has been assigned.
- * Still liblzma accepts any of these eight IDs for future compatibility
- * when decoding files. If a valid but unsupported Check ID is detected,
- * liblzma indicates a warning with LZMA_UNSUPPORTED_CHECK.
+ * Still liblzma accepts any of these IDs for future compatibility when
+ * decoding files. If a valid but unsupported Check ID is detected, liblzma
+ * indicates a warning with LZMA_UNSUPPORTED_CHECK.
  *
  * FIXME bad desc
  */
@@ -85,18 +85,20 @@ typedef enum {
  * Returns true if the given Check ID is supported by this liblzma build.
  * Otherwise false is returned. It is safe to call this with a value that
  * is not in the range [0, 15]; in that case the return value is always false.
+ *
+ * You can assume that LZMA_CHECK_NONE and LZMA_CHECK_CRC32 are always
+ * supported (even if liblzma is built with limited features).
  */
 extern lzma_bool lzma_check_is_supported(lzma_check check)
                lzma_attr_const;
 
 
 /**
- * \brief       Get the size of the Check field with given Check ID
+ * \brief       Get the size of the Check field with the given Check ID
  *
  * Although not all Check IDs have a check algorithm associated, the size of
  * every Check is already frozen. This function returns the size (in bytes) of
- * the Check field with the specified Check ID. The values are taken from the
- * section 2.1.1.2 of the .lzma file format specification:
+ * the Check field with the specified Check ID. The values are:
  * { 0, 4, 4, 4, 8, 8, 8, 16, 16, 16, 32, 32, 32, 64, 64, 64 }
  *
  * If the argument is not in the range [0, 15], UINT32_MAX is returned.
@@ -134,8 +136,8 @@ extern uint64_t lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc)
 
 
 /*
- * SHA256 functions are currently not exported to public API.
- * Contact the author if you think it should be.
+ * SHA-256 functions are currently not exported to public API.
+ * Contact Lasse Collin if you think it should be.
  */
 
 
index ff640a6..800f212 100644 (file)
  ************/
 
 /**
- * \brief       Compression level names for lzma_easy_* functions
+ * \brief       Default compression level for easy encoder
  *
- * At the moment, all the compression levels support LZMA_SYNC_FLUSH.
- * In future there may be levels that don't support LZMA_SYNC_FLUSH.
- * However, the LZMA_SYNC_FLUSH support won't be removed from the
- * existing compression levels.
+ * It's not straightforward to recommend a default level, because in some
+ * cases keeping the resource usage relatively low is more important that
+ * getting the maximum compression ratio.
+ */
+#define LZMA_EASY_LEVEL_DEFAULT 6
+
+
+/*
+ * Flags for easy encoder
  *
- * \note        If liblzma is built without encoder support, or with some
- *              filters disabled, some of the compression levels may be
- *              unsupported. In that case, the initialization functions
- *              will return LZMA_OPTIONS_ERROR.
+ * Currently only one flag is defined.
  */
-typedef enum {
-       LZMA_EASY_COPY      = 0,
-               /**<
-                * No compression; the data is just wrapped into .lzma
-                * container.
-                */
-
-       LZMA_EASY_LZMA2_1   = 1,
-               /**<
-                * LZMA2 filter with fast compression (fast in terms of LZMA2).
-                * If you are interested in the exact options used, see
-                * lzma_lzma_preset(1). Note that the exact options may
-                * change between liblzma versions.
-                *
-                * At the moment, the command line tool uses these settings
-                * when `lzma -1' is used. In future, the command line tool
-                * may default to some more complex way to determine the
-                * settings used e.g. the type of files being compressed.
-                *
-                * LZMA_EASY_LZMA2_2 is equivalent to lzma_lzma_preset(2)
-                * and so on.
-                */
-
-       LZMA_EASY_LZMA2_2    = 2,
-       LZMA_EASY_LZMA2_3    = 3,
-       LZMA_EASY_LZMA2_4    = 4,
-       LZMA_EASY_LZMA2_5    = 5,
-       LZMA_EASY_LZMA2_6    = 6,
-       LZMA_EASY_LZMA2_7    = 7,
-       LZMA_EASY_LZMA2_8    = 8,
-       LZMA_EASY_LZMA2_9    = 9,
-} lzma_easy_level;
+
+/**
+ * Use significantly slower compression to get marginally better compression
+ * ratio. This doesn't affect the memory requirements of the encoder or
+ * decoder. This flag is useful when you don't mind wasting time to get as
+ * small result as possible.
+ *
+ * FIXME: Not implemented yet.
+ */
+#define LZMA_EASY_EXTREME       UINT32_C(0x01)
 
 
 /**
- * \brief       Default compression level
+ * \brief       Calculate rough memory usage of easy encoder
+ *
+ * This function is a wrapper for lzma_raw_encoder_memusage().
  *
- * Data Blocks contain the actual compressed data. It's not straightforward
- * to recommend a default level, because in some cases keeping the resource
- * usage relatively low is more important that getting the maximum
- * compression ratio.
+ * \param       level   Compression level
+ * \param       flags   Easy encoder flags (usually zero). This parameter is
+ *                      needed, because in future some flags may affect the
+ *                      memory requirements.
  */
-#define LZMA_EASY_DEFAULT LZMA_EASY_LZMA2_7
+extern uint64_t lzma_easy_encoder_memusage(uint32_t level, uint32_t flags)
+               lzma_attr_pure;
 
 
 /**
- * \brief       Calculates rough memory requirements of a compression level
+ * \brief       Calculate rough memory usage FIXME
  *
- * This function is a wrapper for lzma_memory_usage(), which is declared
- * in filter.h.
+ * This function is a wrapper for lzma_raw_decoder_memusage().
  *
- * \return      Approximate memory usage of the encoder with the given
- *              compression level in mebibytes (value * 1024 * 1024 bytes).
- *              On error (e.g. compression level is not supported),
- *              UINT32_MAX is returned.
+ * \param       level   Compression level
+ * \param       flags   Easy encoder flags (usually zero). This parameter is
+ *                      needed, because in future some flags may affect the
+ *                      memory requirements.
  */
-extern uint64_t lzma_easy_memory_usage(lzma_easy_level level)
+extern uint64_t lzma_easy_decoder_memusage(uint32_t level, uint32_t flags)
                lzma_attr_pure;
 
 
 /**
- * \brief       Initializes .lzma Stream encoder
+ * \brief       Initialize .xz Stream encoder using a preset number
  *
  * This function is intended for those who just want to use the basic features
- * if liblzma (that is, most developers out there). Lots of assumptions are
- * made, which are correct or at least good enough for most situations.
+ * if liblzma (that is, most developers out there).
  *
  * \param       strm    Pointer to lzma_stream that is at least initialized
  *                      with LZMA_STREAM_INIT.
  * \param       level   Compression level to use. This selects a set of
  *                      compression settings from a list of compression
- *                      presets.
+ *                      presets. Currently levels from 1 to 9 are defined,
+ *                      which match the options -1 .. -9 of the xz command
+ *                      line tool.
+ * \param       flags   Flags that can finetune the compression preset.
+ *                      In most cases, no flags are wanted, and this
+ *                      parameter is zero.
+ * \param       check   Integrity check type to use. See check.h for available
+ *                      checks. If you are unsure, use LZMA_CHECK_CRC32.
  *
  * \return      - LZMA_OK: Initialization succeeded. Use lzma_code() to
  *                encode your data.
@@ -117,18 +105,23 @@ extern uint64_t lzma_easy_memory_usage(lzma_easy_level level)
  *                previously allocated for *strm is now freed.
  *              - LZMA_OPTIONS_ERROR: The given compression level is not
  *                supported by this build of liblzma.
+ *              - LZMA_UNSUPPORTED_CHECK: The given check type is not
+ *                supported by this liblzma build.
+ *              - LZMA_PROG_ERROR: One or more of the parameters have values
+ *                that will never be valid. For example, strm == NULL.
  *
  * If initialization succeeds, use lzma_code() to do the actual encoding.
  * Valid values for `action' (the second argument of lzma_code()) are
  * LZMA_RUN, LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, and LZMA_FINISH. In future,
- * there may be compression levels that don't support LZMA_SYNC_FLUSH.
+ * there may be compression levels or flags that don't support LZMA_SYNC_FLUSH.
  */
-extern lzma_ret lzma_easy_encoder(lzma_stream *strm, lzma_easy_level level)
+extern lzma_ret lzma_easy_encoder(lzma_stream *strm,
+               uint32_t level, uint32_t flags, lzma_check check)
                lzma_attr_warn_unused_result;
 
 
 /**
- * \brief       Initializes .lzma Stream encoder
+ * \brief       Initialize .xz Stream encoder using a custom filter chain
  *
  * \param       strm    Pointer to properly prepared lzma_stream
  * \param       filters Array of filters. This must be terminated with
@@ -150,19 +143,25 @@ extern lzma_ret lzma_stream_encoder(lzma_stream *strm,
 
 
 /**
- * \brief       Initializes LZMA_Alone (deprecated file format) encoder
+ * \brief       Initialize .lzma encoder (legacy file format)
  *
- * LZMA_Alone files have the suffix .lzma like the .lzma Stream files.
- * LZMA_Alone format supports only one filter, the LZMA filter. There is
- * no support for integrity checks like CRC32.
+ * The .lzma format is sometimes called the LZMA_Alone format, which is the
+ * reason for the name of this function. The .lzma format supports only the
+ * LZMA1 filter. There is no support for integrity checks like CRC32.
  *
- * Use this format if and only if you need to create files readable by
- * legacy LZMA tools such as LZMA Utils 4.32.x.
+ * Use this function if and only if you need to create files readable by
+ * legacy LZMA tools such as LZMA Utils 4.32.x. Moving to the .xz format
+ * is strongly recommended.
  *
- * LZMA_Alone encoder doesn't support LZMA_SYNC_FLUSH or LZMA_FULL_FLUSH.
+ * FIXME: Dictionary size limit?
+ *
+ * The valid action values for lzma_code() are LZMA_RUN and LZMA_FINISH.
+ * No kind of flushing is supported, because the file format doesn't make
+ * it possible.
  *
  * \return      - LZMA_OK
  *              - LZMA_MEM_ERROR
+ *              - LZMA_OPTIONS_ERROR // FIXME
  *              - LZMA_PROG_ERROR
  */
 extern lzma_ret lzma_alone_encoder(
@@ -177,7 +176,7 @@ extern lzma_ret lzma_alone_encoder(
 /**
  * This flag makes lzma_code() return LZMA_NO_CHECK if the input stream
  * being decoded has no integrity check. Note that when used with
- * lzma_auto_decoder(), all LZMA_Alone files will trigger LZMA_NO_CHECK
+ * lzma_auto_decoder(), all .lzma files will trigger LZMA_NO_CHECK
  * if LZMA_TELL_NO_CHECK is used.
  */
 #define LZMA_TELL_NO_CHECK              UINT32_C(0x01)
@@ -203,8 +202,8 @@ extern lzma_ret lzma_alone_encoder(
 /**
  * This flag enables decoding of concatenated files with file formats that
  * allow concatenating compressed files as is. From the formats currently
- * supported by liblzma, only the new .lzma format allows concatenated files.
- * Concatenated files are not allowed with the LZMA_Alone format.
+ * supported by liblzma, only the .xz format allows concatenated files.
+ * Concatenated files are not allowed with the legacy .lzma format.
  *
  * This flag also affects the usage of the `action' argument for lzma_code().
  * When LZMA_CONCATENATED is used, lzma_code() won't return LZMA_STREAM_END
@@ -218,7 +217,7 @@ extern lzma_ret lzma_alone_encoder(
 
 
 /**
- * \brief       Initializes decoder for .lzma Stream
+ * \brief       Initialize .xz Stream decoder
  *
  * \param       strm        Pointer to properly prepared lzma_stream
  * \param       memlimit    Rough memory usage limit as bytes
@@ -233,13 +232,13 @@ extern lzma_ret lzma_stream_decoder(
 
 
 /**
- * \brief       Decode .lzma Streams and LZMA_Alone files with autodetection
+ * \brief       Decode .xz Streams and .lzma files with autodetection
  *
- * Autodetects between the .lzma Stream and LZMA_Alone formats, and
+ * This decoder autodetects between the .xz and .lzma file formats, and
  * calls lzma_stream_decoder() or lzma_alone_decoder() once the type
- * of the file has been detected.
+ * of the input file has been detected.
  *
- * \param       strm        Pointer to propertily prepared lzma_stream
+ * \param       strm        Pointer to properly prepared lzma_stream
  * \param       memlimit    Rough memory usage limit as bytes
  * \param       flags       Bitwise-or of flags, or zero for no flags.
  *
@@ -253,7 +252,7 @@ extern lzma_ret lzma_auto_decoder(
 
 
 /**
- * \brief       Initializes decoder for LZMA_Alone file
+ * \brief       Initializes decoder for .lzma file
  *
  * Valid `action' arguments to lzma_code() are LZMA_RUN and LZMA_FINISH.
  * There is no need to use LZMA_FINISH, but allowing it may simplify
index bdb5b92..963c7c0 100644 (file)
@@ -64,12 +64,12 @@ typedef struct {
 #      define LZMA_DELTA_DIST_MIN 1
 #      define LZMA_DELTA_DIST_MAX 256
 
-       /**
-        * \brief       Reserved space for possible future extensions
-        *
-        * You should not touch these, because the names of these variables
-        * may change. These are and will never be used when type is
-        * LZMA_DELTA_TYPE_BYTE, so it is safe to leave these uninitialized.
+       /*
+        * Reserved space to allow possible future extensions without
+        * breaking the ABI. You should not touch these, because the names
+        * of these variables may change. These are and will never be used
+        * when type is LZMA_DELTA_TYPE_BYTE, so it is safe to leave these
+        * uninitialized.
         */
        uint32_t reserved_int1;
        uint32_t reserved_int2;
index b4fb02a..05c0c77 100644 (file)
 
 
 /**
+ * \brief       Maximum number of filters in a chain
+ *
+ * A filter chain can have 1-4 filters, of which three are allowed to change
+ * the size of the data. Usually only one or two filters are needed.
+ */
+#define LZMA_FILTERS_MAX 4
+
+
+/**
  * \brief       Filter options
  *
  * This structure is used to pass Filter ID and a pointer filter's options
- * to liblzma.
+ * to liblzma. An array of lzma_filter structures is used to define a filter
+ * chain.
+ *
+ * A filter chain is indicated with an array of lzma_filter structures.
+ * The array is terminated with .id = LZMA_VLI_UNKNOWN. Thus, the filter array
+ * must have LZMA_FILTERS_MAX + 1 elements (that is, five) to be able to hold
+ * any arbitrary filter chain. This is important when using
+ * lzma_block_header_decode() from block.h, because too small array would
+ * make liblzma write past the end of the filters array.
  */
 typedef struct {
        /**
@@ -55,14 +72,6 @@ typedef struct {
 
 
 /**
- * \brief       Maximum number of filters in a chain
- *
- * FIXME desc
- */
-#define LZMA_FILTERS_MAX 4
-
-
-/**
  * \brief       Test if the given Filter ID is supported for encoding
  *
  * Returns true if the give Filter ID  is supported for encoding by this
index d607261..9d6b755 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * \file        lzma/index.h
- * \brief       Handling of Index lists
+ * \brief       Handling of .xz Index lists
  *
  * \author      Copyright (C) 1999-2006 Igor Pavlov
  * \author      Copyright (C) 2007 Lasse Collin
@@ -69,6 +69,25 @@ typedef struct {
 
 
 /**
+ * \brief       Calculate memory usage for Index with given number of Records
+ *
+ * On disk, the size of the Index field depends on both the number of Records
+ * stored and how big values the Records store (due to variable-length integer
+ * encoding). When the Index is kept in lzma_index structure, the memory usage
+ * depends only on the number of Records stored in the Index. The size in RAM
+ * is almost always a lot bigger than in encoded form on disk.
+ *
+ * This function calculates an approximate amount of memory needed hold the
+ * given number of Records in lzma_index structure. This value may vary
+ * between liblzma versions if the internal implementation is modified.
+ *
+ * If you want to know how much memory an existing lzma_index structure is
+ * using, use lzma_index_memusage(lzma_index_count(i)).
+ */
+extern uint64_t lzma_index_memusage(lzma_vli record_count);
+
+
+/**
  * \brief       Allocate and initialize a new lzma_index structure
  *
  * If i is NULL, a new lzma_index structure is allocated, initialized,
@@ -76,7 +95,7 @@ typedef struct {
  *
  * If i is non-NULL, it is reinitialized and the same pointer returned.
  * In this case, return value cannot be NULL or a different pointer than
- * the i given as argument.
+ * the i that was given as an argument.
  */
 extern lzma_index *lzma_index_init(lzma_index *i, lzma_allocator *allocator)
                lzma_attr_warn_unused_result;
@@ -84,6 +103,8 @@ extern lzma_index *lzma_index_init(lzma_index *i, lzma_allocator *allocator)
 
 /**
  * \brief       Deallocate the Index
+ *
+ * If i is NULL, this does nothing.
  */
 extern void lzma_index_end(lzma_index *i, lzma_allocator *allocator);
 
@@ -91,14 +112,20 @@ extern void lzma_index_end(lzma_index *i, lzma_allocator *allocator);
 /**
  * \brief       Add a new Record to an Index
  *
- * \param       index             Pointer to a lzma_index structure
- * \param       unpadded_size     Unpadded Size of a Block
- * \param       uncompressed_size Uncompressed Size of a Block, or
- *                                LZMA_VLI_UNKNOWN to indicate padding.
+ * \param       i                 Pointer to a lzma_index structure
+ * \param       allocator         Pointer to lzma_allocator, or NULL to
+ *                                use malloc()
+ * \param       unpadded_size     Unpadded Size of a Block. This can be
+ *                                calculated with lzma_block_unpadded_size()
+ *                                after encoding or decoding the Block.
+ * \param       uncompressed_size Uncompressed Size of a Block. This can be
+ *                                taken directly from lzma_block structure
+ *                                after encoding or decoding the Block.
  *
  * Appending a new Record does not affect the read position.
  *
  * \return      - LZMA_OK
+ *              - LZMA_MEM_ERROR
  *              - LZMA_DATA_ERROR: Compressed or uncompressed size of the
  *                Stream or size of the Index field would grow too big.
  *              - LZMA_PROG_ERROR
@@ -117,7 +144,7 @@ extern lzma_vli lzma_index_count(const lzma_index *i) lzma_attr_pure;
 /**
  * \brief       Get the size of the Index field as bytes
  *
- * This is needed to verify the Index Size field from the Stream Footer.
+ * This is needed to verify the Backward Size field in the Stream Footer.
  */
 extern lzma_vli lzma_index_size(const lzma_index *i) lzma_attr_pure;
 
@@ -145,7 +172,8 @@ extern lzma_vli lzma_index_stream_size(const lzma_index *i) lzma_attr_pure;
  *
  * When no Indexes have been combined with lzma_index_cat(), this function is
  * identical to lzma_index_stream_size(). If multiple Indexes have been
- * combined, this includes also the possible Stream Padding fields.
+ * combined, this includes also the headers of each separate Stream and the
+ * possible Stream Padding fields.
  */
 extern lzma_vli lzma_index_file_size(const lzma_index *i) lzma_attr_pure;
 
@@ -181,7 +209,8 @@ extern void lzma_index_rewind(lzma_index *i);
  *
  * \param       i       Pointer to lzma_index structure
  * \param       record  Pointer to a structure to hold the search results
- * \param       target  Uncompressed target offset
+ * \param       target  Uncompressed target offset which the caller would
+ *                      like to locate from the Stream
  *
  * If the target is smaller than the uncompressed size of the Stream (can be
  * checked with lzma_index_uncompressed_size()):
@@ -204,13 +233,15 @@ extern lzma_bool lzma_index_locate(
  *
  *
  *
- * \param       dest      Destination Index after which src is appended Source
- * \param       src       Index. The memory allocated for this is either moved
- *                        to be part of *dest or freed iff the function call
- *                        succeeds, and src will be an invalid pointer.
+ * \param       dest      Destination Index after which src is appended
+ * \param       src       Source Index. The memory allocated for this is
+ *                        either moved to be part of *dest or freed if and
+ *                        only if the function call succeeds, and src will
+ *                        be an invalid pointer.
  * \param       allocator Custom memory allocator; can be NULL to use
  *                        malloc() and free().
  * \param       padding   Size of the Stream Padding field between Streams.
+ *                        This must be a multiple of four.
  *
  * \return      - LZMA_OK: Indexes concatenated successfully.
  *              - LZMA_DATA_ERROR: *dest would grow too big.
@@ -226,6 +257,8 @@ extern lzma_ret lzma_index_cat(lzma_index *lzma_restrict dest,
 /**
  * \brief       Duplicates an Index list
  *
+ * Makes an identical copy of the Index. Also the read position is copied.
+ *
  * \return      A copy of the Index, or NULL if memory allocation failed.
  */
 extern lzma_index *lzma_index_dup(
@@ -235,6 +268,8 @@ extern lzma_index *lzma_index_dup(
 
 /**
  * \brief       Compares if two Index lists are identical
+ *
+ * \return      True if *a and *b are equal, false otherwise.
  */
 extern lzma_bool lzma_index_equal(const lzma_index *a, const lzma_index *b)
                lzma_attr_pure;
@@ -242,6 +277,17 @@ extern lzma_bool lzma_index_equal(const lzma_index *a, const lzma_index *b)
 
 /**
  * \brief       Initializes Index encoder
+ *
+ * \param       strm        Pointer to properly prepared lzma_stream
+ * \param       i           Pointer to lzma_index which should be encoded.
+ *                          The read position will be at the end of the Index
+ *                          after lzma_code() has returned LZMA_STREAM_END.
+ *
+ * The only valid action value for lzma_code() is LZMA_RUN.
+ *
+ * \return      - LZMA_OK: Initialization succeeded, continue with lzma_code().
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_PROG_ERROR
  */
 extern lzma_ret lzma_index_encoder(lzma_stream *strm, lzma_index *i)
                lzma_attr_warn_unused_result;
@@ -249,6 +295,29 @@ extern lzma_ret lzma_index_encoder(lzma_stream *strm, lzma_index *i)
 
 /**
  * \brief       Initializes Index decoder
+ *
+ * \param       strm        Pointer to properly prepared lzma_stream
+ * \param       i           Pointer to a pointer that will be made to point
+ *                          to the final decoded Index once lzma_code() has
+ *                          returned LZMA_STREAM_END. That is,
+ *                          lzma_index_decoder() takes care of allocating
+ *                          a new lzma_index structure.
+ * \param       memlimit    How much memory the resulting Index is allowed
+ *                          to require.
+ *
+ * The only valid action value for lzma_code() is LZMA_RUN.
+ *
+ * \return      - LZMA_OK: Initialization succeeded, continue with lzma_code().
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_MEMLIMIT_ERROR
+ *              - LZMA_PROG_ERROR
+ *
+ * \note        The memory usage limit is checked early in the decoding
+ *              (within the first dozen input bytes or so). The actual memory
+ *              is allocated later in smaller pieces. If the memory usage
+ *              limit is modified after decoding a part of the Index already,
+ *              the new limit may be ignored.
  */
-extern lzma_ret lzma_index_decoder(lzma_stream *strm, lzma_index **i)
+extern lzma_ret lzma_index_decoder(
+               lzma_stream *strm, lzma_index **i, uint64_t memlimit)
                lzma_attr_warn_unused_result;
index 001e6b5..6ebbe9f 100644 (file)
@@ -39,7 +39,7 @@ typedef struct lzma_index_hash_s lzma_index_hash;
  *
  * If index_hash is non-NULL, it is reinitialized and the same pointer
  * returned. In this case, return value cannot be NULL or a different
- * pointer than the index_hash given as argument.
+ * pointer than the index_hash that was given as an argument.
  */
 extern lzma_index_hash *lzma_index_hash_init(
                lzma_index_hash *index_hash, lzma_allocator *allocator)
@@ -47,7 +47,7 @@ extern lzma_index_hash *lzma_index_hash_init(
 
 
 /**
- * \brief       Deallocate the Index hash
+ * \brief       Deallocate lzma_index_hash structure
  */
 extern void lzma_index_hash_end(
                lzma_index_hash *index_hash, lzma_allocator *allocator);
@@ -72,17 +72,29 @@ extern lzma_ret lzma_index_hash_append(lzma_index_hash *index_hash,
 
 
 /**
- * \brief       Decode the Index field
+ * \brief       Decode and validate the Index field
+ *
+ * After telling the sizes of all Blocks with lzma_index_hash_append(),
+ * the actual Index field is decoded with this function. Specifically,
+ * once decoding of the Index field has been started, no more Records
+ * can be added using lzma_index_hash_append().
+ *
+ * This function doesn't use lzma_stream structure to pass the input data.
+ * Instead, the input buffer is specified using three arguments. This is
+ * because it matches better the internal APIs of liblzma.
+ *
+ * \param       index_hash      Pointer to a lzma_index_hash structure
+ * \param       in              Pointer to the beginning of the input buffer
+ * \param       in_pos          in[*in_pos] is the next byte to process
+ * \param       in_size         in[in_size] is the first byte not to process
  *
  * \return      - LZMA_OK: So far good, but more input is needed.
  *              - LZMA_STREAM_END: Index decoded successfully and it matches
  *                the Records given with lzma_index_hash_append().
  *              - LZMA_DATA_ERROR: Index is corrupt or doesn't match the
  *                information given with lzma_index_hash_append().
+ *              - LZMA_BUF_ERROR: Cannot progress because *in_pos >= in_size.
  *              - LZMA_PROG_ERROR
- *
- * \note        Once decoding of the Index field has been started, no more
- *              Records can be added using lzma_index_hash_append().
  */
 extern lzma_ret lzma_index_hash_decode(lzma_index_hash *index_hash,
                const uint8_t *in, size_t *in_pos, size_t in_size)
@@ -92,7 +104,7 @@ extern lzma_ret lzma_index_hash_decode(lzma_index_hash *index_hash,
 /**
  * \brief       Get the size of the Index field as bytes
  *
- * This is needed to verify the Index Size field from the Stream Footer.
+ * This is needed to verify the Backward Size field in the Stream Footer.
  */
 extern lzma_vli lzma_index_hash_size(const lzma_index_hash *index_hash)
                lzma_attr_pure;
index a2130ef..9195e75 100644 (file)
@@ -44,7 +44,7 @@
  * functions, you may use other initialization functions, which initialize
  * only a subset of liblzma's internal static variables. Using those
  * functions have the following advantages:
- *  - When linking statically against liblzma, less useless functions will
+ *  - When linking statically against liblzma, fewer useless functions will
  *    get linked into the binary. E.g. if you need only the decoder functions,
  *    using lzma_init_decoder() avoids linking bunch of encoder related code.
  *  - There is less things to initialize, making the initialization
index 5ec563d..e3db236 100644 (file)
@@ -370,12 +370,12 @@ typedef struct {
         */
        uint32_t depth;
 
-       /**
-        * \brief       Reserved space for possible future extensions
-        *
-        * You should not touch these, because the names of these variables
-        * may change. These are and will never be used with the currently
-        * supported options, so it is safe to leave these uninitialized.
+       /*
+        * Reserved space to allow possible future extensions without
+        * breaking the ABI. You should not touch these, because the names
+        * of these variables may change. These are and will never be used
+        * with the currently supported options, so it is safe to leave these
+        * uninitialized.
         */
        uint32_t reserved_int1;
        uint32_t reserved_int2;
index 98f3f49..6969ffa 100644 (file)
@@ -86,8 +86,8 @@ typedef struct {
         * of the cross-section branch/call/jump instructions will use the
         * same absolute addresses as in the first section.
         *
-        * When the pointer to options is NULL, the default value is used.
-        * The default value is zero.
+        * When the pointer to options is NULL, the default value (zero)
+        * is used.
         */
        uint32_t start_offset;
 
index 44c6861..29d7304 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * \file        lzma/stream_flags.h
- * \brief       .lzma Stream Header and Stream Footer encoder and decoder
+ * \brief       .xz Stream Header and Stream Footer encoder and decoder
  *
  * \author      Copyright (C) 1999-2006 Igor Pavlov
  * \author      Copyright (C) 2007 Lasse Collin
@@ -25,7 +25,7 @@
  * \brief       Size of Stream Header and Stream Footer
  *
  * Stream Header and Stream Footer have the same size and they are not
- * going to change even if a newer version of the .lzma file format is
+ * going to change even if a newer version of the .xz file format is
  * developed in future.
  */
 #define LZMA_STREAM_HEADER_SIZE 12
@@ -55,8 +55,10 @@ typedef struct {
        uint32_t version;
 
        /**
+        * \brief       Backward Size
+        *
         * Backward Size must be a multiple of four bytes. In this Stream
-        * format version Backward Size is the size of the Index field.
+        * format version, Backward Size is the size of the Index field.
         *
         * Backward Size isn't actually part of the Stream Flags field, but
         * it is convenient to include in this structure anyway. Backward
@@ -73,11 +75,14 @@ typedef struct {
 #      define LZMA_BACKWARD_SIZE_MAX (LZMA_VLI_C(1) << 34)
 
        /**
-        * Type of the Check calculated from uncompressed data
+        * \brief       Check ID
+        *
+        * This indicates the type of the integrity check calculated from
+        * uncompressed data.
         */
        lzma_check check;
 
-       /**
+       /*
         * Reserved space to allow possible future extensions without
         * breaking the ABI. You should not touch these, because the
         * names of these variables may change.
@@ -111,11 +116,11 @@ typedef struct {
 /**
  * \brief       Encode Stream Header
  *
- * \param       out         Beginning of the output buffer of
- *                          LZMA_STREAM_HEADER_SIZE bytes.
  * \param       options     Stream Header options to be encoded.
- *                          options->index_size is ignored and doesn't
+ *                          options->backward_size is ignored and doesn't
  *                          need to be initialized.
+ * \param       out         Beginning of the output buffer of
+ *                          LZMA_STREAM_HEADER_SIZE bytes.
  *
  * \return      - LZMA_OK: Encoding was successful.
  *              - LZMA_OPTIONS_ERROR: options->version is not supported by
@@ -130,9 +135,9 @@ extern lzma_ret lzma_stream_header_encode(
 /**
  * \brief       Encode Stream Footer
  *
+ * \param       options     Stream Footer options to be encoded.
  * \param       out         Beginning of the output buffer of
  *                          LZMA_STREAM_HEADER_SIZE bytes.
- * \param       options     Stream Footer options to be encoded.
  *
  * \return      - LZMA_OK: Encoding was successful.
  *              - LZMA_OPTIONS_ERROR: options->version is not supported by
@@ -151,7 +156,7 @@ extern lzma_ret lzma_stream_footer_encode(
  * \param       in          Beginning of the input buffer of
  *                          LZMA_STREAM_HEADER_SIZE bytes.
  *
- * options->index_size is always set to LZMA_VLI_UNKNOWN. This is to
+ * options->backward_size is always set to LZMA_VLI_UNKNOWN. This is to
  * help comparing Stream Flags from Stream Header and Stream Footer with
  * lzma_stream_flags_compare().
  *
@@ -162,6 +167,17 @@ extern lzma_ret lzma_stream_footer_encode(
  *                is corrupt.
  *              - LZMA_OPTIONS_ERROR: Unsupported options are present
  *                in the header.
+ *
+ * \note        When decoding .xz files that contain multiple Streams, it may
+ *              make sense to print "file format not recognized" only if
+ *              decoding of the Stream Header of the _first_ Stream gives
+ *              LZMA_FORMAT_ERROR. If non-first Stream Header gives
+ *              LZMA_FORMAT_ERROR, the message used for LZMA_DATA_ERROR is
+ *              probably more appropriate.
+ *
+ *              For example, Stream decoder in liblzma uses LZMA_DATA_ERROR if
+ *              LZMA_FORMAT_ERROR is returned by lzma_stream_header_decode()
+ *              when decoding non-first Stream.
  */
 extern lzma_ret lzma_stream_header_decode(
                lzma_stream_flags *options, const uint8_t *in)
@@ -178,17 +194,17 @@ extern lzma_ret lzma_stream_header_decode(
  * \return      - LZMA_OK: Decoding was successful.
  *              - LZMA_FORMAT_ERROR: Magic bytes don't match, thus the given
  *                buffer cannot be Stream Footer.
- *              - LZMA_DATA_ERROR: CRC32 doesn't match, thus the footer
+ *              - LZMA_DATA_ERROR: CRC32 doesn't match, thus the Stream Footer
  *                is corrupt.
  *              - LZMA_OPTIONS_ERROR: Unsupported options are present
- *                in the footer.
+ *                in Stream Footer.
  *
  * \note        If Stream Header was already decoded successfully, but
  *              decoding Stream Footer returns LZMA_FORMAT_ERROR, the
  *              application should probably report some other error message
- *              than "unsupported file format", since the file more likely is
- *              corrupt (possibly truncated). Stream decoder in liblzma uses
- *              LZMA_DATA_ERROR in this situation.
+ *              than "file format not recognized", since the file more likely
+ *              is corrupt (possibly truncated). Stream decoder in liblzma
+ *              uses LZMA_DATA_ERROR in this situation.
  */
 extern lzma_ret lzma_stream_footer_decode(
                lzma_stream_flags *options, const uint8_t *in)
index a296f45..2a36120 100644 (file)
  *  - zzz = revision
  *  - s indicates stability: 0 = alpha, 1 = beta, 2 = stable
  *
- * See the README file for details about the version numbering.
+ * See the README file for details about the version numbering. FIXME
  *
- * \note        The version number of LZMA Utils (and thus liblzma)
- *              has nothing to with the version number of LZMA SDK.
+ * \note        The version number of liblzma has nothing to with
+ *              the version number of Igor Pavlov's LZMA SDK.
  */
 #define LZMA_VERSION UINT32_C(49990060)
 
index 1b13f86..caca204 100644 (file)
@@ -48,8 +48,7 @@
  *
  * This will always be unsigned integer. Valid VLI values are in the range
  * [0, LZMA_VLI_MAX]. Unknown value is indicated with LZMA_VLI_UNKNOWN,
- * which is the maximum value of the underlaying integer type (this feature
- * is useful in several situations).
+ * which is the maximum value of the underlaying integer type.
  *
  * In future, even if lzma_vli is typdefined to something else than uint64_t,
  * it is guaranteed that 2 * LZMA_VLI_MAX will not overflow lzma_vli.
@@ -74,9 +73,9 @@ typedef uint64_t lzma_vli;
 /**
  * \brief       Encodes variable-length integer
  *
- * In the .lzma format, most integers are encoded in variable-length
- * representation. This saves space when smaller values are more likely
- * than bigger values.
+ * In the .xz format, most integers are encoded in a variable-length
+ * representation, which is sometimes called little endian base-128 encoding.
+ * This saves space when smaller values are more likely than bigger values.
  *
  * The encoding scheme encodes seven bits to every byte, using minimum
  * number of bytes required to represent the given value. Encodings that use
@@ -118,8 +117,7 @@ typedef uint64_t lzma_vli;
  *              - LZMA_BUF_ERROR: No output space was provided.
  *              - LZMA_PROG_ERROR: Arguments are not sane.
  */
-extern lzma_ret lzma_vli_encode(
-               lzma_vli vli, size_t *lzma_restrict vli_pos,
+extern lzma_ret lzma_vli_encode(lzma_vli vli, size_t *lzma_restrict vli_pos,
                uint8_t *lzma_restrict out, size_t *lzma_restrict out_pos,
                size_t out_size);
 
@@ -165,10 +163,9 @@ extern lzma_ret lzma_vli_decode(lzma_vli *lzma_restrict vli,
 
 
 /**
- * \brief       Gets the number of bytes required to encode vli
+ * \brief       Get the number of bytes required to encode a VLI
  *
  * \return      Number of bytes on success (1-9). If vli isn't valid,
  *              zero is returned.
  */
-extern uint32_t lzma_vli_size(lzma_vli vli)
-               lzma_attr_pure;
+extern uint32_t lzma_vli_size(lzma_vli vli) lzma_attr_pure;
index 7ff2928..32d4431 100644 (file)
@@ -42,6 +42,9 @@ struct lzma_coder_s {
        /// Memory usage limit
        uint64_t memlimit;
 
+       /// Amount of memory actually needed (only an estimate)
+       uint64_t memusage;
+
        /// Options decoded from the header needed to initialize
        /// the LZMA decoder
        lzma_options_lzma options;
@@ -117,21 +120,16 @@ alone_decode(lzma_coder *coder,
                }
 
                ++*in_pos;
-               break;
+
+               // Calculate the memory usage so that it is ready
+               // for SEQ_CODER_INIT.
+               coder->memusage = lzma_lzma_decoder_memusage(&coder->options)
+                               + LZMA_MEMUSAGE_BASE;
+
+       // Fall through
 
        case SEQ_CODER_INIT: {
-               // FIXME It is unfair that this doesn't add a fixed amount
-               // like lzma_memusage_common() does.
-               const uint64_t memusage
-                               = lzma_lzma_decoder_memusage(&coder->options);
-
-               // Use LZMA_PROG_ERROR since LZMA_Alone decoder cannot be
-               // built without LZMA support.
-               // FIXME TODO Make the above comment true.
-               if (memusage == UINT64_MAX)
-                       return LZMA_PROG_ERROR;
-
-               if (memusage > coder->memlimit)
+               if (coder->memusage > coder->memlimit)
                        return LZMA_MEMLIMIT_ERROR;
 
                lzma_filter_info filters[2] = {
@@ -153,10 +151,9 @@ alone_decode(lzma_coder *coder,
                                coder->uncompressed_size);
 
                coder->sequence = SEQ_CODE;
+               break;
        }
 
-       // Fall through
-
        case SEQ_CODE: {
                return coder->next.code(coder->next.coder,
                                allocator, in, in_pos, in_size,
@@ -180,12 +177,30 @@ alone_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
 }
 
 
+static lzma_ret
+alone_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
+               uint64_t *old_memlimit, uint64_t new_memlimit)
+{
+       if (new_memlimit != 0 && new_memlimit < coder->memusage)
+               return LZMA_MEMLIMIT_ERROR;
+
+       *memusage = coder->memusage;
+       *old_memlimit = coder->memlimit;
+       coder->memlimit = new_memlimit;
+
+       return LZMA_OK;
+}
+
+
 extern lzma_ret
 lzma_alone_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
                uint64_t memlimit)
 {
        lzma_next_coder_init(lzma_alone_decoder_init, next, allocator);
 
+       if (memlimit == 0)
+               return LZMA_PROG_ERROR;
+
        if (next->coder == NULL) {
                next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
                if (next->coder == NULL)
@@ -193,6 +208,7 @@ lzma_alone_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
 
                next->code = &alone_decode;
                next->end = &alone_decoder_end;
+               next->memconfig = &alone_decoder_memconfig;
                next->coder->next = LZMA_NEXT_CODER_INIT;
        }
 
@@ -201,6 +217,7 @@ lzma_alone_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
        next->coder->options.dict_size = 0;
        next->coder->uncompressed_size = 0;
        next->coder->memlimit = memlimit;
+       next->coder->memusage = LZMA_MEMUSAGE_BASE;
 
        return LZMA_OK;
 }
index dd10832..2520dc1 100644 (file)
@@ -125,11 +125,39 @@ auto_decoder_get_check(const lzma_coder *coder)
 
 
 static lzma_ret
+auto_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
+               uint64_t *old_memlimit, uint64_t new_memlimit)
+{
+       lzma_ret ret;
+
+       if (coder->next.memconfig != NULL) {
+               ret = coder->next.memconfig(coder->next.coder,
+                               memusage, old_memlimit, new_memlimit);
+               assert(*old_memlimit == coder->memlimit);
+       } else {
+               // No coder is configured yet. Use the base value as
+               // the current memory usage.
+               *memusage = LZMA_MEMUSAGE_BASE;
+               *old_memlimit = coder->memlimit;
+               ret = LZMA_OK;
+       }
+
+       if (ret == LZMA_OK && new_memlimit != 0)
+               coder->memlimit = new_memlimit;
+
+       return ret;
+}
+
+
+static lzma_ret
 auto_decoder_init(lzma_next_coder *next, 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;
 
@@ -141,6 +169,7 @@ auto_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
                next->code = &auto_decode;
                next->end = &auto_decoder_end;
                next->get_check = &auto_decoder_get_check;
+               next->memconfig = &auto_decoder_memconfig;
                next->coder->next = LZMA_NEXT_CODER_INIT;
        }
 
index 66e1cad..2fa4584 100644 (file)
 
 
 extern LZMA_API lzma_ret
-lzma_block_compressed_size(lzma_block *options, lzma_vli total_size)
+lzma_block_compressed_size(lzma_block *block, lzma_vli total_size)
 {
-       // Validate.
-       if (options->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
-                       || options->header_size > LZMA_BLOCK_HEADER_SIZE_MAX
-                       || (options->header_size & 3)
-                       || (unsigned)(options->check) > LZMA_CHECK_ID_MAX
-                       || (total_size & 3))
+       // Validate everything but Uncompressed Size and filters.
+       if (lzma_block_unpadded_size(block) == 0)
                return LZMA_PROG_ERROR;
 
-       const uint32_t container_size = options->header_size
-                       + lzma_check_size(options->check);
+       const uint32_t container_size = block->header_size
+                       + lzma_check_size(block->check);
 
        // Validate that Compressed Size will be greater than zero.
        if (container_size <= total_size)
                return LZMA_DATA_ERROR;
 
-       options->compressed_size = total_size - container_size;
+       // Calculate what Compressed Size is supposed to be.
+       // If Compressed Size was present in Block Header,
+       // compare that the new value matches it.
+       const lzma_vli compressed_size = total_size - container_size;
+       if (block->compressed_size != LZMA_VLI_UNKNOWN
+                       && block->compressed_size != compressed_size)
+               return LZMA_DATA_ERROR;
+
+       block->compressed_size = compressed_size;
 
        return LZMA_OK;
 }
 
 
 extern LZMA_API lzma_vli
-lzma_block_unpadded_size(const lzma_block *options)
+lzma_block_unpadded_size(const lzma_block *block)
 {
        // Validate the values that we are interested in i.e. all but
        // Uncompressed Size and the filters.
@@ -54,23 +58,23 @@ lzma_block_unpadded_size(const lzma_block *options)
        // 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 (options->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
-                       || options->header_size > LZMA_BLOCK_HEADER_SIZE_MAX
-                       || (options->header_size & 3)
-                       || !lzma_vli_is_valid(options->compressed_size)
-                       || options->compressed_size == 0
-                       || (unsigned int)(options->check) > LZMA_CHECK_ID_MAX)
+       if (block->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
+                       || block->header_size > LZMA_BLOCK_HEADER_SIZE_MAX
+                       || (block->header_size & 3)
+                       || !lzma_vli_is_valid(block->compressed_size)
+                       || block->compressed_size == 0
+                       || (unsigned int)(block->check) > LZMA_CHECK_ID_MAX)
                return 0;
 
        // If Compressed Size is unknown, return that we cannot know
        // size of the Block either.
-       if (options->compressed_size == LZMA_VLI_UNKNOWN)
+       if (block->compressed_size == LZMA_VLI_UNKNOWN)
                return LZMA_VLI_UNKNOWN;
 
        // Calculate Unpadded Size and validate it.
-       const lzma_vli unpadded_size = options->compressed_size
-                               + options->header_size
-                               + lzma_check_size(options->check);
+       const lzma_vli unpadded_size = block->compressed_size
+                               + block->header_size
+                               + lzma_check_size(block->check);
 
        assert(unpadded_size >= UNPADDED_SIZE_MIN);
        if (unpadded_size > UNPADDED_SIZE_MAX)
@@ -81,11 +85,11 @@ lzma_block_unpadded_size(const lzma_block *options)
 
 
 extern LZMA_API lzma_vli
-lzma_block_total_size(const lzma_block *options)
+lzma_block_total_size(const lzma_block *block)
 {
-       lzma_vli unpadded_size = lzma_block_unpadded_size(options);
+       lzma_vli unpadded_size = lzma_block_unpadded_size(block);
 
-       if (unpadded_size != 0 && unpadded_size != LZMA_VLI_UNKNOWN)
+       if (unpadded_size != LZMA_VLI_UNKNOWN)
                unpadded_size = vli_ceil4(unpadded_size);
 
        return unpadded_size;
index c5f5039..81f783d 100644 (file)
@@ -301,5 +301,63 @@ lzma_end(lzma_stream *strm)
 extern LZMA_API lzma_check
 lzma_get_check(const lzma_stream *strm)
 {
+       // Return LZMA_CHECK_NONE if we cannot know the check type.
+       // It's a bug in the application if this happens.
+       if (strm->internal->next.get_check == NULL)
+               return LZMA_CHECK_NONE;
+
        return strm->internal->next.get_check(strm->internal->next.coder);
 }
+
+
+extern LZMA_API uint64_t
+lzma_memusage(const lzma_stream *strm)
+{
+       uint64_t memusage;
+       uint64_t old_memlimit;
+
+       if (strm == NULL || strm->internal == NULL
+                       || strm->internal->next.memconfig == NULL
+                       || strm->internal->next.memconfig(
+                               strm->internal->next.coder,
+                               &memusage, &old_memlimit, 0) != LZMA_OK)
+               return 0;
+
+       return memusage;
+}
+
+
+extern LZMA_API uint64_t
+lzma_memlimit_get(const lzma_stream *strm)
+{
+       uint64_t old_memlimit;
+       uint64_t memusage;
+
+       if (strm == NULL || strm->internal == NULL
+                       || strm->internal->next.memconfig == NULL
+                       || strm->internal->next.memconfig(
+                               strm->internal->next.coder,
+                               &memusage, &old_memlimit, 0) != LZMA_OK)
+               return 0;
+
+       return old_memlimit;
+}
+
+
+extern LZMA_API lzma_ret
+lzma_memlimit_set(lzma_stream *strm, uint64_t new_memlimit)
+{
+       // Dummy variables to simplify memconfig functions
+       uint64_t old_memlimit;
+       uint64_t memusage;
+
+       if (strm == NULL || strm->internal == NULL
+                       || strm->internal->next.memconfig == NULL)
+               return LZMA_PROG_ERROR;
+
+       if (new_memlimit != 0 && new_memlimit < LZMA_MEMUSAGE_BASE)
+               return LZMA_MEMLIMIT_ERROR;
+
+       return strm->internal->next.memconfig(strm->internal->next.coder,
+                       &memusage, &old_memlimit, new_memlimit);
+}
index 0ee8574..ef8d0cb 100644 (file)
 #define LZMA_BUFFER_SIZE 4096
 
 
+/// Starting value for memory usage estimates. Instead of calculating size
+/// of _every_ structure and taking into accont malloc() overhead etc. we
+/// add a base size to all memory usage estimates. It's not very accurate
+/// but should be easily good enough.
+#define LZMA_MEMUSAGE_BASE (UINT64_C(1) << 15)
+
 /// Start of internal Filter ID space. These IDs must never be used
 /// in Streams.
 #define LZMA_FILTER_RESERVED_START (LZMA_VLI_C(1) << 62)
@@ -134,7 +140,8 @@ struct lzma_next_coder_s {
 
        /// Pointer to function to get and/or change the memory usage limit.
        /// If memlimit == 0, the limit is not changed.
-       uint64_t (*memconfig)(lzma_coder *coder, uint64_t memlimit);
+       lzma_ret (*memconfig)(lzma_coder *coder, uint64_t *memusage,
+                       uint64_t *old_memlimit, uint64_t new_memlimit);
 };
 
 
index d5e1952..769253f 100644 (file)
@@ -33,8 +33,11 @@ struct lzma_coder_s {
 
 
 static bool
-easy_set_filters(lzma_coder *coder, uint32_t level)
+easy_set_filters(lzma_coder *coder, uint32_t level, uint32_t flags)
 {
+       // FIXME
+       (void)flags;
+
        bool error = false;
 
        if (level == 0) {
@@ -43,7 +46,7 @@ easy_set_filters(lzma_coder *coder, uint32_t level)
 
 #ifdef HAVE_ENCODER_LZMA2
        } else if (level <= 9) {
-               error = lzma_lzma_preset(&coder->opt_lzma, level - 1);
+               error = lzma_lzma_preset(&coder->opt_lzma, level);
                coder->filters[0].id = LZMA_FILTER_LZMA2;
                coder->filters[0].options = &coder->opt_lzma;
                coder->filters[1].id = LZMA_VLI_UNKNOWN;
@@ -80,7 +83,7 @@ easy_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
 
 static lzma_ret
 easy_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
-               lzma_easy_level level)
+               uint32_t level, uint32_t flags, lzma_check check)
 {
        lzma_next_coder_init(easy_encoder_init, next, allocator);
 
@@ -95,18 +98,19 @@ easy_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
                next->coder->stream_encoder = LZMA_NEXT_CODER_INIT;
        }
 
-       if (easy_set_filters(next->coder, level))
+       if (easy_set_filters(next->coder, level, flags))
                return LZMA_OPTIONS_ERROR;
 
        return lzma_stream_encoder_init(&next->coder->stream_encoder,
-                       allocator, next->coder->filters, LZMA_CHECK_CRC32);
+                       allocator, next->coder->filters, check);
 }
 
 
 extern LZMA_API lzma_ret
-lzma_easy_encoder(lzma_stream *strm, lzma_easy_level level)
+lzma_easy_encoder(lzma_stream *strm,
+               uint32_t level, uint32_t flags, lzma_check check)
 {
-       lzma_next_strm_init(easy_encoder_init, strm, level);
+       lzma_next_strm_init(easy_encoder_init, strm, level, flags, check);
 
        strm->internal->supported_actions[LZMA_RUN] = true;
        strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
@@ -118,11 +122,22 @@ lzma_easy_encoder(lzma_stream *strm, lzma_easy_level level)
 
 
 extern LZMA_API uint64_t
-lzma_easy_memory_usage(lzma_easy_level level)
+lzma_easy_encoder_memusage(uint32_t level, uint32_t flags)
 {
        lzma_coder coder;
-       if (easy_set_filters(&coder, level))
+       if (easy_set_filters(&coder, level, flags))
                return UINT32_MAX;
 
        return lzma_memusage_encoder(coder.filters);
 }
+
+
+extern LZMA_API uint64_t
+lzma_easy_decoder_memusage(uint32_t level, uint32_t flags)
+{
+       lzma_coder coder;
+       if (easy_set_filters(&coder, level, flags))
+               return UINT32_MAX;
+
+       return lzma_memusage_decoder(coder.filters);
+}
index 13a7cdd..fe3c03a 100644 (file)
@@ -264,5 +264,5 @@ lzma_memusage_coder(lzma_filter_find coder_find,
 
        // Add some fixed amount of extra. It's to compensate memory usage
        // of Stream, Block etc. coders, malloc() overhead, stack etc.
-       return total + (1U << 15);
+       return total + LZMA_MEMUSAGE_BASE;
 }
index 1fe6565..d7025ff 100644 (file)
@@ -114,6 +114,17 @@ struct lzma_index_s {
 };
 
 
+extern LZMA_API lzma_vli
+lzma_index_memusage(lzma_vli count)
+{
+       if (count > LZMA_VLI_MAX)
+               return UINT64_MAX;
+
+       return sizeof(lzma_index) + (count + INDEX_GROUP_SIZE - 1)
+                       / INDEX_GROUP_SIZE * sizeof(lzma_index_group);
+}
+
+
 static void
 free_index_list(lzma_index *i, lzma_allocator *allocator)
 {
index 5faac16..e29e0b0 100644 (file)
@@ -25,6 +25,7 @@ struct lzma_coder_s {
        enum {
                SEQ_INDICATOR,
                SEQ_COUNT,
+               SEQ_MEMUSAGE,
                SEQ_UNPADDED,
                SEQ_UNCOMPRESSED,
                SEQ_PADDING_INIT,
@@ -32,6 +33,9 @@ struct lzma_coder_s {
                SEQ_CRC32,
        } sequence;
 
+       /// Memory usage limit
+       uint64_t memlimit;
+
        /// Target Index
        lzma_index *index;
 
@@ -82,18 +86,27 @@ index_decode(lzma_coder *coder, lzma_allocator *allocator,
                coder->sequence = SEQ_COUNT;
                break;
 
-       case SEQ_COUNT: {
+       case SEQ_COUNT:
                ret = lzma_vli_decode(&coder->count, &coder->pos,
                                in, in_pos, in_size);
                if (ret != LZMA_STREAM_END)
                        goto out;
 
-               ret = LZMA_OK;
                coder->pos = 0;
+               coder->sequence = SEQ_MEMUSAGE;
+
+       // Fall through
+
+       case SEQ_MEMUSAGE:
+               if (lzma_index_memusage(coder->count) > coder->memlimit) {
+                       ret = LZMA_MEMLIMIT_ERROR;
+                       goto out;
+               }
+
+               ret = LZMA_OK;
                coder->sequence = coder->count == 0
                                ? SEQ_PADDING_INIT : SEQ_UNPADDED;
                break;
-       }
 
        case SEQ_UNPADDED:
        case SEQ_UNCOMPRESSED: {
@@ -197,12 +210,28 @@ index_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
 
 
 static lzma_ret
+index_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
+               uint64_t *old_memlimit, uint64_t new_memlimit)
+{
+       *memusage = lzma_index_memusage(coder->count);
+
+       if (new_memlimit != 0 && new_memlimit < *memusage)
+               return LZMA_MEMLIMIT_ERROR;
+
+       *old_memlimit = coder->memlimit;
+       coder->memlimit = new_memlimit;
+
+       return LZMA_OK;
+}
+
+
+static lzma_ret
 index_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
-               lzma_index **i)
+               lzma_index **i, uint64_t memlimit)
 {
        lzma_next_coder_init(index_decoder_init, next, allocator);
 
-       if (i == NULL)
+       if (i == NULL || memlimit == 0)
                return LZMA_PROG_ERROR;
 
        if (next->coder == NULL) {
@@ -212,6 +241,7 @@ index_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
 
                next->code = &index_decode;
                next->end = &index_decoder_end;
+               next->memconfig = &index_decoder_memconfig;
                next->coder->index = NULL;
        } else {
                lzma_index_end(next->coder->index, allocator);
@@ -224,7 +254,9 @@ index_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
 
        // Initialize the rest.
        next->coder->sequence = SEQ_INDICATOR;
+       next->coder->memlimit = memlimit;
        next->coder->index = *i;
+       next->coder->count = 0; // Needs to be initialized due to _memconfig().
        next->coder->pos = 0;
        next->coder->crc32 = 0;
 
@@ -233,9 +265,9 @@ index_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
 
 
 extern LZMA_API lzma_ret
-lzma_index_decoder(lzma_stream *strm, lzma_index **i)
+lzma_index_decoder(lzma_stream *strm, lzma_index **i, uint64_t memlimit)
 {
-       lzma_next_strm_init(index_decoder_init, strm, i);
+       lzma_next_strm_init(index_decoder_init, strm, i, memlimit);
 
        strm->internal->supported_actions[LZMA_RUN] = true;
 
index 9be4789..956a08f 100644 (file)
@@ -50,6 +50,9 @@ struct lzma_coder_s {
        /// Memory usage limit
        uint64_t memlimit;
 
+       /// Amount of memory actually needed (only an estimate)
+       uint64_t memusage;
+
        /// If true, LZMA_NO_CHECK is returned if the Stream has
        /// no integrity check.
        bool tell_no_check;
@@ -204,14 +207,24 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
                if (memusage == UINT64_MAX) {
                        // One or more unknown Filter IDs.
                        ret = LZMA_OPTIONS_ERROR;
-               } else if (memusage > coder->memlimit) {
-                       // The chain would need too much memory.
-                       ret = LZMA_MEMLIMIT_ERROR;
                } else {
-                       // Memory usage is OK. Initialize the Block decoder.
-                       ret = lzma_block_decoder_init(
-                                       &coder->block_decoder,
-                                       allocator, &coder->block_options);
+                       // Now we can set coder->memusage since we know that
+                       // the filter chain is valid. We don't want
+                       // lzma_memusage() to return UINT64_MAX in case of
+                       // invalid filter chain.
+                       coder->memusage = memusage;
+
+                       if (memusage > coder->memlimit) {
+                               // The chain would need too much memory.
+                               ret = LZMA_MEMLIMIT_ERROR;
+                       } else {
+                               // Memory usage is OK.
+                               // Initialize the Block decoder.
+                               ret = lzma_block_decoder_init(
+                                               &coder->block_decoder,
+                                               allocator,
+                                               &coder->block_options);
+                       }
                }
 
                // Free the allocated filter options since they are needed
@@ -374,12 +387,30 @@ stream_decoder_get_check(const lzma_coder *coder)
 }
 
 
+static lzma_ret
+stream_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
+               uint64_t *old_memlimit, uint64_t new_memlimit)
+{
+       if (new_memlimit != 0 && new_memlimit < coder->memusage)
+               return LZMA_MEMLIMIT_ERROR;
+
+       *memusage = coder->memusage;
+       *old_memlimit = coder->memlimit;
+       coder->memlimit = new_memlimit;
+
+       return LZMA_OK;
+}
+
+
 extern lzma_ret
 lzma_stream_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
                uint64_t memlimit, uint32_t flags)
 {
        lzma_next_coder_init(lzma_stream_decoder_init, next, allocator);
 
+       if (memlimit == 0)
+               return LZMA_PROG_ERROR;
+
        if (flags & ~LZMA_SUPPORTED_FLAGS)
                return LZMA_OPTIONS_ERROR;
 
@@ -391,12 +422,14 @@ lzma_stream_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
                next->code = &stream_decode;
                next->end = &stream_decoder_end;
                next->get_check = &stream_decoder_get_check;
+               next->memconfig = &stream_decoder_memconfig;
 
                next->coder->block_decoder = LZMA_NEXT_CODER_INIT;
                next->coder->index_hash = NULL;
        }
 
        next->coder->memlimit = memlimit;
+       next->coder->memusage = LZMA_MEMUSAGE_BASE;
        next->coder->tell_no_check = (flags & LZMA_TELL_NO_CHECK) != 0;
        next->coder->tell_unsupported_check
                        = (flags & LZMA_TELL_UNSUPPORTED_CHECK) != 0;
index 46912c3..09a2f2e 100644 (file)
@@ -369,11 +369,11 @@ lzma_lzma2_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
 extern uint64_t
 lzma_lzma2_encoder_memusage(const void *options)
 {
-       const uint64_t lzma_memusage = lzma_lzma_encoder_memusage(options);
-       if (lzma_memusage == UINT64_MAX)
+       const uint64_t lzma_mem = lzma_lzma_encoder_memusage(options);
+       if (lzma_mem == UINT64_MAX)
                return UINT64_MAX;
 
-       return sizeof(lzma_coder) + lzma_memusage;
+       return sizeof(lzma_coder) + lzma_mem;
 }
 
 
index d9d4e04..46e1d87 100644 (file)
@@ -19,6 +19,8 @@
 
 #include "tests.h"
 
+#define MEMLIMIT (LZMA_VLI_C(1) << 20)
+
 
 static lzma_index *
 create_empty(void)
@@ -170,7 +172,7 @@ test_code(lzma_index *i)
 
        // Decode
        lzma_index *d;
-       expect(lzma_index_decoder(&strm, &d) == LZMA_OK);
+       expect(lzma_index_decoder(&strm, &d, MEMLIMIT) == LZMA_OK);
        succeed(decoder_loop(&strm, buf, index_size));
 
        expect(lzma_index_equal(i, d));
@@ -464,19 +466,19 @@ test_corrupt(void)
 
        // Wrong Index Indicator
        buf[0] ^= 1;
-       expect(lzma_index_decoder(&strm, &i) == LZMA_OK);
+       expect(lzma_index_decoder(&strm, &i, MEMLIMIT) == LZMA_OK);
        succeed(decoder_loop_ret(&strm, buf, 1, LZMA_DATA_ERROR));
        buf[0] ^= 1;
 
        // Wrong Number of Records and thus CRC32 fails.
        --buf[1];
-       expect(lzma_index_decoder(&strm, &i) == LZMA_OK);
+       expect(lzma_index_decoder(&strm, &i, MEMLIMIT) == LZMA_OK);
        succeed(decoder_loop_ret(&strm, buf, 10, LZMA_DATA_ERROR));
        ++buf[1];
 
        // Padding not NULs
        buf[15] ^= 1;
-       expect(lzma_index_decoder(&strm, &i) == LZMA_OK);
+       expect(lzma_index_decoder(&strm, &i, MEMLIMIT) == LZMA_OK);
        succeed(decoder_loop_ret(&strm, buf, 16, LZMA_DATA_ERROR));
 
        lzma_end(&strm);