]> granicus.if.org Git - php/commitdiff
Implement FR #53457 (number_format must support more than one character for
authorAdam Harvey <aharvey@php.net>
Fri, 3 Dec 2010 10:10:08 +0000 (10:10 +0000)
committerAdam Harvey <aharvey@php.net>
Fri, 3 Dec 2010 10:10:08 +0000 (10:10 +0000)
thousands separator).

NEWS
UPGRADING
ext/standard/math.c
ext/standard/php_math.h
ext/standard/tests/math/number_format_multichar.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index c834513b0b68a5eef9658052d9358c12a01ac50a..54f5e4ca673c9df5b2fae457976bc03744a3b890 100644 (file)
--- 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)
index b8aad2f4921265453201d473b7a8cf96431bc2b0..01d5c71ccc8b90ed1cba2196a84c94c5f6d45e5c 100755 (executable)
--- 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 &apos; 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.
index 5c758d28788781fa8c0263d2cd84b49ad5f0522d..78918c45ae5e3a116353b699d6c38f6ef20f8c2d 100644 (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;
index ca059af9fa9f8a36a1868a5c82e14417f036dc06..0b318c2d5678e2b6fd06d15b95fd857f4f97a868 100644 (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);
diff --git a/ext/standard/tests/math/number_format_multichar.phpt b/ext/standard/tests/math/number_format_multichar.phpt
new file mode 100644 (file)
index 0000000..ae36d12
--- /dev/null
@@ -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"