1
0
mirror of https://github.com/adtools/clib2.git synced 2025-12-08 14:59:05 +00:00

- strtoimax(), strtoumax(), strtod(), strtof(), strtol(), strtoll(),

strtoul() and strtoull() now count how many digits were converted.
  If that number is zero, then the conversion is considered to have
  failed: 0 is returned, errno is set to ERANGE and the 'ptr' parameter
  reference is initialized with a pointer to the string to be converted.
  This has two consequences:

     1) A floating point number that has no digits in the significand
        is no longer converted to zero. For example ".e10" can no longer
        result in a successful conversion.

     2) You can detect if a conversion is successful by comparing pointers
        after the conversion function has returned:

           char * str;
           char * ptr;
           long n;

           n = strtol(str,&ptr,10);
           if(n == 0 && str == ptr)
              printf("conversion has failed");


git-svn-id: file:///Users/olsen/Code/migration-svn-zu-git/logical-line-staging/clib2/trunk@15030 87f5fb63-7c3d-0410-a384-fd976d0f7a62
This commit is contained in:
Olaf Barthel
2005-09-28 09:28:39 +00:00
parent 378e50d2ab
commit 3099f6210a
9 changed files with 190 additions and 62 deletions

View File

@ -1,3 +1,25 @@
- strtoimax(), strtoumax(), strtod(), strtof(), strtol(), strtoll(),
strtoul() and strtoull() now count how many digits were converted.
If that number is zero, then the conversion is considered to have
failed: 0 is returned, errno is set to ERANGE and the 'ptr' parameter
reference is initialized with a pointer to the string to be converted.
This has two consequences:
1) A floating point number that has no digits in the significand
is no longer converted to zero. For example ".e10" can no longer
result in a successful conversion.
2) You can detect if a conversion is successful by comparing pointers
after the conversion function has returned:
char * str;
char * ptr;
long n;
n = strtol(str,&ptr,10);
if(n == 0 && str == ptr)
printf("conversion has failed");
- Following detection of a stack overflow, the startup code eventually
called _exit(). It should have called exit() instead.

View File

@ -1,5 +1,5 @@
/*
* $Id: inttypes_strtoimax.c,v 1.1 2005-05-12 13:21:43 obarthel Exp $
* $Id: inttypes_strtoimax.c,v 1.2 2005-09-28 09:28:39 obarthel Exp $
*
* :ts=4
*
@ -46,6 +46,8 @@
intmax_t
strtoimax(const char *str, char **ptr, int base)
{
const char * stop = str;
size_t num_digits_converted = 0;
BOOL is_negative;
intmax_t result = 0;
intmax_t new_sum;
@ -172,20 +174,31 @@ strtoimax(const char *str, char **ptr, int base)
str++;
c = (*str);
num_digits_converted++;
}
}
/* Did we convert anything? */
if(num_digits_converted == 0)
{
__set_errno(ERANGE);
goto out;
}
if(is_negative)
result = (-sum);
else
result = sum;
stop = str;
out:
/* If desired, remember where we stopped reading the
number from the buffer. */
if(ptr != NULL)
(*ptr) = (char *)str;
(*ptr) = (char *)stop;
RETURN(result);
return(result);

View File

@ -1,5 +1,5 @@
/*
* $Id: inttypes_strtoumax.c,v 1.1 2005-05-12 13:21:43 obarthel Exp $
* $Id: inttypes_strtoumax.c,v 1.2 2005-09-28 09:28:39 obarthel Exp $
*
* :ts=4
*
@ -46,6 +46,8 @@
uintmax_t
strtoumax(const char *str, char **ptr, int base)
{
const char * stop = str;
size_t num_digits_converted = 0;
BOOL is_negative;
uintmax_t result = 0;
uintmax_t new_sum;
@ -169,9 +171,22 @@ strtoumax(const char *str, char **ptr, int base)
str++;
c = (*str);
/* Remember where the conversion stopped and
that we converted something. */
stop = str;
num_digits_converted++;
}
}
/* Did we convert anything? */
if(num_digits_converted == 0)
{
__set_errno(ERANGE);
goto out;
}
if(is_negative)
result = (-sum);
else
@ -182,7 +197,7 @@ strtoumax(const char *str, char **ptr, int base)
/* If desired, remember where we stopped reading the
number from the buffer. */
if(ptr != NULL)
(*ptr) = (char *)str;
(*ptr) = (char *)stop;
RETURN(result);
return(result);

