From: Adam Harvey Date: Fri, 3 Dec 2010 10:10:08 +0000 (+0000) Subject: Implement FR #53457 (number_format must support more than one character for X-Git-Tag: php-5.4.0alpha1~191^2~566 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d2263d482d58180377a3c5e848352dbf0421cb68;p=php Implement FR #53457 (number_format must support more than one character for thousands separator). --- diff --git a/NEWS b/NEWS index c834513b0b..54f5e4ca67 100644 --- a/NEWS +++ b/NEWS @@ -112,6 +112,10 @@ PHP NEWS getallheaders(), apache_request_headers() and apache_response_headers() . Improved performance of FastCGI request parsing. +- Improved core functions: + . number_format() no longer truncates multibyte decimal points and thousand + separators to the first byte. FR #53457. (Adam) + - Improved CURL extension: . Added support for CURLOPT_MAX_RECV_SPEED_LARGE and CURLOPT_MAX_SEND_SPEED_LARGE. FR #51815. (Pierrick) diff --git a/UPGRADING b/UPGRADING index b8aad2f492..01d5c71ccc 100755 --- a/UPGRADING +++ b/UPGRADING @@ -133,6 +133,8 @@ UPGRADE NOTES - PHP X.Y behavior follows the recommendations of Unicode Technical Report #36. - htmlspecialchars_decode/html_entity_decode now decode ' if the document type is ENT_XML1, ENT_XHTML, or ENT_HTML5. +- number_format() no longer truncates multibyte decimal points and thousand + separators to the first byte. - The third parameter ($matches) to preg_match_all() is now optional. If omitted, the function will simply return the number of times the pattern was matched in the subject and will have no other side effects. diff --git a/ext/standard/math.c b/ext/standard/math.c index 5c758d2878..78918c45ae 100644 --- a/ext/standard/math.c +++ b/ext/standard/math.c @@ -1081,6 +1081,11 @@ PHP_FUNCTION(base_convert) /* {{{ _php_math_number_format */ PHPAPI char *_php_math_number_format(double d, int dec, char dec_point, char thousand_sep) +{ + return _php_math_number_format_ex(d, dec, &dec_point, 1, &thousand_sep, 1); +} + +PHPAPI char *_php_math_number_format_ex(double d, int dec, char *dec_point, size_t dec_point_len, char *thousand_sep, size_t thousand_sep_len) { char *tmpbuf = NULL, *resbuf; char *s, *t; /* source, target */ @@ -1121,7 +1126,7 @@ PHPAPI char *_php_math_number_format(double d, int dec, char dec_point, char tho /* allow for thousand separators */ if (thousand_sep) { - integral += (integral-1) / 3; + integral += thousand_sep_len * ((integral-1) / 3); } reslen = integral; @@ -1130,7 +1135,7 @@ PHPAPI char *_php_math_number_format(double d, int dec, char dec_point, char tho reslen += dec; if (dec_point) { - reslen++; + reslen += dec_point_len; } } @@ -1166,7 +1171,8 @@ PHPAPI char *_php_math_number_format(double d, int dec, char dec_point, char tho /* add decimal point */ if (dec_point) { - *t-- = dec_point; + t -= dec_point_len; + memcpy(t + 1, dec_point, dec_point_len); } } @@ -1175,7 +1181,8 @@ PHPAPI char *_php_math_number_format(double d, int dec, char dec_point, char tho while(s >= tmpbuf) { *t-- = *s--; if (thousand_sep && (++count%3)==0 && s>=tmpbuf) { - *t-- = thousand_sep; + t -= thousand_sep_len; + memcpy(t + 1, thousand_sep, thousand_sep_len); } } @@ -1212,21 +1219,17 @@ PHP_FUNCTION(number_format) RETURN_STRING(_php_math_number_format(num, dec, dec_point_chr, thousand_sep_chr), 0); break; case 4: - if (dec_point != NULL) { - if (dec_point_len) { - dec_point_chr = dec_point[0]; - } else { - dec_point_chr = 0; - } + if (dec_point == NULL) { + dec_point = &dec_point_chr; + dec_point_len = 1; } - if (thousand_sep != NULL) { - if (thousand_sep_len) { - thousand_sep_chr = thousand_sep[0]; - } else { - thousand_sep_chr = 0; - } + + if (thousand_sep == NULL) { + thousand_sep = &thousand_sep_chr; + thousand_sep_len = 1; } - RETURN_STRING(_php_math_number_format(num, dec, dec_point_chr, thousand_sep_chr), 0); + + RETURN_STRING(_php_math_number_format_ex(num, dec, dec_point, dec_point_len, thousand_sep, thousand_sep_len), 0); break; default: WRONG_PARAM_COUNT; diff --git a/ext/standard/php_math.h b/ext/standard/php_math.h index ca059af9fa..0b318c2d56 100644 --- a/ext/standard/php_math.h +++ b/ext/standard/php_math.h @@ -22,7 +22,8 @@ #ifndef PHP_MATH_H #define PHP_MATH_H -PHPAPI char *_php_math_number_format(double, int, char , char); +PHPAPI char *_php_math_number_format(double, int, char, char); +PHPAPI char *_php_math_number_format_ex(double, int, char *, size_t, char *, size_t); PHPAPI char * _php_math_longtobase(zval *arg, int base); PHPAPI long _php_math_basetolong(zval *arg, int base); PHPAPI int _php_math_basetozval(zval *arg, int base, zval *ret); diff --git a/ext/standard/tests/math/number_format_multichar.phpt b/ext/standard/tests/math/number_format_multichar.phpt new file mode 100644 index 0000000000..ae36d12c73 --- /dev/null +++ b/ext/standard/tests/math/number_format_multichar.phpt @@ -0,0 +1,77 @@ +--TEST-- +Test number_format() - multiple character separator support +--FILE-- + +--EXPECTF-- + number_format tests.....multiple character decimal point +string(13) "1 234·57" +string(14) "-1 234·57" +string(18) "12 346 578·00" +string(19) "-12 345 678·90" +string(19) "305 450 479·00" +string(19) "402 653 183·00" +string(19) "123 456 789·00" +string(11) "123·46" +string(11) "123·46" +string(9) "0·00" +string(9) "1·00" +string(9) "0·00" + + number_format tests.....multiple character thousand separator +string(15) "1 234.57" +string(16) "-1 234.57" +string(27) "12 346 578.00" +string(28) "-12 345 678.90" +string(28) "305 450 479.00" +string(28) "402 653 183.00" +string(28) "123 456 789.00" +string(6) "123.46" +string(6) "123.46" +string(4) "0.00" +string(4) "1.00" +string(4) "0.00" + + number_format tests.....multiple character decimal and thousep +string(20) "1 234·57" +string(21) "-1 234·57" +string(32) "12 346 578·00" +string(33) "-12 345 678·90" +string(33) "305 450 479·00" +string(33) "402 653 183·00" +string(33) "123 456 789·00" +string(11) "123·46" +string(11) "123·46" +string(9) "0·00" +string(9) "1·00" +string(9) "0·00"