2 * Copyright (C) 2009-2012 the libgit2 contributors
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
9 #include "repository.h"
12 static const double git_vector_resize_factor
= 1.75;
13 static const size_t git_vector_minimum_size
= 8;
15 static int resize_vector(git_vector
*v
)
17 v
->_alloc_size
= (size_t)(v
->_alloc_size
* git_vector_resize_factor
) + 1;
18 if (v
->_alloc_size
< git_vector_minimum_size
)
19 v
->_alloc_size
= git_vector_minimum_size
;
21 v
->contents
= git__realloc(v
->contents
, v
->_alloc_size
* sizeof(void *));
22 GITERR_CHECK_ALLOC(v
->contents
);
27 int git_vector_dup(git_vector
*v
, const git_vector
*src
, git_vector_cmp cmp
)
31 v
->_alloc_size
= src
->length
;
33 v
->length
= src
->length
;
34 v
->sorted
= src
->sorted
&& cmp
== src
->_cmp
;
35 v
->contents
= git__malloc(src
->length
* sizeof(void *));
36 GITERR_CHECK_ALLOC(v
->contents
);
38 memcpy(v
->contents
, src
->contents
, src
->length
* sizeof(void *));
43 void git_vector_free(git_vector
*v
)
47 git__free(v
->contents
);
54 int git_vector_init(git_vector
*v
, size_t initial_size
, git_vector_cmp cmp
)
58 memset(v
, 0x0, sizeof(git_vector
));
60 if (initial_size
== 0)
61 initial_size
= git_vector_minimum_size
;
63 v
->_alloc_size
= initial_size
;
69 v
->contents
= git__malloc(v
->_alloc_size
* sizeof(void *));
70 GITERR_CHECK_ALLOC(v
->contents
);
75 int git_vector_insert(git_vector
*v
, void *element
)
79 if (v
->length
>= v
->_alloc_size
&&
83 v
->contents
[v
->length
++] = element
;
89 int git_vector_insert_sorted(
90 git_vector
*v
, void *element
, int (*on_dup
)(void **old
, void *new))
100 if (v
->length
>= v
->_alloc_size
&&
101 resize_vector(v
) < 0)
104 /* If we find the element and have a duplicate handler callback,
105 * invoke it. If it returns non-zero, then cancel insert, otherwise
106 * proceed with normal insert.
108 if (git__bsearch(v
->contents
, v
->length
, element
, v
->_cmp
, &pos
) >= 0 &&
110 (result
= on_dup(&v
->contents
[pos
], element
)) < 0)
113 /* shift elements to the right */
114 if (pos
< v
->length
) {
115 memmove(v
->contents
+ pos
+ 1, v
->contents
+ pos
,
116 (v
->length
- pos
) * sizeof(void *));
119 v
->contents
[pos
] = element
;
124 void git_vector_sort(git_vector
*v
)
128 if (v
->sorted
|| v
->_cmp
== NULL
)
131 git__tsort(v
->contents
, v
->length
, v
->_cmp
);
135 int git_vector_bsearch3(
138 git_vector_cmp key_lookup
,
144 assert(v
&& key
&& key_lookup
);
146 /* need comparison function to sort the vector */
147 assert(v
->_cmp
!= NULL
);
151 rval
= git__bsearch(v
->contents
, v
->length
, key
, key_lookup
, &pos
);
156 return (rval
>= 0) ? (int)pos
: GIT_ENOTFOUND
;
159 int git_vector_search2(
160 const git_vector
*v
, git_vector_cmp key_lookup
, const void *key
)
164 assert(v
&& key
&& key_lookup
);
166 for (i
= 0; i
< v
->length
; ++i
) {
167 if (key_lookup(key
, v
->contents
[i
]) == 0)
171 return GIT_ENOTFOUND
;
174 static int strict_comparison(const void *a
, const void *b
)
176 return (a
== b
) ? 0 : -1;
179 int git_vector_search(const git_vector
*v
, const void *entry
)
181 return git_vector_search2(v
, v
->_cmp
? v
->_cmp
: strict_comparison
, entry
);
184 int git_vector_remove(git_vector
*v
, size_t idx
)
190 if (idx
>= v
->length
|| v
->length
== 0)
191 return GIT_ENOTFOUND
;
193 for (i
= idx
; i
< v
->length
- 1; ++i
)
194 v
->contents
[i
] = v
->contents
[i
+ 1];
200 void git_vector_pop(git_vector
*v
)
206 void git_vector_uniq(git_vector
*v
)
215 cmp
= v
->_cmp
? v
->_cmp
: strict_comparison
;
217 for (i
= 0, j
= 1 ; j
< v
->length
; ++j
)
218 if (!cmp(v
->contents
[i
], v
->contents
[j
]))
219 v
->contents
[i
] = v
->contents
[j
];
221 v
->contents
[++i
] = v
->contents
[j
];
223 v
->length
-= j
- i
- 1;
226 void git_vector_remove_matching(
227 git_vector
*v
, int (*match
)(const git_vector
*v
, size_t idx
))
231 for (i
= 0, j
= 0; j
< v
->length
; ++j
) {
232 v
->contents
[i
] = v
->contents
[j
];
241 void git_vector_clear(git_vector
*v
)
248 void git_vector_swap(git_vector
*a
, git_vector
*b
)
252 if (!a
|| !b
|| a
== b
)
255 memcpy(&t
, a
, sizeof(t
));
256 memcpy(a
, b
, sizeof(t
));
257 memcpy(b
, &t
, sizeof(t
));
260 int git_vector_resize_to(git_vector
*v
, size_t new_length
)
262 if (new_length
<= v
->length
)
265 while (new_length
>= v
->_alloc_size
)
266 if (resize_vector(v
) < 0)
269 memset(&v
->contents
[v
->length
], 0,
270 sizeof(void *) * (new_length
- v
->length
));
272 v
->length
= new_length
;
277 int git_vector_set(void **old
, git_vector
*v
, size_t position
, void *value
)
279 if (git_vector_resize_to(v
, position
+ 1) < 0)
283 *old
= v
->contents
[position
];
285 v
->contents
[position
] = value
;