mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-05 12:40:16 +01:00
macros: rework NM_IN_SET() macro to expand to a plain logical expression
Let the preprocessor do more work, but generate a simple expression that
the compiler can optimize (presumably) better.
(cherry picked from commit 7860ef959a)
This commit is contained in:
parent
daacb01fdd
commit
69b276d6d1
2 changed files with 172 additions and 13 deletions
|
|
@ -46,6 +46,31 @@
|
|||
|
||||
/********************************************************/
|
||||
|
||||
/* http://stackoverflow.com/a/2124385/354393 */
|
||||
|
||||
#define NM_NARG(...) \
|
||||
_NM_NARG(__VA_ARGS__,_NM_NARG_RSEQ_N())
|
||||
#define _NM_NARG(...) \
|
||||
_NM_NARG_ARG_N(__VA_ARGS__)
|
||||
#define _NM_NARG_ARG_N( \
|
||||
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
|
||||
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
|
||||
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
|
||||
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
|
||||
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
|
||||
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
|
||||
_61,_62,_63,N,...) N
|
||||
#define _NM_NARG_RSEQ_N() \
|
||||
63,62,61,60, \
|
||||
59,58,57,56,55,54,53,52,51,50, \
|
||||
49,48,47,46,45,44,43,42,41,40, \
|
||||
39,38,37,36,35,34,33,32,31,30, \
|
||||
29,28,27,26,25,24,23,22,21,20, \
|
||||
19,18,17,16,15,14,13,12,11,10, \
|
||||
9,8,7,6,5,4,3,2,1,0
|
||||
|
||||
/********************************************************/
|
||||
|
||||
#if defined (__GNUC__)
|
||||
#define _NM_PRAGMA_WARNING_DO(warning) G_STRINGIFY(GCC diagnostic ignored warning)
|
||||
#elif defined (__clang__)
|
||||
|
|
@ -85,21 +110,66 @@
|
|||
/* macro to return strlen() of a compile time string. */
|
||||
#define STRLEN(str) ( sizeof ("" str) - 1 )
|
||||
|
||||
#define NM_IN_SET(x, y, ...) \
|
||||
({ \
|
||||
const typeof(y) _y = (y); \
|
||||
typeof(_y) _x = (x); \
|
||||
unsigned _i; \
|
||||
gboolean _found = FALSE; \
|
||||
for (_i = 0; _i < 1 + sizeof((typeof(_x)[]) { __VA_ARGS__ })/sizeof(typeof(_x)); _i++) { \
|
||||
if (((typeof(_x)[]) { _y, __VA_ARGS__ })[_i] == _x) { \
|
||||
_found = TRUE; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
_found; \
|
||||
/********************************************************/
|
||||
|
||||
#define _NM_IN_SET_EVAL_1(op, x, y1) \
|
||||
({ \
|
||||
typeof(x) _x = (x); \
|
||||
( (_x == (y1)) \
|
||||
); \
|
||||
})
|
||||
|
||||
#define _NM_IN_SET_EVAL_2(op, x, y1, y2) \
|
||||
({ \
|
||||
typeof(x) _x = (x); \
|
||||
( (_x == (y1)) \
|
||||
op (_x == (y2)) \
|
||||
); \
|
||||
})
|
||||
|
||||
#define _NM_IN_SET_EVAL_3(op, x, y1, y2, y3) \
|
||||
({ \
|
||||
typeof(x) _x = (x); \
|
||||
( (_x == (y1)) \
|
||||
op (_x == (y2)) \
|
||||
op (_x == (y3)) \
|
||||
); \
|
||||
})
|
||||
|
||||
#define _NM_IN_SET_EVAL_4(op, x, y1, y2, y3, y4) \
|
||||
({ \
|
||||
typeof(x) _x = (x); \
|
||||
( (_x == (y1)) \
|
||||
op (_x == (y2)) \
|
||||
op (_x == (y3)) \
|
||||
op (_x == (y4)) \
|
||||
); \
|
||||
})
|
||||
|
||||
#define _NM_IN_SET_EVAL_5(op, x, y1, y2, y3, y4, y5) \
|
||||
({ \
|
||||
typeof(x) _x = (x); \
|
||||
( (_x == (y1)) \
|
||||
op (_x == (y2)) \
|
||||
op (_x == (y3)) \
|
||||
op (_x == (y4)) \
|
||||
op (_x == (y5)) \
|
||||
); \
|
||||
})
|
||||
|
||||
#define _NM_IN_SET_EVAL_N2(op, x, n, ...) _NM_IN_SET_EVAL_##n(op, x, __VA_ARGS__)
|
||||
#define _NM_IN_SET_EVAL_N(op, x, n, ...) _NM_IN_SET_EVAL_N2(op, x, n, __VA_ARGS__)
|
||||
|
||||
/* does not do short-circuit evaluation to get a more function-like behavior
|
||||
* ("|" instead of "||"). Use NM_IN_SET_SC() if you want that */
|
||||
#define NM_IN_SET(x, ...) _NM_IN_SET_EVAL_N(| , x, NM_NARG (__VA_ARGS__), __VA_ARGS__)
|
||||
|
||||
/* "SC" stands for "short-cirtuit". It will only evaluate the arguments
|
||||
* until a match is found. */
|
||||
#define NM_IN_SET_SC(x, ...) _NM_IN_SET_EVAL_N(||, x, NM_NARG (__VA_ARGS__), __VA_ARGS__)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define NM_PRINT_FMT_QUOTED(cond, prefix, str, suffix, str_else) \
|
||||
(cond) ? (prefix) : "", \
|
||||
(cond) ? (str) : (str_else), \
|
||||
|
|
|
|||
|
|
@ -4449,6 +4449,94 @@ test_nm_utils_ptrarray_find_binary_search (void)
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
static int
|
||||
_test_nm_in_set_get (int *call_counter, gboolean allow_called, int value)
|
||||
{
|
||||
g_assert (call_counter);
|
||||
*call_counter += 1;
|
||||
if (!allow_called)
|
||||
g_assert_not_reached ();
|
||||
return value;
|
||||
}
|
||||
|
||||
static void
|
||||
_test_nm_in_set_assert (int *call_counter, int expected)
|
||||
{
|
||||
g_assert (call_counter);
|
||||
g_assert_cmpint (expected, ==, *call_counter);
|
||||
*call_counter = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
test_nm_in_set (void)
|
||||
{
|
||||
int call_counter = 0;
|
||||
|
||||
#define G(x) _test_nm_in_set_get (&call_counter, TRUE, x)
|
||||
#define N(x) _test_nm_in_set_get (&call_counter, FALSE, x)
|
||||
#define _ASSERT(expected, expr) \
|
||||
G_STMT_START { \
|
||||
_test_nm_in_set_assert (&call_counter, 0); \
|
||||
g_assert (expr); \
|
||||
_test_nm_in_set_assert (&call_counter, (expected)); \
|
||||
} G_STMT_END
|
||||
_ASSERT (1, !NM_IN_SET (-1, G( 1)));
|
||||
_ASSERT (1, NM_IN_SET (-1, G(-1)));
|
||||
|
||||
_ASSERT (2, !NM_IN_SET (-1, G( 1), G( 2)));
|
||||
_ASSERT (2, NM_IN_SET (-1, G(-1), G( 2)));
|
||||
_ASSERT (2, NM_IN_SET (-1, G( 1), G(-1)));
|
||||
_ASSERT (2, NM_IN_SET (-1, G(-1), G(-1)));
|
||||
|
||||
_ASSERT (3, !NM_IN_SET (-1, G( 1), G( 2), G( 3)));
|
||||
_ASSERT (3, NM_IN_SET (-1, G(-1), G( 2), G( 3)));
|
||||
_ASSERT (3, NM_IN_SET (-1, G( 1), G(-1), G( 3)));
|
||||
_ASSERT (3, NM_IN_SET (-1, G( 1), G( 2), G(-1)));
|
||||
_ASSERT (3, NM_IN_SET (-1, G( 1), G(-1), G(-1)));
|
||||
_ASSERT (3, NM_IN_SET (-1, G(-1), G( 2), G(-1)));
|
||||
_ASSERT (3, NM_IN_SET (-1, G(-1), G(-1), G( 3)));
|
||||
_ASSERT (3, NM_IN_SET (-1, G(-1), G(-1), G(-1)));
|
||||
|
||||
_ASSERT (4, !NM_IN_SET (-1, G( 1), G( 2), G( 3), G( 4)));
|
||||
_ASSERT (4, NM_IN_SET (-1, G(-1), G( 2), G( 3), G( 4)));
|
||||
_ASSERT (4, NM_IN_SET (-1, G( 1), G(-1), G( 3), G( 4)));
|
||||
_ASSERT (4, NM_IN_SET (-1, G( 1), G( 2), G(-1), G( 4)));
|
||||
_ASSERT (4, NM_IN_SET (-1, G( 1), G( 2), G( 3), G(-1)));
|
||||
|
||||
_ASSERT (5, NM_IN_SET (-1, G( 1), G( 2), G( 3), G(-1), G( 5)));
|
||||
|
||||
_ASSERT (1, !NM_IN_SET_SC (-1, G( 1)));
|
||||
_ASSERT (1, NM_IN_SET_SC (-1, G(-1)));
|
||||
|
||||
_ASSERT (2, !NM_IN_SET_SC (-1, G( 1), G( 2)));
|
||||
_ASSERT (1, NM_IN_SET_SC (-1, G(-1), N( 2)));
|
||||
_ASSERT (2, NM_IN_SET_SC (-1, G( 1), G(-1)));
|
||||
_ASSERT (1, NM_IN_SET_SC (-1, G(-1), N(-1)));
|
||||
|
||||
_ASSERT (3, !NM_IN_SET_SC (-1, G( 1), G( 2), G( 3)));
|
||||
_ASSERT (1, NM_IN_SET_SC (-1, G(-1), N( 2), N( 3)));
|
||||
_ASSERT (2, NM_IN_SET_SC (-1, G( 1), G(-1), N( 3)));
|
||||
_ASSERT (3, NM_IN_SET_SC (-1, G( 1), G( 2), G(-1)));
|
||||
_ASSERT (2, NM_IN_SET_SC (-1, G( 1), G(-1), N(-1)));
|
||||
_ASSERT (1, NM_IN_SET_SC (-1, G(-1), N( 2), N(-1)));
|
||||
_ASSERT (1, NM_IN_SET_SC (-1, G(-1), N(-1), N( 3)));
|
||||
_ASSERT (1, NM_IN_SET_SC (-1, G(-1), N(-1), N(-1)));
|
||||
|
||||
_ASSERT (4, !NM_IN_SET_SC (-1, G( 1), G( 2), G( 3), G( 4)));
|
||||
_ASSERT (1, NM_IN_SET_SC (-1, G(-1), N( 2), N( 3), N( 4)));
|
||||
_ASSERT (2, NM_IN_SET_SC (-1, G( 1), G(-1), N( 3), N( 4)));
|
||||
_ASSERT (3, NM_IN_SET_SC (-1, G( 1), G( 2), G(-1), N( 4)));
|
||||
_ASSERT (4, NM_IN_SET_SC (-1, G( 1), G( 2), G( 3), G(-1)));
|
||||
|
||||
_ASSERT (4, NM_IN_SET_SC (-1, G( 1), G( 2), G( 3), G(-1), G( 5)));
|
||||
|
||||
#undef G
|
||||
#undef N
|
||||
#undef _ASSERT
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
NMTST_DEFINE ();
|
||||
|
||||
int main (int argc, char **argv)
|
||||
|
|
@ -4456,6 +4544,7 @@ int main (int argc, char **argv)
|
|||
nmtst_init (&argc, &argv, TRUE);
|
||||
|
||||
/* The tests */
|
||||
g_test_add_func ("/core/general/test_nm_in_set", test_nm_in_set);
|
||||
g_test_add_func ("/core/general/test_setting_vpn_items", test_setting_vpn_items);
|
||||
g_test_add_func ("/core/general/test_setting_vpn_update_secrets", test_setting_vpn_update_secrets);
|
||||
g_test_add_func ("/core/general/test_setting_vpn_modify_during_foreach", test_setting_vpn_modify_during_foreach);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue