strutil: introduce sr_atol_base() conversion helper (non-decimal)

Introduce a text to number conversion routine which is more general than
sr_atol() is. It accepts non-decimal numbers, with optional caller given
or automatic base, including 0b for binary. It is not as strict and can
return the position after the number, so that callers can optionally
support suffix notations (units, or scale factors, or multiple separated
numbers in the same text string).
This commit is contained in:
Gerhard Sittig 2020-05-03 16:38:13 +02:00
parent d770bfbbbc
commit 97aa41e9b5
2 changed files with 55 additions and 0 deletions

View File

@ -1501,6 +1501,7 @@ SR_PRIV void *sr_resource_load(struct sr_context *ctx, int type,
/*--- strutil.c -------------------------------------------------------------*/
SR_PRIV int sr_atol(const char *str, long *ret);
SR_PRIV int sr_atol_base(const char *str, long *ret, char **end, int base);
SR_PRIV int sr_atoi(const char *str, int *ret);
SR_PRIV int sr_atod(const char *str, double *ret);
SR_PRIV int sr_atof(const char *str, float *ret);

View File

@ -91,6 +91,60 @@ SR_PRIV int sr_atol(const char *str, long *ret)
return SR_OK;
}
/**
* Convert a text to a number including support for non-decimal bases.
* Also optionally returns the position after the number, where callers
* can either error out, or support application specific suffixes.
*
* @param[in] str The input text to convert.
* @param[out] ret The conversion result.
* @param[out] end The position after the number.
* @param[in] base The number format's base, can be 0.
*
* @retval SR_OK Conversion successful.
* @retval SR_ERR Conversion failed.
*
* @private
*
* This routine is more general than @ref sr_atol(), which strictly
* expects the input text to contain just a decimal number, and nothing
* else in addition. The @ref sr_atol_base() routine accepts trailing
* text after the number, and supports non-decimal numbers (bin, hex),
* including automatic detection from prefix text.
*/
SR_PRIV int sr_atol_base(const char *str, long *ret, char **end, int base)
{
long num;
char *endptr;
/* Add "0b" prefix support which strtol(3) may be missing. */
while (str && isspace(*str))
str++;
if (!base && strncmp(str, "0b", strlen("0b")) == 0) {
str += strlen("0b");
base = 2;
}
/* Run the number conversion. Quick bail out if that fails. */
errno = 0;
endptr = NULL;
num = strtol(str, &endptr, base);
if (!endptr || errno) {
if (!errno)
errno = EINVAL;
return SR_ERR;
}
*ret = num;
/* Advance to optional non-space trailing suffix. */
while (endptr && isspace(*endptr))
endptr++;
if (end)
*end = endptr;
return SR_OK;
}
/**
* Convert a string representation of a numeric value (base 10) to an integer. The
* conversion is strict and will fail if the complete string does not represent