Blame shared/nm-utils/nm-macros-internal.h

Packit fabffb
/* NetworkManager -- Network link manager
Packit fabffb
 *
Packit fabffb
 * This library is free software; you can redistribute it and/or
Packit fabffb
 * modify it under the terms of the GNU Lesser General Public
Packit fabffb
 * License as published by the Free Software Foundation; either
Packit fabffb
 * version 2 of the License, or (at your option) any later version.
Packit fabffb
 *
Packit fabffb
 * This library is distributed in the hope that it will be useful,
Packit fabffb
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit fabffb
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit fabffb
 * Lesser General Public License for more details.
Packit fabffb
 *
Packit fabffb
 * You should have received a copy of the GNU Lesser General Public
Packit fabffb
 * License along with this library; if not, write to the
Packit fabffb
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Packit fabffb
 * Boston, MA 02110-1301 USA.
Packit fabffb
 *
Packit fabffb
 * (C) Copyright 2014 Red Hat, Inc.
Packit fabffb
 */
Packit fabffb
Packit fabffb
#ifndef __NM_MACROS_INTERNAL_H__
Packit fabffb
#define __NM_MACROS_INTERNAL_H__
Packit fabffb
Packit fabffb
#include <stdio.h>
Packit fabffb
#include <stdlib.h>
Packit fabffb
#include <errno.h>
Packit fabffb
Packit fabffb
#define _nm_packed           __attribute__ ((packed))
Packit fabffb
#define _nm_unused           __attribute__ ((unused))
Packit fabffb
#define _nm_pure             __attribute__ ((pure))
Packit fabffb
#define _nm_const            __attribute__ ((const))
Packit fabffb
#define _nm_printf(a,b)      __attribute__ ((__format__ (__printf__, a, b)))
Packit fabffb
#define _nm_align(s)         __attribute__ ((aligned (s)))
Packit fabffb
#define _nm_alignof(type)    __alignof (type)
Packit fabffb
#define _nm_alignas(type)    _nm_align (_nm_alignof (type))
Packit fabffb
Packit fabffb
#if __GNUC__ >= 7
Packit fabffb
#define _nm_fallthrough      __attribute__ ((fallthrough))
Packit fabffb
#else
Packit fabffb
#define _nm_fallthrough
Packit fabffb
#endif
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
#ifdef thread_local
Packit fabffb
#define _nm_thread_local thread_local
Packit fabffb
/*
Packit fabffb
 * Don't break on glibc < 2.16 that doesn't define __STDC_NO_THREADS__
Packit fabffb
 * see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53769
Packit fabffb
 */
Packit fabffb
#elif __STDC_VERSION__ >= 201112L && !(defined(__STDC_NO_THREADS__) || (defined(__GNU_LIBRARY__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 16))
Packit fabffb
#define _nm_thread_local _Thread_local
Packit fabffb
#else
Packit fabffb
#define _nm_thread_local __thread
Packit fabffb
#endif
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
#include "nm-glib.h"
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
#define nm_offsetofend(t,m) (G_STRUCT_OFFSET (t,m) + sizeof (((t *) NULL)->m))
Packit fabffb
Packit fabffb
#define nm_auto(fcn) __attribute__ ((cleanup(fcn)))
Packit fabffb
Packit fabffb
static inline int nm_close (int fd);
Packit fabffb
Packit fabffb
/**
Packit fabffb
 * nm_auto_free:
Packit fabffb
 *
Packit fabffb
 * Call free() on a variable location when it goes out of scope.
Packit fabffb
 */
Packit fabffb
#define nm_auto_free nm_auto(_nm_auto_free_impl)
Packit fabffb
GS_DEFINE_CLEANUP_FUNCTION(void*, _nm_auto_free_impl, free)
Packit fabffb
Packit fabffb
static inline void
Packit fabffb
nm_free_secret (char *secret)
Packit fabffb
{
Packit fabffb
	if (secret) {
Packit fabffb
		memset (secret, 0, strlen (secret));
Packit fabffb
		g_free (secret);
Packit fabffb
	}
Packit fabffb
}
Packit fabffb
Packit fabffb
static inline void
Packit fabffb
_nm_auto_free_secret_impl (char **v)
Packit fabffb
{
Packit fabffb
	nm_free_secret (*v);
Packit fabffb
}
Packit fabffb
Packit fabffb
/**
Packit fabffb
 * nm_auto_free_secret:
Packit fabffb
 *
Packit fabffb
 * Call g_free() on a variable location when it goes out of scope.
Packit fabffb
 * Also, previously, calls memset(loc, 0, strlen(loc)) to clear out
Packit fabffb
 * the secret.
Packit fabffb
 */
Packit fabffb
#define nm_auto_free_secret nm_auto(_nm_auto_free_secret_impl)
Packit fabffb
Packit fabffb
static inline void
Packit fabffb
_nm_auto_unset_gvalue_impl (GValue *v)
Packit fabffb
{
Packit fabffb
	g_value_unset (v);
Packit fabffb
}
Packit fabffb
#define nm_auto_unset_gvalue nm_auto(_nm_auto_unset_gvalue_impl)
Packit fabffb
Packit fabffb
static inline void
Packit fabffb
_nm_auto_unref_gtypeclass (gpointer v)
Packit fabffb
{
Packit fabffb
	if (v && *((gpointer *) v))
Packit fabffb
		g_type_class_unref (*((gpointer *) v));
Packit fabffb
}
Packit fabffb
#define nm_auto_unref_gtypeclass nm_auto(_nm_auto_unref_gtypeclass)
Packit fabffb
Packit fabffb
static inline void
Packit fabffb
_nm_auto_free_gstring_impl (GString **str)
Packit fabffb
{
Packit fabffb
	if (*str)
Packit fabffb
		g_string_free (*str, TRUE);
Packit fabffb
}
Packit fabffb
#define nm_auto_free_gstring nm_auto(_nm_auto_free_gstring_impl)
Packit fabffb
Packit fabffb
static inline void
Packit fabffb
_nm_auto_close_impl (int *pfd)
Packit fabffb
{
Packit fabffb
	if (*pfd >= 0) {
Packit fabffb
		int errsv = errno;
Packit fabffb
Packit fabffb
		(void) nm_close (*pfd);
Packit fabffb
		errno = errsv;
Packit fabffb
	}
Packit fabffb
}
Packit fabffb
#define nm_auto_close nm_auto(_nm_auto_close_impl)
Packit fabffb
Packit fabffb
static inline void
Packit fabffb
_nm_auto_fclose_impl (FILE **pfd)
Packit fabffb
{
Packit fabffb
	if (*pfd) {
Packit fabffb
		int errsv = errno;
Packit fabffb
Packit fabffb
		(void) fclose (*pfd);
Packit fabffb
		errno = errsv;
Packit fabffb
	}
Packit fabffb
}
Packit fabffb
#define nm_auto_fclose nm_auto(_nm_auto_fclose_impl)
Packit fabffb
Packit fabffb
static inline void
Packit fabffb
_nm_auto_protect_errno (int *p_saved_errno)
Packit fabffb
{
Packit fabffb
	errno = *p_saved_errno;
Packit fabffb
}
Packit fabffb
#define NM_AUTO_PROTECT_ERRNO(errsv_saved) nm_auto(_nm_auto_protect_errno) _nm_unused const int errsv_saved = (errno)
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
/* http://stackoverflow.com/a/11172679 */
Packit fabffb
#define  _NM_UTILS_MACRO_FIRST(...)                           __NM_UTILS_MACRO_FIRST_HELPER(__VA_ARGS__, throwaway)
Packit fabffb
#define __NM_UTILS_MACRO_FIRST_HELPER(first, ...)             first
Packit fabffb
Packit fabffb
#define  _NM_UTILS_MACRO_REST(...)                            __NM_UTILS_MACRO_REST_HELPER(__NM_UTILS_MACRO_REST_NUM(__VA_ARGS__), __VA_ARGS__)
Packit fabffb
#define __NM_UTILS_MACRO_REST_HELPER(qty, ...)                __NM_UTILS_MACRO_REST_HELPER2(qty, __VA_ARGS__)
Packit fabffb
#define __NM_UTILS_MACRO_REST_HELPER2(qty, ...)               __NM_UTILS_MACRO_REST_HELPER_##qty(__VA_ARGS__)
Packit fabffb
#define __NM_UTILS_MACRO_REST_HELPER_ONE(first)
Packit fabffb
#define __NM_UTILS_MACRO_REST_HELPER_TWOORMORE(first, ...)    , __VA_ARGS__
Packit fabffb
#define __NM_UTILS_MACRO_REST_NUM(...) \
Packit fabffb
    __NM_UTILS_MACRO_REST_SELECT_30TH(__VA_ARGS__, \
Packit fabffb
                TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\
Packit fabffb
                TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\
Packit fabffb
                TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\
Packit fabffb
                TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\
Packit fabffb
                TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\
Packit fabffb
                TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway)
