schema compile CHANGE min/max and ascending values check in range
- min/max were taken always from the built-in type, but they are
supposed to be taken from the base type where it can be already
restricted by another range.
- strictly ascending values must be only between range's parts. The
lower-inclusive and higher-inclusive bounds can be actually also equal.
diff --git a/src/tree_schema.h b/src/tree_schema.h
index 7c11b63..0934d93 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -172,6 +172,11 @@
typedef enum {
LY_TYPE_UNKNOWN = 0, /**< Unknown type */
LY_TYPE_BINARY, /**< Any binary data ([RFC 6020 sec 9.8](http://tools.ietf.org/html/rfc6020#section-9.8)) */
+ LY_TYPE_UINT8, /**< 8-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */
+ LY_TYPE_UINT16, /**< 16-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */
+ LY_TYPE_UINT32, /**< 32-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */
+ LY_TYPE_UINT64, /**< 64-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */
+ LY_TYPE_STRING, /**< Human-readable string ([RFC 6020 sec 9.4](http://tools.ietf.org/html/rfc6020#section-9.4)) */
LY_TYPE_BITS, /**< A set of bits or flags ([RFC 6020 sec 9.7](http://tools.ietf.org/html/rfc6020#section-9.7)) */
LY_TYPE_BOOL, /**< "true" or "false" ([RFC 6020 sec 9.5](http://tools.ietf.org/html/rfc6020#section-9.5)) */
LY_TYPE_DEC64, /**< 64-bit signed decimal number ([RFC 6020 sec 9.3](http://tools.ietf.org/html/rfc6020#section-9.3))*/
@@ -180,19 +185,17 @@
LY_TYPE_IDENT, /**< A reference to an abstract identity ([RFC 6020 sec 9.10](http://tools.ietf.org/html/rfc6020#section-9.10)) */
LY_TYPE_INST, /**< References a data tree node ([RFC 6020 sec 9.13](http://tools.ietf.org/html/rfc6020#section-9.13)) */
LY_TYPE_LEAFREF, /**< A reference to a leaf instance ([RFC 6020 sec 9.9](http://tools.ietf.org/html/rfc6020#section-9.9))*/
- LY_TYPE_STRING, /**< Human-readable string ([RFC 6020 sec 9.4](http://tools.ietf.org/html/rfc6020#section-9.4)) */
LY_TYPE_UNION, /**< Choice of member types ([RFC 6020 sec 9.12](http://tools.ietf.org/html/rfc6020#section-9.12)) */
LY_TYPE_INT8, /**< 8-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */
- LY_TYPE_UINT8, /**< 8-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */
LY_TYPE_INT16, /**< 16-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */
- LY_TYPE_UINT16, /**< 16-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */
LY_TYPE_INT32, /**< 32-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */
- LY_TYPE_UINT32, /**< 32-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */
LY_TYPE_INT64, /**< 64-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */
- LY_TYPE_UINT64, /**< 64-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */
} LY_DATA_TYPE;
#define LY_DATA_TYPE_COUNT 20 /**< Number of different types */
+/**
+ * @brief Stringified YANG built-in data types
+ */
extern const char* ly_data_type2str[LY_DATA_TYPE_COUNT];
/**
diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index 02ca5bb..024e383 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -56,11 +56,6 @@
LY_CHECK_GOTO(RET != LY_SUCCESS, GOTO); \
}
-const char* ly_data_type2str[LY_DATA_TYPE_COUNT] = {"unknown", "binary", "bits", "boolean", "decimal64", "empty", "enumeration",
- "identityref", "instance-identifier", "leafref", "string", "union", "8bit integer", "8bit unsigned integer", "16bit integer",
- "16bit unsigned integer", "32bit integer", "32bit unsigned integer", "64bit integer", "64bit unsigned integer"
-};
-
static struct lysc_ext_instance *
lysc_ext_instance_dup(struct ly_ctx *ctx, struct lysc_ext_instance *orig)
{
@@ -712,19 +707,21 @@
/**
* @brief Check that values in range are in ascendant order.
* @param[in] unsigned_value Flag to note that we are working with unsigned values.
+ * @param[in] max Flag to distinguish if checking min or max value. min value must be strictly higher than previous,
+ * max can be also equal.
* @param[in] value Current value to check.
* @param[in] prev_value The last seen value.
* @return LY_SUCCESS or LY_EEXIST for invalid order.
*/
static LY_ERR
-range_part_check_ascendancy(int unsigned_value, int64_t value, int64_t prev_value)
+range_part_check_ascendancy(int unsigned_value, int max, int64_t value, int64_t prev_value)
{
if (unsigned_value) {
- if ((uint64_t)prev_value >= (uint64_t)value) {
+ if ((max && (uint64_t)prev_value > (uint64_t)value) || (!max && (uint64_t)prev_value >= (uint64_t)value)) {
return LY_EEXIST;
}
} else {
- if (prev_value >= value) {
+ if ((max && prev_value > value) || (!max && prev_value >= value)) {
return LY_EEXIST;
}
}
@@ -741,6 +738,7 @@
* @param[in] first Flag for the first value of the range to avoid ascendancy order.
* @param[in] length_restr Flag to distinguish between range and length restrictions. Only for logging.
* @param[in] frdigits The fraction-digits value in case of LY_TYPE_DEC64 basetype.
+ * @param[in] base_range Range from the type from which the current type is derived (if not built-in) to get type's min and max values.
* @param[in,out] value Numeric range value to be stored, if not provided the type's min/max value is set.
* @return LY_ERR value - LY_SUCCESS, LY_EDENIED (value brokes type's boundaries), LY_EVALID (not a number),
* LY_EEXIST (value is smaller than the previous one), LY_EINVAL (decimal64 value does not corresponds with the
@@ -748,7 +746,7 @@
*/
static LY_ERR
range_part_minmax(struct lysc_ctx *ctx, struct lysc_range_part *part, int max, int64_t prev, LY_DATA_TYPE basetype, int first, int length_restr,
- uint8_t frdigits, const char **value)
+ uint8_t frdigits, struct lysc_range *base_range, const char **value)
{
LY_ERR ret = LY_SUCCESS;
char *valcopy = NULL;
@@ -756,7 +754,18 @@
if (value) {
ret = range_part_check_value_syntax(ctx, basetype, frdigits, *value, &len, &valcopy);
- LY_CHECK_GOTO(ret, error);
+ LY_CHECK_GOTO(ret, finalize);
+ }
+ if (!valcopy && base_range) {
+ if (max) {
+ part->max_64 = base_range->parts[LY_ARRAY_SIZE(base_range->parts) - 1].max_64;
+ } else {
+ part->min_64 = base_range->parts[0].min_64;
+ }
+ if (!first) {
+ ret = range_part_check_ascendancy(basetype <= LY_TYPE_STRING ? 1 : 0, max, max ? part->max_64 : part->min_64, prev);
+ }
+ goto finalize;
}
switch (basetype) {
@@ -769,7 +778,7 @@
part->min_u64 = UINT64_C(0);
}
if (!ret && !first) {
- ret = range_part_check_ascendancy(1, max ? part->max_64 : part->min_64, prev);
+ ret = range_part_check_ascendancy(1, max, max ? part->max_64 : part->min_64, prev);
}
break;
case LY_TYPE_DEC64: /* range */
@@ -782,7 +791,7 @@
part->min_64 = INT64_C(-9223372036854775807) - INT64_C(1);
}
if (!ret && !first) {
- ret = range_part_check_ascendancy(0, max ? part->max_64 : part->min_64, prev);
+ ret = range_part_check_ascendancy(0, max, max ? part->max_64 : part->min_64, prev);
}
break;
case LY_TYPE_INT8: /* range */
@@ -794,7 +803,7 @@
part->min_64 = INT64_C(-128);
}
if (!ret && !first) {
- ret = range_part_check_ascendancy(0, max ? part->max_64 : part->min_64, prev);
+ ret = range_part_check_ascendancy(0, max, max ? part->max_64 : part->min_64, prev);
}
break;
case LY_TYPE_INT16: /* range */
@@ -806,7 +815,7 @@
part->min_64 = INT64_C(-32768);
}
if (!ret && !first) {
- ret = range_part_check_ascendancy(0, max ? part->max_64 : part->min_64, prev);
+ ret = range_part_check_ascendancy(0, max, max ? part->max_64 : part->min_64, prev);
}
break;
case LY_TYPE_INT32: /* range */
@@ -818,7 +827,7 @@
part->min_64 = INT64_C(-2147483648);
}
if (!ret && !first) {
- ret = range_part_check_ascendancy(0, max ? part->max_64 : part->min_64, prev);
+ ret = range_part_check_ascendancy(0, max, max ? part->max_64 : part->min_64, prev);
}
break;
case LY_TYPE_INT64: /* range */
@@ -831,7 +840,7 @@
part->min_64 = INT64_C(-9223372036854775807) - INT64_C(1);
}
if (!ret && !first) {
- ret = range_part_check_ascendancy(0, max ? part->max_64 : part->min_64, prev);
+ ret = range_part_check_ascendancy(0, max, max ? part->max_64 : part->min_64, prev);
}
break;
case LY_TYPE_UINT8: /* range */
@@ -843,7 +852,7 @@
part->min_u64 = UINT64_C(0);
}
if (!ret && !first) {
- ret = range_part_check_ascendancy(1, max ? part->max_64 : part->min_64, prev);
+ ret = range_part_check_ascendancy(1, max, max ? part->max_64 : part->min_64, prev);
}
break;
case LY_TYPE_UINT16: /* range */
@@ -855,7 +864,7 @@
part->min_u64 = UINT64_C(0);
}
if (!ret && !first) {
- ret = range_part_check_ascendancy(1, max ? part->max_64 : part->min_64, prev);
+ ret = range_part_check_ascendancy(1, max, max ? part->max_64 : part->min_64, prev);
}
break;
case LY_TYPE_UINT32: /* range */
@@ -867,7 +876,7 @@
part->min_u64 = UINT64_C(0);
}
if (!ret && !first) {
- ret = range_part_check_ascendancy(1, max ? part->max_64 : part->min_64, prev);
+ ret = range_part_check_ascendancy(1, max, max ? part->max_64 : part->min_64, prev);
}
break;
case LY_TYPE_UINT64: /* range */
@@ -879,7 +888,7 @@
part->min_u64 = UINT64_C(0);
}
if (!ret && !first) {
- ret = range_part_check_ascendancy(1, max ? part->max_64 : part->min_64, prev);
+ ret = range_part_check_ascendancy(1, max, max ? part->max_64 : part->min_64, prev);
}
break;
case LY_TYPE_STRING: /* length */
@@ -891,7 +900,7 @@
part->min_u64 = UINT64_C(0);
}
if (!ret && !first) {
- ret = range_part_check_ascendancy(1, max ? part->max_64 : part->min_64, prev);
+ ret = range_part_check_ascendancy(1, max, max ? part->max_64 : part->min_64, prev);
}
break;
default:
@@ -899,7 +908,7 @@
ret = LY_EINT;
}
-error:
+finalize:
if (ret == LY_EDENIED) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
"Invalid %s restriction - value \"%s\" does not fit the type limitations.",
@@ -912,7 +921,7 @@
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
"Invalid %s restriction - values are not in ascending order (%s).",
length_restr ? "length" : "range",
- (valcopy && basetype != LY_TYPE_DEC64) ? valcopy : *value);
+ (valcopy && basetype != LY_TYPE_DEC64) ? valcopy : value ? *value : max ? "max" : "min");
} else if (!ret && value) {
*value = *value + len;
}
@@ -974,7 +983,7 @@
expr += 3;
LY_ARRAY_NEW_GOTO(ctx->ctx, parts, part, ret, cleanup);
- LY_CHECK_GOTO(range_part_minmax(ctx, part, 0, 0, basetype, 1, length_restr, frdigits, NULL), cleanup);
+ LY_CHECK_GOTO(range_part_minmax(ctx, part, 0, 0, basetype, 1, length_restr, frdigits, base_range, NULL), cleanup);
part->max_64 = part->min_64;
} else if (*expr == '|') {
if (!parts || range_expected) {
@@ -1001,12 +1010,12 @@
/* number */
if (range_expected) {
part = &parts[LY_ARRAY_SIZE(parts) - 1];
- LY_CHECK_GOTO(range_part_minmax(ctx, part, 1, part->min_64, basetype, 0, length_restr, frdigits, &expr), cleanup);
+ LY_CHECK_GOTO(range_part_minmax(ctx, part, 1, part->min_64, basetype, 0, length_restr, frdigits, NULL, &expr), cleanup);
range_expected = 0;
} else {
LY_ARRAY_NEW_GOTO(ctx->ctx, parts, part, ret, cleanup);
LY_CHECK_GOTO(range_part_minmax(ctx, part, 0, parts_done ? parts[LY_ARRAY_SIZE(parts) - 2].max_64 : 0,
- basetype, parts_done ? 0 : 1, length_restr, frdigits, &expr), cleanup);
+ basetype, parts_done ? 0 : 1, length_restr, frdigits, NULL, &expr), cleanup);
part->max_64 = part->min_64;
}
@@ -1023,12 +1032,12 @@
}
if (range_expected) {
part = &parts[LY_ARRAY_SIZE(parts) - 1];
- LY_CHECK_GOTO(range_part_minmax(ctx, part, 1, part->min_64, basetype, 0, length_restr, frdigits, NULL), cleanup);
+ LY_CHECK_GOTO(range_part_minmax(ctx, part, 1, part->min_64, basetype, 0, length_restr, frdigits, base_range, NULL), cleanup);
range_expected = 0;
} else {
LY_ARRAY_NEW_GOTO(ctx->ctx, parts, part, ret, cleanup);
LY_CHECK_GOTO(range_part_minmax(ctx, part, 1, parts_done ? parts[LY_ARRAY_SIZE(parts) - 2].max_64 : 0,
- basetype, parts_done ? 0 : 1, length_restr, frdigits, NULL), cleanup);
+ basetype, parts_done ? 0 : 1, length_restr, frdigits, base_range, NULL), cleanup);
part->min_64 = part->max_64;
}
} else {
@@ -1418,6 +1427,11 @@
static uint16_t type_substmt_map[LY_DATA_TYPE_COUNT] = {
0 /* LY_TYPE_UNKNOWN */,
LYS_SET_LENGTH /* LY_TYPE_BINARY */,
+ LYS_SET_RANGE /* LY_TYPE_UINT8 */,
+ LYS_SET_RANGE /* LY_TYPE_UINT16 */,
+ LYS_SET_RANGE /* LY_TYPE_UINT32 */,
+ LYS_SET_RANGE /* LY_TYPE_UINT64 */,
+ LYS_SET_LENGTH | LYS_SET_PATTERN /* LY_TYPE_STRING */,
LYS_SET_BIT /* LY_TYPE_BITS */,
0 /* LY_TYPE_BOOL */,
LYS_SET_FRDIGITS | LYS_SET_RANGE /* LY_TYPE_DEC64 */,
@@ -1426,16 +1440,19 @@
LYS_SET_BASE /* LY_TYPE_IDENT */,
LYS_SET_REQINST /* LY_TYPE_INST */,
LYS_SET_REQINST | LYS_SET_PATH /* LY_TYPE_LEAFREF */,
- LYS_SET_LENGTH | LYS_SET_PATTERN /* LY_TYPE_STRING */,
LYS_SET_TYPE /* LY_TYPE_UNION */,
LYS_SET_RANGE /* LY_TYPE_INT8 */,
- LYS_SET_RANGE /* LY_TYPE_UINT8 */,
LYS_SET_RANGE /* LY_TYPE_INT16 */,
- LYS_SET_RANGE /* LY_TYPE_UINT16 */,
LYS_SET_RANGE /* LY_TYPE_INT32 */,
- LYS_SET_RANGE /* LY_TYPE_UINT32 */,
- LYS_SET_RANGE /* LY_TYPE_INT64 */,
- LYS_SET_RANGE /* LY_TYPE_UINT64 */
+ LYS_SET_RANGE /* LY_TYPE_INT64 */
+};
+
+/**
+ * @brief stringification of the YANG built-in data types
+ */
+const char* ly_data_type2str[LY_DATA_TYPE_COUNT] = {"unknown", "binary", "8bit unsigned integer", "16bit unsigned integer",
+ "32bit unsigned integer", "64bit unsigned integer", "string", "bits", "boolean", "decimal64", "empty", "enumeration",
+ "identityref", "instance-identifier", "leafref", "union", "8bit integer", "16bit integer", "32bit integer", "64bit integer"
};
/**