MINOR: standard: add 64 bits conversion functions

This patch adds 3 functions for 64 bit integer conversion.

 * lltoa_r : converts signed 64 bit integer to string
 * read_uint64 : converts from string to signed 64 bits integer with capping
 * read_int64 : converts from string to unsigned 64 bits integer with capping
This commit is contained in:
Thierry FOURNIER 2015-07-06 23:09:52 +02:00 committed by Willy Tarreau
parent 19a106d24a
commit 763a5d85f7
2 changed files with 108 additions and 0 deletions

View File

@ -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);

View File

@ -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 <s> and
* returns it. The <s> pointer is adjusted to point to the first unread char. The
* function automatically stops at <end>. 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 <s> and returns
* it. The <s> pointer is adjusted to point to the first unread char. The function
* automatically stops at <end>. 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.