From b551e9e5c7ec12ec4ab330c94134d3c3ccd5aca7 Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Mon, 19 Feb 2024 12:20:20 +0100 Subject: [PATCH] Added xml_template_apply --- lib/clixon/clixon_string.h | 1 + lib/clixon/clixon_xml_map.h | 1 + lib/src/clixon_string.c | 66 +++++++++++++++++++++++++++++++++++++ lib/src/clixon_xml_map.c | 66 +++++++++++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+) diff --git a/lib/clixon/clixon_string.h b/lib/clixon/clixon_string.h index a5a5d94e..3e112ab4 100644 --- a/lib/clixon/clixon_string.h +++ b/lib/clixon/clixon_string.h @@ -89,6 +89,7 @@ static inline char * strdup4(char *str) * Prototypes */ char **clicon_strsep(char *string, char *delim, int *nvec0); +int clixon_strsep2(char *str, char *delim1, char *delim2, char ***vcp, int *nvec); char *clicon_strjoin (int argc, char **argv, char *delim); char *clixon_string_del_join(char *str1, char *del, char *str2); int clixon_strsplit(char *nodeid, const int delim, char **prefix, char **id); diff --git a/lib/clixon/clixon_xml_map.h b/lib/clixon/clixon_xml_map.h index 53562765..12ace1e7 100644 --- a/lib/clixon/clixon_xml_map.h +++ b/lib/clixon/clixon_xml_map.h @@ -78,5 +78,6 @@ int xml_rpc_isaction(cxobj *xn); int xml_find_action(cxobj *xn, int top, cxobj **xap); int purge_tagged_nodes(cxobj *xn, char *ns, char *name, char *value, int keepnode); int clixon_compare_xmls(cxobj *xc1, cxobj *xc2, enum format_enum format); +int xml_template_apply(cxobj *x, void *arg); #endif /* _CLIXON_XML_MAP_H_ */ diff --git a/lib/src/clixon_string.c b/lib/src/clixon_string.c index 14d72fc6..f715f5c9 100644 --- a/lib/src/clixon_string.c +++ b/lib/src/clixon_string.c @@ -121,6 +121,72 @@ clicon_strsep(char *string, return vec; } +/*! Split string using start and stop delimiter strings usable for variable substitution + * + * Example: "foo ${NAME} bar" + * where delim1="${" and delim2="}" + * returns vec: "foo ", "NAME", "bar" + * Both delim1 and delim2 must match + * @param[in] str + * @param[in] delim1 prefix delimiter string + * @param[in] delim2 postfix delimiter string + * @param[out] cvp Created cligen variable vector, deallocate w cvec_free + * @retval 0 OK + * @retval -1 Error + */ +int +clixon_strsep2(char *str, + char *delim1, + char *delim2, + char ***vcp, + int *nvec) +{ + int retval = -1; + size_t sz; + char **vec = NULL; + char *s1; + char *s2; + int nr = 0; + char *ptr; + int i; + + s1 = str; + while ((s1 = strstr(s1, delim1)) != NULL){ + if ((s2 = strstr(s1+strlen(delim1), delim2)) != NULL) + nr += 2; + s1 = s2 + strlen(delim2); + } + /* alloc vector and append copy of string */ + sz = (nr+1)* sizeof(char*) + strlen(str)+1; + if ((vec = (char**)malloc(sz)) == NULL){ + clixon_err(OE_UNIX, errno, "malloc"); + goto done; + } + memset(vec, 0, sz); + ptr = (char*)vec + (nr+1)* sizeof(char*); /* this is where ptr starts */ + strcpy(ptr, str); + i = 0; + s1 = ptr; + vec[i++] = ptr; + while ((s1 = strstr(s1, delim1)) != NULL){ + if ((s2 = strstr(s1+strlen(delim1), delim2)) != NULL){ + *s1 = '\0'; + *s2 = '\0'; + vec[i++] = s1 + strlen(delim1); + vec[i++] = s2 + strlen(delim2); + } + s1 = s2 + strlen(delim2); + } + *vcp = vec; + ptr = NULL; + *nvec = i; + retval = 0; + done: + if (ptr) + free(ptr); + return retval; +} + /*! Concatenate elements of a string array into a string. * * An optional delimiter string can be specified which will be inserted between diff --git a/lib/src/clixon_xml_map.c b/lib/src/clixon_xml_map.c index b685c5ba..4a8d3e0c 100644 --- a/lib/src/clixon_xml_map.c +++ b/lib/src/clixon_xml_map.c @@ -2104,3 +2104,69 @@ clixon_compare_xmls(cxobj *xc1, unlink(filename2); return retval; } + +/*! XML apply function: replace ${} variables with values from cligen variable vector + * + * @param[in] x XML node + * @param[in] arg cvv: vector of name/value pairs + * @retval -1 Error, aborted at first error encounter, return -1 to end user + * @retval 0 OK, continue + * @retval 1 Abort, dont continue with others, return 1 to end user + * @retval 2 Locally abort this subtree, continue with others + */ +int +xml_template_apply(cxobj *x, + void *arg) +{ + int retval = -1; + cvec *cvv = (cvec *)arg; + cxobj *xb; + char *b; + char *var; + char *varname; + char *varval; + cbuf *cb = NULL; + int i; + char **vec = NULL; + int nvec = 0; + cg_var *cv = NULL; + + if ((xb = xml_body_get(x)) != NULL && + (b = xml_value(xb)) != NULL){ + if (clixon_strsep2(b, "${", "}", &vec, &nvec) < 0) + goto done; + assert(nvec%2 == 1); /* Must be odd */ + if (nvec > 1){ + if ((cb = cbuf_new()) == NULL){ + clixon_err(OE_UNIX, errno, "cbuf_new"); + goto done; + } + i = 0; + while (i < nvec){ + cprintf(cb, "%s", vec[i++]); + if (i == nvec) + break; + var = vec[i++]; + assert(i < nvec); /* Must be odd */ + cv = NULL; + while ((cv = cvec_each(cvv, cv)) != NULL){ + if ((varname = cv_name_get(cv)) == NULL) + continue; + if (strcmp(varname, var) != 0) + continue; + varval = cv_string_get(cv); + cprintf(cb, "%s", varval); + break; + } + } + xml_value_set(xb, cbuf_get(cb)); + } + } + retval = 0; + done: + if (vec) + free(vec); + if (cb) + cbuf_free(cb); + return retval; +}