@ -85,6 +85,17 @@ decimalLength64(const uint64 v)
return t + ( v > = PowersOfTen [ t ] ) ;
}
static const int8 hexlookup [ 128 ] = {
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , 10 , 11 , 12 , 13 , 14 , 15 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , 10 , 11 , 12 , 13 , 14 , 15 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
} ;
/*
* Convert input string to a signed 16 bit integer .
*
@ -108,6 +119,7 @@ int16
pg_strtoint16_safe ( const char * s , Node * escontext )
{
const char * ptr = s ;
const char * firstdigit ;
uint16 tmp = 0 ;
bool neg = false ;
@ -124,19 +136,60 @@ pg_strtoint16_safe(const char *s, Node *escontext)
else if ( * ptr = = ' + ' )
ptr + + ;
/* require at least one digit */
if ( unlikely ( ! isdigit ( ( unsigned char ) * ptr ) ) )
goto invalid_syntax ;
/* process digits */
while ( * ptr & & isdigit ( ( unsigned char ) * ptr ) )
if ( ptr [ 0 ] = = ' 0 ' & & ( ptr [ 1 ] = = ' x ' | | ptr [ 1 ] = = ' X ' ) )
{
if ( unlikely ( tmp > - ( PG_INT16_MIN / 10 ) ) )
goto out_of_range ;
firstdigit = ptr + = 2 ;
while ( * ptr & & isxdigit ( ( unsigned char ) * ptr ) )
{
if ( unlikely ( tmp > - ( PG_INT16_MIN / 16 ) ) )
goto out_of_range ;
tmp = tmp * 16 + hexlookup [ ( unsigned char ) * ptr + + ] ;
}
}
else if ( ptr [ 0 ] = = ' 0 ' & & ( ptr [ 1 ] = = ' o ' | | ptr [ 1 ] = = ' O ' ) )
{
firstdigit = ptr + = 2 ;
while ( * ptr & & ( * ptr > = ' 0 ' & & * ptr < = ' 7 ' ) )
{
if ( unlikely ( tmp > - ( PG_INT16_MIN / 8 ) ) )
goto out_of_range ;
tmp = tmp * 8 + ( * ptr + + - ' 0 ' ) ;
}
}
else if ( ptr [ 0 ] = = ' 0 ' & & ( ptr [ 1 ] = = ' b ' | | ptr [ 1 ] = = ' B ' ) )
{
firstdigit = ptr + = 2 ;
while ( * ptr & & ( * ptr > = ' 0 ' & & * ptr < = ' 1 ' ) )
{
if ( unlikely ( tmp > - ( PG_INT16_MIN / 2 ) ) )
goto out_of_range ;
tmp = tmp * 2 + ( * ptr + + - ' 0 ' ) ;
}
}
else
{
firstdigit = ptr ;
tmp = tmp * 10 + ( * ptr + + - ' 0 ' ) ;
while ( * ptr & & isdigit ( ( unsigned char ) * ptr ) )
{
if ( unlikely ( tmp > - ( PG_INT16_MIN / 10 ) ) )
goto out_of_range ;
tmp = tmp * 10 + ( * ptr + + - ' 0 ' ) ;
}
}
/* require at least one digit */
if ( unlikely ( ptr = = firstdigit ) )
goto invalid_syntax ;
/* allow trailing whitespace, but not other trailing chars */
while ( * ptr ! = ' \0 ' & & isspace ( ( unsigned char ) * ptr ) )
ptr + + ;
@ -193,6 +246,7 @@ int32
pg_strtoint32_safe ( const char * s , Node * escontext )
{
const char * ptr = s ;
const char * firstdigit ;
uint32 tmp = 0 ;
bool neg = false ;
@ -209,19 +263,60 @@ pg_strtoint32_safe(const char *s, Node *escontext)
else if ( * ptr = = ' + ' )
ptr + + ;
/* require at least one digit */
if ( unlikely ( ! isdigit ( ( unsigned char ) * ptr ) ) )
goto invalid_syntax ;
/* process digits */
while ( * ptr & & isdigit ( ( unsigned char ) * ptr ) )
if ( ptr [ 0 ] = = ' 0 ' & & ( ptr [ 1 ] = = ' x ' | | ptr [ 1 ] = = ' X ' ) )
{
if ( unlikely ( tmp > - ( PG_INT32_MIN / 10 ) ) )
goto out_of_range ;
firstdigit = ptr + = 2 ;
while ( * ptr & & isxdigit ( ( unsigned char ) * ptr ) )
{
if ( unlikely ( tmp > - ( PG_INT32_MIN / 16 ) ) )
goto out_of_range ;
tmp = tmp * 16 + hexlookup [ ( unsigned char ) * ptr + + ] ;
}
}
else if ( ptr [ 0 ] = = ' 0 ' & & ( ptr [ 1 ] = = ' o ' | | ptr [ 1 ] = = ' O ' ) )
{
firstdigit = ptr + = 2 ;
while ( * ptr & & ( * ptr > = ' 0 ' & & * ptr < = ' 7 ' ) )
{
if ( unlikely ( tmp > - ( PG_INT32_MIN / 8 ) ) )
goto out_of_range ;
tmp = tmp * 8 + ( * ptr + + - ' 0 ' ) ;
}
}
else if ( ptr [ 0 ] = = ' 0 ' & & ( ptr [ 1 ] = = ' b ' | | ptr [ 1 ] = = ' B ' ) )
{
firstdigit = ptr + = 2 ;
while ( * ptr & & ( * ptr > = ' 0 ' & & * ptr < = ' 1 ' ) )
{
if ( unlikely ( tmp > - ( PG_INT32_MIN / 2 ) ) )
goto out_of_range ;
tmp = tmp * 2 + ( * ptr + + - ' 0 ' ) ;
}
}
else
{
firstdigit = ptr ;
while ( * ptr & & isdigit ( ( unsigned char ) * ptr ) )
{
if ( unlikely ( tmp > - ( PG_INT32_MIN / 10 ) ) )
goto out_of_range ;
tmp = tmp * 10 + ( * ptr + + - ' 0 ' ) ;
tmp = tmp * 10 + ( * ptr + + - ' 0 ' ) ;
}
}
/* require at least one digit */
if ( unlikely ( ptr = = firstdigit ) )
goto invalid_syntax ;
/* allow trailing whitespace, but not other trailing chars */
while ( * ptr ! = ' \0 ' & & isspace ( ( unsigned char ) * ptr ) )
ptr + + ;
@ -278,6 +373,7 @@ int64
pg_strtoint64_safe ( const char * s , Node * escontext )
{
const char * ptr = s ;
const char * firstdigit ;
uint64 tmp = 0 ;
bool neg = false ;
@ -294,18 +390,59 @@ pg_strtoint64_safe(const char *s, Node *escontext)
else if ( * ptr = = ' + ' )
ptr + + ;
/* require at least one digit */
if ( unlikely ( ! isdigit ( ( unsigned char ) * ptr ) ) )
goto invalid_syntax ;
/* process digits */
while ( * ptr & & isdigit ( ( unsigned char ) * ptr ) )
if ( ptr [ 0 ] = = ' 0 ' & & ( ptr [ 1 ] = = ' x ' | | ptr [ 1 ] = = ' X ' ) )
{
if ( unlikely ( tmp > - ( PG_INT64_MIN / 10 ) ) )
goto out_of_range ;
firstdigit = ptr + = 2 ;
while ( * ptr & & isxdigit ( ( unsigned char ) * ptr ) )
{
if ( unlikely ( tmp > - ( PG_INT64_MIN / 16 ) ) )
goto out_of_range ;
tmp = tmp * 10 + ( * ptr + + - ' 0 ' ) ;
tmp = tmp * 16 + hexlookup [ ( unsigned char ) * ptr + + ] ;
}
}
else if ( ptr [ 0 ] = = ' 0 ' & & ( ptr [ 1 ] = = ' o ' | | ptr [ 1 ] = = ' O ' ) )
{
firstdigit = ptr + = 2 ;
while ( * ptr & & ( * ptr > = ' 0 ' & & * ptr < = ' 7 ' ) )
{
if ( unlikely ( tmp > - ( PG_INT64_MIN / 8 ) ) )
goto out_of_range ;
tmp = tmp * 8 + ( * ptr + + - ' 0 ' ) ;
}
}
else if ( ptr [ 0 ] = = ' 0 ' & & ( ptr [ 1 ] = = ' b ' | | ptr [ 1 ] = = ' B ' ) )
{
firstdigit = ptr + = 2 ;
while ( * ptr & & ( * ptr > = ' 0 ' & & * ptr < = ' 1 ' ) )
{
if ( unlikely ( tmp > - ( PG_INT64_MIN / 2 ) ) )
goto out_of_range ;
tmp = tmp * 2 + ( * ptr + + - ' 0 ' ) ;
}
}
else
{
firstdigit = ptr ;
while ( * ptr & & isdigit ( ( unsigned char ) * ptr ) )
{
if ( unlikely ( tmp > - ( PG_INT64_MIN / 10 ) ) )
goto out_of_range ;
tmp = tmp * 10 + ( * ptr + + - ' 0 ' ) ;
}
}
/* require at least one digit */
if ( unlikely ( ptr = = firstdigit ) )
goto invalid_syntax ;
/* allow trailing whitespace, but not other trailing chars */
while ( * ptr ! = ' \0 ' & & isspace ( ( unsigned char ) * ptr ) )