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 #include <glib.h>
39 #include <gst/gst.h>
40
41 #include "macros.h"
42
43 #define N_ELEMENTS(array) (sizeof (array) / sizeof (*(array)))
44
45 #ifdef __GNUC__
46
47 #if __GNUC__ < 3
48 /* Expect expression usually true/false, schedule accordingly. */
49 # define likely(expr) (expr)
50 # define unlikely(expr) (expr)
51 #else
52 # define likely(expr) __builtin_expect(expr, 1)
53 # define unlikely(expr) __builtin_expect(expr, 0)
54 #endif
55
56 #undef __i386__
57 #undef __i686__
58 /* FIXME #cpu is deprecated
59 #if #cpu (i386)
60 # define __i386__ 1
61 #endif
62 #if #cpu (i686)
63 # define __i686__ 1
64 #endif
65 */
66
67 /* &x == PARENT (&x.tm_min, struct tm, tm_min),
68 safer than &x == (struct tm *) &x.tm_min. A NULL _ptr is safe and
69 will return NULL, not -offsetof(_member). */
70 #undef PARENT
71 #define PARENT(_ptr, _type, _member) ({ \
72 __typeof__ (&((_type *) 0)->_member) _p = (_ptr); \
73 (_p != 0) ? (_type *)(((char *) _p) - offsetof (_type, \
74 _member)) : (_type *) 0; \
75 })
76
77 /* Like PARENT(), to be used with const _ptr. */
78 #define CONST_PARENT(_ptr, _type, _member) ({ \
79 __typeof__ (&((const _type *) 0)->_member) _p = (_ptr); \
80 (_p != 0) ? (const _type *)(((const char *) _p) - offsetof \
81 (const _type, _member)) : (const _type *) 0; \
82 })
83
84 /* Note the following macros have no side effects only when you
85 compile with GCC, so don't expect this. */
86
87 /* Absolute value of int, long or long long without a branch.
88 Note ABS (INT_MIN) -> INT_MAX + 1. */
89 #undef ABS
90 #define ABS(n) ({ \
91 register __typeof__ (n) _n = (n), _t = _n; \
92 if (-1 == (-1 >> 1)) { /* do we have signed shifts? */ \
93 _t >>= sizeof (_t) * 8 - 1; \
94 _n ^= _t; \
95 _n -= _t; \
96 } else if (_n < 0) { /* also warns if n is unsigned type */ \
97 _n = -_n; \
98 } \
99 /* return */ _n; \
100 })
101
102 #undef MIN
103 #define MIN(x, y) ({ \
104 __typeof__ (x) _x = (x); \
105 __typeof__ (y) _y = (y); \
106 (void)(&_x == &_y); /* warn if types do not match */ \
107 /* return */ (_x < _y) ? _x : _y; \
108 })
109
110 #undef MAX
111 #define MAX(x, y) ({ \
112 __typeof__ (x) _x = (x); \
113 __typeof__ (y) _y = (y); \
114 (void)(&_x == &_y); /* warn if types do not match */ \
115 /* return */ (_x > _y) ? _x : _y; \
116 })
117
118 /* Note other compilers may swap only int, long or pointer. */
119 #undef SWAP
120 #define SWAP(x, y) \
121 do { \
122 __typeof__ (x) _x = x; \
123 x = y; \
124 y = _x; \
125 } while (0)
126
127 #undef SATURATE
128 #ifdef __i686__ /* has conditional move */
129 #define SATURATE(n, min, max) ({ \
130 __typeof__ (n) _n = (n); \
131 __typeof__ (n) _min = (min); \
132 __typeof__ (n) _max = (max); \
133 (void)(&_n == &_min); /* warn if types do not match */ \
134 (void)(&_n == &_max); \
135 if (_n < _min) \
136 _n = _min; \
137 if (_n > _max) \
138 _n = _max; \
139 /* return */ _n; \
140 })
141 #else
142 #define SATURATE(n, min, max) ({ \
143 __typeof__ (n) _n = (n); \
144 __typeof__ (n) _min = (min); \
145 __typeof__ (n) _max = (max); \
146 (void)(&_n == &_min); /* warn if types do not match */ \
147 (void)(&_n == &_max); \
148 if (_n < _min) \
149 _n = _min; \
150 else if (_n > _max) \
151 _n = _max; \
152 /* return */ _n; \
153 })
154 #endif
155
156 #else /* !__GNUC__ */
157
158 #define likely(expr) (expr)
159 #define unlikely(expr) (expr)
160 #undef __i386__
161 #undef __i686__
162
163 static char *
PARENT_HELPER(char * p,unsigned int offset)164 PARENT_HELPER (char *p, unsigned int offset)
165 { return (0 == p) ? ((char *) 0) : p - offset; }
166
167 static const char *
CONST_PARENT_HELPER(const char * p,unsigned int offset)168 CONST_PARENT_HELPER (const char *p, unsigned int offset)
169 { return (0 == p) ? ((char *) 0) : p - offset; }
170
171 #define PARENT(_ptr, _type, _member) \
172 ((0 == offsetof (_type, _member)) ? (_type *)(_ptr) \
173 : (_type *) PARENT_HELPER ((char *)(_ptr), offsetof (_type, _member)))
174 #define CONST_PARENT(_ptr, _type, _member) \
175 ((0 == offsetof (const _type, _member)) ? (const _type *)(_ptr) \
176 : (const _type *) CONST_PARENT_HELPER ((const char *)(_ptr), \
177 offsetof (const _type, _member)))
178
179 #undef ABS
180 #define ABS(n) (((n) < 0) ? -(n) : (n))
181
182 #undef MIN
183 #define MIN(x, y) (((x) < (y)) ? (x) : (y))
184
185 #undef MAX
186 #define MAX(x, y) (((x) > (y)) ? (x) : (y))
187
188 #undef SWAP
189 #define SWAP(x, y) \
190 do { \
191 long _x = x; \
192 x = y; \
193 y = _x; \
194 } while (0)
195
196 #undef SATURATE
197 #define SATURATE(n, min, max) MIN (MAX (min, n), max)
198
199 #endif /* !__GNUC__ */
200
201 /* 32 bit constant byte reverse, e.g. 0xAABBCCDD -> 0xDDCCBBAA. */
202 #define SWAB32(m) \
203 (+ (((m) & 0xFF000000) >> 24) \
204 + (((m) & 0xFF0000) >> 8) \
205 + (((m) & 0xFF00) << 8) \
206 + (((m) & 0xFF) << 24))
207
208 #ifdef HAVE_BUILTIN_POPCOUNT
209 # define popcnt(x) __builtin_popcount ((uint32_t)(x))
210 #else
211 # define popcnt(x) _vbi_popcnt (x)
212 #endif
213
214 extern unsigned int
215 _vbi_popcnt (uint32_t x);
216
217 /* NB GCC inlines and optimizes these functions when size is const. */
218 #define SET(var) memset (&(var), ~0, sizeof (var))
219
220 #define CLEAR(var) memset (&(var), 0, sizeof (var))
221
222 /* Useful to copy arrays, otherwise use assignment. */
223 #define COPY(d, s) \
224 (assert (sizeof (d) == sizeof (s)), memcpy (d, s, sizeof (d)))
225
226 /* Copy string const into char array. */
227 #define STRACPY(array, s) \
228 do { \
229 /* Complain if s is no string const or won't fit. */ \
230 const char t_[sizeof (array) - 1] _vbi_unused = s; \
231 \
232 memcpy (array, s, sizeof (s)); \
233 } while (0)
234
235 /* Copy bits through mask. */
236 #define COPY_SET_MASK(dest, from, mask) \
237 (dest ^= (from) ^ (dest & (mask)))
238
239 /* Set bits if cond is TRUE, clear if FALSE. */
240 #define COPY_SET_COND(dest, bits, cond) \
241 ((cond) ? (dest |= (bits)) : (dest &= ~(bits)))
242
243 /* Set and clear bits. */
244 #define COPY_SET_CLEAR(dest, set, clear) \
245 (dest = (dest & ~(clear)) | (set))
246
247 /* For applications, debugging and fault injection during unit tests. */
248
249 #define vbi_malloc malloc
250 #define vbi_realloc realloc
251 #define vbi_strdup strdup
252 #define vbi_free free
253
254 #define vbi_cache_malloc vbi_malloc
255 #define vbi_cache_free vbi_free
256
257 /* Helper functions. */
258
259 _vbi_inline int
_vbi_to_ascii(int c)260 _vbi_to_ascii (int c)
261 {
262 if (c < 0)
263 return '?';
264
265 c &= 0x7F;
266
267 if (c < 0x20 || c >= 0x7F)
268 return '.';
269
270 return c;
271 }
272
273 typedef struct {
274 const char * key;
275 int value;
276 } _vbi_key_value_pair;
277
278 extern vbi_bool
279 _vbi_keyword_lookup (int * value,
280 const char ** inout_s,
281 const _vbi_key_value_pair * table,
282 unsigned int n_pairs)
283 _vbi_nonnull ((1, 2, 3));
284
285 extern void
286 _vbi_shrink_vector_capacity (void ** vector,
287 size_t * capacity,
288 size_t min_capacity,
289 size_t element_size)
290 _vbi_nonnull ((1, 2));
291 extern vbi_bool
292 _vbi_grow_vector_capacity (void ** vector,
293 size_t * capacity,
294 size_t min_capacity,
295 size_t element_size)
296 _vbi_nonnull ((1, 2));
297
298 GST_DEBUG_CATEGORY_EXTERN (libzvbi_debug);
299
300 #ifndef GST_DISABLE_GST_DEBUG
301 /* Logging stuff. */
302 #ifdef G_HAVE_ISO_VARARGS
303 #define VBI_CAT_LEVEL_LOG(level,object,...) G_STMT_START{ \
304 if (G_UNLIKELY ((level) <= GST_LEVEL_MAX && (level) <= _gst_debug_min)) { \
305 gst_debug_log (libzvbi_debug, (level), __FILE__, GST_FUNCTION, __LINE__, \
306 (GObject *) (object), __VA_ARGS__); \
307 } \
308 }G_STMT_END
309 #else /* G_HAVE_GNUC_VARARGS */
310 #ifdef G_HAVE_GNUC_VARARGS
311 #define VBI_CAT_LEVEL_LOG(level,object,args...) G_STMT_START{ \
312 if (G_UNLIKELY ((level) <= GST_LEVEL_MAX && (level) <= _gst_debug_min)) { \
313 gst_debug_log (libzvbi_debug, (level), __FILE__, GST_FUNCTION, __LINE__, \
314 (GObject *) (object), ##args ); \
315 } \
316 }G_STMT_END
317 #else /* no variadic macros, use inline */
318 static inline void
VBI_CAT_LEVEL_LOG_valist(GstDebugCategory * cat,GstDebugLevel level,gpointer object,const char * format,va_list varargs)319 VBI_CAT_LEVEL_LOG_valist (GstDebugCategory * cat,
320 GstDebugLevel level, gpointer object, const char *format, va_list varargs)
321 {
322 if (G_UNLIKELY ((level) <= GST_LEVEL_MAX && (level) <= _gst_debug_min)) {
323 gst_debug_log_valist (cat, level, "", "", 0, (GObject *) object, format,
324 varargs);
325 }
326 }
327
328 static inline void
VBI_CAT_LEVEL_LOG(GstDebugLevel level,gpointer object,const char * format,...)329 VBI_CAT_LEVEL_LOG (GstDebugLevel level,
330 gpointer object, const char *format, ...)
331 {
332 va_list varargs;
333
334 va_start (varargs, format);
335 GST_CAT_LEVEL_LOG_valist (libzvbi_debug, level, object, format, varargs);
336 va_end (varargs);
337 }
338 #endif
339 #endif /* G_HAVE_ISO_VARARGS */
340 #else
341 static inline void
VBI_CAT_LEVEL_LOG(GstDebugLevel level,gpointer object,const char * format,...)342 VBI_CAT_LEVEL_LOG (GstDebugLevel level,
343 gpointer object, const char *format, ...)
344 {
345 }
346 #endif /* GST_DISABLE_GST_DEBUG */
347
348 #ifdef G_HAVE_GNUC_VARARGS
349 #define error(hook, templ, args...) \
350 VBI_CAT_LEVEL_LOG (GST_LEVEL_ERROR, NULL, templ , ##args)
351 #define warning(hook, templ, args...) \
352 VBI_CAT_LEVEL_LOG (GST_LEVEL_WARNING, NULL, templ , ##args)
353 #define notice(hook, templ, args...) \
354 VBI_CAT_LEVEL_LOG (GST_LEVEL_INFO, NULL, templ , ##args)
355 #define info(hook, templ, args...) \
356 VBI_CAT_LEVEL_LOG (GST_LEVEL_INFO, NULL, templ , ##args)
357 #define debug1(hook, templ, args...) \
358 VBI_CAT_LEVEL_LOG (GST_LEVEL_DEBUG, NULL, templ , ##args)
359 #define debug2(hook, templ, args...) \
360 VBI_CAT_LEVEL_LOG (GST_LEVEL_LOG, NULL, templ , ##args)
361 #define debug3(hook, templ, args...) \
362 VBI_CAT_LEVEL_LOG (GST_LEVEL_TRACE, NULL, templ , ##args)
363 #elif defined(G_HAVE_ISO_VARARGS)
364 #define error(hook, templ, ...) \
365 VBI_CAT_LEVEL_LOG (GST_LEVEL_ERROR, NULL, templ, __VA_ARGS__)
366 #define warning(hook, templ, ...) \
367 VBI_CAT_LEVEL_LOG (GST_LEVEL_WARNING, NULL, templ, __VA_ARGS__)
368 #define notice(hook, templ, ...) \
369 VBI_CAT_LEVEL_LOG (GST_LEVEL_INFO, NULL, templ, __VA_ARGS__)
370 #define info(hook, templ, ...) \
371 VBI_CAT_LEVEL_LOG (GST_LEVEL_INFO, NULL, templ, __VA_ARGS__)
372 #define debug1(hook, templ, ...) \
373 VBI_CAT_LEVEL_LOG (GST_LEVEL_DEBUG, NULL, templ, __VA_ARGS__)
374 #define debug2(hook, templ, ...) \
375 VBI_CAT_LEVEL_LOG (GST_LEVEL_LOG, NULL, templ, __VA_ARGS__)
376 #define debug3(hook, templ, ...) \
377 VBI_CAT_LEVEL_LOG (GST_LEVEL_TRACE, NULL, templ, __VA_ARGS__)
378 #else
379 /* if someone needs this, they can implement the inline functions for it */
380 #error "variadic macros are required"
381 #endif
382
383
384 #if 0 /* Replaced logging with GStreamer logging system */
385 extern _vbi_log_hook _vbi_global_log;
386
387 extern void
388 _vbi_log_vprintf (vbi_log_fn * log_fn,
389 void * user_data,
390 vbi_log_mask level,
391 const char * source_file,
392 const char * context,
393 const char * templ,
394 va_list ap)
395 _vbi_nonnull ((1, 4, 5, 6));
396 extern void
397 _vbi_log_printf (vbi_log_fn * log_fn,
398 void * user_data,
399 vbi_log_mask level,
400 const char * source_file,
401 const char * context,
402 const char * templ,
403 ...)
404 _vbi_nonnull ((1, 4, 5, 6)) _vbi_format ((printf, 6, 7));
405
406 #define _vbi_log(hook, level, templ, args...) \
407 do { \
408 _vbi_log_hook *_h = hook; \
409 \
410 if ((NULL != _h && 0 != (_h->mask & level)) \
411 || (_h = &_vbi_global_log, 0 != (_h->mask & level))) \
412 _vbi_log_printf (_h->fn, _h->user_data, \
413 level, __FILE__, __FUNCTION__, \
414 templ , ##args); \
415 } while (0)
416
417 #define _vbi_vlog(hook, level, templ, ap) \
418 do { \
419 _vbi_log_hook *_h = hook; \
420 \
421 if ((NULL != _h && 0 != (_h->mask & level)) \
422 || (_h = &_vbi_global_log, 0 != (_h->mask & level))) \
423 _vbi_log_vprintf (_h->fn, _h->user_data, \
424 level, __FILE__, __FUNCTION__, \
425 templ, ap); \
426 } while (0)
427 #define error(hook, templ, args...) \
428 _vbi_log (hook, VBI_LOG_ERROR, templ , ##args)
429 #define warning(hook, templ, args...) \
430 _vbi_log (hook, VBI_LOG_ERROR, templ , ##args)
431 #define notice(hook, templ, args...) \
432 _vbi_log (hook, VBI_LOG_NOTICE, templ , ##args)
433 #define info(hook, templ, args...) \
434 _vbi_log (hook, VBI_LOG_INFO, templ , ##args)
435 #define debug1(hook, templ, args...) \
436 _vbi_log (hook, VBI_LOG_DEBUG, templ , ##args)
437 #define debug2(hook, templ, args...) \
438 _vbi_log (hook, VBI_LOG_DEBUG2, templ , ##args)
439 #define debug3(hook, templ, args...) \
440 _vbi_log (hook, VBI_LOG_DEBUG3, templ , ##args)
441 #endif
442
443 /* Portability stuff. */
444
445 /* These should be defined in inttypes.h. */
446 #ifndef PRId64
447 # define PRId64 "lld"
448 #endif
449 #ifndef PRIu64
450 # define PRIu64 "llu"
451 #endif
452 #ifndef PRIx64
453 # define PRIx64 "llx"
454 #endif
455
456 /* Should be defined in C99 limits.h? */
457 #ifndef SIZE_MAX
458 # define SIZE_MAX ((size_t) -1)
459 #endif
460
461 #ifndef TIME_MIN
462 # define TIME_MIN (_vbi_time_min ())
463 _vbi_inline time_t
_vbi_time_min(void)464 _vbi_time_min (void)
465 {
466 const time_t t = (time_t) -1.25;
467
468 if (t < -1) {
469 return (time_t)((sizeof (time_t) > 4) ? DBL_MIN : FLT_MIN);
470 } else if (t < 0) {
471 return ((uint64_t) 1) << (sizeof (time_t) * 8 - 1);
472 } else {
473 return 0;
474 }
475 }
476 #endif
477
478 #ifndef TIME_MAX
479 # define TIME_MAX (_vbi_time_max ())
480 _vbi_inline time_t
_vbi_time_max(void)481 _vbi_time_max (void)
482 {
483 const time_t t = (time_t) -1.25;
484
485 if (t < -1) {
486 return (time_t)((sizeof (time_t) > 4) ? DBL_MAX : FLT_MAX);
487 } else if (t < 0) {
488 /* Most likely signed 32 or 64 bit. */
489 return (((uint64_t) 1) << (sizeof (time_t) * 8 - 1)) - 1;
490 } else {
491 return -1;
492 }
493 }
494 #endif
495
496 /* __va_copy is a GNU extension. */
497 #ifndef __va_copy
498 # define __va_copy(ap1, ap2) do { ap1 = ap2; } while (0)
499 #endif
500
501 #if 0
502 /* Use this instead of strncpy(). strlcpy() is a BSD extension. */
503 #ifndef HAVE_STRLCPY
504 # define strlcpy _vbi_strlcpy
505 #endif
506 #undef strncpy
507 #define strncpy use_strlcpy_instead
508
509 extern size_t
510 _vbi_strlcpy (char * dst,
511 const char * src,
512 size_t size)
513 _vbi_nonnull ((1, 2));
514 #endif
515
516 /* /\* strndup() is a BSD/GNU extension. *\/ */
517 /* #ifndef HAVE_STRNDUP */
518 /* # define strndup _vbi_strndup */
519 /* #endif */
520
521 /* extern char * */
522 /* _vbi_strndup (const char * s, */
523 /* size_t len) */
524 /* _vbi_nonnull ((1)); */
525
526 /* vasprintf() is a GNU extension. */
527 #ifndef HAVE_VASPRINTF
528 # define vasprintf _vbi_vasprintf
529 #endif
530
531 extern int
532 _vbi_vasprintf (char ** dstp,
533 const char * templ,
534 va_list ap)
535 _vbi_nonnull ((1, 2));
536
537 /* asprintf() is a GNU extension. */
538 #ifndef HAVE_ASPRINTF
539 # define asprintf _vbi_asprintf
540 #endif
541
542 extern int
543 _vbi_asprintf (char ** dstp,
544 const char * templ,
545 ...)
546 _vbi_nonnull ((1, 2)) _vbi_format ((printf, 2, 3));
547
548 #undef sprintf
549 #define sprintf use_snprintf_or_asprintf_instead
550
551 #endif /* MISC_H */
552
553 /*
554 Local variables:
555 c-set-style: K&R
556 c-basic-offset: 8
557 End:
558 */
559