mirror of
https://github.com/php/php-src.git
synced 2024-09-21 09:57:23 +00:00
Move php_gcvt to zend_gcvt
Also move PHP_DOUBLE_MAX_LENGTH to ZEND_DOUBLE_MAX_LENGTH.
This commit is contained in:
parent
7c9ac479eb
commit
d28f6e694d
@ -4507,6 +4507,105 @@ ZEND_API double zend_bin_strtod(const char *str, const char **endptr)
|
||||
return value;
|
||||
}
|
||||
|
||||
ZEND_API char *zend_gcvt(double value, int ndigit, char dec_point, char exponent, char *buf)
|
||||
{
|
||||
char *digits, *dst, *src;
|
||||
int i, decpt;
|
||||
bool sign;
|
||||
int mode = ndigit >= 0 ? 2 : 0;
|
||||
|
||||
if (mode == 0) {
|
||||
ndigit = 17;
|
||||
}
|
||||
digits = zend_dtoa(value, mode, ndigit, &decpt, &sign, NULL);
|
||||
if (decpt == 9999) {
|
||||
/*
|
||||
* Infinity or NaN, convert to inf or nan with sign.
|
||||
* We assume the buffer is at least ndigit long.
|
||||
*/
|
||||
snprintf(buf, ndigit + 1, "%s%s", (sign && *digits == 'I') ? "-" : "", *digits == 'I' ? "INF" : "NAN");
|
||||
zend_freedtoa(digits);
|
||||
return (buf);
|
||||
}
|
||||
|
||||
dst = buf;
|
||||
if (sign) {
|
||||
*dst++ = '-';
|
||||
}
|
||||
|
||||
if ((decpt >= 0 && decpt > ndigit) || decpt < -3) { /* use E-style */
|
||||
/* exponential format (e.g. 1.2345e+13) */
|
||||
if (--decpt < 0) {
|
||||
sign = 1;
|
||||
decpt = -decpt;
|
||||
} else {
|
||||
sign = 0;
|
||||
}
|
||||
src = digits;
|
||||
*dst++ = *src++;
|
||||
*dst++ = dec_point;
|
||||
if (*src == '\0') {
|
||||
*dst++ = '0';
|
||||
} else {
|
||||
do {
|
||||
*dst++ = *src++;
|
||||
} while (*src != '\0');
|
||||
}
|
||||
*dst++ = exponent;
|
||||
if (sign) {
|
||||
*dst++ = '-';
|
||||
} else {
|
||||
*dst++ = '+';
|
||||
}
|
||||
if (decpt < 10) {
|
||||
*dst++ = '0' + decpt;
|
||||
*dst = '\0';
|
||||
} else {
|
||||
/* XXX - optimize */
|
||||
int n;
|
||||
for (n = decpt, i = 0; (n /= 10) != 0; i++);
|
||||
dst[i + 1] = '\0';
|
||||
while (decpt != 0) {
|
||||
dst[i--] = '0' + decpt % 10;
|
||||
decpt /= 10;
|
||||
}
|
||||
}
|
||||
} else if (decpt < 0) {
|
||||
/* standard format 0. */
|
||||
*dst++ = '0'; /* zero before decimal point */
|
||||
*dst++ = dec_point;
|
||||
do {
|
||||
*dst++ = '0';
|
||||
} while (++decpt < 0);
|
||||
src = digits;
|
||||
while (*src != '\0') {
|
||||
*dst++ = *src++;
|
||||
}
|
||||
*dst = '\0';
|
||||
} else {
|
||||
/* standard format */
|
||||
for (i = 0, src = digits; i < decpt; i++) {
|
||||
if (*src != '\0') {
|
||||
*dst++ = *src++;
|
||||
} else {
|
||||
*dst++ = '0';
|
||||
}
|
||||
}
|
||||
if (*src != '\0') {
|
||||
if (src == digits) {
|
||||
*dst++ = '0'; /* zero before decimal point */
|
||||
}
|
||||
*dst++ = dec_point;
|
||||
for (i = decpt; digits[i] != '\0'; i++) {
|
||||
*dst++ = digits[i];
|
||||
}
|
||||
}
|
||||
*dst = '\0';
|
||||
}
|
||||
zend_freedtoa(digits);
|
||||
return (buf);
|
||||
}
|
||||
|
||||
static void destroy_freelist(void)
|
||||
{
|
||||
int i;
|
||||
|
@ -24,7 +24,8 @@
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
ZEND_API void zend_freedtoa(char *s);
|
||||
ZEND_API char * zend_dtoa(double _d, int mode, int ndigits, int *decpt, bool *sign, char **rve);
|
||||
ZEND_API char *zend_dtoa(double _d, int mode, int ndigits, int *decpt, bool *sign, char **rve);
|
||||
ZEND_API char *zend_gcvt(double value, int ndigit, char dec_point, char exponent, char *buf);
|
||||
ZEND_API double zend_strtod(const char *s00, const char **se);
|
||||
ZEND_API double zend_hex_strtod(const char *str, const char **endptr);
|
||||
ZEND_API double zend_oct_strtod(const char *str, const char **endptr);
|
||||
@ -33,4 +34,12 @@ ZEND_API int zend_startup_strtod(void);
|
||||
ZEND_API int zend_shutdown_strtod(void);
|
||||
END_EXTERN_C()
|
||||
|
||||
/* double limits */
|
||||
#include <float.h>
|
||||
#if defined(DBL_MANT_DIG) && defined(DBL_MIN_EXP)
|
||||
#define ZEND_DOUBLE_MAX_LENGTH (3 + DBL_MANT_DIG - DBL_MIN_EXP)
|
||||
#else
|
||||
#define ZEND_DOUBLE_MAX_LENGTH 1080
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -80,11 +80,11 @@ static inline int php_json_is_valid_double(double d) /* {{{ */
|
||||
static inline void php_json_encode_double(smart_str *buf, double d, int options) /* {{{ */
|
||||
{
|
||||
size_t len;
|
||||
char num[PHP_DOUBLE_MAX_LENGTH];
|
||||
char num[ZEND_DOUBLE_MAX_LENGTH];
|
||||
|
||||
php_gcvt(d, (int)PG(serialize_precision), '.', 'e', num);
|
||||
zend_gcvt(d, (int)PG(serialize_precision), '.', 'e', num);
|
||||
len = strlen(num);
|
||||
if (options & PHP_JSON_PRESERVE_ZERO_FRACTION && strchr(num, '.') == NULL && len < PHP_DOUBLE_MAX_LENGTH - 2) {
|
||||
if (options & PHP_JSON_PRESERVE_ZERO_FRACTION && strchr(num, '.') == NULL && len < ZEND_DOUBLE_MAX_LENGTH - 2) {
|
||||
num[len++] = '.';
|
||||
num[len++] = '0';
|
||||
num[len] = '\0';
|
||||
|
@ -38,7 +38,7 @@ static inline double mysql_float_to_double(float fp4, int decimals) {
|
||||
char num_buf[MAX_CHAR_BUF_LEN]; /* Over allocated */
|
||||
|
||||
if (decimals < 0) {
|
||||
php_gcvt(fp4, FLT_DIG, '.', 'e', num_buf);
|
||||
zend_gcvt(fp4, FLT_DIG, '.', 'e', num_buf);
|
||||
} else {
|
||||
snprintf(num_buf, MAX_CHAR_BUF_LEN, "%.*F", decimals, fp4);
|
||||
}
|
||||
|
@ -1083,7 +1083,7 @@ static xmlNodePtr to_xml_double(encodeTypePtr type, zval *data, int style, xmlNo
|
||||
ZVAL_DOUBLE(&tmp, zval_get_double(data));
|
||||
|
||||
str = (char *) safe_emalloc(EG(precision) >= 0 ? EG(precision) : 17, 1, MAX_LENGTH_OF_DOUBLE + 1);
|
||||
php_gcvt(Z_DVAL(tmp), EG(precision), '.', 'E', str);
|
||||
zend_gcvt(Z_DVAL(tmp), EG(precision), '.', 'E', str);
|
||||
xmlNodeSetContentLen(ret, BAD_CAST(str), strlen(str));
|
||||
efree(str);
|
||||
|
||||
|
@ -299,7 +299,7 @@ php_sprintf_appenddouble(zend_string **buffer, size_t *pos,
|
||||
|
||||
char exp_char = fmt == 'G' || fmt == 'H' ? 'E' : 'e';
|
||||
/* We use &num_buf[ 1 ], so that we have room for the sign. */
|
||||
s = php_gcvt(number, precision, decimal_point, exp_char, &num_buf[1]);
|
||||
s = zend_gcvt(number, precision, decimal_point, exp_char, &num_buf[1]);
|
||||
is_negative = 0;
|
||||
if (*s == '-') {
|
||||
is_negative = 1;
|
||||
|
@ -480,7 +480,7 @@ static void php_object_element_export(zval *zv, zend_ulong index, zend_string *k
|
||||
PHPAPI void php_var_export_ex(zval *struc, int level, smart_str *buf) /* {{{ */
|
||||
{
|
||||
HashTable *myht;
|
||||
char tmp_str[PHP_DOUBLE_MAX_LENGTH];
|
||||
char tmp_str[ZEND_DOUBLE_MAX_LENGTH];
|
||||
zend_string *ztmp, *ztmp2;
|
||||
zend_ulong index;
|
||||
zend_string *key;
|
||||
@ -508,7 +508,7 @@ again:
|
||||
smart_str_append_long(buf, Z_LVAL_P(struc));
|
||||
break;
|
||||
case IS_DOUBLE:
|
||||
php_gcvt(Z_DVAL_P(struc), (int)PG(serialize_precision), '.', 'E', tmp_str);
|
||||
zend_gcvt(Z_DVAL_P(struc), (int)PG(serialize_precision), '.', 'E', tmp_str);
|
||||
smart_str_appends(buf, tmp_str);
|
||||
/* Without a decimal point, PHP treats a number literal as an int.
|
||||
* This check even works for scientific notation, because the
|
||||
@ -1038,8 +1038,8 @@ again:
|
||||
return;
|
||||
|
||||
case IS_DOUBLE: {
|
||||
char tmp_str[PHP_DOUBLE_MAX_LENGTH];
|
||||
php_gcvt(Z_DVAL_P(struc), (int)PG(serialize_precision), '.', 'E', tmp_str);
|
||||
char tmp_str[ZEND_DOUBLE_MAX_LENGTH];
|
||||
zend_gcvt(Z_DVAL_P(struc), (int)PG(serialize_precision), '.', 'E', tmp_str);
|
||||
|
||||
size_t len = strlen(tmp_str);
|
||||
char *res = smart_str_extend(buf, 2 + len + 1);
|
||||
|
@ -245,13 +245,7 @@ typedef unsigned int socklen_t;
|
||||
#define INT_MIN (- INT_MAX - 1)
|
||||
#endif
|
||||
|
||||
/* double limits */
|
||||
#include <float.h>
|
||||
#if defined(DBL_MANT_DIG) && defined(DBL_MIN_EXP)
|
||||
#define PHP_DOUBLE_MAX_LENGTH (3 + DBL_MANT_DIG - DBL_MIN_EXP)
|
||||
#else
|
||||
#define PHP_DOUBLE_MAX_LENGTH 1080
|
||||
#endif
|
||||
#define PHP_DOUBLE_MAX_LENGTH ZEND_DOUBLE_MAX_LENGTH
|
||||
|
||||
#define PHP_GCC_VERSION ZEND_GCC_VERSION
|
||||
#define PHP_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_MALLOC
|
||||
|
102
main/snprintf.c
102
main/snprintf.c
@ -128,106 +128,6 @@ static inline char *php_fcvt(double value, int ndigit, int *decpt, bool *sign) /
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
PHPAPI char *php_gcvt(double value, int ndigit, char dec_point, char exponent, char *buf) /* {{{ */
|
||||
{
|
||||
char *digits, *dst, *src;
|
||||
int i, decpt;
|
||||
bool sign;
|
||||
int mode = ndigit >= 0 ? 2 : 0;
|
||||
|
||||
if (mode == 0) {
|
||||
ndigit = 17;
|
||||
}
|
||||
digits = zend_dtoa(value, mode, ndigit, &decpt, &sign, NULL);
|
||||
if (decpt == 9999) {
|
||||
/*
|
||||
* Infinity or NaN, convert to inf or nan with sign.
|
||||
* We assume the buffer is at least ndigit long.
|
||||
*/
|
||||
snprintf(buf, ndigit + 1, "%s%s", (sign && *digits == 'I') ? "-" : "", *digits == 'I' ? "INF" : "NAN");
|
||||
zend_freedtoa(digits);
|
||||
return (buf);
|
||||
}
|
||||
|
||||
dst = buf;
|
||||
if (sign) {
|
||||
*dst++ = '-';
|
||||
}
|
||||
|
||||
if ((decpt >= 0 && decpt > ndigit) || decpt < -3) { /* use E-style */
|
||||
/* exponential format (e.g. 1.2345e+13) */
|
||||
if (--decpt < 0) {
|
||||
sign = 1;
|
||||
decpt = -decpt;
|
||||
} else {
|
||||
sign = 0;
|
||||
}
|
||||
src = digits;
|
||||
*dst++ = *src++;
|
||||
*dst++ = dec_point;
|
||||
if (*src == '\0') {
|
||||
*dst++ = '0';
|
||||
} else {
|
||||
do {
|
||||
*dst++ = *src++;
|
||||
} while (*src != '\0');
|
||||
}
|
||||
*dst++ = exponent;
|
||||
if (sign) {
|
||||
*dst++ = '-';
|
||||
} else {
|
||||
*dst++ = '+';
|
||||
}
|
||||
if (decpt < 10) {
|
||||
*dst++ = '0' + decpt;
|
||||
*dst = '\0';
|
||||
} else {
|
||||
/* XXX - optimize */
|
||||
int n;
|
||||
for (n = decpt, i = 0; (n /= 10) != 0; i++);
|
||||
dst[i + 1] = '\0';
|
||||
while (decpt != 0) {
|
||||
dst[i--] = '0' + decpt % 10;
|
||||
decpt /= 10;
|
||||
}
|
||||
}
|
||||
} else if (decpt < 0) {
|
||||
/* standard format 0. */
|
||||
*dst++ = '0'; /* zero before decimal point */
|
||||
*dst++ = dec_point;
|
||||
do {
|
||||
*dst++ = '0';
|
||||
} while (++decpt < 0);
|
||||
src = digits;
|
||||
while (*src != '\0') {
|
||||
*dst++ = *src++;
|
||||
}
|
||||
*dst = '\0';
|
||||
} else {
|
||||
/* standard format */
|
||||
for (i = 0, src = digits; i < decpt; i++) {
|
||||
if (*src != '\0') {
|
||||
*dst++ = *src++;
|
||||
} else {
|
||||
*dst++ = '0';
|
||||
}
|
||||
}
|
||||
if (*src != '\0') {
|
||||
if (src == digits) {
|
||||
*dst++ = '0'; /* zero before decimal point */
|
||||
}
|
||||
*dst++ = dec_point;
|
||||
for (i = decpt; digits[i] != '\0'; i++) {
|
||||
*dst++ = digits[i];
|
||||
}
|
||||
}
|
||||
*dst = '\0';
|
||||
}
|
||||
zend_freedtoa(digits);
|
||||
return (buf);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Apache license */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1995-1998 The Apache Group. All rights reserved.
|
||||
@ -1043,7 +943,7 @@ static size_t format_converter(buffy * odp, const char *fmt, va_list ap) /* {{{
|
||||
lconv = localeconv();
|
||||
}
|
||||
#endif
|
||||
s = php_gcvt(fp_num, precision, (*fmt=='H' || *fmt == 'k') ? '.' : LCONV_DECIMAL_POINT, (*fmt == 'G' || *fmt == 'H')?'E':'e', &num_buf[1]);
|
||||
s = zend_gcvt(fp_num, precision, (*fmt=='H' || *fmt == 'k') ? '.' : LCONV_DECIMAL_POINT, (*fmt == 'G' || *fmt == 'H')?'E':'e', &num_buf[1]);
|
||||
if (*s == '-') {
|
||||
prefix_char = *s++;
|
||||
} else if (print_sign) {
|
||||
|
@ -75,13 +75,14 @@ PHPAPI int ap_php_snprintf(char *, size_t, const char *, ...) ZEND_ATTRIBUTE_FOR
|
||||
PHPAPI int ap_php_vsnprintf(char *, size_t, const char *, va_list ap);
|
||||
PHPAPI int ap_php_vasprintf(char **buf, const char *format, va_list ap);
|
||||
PHPAPI int ap_php_asprintf(char **buf, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
|
||||
PHPAPI char * php_gcvt(double value, int ndigit, char dec_point, char exponent, char *buf);
|
||||
PHPAPI char * php_0cvt(double value, int ndigit, char dec_point, char exponent, char *buf);
|
||||
PHPAPI char * php_conv_fp(char format, double num,
|
||||
bool add_dp, int precision, char dec_point, bool * is_negative, char *buf, size_t *len);
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
#define php_gcvt zend_gcvt
|
||||
|
||||
#ifdef slprintf
|
||||
#undef slprintf
|
||||
#endif
|
||||
@ -138,7 +139,7 @@ PHPAPI char * ap_php_conv_p2(uint64_t num, int nbits,
|
||||
* another level (see NDIG in php_conv_fp()).
|
||||
* Applies to the formatting functions of both spprintf.c and snprintf.c, which
|
||||
* use equally sized buffers of MAX_BUF_SIZE = 512 to hold the result of the
|
||||
* call to php_gcvt().
|
||||
* call to zend_gcvt().
|
||||
* This should be reasonably smaller than MAX_BUF_SIZE (I think MAX_BUF_SIZE - 9
|
||||
* should be enough, but let's give some more space) */
|
||||
#define FORMAT_CONV_MAX_PRECISION 500
|
||||
|
@ -141,7 +141,7 @@
|
||||
* NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
|
||||
* which can be at most max length of double
|
||||
*/
|
||||
#define NUM_BUF_SIZE PHP_DOUBLE_MAX_LENGTH
|
||||
#define NUM_BUF_SIZE ZEND_DOUBLE_MAX_LENGTH
|
||||
|
||||
#define NUM(c) (c - '0')
|
||||
|
||||
@ -651,7 +651,7 @@ static void xbuf_format_converter(void *xbuf, bool is_char, const char *fmt, va_
|
||||
lconv = localeconv();
|
||||
}
|
||||
#endif
|
||||
s = php_gcvt(fp_num, precision, (*fmt=='H' || *fmt == 'k') ? '.' : LCONV_DECIMAL_POINT, (*fmt == 'G' || *fmt == 'H')?'E':'e', &num_buf[1]);
|
||||
s = zend_gcvt(fp_num, precision, (*fmt=='H' || *fmt == 'k') ? '.' : LCONV_DECIMAL_POINT, (*fmt == 'G' || *fmt == 'H')?'E':'e', &num_buf[1]);
|
||||
if (*s == '-')
|
||||
prefix_char = *s++;
|
||||
else if (print_sign)
|
||||
|
Loading…
Reference in New Issue
Block a user