shared: util.c: unify split and split_quoted

This commit is contained in:
Simon Peeters 2014-01-04 02:35:25 +01:00 committed by Zbigniew Jędrzejewski-Szmek
parent e10e429f2d
commit bf85c24daa
2 changed files with 36 additions and 67 deletions

View file

@ -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;

View file

@ -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);