From 5a80fb4245e266efd6c8a552f72fdf55e9942a17 Mon Sep 17 00:00:00 2001 From: sc0Vu Date: Mon, 5 Mar 2018 16:29:42 +0800 Subject: [PATCH 1/3] Add negative string support. --- src/Utils.php | 57 +++++++++++++++++++++++++++++++++++------ test/unit/UtilsTest.php | 29 +++++++++++++++++++++ 2 files changed, 78 insertions(+), 8 deletions(-) diff --git a/src/Utils.php b/src/Utils.php index 73536f1..0cbf3d4 100644 --- a/src/Utils.php +++ b/src/Utils.php @@ -62,6 +62,14 @@ class Utils 'tether' => '1000000000000000000000000000000' ]; + /** + * NEGATIVE1 + * Cannot work, see: http://php.net/manual/en/language.constants.syntax.php + * + * @const + */ + // const NEGATIVE1 = new BigNumber(-1); + /** * construct * @@ -126,7 +134,7 @@ class Utils public static function isZeroPrefixed($value) { if (!is_string($value)) { - throw new InvalidArgumentException('The value to zeroPrefixed function must be string.'); + throw new InvalidArgumentException('The value to isZeroPrefixed function must be string.'); } return (strpos($value, '0x') === 0); } @@ -146,6 +154,20 @@ class Utils return $value; } + /** + * isNegative + * + * @param string + * @return bool + */ + public static function isNegative($value) + { + if (!is_string($value)) { + throw new InvalidArgumentException('The value to isNegative function must be string.'); + } + return (strpos($value, '-') === 0); + } + /** * isAddress * @@ -415,25 +437,44 @@ class Utils * Change number or number string to bignumber. * * @param BigNumber|string|int $number - * @return \phpseclib\Math\BigInteger + * @return array|\phpseclib\Math\BigInteger */ public static function toBn($number) { - if (is_numeric($number)) { + if ($number instanceof BigNumber){ + $bn = $number; + } elseif (is_int($number)) { $bn = new BigNumber($number); + } elseif (is_numeric($number)) { + $number = (string) $number; + + if (self::isNegative($number)) { + $count = 1; + $number = str_replace('-', '', $number, $count); + $negative1 = new BigNumber(-1); + } + $bn = new BigNumber($number); + + if (isset($negative1)) { + $bn = $bn->multiply($negative1); + } } elseif (is_string($number)) { $number = mb_strtolower($number); + if (self::isNegative($number)) { + $count = 1; + $number = str_replace('-', '', $number, $count); + $negative1 = new BigNumber(-1); + } if (self::isZeroPrefixed($number) || preg_match('/[a-f]+/', $number) === 1) { $number = self::stripZero($number); $bn = new BigNumber($number, 16); - } else { - $bn = new BigNumber($number); } - } elseif ($number instanceof BigNumber){ - $bn = $number; + if (isset($negative1)) { + $bn = $bn->multiply($negative1); + } } else { - throw new InvalidArgumentException('toBn number must be BigNumber, string or int.'); + throw new InvalidArgumentException('toBn number must be BigNumber, numeric string or int.'); } return $bn; } diff --git a/test/unit/UtilsTest.php b/test/unit/UtilsTest.php index 96e3ddd..7673e5d 100644 --- a/test/unit/UtilsTest.php +++ b/test/unit/UtilsTest.php @@ -448,6 +448,20 @@ class UtilsTest extends TestCase $this->assertFalse($isHex); } + /** + * testIsNegative + * + * @return void + */ + public function testIsNegative() + { + $isNegative = Utils::isNegative('-1'); + $this->assertTrue($isNegative); + + $isNegative = Utils::isNegative('1'); + $this->assertFalse($isNegative); + } + /** * testToBn * @@ -461,12 +475,27 @@ class UtilsTest extends TestCase $bn = Utils::toBn('0x12'); $this->assertEquals($bn->toString(), '18'); + $bn = Utils::toBn('-0x12'); + $this->assertEquals($bn->toString(), '-18'); + $bn = Utils::toBn(0x12); $this->assertEquals($bn->toString(), '18'); $bn = Utils::toBn('ae'); $this->assertEquals($bn->toString(), '174'); + $bn = Utils::toBn('-ae'); + $this->assertEquals($bn->toString(), '-174'); + + $bn = Utils::toBn('-1'); + $this->assertEquals($bn->toString(), '-1'); + + // $bn = Utils::toBn('-0.1'); + // $this->assertEquals($bn->toString(), '-0.1'); + + // $bn = Utils::toBn(-0.1); + // $this->assertEquals($bn->toString(), -0.1); + $bn = Utils::toBn(new BigNumber(1)); $this->assertEquals($bn->toString(), '1'); From d9b2dc3c6fe0c366b9a22b5b36321c0233c82f3a Mon Sep 17 00:00:00 2001 From: sc0Vu Date: Mon, 5 Mar 2018 16:41:55 +0800 Subject: [PATCH 2/3] Add fraction number string support. --- src/Utils.php | 18 +++++++++++++++++- test/unit/UtilsTest.php | 37 +++++++++++++++++++++++++++++++++---- 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/Utils.php b/src/Utils.php index 0cbf3d4..c9b0777 100644 --- a/src/Utils.php +++ b/src/Utils.php @@ -453,7 +453,23 @@ class Utils $number = str_replace('-', '', $number, $count); $negative1 = new BigNumber(-1); } - $bn = new BigNumber($number); + if (strpos($number, '.') > 0) { + $comps = explode('.', $number); + + if (count($comps) > 2) { + throw new InvalidArgumentException('toBn number must be a valid number.'); + } + $whole = $comps[0]; + $fraction = $comps[1]; + + return [ + new BigNumber($whole), + new BigNumber($fraction), + isset($negative1) ? $negative1 : false + ]; + } else { + $bn = new BigNumber($number); + } if (isset($negative1)) { $bn = $bn->multiply($negative1); diff --git a/test/unit/UtilsTest.php b/test/unit/UtilsTest.php index 7673e5d..ae94fae 100644 --- a/test/unit/UtilsTest.php +++ b/test/unit/UtilsTest.php @@ -490,11 +490,40 @@ class UtilsTest extends TestCase $bn = Utils::toBn('-1'); $this->assertEquals($bn->toString(), '-1'); - // $bn = Utils::toBn('-0.1'); - // $this->assertEquals($bn->toString(), '-0.1'); + $bn = Utils::toBn('-0.1'); + $this->assertEquals(count($bn), 3); + $this->assertEquals($bn[0]->toString(), '0'); + $this->assertEquals($bn[1]->toString(), '1'); + $this->assertEquals($bn[2]->toString(), '-1'); - // $bn = Utils::toBn(-0.1); - // $this->assertEquals($bn->toString(), -0.1); + $bn = Utils::toBn(-0.1); + $this->assertEquals(count($bn), 3); + $this->assertEquals($bn[0]->toString(), '0'); + $this->assertEquals($bn[1]->toString(), '1'); + $this->assertEquals($bn[2]->toString(), '-1'); + + $bn = Utils::toBn('0.1'); + $this->assertEquals(count($bn), 3); + $this->assertEquals($bn[0]->toString(), '0'); + $this->assertEquals($bn[1]->toString(), '1'); + $this->assertEquals($bn[2], false); + + $bn = Utils::toBn('-1.69'); + $this->assertEquals(count($bn), 3); + $this->assertEquals($bn[0]->toString(), '1'); + $this->assertEquals($bn[1]->toString(), '69'); + $this->assertEquals($bn[2]->toString(), '-1'); + + $bn = Utils::toBn(-1.69); + $this->assertEquals($bn[0]->toString(), '1'); + $this->assertEquals($bn[1]->toString(), '69'); + $this->assertEquals($bn[2]->toString(), '-1'); + + $bn = Utils::toBn('1.69'); + $this->assertEquals(count($bn), 3); + $this->assertEquals($bn[0]->toString(), '1'); + $this->assertEquals($bn[1]->toString(), '69'); + $this->assertEquals($bn[2], false); $bn = Utils::toBn(new BigNumber(1)); $this->assertEquals($bn->toString(), '1'); From 9aacaffff85449bf4033a10fd2af550b982666db Mon Sep 17 00:00:00 2001 From: sc0Vu Date: Mon, 5 Mar 2018 16:52:03 +0800 Subject: [PATCH 3/3] Return 0 when number is empty string. --- src/Utils.php | 7 +++++-- test/unit/UtilsTest.php | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Utils.php b/src/Utils.php index c9b0777..fbcf188 100644 --- a/src/Utils.php +++ b/src/Utils.php @@ -470,7 +470,6 @@ class Utils } else { $bn = new BigNumber($number); } - if (isset($negative1)) { $bn = $bn->multiply($negative1); } @@ -485,12 +484,16 @@ class Utils if (self::isZeroPrefixed($number) || preg_match('/[a-f]+/', $number) === 1) { $number = self::stripZero($number); $bn = new BigNumber($number, 16); + } elseif (empty($number)) { + $bn = new BigNumber(0); + } else { + throw new InvalidArgumentException('toBn number must be valid hex string.'); } if (isset($negative1)) { $bn = $bn->multiply($negative1); } } else { - throw new InvalidArgumentException('toBn number must be BigNumber, numeric string or int.'); + throw new InvalidArgumentException('toBn number must be BigNumber, string or int.'); } return $bn; } diff --git a/test/unit/UtilsTest.php b/test/unit/UtilsTest.php index ae94fae..a519ab4 100644 --- a/test/unit/UtilsTest.php +++ b/test/unit/UtilsTest.php @@ -469,6 +469,9 @@ class UtilsTest extends TestCase */ public function testToBn() { + $bn = Utils::toBn(''); + $this->assertEquals($bn->toString(), '0'); + $bn = Utils::toBn(11); $this->assertEquals($bn->toString(), '11');