Imported Upstream version 2.20.3
[platform/upstream/git.git] / string-list.c
index c54b816..1f6063f 100644 (file)
@@ -1,16 +1,23 @@
 #include "cache.h"
 #include "string-list.h"
 
+void string_list_init(struct string_list *list, int strdup_strings)
+{
+       memset(list, 0, sizeof(*list));
+       list->strdup_strings = strdup_strings;
+}
+
 /* if there is no exact match, point to the index where the entry could be
  * inserted */
 static int get_entry_index(const struct string_list *list, const char *string,
                int *exact_match)
 {
        int left = -1, right = list->nr;
+       compare_strings_fn cmp = list->cmp ? list->cmp : strcmp;
 
        while (left + 1 < right) {
-               int middle = (left + right) / 2;
-               int compare = strcmp(string, list->items[middle].string);
+               int middle = left + (right - left) / 2;
+               int compare = cmp(string, list->items[middle].string);
                if (compare < 0)
                        right = middle;
                else if (compare > 0)
@@ -34,15 +41,10 @@ static int add_entry(int insert_at, struct string_list *list, const char *string
        if (exact_match)
                return -1 - index;
 
-       if (list->nr + 1 >= list->alloc) {
-               list->alloc += 32;
-               list->items = xrealloc(list->items, list->alloc
-                               * sizeof(struct string_list_item));
-       }
+       ALLOC_GROW(list->items, list->nr+1, list->alloc);
        if (index < list->nr)
-               memmove(list->items + index + 1, list->items + index,
-                               (list->nr - index)
-                               * sizeof(struct string_list_item));
+               MOVE_ARRAY(list->items + index + 1, list->items + index,
+                          list->nr - index);
        list->items[index].string = list->strdup_strings ?
                xstrdup(string) : (char *)string;
        list->items[index].util = NULL;
@@ -53,13 +55,7 @@ static int add_entry(int insert_at, struct string_list *list, const char *string
 
 struct string_list_item *string_list_insert(struct string_list *list, const char *string)
 {
-       return string_list_insert_at_index(list, -1, string);
-}
-
-struct string_list_item *string_list_insert_at_index(struct string_list *list,
-                                                    int insert_at, const char *string)
-{
-       int index = add_entry(insert_at, list, string);
+       int index = add_entry(-1, list, string);
 
        if (index < 0)
                index = -1 - index;
@@ -67,6 +63,23 @@ struct string_list_item *string_list_insert_at_index(struct string_list *list,
        return list->items + index;
 }
 
+void string_list_remove(struct string_list *list, const char *string,
+                       int free_util)
+{
+       int exact_match;
+       int i = get_entry_index(list, string, &exact_match);
+
+       if (exact_match) {
+               if (list->strdup_strings)
+                       free(list->items[i].string);
+               if (free_util)
+                       free(list->items[i].util);
+
+               list->nr--;
+               MOVE_ARRAY(list->items + i, list->items + i + 1, list->nr - i);
+       }
+}
+
 int string_list_has_string(const struct string_list *list, const char *string)
 {
        int exact_match;
@@ -96,8 +109,9 @@ void string_list_remove_duplicates(struct string_list *list, int free_util)
 {
        if (list->nr > 1) {
                int src, dst;
+               compare_strings_fn cmp = list->cmp ? list->cmp : strcmp;
                for (src = dst = 1; src < list->nr; src++) {
-                       if (!strcmp(list->items[dst - 1].string, list->items[src].string)) {
+                       if (!cmp(list->items[dst - 1].string, list->items[src].string)) {
                                if (list->strdup_strings)
                                        free(list->items[src].string);
                                if (free_util)
@@ -136,24 +150,13 @@ void filter_string_list(struct string_list *list, int free_util,
        list->nr = dst;
 }
 
-char *string_list_longest_prefix(const struct string_list *prefixes,
-                                const char *string)
+static int item_is_not_empty(struct string_list_item *item, void *unused)
 {
-       int i, max_len = -1;
-       char *retval = NULL;
-
-       for (i = 0; i < prefixes->nr; i++) {
-               char *prefix = prefixes->items[i].string;
-               if (!prefixcmp(string, prefix)) {
-                       int len = strlen(prefix);
-                       if (len > max_len) {
-                               retval = prefix;
-                               max_len = len;
-                       }
-               }
-       }
+       return *item->string != '\0';
+}
 
-       return retval;
+void string_list_remove_empty_items(struct string_list *list, int free_util) {
+       filter_string_list(list, free_util, item_is_not_empty, NULL);
 }
 
 void string_list_clear(struct string_list *list, int free_util)
@@ -192,16 +195,6 @@ void string_list_clear_func(struct string_list *list, string_list_clear_func_t c
        list->nr = list->alloc = 0;
 }
 
-
-void print_string_list(const struct string_list *p, const char *text)
-{
-       int i;
-       if ( text )
-               printf("%s\n", text);
-       for (i = 0; i < p->nr; i++)
-               printf("%s:%p\n", p->items[i].string, p->items[i].util);
-}
-
 struct string_list_item *string_list_append_nodup(struct string_list *list,
                                                  char *string)
 {
@@ -221,25 +214,39 @@ struct string_list_item *string_list_append(struct string_list *list,
                        list->strdup_strings ? xstrdup(string) : (char *)string);
 }
 
-static int cmp_items(const void *a, const void *b)
+/*
+ * Encapsulate the compare function pointer because ISO C99 forbids
+ * casting from void * to a function pointer and vice versa.
+ */
+struct string_list_sort_ctx
+{
+       compare_strings_fn cmp;
+};
+
+static int cmp_items(const void *a, const void *b, void *ctx)
 {
+       struct string_list_sort_ctx *sort_ctx = ctx;
        const struct string_list_item *one = a;
        const struct string_list_item *two = b;
-       return strcmp(one->string, two->string);
+       return sort_ctx->cmp(one->string, two->string);
 }
 
-void sort_string_list(struct string_list *list)
+void string_list_sort(struct string_list *list)
 {
-       qsort(list->items, list->nr, sizeof(*list->items), cmp_items);
+       struct string_list_sort_ctx sort_ctx = {list->cmp ? list->cmp : strcmp};
+
+       QSORT_S(list->items, list->nr, cmp_items, &sort_ctx);
 }
 
 struct string_list_item *unsorted_string_list_lookup(struct string_list *list,
                                                     const char *string)
 {
-       int i;
-       for (i = 0; i < list->nr; i++)
-               if (!strcmp(string, list->items[i].string))
-                       return list->items + i;
+       struct string_list_item *item;
+       compare_strings_fn cmp = list->cmp ? list->cmp : strcmp;
+
+       for_each_string_list_item(item, list)
+               if (!cmp(string, item->string))
+                       return item;
        return NULL;
 }