2 * Generic reference iterator infrastructure. See refs-internal.h for
3 * documentation about the design and use of reference iterators.
8 #include "refs/refs-internal.h"
11 int ref_iterator_advance(struct ref_iterator
*ref_iterator
)
13 return ref_iterator
->vtable
->advance(ref_iterator
);
16 int ref_iterator_peel(struct ref_iterator
*ref_iterator
,
17 struct object_id
*peeled
)
19 return ref_iterator
->vtable
->peel(ref_iterator
, peeled
);
22 int ref_iterator_abort(struct ref_iterator
*ref_iterator
)
24 return ref_iterator
->vtable
->abort(ref_iterator
);
27 void base_ref_iterator_init(struct ref_iterator
*iter
,
28 struct ref_iterator_vtable
*vtable
)
30 iter
->vtable
= vtable
;
36 void base_ref_iterator_free(struct ref_iterator
*iter
)
38 /* Help make use-after-free bugs fail quickly: */
43 struct empty_ref_iterator
{
44 struct ref_iterator base
;
47 static int empty_ref_iterator_advance(struct ref_iterator
*ref_iterator
)
49 return ref_iterator_abort(ref_iterator
);
52 static int empty_ref_iterator_peel(struct ref_iterator
*ref_iterator
,
53 struct object_id
*peeled
)
55 die("BUG: peel called for empty iterator");
58 static int empty_ref_iterator_abort(struct ref_iterator
*ref_iterator
)
60 base_ref_iterator_free(ref_iterator
);
64 static struct ref_iterator_vtable empty_ref_iterator_vtable
= {
65 empty_ref_iterator_advance
,
66 empty_ref_iterator_peel
,
67 empty_ref_iterator_abort
70 struct ref_iterator
*empty_ref_iterator_begin(void)
72 struct empty_ref_iterator
*iter
= xcalloc(1, sizeof(*iter
));
73 struct ref_iterator
*ref_iterator
= &iter
->base
;
75 base_ref_iterator_init(ref_iterator
, &empty_ref_iterator_vtable
);
79 int is_empty_ref_iterator(struct ref_iterator
*ref_iterator
)
81 return ref_iterator
->vtable
== &empty_ref_iterator_vtable
;
84 struct merge_ref_iterator
{
85 struct ref_iterator base
;
87 struct ref_iterator
*iter0
, *iter1
;
89 ref_iterator_select_fn
*select
;
93 * A pointer to iter0 or iter1 (whichever is supplying the
94 * current value), or NULL if advance has not yet been called.
96 struct ref_iterator
**current
;
99 static int merge_ref_iterator_advance(struct ref_iterator
*ref_iterator
)
101 struct merge_ref_iterator
*iter
=
102 (struct merge_ref_iterator
*)ref_iterator
;
105 if (!iter
->current
) {
106 /* Initialize: advance both iterators to their first entries */
107 if ((ok
= ref_iterator_advance(iter
->iter0
)) != ITER_OK
) {
109 if (ok
== ITER_ERROR
)
112 if ((ok
= ref_iterator_advance(iter
->iter1
)) != ITER_OK
) {
114 if (ok
== ITER_ERROR
)
119 * Advance the current iterator past the just-used
122 if ((ok
= ref_iterator_advance(*iter
->current
)) != ITER_OK
) {
123 *iter
->current
= NULL
;
124 if (ok
== ITER_ERROR
)
129 /* Loop until we find an entry that we can yield. */
131 struct ref_iterator
**secondary
;
132 enum iterator_selection selection
=
133 iter
->select(iter
->iter0
, iter
->iter1
, iter
->cb_data
);
135 if (selection
== ITER_SELECT_DONE
) {
136 return ref_iterator_abort(ref_iterator
);
137 } else if (selection
== ITER_SELECT_ERROR
) {
138 ref_iterator_abort(ref_iterator
);
142 if ((selection
& ITER_CURRENT_SELECTION_MASK
) == 0) {
143 iter
->current
= &iter
->iter0
;
144 secondary
= &iter
->iter1
;
146 iter
->current
= &iter
->iter1
;
147 secondary
= &iter
->iter0
;
150 if (selection
& ITER_SKIP_SECONDARY
) {
151 if ((ok
= ref_iterator_advance(*secondary
)) != ITER_OK
) {
153 if (ok
== ITER_ERROR
)
158 if (selection
& ITER_YIELD_CURRENT
) {
159 iter
->base
.refname
= (*iter
->current
)->refname
;
160 iter
->base
.oid
= (*iter
->current
)->oid
;
161 iter
->base
.flags
= (*iter
->current
)->flags
;
167 ref_iterator_abort(ref_iterator
);
171 static int merge_ref_iterator_peel(struct ref_iterator
*ref_iterator
,
172 struct object_id
*peeled
)
174 struct merge_ref_iterator
*iter
=
175 (struct merge_ref_iterator
*)ref_iterator
;
177 if (!iter
->current
) {
178 die("BUG: peel called before advance for merge iterator");
180 return ref_iterator_peel(*iter
->current
, peeled
);
183 static int merge_ref_iterator_abort(struct ref_iterator
*ref_iterator
)
185 struct merge_ref_iterator
*iter
=
186 (struct merge_ref_iterator
*)ref_iterator
;
190 if (ref_iterator_abort(iter
->iter0
) != ITER_DONE
)
194 if (ref_iterator_abort(iter
->iter1
) != ITER_DONE
)
197 base_ref_iterator_free(ref_iterator
);
201 static struct ref_iterator_vtable merge_ref_iterator_vtable
= {
202 merge_ref_iterator_advance
,
203 merge_ref_iterator_peel
,
204 merge_ref_iterator_abort
207 struct ref_iterator
*merge_ref_iterator_begin(
208 struct ref_iterator
*iter0
, struct ref_iterator
*iter1
,
209 ref_iterator_select_fn
*select
, void *cb_data
)
211 struct merge_ref_iterator
*iter
= xcalloc(1, sizeof(*iter
));
212 struct ref_iterator
*ref_iterator
= &iter
->base
;
215 * We can't do the same kind of is_empty_ref_iterator()-style
216 * optimization here as overlay_ref_iterator_begin() does,
217 * because we don't know the semantics of the select function.
218 * It might, for example, implement "intersect" by passing
219 * references through only if they exist in both iterators.
222 base_ref_iterator_init(ref_iterator
, &merge_ref_iterator_vtable
);
225 iter
->select
= select
;
226 iter
->cb_data
= cb_data
;
227 iter
->current
= NULL
;
232 * A ref_iterator_select_fn that overlays the items from front on top
233 * of those from back (like loose refs over packed refs). See
234 * overlay_ref_iterator_begin().
236 static enum iterator_selection
overlay_iterator_select(
237 struct ref_iterator
*front
, struct ref_iterator
*back
,
243 return front ? ITER_SELECT_0
: ITER_SELECT_DONE
;
245 return ITER_SELECT_1
;
247 cmp
= strcmp(front
->refname
, back
->refname
);
250 return ITER_SELECT_0
;
252 return ITER_SELECT_1
;
254 return ITER_SELECT_0_SKIP_1
;
257 struct ref_iterator
*overlay_ref_iterator_begin(
258 struct ref_iterator
*front
, struct ref_iterator
*back
)
261 * Optimization: if one of the iterators is empty, return the
262 * other one rather than incurring the overhead of wrapping
265 if (is_empty_ref_iterator(front
)) {
266 ref_iterator_abort(front
);
268 } else if (is_empty_ref_iterator(back
)) {
269 ref_iterator_abort(back
);
273 return merge_ref_iterator_begin(front
, back
,
274 overlay_iterator_select
, NULL
);
277 struct prefix_ref_iterator
{
278 struct ref_iterator base
;
280 struct ref_iterator
*iter0
;
285 static int prefix_ref_iterator_advance(struct ref_iterator
*ref_iterator
)
287 struct prefix_ref_iterator
*iter
=
288 (struct prefix_ref_iterator
*)ref_iterator
;
291 while ((ok
= ref_iterator_advance(iter
->iter0
)) == ITER_OK
) {
292 if (!starts_with(iter
->iter0
->refname
, iter
->prefix
))
295 iter
->base
.refname
= iter
->iter0
->refname
+ iter
->trim
;
296 iter
->base
.oid
= iter
->iter0
->oid
;
297 iter
->base
.flags
= iter
->iter0
->flags
;
302 if (ref_iterator_abort(ref_iterator
) != ITER_DONE
)
307 static int prefix_ref_iterator_peel(struct ref_iterator
*ref_iterator
,
308 struct object_id
*peeled
)
310 struct prefix_ref_iterator
*iter
=
311 (struct prefix_ref_iterator
*)ref_iterator
;
313 return ref_iterator_peel(iter
->iter0
, peeled
);
316 static int prefix_ref_iterator_abort(struct ref_iterator
*ref_iterator
)
318 struct prefix_ref_iterator
*iter
=
319 (struct prefix_ref_iterator
*)ref_iterator
;
323 ok
= ref_iterator_abort(iter
->iter0
);
325 base_ref_iterator_free(ref_iterator
);
329 static struct ref_iterator_vtable prefix_ref_iterator_vtable
= {
330 prefix_ref_iterator_advance
,
331 prefix_ref_iterator_peel
,
332 prefix_ref_iterator_abort
335 struct ref_iterator
*prefix_ref_iterator_begin(struct ref_iterator
*iter0
,
339 struct prefix_ref_iterator
*iter
;
340 struct ref_iterator
*ref_iterator
;
342 if (!*prefix
&& !trim
)
343 return iter0
; /* optimization: no need to wrap iterator */
345 iter
= xcalloc(1, sizeof(*iter
));
346 ref_iterator
= &iter
->base
;
348 base_ref_iterator_init(ref_iterator
, &prefix_ref_iterator_vtable
);
351 iter
->prefix
= xstrdup(prefix
);