[systemd-devel] [PATCH 3/5] shared: util.c: unify split and split_quoted

Simon Peeters peeters.simon at gmail.com
Fri Jan 3 17:35:25 PST 2014


---
 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 2350204..db3051d 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 311315d..92a8a31 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -182,17 +182,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);
-- 
1.8.5.2



More information about the systemd-devel mailing list