From bf85c24daaf63f72562bbe4c627ca8b963dfb964 Mon Sep 17 00:00:00 2001 From: Simon Peeters Date: Sat, 4 Jan 2014 02:35:25 +0100 Subject: [PATCH] shared: util.c: unify split and split_quoted --- src/shared/util.c | 88 ++++++++++++++--------------------------------- src/shared/util.h | 15 +++++--- 2 files changed, 36 insertions(+), 67 deletions(-) diff --git a/src/shared/util.c b/src/shared/util.c index c824c3934..5551714a3 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -359,8 +359,23 @@ int safe_atod(const char *s, double *ret_d) { return 0; } +static size_t strcspn_escaped(const char *s, const char *reject) { + bool escaped = false; + size_t n; + + for (n=0; s[n]; n++) { + if (escaped) + escaped = false; + else if (s[n] == '\\') + escaped = true; + else if (strchr(reject, s[n])) + return n; + } + return n; +} + /* Split a string into words. */ -char *split(const char *c, size_t *l, const char *separator, char **state) { +char *split(const char *c, size_t *l, const char *separator, bool quoted, char **state) { char *current; current = *state ? *state : (char*) c; @@ -369,70 +384,19 @@ char *split(const char *c, size_t *l, const char *separator, char **state) { return NULL; current += strspn(current, separator); - *l = strcspn(current, separator); - *state = current+*l; - - return (char*) current; -} - -/* Split a string into words, but consider strings enclosed in '' and - * "" as words even if they include spaces. */ -char *split_quoted(const char *c, size_t *l, char **state) { - const char *current, *e; - bool escaped = false; - - assert(c); - assert(l); - assert(state); - - current = *state ? *state : c; - - current += strspn(current, WHITESPACE); - - if (*current == 0) + if (!*current) return NULL; - else if (*current == '\'') { - current ++; - - for (e = current; *e; e++) { - if (escaped) - escaped = false; - else if (*e == '\\') - escaped = true; - else if (*e == '\'') - break; - } - - *l = e-current; - *state = (char*) (*e == 0 ? e : e+1); - - } else if (*current == '\"') { - current ++; - - for (e = current; *e; e++) { - if (escaped) - escaped = false; - else if (*e == '\\') - escaped = true; - else if (*e == '\"') - break; - } - - *l = e-current; - *state = (char*) (*e == 0 ? e : e+1); - + if (quoted && strchr("\'\"", *current)) { + char quotechar = *(current++); + *l = strcspn_escaped(current, (char[]){quotechar, '\0'}); + *state = current+*l+1; + } else if (quoted) { + *l = strcspn_escaped(current, separator); + *state = current+*l; } else { - for (e = current; *e; e++) { - if (escaped) - escaped = false; - else if (*e == '\\') - escaped = true; - else if (strchr(WHITESPACE, *e)) - break; - } - *l = e-current; - *state = (char*) e; + *l = strcspn(current, separator); + *state = current+*l; } return (char*) current; diff --git a/src/shared/util.h b/src/shared/util.h index 864565426..ebc765da3 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -198,17 +198,22 @@ static inline int safe_atoi64(const char *s, int64_t *ret_i) { return safe_atolli(s, (long long int*) ret_i); } -char *split(const char *c, size_t *l, const char *separator, char **state); -char *split_quoted(const char *c, size_t *l, char **state); +char *split(const char *c, size_t *l, const char *separator, bool quoted, char **state); #define FOREACH_WORD(word, length, s, state) \ - for ((state) = NULL, (word) = split((s), &(length), WHITESPACE, &(state)); (word); (word) = split((s), &(length), WHITESPACE, &(state))) + _FOREACH_WORD(word, length, s, WHITESPACE, false, state) #define FOREACH_WORD_SEPARATOR(word, length, s, separator, state) \ - for ((state) = NULL, (word) = split((s), &(length), (separator), &(state)); (word); (word) = split((s), &(length), (separator), &(state))) + _FOREACH_WORD(word, length, s, separator, false, state) #define FOREACH_WORD_QUOTED(word, length, s, state) \ - for ((state) = NULL, (word) = split_quoted((s), &(length), &(state)); (word); (word) = split_quoted((s), &(length), &(state))) + _FOREACH_WORD(word, length, s, WHITESPACE, true, state) + +#define FOREACH_WORD_SEPARATOR_QUOTED(word, length, s, separator, state) \ + _FOREACH_WORD(word, length, s, separator, true, state) + +#define _FOREACH_WORD(word, length, s, separator, quoted, state) \ + for ((state) = NULL, (word) = split((s), &(length), (separator), (quoted), &(state)); (word); (word) = split((s), &(length), (separator), (quoted), &(state))) pid_t get_parent_of_pid(pid_t pid, pid_t *ppid); int get_starttime_of_pid(pid_t pid, unsigned long long *st); -- 2.30.2