Packit fabffb
#define __NM_UTILS_MACRO_REST_SELECT_30TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, ...) a30
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
/* http://stackoverflow.com/a/2124385/354393 */
Packit fabffb
Packit fabffb
#define NM_NARG(...) \
Packit fabffb
         _NM_NARG(__VA_ARGS__,_NM_NARG_RSEQ_N())
Packit fabffb
#define _NM_NARG(...) \
Packit fabffb
         _NM_NARG_ARG_N(__VA_ARGS__)
Packit fabffb
#define _NM_NARG_ARG_N( \
Packit fabffb
          _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
Packit fabffb
         _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
Packit fabffb
         _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
Packit fabffb
         _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
Packit fabffb
         _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
Packit fabffb
         _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
Packit fabffb
         _61,_62,_63,N,...) N
Packit fabffb
#define _NM_NARG_RSEQ_N() \
Packit fabffb
         63,62,61,60,                   \
Packit fabffb
         59,58,57,56,55,54,53,52,51,50, \
Packit fabffb
         49,48,47,46,45,44,43,42,41,40, \
Packit fabffb
         39,38,37,36,35,34,33,32,31,30, \
Packit fabffb
         29,28,27,26,25,24,23,22,21,20, \
Packit fabffb
         19,18,17,16,15,14,13,12,11,10, \
Packit fabffb
         9,8,7,6,5,4,3,2,1,0
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
#if defined (__GNUC__)
Packit fabffb
#define _NM_PRAGMA_WARNING_DO(warning)       G_STRINGIFY(GCC diagnostic ignored warning)
Packit fabffb
#elif defined (__clang__)
Packit fabffb
#define _NM_PRAGMA_WARNING_DO(warning)       G_STRINGIFY(clang diagnostic ignored warning)
Packit fabffb
#endif
Packit fabffb
Packit fabffb
/* you can only suppress a specific warning that the compiler
Packit fabffb
 * understands. Otherwise you will get another compiler warning
Packit fabffb
 * about invalid pragma option.
Packit fabffb
 * It's not that bad however, because gcc and clang often have the
Packit fabffb
 * same name for the same warning. */
Packit fabffb
Packit fabffb
#if defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
Packit fabffb
#define NM_PRAGMA_WARNING_DISABLE(warning) \
Packit fabffb
        _Pragma("GCC diagnostic push") \
Packit fabffb
        _Pragma(_NM_PRAGMA_WARNING_DO(warning))
Packit fabffb
#elif defined (__clang__)
Packit fabffb
#define NM_PRAGMA_WARNING_DISABLE(warning) \
Packit fabffb
        _Pragma("clang diagnostic push") \
Packit fabffb
        _Pragma(_NM_PRAGMA_WARNING_DO(warning))
Packit fabffb
#else
Packit fabffb
#define NM_PRAGMA_WARNING_DISABLE(warning)
Packit fabffb
#endif
Packit fabffb
Packit fabffb
#if defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
Packit fabffb
#define NM_PRAGMA_WARNING_REENABLE \
Packit fabffb
    _Pragma("GCC diagnostic pop")
Packit fabffb
#elif defined (__clang__)
Packit fabffb
#define NM_PRAGMA_WARNING_REENABLE \
Packit fabffb
    _Pragma("clang diagnostic pop")
Packit fabffb
#else
Packit fabffb
#define NM_PRAGMA_WARNING_REENABLE
Packit fabffb
#endif
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
/**
Packit fabffb
 * NM_G_ERROR_MSG:
Packit fabffb
 * @error: (allow-none): the #GError instance
Packit fabffb
 *
Packit fabffb
 * All functions must follow the convention that when they
Packit fabffb
 * return a failure, they must also set the GError to a valid
Packit fabffb
 * message. For external API however, we want to be extra
Packit fabffb
 * careful before accessing the error instance. Use NM_G_ERROR_MSG()
Packit fabffb
 * which is safe to use on NULL.
Packit fabffb
 *
Packit fabffb
 * Returns: the error message.
Packit fabffb
 **/
Packit fabffb
static inline const char *
Packit fabffb
NM_G_ERROR_MSG (GError *error)
Packit fabffb
{
Packit fabffb
	return error ? (error->message ? : "(null)") : "(no-error)"; \
Packit fabffb
}
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
/* macro to return strlen() of a compile time string. */
Packit fabffb
#define NM_STRLEN(str)     ( sizeof ("" str) - 1 )
Packit fabffb
Packit fabffb
/* returns the length of a NULL terminated array of pointers,
Packit fabffb
 * like g_strv_length() does. The difference is:
Packit fabffb
 *  - it operats on arrays of pointers (of any kind, requiring no cast).
Packit fabffb
 *  - it accepts NULL to return zero. */
Packit fabffb
#define NM_PTRARRAY_LEN(array) \
Packit fabffb
	({ \
Packit fabffb
		typeof (*(array)) *const _array = (array); \
Packit fabffb
		gsize _n = 0; \
Packit fabffb
		\
Packit fabffb
		if (_array) { \
Packit fabffb
			_nm_unused typeof (*(_array[0])) *_array_check = _array[0]; \
Packit fabffb
			while (_array[_n]) \
Packit fabffb
				_n++; \
Packit fabffb
		} \
Packit fabffb
		_n; \
Packit fabffb
	})
Packit fabffb
Packit fabffb
/* Note: @value is only evaluated when *out_val is present.
Packit fabffb
 * Thus,
Packit fabffb
 *    NM_SET_OUT (out_str, g_strdup ("hallo"));
Packit fabffb
 * does the right thing.
Packit fabffb
 */
Packit fabffb
#define NM_SET_OUT(out_val, value) \
Packit fabffb
	G_STMT_START { \
Packit fabffb
		typeof(*(out_val)) *_out_val = (out_val); \
Packit fabffb
		\
Packit fabffb
		if (_out_val) { \
Packit fabffb
			*_out_val = (value); \
Packit fabffb
		} \
Packit fabffb
	} G_STMT_END
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
#ifndef _NM_CC_SUPPORT_AUTO_TYPE
Packit fabffb
#if (defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9 )))
Packit fabffb
#define _NM_CC_SUPPORT_AUTO_TYPE 1
Packit fabffb
#else
Packit fabffb
#define _NM_CC_SUPPORT_AUTO_TYPE 0
Packit fabffb
#endif
Packit fabffb
#endif
Packit fabffb
Packit fabffb
#ifndef _NM_CC_SUPPORT_GENERIC
Packit fabffb
#if (defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9 ))) || (defined (__clang__))
Packit fabffb
#define _NM_CC_SUPPORT_GENERIC 1
Packit fabffb
#else
Packit fabffb
#define _NM_CC_SUPPORT_GENERIC 0
Packit fabffb
#endif
Packit fabffb
#endif
Packit fabffb
Packit fabffb
#if _NM_CC_SUPPORT_AUTO_TYPE
Packit fabffb
#define _nm_auto_type __auto_type
Packit fabffb
#endif
Packit fabffb
Packit fabffb
#if _NM_CC_SUPPORT_GENERIC
Packit fabffb
#define _NM_CONSTCAST_FULL_1(type, obj_expr, obj) \
Packit fabffb
	(_Generic ((obj_expr), \
Packit fabffb
	           const void        *const: ((const type *) (obj)), \
Packit fabffb
	           const void        *     : ((const type *) (obj)), \
Packit fabffb
	                 void        *const: ((      type *) (obj)), \
Packit fabffb
	                 void        *     : ((      type *) (obj)), \
Packit fabffb
	           const type        *const: ((const type *) (obj)), \
Packit fabffb
	           const type        *     : ((const type *) (obj)), \
Packit fabffb
	                 type        *const: ((      type *) (obj)), \
Packit fabffb
	                 type        *     : ((      type *) (obj))))
Packit fabffb
#define _NM_CONSTCAST_FULL_2(type, obj_expr, obj, alias_type2) \
Packit fabffb
	(_Generic ((obj_expr), \
Packit fabffb
	           const void        *const: ((const type *) (obj)), \
Packit fabffb
	           const void        *     : ((const type *) (obj)), \
Packit fabffb
	                 void        *const: ((      type *) (obj)), \
Packit fabffb
	                 void        *     : ((      type *) (obj)), \
Packit fabffb
	           const alias_type2 *const: ((const type *) (obj)), \
Packit fabffb
	           const alias_type2 *     : ((const type *) (obj)), \
Packit fabffb
	                 alias_type2 *const: ((      type *) (obj)), \
Packit fabffb
	                 alias_type2 *     : ((      type *) (obj)), \
Packit fabffb
	           const type        *const: ((const type *) (obj)), \
Packit fabffb
	           const type        *     : ((const type *) (obj)), \
Packit fabffb
	                 type        *const: ((      type *) (obj)), \
Packit fabffb
	                 type        *     : ((      type *) (obj))))
