data parsing CHANGE de-duplicate code
re-use existing code parsing int/uint
diff --git a/src/common.c b/src/common.c
index bdb671d..e34d42e 100644
--- a/src/common.c
+++ b/src/common.c
@@ -308,11 +308,11 @@
}
LY_ERR
-ly_parse_int(const char *val_str, int64_t min, int64_t max, int base, int64_t *ret)
+ly_parse_int(const char *val_str, size_t val_len, int64_t min, int64_t max, int base, int64_t *ret)
{
char *strptr;
- LY_CHECK_ARG_RET(NULL, val_str, val_str[0], LY_EINVAL);
+ LY_CHECK_ARG_RET(NULL, val_str, val_str[0], val_len, LY_EINVAL);
/* convert to 64-bit integer, all the redundant characters are handled */
errno = 0;
@@ -320,7 +320,7 @@
/* parse the value */
*ret = strtoll(val_str, &strptr, base);
- if (errno) {
+ if (errno || strptr == val_str) {
return LY_EVALID;
} else if ((*ret < min) || (*ret > max)) {
return LY_EDENIED;
@@ -328,7 +328,7 @@
while (isspace(*strptr)) {
++strptr;
}
- if (*strptr) {
+ if (*strptr && strptr < val_str + val_len) {
return LY_EVALID;
}
}
@@ -336,7 +336,7 @@
}
LY_ERR
-ly_parse_uint(const char *val_str, uint64_t max, int base, uint64_t *ret)
+ly_parse_uint(const char *val_str, size_t val_len, uint64_t max, int base, uint64_t *ret)
{
char *strptr;
uint64_t u;
@@ -346,7 +346,7 @@
errno = 0;
strptr = NULL;
u = strtoull(val_str, &strptr, base);
- if (errno) {
+ if (errno || strptr == val_str) {
return LY_EVALID;
} else if ((u > max) || (u && val_str[0] == '-')) {
return LY_EDENIED;
@@ -354,9 +354,11 @@
while (isspace(*strptr)) {
++strptr;
}
- if (*strptr) {
+ if (*strptr && strptr < val_str + val_len) {
return LY_EVALID;
}
+ } else if (u != 0 && val_str[0] == '-') {
+ return LY_EDENIED;
}
*ret = u;
diff --git a/src/common.h b/src/common.h
index fb77255..225414e 100644
--- a/src/common.h
+++ b/src/common.h
@@ -351,6 +351,7 @@
* @brief Parse signed integer with possible limitation.
* @param[in] val_str String value containing signed integer, note that
* nothing else than whitespaces are expected after the value itself.
+ * @param[in] val_len Length of the @p val_str string.
* @param[in] min Limitation for the value which must not be lower than min.
* @param[in] max Limitation for the value which must not be higher than max.
* @param[in] base Numeric base for parsing:
@@ -362,12 +363,13 @@
* LY_EVALID - string contains invalid value,
* LY_SUCCESS - successful parsing.
*/
-LY_ERR ly_parse_int(const char *val_str, int64_t min, int64_t max, int base, int64_t *ret);
+LY_ERR ly_parse_int(const char *val_str, size_t val_len, int64_t min, int64_t max, int base, int64_t *ret);
/**
* @brief Parse unsigned integer with possible limitation.
* @param[in] val_str String value containing unsigned integer, note that
* nothing else than whitespaces are expected after the value itself.
+ * @param[in] val_len Length of the @p val_str string.
* @param[in] max Limitation for the value which must not be higher than max.
* @param[in] base Numeric base for parsing:
* 0 - to accept decimal, octal, hexadecimal (e.g. in default value)
@@ -378,7 +380,7 @@
* LY_EVALID - string contains invalid value,
* LY_SUCCESS - successful parsing.
*/
-LY_ERR ly_parse_uint(const char *val_str, uint64_t max, int base, uint64_t *ret);
+LY_ERR ly_parse_uint(const char *val_str, size_t val_len, uint64_t max, int base, uint64_t *ret);
/**
* @brief mmap(2) wrapper to map input files into memory to unify parsing.
diff --git a/src/plugins_types.c b/src/plugins_types.c
index 4c71643..822c05e 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -30,8 +30,6 @@
ly_type_parse_int(const char *datatype, int base, int64_t min, int64_t max, const char *value, size_t value_len, int64_t *ret, struct ly_err_item **err)
{
char *errmsg = NULL;
- char *strptr = NULL;
- int64_t i;
LY_CHECK_ARG_RET(NULL, err, datatype, LY_EINVAL);
@@ -43,41 +41,26 @@
goto error;
}
- /* convert to 64-bit integer, all the redundant characters are handled */
- errno = 0;
-
- /* parse the value */
- i = strtoll(value, &strptr, base);
- if (errno || strptr == value || (i < min) || (i > max)) {
+ switch(ly_parse_int(value, value_len, min, max, base, ret)) {
+ case LY_EDENIED:
+ asprintf(&errmsg, "Value is out of %s's min/max bounds.", datatype);
goto error;
- } else if (strptr && *strptr && strptr < value + value_len) {
- while (isspace(*strptr)) {
- ++strptr;
- }
- if (*strptr && strptr < value + value_len) {
- goto error;
- }
+ case LY_SUCCESS:
+ return LY_SUCCESS;
+ default:
+ asprintf(&errmsg, "Invalid %s value \"%.*s\".", datatype, (int)value_len, value);
+ goto error;
}
- if (ret) {
- *ret = i;
- }
- return LY_SUCCESS;
-
error:
- if (!errmsg) {
- asprintf(&errmsg, "Invalid %s value \"%.*s\".", datatype, (int)value_len, value);
- }
*err = ly_err_new(LY_LLERR, LY_EINVAL, LYVE_RESTRICTION, errmsg, NULL, NULL);
return LY_EVALID;
}
API LY_ERR
-ly_type_parse_uint(const char *datatype, int base, uint64_t min, uint64_t max, const char *value, size_t value_len, uint64_t *ret, struct ly_err_item **err)
+ly_type_parse_uint(const char *datatype, int base, uint64_t max, const char *value, size_t value_len, uint64_t *ret, struct ly_err_item **err)
{
char *errmsg = NULL;
- char *strptr = NULL;
- uint64_t u;
LY_CHECK_ARG_RET(NULL, err, datatype, LY_EINVAL);
@@ -90,35 +73,18 @@
}
*err = NULL;
- errno = 0;
- u = strtoull(value, &strptr, base);
- if (errno || strptr == value || (u < min) || (u > max)) {
+ switch(ly_parse_uint(value, value_len, max, base, ret)) {
+ case LY_EDENIED:
+ asprintf(&errmsg, "Value \"%.*s\" is out of %s's min/max bounds.", (int)value_len, value, datatype);
goto error;
- } else if (strptr && *strptr && strptr < value + value_len) {
- while (isspace(*strptr)) {
- ++strptr;
- }
- if (*strptr && strptr < value + value_len) {
- goto error;
- }
- } else if (u != 0 && value[0] == '-') {
+ case LY_SUCCESS:
+ return LY_SUCCESS;
+ default:
+ asprintf(&errmsg, "Invalid %s value \"%.*s\".", datatype, (int)value_len, value);
goto error;
}
- if (ret) {
- *ret = u;
- }
- return LY_SUCCESS;
-
error:
- if (!errmsg) {
- if (strptr && strptr != value + value_len) {
- asprintf(&errmsg, "Invalid %lu. character of %s value \"%.*s\".",
- 1 + (unsigned long int)(strptr - value), datatype, (int)value_len, value);
- } else {
- asprintf(&errmsg, "Invalid %s value \"%.*s\".", datatype, (int)value_len, value);
- }
- }
*err = ly_err_new(LY_LLERR, LY_EINVAL, LYVE_RESTRICTION, errmsg, NULL, NULL);
return LY_EVALID;
}
@@ -428,13 +394,13 @@
{
switch (basetype) {
case LY_TYPE_UINT8:
- return ly_type_parse_uint("uint16", (options & LY_TYPE_OPTS_SCHEMA) ? 0 : 10, 0, UINT64_C(255), value, value_len, val, err);
+ return ly_type_parse_uint("uint16", (options & LY_TYPE_OPTS_SCHEMA) ? 0 : 10, UINT64_C(255), value, value_len, val, err);
case LY_TYPE_UINT16:
- return ly_type_parse_uint("uint16", (options & LY_TYPE_OPTS_SCHEMA) ? 0 : 10, 0, UINT64_C(65535), value, value_len, val, err);
+ return ly_type_parse_uint("uint16", (options & LY_TYPE_OPTS_SCHEMA) ? 0 : 10, UINT64_C(65535), value, value_len, val, err);
case LY_TYPE_UINT32:
- return ly_type_parse_uint("uint32", (options & LY_TYPE_OPTS_SCHEMA) ? 0 : 10, 0, UINT64_C(4294967295), value, value_len, val, err);
+ return ly_type_parse_uint("uint32", (options & LY_TYPE_OPTS_SCHEMA) ? 0 : 10, UINT64_C(4294967295), value, value_len, val, err);
case LY_TYPE_UINT64:
- return ly_type_parse_uint("uint64", (options & LY_TYPE_OPTS_SCHEMA) ? 0 : 10, 0, UINT64_C(18446744073709551615), value, value_len, val, err);
+ return ly_type_parse_uint("uint64", (options & LY_TYPE_OPTS_SCHEMA) ? 0 : 10, UINT64_C(18446744073709551615), value, value_len, val, err);
default:
LOGINT(NULL);
return LY_EINVAL;
diff --git a/src/plugins_types.h b/src/plugins_types.h
index 68631e7..f0df0fb 100644
--- a/src/plugins_types.h
+++ b/src/plugins_types.h
@@ -194,7 +194,6 @@
* @param[in] datatype Type of the unsigned integer for logging.
* @param[in] base Base of the integer's lexical representation. In case of built-in types, data must be represented in decimal format (base 10),
* but default values in schemas can be represented also as hexadecimal or octal values (base 0).
- * @param[in] min Lower bound of the type.
* @param[in] max Upper bound of the type.
* @param[in] value Value string to parse.
* @param[in] value_len Length of the @p value (mandatory parameter).
@@ -202,7 +201,7 @@
* @param[out] err Error information in case of failure. The error structure can be freed by ly_err_free().
* @return LY_ERR value according to the result of the parsing and validation.
*/
-LY_ERR ly_type_parse_uint(const char *datatype, int base, uint64_t min, uint64_t max, const char *value, size_t value_len,
+LY_ERR ly_type_parse_uint(const char *datatype, int base, uint64_t max, const char *value, size_t value_len,
uint64_t *ret, struct ly_err_item **err);
/**
diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index 160153b..c4fa318 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -1135,7 +1135,7 @@
switch (basetype) {
case LY_TYPE_INT8: /* range */
if (valcopy) {
- ret = ly_parse_int(valcopy, INT64_C(-128), INT64_C(127), 10, max ? &part->max_64 : &part->min_64);
+ ret = ly_parse_int(valcopy, strlen(valcopy), INT64_C(-128), INT64_C(127), 10, max ? &part->max_64 : &part->min_64);
} else if (max) {
part->max_64 = INT64_C(127);
} else {
@@ -1147,7 +1147,7 @@
break;
case LY_TYPE_INT16: /* range */
if (valcopy) {
- ret = ly_parse_int(valcopy, INT64_C(-32768), INT64_C(32767), 10, max ? &part->max_64 : &part->min_64);
+ ret = ly_parse_int(valcopy, strlen(valcopy), INT64_C(-32768), INT64_C(32767), 10, max ? &part->max_64 : &part->min_64);
} else if (max) {
part->max_64 = INT64_C(32767);
} else {
@@ -1159,7 +1159,7 @@
break;
case LY_TYPE_INT32: /* range */
if (valcopy) {
- ret = ly_parse_int(valcopy, INT64_C(-2147483648), INT64_C(2147483647), 10, max ? &part->max_64 : &part->min_64);
+ ret = ly_parse_int(valcopy, strlen(valcopy), INT64_C(-2147483648), INT64_C(2147483647), 10, max ? &part->max_64 : &part->min_64);
} else if (max) {
part->max_64 = INT64_C(2147483647);
} else {
@@ -1172,7 +1172,7 @@
case LY_TYPE_INT64: /* range */
case LY_TYPE_DEC64: /* range */
if (valcopy) {
- ret = ly_parse_int(valcopy, INT64_C(-9223372036854775807) - INT64_C(1), INT64_C(9223372036854775807), 10,
+ ret = ly_parse_int(valcopy, strlen(valcopy), INT64_C(-9223372036854775807) - INT64_C(1), INT64_C(9223372036854775807), 10,
max ? &part->max_64 : &part->min_64);
} else if (max) {
part->max_64 = INT64_C(9223372036854775807);
@@ -1185,7 +1185,7 @@
break;
case LY_TYPE_UINT8: /* range */
if (valcopy) {
- ret = ly_parse_uint(valcopy, UINT64_C(255), 10, max ? &part->max_u64 : &part->min_u64);
+ ret = ly_parse_uint(valcopy, strlen(valcopy), UINT64_C(255), 10, max ? &part->max_u64 : &part->min_u64);
} else if (max) {
part->max_u64 = UINT64_C(255);
} else {
@@ -1197,7 +1197,7 @@
break;
case LY_TYPE_UINT16: /* range */
if (valcopy) {
- ret = ly_parse_uint(valcopy, UINT64_C(65535), 10, max ? &part->max_u64 : &part->min_u64);
+ ret = ly_parse_uint(valcopy, strlen(valcopy), UINT64_C(65535), 10, max ? &part->max_u64 : &part->min_u64);
} else if (max) {
part->max_u64 = UINT64_C(65535);
} else {
@@ -1209,7 +1209,7 @@
break;
case LY_TYPE_UINT32: /* range */
if (valcopy) {
- ret = ly_parse_uint(valcopy, UINT64_C(4294967295), 10, max ? &part->max_u64 : &part->min_u64);
+ ret = ly_parse_uint(valcopy, strlen(valcopy), UINT64_C(4294967295), 10, max ? &part->max_u64 : &part->min_u64);
} else if (max) {
part->max_u64 = UINT64_C(4294967295);
} else {
@@ -1223,7 +1223,7 @@
case LY_TYPE_STRING: /* length */
case LY_TYPE_BINARY: /* length */
if (valcopy) {
- ret = ly_parse_uint(valcopy, UINT64_C(18446744073709551615), 10, max ? &part->max_u64 : &part->min_u64);
+ ret = ly_parse_uint(valcopy, strlen(valcopy), UINT64_C(18446744073709551615), 10, max ? &part->max_u64 : &part->min_u64);
} else if (max) {
part->max_u64 = UINT64_C(18446744073709551615);
} else {
diff --git a/tests/features/test_types.c b/tests/features/test_types.c
index a135703..c671a74 100644
--- a/tests/features/test_types.c
+++ b/tests/features/test_types.c
@@ -208,7 +208,7 @@
/* invalid value */
data = "<uint32 xmlns=\"urn:tests:types\">-10</uint32>";
assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, 0));
- logbuf_assert("Invalid uint32 value \"-10\". /");
+ logbuf_assert("Value \"-10\" is out of uint32's min/max bounds. /");
data = "<uint64 xmlns=\"urn:tests:types\"/>";
assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, 0));
@@ -220,7 +220,7 @@
data = "<uint64 xmlns=\"urn:tests:types\">10 xxx</uint64>";
assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, 0));
- logbuf_assert("Invalid 5. character of uint64 value \"10 xxx\". /");
+ logbuf_assert("Invalid uint64 value \"10 xxx\". /");
s->func = NULL;
}