1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
8 #include "alloc-util.h"
10 #include "string-util-fundamental.h"
12 /* What is interpreted as whitespace? */
13 #define WHITESPACE " \t\n\r"
14 #define NEWLINE "\n\r"
17 #define GLOB_CHARS "*?["
18 #define DIGITS "0123456789"
19 #define LOWERCASE_LETTERS "abcdefghijklmnopqrstuvwxyz"
20 #define UPPERCASE_LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
21 #define LETTERS LOWERCASE_LETTERS UPPERCASE_LETTERS
22 #define ALPHANUMERICAL LETTERS DIGITS
23 #define HEXDIGITS DIGITS "abcdefABCDEF"
24 #define LOWERCASE_HEXDIGITS DIGITS "abcdef"
25 #define URI_RESERVED ":/?#[]@!$&'()*+;=" /* [RFC3986] */
26 #define URI_UNRESERVED ALPHANUMERICAL "-._~" /* [RFC3986] */
27 #define URI_VALID URI_RESERVED URI_UNRESERVED /* [RFC3986] */
29 static inline char* strstr_ptr(const char *haystack
, const char *needle
) {
30 if (!haystack
|| !needle
)
32 return strstr(haystack
, needle
);
35 static inline char *strstrafter(const char *haystack
, const char *needle
) {
38 /* Returns NULL if not found, or pointer to first character after needle if found */
40 p
= strstr_ptr(haystack
, needle
);
44 return p
+ strlen(needle
);
47 static inline const char* strnull(const char *s
) {
51 static inline const char *strna(const char *s
) {
55 static inline const char* true_false(bool b
) {
56 return b
? "true" : "false";
59 static inline const char* plus_minus(bool b
) {
63 static inline const char* one_zero(bool b
) {
67 static inline const char* enable_disable(bool b
) {
68 return b
? "enable" : "disable";
71 static inline const char* enabled_disabled(bool b
) {
72 return b
? "enabled" : "disabled";
75 /* This macro's return pointer will have the "const" qualifier set or unset the same way as the input
77 #define empty_to_null(p) \
79 const char *_p = (p); \
80 (typeof(p)) (isempty(_p) ? NULL : _p); \
83 static inline const char *empty_to_na(const char *p
) {
84 return isempty(p
) ? "n/a" : p
;
87 static inline const char *empty_to_dash(const char *str
) {
88 return isempty(str
) ? "-" : str
;
91 static inline bool empty_or_dash(const char *str
) {
94 (str
[0] == '-' && str
[1] == 0);
97 static inline const char *empty_or_dash_to_null(const char *p
) {
98 return empty_or_dash(p
) ? NULL
: p
;
100 #define empty_or_dash_to_null(p) \
102 const char *_p = (p); \
103 (typeof(p)) (empty_or_dash(_p) ? NULL : _p); \
106 char *first_word(const char *s
, const char *word
) _pure_
;
108 char *strnappend(const char *s
, const char *suffix
, size_t length
);
110 char *strjoin_real(const char *x
, ...) _sentinel_
;
111 #define strjoin(a, ...) strjoin_real((a), __VA_ARGS__, NULL)
113 #define strjoina(a, ...) \
115 const char *_appendees_[] = { a, __VA_ARGS__ }; \
119 for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \
120 _len_ += strlen(_appendees_[_i_]); \
121 _p_ = _d_ = newa(char, _len_ + 1); \
122 for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \
123 _p_ = stpcpy(_p_, _appendees_[_i_]); \
128 char *strstrip(char *s
);
129 char *delete_chars(char *s
, const char *bad
);
130 char *delete_trailing_chars(char *s
, const char *bad
);
131 char *truncate_nl_full(char *s
, size_t *ret_len
);
132 static inline char *truncate_nl(char *s
) {
133 return truncate_nl_full(s
, NULL
);
136 static inline char *skip_leading_chars(const char *s
, const char *bad
) {
143 return (char*) s
+ strspn(s
, bad
);
146 char ascii_tolower(char x
);
147 char *ascii_strlower(char *s
);
148 char *ascii_strlower_n(char *s
, size_t n
);
150 char ascii_toupper(char x
);
151 char *ascii_strupper(char *s
);
153 int ascii_strcasecmp_n(const char *a
, const char *b
, size_t n
);
154 int ascii_strcasecmp_nn(const char *a
, size_t n
, const char *b
, size_t m
);
156 bool chars_intersect(const char *a
, const char *b
) _pure_
;
158 static inline bool _pure_
in_charset(const char *s
, const char* charset
) {
161 return s
[strspn(s
, charset
)] == '\0';
164 static inline bool char_is_cc(char p
) {
165 /* char is unsigned on some architectures, e.g. aarch64. So, compiler may warn the condition
166 * p >= 0 is always true. See #19543. Hence, let's cast to unsigned before the comparison. Note
167 * that the cast in the right hand side is redundant, as according to the C standard, compilers
168 * automatically cast a signed value to unsigned when comparing with an unsigned variable. Just
169 * for safety and readability. */
170 return (uint8_t) p
< (uint8_t) ' ' || p
== 127;
172 bool string_has_cc(const char *p
, const char *ok
) _pure_
;
174 char *ellipsize_mem(const char *s
, size_t old_length_bytes
, size_t new_length_columns
, unsigned percent
);
175 static inline char *ellipsize(const char *s
, size_t length
, unsigned percent
) {
176 return ellipsize_mem(s
, strlen(s
), length
, percent
);
179 char *cellescape(char *buf
, size_t len
, const char *s
);
181 /* This limit is arbitrary, enough to give some idea what the string contains */
182 #define CELLESCAPE_DEFAULT_LENGTH 64
184 char* strshorten(char *s
, size_t l
);
186 int strgrowpad0(char **s
, size_t l
);
188 char *strreplace(const char *text
, const char *old_string
, const char *new_string
);
190 char *strip_tab_ansi(char **ibuf
, size_t *_isz
, size_t highlight
[2]);
192 char *strextend_with_separator_internal(char **x
, const char *separator
, ...) _sentinel_
;
193 #define strextend_with_separator(x, separator, ...) strextend_with_separator_internal(x, separator, __VA_ARGS__, NULL)
194 #define strextend(x, ...) strextend_with_separator_internal(x, NULL, __VA_ARGS__, NULL)
196 char *strextendn(char **x
, const char *s
, size_t l
);
198 int strextendf_with_separator(char **x
, const char *separator
, const char *format
, ...) _printf_(3,4);
199 #define strextendf(x, ...) strextendf_with_separator(x, NULL, __VA_ARGS__)
201 char *strrep(const char *s
, unsigned n
);
203 #define strrepa(s, n) \
206 size_t _len_ = strlen(s) * n; \
207 _p_ = _d_ = newa(char, _len_ + 1); \
208 for (unsigned _i_ = 0; _i_ < n; _i_++) \
209 _p_ = stpcpy(_p_, s); \
214 int split_pair(const char *s
, const char *sep
, char **l
, char **r
);
216 int free_and_strdup(char **p
, const char *s
);
217 static inline int free_and_strdup_warn(char **p
, const char *s
) {
220 r
= free_and_strdup(p
, s
);
225 int free_and_strndup(char **p
, const char *s
, size_t l
);
227 int strdup_to_full(char **ret
, const char *src
);
228 static inline int strdup_to(char **ret
, const char *src
) {
229 int r
= strdup_to_full(ASSERT_PTR(ret
), src
);
230 return r
< 0 ? r
: 0; /* Suppress return value of 1. */
233 bool string_is_safe(const char *p
) _pure_
;
235 DISABLE_WARNING_STRINGOP_TRUNCATION
;
236 static inline void strncpy_exact(char *buf
, const char *src
, size_t buf_len
) {
237 strncpy(buf
, src
, buf_len
);
241 /* Like startswith_no_case(), but operates on arbitrary memory blocks.
242 * It works only for ASCII strings.
244 static inline void *memory_startswith_no_case(const void *p
, size_t sz
, const char *token
) {
247 size_t n
= strlen(token
);
253 for (size_t i
= 0; i
< n
; i
++)
254 if (ascii_tolower(((char *)p
)[i
]) != ascii_tolower(token
[i
]))
257 return (uint8_t*) p
+ n
;
260 static inline char* str_realloc(char *p
) {
261 /* Reallocate *p to actual size. Ignore failure, and return the original string on error. */
266 return realloc(p
, strlen(p
) + 1) ?: p
;
269 char* string_erase(char *x
);
271 int string_truncate_lines(const char *s
, size_t n_lines
, char **ret
);
272 int string_extract_line(const char *s
, size_t i
, char **ret
);
274 int string_contains_word_strv(const char *string
, const char *separators
, char * const *words
, const char **ret_word
);
275 static inline int string_contains_word(const char *string
, const char *separators
, const char *word
) {
276 return string_contains_word_strv(string
, separators
, STRV_MAKE(word
), NULL
);
279 bool streq_skip_trailing_chars(const char *s1
, const char *s2
, const char *ok
);
281 char *string_replace_char(char *str
, char old_char
, char new_char
);
283 typedef enum MakeCStringMode
{
284 MAKE_CSTRING_REFUSE_TRAILING_NUL
,
285 MAKE_CSTRING_ALLOW_TRAILING_NUL
,
286 MAKE_CSTRING_REQUIRE_TRAILING_NUL
,
287 _MAKE_CSTRING_MODE_MAX
,
288 _MAKE_CSTRING_MODE_INVALID
= -1,
291 int make_cstring(const char *s
, size_t n
, MakeCStringMode mode
, char **ret
);
293 size_t strspn_from_end(const char *str
, const char *accept
);
295 char *strdupspn(const char *a
, const char *accept
);
296 char *strdupcspn(const char *a
, const char *reject
);
298 char *find_line_startswith(const char *haystack
, const char *needle
);
300 bool version_is_valid(const char *s
);
302 bool version_is_valid_versionspec(const char *s
);
304 ssize_t
strlevenshtein(const char *x
, const char *y
);
306 char *strrstr(const char *haystack
, const char *needle
);