Implement FR #53457 (number_format must support more than one character for

thousands separator).
This commit is contained in:
Adam Harvey 2010-12-03 10:10:08 +00:00
parent 18ec6dae2c
commit d2263d482d
5 changed files with 105 additions and 18 deletions

4
NEWS
View File

@ -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)

View File

@ -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.

View File

@ -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;

View File

@ -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);

View File

@ -0,0 +1,77 @@
--TEST--
Test number_format() - multiple character separator support
--FILE--
<?php
$values = array(1234.5678,
-1234.5678,
1234.6578e4,
-1234.56789e4,
0x1234CDEF,
02777777777,
"123456789",
"123.456789",
"12.3456789e1",
null,
true,
false);
echo " number_format tests.....multiple character decimal point\n";
for ($i = 0; $i < count($values); $i++) {
$res = number_format($values[$i], 2, '&#183;', ' ');
var_dump($res);
}
echo "\n number_format tests.....multiple character thousand separator\n";
for ($i = 0; $i < count($values); $i++) {
$res = number_format($values[$i], 2, '.' , '&thinsp;');
var_dump($res);
}
echo "\n number_format tests.....multiple character decimal and thousep\n";
for ($i = 0; $i < count($values); $i++) {
$res = number_format($values[$i], 2, '&#183;' , '&thinsp;');
var_dump($res);
}
?>
--EXPECTF--
number_format tests.....multiple character decimal point
string(13) "1 234&#183;57"
string(14) "-1 234&#183;57"
string(18) "12 346 578&#183;00"
string(19) "-12 345 678&#183;90"
string(19) "305 450 479&#183;00"
string(19) "402 653 183&#183;00"
string(19) "123 456 789&#183;00"
string(11) "123&#183;46"
string(11) "123&#183;46"
string(9) "0&#183;00"
string(9) "1&#183;00"
string(9) "0&#183;00"
number_format tests.....multiple character thousand separator
string(15) "1&thinsp;234.57"
string(16) "-1&thinsp;234.57"
string(27) "12&thinsp;346&thinsp;578.00"
string(28) "-12&thinsp;345&thinsp;678.90"
string(28) "305&thinsp;450&thinsp;479.00"
string(28) "402&thinsp;653&thinsp;183.00"
string(28) "123&thinsp;456&thinsp;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&thinsp;234&#183;57"
string(21) "-1&thinsp;234&#183;57"
string(32) "12&thinsp;346&thinsp;578&#183;00"
string(33) "-12&thinsp;345&thinsp;678&#183;90"
string(33) "305&thinsp;450&thinsp;479&#183;00"
string(33) "402&thinsp;653&thinsp;183&#183;00"
string(33) "123&thinsp;456&thinsp;789&#183;00"
string(11) "123&#183;46"
string(11) "123&#183;46"
string(9) "0&#183;00"
string(9) "1&#183;00"
string(9) "0&#183;00"