Packit fabffb
#define _NM_CONSTCAST_FULL_3(type, obj_expr, obj, alias_type2, alias_type3) \
Packit fabffb
	(_Generic ((obj_expr), \
Packit fabffb
	           const void        *const: ((const type *) (obj)), \
Packit fabffb
	           const void        *     : ((const type *) (obj)), \
Packit fabffb
	                 void        *const: ((      type *) (obj)), \
Packit fabffb
	                 void        *     : ((      type *) (obj)), \
Packit fabffb
	           const alias_type2 *const: ((const type *) (obj)), \
Packit fabffb
	           const alias_type2 *     : ((const type *) (obj)), \
Packit fabffb
	                 alias_type2 *const: ((      type *) (obj)), \
Packit fabffb
	                 alias_type2 *     : ((      type *) (obj)), \
Packit fabffb
	           const alias_type3 *const: ((const type *) (obj)), \
Packit fabffb
	           const alias_type3 *     : ((const type *) (obj)), \
Packit fabffb
	                 alias_type3 *const: ((      type *) (obj)), \
Packit fabffb
	                 alias_type3 *     : ((      type *) (obj)), \
Packit fabffb
	           const type        *const: ((const type *) (obj)), \
Packit fabffb
	           const type        *     : ((const type *) (obj)), \
Packit fabffb
	                 type        *const: ((      type *) (obj)), \
Packit fabffb
	                 type        *     : ((      type *) (obj))))
Packit fabffb
#define _NM_CONSTCAST_FULL_4(type, obj_expr, obj, alias_type2, alias_type3, alias_type4) \
Packit fabffb
	(_Generic ((obj_expr), \
Packit fabffb
	           const void        *const: ((const type *) (obj)), \
Packit fabffb
	           const void        *     : ((const type *) (obj)), \
Packit fabffb
	                 void        *const: ((      type *) (obj)), \
Packit fabffb
	                 void        *     : ((      type *) (obj)), \
Packit fabffb
	           const alias_type2 *const: ((const type *) (obj)), \
Packit fabffb
	           const alias_type2 *     : ((const type *) (obj)), \
Packit fabffb
	                 alias_type2 *const: ((      type *) (obj)), \
Packit fabffb
	                 alias_type2 *     : ((      type *) (obj)), \
Packit fabffb
	           const alias_type3 *const: ((const type *) (obj)), \
Packit fabffb
	           const alias_type3 *     : ((const type *) (obj)), \
Packit fabffb
	                 alias_type3 *const: ((      type *) (obj)), \
Packit fabffb
	                 alias_type3 *     : ((      type *) (obj)), \
Packit fabffb
	           const alias_type4 *const: ((const type *) (obj)), \
Packit fabffb
	           const alias_type4 *     : ((const type *) (obj)), \
Packit fabffb
	                 alias_type4 *const: ((      type *) (obj)), \
Packit fabffb
	                 alias_type4 *     : ((      type *) (obj)), \
Packit fabffb
	           const type        *const: ((const type *) (obj)), \
Packit fabffb
	           const type        *     : ((const type *) (obj)), \
Packit fabffb
	                 type        *const: ((      type *) (obj)), \
Packit fabffb
	                 type        *     : ((      type *) (obj))))
