[Locale] StubNumberFormatter allow to parse 64bit number in 64bit mode

This commit is contained in:
stealth35 2011-12-11 17:45:39 +01:00
parent 83894be6c8
commit 3759ff0777
3 changed files with 130 additions and 39 deletions

View File

@ -203,11 +203,20 @@ class StubNumberFormatter
* The maximum values of the integer type in 32 bit platforms.
* @var array
*/
static private $intRange = array(
static private $int32Range = array(
'positive' => 2147483647,
'negative' => -2147483648
);
/**
* The maximum values of the integer type in 64 bit platforms.
* @var array
*/
static private $int64Range = array(
'positive' => 9223372036854775807,
'negative' => -9223372036854775808
);
/**
* @var string
*/
@ -450,7 +459,6 @@ class StubNumberFormatter
* @param int $position Offset to begin the parsing on return this value will hold the offset at which the parsing ended
* @return Boolean|string The parsed value of false on error
* @see http://www.php.net/manual/en/numberformatter.parse.php
* @throws MethodArgumentValueNotImplementedException When $type equals to TYPE_INT64, behavior not implemented
* @throws MethodArgumentNotImplementedException When $position different than null, behavior not implemented
*/
public function parse($value, $type = self::TYPE_DOUBLE, &$position = null)
@ -461,11 +469,6 @@ class StubNumberFormatter
return false;
}
// Not implemented, the NumberFormatter behavior is inconsistency
if ($type == self::TYPE_INT64) {
throw new MethodArgumentValueNotImplementedException(__METHOD__, 'type', $type);
}
// We don't calculate the position when parsing the value
if (null !== $position) {
throw new MethodArgumentNotImplementedException(__METHOD__, 'position');
@ -719,9 +722,10 @@ class StubNumberFormatter
{
if ($type == self::TYPE_DOUBLE) {
$value = (float) $value;
}
elseif ($type == self::TYPE_INT32) {
$value = $this->getIntValue($value);
} elseif ($type == self::TYPE_INT32) {
$value = $this->getInt32Value($value);
} elseif ($type == self::TYPE_INT64) {
$value = $this->getInt64Value($value);
}
return $value;
@ -733,15 +737,38 @@ class StubNumberFormatter
* @param mixed $value The value to be converted
* @return int The converted value
*/
private function getIntValue($value)
private function getInt32Value($value)
{
if ($value > self::$intRange['positive'] || $value < self::$intRange['negative']) {
if ($value > self::$int32Range['positive'] || $value < self::$int32Range['negative']) {
return false;
}
return (int) $value;
}
/**
* Convert the value data type to int or returns false if the value is out of the integer value range.
*
* @param mixed $value The value to be converted
* @return int|float The converted value
*/
private function getInt64Value($value)
{
if ($value > self::$int64Range['positive'] || $value < self::$int64Range['negative']) {
return false;
}
if (PHP_INT_SIZE !== 8 && ($value > self::$int32Range['positive'] || $value <= self::$int32Range['negative'])) {
return (float) $value;
}
if (PHP_INT_SIZE === 8 && ($value > self::$int32Range['positive'] || $value < self::$int32Range['negative'])) {
$value = (-2147483648 - ($value % -2147483648)) * ($value / abs($value));
}
return (int) $value;
}
/**
* Check if the rounding mode is invalid.
*

View File

@ -752,28 +752,84 @@ class StubNumberFormatterTest extends LocaleTestCase
);
}
/**
* There are a lot of hard behaviors with TYPE_INT64, see the intl tests
*
* @expectedException Symfony\Component\Locale\Exception\MethodArgumentValueNotImplementedException
* @see testParseTypeInt64IntlWith32BitIntegerInPhp32Bit
* @see testParseTypeInt64IntlWith32BitIntegerInPhp64Bit
* @see testParseTypeInt64IntlWith64BitIntegerInPhp32Bit
* @see testParseTypeInt64IntlWith64BitIntegerInPhp64Bit
*/
public function testParseTypeInt64Stub()
// Stub Tests
public function testParseTypeInt64StubWith32BitIntegerInPhp32Bit()
{
$this->skipIfIntlExtensionIsNotLoaded();
$this->skipIfNot32Bit();
$formatter = $this->getStubFormatterWithDecimalStyle();
$formatter->parse('1', StubNumberFormatter::TYPE_INT64);
$parsedValue = $formatter->parse('2,147,483,647', \NumberFormatter::TYPE_INT64);
$this->assertInternalType('integer', $parsedValue);
$this->assertEquals(2147483647, $parsedValue);
// Look that the parsing of '-2,147,483,648' results in a float like the literal -2147483648
$parsedValue = $formatter->parse('-2,147,483,648', \NumberFormatter::TYPE_INT64);
$this->assertInternalType('float', $parsedValue);
$this->assertEquals(((float) -2147483647 - 1), $parsedValue);
}
public function testParseTypeInt64StubWith32BitIntegerInPhp64Bit()
{
$this->skipIfNot64Bit();
$formatter = $this->getStubFormatterWithDecimalStyle();
$parsedValue = $formatter->parse('2,147,483,647', \NumberFormatter::TYPE_INT64);
$this->assertInternalType('integer', $parsedValue);
$this->assertEquals(2147483647, $parsedValue);
$parsedValue = $formatter->parse('-2,147,483,648', \NumberFormatter::TYPE_INT64);
$this->assertInternalType('integer', $parsedValue);
$this->assertEquals(-2147483647 - 1, $parsedValue);
}
/**
* If PHP is compiled in 32bit mode, the returned value for a 64bit integer are float numbers.
*/
public function testParseTypeInt64StubWith64BitIntegerInPhp32Bit()
{
$this->skipIfNot32Bit();
$formatter = $this->getStubFormatterWithDecimalStyle();
// int 64 using only 32 bit range strangeness
$parsedValue = $formatter->parse('2,147,483,648', \NumberFormatter::TYPE_INT64);
$this->assertInternalType('float', $parsedValue);
$this->assertEquals(2147483648, $parsedValue, '->parse() TYPE_INT64 does not use true 64 bit integers, using only the 32 bit range.');
$parsedValue = $formatter->parse('-2,147,483,649', \NumberFormatter::TYPE_INT64);
$this->assertInternalType('float', $parsedValue);
$this->assertEquals(-2147483649, $parsedValue, '->parse() TYPE_INT64 does not use true 64 bit integers, using only the 32 bit range.');
}
/**
* If PHP is compiled in 64bit mode, the returned value for a 64bit integer are 32bit integer numbers.
*/
public function testParseTypeInt64StubWith64BitIntegerInPhp64Bit()
{
$this->skipIfNot64Bit();
$formatter = $this->getStubFormatterWithDecimalStyle();
$parsedValue = $formatter->parse('2,147,483,648', \NumberFormatter::TYPE_INT64);
$this->assertInternalType('integer', $parsedValue);
$this->assertEquals(-2147483647 - 1, $parsedValue, '->parse() TYPE_INT64 does not use true 64 bit integers, using only the 32 bit range.');
$parsedValue = $formatter->parse('-2,147,483,649', \NumberFormatter::TYPE_INT64);
$this->assertInternalType('integer', $parsedValue);
$this->assertEquals(2147483647, $parsedValue, '->parse() TYPE_INT64 does not use true 64 bit integers, using only the 32 bit range.');
}
// Intl Tests
public function testParseTypeInt64IntlWith32BitIntegerInPhp32Bit()
{
$this->skipIfIntlExtensionIsNotLoaded();
if (!$this->is32Bit()) {
// the PHP must be compiled in 32 bit mode to run this test (64 bits test will be run instead).
return;
}
$this->skipIfNot32Bit();
$formatter = $this->getIntlFormatterWithDecimalStyle();
$parsedValue = $formatter->parse('2,147,483,647', \NumberFormatter::TYPE_INT64);
@ -789,10 +845,8 @@ class StubNumberFormatterTest extends LocaleTestCase
public function testParseTypeInt64IntlWith32BitIntegerInPhp64Bit()
{
$this->skipIfIntlExtensionIsNotLoaded();
if (!$this->is64Bit()) {
// the PHP must be compiled in 64 bit mode to run this test (32 bits test will be run instead).
return;
}
$this->skipIfNot64Bit();
$formatter = $this->getIntlFormatterWithDecimalStyle();
$parsedValue = $formatter->parse('2,147,483,647', \NumberFormatter::TYPE_INT64);
@ -810,10 +864,8 @@ class StubNumberFormatterTest extends LocaleTestCase
public function testParseTypeInt64IntlWith64BitIntegerInPhp32Bit()
{
$this->skipIfIntlExtensionIsNotLoaded();
if (!$this->is32Bit()) {
// the PHP must be compiled in 32 bit mode to run this test (64 bits test will be run instead).
return;
}
$this->skipIfNot32Bit();
$formatter = $this->getIntlFormatterWithDecimalStyle();
// int 64 using only 32 bit range strangeness
@ -832,10 +884,8 @@ class StubNumberFormatterTest extends LocaleTestCase
public function testParseTypeInt64IntlWith64BitIntegerInPhp64Bit()
{
$this->skipIfIntlExtensionIsNotLoaded();
if (!$this->is64Bit()) {
// the PHP must be compiled in 64 bit mode to run this test (32 bits test will be run instead).
return;
}
$this->skipIfNot64Bit();
$formatter = $this->getIntlFormatterWithDecimalStyle();
$parsedValue = $formatter->parse('2,147,483,648', \NumberFormatter::TYPE_INT64);

View File

@ -44,6 +44,20 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
}
}
protected function skipIfNot32Bit()
{
if (!$this->is32Bit()) {
$this->markTestSkipped('PHP must be compiled in 32 bit mode to run this test');
}
}
protected function skipIfNot64Bit()
{
if (!$this->is64Bit()) {
$this->markTestSkipped('PHP must be compiled in 64 bit mode to run this test');
}
}
protected function isGreaterOrEqualThanIcuVersion($version)
{
$version = $this->normalizeIcuVersion($version);