diff options
Diffstat (limited to 'src/vector.c')
-rw-r--r-- | src/vector.c | 80 |
1 files changed, 66 insertions, 14 deletions
diff --git a/src/vector.c b/src/vector.c index 362e7b0c0..c769b696a 100644 --- a/src/vector.c +++ b/src/vector.c @@ -6,7 +6,6 @@ */ #include "common.h" -#include "repository.h" #include "vector.h" /* In elements, not bytes */ @@ -55,9 +54,11 @@ int git_vector_dup(git_vector *v, const git_vector *src, git_vector_cmp cmp) bytes = src->length * sizeof(void *); v->_alloc_size = src->length; - v->_cmp = cmp; + v->_cmp = cmp ? cmp : src->_cmp; v->length = src->length; - v->sorted = src->sorted && cmp == src->_cmp; + v->flags = src->flags; + if (cmp != src->_cmp) + git_vector_set_sorted(v, 0); v->contents = git__malloc(bytes); GITERR_CHECK_ALLOC(v->contents); @@ -77,6 +78,20 @@ void git_vector_free(git_vector *v) v->_alloc_size = 0; } +void git_vector_free_deep(git_vector *v) +{ + size_t i; + + assert(v); + + for (i = 0; i < v->length; ++i) { + git__free(v->contents[i]); + v->contents[i] = NULL; + } + + git_vector_free(v); +} + int git_vector_init(git_vector *v, size_t initial_size, git_vector_cmp cmp) { assert(v); @@ -84,12 +99,28 @@ int git_vector_init(git_vector *v, size_t initial_size, git_vector_cmp cmp) v->_alloc_size = 0; v->_cmp = cmp; v->length = 0; - v->sorted = 1; + v->flags = GIT_VECTOR_SORTED; v->contents = NULL; return resize_vector(v, max(initial_size, MIN_ALLOCSIZE)); } +void **git_vector_detach(size_t *size, size_t *asize, git_vector *v) +{ + void **data = v->contents; + + if (size) + *size = v->length; + if (asize) + *asize = v->_alloc_size; + + v->_alloc_size = 0; + v->length = 0; + v->contents = NULL; + + return data; +} + int git_vector_insert(git_vector *v, void *element) { assert(v); @@ -99,7 +130,8 @@ int git_vector_insert(git_vector *v, void *element) return -1; v->contents[v->length++] = element; - v->sorted = 0; + + git_vector_set_sorted(v, v->length <= 1); return 0; } @@ -112,7 +144,7 @@ int git_vector_insert_sorted( assert(v && v->_cmp); - if (!v->sorted) + if (!git_vector_is_sorted(v)) git_vector_sort(v); if (v->length >= v->_alloc_size && @@ -142,11 +174,12 @@ void git_vector_sort(git_vector *v) { assert(v); - if (v->sorted || !v->_cmp) + if (git_vector_is_sorted(v) || !v->_cmp) return; - git__tsort(v->contents, v->length, v->_cmp); - v->sorted = 1; + if (v->length > 1) + git__tsort(v->contents, v->length, v->_cmp); + git_vector_set_sorted(v, 1); } int git_vector_bsearch2( @@ -244,14 +277,16 @@ void git_vector_uniq(git_vector *v, void (*git_free_cb)(void *)) } void git_vector_remove_matching( - git_vector *v, int (*match)(const git_vector *v, size_t idx)) + git_vector *v, + int (*match)(const git_vector *v, size_t idx, void *payload), + void *payload) { size_t i, j; for (i = 0, j = 0; j < v->length; ++j) { v->contents[i] = v->contents[j]; - if (!match(v, i)) + if (!match(v, i, payload)) i++; } @@ -262,7 +297,7 @@ void git_vector_clear(git_vector *v) { assert(v); v->length = 0; - v->sorted = 1; + git_vector_set_sorted(v, 1); } void git_vector_swap(git_vector *a, git_vector *b) @@ -295,8 +330,10 @@ int git_vector_resize_to(git_vector *v, size_t new_length) int git_vector_set(void **old, git_vector *v, size_t position, void *value) { - if (git_vector_resize_to(v, position + 1) < 0) - return -1; + if (position + 1 > v->length) { + if (git_vector_resize_to(v, position + 1) < 0) + return -1; + } if (old != NULL) *old = v->contents[position]; @@ -305,3 +342,18 @@ int git_vector_set(void **old, git_vector *v, size_t position, void *value) return 0; } + +int git_vector_verify_sorted(const git_vector *v) +{ + size_t i; + + if (!git_vector_is_sorted(v)) + return -1; + + for (i = 1; i < v->length; ++i) { + if (v->_cmp(v->contents[i - 1], v->contents[i]) > 0) + return -1; + } + + return 0; +} |