Skip to content

Commit

Permalink
C-API: string to pointer map
Browse files Browse the repository at this point in the history
Optimization of yspec+namespace lookup
Optimization of non-presence container default tree
  • Loading branch information
olofhagsand committed Jan 10, 2025
1 parent 3be786c commit b09e326
Show file tree
Hide file tree
Showing 10 changed files with 303 additions and 20 deletions.
13 changes: 13 additions & 0 deletions include/clixon_custom.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,16 @@
* A more intelligent algorithm is needed
*/
#define XML_DEFAULT_WHEN_TWICE

/*! If set, make optimized lookup of yspec + namespace -> module
*
* see yang_find_module_by_namespace
*/
#define OPTIMIZE_YSPEC_NAMESPACE

/*! If set, make optimization of non-presence default container
*
* Save the default XML in YANG and reuse next time
* see xml_default
*/
#define OPTIMIZE_NO_PRESENCE_CONTAINER
19 changes: 15 additions & 4 deletions lib/clixon/clixon_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,27 @@ static const map_str2int atmap[] = {
* @see clicon_str2int
*/
struct map_str2int{
char *ms_str;
int ms_int;
char *ms_str;
int ms_int;
};
typedef struct map_str2int map_str2int;

/*! Struct used to map between two strings.
*/
struct map_str2str{
char *ms_s0;
char *ms_s1;
char *ms_s0;
char *ms_s1;
};
typedef struct map_str2str map_str2str;

/*! Struct used to map from string to pointer
*/
struct map_str2ptr{
char *mp_str;
void *mp_ptr;
};
typedef struct map_str2ptr map_str2ptr;

/*! Map from ptr to ptr
*/
struct map_ptr2ptr{
Expand All @@ -82,6 +90,9 @@ const char *clicon_int2str(const map_str2int *mstab, int i);
int clicon_str2int(const map_str2int *mstab, char *str);
int clicon_str2int_search(const map_str2int *mstab, char *str, int upper);
char *clicon_str2str(const map_str2str *mstab, char *str);
void clixon_str2ptr_sort(map_str2ptr *mptab, size_t len);
void *clixon_str2ptr(map_str2ptr *mptab, char *str, size_t len);
int clixon_str2ptr_print(FILE *f, map_str2ptr *mptab);
void *clixon_ptr2ptr(map_ptr2ptr *mptab, void *ptr);
int clixon_ptr2ptr_add(map_ptr2ptr **mptab, void *ptr0, void *ptr1);

Expand Down
4 changes: 4 additions & 0 deletions lib/clixon/clixon_yang.h
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,10 @@ int yang_sort_subelements(yang_stmt *ys);
int yang_single_child_type(yang_stmt *ys, enum rfc_6020 subkeyw);
void *yang_action_cb_get(yang_stmt *ys);
int yang_action_cb_add(yang_stmt *ys, void *rc);
#ifdef OPTIMIZE_NO_PRESENCE_CONTAINER
void *yang_nopresence_cache_get(yang_stmt *ys);
int yang_nopresence_cache_set(yang_stmt *ys, void *x);
#endif
int ys_populate_feature(clixon_handle h, yang_stmt *ys);
int yang_init(clixon_handle h);
int yang_start(clixon_handle h);
Expand Down
5 changes: 5 additions & 0 deletions lib/clixon/clixon_yang_parse_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,10 @@ int yang_spec_load_dir(clixon_handle h, char *dir, yang_stmt *yspec);
int ys_parse_date_arg(char *datearg, uint32_t *dateint);
cg_var *ys_parse(yang_stmt *ys, enum cv_type cvtype);
int ys_parse_sub(yang_stmt *ys, const char *filename, char *extra);
#ifdef OPTIMIZE_YSPEC_NAMESPACE
int yspec_nscache_clear(yang_stmt *yspec);
yang_stmt *yspec_nscache_get(yang_stmt *yspec, char *ns);
int yspec_nscache_new(yang_stmt *yspec);
#endif

#endif /* _CLIXON_YANG_LIB_H_ */
116 changes: 113 additions & 3 deletions lib/src/clixon_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
#include "clixon_yang.h"
#include "clixon_xml.h"
#include "clixon_err.h"
#include "clixon_string.h"

/*! Map from int to string using str2int map
*
Expand Down Expand Up @@ -116,9 +117,9 @@ str2int_search1(const map_str2int *mstab,
int len,
int *found)
{
const struct map_str2int *ms;
int mid;
int cmp;
const map_str2int *ms;
int mid;
int cmp;

if (upper < low)
return 0; /* not found */
Expand All @@ -136,10 +137,58 @@ str2int_search1(const map_str2int *mstab,
return str2int_search1(mstab, str, mid+1, upper, len, found);
}

/*! Map from string to ptr using binary (alphatical) search
*
* Assumes sorted strings, tree search. If two are equal take first
* @param[in] ms String, integer map
* @param[in] str Input string
* @param[in] low Lower bound index
* @param[in] upper Upper bound index
* @param[in] len Length of array (max)
* @param[out] found element
* @retval 1 Found with "found" value set.
* @retval 0 Not found
*/
static int
str2ptr_search1(const map_str2ptr *mptab,
char *str,
size_t low,
size_t upper,
size_t len,
map_str2ptr **found)
{
const map_str2ptr *mp;
int mid;
int cmp;
int i;

if (upper < low)
return 0; /* not found */
mid = (low + upper) / 2;
if (mid >= len) /* beyond range */
return 0; /* not found */
mp = &mptab[mid];
if ((cmp = clicon_strcmp(str, mp->mp_str)) == 0){
i = mid;
while (i >= 0 && clicon_strcmp(str, mptab[i].mp_str) == 0){
mp = &mptab[i];
i--;
}
*found = (map_str2ptr *)mp;
return 1; /* found */
}
else if (cmp < 0)
return str2ptr_search1(mptab, str, low, mid-1, len, found);
else
return str2ptr_search1(mptab, str, mid+1, upper, len, found);
}

/*! Map from string to int using str2int map
*
* @param[in] ms String, integer map
* @param[in] str Input string
* @param[in] len
* @retval int Value
* @retval -1 Error, not found
* @note Assumes sorted strings, tree search
Expand Down Expand Up @@ -176,6 +225,67 @@ clicon_str2str(const map_str2str *mstab,
return NULL;
}

static int
str2ptr_qsort(const void* arg1,
const void* arg2)
{
map_str2ptr *mp1 = (map_str2ptr*)arg1;
map_str2ptr *mp2 = (map_str2ptr*)arg2;
int eq;
yang_stmt *yrev;
char *rev1 = NULL;
char *rev2 = NULL;

eq = clicon_strcmp(mp1->mp_str, mp2->mp_str);
if (0 && eq == 0){
if ((yrev = yang_find(mp1->mp_ptr, Y_REVISION, NULL)) != NULL)
rev1 = yang_argument_get(yrev);
if ((yrev = yang_find(mp2->mp_ptr, Y_REVISION, NULL)) != NULL)
rev2 = yang_argument_get(yrev);
eq = clicon_strcmp(rev1, rev2);
}
return eq;
}

void
clixon_str2ptr_sort(map_str2ptr *mptab,
size_t len)
{
qsort(mptab, len, sizeof(*mptab), str2ptr_qsort);
}

/*! Map from string to string using str2str map
*
* @param[in] mptab String to ptr map
* @param[in] str Input string
* @retval ptr Output pointer
* @retval NULL Error, not found
*/
void*
clixon_str2ptr(map_str2ptr *mptab,
char *str,
size_t len)
{
map_str2ptr *mp = NULL;

if (str2ptr_search1(mptab, str, 0, len, len, &mp))
return mp->mp_ptr;
return NULL; /* not found */
}

int
clixon_str2ptr_print(FILE *f,
map_str2ptr *mptab)
{
map_str2ptr *mp = NULL;
int i;

i = 0;
for (mp = &mptab[0]; mp->mp_str; mp++)
fprintf(f, "%d %s %p\n", i++, mp->mp_str, mp->mp_ptr);
return 0;
}

/*! Map from pointer to pointer using mptab map
*
* @param[in] mptab Ptr to ptr map
Expand Down
41 changes: 31 additions & 10 deletions lib/src/clixon_xml_default.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,9 @@ xml_default(yang_stmt *yt,
int retval = -1;
yang_stmt *yc;
cxobj *xc;
#ifdef OPTIMIZE_NO_PRESENCE_CONTAINER
cxobj *xc1;
#endif
int top = 0; /* Top symbol (set default namespace) */
int create = 0;
int nr = 0;
Expand Down Expand Up @@ -361,19 +364,37 @@ xml_default(yang_stmt *yt,
* defaults.
*/
if (xml_find_type(xt, NULL, yang_argument_get(yc), CX_ELMNT) == NULL){
/* No such container exist, recursively try if needed */
if (xml_nopresence_try(yc, state, &create) < 0)
goto done;
if (create){
/* Retval shows there is a default value need to create the
* container */
if (xml_default_create1(yc, xt, &xc) < 0)
#ifdef OPTIMIZE_NO_PRESENCE_CONTAINER
if ((xc = yang_nopresence_cache_get(yc)) != NULL){
if ((xc1 = xml_dup(xc)) == NULL)
goto done;
xml_sort(xt);
/* Then call it recursively */
if (xml_default(yc, xc, state) < 0)
if (xml_addsub(xt, xc1) < 0)
goto done;
xml_sort(xt);
}
else
#endif
{
/* No such container exist, recursively try if needed */
if (xml_nopresence_try(yc, state, &create) < 0)
goto done;
if (create){
/* Retval shows there is a default value need to create the
* container */
if (xml_default_create1(yc, xt, &xc) < 0)
goto done;
xml_sort(xt);
/* Then call it recursively */
if (xml_default(yc, xc, state) < 0)
goto done;
#ifdef OPTIMIZE_NO_PRESENCE_CONTAINER
if ((xc1 = xml_dup(xc)) == NULL)
goto done;
if (yang_nopresence_cache_set(yc, xc1) < 0)
goto done;
#endif
}
}
}
}
break;
Expand Down
51 changes: 49 additions & 2 deletions lib/src/clixon_yang.c
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,19 @@ ys_free1(yang_stmt *ys,
if (ys->ys_filename)
free(ys->ys_filename);
break;
#ifdef OPTIMIZE_NO_PRESENCE_CONTAINER
case Y_CONTAINER:
if (ys->ys_nopres_cache)
xml_free(ys->ys_nopres_cache);
break;
#endif
#ifdef OPTIMIZE_YSPEC_NAMESPACE
case Y_SPEC:
if (ys->ys_nscache)
free(ys->ys_nscache);
break;
#endif

default:
break;
}
Expand Down Expand Up @@ -1220,6 +1233,11 @@ yn_realloc(yang_stmt *yn)
return -1;
}
yn->ys_stmt[yn->ys_len - 1] = NULL; /* init field */
#ifdef OPTIMIZE_YSPEC_NAMESPACE
if (yn->ys_keyword == Y_SPEC && yn->ys_nscache){ /* Clear cache */
yspec_nscache_clear(yn);
}
#endif
return 0;
}

Expand Down Expand Up @@ -1336,6 +1354,16 @@ ys_cp_one(yang_stmt *ynew,
if (yang_typecache_get(yold)) /* Dont copy type cache, use only original */
yang_typecache_set(ynew, NULL);
break;
#ifdef OPTIMIZE_NO_PRESENCE_CONTAINER
case Y_CONTAINER:
yold->ys_nopres_cache = NULL;
break;
#endif
#ifdef OPTIMIZE_YSPEC_NAMESPACE
case Y_SPEC:
yold->ys_nscache = NULL;
break;
#endif
default:
break;
}
Expand Down Expand Up @@ -4034,11 +4062,12 @@ int
yang_config(yang_stmt *ys)
{
yang_stmt *ym;
cg_var *cv;

if ((ym = yang_find(ys, Y_CONFIG, NULL)) != NULL){
if (yang_cv_get(ym) == NULL) /* shouldnt happen */
if ((cv = yang_cv_get(ym)) == NULL) /* shouldnt happen */
return 1;
return cv_bool_get(yang_cv_get(ym));
return cv_bool_get(cv);
}
return 1;
}
Expand Down Expand Up @@ -4610,6 +4639,24 @@ yang_action_cb_add(yang_stmt *ys,
return 0;
}

#ifdef OPTIMIZE_NO_PRESENCE_CONTAINER
void *
yang_nopresence_cache_get(yang_stmt *ys)
{
return ys->ys_nopres_cache;
}

int
yang_nopresence_cache_set(yang_stmt *ys,
void *x)
{
if (ys->ys_nopres_cache)
xml_free(ys->ys_nopres_cache);
ys->ys_nopres_cache = x;
return 0;
}
#endif

/*! Init yang code. Called before any yang code, before options
*
* Add two external tables for YANGs
Expand Down
Loading

0 comments on commit b09e326

Please sign in to comment.