changeset 22636:96e51a11c0aa

lib: Implement t_strsplit_tabescaped_inplace() This is a more efficient version of t_strsplit_tabescaped(), which modifies the input string instead of duplicating it.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Sat, 04 Nov 2017 01:39:38 +0200
parents 82d8656bb3ad
children da955f909fdd
files src/lib/strescape.c src/lib/strescape.h
diffstat 2 files changed, 47 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib/strescape.c	Sat Nov 04 01:37:19 2017 +0200
+++ b/src/lib/strescape.c	Sat Nov 04 01:39:38 2017 +0200
@@ -249,6 +249,50 @@
 		return str_tabunescape(t_strdup_noconst(str));
 }
 
+const char *const *t_strsplit_tabescaped_inplace(char *data)
+{
+	/* @UNSAFE */
+	char **array;
+	unsigned int count, new_alloc_count, alloc_count;
+
+	if (*data == '\0')
+		return t_new(const char *, 1);
+
+	alloc_count = 32;
+	array = t_malloc(sizeof(char *) * alloc_count);
+
+	array[0] = data; count = 1;
+	bool need_unescape = FALSE;
+	while ((data = strpbrk(data, "\t\001")) != NULL) {
+		/* separator or escape char found */
+		if (*data == '\001') {
+			need_unescape = TRUE;
+			data++;
+			continue;
+		}
+		if (count+1 >= alloc_count) {
+			new_alloc_count = nearest_power(alloc_count+1);
+			array = p_realloc(unsafe_data_stack_pool, array,
+					  sizeof(char *) * alloc_count,
+					  sizeof(char *) *
+					  new_alloc_count);
+			alloc_count = new_alloc_count;
+		}
+		*data++ = '\0';
+		if (need_unescape) {
+			str_tabunescape(array[count-1]);
+			need_unescape = FALSE;
+		}
+		array[count++] = data;
+	}
+	if (need_unescape)
+		str_tabunescape(array[count-1]);
+	i_assert(count < alloc_count);
+	array[count] = NULL;
+
+	return (const char *const *)array;
+}
+
 char **p_strsplit_tabescaped(pool_t pool, const char *str)
 {
 	char **args;
--- a/src/lib/strescape.h	Sat Nov 04 01:37:19 2017 +0200
+++ b/src/lib/strescape.h	Sat Nov 04 01:39:38 2017 +0200
@@ -28,5 +28,8 @@
 
 char **p_strsplit_tabescaped(pool_t pool, const char *str);
 const char *const *t_strsplit_tabescaped(const char *str);
+/* Same as t_strsplit_tabescaped(), but the input string is modified and the
+   returned pointers inside the array point to the original string. */
+const char *const *t_strsplit_tabescaped_inplace(char *str);
 
 #endif