diff --git a/lib/Encoding/UTF16.php b/lib/Encoding/UTF16.php index 6a60d20..5e4fb32 100644 --- a/lib/Encoding/UTF16.php +++ b/lib/Encoding/UTF16.php @@ -87,7 +87,8 @@ abstract class UTF16 extends AbstractEncoding { public function asciiSpan(string $mask, int $length = null): string { // UTF-16 has no ASCII characters, so we must do things the hard way $out = ""; - while (true) { + $left = ($length === null) ? -1 : $length; + while ($left) { $c1 = @$this->string[$this->posByte]; $c2 = @$this->string[$this->posByte + 1]; $b = ord(static::BE ? $c1 : $c2); @@ -98,6 +99,7 @@ abstract class UTF16 extends AbstractEncoding { $out .= $c; $this->posByte += 2; $this->posChar++; + $left--; } else { break; } @@ -111,7 +113,8 @@ abstract class UTF16 extends AbstractEncoding { public function asciiSpanNot(string $mask, int $length = null): string { // this is a copy of asciiSpan above with only the strpos check reversed $out = ""; - while (true) { + $left = ($length === null) ? -1 : $length; + while ($left) { $c1 = @$this->string[$this->posByte]; $c2 = @$this->string[$this->posByte + 1]; $b = ord(static::BE ? $c1 : $c2); @@ -122,6 +125,7 @@ abstract class UTF16 extends AbstractEncoding { $out .= $c; $this->posByte += 2; $this->posChar++; + $left--; } else { break; } diff --git a/tests/cases/Encoding/TestBig5.php b/tests/cases/Encoding/TestBig5.php index cab1492..9856c42 100644 --- a/tests/cases/Encoding/TestBig5.php +++ b/tests/cases/Encoding/TestBig5.php @@ -204,6 +204,13 @@ class TestBig5 extends \MensBeam\Intl\Test\CoderDecoderTest { parent::testExtractAsciiSpans(); } + /** + * @covers MensBeam\Intl\Encoding\Big5::asciiSpanNot + */ + public function testExtractNegativeAsciiSpans() { + parent::testExtractNegativeAsciiSpans(); + } + /** * @group optional */ diff --git a/tests/cases/Encoding/TestEUCJP.php b/tests/cases/Encoding/TestEUCJP.php index ea340d2..178084f 100644 --- a/tests/cases/Encoding/TestEUCJP.php +++ b/tests/cases/Encoding/TestEUCJP.php @@ -215,6 +215,13 @@ class TestEUCJP extends \MensBeam\Intl\Test\CoderDecoderTest { parent::testExtractAsciiSpans(); } + /** + * @covers MensBeam\Intl\Encoding\EUCJP::asciiSpanNot + */ + public function testExtractNegativeAsciiSpans() { + parent::testExtractNegativeAsciiSpans(); + } + /** * @group optional */ diff --git a/tests/cases/Encoding/TestEUCKR.php b/tests/cases/Encoding/TestEUCKR.php index 2e05f38..3bc0629 100644 --- a/tests/cases/Encoding/TestEUCKR.php +++ b/tests/cases/Encoding/TestEUCKR.php @@ -194,6 +194,13 @@ class TestEUCKR extends \MensBeam\Intl\Test\CoderDecoderTest { parent::testExtractAsciiSpans(); } + /** + * @covers MensBeam\Intl\Encoding\EUCKR::asciiSpanNot + */ + public function testExtractNegativeAsciiSpans() { + parent::testExtractNegativeAsciiSpans(); + } + /** * @group optional */ diff --git a/tests/cases/Encoding/TestGB18030.php b/tests/cases/Encoding/TestGB18030.php index 89c6bd8..0999e62 100644 --- a/tests/cases/Encoding/TestGB18030.php +++ b/tests/cases/Encoding/TestGB18030.php @@ -283,6 +283,13 @@ class TestGB18030 extends \MensBeam\Intl\Test\CoderDecoderTest { parent::testExtractAsciiSpans(); } + /** + * @covers MensBeam\Intl\Encoding\GB18030::asciiSpanNot + */ + public function testExtractNegativeAsciiSpans() { + parent::testExtractNegativeAsciiSpans(); + } + /** * @group optional */ diff --git a/tests/cases/Encoding/TestISO2022JP.php b/tests/cases/Encoding/TestISO2022JP.php index 399825e..8be3d07 100644 --- a/tests/cases/Encoding/TestISO2022JP.php +++ b/tests/cases/Encoding/TestISO2022JP.php @@ -250,6 +250,13 @@ class TestISO2022JP extends \MensBeam\Intl\Test\CoderDecoderTest { $this->markTestIncomplete(); } + /** + * @covers MensBeam\Intl\Encoding\ISO2022JP::asciiSpanNot + */ + public function testExtractNegativeAsciiSpans() { + $this->markTestIncomplete(); + } + /** * @group optional */ diff --git a/tests/cases/Encoding/TestReplacement.php b/tests/cases/Encoding/TestReplacement.php index d4fe70c..dae687a 100644 --- a/tests/cases/Encoding/TestReplacement.php +++ b/tests/cases/Encoding/TestReplacement.php @@ -203,6 +203,19 @@ class TestReplacement extends \MensBeam\Intl\Test\DecoderTest { * @covers MensBeam\Intl\Encoding\Replacement::asciiSpan */ public function testExtractAsciiSpans() { - $this->markTestIncomplete(); + $d = new Replacement("VVVVVV"); + $this->assertSame("", $d->asciiSpan($this->allBytes())); + $d->nextChar(); + $this->assertTrue($d->eof()); + } + + /** + * @covers MensBeam\Intl\Encoding\Replacement::asciiSpanNot + */ + public function testExtractNegativeAsciiSpans() { + $d = new Replacement("VVVVVV"); + $this->assertSame("", $d->asciiSpanNot("")); + $d->nextChar(); + $this->assertTrue($d->eof()); } } diff --git a/tests/cases/Encoding/TestShiftJIS.php b/tests/cases/Encoding/TestShiftJIS.php index 0b56f07..8945426 100644 --- a/tests/cases/Encoding/TestShiftJIS.php +++ b/tests/cases/Encoding/TestShiftJIS.php @@ -207,6 +207,13 @@ class TestShiftJIS extends \MensBeam\Intl\Test\CoderDecoderTest { parent::testExtractAsciiSpans(); } + /** + * @covers MensBeam\Intl\Encoding\ShiftJIS::asciiSpanNot + */ + public function testExtractNegativeAsciiSpans() { + parent::testExtractNegativeAsciiSpans(); + } + /** * @group optional */ diff --git a/tests/cases/Encoding/TestSingleByte.php b/tests/cases/Encoding/TestSingleByte.php index a3917d0..a957feb 100644 --- a/tests/cases/Encoding/TestSingleByte.php +++ b/tests/cases/Encoding/TestSingleByte.php @@ -237,12 +237,23 @@ class TestSingleByte extends \MensBeam\Intl\Test\CoderDecoderTest { } /** + * @dataProvider provideClasses * @covers MensBeam\Intl\Encoding\SingleByteEncoding::asciiSpan */ - public function testExtractAsciiSpans() { + public function testExtractAsciiSpans($class = null) { + $this->testedClass = $class; parent::testExtractAsciiSpans(); } + /** + * @dataProvider provideClasses + * @covers MensBeam\Intl\Encoding\SingleByteEncoding::asciiSpan + */ + public function testExtractNegativeAsciiSpans($class = null) { + $this->testedClass = $class; + parent::testExtractNegativeAsciiSpans(); + } + public function provideClasses() { foreach (self::$classes as $name => $class) { yield $name => [$class]; diff --git a/tests/cases/Encoding/TestUTF16LE.php b/tests/cases/Encoding/TestUTF16LE.php index 6cf4bbf..ea9d50d 100644 --- a/tests/cases/Encoding/TestUTF16LE.php +++ b/tests/cases/Encoding/TestUTF16LE.php @@ -142,6 +142,13 @@ class TestUTF16LE extends \MensBeam\Intl\Test\DecoderTest { parent::testExtractAsciiSpans(); } + /** + * @covers MensBeam\Intl\Encoding\UTF16::asciiSpanNot + */ + public function testExtractNegativeAsciiSpans() { + parent::testExtractNegativeAsciiSpans(); + } + public function provideStrings() { return [ // control samples diff --git a/tests/cases/Encoding/TestUTF8.php b/tests/cases/Encoding/TestUTF8.php index 1af1839..80685eb 100644 --- a/tests/cases/Encoding/TestUTF8.php +++ b/tests/cases/Encoding/TestUTF8.php @@ -233,4 +233,11 @@ class TestUTF8 extends \MensBeam\Intl\Test\CoderDecoderTest { public function testExtractAsciiSpans() { parent::testExtractAsciiSpans(); } + + /** + * @covers MensBeam\Intl\Encoding\UTF8::asciiSpanNot + */ + public function testExtractNegativeAsciiSpans() { + parent::testExtractNegativeAsciiSpans(); + } } diff --git a/tests/cases/Encoding/TestXUserDefined.php b/tests/cases/Encoding/TestXUserDefined.php index 7f196fd..658b130 100644 --- a/tests/cases/Encoding/TestXUserDefined.php +++ b/tests/cases/Encoding/TestXUserDefined.php @@ -18,6 +18,8 @@ class TestXUserDefined extends \MensBeam\Intl\Test\CoderDecoderTest { protected $seekOffsets = [0, 1, 2, 3, 4, 5, 6, 7]; /* This string is supposed to contain an invalid character sequence sandwiched between two null characters, but x-user-defined has no invalid characters */ protected $brokenChar = ""; + /* This string conatins the ASCII characters "A" and "Z" followed by two arbitrary non-ASCII characters, followed by the two ASCII characters "0" and "9" */ + protected $spanString = "41 5A 80 FF 30 39"; public function provideCodePoints() { return [ @@ -190,4 +192,11 @@ class TestXUserDefined extends \MensBeam\Intl\Test\CoderDecoderTest { public function testExtractAsciiSpans() { parent::testExtractAsciiSpans(); } + + /** + * @covers MensBeam\Intl\Encoding\XUserDefined::asciiSpanNot + */ + public function testExtractNegativeAsciiSpans() { + parent::testExtractNegativeAsciiSpans(); + } } diff --git a/tests/lib/DecoderTest.php b/tests/lib/DecoderTest.php index 451edc8..8591b9b 100644 --- a/tests/lib/DecoderTest.php +++ b/tests/lib/DecoderTest.php @@ -368,6 +368,19 @@ abstract class DecoderTest extends \PHPUnit\Framework\TestCase { $this->assertSame("09", $d->asciiSpan($allBytes)); } + public function testExtractNegativeAsciiSpans() { + $class = $this->testedClass; + $d = new $class($this->prepString($this->spanString)); + $this->assertSame("", $d->asciiSpanNot("AZ")); + $this->assertSame("A", $d->asciiSpanNot("az", 1)); + $this->assertSame("Z", $d->asciiSpanNot("az")); + $this->assertSame("", $d->asciiSpanNot("")); + $d->nextChar(); + $this->assertSame("", $d->asciiSpanNot("")); + $d->nextChar(); + $this->assertSame("09", $d->asciiSpanNot("")); + } + protected function prepString(string $str): string { return hex2bin(str_replace(" ", "", $str)); }