string-list: allow case-insensitive string list
Some string list needs to be searched case insensitively, and for that to work correctly, the string needs to be sorted case insensitively from the beginning. Allow a custom comparison function to be defined on a string list instance and use it throughout in place of strcmp(). Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
7e0651a630
commit
8dd5afc926
@ -7,10 +7,11 @@ static int get_entry_index(const struct string_list *list, const char *string,
|
|||||||
int *exact_match)
|
int *exact_match)
|
||||||
{
|
{
|
||||||
int left = -1, right = list->nr;
|
int left = -1, right = list->nr;
|
||||||
|
compare_strings_fn cmp = list->cmp ? list->cmp : strcmp;
|
||||||
|
|
||||||
while (left + 1 < right) {
|
while (left + 1 < right) {
|
||||||
int middle = (left + right) / 2;
|
int middle = (left + right) / 2;
|
||||||
int compare = strcmp(string, list->items[middle].string);
|
int compare = cmp(string, list->items[middle].string);
|
||||||
if (compare < 0)
|
if (compare < 0)
|
||||||
right = middle;
|
right = middle;
|
||||||
else if (compare > 0)
|
else if (compare > 0)
|
||||||
@ -96,8 +97,9 @@ void string_list_remove_duplicates(struct string_list *list, int free_util)
|
|||||||
{
|
{
|
||||||
if (list->nr > 1) {
|
if (list->nr > 1) {
|
||||||
int src, dst;
|
int src, dst;
|
||||||
|
compare_strings_fn cmp = list->cmp ? list->cmp : strcmp;
|
||||||
for (src = dst = 1; src < list->nr; src++) {
|
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)
|
if (list->strdup_strings)
|
||||||
free(list->items[src].string);
|
free(list->items[src].string);
|
||||||
if (free_util)
|
if (free_util)
|
||||||
@ -230,15 +232,20 @@ struct string_list_item *string_list_append(struct string_list *list,
|
|||||||
list->strdup_strings ? xstrdup(string) : (char *)string);
|
list->strdup_strings ? xstrdup(string) : (char *)string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Yuck */
|
||||||
|
static compare_strings_fn compare_for_qsort;
|
||||||
|
|
||||||
|
/* Only call this from inside sort_string_list! */
|
||||||
static int cmp_items(const void *a, const void *b)
|
static int cmp_items(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
const struct string_list_item *one = a;
|
const struct string_list_item *one = a;
|
||||||
const struct string_list_item *two = b;
|
const struct string_list_item *two = b;
|
||||||
return strcmp(one->string, two->string);
|
return compare_for_qsort(one->string, two->string);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sort_string_list(struct string_list *list)
|
void sort_string_list(struct string_list *list)
|
||||||
{
|
{
|
||||||
|
compare_for_qsort = list->cmp ? list->cmp : strcmp;
|
||||||
qsort(list->items, list->nr, sizeof(*list->items), cmp_items);
|
qsort(list->items, list->nr, sizeof(*list->items), cmp_items);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,8 +253,10 @@ struct string_list_item *unsorted_string_list_lookup(struct string_list *list,
|
|||||||
const char *string)
|
const char *string)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
compare_strings_fn cmp = list->cmp ? list->cmp : strcmp;
|
||||||
|
|
||||||
for (i = 0; i < list->nr; i++)
|
for (i = 0; i < list->nr; i++)
|
||||||
if (!strcmp(string, list->items[i].string))
|
if (!cmp(string, list->items[i].string))
|
||||||
return list->items + i;
|
return list->items + i;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,14 @@ struct string_list_item {
|
|||||||
char *string;
|
char *string;
|
||||||
void *util;
|
void *util;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef int (*compare_strings_fn)(const char *, const char *);
|
||||||
|
|
||||||
struct string_list {
|
struct string_list {
|
||||||
struct string_list_item *items;
|
struct string_list_item *items;
|
||||||
unsigned int nr, alloc;
|
unsigned int nr, alloc;
|
||||||
unsigned int strdup_strings:1;
|
unsigned int strdup_strings:1;
|
||||||
|
compare_strings_fn cmp; /* NULL uses strcmp() */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define STRING_LIST_INIT_NODUP { NULL, 0, 0, 0 }
|
#define STRING_LIST_INIT_NODUP { NULL, 0, 0, 0 }
|
||||||
|
Loading…
Reference in New Issue
Block a user