-/* SPDX-License-Identifier: LGPL-2.1+ */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <errno.h>
#include <stdarg.h>
#include "alloc-util.h"
#include "escape.h"
+#include "extract-word.h"
#include "fileio.h"
#include "gunicode.h"
#include "locale-util.h"
#include "macro.h"
#include "memory-util.h"
#include "string-util.h"
+#include "strv.h"
#include "terminal-util.h"
#include "utf8.h"
#include "util.h"
-int strcmp_ptr(const char *a, const char *b) {
- /* Like strcmp(), but tries to make sense of NULL pointers */
-
- if (a && b)
- return strcmp(a, b);
- return CMP(a, b); /* Direct comparison of pointers, one of which is NULL */
-}
-
-int strcasecmp_ptr(const char *a, const char *b) {
- /* Like strcasecmp(), but tries to make sense of NULL pointers */
-
- if (a && b)
- return strcasecmp(a, b);
- return CMP(a, b); /* Direct comparison of pointers, one of which is NULL */
-}
-
-char* endswith(const char *s, const char *postfix) {
- size_t sl, pl;
-
- assert(s);
- assert(postfix);
-
- sl = strlen(s);
- pl = strlen(postfix);
-
- if (pl == 0)
- return (char*) s + sl;
-
- if (sl < pl)
- return NULL;
-
- if (memcmp(s + sl - pl, postfix, pl) != 0)
- return NULL;
-
- return (char*) s + sl - pl;
-}
-
-char* endswith_no_case(const char *s, const char *postfix) {
- size_t sl, pl;
-
- assert(s);
- assert(postfix);
-
- sl = strlen(s);
- pl = strlen(postfix);
-
- if (pl == 0)
- return (char*) s + sl;
-
- if (sl < pl)
- return NULL;
-
- if (strcasecmp(s + sl - pl, postfix) != 0)
- return NULL;
-
- return (char*) s + sl - pl;
-}
-
char* first_word(const char *s, const char *word) {
size_t sl, wl;
const char *p;
return (char*) p;
}
-static size_t strcspn_escaped(const char *s, const char *reject) {
- bool escaped = false;
- int n;
-
- for (n = 0; s[n] != '\0'; n++) {
- if (escaped)
- escaped = false;
- else if (s[n] == '\\')
- escaped = true;
- else if (strchr(reject, s[n]))
- break;
- }
-
- return n;
-}
-
-/* Split a string into words. */
-const char* split(
- const char **state,
- size_t *l,
- const char *separator,
- SplitFlags flags) {
-
- const char *current;
-
- assert(state);
- assert(l);
-
- if (!separator)
- separator = WHITESPACE;
-
- current = *state;
-
- if (*current == '\0') /* already at the end? */
- return NULL;
-
- current += strspn(current, separator); /* skip leading separators */
- if (*current == '\0') { /* at the end now? */
- *state = current;
- return NULL;
- }
-
- if (FLAGS_SET(flags, SPLIT_QUOTES)) {
-
- if (strchr(QUOTES, *current)) {
- /* We are looking at a quote */
- *l = strcspn_escaped(current + 1, CHAR_TO_STR(*current));
- if (current[*l + 1] != *current ||
- (current[*l + 2] != 0 && !strchr(separator, current[*l + 2]))) {
- /* right quote missing or garbage at the end */
- if (FLAGS_SET(flags, SPLIT_RELAX)) {
- *state = current + *l + 1 + (current[*l + 1] != '\0');
- return current + 1;
- }
- *state = current;
- return NULL;
- }
- *state = current++ + *l + 2;
-
- } else {
- /* We are looking at a something that is not a quote */
- *l = strcspn_escaped(current, separator);
- if (current[*l] && !strchr(separator, current[*l]) && !FLAGS_SET(flags, SPLIT_RELAX)) {
- /* unfinished escape */
- *state = current;
- return NULL;
- }
- *state = current + *l;
- }
- } else {
- *l = strcspn(current, separator);
- *state = current + *l;
- }
-
- return current;
-}
-
char *strnappend(const char *s, const char *suffix, size_t b) {
size_t a;
char *r;
assert(suffix);
a = strlen(s);
- if (b > ((size_t) -1) - a)
+ if (b > (SIZE_MAX) - a)
return NULL;
r = new(char, a+b+1);
char *strjoin_real(const char *x, ...) {
va_list ap;
- size_t l;
+ size_t l = 1;
char *r, *p;
va_start(ap, x);
+ for (const char *t = x; t; t = va_arg(ap, const char *)) {
+ size_t n;
- if (x) {
- l = strlen(x);
-
- for (;;) {
- const char *t;
- size_t n;
-
- t = va_arg(ap, const char *);
- if (!t)
- break;
-
- n = strlen(t);
- if (n > ((size_t) -1) - l) {
- va_end(ap);
- return NULL;
- }
-
- l += n;
+ n = strlen(t);
+ if (n > SIZE_MAX - l) {
+ va_end(ap);
+ return NULL;
}
- } else
- l = 0;
-
+ l += n;
+ }
va_end(ap);
- r = new(char, l+1);
+ p = r = new(char, l);
if (!r)
return NULL;
- if (x) {
- p = stpcpy(r, x);
-
- va_start(ap, x);
-
- for (;;) {
- const char *t;
-
- t = va_arg(ap, const char *);
- if (!t)
- break;
-
- p = stpcpy(p, t);
- }
+ va_start(ap, x);
+ for (const char *t = x; t; t = va_arg(ap, const char *))
+ p = stpcpy(p, t);
+ va_end(ap);
- va_end(ap);
- } else
- r[0] = 0;
+ *p = 0;
return r;
}
assert(s);
assert(percent <= 100);
- assert(new_length != (size_t) -1);
+ assert(new_length != SIZE_MAX);
if (old_length <= new_length)
return strndup(s, old_length);
assert(s);
assert(percent <= 100);
- if (new_length == (size_t) -1)
+ if (new_length == SIZE_MAX)
return strndup(s, old_length);
if (new_length == 0)
return *ibuf;
}
-char *strextend_with_separator(char **x, const char *separator, ...) {
- bool need_separator;
+char *strextend_with_separator_internal(char **x, const char *separator, ...) {
size_t f, l, l_separator;
- char *r, *p;
+ bool need_separator;
+ char *nr, *p;
va_list ap;
assert(x);
if (need_separator)
n += l_separator;
- if (n > ((size_t) -1) - l) {
+ if (n >= SIZE_MAX - l) {
va_end(ap);
return NULL;
}
need_separator = !isempty(*x);
- r = realloc(*x, l+1);
- if (!r)
+ nr = realloc(*x, GREEDY_ALLOC_ROUND_UP(l+1));
+ if (!nr)
return NULL;
- p = r + f;
+ *x = nr;
+ p = nr + f;
va_start(ap, separator);
for (;;) {
}
va_end(ap);
- assert(p == r + l);
+ assert(p == nr + l);
*p = 0;
- *x = r;
- return r + l;
+ return p;
}
char *strrep(const char *s, unsigned n) {
- size_t l;
char *r, *p;
- unsigned i;
+ size_t l;
assert(s);
if (!r)
return NULL;
- for (i = 0; i < n; i++)
+ for (unsigned i = 0; i < n; i++)
p = stpcpy(p, s);
*p = 0;
c++;
}
}
+
+int string_contains_word_strv(const char *string, const char *separators, char **words, const char **ret_word) {
+ /* In the default mode with no separators specified, we split on whitespace and
+ * don't coalesce separators. */
+ const ExtractFlags flags = separators ? EXTRACT_DONT_COALESCE_SEPARATORS : 0;
+
+ const char *found = NULL;
+
+ for (const char *p = string;;) {
+ _cleanup_free_ char *w = NULL;
+ int r;
+
+ r = extract_first_word(&p, &w, separators, flags);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
+ found = strv_find(words, w);
+ if (found)
+ break;
+ }
+
+ if (ret_word)
+ *ret_word = found;
+ return !!found;
+}