xpath UPDATE allow duplicating parsed subexpr
diff --git a/src/xpath.c b/src/xpath.c
index 3cf8539..d7efcf6 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -3169,55 +3169,84 @@
}
LY_ERR
-lyxp_expr_dup(const struct ly_ctx *ctx, const struct lyxp_expr *exp, struct lyxp_expr **dup_p)
+lyxp_expr_dup(const struct ly_ctx *ctx, const struct lyxp_expr *exp, uint16_t start_idx, uint16_t end_idx,
+ struct lyxp_expr **dup_p)
{
LY_ERR ret = LY_SUCCESS;
struct lyxp_expr *dup = NULL;
- uint32_t i, j;
+ uint16_t used = 0, i, j, k, expr_len;
+ const char *expr_start;
+
+ assert((!start_idx && !end_idx) || ((start_idx < exp->used) && (end_idx < exp->used) && (start_idx <= end_idx)));
if (!exp) {
goto cleanup;
}
+ if (!start_idx && !end_idx) {
+ end_idx = exp->used - 1;
+ }
+
+ expr_start = exp->expr + exp->tok_pos[start_idx];
+ expr_len = (exp->tok_pos[end_idx] + exp->tok_len[end_idx]) - exp->tok_pos[start_idx];
+
dup = calloc(1, sizeof *dup);
LY_CHECK_ERR_GOTO(!dup, LOGMEM(ctx); ret = LY_EMEM, cleanup);
if (exp->used) {
- dup->tokens = malloc(exp->used * sizeof *dup->tokens);
+ used = (end_idx - start_idx) + 1;
+
+ dup->tokens = malloc(used * sizeof *dup->tokens);
LY_CHECK_ERR_GOTO(!dup->tokens, LOGMEM(ctx); ret = LY_EMEM, cleanup);
- memcpy(dup->tokens, exp->tokens, exp->used * sizeof *dup->tokens);
+ memcpy(dup->tokens, exp->tokens + start_idx, used * sizeof *dup->tokens);
- dup->tok_pos = malloc(exp->used * sizeof *dup->tok_pos);
+ dup->tok_pos = malloc(used * sizeof *dup->tok_pos);
LY_CHECK_ERR_GOTO(!dup->tok_pos, LOGMEM(ctx); ret = LY_EMEM, cleanup);
- memcpy(dup->tok_pos, exp->tok_pos, exp->used * sizeof *dup->tok_pos);
+ memcpy(dup->tok_pos, exp->tok_pos + start_idx, used * sizeof *dup->tok_pos);
- dup->tok_len = malloc(exp->used * sizeof *dup->tok_len);
+ if (start_idx) {
+ /* fix the indices in the expression */
+ for (i = 0; i < used; ++i) {
+ dup->tok_pos[i] -= expr_start - exp->expr;
+ }
+ }
+
+ dup->tok_len = malloc(used * sizeof *dup->tok_len);
LY_CHECK_ERR_GOTO(!dup->tok_len, LOGMEM(ctx); ret = LY_EMEM, cleanup);
- memcpy(dup->tok_len, exp->tok_len, exp->used * sizeof *dup->tok_len);
+ memcpy(dup->tok_len, exp->tok_len + start_idx, used * sizeof *dup->tok_len);
if (exp->repeat) {
- dup->repeat = malloc(exp->used * sizeof *dup->repeat);
+ dup->repeat = malloc(used * sizeof *dup->repeat);
LY_CHECK_ERR_GOTO(!dup->repeat, LOGMEM(ctx); ret = LY_EMEM, cleanup);
- for (i = 0; i < exp->used; ++i) {
+ for (i = start_idx; i <= end_idx; ++i) {
if (!exp->repeat[i]) {
- dup->repeat[i] = NULL;
+ dup->repeat[i - start_idx] = NULL;
} else {
for (j = 0; exp->repeat[i][j]; ++j) {}
/* the ending 0 as well */
++j;
- dup->repeat[i] = malloc(j * sizeof **dup->repeat);
- LY_CHECK_ERR_GOTO(!dup->repeat[i], LOGMEM(ctx); ret = LY_EMEM, cleanup);
- memcpy(dup->repeat[i], exp->repeat[i], j * sizeof **dup->repeat);
- dup->repeat[i][j - 1] = 0;
+ dup->repeat[i - start_idx] = malloc(j * sizeof **dup->repeat);
+ LY_CHECK_ERR_GOTO(!dup->repeat[i - start_idx], LOGMEM(ctx); ret = LY_EMEM, cleanup);
+ memcpy(dup->repeat[i - start_idx], exp->repeat[i], j * sizeof **dup->repeat);
+ dup->repeat[i - start_idx][j - 1] = 0;
+
+ if (start_idx) {
+ /* fix the indices in the tokens */
+ for (k = 0; k < j; ++k) {
+ dup->repeat[i - start_idx][k] -= start_idx;
+ }
+ }
}
}
}
}
- dup->used = exp->used;
- dup->size = exp->used;
- LY_CHECK_GOTO(ret = lydict_insert(ctx, exp->expr, 0, &dup->expr), cleanup);
+ dup->used = used;
+ dup->size = used;
+
+ /* copy only subexpression */
+ LY_CHECK_GOTO(ret = lydict_insert(ctx, expr_start, expr_len, &dup->expr), cleanup);
cleanup:
if (ret) {