awful.widget: fix tags removal
[awesome.git] / common / util.h
blob7dc3be8ab8427a794dffe855391a1c00264a7944
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 /* asprintf */
27 #define _GNU_SOURCE
29 #include <string.h>
30 #include <stdlib.h>
31 #include <stdbool.h>
32 #include <stdarg.h>
33 #include <assert.h>
34 #include <stdio.h>
36 #if !(defined (__FreeBSD__) || defined(__OpenBSD__))
37 #include <alloca.h>
38 #endif
40 #include "tokenize.h"
42 typedef enum
44 East,
45 South,
46 North,
47 } orientation_t;
49 /** A list of possible position, not sex related */
50 typedef enum
52 Top,
53 Bottom,
54 Right,
55 Left,
56 Floating
57 } position_t;
59 /** Link a name to a function */
60 typedef struct
62 const char *name;
63 void *func;
64 } name_func_link_t;
66 /** \brief replace \c NULL strings with emtpy strings */
67 #define NONULL(x) (x ? x : "")
69 #define DO_NOTHING(...)
71 #undef MAX
72 #undef MIN
73 #define MAX(a,b) ((a) < (b) ? (b) : (a))
74 #define MIN(a,b) ((a) < (b) ? (a) : (b))
76 #define ssizeof(foo) (ssize_t)sizeof(foo)
77 #define countof(foo) (ssizeof(foo) / ssizeof(foo[0]))
79 #define p_alloca(type, count) \
80 ((type *)memset(alloca(sizeof(type) * (count)), \
81 0, sizeof(type) * (count)))
83 #define p_alloc_nr(x) (((x) + 16) * 3 / 2)
84 #define p_new(type, count) ((type *)xmalloc(sizeof(type) * (count)))
85 #define p_clear(p, count) ((void)memset((p), 0, sizeof(*(p)) * (count)))
86 #define p_realloc(pp, count) xrealloc((void*)(pp), sizeof(**(pp)) * (count))
87 #define p_dup(p, count) xmemdup((p), sizeof(*(p)) * (count))
88 #define p_grow(pp, goalnb, allocnb) \
89 do { \
90 if ((goalnb) > *(allocnb)) { \
91 if (p_alloc_nr(*(allocnb)) < (goalnb)) { \
92 *(allocnb) = (goalnb); \
93 } else { \
94 *(allocnb) = p_alloc_nr(*(allocnb)); \
95 } \
96 p_realloc(pp, *(allocnb)); \
97 } \
98 } while (0)
101 #ifdef __GNUC__
103 #define p_delete(mem_pp) \
104 do { \
105 typeof(**(mem_pp)) **__ptr = (mem_pp); \
106 free(*__ptr); \
107 *__ptr = NULL; \
108 } while(0)
110 #define likely(expr) __builtin_expect(!!(expr), 1)
111 #define unlikely(expr) __builtin_expect((expr), 0)
113 #else
115 #define p_delete(mem_p) \
116 do { \
117 void *__ptr = (mem_p); \
118 free(*__ptr); \
119 *(void **)__ptr = NULL; \
120 } while (0)
122 #define likely(expr) expr
123 #define unlikely(expr) expr
125 #endif
127 static inline void * __attribute__ ((malloc)) xmalloc(ssize_t size)
129 void *ptr;
131 if(size <= 0)
132 return NULL;
134 ptr = calloc(1, size);
136 if(!ptr)
137 abort();
139 return ptr;
142 static inline void
143 xrealloc(void **ptr, ssize_t newsize)
145 if(newsize <= 0)
146 p_delete(ptr);
147 else
149 *ptr = realloc(*ptr, newsize);
150 if(!*ptr)
151 abort();
155 /** Duplicate a memory zone.
156 * \param src The source.
157 * \param size The source size.
158 * \return The memory address of the copy.
160 static inline void *xmemdup(const void *src, ssize_t size)
162 return memcpy(xmalloc(size), src, size);
165 /** \brief \c NULL resistant strlen.
167 * Unlike it's libc sibling, a_strlen returns a ssize_t, and supports its
168 * argument being NULL.
170 * \param[in] s the string.
171 * \return the string length (or 0 if \c s is \c NULL).
173 static inline ssize_t a_strlen(const char *s)
175 return s ? strlen(s) : 0;
178 /** \brief \c NULL resistant strnlen.
180 * Unlike it's GNU libc sibling, a_strnlen returns a ssize_t, and supports
181 * its argument being NULL.
183 * The a_strnlen() function returns the number of characters in the string
184 * pointed to by \c s, not including the terminating \c \\0 character, but at
185 * most \c n. In doing this, a_strnlen() looks only at the first \c n
186 * characters at \c s and never beyond \c s+n.
188 * \param[in] s the string.
189 * \param[in] n the maximum length to return.
190 * \return \c a_strlen(s) if less than \c n, else \c n.
192 static inline ssize_t a_strnlen(const char *s, ssize_t n)
194 if (s)
196 const char *p = memchr(s, '\0', n);
197 return p ? p - s : n;
199 return 0;
202 /** \brief \c NULL resistant strdup.
204 * the a_strdup() function returns a pointer to a new string, which is a
205 * duplicate of \c s. Memory should be freed using p_delete().
207 * \warning when s is \c "", it returns NULL !
209 * \param[in] s the string to duplicate.
210 * \return a pointer to the duplicated string.
212 static inline
213 char *a_strdup(const char *s)
215 ssize_t len = a_strlen(s);
216 return len ? p_dup(s, len + 1) : NULL;
219 /** \brief safe limited strdup.
221 * Copies at most min(<tt>n-1</tt>, \c l) characters from \c src into a newly
222 * allocated buffer, always adding a final \c \\0, and returns that buffer.
224 * \warning when s is \c "" or l is 0, it returns NULL !
226 * \param[in] s source string.
227 * \param[in] l maximum number of chars to copy.
228 * \return a newly allocated buffer containing the first \c l chars of \c src.
230 static inline
231 char * a_strndup(const char *s, ssize_t l)
233 ssize_t len = MIN(a_strlen(s), l);
234 if(len)
236 char *p = p_dup(s, len + 1);
237 p[len] = '\0';
238 return p;
240 return NULL;
243 /** \brief \c NULL resistant strcmp.
244 * \param[in] a the first string.
245 * \param[in] b the second string.
246 * \return <tt>strcmp(a, b)</tt>, and treats \c NULL strings like \c ""
247 * ones.
249 static inline int a_strcmp(const char *a, const char *b)
251 return strcmp(NONULL(a), NONULL(b));
254 /** \brief \c NULL resistant strcasecmp.
255 * \param[in] a the first string.
256 * \param[in] b the second string.
257 * \return <tt>strcasecmp(a, b)</tt>, and treats \c NULL strings like \c ""
258 * ones.
260 static inline int a_strcasecmp(const char *a, const char *b)
262 return strcasecmp(NONULL(a), NONULL(b));
265 /** \brief \c NULL resistant strncmp.
266 * \param[in] a the first string.
267 * \param[in] b the second string.
268 * \param[in] n the number of maximum chars to compare.
269 * \return <tt>strncmp(a, b, n)</tt>, and treats \c NULL strings like \c ""
270 * ones.
272 static inline int a_strncmp(const char *a, const char *b, ssize_t n)
274 return strncmp(NONULL(a), NONULL(b), n);
277 ssize_t a_strncpy(char *dst, ssize_t n, const char *src, ssize_t l) __attribute__((nonnull(1)));
278 ssize_t a_strcpy(char *dst, ssize_t n, const char *src) __attribute__((nonnull(1)));
280 /** \brief safe strcat.
282 * The a_strcat() function appends the string \c src at the end of the buffer
283 * \c dst if space is available.
285 * \param[in] dst destination buffer.
286 * \param[in] n size of the buffer, Negative sizes are allowed.
287 * \param[in] src the string to append.
288 * \return <tt>a_strlen(dst) + a_strlen(src)</tt>
290 static inline ssize_t a_strcat(char *dst, ssize_t n, const char *src)
292 ssize_t dlen = a_strnlen(dst, n - 1);
293 return dlen + a_strcpy(dst + dlen, n - dlen, src);
296 /** \brief safe strncat.
298 * The a_strncat() function appends at most \c n chars from the string \c src
299 * at the end of the buffer \c dst if space is available.
301 * \param[in] dst destination buffer.
302 * \param[in] n size of the buffer, Negative sizes are allowed.
303 * \param[in] src the string to append.
304 * \param[in] l maximum number of chars of src to consider.
305 * \return the smallest value between <tt>a_strlen(dst) + a_strlen(src)</tt>
306 * and <tt>a_strlen(dst) + l</tt>
308 static inline ssize_t
309 a_strncat(char *dst, ssize_t n, const char *src, ssize_t l)
311 ssize_t dlen = a_strnlen(dst, n - 1);
312 return dlen + a_strncpy(dst + dlen, n - dlen, src, l);
315 /** \brief convert a string to a boolean value.
317 * The a_strtobool() function converts a string \c s into a boolean.
318 * It recognizes the strings "true", "on", "yes" and "1".
320 * \param[in] s the string to convert
321 * \return true if the string is recognized as possibly true, false otherwise.
323 static inline bool
324 a_strtobool(const char *s, ssize_t len)
326 switch(a_tokenize(s, len))
328 case A_TK_TRUE:
329 case A_TK_YES:
330 case A_TK_ON:
331 case A_TK_1:
332 return true;
333 default:
334 return false;
338 #define fatal(string, ...) _fatal(__LINE__, \
339 __FUNCTION__, \
340 string, ## __VA_ARGS__)
341 void _fatal(int, const char *, const char *, ...)
342 __attribute__ ((noreturn)) __attribute__ ((format(printf, 3, 4)));
344 #define warn(string, ...) _warn(__LINE__, \
345 __FUNCTION__, \
346 string, ## __VA_ARGS__)
347 void _warn(int, const char *, const char *, ...)
348 __attribute__ ((format(printf, 3, 4)));
350 position_t position_fromstr(const char *, ssize_t);
351 const char * position_tostr(position_t);
352 orientation_t orientation_fromstr(const char *, ssize_t);
353 const char * orientation_tostr(orientation_t);
354 void *name_func_lookup(const char *, const name_func_link_t *);
355 const char * name_func_rlookup(void *, const name_func_link_t *);
356 void a_exec(const char *);
357 char ** a_strsplit(const char *, ssize_t, char);
359 #define a_asprintf(strp, fmt, ...) \
360 do { \
361 if(asprintf(strp, fmt, ## __VA_ARGS__) < 0) \
362 abort(); \
363 } while(0)
365 #endif
366 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80