diff --git a/src/tree_data.h b/src/tree_data.h index fd8137c40a..89c19fc7c6 100644 --- a/src/tree_data.h +++ b/src/tree_data.h @@ -1529,6 +1529,12 @@ LIBYANG_API_DECL LY_ERR lyd_new_attr2(struct lyd_node *parent, const char *modul to unexpected behavior. */ #define LYD_NEW_PATH_WITH_OPAQ 0x20 /**< Consider opaque nodes normally when searching for existing nodes. */ +#define LYD_NEW_PATH_JSON_VALUE 0x40 /**< Interpret the provided leaf/leaf-list @p value as being in the JSON format. + Specifically, strings are quoted as per IETF rfc 8259 + `string = quotation-mark *char quotation-mark` + Example, `const char * data = "\"Great View\"";` should be processed as + `const value = "Great View";` */ + /** @} pathoptions */ /** diff --git a/src/tree_data_new.c b/src/tree_data_new.c index 66c35f34dd..762cddeb11 100644 --- a/src/tree_data_new.c +++ b/src/tree_data_new.c @@ -1616,6 +1616,7 @@ lyd_new_path_(struct lyd_node *parent, const struct ly_ctx *ctx, const struct ly const struct lyd_value *val = NULL; LY_ARRAY_COUNT_TYPE path_idx = 0, orig_count = 0; LY_VALUE_FORMAT format; + const char *str_value = value; assert(parent || ctx); assert(path && ((path[0] == '/') || parent)); @@ -1627,6 +1628,16 @@ lyd_new_path_(struct lyd_node *parent, const struct ly_ctx *ctx, const struct ly if (value && !value_len) { value_len = strlen(value); } + if (options & LYD_NEW_PATH_JSON_VALUE) { + /* if it starts and ends in double-quotes, it can only be a string value */ + if ((value_len > 1) && str_value && + ('"' == str_value[0]) && ('"' == str_value[value_len - 1])) { + /* remove the quotes */ + value = ++str_value; + value_len -= 2; + } + } + if (options & LYD_NEW_PATH_BIN_VALUE) { format = LY_VALUE_LYB; } else if (options & LYD_NEW_PATH_CANON_VALUE) { diff --git a/tests/utests/data/test_new.c b/tests/utests/data/test_new.c index 5cee9032ec..30c963b5d4 100644 --- a/tests/utests/data/test_new.c +++ b/tests/utests/data/test_new.c @@ -495,6 +495,41 @@ test_path_ext(void **state) lyd_free_tree(root); } +static void +test_path_json_val(void **state) +{ + LY_ERR ret; + struct ly_ctx *ctx; + struct lyd_node *root, *node, *parent; + struct lys_module *mod; + LYD_ANYDATA_VALUETYPE type = LYD_ANYDATA_STRING; + uint32_t opts[2] = {LYD_NEW_PATH_JSON_VALUE, 0}; + char *val[5][2] = {{"val", "\"val\""}, {"val2", "\"val2\""}, {"val3", "\"val3\""}, {"val4", "val4"}, {"", "\"\""}}; + char *exp_val[5][2] = {{"val", "val"}, {"val2", "\"val2\""}, {"val3", "\"val3\""}, {"val4", "val4"}, {"", "\"\""}}; + char *path[5] = {"/a:c/x[.='val']", "/a:c/x", "x", "x", "x"}; + + int i, j; + UTEST_ADD_MODULE(schema_a, LYS_IN_YANG, NULL, &mod); + + for (i = 0; i < 2; i++) { + root = node = parent = NULL; + ctx = UTEST_LYCTX; + + for (j = 0; j < 5; j++) { + ret = lyd_new_path2(root, ctx, path[j], val[j][i], 0, type, opts[i], root ? &parent : &root, &node); + assert_int_equal(ret, LY_SUCCESS); + assert_non_null(root); + assert_string_equal(root->schema->name, "c"); + assert_non_null(node); + assert_string_equal(node->schema->name, "x"); + assert_string_equal(lyd_get_value(node), exp_val[j][i]); + node = NULL; + ctx = NULL; + } + lyd_free_tree(root); + } +} + int main(void) { @@ -503,6 +538,7 @@ main(void) UTEST(test_opaq), UTEST(test_path), UTEST(test_path_ext), + UTEST(test_path_json_val), }; return cmocka_run_group_tests(tests, NULL, NULL);