From 1e1eabbc06ffc29989e5f70ea492bd23fbb662e6 Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Tue, 23 Apr 2019 12:53:29 +0200 Subject: [PATCH] Non linear str2int --- lib/clixon/clixon_string.h | 1 + lib/src/clixon_hash.c | 1 + lib/src/clixon_string.c | 61 +++++++++++++++++++++++++++++++++++++- lib/src/clixon_xml.c | 7 +++-- lib/src/clixon_yang_type.c | 45 ++++++++++++++++++++++------ util/clixon_util_xpath.c | 8 +---- 6 files changed, 104 insertions(+), 19 deletions(-) diff --git a/lib/clixon/clixon_string.h b/lib/clixon/clixon_string.h index f78ddbc9..eb106c10 100644 --- a/lib/clixon/clixon_string.h +++ b/lib/clixon/clixon_string.h @@ -86,6 +86,7 @@ int xml_chardata_encode(char **escp, char *fmt, ...); int uri_percent_decode(char *enc, char **str); 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); int nodeid_split(char *nodeid, char **prefix, char **id); char *clixon_trim(char *str); int regexp_xsd2posix(char *xsd, char **posix); diff --git a/lib/src/clixon_hash.c b/lib/src/clixon_hash.c index fa47bfcc..b14e10ad 100644 --- a/lib/src/clixon_hash.c +++ b/lib/src/clixon_hash.c @@ -112,6 +112,7 @@ hash_bucket(const char *str) * * @retval hash Pointer to new hash table. * @retval NULL Error + * @see hash_free For freeing the hash-table */ clicon_hash_t * hash_init(void) diff --git a/lib/src/clixon_string.c b/lib/src/clixon_string.c index ffbc68ff..bf25f146 100644 --- a/lib/src/clixon_string.c +++ b/lib/src/clixon_string.c @@ -552,7 +552,7 @@ clicon_int2str(const map_str2int *mstab, * @param[in] str Input string * @retval int Value * @retval -1 Error, not found - * @note linear search + * @see clicon_str2int_search for optimized lookup, but strings must be sorted */ int clicon_str2int(const map_str2int *mstab, @@ -566,6 +566,65 @@ clicon_str2int(const map_str2int *mstab, return -1; } +/*! Map from string to int using binary (alphatical) search + * @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 Integer found (can also be negative) + * @retval 0 Not found + * @retval 1 Found with "found" value set. + * @note Assumes sorted strings, tree search + */ +static int +str2int_search1(const map_str2int *mstab, + char *str, + int low, + int upper, + int len, + int *found) +{ + const struct map_str2int *ms; + int mid; + int cmp; + + if (upper < low) + return 0; /* not found */ + mid = (low + upper) / 2; + if (mid >= len) /* beyond range */ + return 0; /* not found */ + ms = &mstab[mid]; + if ((cmp = strcmp(str, ms->ms_str)) == 0){ + *found = ms->ms_int; + return 1; /* found */ + } + else if (cmp < 0) + return str2int_search1(mstab, str, low, mid-1, len, found); + else + return str2int_search1(mstab, 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 + * @retval int Value + * @retval -1 Error, not found + * @note Assumes sorted strings, tree search + * @note -1 can not be value + */ +int +clicon_str2int_search(const map_str2int *mstab, + char *str, + int len) +{ + int found; + + if (str2int_search1(mstab, str, 0, len, len, &found)) + return found; + return -1; /* not found */ +} + /*! Split colon-separated node identifier into prefix and name * @param[in] node-id * @param[out] prefix Malloced string. May be NULL. diff --git a/lib/src/clixon_xml.c b/lib/src/clixon_xml.c index 50f6f7e7..1735df14 100644 --- a/lib/src/clixon_xml.c +++ b/lib/src/clixon_xml.c @@ -744,8 +744,10 @@ xml_childvec_get(cxobj *x) * ... * xml_free(x); * @endcode - * @note yspec may be NULL either because it is not known or it is irrelevant, - * eg for body or attribute + * @note As a rule, yspec should be given in normal Clixon calls to enable + * proper sorting and insert functionality. Except as follows: + * - type is body or attribute + * - Yang is unknown * @see xml_sort_insert */ cxobj * @@ -828,6 +830,7 @@ xml_cv_set(cxobj *x, * @retval xmlobj if found. * @retval NULL if no such node found. * @see xml_find_type A more generic function + * @note Linear scalability and relies on strcmp */ cxobj * xml_find(cxobj *x_up, diff --git a/lib/src/clixon_yang_type.c b/lib/src/clixon_yang_type.c index 483ed0ac..1e8f5ff2 100644 --- a/lib/src/clixon_yang_type.c +++ b/lib/src/clixon_yang_type.c @@ -80,19 +80,19 @@ static const map_str2int ytmap[] = { {"int32", CGV_INT32}, /* NOTE, first match on right is significant, dont move */ {"string", CGV_STRING}, /* NOTE, first match on right is significant, dont move */ {"string", CGV_REST}, /* For cv -> yang translation of rest */ - {"binary", CGV_STRING}, - {"bits", CGV_STRING}, + {"binary", CGV_STRING}, + {"bits", CGV_STRING}, {"boolean", CGV_BOOL}, - {"decimal64", CGV_DEC64}, + {"decimal64", CGV_DEC64}, {"empty", CGV_VOID}, /* May not include any content */ - {"enumeration", CGV_STRING}, + {"enumeration", CGV_STRING}, {"identityref", CGV_STRING}, /* XXX */ {"instance-identifier", CGV_STRING}, /* XXX */ - {"int8", CGV_INT8}, - {"int16", CGV_INT16}, + {"int8", CGV_INT8}, + {"int16", CGV_INT16}, {"int64", CGV_INT64}, {"leafref", CGV_STRING}, /* XXX */ - {"uint8", CGV_UINT8}, + {"uint8", CGV_UINT8}, {"uint16", CGV_UINT16}, {"uint32", CGV_UINT32}, {"uint64", CGV_UINT64}, @@ -100,6 +100,33 @@ static const map_str2int ytmap[] = { {NULL, -1} }; +/*! Mapping from yang string types --> cligen types + * @note not 100% same as map_str2int since it has significant order AND + * string->CGV_REST entry removed + */ +static const map_str2int ytmap2[] = { + {"binary", CGV_STRING}, + {"bits", CGV_STRING}, + {"boolean", CGV_BOOL}, + {"decimal64", CGV_DEC64}, + {"empty", CGV_VOID}, /* May not include any content */ + {"enumeration", CGV_STRING}, + {"identityref", CGV_STRING}, /* XXX */ + {"instance-identifier", CGV_STRING}, /* XXX */ + {"int16", CGV_INT16}, + {"int32", CGV_INT32}, + {"int64", CGV_INT64}, + {"int8", CGV_INT8}, + {"leafref", CGV_STRING}, /* XXX */ + {"string", CGV_STRING}, + {"uint16", CGV_UINT16}, + {"uint32", CGV_UINT32}, + {"uint64", CGV_UINT64}, + {"uint8", CGV_UINT8}, + {"union", CGV_REST}, /* Is replaced by actual type */ + {NULL, -1} +}; + /*! Regular expression compiling * @retval -1 Error * @retval 0 regex problem (no match?) @@ -172,7 +199,7 @@ regex_exec(regex_t *re, static int yang_builtin(char *type) { - if (clicon_str2int(ytmap, type) != -1) + if (clicon_str2int_search(ytmap2, type, (sizeof(ytmap)/sizeof(map_str2int))-2) != -1) return 1; return 0; } @@ -318,7 +345,7 @@ yang2cv_type(char *ytype, *cv_type = CGV_ERR; /* built-in types */ - if ((ret = clicon_str2int(ytmap, ytype)) != -1){ + if ((ret = clicon_str2int_search(ytmap2, ytype, (sizeof(ytmap)/sizeof(map_str2int))-2)) != -1){ *cv_type = ret; return 0; } diff --git a/util/clixon_util_xpath.c b/util/clixon_util_xpath.c index b711b072..198cdb8a 100644 --- a/util/clixon_util_xpath.c +++ b/util/clixon_util_xpath.c @@ -33,13 +33,7 @@ See https://www.w3.org/TR/xpath/ - * Turn this on to get an xpath test program - * Usage: xpath [] - * read xpath on first line and xml on rest of lines from input - * Example compile: - gcc -g -o xpath -I. -I../clixon ./clixon_xsl.c -lclixon -lcligen - * Example run: -echo "a\n" | xpath +* */ #ifdef HAVE_CONFIG_H