Packit fabffb
#define _NM_CONSTCAST_FULL_x(type, obj_expr, obj, n, ...)   (_NM_CONSTCAST_FULL_##n (type, obj_expr, obj,                        ##__VA_ARGS__))
Packit fabffb
#define _NM_CONSTCAST_FULL_y(type, obj_expr, obj, n, ...)   (_NM_CONSTCAST_FULL_x   (type, obj_expr, obj, n,                     ##__VA_ARGS__))
Packit fabffb
#define NM_CONSTCAST_FULL(   type, obj_expr, obj,    ...)   (_NM_CONSTCAST_FULL_y   (type, obj_expr, obj, NM_NARG (dummy, ##__VA_ARGS__), ##__VA_ARGS__))
Packit fabffb
#else
Packit fabffb
#define NM_CONSTCAST_FULL(   type, obj_expr, obj,    ...)   ((type *) (obj))
Packit fabffb
#endif
Packit fabffb
Packit fabffb
#define NM_CONSTCAST(type, obj, ...) \
Packit fabffb
	NM_CONSTCAST_FULL(type, (obj), (obj), ##__VA_ARGS__)
Packit fabffb
Packit fabffb
#define NM_GOBJECT_CAST(type, obj, is_check, ...) \
Packit fabffb
	({ \
Packit fabffb
		const void *_obj = (obj); \
Packit fabffb
		\
Packit fabffb
		nm_assert (_obj || (is_check (_obj))); \
Packit fabffb
		NM_CONSTCAST_FULL (type, (obj), _obj, GObject, ##__VA_ARGS__); \
Packit fabffb
	})
Packit fabffb
Packit fabffb
#define NM_GOBJECT_CAST_NON_NULL(type, obj, is_check, ...) \
Packit fabffb
	({ \
Packit fabffb
		const void *_obj = (obj); \
Packit fabffb
		\
Packit fabffb
		nm_assert (is_check (_obj)); \
Packit fabffb
		NM_CONSTCAST_FULL (type, (obj), _obj, GObject, ##__VA_ARGS__); \
Packit fabffb
	})
Packit fabffb
Packit fabffb
#if _NM_CC_SUPPORT_GENERIC
Packit fabffb
/* returns @value, if the type of @value matches @type.
Packit fabffb
 * This requires support for C11 _Generic(). If no support is
Packit fabffb
 * present, this returns @value directly.
Packit fabffb
 *
Packit fabffb
 * It's useful to check the let the compiler ensure that @value is
Packit fabffb
 * of a certain type. */
Packit fabffb
#define _NM_ENSURE_TYPE(type, value) (_Generic ((value), type: (value)))
Packit fabffb
#else
Packit fabffb
#define _NM_ENSURE_TYPE(type, value) (value)
Packit fabffb
#endif
Packit fabffb
Packit fabffb
#if _NM_CC_SUPPORT_GENERIC
Packit fabffb
#define NM_PROPAGATE_CONST(test_expr, ptr) \
Packit fabffb
	(_Generic ((test_expr), \
Packit fabffb
	           const typeof (*(test_expr)) *: ((const typeof (*(ptr)) *) (ptr)), \
Packit fabffb
	                                 default: (_Generic ((test_expr), \
Packit fabffb
	                                                     typeof (*(test_expr)) *: (ptr)))))
Packit fabffb
#else
Packit fabffb
#define NM_PROPAGATE_CONST(test_expr, ptr) (ptr)
Packit fabffb
#endif
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
#define _NM_IN_SET_EVAL_1( op, _x, y)           (_x == (y))
Packit fabffb
#define _NM_IN_SET_EVAL_2( op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_1  (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_SET_EVAL_3( op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_2  (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_SET_EVAL_4( op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_3  (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_SET_EVAL_5( op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_4  (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_SET_EVAL_6( op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_5  (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_SET_EVAL_7( op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_6  (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_SET_EVAL_8( op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_7  (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_SET_EVAL_9( op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_8  (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_SET_EVAL_10(op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_9  (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_SET_EVAL_11(op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_10 (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_SET_EVAL_12(op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_11 (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_SET_EVAL_13(op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_12 (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_SET_EVAL_14(op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_13 (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_SET_EVAL_15(op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_14 (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_SET_EVAL_16(op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_15 (op, _x, __VA_ARGS__)
Packit fabffb
Packit fabffb
#define _NM_IN_SET_EVAL_N2(op, _x, n, ...)      (_NM_IN_SET_EVAL_##n(op, _x, __VA_ARGS__))
Packit fabffb
#define _NM_IN_SET_EVAL_N(op, type, x, n, ...)                      \
Packit fabffb
    ({                                                              \
Packit fabffb
        type _x = (x);                                              \
Packit fabffb
                                                                    \
Packit fabffb
        /* trigger a -Wenum-compare warning */                      \
Packit fabffb
        nm_assert (TRUE || _x == (x));                              \
Packit fabffb
                                                                    \
Packit fabffb
        !!_NM_IN_SET_EVAL_N2(op, _x, n, __VA_ARGS__);               \
Packit fabffb
    })
Packit fabffb
Packit fabffb
#define _NM_IN_SET(op, type, x, ...)        _NM_IN_SET_EVAL_N(op, type, x, NM_NARG (__VA_ARGS__), __VA_ARGS__)
Packit fabffb
Packit fabffb
/* Beware that this does short-circuit evaluation (use "||" instead of "|")
Packit fabffb
 * which has a possibly unexpected non-function-like behavior.
Packit fabffb
 * Use NM_IN_SET_SE if you need all arguments to be evaluted. */
Packit fabffb
#define NM_IN_SET(x, ...)                   _NM_IN_SET(||, typeof (x), x, __VA_ARGS__)
Packit fabffb
Packit fabffb
/* "SE" stands for "side-effect". Contrary to NM_IN_SET(), this does not do
Packit fabffb
 * short-circuit evaluation, which can make a difference if the arguments have
Packit fabffb
 * side-effects. */
Packit fabffb
#define NM_IN_SET_SE(x, ...)                _NM_IN_SET(|,  typeof (x), x, __VA_ARGS__)
Packit fabffb
Packit fabffb
/* the *_TYPED forms allow to explicitly select the type of "x". This is useful
Packit fabffb
 * if "x" doesn't support typeof (bitfields) or you want to gracefully convert
Packit fabffb
 * a type using automatic type conversion rules (but not forcing the conversion
Packit fabffb
 * with a cast). */
Packit fabffb
#define NM_IN_SET_TYPED(type, x, ...)       _NM_IN_SET(||, type,       x, __VA_ARGS__)
Packit fabffb
#define NM_IN_SET_SE_TYPED(type, x, ...)    _NM_IN_SET(|,  type,       x, __VA_ARGS__)
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
static inline gboolean
Packit fabffb
_NM_IN_STRSET_streq (const char *x, const char *s)
Packit fabffb
{
Packit fabffb
	return s && strcmp (x, s) == 0;
Packit fabffb
}
Packit fabffb
Packit fabffb
#define _NM_IN_STRSET_EVAL_1( op, _x, y)        _NM_IN_STRSET_streq (_x, y)
Packit fabffb
#define _NM_IN_STRSET_EVAL_2( op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_1  (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_STRSET_EVAL_3( op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_2  (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_STRSET_EVAL_4( op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_3  (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_STRSET_EVAL_5( op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_4  (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_STRSET_EVAL_6( op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_5  (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_STRSET_EVAL_7( op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_6  (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_STRSET_EVAL_8( op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_7  (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_STRSET_EVAL_9( op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_8  (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_STRSET_EVAL_10(op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_9  (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_STRSET_EVAL_11(op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_10 (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_STRSET_EVAL_12(op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_11 (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_STRSET_EVAL_13(op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_12 (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_STRSET_EVAL_14(op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_13 (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_STRSET_EVAL_15(op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_14 (op, _x, __VA_ARGS__)
Packit fabffb
#define _NM_IN_STRSET_EVAL_16(op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_15 (op, _x, __VA_ARGS__)
Packit fabffb
Packit fabffb
#define _NM_IN_STRSET_EVAL_N2(op, _x, n, ...)   (_NM_IN_STRSET_EVAL_##n(op, _x, __VA_ARGS__))
Packit fabffb
#define _NM_IN_STRSET_EVAL_N(op, x, n, ...)                       \
Packit fabffb
    ({                                                            \
Packit fabffb
        const char *_x = (x);                                     \
Packit fabffb
        (   ((_x == NULL) && _NM_IN_SET_EVAL_N2    (op, ((const char *) NULL), n, __VA_ARGS__)) \
Packit fabffb
         || ((_x != NULL) && _NM_IN_STRSET_EVAL_N2 (op, _x,                    n, __VA_ARGS__)) \
Packit fabffb
        ); \
Packit fabffb
    })
Packit fabffb
Packit fabffb
/* Beware that this does short-circuit evaluation (use "||" instead of "|")
Packit fabffb
 * which has a possibly unexpected non-function-like behavior.
Packit fabffb
 * Use NM_IN_STRSET_SE if you need all arguments to be evaluted. */
Packit fabffb
#define NM_IN_STRSET(x, ...)               _NM_IN_STRSET_EVAL_N(||, x, NM_NARG (__VA_ARGS__), __VA_ARGS__)
Packit fabffb
Packit fabffb
/* "SE" stands for "side-effect". Contrary to NM_IN_STRSET(), this does not do
Packit fabffb
 * short-circuit evaluation, which can make a difference if the arguments have
Packit fabffb
 * side-effects. */
Packit fabffb
#define NM_IN_STRSET_SE(x, ...)            _NM_IN_STRSET_EVAL_N(|, x, NM_NARG (__VA_ARGS__), __VA_ARGS__)
Packit fabffb
Packit fabffb
#define NM_STRCHAR_ALL(str, ch_iter, predicate) \
Packit fabffb
	({ \
Packit fabffb
		gboolean _val = TRUE; \
Packit fabffb
		const char *_str = (str); \
Packit fabffb
		\
Packit fabffb
		if (_str) { \
Packit fabffb
			for (;;) { \
Packit fabffb
				const char ch_iter = _str[0]; \
Packit fabffb
				\
Packit fabffb
				if (ch_iter != '\0') { \
Packit fabffb
					if (predicate) {\
Packit fabffb
						_str++; \
Packit fabffb
						continue; \
Packit fabffb
					} \
Packit fabffb
					_val = FALSE; \
Packit fabffb
				} \
Packit fabffb
				break; \
Packit fabffb
			} \
Packit fabffb
		} \
Packit fabffb
		_val; \
Packit fabffb
	})
Packit fabffb
Packit fabffb
#define NM_STRCHAR_ANY(str, ch_iter, predicate) \
Packit fabffb
	({ \
Packit fabffb
		gboolean _val = FALSE; \
Packit fabffb
		const char *_str = (str); \
Packit fabffb
		\
Packit fabffb
		if (_str) { \
Packit fabffb
			for (;;) { \
Packit fabffb
				const char ch_iter = _str[0]; \
Packit fabffb
				\
Packit fabffb
				if (ch_iter != '\0') { \
Packit fabffb
					if (predicate) { \
Packit fabffb
						; \
Packit fabffb
					} else { \
Packit fabffb
						_str++; \
Packit fabffb
						continue; \
Packit fabffb
					} \
Packit fabffb
					_val = TRUE; \
Packit fabffb
				} \
Packit fabffb
				break; \
Packit fabffb
			} \
Packit fabffb
		} \
Packit fabffb
		_val; \
Packit fabffb
	})
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
/* NM_CACHED_QUARK() returns the GQuark for @string, but caches
Packit fabffb
 * it in a static variable to speed up future lookups.
Packit fabffb
 *
Packit fabffb
 * @string must be a string literal.
Packit fabffb
 */
Packit fabffb
#define NM_CACHED_QUARK(string) \
Packit fabffb
	({ \
Packit fabffb
		static GQuark _nm_cached_quark = 0; \
Packit fabffb
		\
Packit fabffb
		(G_LIKELY (_nm_cached_quark != 0) \
Packit fabffb
			? _nm_cached_quark \
Packit fabffb
			: (_nm_cached_quark = g_quark_from_static_string (""string""))); \
Packit fabffb
	})
Packit fabffb
Packit fabffb
/* NM_CACHED_QUARK_FCN() is essentially the same as G_DEFINE_QUARK
Packit fabffb
 * with two differences:
Packit fabffb
 * - @string must be a quoted string-literal
Packit fabffb
 * - @fcn must be the full function name, while G_DEFINE_QUARK() appends
Packit fabffb
 *   "_quark" to the function name.
Packit fabffb
 * Both properties of G_DEFINE_QUARK() are non favorable, because you can no
Packit fabffb
 * longer grep for string/fcn -- unless you are aware that you are searching
Packit fabffb
 * for G_DEFINE_QUARK() and omit quotes / append _quark(). With NM_CACHED_QUARK_FCN(),
Packit fabffb
 * ctags/cscope can locate the use of @fcn (though it doesn't recognize that
Packit fabffb
 * NM_CACHED_QUARK_FCN() defines it).
Packit fabffb
 */
Packit fabffb
#define NM_CACHED_QUARK_FCN(string, fcn) \
Packit fabffb
GQuark \
Packit fabffb
fcn (void) \
Packit fabffb
{ \
Packit fabffb
	return NM_CACHED_QUARK (string); \
Packit fabffb
}
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
#define nm_streq(s1, s2)  (strcmp (s1, s2) == 0)
Packit fabffb
#define nm_streq0(s1, s2) (g_strcmp0 (s1, s2) == 0)
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
static inline GString *
Packit fabffb
nm_gstring_prepare (GString **l)
Packit fabffb
{
Packit fabffb
	if (*l)
Packit fabffb
		g_string_set_size (*l, 0);
Packit fabffb
	else
Packit fabffb
		*l = g_string_sized_new (30);
Packit fabffb
	return *l;
Packit fabffb
}
Packit fabffb
Packit fabffb
static inline const char *
Packit fabffb
nm_str_not_empty (const char *str)
Packit fabffb
{
Packit fabffb
	return str && str[0] ? str : NULL;
Packit fabffb
}
Packit fabffb
Packit fabffb
static inline char *
Packit fabffb
nm_strdup_not_empty (const char *str)
Packit fabffb
{
Packit fabffb
	return str && str[0] ? g_strdup (str) : NULL;
Packit fabffb
}
Packit fabffb
Packit fabffb
static inline char *
Packit fabffb
nm_str_realloc (char *str)
Packit fabffb
{
Packit fabffb
	gs_free char *s = str;
Packit fabffb
Packit fabffb
	/* Returns a new clone of @str and frees @str. The point is that @str
Packit fabffb
	 * possibly points to a larger chunck of memory. We want to freshly allocate
Packit fabffb
	 * a buffer.
Packit fabffb
	 *
Packit fabffb
	 * We could use realloc(), but that might not do anything or leave
Packit fabffb
	 * @str in its memory pool for chunks of a different size (bad for
Packit fabffb
	 * fragmentation).
Packit fabffb
	 *
Packit fabffb
	 * This is only useful when we want to keep the buffer around for a long
Packit fabffb
	 * time and want to re-allocate a more optimal buffer. */
Packit fabffb
Packit fabffb
	return g_strdup (s);
Packit fabffb
}
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
#define NM_PRINT_FMT_QUOTED(cond, prefix, str, suffix, str_else) \
Packit fabffb
	(cond) ? (prefix) : "", \
Packit fabffb
	(cond) ? (str) : (str_else), \
Packit fabffb
	(cond) ? (suffix) : ""
Packit fabffb
#define NM_PRINT_FMT_QUOTE_STRING(arg) NM_PRINT_FMT_QUOTED((arg), "\"", (arg), "\"", "(null)")
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
/* glib/C provides the following kind of assertions:
Packit fabffb
 *   - assert() -- disable with NDEBUG
Packit fabffb
 *   - g_return_if_fail() -- disable with G_DISABLE_CHECKS
Packit fabffb
 *   - g_assert() -- disable with G_DISABLE_ASSERT
Packit fabffb
 * but they are all enabled by default and usually even production builds have
Packit fabffb
 * these kind of assertions enabled. It also means, that disabling assertions
Packit fabffb
 * is an untested configuration, and might have bugs.
Packit fabffb
 *
Packit fabffb
 * Add our own assertion macro nm_assert(), which is disabled by default and must
Packit fabffb
 * be explicitly enabled. They are useful for more expensive checks or checks that
Packit fabffb
 * depend less on runtime conditions (that is, are generally expected to be true). */
Packit fabffb
Packit fabffb
#ifndef NM_MORE_ASSERTS
Packit fabffb
#define NM_MORE_ASSERTS 0
Packit fabffb
#endif
Packit fabffb
Packit fabffb
#if NM_MORE_ASSERTS
Packit fabffb
#define nm_assert(cond) G_STMT_START { g_assert (cond); } G_STMT_END
Packit fabffb
#define nm_assert_se(cond) G_STMT_START { if (G_LIKELY (cond)) { ; } else { g_assert (FALSE && (cond)); } } G_STMT_END
Packit fabffb
#define nm_assert_not_reached() G_STMT_START { g_assert_not_reached (); } G_STMT_END
Packit fabffb
#else
Packit fabffb
#define nm_assert(cond) G_STMT_START { if (FALSE) { if (cond) { } } } G_STMT_END
Packit fabffb
#define nm_assert_se(cond) G_STMT_START { if (G_LIKELY (cond)) { ; } } G_STMT_END
Packit fabffb
#define nm_assert_not_reached() G_STMT_START { ; } G_STMT_END
Packit fabffb
#endif
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
#define NM_GOBJECT_PROPERTIES_DEFINE_BASE(...) \
Packit fabffb
typedef enum { \
Packit fabffb
	_PROPERTY_ENUMS_0, \
Packit fabffb
	__VA_ARGS__ \
Packit fabffb
	_PROPERTY_ENUMS_LAST, \
Packit fabffb
} _PropertyEnums; \
Packit fabffb
static GParamSpec *obj_properties[_PROPERTY_ENUMS_LAST] = { NULL, }
Packit fabffb
Packit fabffb
#define NM_GOBJECT_PROPERTIES_DEFINE(obj_type, ...) \
Packit fabffb
NM_GOBJECT_PROPERTIES_DEFINE_BASE (__VA_ARGS__); \
Packit fabffb
static inline void \
Packit fabffb
_notify (obj_type *obj, _PropertyEnums prop) \
Packit fabffb
{ \
Packit fabffb
	nm_assert (G_IS_OBJECT (obj)); \
Packit fabffb
	nm_assert ((gsize) prop < G_N_ELEMENTS (obj_properties)); \
Packit fabffb
	g_object_notify_by_pspec ((GObject *) obj, obj_properties[prop]); \
Packit fabffb
}
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
#define _NM_GET_PRIVATE(self, type, is_check, ...) (&(NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__)->_priv))
Packit fabffb
#if _NM_CC_SUPPORT_AUTO_TYPE
Packit fabffb
#define _NM_GET_PRIVATE_PTR(self, type, is_check, ...) \
Packit fabffb
	({ \
Packit fabffb
		_nm_auto_type _self = NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__); \
Packit fabffb
		\
Packit fabffb
		NM_PROPAGATE_CONST (_self, _self->_priv); \
Packit fabffb
	})
Packit fabffb
#else
Packit fabffb
#define _NM_GET_PRIVATE_PTR(self, type, is_check, ...) (NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__)->_priv)
Packit fabffb
#endif
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
static inline gpointer
Packit fabffb
nm_g_object_ref (gpointer obj)
Packit fabffb
{
Packit fabffb
	/* g_object_ref() doesn't accept NULL. */
Packit fabffb
	if (obj)
Packit fabffb
		g_object_ref (obj);
Packit fabffb
	return obj;
Packit fabffb
}
Packit fabffb
#define nm_g_object_ref(obj) ((typeof (obj)) nm_g_object_ref (obj))
Packit fabffb
Packit fabffb
static inline void
Packit fabffb
nm_g_object_unref (gpointer obj)
Packit fabffb
{
Packit fabffb
	/* g_object_unref() doesn't accept NULL. Usully, we workaround that
Packit fabffb
	 * by using g_clear_object(), but sometimes that is not convinient
Packit fabffb
	 * (for example as as destroy function for a hash table that can contain
Packit fabffb
	 * NULL values). */
Packit fabffb
	if (obj)
Packit fabffb
		g_object_unref (obj);
Packit fabffb
}
Packit fabffb
Packit fabffb
/* Assigns GObject @obj to destination @pdst, and takes an additional ref.
Packit fabffb
 * The previous value of @pdst is unrefed.
Packit fabffb
 *
Packit fabffb
 * It makes sure to first increase the ref-count of @obj, and handles %NULL
Packit fabffb
 * @obj correctly.
Packit fabffb
 * */
Packit fabffb
#define nm_g_object_ref_set(pp, obj) \
Packit fabffb
	({ \
Packit fabffb
		typeof (*(pp)) *const _pp = (pp); \
Packit fabffb
		typeof (**_pp) *const _obj = (obj); \
Packit fabffb
		typeof (**_pp) *_p; \
Packit fabffb
		gboolean _changed = FALSE; \
Packit fabffb
		\
Packit fabffb
		if (   _pp \
Packit fabffb
		    && ((_p = *_pp) != _obj)) { \
Packit fabffb
			if (_obj) { \
Packit fabffb
				nm_assert (G_IS_OBJECT (_obj)); \
Packit fabffb
				 g_object_ref (_obj); \
Packit fabffb
			} \
Packit fabffb
			if (_p) { \
Packit fabffb
				nm_assert (G_IS_OBJECT (_p)); \
Packit fabffb
				*_pp = NULL; \
Packit fabffb
				g_object_unref (_p); \
Packit fabffb
			} \
Packit fabffb
			*_pp = _obj; \
Packit fabffb
			_changed = TRUE; \
Packit fabffb
		} \
Packit fabffb
		_changed; \
Packit fabffb
	})
Packit fabffb
Packit fabffb
/* basically, replaces
Packit fabffb
 *   g_clear_pointer (&location, g_free)
Packit fabffb
 * with
Packit fabffb
 *   nm_clear_g_free (&location)
Packit fabffb
 *
Packit fabffb
 * Another advantage is that by using a macro and typeof(), it is more
Packit fabffb
 * typesafe and gives you for example a compiler warning when pp is a const
Packit fabffb
 * pointer or points to a const-pointer.
Packit fabffb
 */
Packit fabffb
#define nm_clear_g_free(pp) \
Packit fabffb
	({  \
Packit fabffb
		typeof (*(pp)) *_pp = (pp); \
Packit fabffb
		typeof (**_pp) *_p; \
Packit fabffb
		gboolean _changed = FALSE; \
Packit fabffb
		\
Packit fabffb
		if (  _pp \
Packit fabffb
		    && (_p = *_pp)) { \
Packit fabffb
			*_pp = NULL; \
Packit fabffb
			g_free (_p); \
Packit fabffb
			_changed = TRUE; \
Packit fabffb
		} \
Packit fabffb
		_changed; \
Packit fabffb
	})
Packit fabffb
Packit fabffb
#define nm_clear_g_object(pp) \
Packit fabffb
	({ \
Packit fabffb
		typeof (*(pp)) *_pp = (pp); \
Packit fabffb
		typeof (**_pp) *_p; \
Packit fabffb
		gboolean _changed = FALSE; \
Packit fabffb
		\
Packit fabffb
		if (   _pp \
Packit fabffb
		    && (_p = *_pp)) { \
Packit fabffb
			nm_assert (G_IS_OBJECT (_p)); \
Packit fabffb
			*_pp = NULL; \
Packit fabffb
			g_object_unref (_p); \
Packit fabffb
			_changed = TRUE; \
Packit fabffb
		} \
Packit fabffb
		_changed; \
Packit fabffb
	})
Packit fabffb
Packit fabffb
static inline gboolean
Packit fabffb
nm_clear_g_source (guint *id)
Packit fabffb
{
Packit fabffb
	if (id && *id) {
Packit fabffb
		g_source_remove (*id);
Packit fabffb
		*id = 0;
Packit fabffb
		return TRUE;
Packit fabffb
	}
Packit fabffb
	return FALSE;
Packit fabffb
}
Packit fabffb
Packit fabffb
static inline gboolean
Packit fabffb
nm_clear_g_signal_handler (gpointer self, gulong *id)
Packit fabffb
{
Packit fabffb
	if (id && *id) {
Packit fabffb
		g_signal_handler_disconnect (self, *id);
Packit fabffb
		*id = 0;
Packit fabffb
		return TRUE;
Packit fabffb
	}
Packit fabffb
	return FALSE;
Packit fabffb
}
Packit fabffb
Packit fabffb
static inline gboolean
Packit fabffb
nm_clear_g_variant (GVariant **variant)
Packit fabffb
{
Packit fabffb
	if (variant && *variant) {
Packit fabffb
		g_variant_unref (*variant);
Packit fabffb
		*variant = NULL;
Packit fabffb
		return TRUE;
Packit fabffb
	}
Packit fabffb
	return FALSE;
Packit fabffb
}
Packit fabffb
Packit fabffb
static inline gboolean
Packit fabffb
nm_clear_g_cancellable (GCancellable **cancellable)
Packit fabffb
{
Packit fabffb
	if (cancellable && *cancellable) {
Packit fabffb
		g_cancellable_cancel (*cancellable);
Packit fabffb
		g_object_unref (*cancellable);
Packit fabffb
		*cancellable = NULL;
Packit fabffb
		return TRUE;
Packit fabffb
	}
Packit fabffb
	return FALSE;
Packit fabffb
}
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
/* Determine whether @x is a power of two (@x being an integer type).
Packit fabffb
 * Basically, this returns TRUE, if @x has exactly one bit set.
Packit fabffb
 * For negative values and zero, this always returns FALSE. */
Packit fabffb
#define nm_utils_is_power_of_two(x) ({ \
Packit fabffb
		typeof(x) __x = (x); \
Packit fabffb
		\
Packit fabffb
		(    (__x > ((typeof(__x)) 0)) \
Packit fabffb
		 && ((__x & (__x - (((typeof(__x)) 1)))) == ((typeof(__x)) 0))); \
Packit fabffb
	})
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
#define NM_UTILS_LOOKUP_DEFAULT(v)            return (v)
Packit fabffb
#define NM_UTILS_LOOKUP_DEFAULT_WARN(v)       g_return_val_if_reached (v)
Packit fabffb
#define NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT(v)  { nm_assert_not_reached (); return (v); }
Packit fabffb
#define NM_UTILS_LOOKUP_ITEM(v, n)            (void) 0; case v: return (n); (void) 0
Packit fabffb
#define NM_UTILS_LOOKUP_STR_ITEM(v, n)        NM_UTILS_LOOKUP_ITEM(v, ""n"")
Packit fabffb
#define NM_UTILS_LOOKUP_ITEM_IGNORE(v)        (void) 0; case v: break; (void) 0
Packit fabffb
#define NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER()   (void) 0; default: break; (void) 0
Packit fabffb
Packit fabffb
#define _NM_UTILS_LOOKUP_DEFINE(scope, fcn_name, lookup_type, result_type, unknown_val, ...) \
Packit fabffb
scope result_type \
Packit fabffb
fcn_name (lookup_type val) \
Packit fabffb
{ \
Packit fabffb
	switch (val) { \
Packit fabffb
		(void) 0, \
Packit fabffb
		__VA_ARGS__ \
Packit fabffb
		(void) 0; \
Packit fabffb
	}; \
Packit fabffb
	{ unknown_val; } \
Packit fabffb
}
Packit fabffb
Packit fabffb
#define NM_UTILS_LOOKUP_STR_DEFINE(fcn_name, lookup_type, unknown_val, ...) \
Packit fabffb
	_NM_UTILS_LOOKUP_DEFINE (, fcn_name, lookup_type, const char *, unknown_val, __VA_ARGS__)
