Keyword "min" (not only "max") can be used in built-in types "range" and "length" statements.

This commit is contained in:
Olof hagsand 2019-01-06 22:11:59 +01:00
parent bd67a2a5f2
commit c7e847cd24
14 changed files with 469 additions and 405 deletions

View file

@ -57,14 +57,15 @@
/*! Split string into a vector based on character delimiters. Using malloc
*
* The given string is split into a vector where the delimiter can be
* any of the characters in the specified delimiter string.
* _any_ of the characters in the specified delimiter string.
*
* The vector returned is one single memory block that must be freed
* by the caller
*
* @code
* char **vec = NULL;
* int nvec;
* char **vec = NULL;
* char *v;
* int nvec;
* if ((vec = clicon_strsep("/home/user/src/clixon", "/", &nvec)) == NULL)
* err;
* for (i=0; i<nvec; i++){
@ -437,15 +438,18 @@ xml_chardata_encode(char **escp,
/*! Split a string into a cligen variable vector using 1st and 2nd delimiter
* Split a string first into elements delimited by delim1, then into
* pairs delimited by delim2.
* @param[in] string String to split
* @param[in] delim1 First delimiter char that delimits between elements
* @param[in] delim2 Second delimiter char for pairs within an element
* @param[in] string String to split
* @param[in] delim1 First delimiter char that delimits between elements
* @param[in] delim2 Second delimiter char for pairs within an element
* @param[out] cvp Created cligen variable vector, deallocate w cvec_free
* @retval 0 on OK
* @retval 0 OK
* @retval -1 error
* @code
* cvec *cvv = NULL;
* if (str2cvec("a=b&c=d", ';', '=', &cvv) < 0)
* err;
* @endcode
*
* @example,
* Assuming delim1 = '&' and delim2 = '='
* a=b&c=d -> [[a,"b"][c="d"]
* kalle&c=d -> [[c="d"]] # Discard elements with no delim2
* XXX differentiate between error and null cvec.
@ -610,6 +614,26 @@ nodeid_split(char *nodeid,
return retval;
}
/*! Trim blanks from front and end of a string, return new string
* @param[in] str
* @retval s Pointer into existing str after trimming blanks
*/
char *
clixon_trim(char *str)
{
char *s = str;
int i;
while (strlen(s) && isblank(s[0]))
s++;
for (i=0; i<strlen(s); i++)
if (isblank(s[i])){
s[i] = '\0';
break;
}
return s;
}
/*! strndup() for systems without it, such as xBSD
*/
#ifndef HAVE_STRNDUP

View file

@ -2414,7 +2414,7 @@ yang_enum_int_value(cxobj *node,
if ((ytype = yang_find((yang_node *)ys, Y_TYPE, NULL)) == NULL)
goto done;
if (yang_type_resolve(ys, ytype, &yrestype,
NULL, NULL, NULL, NULL, NULL) < 0)
NULL, NULL, NULL, NULL) < 0)
goto done;
if (yrestype==NULL || strcmp(yrestype->ys_argument, "enumeration"))
goto done;

View file

