types FEATURE support boolean data types
diff --git a/src/plugins_types.c b/src/plugins_types.c
index 244b7ff..9b88174 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -349,6 +349,7 @@
return LY_EINVAL;
}
}
+
/**
* @brief Validate and canonize value of the YANG built-in signed integer types.
*
@@ -1014,6 +1015,75 @@
return LY_SUCCESS;
}
+/**
+ * @brief Validate value of the YANG built-in boolean type.
+ *
+ * Implementation of the ly_type_validate_clb.
+ */
+static LY_ERR
+ly_type_validate_boolean(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
+ const char **canonized, struct ly_err_item **err, void **priv)
+{
+ int8_t i;
+
+ if (value_len == 4 && !strncmp(value, "true", 4)) {
+ i = 1;
+ } else if (value_len == 5 && !strncmp(value, "false", 5)) {
+ i = 0;
+ } else {
+ char *errmsg;
+ asprintf(&errmsg, "Invalid boolean value \"%.*s\".", (int)value_len, value);
+ *err = ly_err_new(LY_LLERR, LY_EVALID, LYVE_RESTRICTION, errmsg, NULL, NULL);
+ return LY_EVALID;
+ }
+
+ if (options & LY_TYPE_OPTS_CANONIZE) {
+ if (i) {
+ *canonized = lydict_insert(ctx, "true", 4);
+ } else {
+ *canonized = lydict_insert(ctx, "false", 5);
+ }
+ }
+
+ if (options & LY_TYPE_OPTS_STORE) {
+ /* save for the store callback */
+ *priv = malloc(sizeof i);
+ if (!(*priv)) {
+ *err = ly_err_new(LY_LLERR, LY_EMEM, 0, "Memory allocation failed.", NULL, NULL);
+ return LY_EMEM;
+ }
+ *(int8_t*)(*priv) = i;
+ }
+
+ if (options & LY_TYPE_OPTS_DYNAMIC) {
+ free((char*)value);
+ }
+
+ return LY_SUCCESS;
+}
+
+/**
+ * @brief Store value of the YANG built-in boolean type.
+ *
+ * Implementation of the ly_type_store_clb.
+ */
+static LY_ERR
+ly_type_store_boolean(struct ly_ctx *UNUSED(ctx), struct lysc_type *UNUSED(type), int options,
+ struct lyd_value *value, struct ly_err_item **UNUSED(err), void **priv)
+{
+ if (options & LY_TYPE_OPTS_VALIDATE) {
+ /* the value was prepared by ly_type_validate_enum() */
+ value->boolean = *(int8_t*)(*priv);
+ free(*priv);
+ } else {
+ /* TODO if there is usecase for store without validate */
+ LOGINT(NULL);
+ return LY_EINT;
+ }
+
+ return LY_SUCCESS;
+}
+
struct lysc_type_plugin ly_builtin_type_plugins[LY_DATA_TYPE_COUNT] = {
{0}, /* LY_TYPE_UNKNOWN */
{.type = LY_TYPE_BINARY, .validate = ly_type_validate_binary, .store = NULL, .free = NULL},
@@ -1023,7 +1093,7 @@
{.type = LY_TYPE_UINT64, .validate = ly_type_validate_uint, .store = ly_type_store_uint, .free = NULL},
{.type = LY_TYPE_STRING, .validate = ly_type_validate_string, .store = NULL, .free = NULL},
{.type = LY_TYPE_BITS, .validate = ly_type_validate_bits, .store = ly_type_store_bits, .free = ly_type_free_bits},
- {0}, /* TODO LY_TYPE_BOOL */
+ {.type = LY_TYPE_BOOL, .validate = ly_type_validate_boolean, .store = ly_type_store_boolean, .free = NULL},
{.type = LY_TYPE_DEC64, .validate = ly_type_validate_decimal64, .store = ly_type_store_decimal64, .free = NULL},
{0}, /* TODO LY_TYPE_EMPTY */
{.type = LY_TYPE_ENUM, .validate = ly_type_validate_enum, .store = ly_type_store_enum, .free = NULL},
diff --git a/tests/features/test_types.c b/tests/features/test_types.c
index 329c150..536069d 100644
--- a/tests/features/test_types.c
+++ b/tests/features/test_types.c
@@ -72,7 +72,8 @@
"leaf dec64 {type decimal64 {fraction-digits 1; range 1.5..10;}}"
"leaf dec64-norestr {type decimal64 {fraction-digits 18;}}"
"leaf str {type string {length 8..10; pattern '[a-z ]*';}}"
- "leaf str-norestr {type string;}}";
+ "leaf str-norestr {type string;}"
+ "leaf bool {type boolean;}}";
s = calloc(1, sizeof *s);
assert_non_null(s);
@@ -507,6 +508,46 @@
s->func = NULL;
}
+static void
+test_boolean(void **state)
+{
+ struct state_s *s = (struct state_s*)(*state);
+ s->func = test_boolean;
+
+ struct lyd_node *tree;
+ struct lyd_node_term *leaf;
+
+ const char *data = "<bool xmlns=\"urn:tests:types\">true</bool>";
+
+ /* valid data */
+ assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, 0));
+ assert_int_equal(LYS_LEAF, tree->schema->nodetype);
+ assert_string_equal("bool", tree->schema->name);
+ leaf = (struct lyd_node_term*)tree;
+ assert_string_equal("true", leaf->value.canonized);
+ assert_int_equal(1, leaf->value.boolean);
+ lyd_free_all(tree);
+
+ data = "<bool xmlns=\"urn:tests:types\">false</bool>";
+ assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, 0));
+ assert_int_equal(LYS_LEAF, tree->schema->nodetype);
+ assert_string_equal("bool", tree->schema->name);
+ leaf = (struct lyd_node_term*)tree;
+ assert_string_equal("false", leaf->value.canonized);
+ assert_int_equal(0, leaf->value.boolean);
+ lyd_free_all(tree);
+
+ /* invalid value */
+ data = "<bool xmlns=\"urn:tests:types\">unsure</bool>";
+ assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, 0));
+ logbuf_assert("Invalid boolean value \"unsure\". /");
+
+ data = "<bool xmlns=\"urn:tests:types\"> true</bool>";
+ assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, 0));
+ logbuf_assert("Invalid boolean value \" true\". /");
+
+ s->func = NULL;
+}
int main(void)
{
@@ -518,6 +559,7 @@
cmocka_unit_test_setup_teardown(test_bits, setup, teardown),
cmocka_unit_test_setup_teardown(test_enums, setup, teardown),
cmocka_unit_test_setup_teardown(test_binary, setup, teardown),
+ cmocka_unit_test_setup_teardown(test_boolean, setup, teardown),
};
return cmocka_run_group_tests(tests, NULL, NULL);