diff --git a/README.md b/README.md index 63e85d7..d17ce46 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Included here is a partial suite of WHATWG-compatible seekable string decoders w * UTF-8 * gb18030 * GBK -* and all single-byte encodings +* all single-byte encodings Where applicable, code point encoders are also included. In time it will be extended to cover the entire suite of WHATWG character encodings, and may also provide other character-centric internationalization functionality. diff --git a/composer.json b/composer.json index f70aded..0896247 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "mensbeam/intl", "type": "library", "description": "A set of dependency-free basic internationalization tools", - "keywords": ["internationalization", "intl", "encoding", "unicode", "charset", "utf-8", "utf8"], + "keywords": ["whatwg", "internationalization", "intl", "encoding", "unicode", "charset", "utf-8", "utf8"], "license": "MIT", "authors": [ { @@ -27,5 +27,10 @@ "psr-4": { "MensBeam\\Intl\\": "lib/" } + }, + "autoload-dev": { + "psr-4": { + "MensBeam\\Intl\\Test\\": "tests/lib/" + } } } diff --git a/tests/cases/Encoding/TestGB18030.php b/tests/cases/Encoding/TestGB18030.php index 9660090..5b0a376 100644 --- a/tests/cases/Encoding/TestGB18030.php +++ b/tests/cases/Encoding/TestGB18030.php @@ -1,6 +1,6 @@ testedClass = GB18030::class; + } /** * @dataProvider provideCodePoints @@ -34,13 +40,9 @@ class TestGB18030 extends \PHPUnit\Framework\TestCase { * @covers MensBeam\Intl\Encoding\GBK::encode * @covers MensBeam\Intl\Encoding\GBK::err */ - public function testEncodeCodePoints(string $class, bool $fatal, int $input, $exp) { - if ($exp instanceof \Throwable) { - $this->expectException(get_class($exp)); - $this->expectExceptionCode($exp->getCode()); - } - $out = $class::encode($input, $fatal); - $this->assertSame(strtolower($exp), bin2hex($out)); + public function testEncodeCodePoints(bool $fatal, $input, $exp, $class = self::class) { + $this->testedClass = $class; + return parent::testEncodeCodePoints($fatal, $input, $exp); } /** @@ -49,17 +51,7 @@ class TestGB18030 extends \PHPUnit\Framework\TestCase { * @covers MensBeam\Intl\Encoding\GB18030::nextCode */ public function testDecodeMultipleCharactersAsCodePoints(string $input, array $exp) { - $input = $this->prepString($input); - $s = new GB18030($input); - $out = []; - $a = 0; - $this->assertSame($a, $s->posChar()); - while (($p = $s->nextCode()) !== false) { - $this->assertSame(++$a, $s->posChar()); - $out[] = $p; - } - $this->assertSame($exp, $out); - $this->assertSame($s->posByte(), strlen($input)); + return parent::testDecodeMultipleCharactersAsCodePoints($input, $exp); } /** @@ -68,17 +60,7 @@ class TestGB18030 extends \PHPUnit\Framework\TestCase { * @covers MensBeam\Intl\Encoding\GB18030::nextChar */ public function testDecodeMultipleCharactersAsStrings(string $input, array $exp) { - $exp = array_map(function($v) { - return \IntlChar::chr($v); - }, $exp); - $input = $this->prepString($input); - $s = new GB18030($input); - $out = []; - while (($p = $s->nextChar()) !== "") { - $out[] = $p; - } - $this->assertSame($exp, $out); - $this->assertSame($s->posByte(), strlen($input)); + return parent::testDecodeMultipleCharactersAsStrings($input, $exp); } /** @@ -86,17 +68,7 @@ class TestGB18030 extends \PHPUnit\Framework\TestCase { * @covers MensBeam\Intl\Encoding\GB18030::seekBack */ public function testSTepBackThroughAString(string $input, array $exp) { - $input = $this->prepString($input); - $s = new GB18030($input); - $exp = array_reverse($exp); - $act = []; - while ($s->nextCode() !== false); - while($s->posByte()) { - $s->seek(-1); - $act[] = $s->nextCode(); - $s->seek(-1); - } - $this->assertEquals($exp, $act); + return parent::testSTepBackThroughAString($input, $exp); } /** @@ -106,51 +78,7 @@ class TestGB18030 extends \PHPUnit\Framework\TestCase { * @covers MensBeam\Intl\Encoding\GB18030::rewind */ public function testSeekThroughAString() { - $input = $this->prepString($this->seekString); - $off = $this->seekOffsets; - $s = new GB18030($input); - $this->assertSame(0, $s->posChar()); - $this->assertSame(0, $s->posByte()); - - $this->assertSame(0, $s->seek(0)); - $this->assertSame(0, $s->posChar()); - $this->assertSame(0, $s->posByte()); - - $this->assertSame(1, $s->seek(-1)); - $this->assertSame(0, $s->posChar()); - $this->assertSame(0, $s->posByte()); - - $this->assertSame(0, $s->seek(1)); - $this->assertSame(1, $s->posChar()); - $this->assertSame($off[1], $s->posByte()); - - $this->assertSame(0, $s->seek(2)); - $this->assertSame(3, $s->posChar()); - $this->assertSame($off[3], $s->posByte()); - - $this->assertSame(0, $s->seek(4)); - $this->assertSame(7, $s->posChar()); - $this->assertSame($off[7], $s->posByte()); - - $this->assertSame(1, $s->seek(1)); - $this->assertSame(7, $s->posChar()); - $this->assertSame($off[7], $s->posByte()); - - $this->assertSame(0, $s->seek(-3)); - $this->assertSame(4, $s->posChar()); - $this->assertSame($off[4], $s->posByte()); - - $this->assertSame(6, $s->seek(-10)); - $this->assertSame(0, $s->posChar()); - $this->assertSame(0, $s->posByte()); - - $this->assertSame(0, $s->seek(5)); - $this->assertSame(5, $s->posChar()); - $this->assertSame($off[5], $s->posByte()); - - $s->rewind(0); - $this->assertSame(0, $s->posChar()); - $this->assertSame(0, $s->posByte()); + return parent::testSeekThroughAString(); } /** @@ -158,29 +86,7 @@ class TestGB18030 extends \PHPUnit\Framework\TestCase { * @covers MensBeam\Intl\Encoding\GB18030::posByte */ public function testTraversePastTheEndOfAString() { - $s = new GB18030("a"); - $this->assertSame(0, $s->posChar()); - $this->assertSame(0, $s->posByte()); - - $this->assertSame("a", $s->nextChar()); - $this->assertSame(1, $s->posChar()); - $this->assertSame(1, $s->posByte()); - - $this->assertSame("", $s->nextChar()); - $this->assertSame(1, $s->posChar()); - $this->assertSame(1, $s->posByte()); - - $s = new GB18030("a"); - $this->assertSame(0, $s->posChar()); - $this->assertSame(0, $s->posByte()); - - $this->assertSame(ord("a"), $s->nextCode()); - $this->assertSame(1, $s->posChar()); - $this->assertSame(1, $s->posByte()); - - $this->assertSame(false, $s->nextCode()); - $this->assertSame(1, $s->posChar()); - $this->assertSame(1, $s->posByte()); + return parent::testTraversePastTheEndOfAString(); } /** @@ -189,32 +95,7 @@ class TestGB18030 extends \PHPUnit\Framework\TestCase { * @covers MensBeam\Intl\Encoding\GB18030::stateApply */ public function testPeekAtCharacters() { - $input = $this->prepString($this->seekString); - $off = $this->seekOffsets; - $s = new GB18030($input); - $s->seek(2); - $this->assertSame(2, $s->posChar()); - $this->assertSame($off[2], $s->posByte()); - - $this->assertSame(bin2hex("\u{6C34}"), bin2hex($s->peekChar())); - $this->assertSame(2, $s->posChar()); - $this->assertSame($off[2], $s->posByte()); - - $this->assertSame(bin2hex("\u{6C34}\u{1D11E}"), bin2hex($s->peekChar(2))); - $this->assertSame(2, $s->posChar()); - $this->assertSame($off[2], $s->posByte()); - - $s->seek(3); - $this->assertSame(5, $s->posChar()); - $this->assertSame($off[5], $s->posByte()); - - $this->assertSame(bin2hex("\u{10FFFD}\u{FFFE}"), bin2hex($s->peekChar(3))); - $this->assertSame(5, $s->posChar()); - $this->assertSame($off[5], $s->posByte()); - - $this->assertSame("", $s->peekChar(-5)); - $this->assertSame(5, $s->posChar()); - $this->assertSame($off[5], $s->posByte()); + return parent::testPeekAtCharacters(); } /** @@ -223,32 +104,7 @@ class TestGB18030 extends \PHPUnit\Framework\TestCase { * @covers MensBeam\Intl\Encoding\GB18030::stateApply */ public function testPeekAtCodePoints() { - $input = $this->prepString($this->seekString); - $off = $this->seekOffsets; - $s = new GB18030($input); - $s->seek(2); - $this->assertSame(2, $s->posChar()); - $this->assertSame($off[2], $s->posByte()); - - $this->assertSame([0x6C34], $s->peekCode()); - $this->assertSame(2, $s->posChar()); - $this->assertSame($off[2], $s->posByte()); - - $this->assertSame([0x6C34, 0x1D11E], $s->peekCode(2)); - $this->assertSame(2, $s->posChar()); - $this->assertSame($off[2], $s->posByte()); - - $s->seek(3); - $this->assertSame(5, $s->posChar()); - $this->assertSame($off[5], $s->posByte()); - - $this->assertSame([0x10FFFD, 0xFFFE], $s->peekCode(3)); - $this->assertSame(5, $s->posChar()); - $this->assertSame($off[5], $s->posByte()); - - $this->assertSame([], $s->peekCode(-5)); - $this->assertSame(5, $s->posChar()); - $this->assertSame($off[5], $s->posByte()); + return parent::testPeekAtCodePoints(); } /** @@ -258,57 +114,14 @@ class TestGB18030 extends \PHPUnit\Framework\TestCase { * @covers MensBeam\Intl\Encoding\GB18030::stateApply */ public function testGetStringLength(string $input, array $points) { - $input = $this->prepString($input); - $s = new GB18030($input); - $s->seek(1); - $posChar = $s->posChar(); - $posByte = $s->posByte(); - - $this->assertSame(sizeof($points), $s->len()); - $this->assertSame($posChar, $s->posChar()); - $this->assertSame($posByte, $s->posByte()); + return parent::testGetStringLength($input, $points); } /** * @covers MensBeam\Intl\Encoding\GB18030::err */ public function testReplacementModes() { - $input = $this->prepString($this->brokenString); - // officially test replacement characters (already effectively tested by other tests) - $s = new GB18030($input, false); - $s->seek(1); - $this->assertSame(0xFFFD, $s->nextCode()); - $s->seek(-2); - // test fatal mode - $s = new GB18030($input, true); - $s->seek(1); - try { - $p = $s->nextCode(); - } catch (DecoderException $e) { - $p = $e; - } finally { - $this->assertInstanceOf(DecoderException::class, $p); - } - $this->assertSame(2, $s->posChar()); - $this->assertSame(0x30, $s->nextCode()); - $s->seek(-2); - $this->assertSame(1, $s->posChar()); - try { - $p = $s->peekCode(); - } catch (DecoderException $e) { - $p = $e; - } finally { - $this->assertInstanceOf(DecoderException::class, $p); - } - $this->assertSame(1, $s->posChar()); - try { - $p = $s->peekChar(); - } catch (DecoderException $e) { - $p = $e; - } finally { - $this->assertInstanceOf(DecoderException::class, $p); - } - $this->assertSame(1, $s->posChar()); + return parent::testReplacementModes(); } /** @@ -318,54 +131,15 @@ class TestGB18030 extends \PHPUnit\Framework\TestCase { * @covers MensBeam\Intl\Encoding\GB18030::codes */ public function testIterateThroughAString(string $input, array $exp) { - $input = $this->prepString($input); - $s = new GB18030($input); - $out = []; - $a = 0; - $this->assertTrue(true); // prevent risky test of empty string - foreach ($s->codes() as $index => $p) { - $this->assertSame($a, $index, "Character key at index $a reported incorrectly"); - $this->assertSame($exp[$a], $p, "Character at index $a decoded incorrectly"); - $a++; - } - $a = 0; - foreach ($s->codes() as $p) { - $a++; - } - $this->assertSame(0, $a); - $s->rewind(); - foreach ($s->codes() as $p) { - $a++; - } - $this->assertSame(sizeof($exp), $a); - - $exp = array_map(function($v) { - return \IntlChar::chr($v); - }, $exp); - - foreach ($s->chars() as $index => $p) { - $this->assertSame($a, $index, "Character key at index $a reported incorrectly"); - $this->assertSame(bin2hex($exp[$a]), bin2hex($p), "Character at index $a decoded incorrectly"); - $a++; - } - $a = 0; - foreach ($s->chars() as $p) { - $a++; - } - $this->assertSame(0, $a); - $s->rewind(); - foreach ($s->chars() as $p) { - $a++; - } - $this->assertSame(sizeof($exp), $a); + return parent::testIterateThroughAString($input, $exp); } public function provideCodePoints() { // bytes confirmed using Firefox - return [ + $series = [ "GBK ASCII (fatal)" => [GBK::class, true, 0x64, "64"], "GBK 0x20AC (fatal)" => [GBK::class, true, 0x20AC, "80"], - "GBK 0x2164 (fatal)" => [GBK::class, true, 0x2164, "A2F5"], + "GBK 0x2164 (fatal)" => [GBK::class, true, 0x2164, "A2 F5"], "GBK 0x3A74 (fatal)" => [GBK::class, true, 0x3A74, new EncoderException("", GBK::E_UNAVAILABLE_CODE_POINT)], "GBK 0xE7C7 (fatal)" => [GBK::class, true, 0xE7C7, new EncoderException("", GBK::E_UNAVAILABLE_CODE_POINT)], "GBK 0x1D11E (fatal)" => [GBK::class, true, 0x1D11E, new EncoderException("", GBK::E_UNAVAILABLE_CODE_POINT)], @@ -373,17 +147,17 @@ class TestGB18030 extends \PHPUnit\Framework\TestCase { "GBK -1 (fatal)" => [GBK::class, true, -1, new EncoderException("", GBK::E_INVALID_CODE_POINT)], "GBK 0x110000 (fatal)" => [GBK::class, true, 0x110000, new EncoderException("", GBK::E_INVALID_CODE_POINT)], "GB18030 ASCII (fatal)" => [GB18030::class, true, 0x64, "64"], - "GB18030 0x20AC (fatal)" => [GB18030::class, true, 0x20AC, "A2E3"], - "GB18030 0x2164 (fatal)" => [GB18030::class, true, 0x2164, "A2F5"], - "GB18030 0x3A74 (fatal)" => [GB18030::class, true, 0x3A74, "82319730"], - "GB18030 0xE7C7 (fatal)" => [GB18030::class, true, 0xE7C7, "8135F437"], - "GB18030 0x1D11E (fatal)" => [GB18030::class, true, 0x1D11E, "9432BE34"], + "GB18030 0x20AC (fatal)" => [GB18030::class, true, 0x20AC, "A2 E3"], + "GB18030 0x2164 (fatal)" => [GB18030::class, true, 0x2164, "A2 F5"], + "GB18030 0x3A74 (fatal)" => [GB18030::class, true, 0x3A74, "82 31 97 30"], + "GB18030 0xE7C7 (fatal)" => [GB18030::class, true, 0xE7C7, "81 35 F4 37"], + "GB18030 0x1D11E (fatal)" => [GB18030::class, true, 0x1D11E, "94 32 BE 34"], "GB18030 0xE5E5 (fatal)" => [GB18030::class, true, 0xE5E5, new EncoderException("", GB18030::E_UNAVAILABLE_CODE_POINT)], "GB18030 -1 (fatal)" => [GB18030::class, true, -1, new EncoderException("", GB18030::E_INVALID_CODE_POINT)], "GB18030 0x110000 (fatal)" => [GB18030::class, true, 0x110000, new EncoderException("", GB18030::E_INVALID_CODE_POINT)], "GBK ASCII (HTML)" => [GBK::class, false, 0x64, "64"], "GBK 0x20AC (HTML)" => [GBK::class, false, 0x20AC, "80"], - "GBK 0x2164 (HTML)" => [GBK::class, false, 0x2164, "A2F5"], + "GBK 0x2164 (HTML)" => [GBK::class, false, 0x2164, "A2 F5"], "GBK 0x3A74 (HTML)" => [GBK::class, false, 0x3A74, bin2hex("&#".(0x3A74).";")], "GBK 0xE7C7 (HTML)" => [GBK::class, false, 0xE7C7, bin2hex("&#".(0xE7C7).";")], "GBK 0x1D11E (HTML)" => [GBK::class, false, 0x1D11E, bin2hex("&#".(0x1D11E).";")], @@ -391,15 +165,20 @@ class TestGB18030 extends \PHPUnit\Framework\TestCase { "GBK -1 (HTML)" => [GBK::class, false, -1, new EncoderException("", GBK::E_INVALID_CODE_POINT)], "GBK 0x110000 (HTML)" => [GBK::class, false, 0x110000, new EncoderException("", GBK::E_INVALID_CODE_POINT)], "GB18030 ASCII (HTML)" => [GB18030::class, false, 0x64, "64"], - "GB18030 0x20AC (HTML)" => [GB18030::class, false, 0x20AC, "A2E3"], - "GB18030 0x2164 (HTML)" => [GB18030::class, false, 0x2164, "A2F5"], - "GB18030 0x3A74 (HTML)" => [GB18030::class, false, 0x3A74, "82319730"], - "GB18030 0xE7C7 (HTML)" => [GB18030::class, false, 0xE7C7, "8135F437"], - "GB18030 0x1D11E (HTML)" => [GB18030::class, false, 0x1D11E, "9432BE34"], + "GB18030 0x20AC (HTML)" => [GB18030::class, false, 0x20AC, "A2 E3"], + "GB18030 0x2164 (HTML)" => [GB18030::class, false, 0x2164, "A2 F5"], + "GB18030 0x3A74 (HTML)" => [GB18030::class, false, 0x3A74, "82 31 97 30"], + "GB18030 0xE7C7 (HTML)" => [GB18030::class, false, 0xE7C7, "81 35 F4 37"], + "GB18030 0x1D11E (HTML)" => [GB18030::class, false, 0x1D11E, "94 32 BE 34"], "GB18030 0xE5E5 (HTML)" => [GB18030::class, false, 0xE5E5, bin2hex("&#".(0xE5E5).";")], "GB18030 -1 (HTML)" => [GB18030::class, false, -1, new EncoderException("", GB18030::E_INVALID_CODE_POINT)], "GB18030 0x110000 (HTML)" => [GB18030::class, false, 0x110000, new EncoderException("", GB18030::E_INVALID_CODE_POINT)], ]; + foreach ($series as $name => $test) { + $class = array_shift($test); + array_push($test, $class); + yield $name => $test; + } } public function provideStrings() { @@ -478,8 +257,4 @@ class TestGB18030 extends \PHPUnit\Framework\TestCase { } } } - - protected function prepString(string $str): string { - return hex2bin(str_replace(" ", "", $str)); - } } diff --git a/tests/cases/Encoding/TestSingleByte.php b/tests/cases/Encoding/TestSingleByte.php index 824e874..ec4d9bb 100644 --- a/tests/cases/Encoding/TestSingleByte.php +++ b/tests/cases/Encoding/TestSingleByte.php @@ -1,6 +1,6 @@ [1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,9617,9618,9619,9474,9508,9569,9570,9558,9557,9571,9553,9559,9565,9564,9563,9488,9492,9524,9516,9500,9472,9532,9566,9567,9562,9556,9577,9574,9568,9552,9580,9575,9576,9572,9573,9561,9560,9554,9555,9579,9578,9496,9484,9608,9604,9612,9616,9600,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1025,1105,1028,1108,1031,1111,1038,1118,176,8729,183,8730,8470,164,9632,160], - "ISO-8859-2" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,728,321,164,317,346,167,168,352,350,356,377,173,381,379,176,261,731,322,180,318,347,711,184,353,351,357,378,733,382,380,340,193,194,258,196,313,262,199,268,201,280,203,282,205,206,270,272,323,327,211,212,336,214,215,344,366,218,368,220,221,354,223,341,225,226,259,228,314,263,231,269,233,281,235,283,237,238,271,273,324,328,243,244,337,246,247,345,367,250,369,252,253,355,729], - "ISO-8859-3" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,294,728,163,164,null,292,167,168,304,350,286,308,173,null,379,176,295,178,179,180,181,293,183,184,305,351,287,309,189,null,380,192,193,194,null,196,266,264,199,200,201,202,203,204,205,206,207,null,209,210,211,212,288,214,215,284,217,218,219,220,364,348,223,224,225,226,null,228,267,265,231,232,233,234,235,236,237,238,239,null,241,242,243,244,289,246,247,285,249,250,251,252,365,349,729], - "ISO-8859-4" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,312,342,164,296,315,167,168,352,274,290,358,173,381,175,176,261,731,343,180,297,316,711,184,353,275,291,359,330,382,331,256,193,194,195,196,197,198,302,268,201,280,203,278,205,206,298,272,325,332,310,212,213,214,215,216,370,218,219,220,360,362,223,257,225,226,227,228,229,230,303,269,233,281,235,279,237,238,299,273,326,333,311,244,245,246,247,248,371,250,251,252,361,363,729], - "ISO-8859-5" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,173,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,8470,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,167,1118,1119], - "ISO-8859-6" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,null,null,null,164,null,null,null,null,null,null,null,1548,173,null,null,null,null,null,null,null,null,null,null,null,null,null,1563,null,null,null,1567,null,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,null,null,null,null,null,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,null,null,null,null,null,null,null,null,null,null,null,null,null], - "ISO-8859-7" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,8216,8217,163,8364,8367,166,167,168,169,890,171,172,173,null,8213,176,177,178,179,900,901,902,183,904,905,906,187,908,189,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,null,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,null], - "ISO-8859-8" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,null,162,163,164,165,166,167,168,169,215,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,247,187,188,189,190,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,8215,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,null,null,8206,8207,null], - "ISO-8859-8-I" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,null,162,163,164,165,166,167,168,169,215,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,247,187,188,189,190,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,8215,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,null,null,8206,8207,null], - "ISO-8859-10" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,274,290,298,296,310,167,315,272,352,358,381,173,362,330,176,261,275,291,299,297,311,183,316,273,353,359,382,8213,363,331,256,193,194,195,196,197,198,302,268,201,280,203,278,205,206,207,208,325,332,211,212,213,214,360,216,370,218,219,220,221,222,223,257,225,226,227,228,229,230,303,269,233,281,235,279,237,238,239,240,326,333,243,244,245,246,361,248,371,250,251,252,253,254,312], - "ISO-8859-13" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,8221,162,163,164,8222,166,167,216,169,342,171,172,173,174,198,176,177,178,179,8220,181,182,183,248,185,343,187,188,189,190,230,260,302,256,262,196,197,280,274,268,201,377,278,290,310,298,315,352,323,325,211,332,213,214,215,370,321,346,362,220,379,381,223,261,303,257,263,228,229,281,275,269,233,378,279,291,311,299,316,353,324,326,243,333,245,246,247,371,322,347,363,252,380,382,8217], - "ISO-8859-14" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,7682,7683,163,266,267,7690,167,7808,169,7810,7691,7922,173,174,376,7710,7711,288,289,7744,7745,182,7766,7809,7767,7811,7776,7923,7812,7813,7777,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,372,209,210,211,212,213,214,7786,216,217,218,219,220,221,374,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,373,241,242,243,244,245,246,7787,248,249,250,251,252,253,375,255], - "ISO-8859-15" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,8364,165,352,167,353,169,170,171,172,173,174,175,176,177,178,179,381,181,182,183,382,185,186,187,338,339,376,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255], - "ISO-8859-16" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,261,321,8364,8222,352,167,353,169,536,171,377,173,378,379,176,177,268,322,381,8221,182,183,382,269,537,187,338,339,376,380,192,193,194,258,196,262,198,199,200,201,202,203,204,205,206,207,272,323,210,211,212,336,214,346,368,217,218,219,220,280,538,223,224,225,226,259,228,263,230,231,232,233,234,235,236,237,238,239,273,324,242,243,244,337,246,347,369,249,250,251,252,281,539,255], - "KOI8-R" => [9472,9474,9484,9488,9492,9496,9500,9508,9516,9524,9532,9600,9604,9608,9612,9616,9617,9618,9619,8992,9632,8729,8730,8776,8804,8805,160,8993,176,178,183,247,9552,9553,9554,1105,9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,9567,9568,9569,1025,9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,169,1102,1072,1073,1094,1076,1077,1092,1075,1093,1080,1081,1082,1083,1084,1085,1086,1087,1103,1088,1089,1090,1091,1078,1074,1100,1099,1079,1096,1101,1097,1095,1098,1070,1040,1041,1062,1044,1045,1060,1043,1061,1048,1049,1050,1051,1052,1053,1054,1055,1071,1056,1057,1058,1059,1046,1042,1068,1067,1047,1064,1069,1065,1063,1066], - "KOI8-U" => [9472,9474,9484,9488,9492,9496,9500,9508,9516,9524,9532,9600,9604,9608,9612,9616,9617,9618,9619,8992,9632,8729,8730,8776,8804,8805,160,8993,176,178,183,247,9552,9553,9554,1105,1108,9556,1110,1111,9559,9560,9561,9562,9563,1169,1118,9566,9567,9568,9569,1025,1028,9571,1030,1031,9574,9575,9576,9577,9578,1168,1038,169,1102,1072,1073,1094,1076,1077,1092,1075,1093,1080,1081,1082,1083,1084,1085,1086,1087,1103,1088,1089,1090,1091,1078,1074,1100,1099,1079,1096,1101,1097,1095,1098,1070,1040,1041,1062,1044,1045,1060,1043,1061,1048,1049,1050,1051,1052,1053,1054,1055,1071,1056,1057,1058,1059,1046,1042,1068,1067,1047,1064,1069,1065,1063,1066], - "macintosh" => [196,197,199,201,209,214,220,225,224,226,228,227,229,231,233,232,234,235,237,236,238,239,241,243,242,244,246,245,250,249,251,252,8224,176,162,163,167,8226,182,223,174,169,8482,180,168,8800,198,216,8734,177,8804,8805,165,181,8706,8721,8719,960,8747,170,186,937,230,248,191,161,172,8730,402,8776,8710,171,187,8230,160,192,195,213,338,339,8211,8212,8220,8221,8216,8217,247,9674,255,376,8260,8364,8249,8250,64257,64258,8225,183,8218,8222,8240,194,202,193,203,200,205,206,207,204,211,212,63743,210,218,219,217,305,710,732,175,728,729,730,184,733,731,711], - "windows-874" => [8364,129,130,131,132,8230,134,135,136,137,138,139,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,152,153,154,155,156,157,158,159,160,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,null,null,null,null,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3674,3675,null,null,null,null], - "windows-1250" => [8364,129,8218,131,8222,8230,8224,8225,136,8240,352,8249,346,356,381,377,144,8216,8217,8220,8221,8226,8211,8212,152,8482,353,8250,347,357,382,378,160,711,728,321,164,260,166,167,168,169,350,171,172,173,174,379,176,177,731,322,180,181,182,183,184,261,351,187,317,733,318,380,340,193,194,258,196,313,262,199,268,201,280,203,282,205,206,270,272,323,327,211,212,336,214,215,344,366,218,368,220,221,354,223,341,225,226,259,228,314,263,231,269,233,281,235,283,237,238,271,273,324,328,243,244,337,246,247,345,367,250,369,252,253,355,729], - "windows-1251" => [1026,1027,8218,1107,8222,8230,8224,8225,8364,8240,1033,8249,1034,1036,1035,1039,1106,8216,8217,8220,8221,8226,8211,8212,152,8482,1113,8250,1114,1116,1115,1119,160,1038,1118,1032,164,1168,166,167,1025,169,1028,171,172,173,174,1031,176,177,1030,1110,1169,181,182,183,1105,8470,1108,187,1112,1029,1109,1111,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103], - "windows-1252" => [8364,129,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,141,381,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,157,382,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255], - "windows-1253" => [8364,129,8218,402,8222,8230,8224,8225,136,8240,138,8249,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,152,8482,154,8250,156,157,158,159,160,901,902,163,164,165,166,167,168,169,null,171,172,173,174,8213,176,177,178,179,900,181,182,183,904,905,906,187,908,189,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,null,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,null], - "windows-1254" => [8364,129,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,157,158,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,286,209,210,211,212,213,214,215,216,217,218,219,220,304,350,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,287,241,242,243,244,245,246,247,248,249,250,251,252,305,351,255], - "windows-1255" => [8364,129,8218,402,8222,8230,8224,8225,710,8240,138,8249,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,154,8250,156,157,158,159,160,161,162,163,8362,165,166,167,168,169,215,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,247,187,188,189,190,191,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1520,1521,1522,1523,1524,null,null,null,null,null,null,null,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,null,null,8206,8207,null], - "windows-1256" => [8364,1662,8218,402,8222,8230,8224,8225,710,8240,1657,8249,338,1670,1688,1672,1711,8216,8217,8220,8221,8226,8211,8212,1705,8482,1681,8250,339,8204,8205,1722,160,1548,162,163,164,165,166,167,168,169,1726,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,1563,187,188,189,190,1567,1729,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,215,1591,1592,1593,1594,1600,1601,1602,1603,224,1604,226,1605,1606,1607,1608,231,232,233,234,235,1609,1610,238,239,1611,1612,1613,1614,244,1615,1616,247,1617,249,1618,251,252,8206,8207,1746], - "windows-1257" => [8364,129,8218,131,8222,8230,8224,8225,136,8240,138,8249,140,168,711,184,144,8216,8217,8220,8221,8226,8211,8212,152,8482,154,8250,156,175,731,159,160,null,162,163,164,null,166,167,216,169,342,171,172,173,174,198,176,177,178,179,180,181,182,183,248,185,343,187,188,189,190,230,260,302,256,262,196,197,280,274,268,201,377,278,290,310,298,315,352,323,325,211,332,213,214,215,370,321,346,362,220,379,381,223,261,303,257,263,228,229,281,275,269,233,378,279,291,311,299,316,353,324,326,243,333,245,246,247,371,322,347,363,252,380,382,729], - "windows-1258" => [8364,129,8218,402,8222,8230,8224,8225,710,8240,138,8249,338,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,154,8250,339,157,158,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,258,196,197,198,199,200,201,202,203,768,205,206,207,272,209,777,211,212,416,214,215,216,217,218,219,220,431,771,223,224,225,226,259,228,229,230,231,232,233,234,235,769,237,238,239,273,241,803,243,244,417,246,247,248,249,250,251,252,432,8363,255], - "x-mac-cyrillic" => [1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,8224,176,1168,163,167,8226,182,1030,174,169,8482,1026,1106,8800,1027,1107,8734,177,8804,8805,1110,181,1169,1032,1028,1108,1031,1111,1033,1113,1034,1114,1112,1029,172,8730,402,8776,8710,171,187,8230,160,1035,1115,1036,1116,1109,8211,8212,8220,8221,8216,8217,247,8222,1038,1118,1039,1119,8470,1025,1105,1103,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,8364], - ]; + "IBM866" => [1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,9617,9618,9619,9474,9508,9569,9570,9558,9557,9571,9553,9559,9565,9564,9563,9488,9492,9524,9516,9500,9472,9532,9566,9567,9562,9556,9577,9574,9568,9552,9580,9575,9576,9572,9573,9561,9560,9554,9555,9579,9578,9496,9484,9608,9604,9612,9616,9600,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1025,1105,1028,1108,1031,1111,1038,1118,176,8729,183,8730,8470,164,9632,160], + "ISO-8859-2" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,728,321,164,317,346,167,168,352,350,356,377,173,381,379,176,261,731,322,180,318,347,711,184,353,351,357,378,733,382,380,340,193,194,258,196,313,262,199,268,201,280,203,282,205,206,270,272,323,327,211,212,336,214,215,344,366,218,368,220,221,354,223,341,225,226,259,228,314,263,231,269,233,281,235,283,237,238,271,273,324,328,243,244,337,246,247,345,367,250,369,252,253,355,729], + "ISO-8859-3" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,294,728,163,164,null,292,167,168,304,350,286,308,173,null,379,176,295,178,179,180,181,293,183,184,305,351,287,309,189,null,380,192,193,194,null,196,266,264,199,200,201,202,203,204,205,206,207,null,209,210,211,212,288,214,215,284,217,218,219,220,364,348,223,224,225,226,null,228,267,265,231,232,233,234,235,236,237,238,239,null,241,242,243,244,289,246,247,285,249,250,251,252,365,349,729], + "ISO-8859-4" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,312,342,164,296,315,167,168,352,274,290,358,173,381,175,176,261,731,343,180,297,316,711,184,353,275,291,359,330,382,331,256,193,194,195,196,197,198,302,268,201,280,203,278,205,206,298,272,325,332,310,212,213,214,215,216,370,218,219,220,360,362,223,257,225,226,227,228,229,230,303,269,233,281,235,279,237,238,299,273,326,333,311,244,245,246,247,248,371,250,251,252,361,363,729], + "ISO-8859-5" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,173,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,8470,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,167,1118,1119], + "ISO-8859-6" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,null,null,null,164,null,null,null,null,null,null,null,1548,173,null,null,null,null,null,null,null,null,null,null,null,null,null,1563,null,null,null,1567,null,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,null,null,null,null,null,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,null,null,null,null,null,null,null,null,null,null,null,null,null], + "ISO-8859-7" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,8216,8217,163,8364,8367,166,167,168,169,890,171,172,173,null,8213,176,177,178,179,900,901,902,183,904,905,906,187,908,189,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,null,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,null], + "ISO-8859-8" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,null,162,163,164,165,166,167,168,169,215,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,247,187,188,189,190,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,8215,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,null,null,8206,8207,null], + "ISO-8859-8-I" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,null,162,163,164,165,166,167,168,169,215,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,247,187,188,189,190,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,8215,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,null,null,8206,8207,null], + "ISO-8859-10" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,274,290,298,296,310,167,315,272,352,358,381,173,362,330,176,261,275,291,299,297,311,183,316,273,353,359,382,8213,363,331,256,193,194,195,196,197,198,302,268,201,280,203,278,205,206,207,208,325,332,211,212,213,214,360,216,370,218,219,220,221,222,223,257,225,226,227,228,229,230,303,269,233,281,235,279,237,238,239,240,326,333,243,244,245,246,361,248,371,250,251,252,253,254,312], + "ISO-8859-13" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,8221,162,163,164,8222,166,167,216,169,342,171,172,173,174,198,176,177,178,179,8220,181,182,183,248,185,343,187,188,189,190,230,260,302,256,262,196,197,280,274,268,201,377,278,290,310,298,315,352,323,325,211,332,213,214,215,370,321,346,362,220,379,381,223,261,303,257,263,228,229,281,275,269,233,378,279,291,311,299,316,353,324,326,243,333,245,246,247,371,322,347,363,252,380,382,8217], + "ISO-8859-14" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,7682,7683,163,266,267,7690,167,7808,169,7810,7691,7922,173,174,376,7710,7711,288,289,7744,7745,182,7766,7809,7767,7811,7776,7923,7812,7813,7777,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,372,209,210,211,212,213,214,7786,216,217,218,219,220,221,374,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,373,241,242,243,244,245,246,7787,248,249,250,251,252,253,375,255], + "ISO-8859-15" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,8364,165,352,167,353,169,170,171,172,173,174,175,176,177,178,179,381,181,182,183,382,185,186,187,338,339,376,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255], + "ISO-8859-16" => [128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,261,321,8364,8222,352,167,353,169,536,171,377,173,378,379,176,177,268,322,381,8221,182,183,382,269,537,187,338,339,376,380,192,193,194,258,196,262,198,199,200,201,202,203,204,205,206,207,272,323,210,211,212,336,214,346,368,217,218,219,220,280,538,223,224,225,226,259,228,263,230,231,232,233,234,235,236,237,238,239,273,324,242,243,244,337,246,347,369,249,250,251,252,281,539,255], + "KOI8-R" => [9472,9474,9484,9488,9492,9496,9500,9508,9516,9524,9532,9600,9604,9608,9612,9616,9617,9618,9619,8992,9632,8729,8730,8776,8804,8805,160,8993,176,178,183,247,9552,9553,9554,1105,9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,9567,9568,9569,1025,9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,169,1102,1072,1073,1094,1076,1077,1092,1075,1093,1080,1081,1082,1083,1084,1085,1086,1087,1103,1088,1089,1090,1091,1078,1074,1100,1099,1079,1096,1101,1097,1095,1098,1070,1040,1041,1062,1044,1045,1060,1043,1061,1048,1049,1050,1051,1052,1053,1054,1055,1071,1056,1057,1058,1059,1046,1042,1068,1067,1047,1064,1069,1065,1063,1066], + "KOI8-U" => [9472,9474,9484,9488,9492,9496,9500,9508,9516,9524,9532,9600,9604,9608,9612,9616,9617,9618,9619,8992,9632,8729,8730,8776,8804,8805,160,8993,176,178,183,247,9552,9553,9554,1105,1108,9556,1110,1111,9559,9560,9561,9562,9563,1169,1118,9566,9567,9568,9569,1025,1028,9571,1030,1031,9574,9575,9576,9577,9578,1168,1038,169,1102,1072,1073,1094,1076,1077,1092,1075,1093,1080,1081,1082,1083,1084,1085,1086,1087,1103,1088,1089,1090,1091,1078,1074,1100,1099,1079,1096,1101,1097,1095,1098,1070,1040,1041,1062,1044,1045,1060,1043,1061,1048,1049,1050,1051,1052,1053,1054,1055,1071,1056,1057,1058,1059,1046,1042,1068,1067,1047,1064,1069,1065,1063,1066], + "macintosh" => [196,197,199,201,209,214,220,225,224,226,228,227,229,231,233,232,234,235,237,236,238,239,241,243,242,244,246,245,250,249,251,252,8224,176,162,163,167,8226,182,223,174,169,8482,180,168,8800,198,216,8734,177,8804,8805,165,181,8706,8721,8719,960,8747,170,186,937,230,248,191,161,172,8730,402,8776,8710,171,187,8230,160,192,195,213,338,339,8211,8212,8220,8221,8216,8217,247,9674,255,376,8260,8364,8249,8250,64257,64258,8225,183,8218,8222,8240,194,202,193,203,200,205,206,207,204,211,212,63743,210,218,219,217,305,710,732,175,728,729,730,184,733,731,711], + "windows-874" => [8364,129,130,131,132,8230,134,135,136,137,138,139,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,152,153,154,155,156,157,158,159,160,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,null,null,null,null,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3674,3675,null,null,null,null], + "windows-1250" => [8364,129,8218,131,8222,8230,8224,8225,136,8240,352,8249,346,356,381,377,144,8216,8217,8220,8221,8226,8211,8212,152,8482,353,8250,347,357,382,378,160,711,728,321,164,260,166,167,168,169,350,171,172,173,174,379,176,177,731,322,180,181,182,183,184,261,351,187,317,733,318,380,340,193,194,258,196,313,262,199,268,201,280,203,282,205,206,270,272,323,327,211,212,336,214,215,344,366,218,368,220,221,354,223,341,225,226,259,228,314,263,231,269,233,281,235,283,237,238,271,273,324,328,243,244,337,246,247,345,367,250,369,252,253,355,729], + "windows-1251" => [1026,1027,8218,1107,8222,8230,8224,8225,8364,8240,1033,8249,1034,1036,1035,1039,1106,8216,8217,8220,8221,8226,8211,8212,152,8482,1113,8250,1114,1116,1115,1119,160,1038,1118,1032,164,1168,166,167,1025,169,1028,171,172,173,174,1031,176,177,1030,1110,1169,181,182,183,1105,8470,1108,187,1112,1029,1109,1111,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103], + "windows-1252" => [8364,129,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,141,381,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,157,382,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255], + "windows-1253" => [8364,129,8218,402,8222,8230,8224,8225,136,8240,138,8249,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,152,8482,154,8250,156,157,158,159,160,901,902,163,164,165,166,167,168,169,null,171,172,173,174,8213,176,177,178,179,900,181,182,183,904,905,906,187,908,189,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,null,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,null], + "windows-1254" => [8364,129,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,157,158,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,286,209,210,211,212,213,214,215,216,217,218,219,220,304,350,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,287,241,242,243,244,245,246,247,248,249,250,251,252,305,351,255], + "windows-1255" => [8364,129,8218,402,8222,8230,8224,8225,710,8240,138,8249,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,154,8250,156,157,158,159,160,161,162,163,8362,165,166,167,168,169,215,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,247,187,188,189,190,191,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1520,1521,1522,1523,1524,null,null,null,null,null,null,null,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,null,null,8206,8207,null], + "windows-1256" => [8364,1662,8218,402,8222,8230,8224,8225,710,8240,1657,8249,338,1670,1688,1672,1711,8216,8217,8220,8221,8226,8211,8212,1705,8482,1681,8250,339,8204,8205,1722,160,1548,162,163,164,165,166,167,168,169,1726,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,1563,187,188,189,190,1567,1729,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,215,1591,1592,1593,1594,1600,1601,1602,1603,224,1604,226,1605,1606,1607,1608,231,232,233,234,235,1609,1610,238,239,1611,1612,1613,1614,244,1615,1616,247,1617,249,1618,251,252,8206,8207,1746], + "windows-1257" => [8364,129,8218,131,8222,8230,8224,8225,136,8240,138,8249,140,168,711,184,144,8216,8217,8220,8221,8226,8211,8212,152,8482,154,8250,156,175,731,159,160,null,162,163,164,null,166,167,216,169,342,171,172,173,174,198,176,177,178,179,180,181,182,183,248,185,343,187,188,189,190,230,260,302,256,262,196,197,280,274,268,201,377,278,290,310,298,315,352,323,325,211,332,213,214,215,370,321,346,362,220,379,381,223,261,303,257,263,228,229,281,275,269,233,378,279,291,311,299,316,353,324,326,243,333,245,246,247,371,322,347,363,252,380,382,729], + "windows-1258" => [8364,129,8218,402,8222,8230,8224,8225,710,8240,138,8249,338,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,154,8250,339,157,158,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,258,196,197,198,199,200,201,202,203,768,205,206,207,272,209,777,211,212,416,214,215,216,217,218,219,220,431,771,223,224,225,226,259,228,229,230,231,232,233,234,235,769,237,238,239,273,241,803,243,244,417,246,247,248,249,250,251,252,432,8363,255], + "x-mac-cyrillic" => [1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,8224,176,1168,163,167,8226,182,1030,174,169,8482,1026,1106,8800,1027,1107,8734,177,8804,8805,1110,181,1169,1032,1028,1108,1031,1111,1033,1113,1034,1114,1112,1029,172,8730,402,8776,8710,171,187,8230,160,1035,1115,1036,1116,1109,8211,8212,8220,8221,8216,8217,247,8222,1038,1118,1039,1119,8470,1025,1105,1103,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,8364], + ]; protected static $classes = [ - "IBM866" => "IBM866", - "ISO-8859-2" => "ISO88592", - "ISO-8859-3" => "ISO88593", - "ISO-8859-4" => "ISO88594", - "ISO-8859-5" => "ISO88595", - "ISO-8859-6" => "ISO88596", - "ISO-8859-7" => "ISO88597", - "ISO-8859-8" => "ISO88598", - "ISO-8859-8-I" => "ISO88598I", - "ISO-8859-10" => "ISO885910", - "ISO-8859-13" => "ISO885913", - "ISO-8859-14" => "ISO885914", - "ISO-8859-15" => "ISO885915", - "ISO-8859-16" => "ISO885916", - "KOI8-R" => "KOI8R", - "KOI8-U" => "KOI8U", - "macintosh" => "Macintosh", - "windows-874" => "Windows874", - "windows-1250" => "Windows1250", - "windows-1251" => "Windows1251", - "windows-1252" => "Windows1252", - "windows-1253" => "Windows1253", - "windows-1254" => "Windows1254", - "windows-1255" => "Windows1255", - "windows-1256" => "Windows1256", - "windows-1257" => "Windows1257", - "windows-1258" => "Windows1258", - "x-mac-cyrillic" => "XMacCyrillic", - ]; - - protected function checkClass($class) { - $class = '\MensBeam\Intl\Encoding\\'.$class; - if (!class_exists($class)) { - $this->markTestSkipped("Not implemented"); - } - return $class; - } + 'IBM866' => \MensBeam\Intl\Encoding\IBM866::class, + 'ISO-8859-2' => \MensBeam\Intl\Encoding\ISO88592::class, + 'ISO-8859-3' => \MensBeam\Intl\Encoding\ISO88593::class, + 'ISO-8859-4' => \MensBeam\Intl\Encoding\ISO88594::class, + 'ISO-8859-5' => \MensBeam\Intl\Encoding\ISO88595::class, + 'ISO-8859-6' => \MensBeam\Intl\Encoding\ISO88596::class, + 'ISO-8859-7' => \MensBeam\Intl\Encoding\ISO88597::class, + 'ISO-8859-8' => \MensBeam\Intl\Encoding\ISO88598::class, + 'ISO-8859-8-I' => \MensBeam\Intl\Encoding\ISO88598I::class, + 'ISO-8859-10' => \MensBeam\Intl\Encoding\ISO885910::class, + 'ISO-8859-13' => \MensBeam\Intl\Encoding\ISO885913::class, + 'ISO-8859-14' => \MensBeam\Intl\Encoding\ISO885914::class, + 'ISO-8859-15' => \MensBeam\Intl\Encoding\ISO885915::class, + 'ISO-8859-16' => \MensBeam\Intl\Encoding\ISO885916::class, + 'KOI8-R' => \MensBeam\Intl\Encoding\KOI8R::class, + 'KOI8-U' => \MensBeam\Intl\Encoding\KOI8U::class, + 'macintosh' => \MensBeam\Intl\Encoding\Macintosh::class, + 'windows-874' => \MensBeam\Intl\Encoding\Windows874::class, + 'windows-1250' => \MensBeam\Intl\Encoding\Windows1250::class, + 'windows-1251' => \MensBeam\Intl\Encoding\Windows1251::class, + 'windows-1252' => \MensBeam\Intl\Encoding\Windows1252::class, + 'windows-1253' => \MensBeam\Intl\Encoding\Windows1253::class, + 'windows-1254' => \MensBeam\Intl\Encoding\Windows1254::class, + 'windows-1255' => \MensBeam\Intl\Encoding\Windows1255::class, + 'windows-1256' => \MensBeam\Intl\Encoding\Windows1256::class, + 'windows-1257' => \MensBeam\Intl\Encoding\Windows1257::class, + 'windows-1258' => \MensBeam\Intl\Encoding\Windows1258::class, + 'x-mac-cyrillic' => \MensBeam\Intl\Encoding\XMacCyrillic::class, + ]; + + protected $testedClass = SingleByteEncoding::class; + /* Single-byte encodings don't have complex seeking, so this string is generic */ + protected $seekString = "30 31 32 33 34 35 36"; + protected $seekCodes = [0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36]; + protected $seekOffsets = [0, 1, 2, 3, 4, 5, 6, 7]; + /* This string is supposed to contain a single invalid character sequence; this is different for each single-byte encoding (and many do not have invalid characters) */ + protected $brokenChar = ""; /** * @dataProvider provideCodePoints * @covers MensBeam\Intl\Encoding\SingleByteEncoding::encode */ - public function testEncodeCodePoints(string $class, array $input, string $exp) { - $class = $this->checkClass($class); + public function testEncodeCodePoints(bool $fatal, $input, $exp, string $class = SingleByteEncoding::class) { $out = ""; foreach ($input as $code) { - $out .= $class::encode($code); + $out .= $class::encode($code, $fatal); } $this->assertSame(bin2hex($exp), bin2hex($out)); } - /** - * @dataProvider provideInvalids - * @covers MensBeam\Intl\Encoding\SingleByteEncoding::encode - * @covers MensBeam\Intl\Encoding\SingleByteEncoding::err - */ - public function testEncodeInvalidCodePoints(string $class, bool $mode, int $input, $exp) { - $class = $this->checkClass($class); - if ($exp instanceof \Throwable) { - $this->expectException(get_class($exp)); - $this->expectExceptionCode($exp->getCode()); - } - $out = $class::encode($input, $mode); - $this->assertSame($exp, $out); - } - /** * @dataProvider provideStrings * @covers MensBeam\Intl\Encoding\SingleByteEncoding::__construct * @covers MensBeam\Intl\Encoding\SingleByteEncoding::nextCode */ - public function testDecodeMultipleCharactersAsCodePoints(string $class, string $input, array $exp) { - $class = $this->checkClass($class); - $s = new $class($input); - $out = []; - while (($p = $s->nextCode()) !== false) { - $out[] = $p; - } - $this->assertEquals($exp, $out); + public function testDecodeMultipleCharactersAsCodePoints(string $input, array $exp, string $class = SingleByteEncoding::class) { + $this->testedClass = $class; + return parent::testDecodeMultipleCharactersAsCodePoints($input, $exp); } /** @@ -130,66 +109,17 @@ class TestSingleByte extends \PHPUnit\Framework\TestCase { * @covers MensBeam\Intl\Encoding\SingleByteEncoding::__construct * @covers MensBeam\Intl\Encoding\SingleByteEncoding::nextChar */ - public function testDecodeMultipleCharactersAsStrings(string $class, string $input, array $exp) { - $class = $this->checkClass($class); - $exp = array_map(function($v) { - return \IntlChar::chr($v); - }, $exp); - $s = new $class($input); - $out = []; - while (($p = $s->nextChar()) !== "") { - $out[] = $p; - } - $this->assertEquals($exp, $out); + public function testDecodeMultipleCharactersAsStrings(string $input, array $exp, string $class = SingleByteEncoding::class) { + $this->testedClass = $class; + return parent::testDecodeMultipleCharactersAsStrings($input, $exp); } /** - * @dataProvider provideStrings - * @covers MensBeam\Intl\Encoding\SingleByteEncoding::rewind - * @covers MensBeam\Intl\Encoding\SingleByteEncoding::chars - * @covers MensBeam\Intl\Encoding\SingleByteEncoding::codes + * @coversNothing */ - public function testIterateThroughAString(string $class, string $input, array $exp) { - $out = []; - $class = $this->checkClass($class); - $s = new $class($input); - $a = 0; - $this->assertTrue(true); // prevent risky test of empty string - foreach ($s->codes() as $index => $p) { - $this->assertSame($a, $index, "Character key at index $a reported incorrectly"); - $this->assertSame($exp[$a], $p, "Character at index $a decoded incorrectly"); - $a++; - } - $a = 0; - foreach ($s->codes() as $p) { - $a++; - } - $this->assertSame(0, $a); - $s->rewind(); - foreach ($s->codes() as $p) { - $a++; - } - $this->assertSame(sizeof($exp), $a); - - $exp = array_map(function($v) { - return \IntlChar::chr($v); - }, $exp); - - foreach ($s->chars() as $index => $p) { - $this->assertSame($a, $index, "Character key at index $a reported incorrectly"); - $this->assertSame(bin2hex($exp[$a]), bin2hex($p), "Character at index $a decoded incorrectly"); - $a++; - } - $a = 0; - foreach ($s->chars() as $p) { - $a++; - } - $this->assertSame(0, $a); - $s->rewind(); - foreach ($s->chars() as $p) { - $a++; - } - $this->assertSame(sizeof($exp), $a); + public function testSTepBackThroughAString(string $input = "", array $exp = []) { + // this test has no meaning for single-byte encodings + $this->assertTrue(true); } /** @@ -197,45 +127,11 @@ class TestSingleByte extends \PHPUnit\Framework\TestCase { * @covers MensBeam\Intl\Encoding\SingleByteEncoding::seek * @covers MensBeam\Intl\Encoding\SingleByteEncoding::posChar * @covers MensBeam\Intl\Encoding\SingleByteEncoding::posByte + * @covers MensBeam\Intl\Encoding\SingleByteEncoding::rewind */ - public function testSeekThroughAString(string $class) { - $class = $this->checkClass($class); - $input = "0123456"; - $s = new $class($input); - $this->assertSame(0, $s->posChar()); - $this->assertSame(0, $s->posByte()); - - $this->assertSame(0, $s->seek(0)); - $this->assertSame(0, $s->posChar()); - $this->assertSame(0, $s->posByte()); - - $this->assertSame(1, $s->seek(-1)); - $this->assertSame(0, $s->posChar()); - $this->assertSame(0, $s->posByte()); - - $this->assertSame(0, $s->seek(1)); - $this->assertSame(1, $s->posChar()); - $this->assertSame(1, $s->posByte()); - - $this->assertSame(0, $s->seek(2)); - $this->assertSame(3, $s->posChar()); - $this->assertSame(3, $s->posByte()); - - $this->assertSame(0, $s->seek(4)); - $this->assertSame(7, $s->posChar()); - $this->assertSame(7, $s->posByte()); - - $this->assertSame(1, $s->seek(1)); - $this->assertSame(7, $s->posChar()); - $this->assertSame(7, $s->posByte()); - - $this->assertSame(0, $s->seek(-3)); - $this->assertSame(4, $s->posChar()); - $this->assertSame(4, $s->posByte()); - - $this->assertSame(6, $s->seek(-10)); - $this->assertSame(0, $s->posChar()); - $this->assertSame(0, $s->posByte()); + public function testSeekThroughAString(string $class = SingleByteEncoding::class) { + $this->testedClass = $class; + return parent::testSeekThroughAString(); } /** @@ -243,164 +139,72 @@ class TestSingleByte extends \PHPUnit\Framework\TestCase { * @covers MensBeam\Intl\Encoding\SingleByteEncoding::posChar * @covers MensBeam\Intl\Encoding\SingleByteEncoding::posByte */ - public function testTraversePastTheEndOfAString(string $class) { - $class = $this->checkClass($class); - $input = "a"; - $s = new $class($input); - $this->assertSame(0, $s->posChar()); - $this->assertSame(0, $s->posByte()); - - $this->assertSame("a", $s->nextChar()); - $this->assertSame(1, $s->posChar()); - $this->assertSame(1, $s->posByte()); - - $this->assertSame("", $s->nextChar()); - $this->assertSame(1, $s->posChar()); - $this->assertSame(1, $s->posByte()); - - $s = new $class($input); - $this->assertSame(0, $s->posChar()); - $this->assertSame(0, $s->posByte()); - - $this->assertSame(ord("a"), $s->nextCode()); - $this->assertSame(1, $s->posChar()); - $this->assertSame(1, $s->posByte()); - - $this->assertSame(false, $s->nextCode()); - $this->assertSame(1, $s->posChar()); - $this->assertSame(1, $s->posByte()); + public function testTraversePastTheEndOfAString(string $class = SingleByteEncoding::class) { + $this->testedClass = $class; + return parent::testTraversePastTheEndOfAString(); } /** * @dataProvider provideClasses * @covers MensBeam\Intl\Encoding\SingleByteEncoding::peekChar + * @covers MensBeam\Intl\Encoding\SingleByteEncoding::posChar + * @covers MensBeam\Intl\Encoding\SingleByteEncoding::posByte + * @covers MensBeam\Intl\Encoding\SingleByteEncoding::stateSave + * @covers MensBeam\Intl\Encoding\SingleByteEncoding::stateApply */ - public function testPeekAtCharacters(string $class) { - $class = $this->checkClass($class); - $input = "0123456"; - $s = new $class($input); - $s->seek(2); - $this->assertSame(2, $s->posChar()); - $this->assertSame(2, $s->posByte()); - - $this->assertSame(bin2hex("2"), bin2hex($s->peekChar())); - $this->assertSame(2, $s->posChar()); - $this->assertSame(2, $s->posByte()); - - $this->assertSame(bin2hex("23"), bin2hex($s->peekChar(2))); - $this->assertSame(2, $s->posChar()); - $this->assertSame(2, $s->posByte()); - - $s->seek(3); - $this->assertSame(5, $s->posChar()); - $this->assertSame(5, $s->posByte()); - - $this->assertSame(bin2hex("56"), bin2hex($s->peekChar(3))); - $this->assertSame(5, $s->posChar()); - $this->assertSame(5, $s->posByte()); - - $this->assertSame("", $s->peekChar(-5)); - $this->assertSame(5, $s->posChar()); - $this->assertSame(5, $s->posByte()); + public function testPeekAtCharacters(string $class = SingleByteEncoding::class) { + $this->testedClass = $class; + return parent::testPeekAtCharacters(); } /** * @dataProvider provideClasses * @covers MensBeam\Intl\Encoding\SingleByteEncoding::peekCode + * @covers MensBeam\Intl\Encoding\SingleByteEncoding::posChar + * @covers MensBeam\Intl\Encoding\SingleByteEncoding::posByte + * @covers MensBeam\Intl\Encoding\SingleByteEncoding::stateSave + * @covers MensBeam\Intl\Encoding\SingleByteEncoding::stateApply */ - public function testPeekAtCodePoints(string $class) { - $class = $this->checkClass($class); - $input = "0123456"; - $s = new $class($input); - $s->seek(2); - $this->assertSame(2, $s->posChar()); - $this->assertSame(2, $s->posByte()); - - $this->assertSame([0x32], $s->peekCode()); - $this->assertSame(2, $s->posChar()); - $this->assertSame(2, $s->posByte()); - - $this->assertSame([0x32, 0x33], $s->peekCode(2)); - $this->assertSame(2, $s->posChar()); - $this->assertSame(2, $s->posByte()); - - $s->seek(3); - $this->assertSame(5, $s->posChar()); - $this->assertSame(5, $s->posByte()); - - $this->assertSame([0x35, 0x36], $s->peekCode(3)); - $this->assertSame(5, $s->posChar()); - $this->assertSame(5, $s->posByte()); - - $this->assertSame([], $s->peekCode(-5)); - $this->assertSame(5, $s->posChar()); - $this->assertSame(5, $s->posByte()); + public function testPeekAtCodePoints(string $class = SingleByteEncoding::class) { + $this->testedClass = $class; + return parent::testPeekAtCodePoints(); } /** - * @dataProvider provideClasses + * @dataProvider provideStrings * @covers MensBeam\Intl\Encoding\SingleByteEncoding::len * @covers MensBeam\Intl\Encoding\SingleByteEncoding::stateSave * @covers MensBeam\Intl\Encoding\SingleByteEncoding::stateApply */ - public function testGetStringLength(string $class) { - $class = $this->checkClass($class); - $input = "0123456"; - $s = new $class($input); - $s->seek(1); - $posChar = $s->posChar(); - $posByte = $s->posByte(); - - $this->assertSame(strlen($input), $s->len()); - $this->assertSame($posChar, $s->posChar()); - $this->assertSame($posByte, $s->posByte()); + public function testGetStringLength(string $input, array $points, string $class = SingleByteEncoding::class) { + $this->testedClass = $class; + return parent::testGetStringLength($input, $points); } /** * @dataProvider provideStrings * @covers MensBeam\Intl\Encoding\SingleByteEncoding::err */ - public function testReplacementModes(string $class, string $input, array $points) { - $class = $this->checkClass($class); + public function testReplacementModes(string $input = "", array $points = [], string $class = SingleByteEncoding::class) { if (($bump = array_search(0xFFFD, $points, true)) === false) { // if the encoding uses all 128 high byte values, this test is non-operative $this->assertTrue(true); return; } - // officially test replacement characters and null replacement (already effectively tested by other tests) - $s = new $class($input, false); - $s->seek($bump); - $this->assertSame(0xFFFD, $s->nextCode()); - $s->seek(-2); - // test fatal mode - $s = new $class($input, true); - $s->seek($bump); - try { - $p = $s->nextCode(); - } catch (DecoderException $e) { - $p = $e; - } finally { - $this->assertInstanceOf(DecoderException::class, $p); - } - $this->assertSame($bump + 1, $s->posChar()); - $s->seek(-2); - $this->assertSame($bump - 1, $s->posChar()); - try { - $p = $s->peekCode(2); - } catch (DecoderException $e) { - $p = $e; - } finally { - $this->assertInstanceOf(DecoderException::class, $p); - } - $this->assertSame($bump - 1, $s->posChar()); - try { - $p = $s->peekChar(2); - } catch (DecoderException $e) { - $p = $e; - } finally { - $this->assertInstanceOf(DecoderException::class, $p); - } - $this->assertSame($bump - 1, $s->posChar()); + $this->testedClass = $class; + $this->brokenChar = bin2hex(chr($bump)); + return parent::testReplacementModes(); + } + + /** + * @dataProvider provideStrings + * @covers MensBeam\Intl\Encoding\SingleByteEncoding::rewind + * @covers MensBeam\Intl\Encoding\SingleByteEncoding::chars + * @covers MensBeam\Intl\Encoding\SingleByteEncoding::codes + */ + public function testIterateThroughAString(string $input, array $exp, string $class = SingleByteEncoding::class) { + $this->testedClass = $class; + return parent::testIterateThroughAString($input, $exp); } public function provideClasses() { @@ -437,7 +241,8 @@ class TestSingleByte extends \PHPUnit\Framework\TestCase { $bytes .= chr($a + 128); $codes[] = self::$maps[$name][$a]; } - yield $name => [$class, $codes, $bytes]; + yield "$name (fatal)" => [true, $codes, $bytes, $class]; + yield "$name (HTML)" => [false, $codes, $bytes, $class]; } } @@ -445,7 +250,7 @@ class TestSingleByte extends \PHPUnit\Framework\TestCase { $bytes = (function() { $out = ""; for ($a = 0; $a < 256; $a++) { - $out .= chr($a); + $out .= bin2hex(chr($a)); } return $out; })(); @@ -453,7 +258,21 @@ class TestSingleByte extends \PHPUnit\Framework\TestCase { $codes = array_merge(range(0, 127), array_map(function($v) { return $v ?? 0xFFFD; }, self::$maps[$name])); - yield $name => [$class, $bytes, $codes]; + yield $name => [$bytes, $codes, $class]; + } + } + + /** + * @dataProvider provideInvalids + * @covers MensBeam\Intl\Encoding\SingleByteEncoding::encode + * @covers MensBeam\Intl\Encoding\SingleByteEncoding::err + */ + public function testEncodeInvalidCodePoints(string $class, bool $mode, int $input, $exp) { + if ($exp instanceof \Throwable) { + $this->expectException(get_class($exp)); + $this->expectExceptionCode($exp->getCode()); } + $out = $class::encode($input, $mode); + $this->assertSame($exp, $out); } } diff --git a/tests/cases/Encoding/TestUTF8.php b/tests/cases/Encoding/TestUTF8.php index 9afd561..a026809 100644 --- a/tests/cases/Encoding/TestUTF8.php +++ b/tests/cases/Encoding/TestUTF8.php @@ -1,6 +1,6 @@ expectException(get_class($exp)); - $this->expectExceptionCode($exp->getCode()); - } - $out = UTF8::encode($input); - $this->assertSame(bin2hex($exp), bin2hex($out)); + public function testEncodeCodePoints(bool $fatal, $input, $exp) { + return parent::testEncodeCodePoints($fatal, $input, $exp); } /** @@ -31,12 +43,7 @@ class TestUTF8 extends \PHPUnit\Framework\TestCase { * @covers MensBeam\Intl\Encoding\UTF8::nextCode */ public function testDecodeMultipleCharactersAsCodePoints(string $input, array $exp) { - $s = new UTF8($input); - $out = []; - while (($p = $s->nextCode()) !== false) { - $out[] = $p; - } - $this->assertEquals($exp, $out); + return parent::testDecodeMultipleCharactersAsCodePoints($input, $exp); } /** @@ -45,133 +52,25 @@ class TestUTF8 extends \PHPUnit\Framework\TestCase { * @covers MensBeam\Intl\Encoding\UTF8::nextChar */ public function testDecodeMultipleCharactersAsStrings(string $input, array $exp) { - $out = []; - $exp = array_map(function($v) { - return \IntlChar::chr($v); - }, $exp); - $s = new UTF8($input); - while (($c = $s->nextChar()) !== "") { - $out[] = $c; - } - $this->assertEquals($exp, $out); - } - - /** - * @dataProvider provideStrings - * @covers MensBeam\Intl\Encoding\UTF8::rewind - * @covers MensBeam\Intl\Encoding\UTF8::chars - * @covers MensBeam\Intl\Encoding\UTF8::codes - */ - public function testIterateThroughAString(string $input, array $exp) { - $out = []; - $s = new UTF8($input); - $a = 0; - $this->assertTrue(true); // prevent risky test of empty string - foreach ($s->codes() as $index => $p) { - $this->assertSame($a, $index, "Character key at index $a reported incorrectly"); - $this->assertSame($exp[$a], $p, "Character at index $a decoded incorrectly"); - $a++; - } - $a = 0; - foreach ($s->codes() as $p) { - $a++; - } - $this->assertSame(0, $a); - $s->rewind(); - foreach ($s->codes() as $p) { - $a++; - } - $this->assertSame(sizeof($exp), $a); - - $exp = array_map(function($v) { - return \IntlChar::chr($v); - }, $exp); - - foreach ($s->chars() as $index => $p) { - $this->assertSame($a, $index, "Character key at index $a reported incorrectly"); - $this->assertSame(bin2hex($exp[$a]), bin2hex($p), "Character at index $a decoded incorrectly"); - $a++; - } - $a = 0; - foreach ($s->chars() as $p) { - $a++; - } - $this->assertSame(0, $a); - $s->rewind(); - foreach ($s->chars() as $p) { - $a++; - } - $this->assertSame(sizeof($exp), $a); + return parent::testDecodeMultipleCharactersAsStrings($input, $exp); } /** * @dataProvider provideStrings * @covers MensBeam\Intl\Encoding\UTF8::sync */ - public function testSTepBackThroughAString(string $input, array $points) { - $s = new UTF8($input); - $a = 0; - $this->assertTrue(true); // prevent risky test of empty string - while (($p1 = $s->nextCode()) !== false) { - $this->assertSame(0, $s->seek(-1)); - $p2 = $s->nextCode(); - $this->assertSame($p1, $p2, "Mismatch at character position $a"); - $this->assertSame(++$a, $s->posChar(), "Character position should be $a"); - } + public function testSTepBackThroughAString(string $input, array $exp) { + return parent::testSTepBackThroughAString($input, $exp); } /** * @covers MensBeam\Intl\Encoding\UTF8::seek * @covers MensBeam\Intl\Encoding\UTF8::posChar * @covers MensBeam\Intl\Encoding\UTF8::posByte + * @covers MensBeam\Intl\Encoding\UTF8::rewind */ public function testSeekThroughAString() { - /* - Char 0 U+007A (1 byte) Offset 0 - Char 1 U+00A2 (2 bytes) Offset 1 - Char 2 U+6C34 (3 bytes) Offset 3 - Char 3 U+1D11E (4 bytes) Offset 6 - Char 4 U+F8FF (3 bytes) Offset 10 - Char 5 U+10FFFD (4 bytes) Offset 13 - Char 6 U+FFFE (3 bytes) Offset 17 - End of string at char 7, offset 20 - */ - $input = "\x7A\xC2\xA2\xE6\xB0\xB4\xF0\x9D\x84\x9E\xEF\xA3\xBF\xF4\x8F\xBF\xBD\xEF\xBF\xBE"; - $s = new UTF8($input); - $this->assertSame(0, $s->posChar()); - $this->assertSame(0, $s->posByte()); - - $this->assertSame(0, $s->seek(0)); - $this->assertSame(0, $s->posChar()); - $this->assertSame(0, $s->posByte()); - - $this->assertSame(1, $s->seek(-1)); - $this->assertSame(0, $s->posChar()); - $this->assertSame(0, $s->posByte()); - - $this->assertSame(0, $s->seek(1)); - $this->assertSame(1, $s->posChar()); - $this->assertSame(1, $s->posByte()); - - $this->assertSame(0, $s->seek(2)); - $this->assertSame(3, $s->posChar()); - $this->assertSame(6, $s->posByte()); - - $this->assertSame(0, $s->seek(4)); - $this->assertSame(7, $s->posChar()); - $this->assertSame(20, $s->posByte()); - - $this->assertSame(1, $s->seek(1)); - $this->assertSame(7, $s->posChar()); - $this->assertSame(20, $s->posByte()); - - $this->assertSame(0, $s->seek(-3)); - $this->assertSame(4, $s->posChar()); - $this->assertSame(10, $s->posByte()); - - $this->assertSame(6, $s->seek(-10)); - $this->assertSame(0, $s->posChar()); - $this->assertSame(0, $s->posByte()); + return parent::testSeekThroughAString(); } /** @@ -179,111 +78,25 @@ class TestUTF8 extends \PHPUnit\Framework\TestCase { * @covers MensBeam\Intl\Encoding\UTF8::posByte */ public function testTraversePastTheEndOfAString() { - $s = new UTF8("a"); - $this->assertSame(0, $s->posChar()); - $this->assertSame(0, $s->posByte()); - - $this->assertSame("a", $s->nextChar()); - $this->assertSame(1, $s->posChar()); - $this->assertSame(1, $s->posByte()); - - $this->assertSame("", $s->nextChar()); - $this->assertSame(1, $s->posChar()); - $this->assertSame(1, $s->posByte()); - - $s = new UTF8("a"); - $this->assertSame(0, $s->posChar()); - $this->assertSame(0, $s->posByte()); - - $this->assertSame(ord("a"), $s->nextCode()); - $this->assertSame(1, $s->posChar()); - $this->assertSame(1, $s->posByte()); - - $this->assertSame(false, $s->nextCode()); - $this->assertSame(1, $s->posChar()); - $this->assertSame(1, $s->posByte()); + return parent::testTraversePastTheEndOfAString(); } /** * @covers MensBeam\Intl\Encoding\UTF8::peekChar + * @covers MensBeam\Intl\Encoding\UTF8::stateSave + * @covers MensBeam\Intl\Encoding\UTF8::stateApply */ public function testPeekAtCharacters() { - /* - Char 0 U+007A (1 byte) Offset 0 - Char 1 U+00A2 (2 bytes) Offset 1 - Char 2 U+6C34 (3 bytes) Offset 3 - Char 3 U+1D11E (4 bytes) Offset 6 - Char 4 U+F8FF (3 bytes) Offset 10 - Char 5 U+10FFFD (4 bytes) Offset 13 - Char 6 U+FFFE (3 bytes) Offset 17 - End of string at char 7, offset 20 - */ - $input = "\x7A\xC2\xA2\xE6\xB0\xB4\xF0\x9D\x84\x9E\xEF\xA3\xBF\xF4\x8F\xBF\xBD\xEF\xBF\xBE"; - $s = new UTF8($input); - $s->seek(2); - $this->assertSame(2, $s->posChar()); - $this->assertSame(3, $s->posByte()); - - $this->assertSame(bin2hex("\u{6C34}"), bin2hex($s->peekChar())); - $this->assertSame(2, $s->posChar()); - $this->assertSame(3, $s->posByte()); - - $this->assertSame(bin2hex("\u{6C34}\u{1D11E}"), bin2hex($s->peekChar(2))); - $this->assertSame(2, $s->posChar()); - $this->assertSame(3, $s->posByte()); - - $s->seek(3); - $this->assertSame(5, $s->posChar()); - $this->assertSame(13, $s->posByte()); - - $this->assertSame(bin2hex("\u{10FFFD}\u{FFFE}"), bin2hex($s->peekChar(3))); - $this->assertSame(5, $s->posChar()); - $this->assertSame(13, $s->posByte()); - - $this->assertSame("", $s->peekChar(-5)); - $this->assertSame(5, $s->posChar()); - $this->assertSame(13, $s->posByte()); + return parent::testPeekAtCharacters(); } /** * @covers MensBeam\Intl\Encoding\UTF8::peekCode + * @covers MensBeam\Intl\Encoding\UTF8::stateSave + * @covers MensBeam\Intl\Encoding\UTF8::stateApply */ public function testPeekAtCodePoints() { - /* - Char 0 U+007A (1 byte) Offset 0 - Char 1 U+00A2 (2 bytes) Offset 1 - Char 2 U+6C34 (3 bytes) Offset 3 - Char 3 U+1D11E (4 bytes) Offset 6 - Char 4 U+F8FF (3 bytes) Offset 10 - Char 5 U+10FFFD (4 bytes) Offset 13 - Char 6 U+FFFE (3 bytes) Offset 17 - End of string at char 7, offset 20 - */ - $input = "\x7A\xC2\xA2\xE6\xB0\xB4\xF0\x9D\x84\x9E\xEF\xA3\xBF\xF4\x8F\xBF\xBD\xEF\xBF\xBE"; - $s = new UTF8($input); - $s->seek(2); - $this->assertSame(2, $s->posChar()); - $this->assertSame(3, $s->posByte()); - - $this->assertSame([0x6C34], $s->peekCode()); - $this->assertSame(2, $s->posChar()); - $this->assertSame(3, $s->posByte()); - - $this->assertSame([0x6C34, 0x1D11E], $s->peekCode(2)); - $this->assertSame(2, $s->posChar()); - $this->assertSame(3, $s->posByte()); - - $s->seek(3); - $this->assertSame(5, $s->posChar()); - $this->assertSame(13, $s->posByte()); - - $this->assertSame([0x10FFFD, 0xFFFE], $s->peekCode(3)); - $this->assertSame(5, $s->posChar()); - $this->assertSame(13, $s->posByte()); - - $this->assertSame([], $s->peekCode(-5)); - $this->assertSame(5, $s->posChar()); - $this->assertSame(13, $s->posByte()); + return parent::testPeekAtCodePoints(); } /** @@ -293,117 +106,89 @@ class TestUTF8 extends \PHPUnit\Framework\TestCase { * @covers MensBeam\Intl\Encoding\UTF8::stateApply */ public function testGetStringLength(string $input, array $points) { - $s = new UTF8($input); - $s->seek(1); - $posChar = $s->posChar(); - $posByte = $s->posByte(); - - $this->assertSame(sizeof($points), $s->len()); - $this->assertSame($posChar, $s->posChar()); - $this->assertSame($posByte, $s->posByte()); + return parent::testGetStringLength($input, $points); } /** * @covers MensBeam\Intl\Encoding\UTF8::err */ public function testReplacementModes() { - $input = "\x30\xFF\x30"; - // officially test replacement characters and null replacement (already effectively tested by other tests) - $s = new UTF8($input, false); - $s->seek(1); - $this->assertSame(0xFFFD, $s->nextCode()); - $s->seek(-2); - // test fatal mode - $s = new UTF8($input, true); - $s->seek(1); - try { - $p = $s->nextCode(); - } catch (DecoderException $e) { - $p = $e; - } finally { - $this->assertInstanceOf(DecoderException::class, $p); - } - $this->assertSame(2, $s->posChar()); - $this->assertSame(0x30, $s->nextCode()); - $s->seek(-2); - $this->assertSame(1, $s->posChar()); - try { - $p = $s->peekCode(); - } catch (DecoderException $e) { - $p = $e; - } finally { - $this->assertInstanceOf(DecoderException::class, $p); - } - $this->assertSame(1, $s->posChar()); - try { - $p = $s->peekChar(); - } catch (DecoderException $e) { - $p = $e; - } finally { - $this->assertInstanceOf(DecoderException::class, $p); - } - $this->assertSame(1, $s->posChar()); + return parent::testReplacementModes(); + } + + /** + * @dataProvider provideStrings + * @covers MensBeam\Intl\Encoding\UTF8::rewind + * @covers MensBeam\Intl\Encoding\UTF8::chars + * @covers MensBeam\Intl\Encoding\UTF8::codes + */ + public function testIterateThroughAString(string $input, array $exp) { + return parent::testIterateThroughAString($input, $exp); } public function provideCodePoints() { - return [ - "122" => [122, "\x7A"], - "162" => [162, "\xC2\xA2"], - "27700" => [27700, "\xE6\xB0\xB4"], - "119070" => [119070, "\xF0\x9D\x84\x9E"], - "63743" => [63743, "\xEF\xA3\xBF"], - "1114109" => [1114109, "\xF4\x8F\xBF\xBD"], - "65534" => [65534, "\xEF\xBF\xBE"], - "-1" => [-1, new EncoderException("", UTF8::E_INVALID_CODE_POINT)], + $series = [ + "122" => [122, "7A"], + "162" => [162, "C2 A2"], + "27700" => [27700, "E6 B0 B4"], + "119070" => [119070, "F0 9D 84 9E"], + "63743" => [63743, "EF A3 BF"], + "1114109" => [1114109, "F4 8F BF BD"], + "65534" => [65534, "EF BF BE"], + "-1" => [-1, new EncoderException("", UTF8::E_INVALID_CODE_POINT)], "1114112" => [1114112, new EncoderException("", UTF8::E_INVALID_CODE_POINT)], ]; + foreach ($series as $name => $test) { + yield "$name (fatal)" => array_merge([true], $test); + yield "$name (HTML)" => array_merge([false], $test); + } } public function provideStrings() { return [ // control samples 'empty string' => ["", []], - 'sanity check' => ["\x61\x62\x63\x31\x32\x33", [97, 98, 99, 49, 50, 51]], - 'multibyte control' => ["\xE5\x8F\xA4\xE6\xB1\xA0\xE3\x82\x84\xE8\x9B\x99\xE9\xA3\x9B\xE3\x81\xB3\xE8\xBE\xBC\xE3\x82\x80\xE6\xB0\xB4\xE3\x81\xAE\xE9\x9F\xB3", [21476, 27744, 12420, 34521, 39131, 12403, 36796, 12416, 27700, 12398, 38899]], - 'mixed sample' => ["\x7A\xC2\xA2\xE6\xB0\xB4\xF0\x9D\x84\x9E\xEF\xA3\xBF\xF4\x8F\xBF\xBD\xEF\xBF\xBE", [122, 162, 27700, 119070, 63743, 1114109, 65534]], + 'sanity check' => ["61 62 63 31 32 33", [97, 98, 99, 49, 50, 51]], + 'multibyte control' => ["E5 8F A4 E6 B1 A0 E3 82 84 E8 9B 99 E9 A3 9B E3 81 B3 E8 BE BC E3 82 80 E6 B0 B4 E3 81 AE E9 9F B3", [21476, 27744, 12420, 34521, 39131, 12403, 36796, 12416, 27700, 12398, 38899]], + 'mixed sample' => ["7A C2 A2 E6 B0 B4 F0 9D 84 9E EF A3 BF F4 8F BF BD EF BF BE", [122, 162, 27700, 119070, 63743, 1114109, 65534]], // various invalid sequences - 'invalid code' => ["\xFF", [65533]], - 'ends early' => ["\xC0", [65533]], - 'ends early 2' => ["\xE0", [65533]], - 'invalid trail' => ["\xC0\x00", [65533, 0]], - 'invalid trail 2' => ["\xC0\xC0", [65533, 65533]], - 'invalid trail 3' => ["\xE0\x00", [65533, 0]], - 'invalid trail 4' => ["\xE0\xC0", [65533, 65533]], - 'invalid trail 5' => ["\xE0\x80\x00", [65533, 65533, 0]], - 'invalid trail 6' => ["\xE0\x80\xC0", [65533, 65533, 65533]], - '> 0x10FFFF' => ["\xFC\x80\x80\x80\x80\x80", [65533, 65533, 65533, 65533, 65533, 65533]], - 'obsolete lead byte' => ["\xFE\x80\x80\x80\x80\x80", [65533, 65533, 65533, 65533, 65533, 65533]], - 'overlong U+0000 - 2 bytes' => ["\xC0\x80", [65533, 65533]], - 'overlong U+0000 - 3 bytes' => ["\xE0\x80\x80", [65533, 65533, 65533]], - 'overlong U+0000 - 4 bytes' => ["\xF0\x80\x80\x80", [65533, 65533, 65533, 65533]], - 'overlong U+0000 - 5 bytes' => ["\xF8\x80\x80\x80\x80", [65533, 65533, 65533, 65533, 65533]], - 'overlong U+0000 - 6 bytes' => ["\xFC\x80\x80\x80\x80\x80", [65533, 65533, 65533, 65533, 65533, 65533]], - 'overlong U+007F - 2 bytes' => ["\xC1\xBF", [65533, 65533]], - 'overlong U+007F - 3 bytes' => ["\xE0\x81\xBF", [65533, 65533, 65533]], - 'overlong U+007F - 4 bytes' => ["\xF0\x80\x81\xBF", [65533, 65533, 65533, 65533]], - 'overlong U+007F - 5 bytes' => ["\xF8\x80\x80\x81\xBF", [65533, 65533, 65533, 65533, 65533]], - 'overlong U+007F - 6 bytes' => ["\xFC\x80\x80\x80\x81\xBF", [65533, 65533, 65533, 65533, 65533, 65533]], - 'overlong U+07FF - 3 bytes' => ["\xE0\x9F\xBF", [65533, 65533, 65533]], - 'overlong U+07FF - 4 bytes' => ["\xF0\x80\x9F\xBF", [65533, 65533, 65533, 65533]], - 'overlong U+07FF - 5 bytes' => ["\xF8\x80\x80\x9F\xBF", [65533, 65533, 65533, 65533, 65533]], - 'overlong U+07FF - 6 bytes' => ["\xFC\x80\x80\x80\x9F\xBF", [65533, 65533, 65533, 65533, 65533, 65533]], - 'overlong U+FFFF - 4 bytes' => ["\xF0\x8F\xBF\xBF", [65533, 65533, 65533, 65533]], - 'overlong U+FFFF - 5 bytes' => ["\xF8\x80\x8F\xBF\xBF", [65533, 65533, 65533, 65533, 65533]], - 'overlong U+FFFF - 6 bytes' => ["\xFC\x80\x80\x8F\xBF\xBF", [65533, 65533, 65533, 65533, 65533, 65533]], - 'overlong U+10FFFF - 5 bytes' => ["\xF8\x84\x8F\xBF\xBF", [65533, 65533, 65533, 65533, 65533]], - 'overlong U+10FFFF - 6 bytes' => ["\xFC\x80\x84\x8F\xBF\xBF", [65533, 65533, 65533, 65533, 65533, 65533]], + 'invalid code' => ["FF", [65533]], + 'ends early' => ["C0", [65533]], + 'ends early 2' => ["E0", [65533]], + 'invalid trail' => ["C0 00", [65533, 0]], + 'invalid trail 2' => ["C0 C0", [65533, 65533]], + 'invalid trail 3' => ["E0 00", [65533, 0]], + 'invalid trail 4' => ["E0 C0", [65533, 65533]], + 'invalid trail 5' => ["E0 80 00", [65533, 65533, 0]], + 'invalid trail 6' => ["E0 80 C0", [65533, 65533, 65533]], + '> 0x10FFFF' => ["FC 80 80 80 80 80", [65533, 65533, 65533, 65533, 65533, 65533]], + 'obsolete lead byte' => ["FE 80 80 80 80 80", [65533, 65533, 65533, 65533, 65533, 65533]], + 'overlong U+0000 - 2 bytes' => ["C0 80", [65533, 65533]], + 'overlong U+0000 - 3 bytes' => ["E0 80 80", [65533, 65533, 65533]], + 'overlong U+0000 - 4 bytes' => ["F0 80 80 80", [65533, 65533, 65533, 65533]], + 'overlong U+0000 - 5 bytes' => ["F8 80 80 80 80", [65533, 65533, 65533, 65533, 65533]], + 'overlong U+0000 - 6 bytes' => ["FC 80 80 80 80 80", [65533, 65533, 65533, 65533, 65533, 65533]], + 'overlong U+007F - 2 bytes' => ["C1 BF", [65533, 65533]], + 'overlong U+007F - 3 bytes' => ["E0 81 BF", [65533, 65533, 65533]], + 'overlong U+007F - 4 bytes' => ["F0 80 81 BF", [65533, 65533, 65533, 65533]], + 'overlong U+007F - 5 bytes' => ["F8 80 80 81 BF", [65533, 65533, 65533, 65533, 65533]], + 'overlong U+007F - 6 bytes' => ["FC 80 80 80 81 BF", [65533, 65533, 65533, 65533, 65533, 65533]], + 'overlong U+07FF - 3 bytes' => ["E0 9F BF", [65533, 65533, 65533]], + 'overlong U+07FF - 4 bytes' => ["F0 80 9F BF", [65533, 65533, 65533, 65533]], + 'overlong U+07FF - 5 bytes' => ["F8 80 80 9F BF", [65533, 65533, 65533, 65533, 65533]], + 'overlong U+07FF - 6 bytes' => ["FC 80 80 80 9F BF", [65533, 65533, 65533, 65533, 65533, 65533]], + 'overlong U+FFFF - 4 bytes' => ["F0 8F BF BF", [65533, 65533, 65533, 65533]], + 'overlong U+FFFF - 5 bytes' => ["F8 80 8F BF BF", [65533, 65533, 65533, 65533, 65533]], + 'overlong U+FFFF - 6 bytes' => ["FC 80 80 8F BF BF", [65533, 65533, 65533, 65533, 65533, 65533]], + 'overlong U+10FFFF - 5 bytes' => ["F8 84 8F BF BF", [65533, 65533, 65533, 65533, 65533]], + 'overlong U+10FFFF - 6 bytes' => ["FC 80 84 8F BF BF", [65533, 65533, 65533, 65533, 65533, 65533]], // UTF-16 surrogates - 'lead surrogate' => ["\xED\xA0\x80", [65533, 65533, 65533]], - 'trail surrogate' => ["\xED\xB0\x80", [65533, 65533, 65533]], - 'surrogate pair' => ["\xED\xA0\x80\xED\xB0\x80", [65533, 65533, 65533, 65533, 65533, 65533]], + 'lead surrogate' => ["ED A0 80", [65533, 65533, 65533]], + 'trail surrogate' => ["ED B0 80", [65533, 65533, 65533]], + 'surrogate pair' => ["ED A0 80 ED B0 80", [65533, 65533, 65533, 65533, 65533, 65533]], // self-sync edge cases - 'trailing continuation' => ["\x0A\x80\x80", [10, 65533, 65533]], - 'trailing continuation 2' => ["\xE5\x8F\xA4\x80", [21476, 65533]], + 'trailing continuation' => ["0A 80 80", [10, 65533, 65533]], + 'trailing continuation 2' => ["E5 8F A4 80", [21476, 65533]], ]; } } diff --git a/tests/lib/EncodingTest.php b/tests/lib/EncodingTest.php new file mode 100644 index 0000000..be7932a --- /dev/null +++ b/tests/lib/EncodingTest.php @@ -0,0 +1,309 @@ +testedClass; + if ($exp instanceof \Throwable) { + $this->expectException(get_class($exp)); + $this->expectExceptionCode($exp->getCode()); + } else { + $exp = strtolower(str_replace(" ", "", $exp)); + } + $out = $class::encode($input, $fatal); + $this->assertSame($exp, bin2hex($out)); + } + + public function testDecodeMultipleCharactersAsCodePoints(string $input, array $exp) { + $class = $this->testedClass; + $input = $this->prepString($input); + $s = new $class($input); + $out = []; + $a = 0; + $this->assertSame($a, $s->posChar()); + while (($p = $s->nextCode()) !== false) { + $this->assertSame(++$a, $s->posChar()); + $out[] = $p; + } + $this->assertSame($exp, $out); + $this->assertSame($s->posByte(), strlen($input)); + } + + public function testDecodeMultipleCharactersAsStrings(string $input, array $exp) { + $class = $this->testedClass; + $exp = array_map(function($v) { + return \IntlChar::chr($v); + }, $exp); + $input = $this->prepString($input); + $s = new $class($input); + $out = []; + while (($p = $s->nextChar()) !== "") { + $out[] = $p; + } + $this->assertSame($exp, $out); + $this->assertSame($s->posByte(), strlen($input)); + } + + public function testSTepBackThroughAString(string $input, array $exp) { + $class = $this->testedClass; + $input = $this->prepString($input); + $s = new $class($input); + $exp = array_reverse($exp); + $act = []; + while ($s->nextCode() !== false); + while($s->posByte()) { + $s->seek(-1); + $act[] = $s->nextCode(); + $s->seek(-1); + } + $this->assertEquals($exp, $act); + } + + public function testSeekThroughAString() { + $class = $this->testedClass; + $input = $this->prepString($this->seekString); + $off = $this->seekOffsets; + $s = new $class($input); + $this->assertSame(0, $s->posChar()); + $this->assertSame(0, $s->posByte()); + + $this->assertSame(0, $s->seek(0)); + $this->assertSame(0, $s->posChar()); + $this->assertSame(0, $s->posByte()); + + $this->assertSame(1, $s->seek(-1)); + $this->assertSame(0, $s->posChar()); + $this->assertSame(0, $s->posByte()); + + $this->assertSame(0, $s->seek(1)); + $this->assertSame(1, $s->posChar()); + $this->assertSame($off[1], $s->posByte()); + + $this->assertSame(0, $s->seek(2)); + $this->assertSame(3, $s->posChar()); + $this->assertSame($off[3], $s->posByte()); + + $this->assertSame(0, $s->seek(4)); + $this->assertSame(7, $s->posChar()); + $this->assertSame($off[7], $s->posByte()); + + $this->assertSame(1, $s->seek(1)); + $this->assertSame(7, $s->posChar()); + $this->assertSame($off[7], $s->posByte()); + + $this->assertSame(0, $s->seek(-3)); + $this->assertSame(4, $s->posChar()); + $this->assertSame($off[4], $s->posByte()); + + $this->assertSame(6, $s->seek(-10)); + $this->assertSame(0, $s->posChar()); + $this->assertSame(0, $s->posByte()); + + $this->assertSame(0, $s->seek(5)); + $this->assertSame(5, $s->posChar()); + $this->assertSame($off[5], $s->posByte()); + + $s->rewind(0); + $this->assertSame(0, $s->posChar()); + $this->assertSame(0, $s->posByte()); + } + + public function testTraversePastTheEndOfAString() { + $class = $this->testedClass; + $s = new $class("a"); + $this->assertSame(0, $s->posChar()); + $this->assertSame(0, $s->posByte()); + + $this->assertSame("a", $s->nextChar()); + $this->assertSame(1, $s->posChar()); + $this->assertSame(1, $s->posByte()); + + $this->assertSame("", $s->nextChar()); + $this->assertSame(1, $s->posChar()); + $this->assertSame(1, $s->posByte()); + + $s = new $class("a"); + $this->assertSame(0, $s->posChar()); + $this->assertSame(0, $s->posByte()); + + $this->assertSame(ord("a"), $s->nextCode()); + $this->assertSame(1, $s->posChar()); + $this->assertSame(1, $s->posByte()); + + $this->assertSame(false, $s->nextCode()); + $this->assertSame(1, $s->posChar()); + $this->assertSame(1, $s->posByte()); + } + + public function testPeekAtCharacters() { + $class = $this->testedClass; + $input = $this->prepString($this->seekString); + $off = $this->seekOffsets; + $codes = $this->seekCodes; + $s = new $class($input); + $s->seek(2); + $this->assertSame(2, $s->posChar()); + $this->assertSame($off[2], $s->posByte()); + + $this->assertSame(bin2hex(\IntlChar::chr($codes[2])), bin2hex($s->peekChar())); + $this->assertSame(2, $s->posChar()); + $this->assertSame($off[2], $s->posByte()); + + $this->assertSame(bin2hex(\IntlChar::chr($codes[2]).\IntlChar::chr($codes[3])), bin2hex($s->peekChar(2))); + $this->assertSame(2, $s->posChar()); + $this->assertSame($off[2], $s->posByte()); + + $s->seek(3); + $this->assertSame(5, $s->posChar()); + $this->assertSame($off[5], $s->posByte()); + + $this->assertSame(bin2hex(\IntlChar::chr($codes[5]).\IntlChar::chr($codes[6])), bin2hex($s->peekChar(3))); + $this->assertSame(5, $s->posChar()); + $this->assertSame($off[5], $s->posByte()); + + $this->assertSame("", $s->peekChar(-5)); + $this->assertSame(5, $s->posChar()); + $this->assertSame($off[5], $s->posByte()); + } + + public function testPeekAtCodePoints() { + $class = $this->testedClass; + $input = $this->prepString($this->seekString); + $off = $this->seekOffsets; + $codes = $this->seekCodes; + $s = new $class($input); + $s->seek(2); + $this->assertSame(2, $s->posChar()); + $this->assertSame($off[2], $s->posByte()); + + $this->assertSame([$codes[2]], $s->peekCode()); + $this->assertSame(2, $s->posChar()); + $this->assertSame($off[2], $s->posByte()); + + $this->assertSame([$codes[2], $codes[3]], $s->peekCode(2)); + $this->assertSame(2, $s->posChar()); + $this->assertSame($off[2], $s->posByte()); + + $s->seek(3); + $this->assertSame(5, $s->posChar()); + $this->assertSame($off[5], $s->posByte()); + + $this->assertSame([$codes[5], $codes[6]], $s->peekCode(3)); + $this->assertSame(5, $s->posChar()); + $this->assertSame($off[5], $s->posByte()); + + $this->assertSame([], $s->peekCode(-5)); + $this->assertSame(5, $s->posChar()); + $this->assertSame($off[5], $s->posByte()); + } + + public function testGetStringLength(string $input, array $points) { + $class = $this->testedClass; + $input = $this->prepString($input); + $s = new $class($input); + $s->seek(1); + $posChar = $s->posChar(); + $posByte = $s->posByte(); + + $this->assertSame(sizeof($points), $s->len()); + $this->assertSame($posChar, $s->posChar()); + $this->assertSame($posByte, $s->posByte()); + } + + public function testReplacementModes() { + $class = $this->testedClass; + $input = $this->prepString("00".$this->brokenChar."00"); + // officially test replacement characters (already effectively tested by other tests) + $s = new $class($input, false); + $s->seek(1); + $this->assertSame(0xFFFD, $s->nextCode()); + $s->seek(-2); + // test fatal mode + $s = new $class($input, true); + $s->seek(1); + try { + $p = $s->nextCode(); + } catch (DecoderException $e) { + $p = $e; + } finally { + $this->assertInstanceOf(DecoderException::class, $p); + } + $this->assertSame(2, $s->posChar()); + $this->assertSame(0x00, $s->nextCode()); + $s->seek(-2); + $this->assertSame(1, $s->posChar()); + try { + $p = $s->peekCode(); + } catch (DecoderException $e) { + $p = $e; + } finally { + $this->assertInstanceOf(DecoderException::class, $p); + } + $this->assertSame(1, $s->posChar()); + try { + $p = $s->peekChar(); + } catch (DecoderException $e) { + $p = $e; + } finally { + $this->assertInstanceOf(DecoderException::class, $p); + } + $this->assertSame(1, $s->posChar()); + } + + public function testIterateThroughAString(string $input, array $exp) { + $class = $this->testedClass; + $input = $this->prepString($input); + $s = new $class($input); + $out = []; + $a = 0; + $this->assertTrue(true); // prevent risky test of empty string + foreach ($s->codes() as $index => $p) { + $this->assertSame($a, $index, "Character key at index $a reported incorrectly"); + $this->assertSame($exp[$a], $p, "Character at index $a decoded incorrectly"); + $a++; + } + $a = 0; + foreach ($s->codes() as $p) { + $a++; + } + $this->assertSame(0, $a); + $s->rewind(); + foreach ($s->codes() as $p) { + $a++; + } + $this->assertSame(sizeof($exp), $a); + + $exp = array_map(function($v) { + return \IntlChar::chr($v); + }, $exp); + + foreach ($s->chars() as $index => $p) { + $this->assertSame($a, $index, "Character key at index $a reported incorrectly"); + $this->assertSame(bin2hex($exp[$a]), bin2hex($p), "Character at index $a decoded incorrectly"); + $a++; + } + $a = 0; + foreach ($s->chars() as $p) { + $a++; + } + $this->assertSame(0, $a); + $s->rewind(); + foreach ($s->chars() as $p) { + $a++; + } + $this->assertSame(sizeof($exp), $a); + } + + protected function prepString(string $str): string { + return hex2bin(str_replace(" ", "", $str)); + } +} diff --git a/vendor-bin/csfixer/composer.lock b/vendor-bin/csfixer/composer.lock index 62c97b8..3a92589 100644 --- a/vendor-bin/csfixer/composer.lock +++ b/vendor-bin/csfixer/composer.lock @@ -70,16 +70,16 @@ }, { "name": "composer/xdebug-handler", - "version": "1.1.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", - "reference": "c919dc6c62e221fc6406f861ea13433c0aa24f08" + "reference": "e37cbd80da64afe314c72de8d2d2fec0e40d9373" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/c919dc6c62e221fc6406f861ea13433c0aa24f08", - "reference": "c919dc6c62e221fc6406f861ea13433c0aa24f08", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/e37cbd80da64afe314c72de8d2d2fec0e40d9373", + "reference": "e37cbd80da64afe314c72de8d2d2fec0e40d9373", "shasum": "" }, "require": { @@ -110,7 +110,7 @@ "Xdebug", "performance" ], - "time": "2018-04-11T15:42:36+00:00" + "time": "2018-08-23T12:00:19+00:00" }, { "name": "doctrine/annotations", @@ -236,21 +236,21 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v2.12.2", + "version": "v2.13.0", "source": { "type": "git", "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "dcc87d5414e9d0bd316fce81a5bedb9ce720b183" + "reference": "7136aa4e0c5f912e8af82383775460d906168a10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/dcc87d5414e9d0bd316fce81a5bedb9ce720b183", - "reference": "dcc87d5414e9d0bd316fce81a5bedb9ce720b183", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/7136aa4e0c5f912e8af82383775460d906168a10", + "reference": "7136aa4e0c5f912e8af82383775460d906168a10", "shasum": "" }, "require": { "composer/semver": "^1.4", - "composer/xdebug-handler": "^1.0", + "composer/xdebug-handler": "^1.2", "doctrine/annotations": "^1.2", "ext-json": "*", "ext-tokenizer": "*", @@ -292,6 +292,11 @@ "php-cs-fixer" ], "type": "application", + "extra": { + "branch-alias": { + "dev-master": "2.13-dev" + } + }, "autoload": { "psr-4": { "PhpCsFixer\\": "src/" @@ -323,7 +328,7 @@ } ], "description": "A tool to automatically fix PHP code style", - "time": "2018-07-06T10:37:40+00:00" + "time": "2018-08-23T13:15:44+00:00" }, { "name": "paragonie/random_compat", @@ -470,7 +475,7 @@ }, { "name": "symfony/console", - "version": "v3.4.14", + "version": "v3.4.15", "source": { "type": "git", "url": "https://github.com/symfony/console.git", @@ -539,16 +544,16 @@ }, { "name": "symfony/debug", - "version": "v3.4.14", + "version": "v3.4.15", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "d5a058ff6ecad26b30c1ba452241306ea34c65cc" + "reference": "c4625e75341e4fb309ce0c049cbf7fb84b8897cd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/d5a058ff6ecad26b30c1ba452241306ea34c65cc", - "reference": "d5a058ff6ecad26b30c1ba452241306ea34c65cc", + "url": "https://api.github.com/repos/symfony/debug/zipball/c4625e75341e4fb309ce0c049cbf7fb84b8897cd", + "reference": "c4625e75341e4fb309ce0c049cbf7fb84b8897cd", "shasum": "" }, "require": { @@ -591,11 +596,11 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2018-07-26T11:19:56+00:00" + "time": "2018-08-03T10:42:44+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v3.4.14", + "version": "v3.4.15", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", @@ -658,16 +663,16 @@ }, { "name": "symfony/filesystem", - "version": "v3.4.14", + "version": "v3.4.15", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "a59f917e3c5d82332514cb4538387638f5bde2d6" + "reference": "285ce5005cb01a0aeaa5b0cf590bd0cc40bb631c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/a59f917e3c5d82332514cb4538387638f5bde2d6", - "reference": "a59f917e3c5d82332514cb4538387638f5bde2d6", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/285ce5005cb01a0aeaa5b0cf590bd0cc40bb631c", + "reference": "285ce5005cb01a0aeaa5b0cf590bd0cc40bb631c", "shasum": "" }, "require": { @@ -704,11 +709,11 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2018-07-26T11:19:56+00:00" + "time": "2018-08-10T07:29:05+00:00" }, { "name": "symfony/finder", - "version": "v3.4.14", + "version": "v3.4.15", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", @@ -757,7 +762,7 @@ }, { "name": "symfony/options-resolver", - "version": "v3.4.14", + "version": "v3.4.15", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", @@ -1042,16 +1047,16 @@ }, { "name": "symfony/process", - "version": "v3.4.14", + "version": "v3.4.15", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "0414db29bd770ec5a4152683e655f55efd4fa60f" + "reference": "4d6b125d5293cbceedc2aa10f2c71617e76262e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/0414db29bd770ec5a4152683e655f55efd4fa60f", - "reference": "0414db29bd770ec5a4152683e655f55efd4fa60f", + "url": "https://api.github.com/repos/symfony/process/zipball/4d6b125d5293cbceedc2aa10f2c71617e76262e7", + "reference": "4d6b125d5293cbceedc2aa10f2c71617e76262e7", "shasum": "" }, "require": { @@ -1087,11 +1092,11 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2018-07-26T11:19:56+00:00" + "time": "2018-08-03T10:42:44+00:00" }, { "name": "symfony/stopwatch", - "version": "v3.4.14", + "version": "v3.4.15", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", diff --git a/vendor-bin/phpunit/composer.lock b/vendor-bin/phpunit/composer.lock index dc6874b..0cc2920 100644 --- a/vendor-bin/phpunit/composer.lock +++ b/vendor-bin/phpunit/composer.lock @@ -673,16 +673,16 @@ }, { "name": "phpunit/phpunit", - "version": "6.5.11", + "version": "6.5.12", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "7bab54cb366076023bbf457a2a0d513332cd40f2" + "reference": "24da433d7384824d65ea93fbb462e2f31bbb494e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/7bab54cb366076023bbf457a2a0d513332cd40f2", - "reference": "7bab54cb366076023bbf457a2a0d513332cd40f2", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/24da433d7384824d65ea93fbb462e2f31bbb494e", + "reference": "24da433d7384824d65ea93fbb462e2f31bbb494e", "shasum": "" }, "require": { @@ -753,7 +753,7 @@ "testing", "xunit" ], - "time": "2018-08-07T07:05:35+00:00" + "time": "2018-08-22T06:32:48+00:00" }, { "name": "phpunit/phpunit-mock-objects", diff --git a/vendor-bin/robo/composer.lock b/vendor-bin/robo/composer.lock index 2f54668..e91d4b2 100644 --- a/vendor-bin/robo/composer.lock +++ b/vendor-bin/robo/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "consolidation/annotated-command", - "version": "2.8.4", + "version": "2.8.5", "source": { "type": "git", "url": "https://github.com/consolidation/annotated-command.git", - "reference": "651541a0b68318a2a202bda558a676e5ad92223c" + "reference": "1e8ff512072422b850b44aa721b5b303e4a5ebb3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/annotated-command/zipball/651541a0b68318a2a202bda558a676e5ad92223c", - "reference": "651541a0b68318a2a202bda558a676e5ad92223c", + "url": "https://api.github.com/repos/consolidation/annotated-command/zipball/1e8ff512072422b850b44aa721b5b303e4a5ebb3", + "reference": "1e8ff512072422b850b44aa721b5b303e4a5ebb3", "shasum": "" }, "require": { @@ -56,7 +56,7 @@ } ], "description": "Initialize Symfony Console commands from annotated command class methods.", - "time": "2018-05-25T18:04:25+00:00" + "time": "2018-08-18T23:51:49+00:00" }, { "name": "consolidation/config", @@ -218,16 +218,16 @@ }, { "name": "consolidation/robo", - "version": "1.3.0", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/consolidation/Robo.git", - "reference": "ac563abfadf7cb7314b4e152f2b5033a6c255f6f" + "reference": "31f2d2562c4e1dcde70f2659eefd59aa9c7f5b2d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/Robo/zipball/ac563abfadf7cb7314b4e152f2b5033a6c255f6f", - "reference": "ac563abfadf7cb7314b4e152f2b5033a6c255f6f", + "url": "https://api.github.com/repos/consolidation/Robo/zipball/31f2d2562c4e1dcde70f2659eefd59aa9c7f5b2d", + "reference": "31f2d2562c4e1dcde70f2659eefd59aa9c7f5b2d", "shasum": "" }, "require": { @@ -235,6 +235,8 @@ "consolidation/config": "^1.0.10", "consolidation/log": "~1", "consolidation/output-formatters": "^3.1.13", + "consolidation/self-update": "^1", + "g1a/composer-test-scenarios": "^2", "grasmash/yaml-expander": "^1.3", "league/container": "^2.2", "php": ">=5.5.0", @@ -251,7 +253,6 @@ "codeception/aspect-mock": "^1|^2.1.1", "codeception/base": "^2.3.7", "codeception/verify": "^0.3.2", - "g1a/composer-test-scenarios": "^2", "goaop/framework": "~2.1.2", "goaop/parser-reflection": "^1.1.0", "natxet/cssmin": "3.0.4", @@ -294,7 +295,57 @@ } ], "description": "Modern task runner", - "time": "2018-05-27T01:42:53+00:00" + "time": "2018-08-17T18:44:18+00:00" + }, + { + "name": "consolidation/self-update", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/consolidation/self-update.git", + "reference": "de33822f907e0beb0ffad24cf4b1b4fae5ada318" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/consolidation/self-update/zipball/de33822f907e0beb0ffad24cf4b1b4fae5ada318", + "reference": "de33822f907e0beb0ffad24cf4b1b4fae5ada318", + "shasum": "" + }, + "require": { + "php": ">=5.5.0", + "symfony/console": "^2.8|^3|^4", + "symfony/filesystem": "^2.5|^3|^4" + }, + "bin": [ + "scripts/release" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "SelfUpdate\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Greg Anderson", + "email": "greg.1.anderson@greenknowe.org" + }, + { + "name": "Alexander Menk", + "email": "menk@mestrona.net" + } + ], + "description": "Provides a self:update command for Symfony Console applications.", + "time": "2018-08-24T17:01:46+00:00" }, { "name": "container-interop/container-interop", @@ -386,6 +437,39 @@ ], "time": "2017-01-20T21:14:22+00:00" }, + { + "name": "g1a/composer-test-scenarios", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/g1a/composer-test-scenarios.git", + "reference": "a166fd15191aceab89f30c097e694b7cf3db4880" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/g1a/composer-test-scenarios/zipball/a166fd15191aceab89f30c097e694b7cf3db4880", + "reference": "a166fd15191aceab89f30c097e694b7cf3db4880", + "shasum": "" + }, + "bin": [ + "scripts/create-scenario", + "scripts/dependency-licenses", + "scripts/install-scenario" + ], + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Greg Anderson", + "email": "greg.1.anderson@greenknowe.org" + } + ], + "description": "Useful scripts for testing multiple sets of Composer dependencies.", + "time": "2018-08-08T23:37:23+00:00" + }, { "name": "grasmash/expander", "version": "1.0.0", @@ -644,7 +728,7 @@ }, { "name": "symfony/console", - "version": "v3.4.14", + "version": "v3.4.15", "source": { "type": "git", "url": "https://github.com/symfony/console.git", @@ -713,16 +797,16 @@ }, { "name": "symfony/debug", - "version": "v3.4.14", + "version": "v3.4.15", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "d5a058ff6ecad26b30c1ba452241306ea34c65cc" + "reference": "c4625e75341e4fb309ce0c049cbf7fb84b8897cd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/d5a058ff6ecad26b30c1ba452241306ea34c65cc", - "reference": "d5a058ff6ecad26b30c1ba452241306ea34c65cc", + "url": "https://api.github.com/repos/symfony/debug/zipball/c4625e75341e4fb309ce0c049cbf7fb84b8897cd", + "reference": "c4625e75341e4fb309ce0c049cbf7fb84b8897cd", "shasum": "" }, "require": { @@ -765,11 +849,11 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2018-07-26T11:19:56+00:00" + "time": "2018-08-03T10:42:44+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v3.4.14", + "version": "v3.4.15", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", @@ -832,16 +916,16 @@ }, { "name": "symfony/filesystem", - "version": "v3.4.14", + "version": "v3.4.15", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "a59f917e3c5d82332514cb4538387638f5bde2d6" + "reference": "285ce5005cb01a0aeaa5b0cf590bd0cc40bb631c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/a59f917e3c5d82332514cb4538387638f5bde2d6", - "reference": "a59f917e3c5d82332514cb4538387638f5bde2d6", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/285ce5005cb01a0aeaa5b0cf590bd0cc40bb631c", + "reference": "285ce5005cb01a0aeaa5b0cf590bd0cc40bb631c", "shasum": "" }, "require": { @@ -878,11 +962,11 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2018-07-26T11:19:56+00:00" + "time": "2018-08-10T07:29:05+00:00" }, { "name": "symfony/finder", - "version": "v3.4.14", + "version": "v3.4.15", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", @@ -1048,16 +1132,16 @@ }, { "name": "symfony/process", - "version": "v3.4.14", + "version": "v3.4.15", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "0414db29bd770ec5a4152683e655f55efd4fa60f" + "reference": "4d6b125d5293cbceedc2aa10f2c71617e76262e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/0414db29bd770ec5a4152683e655f55efd4fa60f", - "reference": "0414db29bd770ec5a4152683e655f55efd4fa60f", + "url": "https://api.github.com/repos/symfony/process/zipball/4d6b125d5293cbceedc2aa10f2c71617e76262e7", + "reference": "4d6b125d5293cbceedc2aa10f2c71617e76262e7", "shasum": "" }, "require": { @@ -1093,20 +1177,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2018-07-26T11:19:56+00:00" + "time": "2018-08-03T10:42:44+00:00" }, { "name": "symfony/yaml", - "version": "v3.4.14", + "version": "v3.4.15", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "810af2d35fc72b6cf5c01116806d2b65ccaaf2e2" + "reference": "c2f4812ead9f847cb69e90917ca7502e6892d6b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/810af2d35fc72b6cf5c01116806d2b65ccaaf2e2", - "reference": "810af2d35fc72b6cf5c01116806d2b65ccaaf2e2", + "url": "https://api.github.com/repos/symfony/yaml/zipball/c2f4812ead9f847cb69e90917ca7502e6892d6b8", + "reference": "c2f4812ead9f847cb69e90917ca7502e6892d6b8", "shasum": "" }, "require": { @@ -1152,7 +1236,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2018-07-26T11:19:56+00:00" + "time": "2018-08-10T07:34:36+00:00" } ], "packages-dev": [],