libinput-util: fix logical error regarding comparison of a long variable with its...
[platform/upstream/libinput.git] / src / util-strings.h
1 /*
2  * Copyright © 2008 Kristian Høgsberg
3  * Copyright © 2013-2015 Red Hat, Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24
25 #pragma once
26
27 #include "config.h"
28
29 #include <assert.h>
30 #include <ctype.h>
31 #include <errno.h>
32 #include <limits.h>
33 #include <math.h>
34 #include <string.h>
35 #include <stdio.h>
36 #include <stdbool.h>
37 #include <stdlib.h>
38 #include <stdarg.h>
39 #ifdef HAVE_LOCALE_H
40 #include <locale.h>
41 #endif
42 #ifdef HAVE_XLOCALE_H
43 #include <xlocale.h>
44 #endif
45
46 #include "util-macros.h"
47
48 static inline bool
49 streq(const char *str1, const char *str2)
50 {
51         /* one NULL, one not NULL is always false */
52         if (str1 && str2)
53                 return strcmp(str1, str2) == 0;
54         return str1 == str2;
55 }
56
57 static inline bool
58 strneq(const char *str1, const char *str2, int n)
59 {
60         /* one NULL, one not NULL is always false */
61         if (str1 && str2)
62                 return strncmp(str1, str2, n) == 0;
63         return str1 == str2;
64 }
65
66 static inline void *
67 zalloc(size_t size)
68 {
69         void *p;
70
71         /* We never need to alloc anything more than 1,5 MB so we can assume
72          * if we ever get above that something's going wrong */
73         if (size > 1536 * 1024)
74                 assert(!"bug: internal malloc size limit exceeded");
75
76         p = calloc(1, size);
77         if (!p)
78                 abort();
79
80         return p;
81 }
82
83 /**
84  * strdup guaranteed to succeed. If the input string is NULL, the output
85  * string is NULL. If the input string is a string pointer, we strdup or
86  * abort on failure.
87  */
88 static inline char*
89 safe_strdup(const char *str)
90 {
91         char *s;
92
93         if (!str)
94                 return NULL;
95
96         s = strdup(str);
97         if (!s)
98                 abort();
99         return s;
100 }
101
102 /**
103  * Simple wrapper for asprintf that ensures the passed in-pointer is set
104  * to NULL upon error.
105  * The standard asprintf() call does not guarantee the passed in pointer
106  * will be NULL'ed upon failure, whereas this wrapper does.
107  *
108  * @param strp pointer to set to newly allocated string.
109  * This pointer should be passed to free() to release when done.
110  * @param fmt the format string to use for printing.
111  * @return The number of bytes printed (excluding the null byte terminator)
112  * upon success or -1 upon failure. In the case of failure the pointer is set
113  * to NULL.
114  */
115 __attribute__ ((format (printf, 2, 3)))
116 static inline int
117 xasprintf(char **strp, const char *fmt, ...)
118 {
119         int rc = 0;
120         va_list args;
121
122         va_start(args, fmt);
123         rc = vasprintf(strp, fmt, args);
124         va_end(args);
125         if ((rc == -1) && strp)
126                 *strp = NULL;
127
128         return rc;
129 }
130
131 __attribute__ ((format (printf, 2, 0)))
132 static inline int
133 xvasprintf(char **strp, const char *fmt, va_list args)
134 {
135         int rc = 0;
136         rc = vasprintf(strp, fmt, args);
137         if ((rc == -1) && strp)
138                 *strp = NULL;
139
140         return rc;
141 }
142
143 static inline bool
144 safe_atoi_base(const char *str, int *val, int base)
145 {
146         char *endptr;
147         long v;
148
149         assert(base == 10 || base == 16 || base == 8);
150
151         errno = 0;
152         v = strtol(str, &endptr, base);
153         if (errno > 0)
154                 return false;
155         if (str == endptr)
156                 return false;
157         if (*str != '\0' && *endptr != '\0')
158                 return false;
159
160         if (v >= INT_MAX || v <= INT_MIN)
161                 return false;
162
163         *val = v;
164         return true;
165 }
166
167 static inline bool
168 safe_atoi(const char *str, int *val)
169 {
170         return safe_atoi_base(str, val, 10);
171 }
172
173 static inline bool
174 safe_atou_base(const char *str, unsigned int *val, int base)
175 {
176         char *endptr;
177         unsigned long v;
178
179         assert(base == 10 || base == 16 || base == 8);
180
181         errno = 0;
182         v = strtoul(str, &endptr, base);
183         if (errno > 0)
184                 return false;
185         if (str == endptr)
186                 return false;
187         if (*str != '\0' && *endptr != '\0')
188                 return false;
189
190         if ((long)v < 0)
191                 return false;
192
193         *val = v;
194         return true;
195 }
196
197 static inline bool
198 safe_atou(const char *str, unsigned int *val)
199 {
200         return safe_atou_base(str, val, 10);
201 }
202
203 static inline bool
204 safe_atod(const char *str, double *val)
205 {
206         char *endptr;
207         double v;
208 #ifdef HAVE_LOCALE_H
209         locale_t c_locale;
210 #endif
211         size_t slen = strlen(str);
212
213         /* We don't have a use-case where we want to accept hex for a double
214          * or any of the other values strtod can parse */
215         for (size_t i = 0; i < slen; i++) {
216                 char c = str[i];
217
218                 if (isdigit(c))
219                        continue;
220                 switch(c) {
221                 case '+':
222                 case '-':
223                 case '.':
224                         break;
225                 default:
226                         return false;
227                 }
228         }
229
230 #ifdef HAVE_LOCALE_H
231         /* Create a "C" locale to force strtod to use '.' as separator */
232         c_locale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0);
233         if (c_locale == (locale_t)0)
234                 return false;
235
236         errno = 0;
237         v = strtod_l(str, &endptr, c_locale);
238         freelocale(c_locale);
239 #else
240         /* No locale support in provided libc, assume it already uses '.' */
241         errno = 0;
242         v = strtod(str, &endptr);
243 #endif
244         if (errno > 0)
245                 return false;
246         if (str == endptr)
247                 return false;
248         if (*str != '\0' && *endptr != '\0')
249                 return false;
250         if (v != 0.0 && !isnormal(v))
251                 return false;
252
253         *val = v;
254         return true;
255 }
256
257 char **strv_from_argv(int argc, char **argv);
258 char **strv_from_string(const char *in, const char *separator, size_t *num_elements);
259 char *strv_join(char **strv, const char *joiner);
260
261 static inline void
262 strv_free(char **strv) {
263         char **s = strv;
264
265         if (!strv)
266                 return;
267
268         while (*s != NULL) {
269                 free(*s);
270                 *s = (char*)0x1; /* detect use-after-free */
271                 s++;
272         }
273
274         free (strv);
275 }
276
277 struct key_value_str{
278         char *key;
279         char *value;
280 };
281
282 struct key_value_double {
283         double key;
284         double value;
285 };
286
287 static inline ssize_t
288 kv_double_from_string(const char *string,
289                       const char *pair_separator,
290                       const char *kv_separator,
291                       struct key_value_double **result_out)
292
293 {
294         struct key_value_double *result = NULL;
295
296         if (!pair_separator || pair_separator[0] == '\0' ||
297             !kv_separator || kv_separator[0] == '\0')
298                 return -1;
299
300         size_t npairs;
301         char **pairs = strv_from_string(string, pair_separator, &npairs);
302         if (!pairs || npairs == 0)
303                 goto error;
304
305         result = zalloc(npairs * sizeof *result);
306
307         for (size_t idx = 0; idx < npairs; idx++) {
308                 char *pair = pairs[idx];
309                 size_t nelem;
310                 char **kv = strv_from_string(pair, kv_separator, &nelem);
311                 double k, v;
312
313                 if (!kv || nelem != 2 ||
314                     !safe_atod(kv[0], &k) ||
315                     !safe_atod(kv[1], &v)) {
316                         strv_free(kv);
317                         goto error;
318                 }
319
320                 result[idx].key = k;
321                 result[idx].value = v;
322
323                 strv_free(kv);
324         }
325
326         strv_free(pairs);
327
328         *result_out = result;
329
330         return npairs;
331
332 error:
333         strv_free(pairs);
334         free(result);
335         return -1;
336 }
337
338 /**
339  * Strip any of the characters in what from the beginning and end of the
340  * input string.
341  *
342  * @return a newly allocated string with none of "what" at the beginning or
343  * end of string
344  */
345 static inline char *
346 strstrip(const char *input, const char *what)
347 {
348         char *str, *last;
349
350         str = safe_strdup(&input[strspn(input, what)]);
351
352         last = str;
353
354         for (char *c = str; *c != '\0'; c++) {
355                 if (!strchr(what, *c))
356                         last = c + 1;
357         }
358
359         *last = '\0';
360
361         return str;
362 }
363
364 /**
365  * Return true if str ends in suffix, false otherwise. If the suffix is the
366  * empty string, strendswith() always returns false.
367  */
368 static inline bool
369 strendswith(const char *str, const char *suffix)
370 {
371         size_t slen = strlen(str);
372         size_t suffixlen = strlen(suffix);
373         size_t offset;
374
375         if (slen == 0 || suffixlen == 0 || suffixlen > slen)
376                 return false;
377
378         offset = slen - suffixlen;
379         return strneq(&str[offset], suffix, suffixlen);
380 }
381
382 static inline bool
383 strstartswith(const char *str, const char *prefix)
384 {
385         size_t prefixlen = strlen(prefix);
386
387         return prefixlen > 0 ? strneq(str, prefix, strlen(prefix)) : false;
388 }
389
390 const char *
391 safe_basename(const char *filename);
392
393 char *
394 trunkname(const char *filename);
395
396 /**
397  * Return a copy of str with all % converted to %% to make the string
398  * acceptable as printf format.
399  */
400 static inline char *
401 str_sanitize(const char *str)
402 {
403         if (!str)
404                 return NULL;
405
406         if (!strchr(str, '%'))
407                 return strdup(str);
408
409         size_t slen = min(strlen(str), 512);
410         char *sanitized = zalloc(2 * slen + 1);
411         const char *src = str;
412         char *dst = sanitized;
413
414         for (size_t i = 0; i < slen; i++) {
415                 if (*src == '%')
416                         *dst++ = '%';
417                 *dst++ = *src++;
418         }
419         *dst = '\0';
420
421         return sanitized;
422 }