diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/buffer.c | 4 | ||||
-rw-r--r-- | common/compat.c | 1 | ||||
-rw-r--r-- | common/sock_any.c | 1 | ||||
-rw-r--r-- | common/stringx.c | 201 | ||||
-rw-r--r-- | common/stringx.h | 9 |
5 files changed, 214 insertions, 2 deletions
diff --git a/common/buffer.c b/common/buffer.c index 25494c9..088c2df 100644 --- a/common/buffer.c +++ b/common/buffer.c @@ -40,6 +40,8 @@ #include <string.h> #include <stdlib.h> #include <stdio.h> +#include <unistd.h> +#include <ctype.h> /* ----------------------------------------------------------------------- * Memory Buffer @@ -368,7 +370,7 @@ char* ha_bufparseline(ha_buffer_t* buf, int trim) if(trim) { /* Knock out any previous whitespace */ - while(buf->_pp < buf->_rp && isblank(*(buf->_pp))) + while(buf->_pp < buf->_rp && strchr (" \t", *(buf->_pp))) buf->_pp++; } diff --git a/common/compat.c b/common/compat.c index 081a7ee..3ab7ae2 100644 --- a/common/compat.c +++ b/common/compat.c @@ -33,6 +33,7 @@ #include "compat.h" #include <stdlib.h> +#include <ctype.h> #ifndef HAVE_REALLOCF diff --git a/common/sock_any.c b/common/sock_any.c index 714154a..5972e62 100644 --- a/common/sock_any.c +++ b/common/sock_any.c @@ -44,6 +44,7 @@ #include <netdb.h> #include <string.h> #include <stdio.h> +#include <ctype.h> #include "sock_any.h" diff --git a/common/stringx.c b/common/stringx.c index 2246cf8..24cf9d1 100644 --- a/common/stringx.c +++ b/common/stringx.c @@ -36,9 +36,16 @@ * */ -#include <string.h> #include "stringx.h" +#include <string.h> +#include <ctype.h> +#include <assert.h> +#include <stdarg.h> +#include <stdlib.h> + +#define WHITESPACE " \t\r\n\v" + const char* trim_start(const char* data) { while(*data && isspace(*data)) @@ -64,3 +71,195 @@ char* trim_space(char* data) data = (char*)trim_start(data); return trim_end(data); } + +static int +is_escaped (const char *string, const char *at) +{ + int escaped = 0; + while (at > string) { + at = at - 1; + if (*at != '\\') + break; + escaped = !escaped; + } + return escaped; +} + +void +str_unescape (char *str) +{ + int len = strlen (str); + char *at; + + while (len > 0) { + at = strchr (str, '\\'); + if (!at) + break; + + len -= at - str; + str = at + 1; + --len; + memmove (at, str, len); + at[len] = 0; + } +} + +char** +str_array_parse_quoted (const char *data) +{ + char **array; + const char *at; + char quote; + int n; + + assert (data); + + array = str_array_create (NULL); + + for (n = 0; 1; ++n) { + quote = 0; + + /* Strip all leading blanks */ + while (data && data[0] && strchr (WHITESPACE, data[0])) + ++data; + + if (!data || !data[0]) + break; + + /* See if the next character is a quote */ + if (data[0] == '\'' || data[0] == '\"') { + quote = data[0]; + ++data; + } + + if (quote) { + at = data; + do { + ++data; + data = strchr (data, quote); + } while (data && is_escaped (at, data)); + + if (!data) { + array = str_array_append (array, at); + } else { + array = str_array_appendn (array, at, data - at); + ++data; + } + + str_unescape (array[n]); + } else { + at = data; + do { + ++data; + data = data + strcspn (data, WHITESPACE); + } while (*data && is_escaped (at, data)); + + array = str_array_appendn (array, at, data - at); + str_unescape (array[n]); + } + + if (!array) + break; + } + + return array; +} + +char** +str_array_create (const char *first, ...) +{ + char **array; + char *value; + va_list va; + + array = calloc (32, sizeof (char*)); + if (!array) + return NULL; + + if (first) { + array[0] = strdup (first); + if (!array[0]) { + free (array); + return NULL; + } + + va_start (va, first); + while ((value = va_arg (va, char*)) != NULL) { + array = str_array_append (array, value); + if (!array) + break; + } + va_end (va); + } + + return array; +} + +unsigned int +str_array_length (char **array) +{ + unsigned int length = 0; + + assert (array); + + while (*array) { + ++length; + ++array; + } + return length; +} + +char** +str_array_append (char **array, const char *next) +{ + assert (array); + assert (next); + + return str_array_appendn (array, next, strlen (next)); +} + +char** +str_array_appendn (char **array, const char *next, unsigned int len) +{ + char **narray; + int num; + + assert (array); + assert (next || !len); + + num = str_array_length (array); + + /* + * Actually because of intelligent libc this is not + * as inefficient as it looks. + */ + narray = realloc (array, (num + 2) * sizeof (char*)); + if (!narray) { + str_array_free (array); + return NULL; + } + + narray[num] = malloc (len + 1); + if (!narray[num]) { + str_array_free (narray); + return NULL; + } + memcpy (narray[num], next, len); + narray[num][len] = 0; + narray[num + 1] = NULL; + + return narray; +} + +void +str_array_free (char **array) +{ + char **a; + + if (!array); + return; + + for (a = array; *a; ++a) + free (*a); + free (array); +} diff --git a/common/stringx.h b/common/stringx.h index c9a2832..4216d4f 100644 --- a/common/stringx.h +++ b/common/stringx.h @@ -43,4 +43,13 @@ const char* trim_start(const char* data); char* trim_end(char* data); char* trim_space(char* data); +void str_unescape (char *str); + +unsigned int str_array_length (char **array); +char** str_array_parse_quoted (const char *data); +char** str_array_create (const char *first, ...); +char** str_array_append (char **array, const char *next); +char** str_array_appendn (char **array, const char *next, unsigned int len); +void str_array_free (char **array); + #endif /* __STRINGX_H__ */ |