userdiff: add and use for_each_userdiff_driver()
Refactor the userdiff_find_by_namelen() function so that a new for_each_userdiff_driver() API function does most of the work. This will be useful for the same reason we've got other for_each_*() API functions as part of various APIs, and will be used in a follow-up commit. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Ævar Arnfjörð Bjarmason committed
Apr 8, 2021 at 17:04 UTC
f12fa9ee6c87efa8a926973bd203ef327686fb62
2 files changed
+71
-12
userdiff.c
+58
-12
@@ -259,20 +259,33 @@ static struct userdiff_driver driver_false = {
259
{ NULL, 0 }
260
};
261
262
-static struct userdiff_driver *userdiff_find_by_namelen(const char *k, size_t len)
262
+struct find_by_namelen_data {
263
+ const char *name;
264
+ size_t len;
265
+ struct userdiff_driver *driver;
266
+};
267
+
268
+static int userdiff_find_by_namelen_cb(struct userdiff_driver *driver,
269
+ enum userdiff_driver_type type, void *priv)
270
{
264
- int i;
265
- for (i = 0; i < ndrivers; i++) {
266
- struct userdiff_driver *drv = drivers + i;
267
- if (!strncmp(drv->name, k, len) && !drv->name[len])
268
- return drv;
269
- }
270
- for (i = 0; i < ARRAY_SIZE(builtin_drivers); i++) {
271
- struct userdiff_driver *drv = builtin_drivers + i;
272
- if (!strncmp(drv->name, k, len) && !drv->name[len])
273
- return drv;
271
+ struct find_by_namelen_data *cb_data = priv;
272
+
273
+ if (!strncmp(driver->name, cb_data->name, cb_data->len) &&
274
+ !driver->name[cb_data->len]) {
275
+ cb_data->driver = driver;
276
+ return 1; /* tell the caller to stop iterating */
277
}
275
- return NULL;
278
+ return 0;
279
+}
280
+
281
+static struct userdiff_driver *userdiff_find_by_namelen(const char *name, size_t len)
282
+{
283
+ struct find_by_namelen_data udcbdata = {
284
+ .name = name,
285
+ .len = len,
286
+ };
287
+ for_each_userdiff_driver(userdiff_find_by_namelen_cb, &udcbdata);
288
+ return udcbdata.driver;
289
}
290
291
static int parse_funcname(struct userdiff_funcname *f, const char *k,
@@ -379,3 +392,36 @@ struct userdiff_driver *userdiff_get_textconv(struct repository *r,
392
393
return driver;
394
}
395
+
396
+static int for_each_userdiff_driver_list(each_userdiff_driver_fn fn,
397
+ enum userdiff_driver_type type, void *cb_data,
398
+ struct userdiff_driver *drv,
399
+ int drv_size)
400
+{
401
+ int i;
402
+ int ret;
403
+ for (i = 0; i < drv_size; i++) {
404
+ struct userdiff_driver *item = drv + i;
405
+ if ((ret = fn(item, type, cb_data)))
406
+ return ret;
407
+ }
408
+ return 0;
409
+}
410
+
411
+int for_each_userdiff_driver(each_userdiff_driver_fn fn, void *cb_data)
412
+{
413
+ int ret;
414
+
415
+ ret = for_each_userdiff_driver_list(fn, USERDIFF_DRIVER_TYPE_CUSTOM,
416
+ cb_data, drivers, ndrivers);
417
+ if (ret)
418
+ return ret;
419
+
420
+ ret = for_each_userdiff_driver_list(fn, USERDIFF_DRIVER_TYPE_BUILTIN,
421
+ cb_data, builtin_drivers,
422
+ ARRAY_SIZE(builtin_drivers));
423
+ if (ret)
424
+ return ret;
425
+
426
+ return 0;
427
+}
userdiff.h
+13
@@ -21,6 +21,12 @@ struct userdiff_driver {
21
struct notes_cache *textconv_cache;
22
int textconv_want_cache;
23
};
24
+enum userdiff_driver_type {
25
+ USERDIFF_DRIVER_TYPE_BUILTIN = 1<<0,
26
+ USERDIFF_DRIVER_TYPE_CUSTOM = 1<<1,
27
+};
28
+typedef int (*each_userdiff_driver_fn)(struct userdiff_driver *,
29
+ enum userdiff_driver_type, void *);
30
31
int userdiff_config(const char *k, const char *v);
32
struct userdiff_driver *userdiff_find_by_name(const char *name);
@@ -34,4 +40,11 @@ struct userdiff_driver *userdiff_find_by_path(struct index_state *istate,
40
struct userdiff_driver *userdiff_get_textconv(struct repository *r,
41
struct userdiff_driver *driver);
42
43
+/*
44
+ * Iterate over all userdiff drivers. The userdiff_driver_type
45
+ * argument to each_userdiff_driver_fn indicates their type. Return
46
+ * non-zero to exit early from the loop.
47
+ */
48
+int for_each_userdiff_driver(each_userdiff_driver_fn, void *);
49
+
50
#endif /* USERDIFF */