Skip to content

Commit 8a565a7

Browse files
romkatvtiennou
authored andcommitted
iterator: replace O(N) skip-to-start with O(log N)
1 parent 0e80a01 commit 8a565a7

1 file changed

Lines changed: 27 additions & 0 deletions

File tree

src/iterator.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,6 +2018,8 @@ typedef struct {
20182018
git_buf tree_buf;
20192019
bool skip_tree;
20202020

2021+
size_t end_idx;
2022+
20212023
const git_index_entry *entry;
20222024
} index_iterator;
20232025

@@ -2094,9 +2096,33 @@ static int index_iterator_advance(
20942096
const git_index_entry *entry = NULL;
20952097
bool is_submodule;
20962098
int error = 0;
2099+
git_index_entry key;
2100+
git_buf buf = GIT_BUF_INIT;
20972101

20982102
iter->base.flags |= GIT_ITERATOR_FIRST_ACCESS;
20992103

2104+
if (iter->end_idx == (size_t)-1) {
2105+
if (iter->base.start_len && !iterator__include_trees(&iter->base)) {
2106+
memset(&key, 0, sizeof(key));
2107+
if (iter->base.start[iter->base.start_len - 1] == '/') {
2108+
git_buf_puts(&buf, iter->base.start);
2109+
buf.ptr[buf.size - 1] = 0;
2110+
key.path = buf.ptr;
2111+
} else {
2112+
key.path = iter->base.start;
2113+
}
2114+
git_vector_bsearch(&iter->next_idx, &iter->entries, &key);
2115+
git_buf_dispose(&buf);
2116+
}
2117+
2118+
if (iter->base.end_len) {
2119+
key.path = iter->base.end;
2120+
if (!git_vector_bsearch(&iter->end_idx, &iter->entries, &key)) ++iter->end_idx;
2121+
} else {
2122+
iter->end_idx = iter->entries.length;
2123+
}
2124+
}
2125+
21002126
while (true) {
21012127
if (iter->next_idx >= iter->entries.length) {
21022128
error = GIT_ITEROVER;
@@ -2205,6 +2231,7 @@ static int index_iterator_init(index_iterator *iter)
22052231
iter->base.flags &= ~GIT_ITERATOR_FIRST_ACCESS;
22062232
iter->next_idx = 0;
22072233
iter->skip_tree = false;
2234+
iter->end_idx = -1;
22082235
return 0;
22092236
}
22102237

0 commit comments

Comments
 (0)