Commit 0543606d for xz
commit 0543606d156c3bd3bb5b1c08b848b4cbb794c094
Author: Lasse Collin <lasse.collin@tukaani.org>
Date: Sat Aug 15 19:42:55 2026 +0300
liblzma: index.c 2/4: Make index_tree_append support prepending too
diff --git a/src/liblzma/common/index.c b/src/liblzma/common/index.c
index ceaa9222..09ee2fed 100644
--- a/src/liblzma/common/index.c
+++ b/src/liblzma/common/index.c
@@ -57,13 +57,10 @@ typedef struct {
/// Root node
index_tree_node *root;
- /// Leftmost node. Since the tree will be filled sequentially,
- /// this won't change after the first node has been added to
- /// the tree.
+ /// Leftmost (first) node
index_tree_node *leftmost;
- /// The rightmost node in the tree. Since the tree is filled
- /// sequentially, this is always the node where to add the new data.
+ /// Rightmost (last) node
index_tree_node *rightmost;
/// Number of nodes in the tree
@@ -246,10 +243,13 @@ index_tree_end(index_tree *tree, const lzma_allocator *allocator,
/// Add a new node to the tree. node->uncompressed_base and
/// node->compressed_base must have been set by the caller already.
+///
+/// The tree is always filled sequentially: index_streams are prepended
+/// and index_groups are appended.
static void
-index_tree_append(index_tree *tree, index_tree_node *node)
+index_tree_append(index_tree *tree, index_tree_node *node, bool prepend)
{
- node->parent = tree->rightmost;
+ node->parent = prepend ? tree->leftmost : tree->rightmost;
node->left = NULL;
node->right = NULL;
@@ -263,14 +263,22 @@ index_tree_append(index_tree *tree, index_tree_node *node)
return;
}
- // The tree is always filled sequentially.
- assert(tree->rightmost->uncompressed_base <= node->uncompressed_base);
- assert(tree->rightmost->compressed_base < node->compressed_base);
-
- // Add the new node after the rightmost node. It's the correct
- // place due to the reason above.
- tree->rightmost->right = node;
- tree->rightmost = node;
+ // Add the new node before the leftmost or after the rightmost node.
+ if (prepend) {
+ assert(tree->leftmost->uncompressed_base
+ >= node->uncompressed_base);
+ assert(tree->leftmost->compressed_base
+ > node->compressed_base);
+ tree->leftmost->left = node;
+ tree->leftmost = node;
+ } else {
+ assert(tree->rightmost->uncompressed_base
+ <= node->uncompressed_base);
+ assert(tree->rightmost->compressed_base
+ < node->compressed_base);
+ tree->rightmost->right = node;
+ tree->rightmost = node;
+ }
// Balance the AVL-tree if needed. We don't need to keep the balance
// factors in nodes, because we always fill the tree sequentially,
@@ -285,11 +293,14 @@ index_tree_append(index_tree *tree, index_tree_node *node)
node = node->parent;
} while (--up > 0);
- // Rotate left using node as the rotation root.
- index_tree_node *pivot = node->right;
+ // Rotate right/left using node as the rotation root.
+ index_tree_node *pivot = prepend ? node->left : node->right;
if (node->parent == NULL) {
tree->root = pivot;
+ } else if (prepend) {
+ assert(node->parent->left == node);
+ node->parent->left = pivot;
} else {
assert(node->parent->right == node);
node->parent->right = pivot;
@@ -297,11 +308,20 @@ index_tree_append(index_tree *tree, index_tree_node *node)
pivot->parent = node->parent;
- node->right = pivot->left;
- if (node->right != NULL)
- node->right->parent = node;
+ if (prepend) {
+ node->left = pivot->right;
+ if (node->left != NULL)
+ node->left->parent = node;
+
+ pivot->right = node;
+ } else {
+ node->right = pivot->left;
+ if (node->right != NULL)
+ node->right->parent = node;
+
+ pivot->left = node;
+ }
- pivot->left = node;
node->parent = pivot;
}
@@ -429,7 +449,7 @@ lzma_index_init(const lzma_allocator *allocator)
return NULL;
}
- index_tree_append(&i->streams, &s->node);
+ index_tree_append(&i->streams, &s->node, false);
return i;
}
@@ -745,7 +765,7 @@ lzma_index_append(lzma_index *i, const lzma_allocator *allocator,
g->number_base = s->record_count + 1;
// Add the new group to the Stream.
- index_tree_append(&s->groups, &g->node);
+ index_tree_append(&s->groups, &g->node, false);
}
// Add the new Record to the group.
@@ -805,7 +825,7 @@ index_cat_helper(const index_cat_info *info, index_stream *this)
this->node.compressed_base += info->file_size;
this->number += info->stream_number_add;
this->block_number_base += info->block_number_add;
- index_tree_append(info->streams, &this->node);
+ index_tree_append(info->streams, &this->node, false);
if (right != NULL)
index_cat_helper(info, right);
@@ -980,7 +1000,7 @@ index_dup_stream(const index_stream *src, const lzma_allocator *allocator)
assert(i == destg->allocated);
// Add the group to the new Stream.
- index_tree_append(&dest->groups, &destg->node);
+ index_tree_append(&dest->groups, &destg->node, false);
return dest;
}
@@ -1015,7 +1035,7 @@ lzma_index_dup(const lzma_index *src, const lzma_allocator *allocator)
return NULL;
}
- index_tree_append(&dest->streams, &deststream->node);
+ index_tree_append(&dest->streams, &deststream->node, false);
srcstream = index_tree_next(&srcstream->node);
} while (srcstream != NULL);