diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index bc0bf39426..06456e6577 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -874,4 +874,13 @@ const char *nm_utils_wifi_freq_to_band (guint32 freq); gboolean _nm_utils_iaid_verify (const char *str, gint64 *out_value); +/*****************************************************************************/ + +gboolean _nmtst_variant_attribute_spec_assert_sorted (const NMVariantAttributeSpec *const*array, + gsize len); + +const NMVariantAttributeSpec *_nm_variant_attribute_spec_find_binary_search (const NMVariantAttributeSpec *const*array, + gsize len, + const char *name); + #endif diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c index f966a53743..0d7e9b0530 100644 --- a/libnm-core/nm-setting-ip-config.c +++ b/libnm-core/nm-setting-ip-config.c @@ -1197,21 +1197,21 @@ nm_ip_route_set_attribute (NMIPRoute *route, const char *name, GVariant *value) } static const NMVariantAttributeSpec *const ip_route_attribute_spec[] = { - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_TABLE, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_SRC, G_VARIANT_TYPE_STRING, .v4 = TRUE, .v6 = TRUE, .str_type = 'a', ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_FROM, G_VARIANT_TYPE_STRING, .v6 = TRUE, .str_type = 'p', ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_TOS, G_VARIANT_TYPE_BYTE, .v4 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_ONLINK, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_WINDOW, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_CWND, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_FROM, G_VARIANT_TYPE_STRING, .v6 = TRUE, .str_type = 'p', ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_INITCWND, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_INITRWND, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_MTU, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_MTU, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_ONLINK, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_SRC, G_VARIANT_TYPE_STRING, .v4 = TRUE, .v6 = TRUE, .str_type = 'a', ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_TABLE, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_TOS, G_VARIANT_TYPE_BYTE, .v4 = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_WINDOW, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ), NULL, }; @@ -1250,21 +1250,16 @@ nm_ip_route_attribute_validate (const char *name, gboolean *known, GError **error) { - const NMVariantAttributeSpec *const *iter; - const NMVariantAttributeSpec *spec = NULL; + const NMVariantAttributeSpec *spec; g_return_val_if_fail (name, FALSE); g_return_val_if_fail (value, FALSE); g_return_val_if_fail (family == AF_INET || family == AF_INET6, FALSE); g_return_val_if_fail (!error || !*error, FALSE); - for (iter = ip_route_attribute_spec; *iter; iter++) { - if (nm_streq (name, (*iter)->name)) { - spec = *iter; - break; - } - } - + spec = _nm_variant_attribute_spec_find_binary_search (ip_route_attribute_spec, + G_N_ELEMENTS (ip_route_attribute_spec) - 1, + name); if (!spec) { NM_SET_OUT (known, FALSE); g_set_error_literal (error, diff --git a/libnm-core/nm-setting-ip-config.h b/libnm-core/nm-setting-ip-config.h index 440ebe5a6c..feea89db22 100644 --- a/libnm-core/nm-setting-ip-config.h +++ b/libnm-core/nm-setting-ip-config.h @@ -127,21 +127,21 @@ gboolean nm_ip_route_attribute_validate (const char *name, gboolean *known, GError **error); -#define NM_IP_ROUTE_ATTRIBUTE_TABLE "table" -#define NM_IP_ROUTE_ATTRIBUTE_SRC "src" -#define NM_IP_ROUTE_ATTRIBUTE_FROM "from" -#define NM_IP_ROUTE_ATTRIBUTE_TOS "tos" -#define NM_IP_ROUTE_ATTRIBUTE_ONLINK "onlink" -#define NM_IP_ROUTE_ATTRIBUTE_WINDOW "window" #define NM_IP_ROUTE_ATTRIBUTE_CWND "cwnd" +#define NM_IP_ROUTE_ATTRIBUTE_FROM "from" #define NM_IP_ROUTE_ATTRIBUTE_INITCWND "initcwnd" #define NM_IP_ROUTE_ATTRIBUTE_INITRWND "initrwnd" -#define NM_IP_ROUTE_ATTRIBUTE_MTU "mtu" -#define NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW "lock-window" #define NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND "lock-cwnd" #define NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND "lock-initcwnd" #define NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND "lock-initrwnd" #define NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU "lock-mtu" +#define NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW "lock-window" +#define NM_IP_ROUTE_ATTRIBUTE_MTU "mtu" +#define NM_IP_ROUTE_ATTRIBUTE_ONLINK "onlink" +#define NM_IP_ROUTE_ATTRIBUTE_SRC "src" +#define NM_IP_ROUTE_ATTRIBUTE_TABLE "table" +#define NM_IP_ROUTE_ATTRIBUTE_TOS "tos" +#define NM_IP_ROUTE_ATTRIBUTE_WINDOW "window" /*****************************************************************************/ diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index c825bb12ba..347ef84093 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -5555,6 +5555,48 @@ attribute_unescape (const char *start, const char *end) return ret; } +gboolean +_nmtst_variant_attribute_spec_assert_sorted (const NMVariantAttributeSpec *const*array, + gsize len) +{ + gsize i; + + g_assert (array); + g_assert (len > 0); + g_assert_cmpint(len, ==, NM_PTRARRAY_LEN (array)); + + for (i = 0; i < len; i++) { + nm_assert (array[i]->name); + nm_assert (array[i]->name[0]); + if (i > 0) + nm_assert (strcmp (array[i - 1]->name, array[i]->name) < 0); + } + nm_assert (!array[i]); + + return TRUE; +} + +const NMVariantAttributeSpec * +_nm_variant_attribute_spec_find_binary_search (const NMVariantAttributeSpec *const*array, + gsize len, + const char *name) +{ + gssize idx; + + G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMVariantAttributeSpec, name) == 0); + + idx = nm_utils_ptrarray_find_binary_search ((gconstpointer *) array, + len, + &name, + nm_strcmp_p_with_data, + NULL, + NULL, + NULL); + if (idx < 0) + return NULL; + return array[idx]; +} + /** * nm_utils_parse_variant_attributes: * @string: the input string diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index 40eabc1208..cbc1a2f2ff 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -7986,6 +7986,33 @@ test_route_attributes_format (void) /*****************************************************************************/ +static void +test_variant_attribute_spec (void) +{ + const NMVariantAttributeSpec *const *const specs_list[] = { + nm_ip_route_get_variant_attribute_spec (), + }; + int i_specs; + + for (i_specs = 0; i_specs < G_N_ELEMENTS (specs_list); i_specs++) { + const NMVariantAttributeSpec *const *const specs = specs_list[i_specs]; + gsize len; + gsize i; + + g_assert (specs); + + len = NM_PTRARRAY_LEN (specs); + g_assert_cmpint (len, >, 0u); + + _nmtst_variant_attribute_spec_assert_sorted (specs, len); + for (i = 0; i < len; i++) + g_assert (specs[i] == _nm_variant_attribute_spec_find_binary_search (specs, len, specs[i]->name)); + g_assert (!_nm_variant_attribute_spec_find_binary_search (specs, len, "bogus")); + } +} + +/*****************************************************************************/ + static gboolean do_test_nm_set_out_called (int *call_count) { @@ -8448,6 +8475,7 @@ int main (int argc, char **argv) g_test_add_func ("/core/general/nm-set-out", test_nm_set_out); g_test_add_func ("/core/general/route_attributes/parse", test_route_attributes_parse); g_test_add_func ("/core/general/route_attributes/format", test_route_attributes_format); + g_test_add_func ("/core/general/test_variant_attribute_spec", test_variant_attribute_spec); g_test_add_func ("/core/general/get_start_time_for_pid", test_get_start_time_for_pid); g_test_add_func ("/core/general/test_nm_va_args_macros", test_nm_va_args_macros);