Packit fabffb
#define NM_UTILS_LOOKUP_STR_DEFINE_STATIC(fcn_name, lookup_type, unknown_val, ...) \
Packit fabffb
	_NM_UTILS_LOOKUP_DEFINE (static, fcn_name, lookup_type, const char *, unknown_val, __VA_ARGS__)
Packit fabffb
Packit fabffb
/* Call the string-lookup-table function @fcn_name. If the function returns
Packit fabffb
 * %NULL, the numeric index is converted to string using a alloca() buffer.
Packit fabffb
 * Beware: this macro uses alloca(). */
Packit fabffb
#define NM_UTILS_LOOKUP_STR(fcn_name, idx) \
Packit fabffb
	({ \
Packit fabffb
		typeof (idx) _idx = (idx); \
Packit fabffb
		const char *_s; \
Packit fabffb
		\
Packit fabffb
		_s = fcn_name (_idx); \
Packit fabffb
		if (!_s) { \
Packit fabffb
			_s = g_alloca (30); \
Packit fabffb
			\
Packit fabffb
			g_snprintf ((char *) _s, 30, "(%lld)", (long long) _idx); \
Packit fabffb
		} \
Packit fabffb
		_s; \
Packit fabffb
	})
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
/* check if @flags has exactly one flag (@check) set. You should call this
Packit fabffb
 * only with @check being a compile time constant and a power of two. */
