blob: dd1bb9e331987685a058d5c79b392fb3d058a698 [file] [log] [blame]
Michal Vasko25895052015-09-21 11:41:12 +02001/**
2 * @file xpath.h
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief YANG XPath evaluation functions header
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of the Company nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 */
21
22#ifndef _XPATH_H
23#define _XPATH_H
24
25#include <stdint.h>
26
Michal Vaskofd76bd12015-09-24 15:49:57 +020027#include "tree_schema.h"
28#include "tree_data.h"
Michal Vasko25895052015-09-21 11:41:12 +020029
30/*
31 * XPath evaluator fully compliant with http://www.w3.org/TR/1999/REC-xpath-19991116/
32 * except the following restrictions in the grammar.
33 *
34 * PARSED GRAMMAR
35 *
36 * Full axes are not supported, abbreviated forms must be used,
37 * variables are not supported, "id()" function is not supported,
Michal Vaskoca3f1dc2015-10-06 15:57:40 +020038 * and processing instruction and comment nodes are not supported,
39 * which is also reflected in the grammar. Undefined rules and
40 * constants are tokens.
Michal Vasko25895052015-09-21 11:41:12 +020041 *
42 * Modified full grammar:
43 *
44 * [1] LocationPath ::= RelativeLocationPath | AbsoluteLocationPath
Michal Vaskoca3f1dc2015-10-06 15:57:40 +020045 * [2] AbsoluteLocationPath ::= '/' RelativeLocationPath? | '//' RelativeLocationPath
Michal Vasko25895052015-09-21 11:41:12 +020046 * [3] RelativeLocationPath ::= Step | RelativeLocationPath '/' Step | RelativeLocationPath '//' Step
47 * [4] Step ::= '@'? NodeTest Predicate* | '.' | '..'
48 * [5] NodeTest ::= NameTest | NodeType '(' ')'
49 * [6] Predicate ::= '[' Expr ']'
50 * [7] PrimaryExpr ::= '(' Expr ')' | Literal | Number | FunctionCall
51 * [8] FunctionCall ::= FunctionName '(' ( Expr ( ',' Expr )* )? ')'
52 * [9] PathExpr ::= LocationPath | PrimaryExpr Predicate*
53 * | PrimaryExpr Predicate* '/' RelativeLocationPath
54 * | PrimaryExpr Predicate* '//' RelativeLocationPath
55 * [10] Expr ::= AndExpr | Expr 'or' AndExpr
56 * [11] AndExpr ::= EqualityExpr | AndExpr 'and' EqualityExpr
57 * [12] EqualityExpr ::= RelationalExpr | EqualityExpr '=' RelationalExpr
58 * | EqualityExpr '!=' RelationalExpr
59 * [13] RelationalExpr ::= AdditiveExpr
60 * | RelationalExpr '<' AdditiveExpr
61 * | RelationalExpr '>' AdditiveExpr
62 * | RelationalExpr '<=' AdditiveExpr
63 * | RelationalExpr '>=' AdditiveExpr
64 * [14] AdditiveExpr ::= MultiplicativeExpr
65 * | AdditiveExpr '+' MultiplicativeExpr
66 * | AdditiveExpr '-' MultiplicativeExpr
67 * [15] MultiplicativeExpr ::= UnaryExpr
68 * | MultiplicativeExpr '*' UnaryExpr
69 * | MultiplicativeExpr 'div' UnaryExpr
70 * | MultiplicativeExpr 'mod' UnaryExpr
71 * [16] UnaryExpr ::= UnionExpr | '-' UnaryExpr
72 * [17] UnionExpr ::= PathExpr | UnionExpr '|' PathExpr
73 */
74
75/* expression tokens allocation */
76#define LYXP_EXPR_SIZE_START 10
77#define LYXP_EXPR_SIZE_STEP 5
78
79/* XPath matches allocation */
80#define LYXP_SET_SIZE_START 2
81#define LYXP_SET_SIZE_STEP 2
82
83/* building string when casting */
84#define LYXP_STRING_CAST_SIZE_START 64
85#define LYXP_STRING_CAST_SIZE_STEP 16
86
87/**
88 * @brief Tokens that can be in an XPath expression.
89 */
90enum lyxp_token {
91 LYXP_TOKEN_NONE = 0,
92 LYXP_TOKEN_PAR1, /* '(' */
93 LYXP_TOKEN_PAR2, /* ')' */
94 LYXP_TOKEN_BRACK1, /* '[' */
95 LYXP_TOKEN_BRACK2, /* ']' */
96 LYXP_TOKEN_DOT, /* '.' */
97 LYXP_TOKEN_DDOT, /* '..' */
98 LYXP_TOKEN_AT, /* '@' */
99 LYXP_TOKEN_COMMA, /* ',' */
100 /* LYXP_TOKEN_DCOLON, * '::' * axes not supported */
101 LYXP_TOKEN_NAMETEST, /* NameTest */
102 LYXP_TOKEN_NODETYPE, /* NodeType */
103 LYXP_TOKEN_FUNCNAME, /* FunctionName */
104 LYXP_TOKEN_OPERATOR_LOG, /* Operator 'and', 'or' */
105 LYXP_TOKEN_OPERATOR_COMP, /* Operator '=', '!=', '<', '<=', '>', '>=' */
106 LYXP_TOKEN_OPERATOR_MATH, /* Operator '+', '-', '*', 'div', 'mod', '-' (unary) */
107 LYXP_TOKEN_OPERATOR_UNI, /* Operator '|' */
108 LYXP_TOKEN_OPERATOR_PATH, /* Operator '/', '//' */
109 /* LYXP_TOKEN_AXISNAME, * AxisName * axes not supported */
110 LYXP_TOKEN_LITERAL, /* Literal - with either single or double quote */
111 LYXP_TOKEN_NUMBER /* Number */
112};
113
114/**
115 * @brief Structure holding a parsed XPath expression.
116 */
117struct lyxp_expr {
118 enum lyxp_token *tokens; /* array of tokens */
119 uint16_t *expr_pos; /* array of pointers to the expression in expr (idx of the beginning) */
120 uint8_t *tok_len; /* array of token lengths in expr */
121 uint8_t **repeat; /* array of the operator token indices that succeed this expression ended with 0,
122 more in the comment after this declaration */
123 uint16_t used; /* used array items */
124 uint16_t size; /* allocated array items */
125
126 const char *expr; /* the original XPath expression */
127};
128
129/*
130 * lyxp_expr repeat
131 *
132 * This value is NULL for all the tokens that do not begin an
133 * expression which can be repeated. Otherwise it is an array
134 * of indices in the tokens array that are an operator for
135 * which the current expression is an operand. These values
136 * are used during evaluation to know whether we need to
137 * duplicate the current context or not. Examples:
138 *
139 * Expression: "/ *[key1 and key2 or key1 < key2]"
140 * Tokens: '/', '*', '[', NameTest, 'and', NameTest, 'or', NameTest, '<', NameTest, ']'
141 * Repeat: NULL, NULL, NULL, [4, 6, 0], NULL, NULL, NULL, [8, 0], NULL, NULL, NULL
142 *
143 * Expression: "//node[key and node2]/key | /cont"
144 * Tokens: '//', 'NameTest', '[', 'NameTest', 'and', 'NameTest', ']', '/', 'NameTest', '|', '/', 'NameTest'
145 * Repeat: [9, 0], NULL, NULL, [4, 0], NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
146 *
147 * Operators between expressions that are concerned:
148 * 'or', 'and', '=', '!=', '<', '>', '<=', '>=', '+', '-', '*', 'div', 'mod', '|'
149 */
150
151/**
152 * @brief Supported types of (partial) XPath results.
153 */
154enum lyxp_set_type {
155 LYXP_SET_EMPTY = 0,
156 LYXP_SET_NODE_SET,
157 LYXP_SET_BOOLEAN,
158 LYXP_SET_NUMBER,
159 LYXP_SET_STRING
160};
161
162/**
163 * @brief XPath set - (partial) result.
164 */
165struct lyxp_set {
166 enum lyxp_set_type type;
167 union {
168 struct lyd_node **nodes;
169 struct lyd_attr **attrs;
170 const char *str;
171 long double num;
172 int bool;
173 } value;
174
175 /* this is valid only for type == LYXP_NODE_SET */
176 enum lyxp_node_type *node_type; /* item with this index is of this node type */
177 uint16_t used;
178 uint16_t size;
179 uint16_t pos; /* current context position, indexed from 1, relevant only for predicates */
180};
181
182/**
183 * @brief Types of nodes that can be in an LYXP_SET_NODE_SET XPath set.
184 */
185enum lyxp_node_type {
Michal Vaskoc5f2dc22015-10-06 11:40:39 +0200186 LYXP_NODE_ROOT_CONFIG, /* <running> data context (node value NULL) */
187 LYXP_NODE_ROOT_STATE, /* <running> + state data context (node value NULL) */
188 LYXP_NODE_ROOT_NOTIF, /* notification context (node value LYS_NOTIF) */
189 LYXP_NODE_ROOT_RPC, /* RPC (input) context (node value LYS_RPC) */
190 LYXP_NODE_ROOT_OUTPUT, /* RPC output-only context (node value LYS_RPC) */
Michal Vasko8c09d262015-10-01 16:03:01 +0200191
Michal Vasko25895052015-09-21 11:41:12 +0200192 LYXP_NODE_ELEM,
193 LYXP_NODE_TEXT,
194 LYXP_NODE_ATTR
195};
196
197/**
Michal Vaskoe8652d82015-10-01 09:50:58 +0200198 * @brief Evaluate the XPath expression \p expr on data. The context must have
199 * a single root without configuration meaning, but with schema with nodetype set.
Michal Vasko25895052015-09-21 11:41:12 +0200200 *
Michal Vaskoc5f2dc22015-10-06 11:40:39 +0200201 * @param[in] expr XPath expression to evaluate.
Michal Vasko25895052015-09-21 11:41:12 +0200202 * @param[in] cur_node Current (context) data node.
203 * @param[out] set Result set.
Michal Vasko8c09d262015-10-01 16:03:01 +0200204 * @param[in] line Line in the input file.
Michal Vasko25895052015-09-21 11:41:12 +0200205 *
206 * @return EXIT_SUCCESS on success, -1 on error.
207 */
208int lyxp_eval(const char *expr, struct lyd_node *cur_node, struct lyxp_set **set, uint32_t line);
209
Michal Vasko5fb299e2015-10-06 15:44:55 +0200210/**
Michal Vasko7e18c452015-10-07 09:34:36 +0200211 * @brief Check the syntax of an XPath expression \p expr. Since it's only syntactic,
212 * node and function names may still be invalid.
213 *
214 * @param[in] expr XPath expression to check.
215 * @param[in] line Line in the input file.
216 *
217 * @return EXIT_SUCCESS on pass, -1 on failure.
218 */
219int lyxp_syntax_check(const char *expr, uint32_t line);
220
221/**
Michal Vasko04854892015-10-06 15:45:43 +0200222 * @brief Print \p set contents.
223 *
224 * @param[in] f File stream to use.
225 * @param[in] set Set to print.
226 */
227void lyxp_print_set_xml(FILE *f, struct lyxp_set *set);
228
229/**
Michal Vasko5fb299e2015-10-06 15:44:55 +0200230 * @brief Free contents of an XPath \p set.
231 *
232 * @param[in] set Set to free.
233 * @param[in] ctx libyang context to use.
234 */
235void lyxp_set_free(struct lyxp_set *set, struct ly_ctx *ctx);
236
Michal Vasko25895052015-09-21 11:41:12 +0200237#endif /* _XPATH_H */