plugins types FEATURE sort callback in inet_types
diff --git a/src/plugins_types/ipv4_address.c b/src/plugins_types/ipv4_address.c
index 946968c..b1a0636 100644
--- a/src/plugins_types/ipv4_address.c
+++ b/src/plugins_types/ipv4_address.c
@@ -14,6 +14,7 @@
#define _GNU_SOURCE /* strndup */
+#include "plugins_internal.h"
#include "plugins_types.h"
#ifdef _WIN32
@@ -226,6 +227,35 @@
}
/**
+ * @brief Implementation of ::lyplg_type_sort_clb for the ipv4-address ietf-inet-types type.
+ */
+static int
+lyplg_type_sort_ipv4_address(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1,
+ const struct lyd_value *val2)
+{
+ struct lyd_value_ipv4_address *v1, *v2;
+ int cmp;
+
+ LYD_VALUE_GET(val1, v1);
+ LYD_VALUE_GET(val2, v2);
+
+ cmp = memcmp(&v1->addr, &v2->addr, sizeof v1->addr);
+ if (cmp != 0) {
+ return cmp;
+ }
+
+ if (!v1->zone && v2->zone) {
+ return -1;
+ } else if (v1->zone && !v2->zone) {
+ return 1;
+ } else if (v1->zone && v2->zone) {
+ return strcmp(v1->zone, v2->zone);
+ }
+
+ return 0;
+}
+
+/**
* @brief Implementation of ::lyplg_type_print_clb for the ipv4-address ietf-inet-types type.
*/
static const void *
@@ -364,7 +394,7 @@
.plugin.store = lyplg_type_store_ipv4_address,
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_ipv4_address,
- .plugin.sort = NULL,
+ .plugin.sort = lyplg_type_sort_ipv4_address,
.plugin.print = lyplg_type_print_ipv4_address,
.plugin.duplicate = lyplg_type_dup_ipv4_address,
.plugin.free = lyplg_type_free_ipv4_address,
diff --git a/src/plugins_types/ipv4_address_no_zone.c b/src/plugins_types/ipv4_address_no_zone.c
index 67db22b..5476c19 100644
--- a/src/plugins_types/ipv4_address_no_zone.c
+++ b/src/plugins_types/ipv4_address_no_zone.c
@@ -14,6 +14,7 @@
#define _GNU_SOURCE /* strndup */
+#include "plugins_internal.h"
#include "plugins_types.h"
#ifdef _WIN32
@@ -26,6 +27,7 @@
# include <sys/socket.h>
# endif
#endif
+#include <assert.h>
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
@@ -143,6 +145,21 @@
}
/**
+ * @brief Implementation of ::lyplg_type_sort_clb for the ipv4-address-no-zone ietf-inet-types type.
+ */
+static int
+lyplg_type_sort_ipv4_address_no_zone(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1,
+ const struct lyd_value *val2)
+{
+ struct lyd_value_ipv4_address_no_zone *v1, *v2;
+
+ LYD_VALUE_GET(val1, v1);
+ LYD_VALUE_GET(val2, v2);
+
+ return memcmp(&v1->addr, &v2->addr, sizeof v1->addr);
+}
+
+/**
* @brief Implementation of ::lyplg_type_print_clb for the ipv4-address-no-zone ietf-inet-types type.
*/
static const void *
@@ -208,7 +225,7 @@
.plugin.store = lyplg_type_store_ipv4_address_no_zone,
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_ipv4_address_no_zone,
- .plugin.sort = NULL,
+ .plugin.sort = lyplg_type_sort_ipv4_address_no_zone,
.plugin.print = lyplg_type_print_ipv4_address_no_zone,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple,
diff --git a/src/plugins_types/ipv4_prefix.c b/src/plugins_types/ipv4_prefix.c
index d4fb785..2a86f36 100644
--- a/src/plugins_types/ipv4_prefix.c
+++ b/src/plugins_types/ipv4_prefix.c
@@ -14,6 +14,7 @@
#define _GNU_SOURCE /* strndup */
+#include "plugins_internal.h"
#include "plugins_types.h"
#ifdef _WIN32
@@ -26,6 +27,7 @@
# include <sys/socket.h>
# endif
#endif
+#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -214,6 +216,21 @@
}
/**
+ * @brief Implementation of ::lyplg_type_sort_clb for the ietf-inet-types ipv4-prefix type.
+ */
+static int
+lyplg_type_sort_ipv4_prefix(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1,
+ const struct lyd_value *val2)
+{
+ struct lyd_value_ipv4_prefix *v1, *v2;
+
+ LYD_VALUE_GET(val1, v1);
+ LYD_VALUE_GET(val2, v2);
+
+ return memcmp(v1, v2, sizeof *v1);
+}
+
+/**
* @brief Implementation of ::lyplg_type_compare_clb for the ietf-inet-types ipv4-prefix type.
*/
static const void *
@@ -324,7 +341,7 @@
.plugin.store = lyplg_type_store_ipv4_prefix,
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_ipv4_prefix,
- .plugin.sort = NULL,
+ .plugin.sort = lyplg_type_sort_ipv4_prefix,
.plugin.print = lyplg_type_print_ipv4_prefix,
.plugin.duplicate = lyplg_type_dup_ipv4_prefix,
.plugin.free = lyplg_type_free_ipv4_prefix,
diff --git a/src/plugins_types/ipv6_address.c b/src/plugins_types/ipv6_address.c
index 9a2c31a..031bb8f 100644
--- a/src/plugins_types/ipv6_address.c
+++ b/src/plugins_types/ipv6_address.c
@@ -14,6 +14,7 @@
#define _GNU_SOURCE /* strndup */
+#include "plugins_internal.h"
#include "plugins_types.h"
#ifdef _WIN32
@@ -26,6 +27,7 @@
# include <sys/socket.h>
# endif
#endif
+#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <stdint.h>
@@ -228,6 +230,35 @@
}
/**
+ * @brief Implementation of ::lyplg_type_sort_clb for the ipv6-address ietf-inet-types type.
+ */
+static int
+lyplg_type_sort_ipv6_address(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1,
+ const struct lyd_value *val2)
+{
+ struct lyd_value_ipv6_address *v1, *v2;
+ int cmp;
+
+ LYD_VALUE_GET(val1, v1);
+ LYD_VALUE_GET(val2, v2);
+
+ cmp = memcmp(&v1->addr, &v2->addr, sizeof v1->addr);
+ if (cmp != 0) {
+ return cmp;
+ }
+
+ if (!v1->zone && v2->zone) {
+ return -1;
+ } else if (v1->zone && !v2->zone) {
+ return 1;
+ } else if (v1->zone && v2->zone) {
+ return strcmp(v1->zone, v2->zone);
+ }
+
+ return 0;
+}
+
+/**
* @brief Implementation of ::lyplg_type_print_clb for the ipv6-address ietf-inet-types type.
*/
static const void *
@@ -365,7 +396,7 @@
.plugin.store = lyplg_type_store_ipv6_address,
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_ipv6_address,
- .plugin.sort = NULL,
+ .plugin.sort = lyplg_type_sort_ipv6_address,
.plugin.print = lyplg_type_print_ipv6_address,
.plugin.duplicate = lyplg_type_dup_ipv6_address,
.plugin.free = lyplg_type_free_ipv6_address,
diff --git a/src/plugins_types/ipv6_address_no_zone.c b/src/plugins_types/ipv6_address_no_zone.c
index 56e0760..6b4f0e6 100644
--- a/src/plugins_types/ipv6_address_no_zone.c
+++ b/src/plugins_types/ipv6_address_no_zone.c
@@ -14,6 +14,7 @@
#define _GNU_SOURCE /* strndup */
+#include "plugins_internal.h"
#include "plugins_types.h"
#ifdef _WIN32
@@ -26,6 +27,7 @@
# include <sys/socket.h>
# endif
#endif
+#include <assert.h>
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
@@ -191,6 +193,21 @@
}
/**
+ * @brief Implementation of ::lyplg_type_sort_clb for the ipv6-address-no-zone ietf-inet-types type.
+ */
+static int
+lyplg_type_sort_ipv6_address_no_zone(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1,
+ const struct lyd_value *val2)
+{
+ struct lyd_value_ipv6_address_no_zone *v1, *v2;
+
+ LYD_VALUE_GET(val1, v1);
+ LYD_VALUE_GET(val2, v2);
+
+ return memcmp(&v1->addr, &v2->addr, sizeof v1->addr);
+}
+
+/**
* @brief Implementation of ::lyplg_type_print_clb for the ipv6-address-no-zone ietf-inet-types type.
*/
static const void *
@@ -299,7 +316,7 @@
.plugin.store = lyplg_type_store_ipv6_address_no_zone,
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_ipv6_address_no_zone,
- .plugin.sort = NULL,
+ .plugin.sort = lyplg_type_sort_ipv6_address_no_zone,
.plugin.print = lyplg_type_print_ipv6_address_no_zone,
.plugin.duplicate = lyplg_type_dup_ipv6_address_no_zone,
.plugin.free = lyplg_type_free_ipv6_address_no_zone,
diff --git a/src/plugins_types/ipv6_prefix.c b/src/plugins_types/ipv6_prefix.c
index d6823ad..05b1be7 100644
--- a/src/plugins_types/ipv6_prefix.c
+++ b/src/plugins_types/ipv6_prefix.c
@@ -14,6 +14,7 @@
#define _GNU_SOURCE /* strndup */
+#include "plugins_internal.h"
#include "plugins_types.h"
#ifdef _WIN32
@@ -26,6 +27,7 @@
# include <sys/socket.h>
# endif
#endif
+#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -228,6 +230,21 @@
}
/**
+ * @brief Implementation of ::lyplg_type_sort_clb for the ietf-inet-types ipv6-prefix type.
+ */
+static int
+lyplg_type_sort_ipv6_prefix(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1,
+ const struct lyd_value *val2)
+{
+ struct lyd_value_ipv6_prefix *v1, *v2;
+
+ LYD_VALUE_GET(val1, v1);
+ LYD_VALUE_GET(val2, v2);
+
+ return memcmp(v1, v2, sizeof *v1);
+}
+
+/**
* @brief Implementation of ::lyplg_type_compare_clb for the ietf-inet-types ipv6-prefix type.
*/
static const void *
@@ -338,7 +355,7 @@
.plugin.store = lyplg_type_store_ipv6_prefix,
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_ipv6_prefix,
- .plugin.sort = NULL,
+ .plugin.sort = lyplg_type_sort_ipv6_prefix,
.plugin.print = lyplg_type_print_ipv6_prefix,
.plugin.duplicate = lyplg_type_dup_ipv6_prefix,
.plugin.free = lyplg_type_free_ipv6_prefix,
diff --git a/tests/utests/types/inet_types.c b/tests/utests/types/inet_types.c
index eb4e480..3874cc3 100644
--- a/tests/utests/types/inet_types.c
+++ b/tests/utests/types/inet_types.c
@@ -137,12 +137,147 @@
TEST_SUCCESS_LYB("lyb", "l7", "::C:D:E:f:a/112");
}
+static void
+test_plugin_sort(void **state)
+{
+ const char *v1, *v2;
+ const char *schema;
+ struct lys_module *mod;
+ struct lyd_value val1 = {0}, val2 = {0};
+ struct lyplg_type *type = lyplg_type_plugin_find("", NULL, ly_data_type2str[LY_TYPE_UNION]);
+ struct lysc_type *lysc_type;
+ struct ly_err_item *err = NULL;
+
+ schema = MODULE_CREATE_YANG("a",
+ "leaf l {type inet:ip-address;}"
+ "leaf l2 {type inet:ipv6-address;}"
+ "leaf l3 {type inet:ip-address-no-zone;}"
+ "leaf l4 {type inet:ipv6-address-no-zone;}"
+ "leaf l5 {type inet:ipv4-prefix;}"
+ "leaf l6 {type inet:ipv6-prefix;}");
+ UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
+
+ /* ipv4-address */
+ lysc_type = ((struct lysc_node_leaf *)mod->compiled->data)->type;
+
+ v1 = "192.168.0.1";
+ assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
+ 0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
+ v2 = "192.168.0.2";
+ assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
+ 0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
+ assert_true(0 > type->sort(UTEST_LYCTX, &val1, &val2));
+ assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
+ assert_true(0 < type->sort(UTEST_LYCTX, &val2, &val1));
+ type->free(UTEST_LYCTX, &val1);
+ type->free(UTEST_LYCTX, &val2);
+
+ v1 = "192.168.0.1%1A";
+ assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
+ 0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
+ v2 = "192.168.0.1";
+ assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
+ 0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
+ assert_true(0 < type->sort(UTEST_LYCTX, &val1, &val2));
+ assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
+ assert_true(0 > type->sort(UTEST_LYCTX, &val2, &val1));
+ type->free(UTEST_LYCTX, &val1);
+ type->free(UTEST_LYCTX, &val2);
+
+ /* ipv6-address */
+ lysc_type = ((struct lysc_node_leaflist *)mod->compiled->data->next)->type;
+ type = lyplg_type_plugin_find("", NULL, ly_data_type2str[LY_TYPE_STRING]);
+
+ v1 = "2008:15:0:0:0:0:feAC:1";
+ assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
+ 0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
+ v2 = "2008:15::feac:2";
+ assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
+ 0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
+ assert_true(0 > type->sort(UTEST_LYCTX, &val1, &val2));
+ assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
+ assert_true(0 < type->sort(UTEST_LYCTX, &val2, &val1));
+ type->free(UTEST_LYCTX, &val1);
+ type->free(UTEST_LYCTX, &val2);
+
+ v1 = "FAAC:21:011:Da85::87:daaF%1";
+ assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
+ 0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
+ v2 = "FAAC:21:011:Da85::87:daaF%14";
+ assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
+ 0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
+ assert_true(0 > type->sort(UTEST_LYCTX, &val1, &val2));
+ assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
+ assert_true(0 < type->sort(UTEST_LYCTX, &val2, &val1));
+ type->free(UTEST_LYCTX, &val1);
+ type->free(UTEST_LYCTX, &val2);
+
+ /* ipv4-address-no-zone */
+ lysc_type = ((struct lysc_node_leaflist *)mod->compiled->data->next->next)->type;
+ type = lyplg_type_plugin_find("", NULL, ly_data_type2str[LY_TYPE_UNION]);
+ v1 = "127.0.0.1";
+ assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
+ 0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
+ v2 = "127.0.1.1";
+ assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
+ 0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
+ assert_true(0 > type->sort(UTEST_LYCTX, &val1, &val2));
+ assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
+ assert_true(0 < type->sort(UTEST_LYCTX, &val2, &val1));
+ type->free(UTEST_LYCTX, &val1);
+ type->free(UTEST_LYCTX, &val2);
+
+ /* ipv6-address-no-zone */
+ lysc_type = ((struct lysc_node_leaflist *)mod->compiled->data->next->next->next)->type;
+ type = lyplg_type_plugin_find("", NULL, ly_data_type2str[LY_TYPE_STRING]);
+ v1 = "A:B:c:D:e:f:1:1";
+ assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
+ 0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
+ v2 = "A:B:c:D:e:f:1:0";
+ assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
+ 0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
+ assert_true(0 < type->sort(UTEST_LYCTX, &val1, &val2));
+ assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
+ assert_true(0 > type->sort(UTEST_LYCTX, &val2, &val1));
+ type->free(UTEST_LYCTX, &val1);
+ type->free(UTEST_LYCTX, &val2);
+
+ /* ipv4-prefix */
+ lysc_type = ((struct lysc_node_leaflist *)mod->compiled->data->next->next->next->next)->type;
+ v1 = "0.1.58.4/32";
+ assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
+ 0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
+ v2 = "0.1.58.4/16";
+ assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
+ 0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
+ assert_true(0 < type->sort(UTEST_LYCTX, &val1, &val2));
+ assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
+ assert_true(0 > type->sort(UTEST_LYCTX, &val2, &val1));
+ type->free(UTEST_LYCTX, &val1);
+ type->free(UTEST_LYCTX, &val2);
+
+ /* ipv6-prefix */
+ lysc_type = ((struct lysc_node_leaflist *)mod->compiled->data->next->next->next->next->next)->type;
+ v1 = "::C:D:E:f:a/96";
+ assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
+ 0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
+ v2 = "::C:D:E:f:a/112";
+ assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
+ 0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
+ assert_true(0 < type->sort(UTEST_LYCTX, &val1, &val2));
+ assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
+ assert_true(0 > type->sort(UTEST_LYCTX, &val2, &val1));
+ type->free(UTEST_LYCTX, &val1);
+ type->free(UTEST_LYCTX, &val2);
+}
+
int
main(void)
{
const struct CMUnitTest tests[] = {
UTEST(test_data_xml),
UTEST(test_data_lyb),
+ UTEST(test_plugin_sort),
};
return cmocka_run_group_tests(tests, NULL, NULL);