View File

@ -1,5 +1,5 @@
/*
* $Id: stdlib_strtod.c,v 1.8 2005-05-29 08:19:36 obarthel Exp $
* $Id: stdlib_strtod.c,v 1.9 2005-09-28 09:28:39 obarthel Exp $
*
* :ts=4
*
@ -66,6 +66,7 @@
double
strtod(const char *str, char ** ptr)
{
const char * stop = str;
double sum = 0.0;
double result;
int is_negative;
@ -128,6 +129,8 @@ strtod(const char *str, char ** ptr)
str += strlen(str);
sum = __inf();
stop = str;
}
else if (strncasecmp(str,"nan",3) == SAME && (str[3] == '(' || str[3] == '\0'))
{
@ -146,9 +149,12 @@ strtod(const char *str, char ** ptr)
}
sum = nan(NULL);
stop = str;
}
else
{
size_t num_digits_converted = 0;
int decimal_point_matches;
double new_sum;
int error = 0;
@ -191,6 +197,8 @@ strtod(const char *str, char ** ptr)
else
sum = new_sum;
}
num_digits_converted++;
}
/* Did we find the decimal point? We accept both the
@ -258,6 +266,8 @@ strtod(const char *str, char ** ptr)
divisor = divisor / radix;
}
num_digits_converted++;
}
}
@ -352,11 +362,22 @@ strtod(const char *str, char ** ptr)
}
}
if(error != 0)
if(num_digits_converted == 0)
{
__set_errno(error);
__set_errno(ERANGE);
sum = __get_huge_val();
sum = 0;
}
else
{
if(error != 0)
{
__set_errno(error);
sum = __get_huge_val();
}
stop = str;
}
}
@ -365,12 +386,12 @@ strtod(const char *str, char ** ptr)
result = sum;
out:
/* If desired, remember where we stopped reading the
number from the buffer. */
if(ptr != NULL)
(*ptr) = (char *)str;
out:
(*ptr) = (char *)stop;
RETURN(result);
return(result);

View File

@ -1,5 +1,5 @@
/*
* $Id: stdlib_strtof.c,v 1.8 2005-05-30 18:28:45 obarthel Exp $
* $Id: stdlib_strtof.c,v 1.9 2005-09-28 09:28:39 obarthel Exp $
*
* :ts=4
*
@ -66,6 +66,7 @@
float
strtof(const char *str, char ** ptr)
{
const char * stop = str;
float sum = 0.0;
float result;
int is_negative;
@ -128,6 +129,8 @@ strtof(const char *str, char ** ptr)
str += strlen(str);
sum = __inff();
stop = str;
}
else if (strncasecmp(str,"nan",3) == SAME && (str[3] == '(' || str[3] == '\0'))
{
@ -146,9 +149,12 @@ strtof(const char *str, char ** ptr)
}
sum = nanf(NULL);
stop = str;
}
else
{
size_t num_digits_converted = 0;
int decimal_point_matches;
float new_sum;
int error = 0;
@ -183,6 +189,8 @@ strtof(const char *str, char ** ptr)
str++;
num_digits_converted++;
if(error == 0)
{
new_sum = (radix * sum) + c;
@ -248,6 +256,8 @@ strtof(const char *str, char ** ptr)
str++;
num_digits_converted++;
if(error == 0 && divisor != 0.0)
{
new_sum = sum + c * divisor;
@ -352,11 +362,22 @@ strtof(const char *str, char ** ptr)
}
}
if(error != 0)
if(num_digits_converted == 0)
{
__set_errno(error);
__set_errno(ERANGE);
sum = __get_huge_valf();
sum = 0;
}
else
{
stop = str;
if(error != 0)
{
__set_errno(error);
sum = __get_huge_valf();
}
}
}
@ -365,12 +386,12 @@ strtof(const char *str, char ** ptr)
result = sum;
out:
/* If desired, remember where we stopped reading the
number from the buffer. */
if(ptr != NULL)
(*ptr) = (char *)str;
out:
(*ptr) = (char *)stop;
RETURN(result);
return(result);

