summaryrefslogtreecommitdiff
path: root/common/stringx.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/stringx.c')
-rw-r--r--common/stringx.c201
1 files changed, 200 insertions, 1 deletions
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);
+}