@ -1068,7 +1068,7 @@ ys_populate_leaf(yang_stmt *ys,
yparent = ys->ys_parent; /* Find parent: list/container */
/* 1. Find type specification and set cv type accordingly */
if (yang_type_get(ys, &type, &yrestype, &options, NULL, NULL, NULL, &fraction_digits) < 0)
if (yang_type_get(ys, &type, &yrestype, &options, NULL, NULL, &fraction_digits) < 0)
goto done;
restype = yrestype?yrestype->ys_argument:NULL;
if (clicon_type2cv(type, restype, &cvtype) < 0) /* This handles non-resolved also */
@ -1133,12 +1133,62 @@ ys_populate_list(yang_stmt *ys,
return 0;
}
/*! Populate range and length statements
/*! Set range or length boundary for built-in yang types
* Help functions to range and length statements
*/
static int
bound_add(yang_stmt *ys,
enum cv_type cvtype,
char *name,
char *val,
int options,
uint8_t fraction_digits
)
{
int retval = -1;
cg_var *cv;
char *reason = NULL;
int ret = 1;
if ((cv = cvec_add(ys->ys_cvec, cvtype)) == NULL){
clicon_err(OE_YANG, errno, "cvec_add");
goto done;
}
if (cv_name_set(cv, name) == NULL){
clicon_err(OE_YANG, errno, "cv_name_set(%s)", name);
goto done;
}
if (options & YANG_OPTIONS_FRACTION_DIGITS && cvtype == CGV_DEC64)
cv_dec64_n_set(cv, fraction_digits);
if (strcmp(val, "min") == 0)
cv_min_set(cv);
else if (strcmp(val, "max") == 0)
cv_max_set(cv);
else if ((ret = cv_parse1(val, cv, &reason)) < 0){
clicon_err(OE_YANG, errno, "cv_parse1");
goto done;
}
if (ret == 0){ /* parsing failed */
clicon_err(OE_YANG, errno, "range statement %s: %s", val, reason);
free(reason);
goto done;
}
retval = 0;
done:
return retval;
}
/*! Populate string built-in range statement
*
* Create cvec variables "range_min" and "range_max". Assume parent is type.
* Actually: min..max [| min..max]*
* where min,max is integer or keywords 'min' or 'max.
* We only allow one range, ie not 1..2|4..5
* Actually: bound[..bound] (| bound[..bound])*
* where bound is integer, decimal or keywords 'min' or 'max.
* RFC 7950 9.2.4:
* A range consists of an explicit value, or a lower-inclusive bound,
* two consecutive dots "..", and an upper-inclusive bound. Multiple
* values or ranges can be given, separated by "|". If multiple values
* or ranges are given, they all MUST be disjoint and MUST be in
* ascending order
*/
static int
ys_populate_range(yang_stmt *ys,
@ -1152,11 +1202,11 @@ ys_populate_range(yang_stmt *ys,
int options = 0x0;
uint8_t fraction_digits;
enum cv_type cvtype = CGV_ERR;
char *minstr = NULL;
char *maxstr;
cg_var *cv;
char *reason = NULL;
int cvret;
char **vec = NULL;
char *v;
char *v2;
int nvec;
int i;
yparent = ys->ys_parent; /* Find parent: type */
if (yparent->yn_keyword != Y_TYPE){
@ -1164,81 +1214,90 @@ ys_populate_range(yang_stmt *ys,
goto done;
}
if (yang_type_resolve(ys, (yang_stmt*)yparent, &yrestype,
&options, NULL, NULL, NULL, &fraction_digits) < 0)
&options, NULL, NULL, &fraction_digits) < 0)
goto done;
restype = yrestype?yrestype->ys_argument:NULL;
origtype = yarg_id((yang_stmt*)yparent);
/* This handles non-resolved also */
if (clicon_type2cv(origtype, restype, &cvtype) < 0)
goto done;
/* special case for strings, where limit is length, not a string */
if (cvtype == CGV_STRING)
cvtype = CGV_UINT64;
if ((minstr = strdup(ys->ys_argument)) == NULL){
clicon_err(OE_YANG, errno, "strdup");
if ((vec = clicon_strsep(ys->ys_argument, "|", &nvec)) == NULL)
goto done;
}
if ((maxstr = strstr(minstr, "..")) != NULL){
if (strlen(maxstr) < 2){
clicon_err(OE_YANG, 0, "range statement: %s not on the form: <int>..<int>",
ys->ys_argument);
goto done;
}
minstr[maxstr-minstr] = '\0';
maxstr += 2;
/* minstr and maxstr need trimming */
if (isblank(minstr[strlen(minstr)-1]))
minstr[strlen(minstr)-1] = '\0';
if (isblank(maxstr[0]))
maxstr++;
if ((cv = cvec_add(ys->ys_cvec, cvtype)) == NULL){
clicon_err(OE_YANG, errno, "cvec_add");
goto done;
for (i=0; i<nvec; i++){
v = vec[i++];
v = clixon_trim(v); /* trim blanks */
if ((v2 = strstr(v, "..")) != NULL){
*v2 = '\0';
v2 += 2;
v2 = clixon_trim(v2); /* trim blanks */
}
if (cv_name_set(cv, "range_min") == NULL){
clicon_err(OE_YANG, errno, "cv_name_set");
if (bound_add(ys, cvtype, "range_min", v,
options, fraction_digits) < 0)
goto done;
}
if (options & YANG_OPTIONS_FRACTION_DIGITS && cvtype == CGV_DEC64)
cv_dec64_n_set(cv, fraction_digits);
if ((cvret = cv_parse1(minstr, cv, &reason)) < 0){
clicon_err(OE_YANG, errno, "cv_parse1");
goto done;
}
if (cvret == 0){ /* parsing failed */
clicon_err(OE_YANG, errno, "range statement, min: %s", reason);
free(reason);
goto done;
}
}
else
maxstr = minstr;
if (strcmp(maxstr, "max") != 0){ /* no range_max means max */
if ((cv = cvec_add(ys->ys_cvec, cvtype)) == NULL){
clicon_err(OE_YANG, errno, "cvec_add");
goto done;
}
if (cv_name_set(cv, "range_max") == NULL){
clicon_err(OE_YANG, errno, "cv_name_set");
goto done;
}
if (options & YANG_OPTIONS_FRACTION_DIGITS && cvtype == CGV_DEC64)
cv_dec64_n_set(cv, fraction_digits);
if ((cvret = cv_parse1(maxstr, cv, &reason)) < 0){
clicon_err(OE_YANG, errno, "cv_parse1");
goto done;
}
if (cvret == 0){ /* parsing failed */
clicon_err(OE_YANG, errno, "range statement, max: %s", reason);
free(reason);
goto done;
}
if (v2)
if (bound_add(ys, cvtype, "range_max",v2,
options, fraction_digits) < 0)
goto done;
}
retval = 0;
done:
if (minstr)
free(minstr);
if (vec)
free(vec);
return retval;
}
/*! Populate integer built-in length statement
*
* Create cvec variables "range_min" and "range_max". Assume parent is type.
* Actually: len[..len] (| len[..len])*
* len is unsigned integer or keywords 'min' or 'max.
* RFC 7950 9.4.4
* A length range consists of an explicit value, or a lower bound, two
* consecutive dots "..", and an upper bound. Multiple values or ranges
* can be given, separated by "|". Length-restricting values MUST NOT
* be negative. If multiple values or ranges are given, they all MUST
* be disjoint and MUST be in ascending order.
*/
static int
ys_populate_length(yang_stmt *ys,
void *arg)
{
int retval = -1;
yang_node *yparent; /* type */
enum cv_type cvtype = CGV_ERR;
char **vec = NULL;
char *v;
int nvec;
int i;
char *v2;
yparent = ys->ys_parent; /* Find parent: type */
if (yparent->yn_keyword != Y_TYPE){
clicon_err(OE_YANG, 0, "parent should be type");
goto done;
}
cvtype = CGV_UINT64;
if ((vec = clicon_strsep(ys->ys_argument, "|", &nvec)) == NULL)
goto done;
for (i=0; i<nvec; i++){
v = vec[i++];
v = clixon_trim(v); /* trim blanks */
if ((v2 = strstr(v, "..")) != NULL){
*v2 = '\0';
v2 += 2;
v2 = clixon_trim(v2); /* trim blanks */
}
if (bound_add(ys, cvtype, "range_min", v, 0, 0) < 0)
goto done;
if (v2)
if (bound_add(ys, cvtype, "range_max",v2, 0, 0) < 0)
goto done;
}
retval = 0;
done:
if (vec)
free(vec);
return retval;
}
@ -1485,10 +1544,13 @@ ys_populate(yang_stmt *ys,
goto done;
break;
case Y_RANGE:
case Y_LENGTH:
if (ys_populate_range(ys, NULL) < 0)
goto done;
break;
case Y_LENGTH:
if (ys_populate_length(ys, NULL) < 0)
goto done;
break;
case Y_MANDATORY: /* call yang_mandatory() to check if set */
case Y_CONFIG:
if (ys_parse(ys, CGV_BOOL) == NULL)

View file

@ -115,8 +115,7 @@ int
yang_type_cache_set(yang_type_cache **ycache0,
yang_stmt *resolved,
int options,
cg_var *mincv,
cg_var *maxcv,
cvec *cvv,
char *pattern,
uint8_t fraction)
{
@ -132,13 +131,11 @@ yang_type_cache_set(yang_type_cache **ycache0,
*ycache0 = ycache;
ycache->yc_resolved = resolved;
ycache->yc_options = options;
if (mincv && (ycache->yc_mincv = cv_dup(mincv)) == NULL){
clicon_err(OE_UNIX, errno, "cv_dup");
goto done;
}
if (maxcv && (ycache->yc_maxcv = cv_dup(maxcv)) == NULL){
clicon_err(OE_UNIX, errno, "cv_dup");
goto done;
if (cvv){
if ((ycache->yc_cvv = cvec_dup(cvv)) == NULL){
clicon_err(OE_UNIX, errno, "cvec_dup");
goto done;
}
}
if (pattern && (ycache->yc_pattern = strdup(pattern)) == NULL){
clicon_err(OE_UNIX, errno, "strdup");
@ -155,8 +152,7 @@ int
yang_type_cache_get(yang_type_cache *ycache,
yang_stmt **resolved,
int *options,
cg_var **mincv,
cg_var **maxcv,
cvec **cvv,
char **pattern,
uint8_t *fraction)
{
@ -164,10 +160,8 @@ yang_type_cache_get(yang_type_cache *ycache,
*resolved = ycache->yc_resolved;
if (options)
*options = ycache->yc_options;
if (mincv)
*mincv = ycache->yc_mincv;
if (maxcv)
*maxcv = ycache->yc_maxcv;
if (cvv)
*cvv = ycache->yc_cvv;
if (pattern)
*pattern = ycache->yc_pattern;
if (fraction)
@ -181,14 +175,13 @@ yang_type_cache_cp(yang_type_cache **ycnew,
{
int retval = -1;
int options;
cg_var *mincv;
cg_var *maxcv;
cvec *cvv;
char *pattern;
uint8_t fraction;
yang_stmt *resolved;
yang_type_cache_get(ycold, &resolved, &options, &mincv, &maxcv, &pattern, &fraction);
if (yang_type_cache_set(ycnew, resolved, options, mincv, maxcv, pattern, fraction) < 0)
yang_type_cache_get(ycold, &resolved, &options, &cvv, &pattern, &fraction);
if (yang_type_cache_set(ycnew, resolved, options, cvv, pattern, fraction) < 0)
goto done;
retval = 0;
done:
@ -198,10 +191,8 @@ yang_type_cache_cp(yang_type_cache **ycnew,
int
yang_type_cache_free(yang_type_cache *ycache)
{
if (ycache->yc_mincv)
cv_free(ycache->yc_mincv);
if (ycache->yc_maxcv)
cv_free(ycache->yc_maxcv);
if (ycache->yc_cvv)
cvec_free(ycache->yc_cvv);
if (ycache->yc_pattern)
free(ycache->yc_pattern);
free(ycache);
@ -220,8 +211,7 @@ ys_resolve_type(yang_stmt *ys,
{
int retval = -1;
int options = 0x0;
cg_var *mincv = NULL;
cg_var *maxcv = NULL;
cvec *cvv = NULL;
char *pattern = NULL;
uint8_t fraction = 0;
yang_stmt *resolved = NULL;
@ -231,12 +221,12 @@ ys_resolve_type(yang_stmt *ys,
* Note that the resolved type could be ys itself.
*/
if (yang_type_resolve((yang_stmt*)ys->ys_parent, ys, &resolved,
&options, &mincv, &maxcv, &pattern, &fraction) < 0)
&options, &cvv, &pattern, &fraction) < 0)
goto done;
/* Cache the resolve locally */
if (yang_type_cache_set(&ys->ys_typecache,
resolved, options, mincv, maxcv, pattern, fraction) < 0)
resolved, options, cvv, pattern, fraction) < 0)
goto done;
retval = 0;
done:
@ -388,132 +378,121 @@ static int
cv_validate1(cg_var *cv,
enum cv_type cvtype,
int options,
cg_var *range_min,
cg_var *range_max,
cvec *cvv,
char *pattern,
yang_stmt *yrestype,
char *restype,
char **reason)
{
int retval = 1; /* OK */
cg_var *cv1;
cg_var *cv2;
int retval2;
yang_stmt *yi = NULL;
unsigned int u = 0;
int i = 0;
char *str;
int found;
char **vec = NULL;
int nvec;
char *v;
uint64_t uu = 0;
int64_t ii = 0;
int i;
int ret;
if (reason && *reason){
free(*reason);
*reason = NULL;
}
/* check options first for length and range */
if ((options & YANG_OPTIONS_RANGE) != 0 ||
(options & YANG_OPTIONS_LENGTH) != 0){
i = 0;
while (i<cvec_len(cvv)){
cv1 = cvec_i(cvv, i++);
if (strcmp(cv_name_get(cv1),"range_min") == 0){
if (i<cvec_len(cvv) &&
(cv2 = cvec_i(cvv, i)) != NULL &&
strcmp(cv_name_get(cv2),"range_max") == 0){
i++;
}
else
cv2 = cv1;
ret = 0;
switch (cvtype){
case CGV_INT8:
ii = cv_int8_get(cv);
ret = range_check(ii, cv1, cv2, int8);
break;
case CGV_INT16:
ii = cv_int16_get(cv);
ret = range_check(ii, cv1, cv2, int16);
break;
case CGV_INT32:
ii = cv_int32_get(cv);
ret = range_check(ii, cv1, cv2, int32);
break;
case CGV_DEC64: /* XXX look at fraction-digit? */
case CGV_INT64:
ii = cv_int64_get(cv);
ret = range_check(ii, cv1, cv2, int64);
break;
default:
break;
}
if (ret){
if (reason)
*reason = cligen_reason("Number out of range: %" PRId64, ii);
goto fail;
break;
}
ret = 0;
switch (cvtype){
case CGV_UINT8:
uu = cv_uint8_get(cv);
ret = range_check(uu, cv1, cv2, uint8);
break;
case CGV_UINT16:
uu = cv_uint16_get(cv);
ret = range_check(uu, cv1, cv2, uint16);
break;
case CGV_UINT32:
uu = cv_uint32_get(cv);
ret = range_check(uu, cv1, cv2, uint32);
break;
case CGV_UINT64:
uu = cv_uint32_get(cv);
ret = range_check(uu, cv1, cv2, uint64);
break;
default:
break;
}
if (ret){
if (reason)
*reason = cligen_reason("Number out of range: %" PRIu64, uu);
goto fail;
break;
}
ret = 0;
switch (cvtype){
case CGV_STRING:
case CGV_REST:
if ((str = cv_string_get(cv)) == NULL)
break;
uu = strlen(str);
if (range_check(uu, cv1, cv2, uint64)){
if (reason)
*reason = cligen_reason("string length out of range: %" PRIu64, uu);
goto fail;
}
break;
default:
break;
}
}
}
}
/* then check options for others */
switch (cvtype){
case CGV_INT8:
if ((options & YANG_OPTIONS_RANGE) != 0){
i = cv_int8_get(cv);
if (range_check(i, range_min, range_max, int8)){
if (reason)
*reason = cligen_reason("Number out of range: %d", i);
retval = 0;
break;
}
}
break;
case CGV_INT16:
if ((options & YANG_OPTIONS_RANGE) != 0){
i = cv_int16_get(cv);
if (range_check(i, range_min, range_max, int16)){
if (reason)
*reason = cligen_reason("Number out of range: %d", i);
retval = 0;
break;
}
}
break;
case CGV_INT32:
if ((options & YANG_OPTIONS_RANGE) != 0){
i = cv_int32_get(cv);
if (range_check(i, range_min, range_max, int32)){
if (reason)
*reason = cligen_reason("Number out of range: %d", i);
retval = 0;
break;
}
}
break;
case CGV_INT64:{
int64_t i64;
if ((options & YANG_OPTIONS_RANGE) != 0){
i64 = cv_int64_get(cv);
if (range_check(i, range_min, range_max, int64)){
if (reason)
*reason = cligen_reason("Number out of range: %" PRId64, i64);
retval = 0;
break;
}
}
break;
}
case CGV_UINT8:
if ((options & YANG_OPTIONS_RANGE) != 0){
u = cv_uint8_get(cv);
if (range_check(u, range_min, range_max, uint8)){
if (reason)
*reason = cligen_reason("Number out of range: %u", u);
retval = 0;
break;
}
}
break;
case CGV_UINT16:
if ((options & YANG_OPTIONS_RANGE) != 0){
u = cv_uint16_get(cv);
if (range_check(u, range_min, range_max, uint16)){
if (reason)
*reason = cligen_reason("Number out of range: %u", u);
retval = 0;
break;
}
}
break;
case CGV_UINT32:
if ((options & YANG_OPTIONS_RANGE) != 0){
u = cv_uint32_get(cv);
if (range_check(u, range_min, range_max, uint32)){
if (reason)
*reason = cligen_reason("Number out of range: %u", u);
retval = 0;
break;
}
}
break;
case CGV_UINT64:{
uint64_t u64;
if ((options & YANG_OPTIONS_RANGE) != 0){
u64 = cv_uint64_get(cv);
if (range_check(u, range_min, range_max, uint64)){
if (reason)
*reason = cligen_reason("Number out of range: %" PRIu64, u64);
retval = 0;
break;
}
}
break;
}
case CGV_DEC64:
if ((options & YANG_OPTIONS_RANGE) != 0){
i = cv_int64_get(cv);
if (range_check(i, range_min, range_max, int64)){
if (reason)
*reason = cligen_reason("Number out of range: %d", i);
retval = 0;
break;
}
}
break;
case CGV_STRING:
case CGV_REST:
str = cv_string_get(cv);
@ -531,8 +510,7 @@ cv_validate1(cg_var *cv,
if (!found){
if (reason)
*reason = cligen_reason("'%s' does not match enumeration", str);
retval = 0;
break;
goto fail;
}
}
if (strcmp(restype, "bits") == 0){
@ -557,21 +535,12 @@ cv_validate1(cg_var *cv,
if (!found){
if (reason)
*reason = cligen_reason("'%s' does not match enumeration", v);
retval = 0;
goto fail;
break;
}
}
}
}
if ((options & YANG_OPTIONS_LENGTH) != 0){
u = strlen(str);
if (range_check(u, range_min, range_max, uint64)){
if (reason)
*reason = cligen_reason("string length out of range: %u", u);
retval = 0;
break;
}
}
if ((options & YANG_OPTIONS_PATTERN) != 0){
if ((retval2 = match_regexp(str, pattern)) < 0){
clicon_err(OE_DB, 0, "match_regexp: %s", pattern);
@ -581,7 +550,7 @@ cv_validate1(cg_var *cv,
if (reason)
*reason = cligen_reason("regexp match fail: \"%s\" does not match %s",
str, pattern);
retval = 0;
goto fail;
break;
}
}
@ -591,27 +560,19 @@ cv_validate1(cg_var *cv,
retval = 0;
if (reason)
*reason = cligen_reason("Invalid cv");
retval = 0;
goto fail;
break;
case CGV_BOOL:
case CGV_INTERFACE:
case CGV_IPV4ADDR:
case CGV_IPV6ADDR:
case CGV_IPV4PFX:
case CGV_IPV6PFX:
case CGV_MACADDR:
case CGV_URL:
case CGV_UUID:
case CGV_TIME:
case CGV_EMPTY: /* XXX */
default:
break;
}
if (reason && *reason)
assert(retval == 0); /* validation failed with error reason */
retval = 1; /* validation OK */
done:
if (vec)
free(vec);
return retval;
fail:
retval = 0; /* validation failed */
goto done;
}
/* Forward */
@ -633,16 +594,14 @@ ys_cv_validate_union_one(yang_stmt *ys,
int retval = -1;
yang_stmt *yrt; /* union subtype */
int options = 0;
cg_var *range_min = NULL;
cg_var *range_max = NULL;
cvec *cvv = NULL;
char *pattern = NULL;
uint8_t fraction = 0;
char *restype;
enum cv_type cvtype;
cg_var *cvt=NULL;
if (yang_type_resolve(ys, yt, &yrt,
&options, &range_min, &range_max, &pattern,
if (yang_type_resolve(ys, yt, &yrt, &options, &cvv, &pattern,
&fraction) < 0)
goto done;
restype = yrt?yrt->ys_argument:NULL;
@ -664,7 +623,7 @@ ys_cv_validate_union_one(yang_stmt *ys,
}
if (retval == 0)
goto done;
if ((retval = cv_validate1(cvt, cvtype, options, range_min, range_max,
if ((retval = cv_validate1(cvt, cvtype, options, cvv,
pattern, yrt, restype, reason)) < 0)
goto done;
}
@ -736,8 +695,7 @@ ys_cv_validate(cg_var *cv,
int retval = -1;
cg_var *ycv; /* cv of yang-statement */
int options = 0;
cg_var *range_min = NULL;
cg_var *range_max = NULL;
cvec *cvv = NULL;
char *pattern = NULL;
enum cv_type cvtype;
char *type; /* orig type */
@ -756,8 +714,7 @@ ys_cv_validate(cg_var *cv,
}
ycv = ys->ys_cv;
if (yang_type_get(ys, &type, &yrestype,
&options, &range_min, &range_max, &pattern,
&fraction) < 0)
&options, &cvv, &pattern, &fraction) < 0)
goto done;
restype = yrestype?yrestype->ys_argument:NULL;
if (clicon_type2cv(type, restype, &cvtype) < 0)
@ -782,7 +739,7 @@ ys_cv_validate(cg_var *cv,
retval = retval2; /* invalid (0) with latest reason or valid 1 */
}
else
if ((retval = cv_validate1(cv, cvtype, options, range_min, range_max, pattern,
if ((retval = cv_validate1(cv, cvtype, options, cvv, pattern,
yrestype, restype, reason)) < 0)
goto done;
done:
@ -889,7 +846,17 @@ yang_find_identity(yang_stmt *ys,
return yid;
}
/*
/*! Resolve type restrictions, return contraining parameters
* @param[in] yrange Yang type range restriction if any
* @param[in] ylength Yang type length restriction if any
* @param[in] ypattern Yang type pattern restriction if any
* @param[in] yfraction Yang type fraction restriction if any
* @param[out] options Pointer to flags field of optional values. optional
* @param[out] cvv Pointer to cvec with min range or length.
* If options&YANG_OPTIONS_RANGE or YANG_OPTIONS_LENGTH
* @param[out] pattern Pointer to static string of yang string pattern. optional
* @param[out] fraction For decimal64, how many digits after period
* @retval 0 OK.
*/
static int
resolve_restrictions(yang_stmt *yrange,
@ -897,19 +864,16 @@ resolve_restrictions(yang_stmt *yrange,
yang_stmt *ypattern,
yang_stmt *yfraction,
int *options,
cg_var **mincv,
cg_var **maxcv,
cvec **cvv,
char **pattern,
uint8_t *fraction)
{
if (options && mincv && maxcv && yrange != NULL){
*mincv = cvec_find(yrange->ys_cvec, "range_min");
*maxcv = cvec_find(yrange->ys_cvec, "range_max");
if (options && cvv && yrange != NULL){
*cvv = yrange->ys_cvec;
*options |= YANG_OPTIONS_RANGE;
}
if (options && mincv && maxcv && ylength != NULL){
*mincv = cvec_find(ylength->ys_cvec, "range_min"); /* XXX fel typ */
*maxcv = cvec_find(ylength->ys_cvec, "range_max");
if (options && cvv && ylength != NULL){
*cvv = ylength->ys_cvec;
*options |= YANG_OPTIONS_LENGTH;
}
if (options && pattern && ypattern != NULL){
@ -928,8 +892,8 @@ resolve_restrictions(yang_stmt *yrange,
* @param[in] ytype yang-stmt object containing currently resolving type
* @param[out] yrestype resolved type. return built-in type or NULL. mandatory
* @param[out] options pointer to flags field of optional values. optional
* @param[out] mincv pointer to cv with min range or length. If options&YANG_OPTIONS_RANGE
* @param[out] maxcv pointer to cv with max range or length. If options&YANG_OPTIONS_RANGE
* @param[out] cvv pointer to cvec with min range or length.
* If options&YANG_OPTIONS_RANGE or YANG_OPTIONS_LENGTH
* @param[out] pattern pointer to static string of yang string pattern. optional
* @param[out] fraction for decimal64, how many digits after period
* @retval 0 OK. Note yrestype may still be NULL.
@ -946,8 +910,7 @@ yang_type_resolve(yang_stmt *ys,
yang_stmt *ytype,
yang_stmt **yrestype,
int *options,
cg_var **mincv,
cg_var **maxcv,
cvec **cvv,
char **pattern,
uint8_t *fraction)
{
@ -970,8 +933,8 @@ yang_type_resolve(yang_stmt *ys,
prefix = yarg_prefix(ytype); /* And this its prefix */
/* Cache does not work for eg string length 32? */
if (!yang_builtin(type) && ytype->ys_typecache != NULL){
if (yang_type_cache_get(ytype->ys_typecache,
yrestype, options, mincv, maxcv, pattern, fraction) < 0)
if (yang_type_cache_get(ytype->ys_typecache, yrestype,
options, cvv, pattern, fraction) < 0)
goto done;
goto ok;
}
@ -984,7 +947,7 @@ yang_type_resolve(yang_stmt *ys,
if (prefix == NULL && yang_builtin(type)){
*yrestype = ytype;
resolve_restrictions(yrange, ylength, ypattern, yfraction, options,
mincv, maxcv, pattern, fraction);
cvv, pattern, fraction);
goto ok;
}
@ -1022,13 +985,12 @@ yang_type_resolve(yang_stmt *ys,
}
/* recursively resolve this new type */
if (yang_type_resolve(ys, rytype, yrestype,
options, mincv, maxcv, pattern, fraction) < 0)
options, cvv, pattern, fraction) < 0)
goto done;
/* overwrites the resolved if any */
resolve_restrictions(yrange, ylength, ypattern, yfraction,
options, mincv, maxcv, pattern, fraction);
resolve_restrictions(yrange, ylength, ypattern, yfraction, options,
cvv, pattern, fraction);
}
ok:
retval = 0;
done:
@ -1042,11 +1004,11 @@ yang_type_resolve(yang_stmt *ys,
* @code
* yang_stmt *yrestype;
* int options;
* int64_t min, max;
* cvec *cvv = NULL;
* char *pattern;
* uint8_t fraction;
*
* if (yang_type_get(ys, &type, &yrestype, &options, &min, &max, &pattern, &fraction) < 0)
* if (yang_type_get(ys, &type, &yrestype, &options, &cvv, &pattern, &fraction) < 0)
* goto err;
* if (yrestype == NULL) # unresolved
* goto err;
@ -1078,8 +1040,7 @@ yang_type_get(yang_stmt *ys,
char **origtype,
yang_stmt **yrestype,
int *options,
cg_var **mincv,
cg_var **maxcv,
cvec **cvv,
char **pattern,
uint8_t *fraction
)
@ -1100,7 +1061,7 @@ yang_type_get(yang_stmt *ys,
if (origtype)
*origtype = type;
if (yang_type_resolve(ys, ytype, yrestype,
options, mincv, maxcv, pattern, fraction) < 0)
options, cvv, pattern, fraction) < 0)
goto done;
clicon_debug(3, "%s: %s %s->%s", __FUNCTION__, ys->ys_argument, type,
*yrestype?(*yrestype)->ys_argument:"null");