Zend/zend_operators.h
/**
 * Checks whether the string "str" with length "length" is numeric. The value
 * of allow_errors determines whether it's required to be entirely numeric, or
 * just its prefix. Leading whitespace is allowed.
 *
 * The function returns 0 if the string did not contain a valid number; IS_LONG
 * if it contained a number that fits within the range of a long; or IS_DOUBLE
 * if the number was out of long range or contained a decimal point/exponent.
 * The number's value is returned into the respective pointer, *lval or *dval,
 * if that pointer is not NULL.
 */
Checks whether the string "str" with length "length" is numeric. The value
of allow_errors determines whether it's required to be entirely numeric, or
just its prefix. Leading whitespace is allowed.

The function returns 0 if the string did not contain a valid number; IS_LONG
if it contained a number that fits within the range of a long; or IS_DOUBLE
if the number was out of long range or contained a decimal point/exponent.
The number's value is returned into the respective pointer, *lval or *dval,
if that pointer is not NULL.
Checks whether the string " str " with length " length " is numeric . The value of allow_errors determines whether it ' s required to be entirely numeric or just its prefix . Leading whitespace is allowed . The function returns 0 if the string did not contain a valid number ; IS_LONG if it contained a number that fits within the range of a long ; or IS_DOUBLE if the number was out of long range or contained a decimal point / exponent . The number ' s value is returned into the respective pointer * lval or * dval if that pointer is not NULL .
static inline zend_uchar is_numeric_string(const char *str, int length, long *lval, double *dval, int allow_errors)
{
	const char *ptr;
	int base = 10, digits = 0, dp_or_e = 0;
	double local_dval;
	zend_uchar type;
	if (!length) {
		return 0;
	}
	while (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r' || *str == '\v' || *str == '\f') {
		str++;
		length--;
	}
	ptr = str;
	if (*ptr == '-' || *ptr == '+') {
		ptr++;
	}
	if (ZEND_IS_DIGIT(*ptr)) {
		if (length > 2 && *str == '0' && (str[1] == 'x' || str[1] == 'X')) {
			base = 16;
			ptr += 2;
		}
		while (*ptr == '0') {
			ptr++;
		}
		for (type = IS_LONG; !(digits >= MAX_LENGTH_OF_LONG && (dval || allow_errors == 1)); digits++, ptr++) {
check_digits:
			if (ZEND_IS_DIGIT(*ptr) || (base == 16 && ZEND_IS_XDIGIT(*ptr))) {
				continue;
			} else if (base == 10) {
				if (*ptr == '.' && dp_or_e < 1) {
					goto process_double;
				} else if ((*ptr == 'e' || *ptr == 'E') && dp_or_e < 2) {
					const char *e = ptr + 1;
					if (*e == '-' || *e == '+') {
						ptr = e++;
					}
					if (ZEND_IS_DIGIT(*e)) {
						goto process_double;
					}
				}
			}
			break;
		}
		if (base == 10) {
			if (digits >= MAX_LENGTH_OF_LONG) {
				dp_or_e = -1;
				goto process_double;
			}
		} else if (!(digits < SIZEOF_LONG * 2 || (digits == SIZEOF_LONG * 2 && ptr[-digits] <= '7'))) {
			if (dval) {
				local_dval = zend_hex_strtod(str, (char **)&ptr);
			}
			type = IS_DOUBLE;
		}
	} else if (*ptr == '.' && ZEND_IS_DIGIT(ptr[1])) {
process_double:
		type = IS_DOUBLE;
		if (dval) {
			local_dval = zend_strtod(str, (char **)&ptr);
		} else if (allow_errors != 1 && dp_or_e != -1) {
			dp_or_e = (*ptr++ == '.') ? 1 : 2;
			goto check_digits;
		}
	} else {
		return 0;
	}
	if (ptr != str + length) {
		if (!allow_errors) {
			return 0;
		}
		if (allow_errors == -1) {
			zend_error(E_NOTICE, "A non well formed numeric value encountered");
		}
	}
	if (type == IS_LONG) {
		if (digits == MAX_LENGTH_OF_LONG - 1) {
			int cmp = strcmp(&ptr[-digits], long_min_digits);
			if (!(cmp < 0 || (cmp == 0 && *str == '-'))) {
				if (dval) {
					*dval = zend_strtod(str, NULL);
				}
				return IS_DOUBLE;
			}
		}
		if (lval) {
			*lval = strtol(str, NULL, base);
		}
		return IS_LONG;
	} else {
		if (dval) {
			*dval = local_dval;
		}
		return IS_DOUBLE;
	}
}
static inline zend_uchar is_numeric_string ( const char * str , int length , long * lval , double * dval , int allow_errors ) { const char * ptr ; int base = 10 , digits = 0 , dp_or_e = 0 ; double local_dval ; zend_uchar type ; if ( ! length ) { return 0 ; } while ( * str == ' ' || * str == ' \t ' || * str == ' \n ' || * str == ' \r ' || * str == ' \v ' || * str == ' \f ' ) { str ++ ; length -- ; } ptr = str ; if ( * ptr == ' ' || * ptr == ' ' ) { ptr ++ ; } if ( ZEND_IS_DIGIT ( * ptr ) ) { if ( length > 2 && * str == ' ' && ( str [ 1 ] == ' ' || str [ 1 ] == ' ' ) ) { base = 16 ; ptr += 2 ; } while ( * ptr == ' ' ) { ptr ++ ; } for ( type = IS_LONG ; ! ( digits >= MAX_LENGTH_OF_LONG && ( dval || allow_errors == 1 ) ) ; digits ++ , ptr ++ ) { check_digits : if ( ZEND_IS_DIGIT ( * ptr ) || ( base == 16 && ZEND_IS_XDIGIT ( * ptr ) ) ) { continue ; } else if ( base == 10 ) { if ( * ptr == ' ' && dp_or_e < 1 ) { goto process_double ; } else if ( ( * ptr == ' ' || * ptr == ' ' ) && dp_or_e < 2 ) { const char * e = ptr + 1 ; if ( * e == ' ' || * e == ' ' ) { ptr = e ++ ; } if ( ZEND_IS_DIGIT ( * e ) ) { goto process_double ; } } } break ; } if ( base == 10 ) { if ( digits >= MAX_LENGTH_OF_LONG ) { dp_or_e = -1 ; goto process_double ; } } else if ( ! ( digits < SIZEOF_LONG * 2 || ( digits == SIZEOF_LONG * 2 && ptr [ - digits ] <= ' ' ) ) ) { if ( dval ) { local_dval = zend_hex_strtod ( str , ( char * * ) & ptr ) ; } type = IS_DOUBLE ; } } else if ( * ptr == ' ' && ZEND_IS_DIGIT ( ptr [ 1 ] ) ) { process_double : type = IS_DOUBLE ; if ( dval ) { local_dval = zend_strtod ( str , ( char * * ) & ptr ) ; } else if ( allow_errors != 1 && dp_or_e != -1 ) { dp_or_e = ( * ptr ++ == ' ' ) ? 1 : 2 ; goto check_digits ; } } else { return 0 ; } if ( ptr != str + length ) { if ( ! allow_errors ) { return 0 ; } if ( allow_errors == -1 ) { zend_error ( E_NOTICE , " " ) ; } } if ( type == IS_LONG ) { if ( digits == MAX_LENGTH_OF_LONG - 1 ) { int cmp = strcmp ( & ptr [ - digits ] , long_min_digits ) ; if ( ! ( cmp < 0 || ( cmp == 0 && * str == ' ' ) ) ) { if ( dval ) { * dval = zend_strtod ( str , NULL ) ; } return IS_DOUBLE ; } } if ( lval ) { * lval = strtol ( str , NULL , base ) ; } return IS_LONG ; } else { if ( dval ) { * dval = local_dval ; } return IS_DOUBLE ; } }
Checks whether the string "str" with length "length" is numeric.
Checks whether the string " str " with length " length " is numeric .
/* Skip any whitespace
	 * This is much faster than the isspace() function */ /* Handle hex numbers
		 * str is used instead of ptr to disallow signs and keep old behavior */ /* Skip any leading 0s */ /* Count the number of digits. If a decimal point/exponent is found,
		 * it's a double. Otherwise, if there's a dval or no need to check for
		 * a full match, stop when there are too many digits for a long */ /* If there's a dval, do the conversion; else continue checking
		 * the digits if we need to check for a full match */