diff options
Diffstat (limited to 'ext/json/json.c')
| -rw-r--r-- | ext/json/json.c | 37 | 
1 files changed, 29 insertions, 8 deletions
| diff --git a/ext/json/json.c b/ext/json/json.c index 22c6353803..baad4bc399 100644 --- a/ext/json/json.c +++ b/ext/json/json.c @@ -31,6 +31,14 @@  #include "php_json.h"  #include <zend_exceptions.h> +#include <float.h> +#if defined(DBL_MANT_DIG) && defined(DBL_MIN_EXP) +#define NUM_BUF_SIZE (3 + DBL_MANT_DIG - DBL_MIN_EXP) +#else +#define NUM_BUF_SIZE 1080 +#endif + +  static PHP_MINFO_FUNCTION(json);  static PHP_FUNCTION(json_encode);  static PHP_FUNCTION(json_decode); @@ -103,6 +111,7 @@ static PHP_MINIT_FUNCTION(json)  	REGISTER_LONG_CONSTANT("JSON_PRETTY_PRINT", PHP_JSON_PRETTY_PRINT, CONST_CS | CONST_PERSISTENT);  	REGISTER_LONG_CONSTANT("JSON_UNESCAPED_UNICODE", PHP_JSON_UNESCAPED_UNICODE, CONST_CS | CONST_PERSISTENT);  	REGISTER_LONG_CONSTANT("JSON_PARTIAL_OUTPUT_ON_ERROR", PHP_JSON_PARTIAL_OUTPUT_ON_ERROR, CONST_CS | CONST_PERSISTENT); +	REGISTER_LONG_CONSTANT("JSON_PRESERVE_ZERO_FRACTION", PHP_JSON_PRESERVE_ZERO_FRACTION, CONST_CS | CONST_PERSISTENT);  	REGISTER_LONG_CONSTANT("JSON_ERROR_NONE", PHP_JSON_ERROR_NONE, CONST_CS | CONST_PERSISTENT);  	REGISTER_LONG_CONSTANT("JSON_ERROR_DEPTH", PHP_JSON_ERROR_DEPTH, CONST_CS | CONST_PERSISTENT); @@ -407,10 +416,17 @@ static void json_escape_string(smart_str *buf, char *s, size_t len, int options)  				smart_str_append_long(buf, p);  			} else if (type == IS_DOUBLE) {  				if (!zend_isinf(d) && !zend_isnan(d)) { -					char *tmp; -					int l = spprintf(&tmp, 0, "%.*k", (int) EG(precision), d); -					smart_str_appendl(buf, tmp, l); -					efree(tmp); +					char num[NUM_BUF_SIZE]; +					int l; + +					php_gcvt(d, EG(precision), '.', 'e', (char *)num); +					l = strlen(num); +					if (options & PHP_JSON_PRESERVE_ZERO_FRACTION && strchr(num, '.') == NULL && l < NUM_BUF_SIZE - 2) { +						num[l++] = '.'; +						num[l++] = '0'; +						num[l] = '\0'; +					} +					smart_str_appendl(buf, num, l);  				} else {  					JSON_G(error_code) = PHP_JSON_ERROR_INF_OR_NAN;  					smart_str_appendc(buf, '0'); @@ -627,14 +643,19 @@ again:  		case IS_DOUBLE:  			{ -				char *d = NULL; +				char num[NUM_BUF_SIZE];  				int len;  				double dbl = Z_DVAL_P(val);  				if (!zend_isinf(dbl) && !zend_isnan(dbl)) { -					len = spprintf(&d, 0, "%.*k", (int) EG(precision), dbl); -					smart_str_appendl(buf, d, len); -					efree(d); +					php_gcvt(dbl, EG(precision), '.', 'e', (char *)num); +					len = strlen(num); +					if (options & PHP_JSON_PRESERVE_ZERO_FRACTION && strchr(num, '.') == NULL && len < NUM_BUF_SIZE - 2) { +						num[len++] = '.'; +						num[len++] = '0'; +						num[len] = '\0'; +					} +					smart_str_appendl(buf, num, len);  				} else {  					JSON_G(error_code) = PHP_JSON_ERROR_INF_OR_NAN;  					smart_str_appendc(buf, '0'); | 
