Browse Source

Implement 'insert' operation

Serj Kalichev 1 year ago
parent
commit
24eedb5772
7 changed files with 211 additions and 45 deletions
  1. 9 0
      src/pline.c
  2. 1 0
      src/pline.h
  3. 4 0
      src/plugin.c
  4. 171 42
      src/syms.c
  5. 2 0
      src/syms.h
  6. 21 0
      ttt.yang
  7. 3 3
      xml/sysrepo.xml

+ 9 - 0
src/pline.c

@@ -39,6 +39,7 @@ static pexpr_t *pexpr_new(void)
 	pexpr->pat = PAT_NONE;
 	pexpr->args_num = 0;
 	pexpr->list_pos = 0;
+	pexpr->last_keys = NULL;
 
 	return pexpr;
 }
@@ -51,6 +52,7 @@ static void pexpr_free(pexpr_t *pexpr)
 
 	faux_str_free(pexpr->xpath);
 	faux_str_free(pexpr->value);
+	faux_str_free(pexpr->last_keys);
 
 	free(pexpr);
 }
@@ -243,6 +245,7 @@ void pline_debug(pline_t *pline)
 		printf("pexpr.pat = %s\n", pat);
 		printf("pexpr.args_num = %lu\n", pexpr->args_num);
 		printf("pexpr.list_pos = %lu\n", pexpr->list_pos);
+		printf("pexpr.last_keys = %s\n", pexpr->last_keys ? pexpr->last_keys : "NULL");
 		printf("\n");
 	}
 
