aacb4a24e8b8e3f66395dfdfd42f32556b066328
[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 char
66 to_lower(char c);
67
68 int
69 istrcmp(const char *a, const char *b);
70
71 int
72 istrncmp(const char *a, const char *b, size_t n);
73
74 static inline bool
75 streq(const char *s1, const char *s2)
76 {
77     assert(s1 && s2);
78     return strcmp(s1, s2) == 0;
79 }
80
81 static inline bool
82 streq_null(const char *s1, const char *s2)
83 {
84     if (s1 == NULL || s2 == NULL)
85         return s1 == s2;
86     return streq(s1, s2);
87 }
88
89 static inline bool
90 streq_not_null(const char *s1, const char *s2)
91 {
92     if (!s1 || !s2)
93         return false;
94     return streq(s1, s2);
95 }
96
97 static inline bool
98 istreq(const char *s1, const char *s2)
99 {
100     return istrcmp(s1, s2) == 0;
101 }
102
103 static inline bool
104 istreq_prefix(const char *s1, const char *s2)
105 {
106     return istrncmp(s1, s2, strlen(s1)) == 0;
107 }
108
109 static inline char *
110 strdup_safe(const char *s)
111 {
112     return s ? strdup(s) : NULL;
113 }
114
115 static inline size_t
116 strlen_safe(const char *s)
117 {
118     return s ? strlen(s) : 0;
119 }
120
121 static inline bool
122 isempty(const char *s)
123 {
124     return s == NULL || s[0] == '\0';
125 }
126
127 static inline const char *
128 strnull(const char *s)
129 {
130     return s ? s : "(null)";
131 }
132
133 static inline const char *
134 strempty(const char *s)
135 {
136     return s ? s : "";
137 }
138
139 static inline void *
140 memdup(const void *mem, size_t nmemb, size_t size)
141 {
142     void *p = calloc(nmemb, size);
143     if (p)
144         memcpy(p, mem, nmemb * size);
145     return p;
146 }
147
148 #if !(defined(HAVE_STRNDUP) && HAVE_STRNDUP)
149 static inline char *
150 strndup(const char *s, size_t n)
151 {
152     size_t slen = strlen(s);
153     size_t len = MIN(slen, n);
154     char *p = malloc(len + 1);
155     if (!p)
156         return NULL;
157     memcpy(p, s, len);
158     p[len] = '\0';
159     return p;
160 }
161 #endif
162
163 /* ctype.h is locale-dependent and has other oddities. */
164 static inline bool
165 is_space(char ch)
166 {
167     return ch == ' ' || (ch >= '\t' && ch <= '\r');
168 }
169
170 static inline bool
171 is_alpha(char ch)
172 {
173     return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
174 }
175
176 static inline bool
177 is_digit(char ch)
178 {
179     return ch >= '0' && ch <= '9';
180 }
181
182 static inline bool
183 is_alnum(char ch)
184 {
185     return is_alpha(ch) || is_digit(ch);
186 }
187
188 static inline bool
189 is_xdigit(char ch)
190 {
191     return
192         (ch >= '0' && ch <= '9') ||
193         (ch >= 'a' && ch <= 'f') ||
194         (ch >= 'A' && ch <= 'F');
195 }
196
197 static inline bool
198 is_graph(char ch)
199 {
200     /* See table in ascii(7). */
201     return ch >= '!' && ch <= '~';
202 }
203
204 /*
205  * Return the bit position of the most significant bit.
206  * Note: this is 1-based! It's more useful this way, and returns 0 when
207  * mask is all 0s.
208  */
209 static inline unsigned
210 msb_pos(uint32_t mask)
211 {
212     unsigned pos = 0;
213     while (mask) {
214         pos++;
215         mask >>= 1u;
216     }
217     return pos;
218 }
219
220 static inline int
221 one_bit_set(uint32_t x)
222 {
223     return x && (x & (x - 1)) == 0;
224 }
225
226 bool
227 map_file(FILE *file, char **string_out, size_t *size_out);
228
229 void
230 unmap_file(char *string, size_t size);
231
232 static inline bool
233 check_eaccess(const char *path, int mode)
234 {
235 #if defined(HAVE_EACCESS)
236     if (eaccess(path, mode) != 0)
237         return false;
238 #elif defined(HAVE_EUIDACCESS)
239     if (euidaccess(path, mode) != 0)
240         return false;
241 #endif
242
243     return true;
244 }
245
246 #if defined(HAVE_SECURE_GETENV)
247 # define secure_getenv secure_getenv
248 #elif defined(HAVE___SECURE_GETENV)
249 # define secure_getenv __secure_getenv
250 #else
251 # define secure_getenv getenv
252 #endif
253
254 #if defined(HAVE___BUILTIN_EXPECT)
255 # define likely(x)   __builtin_expect(!!(x), 1)
256 # define unlikely(x) __builtin_expect(!!(x), 0)
257 #else
258 # define likely(x)   (x)
259 # define unlikely(x) (x)
260 #endif
261
262 /* Compiler Attributes */
263
264 #if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__CYGWIN__)
265 # define XKB_EXPORT      __attribute__((visibility("default")))
266 #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
267 # define XKB_EXPORT      __global
268 #else /* not gcc >= 4 and not Sun Studio >= 8 */
269 # define XKB_EXPORT
270 #endif
271
272 #if defined(__MINGW32__)
273 # define ATTR_PRINTF(x,y) __attribute__((__format__(__MINGW_PRINTF_FORMAT, x, y)))
274 #elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)
275 # define ATTR_PRINTF(x,y) __attribute__((__format__(__printf__, x, y)))
276 #else /* not gcc >= 2.3 */
277 # define ATTR_PRINTF(x,y)
278 #endif
279
280 #if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)) \
281     || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
282 # define ATTR_NORETURN __attribute__((__noreturn__))
283 #else
284 # define ATTR_NORETURN
285 #endif /* GNUC  */
286
287 #if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 296)
288 #define ATTR_MALLOC  __attribute__((__malloc__))
289 #else
290 #define ATTR_MALLOC
291 #endif
292
293 #if defined(__GNUC__) && (__GNUC__ >= 4)
294 # define ATTR_NULL_SENTINEL __attribute__((__sentinel__))
295 #else
296 # define ATTR_NULL_SENTINEL
297 #endif /* GNUC >= 4 */
298
299 #if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 295)
300 #define ATTR_PACKED  __attribute__((__packed__))
301 #else
302 #define ATTR_PACKED
303 #endif
304
305 #if !(defined(HAVE_ASPRINTF) && HAVE_ASPRINTF)
306 int asprintf(char **strp, const char *fmt, ...) ATTR_PRINTF(2, 3);
307 # if !(defined(HAVE_VASPRINTF) && HAVE_VASPRINTF)
308 #  include <stdarg.h>
309 int vasprintf(char **strp, const char *fmt, va_list ap);
310 # endif /* !HAVE_VASPRINTF */
311 #endif /* !HAVE_ASPRINTF */
312
313 static inline bool
314 ATTR_PRINTF(3, 4)
315 snprintf_safe(char *buf, size_t sz, const char *format, ...)
316 {
317     va_list ap;
318     int rc;
319
320     va_start(ap, format);
321     rc = vsnprintf(buf, sz, format, ap);
322     va_end(ap);
323
324     return rc >= 0 && (size_t)rc < sz;
325 }
326
327 static inline char *
328 ATTR_PRINTF(1, 0)
329 vasprintf_safe(const char *fmt, va_list args)
330 {
331     char *str;
332     int len;
333
334     len = vasprintf(&str, fmt, args);
335
336     if (len == -1)
337         return NULL;
338
339     return str;
340 }
341
342 /**
343  * A version of asprintf that returns the allocated string or NULL on error.
344  */
345 static inline char *
346 ATTR_PRINTF(1, 2)
347 asprintf_safe(const char *fmt, ...)
348 {
349     va_list args;
350     char *str;
351
352     va_start(args, fmt);
353     str = vasprintf_safe(fmt, args);
354     va_end(args);
355
356     return str;
357 }
358
359 #endif /* UTILS_H */