changeset 22637:da955f909fdd

lib: *_strsplit() - implement more efficient version for a single separator char
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Sat, 04 Nov 2017 01:40:24 +0200
parents 96e51a11c0aa
children 7d5634889da8
files src/lib/strfuncs.c
diffstat 1 files changed, 46 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib/strfuncs.c	Sat Nov 04 01:39:38 2017 +0200
+++ b/src/lib/strfuncs.c	Sat Nov 04 01:40:24 2017 +0200
@@ -492,14 +492,12 @@
 }
 
 static char **
-split_str(pool_t pool, const char *data, const char *separators, int spaces)
+split_str_slow(pool_t pool, const char *data, const char *separators, bool spaces)
 {
         char **array;
 	char *str;
         unsigned int count, alloc_count, new_alloc_count;
 
-	i_assert(*separators != '\0');
-
 	if (spaces) {
 		/* skip leading separators */
 		while (*data != '\0' && strchr(separators, *data) != NULL)
@@ -549,6 +547,51 @@
         return array;
 }
 
+static char **
+split_str_fast(pool_t pool, const char *data, char sep)
+{
+	char **array, *str;
+	unsigned int count, alloc_count, new_alloc_count;
+
+	if (*data == '\0')
+		return p_new(pool, char *, 1);
+
+	str = p_strdup(pool, data);
+
+	alloc_count = 32;
+	array = p_new(pool, char *, alloc_count);
+
+	array[0] = str; count = 1;
+	while ((str = strchr(str, sep)) != NULL) {
+		/* separator found */
+		if (count+1 >= alloc_count) {
+			new_alloc_count = nearest_power(alloc_count+1);
+			array = p_realloc(pool, array,
+					  sizeof(char *) * alloc_count,
+					  sizeof(char *) *
+					  new_alloc_count);
+			alloc_count = new_alloc_count;
+		}
+		*str++ = '\0';
+		array[count++] = str;
+	}
+	i_assert(count < alloc_count);
+	i_assert(array[count] == NULL);
+
+	return array;
+}
+
+static char **
+split_str(pool_t pool, const char *data, const char *separators, bool spaces)
+{
+	i_assert(*separators != '\0');
+
+	if (separators[1] == '\0' && !spaces)
+		return split_str_fast(pool, data, separators[0]);
+	else
+		return split_str_slow(pool, data, separators, spaces);
+}
+
 const char **t_strsplit(const char *data, const char *separators)
 {
 	return (const char **)split_str(unsafe_data_stack_pool, data,