/**
* \file lzma/info.h
* \brief Handling of Stream size information
*
* \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
/**********
* Basics *
**********/
/**
* \brief Opaque data type to hold the size information
*/
typedef struct lzma_info_s lzma_info;
typedef struct {
/**
* \brief Total Size of this Block
*
* This can be LZMA_VLI_VALUE_UNKNOWN.
*/
lzma_vli total_size;
/**
* \brief Uncompressed Size of this Block
*
* This can be LZMA_VLI_VALUE_UNKNOWN.
*/
lzma_vli uncompressed_size;
/**
* \brief Offset of the first byte of the Block
*
* In encoder, this is useful to find out the alignment of the Block.
*
* In decoder, this is useful when doing random-access reading
* with help from lzma_info_data_locate().
*/
lzma_vli stream_offset;
/**
* \brief Uncompressed offset of the Block
*
* Offset of the first uncompressed byte of the Block relative to
* all uncompressed data in the Block.
* FIXME desc
*/
lzma_vli uncompressed_offset;
/**
* \brief Pointers to internal data structures
*
* Applications must not touch these.
*/
void *internal[4];
} lzma_info_iter;
typedef enum {
LZMA_INFO_STREAM_START,
LZMA_INFO_HEADER_METADATA,
LZMA_INFO_TOTAL,
LZMA_INFO_UNCOMPRESSED,
LZMA_INFO_FOOTER_METADATA
} lzma_info_size;
/**
* \brief Allocates and initializes a new lzma_info structure
*
* If info is NULL, a new lzma_info structure is allocated, initialized, and
* a pointer to it returned. If allocation fails, NULL is returned.
*
* If info 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 info given as argument.)
*/
extern lzma_info *lzma_info_init(lzma_info *info, lzma_allocator *allocator);
/**
* \brief Resets lzma_info
*
* This is like calling lzma_info_end() and lzma_info_create(), but
* re-uses the existing base structure.
*/
extern void lzma_info_reset(
lzma_info *info, lzma_allocator *allocator);
/**
* \brief Frees memory allocated for a lzma_info structure
*/
extern void lzma_info_free(lzma_info *info, lzma_allocator *allocator);
/************************
* Setting known values *
************************/
/**
* \brief Set a known size value
*
* \param info Pointer returned by lzma_info_create()
* \param type Any value from lzma_info_size
* \param size Value to set or verify
*
* \return LZMA_OK on success, LZMA_DATA_ERROR if the size doesn't
* match the existing information, or LZMA_PROG_ERROR
* if type is invalid or size is not a valid VLI.
*/
extern lzma_ret lzma_info_size_set(
lzma_info *info, lzma_info_size type, lzma_vli size);
/**
* \brief Sets the Index
*
* The given lzma_index list is "absorbed" by this function. The application
* must not access it after this function call, even if this function returns
* an error.
*
* \note The given lzma_index will at some point get freed by the
* lzma_info_* functions. If you use a custom lzma_allocator,
* make sure that it can free the lzma_index.
*/
extern lzma_ret lzma_info_index_set(
lzma_info *info, lzma_allocator *allocator,
lzma_index *index, lzma_bool eat_index);
/**
* \brief Sets information from a known Metadata Block
*
* This is a shortcut for calling lzma_info_size_set() with different type
* arguments, lzma_info_index_set() with metadata->index.
*/
extern lzma_ret lzma_info_metadata_set(lzma_info *info,
lzma_allocator *allocator, lzma_metadata *metadata,
lzma_bool is_header_metadata, lzma_bool eat_index);
/***************
* Incremental *
***************/
/**
* \brief Prepares an iterator to be used with given lzma_info structure
*
*
*/
extern void lzma_info_iter_begin(lzma_info *info, lzma_info_iter *iter);
/**
* \brief Moves to the next Index Record
*
*
*/
extern lzma_ret lzma_info_iter_next(
lzma_info_iter *iter, lzma_allocator *allocator);
/**
* \brief Sets or verifies the sizes in the Index Record
*
* \param iter Pointer to iterator to be set or verified
* \param total_size
* Total Size in bytes or LZMA_VLI_VALUE_UNKNOWN
* \param uncompressed_size
* Uncompressed Size or LZMA_VLI_VALUE_UNKNOWN
*
* \return - LZMA_OK: All OK.
* - LZMA_DATA_ERROR: Given sizes don't match with the already
* known sizes.
* - LZMA_PROG_ERROR: Internal error, possibly integer
* overflow (e.g. the sum of all the known sizes is too big)
*/
extern lzma_ret lzma_info_iter_set(lzma_info_iter *iter,
lzma_vli total_size, lzma_vli uncompressed_size);
/**
* \brief Locates a Data Block
*
* \param iter Properly initialized iterator
* \param allocator Pointer to lzma_allocator or NULL
* \param uncompressed_offset
* Target offset to locate. The final offset
* will be equal or smaller than this.
* \param allow_alloc True if this function is allowed to call
* lzma_info_iter_next() to allocate a new Record
* if the requested offset reached end of Index
* Record list. Note that if Index has been marked
* final, lzma_info_iter_next() is never called.
*
* \return - LZMA_OK: All OK, *iter updated accordingly.
* - LZMA_DATA_ERROR: Trying to search past the end of the Index
* Record list, and allocating a new Record was not allowed
* either because allow_alloc was false or Index was final.
* - LZMA_PROG_ERROR: Internal error (probably integer
* overflow causing some lzma_vli getting too big).
*/
extern lzma_ret lzma_info_iter_locate(lzma_info_iter *iter,
lzma_allocator *allocator, lzma_vli uncompressed_offset,
lzma_bool allow_alloc);
/**
* \brief Finishes incrementally constructed Index
*
* This sets the known Total Size and Uncompressed of the Data Blocks
* based on the information collected from the Index Records, and marks
* the Index as final.
*/
extern lzma_ret lzma_info_index_finish(lzma_info *info);
/***************************
* Reading the information *
***************************/
/**
* \brief Gets a known size
*
*
*/
extern lzma_vli lzma_info_size_get(
const lzma_info *info, lzma_info_size type);
extern lzma_vli lzma_info_metadata_locate(
const lzma_info *info, lzma_bool is_header_metadata);
/**
* \brief Gets a pointer to the beginning of the Index list
*
* If detach is true, the Index will be detached from the lzma_info
* structure, and thus not be modified or freed by lzma_info_end().
*
* If detach is false, the application must not modify the Index in any way.
* Also, the Index list is guaranteed to be valid only till the next call
* to any lzma_info_* function.
*/
extern lzma_index *lzma_info_index_get(lzma_info *info, lzma_bool detach);
extern size_t lzma_info_index_count_get(const lzma_info *info);
extern uint32_t lzma_info_metadata_alignment_get(
const lzma_info *info, lzma_bool is_header_metadata);
/**
* \brief Locate a Block containing the given uncompressed offset
*
* This function is useful when you need to do random-access reading in
* a Multi-Block Stream.
*
* \param info Pointer to lzma_info that has at least one
* Index Record. The Index doesn't need to be finished.
* \param uncompressed_target
* Uncompressed target offset which the caller would
* like to locate from the Stream.
* \param stream_offset
* Starting offset (relative to the beginning the Stream)
* of the Block containing the requested location.
* \param uncompressed_offset
* The actual uncompressed offset of the beginning of
* the Block. uncompressed_offset <= uncompressed_target
* is always true; the application needs to uncompress
* uncompressed_target - uncompressed_offset bytes to
* reach the requested target offset.
* \param total_size
* Total Size of the Block. If the Index is incomplete,
* this may be LZMA_VLI_VALUE_UNKNOWN indicating unknown
* size.
* \param uncompressed_size
* Uncompressed Size of the Block. If the Index is
* incomplete, this may be LZMA_VLI_VALUE_UNKNOWN
* indicating unknown size. The application must pass
* this value to the Block decoder to verify FIXME
*
* \return
*
* \note This function is currently implemented as a linear search.
* If there are many Index Records, this can be really slow.
* This can be improved in newer liblzma versions if needed.
*/
extern lzma_bool lzma_info_data_locate(const lzma_info *info,
lzma_vli uncompressed_target,
lzma_vli *lzma_restrict stream_offset,
lzma_vli *lzma_restrict uncompressed_offset,
lzma_vli *lzma_restrict total_size,
lzma_vli *lzma_restrict uncompressed_size);