1 /*
2 * libzvbi -- Miscellaneous cows and chickens
3 *
4 * Copyright (C) 2000-2003 I�aki Garc�a Etxebarria
5 * Copyright (C) 2002-2007 Michael H. Schimek
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library 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 GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301 USA.
21 */
22
23 /* $Id: misc.h,v 1.24 2013/07/02 02:32:31 mschimek Exp $ */
24
25 #ifndef MISC_H
26 #define MISC_H
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <stddef.h>
31 #include <stdarg.h>
32 #include <string.h>
33 #include <inttypes.h> /* (u)intXX_t */
34 #include <sys/types.h> /* (s)size_t */
35 #include <float.h> /* DBL_MAX */
36 #include <limits.h> /* (S)SIZE_MAX */
37 #include <assert.h>
38
39 #include "macros.h"
40 #include "version.h"
41
42 #define N_ELEMENTS(array) (sizeof (array) / sizeof (*(array)))
43
44 #ifdef __GNUC__
45
46 #if __GNUC__ < 3
47 /* Expect expression usually true/false, schedule accordingly. */
48 # define likely(expr) (expr)
49 # define unlikely(expr) (expr)
50 #else
51 # define likely(expr) __builtin_expect(expr, 1)
52 # define unlikely(expr) __builtin_expect(expr, 0)
53 #endif
54
55 #undef __i386__
56 #undef __i686__
57 /* FIXME #cpu is deprecated
58 #if defined(__i386__)
59 # define __i386__ 1
60 #endif
61 #if defined(__i686__)
62 # define __i686__ 1
63 #endif
64 */
65
66 /* &x == PARENT (&x.tm_min, struct tm, tm_min),
67 safer than &x == (struct tm *) &x.tm_min. A NULL _ptr is safe and
68 will return NULL, not -offsetof(_member). */
69 #undef PARENT
70 #define PARENT(_ptr, _type, _member) ({ \
71 __typeof__ (&((_type *) 0)->_member) _p = (_ptr); \
72 (_p != 0) ? (_type *)(((char *) _p) - offsetof (_type, \
73 _member)) : (_type *) 0; \
74 })
75
76 /* Like PARENT(), to be used with const _ptr. */
77 #define CONST_PARENT(_ptr, _type, _member) ({ \
78 __typeof__ (&((const _type *) 0)->_member) _p = (_ptr); \
79 (_p != 0) ? (const _type *)(((const char *) _p) - offsetof \
80 (const _type, _member)) : (const _type *) 0; \
81 })
82
83 /* Note the following macros have no side effects only when you
84 compile with GCC, so don't expect this. */
85
86 /* Absolute value of int, long or long long without a branch.
87 Note ABS (INT_MIN) -> INT_MAX + 1. */
88 #undef ABS
89 #define ABS(n) ({ \
90 register __typeof__ (n) _n = (n), _t = _n; \
91 if (-1 == (-1 >> 1)) { /* do we have signed shifts? */ \
92 _t >>= sizeof (_t) * 8 - 1; \
93 _n ^= _t; \
94 _n -= _t; \
95 } else if (_n < 0) { /* also warns if n is unsigned type */ \
96 _n = -_n; \
97 } \
98 /* return */ _n; \
99 })
100
101 #undef MIN
102 #define MIN(x, y) ({ \
103 __typeof__ (x) _x = (x); \
104 __typeof__ (y) _y = (y); \
105 (void)(&_x == &_y); /* warn if types do not match */ \
106 /* return */ (_x < _y) ? _x : _y; \
107 })
108
109 #undef MAX
110 #define MAX(x, y) ({ \
111 __typeof__ (x) _x = (x); \
112 __typeof__ (y) _y = (y); \
113 (void)(&_x == &_y); /* warn if types do not match */ \
114 /* return */ (_x > _y) ? _x : _y; \
115 })
116
117 /* Note other compilers may swap only int, long or pointer. */
118 #undef SWAP
119 #define SWAP(x, y) \
120 do { \
121 __typeof__ (x) _x = x; \
122 x = y; \
123 y = _x; \
124 } while (0)
125
126 #undef SATURATE
127 #ifdef __i686__ /* has conditional move */
128 #define SATURATE(n, min, max) ({ \
129 __typeof__ (n) _n = (n); \
130 __typeof__ (n) _min = (min); \
131 __typeof__ (n) _max = (max); \
132 (void)(&_n == &_min); /* warn if types do not match */ \
133 (void)(&_n == &_max); \
134 if (_n < _min) \
135 _n = _min; \
136 if (_n > _max) \
137 _n = _max; \
138 /* return */ _n; \
139 })
140 #else
141 #define SATURATE(n, min, max) ({ \
142 __typeof__ (n) _n = (n); \
143 __typeof__ (n) _min = (min); \
144 __typeof__ (n) _max = (max); \
145 (void)(&_n == &_min); /* warn if types do not match */ \
146 (void)(&_n == &_max); \
147 if (_n < _min) \
148 _n = _min; \
149 else if (_n > _max) \
150 _n = _max; \
151 /* return */ _n; \
152 })
153 #endif
154
155 #else /* !__GNUC__ */
156
157 #define likely(expr) (expr)
158 #define unlikely(expr) (expr)
159 #undef __i386__
160 #undef __i686__
161
162 static char *
PARENT_HELPER(char * p,unsigned int offset)163 PARENT_HELPER (char *p, unsigned int offset)
164 { return (0 == p) ? ((char *) 0) : p - offset; }
165
166 static const char *
CONST_PARENT_HELPER(const char * p,unsigned int offset)167 CONST_PARENT_HELPER (const char *p, unsigned int offset)
168 { return (0 == p) ? ((char *) 0) : p - offset; }
169
170 #define PARENT(_ptr, _type, _member) \
171 ((0 == offsetof (_type, _member)) ? (_type *)(_ptr) \
172 : (_type *) PARENT_HELPER ((char *)(_ptr), offsetof (_type, _member)))
173 #define CONST_PARENT(_ptr, _type, _member) \
174 ((0 == offsetof (const _type, _member)) ? (const _type *)(_ptr) \
175 : (const _type *) CONST_PARENT_HELPER ((const char *)(_ptr), \
176 offsetof (const _type, _member)))
177
178 #undef ABS
179 #define ABS(n) (((n) < 0) ? -(n) : (n))
180
181 #undef MIN
182 #define MIN(x, y) (((x) < (y)) ? (x) : (y))
183
184 #undef MAX
185 #define MAX(x, y) (((x) > (y)) ? (x) : (y))
186
187 #undef SWAP
188 #define SWAP(x, y) \
189 do { \
190 long _x = x; \
191 x = y; \
192 y = _x; \
193 } while (0)
194
195 #undef SATURATE
196 #define SATURATE(n, min, max) MIN (MAX (min, n), max)
197
198 #endif /* !__GNUC__ */
199
200 /* 32 bit constant byte reverse, e.g. 0xAABBCCDD -> 0xDDCCBBAA. */
201 #define SWAB32(m) \
202 (+ (((m) & 0xFF000000) >> 24) \
203 + (((m) & 0xFF0000) >> 8) \
204 + (((m) & 0xFF00) << 8) \
205 + (((m) & 0xFF) << 24))
206
207 #ifdef HAVE_BUILTIN_POPCOUNT
208 # define popcnt(x) __builtin_popcount ((uint32_t)(x))
209 #else
210 # define popcnt(x) _vbi_popcnt (x)
211 #endif
212
213 extern unsigned int
214 _vbi_popcnt (uint32_t x);
215
216 /* NB GCC inlines and optimizes these functions when size is const. */
217 #define SET(var) memset (&(var), ~0, sizeof (var))
218
219 #define CLEAR(var) memset (&(var), 0, sizeof (var))
220
221 /* Useful to copy arrays, otherwise use assignment. */
222 #define COPY(d, s) \
223 (assert (sizeof (d) == sizeof (s)), memcpy (d, s, sizeof (d)))
224
225 /* Copy string const into char array. */
226 #define STRACPY(array, s) \
227 do { \
228 /* Complain if s is no string const or won't fit. */ \
229 const char t_[sizeof (array) - 1] _vbi_unused = s; \
230 \
231 memcpy (array, s, sizeof (s)); \
232 } while (0)
233
234 /* Copy bits through mask. */
235 #define COPY_SET_MASK(dest, from, mask) \
236 (dest ^= (from) ^ (dest & (mask)))
237
238 /* Set bits if cond is TRUE, clear if FALSE. */
239 #define COPY_SET_COND(dest, bits, cond) \
240 ((cond) ? (dest |= (bits)) : (dest &= ~(bits)))
241
242 /* Set and clear bits. */
243 #define COPY_SET_CLEAR(dest, set, clear) \
244 (dest = (dest & ~(clear)) | (set))
245
246 /* For applications, debugging and fault injection during unit tests. */
247
248 #if 2 == VBI_VERSION_MINOR
249 # define vbi_malloc malloc
250 # define vbi_realloc realloc
251 # define vbi_strdup strdup
252 # define vbi_free free
253 #else
254
255 extern void *
256 (* vbi_malloc) (size_t);
257 extern void *
258 (* vbi_realloc) (void *,
259 size_t)
260 _vbi_nonnull ((1));
261 extern char *
262 (* vbi_strdup) (const char *)
263 _vbi_nonnull ((1));
264 extern void
265 (* vbi_free) (void *);
266
267 #endif
268
269 #define vbi_cache_malloc vbi_malloc
270 #define vbi_cache_free vbi_free
271
272 /* Helper functions. */
273
274 _vbi_inline int
_vbi_to_ascii(int c)275 _vbi_to_ascii (int c)
276 {
277 if (c < 0)
278 return '?';
279
280 c &= 0x7F;
281
282 if (c < 0x20 || c >= 0x7F)
283 return '.';
284
285 return c;
286 }
287
288 typedef struct {
289 const char * key;
290 int value;
291 } _vbi_key_value_pair;
292
293 extern vbi_bool
294 _vbi_keyword_lookup (int * value,
295 const char ** inout_s,
296 const _vbi_key_value_pair * table,
297 unsigned int n_pairs)
298 _vbi_nonnull ((1, 2, 3));
299
300 extern void
301 _vbi_shrink_vector_capacity (void ** vector,
302 size_t * capacity,
303 size_t min_capacity,
304 size_t element_size)
305 _vbi_nonnull ((1, 2));
306 extern vbi_bool
307 _vbi_grow_vector_capacity (void ** vector,
308 size_t * capacity,
309 size_t min_capacity,
310 size_t element_size)
311 _vbi_nonnull ((1, 2));
312
313 /* Logging stuff. */
314
315 extern _vbi_log_hook _vbi_global_log;
316
317 extern void
318 _vbi_log_vprintf (vbi_log_fn * log_fn,
319 void * user_data,
320 vbi_log_mask level,
321 const char * source_file,
322 const char * context,
323 const char * templ,
324 va_list ap)
325 _vbi_nonnull ((1, 4, 5, 6));
326 extern void
327 _vbi_log_printf (vbi_log_fn * log_fn,
328 void * user_data,
329 vbi_log_mask level,
330 const char * source_file,
331 const char * context,
332 const char * templ,
333 ...)
334 _vbi_nonnull ((1, 4, 5, 6)) _vbi_format ((printf, 6, 7));
335
336 #define _vbi_log(hook, level, templ, args...) \
337 do { \
338 _vbi_log_hook *_h = hook; \
339 \
340 if ((NULL != _h && 0 != (_h->mask & level)) \
341 || (_h = &_vbi_global_log, 0 != (_h->mask & level))) \
342 _vbi_log_printf (_h->fn, _h->user_data, \
343 level, __FILE__, __FUNCTION__, \
344 templ , ##args); \
345 } while (0)
346
347 #define _vbi_vlog(hook, level, templ, ap) \
348 do { \
349 _vbi_log_hook *_h = hook; \
350 \
351 if ((NULL != _h && 0 != (_h->mask & level)) \
352 || (_h = &_vbi_global_log, 0 != (_h->mask & level))) \
353 _vbi_log_vprintf (_h->fn, _h->user_data, \
354 level, __FILE__, __FUNCTION__, \
355 templ, ap); \
356 } while (0)
357
358 #define error(hook, templ, args...) \
359 _vbi_log (hook, VBI_LOG_ERROR, templ , ##args)
360 #define warning(hook, templ, args...) \
361 _vbi_log (hook, VBI_LOG_ERROR, templ , ##args)
362 #define notice(hook, templ, args...) \
363 _vbi_log (hook, VBI_LOG_NOTICE, templ , ##args)
364 #define info(hook, templ, args...) \
365 _vbi_log (hook, VBI_LOG_INFO, templ , ##args)
366 #define debug1(hook, templ, args...) \
367 _vbi_log (hook, VBI_LOG_DEBUG, templ , ##args)
368 #define debug2(hook, templ, args...) \
369 _vbi_log (hook, VBI_LOG_DEBUG2, templ , ##args)
370 #define debug3(hook, templ, args...) \
371 _vbi_log (hook, VBI_LOG_DEBUG3, templ , ##args)
372
373 /* Portability stuff. */
374
375 /* These should be defined in inttypes.h. */
376 #ifndef PRId64
377 # define PRId64 "lld"
378 #endif
379 #ifndef PRIu64
380 # define PRIu64 "llu"
381 #endif
382 #ifndef PRIx64
383 # define PRIx64 "llx"
384 #endif
385
386 /* Should be defined in C99 limits.h? */
387 #ifndef SIZE_MAX
388 # define SIZE_MAX ((size_t) -1)
389 #endif
390
391 #ifndef TIME_MIN
392 # define TIME_MIN (_vbi_time_min ())
393 _vbi_inline time_t
_vbi_time_min(void)394 _vbi_time_min (void)
395 {
396 const time_t t = (time_t) -1.25;
397
398 if (t < -1) {
399 return (time_t)((sizeof (time_t) > 4) ? DBL_MIN : FLT_MIN);
400 } else if (t < 0) {
401 return ((uint64_t) 1) << (sizeof (time_t) * 8 - 1);
402 } else {
403 return 0;
404 }
405 }
406 #endif
407
408 #ifndef TIME_MAX
409 # define TIME_MAX (_vbi_time_max ())
410 _vbi_inline time_t
_vbi_time_max(void)411 _vbi_time_max (void)
412 {
413 const time_t t = (time_t) -1.25;
414
415 if (t < -1) {
416 return (time_t)((sizeof (time_t) > 4) ? DBL_MAX : FLT_MAX);
417 } else if (t < 0) {
418 /* Most likely signed 32 or 64 bit. */
419 return (((uint64_t) 1) << (sizeof (time_t) * 8 - 1)) - 1;
420 } else {
421 return -1;
422 }
423 }
424 #endif
425
426 /* __va_copy is a GNU extension. */
427 #ifndef __va_copy
428 # define __va_copy(ap1, ap2) do { ap1 = ap2; } while (0)
429 #endif
430
431 /* Use this instead of strncpy(). strlcpy() is a BSD extension. */
432 #ifndef HAVE_STRLCPY
433 # define strlcpy _vbi_strlcpy
434 #endif
435 #undef strncpy
436 #define strncpy use_strlcpy_instead
437
438 extern size_t
439 _vbi_strlcpy (char * dst,
440 const char * src,
441 size_t size)
442 _vbi_nonnull ((1, 2));
443
444 /* strndup() is a BSD/GNU extension. */
445 #ifndef HAVE_STRNDUP
446 # define strndup _vbi_strndup
447 #endif
448
449 extern char *
450 _vbi_strndup (const char * s,
451 size_t len)
452 _vbi_nonnull ((1));
453
454 /* vasprintf() is a GNU extension. */
455 #ifndef HAVE_VASPRINTF
456 # define vasprintf _vbi_vasprintf
457 #endif
458
459 extern int
460 _vbi_vasprintf (char ** dstp,
461 const char * templ,
462 va_list ap)
463 _vbi_nonnull ((1, 2));
464
465 /* asprintf() is a GNU extension. */
466 #ifndef HAVE_ASPRINTF
467 # define asprintf _vbi_asprintf
468 #endif
469
470 extern int
471 _vbi_asprintf (char ** dstp,
472 const char * templ,
473 ...)
474 _vbi_nonnull ((1, 2)) _vbi_format ((printf, 2, 3));
475
476 #undef sprintf
477 #define sprintf use_snprintf_or_asprintf_instead
478
479 #endif /* MISC_H */
480
481 /*
482 Local variables:
483 c-set-style: K&R
484 c-basic-offset: 8
485 End:
486 */
487