410 lines
12 KiB
C
410 lines
12 KiB
C
|
/**
|
||
|
* \file lzma/block.h
|
||
|
* \brief .lzma Block handling
|
||
|
*
|
||
|
* \author Copyright (C) 1999-2006 Igor Pavlov
|
||
|
* \author Copyright (C) 2007 Lasse Collin
|
||
|
*
|
||
|
* This library is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU Lesser General Public
|
||
|
* License as published by the Free Software Foundation; either
|
||
|
* version 2.1 of the License, or (at your option) any later version.
|
||
|
*
|
||
|
* This library is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
* Lesser General Public License for more details.
|
||
|
*/
|
||
|
|
||
|
#ifndef LZMA_H_INTERNAL
|
||
|
# error Never include this file directly. Use <lzma.h> instead.
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/**
|
||
|
* \brief Options for the Block Header encoder and decoder
|
||
|
*
|
||
|
* Different things use different parts of this structure. Some read
|
||
|
* some members, other functions write, and some do both. Only the
|
||
|
* members listed for reading need to be initialized when the specified
|
||
|
* functions are called. The members marked for writing will be assigned
|
||
|
* new values at some point either by calling the given function or by
|
||
|
* later calls to lzma_code().
|
||
|
*/
|
||
|
typedef struct {
|
||
|
/**
|
||
|
* \brief 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.
|
||
|
*
|
||
|
* Read by:
|
||
|
* - lzma_block_encoder()
|
||
|
* - lzma_block_decoder()
|
||
|
*/
|
||
|
lzma_check_type check;
|
||
|
|
||
|
/**
|
||
|
* \brief Precense of CRC32 of the Block Header
|
||
|
*
|
||
|
* Set this to true if CRC32 of the Block Header should be
|
||
|
* calculated and stored in the Block Header.
|
||
|
*
|
||
|
* There is no way to autodetect if CRC32 is present in the Block
|
||
|
* Header, thus this information must be provided also when decoding.
|
||
|
*
|
||
|
* Read by:
|
||
|
* - lzma_block_header_size()
|
||
|
* - lzma_block_header_encoder()
|
||
|
* - lzma_block_header_decoder()
|
||
|
*/
|
||
|
lzma_bool has_crc32;
|
||
|
|
||
|
/**
|
||
|
* \brief Usage of End of Payload Marker
|
||
|
*
|
||
|
* If this is true, End of Payload Marker is used even if
|
||
|
* Uncompressed Size is known.
|
||
|
*
|
||
|
* Read by:
|
||
|
* - lzma_block_header_encoder()
|
||
|
* - lzma_block_encoder()
|
||
|
* - lzma_block_decoder()
|
||
|
*
|
||
|
* Written by:
|
||
|
* - lzma_block_header_decoder()
|
||
|
*/
|
||
|
lzma_bool has_eopm;
|
||
|
|
||
|
/**
|
||
|
* \brief True if the Block is a Metadata Block
|
||
|
*
|
||
|
* If this is true, the Metadata bit will be set in the Block Header.
|
||
|
* It is up to the application to store correctly formatted data
|
||
|
* into Metadata Block.
|
||
|
*
|
||
|
* Read by:
|
||
|
* - lzma_block_header_encoder()
|
||
|
*
|
||
|
* Written by:
|
||
|
* - lzma_block_header_decoder()
|
||
|
*/
|
||
|
lzma_bool is_metadata;
|
||
|
|
||
|
/**
|
||
|
* \brief True if Uncompressed Size is in Block Footer
|
||
|
*
|
||
|
* Read by:
|
||
|
* - lzma_block_encoder()
|
||
|
* - lzma_block_decoder()
|
||
|
*/
|
||
|
lzma_bool has_uncompressed_size_in_footer;
|
||
|
|
||
|
/**
|
||
|
* \brief True if Backward Size is in Block Footer
|
||
|
*
|
||
|
* Read by:
|
||
|
* - lzma_block_encoder()
|
||
|
* - lzma_block_decoder()
|
||
|
*/
|
||
|
lzma_bool has_backward_size;
|
||
|
|
||
|
/**
|
||
|
* \brief True if Block coder should take care of Padding
|
||
|
*
|
||
|
* In liblzma, Stream decoder sets this to true when decoding
|
||
|
* Header Metadata Block or Data Blocks from Multi-Block Stream,
|
||
|
* and to false when decoding Single-Block Stream or Footer
|
||
|
* Metadata Block from a Multi-Block Stream.
|
||
|
*
|
||
|
* Read by:
|
||
|
* - lzma_block_encoder()
|
||
|
* - lzma_block_decoder()
|
||
|
*/
|
||
|
lzma_bool handle_padding;
|
||
|
|
||
|
/**
|
||
|
* \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.
|
||
|
*
|
||
|
* Read by:
|
||
|
* - lzma_block_header_size()
|
||
|
* - lzma_block_header_encoder()
|
||
|
* - lzma_block_encoder()
|
||
|
* - lzma_block_decoder()
|
||
|
*
|
||
|
* Written by:
|
||
|
* - lzma_block_header_decoder()
|
||
|
* - lzma_block_encoder()
|
||
|
* - lzma_block_decoder()
|
||
|
*/
|
||
|
lzma_vli compressed_size;
|
||
|
|
||
|
/**
|
||
|
* \brief Uncompressed Size in bytes
|
||
|
*
|
||
|
* Encoder: If this value is not LZMA_VLI_VALUE_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_HEADER_ERROR is returned.
|
||
|
*
|
||
|
* If Uncompressed Size is unknown, End of Payload Marker must
|
||
|
* be used. If uncompressed_size == LZMA_VLI_VALUE_UNKNOWN and
|
||
|
* has_eopm == 0, LZMA_HEADER_ERROR will be returned.
|
||
|
*
|
||
|
* Decoder: If this value is not LZMA_VLI_VALUE_UNKNOWN, it is
|
||
|
* compared to the real Uncompressed Size. If they do not match,
|
||
|
* LZMA_HEADER_ERROR is returned.
|
||
|
*
|
||
|
* Read by:
|
||
|
* - lzma_block_header_size()
|
||
|
* - lzma_block_header_encoder()
|
||
|
* - lzma_block_encoder()
|
||
|
* - lzma_block_decoder()
|
||
|
*
|
||
|
* Written by:
|
||
|
* - lzma_block_header_decoder()
|
||
|
* - lzma_block_encoder()
|
||
|
* - lzma_block_decoder()
|
||
|
*/
|
||
|
lzma_vli uncompressed_size;
|
||
|
|
||
|
/**
|
||
|
* \brief Number of bytes to reserve for Compressed Size
|
||
|
*
|
||
|
* This is useful if you want to be able to store the Compressed Size
|
||
|
* to the Block Header, but you don't know it when starting to encode.
|
||
|
* Setting this to non-zero value at maximum of LZMA_VLI_BYTES_MAX,
|
||
|
* the Block Header encoder will force the Compressed Size field to
|
||
|
* occupy specified number of bytes. You can later rewrite the Block
|
||
|
* Header to contain correct information by using otherwise identical
|
||
|
* lzma_options_block structure except the correct compressed_size.
|
||
|
*
|
||
|
* Read by:
|
||
|
* - lzma_block_header_size()
|
||
|
* - lzma_block_header_encoder()
|
||
|
*
|
||
|
* Written by:
|
||
|
* - lzma_block_header_decoder()
|
||
|
*/
|
||
|
uint32_t compressed_reserve;
|
||
|
|
||
|
/**
|
||
|
* \brief Number of bytes to reserve for Uncompressed Size
|
||
|
*
|
||
|
* See the description of compressed_size above.
|
||
|
*
|
||
|
* Read by:
|
||
|
* - lzma_block_header_size()
|
||
|
* - lzma_block_header_encoder()
|
||
|
*
|
||
|
* Written by:
|
||
|
* - lzma_block_header_decoder()
|
||
|
*/
|
||
|
uint32_t uncompressed_reserve;
|
||
|
|
||
|
/**
|
||
|
* \brief Total Size of the Block in bytes
|
||
|
*
|
||
|
* This is useful in the decoder, which can verify the Total Size
|
||
|
* if it is known from Index.
|
||
|
*
|
||
|
* Read by:
|
||
|
* - lzma_block_encoder()
|
||
|
* - lzma_block_decoder()
|
||
|
*
|
||
|
* Written by:
|
||
|
* - lzma_block_encoder()
|
||
|
* - lzma_block_decoder()
|
||
|
*/
|
||
|
lzma_vli total_size;
|
||
|
|
||
|
/**
|
||
|
* \brief Upper limit of Total Size
|
||
|
*
|
||
|
* Read by:
|
||
|
* - lzma_block_encoder()
|
||
|
* - lzma_block_decoder()
|
||
|
*/
|
||
|
lzma_vli total_limit;
|
||
|
|
||
|
/**
|
||
|
* \brief Upper limit of Uncompressed Size
|
||
|
*
|
||
|
* Read by:
|
||
|
* - lzma_block_encoder()
|
||
|
* - lzma_block_decoder()
|
||
|
*/
|
||
|
lzma_vli uncompressed_limit;
|
||
|
|
||
|
/**
|
||
|
* \brief Array of filters
|
||
|
*
|
||
|
* There can be at maximum of seven filters. The end of the array
|
||
|
* is marked with .id = LZMA_VLI_VALUE_UNKNOWN. Minimum number of
|
||
|
* filters is zero; in that case, an implicit Copy filter is used.
|
||
|
*
|
||
|
* Read by:
|
||
|
* - lzma_block_header_size()
|
||
|
* - lzma_block_header_encoder()
|
||
|
* - lzma_block_encoder()
|
||
|
* - lzma_block_decoder()
|
||
|
*
|
||
|
* Written by:
|
||
|
* - lzma_block_header_decoder(): Note that this does NOT free()
|
||
|
* the old filter options structures. If decoding fails, the
|
||
|
* caller must take care of freeing the options structures
|
||
|
* that may have been allocated and decoded before the error
|
||
|
* occurred.
|
||
|
*/
|
||
|
lzma_options_filter filters[8];
|
||
|
|
||
|
/**
|
||
|
* \brief Size of the Padding field
|
||
|
*
|
||
|
* The Padding field exist to allow aligning the Compressed Data field
|
||
|
* optimally in the Block. See lzma_options_stream.alignment in
|
||
|
* stream.h for more information.
|
||
|
*
|
||
|
* If you want the Block Header encoder to automatically calculate
|
||
|
* optimal size for the Padding field by looking at the information
|
||
|
* in filters[], set this to LZMA_BLOCK_HEADER_PADDING_AUTO. In that
|
||
|
* case, you must also set the aligmnet variable to tell the the
|
||
|
* encoder the aligmnet of the beginning of the Block Header.
|
||
|
*
|
||
|
* The decoder never sets this to LZMA_BLOCK_HEADER_PADDING_AUTO.
|
||
|
*
|
||
|
* Read by:
|
||
|
* - lzma_block_header_size()
|
||
|
* - lzma_block_header_encoder(): Note that this doesn't
|
||
|
* accept LZMA_BLOCK_HEADER_PADDING_AUTO.
|
||
|
*
|
||
|
* Written by (these never set padding to
|
||
|
* LZMA_BLOCK_HEADER_PADDING_AUTO):
|
||
|
* - lzma_block_header_size()
|
||
|
* - lzma_block_header_decoder()
|
||
|
*/
|
||
|
int32_t padding;
|
||
|
# define LZMA_BLOCK_HEADER_PADDING_AUTO (-1)
|
||
|
# define LZMA_BLOCK_HEADER_PADDING_MIN 0
|
||
|
# define LZMA_BLOCK_HEADER_PADDING_MAX 31
|
||
|
|
||
|
/**
|
||
|
* \brief Alignment of the beginning of the Block Header
|
||
|
*
|
||
|
* This variable is read only if padding has been set to
|
||
|
* LZMA_BLOCK_HEADER_PADDING_AUTO.
|
||
|
*
|
||
|
* Read by:
|
||
|
* - lzma_block_header_size()
|
||
|
* - lzma_block_header_encoder()
|
||
|
*/
|
||
|
uint32_t alignment;
|
||
|
|
||
|
/**
|
||
|
* \brief Size of the Block Header
|
||
|
*
|
||
|
* Read by:
|
||
|
* - lzma_block_encoder()
|
||
|
* - lzma_block_decoder()
|
||
|
*
|
||
|
* Written by:
|
||
|
* - lzma_block_header_size()
|
||
|
* - lzma_block_header_decoder()
|
||
|
*/
|
||
|
uint32_t header_size;
|
||
|
|
||
|
} lzma_options_block;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* \brief Calculates the size of Header Padding and Block Header
|
||
|
*
|
||
|
* \return - LZMA_OK: Size calculated successfully and stored to
|
||
|
* options->header_size.
|
||
|
* - LZMA_HEADER_ERROR: Unsupported filters or filter options.
|
||
|
* - LZMA_PROG_ERROR: Invalid options
|
||
|
*
|
||
|
* \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.
|
||
|
*/
|
||
|
extern lzma_ret lzma_block_header_size(lzma_options_block *options);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* \brief Encodes 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().
|
||
|
*
|
||
|
* \param out Beginning of the output buffer. This must be
|
||
|
* at least options->header_size bytes.
|
||
|
* \param options Block options to be encoded.
|
||
|
*
|
||
|
* \return - LZMA_OK: Encoding was successful. options->header_size
|
||
|
* bytes were written to output buffer.
|
||
|
* - LZMA_HEADER_ERROR: Invalid or unsupported options.
|
||
|
* - LZMA_PROG_ERROR
|
||
|
*/
|
||
|
extern lzma_ret lzma_block_header_encode(
|
||
|
uint8_t *out, const lzma_options_block *options);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* \brief Initializes Block Header decoder
|
||
|
*
|
||
|
* Because the results of this decoder are placed into *options,
|
||
|
* strm->next_in, strm->avail_in, and strm->total_in are not used.
|
||
|
*
|
||
|
* The only valid `action' with lzma_code() is LZMA_RUN.
|
||
|
*
|
||
|
* \return - LZMA_OK: Encoding was successful. options->header_size
|
||
|
* bytes were written to output buffer.
|
||
|
* - LZMA_HEADER_ERROR: Invalid or unsupported options.
|
||
|
* - LZMA_PROG_ERROR
|
||
|
*/
|
||
|
extern lzma_ret lzma_block_header_decoder(
|
||
|
lzma_stream *strm, lzma_options_block *options);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* \brief Initializes .lzma Block encoder
|
||
|
*
|
||
|
* This function is required for multi-thread encoding. It may also be
|
||
|
* useful when implementing custom file formats.
|
||
|
*
|
||
|
* \return - LZMA_OK: All good, continue with lzma_code().
|
||
|
* - LZMA_MEM_ERROR
|
||
|
* - LZMA_HEADER_ERROR
|
||
|
* - LZMA_DATA_ERROR: Limits (total_limit and uncompressed_limit)
|
||
|
* have been reached already.
|
||
|
* - LZMA_UNSUPPORTED_CHECK: options->check specfies a Check
|
||
|
* 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_options_block *options);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* \brief Initializes decoder for .lzma Block
|
||
|
*
|
||
|
* \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
|
||
|
* ignored.
|
||
|
* - LZMA_PROG_ERROR
|
||
|
* - LZMA_MEM_ERROR
|
||
|
*/
|
||
|
extern lzma_ret lzma_block_decoder(
|
||
|
lzma_stream *strm, lzma_options_block *options);
|