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
35 #if !(defined (__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__))
46 /** A list of possible position, not sex related */
55 /** \brief replace \c NULL strings with empty strings */
56 #define NONULL(x) (x ? x : "")
58 #define DO_NOTHING(...)
62 #define MAX(a,b) ((a) < (b) ? (b) : (a))
63 #define MIN(a,b) ((a) < (b) ? (a) : (b))
65 #define unsigned_subtract(a, b) \
73 #define ssizeof(foo) (ssize_t)sizeof(foo)
74 #define countof(foo) (ssizeof(foo) / ssizeof(foo[0]))
75 #define fieldsizeof(type_t, m) sizeof(((type_t *)0)->m)
76 #define fieldtypeof(type_t, m) typeof(((type_t *)0)->m)
78 #define p_alloca(type, count) \
79 ((type *)memset(alloca(sizeof(type) * (count)), \
80 0, sizeof(type) * (count)))
82 #define p_alloc_nr(x) (((x) + 16) * 3 / 2)
83 #define p_new(type, count) ((type *)xmalloc(sizeof(type) * (count)))
84 #define p_clear(p, count) ((void)memset((p), 0, sizeof(*(p)) * (count)))
85 #define p_realloc(pp, count) xrealloc((void*)(pp), sizeof(**(pp)) * (count))
86 #define p_dup(p, count) xmemdup((p), sizeof(*(p)) * (count))
87 #define p_grow(pp, goalnb, allocnb) \
89 if ((goalnb) > *(allocnb)) { \
90 if (p_alloc_nr(*(allocnb)) < (goalnb)) { \
91 *(allocnb) = (goalnb); \
93 *(allocnb) = p_alloc_nr(*(allocnb)); \
95 p_realloc(pp, *(allocnb)); \
102 #define p_delete(mem_pp) \
104 typeof(**(mem_pp)) **__ptr = (mem_pp); \
109 #define likely(expr) __builtin_expect(!!(expr), 1)
110 #define unlikely(expr) __builtin_expect((expr), 0)
114 #define p_delete(mem_p) \
116 void *__ptr = (mem_p); \
118 *(void **)__ptr = NULL; \
121 #define likely(expr) expr
122 #define unlikely(expr) expr
126 static inline void * __attribute__ ((malloc
)) xmalloc(ssize_t size
)
133 ptr
= calloc(1, size
);
142 xrealloc(void **ptr
, ssize_t newsize
)
148 *ptr
= realloc(*ptr
, newsize
);
154 /** Duplicate a memory zone.
155 * \param src The source.
156 * \param size The source size.
157 * \return The memory address of the copy.
159 static inline void *xmemdup(const void *src
, ssize_t size
)
161 return memcpy(xmalloc(size
), src
, size
);
164 /** \brief \c NULL resistant strlen.
166 * Unlike it's libc sibling, a_strlen returns a ssize_t, and supports its
167 * argument being NULL.
169 * \param[in] s the string.
170 * \return the string length (or 0 if \c s is \c NULL).
172 static inline ssize_t
a_strlen(const char *s
)
174 return s
? strlen(s
) : 0;
177 /** \brief \c NULL resistant strnlen.
179 * Unlike it's GNU libc sibling, a_strnlen returns a ssize_t, and supports
180 * its argument being NULL.
182 * The a_strnlen() function returns the number of characters in the string
183 * pointed to by \c s, not including the terminating \c \\0 character, but at
184 * most \c n. In doing this, a_strnlen() looks only at the first \c n
185 * characters at \c s and never beyond \c s+n.
187 * \param[in] s the string.
188 * \param[in] n the maximum length to return.
189 * \return \c a_strlen(s) if less than \c n, else \c n.
191 static inline ssize_t
a_strnlen(const char *s
, ssize_t n
)
195 const char *p
= memchr(s
, '\0', n
);
196 return p
? p
- s
: n
;
201 /** \brief \c NULL resistant strdup.
203 * The a_strdup() function returns a pointer to a new string, which is a
204 * duplicate of \c s. Memory should be freed using p_delete().
206 * \warning when s is \c "", it returns NULL !
208 * \param[in] s the string to duplicate.
209 * \return a pointer to the duplicated string.
212 char *a_strdup(const char *s
)
214 ssize_t len
= a_strlen(s
);
215 return len
? p_dup(s
, len
+ 1) : NULL
;
218 /** \brief safe limited strdup.
220 * Copies at most min(<tt>n-1</tt>, \c l) characters from \c src into a newly
221 * allocated buffer, always adding a final \c \\0, and returns that buffer.
223 * \warning when s is \c "" or l is 0, it returns NULL !
225 * \param[in] s source string.
226 * \param[in] l maximum number of chars to copy.
227 * \return a newly allocated buffer containing the first \c l chars of \c src.
230 char * a_strndup(const char *s
, ssize_t l
)
232 ssize_t len
= MIN(a_strlen(s
), l
);
235 char *p
= p_dup(s
, len
+ 1);
242 /** \brief \c NULL resistant strcmp.
243 * \param[in] a the first string.
244 * \param[in] b the second string.
245 * \return <tt>strcmp(a, b)</tt>, and treats \c NULL strings like \c ""
248 static inline int a_strcmp(const char *a
, const char *b
)
250 return strcmp(NONULL(a
), NONULL(b
));
253 /** \brief \c NULL resistant strcasecmp.
254 * \param[in] a the first string.
255 * \param[in] b the second string.
256 * \return <tt>strcasecmp(a, b)</tt>, and treats \c NULL strings like \c ""
259 static inline int a_strcasecmp(const char *a
, const char *b
)
261 return strcasecmp(NONULL(a
), NONULL(b
));
264 /** \brief \c NULL resistant strncmp.
265 * \param[in] a the first string.
266 * \param[in] b the second string.
267 * \param[in] n the number of maximum chars to compare.
268 * \return <tt>strncmp(a, b, n)</tt>, and treats \c NULL strings like \c ""
271 static inline int a_strncmp(const char *a
, const char *b
, ssize_t n
)
273 return strncmp(NONULL(a
), NONULL(b
), n
);
276 ssize_t
a_strncpy(char *dst
, ssize_t n
, const char *src
, ssize_t l
) __attribute__((nonnull(1)));
277 ssize_t
a_strcpy(char *dst
, ssize_t n
, const char *src
) __attribute__((nonnull(1)));
279 /** \brief safe strcat.
281 * The a_strcat() function appends the string \c src at the end of the buffer
282 * \c dst if space is available.
284 * \param[in] dst destination buffer.
285 * \param[in] n size of the buffer, Negative sizes are allowed.
286 * \param[in] src the string to append.
287 * \return <tt>a_strlen(dst) + a_strlen(src)</tt>
289 static inline ssize_t
a_strcat(char *dst
, ssize_t n
, const char *src
)
291 ssize_t dlen
= a_strnlen(dst
, n
- 1);
292 return dlen
+ a_strcpy(dst
+ dlen
, n
- dlen
, src
);
295 /** \brief safe strncat.
297 * The a_strncat() function appends at most \c n chars from the string \c src
298 * at the end of the buffer \c dst if space is available.
300 * \param[in] dst destination buffer.
301 * \param[in] n size of the buffer, Negative sizes are allowed.
302 * \param[in] src the string to append.
303 * \param[in] l maximum number of chars of src to consider.
304 * \return the smallest value between <tt>a_strlen(dst) + a_strlen(src)</tt>
305 * and <tt>a_strlen(dst) + l</tt>
307 static inline ssize_t
308 a_strncat(char *dst
, ssize_t n
, const char *src
, ssize_t l
)
310 ssize_t dlen
= a_strnlen(dst
, n
- 1);
311 return dlen
+ a_strncpy(dst
+ dlen
, n
- dlen
, src
, l
);
314 /** Compute a hash for a string.
315 * This is based on 'djb2' algorithm.
317 static inline unsigned long __attribute__ ((nonnull(1)))
318 a_strhash(const unsigned char *str
)
320 unsigned long hash
= 5381;
324 hash
= ((hash
<< 5) + hash
) + c
; /* hash * 33 + c */
329 #define fatal(string, ...) _fatal(__LINE__, \
331 string, ## __VA_ARGS__)
332 void _fatal(int, const char *, const char *, ...)
333 __attribute__ ((noreturn
)) __attribute__ ((format(printf
, 3, 4)));
335 #define warn(string, ...) _warn(__LINE__, \
337 string, ## __VA_ARGS__)
338 void _warn(int, const char *, const char *, ...)
339 __attribute__ ((format(printf
, 3, 4)));
341 position_t
position_fromstr(const char *, ssize_t
);
342 const char * position_tostr(position_t
);
343 orientation_t
orientation_fromstr(const char *, ssize_t
);
344 const char * orientation_tostr(orientation_t
);
345 void a_exec(const char *);
348 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80