View File

@ -1,5 +1,5 @@
/*
* $Id: stdlib_strtol.c,v 1.3 2005-02-03 16:56:17 obarthel Exp $
* $Id: stdlib_strtol.c,v 1.4 2005-09-28 09:28:39 obarthel Exp $
*
* :ts=4
*
@ -46,6 +46,8 @@
long
strtol(const char *str, char **ptr, int base)
{
const char * stop = str;
size_t num_digits_converted = 0;
BOOL is_negative;
long result = 0;
long new_sum;
@ -103,8 +105,7 @@ strtol(const char *str, char **ptr, int base)
is_negative = FALSE;
/* But there may be a sign we will choose to
* ignore.
*/
ignore. */
if(c == '+')
str++;
}
@ -112,8 +113,7 @@ strtol(const char *str, char **ptr, int base)
c = (*str);
/* There may be a leading '0x' to indicate that what
* follows is a hexadecimal number.
*/
follows is a hexadecimal number. */
if(base == 0 || base == 16)
{
if((c == '0') && (str[1] == 'x' || str[1] == 'X'))
@ -127,9 +127,8 @@ strtol(const char *str, char **ptr, int base)
}
/* If we still don't know what base to use and the
* next letter to follow is a zero then this is
* probably a number in octal notation.
*/
next letter to follow is a zero then this is
probably a number in octal notation. */
if(base == 0)
{
if(c == '0')
@ -175,21 +174,31 @@ strtol(const char *str, char **ptr, int base)
str++;
c = (*str);
num_digits_converted++;
}
}
/* Did we convert anything? */
if(num_digits_converted == 0)
{
__set_errno(ERANGE);
goto out;
}
if(is_negative)
result = (-sum);
else
result = sum;
stop = str;
out:
/* If desired, remember where we stopped reading the
* number from the buffer.
*/
number from the buffer. */
if(ptr != NULL)
(*ptr) = (char *)str;
(*ptr) = (char *)stop;
RETURN(result);
return(result);

View File

@ -1,5 +1,5 @@
/*
* $Id: stdlib_strtoll.c,v 1.3 2005-02-03 16:56:17 obarthel Exp $
* $Id: stdlib_strtoll.c,v 1.4 2005-09-28 09:28:39 obarthel Exp $
*
* :ts=4
*
@ -50,6 +50,8 @@
long long
strtoll(const char *str, char **ptr, int base)
{
const char * stop = str;
size_t num_digits_converted = 0;
BOOL is_negative;
long long result = 0;
long long new_sum;
@ -107,8 +109,7 @@ strtoll(const char *str, char **ptr, int base)
is_negative = FALSE;
/* But there may be a sign we will choose to
* ignore.
*/
ignore. */
if(c == '+')
str++;
}
@ -116,8 +117,7 @@ strtoll(const char *str, char **ptr, int base)
c = (*str);
/* There may be a leading '0x' to indicate that what
* follows is a hexadecimal number.
*/
follows is a hexadecimal number. */
if(base == 0 || base == 16)
{
if((c == '0') && (str[1] == 'x' || str[1] == 'X'))
@ -131,9 +131,8 @@ strtoll(const char *str, char **ptr, int base)
}
/* If we still don't know what base to use and the
* next letter to follow is a zero then this is
* probably a number in octal notation.
*/
next letter to follow is a zero then this is
probably a number in octal notation. */
if(base == 0)
{
if(c == '0')
@ -179,21 +178,31 @@ strtoll(const char *str, char **ptr, int base)
str++;
c = (*str);
num_digits_converted++;
}
}
/* Did we convert anything? */
if(num_digits_converted == 0)
{
__set_errno(ERANGE);
goto out;
}
if(is_negative)
result = (-sum);
else
result = sum;
stop = str;
out:
/* If desired, remember where we stopped reading the
* number from the buffer.
*/
number from the buffer. */
if(ptr != NULL)
(*ptr) = (char *)str;
(*ptr) = (char *)stop;
RETURN(result);
return(result);

