]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: *_strsplit() - implement more efficient version for a single separator char
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 3 Nov 2017 23:40:24 +0000 (01:40 +0200)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 7 Nov 2017 19:21:02 +0000 (21:21 +0200)
src/lib/strfuncs.c

index ee9f300e540faefd7ac57a41ae7874c5c9bb51e1..82d2d8e55967f8210fc006145aa24f10f6ee457f 100644 (file)
@@ -492,14 +492,12 @@ bool mem_equals_timing_safe(const void *p1, const void *p2, size_t size)
 }
 
 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 @@ split_str(pool_t pool, const char *data, const char *separators, int spaces)
         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,