Packit fabffb
#define NM_FLAGS_HAS(flags, check)  \
Packit fabffb
    ( G_STATIC_ASSERT_EXPR ((check) > 0 && ((check) & ((check) - 1)) == 0), NM_FLAGS_ANY ((flags), (check)) )
Packit fabffb
Packit fabffb
#define NM_FLAGS_ANY(flags, check)  ( ( ((flags) & (check)) != 0       ) ? TRUE : FALSE )
Packit fabffb
#define NM_FLAGS_ALL(flags, check)  ( ( ((flags) & (check)) == (check) ) ? TRUE : FALSE )
Packit fabffb
Packit fabffb
#define NM_FLAGS_SET(flags, val)  ({ \
Packit fabffb
		const typeof(flags) _flags = (flags); \
Packit fabffb
		const typeof(flags) _val = (val); \
Packit fabffb
		\
Packit fabffb
		_flags | _val; \
Packit fabffb
	})
Packit fabffb
Packit fabffb
#define NM_FLAGS_UNSET(flags, val)  ({ \
Packit fabffb
		const typeof(flags) _flags = (flags); \
Packit fabffb
		const typeof(flags) _val = (val); \
Packit fabffb
		\
Packit fabffb
		_flags & (~_val); \
Packit fabffb
	})
Packit fabffb
Packit fabffb
#define NM_FLAGS_ASSIGN(flags, val, assign)  ({ \
Packit fabffb
		const typeof(flags) _flags = (flags); \
Packit fabffb
		const typeof(flags) _val = (val); \
Packit fabffb
		\
Packit fabffb
		(assign) \
Packit fabffb
			? _flags | (_val) \
Packit fabffb
			: _flags & (~_val); \
Packit fabffb
	})
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
#define _NM_BACKPORT_SYMBOL_IMPL(VERSION, RETURN_TYPE, ORIG_FUNC, VERSIONED_FUNC, ARGS_TYPED, ARGS) \
Packit fabffb
RETURN_TYPE VERSIONED_FUNC ARGS_TYPED; \
Packit fabffb
RETURN_TYPE VERSIONED_FUNC ARGS_TYPED \
Packit fabffb
{ \
Packit fabffb
    return ORIG_FUNC ARGS; \
Packit fabffb
} \
Packit fabffb
RETURN_TYPE ORIG_FUNC ARGS_TYPED; \
Packit fabffb
__asm__(".symver "G_STRINGIFY(VERSIONED_FUNC)", "G_STRINGIFY(ORIG_FUNC)"@"G_STRINGIFY(VERSION))
Packit fabffb
Packit fabffb
#define NM_BACKPORT_SYMBOL(VERSION, RETURN_TYPE, FUNC, ARGS_TYPED, ARGS) \
Packit fabffb
_NM_BACKPORT_SYMBOL_IMPL(VERSION, RETURN_TYPE, FUNC, _##FUNC##_##VERSION, ARGS_TYPED, ARGS)
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
#define nm_str_skip_leading_spaces(str) \
Packit fabffb
	({ \
Packit fabffb
		typeof (*(str)) *_str = (str); \
Packit fabffb
		_nm_unused const char *_str_type_check = _str; \
Packit fabffb
		\
Packit fabffb
		if (_str) { \
Packit fabffb
			while (g_ascii_isspace (_str[0])) \
Packit fabffb
				_str++; \
Packit fabffb
		} \
Packit fabffb
		_str; \
Packit fabffb
	})
Packit fabffb
Packit fabffb
static inline char *
Packit fabffb
nm_strstrip (char *str)
Packit fabffb
{
Packit fabffb
	/* g_strstrip doesn't like NULL. */
Packit fabffb
	return str ? g_strstrip (str) : NULL;
Packit fabffb
}
Packit fabffb
Packit fabffb
static inline const char *
Packit fabffb
nm_strstrip_avoid_copy (const char *str, char **str_free)
Packit fabffb
{
Packit fabffb
	gsize l;
Packit fabffb
	char *s;
Packit fabffb
Packit fabffb
	nm_assert (str_free && !*str_free);
Packit fabffb
Packit fabffb
	if (!str)
Packit fabffb
		return NULL;
Packit fabffb
Packit fabffb
	str = nm_str_skip_leading_spaces (str);
Packit fabffb
	l = strlen (str);
Packit fabffb
	if (   l == 0
Packit fabffb
	    || !g_ascii_isspace (str[l - 1]))
Packit fabffb
		return str;
Packit fabffb
	while (   l > 0
Packit fabffb
	       && g_ascii_isspace (str[l - 1]))
Packit fabffb
		l--;
Packit fabffb
Packit fabffb
	s = g_new (char, l + 1);
Packit fabffb
	memcpy (s, str, l);
Packit fabffb
	s[l] = '\0';
Packit fabffb
	*str_free = s;
Packit fabffb
	return s;
Packit fabffb
}
Packit fabffb
Packit fabffb
/* g_ptr_array_sort()'s compare function takes pointers to the
Packit fabffb
 * value. Thus, you cannot use strcmp directly. You can use
Packit fabffb
 * nm_strcmp_p().
Packit fabffb
 *
Packit fabffb
 * Like strcmp(), this function is not forgiving to accept %NULL. */
Packit fabffb
static inline int
Packit fabffb
nm_strcmp_p (gconstpointer a, gconstpointer b)
Packit fabffb
{
Packit fabffb
	const char *s1 = *((const char **) a);
Packit fabffb
	const char *s2 = *((const char **) b);
Packit fabffb
Packit fabffb
	return strcmp (s1, s2);
Packit fabffb
}
Packit fabffb
Packit fabffb
/* like nm_strcmp_p(), suitable for g_ptr_array_sort_with_data().
Packit fabffb
 * g_ptr_array_sort() just casts nm_strcmp_p() to a function of different
Packit fabffb
 * signature. I guess, in glib there are knowledgeable people that ensure
Packit fabffb
 * that this additional argument doesn't cause problems due to different ABI
Packit fabffb
 * for every architecture that glib supports.
Packit fabffb
 * For NetworkManager, we'd rather avoid such stunts.
Packit fabffb
 **/
Packit fabffb
static inline int
Packit fabffb
nm_strcmp_p_with_data (gconstpointer a, gconstpointer b, gpointer user_data)
Packit fabffb
{
Packit fabffb
	const char *s1 = *((const char **) a);
Packit fabffb
	const char *s2 = *((const char **) b);
Packit fabffb
Packit fabffb
	return strcmp (s1, s2);
Packit fabffb
}
Packit fabffb
Packit fabffb
static inline int
Packit fabffb
nm_cmp_uint32_p_with_data (gconstpointer p_a, gconstpointer p_b, gpointer user_data)
Packit fabffb
{
Packit fabffb
	const guint32 a = *((const guint32 *) p_a);
Packit fabffb
	const guint32 b = *((const guint32 *) p_b);
Packit fabffb
Packit fabffb
	if (a < b)
Packit fabffb
		return -1;
Packit fabffb
	if (a > b)
Packit fabffb
		return 1;
Packit fabffb
	return 0;
Packit fabffb
}
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
/* Taken from systemd's UNIQ_T and UNIQ macros. */
Packit fabffb
Packit fabffb
#define NM_UNIQ_T(x, uniq) G_PASTE(__unique_prefix_, G_PASTE(x, uniq))
Packit fabffb
#define NM_UNIQ __COUNTER__
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
/* glib's MIN()/MAX() macros don't have function-like behavior, in that they evaluate
Packit fabffb
 * the argument possibly twice.
Packit fabffb
 *
Packit fabffb
 * Taken from systemd's MIN()/MAX() macros. */
Packit fabffb
Packit fabffb
#define NM_MIN(a, b) __NM_MIN(NM_UNIQ, a, NM_UNIQ, b)
Packit fabffb
#define __NM_MIN(aq, a, bq, b) \
Packit fabffb
	({ \
Packit fabffb
		typeof (a) NM_UNIQ_T(A, aq) = (a); \
Packit fabffb
		typeof (b) NM_UNIQ_T(B, bq) = (b); \
Packit fabffb
		((NM_UNIQ_T(A, aq) < NM_UNIQ_T(B, bq)) ? NM_UNIQ_T(A, aq) : NM_UNIQ_T(B, bq)); \
Packit fabffb
	})
Packit fabffb
Packit fabffb
#define NM_MAX(a, b) __NM_MAX(NM_UNIQ, a, NM_UNIQ, b)
Packit fabffb
#define __NM_MAX(aq, a, bq, b) \
Packit fabffb
	({ \
Packit fabffb
		typeof (a) NM_UNIQ_T(A, aq) = (a); \
Packit fabffb
		typeof (b) NM_UNIQ_T(B, bq) = (b); \
Packit fabffb
		((NM_UNIQ_T(A, aq) > NM_UNIQ_T(B, bq)) ? NM_UNIQ_T(A, aq) : NM_UNIQ_T(B, bq)); \
Packit fabffb
	})
Packit fabffb
Packit fabffb
#define NM_CLAMP(x, low, high) __NM_CLAMP(NM_UNIQ, x, NM_UNIQ, low, NM_UNIQ, high)
Packit fabffb
#define __NM_CLAMP(xq, x, lowq, low, highq, high) \
Packit fabffb
	({ \
Packit fabffb
		typeof(x)NM_UNIQ_T(X,xq) = (x); \
Packit fabffb
		typeof(low) NM_UNIQ_T(LOW,lowq) = (low); \
Packit fabffb
		typeof(high) NM_UNIQ_T(HIGH,highq) = (high); \
Packit fabffb
		\
Packit fabffb
		( (NM_UNIQ_T(X,xq) > NM_UNIQ_T(HIGH,highq)) \
Packit fabffb
		  ? NM_UNIQ_T(HIGH,highq) \
Packit fabffb
		  : (NM_UNIQ_T(X,xq) < NM_UNIQ_T(LOW,lowq)) \
Packit fabffb
		     ? NM_UNIQ_T(LOW,lowq) \
Packit fabffb
		     : NM_UNIQ_T(X,xq)); \
Packit fabffb
	})
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
static inline guint
Packit fabffb
nm_encode_version (guint major, guint minor, guint micro)
Packit fabffb
{
Packit fabffb
	/* analog to the preprocessor macro NM_ENCODE_VERSION(). */
Packit fabffb
	return (major << 16) | (minor << 8) | micro;
Packit fabffb
}
Packit fabffb
Packit fabffb
static inline void
Packit fabffb
nm_decode_version (guint version, guint *major, guint *minor, guint *micro)
Packit fabffb
{
Packit fabffb
	*major = (version & 0xFFFF0000u) >> 16;
Packit fabffb
	*minor = (version & 0x0000FF00u) >>  8;
Packit fabffb
	*micro = (version & 0x000000FFu);
Packit fabffb
}
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
/* taken from systemd's DECIMAL_STR_MAX()
Packit fabffb
 *
Packit fabffb
 * Returns the number of chars needed to format variables of the
Packit fabffb
 * specified type as a decimal string. Adds in extra space for a
Packit fabffb
 * negative '-' prefix (hence works correctly on signed
Packit fabffb
 * types). Includes space for the trailing NUL. */
Packit fabffb
#define NM_DECIMAL_STR_MAX(type) \
Packit fabffb
    (2+(sizeof(type) <= 1 ? 3 : \
Packit fabffb
        sizeof(type) <= 2 ? 5 : \
Packit fabffb
        sizeof(type) <= 4 ? 10 : \
Packit fabffb
        sizeof(type) <= 8 ? 20 : sizeof(int[-2*(sizeof(type) > 8)])))
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
/* if @str is NULL, return "(null)". Otherwise, allocate a buffer using
Packit fabffb
 * alloca() of and fill it with @str. @str will be quoted with double quote.
Packit fabffb
 * If @str is longer then @trunc_at, the string is truncated and the closing
Packit fabffb
 * quote is instead '^' to indicate truncation.
Packit fabffb
 *
Packit fabffb
 * Thus, the maximum stack allocated buffer will be @trunc_at+3. */
Packit fabffb
#define nm_strquote_a(trunc_at, str) \
Packit fabffb
	({ \
Packit fabffb
		const char *const _str = (str); \
Packit fabffb
		\
Packit fabffb
		(_str \
Packit fabffb
			? ({ \
Packit fabffb
				const gsize _trunc_at = (trunc_at); \
Packit fabffb
				const gsize _strlen_trunc = NM_MIN (strlen (_str), _trunc_at); \
Packit fabffb
				char *_buf; \
Packit fabffb
				\
Packit fabffb
				_buf = g_alloca (_strlen_trunc + 3); \
Packit fabffb
				_buf[0] = '"'; \
Packit fabffb
				memcpy (&_buf[1], _str, _strlen_trunc); \
Packit fabffb
				_buf[_strlen_trunc + 1] = _str[_strlen_trunc] ? '^' : '"'; \
Packit fabffb
				_buf[_strlen_trunc + 2] = '\0'; \
Packit fabffb
				_buf; \
Packit fabffb
			}) \
Packit fabffb
			: "(null)"); \
Packit fabffb
	})
Packit fabffb
Packit fabffb
#define nm_sprintf_buf(buf, format, ...) \
Packit fabffb
	({ \
Packit fabffb
		char * _buf = (buf); \
Packit fabffb
		int _buf_len; \
Packit fabffb
		\
Packit fabffb
		/* some static assert trying to ensure that the buffer is statically allocated.
Packit fabffb
		 * It disallows a buffer size of sizeof(gpointer) to catch that. */ \
Packit fabffb
		G_STATIC_ASSERT (G_N_ELEMENTS (buf) == sizeof (buf) && sizeof (buf) != sizeof (char *)); \
Packit fabffb
		_buf_len = g_snprintf (_buf, sizeof (buf), \
Packit fabffb
		                       ""format"", ##__VA_ARGS__); \
Packit fabffb
		nm_assert (_buf_len < sizeof (buf)); \
Packit fabffb
		_buf; \
Packit fabffb
	})
Packit fabffb
Packit fabffb
#define nm_sprintf_bufa(n_elements, format, ...) \
Packit fabffb
	({ \
Packit fabffb
		char *_buf; \
Packit fabffb
		int _buf_len; \
Packit fabffb
		typeof (n_elements) _n_elements = (n_elements); \
Packit fabffb
		\
Packit fabffb
		_buf = g_alloca (_n_elements); \
Packit fabffb
		_buf_len = g_snprintf (_buf, _n_elements, \
Packit fabffb
		                       ""format"", ##__VA_ARGS__); \
Packit fabffb
		nm_assert (_buf_len < _n_elements); \
Packit fabffb
		_buf; \
Packit fabffb
	})
Packit fabffb
Packit fabffb
/* aims to alloca() a buffer and fill it with printf(format, name).
Packit fabffb
 * Note that format must not contain any format specifier except
Packit fabffb
 * "%s".
Packit fabffb
 * If the resulting string would be too large for stack allocation,
Packit fabffb
 * it allocates a buffer with g_malloc() and assigns it to *p_val_to_free. */
Packit fabffb
#define nm_construct_name_a(format, name, p_val_to_free) \
Packit fabffb
	({ \
Packit fabffb
		const char *const _name = (name); \
Packit fabffb
		char **const _p_val_to_free = (p_val_to_free); \
Packit fabffb
		const gsize _name_len = strlen (_name); \
Packit fabffb
		char *_buf2; \
Packit fabffb
		\
Packit fabffb
		nm_assert (_p_val_to_free && !*_p_val_to_free); \
Packit fabffb
		if (NM_STRLEN (format) + _name_len < 200) \
Packit fabffb
			_buf2 = nm_sprintf_bufa (NM_STRLEN (format) + _name_len, format, _name); \
Packit fabffb
		else { \
Packit fabffb
			_buf2 = g_strdup_printf (format, _name); \
Packit fabffb
			*_p_val_to_free = _buf2; \
Packit fabffb
		} \
Packit fabffb
		(const char *) _buf2; \
Packit fabffb
	})
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
/**
Packit fabffb
 * The boolean type _Bool is C99 while we mostly stick to C89. However, _Bool is too
Packit fabffb
 * convinient to miss and is effectively available in gcc and clang. So, just use it.
Packit fabffb
 *
Packit fabffb
 * Usually, one would include "stdbool.h" to get the "bool" define which aliases
Packit fabffb
 * _Bool. We provide this define here, because we want to make use of it anywhere.
Packit fabffb
 * (also, stdbool.h is again C99).
Packit fabffb
 *
Packit fabffb
 * Using _Bool has advantages over gboolean:
Packit fabffb
 *
Packit fabffb
 * - commonly _Bool is one byte large, instead of gboolean's 4 bytes (because gboolean
Packit fabffb
 *   is a typedef for gint). Especially when having boolean fields in a struct, we can
Packit fabffb
 *   thereby easily save some space.
Packit fabffb
 *
Packit fabffb
 * - _Bool type guarantees that two "true" expressions compare equal. E.g. the follwing
Packit fabffb
 *   will not work:
Packit fabffb
 *        gboolean v1 = 1;
Packit fabffb
 *        gboolean v2 = 2;
Packit fabffb
 *        g_assert_cmpint (v1, ==, v2); // will fail
Packit fabffb
 *   For that, we often to use !! to coerce gboolean values to 0 or 1:
Packit fabffb
 *        g_assert_cmpint (!!v2, ==, TRUE);
Packit fabffb
 *   With _Bool type, this will be handled properly by the compiler.
Packit fabffb
 *
Packit fabffb
 * - For structs, we might want to safe even more space and use bitfields:
Packit fabffb
 *       struct s1 {
Packit fabffb
 *           gboolean v1:1;
Packit fabffb
 *       };
Packit fabffb
 *   But the problem here is that gboolean is signed, so that
Packit fabffb
 *   v1 will be either 0 or -1 (not 1, TRUE). Thus, the following
Packit fabffb
 *   fails:
Packit fabffb
 *      struct s1 s = { .v1 = TRUE, };
Packit fabffb
 *      g_assert_cmpint (s1.v1, ==, TRUE);
Packit fabffb
 *   It will however work just fine with bool/_Bool while retaining the
Packit fabffb
 *   notion of having a boolean value.
Packit fabffb
 *
Packit fabffb
 * Also, add the defines for "true" and "false". Those are nicely highlighted by the editor
Packit fabffb
 * as special types, contrary to glib's "TRUE"/"FALSE".
Packit fabffb
 */
Packit fabffb
Packit fabffb
#ifndef bool
Packit fabffb
#define bool _Bool
Packit fabffb
#define true    1
Packit fabffb
#define false   0
Packit fabffb
#endif
Packit fabffb
Packit fabffb
Packit fabffb
#ifdef _G_BOOLEAN_EXPR
Packit fabffb
/* g_assert() uses G_LIKELY(), which in turn uses _G_BOOLEAN_EXPR().
Packit fabffb
 * As glib's implementation uses a local variable _g_boolean_var_,
Packit fabffb
 * we cannot do
Packit fabffb
 *   g_assert (some_macro ());
Packit fabffb
 * where some_macro() itself expands to ({g_assert(); ...}).
Packit fabffb
 * In other words, you cannot have a g_assert() inside a g_assert()
Packit fabffb
 * without getting a -Werror=shadow failure.
Packit fabffb
 *
Packit fabffb
 * Workaround that by re-defining _G_BOOLEAN_EXPR()
Packit fabffb
 **/
Packit fabffb
#undef  _G_BOOLEAN_EXPR
Packit fabffb
#define __NM_G_BOOLEAN_EXPR_IMPL(v, expr) \
Packit fabffb
	({ \
Packit fabffb
		int NM_UNIQ_T(V, v); \
Packit fabffb
		\
Packit fabffb
		if (expr) \
Packit fabffb
			NM_UNIQ_T(V, v) = 1; \
Packit fabffb
		else \
Packit fabffb
			NM_UNIQ_T(V, v) = 0; \
Packit fabffb
		NM_UNIQ_T(V, v); \
Packit fabffb
	})
Packit fabffb
#define _G_BOOLEAN_EXPR(expr) __NM_G_BOOLEAN_EXPR_IMPL (NM_UNIQ, expr)
Packit fabffb
#endif
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
static inline int
Packit fabffb
nm_steal_fd (int *p_fd)
Packit fabffb
{
Packit fabffb
	int fd;
Packit fabffb
Packit fabffb
	if (   p_fd
Packit fabffb
	    && ((fd = *p_fd) >= 0)) {
Packit fabffb
		*p_fd = -1;
Packit fabffb
		return fd;
Packit fabffb
	}
Packit fabffb
	return -1;
Packit fabffb
}
Packit fabffb
Packit fabffb
/**
Packit fabffb
 * nm_close:
Packit fabffb
 *
Packit fabffb
 * Like close() but throws an assertion if the input fd is
Packit fabffb
 * invalid.  Closing an invalid fd is a programming error, so
Packit fabffb
 * it's better to catch it early.
Packit fabffb
 */
Packit fabffb
static inline int
Packit fabffb
nm_close (int fd)
Packit fabffb
{
Packit fabffb
	int r;
Packit fabffb
Packit fabffb
	r = close (fd);
Packit fabffb
	nm_assert (r != -1 || fd < 0 || errno != EBADF);
Packit fabffb
	return r;
Packit fabffb
}
Packit fabffb
Packit fabffb
#endif /* __NM_MACROS_INTERNAL_H__ */