From 525dd550654118282697bb37d0d3195228d4395e Mon Sep 17 00:00:00 2001 From: Kunal Mehta Date: Thu, 29 Oct 2015 15:56:07 -0700 Subject: [PATCH] Add and use wikimedia/base-convert 1.0.1 Change-Id: I3ae56e761ef6fb2b2d506bc2990b97f57183ccf1 --- composer.json | 1 + includes/GlobalFunctions.php | 92 +-------- .../GlobalFunctions/wfBaseConvertTest.php | 195 ------------------ 3 files changed, 2 insertions(+), 286 deletions(-) delete mode 100644 tests/phpunit/includes/GlobalFunctions/wfBaseConvertTest.php diff --git a/composer.json b/composer.json index 4aa9b92c5c..553ec44f6a 100644 --- a/composer.json +++ b/composer.json @@ -26,6 +26,7 @@ "php": ">=5.3.3", "psr/log": "1.0.0", "wikimedia/assert": "0.2.2", + "wikimedia/base-convert": "1.0.1", "wikimedia/cdb": "1.3.0", "wikimedia/cldr-plural-rule-parser": "1.0.0", "wikimedia/composer-merge-plugin": "1.2.1", diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index cda3154253..791bf33667 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -3336,97 +3336,7 @@ function wfRelativePath( $path, $from ) { function wfBaseConvert( $input, $sourceBase, $destBase, $pad = 1, $lowercase = true, $engine = 'auto' ) { - $input = (string)$input; - if ( - $sourceBase < 2 || - $sourceBase > 36 || - $destBase < 2 || - $destBase > 36 || - $sourceBase != (int)$sourceBase || - $destBase != (int)$destBase || - $pad != (int)$pad || - !preg_match( - "/^[" . substr( '0123456789abcdefghijklmnopqrstuvwxyz', 0, $sourceBase ) . "]+$/i", - $input - ) - ) { - return false; - } - - static $baseChars = array( - 10 => 'a', 11 => 'b', 12 => 'c', 13 => 'd', 14 => 'e', 15 => 'f', - 16 => 'g', 17 => 'h', 18 => 'i', 19 => 'j', 20 => 'k', 21 => 'l', - 22 => 'm', 23 => 'n', 24 => 'o', 25 => 'p', 26 => 'q', 27 => 'r', - 28 => 's', 29 => 't', 30 => 'u', 31 => 'v', 32 => 'w', 33 => 'x', - 34 => 'y', 35 => 'z', - - '0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, - '6' => 6, '7' => 7, '8' => 8, '9' => 9, 'a' => 10, 'b' => 11, - 'c' => 12, 'd' => 13, 'e' => 14, 'f' => 15, 'g' => 16, 'h' => 17, - 'i' => 18, 'j' => 19, 'k' => 20, 'l' => 21, 'm' => 22, 'n' => 23, - 'o' => 24, 'p' => 25, 'q' => 26, 'r' => 27, 's' => 28, 't' => 29, - 'u' => 30, 'v' => 31, 'w' => 32, 'x' => 33, 'y' => 34, 'z' => 35 - ); - - if ( extension_loaded( 'gmp' ) && ( $engine == 'auto' || $engine == 'gmp' ) ) { - // Removing leading zeros works around broken base detection code in - // some PHP versions (see and - // ). - $result = gmp_strval( gmp_init( ltrim( $input, '0' ) ?: '0', $sourceBase ), $destBase ); - } elseif ( extension_loaded( 'bcmath' ) && ( $engine == 'auto' || $engine == 'bcmath' ) ) { - $decimal = '0'; - foreach ( str_split( strtolower( $input ) ) as $char ) { - $decimal = bcmul( $decimal, $sourceBase ); - $decimal = bcadd( $decimal, $baseChars[$char] ); - } - - // @codingStandardsIgnoreStart Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed - for ( $result = ''; bccomp( $decimal, 0 ); $decimal = bcdiv( $decimal, $destBase, 0 ) ) { - $result .= $baseChars[bcmod( $decimal, $destBase )]; - } - // @codingStandardsIgnoreEnd - - $result = strrev( $result ); - } else { - $inDigits = array(); - foreach ( str_split( strtolower( $input ) ) as $char ) { - $inDigits[] = $baseChars[$char]; - } - - // Iterate over the input, modulo-ing out an output digit - // at a time until input is gone. - $result = ''; - while ( $inDigits ) { - $work = 0; - $workDigits = array(); - - // Long division... - foreach ( $inDigits as $digit ) { - $work *= $sourceBase; - $work += $digit; - - if ( $workDigits || $work >= $destBase ) { - $workDigits[] = (int)( $work / $destBase ); - } - $work %= $destBase; - } - - // All that division leaves us with a remainder, - // which is conveniently our next output digit. - $result .= $baseChars[$work]; - - // And we continue! - $inDigits = $workDigits; - } - - $result = strrev( $result ); - } - - if ( !$lowercase ) { - $result = strtoupper( $result ); - } - - return str_pad( $result, $pad, '0', STR_PAD_LEFT ); + return Wikimedia\base_convert( $input, $sourceBase, $destBase, $pad, $lowercase, $engine ); } /** diff --git a/tests/phpunit/includes/GlobalFunctions/wfBaseConvertTest.php b/tests/phpunit/includes/GlobalFunctions/wfBaseConvertTest.php deleted file mode 100644 index 9d55e85c81..0000000000 --- a/tests/phpunit/includes/GlobalFunctions/wfBaseConvertTest.php +++ /dev/null @@ -1,195 +0,0 @@ -assertSame( $base2, wfBaseConvert( $base3, '3', '2' ) ); - $this->assertSame( $base2, wfBaseConvert( $base5, '5', '2' ) ); - $this->assertSame( $base2, wfBaseConvert( $base8, '8', '2' ) ); - $this->assertSame( $base2, wfBaseConvert( $base10, '10', '2' ) ); - $this->assertSame( $base2, wfBaseConvert( $base16, '16', '2' ) ); - $this->assertSame( $base2, wfBaseConvert( $base36, '36', '2' ) ); - } - - /** - * @dataProvider provideSingleDigitConversions - */ - public function testDigitToBase3( $base2, $base3, $base5, $base8, $base10, $base16, $base36 ) { - $this->assertSame( $base3, wfBaseConvert( $base2, '2', '3' ) ); - $this->assertSame( $base3, wfBaseConvert( $base5, '5', '3' ) ); - $this->assertSame( $base3, wfBaseConvert( $base8, '8', '3' ) ); - $this->assertSame( $base3, wfBaseConvert( $base10, '10', '3' ) ); - $this->assertSame( $base3, wfBaseConvert( $base16, '16', '3' ) ); - $this->assertSame( $base3, wfBaseConvert( $base36, '36', '3' ) ); - } - - /** - * @dataProvider provideSingleDigitConversions - */ - public function testDigitToBase5( $base2, $base3, $base5, $base8, $base10, $base16, $base36 ) { - $this->assertSame( $base5, wfBaseConvert( $base2, '2', '5' ) ); - $this->assertSame( $base5, wfBaseConvert( $base3, '3', '5' ) ); - $this->assertSame( $base5, wfBaseConvert( $base8, '8', '5' ) ); - $this->assertSame( $base5, wfBaseConvert( $base10, '10', '5' ) ); - $this->assertSame( $base5, wfBaseConvert( $base16, '16', '5' ) ); - $this->assertSame( $base5, wfBaseConvert( $base36, '36', '5' ) ); - } - - /** - * @dataProvider provideSingleDigitConversions - */ - public function testDigitToBase8( $base2, $base3, $base5, $base8, $base10, $base16, $base36 ) { - $this->assertSame( $base8, wfBaseConvert( $base2, '2', '8' ) ); - $this->assertSame( $base8, wfBaseConvert( $base3, '3', '8' ) ); - $this->assertSame( $base8, wfBaseConvert( $base5, '5', '8' ) ); - $this->assertSame( $base8, wfBaseConvert( $base10, '10', '8' ) ); - $this->assertSame( $base8, wfBaseConvert( $base16, '16', '8' ) ); - $this->assertSame( $base8, wfBaseConvert( $base36, '36', '8' ) ); - } - - /** - * @dataProvider provideSingleDigitConversions - */ - public function testDigitToBase10( $base2, $base3, $base5, $base8, $base10, $base16, $base36 ) { - $this->assertSame( $base10, wfBaseConvert( $base2, '2', '10' ) ); - $this->assertSame( $base10, wfBaseConvert( $base3, '3', '10' ) ); - $this->assertSame( $base10, wfBaseConvert( $base5, '5', '10' ) ); - $this->assertSame( $base10, wfBaseConvert( $base8, '8', '10' ) ); - $this->assertSame( $base10, wfBaseConvert( $base16, '16', '10' ) ); - $this->assertSame( $base10, wfBaseConvert( $base36, '36', '10' ) ); - } - - /** - * @dataProvider provideSingleDigitConversions - */ - public function testDigitToBase16( $base2, $base3, $base5, $base8, $base10, $base16, $base36 ) { - $this->assertSame( $base16, wfBaseConvert( $base2, '2', '16' ) ); - $this->assertSame( $base16, wfBaseConvert( $base3, '3', '16' ) ); - $this->assertSame( $base16, wfBaseConvert( $base5, '5', '16' ) ); - $this->assertSame( $base16, wfBaseConvert( $base8, '8', '16' ) ); - $this->assertSame( $base16, wfBaseConvert( $base10, '10', '16' ) ); - $this->assertSame( $base16, wfBaseConvert( $base36, '36', '16' ) ); - } - - /** - * @dataProvider provideSingleDigitConversions - */ - public function testDigitToBase36( $base2, $base3, $base5, $base8, $base10, $base16, $base36 ) { - $this->assertSame( $base36, wfBaseConvert( $base2, '2', '36' ) ); - $this->assertSame( $base36, wfBaseConvert( $base3, '3', '36' ) ); - $this->assertSame( $base36, wfBaseConvert( $base5, '5', '36' ) ); - $this->assertSame( $base36, wfBaseConvert( $base8, '8', '36' ) ); - $this->assertSame( $base36, wfBaseConvert( $base10, '10', '36' ) ); - $this->assertSame( $base36, wfBaseConvert( $base16, '16', '36' ) ); - } - - public function testLargeNumber() { - $this->assertSame( '1100110001111010000000101110100', wfBaseConvert( 'sd89ys', 36, 2 ) ); - $this->assertSame( '11102112120221201101', wfBaseConvert( 'sd89ys', 36, 3 ) ); - $this->assertSame( '12003102232400', wfBaseConvert( 'sd89ys', 36, 5 ) ); - $this->assertSame( '14617200564', wfBaseConvert( 'sd89ys', 36, 8 ) ); - $this->assertSame( '1715274100', wfBaseConvert( 'sd89ys', 36, 10 ) ); - $this->assertSame( '663d0174', wfBaseConvert( 'sd89ys', 36, 16 ) ); - } - - public static function provideNumbers() { - $x = array(); - $chars = '0123456789abcdefghijklmnopqrstuvwxyz'; - for ( $i = 0; $i < 50; $i++ ) { - $base = mt_rand( 2, 36 ); - $len = mt_rand( 10, 100 ); - - $str = ''; - for ( $j = 0; $j < $len; $j++ ) { - $str .= $chars[mt_rand( 0, $base - 1 )]; - } - - $x[] = array( $base, $str ); - } - - return $x; - } - - /** - * @dataProvider provideNumbers - */ - public function testIdentity( $base, $number ) { - $this->assertSame( $number, wfBaseConvert( $number, $base, $base, strlen( $number ) ) ); - } - - public function testInvalid() { - $this->assertFalse( wfBaseConvert( '101', 1, 15 ) ); - $this->assertFalse( wfBaseConvert( '101', 15, 1 ) ); - $this->assertFalse( wfBaseConvert( '101', 37, 15 ) ); - $this->assertFalse( wfBaseConvert( '101', 15, 37 ) ); - $this->assertFalse( wfBaseConvert( 'abcde', 10, 11 ) ); - $this->assertFalse( wfBaseConvert( '12930', 2, 10 ) ); - $this->assertFalse( wfBaseConvert( '101', 'abc', 15 ) ); - $this->assertFalse( wfBaseConvert( '101', 15, 'abc' ) ); - } - - public function testPadding() { - $number = "10101010101"; - $this->assertSame( - strlen( $number ) + 5, - strlen( wfBaseConvert( $number, 2, 2, strlen( $number ) + 5 ) ) - ); - $this->assertSame( - strlen( $number ), - strlen( wfBaseConvert( $number, 2, 2, strlen( $number ) - 5 ) ) - ); - } - - public function testLeadingZero() { - $this->assertSame( '24', wfBaseConvert( '010', 36, 16 ) ); - $this->assertSame( '37d4', wfBaseConvert( '0b10', 36, 16 ) ); - $this->assertSame( 'a734', wfBaseConvert( '0x10', 36, 16 ) ); - } -} -- 2.20.1