From ca6638860805366148ab8bbd6d731a1df8ce8bbb Mon Sep 17 00:00:00 2001 From: Georg Chini Date: Tue, 14 Jan 2020 14:04:11 +0100 Subject: [PATCH] core-util: Add pa_atoi64() and pa_atou64() functions Part-of: --- src/pulsecore/core-util.c | 87 +++++++++++++++++++++++++++++++++++++++ src/pulsecore/core-util.h | 2 + 2 files changed, 89 insertions(+) diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 601b1d1df..d421a7572 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -2243,6 +2243,50 @@ int pa_atou(const char *s, uint32_t *ret_u) { return 0; } +/* Convert the string s to an unsigned 64 bit integer in *ret_u */ +int pa_atou64(const char *s, uint64_t *ret_u) { + char *x = NULL; + unsigned long long l; + + pa_assert(s); + pa_assert(ret_u); + + /* strtoull() ignores leading spaces. We don't. */ + if (isspace((unsigned char)*s)) { + errno = EINVAL; + return -1; + } + + /* strtoull() accepts strings that start with a minus sign. In that case the + * original negative number gets negated, and strtoull() returns the negated + * result. We don't want that kind of behaviour. strtoull() also allows a + * leading plus sign, which is also a thing that we don't want. */ + if (*s == '-' || *s == '+') { + errno = EINVAL; + return -1; + } + + errno = 0; + l = strtoull(s, &x, 0); + + /* If x doesn't point to the end of s, there was some trailing garbage in + * the string. If x points to s, no conversion was done (empty string). */ + if (!x || *x || x == s || errno) { + if (!errno) + errno = EINVAL; + return -1; + } + + if ((uint64_t) l != l) { + errno = ERANGE; + return -1; + } + + *ret_u = (uint64_t) l; + + return 0; +} + /* Convert the string s to a signed long integer in *ret_l. */ int pa_atol(const char *s, long *ret_l) { char *x = NULL; @@ -2281,6 +2325,49 @@ int pa_atol(const char *s, long *ret_l) { return 0; } +/* Convert the string s to a signed 64 bit integer in *ret_l. */ +int pa_atoi64(const char *s, int64_t *ret_l) { + char *x = NULL; + long long l; + + pa_assert(s); + pa_assert(ret_l); + + /* strtoll() ignores leading spaces. We don't. */ + if (isspace((unsigned char)*s)) { + errno = EINVAL; + return -1; + } + + /* strtoll() accepts leading plus signs, but that's ugly, so we don't allow + * that. */ + if (*s == '+') { + errno = EINVAL; + return -1; + } + + errno = 0; + l = strtoll(s, &x, 0); + + /* If x doesn't point to the end of s, there was some trailing garbage in + * the string. If x points to s, no conversion was done (at least an empty + * string can trigger this). */ + if (!x || *x || x == s || errno) { + if (!errno) + errno = EINVAL; + return -1; + } + + *ret_l = l; + + if ((int64_t) l != l) { + errno = ERANGE; + return -1; + } + + return 0; +} + #ifdef HAVE_STRTOD_L static locale_t c_locale = NULL; diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index 9440af917..3117df882 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -151,6 +151,8 @@ int pa_atoi(const char *s, int32_t *ret_i); int pa_atou(const char *s, uint32_t *ret_u); int pa_atol(const char *s, long *ret_l); int pa_atod(const char *s, double *ret_d); +int pa_atoi64(const char *s, int64_t *ret_l); +int pa_atou64(const char *s, uint64_t *ret_u); size_t pa_snprintf(char *str, size_t size, const char *format, ...); size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap);