Make callbacks to rules.execute optional
[awesome.git] / common / util.h
blobcf4500f44a209ec6d8bc080dcdd77961e82922dd
1 /*
2 * util.h - useful functions header
4 * Copyright © 2007-2008 Julien Danjou <julien@danjou.info>
5 * Copyright © 2006 Pierre Habouzit <madcoder@debian.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #ifndef AWESOME_COMMON_UTIL_H
24 #define AWESOME_COMMON_UTIL_H
26 #define _GNU_SOURCE
28 #include <string.h>
29 #include <stdlib.h>
30 #include <stdbool.h>
31 #include <stdarg.h>
32 #include <assert.h>
33 #include <stdio.h>
35 #if !(defined (__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined (__DragonFly__))
36 #include <alloca.h>
37 #endif
39 /** \brief replace \c NULL strings with empty strings */
40 #define NONULL(x) (x ? x : "")
42 #define DO_NOTHING(...)
44 #undef MAX
45 #undef MIN
46 #define MAX(a,b) ((a) < (b) ? (b) : (a))
47 #define MIN(a,b) ((a) < (b) ? (a) : (b))
49 #define unsigned_subtract(a, b) \
50 do { \
51 if (b > a) \
52 a = 0; \
53 else \
54 a -= b; \
55 } while (0)
57 #define ssizeof(foo) (ssize_t)sizeof(foo)
58 #define countof(foo) (ssizeof(foo) / ssizeof(foo[0]))
59 #define fieldsizeof(type_t, m) sizeof(((type_t *)0)->m)
60 #define fieldtypeof(type_t, m) typeof(((type_t *)0)->m)
62 #define p_alloca(type, count) \
63 ((type *)memset(alloca(sizeof(type) * (count)), \
64 0, sizeof(type) * (count)))
66 #define p_alloc_nr(x) (((x) + 16) * 3 / 2)
67 #define p_new(type, count) ((type *)xmalloc(sizeof(type) * (count)))
68 #define p_clear(p, count) ((void)memset((p), 0, sizeof(*(p)) * (count)))
69 #define p_realloc(pp, count) xrealloc((void*)(pp), sizeof(**(pp)) * (count))
70 #define p_dup(p, count) xmemdup((p), sizeof(*(p)) * (count))
71 #define p_grow(pp, goalnb, allocnb) \
72 do { \
73 if ((goalnb) > *(allocnb)) { \
74 if (p_alloc_nr(*(allocnb)) < (goalnb)) { \
75 *(allocnb) = (goalnb); \
76 } else { \
77 *(allocnb) = p_alloc_nr(*(allocnb)); \
78 } \
79 p_realloc(pp, *(allocnb)); \
80 } \
81 } while (0)
83 #define p_delete(mem_p) \
84 do { \
85 void **__ptr = (void **) (mem_p); \
86 free(*__ptr); \
87 *(void **)__ptr = NULL; \
88 } while (0)
90 #ifdef __GNUC__
91 #define likely(expr) __builtin_expect(!!(expr), 1)
92 #define unlikely(expr) __builtin_expect((expr), 0)
93 #else
94 #define likely(expr) expr
95 #define unlikely(expr) expr
96 #endif
98 static inline void * __attribute__ ((malloc)) xmalloc(ssize_t size)
100 void *ptr;
102 if(size <= 0)
103 return NULL;
105 ptr = calloc(1, size);
107 if(!ptr)
108 abort();
110 return ptr;
113 static inline void
114 xrealloc(void **ptr, ssize_t newsize)
116 if(newsize <= 0)
117 p_delete(ptr);
118 else
120 *ptr = realloc(*ptr, newsize);
121 if(!*ptr)
122 abort();
126 /** Duplicate a memory zone.
127 * \param src The source.
128 * \param size The source size.
129 * \return The memory address of the copy.
131 static inline void *xmemdup(const void *src, ssize_t size)
133 return memcpy(xmalloc(size), src, size);
136 /** \brief \c NULL resistant strlen.
138 * Unlike it's libc sibling, a_strlen returns a ssize_t, and supports its
139 * argument being NULL.
141 * \param[in] s the string.
142 * \return the string length (or 0 if \c s is \c NULL).
144 static inline ssize_t a_strlen(const char *s)
146 return s ? strlen(s) : 0;
149 /** \brief \c NULL resistant strnlen.
151 * Unlike it's GNU libc sibling, a_strnlen returns a ssize_t, and supports
152 * its argument being NULL.
154 * The a_strnlen() function returns the number of characters in the string
155 * pointed to by \c s, not including the terminating \c \\0 character, but at
156 * most \c n. In doing this, a_strnlen() looks only at the first \c n
157 * characters at \c s and never beyond \c s+n.
159 * \param[in] s the string.
160 * \param[in] n the maximum length to return.
161 * \return \c a_strlen(s) if less than \c n, else \c n.
163 static inline ssize_t a_strnlen(const char *s, ssize_t n)
165 if (s)
167 const char *p = memchr(s, '\0', n);
168 return p ? p - s : n;
170 return 0;
173 /** \brief \c NULL resistant strdup.
175 * The a_strdup() function returns a pointer to a new string, which is a
176 * duplicate of \c s. Memory should be freed using p_delete().
178 * \warning when s is \c "", it returns NULL !
180 * \param[in] s the string to duplicate.
181 * \return a pointer to the duplicated string.
183 static inline
184 char *a_strdup(const char *s)
186 ssize_t len = a_strlen(s);
187 return len ? p_dup(s, len + 1) : NULL;
190 /** \brief safe limited strdup.
192 * Copies at most min(<tt>n-1</tt>, \c l) characters from \c src into a newly
193 * allocated buffer, always adding a final \c \\0, and returns that buffer.
195 * \warning when s is \c "" or l is 0, it returns NULL !
197 * \param[in] s source string.
198 * \param[in] l maximum number of chars to copy.
199 * \return a newly allocated buffer containing the first \c l chars of \c src.
201 static inline
202 char * a_strndup(const char *s, ssize_t l)
204 ssize_t len = MIN(a_strlen(s), l);
205 if(len)
207 char *p = p_dup(s, len + 1);
208 p[len] = '\0';
209 return p;
211 return NULL;
214 /** \brief \c NULL resistant strcmp.
215 * \param[in] a the first string.
216 * \param[in] b the second string.
217 * \return <tt>strcmp(a, b)</tt>, and treats \c NULL strings like \c ""
218 * ones.
220 static inline int a_strcmp(const char *a, const char *b)
222 return strcmp(NONULL(a), NONULL(b));
225 #define A_STREQ(a, b) (((a) == (b)) || a_strcmp(a, b) == 0)
226 #define A_STRNEQ(a, b) (!A_STREQ(a, b))
228 /** \brief \c NULL resistant strcasecmp.
229 * \param[in] a the first string.
230 * \param[in] b the second string.
231 * \return <tt>strcasecmp(a, b)</tt>, and treats \c NULL strings like \c ""
232 * ones.
234 static inline int a_strcasecmp(const char *a, const char *b)
236 return strcasecmp(NONULL(a), NONULL(b));
239 #define A_STREQ_CASE(a, b) (((a) == (b)) || a_strcasecmp(a, b) == 0)
240 #define A_STRNEQ_CASE(a, b) (!A_STRCASEEQ(a, b))
242 /** \brief \c NULL resistant strncmp.
243 * \param[in] a the first string.
244 * \param[in] b the second string.
245 * \param[in] n the number of maximum chars to compare.
246 * \return <tt>strncmp(a, b, n)</tt>, and treats \c NULL strings like \c ""
247 * ones.
249 static inline int a_strncmp(const char *a, const char *b, ssize_t n)
251 return strncmp(NONULL(a), NONULL(b), n);
254 #define A_STREQ_N(a, b, n) (((a) == (b)) || (n) == ((ssize_t) 0) || a_strncmp(a, b, n) == 0)
255 #define A_STRNEQ_N(a, b) (!A_STREQN(a, b))
257 ssize_t a_strncpy(char *dst, ssize_t n, const char *src, ssize_t l) __attribute__((nonnull(1)));
258 ssize_t a_strcpy(char *dst, ssize_t n, const char *src) __attribute__((nonnull(1)));
260 /** \brief safe strcat.
262 * The a_strcat() function appends the string \c src at the end of the buffer
263 * \c dst if space is available.
265 * \param[in] dst destination buffer.
266 * \param[in] n size of the buffer, Negative sizes are allowed.
267 * \param[in] src the string to append.
268 * \return <tt>a_strlen(dst) + a_strlen(src)</tt>
270 static inline ssize_t a_strcat(char *dst, ssize_t n, const char *src)
272 ssize_t dlen = a_strnlen(dst, n - 1);
273 return dlen + a_strcpy(dst + dlen, n - dlen, src);
276 /** \brief safe strncat.
278 * The a_strncat() function appends at most \c n chars from the string \c src
279 * at the end of the buffer \c dst if space is available.
281 * \param[in] dst destination buffer.
282 * \param[in] n size of the buffer, Negative sizes are allowed.
283 * \param[in] src the string to append.
284 * \param[in] l maximum number of chars of src to consider.
285 * \return the smallest value between <tt>a_strlen(dst) + a_strlen(src)</tt>
286 * and <tt>a_strlen(dst) + l</tt>
288 static inline ssize_t
289 a_strncat(char *dst, ssize_t n, const char *src, ssize_t l)
291 ssize_t dlen = a_strnlen(dst, n - 1);
292 return dlen + a_strncpy(dst + dlen, n - dlen, src, l);
295 /** Compute a hash for a string.
296 * This is based on 'djb2' algorithm.
298 static inline unsigned long __attribute__ ((nonnull(1)))
299 a_strhash(const unsigned char *str)
301 unsigned long hash = 5381;
302 int c;
304 while((c = *str++))
305 hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
307 return hash;
310 #define fatal(string, ...) _fatal(__LINE__, \
311 __FUNCTION__, \
312 string, ## __VA_ARGS__)
313 void _fatal(int, const char *, const char *, ...)
314 __attribute__ ((noreturn)) __attribute__ ((format(printf, 3, 4)));
316 #define warn(string, ...) _warn(__LINE__, \
317 __FUNCTION__, \
318 string, ## __VA_ARGS__)
319 void _warn(int, const char *, const char *, ...)
320 __attribute__ ((format(printf, 3, 4)));
322 void a_exec(const char *);
324 #endif
325 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80