diff options
Diffstat (limited to 'string-list.c')
| -rw-r--r-- | string-list.c | 149 | 
1 files changed, 96 insertions, 53 deletions
| diff --git a/string-list.c b/string-list.c index 53faaa8420..08dc00984c 100644 --- a/string-list.c +++ b/string-list.c @@ -16,7 +16,7 @@ void string_list_init_dup(struct string_list *list)  /* if there is no exact match, point to the index where the entry could be   * inserted */  static size_t get_entry_index(const struct string_list *list, const char *string, -			      int *exact_match) +			      bool *exact_match)  {  	size_t left = 0, right = list->nr;  	compare_strings_fn cmp = list->cmp ? list->cmp : strcmp; @@ -29,18 +29,20 @@ static size_t get_entry_index(const struct string_list *list, const char *string  		else if (compare > 0)  			left = middle + 1;  		else { -			*exact_match = 1; +			if (exact_match) +				*exact_match = true;  			return middle;  		}  	} -	*exact_match = 0; +	if (exact_match) +		*exact_match = false;  	return right;  }  static size_t add_entry(struct string_list *list, const char *string)  { -	int exact_match = 0; +	bool exact_match;  	size_t index = get_entry_index(list, string, &exact_match);  	if (exact_match) @@ -68,7 +70,7 @@ struct string_list_item *string_list_insert(struct string_list *list, const char  void string_list_remove(struct string_list *list, const char *string,  			int free_util)  { -	int exact_match; +	bool exact_match;  	int i = get_entry_index(list, string, &exact_match);  	if (exact_match) { @@ -82,26 +84,23 @@ void string_list_remove(struct string_list *list, const char *string,  	}  } -int string_list_has_string(const struct string_list *list, const char *string) +bool string_list_has_string(const struct string_list *list, const char *string)  { -	int exact_match; +	bool exact_match;  	get_entry_index(list, string, &exact_match);  	return exact_match;  } -int string_list_find_insert_index(const struct string_list *list, const char *string, -				  int negative_existing_index) +size_t string_list_find_insert_index(const struct string_list *list, const char *string, +				     bool *exact_match)  { -	int exact_match; -	int index = get_entry_index(list, string, &exact_match); -	if (exact_match) -		index = -1 - (negative_existing_index ? index : 0); -	return index; +	return get_entry_index(list, string, exact_match);  }  struct string_list_item *string_list_lookup(struct string_list *list, const char *string)  { -	int exact_match, i = get_entry_index(list, string, &exact_match); +	bool exact_match; +	size_t i = get_entry_index(list, string, &exact_match);  	if (!exact_match)  		return NULL;  	return list->items + i; @@ -276,55 +275,99 @@ void unsorted_string_list_delete_item(struct string_list *list, int i, int free_  	list->nr--;  } -int string_list_split(struct string_list *list, const char *string, -		      int delim, int maxsplit) +/* + * append a substring [p..end] to list; return number of things it + * appended to the list. + */ +static int append_one(struct string_list *list, +		      const char *p, const char *end, +		      int in_place, unsigned flags) +{ +	if (!end) +		end = p + strlen(p); + +	if ((flags & STRING_LIST_SPLIT_TRIM)) { +		/* rtrim */ +		for (; p < end; end--) +			if (!isspace(end[-1])) +				break; +	} + +	if ((flags & STRING_LIST_SPLIT_NONEMPTY) && (end <= p)) +		return 0; + +	if (in_place) { +		*((char *)end) = '\0'; +		string_list_append(list, p); +	} else { +		string_list_append_nodup(list, xmemdupz(p, end - p)); +	} +	return 1; +} + +/* + * Unfortunately this cannot become a public interface, as _in_place() + * wants to have "const char *string" while the other variant wants to + * have "char *string" for type safety. + * + * This accepts "const char *string" to allow both wrappers to use it; + * it internally casts away the constness when in_place is true by + * taking advantage of strpbrk() that takes a "const char *" arg and + * returns "char *" pointer into that const string.  Yucky but works ;-). + */ +static int split_string(struct string_list *list, const char *string, const char *delim, +			int maxsplit, int in_place, unsigned flags)  {  	int count = 0; -	const char *p = string, *end; +	const char *p = string; + +	if (in_place && list->strdup_strings) +		BUG("string_list_split_in_place() called with strdup_strings"); +	else if (!in_place && !list->strdup_strings) +		BUG("string_list_split() called without strdup_strings"); -	if (!list->strdup_strings) -		die("internal error in string_list_split(): " -		    "list->strdup_strings must be set");  	for (;;) { -		count++; -		if (maxsplit >= 0 && count > maxsplit) { -			string_list_append(list, p); -			return count; +		char *end; + +		if (flags & STRING_LIST_SPLIT_TRIM) { +			/* ltrim */ +			while (*p && isspace(*p)) +				p++;  		} -		end = strchr(p, delim); -		if (end) { -			string_list_append_nodup(list, xmemdupz(p, end - p)); -			p = end + 1; -		} else { -			string_list_append(list, p); + +		if (0 <= maxsplit && maxsplit <= count) +			end = NULL; +		else +			end = strpbrk(p, delim); + +		count += append_one(list, p, end, in_place, flags); + +		if (!end)  			return count; -		} +		p = end + 1;  	}  } +int string_list_split(struct string_list *list, const char *string, +		      const char *delim, int maxsplit) +{ +	return split_string(list, string, delim, maxsplit, 0, 0); +} +  int string_list_split_in_place(struct string_list *list, char *string,  			       const char *delim, int maxsplit)  { -	int count = 0; -	char *p = string, *end; +	return split_string(list, string, delim, maxsplit, 1, 0); +} -	if (list->strdup_strings) -		die("internal error in string_list_split_in_place(): " -		    "list->strdup_strings must not be set"); -	for (;;) { -		count++; -		if (maxsplit >= 0 && count > maxsplit) { -			string_list_append(list, p); -			return count; -		} -		end = strpbrk(p, delim); -		if (end) { -			*end = '\0'; -			string_list_append(list, p); -			p = end + 1; -		} else { -			string_list_append(list, p); -			return count; -		} -	} +int string_list_split_f(struct string_list *list, const char *string, +			const char *delim, int maxsplit, unsigned flags) +{ +	return split_string(list, string, delim, maxsplit, 0, flags); +} + +int string_list_split_in_place_f(struct string_list *list, char *string, +			       const char *delim, int maxsplit, unsigned flags) +{ +	return split_string(list, string, delim, maxsplit, 1, flags);  } | 
