diff options
Diffstat (limited to 'util/cutils.c')
-rw-r--r-- | util/cutils.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/util/cutils.c b/util/cutils.c index 923445267f..ae351984d9 100644 --- a/util/cutils.c +++ b/util/cutils.c @@ -354,6 +354,156 @@ int64_t strtosz(const char *nptr, char **end) } /** + * Helper function for qemu_strto*l() functions. + */ +static int check_strtox_error(const char *p, char *endptr, const char **next, + int err) +{ + /* If no conversion was performed, prefer BSD behavior over glibc + * behavior. + */ + if (err == 0 && endptr == p) { + err = EINVAL; + } + if (!next && *endptr) { + return -EINVAL; + } + if (next) { + *next = endptr; + } + return -err; +} + +/** + * QEMU wrappers for strtol(), strtoll(), strtoul(), strotull() C functions. + * + * Convert ASCII string @nptr to a long integer value + * from the given @base. Parameters @nptr, @endptr, @base + * follows same semantics as strtol() C function. + * + * Unlike from strtol() function, if @endptr is not NULL, this + * function will return -EINVAL whenever it cannot fully convert + * the string in @nptr with given @base to a long. This function returns + * the result of the conversion only through the @result parameter. + * + * If NULL is passed in @endptr, then the whole string in @ntpr + * is a number otherwise it returns -EINVAL. + * + * RETURN VALUE + * Unlike from strtol() function, this wrapper returns either + * -EINVAL or the errno set by strtol() function (e.g -ERANGE). + * If the conversion overflows, -ERANGE is returned, and @result + * is set to the max value of the desired type + * (e.g. LONG_MAX, LLONG_MAX, ULONG_MAX, ULLONG_MAX). If the case + * of underflow, -ERANGE is returned, and @result is set to the min + * value of the desired type. For strtol(), strtoll(), @result is set to + * LONG_MIN, LLONG_MIN, respectively, and for strtoul(), strtoull() it + * is set to 0. + */ +int qemu_strtol(const char *nptr, const char **endptr, int base, + long *result) +{ + char *p; + int err = 0; + if (!nptr) { + if (endptr) { + *endptr = nptr; + } + err = -EINVAL; + } else { + errno = 0; + *result = strtol(nptr, &p, base); + err = check_strtox_error(nptr, p, endptr, errno); + } + return err; +} + +/** + * Converts ASCII string to an unsigned long integer. + * + * If string contains a negative number, value will be converted to + * the unsigned representation of the signed value, unless the original + * (nonnegated) value would overflow, in this case, it will set @result + * to ULONG_MAX, and return ERANGE. + * + * The same behavior holds, for qemu_strtoull() but sets @result to + * ULLONG_MAX instead of ULONG_MAX. + * + * See qemu_strtol() documentation for more info. + */ +int qemu_strtoul(const char *nptr, const char **endptr, int base, + unsigned long *result) +{ + char *p; + int err = 0; + if (!nptr) { + if (endptr) { + *endptr = nptr; + } + err = -EINVAL; + } else { + errno = 0; + *result = strtoul(nptr, &p, base); + /* Windows returns 1 for negative out-of-range values. */ + if (errno == ERANGE) { + *result = -1; + } + err = check_strtox_error(nptr, p, endptr, errno); + } + return err; +} + +/** + * Converts ASCII string to a long long integer. + * + * See qemu_strtol() documentation for more info. + */ +int qemu_strtoll(const char *nptr, const char **endptr, int base, + int64_t *result) +{ + char *p; + int err = 0; + if (!nptr) { + if (endptr) { + *endptr = nptr; + } + err = -EINVAL; + } else { + errno = 0; + *result = strtoll(nptr, &p, base); + err = check_strtox_error(nptr, p, endptr, errno); + } + return err; +} + +/** + * Converts ASCII string to an unsigned long long integer. + * + * See qemu_strtol() documentation for more info. + */ +int qemu_strtoull(const char *nptr, const char **endptr, int base, + uint64_t *result) +{ + char *p; + int err = 0; + if (!nptr) { + if (endptr) { + *endptr = nptr; + } + err = -EINVAL; + } else { + errno = 0; + *result = strtoull(nptr, &p, base); + /* Windows returns 1 for negative out-of-range values. */ + if (errno == ERANGE) { + *result = -1; + } + err = check_strtox_error(nptr, p, endptr, errno); + } + return err; +} + +/** * parse_uint: * * @s: String to parse |