@@ -259,20 +259,32 @@ static struct userdiff_driver driver_false = {
{ NULL, 0 }
};
-static struct userdiff_driver *userdiff_find_by_namelen(const char *k, size_t len)
+struct for_each_userdiff_driver_cb {
+ const char *k;
+ size_t len;
+ struct userdiff_driver *driver;
+};
+
+static int userdiff_find_by_namelen_cb(struct userdiff_driver *driver,
+ enum userdiff_driver_type type, void *priv)
{
- int i;
- for (i = 0; i < ndrivers; i++) {
- struct userdiff_driver *drv = drivers + i;
- if (!strncmp(drv->name, k, len) && !drv->name[len])
- return drv;
- }
- for (i = 0; i < ARRAY_SIZE(builtin_drivers); i++) {
- struct userdiff_driver *drv = builtin_drivers + i;
- if (!strncmp(drv->name, k, len) && !drv->name[len])
- return drv;
+ struct for_each_userdiff_driver_cb *cb_data = priv;
+
+ if (!strncmp(driver->name, cb_data->k, cb_data->len) &&
+ !driver->name[cb_data->len]) {
+ cb_data->driver = driver;
+ return -1; /* found it! */
}
- return NULL;
+ return 0;
+}
+
+static struct userdiff_driver *userdiff_find_by_namelen(const char *k, size_t len)
+{
+ struct for_each_userdiff_driver_cb udcbdata = { .k = k, .len = len, .driver = NULL };
+
+ for_each_userdiff_driver(userdiff_find_by_namelen_cb,
+ USERDIFF_DRIVER_TYPE_UNSPECIFIED, &udcbdata);
+ return udcbdata.driver;
}
static int parse_funcname(struct userdiff_funcname *f, const char *k,
@@ -373,3 +385,28 @@ struct userdiff_driver *userdiff_get_textconv(struct repository *r,
return driver;
}
+
+int for_each_userdiff_driver(each_userdiff_driver_fn fn,
+ enum userdiff_driver_type type, void *cb_data)
+{
+ int i, ret;
+ if (type & (USERDIFF_DRIVER_TYPE_UNSPECIFIED | USERDIFF_DRIVER_TYPE_CUSTOM)) {
+
+ for (i = 0; i < ndrivers; i++) {
+ struct userdiff_driver *drv = drivers + i;
+ ret = fn(drv, USERDIFF_DRIVER_TYPE_CUSTOM, cb_data);
+ if (ret)
+ return ret;
+ }
+ }
+ if (type & (USERDIFF_DRIVER_TYPE_UNSPECIFIED | USERDIFF_DRIVER_TYPE_BUILTIN)) {
+
+ for (i = 0; i < ARRAY_SIZE(builtin_drivers); i++) {
+ struct userdiff_driver *drv = builtin_drivers + i;
+ ret = fn(drv, USERDIFF_DRIVER_TYPE_BUILTIN, cb_data);
+ if (ret)
+ return ret;
+ }
+ }
+ return 0;
+}
@@ -21,6 +21,13 @@ struct userdiff_driver {
struct notes_cache *textconv_cache;
int textconv_want_cache;
};
+enum userdiff_driver_type {
+ USERDIFF_DRIVER_TYPE_UNSPECIFIED = 1<<0,
+ USERDIFF_DRIVER_TYPE_BUILTIN = 1<<1,
+ USERDIFF_DRIVER_TYPE_CUSTOM = 1<<2,
+};
+typedef int (*each_userdiff_driver_fn)(struct userdiff_driver *,
+ enum userdiff_driver_type, void *);
int userdiff_config(const char *k, const char *v);
struct userdiff_driver *userdiff_find_by_name(const char *name);
@@ -34,4 +41,12 @@ struct userdiff_driver *userdiff_find_by_path(struct index_state *istate,
struct userdiff_driver *userdiff_get_textconv(struct repository *r,
struct userdiff_driver *driver);
+/*
+ * Iterate over each driver of type userdiff_driver_type, or
+ * USERDIFF_DRIVER_TYPE_UNSPECIFIED for all of them. Return non-zero
+ * to exit from the loop.
+ */
+int for_each_userdiff_driver(each_userdiff_driver_fn,
+ enum userdiff_driver_type, void *);
+
#endif /* USERDIFF */
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> --- userdiff.c | 61 +++++++++++++++++++++++++++++++++++++++++++----------- userdiff.h | 15 ++++++++++++++ 2 files changed, 64 insertions(+), 12 deletions(-)