@@ -408,6 +411,8 @@ static bool_t pline_parse_module(const struct lys_module *module, faux_argv_t *a
 
 			pexpr->pat = PAT_LIST;
 			pexpr->list_pos = pexpr->args_num;
+			faux_str_free(pexpr->last_keys);
+			pexpr->last_keys = NULL;
 
 			// Next element
 			if (!is_rollback) {
@@ -440,6 +445,7 @@ static bool_t pline_parse_module(const struct lys_module *module, faux_argv_t *a
 					tmp = faux_str_sprintf("[%s='%s']",
 						leaf->name, str);
 					faux_str_cat(&pexpr->xpath, tmp);
+					faux_str_cat(&pexpr->last_keys, tmp);
 					faux_str_free(tmp);
 					pexpr->args_num++;
 					faux_argv_each(&arg);
@@ -522,6 +528,8 @@ static bool_t pline_parse_module(const struct lys_module *module, faux_argv_t *a
 
 			pexpr->pat = PAT_LEAFLIST;
 			pexpr->list_pos = pexpr->args_num;
+			faux_str_free(pexpr->last_keys);
+			pexpr->last_keys = NULL;
 
 			// Completion
 			if (!str) {
@@ -542,6 +550,7 @@ static bool_t pline_parse_module(const struct lys_module *module, faux_argv_t *a
 			tmp = faux_str_sprintf("[.='%s%s%s']",
 			prefix ? prefix : "", prefix ? ":" : "", str);
 			faux_str_cat(&pexpr->xpath, tmp);
+			faux_str_cat(&pexpr->last_keys, str);
 			faux_str_free(tmp);
 			pexpr->args_num++;
 

+ 1 - 0
src/pline.h

@@ -81,6 +81,7 @@ typedef struct {
 	pat_e pat;
 	size_t args_num;
 	size_t list_pos;
+	char *last_keys;
 } pexpr_t;
 
 

+ 4 - 0
src/plugin.c

@@ -51,6 +51,10 @@ int kplugin_sysrepo_init(kcontext_t *context)
 		KSYM_USERDEFINED_PERMANENT, KSYM_UNSYNC));
 	kplugin_add_syms(plugin, ksym_new_ext("srp_help", srp_help,
 		KSYM_USERDEFINED_PERMANENT, KSYM_UNSYNC));
+	kplugin_add_syms(plugin, ksym_new_ext("srp_compl_insert_to", srp_compl_insert_to,
+		KSYM_USERDEFINED_PERMANENT, KSYM_UNSYNC));
+	kplugin_add_syms(plugin, ksym_new_ext("srp_help_insert_to", srp_help_insert_to,
+		KSYM_USERDEFINED_PERMANENT, KSYM_UNSYNC));
 	kplugin_add_syms(plugin, ksym_new_ext("srp_prompt_edit_path", srp_prompt_edit_path,
 		KSYM_USERDEFINED_PERMANENT, KSYM_UNSYNC));
 

+ 171 - 42
src/syms.c

@@ -123,6 +123,7 @@ static int srp_check_type(kcontext_t *context,
 	pt_e not_accepted_nodes,
 	size_t max_expr_num)
 {
+	int ret = -1;
 	faux_argv_t *args = NULL;
 	pline_t *pline = NULL;
 	sr_conn_ctx_t *conn = NULL;
@@ -154,21 +155,23 @@ static int srp_check_type(kcontext_t *context,
 	faux_argv_free(args);
 
 	if (pline->invalid)
-		return -1;
+		goto err;
 	expr_num = faux_list_len(pline->exprs);
 	if (expr_num < 1)
-		return -1;
+		goto err;
 	if ((max_expr_num > 0) &&  // '0' means unlimited
 		(expr_num > max_expr_num))
-		return -1;
+		goto err;
 	expr = pline_current_expr(pline);
 	if (expr->pat & not_accepted_nodes)
-		return -1;
+		goto err;
 
+	ret = 0;
+err:
 	pline_free(pline);
 	sr_disconnect(conn);
 
-	return 0;
+	return ret;
 }
 
 
@@ -227,7 +230,94 @@ static faux_argv_t *assemble_insert_to(sr_session_ctx_t *sess, const kpargv_t *p
 
 int srp_PLINE_INSERT_TO(kcontext_t *context)
 {
-	return srp_check_type(context, PT_NOT_INSERT, 1);
+	int ret = -1;
+	faux_argv_t *args = NULL;
+	pline_t *pline = NULL;
+	sr_conn_ctx_t *conn = NULL;
+	sr_session_ctx_t *sess = NULL;
+	const char *value = NULL;
+	pexpr_t *expr = NULL;
+	size_t expr_num = 0;
+	faux_argv_t *cur_path = NULL;
+	kplugin_t *plugin = NULL;
+
+	assert(context);
+
+	if (sr_connect(SR_CONN_DEFAULT, &conn))
+		return -1;
+	if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
+		sr_disconnect(conn);
+		return -1;
+	}
+
+	plugin = kcontext_plugin(context);
+	cur_path = (faux_argv_t *)kplugin_udata(plugin);
+	value = kcontext_candidate_value(context);
+	args = assemble_insert_to(sess, kcontext_parent_pargv(context),
+		cur_path, value);
+	pline = pline_parse(sess, args, 0);
+	faux_argv_free(args);
+
+	if (pline->invalid)
+		goto err;
+	expr_num = faux_list_len(pline->exprs);
+	if (expr_num != 1)
+		goto err;
+	expr = pline_current_expr(pline);
+	if (expr->pat & PT_NOT_INSERT)
+		goto err;
+
+	ret = 0;
+err:
+	pline_free(pline);
+	sr_disconnect(conn);
+
+	return ret;
+}
+
+
+static int srp_compl_or_help_insert_to(kcontext_t *context, bool_t help)
+{
+	faux_argv_t *args = NULL;
+	pline_t *pline = NULL;
+	sr_conn_ctx_t *conn = NULL;
+	sr_session_ctx_t *sess = NULL;
+	faux_argv_t *cur_path = NULL;
+	kplugin_t *plugin = NULL;
+
+	assert(context);
+
+	if (sr_connect(SR_CONN_DEFAULT, &conn))
+		return -1;
+	if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
+		sr_disconnect(conn);
+		return -1;
+	}
+
+	plugin = kcontext_plugin(context);
+	cur_path = (faux_argv_t *)kplugin_udata(plugin);
+	args = assemble_insert_to(sess, kcontext_parent_pargv(context),
+		cur_path, NULL);
+	pline = pline_parse(sess, args, 0);
+	faux_argv_free(args);
+	pline_print_completions(pline, help);
+	pline_free(pline);
+
+	sr_disconnect(conn);
+
+	return 0;
+}
+
+
+int srp_compl_insert_to(kcontext_t *context)
+{
+	return srp_compl_or_help_insert_to(context, BOOL_FALSE);
+}
+
+
+int srp_help_insert_to(kcontext_t *context)
+{
+	return srp_compl_or_help_insert_to(context, BOOL_TRUE);
 }
 
 
@@ -508,17 +598,22 @@ int srp_up(kcontext_t *context)
 
 int srp_insert(kcontext_t *context)
 {
-	int ret = 0;
-	faux_argv_t *args = NULL;
+	int ret = -1;
 	pline_t *pline = NULL;
+	pline_t *pline_to = NULL;
 	sr_conn_ctx_t *conn = NULL;
 	sr_session_ctx_t *sess = NULL;
 	faux_list_node_t *iter = NULL;
 	pexpr_t *expr = NULL;
-	size_t err_num = 0;
+	pexpr_t *expr_to = NULL;
 	faux_argv_t *cur_path = NULL;
 	kplugin_t *plugin = NULL;
+	faux_argv_t *insert_from = NULL;
 	faux_argv_t *insert_to = NULL;
+	sr_move_position_t position = SR_MOVE_LAST;
+	kpargv_t *pargv = NULL;
+	const char *list_keys = NULL;
+	const char *leaflist_value = NULL;
 
 	assert(context);
 
@@ -531,51 +626,85 @@ int srp_insert(kcontext_t *context)
 
 	plugin = kcontext_plugin(context);
 	cur_path = (faux_argv_t *)kplugin_udata(plugin);
+	pargv = kcontext_pargv(context);
 
-	insert_to = assemble_insert_to(sess, kcontext_pargv(context),
-		cur_path, NULL);
-	printf("insert_to: %s\n", faux_argv_line(insert_to));
-	faux_argv_free(insert_to);
-
-/*
-	args = param2argv(cur_path, kcontext_pargv(context), "path");
-	pline = pline_parse(sess, args, 0);
-	faux_argv_free(args);
+	// 'from' argument
+	insert_from = param2argv(cur_path, pargv, "from_path");
+	pline = pline_parse(sess, insert_from, 0);
+	faux_argv_free(insert_from);
 
 	if (pline->invalid) {
-		fprintf(stderr, "Invalid set request\n");
-		ret = -1;
-		goto cleanup;
+		fprintf(stderr, "Invalid 'from' expression\n");
+		goto err;
 	}
 
-	iter = faux_list_head(pline->exprs);
-	while ((expr = (pexpr_t *)faux_list_each(&iter))) {
-		if (!(expr->pat & PT_SET)) {
-			err_num++;
-			fprintf(stderr, "Illegal expression for set operation\n");
-			break;
+	if (faux_list_len(pline->exprs) > 1) {
+		fprintf(stderr, "Can't process more than one object\n");
+		goto err;
+	}
+
+	expr = (pexpr_t *)faux_list_data(faux_list_head(pline->exprs));
+
+	if (!(expr->pat & PT_INSERT)) {
+		fprintf(stderr, "Illegal 'from' expression for 'insert' operation\n");
+		goto err;
+	}
+
+	// Position
+	if (kpargv_find(pargv, "first"))
+		position = SR_MOVE_FIRST;
+	else if (kpargv_find(pargv, "last"))
+		position = SR_MOVE_LAST;
+	else if (kpargv_find(pargv, "before"))
+		position = SR_MOVE_BEFORE;
+	else if (kpargv_find(pargv, "after"))
+		position = SR_MOVE_AFTER;
+	else {
+		fprintf(stderr, "Illegal 'position' argument\n");
+		goto err;
+	}
+
+	// 'to' argument
+	if ((SR_MOVE_BEFORE == position) || (SR_MOVE_AFTER == position)) {
+		insert_to = assemble_insert_to(sess, pargv, cur_path, NULL);
+		pline_to = pline_parse(sess, insert_to, 0);
+		faux_argv_free(insert_to);
+
+		if (pline_to->invalid) {
+			fprintf(stderr, "Invalid 'to' expression\n");
+			goto err;
 		}
-		if (sr_set_item_str(sess, expr->xpath, expr->value, NULL, 0) !=
-			SR_ERR_OK) {
-			err_num++;
-			fprintf(stderr, "Can't set data\n");
-			break;
+
+		if (faux_list_len(pline_to->exprs) > 1) {
+			fprintf(stderr, "Can't process more than one object\n");
+			goto err;
 		}
-	}
 
-	if (sr_has_changes(sess)) {
-		if (err_num > 0)
-			sr_discard_changes(sess);
-		else
-			sr_apply_changes(sess, 0);
+		expr_to = (pexpr_t *)faux_list_data(faux_list_head(pline_to->exprs));
+
+		if (!(expr_to->pat & PT_INSERT)) {
+			fprintf(stderr, "Illegal 'to' expression for 'insert' operation\n");
+			goto err;
+		}
+
+		if (PAT_LIST_KEY == expr_to->pat)
+			list_keys = expr_to->last_keys;
+		else // PATH_LEAFLIST_VALUE
+			leaflist_value = expr_to->last_keys;
 	}
 
-	if (err_num > 0)
-		ret = -1;
+	if (sr_move_item(sess, expr->xpath, position,
+		list_keys, leaflist_value, NULL, 0) != SR_ERR_OK) {
+		fprintf(stderr, "Can't move element\n");
+		goto err;
+	}
+	sr_apply_changes(sess, 0);
 
-cleanup:
+	ret = 0;
+err:
 	pline_free(pline);
-*/	sr_disconnect(conn);
+	pline_free(pline_to);
+	sr_disconnect(conn);
 
 	return ret;
 }

+ 2 - 0
src/syms.h

@@ -23,6 +23,8 @@ int srp_PLINE_INSERT_TO(kcontext_t *context);
 // Completion/Help/Prompt
 int srp_compl(kcontext_t *context);
 int srp_help(kcontext_t *context);
+int srp_compl_insert_to(kcontext_t *context);
+int srp_help_insert_to(kcontext_t *context);
 int srp_prompt_edit_path(kcontext_t *context);
 
 // Operations

+ 21 - 0
ttt.yang

@@ -44,4 +44,25 @@ module ttt {
 
     }
   }
+
+
+  list acl {
+    ordered-by user;
+    key "name";
+
+    leaf name {
+      type string;
+    }
+
+    leaf comment {
+      type string;
+    }
+
+    leaf-list multi {
+      ordered-by user;
+      type string;
+    }
+
+  }
+
 }

+ 3 - 3
xml/sysrepo.xml

@@ -49,10 +49,10 @@
 
 <ENTRY name="PLINE_INSERT_TO" purpose="ptype">
 	<ENTRY name="completion" purpose="completion">
-		<ACTION sym="srp_compl@sysrepo"/>
+		<ACTION sym="srp_compl_insert_to@sysrepo"/>
 	</ENTRY>
 	<ENTRY name="help" purpose="help">
-		<ACTION sym="srp_help@sysrepo"/>
+		<ACTION sym="srp_help_insert_to@sysrepo"/>
 	</ENTRY>
 	<ACTION sym="PLINE_INSERT_TO@sysrepo"/>
 </ENTRY>
@@ -128,7 +128,7 @@
 				<ENTRY name="SUBCOMMAND" purpose="ptype" ref="/SUBCOMMAND"/>
 			</ENTRY>
 			<ENTRY name="relative_block" mode="sequence" container="true">
-				<ENTRY name="position" mode="switch" container="true">
+				<ENTRY name="relative" mode="switch" container="true">
 					<ENTRY name="before" help="Before specified element">
 						<ENTRY name="SUBCOMMAND" purpose="ptype" ref="/SUBCOMMAND"/>
 					</ENTRY>