Signed-off-by: Stefan Beller <sbeller@xxxxxxxxxx> --- sha1-array.c | 39 +++++++++++++++++++++++++++++++++++++++ sha1-array.h | 3 +++ 2 files changed, 42 insertions(+) diff --git a/sha1-array.c b/sha1-array.c index 265941fbf40..10eb08b425e 100644 --- a/sha1-array.c +++ b/sha1-array.c @@ -77,3 +77,42 @@ int oid_array_for_each_unique(struct oid_array *array, } return 0; } + +int oid_array_remove_if(struct oid_array *array, + for_each_oid_fn fn, + void *data) +{ + int i, j; + char *to_remove = xcalloc(array->nr, sizeof(char)); + + /* No oid_array_sort() here! See the api-oid-array.txt docs! */ + + for (i = 0; i < array->nr; i++) { + int ret = fn(array->oid + i, data); + if (ret) + to_remove[i] = 1; + } + + i = 0, j = 0; + while (i < array->nr && j < array->nr) { + while (i < array->nr && !to_remove[i]) + i++; + /* i at first marked for deletion or out */ + if (j < i) + j = i; + while (j < array->nr && to_remove[j]) + j++; + /* j > i; j at first valid after first deletion range or out */ + if (i < array->nr && j < array->nr) + oidcpy(&array->oid[i], &array->oid[j]); + else if (i >= array->nr) + assert(j >= array->nr); + /* no pruning happened, keep original array->nr */ + else if (j >= array->nr) + array->nr = i; + } + + free(to_remove); + + return 0; +} diff --git a/sha1-array.h b/sha1-array.h index 232bf950172..151c7ad7f30 100644 --- a/sha1-array.h +++ b/sha1-array.h @@ -22,5 +22,8 @@ int oid_array_for_each(struct oid_array *array, int oid_array_for_each_unique(struct oid_array *array, for_each_oid_fn fn, void *data); +int oid_array_remove_if(struct oid_array *array, + for_each_oid_fn fn, + void *data); #endif /* SHA1_ARRAY_H */ -- 2.18.0.597.ga71716f1ad-goog