View File

@ -1,5 +1,5 @@
/*
* $Id: stdlib_strtoul.c,v 1.3 2005-02-03 16:56:17 obarthel Exp $
* $Id: stdlib_strtoul.c,v 1.4 2005-09-28 09:28:39 obarthel Exp $
*
* :ts=4
*
@ -46,6 +46,8 @@
unsigned long
strtoul(const char *str, char **ptr, int base)
{
const char * stop = str;
size_t num_digits_converted = 0;
BOOL is_negative;
unsigned long result = 0;
unsigned long new_sum;
@ -103,8 +105,7 @@ strtoul(const char *str, char **ptr, int base)
is_negative = FALSE;
/* But there may be a sign we will choose to
* ignore.
*/
ignore. */
if(c == '+')
str++;
}
@ -112,8 +113,7 @@ strtoul(const char *str, char **ptr, int base)
c = (*str);
/* There may be a leading '0x' to indicate that what
* follows is a hexadecimal number.
*/
follows is a hexadecimal number. */
if(base == 0 || base == 16)
{
if((c == '0') && (str[1] == 'x' || str[1] == 'X'))
@ -127,9 +127,8 @@ strtoul(const char *str, char **ptr, int base)
}
/* If we still don't know what base to use and the
* next letter to follow is a zero then this is
* probably a number in octal notation.
*/
next letter to follow is a zero then this is
probably a number in octal notation. */
if(base == 0)
{
if(c == '0')
@ -172,21 +171,31 @@ strtoul(const char *str, char **ptr, int base)
str++;
c = (*str);
num_digits_converted++;
}
}
/* Did we convert anything? */
if(num_digits_converted == 0)
{
__set_errno(ERANGE);
goto out;
}
if(is_negative)
result = (-sum);
else
result = sum;
stop = str;
out:
/* If desired, remember where we stopped reading the
* number from the buffer.
*/
number from the buffer. */
if(ptr != NULL)
(*ptr) = (char *)str;
(*ptr) = (char *)stop;
RETURN(result);
return(result);

View File

@ -1,5 +1,5 @@
/*
* $Id: stdlib_strtoull.c,v 1.3 2005-02-03 16:56:17 obarthel Exp $
* $Id: stdlib_strtoull.c,v 1.4 2005-09-28 09:28:39 obarthel Exp $
*
* :ts=4
*
@ -50,6 +50,8 @@
unsigned long long
strtoull(const char *str, char **ptr, int base)
{
const char * stop = str;
size_t num_digits_converted = 0;
BOOL is_negative;
unsigned long long result = 0;
unsigned long long new_sum;
@ -107,8 +109,7 @@ strtoull(const char *str, char **ptr, int base)
is_negative = FALSE;
/* But there may be a sign we will choose to
* ignore.
*/
ignore. */
if(c == '+')
str++;
}
@ -116,8 +117,7 @@ strtoull(const char *str, char **ptr, int base)
c = (*str);
/* There may be a leading '0x' to indicate that what
* follows is a hexadecimal number.
*/
follows is a hexadecimal number. */
if(base == 0 || base == 16)
{
if((c == '0') && (str[1] == 'x' || str[1] == 'X'))
@ -131,9 +131,8 @@ strtoull(const char *str, char **ptr, int base)
}
/* If we still don't know what base to use and the
* next letter to follow is a zero then this is
* probably a number in octal notation.
*/
next letter to follow is a zero then this is
probably a number in octal notation. */
if(base == 0)
{
if(c == '0')
@ -176,21 +175,31 @@ strtoull(const char *str, char **ptr, int base)
str++;
c = (*str);
num_digits_converted++;
}
}
/* Did we convert anything? */
if(num_digits_converted == 0)
{
__set_errno(ERANGE);
goto out;
}
if(is_negative)
result = (-sum);
else
result = sum;
stop = str;
out:
/* If desired, remember where we stopped reading the
* number from the buffer.
*/
number from the buffer. */
if(ptr != NULL)
(*ptr) = (char *)str;
(*ptr) = (char *)stop;
RETURN(result);
return(result);