Merge pull request #1793 from filbranden/extract1
More refactorings in extract_first_word
This commit is contained in:
+71
-68
@@ -29,54 +29,51 @@
|
||||
int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
size_t allocated = 0, sz = 0;
|
||||
char c;
|
||||
int r;
|
||||
|
||||
char quote = 0; /* 0 or ' or " */
|
||||
bool backslash = false; /* whether we've just seen a backslash */
|
||||
bool separator = false; /* whether we've just seen a separator */
|
||||
bool start = true; /* false means we're looking at a value */
|
||||
|
||||
assert(p);
|
||||
assert(ret);
|
||||
|
||||
if (!separators)
|
||||
separators = WHITESPACE;
|
||||
|
||||
/* Bail early if called after last value or with no input */
|
||||
if (!*p)
|
||||
goto finish_force_terminate;
|
||||
c = **p;
|
||||
|
||||
if (!separators)
|
||||
separators = WHITESPACE;
|
||||
|
||||
/* Parses the first word of a string, and returns it in
|
||||
* *ret. Removes all quotes in the process. When parsing fails
|
||||
* (because of an uneven number of quotes or similar), leaves
|
||||
* the pointer *p at the first invalid character. */
|
||||
|
||||
for (;;) {
|
||||
char c = **p;
|
||||
if (flags & EXTRACT_DONT_COALESCE_SEPARATORS)
|
||||
if (!GREEDY_REALLOC(s, allocated, sz+1))
|
||||
return -ENOMEM;
|
||||
|
||||
if (start) {
|
||||
if (flags & EXTRACT_DONT_COALESCE_SEPARATORS)
|
||||
if (!GREEDY_REALLOC(s, allocated, sz+1))
|
||||
return -ENOMEM;
|
||||
|
||||
if (c == 0)
|
||||
goto finish_force_terminate;
|
||||
else if (strchr(separators, c)) {
|
||||
for (;; (*p) ++, c = **p) {
|
||||
if (c == 0)
|
||||
goto finish_force_terminate;
|
||||
else if (strchr(separators, c)) {
|
||||
if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
|
||||
(*p) ++;
|
||||
if (flags & EXTRACT_DONT_COALESCE_SEPARATORS)
|
||||
goto finish_force_next;
|
||||
continue;
|
||||
goto finish_force_next;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* We found a non-blank character, so we will always
|
||||
* want to return a string (even if it is empty),
|
||||
* allocate it here. */
|
||||
if (!GREEDY_REALLOC(s, allocated, sz+1))
|
||||
return -ENOMEM;
|
||||
|
||||
start = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (;; (*p) ++, c = **p) {
|
||||
if (backslash) {
|
||||
if (!GREEDY_REALLOC(s, allocated, sz+7))
|
||||
return -ENOMEM;
|
||||
@@ -107,67 +104,73 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
|
||||
if (flags & EXTRACT_CUNESCAPE_RELAX) {
|
||||
s[sz++] = '\\';
|
||||
s[sz++] = c;
|
||||
goto end_escape;
|
||||
}
|
||||
return -EINVAL;
|
||||
} else
|
||||
return -EINVAL;
|
||||
} else {
|
||||
(*p) += r - 1;
|
||||
|
||||
if (c != 0)
|
||||
s[sz++] = c; /* normal explicit char */
|
||||
else
|
||||
sz += utf8_encode_unichar(s + sz, u); /* unicode chars we'll encode as utf8 */
|
||||
}
|
||||
|
||||
(*p) += r - 1;
|
||||
|
||||
if (c != 0)
|
||||
s[sz++] = c; /* normal explicit char */
|
||||
else
|
||||
sz += utf8_encode_unichar(s + sz, u); /* unicode chars we'll encode as utf8 */
|
||||
} else
|
||||
s[sz++] = c;
|
||||
|
||||
end_escape:
|
||||
backslash = false;
|
||||
|
||||
} else if (quote) { /* inside either single or double quotes */
|
||||
if (c == 0) {
|
||||
if (flags & EXTRACT_RELAX)
|
||||
goto finish_force_terminate;
|
||||
return -EINVAL;
|
||||
} else if (c == quote) /* found the end quote */
|
||||
quote = 0;
|
||||
else if (c == '\\')
|
||||
backslash = true;
|
||||
else {
|
||||
if (!GREEDY_REALLOC(s, allocated, sz+2))
|
||||
return -ENOMEM;
|
||||
for (;; (*p) ++, c = **p) {
|
||||
if (c == 0) {
|
||||
if (flags & EXTRACT_RELAX)
|
||||
goto finish_force_terminate;
|
||||
return -EINVAL;
|
||||
} else if (c == quote) { /* found the end quote */
|
||||
quote = 0;
|
||||
break;
|
||||
} else if (c == '\\') {
|
||||
backslash = true;
|
||||
break;
|
||||
} else {
|
||||
if (!GREEDY_REALLOC(s, allocated, sz+2))
|
||||
return -ENOMEM;
|
||||
|
||||
s[sz++] = c;
|
||||
s[sz++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (separator) {
|
||||
if (c == 0)
|
||||
goto finish_force_terminate;
|
||||
if (!strchr(separators, c))
|
||||
goto finish;
|
||||
|
||||
} else {
|
||||
if (c == 0)
|
||||
goto finish_force_terminate;
|
||||
else if ((c == '\'' || c == '"') && (flags & EXTRACT_QUOTES))
|
||||
quote = c;
|
||||
else if (c == '\\')
|
||||
backslash = true;
|
||||
else if (strchr(separators, c)) {
|
||||
if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
|
||||
(*p) ++;
|
||||
goto finish_force_next;
|
||||
}
|
||||
separator = true;
|
||||
} else {
|
||||
if (!GREEDY_REALLOC(s, allocated, sz+2))
|
||||
return -ENOMEM;
|
||||
for (;; (*p) ++, c = **p) {
|
||||
if (c == 0)
|
||||
goto finish_force_terminate;
|
||||
else if ((c == '\'' || c == '"') && (flags & EXTRACT_QUOTES)) {
|
||||
quote = c;
|
||||
break;
|
||||
} else if (c == '\\') {
|
||||
backslash = true;
|
||||
break;
|
||||
} else if (strchr(separators, c)) {
|
||||
if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
|
||||
(*p) ++;
|
||||
goto finish_force_next;
|
||||
}
|
||||
/* Skip additional coalesced separators. */
|
||||
for (;; (*p) ++, c = **p) {
|
||||
if (c == 0)
|
||||
goto finish_force_terminate;
|
||||
if (!strchr(separators, c))
|
||||
break;
|
||||
}
|
||||
goto finish;
|
||||
|
||||
s[sz++] = c;
|
||||
} else {
|
||||
if (!GREEDY_REALLOC(s, allocated, sz+2))
|
||||
return -ENOMEM;
|
||||
|
||||
s[sz++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(*p) ++;
|
||||
}
|
||||
|
||||
finish_force_terminate:
|
||||
|
||||
Reference in New Issue
Block a user