chiark / gitweb /
cocci: use strempty() at more places
[elogind.git] / src / basic / string-util.h
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 #pragma once
3
4 /***
5   This file is part of systemd.
6
7   Copyright 2010 Lennart Poettering
8
9   systemd is free software; you can redistribute it and/or modify it
10   under the terms of the GNU Lesser General Public License as published by
11   the Free Software Foundation; either version 2.1 of the License, or
12   (at your option) any later version.
13
14   systemd is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   Lesser General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public License
20   along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 ***/
22
23 #include <alloca.h>
24 #include <stdbool.h>
25 #include <stddef.h>
26 #include <string.h>
27
28 #include "macro.h"
29
30 /* What is interpreted as whitespace? */
31 #define WHITESPACE        " \t\n\r"
32 #define NEWLINE           "\n\r"
33 #define QUOTES            "\"\'"
34 #define COMMENTS          "#;"
35 #define GLOB_CHARS        "*?["
36 #define DIGITS            "0123456789"
37 #define LOWERCASE_LETTERS "abcdefghijklmnopqrstuvwxyz"
38 #define UPPERCASE_LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
39 #define LETTERS           LOWERCASE_LETTERS UPPERCASE_LETTERS
40 #define ALPHANUMERICAL    LETTERS DIGITS
41 #define HEXDIGITS         DIGITS "abcdefABCDEF"
42
43 #define streq(a,b) (strcmp((a),(b)) == 0)
44 #define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
45 #define strcaseeq(a,b) (strcasecmp((a),(b)) == 0)
46 #define strncaseeq(a, b, n) (strncasecmp((a), (b), (n)) == 0)
47
48 int strcmp_ptr(const char *a, const char *b) _pure_;
49
50 static inline bool streq_ptr(const char *a, const char *b) {
51         return strcmp_ptr(a, b) == 0;
52 }
53
54 static inline const char* strempty(const char *s) {
55         return s ?: "";
56 }
57
58 static inline const char* strnull(const char *s) {
59         return s ?: "(null)";
60 }
61
62 static inline const char *strna(const char *s) {
63         return s ?: "n/a";
64 }
65
66 static inline bool isempty(const char *p) {
67         return !p || !p[0];
68 }
69
70 static inline const char *empty_to_null(const char *p) {
71         return isempty(p) ? NULL : p;
72 }
73
74 #if 0 /// UNNEEDED by elogind
75 static inline const char *strdash_if_empty(const char *str) {
76         return isempty(str) ? "-" : str;
77 }
78 #endif // 0
79
80 static inline char *startswith(const char *s, const char *prefix) {
81         size_t l;
82
83         l = strlen(prefix);
84         if (strncmp(s, prefix, l) == 0)
85                 return (char*) s + l;
86
87         return NULL;
88 }
89
90 #if 0 /// UNNEEDED by elogind
91 static inline char *startswith_no_case(const char *s, const char *prefix) {
92         size_t l;
93
94         l = strlen(prefix);
95         if (strncasecmp(s, prefix, l) == 0)
96                 return (char*) s + l;
97
98         return NULL;
99 }
100 #endif // 0
101
102 char *endswith(const char *s, const char *postfix) _pure_;
103 char *endswith_no_case(const char *s, const char *postfix) _pure_;
104
105 char *first_word(const char *s, const char *word) _pure_;
106
107 const char* split(const char **state, size_t *l, const char *separator, bool quoted);
108
109 #define FOREACH_WORD(word, length, s, state)                            \
110         _FOREACH_WORD(word, length, s, WHITESPACE, false, state)
111
112 #define FOREACH_WORD_SEPARATOR(word, length, s, separator, state)       \
113         _FOREACH_WORD(word, length, s, separator, false, state)
114
115 #define _FOREACH_WORD(word, length, s, separator, quoted, state)        \
116         for ((state) = (s), (word) = split(&(state), &(length), (separator), (quoted)); (word); (word) = split(&(state), &(length), (separator), (quoted)))
117
118 char *strappend(const char *s, const char *suffix);
119 char *strnappend(const char *s, const char *suffix, size_t length);
120
121 char *strjoin_real(const char *x, ...) _sentinel_;
122 #define strjoin(a, ...) strjoin_real((a), __VA_ARGS__, NULL)
123
124 #define strjoina(a, ...)                                                \
125         ({                                                              \
126                 const char *_appendees_[] = { a, __VA_ARGS__ };         \
127                 char *_d_, *_p_;                                        \
128                 size_t _len_ = 0;                                          \
129                 unsigned _i_;                                           \
130                 for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \
131                         _len_ += strlen(_appendees_[_i_]);              \
132                 _p_ = _d_ = alloca(_len_ + 1);                          \
133                 for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \
134                         _p_ = stpcpy(_p_, _appendees_[_i_]);            \
135                 *_p_ = 0;                                               \
136                 _d_;                                                    \
137         })
138
139 char *strstrip(char *s);
140 #if 0 /// UNNEEDED by elogind
141 char *delete_chars(char *s, const char *bad);
142 #endif // 0
143 char *delete_trailing_chars(char *s, const char *bad);
144 char *truncate_nl(char *s);
145
146 #if 0 /// UNNEEDED by elogind
147 static inline char *skip_leading_chars(const char *s, const char *bad) {
148
149         if (!s)
150                 return NULL;
151
152         if (!bad)
153                 bad = WHITESPACE;
154
155         return (char*) s + strspn(s, bad);
156 }
157
158 char ascii_tolower(char x);
159 char *ascii_strlower(char *s);
160 char *ascii_strlower_n(char *s, size_t n);
161
162 char ascii_toupper(char x);
163 char *ascii_strupper(char *s);
164
165 int ascii_strcasecmp_n(const char *a, const char *b, size_t n);
166 int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m);
167
168 bool chars_intersect(const char *a, const char *b) _pure_;
169 #endif // 0
170
171 static inline bool _pure_ in_charset(const char *s, const char* charset) {
172         assert(s);
173         assert(charset);
174         return s[strspn(s, charset)] == '\0';
175 }
176
177 bool string_has_cc(const char *p, const char *ok) _pure_;
178
179 char *ellipsize_mem(const char *s, size_t old_length_bytes, size_t new_length_columns, unsigned percent);
180 char *ellipsize(const char *s, size_t length, unsigned percent);
181
182 bool nulstr_contains(const char *nulstr, const char *needle);
183
184 char* strshorten(char *s, size_t l);
185
186 char *strreplace(const char *text, const char *old_string, const char *new_string);
187
188 char *strip_tab_ansi(char **p, size_t *l);
189
190 char *strextend_with_separator(char **x, const char *separator, ...) _sentinel_;
191
192 #define strextend(x, ...) strextend_with_separator(x, NULL, __VA_ARGS__)
193
194 char *strrep(const char *s, unsigned n);
195
196 int split_pair(const char *s, const char *sep, char **l, char **r);
197
198 int free_and_strdup(char **p, const char *s);
199
200 /* Normal memmem() requires haystack to be nonnull, which is annoying for zero-length buffers */
201 static inline void *memmem_safe(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) {
202
203         if (needlelen <= 0)
204                 return (void*) haystack;
205
206         if (haystacklen < needlelen)
207                 return NULL;
208
209         assert(haystack);
210         assert(needle);
211
212         return memmem(haystack, haystacklen, needle, needlelen);
213 }
214
215 #if !HAVE_EXPLICIT_BZERO
216 void explicit_bzero(void *p, size_t l);
217 #endif
218
219 char *string_erase(char *x);
220
221 char *string_free_erase(char *s);
222 DEFINE_TRIVIAL_CLEANUP_FUNC(char *, string_free_erase);
223 #define _cleanup_string_free_erase_ _cleanup_(string_free_erasep)
224
225 bool string_is_safe(const char *p) _pure_;
226
227 static inline size_t strlen_ptr(const char *s) {
228         if (!s)
229                 return 0;
230
231         return strlen(s);
232 }