diff options
author | Yasuo Ohgaki <yohgaki@ohgaki.net> | 2015-08-05 08:12:10 +0900 |
---|---|---|
committer | Jakub Zelenka <bukka@php.net> | 2016-06-26 13:26:42 +0100 |
commit | f943daf2d7eeed98d3ead5c05637c2ea8a2ff0e6 (patch) | |
tree | 869bb1269326a413167ce94e81aaa1136cfce71f | |
parent | 8de8636a2b6dc331486284f1f037259bb7347768 (diff) | |
download | php-git-f943daf2d7eeed98d3ead5c05637c2ea8a2ff0e6.tar.gz |
Initial patch for 0 mode float conversion. The magic number is better to be improved. Any suggestion where to define it?
-rw-r--r-- | ext/json/json_encoder.c | 6 | ||||
-rw-r--r-- | ext/standard/var.c | 34 | ||||
-rw-r--r-- | main/main.c | 19 | ||||
-rw-r--r-- | main/snprintf.c | 18 | ||||
-rw-r--r-- | main/snprintf.h | 1 |
5 files changed, 61 insertions, 17 deletions
diff --git a/ext/json/json_encoder.c b/ext/json/json_encoder.c index f944b888c7..92ab413cf0 100644 --- a/ext/json/json_encoder.c +++ b/ext/json/json_encoder.c @@ -104,7 +104,11 @@ static inline void php_json_encode_double(smart_str *buf, double d, int options) { size_t len; char num[PHP_JSON_DOUBLE_MAX_LENGTH]; - php_gcvt(d, (int)EG(precision), '.', 'e', &num[0]); + if (PG(serialize_precision) == -1) { + php_0cvt(d, 17, '.', 'e', num); + } else { + php_gcvt(d, PG(serialize_precision), '.', 'e', num); + } len = strlen(num); if (options & PHP_JSON_PRESERVE_ZERO_FRACTION && strchr(num, '.') == NULL && len < PHP_JSON_DOUBLE_MAX_LENGTH - 2) { num[len++] = '.'; diff --git a/ext/standard/var.c b/ext/standard/var.c index efd5119fed..e197198557 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -436,8 +436,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; - size_t tmp_len; + char tmp_str[2048]; /* Use the same magic number of spprintf.c NUM_BUF_SIZE */ zend_string *ztmp, *ztmp2; zend_ulong index; zend_string *key; @@ -458,18 +457,26 @@ again: smart_str_append_long(buf, Z_LVAL_P(struc)); break; case IS_DOUBLE: + /* TODO: check INF, -INF and NAN in the new logic tmp_len = spprintf(&tmp_str, 0,"%.*H", PG(serialize_precision), Z_DVAL_P(struc)); smart_str_appendl(buf, tmp_str, tmp_len); - /* Without a decimal point, PHP treats a number literal as an int. + * Without a decimal point, PHP treats a number literal as an int. * This check even works for scientific notation, because the * mantissa always contains a decimal point. * We need to check for finiteness, because INF, -INF and NAN * must not have a decimal point added. - */ + * if (zend_finite(Z_DVAL_P(struc)) && NULL == strchr(tmp_str, '.')) { smart_str_appendl(buf, ".0", 2); } efree(tmp_str); + */ + if (PG(serialize_precision < 0)) { + php_0cvt(Z_DVAL_P(struc), 17, '.', 'E', tmp_str); + } else { + php_gcvt(Z_DVAL_P(struc), (int)PG(serialize_precision), '.', 'E', tmp_str); + } + smart_str_appends(buf, tmp_str); break; case IS_STRING: ztmp = php_addcslashes(Z_STR_P(struc), 0, "'\\", 2); @@ -844,16 +851,17 @@ again: return; case IS_DOUBLE: { - char *s; - - smart_str_appendl(buf, "d:", 2); - s = (char *) safe_emalloc(PG(serialize_precision), 1, MAX_LENGTH_OF_DOUBLE + 1); - php_gcvt(Z_DVAL_P(struc), (int)PG(serialize_precision), '.', 'E', s); - smart_str_appends(buf, s); - smart_str_appendc(buf, ';'); - efree(s); - return; + char tmp_str[2048]; /* Use the same magic number of spprintf.c NUM_BUF_SIZE */ + smart_str_appendl(buf, "d:", 2); + if (PG(serialize_precision < 0)) { + php_0cvt(Z_DVAL_P(struc), 17, '.', 'E', tmp_str); + } else { + php_gcvt(Z_DVAL_P(struc), (int)PG(serialize_precision), '.', 'E', tmp_str); } + smart_str_appends(buf, tmp_str); + smart_str_appendc(buf, ';'); + return; + } case IS_STRING: php_var_serialize_string(buf, Z_STRVAL_P(struc), Z_STRLEN_P(struc)); diff --git a/main/main.c b/main/main.c index 83f5c1a6b9..8a3dc1ce9e 100644 --- a/main/main.c +++ b/main/main.c @@ -142,6 +142,23 @@ static PHP_INI_MH(OnSetPrecision) /* {{{ PHP_INI_MH */ +static PHP_INI_MH(OnSetSerializePrecision) +{ + zend_long i; + + ZEND_ATOL(i, ZSTR_VAL(new_value)); + if (i >= -1) { + PG(serialize_precision) = i; + return SUCCESS; + } else { + return FAILURE; + } +} +/* }}} */ + + +/* {{{ PHP_INI_MH + */ static PHP_INI_MH(OnChangeMemoryLimit) { if (new_value) { @@ -533,7 +550,7 @@ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("track_errors", "0", PHP_INI_ALL, OnUpdateBool, track_errors, php_core_globals, core_globals) STD_PHP_INI_ENTRY("unserialize_callback_func", NULL, PHP_INI_ALL, OnUpdateString, unserialize_callback_func, php_core_globals, core_globals) - STD_PHP_INI_ENTRY("serialize_precision", "17", PHP_INI_ALL, OnUpdateLongGEZero, serialize_precision, php_core_globals, core_globals) + STD_PHP_INI_ENTRY("serialize_precision", "-1", PHP_INI_ALL, OnSetSerializePrecision, serialize_precision, php_core_globals, core_globals) STD_PHP_INI_ENTRY("arg_separator.output", "&", PHP_INI_ALL, OnUpdateStringUnempty, arg_separator.output, php_core_globals, core_globals) STD_PHP_INI_ENTRY("arg_separator.input", "&", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateStringUnempty, arg_separator.input, php_core_globals, core_globals) diff --git a/main/snprintf.c b/main/snprintf.c index 9e86d72221..a69ebb3e31 100644 --- a/main/snprintf.c +++ b/main/snprintf.c @@ -139,12 +139,12 @@ static inline char *php_fcvt(double value, int ndigit, int *decpt, int *sign) /* } /* }}} */ -PHPAPI char *php_gcvt(double value, int ndigit, char dec_point, char exponent, char *buf) /* {{{ */ +static inline char *_php_cvt(double value, int ndigit, char dec_point, char exponent, char *buf, int mode) /* {{{ */ { char *digits, *dst, *src; int i, decpt, sign; - digits = zend_dtoa(value, 2, ndigit, &decpt, &sign, NULL); + digits = zend_dtoa(value, mode, ndigit, &decpt, &sign, NULL); if (decpt == 9999) { /* * Infinity or NaN, convert to inf or nan with sign. @@ -234,6 +234,20 @@ PHPAPI char *php_gcvt(double value, int ndigit, char dec_point, char exponent, c } /* }}} */ +PHPAPI char *php_gcvt(double value, int ndigit, char dec_point, char exponent, char *buf) /* {{{ */ +{ + return _php_cvt(value, ndigit, dec_point, exponent, buf, 2); +} +/* }}} */ + +PHPAPI char *php_0cvt(double value, int ndigit, char dec_point, char exponent, char *buf) /* {{{ */ +{ + return _php_cvt(value, ndigit, dec_point, exponent, buf, 0); +} +/* }}} */ + + + /* {{{ Apache license */ /* ==================================================================== * Copyright (c) 1995-1998 The Apache Group. All rights reserved. diff --git a/main/snprintf.h b/main/snprintf.h index 7bb92ecb19..8cd2c0c5ca 100644 --- a/main/snprintf.h +++ b/main/snprintf.h @@ -86,6 +86,7 @@ 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 int php_sprintf (char* s, const char* format, ...) PHP_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, boolean_e add_dp, int precision, char dec_point, bool_int * is_negative, char *buf, size_t *len); |