21 #define INDEX_GROUP_SIZE 512
25 #define PREALLOC_MAX ((SIZE_MAX - sizeof(index_group)) / sizeof(index_record))
199 if (node->left !=
NULL)
202 if (node->right !=
NULL)
301 return (
void *)(node);
307 return (
void *)(node->
parent);
325 while (node !=
NULL) {
334 return (
void *)(result);
348 s->node.uncompressed_base = uncompressed_base;
349 s->node.compressed_base = compressed_base;
350 s->node.parent =
NULL;
352 s->node.right =
NULL;
354 s->number = stream_number;
355 s->block_number_base = block_number_base;
360 s->index_list_size = 0;
362 s->stream_padding = 0;
451 const size_t alloc_overhead = 4 *
sizeof(
void *);
483 ||
limit - streams_mem < groups_mem)
486 return index_base + streams_mem + groups_mem;
551 file_size +=
index_size(record_count, index_list_size);
565 g ==
NULL ? 0 :
g->records[
g->last].unpadded_sum,
566 s->record_count,
s->index_list_size,
608 stream_flags, stream_flags));
611 s->stream_flags = *stream_flags;
627 const lzma_vli old_stream_padding =
s->stream_padding;
628 s->stream_padding = 0;
630 s->stream_padding = old_stream_padding;
655 :
g->records[
g->last].uncompressed_sum;
662 s->index_list_size + index_list_size_add,
673 if (
g !=
NULL &&
g->last + 1 <
g->allocated) {
692 g->node.uncompressed_base = uncompressed_base;
693 g->node.compressed_base = compressed_base;
694 g->number_base =
s->record_count + 1;
701 g->records[
g->last].uncompressed_sum
703 g->records[
g->last].unpadded_sum
708 s->index_list_size += index_list_size_add;
755 this->number +=
info->stream_number_add;
756 this->block_number_base +=
info->block_number_add;
770 const lzma_vli dest_file_size = lzma_index_file_size(
dest);
786 dest->record_count,
dest->index_list_size);
798 if (
g !=
NULL &&
g->last + 1 <
g->allocated) {
809 newg->
node =
g->node;
811 newg->
last =
g->last;
817 if (
g->node.parent !=
NULL) {
818 assert(
g->node.parent->right == &
g->node);
819 g->node.parent->right = &newg->
node;
822 if (
s->groups.leftmost == &
g->node) {
824 s->groups.leftmost = &newg->
node;
825 s->groups.root = &newg->
node;
828 assert(
s->groups.rightmost == &
g->node);
829 s->groups.rightmost = &newg->
node;
841 .uncompressed_size =
dest->uncompressed_size,
842 .file_size = dest_file_size,
843 .stream_number_add =
dest->streams.count,
844 .block_number_add =
dest->record_count,
845 .streams = &
dest->streams,
873 src->node.uncompressed_base,
src->number,
881 dest->stream_flags =
src->stream_flags;
882 dest->stream_padding =
src->stream_padding;
885 if (
src->groups.leftmost ==
NULL)
914 }
while (srcg !=
NULL);
945 if (deststream ==
NULL) {
953 }
while (srcstream !=
NULL);
994 ||
stream->groups.rightmost != &group->
node) {
998 }
else if (
stream->groups.leftmost != &group->
node) {
1018 iter->stream.block_count =
stream->record_count;
1019 iter->stream.compressed_offset =
stream->node.compressed_base;
1020 iter->stream.uncompressed_offset =
stream->node.uncompressed_base;
1026 iter->stream.padding =
stream->stream_padding;
1032 iter->stream.uncompressed_size = 0;
1035 stream->groups.rightmost);
1042 iter->stream.uncompressed_size
1043 =
g->records[
g->last].uncompressed_sum;
1046 if (group !=
NULL) {
1048 iter->block.number_in_file =
iter->block.number_in_stream
1049 +
stream->block_number_base;
1051 iter->block.compressed_stream_offset
1055 iter->block.uncompressed_stream_offset
1059 iter->block.uncompressed_size
1061 -
iter->block.uncompressed_stream_offset;
1062 iter->block.unpadded_size
1064 -
iter->block.compressed_stream_offset;
1067 iter->block.compressed_stream_offset
1070 iter->block.compressed_file_offset
1071 =
iter->block.compressed_stream_offset
1072 +
iter->stream.compressed_offset;
1073 iter->block.uncompressed_file_offset
1074 =
iter->block.uncompressed_stream_offset
1075 +
iter->stream.uncompressed_offset;
1086 lzma_index_iter_rewind(
iter);
1131 stream->groups.leftmost);
1170 if (group ==
NULL) {
1182 stream->groups.leftmost);
1221 target -=
stream->node.uncompressed_base;
1233 size_t right = group->
last;
1235 while (left < right) {
1236 const size_t pos = left + (right - left) / 2;
lzma_index_iter_mode
Operation mode for lzma_index_iter_next()
@ LZMA_INDEX_ITER_BLOCK
Get the next Block.
@ LZMA_INDEX_ITER_STREAM
Get the next Stream.
@ LZMA_INDEX_ITER_NONEMPTY_BLOCK
Get the next non-empty Block.
const lzma_allocator lzma_vli unpadded_size
struct lzma_index_s lzma_index
Opaque data type to hold the Index(es) and other information.
RzBinInfo * info(RzBinFile *bf)
const lzma_allocator * allocator
static lzma_vli vli_ceil4(lzma_vli vli)
Round the variable-length integer to the next multiple of four.
#define UNPADDED_SIZE_MAX
Maximum Unpadded Size.
static lzma_vli index_size(lzma_vli count, lzma_vli index_list_size)
Calculate the size of the Index field including Index Padding.
static lzma_vli index_size_unpadded(lzma_vli count, lzma_vli index_list_size)
Calculate the size of the Index field excluding Index Padding.
#define UNPADDED_SIZE_MIN
Minimum Unpadded Size.
void lzma_index_prealloc(lzma_index *i, lzma_vli records)
static void index_tree_node_end(index_tree_node *node, const lzma_allocator *allocator, void(*free_func)(void *node, const lzma_allocator *allocator))
Helper for index_tree_end()
static void index_stream_end(void *node, const lzma_allocator *allocator)
Free the memory allocated for a Stream and its Record groups.
static lzma_index * index_init_plain(const lzma_allocator *allocator)
static lzma_vli index_file_size(lzma_vli compressed_base, lzma_vli unpadded_sum, lzma_vli record_count, lzma_vli index_list_size, lzma_vli stream_padding)
static void iter_set_info(lzma_index_iter *iter)
static index_stream * index_stream_init(lzma_vli compressed_base, lzma_vli uncompressed_base, uint32_t stream_number, lzma_vli block_number_base, const lzma_allocator *allocator)
Allocate and initialize a new Stream using the given base offsets.
#define INDEX_GROUP_SIZE
How many Records to allocate at once.
#define PREALLOC_MAX
How many Records can be allocated at once at maximum.
static void index_tree_init(index_tree *tree)
static void index_tree_append(index_tree *tree, index_tree_node *node)
static void index_tree_end(index_tree *tree, const lzma_allocator *allocator, void(*free_func)(void *node, const lzma_allocator *allocator))
static void * index_tree_next(const index_tree_node *node)
Get the next node in the tree. Return NULL if there are no more nodes.
uint32_t lzma_index_padding_size(const lzma_index *i)
static void * index_tree_locate(const index_tree *tree, lzma_vli target)
static void index_cat_helper(const index_cat_info *info, index_stream *this)
static index_stream * index_dup_stream(const index_stream *src, const lzma_allocator *allocator)
Duplicate an index_stream.
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
assert(limit<=UINT32_MAX/2)
static uint32_t const uint8_t uint32_t uint32_t limit
#define LZMA_BACKWARD_SIZE_MAX
#define LZMA_STREAM_HEADER_SIZE
Size of Stream Header and Stream Footer.
Common stuff for Stream flags coders.
Structure to pass info to index_cat_helper()
index_tree * streams
Destination index' Stream tree.
lzma_vli file_size
Compressed file size of the destination.
lzma_vli block_number_add
Same as above but for Block numbers.
uint32_t stream_number_add
lzma_vli uncompressed_size
Uncompressed size of the destination.
size_t last
Index of the last Record in use.
lzma_vli number_base
Number of Blocks in this Stream before this group.
size_t allocated
Number of Records that can be put in records[].
index_tree_node node
Every Record group is part of index_stream.groups tree.
lzma_vli uncompressed_sum
index_tree_node node
Every index_stream is a node in the tree of Streams.
uint32_t number
Number of this Stream (first one is 1)
lzma_vli block_number_base
Total number of Blocks before this Stream.
lzma_stream_flags stream_flags
lzma_vli record_count
Number of Records in this Stream.
lzma_vli uncompressed_base
lzma_vli compressed_base
Compressed start offset of this Stream or Block.
AVL tree to hold index_stream or index_group structures.
index_tree_node * rightmost
uint32_t count
Number of nodes in the tree.
index_tree_node * leftmost
index_tree_node * root
Root node.
Custom functions for memory handling.
Iterator to get information about Blocks and Streams.
lzma_vli total_size
Total size of all the Blocks in the Stream(s)
lzma_vli record_count
Total number of Records in all Streams in this lzma_index.
lzma_vli uncompressed_size
Uncompressed size of all the Blocks in the Stream(s)
Options for encoding/decoding Stream Header and Stream Footer.
#define return_if_error(expr)
Return if expression doesn't evaluate to LZMA_OK.
void * lzma_alloc(size_t size, const lzma_allocator *allocator) lzma_attribute((__malloc__)) lzma_attr_alloc_size(1)
Allocates memory.
uint64_t uncompressed_size
static uint32_t ctz32(uint32_t n)
static uint32_t bsr32(uint32_t n)
uint64_t lzma_vli
Variable-length integer type.
#define LZMA_VLI_C(n)
VLI constant suffix.
#define LZMA_VLI_UNKNOWN
VLI value to denote that the value is unknown.
#define LZMA_VLI_MAX
Maximum supported value of a variable-length integer.
lzma_ret
Return values used by several functions in liblzma.
@ LZMA_PROG_ERROR
Programming error.
@ LZMA_DATA_ERROR
Data is corrupt.
@ LZMA_MEM_ERROR
Cannot allocate memory.
@ LZMA_OK
Operation completed successfully.
unsigned char lzma_bool
Boolean.
void lzma_free(void *ptr, const lzma_allocator *allocator)
Frees memory.