0
0
mirror of https://github.com/ezyang/htmlpurifier.git synced 2024-09-18 18:25:18 +00:00

Improve floating point scaling in UnitConverter.

When precision dictates that a number be zero padded, we cannot give sprintf()
a negative precision specifier.  This commit implements manual negative precision
printing of floats, taking into account common rounding errors with floating
point numbers.

Signed-off-by: Edward Z. Yang <edwardzyang@thewritingpot.com>
This commit is contained in:
Edward Z. Yang 2008-10-24 12:50:59 -04:00
parent 25fa53c15b
commit 3a2fd0b5db
4 changed files with 38 additions and 3 deletions

2
NEWS
View File

@ -66,6 +66,8 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
throw an exception when MaintainLineNumbers is true, but a non-tracksLineNumbers
is being used.
- Detect if domxml extension is loaded, and use DirectLEx accordingly.
- Improve handling of big numbers with floating point arithmetic in UnitConverter.
Reported by David Morton.
. Strategy_MakeWellFormed now operates in-place, saving memory and allowing
for more interesting filter-backtracking
. New HTMLPurifier_Injector->rewind() functionality, allows injectors to rewind

View File

@ -234,6 +234,18 @@ class HTMLPurifier_UnitConverter
* Scales a float to $scale digits right of decimal point, like BCMath.
*/
private function scale($r, $scale) {
if ($scale < 0) {
// The f sprintf type doesn't support negative numbers, so we
// need to cludge things manually. First get the string.
$r = sprintf('%.0f', (float) $r);
// Due to floating point precision loss, $r will more than likely
// look something like 4652999999999.9234. We grab one more digit
// than we need to precise from $r and then use that to round
// appropriately.
$precise = (string) round(substr($r, 0, strlen($r) + $scale), -1);
// Now we return it, truncating the zero that was rounded off.
return substr($precise, 0, -1) . str_repeat('0', -$scale + 1);
}
return sprintf('%.' . $scale . 'f', (float) $r);
}

View File

@ -94,6 +94,10 @@ class HTMLPurifier_UnitConverterTest extends HTMLPurifier_Harness
$this->assertConversion('11.112pt', '0.15433in');
}
function __onlytestRoundingBigNumber() {
$this->assertConversion('444400000000000000000000in', '42660000000000000000000000px');
}
protected function assertSigFig($n, $sigfigs) {
$converter = new HTMLPurifier_UnitConverter();
$result = $converter->getSigFigs($n);

View File

@ -36,9 +36,10 @@ $AC = array(); // parameters
$AC['flush'] = false;
$AC['standalone'] = false;
$AC['file'] = '';
$AC['xml'] = false;
$AC['dry'] = false;
$AC['php'] = $php;
$AC['xml'] = false;
$AC['dry'] = false;
$AC['php'] = $php;
$AC['help'] = false;
$AC['type'] = '';
$AC['disable-phpt'] = false;
@ -46,12 +47,28 @@ $AC['only-phpt'] = false; // alias for --type=phpt
$aliases = array(
'f' => 'file',
'h' => 'help'
);
// It's important that this does not call the autoloader. Not a problem
// with a function, but could be if we put this in a class.
htmlpurifier_parse_args($AC, $aliases);
if ($AC['help']) {
?>HTML Purifier test suite
Allowed options:
--flush
--standalone
--file (-f) HTMLPurifier/NameOfTest.php
--xml
--dry
--php /path/to/php
--type ( htmlpurifier | configdoc | fstools | htmlt | vtest | phpt )
--disable-phpt
<?php
exit;
}
// Disable PHPT tests if they're not enabled
if (!$GLOBALS['HTMLPurifierTest']['PHPT']) {
$AC['disable-phpt'] = true;