diff --git a/include/common/standard.h b/include/common/standard.h index ec566544b..085ec791d 100644 --- a/include/common/standard.h +++ b/include/common/standard.h @@ -105,6 +105,7 @@ extern int strlcpy2(char *dst, const char *src, int size); */ extern char itoa_str[][171]; extern char *ultoa_r(unsigned long n, char *buffer, int size); +extern char *lltoa_r(long long int n, char *buffer, int size); extern char *sltoa_r(long n, char *buffer, int size); extern const char *ulltoh_r(unsigned long long n, char *buffer, int size); static inline const char *ultoa(unsigned long n) @@ -495,6 +496,9 @@ static inline unsigned int __read_uint(const char **s, const char *end) return i; } +unsigned long long int read_uint64(const char **s, const char *end); +long long int read_int64(const char **s, const char *end); + extern unsigned int str2ui(const char *s); extern unsigned int str2uic(const char *s); extern unsigned int strl2ui(const char *s, int len); diff --git a/src/standard.c b/src/standard.c index fb24f7d37..464173937 100644 --- a/src/standard.c +++ b/src/standard.c @@ -406,6 +406,35 @@ char *ultoa_r(unsigned long n, char *buffer, int size) return pos + 1; } +/* + * This function simply returns a locally allocated string containing + * the ascii representation for number 'n' in decimal. + */ +char *lltoa_r(long long int in, char *buffer, int size) +{ + char *pos; + int neg = 0; + unsigned long long int n; + + pos = buffer + size - 1; + *pos-- = '\0'; + + if (in < 0) { + neg = 1; + n = -in; + } + else + n = in; + + do { + *pos-- = '0' + n % 10; + n /= 10; + } while (n && pos >= buffer); + if (neg && pos > buffer) + *pos-- = '-'; + return pos + 1; +} + /* * This function simply returns a locally allocated string containing * the ascii representation for signed number 'n' in decimal. @@ -1454,6 +1483,81 @@ unsigned int read_uint(const char **s, const char *end) return __read_uint(s, end); } +/* This function reads an unsigned integer from the string pointed to by and + * returns it. The pointer is adjusted to point to the first unread char. The + * function automatically stops at . If the number overflows, the 2^64-1 + * value is returned. + */ +unsigned long long int read_uint64(const char **s, const char *end) +{ + const char *ptr = *s; + unsigned long long int i = 0, tmp; + unsigned int j; + + while (ptr < end) { + + /* read next char */ + j = *ptr - '0'; + if (j > 9) + goto read_uint64_end; + + /* add char to the number and check overflow. */ + tmp = i * 10; + if (tmp / 10 != i) { + i = ULLONG_MAX; + goto read_uint64_eat; + } + if (ULLONG_MAX - tmp < j) { + i = ULLONG_MAX; + goto read_uint64_eat; + } + i = tmp + j; + ptr++; + } +read_uint64_eat: + /* eat each numeric char */ + while (ptr < end) { + if ((unsigned int)(*ptr - '0') > 9) + break; + ptr++; + } +read_uint64_end: + *s = ptr; + return i; +} + +/* This function reads an integer from the string pointed to by and returns + * it. The pointer is adjusted to point to the first unread char. The function + * automatically stops at . Il the number is bigger than 2^63-2, the 2^63-1 + * value is returned. If the number is lowest than -2^63-1, the -2^63 value is + * returned. + */ +long long int read_int64(const char **s, const char *end) +{ + unsigned long long int i = 0; + int neg = 0; + + /* Look for minus char. */ + if (**s == '-') { + neg = 1; + (*s)++; + } + else if (**s == '+') + (*s)++; + + /* convert as positive number. */ + i = read_uint64(s, end); + + if (neg) { + if (i > 0x8000000000000000ULL) + return LLONG_MIN; + return -i; + } + if (i > 0x7fffffffffffffffULL) + return LLONG_MAX; + return i; +} + /* This one is 7 times faster than strtol() on athlon with checks. * It returns the value of the number composed of all valid digits read, * and can process negative numbers too.