gstreamer/ext/closedcaption/misc.h
2018-05-28 15:55:57 +02:00

535 lines
14 KiB
C

/*
* libzvbi -- Miscellaneous cows and chickens
*
* Copyright (C) 2000-2003 Iñaki García Etxebarria
* Copyright (C) 2002-2007 Michael H. Schimek
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*/
/* $Id: misc.h,v 1.24 2013-07-02 02:32:31 mschimek Exp $ */
#ifndef MISC_H
#define MISC_H
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <inttypes.h> /* (u)intXX_t */
#include <sys/types.h> /* (s)size_t */
#include <float.h> /* DBL_MAX */
#include <limits.h> /* (S)SIZE_MAX */
#include <assert.h>
#include <glib.h>
#include <gst/gst.h>
#include "macros.h"
#define N_ELEMENTS(array) (sizeof (array) / sizeof (*(array)))
#ifdef __GNUC__
#if __GNUC__ < 3
/* Expect expression usually true/false, schedule accordingly. */
# define likely(expr) (expr)
# define unlikely(expr) (expr)
#else
# define likely(expr) __builtin_expect(expr, 1)
# define unlikely(expr) __builtin_expect(expr, 0)
#endif
#undef __i386__
#undef __i686__
/* FIXME #cpu is deprecated
#if #cpu (i386)
# define __i386__ 1
#endif
#if #cpu (i686)
# define __i686__ 1
#endif
*/
/* &x == PARENT (&x.tm_min, struct tm, tm_min),
safer than &x == (struct tm *) &x.tm_min. A NULL _ptr is safe and
will return NULL, not -offsetof(_member). */
#undef PARENT
#define PARENT(_ptr, _type, _member) ({ \
__typeof__ (&((_type *) 0)->_member) _p = (_ptr); \
(_p != 0) ? (_type *)(((char *) _p) - offsetof (_type, \
_member)) : (_type *) 0; \
})
/* Like PARENT(), to be used with const _ptr. */
#define CONST_PARENT(_ptr, _type, _member) ({ \
__typeof__ (&((const _type *) 0)->_member) _p = (_ptr); \
(_p != 0) ? (const _type *)(((const char *) _p) - offsetof \
(const _type, _member)) : (const _type *) 0; \
})
/* Note the following macros have no side effects only when you
compile with GCC, so don't expect this. */
/* Absolute value of int, long or long long without a branch.
Note ABS (INT_MIN) -> INT_MAX + 1. */
#undef ABS
#define ABS(n) ({ \
register __typeof__ (n) _n = (n), _t = _n; \
if (-1 == (-1 >> 1)) { /* do we have signed shifts? */ \
_t >>= sizeof (_t) * 8 - 1; \
_n ^= _t; \
_n -= _t; \
} else if (_n < 0) { /* also warns if n is unsigned type */ \
_n = -_n; \
} \
/* return */ _n; \
})
#undef MIN
#define MIN(x, y) ({ \
__typeof__ (x) _x = (x); \
__typeof__ (y) _y = (y); \
(void)(&_x == &_y); /* warn if types do not match */ \
/* return */ (_x < _y) ? _x : _y; \
})
#undef MAX
#define MAX(x, y) ({ \
__typeof__ (x) _x = (x); \
__typeof__ (y) _y = (y); \
(void)(&_x == &_y); /* warn if types do not match */ \
/* return */ (_x > _y) ? _x : _y; \
})
/* Note other compilers may swap only int, long or pointer. */
#undef SWAP
#define SWAP(x, y) \
do { \
__typeof__ (x) _x = x; \
x = y; \
y = _x; \
} while (0)
#undef SATURATE
#ifdef __i686__ /* has conditional move */
#define SATURATE(n, min, max) ({ \
__typeof__ (n) _n = (n); \
__typeof__ (n) _min = (min); \
__typeof__ (n) _max = (max); \
(void)(&_n == &_min); /* warn if types do not match */ \
(void)(&_n == &_max); \
if (_n < _min) \
_n = _min; \
if (_n > _max) \
_n = _max; \
/* return */ _n; \
})
#else
#define SATURATE(n, min, max) ({ \
__typeof__ (n) _n = (n); \
__typeof__ (n) _min = (min); \
__typeof__ (n) _max = (max); \
(void)(&_n == &_min); /* warn if types do not match */ \
(void)(&_n == &_max); \
if (_n < _min) \
_n = _min; \
else if (_n > _max) \
_n = _max; \
/* return */ _n; \
})
#endif
#else /* !__GNUC__ */
#define likely(expr) (expr)
#define unlikely(expr) (expr)
#undef __i386__
#undef __i686__
static char *
PARENT_HELPER (char *p, unsigned int offset)
{ return (0 == p) ? ((char *) 0) : p - offset; }
static const char *
CONST_PARENT_HELPER (const char *p, unsigned int offset)
{ return (0 == p) ? ((char *) 0) : p - offset; }
#define PARENT(_ptr, _type, _member) \
((0 == offsetof (_type, _member)) ? (_type *)(_ptr) \
: (_type *) PARENT_HELPER ((char *)(_ptr), offsetof (_type, _member)))
#define CONST_PARENT(_ptr, _type, _member) \
((0 == offsetof (const _type, _member)) ? (const _type *)(_ptr) \
: (const _type *) CONST_PARENT_HELPER ((const char *)(_ptr), \
offsetof (const _type, _member)))
#undef ABS
#define ABS(n) (((n) < 0) ? -(n) : (n))
#undef MIN
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#undef MAX
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#undef SWAP
#define SWAP(x, y) \
do { \
long _x = x; \
x = y; \
y = _x; \
} while (0)
#undef SATURATE
#define SATURATE(n, min, max) MIN (MAX (min, n), max)
#endif /* !__GNUC__ */
/* 32 bit constant byte reverse, e.g. 0xAABBCCDD -> 0xDDCCBBAA. */
#define SWAB32(m) \
(+ (((m) & 0xFF000000) >> 24) \
+ (((m) & 0xFF0000) >> 8) \
+ (((m) & 0xFF00) << 8) \
+ (((m) & 0xFF) << 24))
#ifdef HAVE_BUILTIN_POPCOUNT
# define popcnt(x) __builtin_popcount ((uint32_t)(x))
#else
# define popcnt(x) _vbi_popcnt (x)
#endif
extern unsigned int
_vbi_popcnt (uint32_t x);
/* NB GCC inlines and optimizes these functions when size is const. */
#define SET(var) memset (&(var), ~0, sizeof (var))
#define CLEAR(var) memset (&(var), 0, sizeof (var))
/* Useful to copy arrays, otherwise use assignment. */
#define COPY(d, s) \
(assert (sizeof (d) == sizeof (s)), memcpy (d, s, sizeof (d)))
/* Copy string const into char array. */
#define STRACPY(array, s) \
do { \
/* Complain if s is no string const or won't fit. */ \
const char t_[sizeof (array) - 1] _vbi_unused = s; \
\
memcpy (array, s, sizeof (s)); \
} while (0)
/* Copy bits through mask. */
#define COPY_SET_MASK(dest, from, mask) \
(dest ^= (from) ^ (dest & (mask)))
/* Set bits if cond is TRUE, clear if FALSE. */
#define COPY_SET_COND(dest, bits, cond) \
((cond) ? (dest |= (bits)) : (dest &= ~(bits)))
/* Set and clear bits. */
#define COPY_SET_CLEAR(dest, set, clear) \
(dest = (dest & ~(clear)) | (set))
/* For applications, debugging and fault injection during unit tests. */
#define vbi_malloc malloc
#define vbi_realloc realloc
#define vbi_strdup strdup
#define vbi_free free
#define vbi_cache_malloc vbi_malloc
#define vbi_cache_free vbi_free
/* Helper functions. */
_vbi_inline int
_vbi_to_ascii (int c)
{
if (c < 0)
return '?';
c &= 0x7F;
if (c < 0x20 || c >= 0x7F)
return '.';
return c;
}
typedef struct {
const char * key;
int value;
} _vbi_key_value_pair;
extern vbi_bool
_vbi_keyword_lookup (int * value,
const char ** inout_s,
const _vbi_key_value_pair * table,
unsigned int n_pairs)
_vbi_nonnull ((1, 2, 3));
extern void
_vbi_shrink_vector_capacity (void ** vector,
size_t * capacity,
size_t min_capacity,
size_t element_size)
_vbi_nonnull ((1, 2));
extern vbi_bool
_vbi_grow_vector_capacity (void ** vector,
size_t * capacity,
size_t min_capacity,
size_t element_size)
_vbi_nonnull ((1, 2));
GST_DEBUG_CATEGORY_EXTERN (libzvbi_debug);
#ifndef GST_DISABLE_GST_DEBUG
/* Logging stuff. */
#ifdef G_HAVE_ISO_VARARGS
#define VBI_CAT_LEVEL_LOG(level,object,...) G_STMT_START{ \
if (G_UNLIKELY ((level) <= GST_LEVEL_MAX && (level) <= _gst_debug_min)) { \
gst_debug_log (libzvbi_debug, (level), __FILE__, GST_FUNCTION, __LINE__, \
(GObject *) (object), __VA_ARGS__); \
} \
}G_STMT_END
#else /* G_HAVE_GNUC_VARARGS */
#ifdef G_HAVE_GNUC_VARARGS
#define VBI_CAT_LEVEL_LOG(level,object,args...) G_STMT_START{ \
if (G_UNLIKELY ((level) <= GST_LEVEL_MAX && (level) <= _gst_debug_min)) { \
gst_debug_log (libzvbi_debug, (level), __FILE__, GST_FUNCTION, __LINE__, \
(GObject *) (object), ##args ); \
} \
}G_STMT_END
#else /* no variadic macros, use inline */
static inline void
VBI_CAT_LEVEL_LOG_valist (GstDebugCategory * cat,
GstDebugLevel level, gpointer object, const char *format, va_list varargs)
{
if (G_UNLIKELY ((level) <= GST_LEVEL_MAX && (level) <= _gst_debug_min)) {
gst_debug_log_valist (cat, level, "", "", 0, (GObject *) object, format,
varargs);
}
}
static inline void
VBI_CAT_LEVEL_LOG (GstDebugLevel level,
gpointer object, const char *format, ...)
{
va_list varargs;
va_start (varargs, format);
GST_CAT_LEVEL_LOG_valist (libzvbi_debug, level, object, format, varargs);
va_end (varargs);
}
#endif
#endif /* G_HAVE_ISO_VARARGS */
#else
static inline void
VBI_CAT_LEVEL_LOG (GstDebugLevel level,
gpointer object, const char *format, ...)
{
}
#endif /* GST_DISABLE_GST_DEBUG */
#define error(hook, templ, args...) \
VBI_CAT_LEVEL_LOG (GST_LEVEL_ERROR, NULL, templ , ##args)
#define warning(hook, templ, args...) \
VBI_CAT_LEVEL_LOG (GST_LEVEL_WARNING, NULL, templ , ##args)
#define notice(hook, templ, args...) \
VBI_CAT_LEVEL_LOG (GST_LEVEL_INFO, NULL, templ , ##args)
#define info(hook, templ, args...) \
VBI_CAT_LEVEL_LOG (GST_LEVEL_INFO, NULL, templ , ##args)
#define debug1(hook, templ, args...) \
VBI_CAT_LEVEL_LOG (GST_LEVEL_DEBUG, NULL, templ , ##args)
#define debug2(hook, templ, args...) \
VBI_CAT_LEVEL_LOG (GST_LEVEL_LOG, NULL, templ , ##args)
#define debug3(hook, templ, args...) \
VBI_CAT_LEVEL_LOG (GST_LEVEL_TRACE, NULL, templ , ##args)
#if 0 /* Replaced logging with GStreamer logging system */
extern _vbi_log_hook _vbi_global_log;
extern void
_vbi_log_vprintf (vbi_log_fn * log_fn,
void * user_data,
vbi_log_mask level,
const char * source_file,
const char * context,
const char * templ,
va_list ap)
_vbi_nonnull ((1, 4, 5, 6));
extern void
_vbi_log_printf (vbi_log_fn * log_fn,
void * user_data,
vbi_log_mask level,
const char * source_file,
const char * context,
const char * templ,
...)
_vbi_nonnull ((1, 4, 5, 6)) _vbi_format ((printf, 6, 7));
#define _vbi_log(hook, level, templ, args...) \
do { \
_vbi_log_hook *_h = hook; \
\
if ((NULL != _h && 0 != (_h->mask & level)) \
|| (_h = &_vbi_global_log, 0 != (_h->mask & level))) \
_vbi_log_printf (_h->fn, _h->user_data, \
level, __FILE__, __FUNCTION__, \
templ , ##args); \
} while (0)
#define _vbi_vlog(hook, level, templ, ap) \
do { \
_vbi_log_hook *_h = hook; \
\
if ((NULL != _h && 0 != (_h->mask & level)) \
|| (_h = &_vbi_global_log, 0 != (_h->mask & level))) \
_vbi_log_vprintf (_h->fn, _h->user_data, \
level, __FILE__, __FUNCTION__, \
templ, ap); \
} while (0)
#define error(hook, templ, args...) \
_vbi_log (hook, VBI_LOG_ERROR, templ , ##args)
#define warning(hook, templ, args...) \
_vbi_log (hook, VBI_LOG_ERROR, templ , ##args)
#define notice(hook, templ, args...) \
_vbi_log (hook, VBI_LOG_NOTICE, templ , ##args)
#define info(hook, templ, args...) \
_vbi_log (hook, VBI_LOG_INFO, templ , ##args)
#define debug1(hook, templ, args...) \
_vbi_log (hook, VBI_LOG_DEBUG, templ , ##args)
#define debug2(hook, templ, args...) \
_vbi_log (hook, VBI_LOG_DEBUG2, templ , ##args)
#define debug3(hook, templ, args...) \
_vbi_log (hook, VBI_LOG_DEBUG3, templ , ##args)
#endif
/* Portability stuff. */
/* These should be defined in inttypes.h. */
#ifndef PRId64
# define PRId64 "lld"
#endif
#ifndef PRIu64
# define PRIu64 "llu"
#endif
#ifndef PRIx64
# define PRIx64 "llx"
#endif
/* Should be defined in C99 limits.h? */
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
#endif
#ifndef TIME_MIN
# define TIME_MIN (_vbi_time_min ())
_vbi_inline time_t
_vbi_time_min (void)
{
const time_t t = (time_t) -1.25;
if (t < -1) {
return (time_t)((sizeof (time_t) > 4) ? DBL_MIN : FLT_MIN);
} else if (t < 0) {
return ((uint64_t) 1) << (sizeof (time_t) * 8 - 1);
} else {
return 0;
}
}
#endif
#ifndef TIME_MAX
# define TIME_MAX (_vbi_time_max ())
_vbi_inline time_t
_vbi_time_max (void)
{
const time_t t = (time_t) -1.25;
if (t < -1) {
return (time_t)((sizeof (time_t) > 4) ? DBL_MAX : FLT_MAX);
} else if (t < 0) {
/* Most likely signed 32 or 64 bit. */
return (((uint64_t) 1) << (sizeof (time_t) * 8 - 1)) - 1;
} else {
return -1;
}
}
#endif
/* __va_copy is a GNU extension. */
#ifndef __va_copy
# define __va_copy(ap1, ap2) do { ap1 = ap2; } while (0)
#endif
/* Use this instead of strncpy(). strlcpy() is a BSD extension. */
#ifndef HAVE_STRLCPY
# define strlcpy _vbi_strlcpy
#endif
#undef strncpy
#define strncpy use_strlcpy_instead
extern size_t
_vbi_strlcpy (char * dst,
const char * src,
size_t size)
_vbi_nonnull ((1, 2));
/* /\* strndup() is a BSD/GNU extension. *\/ */
/* #ifndef HAVE_STRNDUP */
/* # define strndup _vbi_strndup */
/* #endif */
/* extern char * */
/* _vbi_strndup (const char * s, */
/* size_t len) */
/* _vbi_nonnull ((1)); */
/* vasprintf() is a GNU extension. */
#ifndef HAVE_VASPRINTF
# define vasprintf _vbi_vasprintf
#endif
extern int
_vbi_vasprintf (char ** dstp,
const char * templ,
va_list ap)
_vbi_nonnull ((1, 2));
/* asprintf() is a GNU extension. */
#ifndef HAVE_ASPRINTF
# define asprintf _vbi_asprintf
#endif
extern int
_vbi_asprintf (char ** dstp,
const char * templ,
...)
_vbi_nonnull ((1, 2)) _vbi_format ((printf, 2, 3));
#undef sprintf
#define sprintf use_snprintf_or_asprintf_instead
#endif /* MISC_H */
/*
Local variables:
c-set-style: K&R
c-basic-offset: 8
End:
*/