|
Packit |
8fb591 |
/**
|
|
Packit |
8fb591 |
* @file common.c
|
|
Packit |
8fb591 |
* @author Radek Krejci <rkrejci@cesnet.cz>
|
|
Packit |
8fb591 |
* @brief common libyang routines implementations
|
|
Packit |
8fb591 |
*
|
|
Packit |
8fb591 |
* Copyright (c) 2015 - 2017 CESNET, z.s.p.o.
|
|
Packit |
8fb591 |
*
|
|
Packit |
8fb591 |
* This source code is licensed under BSD 3-Clause License (the "License").
|
|
Packit |
8fb591 |
* You may not use this file except in compliance with the License.
|
|
Packit |
8fb591 |
* You may obtain a copy of the License at
|
|
Packit |
8fb591 |
*
|
|
Packit |
8fb591 |
* https://opensource.org/licenses/BSD-3-Clause
|
|
Packit |
8fb591 |
*/
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
#define _GNU_SOURCE
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
#include <assert.h>
|
|
Packit |
8fb591 |
#include <ctype.h>
|
|
Packit |
8fb591 |
#include <errno.h>
|
|
Packit |
8fb591 |
#include <limits.h>
|
|
Packit |
8fb591 |
#include <pthread.h>
|
|
Packit |
8fb591 |
#include <string.h>
|
|
Packit |
8fb591 |
#include <stdlib.h>
|
|
Packit |
8fb591 |
#include <sys/syscall.h>
|
|
Packit |
8fb591 |
#include <sys/types.h>
|
|
Packit |
8fb591 |
#include <unistd.h>
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
#include "common.h"
|
|
Packit |
8fb591 |
#include "parser.h"
|
|
Packit |
8fb591 |
#include "xpath.h"
|
|
Packit |
8fb591 |
#include "context.h"
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
THREAD_LOCAL enum int_log_opts log_opt;
|
|
Packit |
8fb591 |
THREAD_LOCAL int8_t ly_errno_glob;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
API LY_ERR *
|
|
Packit |
8fb591 |
ly_errno_glob_address(void)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
return (LY_ERR *)&ly_errno_glob;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
API LY_VECODE
|
|
Packit |
8fb591 |
ly_vecode(const struct ly_ctx *ctx)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
struct ly_err_item *i;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
i = ly_err_first(ctx);
|
|
Packit |
8fb591 |
if (i) {
|
|
Packit |
8fb591 |
return i->prev->vecode;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
API const char *
|
|
Packit |
8fb591 |
ly_errmsg(const struct ly_ctx *ctx)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
struct ly_err_item *i;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
i = ly_err_first(ctx);
|
|
Packit |
8fb591 |
if (i) {
|
|
Packit |
8fb591 |
return i->prev->msg;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
API const char *
|
|
Packit |
8fb591 |
ly_errpath(const struct ly_ctx *ctx)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
struct ly_err_item *i;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
i = ly_err_first(ctx);
|
|
Packit |
8fb591 |
if (i) {
|
|
Packit |
8fb591 |
return i->prev->path;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
API const char *
|
|
Packit |
8fb591 |
ly_errapptag(const struct ly_ctx *ctx)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
struct ly_err_item *i;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
i = ly_err_first(ctx);
|
|
Packit |
8fb591 |
if (i) {
|
|
Packit |
8fb591 |
return i->prev->apptag;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
API struct ly_err_item *
|
|
Packit |
8fb591 |
ly_err_first(const struct ly_ctx *ctx)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
if (!ctx) {
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return pthread_getspecific(ctx->errlist_key);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
void
|
|
Packit |
8fb591 |
ly_err_free(void *ptr)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
struct ly_err_item *i, *next;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* clean the error list */
|
|
Packit |
8fb591 |
for (i = (struct ly_err_item *)ptr; i; i = next) {
|
|
Packit |
8fb591 |
next = i->next;
|
|
Packit |
8fb591 |
free(i->msg);
|
|
Packit |
8fb591 |
free(i->path);
|
|
Packit |
8fb591 |
free(i->apptag);
|
|
Packit |
8fb591 |
free(i);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
API void
|
|
Packit |
8fb591 |
ly_err_clean(struct ly_ctx *ctx, struct ly_err_item *eitem)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
struct ly_err_item *i, *first;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
first = ly_err_first(ctx);
|
|
Packit |
8fb591 |
if (first == eitem) {
|
|
Packit |
8fb591 |
eitem = NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
if (eitem) {
|
|
Packit |
8fb591 |
/* disconnect the error */
|
|
Packit |
8fb591 |
for (i = first; i && (i->next != eitem); i = i->next);
|
|
Packit |
8fb591 |
assert(i);
|
|
Packit |
8fb591 |
i->next = NULL;
|
|
Packit |
8fb591 |
first->prev = i;
|
|
Packit |
8fb591 |
/* free this err and newer */
|
|
Packit |
8fb591 |
ly_err_free(eitem);
|
|
Packit |
8fb591 |
/* update errno */
|
|
Packit |
8fb591 |
ly_errno = i->no;
|
|
Packit |
8fb591 |
} else {
|
|
Packit |
8fb591 |
/* free all err */
|
|
Packit |
8fb591 |
ly_err_free(first);
|
|
Packit |
8fb591 |
pthread_setspecific(ctx->errlist_key, NULL);
|
|
Packit |
8fb591 |
/* also clean errno */
|
|
Packit |
8fb591 |
ly_errno = LY_SUCCESS;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
#ifndef __USE_GNU
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
char *
|
|
Packit |
8fb591 |
get_current_dir_name(void)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
char tmp[PATH_MAX];
|
|
Packit |
8fb591 |
char *retval;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (getcwd(tmp, sizeof(tmp))) {
|
|
Packit |
8fb591 |
retval = strdup(tmp);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_RETURN(!retval, LOGMEM(NULL), NULL);
|
|
Packit |
8fb591 |
return retval;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
#endif
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
const char *
|
|
Packit |
8fb591 |
strpbrk_backwards(const char *s, const char *accept, unsigned int s_len)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
const char *sc;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
for (; *s != '\0' && s_len; --s, --s_len) {
|
|
Packit |
8fb591 |
for (sc = accept; *sc != '\0'; ++sc) {
|
|
Packit |
8fb591 |
if (*s == *sc) {
|
|
Packit |
8fb591 |
return s;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
return s;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
char *
|
|
Packit |
8fb591 |
strnchr(const char *s, int c, unsigned int len)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
for (; *s != (char)c; ++s, --len) {
|
|
Packit |
8fb591 |
if ((*s == '\0') || (!len)) {
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
return (char *)s;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
const char *
|
|
Packit |
8fb591 |
strnodetype(LYS_NODE type)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
switch (type) {
|
|
Packit |
8fb591 |
case LYS_UNKNOWN:
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
case LYS_AUGMENT:
|
|
Packit |
8fb591 |
return "augment";
|
|
Packit |
8fb591 |
case LYS_CONTAINER:
|
|
Packit |
8fb591 |
return "container";
|
|
Packit |
8fb591 |
case LYS_CHOICE:
|
|
Packit |
8fb591 |
return "choice";
|
|
Packit |
8fb591 |
case LYS_LEAF:
|
|
Packit |
8fb591 |
return "leaf";
|
|
Packit |
8fb591 |
case LYS_LEAFLIST:
|
|
Packit |
8fb591 |
return "leaf-list";
|
|
Packit |
8fb591 |
case LYS_LIST:
|
|
Packit |
8fb591 |
return "list";
|
|
Packit |
8fb591 |
case LYS_ANYXML:
|
|
Packit |
8fb591 |
return "anyxml";
|
|
Packit |
8fb591 |
case LYS_GROUPING:
|
|
Packit |
8fb591 |
return "grouping";
|
|
Packit |
8fb591 |
case LYS_CASE:
|
|
Packit |
8fb591 |
return "case";
|
|
Packit |
8fb591 |
case LYS_INPUT:
|
|
Packit |
8fb591 |
return "input";
|
|
Packit |
8fb591 |
case LYS_OUTPUT:
|
|
Packit |
8fb591 |
return "output";
|
|
Packit |
8fb591 |
case LYS_NOTIF:
|
|
Packit |
8fb591 |
return "notification";
|
|
Packit |
8fb591 |
case LYS_RPC:
|
|
Packit |
8fb591 |
return "rpc";
|
|
Packit |
8fb591 |
case LYS_USES:
|
|
Packit |
8fb591 |
return "uses";
|
|
Packit |
8fb591 |
case LYS_ACTION:
|
|
Packit |
8fb591 |
return "action";
|
|
Packit |
8fb591 |
case LYS_ANYDATA:
|
|
Packit |
8fb591 |
return "anydata";
|
|
Packit |
8fb591 |
case LYS_EXT:
|
|
Packit |
8fb591 |
return "extension instance";
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
const char *
|
|
Packit |
8fb591 |
transform_module_name2import_prefix(const struct lys_module *module, const char *module_name)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
uint16_t i;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (!module_name) {
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (!strcmp(lys_main_module(module)->name, module_name)) {
|
|
Packit |
8fb591 |
/* the same for module and submodule */
|
|
Packit |
8fb591 |
return module->prefix;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
for (i = 0; i < module->imp_size; ++i) {
|
|
Packit |
8fb591 |
if (!strcmp(module->imp[i].module->name, module_name)) {
|
|
Packit |
8fb591 |
return module->imp[i].prefix;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
_transform_json2xml_subexp(const struct lys_module *module, const char *expr, char **out, size_t *out_used, size_t *out_size, int schema, int inst_id, const char ***prefixes,
|
|
Packit |
8fb591 |
const char ***namespaces, uint32_t *ns_count)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
const char *cur_expr, *end, *prefix, *literal;
|
|
Packit |
8fb591 |
char *name;
|
|
Packit |
8fb591 |
size_t name_len;
|
|
Packit |
8fb591 |
const struct lys_module *mod = NULL, *prev_mod = NULL;
|
|
Packit |
8fb591 |
uint32_t i, j;
|
|
Packit |
8fb591 |
struct lyxp_expr *exp;
|
|
Packit |
8fb591 |
struct ly_ctx *ctx = module->ctx;
|
|
Packit |
8fb591 |
enum int_log_opts prev_ilo;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
assert(module && expr && ((!prefixes && !namespaces && !ns_count) || (prefixes && namespaces && ns_count)));
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
exp = lyxp_parse_expr(ctx, expr);
|
|
Packit |
8fb591 |
LY_CHECK_RETURN(!exp, 1);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
for (i = 0; i < exp->used; ++i) {
|
|
Packit |
8fb591 |
cur_expr = &exp->expr[exp->expr_pos[i]];
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy WS */
|
|
Packit |
8fb591 |
if (i && ((end = exp->expr + exp->expr_pos[i - 1] + exp->tok_len[i - 1]) != cur_expr)) {
|
|
Packit |
8fb591 |
strncpy(&(*out)[*out_used], end, cur_expr - end);
|
|
Packit |
8fb591 |
(*out_used) += cur_expr - end;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if ((exp->tokens[i] == LYXP_TOKEN_NAMETEST) && ((end = strnchr(cur_expr, ':', exp->tok_len[i])) || inst_id)) {
|
|
Packit |
8fb591 |
/* get the module */
|
|
Packit |
8fb591 |
if (!schema) {
|
|
Packit |
8fb591 |
if (end) {
|
|
Packit |
8fb591 |
name_len = end - cur_expr;
|
|
Packit |
8fb591 |
name = strndup(cur_expr, name_len);
|
|
Packit |
8fb591 |
mod = ly_ctx_get_module(module->ctx, name, NULL, 0);
|
|
Packit |
8fb591 |
if (module->ctx->data_clb) {
|
|
Packit |
8fb591 |
if (!mod) {
|
|
Packit |
8fb591 |
mod = module->ctx->data_clb(module->ctx, name, NULL, 0, module->ctx->data_clb_data);
|
|
Packit |
8fb591 |
} else if (!mod->implemented) {
|
|
Packit |
8fb591 |
mod = module->ctx->data_clb(module->ctx, name, mod->ns, LY_MODCLB_NOT_IMPLEMENTED, module->ctx->data_clb_data);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
free(name);
|
|
Packit |
8fb591 |
if (!mod) {
|
|
Packit |
8fb591 |
LOGVAL(ctx, LYE_INMOD_LEN, LY_VLOG_NONE, NULL, name_len, cur_expr);
|
|
Packit |
8fb591 |
goto error;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
prev_mod = mod;
|
|
Packit |
8fb591 |
} else {
|
|
Packit |
8fb591 |
mod = prev_mod;
|
|
Packit |
8fb591 |
if (!mod) {
|
|
Packit |
8fb591 |
LOGINT(ctx);
|
|
Packit |
8fb591 |
goto error;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
name_len = 0;
|
|
Packit |
8fb591 |
end = cur_expr;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
prefix = mod->prefix;
|
|
Packit |
8fb591 |
} else {
|
|
Packit |
8fb591 |
if (end) {
|
|
Packit |
8fb591 |
name_len = end - cur_expr;
|
|
Packit |
8fb591 |
} else {
|
|
Packit |
8fb591 |
name_len = strlen(cur_expr);
|
|
Packit |
8fb591 |
end = cur_expr;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
name = strndup(cur_expr, name_len);
|
|
Packit |
8fb591 |
prefix = transform_module_name2import_prefix(module, name);
|
|
Packit |
8fb591 |
free(name);
|
|
Packit |
8fb591 |
if (!prefix) {
|
|
Packit |
8fb591 |
LOGVAL(ctx, LYE_INMOD_LEN, LY_VLOG_NONE, NULL, name_len, cur_expr);
|
|
Packit |
8fb591 |
goto error;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* remember the namespace definition (only if it's new) */
|
|
Packit |
8fb591 |
if (!schema && ns_count) {
|
|
Packit |
8fb591 |
for (j = 0; j < *ns_count; ++j) {
|
|
Packit |
8fb591 |
if (ly_strequal((*namespaces)[j], mod->ns, 1)) {
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
if (j == *ns_count) {
|
|
Packit |
8fb591 |
++(*ns_count);
|
|
Packit |
8fb591 |
*prefixes = ly_realloc(*prefixes, *ns_count * sizeof **prefixes);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_GOTO(!(*prefixes), LOGMEM(ctx), error);
|
|
Packit |
8fb591 |
*namespaces = ly_realloc(*namespaces, *ns_count * sizeof **namespaces);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_GOTO(!(*namespaces), LOGMEM(ctx), error);
|
|
Packit |
8fb591 |
(*prefixes)[*ns_count - 1] = mod->prefix;
|
|
Packit |
8fb591 |
(*namespaces)[*ns_count - 1] = mod->ns;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* adjust out size (it can even decrease in some strange cases) */
|
|
Packit |
8fb591 |
*out_size += strlen(prefix) + 1 - name_len;
|
|
Packit |
8fb591 |
*out = ly_realloc(*out, *out_size);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_GOTO(!(*out), LOGMEM(ctx), error);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy the model name */
|
|
Packit |
8fb591 |
strcpy(&(*out)[*out_used], prefix);
|
|
Packit |
8fb591 |
*out_used += strlen(prefix);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (!name_len) {
|
|
Packit |
8fb591 |
/* we are adding the prefix, so also ':' */
|
|
Packit |
8fb591 |
(*out)[*out_used] = ':';
|
|
Packit |
8fb591 |
++(*out_used);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy the rest */
|
|
Packit |
8fb591 |
strncpy(&(*out)[*out_used], end, exp->tok_len[i] - name_len);
|
|
Packit |
8fb591 |
*out_used += exp->tok_len[i] - name_len;
|
|
Packit |
8fb591 |
} else if ((exp->tokens[i] == LYXP_TOKEN_LITERAL) && (end = strnchr(cur_expr, ':', exp->tok_len[i]))) {
|
|
Packit |
8fb591 |
/* copy begin quote */
|
|
Packit |
8fb591 |
(*out)[*out_used] = cur_expr[0];
|
|
Packit |
8fb591 |
++(*out_used);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* skip quotes */
|
|
Packit |
8fb591 |
literal = lydict_insert(module->ctx, cur_expr + 1, exp->tok_len[i] - 2);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* parse literals as subexpressions if possible, otherwise treat as a literal */
|
|
Packit |
8fb591 |
ly_ilo_change(NULL, ILO_IGNORE, &prev_ilo, NULL);
|
|
Packit |
8fb591 |
if (_transform_json2xml_subexp(module, literal, out, out_used, out_size, schema, inst_id, prefixes, namespaces, ns_count)) {
|
|
Packit |
8fb591 |
strncpy(&(*out)[*out_used], literal, exp->tok_len[i] - 2);
|
|
Packit |
8fb591 |
*out_used += exp->tok_len[i] - 2;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
ly_ilo_restore(NULL, prev_ilo, NULL, 0);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
lydict_remove(module->ctx, literal);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy end quote */
|
|
Packit |
8fb591 |
(*out)[*out_used] = cur_expr[exp->tok_len[i] - 1];
|
|
Packit |
8fb591 |
++(*out_used);
|
|
Packit |
8fb591 |
} else {
|
|
Packit |
8fb591 |
strncpy(&(*out)[*out_used], &exp->expr[exp->expr_pos[i]], exp->tok_len[i]);
|
|
Packit |
8fb591 |
*out_used += exp->tok_len[i];
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
lyxp_expr_free(exp);
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
error:
|
|
Packit |
8fb591 |
if (!schema && ns_count) {
|
|
Packit |
8fb591 |
free(*prefixes);
|
|
Packit |
8fb591 |
free(*namespaces);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
lyxp_expr_free(exp);
|
|
Packit |
8fb591 |
return 1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static const char *
|
|
Packit |
8fb591 |
_transform_json2xml(const struct lys_module *module, const char *expr, int schema, int inst_id, const char ***prefixes,
|
|
Packit |
8fb591 |
const char ***namespaces, uint32_t *ns_count)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
char *out;
|
|
Packit |
8fb591 |
size_t out_size, out_used;
|
|
Packit |
8fb591 |
int ret;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
assert(module && expr && ((!prefixes && !namespaces && !ns_count) || (prefixes && namespaces && ns_count)));
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (ns_count) {
|
|
Packit |
8fb591 |
*ns_count = 0;
|
|
Packit |
8fb591 |
*prefixes = NULL;
|
|
Packit |
8fb591 |
*namespaces = NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (!expr[0]) {
|
|
Packit |
8fb591 |
/* empty value */
|
|
Packit |
8fb591 |
return lydict_insert(module->ctx, expr, 0);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
out_size = strlen(expr) + 1;
|
|
Packit |
8fb591 |
out = malloc(out_size);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_RETURN(!out, LOGMEM(module->ctx), NULL);
|
|
Packit |
8fb591 |
out_used = 0;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
ret = _transform_json2xml_subexp(module, expr, &out, &out_used, &out_size, schema, inst_id, prefixes, namespaces, ns_count);
|
|
Packit |
8fb591 |
if (!ret) {
|
|
Packit |
8fb591 |
out[out_used] = '\0';
|
|
Packit |
8fb591 |
return lydict_insert_zc(module->ctx, out);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
free(out);
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
const char *
|
|
Packit |
8fb591 |
transform_json2xml(const struct lys_module *module, const char *expr, int inst_id, const char ***prefixes,
|
|
Packit |
8fb591 |
const char ***namespaces, uint32_t *ns_count)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
return _transform_json2xml(module, expr, 0, inst_id, prefixes, namespaces, ns_count);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
const char *
|
|
Packit |
8fb591 |
transform_json2schema(const struct lys_module *module, const char *expr)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
return _transform_json2xml(module, expr, 1, 0, NULL, NULL, NULL);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
transform_xml2json_subexp(struct ly_ctx *ctx, const char *expr, char **out, size_t *out_used, size_t *out_size,
|
|
Packit |
8fb591 |
struct lyxml_elem *xml, int inst_id, int use_ctx_data_clb)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
const char *end, *cur_expr, *literal;
|
|
Packit |
8fb591 |
char *prefix;
|
|
Packit |
8fb591 |
uint16_t i;
|
|
Packit |
8fb591 |
enum int_log_opts prev_ilo;
|
|
Packit |
8fb591 |
size_t pref_len;
|
|
Packit |
8fb591 |
const struct lys_module *mod, *prev_mod = NULL;
|
|
Packit |
8fb591 |
const struct lyxml_ns *ns;
|
|
Packit |
8fb591 |
struct lyxp_expr *exp;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
exp = lyxp_parse_expr(ctx, expr);
|
|
Packit |
8fb591 |
if (!exp) {
|
|
Packit |
8fb591 |
return 1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
for (i = 0; i < exp->used; ++i) {
|
|
Packit |
8fb591 |
cur_expr = &exp->expr[exp->expr_pos[i]];
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy WS */
|
|
Packit |
8fb591 |
if (i && ((end = exp->expr + exp->expr_pos[i - 1] + exp->tok_len[i - 1]) != cur_expr)) {
|
|
Packit |
8fb591 |
strncpy(&(*out)[*out_used], end, cur_expr - end);
|
|
Packit |
8fb591 |
(*out_used) += cur_expr - end;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if ((exp->tokens[i] == LYXP_TOKEN_NAMETEST) && (end = strnchr(cur_expr, ':', exp->tok_len[i]))) {
|
|
Packit |
8fb591 |
/* get the module */
|
|
Packit |
8fb591 |
pref_len = end - cur_expr;
|
|
Packit |
8fb591 |
prefix = strndup(cur_expr, pref_len);
|
|
Packit |
8fb591 |
if (!prefix) {
|
|
Packit |
8fb591 |
LOGMEM(ctx);
|
|
Packit |
8fb591 |
goto error;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
ns = lyxml_get_ns(xml, prefix);
|
|
Packit |
8fb591 |
free(prefix);
|
|
Packit |
8fb591 |
if (!ns) {
|
|
Packit |
8fb591 |
LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_XML, xml, "namespace prefix");
|
|
Packit |
8fb591 |
LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "XML namespace with prefix \"%.*s\" not defined.", pref_len, cur_expr);
|
|
Packit |
8fb591 |
goto error;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
mod = ly_ctx_get_module_by_ns(ctx, ns->value, NULL, 0);
|
|
Packit |
8fb591 |
if (use_ctx_data_clb && ctx->data_clb) {
|
|
Packit |
8fb591 |
if (!mod) {
|
|
Packit |
8fb591 |
mod = ctx->data_clb(ctx, NULL, ns->value, 0, ctx->data_clb_data);
|
|
Packit |
8fb591 |
} else if (!mod->implemented) {
|
|
Packit |
8fb591 |
mod = ctx->data_clb(ctx, mod->name, mod->ns, LY_MODCLB_NOT_IMPLEMENTED, ctx->data_clb_data);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
if (!mod) {
|
|
Packit |
8fb591 |
LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_XML, xml, "module namespace");
|
|
Packit |
8fb591 |
LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "Module with the namespace \"%s\" could not be found.", ns->value);
|
|
Packit |
8fb591 |
goto error;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (!inst_id || (mod != prev_mod)) {
|
|
Packit |
8fb591 |
/* adjust out size (it can even decrease in some strange cases) */
|
|
Packit |
8fb591 |
*out_size += strlen(mod->name) - pref_len;
|
|
Packit |
8fb591 |
*out = ly_realloc(*out, *out_size);
|
|
Packit |
8fb591 |
if (!(*out)) {
|
|
Packit |
8fb591 |
LOGMEM(ctx);
|
|
Packit |
8fb591 |
goto error;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy the model name */
|
|
Packit |
8fb591 |
strcpy(&(*out)[*out_used], mod->name);
|
|
Packit |
8fb591 |
*out_used += strlen(mod->name);
|
|
Packit |
8fb591 |
} else {
|
|
Packit |
8fb591 |
/* skip ':' */
|
|
Packit |
8fb591 |
++end;
|
|
Packit |
8fb591 |
++pref_len;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* remember previous model name */
|
|
Packit |
8fb591 |
prev_mod = mod;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy the rest */
|
|
Packit |
8fb591 |
strncpy(&(*out)[*out_used], end, exp->tok_len[i] - pref_len);
|
|
Packit |
8fb591 |
*out_used += exp->tok_len[i] - pref_len;
|
|
Packit |
8fb591 |
} else if ((exp->tokens[i] == LYXP_TOKEN_NAMETEST) && inst_id) {
|
|
Packit |
8fb591 |
LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_XML, xml, "namespace prefix");
|
|
Packit |
8fb591 |
LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "Node name is missing module prefix.");
|
|
Packit |
8fb591 |
goto error;
|
|
Packit |
8fb591 |
} else if ((exp->tokens[i] == LYXP_TOKEN_LITERAL) && (end = strnchr(cur_expr, ':', exp->tok_len[i]))) {
|
|
Packit |
8fb591 |
/* copy begin quote */
|
|
Packit |
8fb591 |
(*out)[*out_used] = cur_expr[0];
|
|
Packit |
8fb591 |
++(*out_used);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* skip quotes */
|
|
Packit |
8fb591 |
literal = lydict_insert(ctx, cur_expr + 1, exp->tok_len[i] - 2);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* parse literals as subexpressions if possible, otherwise treat as a literal, do not log */
|
|
Packit |
8fb591 |
prev_ilo = log_opt;
|
|
Packit |
8fb591 |
log_opt = ILO_IGNORE;
|
|
Packit |
8fb591 |
if (transform_xml2json_subexp(ctx, literal, out, out_used, out_size, xml, inst_id, use_ctx_data_clb)) {
|
|
Packit |
8fb591 |
strncpy(&(*out)[*out_used], literal, exp->tok_len[i] - 2);
|
|
Packit |
8fb591 |
*out_used += exp->tok_len[i] - 2;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
log_opt = prev_ilo;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
lydict_remove(ctx, literal);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy end quote */
|
|
Packit |
8fb591 |
(*out)[*out_used] = cur_expr[exp->tok_len[i] - 1];
|
|
Packit |
8fb591 |
++(*out_used);
|
|
Packit |
8fb591 |
} else {
|
|
Packit |
8fb591 |
strncpy(&(*out)[*out_used], &exp->expr[exp->expr_pos[i]], exp->tok_len[i]);
|
|
Packit |
8fb591 |
*out_used += exp->tok_len[i];
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
lyxp_expr_free(exp);
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
error:
|
|
Packit |
8fb591 |
lyxp_expr_free(exp);
|
|
Packit |
8fb591 |
return 1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
const char *
|
|
Packit |
8fb591 |
transform_xml2json(struct ly_ctx *ctx, const char *expr, struct lyxml_elem *xml, int inst_id, int use_ctx_data_clb)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
char *out;
|
|
Packit |
8fb591 |
size_t out_size, out_used;
|
|
Packit |
8fb591 |
int ret;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
out_size = strlen(expr) + 1;
|
|
Packit |
8fb591 |
out = malloc(out_size);
|
|
Packit |
8fb591 |
if (!out) {
|
|
Packit |
8fb591 |
LOGMEM(ctx);
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
out_used = 0;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
ret = transform_xml2json_subexp(ctx, expr, &out, &out_used, &out_size, xml, inst_id, use_ctx_data_clb);
|
|
Packit |
8fb591 |
if (!ret) {
|
|
Packit |
8fb591 |
out[out_used] = '\0';
|
|
Packit |
8fb591 |
return lydict_insert_zc(ctx, out);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
free(out);
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
API char *
|
|
Packit |
8fb591 |
ly_path_xml2json(struct ly_ctx *ctx, const char *xml_path, struct lyxml_elem *xml)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
const char *json_path;
|
|
Packit |
8fb591 |
char *ret = NULL;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (!ctx || !xml_path || !xml) {
|
|
Packit |
8fb591 |
LOGARG;
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
json_path = transform_xml2json(ctx, xml_path, xml, 0, 1);
|
|
Packit |
8fb591 |
if (json_path) {
|
|
Packit |
8fb591 |
ret = strdup(json_path);
|
|
Packit |
8fb591 |
lydict_remove(ctx, json_path);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return ret;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
const char *
|
|
Packit |
8fb591 |
transform_schema2json(const struct lys_module *module, const char *expr)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
const char *end, *cur_expr, *ptr;
|
|
Packit |
8fb591 |
char *out;
|
|
Packit |
8fb591 |
uint16_t i;
|
|
Packit |
8fb591 |
size_t out_size, out_used, pref_len;
|
|
Packit |
8fb591 |
const struct lys_module *mod;
|
|
Packit |
8fb591 |
struct ly_ctx *ctx = module->ctx;
|
|
Packit |
8fb591 |
struct lyxp_expr *exp = NULL;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
out_size = strlen(expr) + 1;
|
|
Packit |
8fb591 |
out = malloc(out_size);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_RETURN(!out, LOGMEM(ctx), NULL);
|
|
Packit |
8fb591 |
out_used = 0;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
exp = lyxp_parse_expr(ctx, expr);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_GOTO(!exp, , error);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
for (i = 0; i < exp->used; ++i) {
|
|
Packit |
8fb591 |
cur_expr = &exp->expr[exp->expr_pos[i]];
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy WS */
|
|
Packit |
8fb591 |
if (i && ((end = exp->expr + exp->expr_pos[i - 1] + exp->tok_len[i - 1]) != cur_expr)) {
|
|
Packit |
8fb591 |
strncpy(&out[out_used], end, cur_expr - end);
|
|
Packit |
8fb591 |
out_used += cur_expr - end;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if ((exp->tokens[i] == LYXP_TOKEN_NAMETEST) && (end = strnchr(cur_expr, ':', exp->tok_len[i]))) {
|
|
Packit |
8fb591 |
/* get the module */
|
|
Packit |
8fb591 |
pref_len = end - cur_expr;
|
|
Packit |
8fb591 |
mod = lyp_get_module(module, cur_expr, pref_len, NULL, 0, 0);
|
|
Packit |
8fb591 |
if (!mod) {
|
|
Packit |
8fb591 |
LOGVAL(ctx, LYE_INMOD_LEN, LY_VLOG_NONE, NULL, pref_len, cur_expr);
|
|
Packit |
8fb591 |
goto error;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* adjust out size (it can even decrease in some strange cases) */
|
|
Packit |
8fb591 |
out_size += strlen(mod->name) - pref_len;
|
|
Packit |
8fb591 |
out = ly_realloc(out, out_size);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_GOTO(!out, LOGMEM(ctx), error);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy the model name */
|
|
Packit |
8fb591 |
strcpy(&out[out_used], mod->name);
|
|
Packit |
8fb591 |
out_used += strlen(mod->name);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy the rest */
|
|
Packit |
8fb591 |
strncpy(&out[out_used], end, exp->tok_len[i] - pref_len);
|
|
Packit |
8fb591 |
out_used += exp->tok_len[i] - pref_len;
|
|
Packit |
8fb591 |
} else if ((exp->tokens[i] == LYXP_TOKEN_LITERAL) && (end = strnchr(cur_expr, ':', exp->tok_len[i]))) {
|
|
Packit |
8fb591 |
ptr = end;
|
|
Packit |
8fb591 |
while (isalnum(ptr[-1]) || (ptr[-1] == '_') || (ptr[-1] == '-') || (ptr[-1] == '.')) {
|
|
Packit |
8fb591 |
--ptr;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* get the module */
|
|
Packit |
8fb591 |
pref_len = end - ptr;
|
|
Packit |
8fb591 |
mod = lyp_get_module(module, ptr, pref_len, NULL, 0, 0);
|
|
Packit |
8fb591 |
if (mod) {
|
|
Packit |
8fb591 |
/* adjust out size (it can even decrease in some strange cases) */
|
|
Packit |
8fb591 |
out_size += strlen(mod->name) - pref_len;
|
|
Packit |
8fb591 |
out = ly_realloc(out, out_size);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_GOTO(!out, LOGMEM(ctx), error);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy any beginning */
|
|
Packit |
8fb591 |
strncpy(&out[out_used], cur_expr, ptr - cur_expr);
|
|
Packit |
8fb591 |
out_used += ptr - cur_expr;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy the model name */
|
|
Packit |
8fb591 |
strcpy(&out[out_used], mod->name);
|
|
Packit |
8fb591 |
out_used += strlen(mod->name);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy the rest */
|
|
Packit |
8fb591 |
strncpy(&out[out_used], end, (exp->tok_len[i] - pref_len) - (ptr - cur_expr));
|
|
Packit |
8fb591 |
out_used += (exp->tok_len[i] - pref_len) - (ptr - cur_expr);
|
|
Packit |
8fb591 |
} else {
|
|
Packit |
8fb591 |
strncpy(&out[out_used], &exp->expr[exp->expr_pos[i]], exp->tok_len[i]);
|
|
Packit |
8fb591 |
out_used += exp->tok_len[i];
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
} else {
|
|
Packit |
8fb591 |
strncpy(&out[out_used], &exp->expr[exp->expr_pos[i]], exp->tok_len[i]);
|
|
Packit |
8fb591 |
out_used += exp->tok_len[i];
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
out[out_used] = '\0';
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
lyxp_expr_free(exp);
|
|
Packit |
8fb591 |
return lydict_insert_zc(module->ctx, out);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
error:
|
|
Packit |
8fb591 |
free(out);
|
|
Packit |
8fb591 |
lyxp_expr_free(exp);
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
const char *
|
|
Packit |
8fb591 |
transform_iffeat_schema2json(const struct lys_module *module, const char *expr)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
const char *in, *id;
|
|
Packit |
8fb591 |
char *out, *col;
|
|
Packit |
8fb591 |
size_t out_size, out_used, id_len, rc;
|
|
Packit |
8fb591 |
const struct lys_module *mod;
|
|
Packit |
8fb591 |
struct ly_ctx *ctx = module->ctx;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
in = expr;
|
|
Packit |
8fb591 |
out_size = strlen(in) + 1;
|
|
Packit |
8fb591 |
out = malloc(out_size);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_RETURN(!out, LOGMEM(ctx), NULL);
|
|
Packit |
8fb591 |
out_used = 0;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
while (1) {
|
|
Packit |
8fb591 |
col = strchr(in, ':');
|
|
Packit |
8fb591 |
/* we're finished, copy the remaining part */
|
|
Packit |
8fb591 |
if (!col) {
|
|
Packit |
8fb591 |
strcpy(&out[out_used], in);
|
|
Packit |
8fb591 |
out_used += strlen(in) + 1;
|
|
Packit |
8fb591 |
assert(out_size == out_used);
|
|
Packit |
8fb591 |
return lydict_insert_zc(ctx, out);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
id = strpbrk_backwards(col - 1, " \f\n\r\t\v(", (col - in) - 1);
|
|
Packit |
8fb591 |
if ((id[0] == ' ') || (id[0] == '\f') || (id[0] == '\n') || (id[0] == '\r') ||
|
|
Packit |
8fb591 |
(id[0] == '\t') || (id[0] == '\v') || (id[0] == '(')) {
|
|
Packit |
8fb591 |
++id;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
id_len = col - id;
|
|
Packit |
8fb591 |
rc = parse_identifier(id);
|
|
Packit |
8fb591 |
if (rc < id_len) {
|
|
Packit |
8fb591 |
LOGVAL(ctx, LYE_INCHAR, LY_VLOG_NONE, NULL, id[rc], &id[rc]);
|
|
Packit |
8fb591 |
free(out);
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* get the module */
|
|
Packit |
8fb591 |
mod = lyp_get_module(module, id, id_len, NULL, 0, 0);
|
|
Packit |
8fb591 |
if (!mod) {
|
|
Packit |
8fb591 |
LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Module prefix \"%.*s\" is unknown.", id_len, id);
|
|
Packit |
8fb591 |
free(out);
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* adjust out size (it can even decrease in some strange cases) */
|
|
Packit |
8fb591 |
out_size += strlen(mod->name) - id_len;
|
|
Packit |
8fb591 |
out = ly_realloc(out, out_size);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_RETURN(!out, LOGMEM(ctx), NULL);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy the data before prefix */
|
|
Packit |
8fb591 |
strncpy(&out[out_used], in, id - in);
|
|
Packit |
8fb591 |
out_used += id - in;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy the model name */
|
|
Packit |
8fb591 |
strcpy(&out[out_used], mod->name);
|
|
Packit |
8fb591 |
out_used += strlen(mod->name);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy ':' */
|
|
Packit |
8fb591 |
out[out_used] = ':';
|
|
Packit |
8fb591 |
++out_used;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* finally adjust in pointer for next round */
|
|
Packit |
8fb591 |
in = col + 1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* unreachable */
|
|
Packit |
8fb591 |
LOGINT(ctx);
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
transform_json2xpath_subexpr(const struct lys_module *cur_module, const struct lys_module *prev_mod, struct lyxp_expr *exp,
|
|
Packit |
8fb591 |
uint32_t *i, enum lyxp_token end_token, char **out, size_t *out_used, size_t *out_size)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
const char *cur_expr, *end, *ptr;
|
|
Packit |
8fb591 |
size_t name_len;
|
|
Packit |
8fb591 |
char *name;
|
|
Packit |
8fb591 |
const struct lys_module *mod;
|
|
Packit |
8fb591 |
struct ly_ctx *ctx = cur_module->ctx;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
while (*i < exp->used) {
|
|
Packit |
8fb591 |
if (exp->tokens[*i] == end_token) {
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
cur_expr = &exp->expr[exp->expr_pos[*i]];
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy WS */
|
|
Packit |
8fb591 |
if (*i && ((end = exp->expr + exp->expr_pos[*i - 1] + exp->tok_len[*i - 1]) != cur_expr)) {
|
|
Packit |
8fb591 |
strncpy(*out + *out_used, end, cur_expr - end);
|
|
Packit |
8fb591 |
*out_used += cur_expr - end;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (exp->tokens[*i] == LYXP_TOKEN_BRACK1) {
|
|
Packit |
8fb591 |
/* copy "[" */
|
|
Packit |
8fb591 |
strncpy(*out + *out_used, &exp->expr[exp->expr_pos[*i]], exp->tok_len[*i]);
|
|
Packit |
8fb591 |
*out_used += exp->tok_len[*i];
|
|
Packit |
8fb591 |
++(*i);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* call recursively because we need to remember current prev_mod for after the predicate */
|
|
Packit |
8fb591 |
if (transform_json2xpath_subexpr(cur_module, prev_mod, exp, i, LYXP_TOKEN_BRACK2, out, out_used, out_size)) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (*i >= exp->used) {
|
|
Packit |
8fb591 |
LOGVAL(ctx, LYE_XPATH_EOF, LY_VLOG_NONE, NULL);
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy "]" */
|
|
Packit |
8fb591 |
strncpy(*out + *out_used, &exp->expr[exp->expr_pos[*i]], exp->tok_len[*i]);
|
|
Packit |
8fb591 |
*out_used += exp->tok_len[*i];
|
|
Packit |
8fb591 |
} else if (exp->tokens[*i] == LYXP_TOKEN_NAMETEST) {
|
|
Packit |
8fb591 |
if ((end = strnchr(cur_expr, ':', exp->tok_len[*i]))) {
|
|
Packit |
8fb591 |
/* there is a prefix, get the module */
|
|
Packit |
8fb591 |
name_len = end - cur_expr;
|
|
Packit |
8fb591 |
name = strndup(cur_expr, name_len);
|
|
Packit |
8fb591 |
prev_mod = ly_ctx_get_module(ctx, name, NULL, 1);
|
|
Packit |
8fb591 |
free(name);
|
|
Packit |
8fb591 |
if (!prev_mod) {
|
|
Packit |
8fb591 |
LOGVAL(ctx, LYE_INMOD_LEN, LY_VLOG_NONE, NULL, name_len ? name_len : exp->tok_len[*i], cur_expr);
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
/* skip ":" */
|
|
Packit |
8fb591 |
++end;
|
|
Packit |
8fb591 |
++name_len;
|
|
Packit |
8fb591 |
} else {
|
|
Packit |
8fb591 |
end = cur_expr;
|
|
Packit |
8fb591 |
name_len = 0;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* do we print the module name? (always for "*" if there was any, it's an exception) */
|
|
Packit |
8fb591 |
if (((prev_mod != cur_module) && (end[0] != '*')) || (name_len && (end[0] == '*'))) {
|
|
Packit |
8fb591 |
/* adjust out size (it can even decrease in some strange cases) */
|
|
Packit |
8fb591 |
*out_size += (strlen(prev_mod->name) - name_len) + 1;
|
|
Packit |
8fb591 |
*out = ly_realloc(*out, *out_size);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_RETURN(!*out, LOGMEM(ctx), -1);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy the model name */
|
|
Packit |
8fb591 |
strcpy(*out + *out_used, prev_mod->name);
|
|
Packit |
8fb591 |
*out_used += strlen(prev_mod->name);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* print ":" */
|
|
Packit |
8fb591 |
(*out)[*out_used] = ':';
|
|
Packit |
8fb591 |
++(*out_used);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy the rest */
|
|
Packit |
8fb591 |
strncpy(*out + *out_used, end, exp->tok_len[*i] - name_len);
|
|
Packit |
8fb591 |
*out_used += exp->tok_len[*i] - name_len;
|
|
Packit |
8fb591 |
} else if ((exp->tokens[*i] == LYXP_TOKEN_LITERAL) && (end = strnchr(cur_expr, ':', exp->tok_len[*i]))) {
|
|
Packit |
8fb591 |
ptr = end;
|
|
Packit |
8fb591 |
while (isalnum(ptr[-1]) || (ptr[-1] == '_') || (ptr[-1] == '-') || (ptr[-1] == '.')) {
|
|
Packit |
8fb591 |
--ptr;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* get the module, but it may actually not be a module name */
|
|
Packit |
8fb591 |
name_len = end - ptr;
|
|
Packit |
8fb591 |
name = strndup(ptr, name_len);
|
|
Packit |
8fb591 |
mod = ly_ctx_get_module(ctx, name, NULL, 1);
|
|
Packit |
8fb591 |
free(name);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (mod && (mod != cur_module)) {
|
|
Packit |
8fb591 |
/* adjust out size (it can even decrease in some strange cases) */
|
|
Packit |
8fb591 |
*out_size += strlen(mod->name) - name_len;
|
|
Packit |
8fb591 |
*out = ly_realloc(*out, *out_size);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_RETURN(!*out, LOGMEM(ctx), -1);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy any beginning */
|
|
Packit |
8fb591 |
strncpy(*out + *out_used, cur_expr, ptr - cur_expr);
|
|
Packit |
8fb591 |
*out_used += ptr - cur_expr;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy the model name */
|
|
Packit |
8fb591 |
strcpy(*out + *out_used, mod->name);
|
|
Packit |
8fb591 |
*out_used += strlen(mod->name);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy the rest */
|
|
Packit |
8fb591 |
strncpy(*out + *out_used, end, (exp->tok_len[*i] - name_len) - (ptr - cur_expr));
|
|
Packit |
8fb591 |
*out_used += (exp->tok_len[*i] - name_len) - (ptr - cur_expr);
|
|
Packit |
8fb591 |
} else {
|
|
Packit |
8fb591 |
strncpy(*out + *out_used, &exp->expr[exp->expr_pos[*i]], exp->tok_len[*i]);
|
|
Packit |
8fb591 |
*out_used += exp->tok_len[*i];
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
} else {
|
|
Packit |
8fb591 |
strncpy(*out + *out_used, &exp->expr[exp->expr_pos[*i]], exp->tok_len[*i]);
|
|
Packit |
8fb591 |
*out_used += exp->tok_len[*i];
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
++(*i);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
char *
|
|
Packit |
8fb591 |
transform_json2xpath(const struct lys_module *cur_module, const char *expr)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
char *out;
|
|
Packit |
8fb591 |
size_t out_size, out_used;
|
|
Packit |
8fb591 |
uint32_t i;
|
|
Packit |
8fb591 |
struct lyxp_expr *exp;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
assert(cur_module && expr);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
out_size = strlen(expr) + 1;
|
|
Packit |
8fb591 |
out = malloc(out_size);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_RETURN(!out, LOGMEM(cur_module->ctx), NULL);
|
|
Packit |
8fb591 |
out_used = 0;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
exp = lyxp_parse_expr(cur_module->ctx, expr);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_RETURN(!exp, free(out), NULL);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
i = 0;
|
|
Packit |
8fb591 |
if (transform_json2xpath_subexpr(cur_module, cur_module, exp, &i, LYXP_TOKEN_NONE, &out, &out_used, &out_size)) {
|
|
Packit |
8fb591 |
goto error;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
out[out_used] = '\0';
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
lyxp_expr_free(exp);
|
|
Packit |
8fb591 |
return out;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
error:
|
|
Packit |
8fb591 |
free(out);
|
|
Packit |
8fb591 |
lyxp_expr_free(exp);
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
ly_path_data2schema_copy_token(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t cur_exp, char **out, uint16_t *out_used)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
uint16_t len;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
for (len = exp->tok_len[cur_exp]; isspace(exp->expr[exp->expr_pos[cur_exp] + len]); ++len);
|
|
Packit |
8fb591 |
*out = ly_realloc(*out, *out_used + len);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_RETURN(!(*out), LOGMEM(ctx), -1);
|
|
Packit |
8fb591 |
sprintf(*out + *out_used - 1, "%.*s", len, exp->expr + exp->expr_pos[cur_exp]);
|
|
Packit |
8fb591 |
*out_used += len;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
ly_path_data2schema_subexp(const struct ly_ctx *ctx, const struct lys_node *orig_parent, const struct lys_module *cur_mod,
|
|
Packit |
8fb591 |
struct lyxp_expr *exp, uint16_t *cur_exp, char **out, uint16_t *out_used)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
uint16_t j, k, len, slash;
|
|
Packit |
8fb591 |
char *str = NULL, *col;
|
|
Packit |
8fb591 |
const struct lys_node *node, *node2, *parent;
|
|
Packit |
8fb591 |
enum lyxp_token end_token = 0;
|
|
Packit |
8fb591 |
int first, path_lost;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
switch (exp->tokens[*cur_exp]) {
|
|
Packit |
8fb591 |
case LYXP_TOKEN_BRACK1:
|
|
Packit |
8fb591 |
end_token = LYXP_TOKEN_BRACK2;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (ly_path_data2schema_copy_token(ctx, exp, *cur_exp, out, out_used)) {
|
|
Packit |
8fb591 |
goto error;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
++(*cur_exp);
|
|
Packit |
8fb591 |
first = 0;
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
case LYXP_TOKEN_PAR1:
|
|
Packit |
8fb591 |
end_token = LYXP_TOKEN_PAR2;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (ly_path_data2schema_copy_token(ctx, exp, *cur_exp, out, out_used)) {
|
|
Packit |
8fb591 |
goto error;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
++(*cur_exp);
|
|
Packit |
8fb591 |
first = 0;
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
case LYXP_TOKEN_OPERATOR_PATH:
|
|
Packit |
8fb591 |
first = (orig_parent) ? 0 : 1;
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
default:
|
|
Packit |
8fb591 |
first = 1;
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
path_lost = 0;
|
|
Packit |
8fb591 |
parent = orig_parent;
|
|
Packit |
8fb591 |
while (*cur_exp < exp->used) {
|
|
Packit |
8fb591 |
switch (exp->tokens[*cur_exp]) {
|
|
Packit |
8fb591 |
case LYXP_TOKEN_DOT:
|
|
Packit |
8fb591 |
case LYXP_TOKEN_DDOT:
|
|
Packit |
8fb591 |
case LYXP_TOKEN_NAMETEST:
|
|
Packit |
8fb591 |
if (path_lost) {
|
|
Packit |
8fb591 |
/* we do not know anything anymore, just copy it */
|
|
Packit |
8fb591 |
if (ly_path_data2schema_copy_token(ctx, exp, *cur_exp, out, out_used)) {
|
|
Packit |
8fb591 |
goto error;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
str = strndup(exp->expr + exp->expr_pos[*cur_exp], exp->tok_len[*cur_exp]);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_GOTO(!str, LOGMEM(ctx), error);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
col = strchr(str, ':');
|
|
Packit |
8fb591 |
if (col) {
|
|
Packit |
8fb591 |
*col = '\0';
|
|
Packit |
8fb591 |
++col;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* first node */
|
|
Packit |
8fb591 |
if (first) {
|
|
Packit |
8fb591 |
if (!col) {
|
|
Packit |
8fb591 |
LOGVAL(ctx, LYE_PATH_MISSMOD, LY_VLOG_NONE, NULL);
|
|
Packit |
8fb591 |
goto error;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
cur_mod = ly_ctx_get_module(ctx, str, NULL, 0);
|
|
Packit |
8fb591 |
if (!cur_mod) {
|
|
Packit |
8fb591 |
LOGVAL(ctx, LYE_PATH_INMOD, LY_VLOG_STR, str);
|
|
Packit |
8fb591 |
goto error;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
first = 0;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (((col ? col[0] : str[0]) == '.') || ((col ? col[0] : str[0]) == '*')) {
|
|
Packit |
8fb591 |
free(str);
|
|
Packit |
8fb591 |
str = NULL;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (end_token) {
|
|
Packit |
8fb591 |
LOGERR(ctx, LY_EINVAL, "Invalid path used (%s in a subexpression).", str);
|
|
Packit |
8fb591 |
goto error;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* we can no longer evaluate the path, so just copy the rest */
|
|
Packit |
8fb591 |
path_lost = 1;
|
|
Packit |
8fb591 |
if (ly_path_data2schema_copy_token(ctx, exp, *cur_exp, out, out_used)) {
|
|
Packit |
8fb591 |
goto error;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* create schema path for this data node */
|
|
Packit |
8fb591 |
node = NULL;
|
|
Packit |
8fb591 |
while ((node = lys_getnext(node, parent, cur_mod, LYS_GETNEXT_NOSTATECHECK))) {
|
|
Packit |
8fb591 |
if (strcmp(node->name, col ? col : str)) {
|
|
Packit |
8fb591 |
continue;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (col && strcmp(lys_node_module(node)->name, str)) {
|
|
Packit |
8fb591 |
continue;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
if (!col && (lys_node_module(node) != lys_node_module(parent))) {
|
|
Packit |
8fb591 |
continue;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* determine how deep the node actually is, we must generate the path from the highest parent */
|
|
Packit |
8fb591 |
j = 0;
|
|
Packit |
8fb591 |
node2 = node;
|
|
Packit |
8fb591 |
while (node2 != parent) {
|
|
Packit |
8fb591 |
node2 = lys_parent(node2);
|
|
Packit |
8fb591 |
if (!node2 || (node2->nodetype != LYS_USES)) {
|
|
Packit |
8fb591 |
++j;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* first node, do not print '/' */
|
|
Packit |
8fb591 |
slash = 0;
|
|
Packit |
8fb591 |
while (j) {
|
|
Packit |
8fb591 |
k = j - 1;
|
|
Packit |
8fb591 |
node2 = node;
|
|
Packit |
8fb591 |
while (k) {
|
|
Packit |
8fb591 |
node2 = lys_parent(node2);
|
|
Packit |
8fb591 |
assert(node2);
|
|
Packit |
8fb591 |
if (node2->nodetype != LYS_USES) {
|
|
Packit |
8fb591 |
--k;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if ((lys_node_module(node2) != cur_mod) || !parent) {
|
|
Packit |
8fb591 |
/* module name and node name */
|
|
Packit |
8fb591 |
len = slash + strlen(lys_node_module(node2)->name) + 1 + strlen(node2->name);
|
|
Packit |
8fb591 |
*out = ly_realloc(*out, *out_used + len);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_GOTO(!(*out), LOGMEM(ctx), error);
|
|
Packit |
8fb591 |
sprintf(*out + *out_used - 1, "%s%s:%s", slash ? "/" : "", lys_node_module(node2)->name, node2->name);
|
|
Packit |
8fb591 |
*out_used += len;
|
|
Packit |
8fb591 |
} else {
|
|
Packit |
8fb591 |
/* only node name */
|
|
Packit |
8fb591 |
len = slash + strlen(node2->name);
|
|
Packit |
8fb591 |
*out = ly_realloc(*out, *out_used + len);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_GOTO(!(*out), LOGMEM(ctx), error);
|
|
Packit |
8fb591 |
sprintf(*out + *out_used - 1, "%s%s", slash ? "/" : "", node2->name);
|
|
Packit |
8fb591 |
*out_used += len;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
slash = 1;
|
|
Packit |
8fb591 |
--j;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
if (!node) {
|
|
Packit |
8fb591 |
LOGVAL(ctx, LYE_PATH_INNODE, LY_VLOG_STR, col ? col : str);
|
|
Packit |
8fb591 |
goto error;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* copy any whitespaces */
|
|
Packit |
8fb591 |
for (len = 0; isspace(exp->expr[exp->expr_pos[*cur_exp] + exp->tok_len[*cur_exp] + len]); ++len);
|
|
Packit |
8fb591 |
if (len) {
|
|
Packit |
8fb591 |
*out = ly_realloc(*out, *out_used + len);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_GOTO(!(*out), LOGMEM(ctx), error);
|
|
Packit |
8fb591 |
sprintf(*out + *out_used - 1, "%*s", len, " ");
|
|
Packit |
8fb591 |
*out_used += len;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* next iteration */
|
|
Packit |
8fb591 |
free(str);
|
|
Packit |
8fb591 |
str = NULL;
|
|
Packit |
8fb591 |
parent = node;
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
case LYXP_TOKEN_COMMA:
|
|
Packit |
8fb591 |
case LYXP_TOKEN_OPERATOR_LOG:
|
|
Packit |
8fb591 |
case LYXP_TOKEN_OPERATOR_COMP:
|
|
Packit |
8fb591 |
case LYXP_TOKEN_OPERATOR_MATH:
|
|
Packit |
8fb591 |
case LYXP_TOKEN_OPERATOR_UNI:
|
|
Packit |
8fb591 |
/* reset the processing */
|
|
Packit |
8fb591 |
first = 1;
|
|
Packit |
8fb591 |
path_lost = 0;
|
|
Packit |
8fb591 |
parent = orig_parent;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* fallthrough */
|
|
Packit |
8fb591 |
case LYXP_TOKEN_OPERATOR_PATH:
|
|
Packit |
8fb591 |
if ((exp->tokens[*cur_exp] == LYXP_TOKEN_OPERATOR_PATH) && (exp->tok_len[*cur_exp] == 2)) {
|
|
Packit |
8fb591 |
/* we can no longer evaluate the path further */
|
|
Packit |
8fb591 |
path_lost = 1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
/* fallthrough */
|
|
Packit |
8fb591 |
case LYXP_TOKEN_NODETYPE:
|
|
Packit |
8fb591 |
case LYXP_TOKEN_FUNCNAME:
|
|
Packit |
8fb591 |
case LYXP_TOKEN_LITERAL:
|
|
Packit |
8fb591 |
case LYXP_TOKEN_NUMBER:
|
|
Packit |
8fb591 |
/* just copy it */
|
|
Packit |
8fb591 |
if (ly_path_data2schema_copy_token(ctx, exp, *cur_exp, out, out_used)) {
|
|
Packit |
8fb591 |
goto error;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
case LYXP_TOKEN_BRACK1:
|
|
Packit |
8fb591 |
case LYXP_TOKEN_PAR1:
|
|
Packit |
8fb591 |
if (ly_path_data2schema_subexp(ctx, parent, cur_mod, exp, cur_exp, out, out_used)) {
|
|
Packit |
8fb591 |
goto error;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
default:
|
|
Packit |
8fb591 |
if (end_token && (exp->tokens[*cur_exp] == end_token)) {
|
|
Packit |
8fb591 |
/* we are done (with this subexpression) */
|
|
Packit |
8fb591 |
if (ly_path_data2schema_copy_token(ctx, exp, *cur_exp, out, out_used)) {
|
|
Packit |
8fb591 |
goto error;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
LOGERR(ctx, LY_EINVAL, "Invalid token used (%.*s).", exp->tok_len[*cur_exp], exp->expr + exp->expr_pos[*cur_exp]);
|
|
Packit |
8fb591 |
goto error;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
++(*cur_exp);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (end_token) {
|
|
Packit |
8fb591 |
LOGVAL(ctx, LYE_XPATH_EOF, LY_VLOG_NONE, NULL);
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
error:
|
|
Packit |
8fb591 |
free(str);
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
API char *
|
|
Packit |
8fb591 |
ly_path_data2schema(struct ly_ctx *ctx, const char *data_path)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
struct lyxp_expr *exp;
|
|
Packit |
8fb591 |
uint16_t out_used, cur_exp = 0;
|
|
Packit |
8fb591 |
char *out;
|
|
Packit |
8fb591 |
int r, mod_name_len, nam_len, is_relative = -1;
|
|
Packit |
8fb591 |
const char *mod_name, *name;
|
|
Packit |
8fb591 |
const struct lys_module *mod = NULL;
|
|
Packit |
8fb591 |
const struct lys_node *parent = NULL;
|
|
Packit |
8fb591 |
char *str;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (!ctx || !data_path) {
|
|
Packit |
8fb591 |
LOGARG;
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if ((r = parse_schema_nodeid(data_path, &mod_name, &mod_name_len, &name, &nam_len, &is_relative, NULL, NULL, 1)) < 1) {
|
|
Packit |
8fb591 |
LOGVAL(ctx, LYE_PATH_INCHAR, LY_VLOG_NONE, NULL, data_path[-r], &data_path[-r]);
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (name[0] == '#') {
|
|
Packit |
8fb591 |
if (is_relative) {
|
|
Packit |
8fb591 |
LOGVAL(ctx, LYE_PATH_INCHAR, LY_VLOG_NONE, NULL, '#', name);
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
++name;
|
|
Packit |
8fb591 |
--nam_len;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (!mod_name) {
|
|
Packit |
8fb591 |
str = strndup(data_path, (name + nam_len) - data_path);
|
|
Packit |
8fb591 |
LOGVAL(ctx, LYE_PATH_MISSMOD, LY_VLOG_STR, str);
|
|
Packit |
8fb591 |
free(str);
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
str = strndup(mod_name, mod_name_len);
|
|
Packit |
8fb591 |
if (!str) {
|
|
Packit |
8fb591 |
LOGMEM(ctx);
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
mod = ly_ctx_get_module(ctx, str, NULL, 1);
|
|
Packit |
8fb591 |
free(str);
|
|
Packit |
8fb591 |
if (!mod) {
|
|
Packit |
8fb591 |
str = strndup(data_path, (mod_name + mod_name_len) - data_path);
|
|
Packit |
8fb591 |
LOGVAL(ctx, LYE_PATH_INMOD, LY_VLOG_STR, str);
|
|
Packit |
8fb591 |
free(str);
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
parent = lyp_get_yang_data_template(mod, name, nam_len);
|
|
Packit |
8fb591 |
if (!parent) {
|
|
Packit |
8fb591 |
str = strndup(data_path, (name + nam_len) - data_path);
|
|
Packit |
8fb591 |
LOGVAL(ctx, LYE_PATH_INNODE, LY_VLOG_STR, str);
|
|
Packit |
8fb591 |
free(str);
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
out_used = (name + nam_len) - data_path + 1;
|
|
Packit |
8fb591 |
out = malloc(out_used);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_RETURN(!out, LOGMEM(ctx), NULL);
|
|
Packit |
8fb591 |
memcpy(out, data_path, out_used -1);
|
|
Packit |
8fb591 |
data_path += r;
|
|
Packit |
8fb591 |
} else {
|
|
Packit |
8fb591 |
out_used = 1;
|
|
Packit |
8fb591 |
out = malloc(1);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_RETURN(!out, LOGMEM(ctx), NULL);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
exp = lyxp_parse_expr(ctx, data_path);
|
|
Packit |
8fb591 |
if (!exp) {
|
|
Packit |
8fb591 |
free(out);
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (parent) {
|
|
Packit |
8fb591 |
if (ly_path_data2schema_subexp(ctx, parent, mod, exp, &cur_exp, &out, &out_used)) {
|
|
Packit |
8fb591 |
free(out);
|
|
Packit |
8fb591 |
out = NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
} else {
|
|
Packit |
8fb591 |
if (ly_path_data2schema_subexp(ctx, NULL, NULL, exp, &cur_exp, &out, &out_used)) {
|
|
Packit |
8fb591 |
free(out);
|
|
Packit |
8fb591 |
out = NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
lyxp_expr_free(exp);
|
|
Packit |
8fb591 |
return out;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
int
|
|
Packit |
8fb591 |
ly_new_node_validity(const struct lys_node *schema)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
int validity;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
validity = LYD_VAL_OK;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
|
|
Packit |
8fb591 |
if (((struct lys_node_leaf *)schema)->type.base == LY_TYPE_LEAFREF) {
|
|
Packit |
8fb591 |
/* leafref target validation */
|
|
Packit |
8fb591 |
validity |= LYD_VAL_LEAFREF;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
if (schema->nodetype & (LYS_LEAFLIST | LYS_LIST)) {
|
|
Packit |
8fb591 |
/* duplicit instance check */
|
|
Packit |
8fb591 |
validity |= LYD_VAL_DUP;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
if ((schema->nodetype == LYS_LIST) && ((struct lys_node_list *)schema)->unique_size) {
|
|
Packit |
8fb591 |
/* unique check */
|
|
Packit |
8fb591 |
validity |= LYD_VAL_UNIQUE;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_NOTIF | LYS_RPC | LYS_ACTION | LYS_ANYDATA)) {
|
|
Packit |
8fb591 |
/* mandatory children check */
|
|
Packit |
8fb591 |
validity |= LYD_VAL_MAND;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return validity;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
void *
|
|
Packit |
8fb591 |
ly_realloc(void *ptr, size_t size)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
void *new_mem;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
new_mem = realloc(ptr, size);
|
|
Packit |
8fb591 |
if (!new_mem) {
|
|
Packit |
8fb591 |
free(ptr);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return new_mem;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
int
|
|
Packit |
8fb591 |
ly_strequal_(const char *s1, const char *s2)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
if (s1 == s2) {
|
|
Packit |
8fb591 |
return 1;
|
|
Packit |
8fb591 |
} else if (!s1 || !s2) {
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
} else {
|
|
Packit |
8fb591 |
for ( ; *s1 == *s2; s1++, s2++) {
|
|
Packit |
8fb591 |
if (*s1 == '\0') {
|
|
Packit |
8fb591 |
return 1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
int64_t
|
|
Packit |
8fb591 |
dec_pow(uint8_t exp)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
int64_t ret = 1;
|
|
Packit |
8fb591 |
uint8_t i;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
for (i = 0; i < exp; ++i) {
|
|
Packit |
8fb591 |
ret *= 10;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return ret;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
int
|
|
Packit |
8fb591 |
dec64cmp(int64_t num1, uint8_t dig1, int64_t num2, uint8_t dig2)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
if (dig1 < dig2) {
|
|
Packit |
8fb591 |
num2 /= dec_pow(dig2 - dig1);
|
|
Packit |
8fb591 |
} else if (dig1 > dig2) {
|
|
Packit |
8fb591 |
num1 /= dec_pow(dig1 - dig2);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (num1 == num2) {
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
return (num1 > num2 ? 1 : -1);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
LYB_HASH
|
|
Packit |
8fb591 |
lyb_hash(struct lys_node *sibling, uint8_t collision_id)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
struct lys_module *mod;
|
|
Packit |
8fb591 |
int ext_len;
|
|
Packit |
8fb591 |
uint32_t full_hash;
|
|
Packit |
8fb591 |
LYB_HASH hash;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
#ifdef LY_ENABLED_CACHE
|
|
Packit |
8fb591 |
if ((collision_id < LYS_NODE_HASH_COUNT) && sibling->hash[collision_id]) {
|
|
Packit |
8fb591 |
return sibling->hash[collision_id];
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
#endif
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
mod = lys_node_module(sibling);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
full_hash = dict_hash_multi(0, mod->name, strlen(mod->name));
|
|
Packit |
8fb591 |
full_hash = dict_hash_multi(full_hash, sibling->name, strlen(sibling->name));
|
|
Packit |
8fb591 |
if (collision_id) {
|
|
Packit |
8fb591 |
if (collision_id > strlen(mod->name)) {
|
|
Packit |
8fb591 |
/* fine, we will not hash more bytes, just use more bits from the hash than previously */
|
|
Packit |
8fb591 |
ext_len = strlen(mod->name);
|
|
Packit |
8fb591 |
} else {
|
|
Packit |
8fb591 |
/* use one more byte from the module name than before */
|
|
Packit |
8fb591 |
ext_len = collision_id;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
full_hash = dict_hash_multi(full_hash, mod->name, ext_len);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
full_hash = dict_hash_multi(full_hash, NULL, 0);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* use the shortened hash */
|
|
Packit |
8fb591 |
hash = full_hash & (LYB_HASH_MASK >> collision_id);
|
|
Packit |
8fb591 |
/* add colision identificator */
|
|
Packit |
8fb591 |
hash |= LYB_HASH_COLLISION_ID >> collision_id;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* save this hash */
|
|
Packit |
8fb591 |
#ifdef LY_ENABLED_CACHE
|
|
Packit |
8fb591 |
if (collision_id < LYS_NODE_HASH_COUNT) {
|
|
Packit |
8fb591 |
sibling->hash[collision_id] = hash;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
#endif
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return hash;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
int
|
|
Packit |
8fb591 |
lyb_has_schema_model(struct lys_node *sibling, const struct lys_module **models, int mod_count)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
int i;
|
|
Packit |
8fb591 |
const struct lys_module *mod = lys_node_module(sibling);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
for (i = 0; i < mod_count; ++i) {
|
|
Packit |
8fb591 |
if (mod == models[i]) {
|
|
Packit |
8fb591 |
return 1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
}
|