Structured log messages with a message registry
[platform/upstream/libxkbcommon.git] / src / utils.h
1 /*
2  * Copyright © 2012 Ran Benita <ran234@gmail.com>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23
24 #ifndef UTILS_H
25 #define UTILS_H 1
26
27 #include <errno.h>
28 #include <inttypes.h>
29 #include <stdarg.h>
30 #include <stdbool.h>
31 #include <stdio.h>
32 #include <string.h>
33 #if HAVE_UNISTD_H
34 # include <unistd.h>
35 #else
36 /* Required on Windows where unistd.h doesn't exist */
37 # define R_OK    4               /* Test for read permission.  */
38 # define W_OK    2               /* Test for write permission.  */
39 # define X_OK    1               /* Test for execute permission.  */
40 # define F_OK    0               /* Test for existence.  */
41 #endif
42
43 #ifdef _WIN32
44 # include <direct.h>
45 # include <io.h>
46 # ifndef S_ISDIR
47 #  define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
48 # endif
49 #endif
50
51 #include "darray.h"
52
53 #define STATIC_ASSERT(expr, message) do { \
54     switch (0) { case 0: case (expr): ; } \
55 } while (0)
56
57 #define ARRAY_SIZE(arr) ((sizeof(arr) / sizeof(*(arr))))
58
59 #define MIN(a, b) ((a) < (b) ? (a) : (b))
60 #define MAX(a, b) ((a) > (b) ? (a) : (b))
61
62 /* Round up @a so it's divisible by @b. */
63 #define ROUNDUP(a, b) (((a) + (b) - 1) / (b) * (b))
64
65 #define STRINGIFY(x) #x
66 #define STRINGIFY2(x) STRINGIFY(x)
67
68 char
69 to_lower(char c);
70
71 int
72 istrcmp(const char *a, const char *b);
73
74 int
75 istrncmp(const char *a, const char *b, size_t n);
76
77 static inline bool
78 streq(const char *s1, const char *s2)
79 {
80     assert(s1 && s2);
81     return strcmp(s1, s2) == 0;
82 }
83
84 static inline bool
85 streq_null(const char *s1, const char *s2)
86 {
87     if (s1 == NULL || s2 == NULL)
88         return s1 == s2;
89     return streq(s1, s2);
90 }
91
92 static inline bool
93 streq_not_null(const char *s1, const char *s2)
94 {
95     if (!s1 || !s2)
96         return false;
97     return streq(s1, s2);
98 }
99
100 static inline bool
101 istreq(const char *s1, const char *s2)
102 {
103     return istrcmp(s1, s2) == 0;
104 }
105
106 static inline bool
107 istreq_prefix(const char *s1, const char *s2)
108 {
109     return istrncmp(s1, s2, strlen(s1)) == 0;
110 }
111
112 static inline char *
113 strdup_safe(const char *s)
114 {
115     return s ? strdup(s) : NULL;
116 }
117
118 static inline size_t
119 strlen_safe(const char *s)
120 {
121     return s ? strlen(s) : 0;
122 }
123
124 static inline bool
125 isempty(const char *s)
126 {
127     return s == NULL || s[0] == '\0';
128 }
129
130 static inline const char *
131 strnull(const char *s)
132 {
133     return s ? s : "(null)";
134 }
135
136 static inline const char *
137 strempty(const char *s)
138 {
139     return s ? s : "";
140 }
141
142 static inline void *
143 memdup(const void *mem, size_t nmemb, size_t size)
144 {
145     void *p = calloc(nmemb, size);
146     if (p)
147         memcpy(p, mem, nmemb * size);
148     return p;
149 }
150
151 #if !(defined(HAVE_STRNDUP) && HAVE_STRNDUP)
152 static inline char *
153 strndup(const char *s, size_t n)
154 {
155     size_t slen = strlen(s);
156     size_t len = MIN(slen, n);
157     char *p = malloc(len + 1);
158     if (!p)
159         return NULL;
160     memcpy(p, s, len);
161     p[len] = '\0';
162     return p;
163 }
164 #endif
165
166 /* ctype.h is locale-dependent and has other oddities. */
167 static inline bool
168 is_space(char ch)
169 {
170     return ch == ' ' || (ch >= '\t' && ch <= '\r');
171 }
172
173 static inline bool
174 is_alpha(char ch)
175 {
176     return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
177 }
178
179 static inline bool
180 is_digit(char ch)
181 {
182     return ch >= '0' && ch <= '9';
183 }
184
185 static inline bool
186 is_alnum(char ch)
187 {
188     return is_alpha(ch) || is_digit(ch);
189 }
190
191 static inline bool
192 is_xdigit(char ch)
193 {
194     return
195         (ch >= '0' && ch <= '9') ||
196         (ch >= 'a' && ch <= 'f') ||
197         (ch >= 'A' && ch <= 'F');
198 }
199
200 static inline bool
201 is_graph(char ch)
202 {
203     /* See table in ascii(7). */
204     return ch >= '!' && ch <= '~';
205 }
206
207 /*
208  * Return the bit position of the most significant bit.
209  * Note: this is 1-based! It's more useful this way, and returns 0 when
210  * mask is all 0s.
211  */
212 static inline unsigned
213 msb_pos(uint32_t mask)
214 {
215     unsigned pos = 0;
216     while (mask) {
217         pos++;
218         mask >>= 1u;
219     }
220     return pos;
221 }
222
223 static inline int
224 one_bit_set(uint32_t x)
225 {
226     return x && (x & (x - 1)) == 0;
227 }
228
229 bool
230 map_file(FILE *file, char **string_out, size_t *size_out);
231
232 void
233 unmap_file(char *string, size_t size);
234
235 static inline bool
236 check_eaccess(const char *path, int mode)
237 {
238 #if defined(HAVE_EACCESS)
239     if (eaccess(path, mode) != 0)
240         return false;
241 #elif defined(HAVE_EUIDACCESS)
242     if (euidaccess(path, mode) != 0)
243         return false;
244 #endif
245
246     return true;
247 }
248
249 #if defined(HAVE_SECURE_GETENV)
250 # define secure_getenv secure_getenv
251 #elif defined(HAVE___SECURE_GETENV)
252 # define secure_getenv __secure_getenv
253 #else
254 # define secure_getenv getenv
255 #endif
256
257 #if defined(HAVE___BUILTIN_EXPECT)
258 # define likely(x)   __builtin_expect(!!(x), 1)
259 # define unlikely(x) __builtin_expect(!!(x), 0)
260 #else
261 # define likely(x)   (x)
262 # define unlikely(x) (x)
263 #endif
264
265 /* Compiler Attributes */
266
267 #if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__CYGWIN__)
268 # define XKB_EXPORT      __attribute__((visibility("default")))
269 #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
270 # define XKB_EXPORT      __global
271 #else /* not gcc >= 4 and not Sun Studio >= 8 */
272 # define XKB_EXPORT
273 #endif
274
275 #if defined(__MINGW32__)
276 # define ATTR_PRINTF(x,y) __attribute__((__format__(__MINGW_PRINTF_FORMAT, x, y)))
277 #elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)
278 # define ATTR_PRINTF(x,y) __attribute__((__format__(__printf__, x, y)))
279 #else /* not gcc >= 2.3 */
280 # define ATTR_PRINTF(x,y)
281 #endif
282
283 #if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)) \
284     || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
285 # define ATTR_NORETURN __attribute__((__noreturn__))
286 #else
287 # define ATTR_NORETURN
288 #endif /* GNUC  */
289
290 #if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 296)
291 #define ATTR_MALLOC  __attribute__((__malloc__))
292 #else
293 #define ATTR_MALLOC
294 #endif
295
296 #if defined(__GNUC__) && (__GNUC__ >= 4)
297 # define ATTR_NULL_SENTINEL __attribute__((__sentinel__))
298 #else
299 # define ATTR_NULL_SENTINEL
300 #endif /* GNUC >= 4 */
301
302 #if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 295)
303 #define ATTR_PACKED  __attribute__((__packed__))
304 #else
305 #define ATTR_PACKED
306 #endif
307
308 #if !(defined(HAVE_ASPRINTF) && HAVE_ASPRINTF)
309 int asprintf(char **strp, const char *fmt, ...) ATTR_PRINTF(2, 3);
310 # if !(defined(HAVE_VASPRINTF) && HAVE_VASPRINTF)
311 #  include <stdarg.h>
312 int vasprintf(char **strp, const char *fmt, va_list ap);
313 # endif /* !HAVE_VASPRINTF */
314 #endif /* !HAVE_ASPRINTF */
315
316 static inline bool
317 ATTR_PRINTF(3, 4)
318 snprintf_safe(char *buf, size_t sz, const char *format, ...)
319 {
320     va_list ap;
321     int rc;
322
323     va_start(ap, format);
324     rc = vsnprintf(buf, sz, format, ap);
325     va_end(ap);
326
327     return rc >= 0 && (size_t)rc < sz;
328 }
329
330 static inline char *
331 ATTR_PRINTF(1, 0)
332 vasprintf_safe(const char *fmt, va_list args)
333 {
334     char *str;
335     int len;
336
337     len = vasprintf(&str, fmt, args);
338
339     if (len == -1)
340         return NULL;
341
342     return str;
343 }
344
345 /**
346  * A version of asprintf that returns the allocated string or NULL on error.
347  */
348 static inline char *
349 ATTR_PRINTF(1, 2)
350 asprintf_safe(const char *fmt, ...)
351 {
352     va_list args;
353     char *str;
354
355     va_start(args, fmt);
356     str = vasprintf_safe(fmt, args);
357     va_end(args);
358
359     return str;
360 }
361
362 #endif /* UTILS_H */