@ -18,6 +18,7 @@
# include <limits.h>
# include <ctype.h>
# include "common/int.h"
# include "utils/builtins.h"
/*
@ -108,6 +109,154 @@ pg_atoi(const char *s, int size, int c)
return ( int32 ) l ;
}
/*
* Convert input string to a signed 16 bit integer .
*
* Allows any number of leading or trailing whitespace characters . Will throw
* ereport ( ) upon bad input format or overflow .
*
* NB : Accumulate input as a negative number , to deal with two ' s complement
* representation of the most negative number , which can ' t be represented as a
* positive number .
*/
int16
pg_strtoint16 ( const char * s )
{
const char * ptr = s ;
int16 tmp = 0 ;
bool neg = false ;
/* skip leading spaces */
while ( likely ( * ptr ) & & isspace ( ( unsigned char ) * ptr ) )
ptr + + ;
/* handle sign */
if ( * ptr = = ' - ' )
{
ptr + + ;
neg = true ;
}
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 ) )
{
int8 digit = ( * ptr + + - ' 0 ' ) ;
if ( unlikely ( pg_mul_s16_overflow ( tmp , 10 , & tmp ) ) | |
unlikely ( pg_sub_s16_overflow ( tmp , digit , & tmp ) ) )
goto out_of_range ;
}
/* allow trailing whitespace, but not other trailing chars */
while ( * ptr ! = ' \0 ' & & isspace ( ( unsigned char ) * ptr ) )
ptr + + ;
if ( unlikely ( * ptr ! = ' \0 ' ) )
goto invalid_syntax ;
if ( ! neg )
{
/* could fail if input is most negative number */
if ( unlikely ( tmp = = PG_INT16_MIN ) )
goto out_of_range ;
tmp = - tmp ;
}
return tmp ;
out_of_range :
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " value \" %s \" is out of range for type %s " ,
s , " smallint " ) ) ) ;
invalid_syntax :
ereport ( ERROR ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " invalid input syntax for type %s: \" %s \" " ,
" smallint " , s ) ) ) ;
}
/*
* Convert input string to a signed 32 bit integer .
*
* Allows any number of leading or trailing whitespace characters . Will throw
* ereport ( ) upon bad input format or overflow .
*
* NB : Accumulate input as a negative number , to deal with two ' s complement
* representation of the most negative number , which can ' t be represented as a
* positive number .
*/
int32
pg_strtoint32 ( const char * s )
{
const char * ptr = s ;
int32 tmp = 0 ;
bool neg = false ;
/* skip leading spaces */
while ( likely ( * ptr ) & & isspace ( ( unsigned char ) * ptr ) )
ptr + + ;
/* handle sign */
if ( * ptr = = ' - ' )
{
ptr + + ;
neg = true ;
}
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 ) )
{
int8 digit = ( * ptr + + - ' 0 ' ) ;
if ( unlikely ( pg_mul_s32_overflow ( tmp , 10 , & tmp ) ) | |
unlikely ( pg_sub_s32_overflow ( tmp , digit , & tmp ) ) )
goto out_of_range ;
}
/* allow trailing whitespace, but not other trailing chars */
while ( * ptr ! = ' \0 ' & & isspace ( ( unsigned char ) * ptr ) )
ptr + + ;
if ( unlikely ( * ptr ! = ' \0 ' ) )
goto invalid_syntax ;
if ( ! neg )
{
/* could fail if input is most negative number */
if ( unlikely ( tmp = = PG_INT32_MIN ) )
goto out_of_range ;
tmp = - tmp ;
}
return tmp ;
out_of_range :
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " value \" %s \" is out of range for type %s " ,
s , " integer " ) ) ) ;
invalid_syntax :
ereport ( ERROR ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " invalid input syntax for type %s: \" %s \" " ,
" integer " , s ) ) ) ;
}
/*
* pg_itoa : converts a signed 16 - bit integer to its string representation
*